mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-28 12:43:47 +08:00
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:
@@ -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'])
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user