Merge fixes for intraday perfomance.

Contains bugs and protocol compatibility changes.
This commit is contained in:
Eddie Hebert
2013-05-07 19:48:40 -04:00
4 changed files with 42 additions and 49 deletions
+6 -6
View File
@@ -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'])
+29 -30
View File
@@ -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
View File
@@ -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)
+3 -2
View File
@@ -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):