mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-07 14:22:56 +08:00
Rolls over existing PerformancePeriod.
Instead of doing the rollover by creating a new PerformancePeriod, introduces a `rollover` method that resets the values that need to be fresh in a new period, and moves the ending values to starting values, and leaves positions intact. This isn't a major runtime improvement in of itself, but it does allow us to more easily keep track of position values from period to period, which other improvements will use.
This commit is contained in:
+25
-33
@@ -94,7 +94,7 @@ check treasury and benchmark data in findb, and re-run the test."""
|
||||
)
|
||||
|
||||
txn = factory.create_txn(1, 10.0, 100, self.dt + self.onesec)
|
||||
pp = perf.PerformancePeriod({}, 0.0, 1000.0)
|
||||
pp = perf.PerformancePeriod(1000.0)
|
||||
|
||||
pp.execute_transaction(txn)
|
||||
for trade in trades:
|
||||
@@ -165,7 +165,7 @@ single short-sale transaction"""
|
||||
trades_1 = trades[:-2]
|
||||
|
||||
txn = factory.create_txn(1, 10.0, -100, self.dt + self.onesec)
|
||||
pp = perf.PerformancePeriod({}, 0.0, 1000.0)
|
||||
pp = perf.PerformancePeriod(1000.0)
|
||||
|
||||
pp.execute_transaction(txn)
|
||||
for trade in trades_1:
|
||||
@@ -223,68 +223,64 @@ single short-sale transaction"""
|
||||
trades_2 = trades[-2:]
|
||||
|
||||
#simulate a rollover to a new period
|
||||
pp2 = perf.PerformancePeriod(
|
||||
pp.positions,
|
||||
pp.ending_value,
|
||||
pp.ending_cash
|
||||
)
|
||||
pp.rollover()
|
||||
|
||||
for trade in trades_2:
|
||||
pp2.update_last_sale(trade)
|
||||
pp.update_last_sale(trade)
|
||||
|
||||
pp2.calculate_performance()
|
||||
pp.calculate_performance()
|
||||
|
||||
self.assertEqual(
|
||||
pp2.period_capital_used,
|
||||
pp.period_capital_used,
|
||||
0,
|
||||
"capital used should be zero, there were no transactions in \
|
||||
performance period"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
len(pp2.positions),
|
||||
len(pp.positions),
|
||||
1,
|
||||
"should be just one position"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp2.positions[1].sid,
|
||||
pp.positions[1].sid,
|
||||
txn.sid,
|
||||
"position should be in security from the transaction"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp2.positions[1].amount,
|
||||
pp.positions[1].amount,
|
||||
-100,
|
||||
"should have a position of -100 shares"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp2.positions[1].cost_basis,
|
||||
pp.positions[1].cost_basis,
|
||||
txn.price,
|
||||
"should have a cost basis of 10"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp2.positions[1].last_sale_price,
|
||||
pp.positions[1].last_sale_price,
|
||||
trades_2[-1].price,
|
||||
"last sale should be price of last trade"
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
pp2.ending_value,
|
||||
pp.ending_value,
|
||||
-900,
|
||||
"ending value should be price of last trade times number of \
|
||||
shares in position")
|
||||
|
||||
self.assertEqual(
|
||||
pp2.pnl,
|
||||
pp.pnl,
|
||||
200,
|
||||
"drop of 2 on -100 shares should be 200"
|
||||
)
|
||||
|
||||
#now run a performance period encompassing the entire trade sample.
|
||||
ppTotal = perf.PerformancePeriod({}, 0.0, 1000.0)
|
||||
ppTotal = perf.PerformancePeriod(1000.0)
|
||||
|
||||
for trade in trades_1:
|
||||
ppTotal.update_last_sale(trade)
|
||||
@@ -364,7 +360,7 @@ trade after cover"""
|
||||
)
|
||||
|
||||
cover_txn = factory.create_txn(1, 7.0, 100, self.dt + self.onesec * 6)
|
||||
pp = perf.PerformancePeriod({}, 0.0, 1000.0)
|
||||
pp = perf.PerformancePeriod(1000.0)
|
||||
|
||||
pp.execute_transaction(short_txn)
|
||||
pp.execute_transaction(cover_txn)
|
||||
@@ -443,7 +439,7 @@ shares in position"
|
||||
self.trading_environment
|
||||
)
|
||||
|
||||
pp = perf.PerformancePeriod({}, 0.0, 1000.0)
|
||||
pp = perf.PerformancePeriod(1000.0)
|
||||
|
||||
for txn in transactions:
|
||||
pp.execute_transaction(txn)
|
||||
@@ -483,33 +479,29 @@ shares in position"
|
||||
100,
|
||||
trades[-1].dt + self.onesec)
|
||||
|
||||
pp2 = perf.PerformancePeriod(
|
||||
copy.deepcopy(pp.positions),
|
||||
pp.ending_value,
|
||||
pp.ending_cash
|
||||
)
|
||||
pp.rollover()
|
||||
|
||||
pp2.execute_transaction(saleTxn)
|
||||
pp2.update_last_sale(down_tick)
|
||||
pp.execute_transaction(saleTxn)
|
||||
pp.update_last_sale(down_tick)
|
||||
|
||||
pp2.calculate_performance()
|
||||
pp.calculate_performance()
|
||||
self.assertEqual(
|
||||
pp2.positions[1].last_sale_price,
|
||||
pp.positions[1].last_sale_price,
|
||||
10,
|
||||
"should have a last sale of 10, was {val}".format(
|
||||
val=pp2.positions[1].last_sale_price)
|
||||
val=pp.positions[1].last_sale_price)
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
round(pp2.positions[1].cost_basis, 2),
|
||||
round(pp.positions[1].cost_basis, 2),
|
||||
11.33,
|
||||
"should have a cost basis of 11.33"
|
||||
)
|
||||
|
||||
#print "second period pnl is {pnl}".format(pnl=pp2.pnl)
|
||||
self.assertEqual(pp2.pnl, -800, "this period goes from +400 to -400")
|
||||
self.assertEqual(pp.pnl, -800, "this period goes from +400 to -400")
|
||||
|
||||
pp3 = perf.PerformancePeriod({}, 0.0, 1000.0)
|
||||
pp3 = perf.PerformancePeriod(1000.0)
|
||||
|
||||
transactions.append(saleTxn)
|
||||
for txn in transactions:
|
||||
|
||||
@@ -179,10 +179,6 @@ class PerformanceTracker(object):
|
||||
|
||||
# this performance period will span the entire simulation.
|
||||
self.cumulative_performance = PerformancePeriod(
|
||||
# initial positions are empty
|
||||
positiondict(),
|
||||
# initial portfolio positions have zero value
|
||||
0,
|
||||
# initial cash is your capital base.
|
||||
self.capital_base,
|
||||
# the cumulative period will be calculated over the entire test.
|
||||
@@ -192,10 +188,6 @@ class PerformanceTracker(object):
|
||||
|
||||
# this performance period will span just the current market day
|
||||
self.todays_performance = PerformancePeriod(
|
||||
# initial positions are empty
|
||||
positiondict(),
|
||||
# initial portfolio positions have zero value
|
||||
0,
|
||||
# initial cash is your capital base.
|
||||
self.capital_base,
|
||||
# the daily period will be calculated for the market day
|
||||
@@ -313,14 +305,9 @@ Last successful date: %s" % self.market_open)
|
||||
self.market_close = self.market_open + self.trading_day
|
||||
|
||||
# Roll over positions to current day.
|
||||
self.todays_performance = PerformancePeriod(
|
||||
self.todays_performance.positions,
|
||||
self.todays_performance.ending_value,
|
||||
self.todays_performance.ending_cash,
|
||||
self.market_open,
|
||||
self.market_close,
|
||||
keep_transactions=True
|
||||
)
|
||||
self.todays_performance.rollover()
|
||||
self.todays_performance.period_open = self.market_open
|
||||
self.todays_performance.period_close = self.market_close
|
||||
|
||||
return daily_update
|
||||
|
||||
@@ -410,8 +397,6 @@ class PerformancePeriod(object):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
initial_positions,
|
||||
starting_value,
|
||||
starting_cash,
|
||||
period_open=None,
|
||||
period_close=None,
|
||||
@@ -424,12 +409,8 @@ class PerformancePeriod(object):
|
||||
self.period_capital_used = 0.0
|
||||
self.pnl = 0.0
|
||||
#sid => position object
|
||||
if not isinstance(initial_positions, positiondict):
|
||||
self.positions = positiondict()
|
||||
self.positions.update(initial_positions)
|
||||
else:
|
||||
self.positions = initial_positions
|
||||
self.starting_value = starting_value
|
||||
self.positions = positiondict()
|
||||
self.starting_value = 0.0
|
||||
#cash balance at start of period
|
||||
self.starting_cash = starting_cash
|
||||
self.ending_cash = starting_cash
|
||||
@@ -447,6 +428,16 @@ class PerformancePeriod(object):
|
||||
self._portfolio_store = zp.Portfolio()
|
||||
self._positions_store = zp.Positions()
|
||||
|
||||
def rollover(self):
|
||||
self.starting_value = self.ending_value
|
||||
self.starting_cash = self.ending_cash
|
||||
self.period_capital_used = 0.0
|
||||
self.pnl = 0.0
|
||||
self.processed_transactions = []
|
||||
self.cumulative_capital_used = 0.0
|
||||
self.max_capital_used = 0.0
|
||||
self.max_leverage = 0.0
|
||||
|
||||
def calculate_performance(self):
|
||||
self.ending_value = self.calculate_positions_value()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user