mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-02 11:52:39 +08:00
Merge fixes for intraday perfomance.
Contains bugs and protocol compatibility changes.
This commit is contained in:
@@ -1098,21 +1098,21 @@ class TestPerformanceTracker(unittest.TestCase):
|
||||
msg_1 = messages[foo_event_1.dt]
|
||||
msg_2 = messages[foo_event_2.dt]
|
||||
|
||||
self.assertEquals(1, len(msg_1['intraday_perf']['transactions']),
|
||||
self.assertEquals(1, len(msg_1['minute_perf']['transactions']),
|
||||
"The first message should contain one transaction.")
|
||||
# Check that transactions aren't emitted for previous events.
|
||||
self.assertEquals(0, len(msg_2['intraday_perf']['transactions']),
|
||||
self.assertEquals(0, len(msg_2['minute_perf']['transactions']),
|
||||
"The second message should have no transactions.")
|
||||
|
||||
self.assertEquals(1, len(msg_1['intraday_perf']['orders']),
|
||||
self.assertEquals(1, len(msg_1['minute_perf']['orders']),
|
||||
"The first message should contain one orders.")
|
||||
# Check that orders aren't emitted for previous events.
|
||||
self.assertEquals(0, len(msg_2['intraday_perf']['orders']),
|
||||
self.assertEquals(0, len(msg_2['minute_perf']['orders']),
|
||||
"The second message should have no orders.")
|
||||
|
||||
# Ensure that period_close moves through time.
|
||||
# Also, ensure that the period_closes are the expected dts.
|
||||
self.assertEquals(foo_event_1.dt,
|
||||
msg_1['intraday_perf']['period_close'])
|
||||
msg_1['minute_perf']['period_close'])
|
||||
self.assertEquals(foo_event_2.dt,
|
||||
msg_2['intraday_perf']['period_close'])
|
||||
msg_2['minute_perf']['period_close'])
|
||||
|
||||
@@ -270,25 +270,16 @@ class PerformanceTracker(object):
|
||||
'period_end': self.period_end,
|
||||
'capital_base': self.capital_base,
|
||||
'cumulative_perf': self.cumulative_performance.to_dict(),
|
||||
'progress': self.progress
|
||||
'progress': self.progress,
|
||||
'cumulative_risk_metrics': self.cumulative_risk_metrics.to_dict()
|
||||
}
|
||||
if emission_type == 'daily':
|
||||
_dict.update({'cumulative_risk_metrics':
|
||||
self.cumulative_risk_metrics.to_dict(),
|
||||
'daily_perf':
|
||||
self.todays_performance.to_dict()})
|
||||
if emission_type == 'minute':
|
||||
# Currently reusing 'todays_performance' for intraday trading
|
||||
# result, should be analogous, but has the potential for needing
|
||||
# its own configuration down the line.
|
||||
# Naming as intraday to make clear that these results are
|
||||
# being updated per minute
|
||||
_dict['intraday_risk_metrics'] = \
|
||||
self.intraday_risk_metrics.to_dict()
|
||||
_dict['intraday_perf'] = self.todays_performance.to_dict(
|
||||
self.saved_dt)
|
||||
_dict['cumulative_risk_metrics'] = \
|
||||
self.cumulative_risk_metrics.to_dict()
|
||||
_dict.update({'daily_perf': self.todays_performance.to_dict()})
|
||||
elif emission_type == 'minute':
|
||||
_dict.update({
|
||||
'intraday_risk_metrics': self.intraday_risk_metrics.to_dict(),
|
||||
'minute_perf': self.todays_performance.to_dict(self.saved_dt)
|
||||
})
|
||||
|
||||
return _dict
|
||||
|
||||
@@ -327,9 +318,7 @@ class PerformanceTracker(object):
|
||||
perf_period.calculate_performance()
|
||||
|
||||
def handle_minute_close(self, dt):
|
||||
|
||||
todays_date = self.market_close.replace(hour=0, minute=0, second=0,
|
||||
microsecond=0)
|
||||
todays_date = dt.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
|
||||
minute_returns = self.minute_performance.returns
|
||||
self.minute_performance.rollover()
|
||||
@@ -340,22 +329,20 @@ class PerformanceTracker(object):
|
||||
self.intraday_risk_metrics.update(dt,
|
||||
algo_minute_returns,
|
||||
bench_minute_returns)
|
||||
# the intraday risk metrics compound the minutely returns of the
|
||||
# benchmark.
|
||||
bench_since_open = self.intraday_risk_metrics.benchmark_returns[-1]
|
||||
benchmark_returns = pd.Series({dt: bench_since_open})
|
||||
|
||||
bench_since_open = \
|
||||
self.intraday_risk_metrics.benchmark_period_returns[-1]
|
||||
|
||||
benchmark_returns = pd.Series({todays_date: bench_since_open})
|
||||
|
||||
# if we've reached market close, check on dividends
|
||||
if dt == self.market_close:
|
||||
for perf_period in self.perf_periods:
|
||||
perf_period.update_dividends(todays_date)
|
||||
|
||||
algorithm_returns = pd.Series({dt: self.todays_performance.returns})
|
||||
|
||||
self.intraday_risk_metrics.update(dt,
|
||||
algorithm_returns,
|
||||
benchmark_returns)
|
||||
|
||||
algorithm_returns = pd.Series({
|
||||
todays_date: self.todays_performance.returns
|
||||
})
|
||||
self.cumulative_risk_metrics.update(todays_date,
|
||||
algorithm_returns,
|
||||
benchmark_returns)
|
||||
@@ -369,6 +356,18 @@ class PerformanceTracker(object):
|
||||
)
|
||||
self.returns.append(todays_return_obj)
|
||||
|
||||
def handle_intraday_close(self):
|
||||
self.intraday_risk_metrics = \
|
||||
risk.RiskMetricsIterative(self.sim_params)
|
||||
# increment the day counter before we move markers forward.
|
||||
self.day_count += 1.0
|
||||
# move the market day markers forward
|
||||
if self.market_close < trading.environment.last_trading_day:
|
||||
_, self.market_close = \
|
||||
trading.environment.next_open_and_close(self.market_open)
|
||||
else:
|
||||
self.market_close = self.sim_params.last_close
|
||||
|
||||
def handle_market_close(self):
|
||||
# add the return results from today to the list of DailyReturn objects.
|
||||
todays_date = self.market_close.replace(hour=0, minute=0, second=0,
|
||||
|
||||
+4
-11
@@ -649,7 +649,7 @@ algorithm_returns ({algo_count}) in range {start} : {end} on {dt}"
|
||||
self.algorithm_volatility.append(
|
||||
self.calculate_volatility(self.algorithm_returns))
|
||||
|
||||
# caching the treasury rates for the live case is a
|
||||
# caching the treasury rates for the minutely case is a
|
||||
# big speedup, because it avoids searching the treasury
|
||||
# curves on every minute.
|
||||
treasury_end = self.algorithm_returns.index[-1].replace(
|
||||
@@ -693,16 +693,9 @@ algorithm_returns ({algo_count}) in range {start} : {end} on {dt}"
|
||||
'period_label': period_label
|
||||
}
|
||||
|
||||
if self.sim_params.emission_rate == 'daily':
|
||||
# Some risk metrics only make sense in a context of daily
|
||||
# risk calculations.
|
||||
rval['sharpe'] = self.sharpe[-1]
|
||||
rval['sortino'] = self.sortino[-1]
|
||||
rval['information'] = self.information[-1]
|
||||
elif self.sim_params.emission_rate == 'minute':
|
||||
rval['sharpe'] = 0.0
|
||||
rval['sortino'] = 0.0
|
||||
rval['information'] = 0.0
|
||||
rval['sharpe'] = self.sharpe[-1]
|
||||
rval['sortino'] = self.sortino[-1]
|
||||
rval['information'] = self.information[-1]
|
||||
|
||||
return {k: None
|
||||
if check_entry(k, v)
|
||||
|
||||
@@ -26,7 +26,7 @@ log = Logger('Trade Simulation')
|
||||
class AlgorithmSimulator(object):
|
||||
|
||||
EMISSION_TO_PERF_KEY_MAP = {
|
||||
'minute': 'intraday_perf',
|
||||
'minute': 'minute_perf',
|
||||
'daily': 'daily_perf'
|
||||
}
|
||||
|
||||
@@ -170,6 +170,7 @@ class AlgorithmSimulator(object):
|
||||
tp.rollover()
|
||||
if mkt_close < self.algo.perf_tracker.last_close:
|
||||
mkt_close = self.get_next_close(mkt_close)
|
||||
self.algo.perf_tracker.handle_intraday_close()
|
||||
|
||||
risk_message = self.algo.perf_tracker.handle_simulation_end()
|
||||
yield risk_message
|
||||
@@ -185,7 +186,7 @@ class AlgorithmSimulator(object):
|
||||
elif self.algo.perf_tracker.emission_rate == 'minute':
|
||||
self.algo.perf_tracker.handle_minute_close(date)
|
||||
perf_message = self.algo.perf_tracker.to_dict()
|
||||
perf_message['intraday_perf']['recorded_vars'] = rvars
|
||||
perf_message['minute_perf']['recorded_vars'] = rvars
|
||||
return perf_message
|
||||
|
||||
def get_next_close(self, mkt_close):
|
||||
|
||||
Reference in New Issue
Block a user