mirror of
https://github.com/wassname/catalyst.git
synced 2026-08-04 12:45:06 +08:00
MAINT: Remove future/equity distinction.
In the data portal, remove methods that make a distinction between future and equity asset type. Instead rely on the pricing reader dispatching. In support of incoming work which will upsample equity history arrays to the larger future calendar. Also, remove perf tracker tests which were using an equity reader/writer, to be added back in later.
This commit is contained in:
@@ -1615,376 +1615,6 @@ cost of sole txn in test"
|
||||
net_leverage=-0.8181,
|
||||
net_liquidation=1100.0)
|
||||
|
||||
def test_long_future_position(self):
|
||||
"""
|
||||
verify that the performance period calculates properly for a
|
||||
single buy transaction
|
||||
"""
|
||||
self.create_environment_stuff()
|
||||
sim_params = copy.copy(self.sim_params)
|
||||
sim_params.data_frequency = 'minute'
|
||||
|
||||
# post some trades in the market
|
||||
trades = factory.create_trade_history(
|
||||
self.asset3,
|
||||
[10, 10, 10, 11],
|
||||
[100, 100, 100, 100],
|
||||
oneday,
|
||||
sim_params,
|
||||
trading_calendar=self.trading_calendar,
|
||||
)
|
||||
|
||||
data_portal = create_data_portal_from_trade_history(
|
||||
self.env.asset_finder,
|
||||
self.trading_calendar,
|
||||
self.instance_tmpdir,
|
||||
self.sim_params,
|
||||
{3: trades}
|
||||
)
|
||||
|
||||
txn = create_txn(self.asset3, trades[1].dt, 10.0, 1)
|
||||
pt = perf.PositionTracker(self.env.asset_finder,
|
||||
self.sim_params.data_frequency)
|
||||
pp = perf.PerformancePeriod(1000.0, self.env.asset_finder,
|
||||
self.sim_params.data_frequency)
|
||||
pp.position_tracker = pt
|
||||
|
||||
pt.execute_transaction(txn)
|
||||
pp.handle_execution(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[3].last_sale_price, 10.0)
|
||||
|
||||
pt.sync_last_sale_prices(trades[-1].dt, False, data_portal)
|
||||
pp.calculate_performance()
|
||||
|
||||
self.assertEqual(
|
||||
pp.cash_flow,
|
||||
0,
|
||||
"there should be no cash flow on a futures txn"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
len(pp.positions),
|
||||
1,
|
||||
"should be just one position")
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].sid,
|
||||
txn.sid,
|
||||
"position should be in security with id 1")
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].amount,
|
||||
txn.amount,
|
||||
"should have a position of {sharecount} shares".format(
|
||||
sharecount=txn.amount
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].cost_basis,
|
||||
txn.price,
|
||||
"should have a cost basis of 10"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].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[3].last_sale_price)
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.ending_value,
|
||||
0,
|
||||
"ending value should be 0 because only futures are held"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.ending_exposure,
|
||||
1100,
|
||||
"ending exposure should be price of last trade times number of \
|
||||
contracts in position")
|
||||
|
||||
self.assertEqual(pp.pnl, 100, "gain of 1 on 1 100x contract should be "
|
||||
"100")
|
||||
|
||||
check_perf_period(
|
||||
pp,
|
||||
gross_leverage=1.0,
|
||||
net_leverage=1.0,
|
||||
long_exposure=1100.0,
|
||||
longs_count=1,
|
||||
short_exposure=0.0,
|
||||
shorts_count=0)
|
||||
|
||||
# Validate that the account attributes were updated.
|
||||
account = pp.as_account()
|
||||
check_account(account,
|
||||
settled_cash=1100.0,
|
||||
equity_with_loan=1100.0,
|
||||
total_positions_value=0.0,
|
||||
total_positions_exposure=1100.0,
|
||||
regt_equity=1100.0,
|
||||
available_funds=1100.0,
|
||||
excess_liquidity=1100.0,
|
||||
cushion=1.0,
|
||||
leverage=1.0,
|
||||
net_leverage=1.0,
|
||||
net_liquidation=1100.0)
|
||||
|
||||
def test_short_future_position(self):
|
||||
"""verify that the performance period calculates properly for a \
|
||||
single short-sale transaction"""
|
||||
self.create_environment_stuff(num_days=6)
|
||||
|
||||
trades = factory.create_trade_history(
|
||||
self.asset3,
|
||||
[10, 10, 10, 11, 10, 9],
|
||||
[100, 100, 100, 100, 100, 100],
|
||||
oneday,
|
||||
self.sim_params,
|
||||
trading_calendar=self.trading_calendar,
|
||||
)
|
||||
|
||||
data_portal = create_data_portal_from_trade_history(
|
||||
self.env.asset_finder,
|
||||
self.trading_calendar,
|
||||
self.instance_tmpdir,
|
||||
self.sim_params,
|
||||
{3: trades}
|
||||
)
|
||||
trades_1 = trades[:-2]
|
||||
|
||||
txn = create_txn(self.asset3, trades[0].dt, 10.0, -1)
|
||||
pt = perf.PositionTracker(self.env.asset_finder,
|
||||
self.sim_params.data_frequency)
|
||||
pp = perf.PerformancePeriod(1000.0, self.env.asset_finder,
|
||||
self.sim_params.data_frequency)
|
||||
pp.position_tracker = pt
|
||||
|
||||
pt.execute_transaction(txn)
|
||||
pp.handle_execution(txn)
|
||||
|
||||
pt.sync_last_sale_prices(trades[-3].dt, False, data_portal)
|
||||
pp.calculate_performance()
|
||||
|
||||
self.assertEqual(
|
||||
pp.cash_flow,
|
||||
0,
|
||||
"there should be no cash flow on a futures txn"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
len(pp.positions),
|
||||
1,
|
||||
"should be just one position")
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].sid,
|
||||
txn.sid,
|
||||
"position should be in future from the transaction"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].amount,
|
||||
-1,
|
||||
"should have a position of -1 contract"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].cost_basis,
|
||||
txn.price,
|
||||
"should have a cost basis of 10"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].last_sale_price,
|
||||
trades_1[-1]['price'],
|
||||
"last sale should be price of last trade"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.ending_value,
|
||||
0,
|
||||
"ending value should be 0 because only futures are held"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.ending_exposure,
|
||||
-1100,
|
||||
"ending exposure should be price of last trade times number of \
|
||||
contracts in position")
|
||||
|
||||
self.assertEqual(pp.pnl, -100, "gain of 1 on 1 100x contract 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()
|
||||
|
||||
pt.sync_last_sale_prices(trades_2[-1].dt, False, data_portal)
|
||||
pp.calculate_performance()
|
||||
|
||||
self.assertEqual(
|
||||
pp.cash_flow,
|
||||
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[3].sid,
|
||||
txn.sid,
|
||||
"position should be in future from the transaction"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].amount,
|
||||
-1,
|
||||
"should have a position of -1 contract"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].cost_basis,
|
||||
txn.price,
|
||||
"should have a cost basis of 10"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.positions[3].last_sale_price,
|
||||
trades_2[-1].price,
|
||||
"last sale should be price of last trade"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.ending_value,
|
||||
0,
|
||||
"ending value should be 0 because only futures are held")
|
||||
|
||||
self.assertEqual(
|
||||
pp.ending_exposure,
|
||||
-900,
|
||||
"ending exposure should be price of last trade times number of \
|
||||
shares in position")
|
||||
|
||||
self.assertEqual(
|
||||
pp.pnl,
|
||||
200,
|
||||
"drop of 2 on -1 100x contract should be 200"
|
||||
)
|
||||
|
||||
# now run a performance period encompassing the entire trade sample.
|
||||
ptTotal = perf.PositionTracker(self.env.asset_finder,
|
||||
self.sim_params.data_frequency)
|
||||
ppTotal = perf.PerformancePeriod(1000.0, self.env.asset_finder,
|
||||
self.sim_params.data_frequency)
|
||||
ppTotal.position_tracker = ptTotal
|
||||
|
||||
for trade in trades_1:
|
||||
ptTotal.sync_last_sale_prices(trade.dt, False, data_portal)
|
||||
|
||||
ptTotal.execute_transaction(txn)
|
||||
ppTotal.handle_execution(txn)
|
||||
|
||||
for trade in trades_2:
|
||||
ptTotal.sync_last_sale_prices(trade.dt, False, data_portal)
|
||||
|
||||
ppTotal.calculate_performance()
|
||||
|
||||
self.assertEqual(
|
||||
ppTotal.cash_flow,
|
||||
0,
|
||||
"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[3].sid,
|
||||
txn.sid,
|
||||
"position should be in security from the transaction"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
ppTotal.positions[3].amount,
|
||||
-1,
|
||||
"should have a position of -1 contract"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
ppTotal.positions[3].cost_basis,
|
||||
txn.price,
|
||||
"should have a cost basis of 10"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
ppTotal.positions[3].last_sale_price,
|
||||
trades_2[-1].price,
|
||||
"last sale should be price of last trade"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp.ending_value,
|
||||
0,
|
||||
"ending value should be 0 because only futures are held")
|
||||
|
||||
self.assertEqual(
|
||||
pp.ending_exposure,
|
||||
-900,
|
||||
"ending exposure should be price of last trade times number of \
|
||||
shares in position")
|
||||
|
||||
self.assertEqual(
|
||||
ppTotal.pnl,
|
||||
100,
|
||||
"drop of 1 on -1 100x contract should be 100"
|
||||
)
|
||||
|
||||
check_perf_period(
|
||||
pp,
|
||||
gross_leverage=0.8181,
|
||||
net_leverage=-0.8181,
|
||||
long_exposure=0.0,
|
||||
longs_count=0,
|
||||
short_exposure=-900.0,
|
||||
shorts_count=1)
|
||||
|
||||
# Validate that the account attributes.
|
||||
account = ppTotal.as_account()
|
||||
check_account(account,
|
||||
settled_cash=1100.0,
|
||||
equity_with_loan=1100.0,
|
||||
total_positions_value=0.0,
|
||||
total_positions_exposure=-900.0,
|
||||
regt_equity=1100.0,
|
||||
available_funds=1100.0,
|
||||
excess_liquidity=1100.0,
|
||||
cushion=1.0,
|
||||
leverage=0.8181,
|
||||
net_leverage=-0.8181,
|
||||
net_liquidation=1100.0)
|
||||
|
||||
def test_covering_short(self):
|
||||
"""verify performance where short is bought and covered, and shares \
|
||||
trade after cover"""
|
||||
|
||||
Reference in New Issue
Block a user