def test_close_all(self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='fut1') pos.add(trans) trans2 = Transaction(self.fut_contract, self.date, 2.0, 15.3) pos.add(trans2) positions = pos.netpositions self.assertEqual(1, len(positions)) self.assertEqual(True, self.fut_contract in positions) p = positions[self.fut_contract] self.assertEqual(p['qty'], 6.0) self.assertEqual(p['value'], trans.usdvalue + trans2.usdvalue) self.assertEqual(0, pos._realized_pnl) self.fut_contract._price = 14.3 trans = pos.close_all_translist() self.assertEqual( [Transaction(self.fut_contract, self.date, -6.0, 14.3)], trans) self.assertEqual('fut1', trans[0].leg_name) self.assertNotEqual(None, Transaction(self.fut_contract, self.date, -6.0, 14.3)) # For 100% coverage
def test_add_leg_expection_if_leg_name_duplicate_but_different_assets( self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='fut1') pos.add(trans) self.assertEqual(True, 'fut1' in pos.legs) self.assertEqual(1, len(pos.legs)) contract_dict = { '_id': '577a4fa34b01f47f84cab23c', 'contractname': 'F.EPZ16', 'cqgsymbol': 'F.EPZ16', 'expirationdate': datetime(2016, 12, 16, 0, 0), 'idcontract': 650, 'idinstrument': 11, 'month': 'Z', 'monthint': 12, 'year': 2016 } fut_contract2 = FutureContract(contract_dict, self.instrument) trans = Transaction(fut_contract2, self.date, -4.0, 12.3, leg_name='fut1') self.assertRaises(NameError, pos.add, trans)
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 [] put = opt_chain[-5].P call = opt_chain[5].C trans_list = [ Transaction(fut, self.date, 1.0, fut.price, leg_name='fut'), Transaction(call, self.date, -1.0, call.price, leg_name='opt_call'), Transaction(put, self.date, 1.0, put.price, leg_name='opt_put'), ] return trans_list
def new_position_bearish_zone(date, fut, opt_chain): """ Returns transaction to open new Smart EXO position for bearish zone params date: current date params fut: current actual future contract params opt_chain: current actual options chain returns: List of Transactions to open """ # # Opening small ITM straddle in bearish zone # trans_list = [ # Transaction(asset, date, qty, price=[MktPrice], leg_name=['' or unique name]) Transaction(opt_chain[4].c, date, 0.0, leg_name='bearish'), Transaction(opt_chain[7].c, date, 0.0), Transaction(opt_chain[3].p, date, -1.0), Transaction(opt_chain[-6].p, date, 1.0), # Transaction(opt_chain[-7].p, date, 1.0), # Transaction(opt_chain[-9].p, date, -1.0), # Transaction(opt_chain[2].c, date, 0.0, leg_name='bearish'), # Transaction(opt_chain[2].p, date, 0.0), ] return trans_list
def test_as_dict(self): exo_engine = EXOTestEngine('', '', self.date, self.datasource) trans = Transaction(self.fut_contract, self.date, 4.0, 12.3) exo_engine.position.add(trans) tr_list = exo_engine._transactions tr_list.append(trans) date = pd.date_range("2015-01-01 00:00:00", "2015-01-01 00:00:10", freq="1S") price = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=np.float64) exo_engine._series = pd.DataFrame(price, index=date, columns=['exo']) exo_engine._series.index = pd.to_datetime(exo_engine._series.index) exo_dic = exo_engine.as_dict() self.assertEqual(True, 'position' in exo_dic) self.assertEqual(exo_engine.position.as_dict(), exo_dic['position']) self.assertEqual(True, 'transactions' in exo_dic) self.assertEqual([trans.as_dict()], exo_dic['transactions']) self.assertEqual(exo_dic['name'], self.exo_engine.name) self.assertEqual(True, 'series' in exo_dic) self.assertEqual(pickle.dumps(exo_engine.series), exo_dic['series'])
def new_position_bearish_zone(date, fut, opt_chain): trans_list = [ # Transaction(asset, date, qty, price=[MktPrice], leg_name=['' or unique name]) # # Transaction(opt_chain.get_by_delta(0.10), date, 3.0), Transaction(opt_chain.get_by_delta(0.35), date, -1.0), ] return trans_list
def new_position_neutral_zone(date, fut, opt_chain): # Edit transactions to trade trans_list = [ # Transaction(asset, date, qty, price=[MktPrice], leg_name=['' or unique name]) # # Transaction(opt_chain.get_by_delta(0.15), date, 1.0), Transaction(opt_chain.get_by_delta(-0.25), date, -1.0), ] return trans_list
def test_from_dict(self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='fut1') pos.add(trans) trans2 = Transaction(self.fut_contract, self.date, -2.0, 13.3) pos.add(trans2) positions = pos.netpositions self.assertEqual(1, len(positions)) self.assertEqual(100, pos._realized_pnl) self.assertEqual(1, len(positions)) self.assertEqual(True, self.fut_contract in positions) p = positions[self.fut_contract] self.assertEqual(p['qty'], 2.0) self.assertEqual(p['value'], trans.usdvalue / 2) self.fut_contract._price = 14.3 self.assertEqual(100, pos._realized_pnl) self.assertEqual(pos.pnl, 100 + 200) pos_dic = pos.as_dict() # Deserealizing position p2 = Position.from_dict(pos_dic, self.datasource, self.date) positions = p2.netpositions self.assertEqual(100, p2._realized_pnl) self.assertEqual(1, len(positions)) self.assertEqual(True, self.fut_contract in positions) p = positions[self.fut_contract] # Wrong - because we have new object from datsource #self.fut_contract._price = 14.3 for k in positions.keys(): k._price = 14.3 self.assertEqual(p['qty'], 2.0) self.assertEqual(p['value'], trans.usdvalue / 2) self.assertEqual(1, len(p2.legs)) self.assertEqual(True, 'fut1' in p2.legs) self.assertEqual(self.fut_contract, p2.legs['fut1']) self.assertEqual(100, p2._realized_pnl) self.assertEqual(p2.pnl, 100 + 200)
def test_add_to_closeposition_short(self): pos = Position() trans = Transaction(self.fut_contract, self.date, -4.0, 12.3) pos.add(trans) trans = Transaction(self.fut_contract, self.date, 4.0, 13.3) pos.add(trans) positions = pos.netpositions self.assertEqual(0, len(positions)) self.assertEqual(-200, pos._realized_pnl)
def test_add_shrink_position_long_and_then_close(self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3) pos.add(trans) trans2 = Transaction(self.fut_contract, self.date, -2.0, 13.3) pos.add(trans2) trans3 = Transaction(self.fut_contract, self.date, -2.0, 13.3) pos.add(trans3) positions = pos.netpositions self.assertEqual(0, len(positions)) self.assertEqual(200, pos._realized_pnl)
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 test_add_2transactions(self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3) pos.add(trans) trans2 = Transaction(self.fut_contract, self.date, 2.0, 15.3) pos.add(trans2) positions = pos.netpositions self.assertEqual(1, len(positions)) self.assertEqual(True, self.fut_contract in positions) p = positions[self.fut_contract] self.assertEqual(p['qty'], 6.0) self.assertEqual(p['value'], trans.usdvalue + trans2.usdvalue) self.assertEqual(0, pos._realized_pnl)
def test_constructor(self): t = Transaction(self.fut_contract, self.date, 4.0, 12.3) self.assertEqual(t._asset, self.fut_contract) self.assertEqual(t._date, self.date) self.assertEqual(t._qty, 4.0) self.assertEqual(t._price, 12.3) self.assertEqual(t._leg_name, '')
def test_add_shrink_position_short(self): pos = Position() trans = Transaction(self.fut_contract, self.date, -4.0, 12.3) pos.add(trans) trans2 = Transaction(self.fut_contract, self.date, 2.0, 13.3) pos.add(trans2) positions = pos.netpositions self.assertEqual(1, len(positions)) self.assertEqual(-100, pos._realized_pnl) self.assertEqual(1, len(positions)) self.assertEqual(True, self.fut_contract in positions) p = positions[self.fut_contract] self.assertEqual(p['qty'], -2.0) self.assertEqual(p['value'], trans.usdvalue / 2)
class TransactionTestCase(unittest.TestCase): def setUp(self): self.assetindex = AssetIndexDicts() self.symbol = 'EP' self.date = datetime(2014, 1, 5, 0, 0, 0) self.futures_limit = 12 self.instrument_dbid = 11 self.datasource = DataSourceForTest(self.assetindex, self.futures_limit, 0) self.instrument = self.datasource.get(self.symbol, self.date) self.contract_dict = {'_id': '577a4fa34b01f47f84cab23c', 'contractname': 'F.EPZ16', 'cqgsymbol': 'F.EPZ16', 'expirationdate': datetime(2016, 12, 16, 0, 0), 'idcontract': 6570, 'idinstrument': 11, 'month': 'Z', 'monthint': 12, 'year': 2016} self.fut_contract = FutureContract(self.contract_dict, self.instrument) self.trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='leg1') def test_constructor(self): t = Transaction(self.fut_contract, self.date, 4.0, 12.3) self.assertEqual(t._asset, self.fut_contract) self.assertEqual(t._date, self.date) self.assertEqual(t._qty, 4.0) self.assertEqual(t._price, 12.3) self.assertEqual(t._leg_name, '') def test_has_leg_name(self): self.assertEqual(self.trans._leg_name, 'leg1') self.assertEqual(self.trans.leg_name, 'leg1') def test_has_asset(self): self.assertEqual(self.trans.asset, self.fut_contract) def test_has_date(self): self.assertEqual(self.trans.date, self.date) def test_has_qty(self): self.assertEqual(self.trans.qty, 4.0) def test_has_price(self): self.assertEqual(self.trans.price, 12.3) def test_has_usdvalue(self): self.assertEqual(self.trans.usdvalue, 4*12.3*self.fut_contract.pointvalue) def test_has_as_dict(self): self.assertEqual({'date': self.trans.date, 'qty': self.trans.qty, 'price': self.trans.price, 'asset': self.fut_contract.as_dict(), 'usdvalue': self.trans.usdvalue}, self.trans.as_dict())
def close_all_translist(self): """ Returns list of transaction to close EXO position :return: """ transactions = [] for asset, netposition in self.netpositions.items(): transactions.append(Transaction(asset, asset.date, -netposition['qty'], asset.price, leg_name=netposition['leg_name'])) return transactions
def test_add_leg_has_legs(self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='fut1') pos.add(trans) self.assertEqual(True, 'fut1' in pos.legs)
def test_add_leg_has_no_legs_if_leg_name_is_empty(self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='') pos.add(trans) self.assertEqual(False, 'fut1' in pos.legs)
def new_position_bullish_zone(date, fut, opt_chain): """ opt_chain.get_by_delta(delta_value) help: Search option contract by delta value: If delta == 0.5 - returns ATM call If delta == -0.5 - returns ATM put If delta > 0.5 - returns ITM call near target delta If delta < -0.5 - returns ITM put near target delta If delta > 0 and < 0.5 - returns OTM call If delta < 0 and > -0.5 - returns OTM put If delta <= -1 or >= 1 or 0 - raises error Examples: # ATM put (delta = -0.5) Transaction(opt_chain.get_by_delta(-0.5), date, 1.0), # OTM put (delta = -0.25) Transaction(opt_chain.get_by_delta(-0.25), date, 1.0), # ITM put (delta = -0.75) Transaction(opt_chain.get_by_delta(-0.75), date, 1.0), # ATM call (delta = 0.5) Transaction(opt_chain.get_by_delta(0.5), date, 1.0), # OTM call (delta = 0.25) Transaction(opt_chain.get_by_delta(0.25), date, 1.0), # ITM call (delta = 0.75) Transaction(opt_chain.get_by_delta(0.75), date, 1.0), """ # Edit transactions to trade trans_list = [ # Transaction(asset, date, qty, price=[MktPrice], leg_name=['' or unique name]) # # Transaction(opt_chain.get_by_delta(-0.90), date, 1.0), Transaction(opt_chain.get_by_delta(-0.35), date, -1.0), Transaction(opt_chain.get_by_delta(-0.05), date, 1.0), ] return trans_list
def setUp(self): self.assetindex = AssetIndexDicts() self.symbol = 'EP' self.date = datetime(2014, 1, 5, 0, 0, 0) self.futures_limit = 12 self.instrument_dbid = 11 self.datasource = DataSourceForTest(self.assetindex, self.futures_limit, 0) self.instrument = self.datasource.get(self.symbol, self.date) self.contract_dict = {'_id': '577a4fa34b01f47f84cab23c', 'contractname': 'F.EPZ16', 'cqgsymbol': 'F.EPZ16', 'expirationdate': datetime(2016, 12, 16, 0, 0), 'idcontract': 6570, 'idinstrument': 11, 'month': 'Z', 'monthint': 12, 'year': 2016} self.fut_contract = FutureContract(self.contract_dict, self.instrument) self.trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='leg1')
def test_add_leg_delete_leg_is_position_closed(self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='fut1') pos.add(trans) self.assertEqual(True, 'fut1' in pos.legs) self.assertEqual(1, len(pos.legs)) trans = Transaction(self.fut_contract, self.date, -4.0, 12.3, leg_name='') pos.add(trans) self.assertEqual(False, 'fut1' in pos.legs) self.assertEqual(0, len(pos.legs))
def new_position_bullish_zone(date, fut, opt_chain): """ Returns transaction to open new Smart EXO position for bullish zone params date: current date params fut: current actual future contract params opt_chain: current actual options chain returns: List of Transactions to open """ # # Opening short put spread bullish zone # # https://files.slack.com/files-tmb/T0484J7T7-F2QBLK53R-93b4252806/pasted_image_at_2016_10_17_10_08_am_720.png trans_list = [ # Transaction(asset, date, qty, price=[MktPrice], leg_name=['' or unique name]) Transaction(opt_chain[2].c, date, 0.0, leg_name='bullish'), Transaction(opt_chain[7].c, date, 0.0), Transaction(opt_chain[-7].p, date, 1.0), Transaction(opt_chain[-9].p, date, -1.0), # Transaction(opt_chain[3].p, date, -3.0), Transaction(opt_chain[-6].p, date, 3.0), Transaction(opt_chain[-11].p, date, -3.0), ] return trans_list
def test_as_dict(self): pos = Position() trans = Transaction(self.fut_contract, self.date, 4.0, 12.3, leg_name='leg1') pos.add(trans) trans2 = Transaction(self.fut_contract, self.date, -2.0, 13.3) pos.add(trans2) positions = pos.netpositions self.assertEqual(1, len(positions)) self.assertEqual(100, pos._realized_pnl) self.assertEqual(1, len(positions)) self.assertEqual(True, self.fut_contract in positions) p = positions[self.fut_contract] self.assertEqual(p['qty'], 2.0) self.assertEqual(p['value'], trans.usdvalue / 2) self.fut_contract._price = 14.3 self.assertEqual(100, pos._realized_pnl) self.assertEqual(pos.pnl, 100 + 200) self.assertEqual( { 'positions': { str(self.fut_contract.__hash__()): { 'qty': 2.0, 'value': trans.usdvalue / 2, 'leg_name': 'leg1' } }, '_realized_pnl': 100.0 }, pos.as_dict())
def new_position_neutral_zone(date, fut, opt_chain): """ Returns transaction to open new Smart EXO position for neutral zone params date: current date params fut: current actual future contract params opt_chain: current actual options chain returns: List of Transactions to open """ # Opening long asymmetric butterfly in neutral zone # # https://files.slack.com/files-tmb/T0484J7T7-F2PGU8QNQ-6344e6a04c/pasted_image_at_2016_10_14_09_43_am_720.png trans_list = [ # Transaction(asset, date, qty, price=[MktPrice], leg_name=['' or unique name]) Transaction(opt_chain[-2].c, date, -0.0, leg_name='neutral'), Transaction(opt_chain[2].c, date, 0.0), Transaction(opt_chain[8].c, date, -0.0), Transaction(opt_chain[3].c, date, 0.0), ] return trans_list
def test_add_2transactions_and_do_reverse_add(self): pos = Position() trans = Transaction(self.fut_contract, datetime(2014, 1, 5, 0, 0, 0), 4.0, 12.3) pos.add(trans) contract_dict = { '_id': '577a4fa34b01f47f84cab23c', 'contractname': 'F.EPZ16', 'cqgsymbol': 'F.EPZ16', 'expirationdate': datetime(2016, 12, 16, 0, 0), 'idcontract': 650, 'idinstrument': 11, 'month': 'Z', 'monthint': 12, 'year': 2016 } fut_contract2 = FutureContract(contract_dict, self.instrument) trans2 = Transaction(fut_contract2, datetime(2014, 1, 6, 0, 0, 0), 2.0, 15.3) pos.add(trans2) # Do offset trade to close previous transaction trans3 = Transaction(fut_contract2, datetime(2014, 1, 7, 0, 0, 0), -2.0, 15.3) pos.add(trans3) positions = pos.netpositions self.assertEqual(1, len(positions)) self.assertEqual(True, self.fut_contract in positions) p = positions[self.fut_contract] self.assertEqual(p['qty'], 4.0) self.assertEqual(0, pos._realized_pnl)
def test_has_len(self): pos = Position() self.assertEqual(len(pos), 0) trans = Transaction(self.fut_contract, self.date, 4.0, 12.3) pos.add(trans) self.assertEqual(len(pos), 1)
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 []
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'), ]