Merge pull request #1413 from quantopian/normalize-equity-future-in-data-portal

MAINT: Remove future/equity distinction.
This commit is contained in:
Eddie Hebert
2016-08-18 23:50:36 -04:00
committed by GitHub
2 changed files with 33 additions and 502 deletions
-370
View File
@@ -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"""