def test_minute_tracker(self): """ Tests minute performance tracking.""" start_dt = trading.environment.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 9, 30)) end_dt = trading.environment.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 16, 0)) sim_params = SimulationParameters( period_start=start_dt, period_end=end_dt, emission_rate='minute' ) tracker = perf.PerformanceTracker(sim_params) foo_event_1 = factory.create_trade('foo', 10.0, 20, start_dt) bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt) txn = Transaction(sid=foo_event_1.sid, amount=-25, dt=foo_event_1.dt, price=10.0, commission=0.50) foo_event_1.TRANSACTION = txn foo_event_2 = factory.create_trade( 'foo', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) bar_event_2 = factory.create_trade( 'bar', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) events = [ foo_event_1, bar_event_1, foo_event_2, bar_event_2 ] import operator messages = {date: snapshot[0].perf_messages[0] for date, snapshot in tracker.transform( itertools.groupby( events, operator.attrgetter('dt')))} self.assertEquals(2, len(messages)) msg_1 = messages[foo_event_1.dt] msg_2 = messages[foo_event_2.dt] self.assertEquals(1, len(msg_1['intraday_perf']['transactions']), "The first message should contain one transaction.") # Check that transactions aren't emitted for previous events. self.assertEquals(0, len(msg_2['intraday_perf']['transactions']), "The second message should have no transactions.") # Ensure that period_close moves through time. # Also, ensure that the period_closes are the expected dts. self.assertEquals(foo_event_1.dt, msg_1['intraday_perf']['period_close']) self.assertEquals(foo_event_2.dt, msg_2['intraday_perf']['period_close'])
def test_minute_tracker(self): """ Tests minute performance tracking.""" start_dt = trading.environment.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 9, 30)) end_dt = trading.environment.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 16, 0)) sim_params = SimulationParameters( period_start=start_dt, period_end=end_dt, emission_rate='minute' ) tracker = perf.PerformanceTracker(sim_params) foo_event_1 = factory.create_trade('foo', 10.0, 20, start_dt) bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt) txn = Transaction(sid=foo_event_1.sid, amount=-25, dt=foo_event_1.dt, price=10.0, commission=0.50) foo_event_1.TRANSACTION = txn foo_event_2 = factory.create_trade( 'foo', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) bar_event_2 = factory.create_trade( 'bar', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) foo_event_3 = factory.create_trade( 'foo', 12.0, 30, start_dt + datetime.timedelta(minutes=2)) tracker.process_event(foo_event_1) tracker.process_event(bar_event_1) messages = tracker.process_event(foo_event_2) tracker.process_event(bar_event_2) messages += tracker.process_event(foo_event_3) self.assertEquals(2, len(messages)) self.assertEquals(1, len(messages[0]['intraday_perf']['transactions']), "The first message should contain one transaction.") # Check that transactions aren't emitted for previous events. self.assertEquals(0, len(messages[1]['intraday_perf']['transactions']), "The second message should have no transactions.")
def test_minute_tracker(self): """ Tests minute performance tracking.""" exc_tz = pytz.timezone('US/Eastern') start_dt = trading.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 9, 30, tzinfo=exc_tz)) end_dt = trading.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 16, 0, tzinfo=exc_tz)) sim_params = SimulationParameters( period_start=start_dt, period_end=end_dt, emission_rate='minute' ) tracker = perf.PerformanceTracker(sim_params) foo_event_1 = factory.create_trade('foo', 10.0, 20, start_dt) bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt) txn = Transaction(sid=foo_event_1.sid, amount=-25, dt=foo_event_1.dt, price=10.0, commission=0.50) foo_event_1.TRANSACTION = txn foo_event_2 = factory.create_trade( 'foo', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) bar_event_2 = factory.create_trade( 'bar', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) foo_event_3 = factory.create_trade( 'foo', 12.0, 30, start_dt + datetime.timedelta(minutes=2)) tracker.process_event(foo_event_1) tracker.process_event(bar_event_1) messages = tracker.process_event(foo_event_2) tracker.process_event(bar_event_2) messages += tracker.process_event(foo_event_3) self.assertEquals(2, len(messages))
def test_minute_tracker(self): """ Tests minute performance tracking.""" with trading.TradingEnvironment(): start_dt = trading.environment.exchange_dt_in_utc( datetime(2013, 3, 1, 9, 31)) end_dt = trading.environment.exchange_dt_in_utc( datetime(2013, 3, 1, 16, 0)) sim_params = SimulationParameters( period_start=start_dt, period_end=end_dt, emission_rate='minute' ) tracker = perf.PerformanceTracker(sim_params) foo_event_1 = factory.create_trade('foo', 10.0, 20, start_dt) order_event_1 = Order(sid=foo_event_1.sid, amount=-25, dt=foo_event_1.dt) bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt) txn_event_1 = Transaction(sid=foo_event_1.sid, amount=-25, dt=foo_event_1.dt, price=10.0, commission=0.50, order_id=order_event_1.id) benchmark_event_1 = Event({ 'dt': start_dt, 'returns': 0.01, 'type': zp.DATASOURCE_TYPE.BENCHMARK }) foo_event_2 = factory.create_trade( 'foo', 11.0, 20, start_dt + timedelta(minutes=1)) bar_event_2 = factory.create_trade( 'bar', 11.0, 20, start_dt + timedelta(minutes=1)) benchmark_event_2 = Event({ 'dt': start_dt + timedelta(minutes=1), 'returns': 0.02, 'type': zp.DATASOURCE_TYPE.BENCHMARK }) events = [ foo_event_1, order_event_1, benchmark_event_1, txn_event_1, bar_event_1, foo_event_2, benchmark_event_2, bar_event_2, ] grouped_events = itertools.groupby( events, operator.attrgetter('dt')) messages = {} for date, group in grouped_events: tracker.set_date(date) for event in group: tracker.process_event(event) tracker.handle_minute_close(date) msg = tracker.to_dict() messages[date] = msg self.assertEquals(2, len(messages)) msg_1 = messages[foo_event_1.dt] msg_2 = messages[foo_event_2.dt] self.assertEquals(1, len(msg_1['minute_perf']['transactions']), "The first message should contain one " "transaction.") # Check that transactions aren't emitted for previous events. self.assertEquals(0, len(msg_2['minute_perf']['transactions']), "The second message should have no " "transactions.") self.assertEquals(1, len(msg_1['minute_perf']['orders']), "The first message should contain one orders.") # Check that orders aren't emitted for previous events. self.assertEquals(0, len(msg_2['minute_perf']['orders']), "The second message should have no orders.") # Ensure that period_close moves through time. # Also, ensure that the period_closes are the expected dts. self.assertEquals(foo_event_1.dt, msg_1['minute_perf']['period_close']) self.assertEquals(foo_event_2.dt, msg_2['minute_perf']['period_close']) # In this test event1 transactions arrive on the first bar. # This leads to no returns as the price is constant. # Sharpe ratio cannot be computed and is None. # In the second bar we can start establishing a sharpe ratio. self.assertIsNone(msg_1['cumulative_risk_metrics']['sharpe']) self.assertIsNotNone(msg_2['cumulative_risk_metrics']['sharpe'])
def test_cost_basis_calc(self): history_args = ( 1, [10, 11, 11, 12], [100, 100, 100, 100], onesec, self.sim_params ) trades = factory.create_trade_history(*history_args) transactions = factory.create_txn_history(*history_args) pp = perf.PerformancePeriod(1000.0) average_cost = 0 for i, txn in enumerate(transactions): pp.execute_transaction(txn) average_cost = (average_cost * i + txn.price) / (i + 1) self.assertEqual(pp.positions[1].cost_basis, average_cost) for trade in trades: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.positions[1].last_sale_price, trades[-1].price, "should have a last sale of 12, got {val}".format( val=pp.positions[1].last_sale_price) ) self.assertEqual( pp.positions[1].cost_basis, 11, "should have a cost basis of 11" ) self.assertEqual( pp.pnl, 400 ) down_tick = factory.create_trade( 1, 10.0, 100, trades[-1].dt + onesec) sale_txn = create_txn( down_tick, 10.0, -100) pp.rollover() pp.execute_transaction(sale_txn) pp.update_last_sale(down_tick) pp.calculate_performance() self.assertEqual( pp.positions[1].last_sale_price, 10, "should have a last sale of 10, was {val}".format( val=pp.positions[1].last_sale_price) ) self.assertEqual( pp.positions[1].cost_basis, 11, "should have a cost basis of 11" ) self.assertEqual(pp.pnl, -800, "this period goes from +400 to -400") pp3 = perf.PerformancePeriod(1000.0) average_cost = 0 for i, txn in enumerate(transactions): pp3.execute_transaction(txn) average_cost = (average_cost * i + txn.price) / (i + 1) self.assertEqual(pp3.positions[1].cost_basis, average_cost) pp3.execute_transaction(sale_txn) trades.append(down_tick) for trade in trades: pp3.update_last_sale(trade) pp3.calculate_performance() self.assertEqual( pp3.positions[1].last_sale_price, 10, "should have a last sale of 10" ) self.assertEqual( pp3.positions[1].cost_basis, 11, "should have a cost basis of 11" ) self.assertEqual( pp3.pnl, -400, "should be -400 for all trades and transactions in period" )
def test_cost_basis_calc(self): trades = factory.create_trade_history( 1, [10, 11, 11, 12], [100, 100, 100, 100], self.onesec, self.trading_environment ) transactions = factory.create_txn_history( 1, [10, 11, 11, 12], [100, 100, 100, 100], self.onesec, self.trading_environment ) pp = perf.PerformancePeriod(1000.0) for txn in transactions: pp.execute_transaction(txn) for trade in trades: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.positions[1].last_sale_price, trades[-1].price, "should have a last sale of 12, got {val}".format( val=pp.positions[1].last_sale_price) ) self.assertEqual( pp.positions[1].cost_basis, 11, "should have a cost basis of 11" ) self.assertEqual( pp.pnl, 400 ) saleTxn = factory.create_txn( 1, 10.0, -100, self.dt + self.onesec * 4) down_tick = factory.create_trade( 1, 10.0, 100, trades[-1].dt + self.onesec) pp.rollover() pp.execute_transaction(saleTxn) pp.update_last_sale(down_tick) pp.calculate_performance() self.assertEqual( pp.positions[1].last_sale_price, 10, "should have a last sale of 10, was {val}".format( val=pp.positions[1].last_sale_price) ) self.assertEqual( round(pp.positions[1].cost_basis, 2), 11.33, "should have a cost basis of 11.33" ) #print "second period pnl is {pnl}".format(pnl=pp2.pnl) self.assertEqual(pp.pnl, -800, "this period goes from +400 to -400") pp3 = perf.PerformancePeriod(1000.0) transactions.append(saleTxn) for txn in transactions: pp3.execute_transaction(txn) trades.append(down_tick) for trade in trades: pp3.update_last_sale(trade) pp3.calculate_performance() self.assertEqual( pp3.positions[1].last_sale_price, 10, "should have a last sale of 10" ) self.assertEqual( round(pp3.positions[1].cost_basis, 2), 11.33, "should have a cost basis of 11.33" ) self.assertEqual( pp3.pnl, -400, "should be -400 for all trades and transactions in period" )
def test_minute_tracker(self): """ Tests minute performance tracking.""" with trading.TradingEnvironment(): start_dt = trading.environment.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 9, 31)) end_dt = trading.environment.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 16, 0)) sim_params = SimulationParameters( period_start=start_dt, period_end=end_dt, emission_rate='minute' ) tracker = perf.PerformanceTracker(sim_params) foo_event_1 = factory.create_trade('foo', 10.0, 20, start_dt) order_event_1 = Order(sid=foo_event_1.sid, amount=-25, dt=foo_event_1.dt) bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt) txn_event_1 = Transaction(sid=foo_event_1.sid, amount=-25, dt=foo_event_1.dt, price=10.0, commission=0.50, order_id=order_event_1.id) benchmark_event_1 = Event({ 'dt': start_dt, 'returns': 0.01, 'type': DATASOURCE_TYPE.BENCHMARK }) foo_event_2 = factory.create_trade( 'foo', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) bar_event_2 = factory.create_trade( 'bar', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) benchmark_event_2 = Event({ 'dt': start_dt + datetime.timedelta(minutes=1), 'returns': 0.02, 'type': DATASOURCE_TYPE.BENCHMARK }) events = [ foo_event_1, order_event_1, benchmark_event_1, txn_event_1, bar_event_1, foo_event_2, benchmark_event_2, bar_event_2, ] grouped_events = itertools.groupby( events, operator.attrgetter('dt')) messages = {} for date, group in grouped_events: tracker.set_date(date) for event in group: tracker.process_event(event) tracker.handle_minute_close(date) msg = tracker.to_dict() messages[date] = msg self.assertEquals(2, len(messages)) msg_1 = messages[foo_event_1.dt] msg_2 = messages[foo_event_2.dt] self.assertEquals(1, len(msg_1['minute_perf']['transactions']), "The first message should contain one " "transaction.") # Check that transactions aren't emitted for previous events. self.assertEquals(0, len(msg_2['minute_perf']['transactions']), "The second message should have no " "transactions.") self.assertEquals(1, len(msg_1['minute_perf']['orders']), "The first message should contain one orders.") # Check that orders aren't emitted for previous events. self.assertEquals(0, len(msg_2['minute_perf']['orders']), "The second message should have no orders.") # Ensure that period_close moves through time. # Also, ensure that the period_closes are the expected dts. self.assertEquals(foo_event_1.dt, msg_1['minute_perf']['period_close']) self.assertEquals(foo_event_2.dt, msg_2['minute_perf']['period_close']) # Ensure that a Sharpe value for cumulative metrics is being # created. self.assertIsNotNone(msg_1['cumulative_risk_metrics']['sharpe']) self.assertIsNotNone(msg_2['cumulative_risk_metrics']['sharpe'])
def test_minute_tracker(self): """ Tests minute performance tracking.""" start_dt = trading.environment.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 9, 31)) end_dt = trading.environment.exchange_dt_in_utc( datetime.datetime(2013, 3, 1, 16, 0)) sim_params = SimulationParameters( period_start=start_dt, period_end=end_dt, emission_rate='minute' ) tracker = perf.PerformanceTracker(sim_params) foo_event_1 = factory.create_trade('foo', 10.0, 20, start_dt) order_event_1 = Order(**{ 'sid': foo_event_1.sid, 'amount': -25, 'dt': foo_event_1.dt }) bar_event_1 = factory.create_trade('bar', 100.0, 200, start_dt) txn_event_1 = Transaction(sid=foo_event_1.sid, amount=-25, dt=foo_event_1.dt, price=10.0, commission=0.50) benchmark_event_1 = Event({ 'dt': start_dt, 'returns': 1.0, 'type': DATASOURCE_TYPE.BENCHMARK }) foo_event_2 = factory.create_trade( 'foo', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) bar_event_2 = factory.create_trade( 'bar', 11.0, 20, start_dt + datetime.timedelta(minutes=1)) benchmark_event_2 = Event({ 'dt': start_dt + datetime.timedelta(minutes=1), 'returns': 2.0, 'type': DATASOURCE_TYPE.BENCHMARK }) events = [ foo_event_1, order_event_1, benchmark_event_1, txn_event_1, bar_event_1, foo_event_2, benchmark_event_2, bar_event_2, ] grouped_events = itertools.groupby( events, operator.attrgetter('dt')) messages = {} for date, group in grouped_events: tracker.set_date(date) for event in group: tracker.process_event(event) tracker.handle_minute_close(date) msg = tracker.to_dict() messages[date] = msg self.assertEquals(2, len(messages)) msg_1 = messages[foo_event_1.dt] msg_2 = messages[foo_event_2.dt] self.assertEquals(1, len(msg_1['minute_perf']['transactions']), "The first message should contain one transaction.") # Check that transactions aren't emitted for previous events. self.assertEquals(0, len(msg_2['minute_perf']['transactions']), "The second message should have no transactions.") self.assertEquals(1, len(msg_1['minute_perf']['orders']), "The first message should contain one orders.") # Check that orders aren't emitted for previous events. self.assertEquals(0, len(msg_2['minute_perf']['orders']), "The second message should have no orders.") # Ensure that period_close moves through time. # Also, ensure that the period_closes are the expected dts. self.assertEquals(foo_event_1.dt, msg_1['minute_perf']['period_close']) self.assertEquals(foo_event_2.dt, msg_2['minute_perf']['period_close'])
def test_cost_basis_calc(self): trades = factory.create_trade_history(1, [10, 11, 11, 12], [100, 100, 100, 100], onesec, self.sim_params) transactions = factory.create_txn_history(1, [10, 11, 11, 12], [100, 100, 100, 100], onesec, self.sim_params) pp = perf.PerformancePeriod(1000.0) for txn in transactions: pp.execute_transaction(txn) for trade in trades: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.positions[1].last_sale_price, trades[-1].price, "should have a last sale of 12, got {val}".format( val=pp.positions[1].last_sale_price)) self.assertEqual(pp.positions[1].cost_basis, 11, "should have a cost basis of 11") self.assertEqual(pp.pnl, 400) down_tick = factory.create_trade(1, 10.0, 100, trades[-1].dt + onesec) saleTxn = create_txn(down_tick, 10.0, -100) pp.rollover() pp.execute_transaction(saleTxn) pp.update_last_sale(down_tick) pp.calculate_performance() self.assertEqual( pp.positions[1].last_sale_price, 10, "should have a last sale of 10, was {val}".format( val=pp.positions[1].last_sale_price)) self.assertEqual(round(pp.positions[1].cost_basis, 2), 11.33, "should have a cost basis of 11.33") # print "second period pnl is {pnl}".format(pnl=pp2.pnl) self.assertEqual(pp.pnl, -800, "this period goes from +400 to -400") pp3 = perf.PerformancePeriod(1000.0) transactions.append(saleTxn) for txn in transactions: pp3.execute_transaction(txn) trades.append(down_tick) for trade in trades: pp3.update_last_sale(trade) pp3.calculate_performance() self.assertEqual(pp3.positions[1].last_sale_price, 10, "should have a last sale of 10") self.assertEqual(round(pp3.positions[1].cost_basis, 2), 11.33, "should have a cost basis of 11.33") self.assertEqual( pp3.pnl, -400, "should be -400 for all trades and transactions in period")
def test_cost_basis_calc(self): trades = factory.create_trade_history(1, [10, 11, 11, 12], [100, 100, 100, 100], self.onesec, self.trading_environment) transactions = factory.create_txn_history(1, [10, 11, 11, 12], [100, 100, 100, 100], self.onesec, self.trading_environment) pp = perf.PerformancePeriod({}, 0.0, 1000.0) for txn in transactions: pp.execute_transaction(txn) for trade in trades: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.positions[1].last_sale_price, trades[-1].price, "should have a last sale of 12, got {val}".format( val=pp.positions[1].last_sale_price)) self.assertEqual(pp.positions[1].cost_basis, 11, "should have a cost basis of 11") self.assertEqual(pp.pnl, 400) saleTxn = factory.create_txn(1, 10.0, -100, self.dt + self.onesec * 4) down_tick = factory.create_trade(1, 10.0, 100, trades[-1].dt + self.onesec) pp2 = perf.PerformancePeriod(copy.deepcopy(pp.positions), pp.ending_value, pp.ending_cash) pp2.execute_transaction(saleTxn) pp2.update_last_sale(down_tick) pp2.calculate_performance() self.assertEqual( pp2.positions[1].last_sale_price, 10, "should have a last sale of 10, was {val}".format( val=pp2.positions[1].last_sale_price)) self.assertEqual(round(pp2.positions[1].cost_basis, 2), 11.33, "should have a cost basis of 11.33") #print "second period pnl is {pnl}".format(pnl=pp2.pnl) self.assertEqual(pp2.pnl, -800, "this period goes from +400 to -400") pp3 = perf.PerformancePeriod({}, 0.0, 1000.0) transactions.append(saleTxn) for txn in transactions: pp3.execute_transaction(txn) trades.append(down_tick) for trade in trades: pp3.update_last_sale(trade) pp3.calculate_performance() self.assertEqual(pp3.positions[1].last_sale_price, 10, "should have a last sale of 10") self.assertEqual(round(pp3.positions[1].cost_basis, 2), 11.33, "should have a cost basis of 11.33") self.assertEqual( pp3.pnl, -400, "should be -400 for all trades and transactions in period")