def test_chain_handle_missing_data(self): assetindex = AssetIndexMongo(MONGO_CONNSTR, MONGO_EXO_DB) futures_limit = 3 options_limit = 20 datasource = DataSourceSQL(SQL_HOST, SQL_USER, SQL_PASS, assetindex, futures_limit, options_limit) base_date = datetime(2014, 2, 18, 11, 10, 0) instr = datasource.get("CL", base_date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() # opt_chain.get_by_delta(0.05) on the CL on this date is has absent data # opt_chain selects next available date self.assertEqual(opt_chain.get_by_delta(0.05), opt_chain.get_by_delta(0.04)) base_date = datetime(2016, 2, 17, 11, 10, 0) instr = datasource.get("ZN", base_date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() # opt_chain[11] is an absent strike inside DB, if it absent opt_chain selects next available strike self.assertEqual(opt_chain[11], opt_chain[12]) self.assertEqual(opt_chain[-11], opt_chain[-12])
def process_day(self): """ Main EXO's position management method :return: list of Transactions to process """ if len(self.position) == 0: instr = self.datasource.get(self._symbol, self.date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() if fut is None or opt_chain is None: if self.debug_mode: self.logger.write( 'Futures contract or option chain not found.\n\tFuture: {0}\tOption chain: {1}\n' .format(fut, opt_chain)) return [] call = opt_chain[0].C trans_list = [ Transaction(call, self.date, 1.0, call.price, leg_name='opt_call'), ] return trans_list
def test_active_chains_current(self): inst_dict = { 'name': 'TEST', 'futures': [{ 'days': 5, 'name': 'fut1', 'expiration': datetime(2015, 1, 10), 'options': [ { 'days': 3, 'expiration': datetime(2015, 1, 8), 'name': 'fut1_opt1' }, ] }] } dinst = DummyInstrument(inst_dict) rh = RolloverHelper(dinst) fut, opt = rh.get_active_chains() self.assertEqual(fut.name, 'fut1') self.assertEqual(opt.name, 'fut1_opt1')
def test_active_chains_rollover_options_no_options_chains(self): inst_dict = { 'name': 'TEST', 'futures': [{ 'days': 20, 'name': 'fut1', 'expiration': datetime(2015, 1, 10), 'options': [] }, { 'days': 20, 'name': 'fut2', 'expiration': datetime(2015, 2, 10), 'options': [] }, { 'days': 40, 'name': 'fut3', 'expiration': datetime(2015, 3, 10), 'options': [] }] } dinst = DummyInstrument(inst_dict) rh = RolloverHelper(dinst) rh.rollover_months = [1, 3] rh.days_before_expiration = 10 fut, opt = rh.get_active_chains() self.assertEqual(fut.name, 'fut1') self.assertEqual(opt, None)
def test_active_chains_rollover_options_no_futures(self): inst_dict = {'name': 'TEST', 'futures': []} dinst = DummyInstrument(inst_dict) rh = RolloverHelper(dinst) rh.rollover_months = [1, 3] rh.days_before_expiration = 10 fut, opt = rh.get_active_chains() self.assertEqual(fut, None) self.assertEqual(opt, None)
def process_day(self): """ Main EXO's position management method :return: list of Transactions to process """ if len(self.position) == 0: instr = self.datasource.get(self._symbol, self.date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() if fut is None or opt_chain is None: if self.debug_mode: self.logger.write( 'Futures contract or option chain not found.\n\tFuture: {0}\tOption chain: {1}\n' .format(fut, opt_chain)) return [] if self._direction == 1: itm_call = opt_chain[-2].C otm_call = opt_chain[10].C return [ Transaction(itm_call, self.date, 1.0, itm_call.price, leg_name='opt_itm_leg'), Transaction(otm_call, self.date, -1.0, otm_call.price, leg_name='opt_otm_leg'), ] if self._direction == -1: itm_put = opt_chain[2].P otm_put = opt_chain[-10].P return [ Transaction(itm_put, self.date, 1.0, itm_put.price, leg_name='opt_itm_leg'), Transaction(otm_put, self.date, -1.0, otm_put.price, leg_name='opt_otm_leg'), ]
def plot_transactions_payoff(self, smart_exo_position_func, analysis_date, analysis_instrument, **whatif_kwargs): payoff = PayoffAnalyzer(self.datasource) instr = self.datasource.get(analysis_instrument, analysis_date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() strikes_on_graph = whatif_kwargs.get('strikes_on_graph', 30) whatif_iv_change = whatif_kwargs.get('whatif_iv_change', 0) whatif_days_to_expiration = whatif_kwargs.get( 'whatif_days_to_expiration', int(opt_chain.to_expiration_days / 2)) payoff.load_transactions( smart_exo_position_func(analysis_date, fut, opt_chain), analysis_date) payoff.plot(strikes_on_graph, whatif_iv_change, whatif_days_to_expiration)
def test_max_min_offset(self): assetindex = AssetIndexMongo(MONGO_CONNSTR, MONGO_EXO_DB) base_date = datetime(2015, 6, 13, 12, 45, 0) futures_limit = 3 options_limit = 20 datasource = DataSourceSQL(SQL_HOST, SQL_USER, SQL_PASS, assetindex, futures_limit, options_limit) instr = datasource.get("ES", base_date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() offset = opt_chain.maxoffset self.assertEqual(20, offset) offset = opt_chain.minoffset self.assertEqual(-20, offset)
def process_day(self): """ Main EXO's position management method :return: list of Transactions to process """ # Get cont futures price for EXO exo_df, exo_info = self.datasource.exostorage.load_series( self._base_exo_name) regime = self.calculate_regime(self.date, exo_df) logging.debug("Regime {0}".format(regime)) trans_list = [] if regime is None and len(self.position) > 0: return self.position.close_all_translist() instr = self.datasource.get(self._symbol, self.date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() if regime == 1 and 'bullish' not in self.position.legs: # Close all trans_list += self.position.close_all_translist() tl = self.new_position_bullish_zone(self.date, fut, opt_chain) if len(tl) > 0: tl[0]._leg_name = 'bullish' trans_list += tl self._log_transactions(trans_list) return trans_list if regime == -1 and 'bearish' not in self.position.legs: # Close all trans_list += self.position.close_all_translist() tl = self.new_position_bearish_zone(self.date, fut, opt_chain) if len(tl) > 0: tl[0]._leg_name = 'bearish' trans_list += tl self._log_transactions(trans_list) return trans_list if regime == 0 and 'neutral' not in self.position.legs: # Close all trans_list += self.position.close_all_translist() tl = self.new_position_neutral_zone(self.date, fut, opt_chain) if len(tl) > 0: tl[0]._leg_name = 'neutral' trans_list += tl self._log_transactions(trans_list) return trans_list # # Writing custom values to store inside DB # self.custom_values = { 'regime': regime if regime is not None else float('nan') } # # Manage opened position # return self.manage_opened_position(self.date, fut, opt_chain, regime, self.position)
def test_chain_get_by_delta(self): assetindex = AssetIndexMongo(MONGO_CONNSTR, MONGO_EXO_DB) base_date = datetime(2015, 6, 13, 12, 45, 0) futures_limit = 3 options_limit = 20 datasource = DataSourceSQL(SQL_HOST, SQL_USER, SQL_PASS, assetindex, futures_limit, options_limit) instr = datasource.get("ES", base_date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() atm_strike = opt_chain.atmstrike opt = opt_chain.get_by_delta(0.5) self.assertEqual(opt.strike, atm_strike) self.assertEqual(opt.putorcall, 'C') opt = opt_chain.get_by_delta(-0.5) self.assertEqual(opt.strike, atm_strike) self.assertEqual(opt.putorcall, 'P') self.assertRaises(ValueError, opt_chain.get_by_delta, 0) self.assertRaises(ValueError, opt_chain.get_by_delta, float('nan')) self.assertRaises(ValueError, opt_chain.get_by_delta, 1) self.assertRaises(ValueError, opt_chain.get_by_delta, 2) self.assertRaises(ValueError, opt_chain.get_by_delta, -2) self.assertRaises(ValueError, opt_chain.get_by_delta, -1) # ITM Put opt = opt_chain.get_by_delta(-0.7) self.assertEqual(opt.strike, 2115) self.assertEqual(opt.putorcall, 'P') self.assertAlmostEqual(opt.delta, -0.75, 2) opt = opt_chain.get_by_delta(-0.999999) self.assertEqual(opt.strike, 2195.0) self.assertEqual(opt.putorcall, 'P') self.assertAlmostEqual(opt.delta, -0.989, 3) # OTM Put opt = opt_chain.get_by_delta(-0.3) self.assertEqual(opt.strike, 2070) self.assertEqual(opt.putorcall, 'P') self.assertAlmostEqual(opt.delta, -0.27, 2) opt = opt_chain.get_by_delta(-0.00001) self.assertEqual(opt, opt_chain[-20].P) # ITM Call opt = opt_chain.get_by_delta(0.7) self.assertEqual(opt.strike, 2070) self.assertEqual(opt.putorcall, 'C') self.assertAlmostEqual(opt.delta, 0.73, 2) opt = opt_chain.get_by_delta(0.9999999) self.assertEqual(opt, opt_chain[-20].C) # OTM Call opt = opt_chain.get_by_delta(0.3) self.assertEqual(opt.strike, 2115) self.assertEqual(opt.putorcall, 'C') self.assertAlmostEqual(opt.delta, 0.24, 2) opt = opt_chain.get_by_delta(0.000001) self.assertEqual(opt, opt_chain[20].C)
def process_day(self): """ Main EXO's position management method :return: list of Transactions to process """ if len(self.position) == 0: instr = self.datasource.get(self._symbol, self.date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() if fut is None or opt_chain is None: if self.debug_mode: self.logger.write( 'Futures contract or option chain not found.\n\tFuture: {0}\tOption chain: {1}\n' .format(fut, opt_chain)) return [] if self._direction == 1: # the bullish broken wings are long the -5 put , long the future, short the + 5 call and long the +9 call put_dn5 = opt_chain[-5].P call_up5 = opt_chain[5].C call_up9 = opt_chain[9].C return [ Transaction(put_dn5, self.date, 1.0, put_dn5.price, leg_name='opt_otm_leg'), Transaction(fut, self.date, 1.0, fut.price, leg_name='fut_leg'), Transaction(call_up5, self.date, -1.0, call_up5.price, leg_name='call_up5_short_leg'), Transaction(call_up9, self.date, 1.0, call_up9.price, leg_name='call_up9_long_leg'), ] if self._direction == -1: # the bearish BW long the -9 put, short the -5 put , short the future, long the + 5 call call_up5 = opt_chain[5].C put_dn9 = opt_chain[-9].P put_dn5 = opt_chain[-5].P return [ Transaction(call_up5, self.date, 1.0, call_up5.price, leg_name='opt_otm_leg'), Transaction(fut, self.date, -1.0, fut.price, leg_name='fut_leg'), Transaction(put_dn9, self.date, 1.0, put_dn9.price, leg_name='put_dn9_long_leg'), Transaction(put_dn5, self.date, -1.0, put_dn5.price, leg_name='put_dn5_short_leg'), ]
def process_day(self): """ Main EXO's position management method :return: list of Transactions to process """ # Get cont futures price for EXO exo_df, exo_info = self.datasource.exostorage.load_series( "{0}_ContFut".format(self._symbol)) regime = self.ichimoku_regimes(exo_df['exo']) trans_list = [] if regime is None and len(self.position) > 0: return self.position.close_all_translist() if regime == 1 and 'bullish' not in self.position.legs: # Close all trans_list += self.position.close_all_translist() instr = self.datasource.get(self._symbol, self.date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() trans_list += [ Transaction(fut, self.date, 15.0, fut.price, leg_name='bullish'), ] return trans_list if regime == -1 and 'bearish' not in self.position.legs: # Close all trans_list += self.position.close_all_translist() instr = self.datasource.get(self._symbol, self.date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() trans_list += [ Transaction(fut, self.date, 1.0, fut.price, leg_name='bearish'), ] return trans_list if regime == 0 and 'neutral' not in self.position.legs: # Close all trans_list += self.position.close_all_translist() instr = self.datasource.get(self._symbol, self.date) rh = RolloverHelper(instr) fut, opt_chain = rh.get_active_chains() trans_list += [ Transaction(fut, self.date, 5.0, fut.price, leg_name='neutral'), ] return trans_list return []