diff --git a/tests/test_perf_tracking.py b/tests/test_perf_tracking.py index 87951e1b..39e0c420 100644 --- a/tests/test_perf_tracking.py +++ b/tests/test_perf_tracking.py @@ -760,6 +760,14 @@ class TestPositionPerformance(unittest.TestCase): pp = perf.PerformancePeriod(1000.0) pp.execute_transaction(txn) + + # This verifies that the last sale price is being correctly + # set in the positions. If this is not the case then returns can + # incorrectly show as sharply dipping if a transaction arrives + # before a trade. This is caused by returns being based on holding + # stocks with a last sale price of 0. + self.assertEqual(pp.positions[1].last_sale_price, 10.0) + for trade in trades: pp.update_last_sale(trade) @@ -1487,7 +1495,9 @@ class TestPerformanceTracker(unittest.TestCase): 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']) + # 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']) diff --git a/zipline/finance/performance/period.py b/zipline/finance/performance/period.py index aa8e752c..f8400acf 100644 --- a/zipline/finance/performance/period.py +++ b/zipline/finance/performance/period.py @@ -303,6 +303,7 @@ class PerformancePeriod(object): position.update(txn) self.ensure_position_index(txn.sid) self._position_amounts[txn.sid] = position.amount + self._position_last_sale_prices[txn.sid] = position.last_sale_price self.period_cash_flow -= txn.price * txn.amount diff --git a/zipline/finance/performance/position.py b/zipline/finance/performance/position.py index 008ced15..52bda2be 100644 --- a/zipline/finance/performance/position.py +++ b/zipline/finance/performance/position.py @@ -152,6 +152,12 @@ class Position(object): total_cost = prev_cost + txn_cost self.cost_basis = total_cost / total_shares + # Update the last sale price if txn is + # best data we have so far + if self.last_sale_date is None or txn.dt > self.last_sale_date: + self.last_sale_price = txn.price + self.last_sale_date = txn.dt + self.amount = total_shares def adjust_commission_cost_basis(self, commission):