def test_covering_short(self): """verify performance where short is bought and covered, and shares \ trade after cover""" trades = factory.create_trade_history( 1, [10, 10, 10, 11, 9, 8, 7, 8, 9, 10], [100, 100, 100, 100, 100, 100, 100, 100, 100, 100], self.onesec, self.trading_environment) short_txn = factory.create_txn(1, 10.0, -100, self.dt + self.onesec) cover_txn = factory.create_txn(1, 7.0, 100, self.dt + self.onesec * 6) pp = perf.PerformancePeriod({}, 0.0, 1000.0) pp.execute_transaction(short_txn) pp.execute_transaction(cover_txn) for trade in trades: pp.update_last_sale(trade) pp.calculate_performance() short_txn_cost = short_txn.price * short_txn.amount cover_txn_cost = cover_txn.price * cover_txn.amount self.assertEqual( pp.period_capital_used, -1 * short_txn_cost - cover_txn_cost, "capital used should be equal to the net transaction costs") self.assertEqual(len(pp.positions), 1, "should be just one position") self.assertEqual( pp.positions[1].sid, short_txn.sid, "position should be in security from the transaction") self.assertEqual(pp.positions[1].amount, 0, "should have a position of -100 shares") self.assertEqual(pp.positions[1].cost_basis, 0, "a covered position should have a cost basis of 0") self.assertEqual(pp.positions[1].last_sale_price, trades[-1].price, "last sale should be price of last trade") self.assertEqual( pp.ending_value, 0, "ending value should be price of last trade times number of \ shares in position") self.assertEqual(pp.pnl, 300, "gain of 1 on 100 shares should be 300")
def test_buy_and_sell_before_ex(self): #post some trades in the market events = factory.create_trade_history( 1, [10, 10, 10, 10, 10, 10], [100, 100, 100, 100, 100, 100], oneday, self.sim_params ) dividend = factory.create_dividend( 1, 10.00, events[3].dt, events[4].dt, events[5].dt ) buy_txn = factory.create_txn(1, 10.0, 100, events[1].dt) events[1].TRANSACTION = buy_txn sell_txn = factory.create_txn(1, 10.0, -100, events[2].dt) events[2].TRANSACTION = sell_txn events.insert(1, dividend) perf_tracker = perf.PerformanceTracker(self.sim_params) transformed_events = list(perf_tracker.transform( ((event.dt, [event]) for event in events)) ) #flatten the list of events results = [] for te in transformed_events: for event in te[1]: for message in event.perf_messages: results.append(message) perf_messages, risk = perf_tracker.handle_simulation_end() results.append(perf_messages[0]) self.assertEqual(len(results), 6) cumulative_returns = \ [event['cumulative_perf']['returns'] for event in results] self.assertEqual(cumulative_returns, [0, 0, 0, 0, 0, 0]) daily_returns = [event['daily_perf']['returns'] for event in results] self.assertEqual(daily_returns, [0, 0, 0, 0, 0, 0]) cash_flows = [event['daily_perf']['capital_used'] for event in results] self.assertEqual(cash_flows, [0, -1000, 1000, 0, 0, 0]) cumulative_cash_flows = \ [event['cumulative_perf']['capital_used'] for event in results] self.assertEqual(cumulative_cash_flows, [0, -1000, 0, 0, 0, 0])
def test_long_position_receives_dividend(self): #post some trades in the market events = factory.create_trade_history(1, [10, 10, 10, 10, 10], [100, 100, 100, 100, 100], oneday, self.sim_params) dividend = factory.create_dividend( 1, 10.00, # declared date, when the algorithm finds out about # the dividend events[1].dt, # ex_date, when the algorithm is credited with the # dividend events[1].dt, # pay date, when the algorithm receives the dividend. events[2].dt) txn = factory.create_txn(1, 10.0, 100, events[0].dt) events[0].TRANSACTION = txn events.insert(1, dividend) perf_tracker = perf.PerformanceTracker(self.sim_params) transformed_events = list( perf_tracker.transform(((event.dt, [event]) for event in events))) #flatten the list of events results = [] for te in transformed_events: for event in te[1]: for message in event.perf_messages: results.append(message) perf_messages, risk = perf_tracker.handle_simulation_end() results.append(perf_messages[0]) self.assertEqual(results[0]['daily_perf']['period_open'], events[0].dt) self.assertEqual(results[-1]['daily_perf']['period_open'], events[-1].dt) self.assertEqual(len(results), 5) cumulative_returns = \ [event['cumulative_perf']['returns'] for event in results] self.assertEqual(cumulative_returns, [0.0, 0.0, 0.1, 0.1, 0.1]) daily_returns = [event['daily_perf']['returns'] for event in results] self.assertEqual(daily_returns, [0.0, 0.0, 0.10, 0.0, 0.0]) cash_flows = [event['daily_perf']['capital_used'] for event in results] self.assertEqual(cash_flows, [-1000, 0, 1000, 0, 0]) cumulative_cash_flows = \ [event['cumulative_perf']['capital_used'] for event in results] self.assertEqual(cumulative_cash_flows, [-1000, -1000, 0, 0, 0]) cash_pos = \ [event['cumulative_perf']['ending_cash'] for event in results] self.assertEqual(cash_pos, [9000, 9000, 10000, 10000, 10000])
def test_long_position_receives_dividend(self): #post some trades in the market events = factory.create_trade_history( 1, [10, 10, 10, 10, 10], [100, 100, 100, 100, 100], oneday, self.trading_environment ) dividend = factory.create_dividend( 1, 10.00, events[0].dt, events[1].dt, events[2].dt ) events.insert(1, dividend) txn = factory.create_txn(1, 10.0, 100, self.dt+oneday) events[2].TRANSACTION = txn perf_tracker = perf.PerformanceTracker(self.trading_environment) transformed_events = list(perf_tracker.transform( ((event.dt, [event]) for event in events)) ) #flatten the list of events results = [] for te in transformed_events: for event in te[1]: for message in event.perf_messages: results.append(message) perf_messages, risk = perf_tracker.handle_simulation_end() results.append(perf_messages[0]) self.assertEqual(results[0]['daily_perf']['period_open'], events[0].dt) self.assertEqual( results[-1]['daily_perf']['period_open'], events[-1].dt ) self.assertEqual(len(results), 5) cumulative_returns = \ [event['cumulative_perf']['returns'] for event in results] self.assertEqual(cumulative_returns, [0.0, 0.0, 0.1, 0.1, 0.1]) daily_returns = [event['daily_perf']['returns'] for event in results] self.assertEqual(daily_returns, [0.0, 0.0, 0.10, 0.0, 0.0]) cash_flows = [event['daily_perf']['capital_used'] for event in results] self.assertEqual(cash_flows, [0, -1000, 1000, 0, 0]) cumulative_cash_flows = \ [event['cumulative_perf']['capital_used'] for event in results] self.assertEqual(cumulative_cash_flows, [0, -1000, 0, 0, 0])
def test_long_position(self): """ verify that the performance period calculates properly for a single buy transaction """ #post some trades in the market trades = factory.create_trade_history(1, [10, 10, 10, 11], [100, 100, 100, 100], self.onesec, self.trading_environment) txn = factory.create_txn(1, 10.0, 100, self.dt + self.onesec) pp = perf.PerformancePeriod({}, 0.0, 1000.0) pp.execute_transaction(txn) for trade in trades: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.period_capital_used, -1 * txn.price * txn.amount, "capital used should be equal to the opposite of the transaction \ cost of sole txn in test") self.assertEqual(len(pp.positions), 1, "should be just one position") self.assertEqual(pp.positions[1].sid, txn.sid, "position should be in security with id 1") self.assertEqual( pp.positions[1].amount, txn.amount, "should have a position of {sharecount} shares".format( sharecount=txn.amount)) self.assertEqual(pp.positions[1].cost_basis, txn.price, "should have a cost basis of 10") self.assertEqual( pp.positions[1].last_sale_price, trades[-1]['price'], "last sale should be same as last trade. \ expected {exp} actual {act}".format( exp=trades[-1]['price'], act=pp.positions[1].last_sale_price)) self.assertEqual( pp.ending_value, 1100, "ending value should be price of last trade times number of \ shares in position") self.assertEqual(pp.pnl, 100, "gain of 1 on 100 shares should be 100")
def test_long_position(self): """ verify that the performance period calculates properly for a single buy transaction """ #post some trades in the market trades = factory.create_trade_history( 1, [10, 10, 10, 11], [100, 100, 100, 100], self.onesec, self.trading_environment ) txn = factory.create_txn(1, 10.0, 100, self.dt + self.onesec) pp = perf.PerformancePeriod(1000.0) pp.execute_transaction(txn) for trade in trades: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.period_capital_used, -1 * txn.price * txn.amount, "capital used should be equal to the opposite of the transaction \ cost of sole txn in test" ) self.assertEqual( len(pp.positions), 1, "should be just one position") self.assertEqual( pp.positions[1].sid, txn.sid, "position should be in security with id 1") self.assertEqual( pp.positions[1].amount, txn.amount, "should have a position of {sharecount} shares".format( sharecount=txn.amount ) ) self.assertEqual( pp.positions[1].cost_basis, txn.price, "should have a cost basis of 10" ) self.assertEqual( pp.positions[1].last_sale_price, trades[-1]['price'], "last sale should be same as last trade. \ expected {exp} actual {act}".format( exp=trades[-1]['price'], act=pp.positions[1].last_sale_price) ) self.assertEqual( pp.ending_value, 1100, "ending value should be price of last trade times number of \ shares in position" ) self.assertEqual(pp.pnl, 100, "gain of 1 on 100 shares should be 100")
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_covering_short(self): """verify performance where short is bought and covered, and shares \ trade after cover""" trades = factory.create_trade_history( 1, [10, 10, 10, 11, 9, 8, 7, 8, 9, 10], [100, 100, 100, 100, 100, 100, 100, 100, 100, 100], self.onesec, self.trading_environment ) short_txn = factory.create_txn( 1, 10.0, -100, self.dt + self.onesec ) cover_txn = factory.create_txn(1, 7.0, 100, self.dt + self.onesec * 6) pp = perf.PerformancePeriod(1000.0) pp.execute_transaction(short_txn) pp.execute_transaction(cover_txn) for trade in trades: pp.update_last_sale(trade) pp.calculate_performance() short_txn_cost = short_txn.price * short_txn.amount cover_txn_cost = cover_txn.price * cover_txn.amount self.assertEqual( pp.period_capital_used, -1 * short_txn_cost - cover_txn_cost, "capital used should be equal to the net transaction costs" ) self.assertEqual( len(pp.positions), 1, "should be just one position" ) self.assertEqual( pp.positions[1].sid, short_txn.sid, "position should be in security from the transaction" ) self.assertEqual( pp.positions[1].amount, 0, "should have a position of -100 shares" ) self.assertEqual( pp.positions[1].cost_basis, 0, "a covered position should have a cost basis of 0" ) self.assertEqual( pp.positions[1].last_sale_price, trades[-1].price, "last sale should be price of last trade" ) self.assertEqual( pp.ending_value, 0, "ending value should be price of last trade times number of \ shares in position" ) self.assertEqual( pp.pnl, 300, "gain of 1 on 100 shares should be 300" )
def test_short_position(self): """verify that the performance period calculates properly for a \ single short-sale transaction""" trades = factory.create_trade_history( 1, [10, 10, 10, 11, 10, 9], [100, 100, 100, 100, 100, 100], self.onesec, self.trading_environment ) trades_1 = trades[:-2] txn = factory.create_txn(1, 10.0, -100, self.dt + self.onesec) pp = perf.PerformancePeriod(1000.0) pp.execute_transaction(txn) for trade in trades_1: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.period_capital_used, -1 * txn.price * txn.amount, "capital used should be equal to the opposite of the transaction\ cost of sole txn in test" ) self.assertEqual( len(pp.positions), 1, "should be just one position") self.assertEqual( pp.positions[1].sid, txn.sid, "position should be in security from the transaction" ) self.assertEqual( pp.positions[1].amount, -100, "should have a position of -100 shares" ) self.assertEqual( pp.positions[1].cost_basis, txn.price, "should have a cost basis of 10" ) self.assertEqual( pp.positions[1].last_sale_price, trades_1[-1]['price'], "last sale should be price of last trade" ) self.assertEqual( pp.ending_value, -1100, "ending value should be price of last trade times number of \ shares in position" ) self.assertEqual(pp.pnl, -100, "gain of 1 on 100 shares should be 100") # simulate additional trades, and ensure that the position value # reflects the new price trades_2 = trades[-2:] #simulate a rollover to a new period pp.rollover() for trade in trades_2: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.period_capital_used, 0, "capital used should be zero, there were no transactions in \ performance period" ) self.assertEqual( len(pp.positions), 1, "should be just one position" ) self.assertEqual( pp.positions[1].sid, txn.sid, "position should be in security from the transaction" ) self.assertEqual( pp.positions[1].amount, -100, "should have a position of -100 shares" ) self.assertEqual( pp.positions[1].cost_basis, txn.price, "should have a cost basis of 10" ) self.assertEqual( pp.positions[1].last_sale_price, trades_2[-1].price, "last sale should be price of last trade" ) self.assertEqual( pp.ending_value, -900, "ending value should be price of last trade times number of \ shares in position") self.assertEqual( pp.pnl, 200, "drop of 2 on -100 shares should be 200" ) #now run a performance period encompassing the entire trade sample. ppTotal = perf.PerformancePeriod(1000.0) for trade in trades_1: ppTotal.update_last_sale(trade) ppTotal.execute_transaction(txn) for trade in trades_2: ppTotal.update_last_sale(trade) ppTotal.calculate_performance() self.assertEqual( ppTotal.period_capital_used, -1 * txn.price * txn.amount, "capital used should be equal to the opposite of the transaction \ cost of sole txn in test" ) self.assertEqual( len(ppTotal.positions), 1, "should be just one position" ) self.assertEqual( ppTotal.positions[1].sid, txn.sid, "position should be in security from the transaction" ) self.assertEqual( ppTotal.positions[1].amount, -100, "should have a position of -100 shares" ) self.assertEqual( ppTotal.positions[1].cost_basis, txn.price, "should have a cost basis of 10" ) self.assertEqual( ppTotal.positions[1].last_sale_price, trades_2[-1].price, "last sale should be price of last trade" ) self.assertEqual( ppTotal.ending_value, -900, "ending value should be price of last trade times number of \ shares in position") self.assertEqual( ppTotal.pnl, 100, "drop of 1 on -100 shares should be 100" )
def test_long_position_receives_dividend(self): #post some trades in the market events = factory.create_trade_history( 1, [10, 10, 10, 10, 10], [100, 100, 100, 100, 100], oneday, self.sim_params ) dividend = factory.create_dividend( 1, 10.00, # declared date, when the algorithm finds out about # the dividend events[1].dt, # ex_date, when the algorithm is credited with the # dividend events[1].dt, # pay date, when the algorithm receives the dividend. events[2].dt ) txn = factory.create_txn(1, 10.0, 100, events[0].dt) events[0].TRANSACTION = txn events.insert(1, dividend) perf_tracker = perf.PerformanceTracker(self.sim_params) transformed_events = list(perf_tracker.transform( ((event.dt, [event]) for event in events)) ) #flatten the list of events results = [] for te in transformed_events: for event in te[1]: for message in event.perf_messages: results.append(message) perf_messages, risk = perf_tracker.handle_simulation_end() results.append(perf_messages[0]) self.assertEqual(results[0]['daily_perf']['period_open'], events[0].dt) self.assertEqual( results[-1]['daily_perf']['period_open'], events[-1].dt ) self.assertEqual(len(results), 5) cumulative_returns = \ [event['cumulative_perf']['returns'] for event in results] self.assertEqual(cumulative_returns, [0.0, 0.0, 0.1, 0.1, 0.1]) daily_returns = [event['daily_perf']['returns'] for event in results] self.assertEqual(daily_returns, [0.0, 0.0, 0.10, 0.0, 0.0]) cash_flows = [event['daily_perf']['capital_used'] for event in results] self.assertEqual(cash_flows, [-1000, 0, 1000, 0, 0]) cumulative_cash_flows = \ [event['cumulative_perf']['capital_used'] for event in results] self.assertEqual(cumulative_cash_flows, [-1000, -1000, 0, 0, 0]) cash_pos = \ [event['cumulative_perf']['ending_cash'] for event in results] self.assertEqual(cash_pos, [9000, 9000, 10000, 10000, 10000])
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")
def test_short_position(self): """verify that the performance period calculates properly for a \ single short-sale transaction""" trades = factory.create_trade_history(1, [10, 10, 10, 11, 10, 9], [100, 100, 100, 100, 100, 100], self.onesec, self.trading_environment) trades_1 = trades[:-2] txn = factory.create_txn(1, 10.0, -100, self.dt + self.onesec) pp = perf.PerformancePeriod({}, 0.0, 1000.0) pp.execute_transaction(txn) for trade in trades_1: pp.update_last_sale(trade) pp.calculate_performance() self.assertEqual( pp.period_capital_used, -1 * txn.price * txn.amount, "capital used should be equal to the opposite of the transaction\ cost of sole txn in test") self.assertEqual(len(pp.positions), 1, "should be just one position") self.assertEqual( pp.positions[1].sid, txn.sid, "position should be in security from the transaction") self.assertEqual(pp.positions[1].amount, -100, "should have a position of -100 shares") self.assertEqual(pp.positions[1].cost_basis, txn.price, "should have a cost basis of 10") self.assertEqual(pp.positions[1].last_sale_price, trades_1[-1]['price'], "last sale should be price of last trade") self.assertEqual( pp.ending_value, -1100, "ending value should be price of last trade times number of \ shares in position") self.assertEqual(pp.pnl, -100, "gain of 1 on 100 shares should be 100") # simulate additional trades, and ensure that the position value # reflects the new price trades_2 = trades[-2:] #simulate a rollover to a new period pp2 = perf.PerformancePeriod(pp.positions, pp.ending_value, pp.ending_cash) for trade in trades_2: pp2.update_last_sale(trade) pp2.calculate_performance() self.assertEqual( pp2.period_capital_used, 0, "capital used should be zero, there were no transactions in \ performance period") self.assertEqual(len(pp2.positions), 1, "should be just one position") self.assertEqual( pp2.positions[1].sid, txn.sid, "position should be in security from the transaction") self.assertEqual(pp2.positions[1].amount, -100, "should have a position of -100 shares") self.assertEqual(pp2.positions[1].cost_basis, txn.price, "should have a cost basis of 10") self.assertEqual(pp2.positions[1].last_sale_price, trades_2[-1].price, "last sale should be price of last trade") self.assertEqual( pp2.ending_value, -900, "ending value should be price of last trade times number of \ shares in position") self.assertEqual(pp2.pnl, 200, "drop of 2 on -100 shares should be 200") #now run a performance period encompassing the entire trade sample. ppTotal = perf.PerformancePeriod({}, 0.0, 1000.0) for trade in trades_1: ppTotal.update_last_sale(trade) ppTotal.execute_transaction(txn) for trade in trades_2: ppTotal.update_last_sale(trade) ppTotal.calculate_performance() self.assertEqual( ppTotal.period_capital_used, -1 * txn.price * txn.amount, "capital used should be equal to the opposite of the transaction \ cost of sole txn in test") self.assertEqual(len(ppTotal.positions), 1, "should be just one position") self.assertEqual( ppTotal.positions[1].sid, txn.sid, "position should be in security from the transaction") self.assertEqual(ppTotal.positions[1].amount, -100, "should have a position of -100 shares") self.assertEqual(ppTotal.positions[1].cost_basis, txn.price, "should have a cost basis of 10") self.assertEqual(ppTotal.positions[1].last_sale_price, trades_2[-1].price, "last sale should be price of last trade") self.assertEqual( ppTotal.ending_value, -900, "ending value should be price of last trade times number of \ shares in position") self.assertEqual(ppTotal.pnl, 100, "drop of 1 on -100 shares should be 100")