mirror of
https://github.com/wassname/catalyst.git
synced 2026-06-30 10:13:05 +08:00
Merge pull request #1359 from quantopian/refactor_subperiod
MAINT: Refactor application of capital changes
This commit is contained in:
@@ -2264,12 +2264,11 @@ shares in position"
|
||||
pt.execute_transaction(txn)
|
||||
pp.handle_execution(txn)
|
||||
|
||||
# sync prices and calculate performance before we introduce a capital
|
||||
# change
|
||||
# sync prices before we introduce a capital change
|
||||
pt.sync_last_sale_prices(trades[2].dt, False, data_portal)
|
||||
pp.calculate_performance()
|
||||
|
||||
pp.subdivide_period(1000.0)
|
||||
pp.initialize_subperiod_divider()
|
||||
pp.set_current_subperiod_starting_values(1000.0)
|
||||
|
||||
pt.sync_last_sale_prices(trades[-1].dt, False, data_portal)
|
||||
pp.calculate_performance()
|
||||
|
||||
+4
-17
@@ -844,25 +844,12 @@ class TradingAlgorithm(object):
|
||||
self.data_portal
|
||||
)
|
||||
|
||||
# Calculate performance before we sync prices price for the current dt
|
||||
self.perf_tracker.cumulative_performance.calculate_performance()
|
||||
self.perf_tracker.todays_performance.calculate_performance()
|
||||
self.perf_tracker.prepare_capital_change(is_interday)
|
||||
|
||||
if capital_change['type'] == 'target':
|
||||
# Get an updated portfolio value as of this dt, but do it in a way
|
||||
# so that the performance is not recalculated. This is done so
|
||||
# that `process_capital_change` can find the performance values
|
||||
# for the end of the subperiod, which is the previous dt
|
||||
self.perf_tracker.position_tracker.sync_last_sale_prices(
|
||||
dt,
|
||||
self._in_before_trading_start,
|
||||
self.data_portal
|
||||
)
|
||||
portfolio_value = \
|
||||
self.perf_tracker.position_tracker.stats().net_value + \
|
||||
self.perf_tracker.cumulative_performance.ending_cash
|
||||
|
||||
capital_change_amount = capital_change['value'] - portfolio_value
|
||||
capital_change_amount = capital_change['value'] - \
|
||||
self.updated_portfolio().portfolio_value
|
||||
self.portfolio_needs_update = True
|
||||
|
||||
log.info('Processing capital change to target %s at %s. Capital '
|
||||
'change delta is %s' % (capital_change['value'], dt,
|
||||
|
||||
@@ -241,14 +241,12 @@ class PerformancePeriod(object):
|
||||
else:
|
||||
del self._payout_last_sale_prices[asset]
|
||||
|
||||
def subdivide_period(self, capital_change):
|
||||
# Apply the capital change to the ending cash
|
||||
self.ending_cash += capital_change
|
||||
def initialize_subperiod_divider(self):
|
||||
self.calculate_performance()
|
||||
|
||||
# Increment the total capital change occurred within the period
|
||||
self._total_intraperiod_capital_change += capital_change
|
||||
|
||||
# Divide the period into subperiods
|
||||
# Initialize a subperiod divider to stash the current performance
|
||||
# values. Current period starting values are set to equal ending values
|
||||
# of the previous subperiod
|
||||
self.subperiod_divider = SubPeriodDivider(
|
||||
prev_returns=self.returns,
|
||||
prev_pnl=self.pnl,
|
||||
@@ -257,6 +255,20 @@ class PerformancePeriod(object):
|
||||
curr_starting_cash=self.ending_cash
|
||||
)
|
||||
|
||||
def set_current_subperiod_starting_values(self, capital_change):
|
||||
# Apply the capital change to the ending cash
|
||||
self.ending_cash += capital_change
|
||||
|
||||
# Increment the total capital change occurred within the period
|
||||
self._total_intraperiod_capital_change += capital_change
|
||||
|
||||
# Update the current subperiod starting cash to reflect the capital
|
||||
# change
|
||||
starting_value = self.subperiod_divider.curr_subperiod.starting_value
|
||||
self.subperiod_divider.curr_subperiod = CurrSubPeriodStats(
|
||||
starting_value=starting_value,
|
||||
starting_cash=self.ending_cash)
|
||||
|
||||
def handle_dividends_paid(self, net_cash_payment):
|
||||
if net_cash_payment:
|
||||
self.handle_cash_payment(net_cash_payment)
|
||||
|
||||
@@ -238,8 +238,16 @@ class PerformanceTracker(object):
|
||||
|
||||
return _dict
|
||||
|
||||
def prepare_capital_change(self, is_interday):
|
||||
self.cumulative_performance.initialize_subperiod_divider()
|
||||
|
||||
if not is_interday:
|
||||
# Change comes in the middle of day
|
||||
self.todays_performance.initialize_subperiod_divider()
|
||||
|
||||
def process_capital_change(self, capital_change_amount, is_interday):
|
||||
self.cumulative_performance.subdivide_period(capital_change_amount)
|
||||
self.cumulative_performance.set_current_subperiod_starting_values(
|
||||
capital_change_amount)
|
||||
|
||||
if is_interday:
|
||||
# Change comes between days
|
||||
@@ -247,7 +255,8 @@ class PerformanceTracker(object):
|
||||
capital_change_amount)
|
||||
else:
|
||||
# Change comes in the middle of day
|
||||
self.todays_performance.subdivide_period(capital_change_amount)
|
||||
self.todays_performance.set_current_subperiod_starting_values(
|
||||
capital_change_amount)
|
||||
|
||||
def process_transaction(self, transaction):
|
||||
self.txn_count += 1
|
||||
|
||||
@@ -100,11 +100,11 @@ class AlgorithmSimulator(object):
|
||||
def every_bar(dt_to_use, current_data=self.current_data,
|
||||
handle_data=algo.event_manager.handle_data):
|
||||
# called every tick (minute or day).
|
||||
algo.on_dt_changed(dt_to_use)
|
||||
|
||||
calculate_minute_capital_changes(dt_to_use)
|
||||
|
||||
self.simulation_dt = dt_to_use
|
||||
algo.on_dt_changed(dt_to_use)
|
||||
|
||||
blotter = algo.blotter
|
||||
perf_tracker = algo.perf_tracker
|
||||
@@ -149,10 +149,6 @@ class AlgorithmSimulator(object):
|
||||
|
||||
perf_tracker = algo.perf_tracker
|
||||
|
||||
# process any capital changes that came overnight
|
||||
algo.calculate_capital_changes(
|
||||
midnight_dt, emission_rate=emission_rate, is_interday=True)
|
||||
|
||||
# Get the positions before updating the date so that prices are
|
||||
# fetched for trading close instead of midnight
|
||||
positions = algo.perf_tracker.position_tracker.positions
|
||||
@@ -162,6 +158,10 @@ class AlgorithmSimulator(object):
|
||||
self.simulation_dt = midnight_dt
|
||||
algo.on_dt_changed(midnight_dt)
|
||||
|
||||
# process any capital changes that came overnight
|
||||
algo.calculate_capital_changes(
|
||||
midnight_dt, emission_rate=emission_rate, is_interday=True)
|
||||
|
||||
# we want to wait until the clock rolls over to the next day
|
||||
# before cleaning up expired assets.
|
||||
self._cleanup_expired_assets(midnight_dt, position_assets)
|
||||
|
||||
Reference in New Issue
Block a user