BUG: Fixed random dips in returns as shown to user.

Previously the last sale price was not correctly being set on
positions when the transaction arrived before the trade event.
The last sale price was defaulted to zero and never updated. This resulted
in one holding stocks that were bough >>0 and now had value 0 from
the perspective of returns. The returns would display correctly again
when the next trade of that security happened. For most securities trading is
frequent enough that there's no issue, but for some illiquid ones it took
hours to fix itself.

Updated test_perf_tracking:TestPerformanceTracker.test_minute_tracker
This test was based on assuming that last_sale_price was zero,
allowing the sharpe ratio to be calculated. The sharpe ratio can no longer
be calculated for this specific tested scenario and the test has been changed
accordingly.
This commit is contained in:
Delaney Granizo-Mackenzie
2014-07-25 15:04:23 -04:00
parent d4d0477eb5
commit 0fd78cd54a
3 changed files with 20 additions and 3 deletions
+13 -3
View File
@@ -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'])
+1
View File
@@ -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
+6
View File
@@ -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):