def test_blotter_processes_splits(self): sim_params = factory.create_simulation_parameters() blotter = Blotter() blotter.set_date(sim_params.period_start) # set up two open limit orders with very low limit prices, # one for sid 1 and one for sid 2 blotter.order(1, 100, LimitOrder(10)) blotter.order(2, 100, LimitOrder(10)) # send in a split for sid 2 split_event = factory.create_split( 2, 0.33333, sim_params.period_start + timedelta(days=1)) blotter.process_split(split_event) for sid in [1, 2]: order_lists = blotter.open_orders[sid] self.assertIsNotNone(order_lists) self.assertEqual(1, len(order_lists)) aapl_order = blotter.open_orders[1][0].to_dict() fls_order = blotter.open_orders[2][0].to_dict() # make sure the aapl order didn't change self.assertEqual(100, aapl_order['amount']) self.assertEqual(10, aapl_order['limit']) self.assertEqual(1, aapl_order['sid']) # make sure the fls order did change # to 300 shares at 3.33 self.assertEqual(300, fls_order['amount']) self.assertEqual(3.33, fls_order['limit']) self.assertEqual(2, fls_order['sid'])
def test_blotter_processes_splits(self): sim_params = factory.create_simulation_parameters() blotter = Blotter() blotter.set_date(sim_params.period_start) # set up two open limit orders with very low limit prices, # one for sid 1 and one for sid 2 blotter.order(1, 100, LimitOrder(10)) blotter.order(2, 100, LimitOrder(10)) # send in a split for sid 2 split_event = factory.create_split(2, 0.33333, sim_params.period_start + timedelta(days=1)) blotter.process_split(split_event) for sid in [1, 2]: order_lists = blotter.open_orders[sid] self.assertIsNotNone(order_lists) self.assertEqual(1, len(order_lists)) aapl_order = blotter.open_orders[1][0].to_dict() fls_order = blotter.open_orders[2][0].to_dict() # make sure the aapl order didn't change self.assertEqual(100, aapl_order['amount']) self.assertEqual(10, aapl_order['limit']) self.assertEqual(1, aapl_order['sid']) # make sure the fls order did change # to 300 shares at 3.33 self.assertEqual(300, fls_order['amount']) self.assertEqual(3.33, fls_order['limit']) self.assertEqual(2, fls_order['sid'])
def test_split_long_position(self): events = factory.create_trade_history(1, [20, 20], [100, 100], oneday, self.sim_params) # set up a long position in sid 1 # 100 shares at $20 apiece = $2000 position txns = [create_txn(events[0], 20, 100)] # set up a split with ratio 3 occurring at the start of the second # day. splits = [ factory.create_split( 1, 3, events[1].dt, ), ] results = calculate_results(self, events, txns=txns, splits=splits) # should have 33 shares (at $60 apiece) and $20 in cash self.assertEqual(2, len(results)) latest_positions = results[1]['daily_perf']['positions'] self.assertEqual(1, len(latest_positions)) # check the last position to make sure it's been updated position = latest_positions[0] self.assertEqual(1, position['sid']) self.assertEqual(33, position['amount']) self.assertEqual(60, position['cost_basis']) self.assertEqual(60, position['last_sale_price']) # since we started with $10000, and we spent $2000 on the # position, but then got $20 back, we should have $8020 # (or close to it) in cash. # we won't get exactly 8020 because sometimes a split is # denoted as a ratio like 0.3333, and we lose some digits # of precision. thus, make sure we're pretty close. daily_perf = results[1]['daily_perf'] self.assertTrue( zp_math.tolerant_equals(8020, daily_perf['ending_cash'], 1)) for i, result in enumerate(results): for perf_kind in ('daily_perf', 'cumulative_perf'): perf_result = result[perf_kind] # prices aren't changing, so pnl and returns should be 0.0 self.assertEqual( 0.0, perf_result['pnl'], "day %s %s pnl %s instead of 0.0" % (i, perf_kind, perf_result['pnl'])) self.assertEqual( 0.0, perf_result['returns'], "day %s %s returns %s instead of 0.0" % (i, perf_kind, perf_result['returns']))
def test_split_long_position(self): with trading.TradingEnvironment() as env: events = factory.create_trade_history( 1, [20, 20], [100, 100], oneday, self.sim_params ) # set up a long position in sid 1 # 100 shares at $20 apiece = $2000 position events.insert(0, create_txn(events[0], 20, 100)) # set up a split with ratio 3 events.append(factory.create_split(1, 3, env.next_trading_day(events[1].dt))) results = calculate_results(self, events) # should have 33 shares (at $60 apiece) and $20 in cash self.assertEqual(2, len(results)) latest_positions = results[1]['daily_perf']['positions'] self.assertEqual(1, len(latest_positions)) # check the last position to make sure it's been updated position = latest_positions[0] self.assertEqual(1, position['sid']) self.assertEqual(33, position['amount']) self.assertEqual(60, position['cost_basis']) self.assertEqual(60, position['last_sale_price']) # since we started with $10000, and we spent $2000 on the # position, but then got $20 back, we should have $8020 # (or close to it) in cash. # we won't get exactly 8020 because sometimes a split is # denoted as a ratio like 0.3333, and we lose some digits # of precision. thus, make sure we're pretty close. daily_perf = results[1]['daily_perf'] self.assertTrue( zp_math.tolerant_equals(8020, daily_perf['ending_cash'], 1)) for i, result in enumerate(results): for perf_kind in ('daily_perf', 'cumulative_perf'): perf_result = result[perf_kind] # prices aren't changing, so pnl and returns should be 0.0 self.assertEqual(0.0, perf_result['pnl'], "day %s %s pnl %s instead of 0.0" % (i, perf_kind, perf_result['pnl'])) self.assertEqual(0.0, perf_result['returns'], "day %s %s returns %s instead of 0.0" % (i, perf_kind, perf_result['returns']))
def raw_data_gen(self): with open(self.fname, 'r') as f: for line in f: toks = line.split(',') ''' Note: In create_split(sid, ratio, dt), the input dt is zeroed out to the day, ie) dt.replace(hour=0, minute=0, second=0, microsecond=0). <TODO> When exactly do these split events get fired, on open or on close? ''' event = create_split(toks[0], float(toks[-1].replace('\n','')), pytz.utc.localize(datetime.strptime(str(toks[1]), '%Y%m%d'))) yield event
def test_split_long_position(self): with trading.TradingEnvironment() as env: events = factory.create_trade_history( 1, [20, 20], [100, 100], oneday, self.sim_params ) # set up a long position in sid 1 # 100 shares at $20 apiece = $2000 position events.insert(0, create_txn(events[0], 20, 100)) # set up a split with ratio 3 events.append(factory.create_split(1, 3, env.next_trading_day(events[1].dt))) results = calculate_results(self, events) # should have 33 shares (at $60 apiece) and $20 in cash self.assertEqual(2, len(results)) latest_positions = results[1]['daily_perf']['positions'] self.assertEqual(1, len(latest_positions)) # check the last position to make sure it's been updated position = latest_positions[0] self.assertEqual(1, position['sid']) self.assertEqual(33, position['amount']) self.assertEqual(60, position['cost_basis']) self.assertEqual(60, position['last_sale_price']) # since we started with $10000, and we spent $2000 on the # position, but then got $20 back, we should have $8020 # (or close to it) in cash. # we won't get exactly 8020 because sometimes a split is # denoted as a ratio like 0.3333, and we lose some digits # of precision. thus, make sure we're pretty close. daily_perf = results[1]['daily_perf'] self.assertTrue( zp_math.tolerant_equals(8020, daily_perf['ending_cash'], 1))