From 1406f8e9ba96f34c753103ff32d8f58cca3d07f8 Mon Sep 17 00:00:00 2001 From: Eddie Hebert Date: Wed, 16 Apr 2014 15:48:13 -0400 Subject: [PATCH] PERF: Remove the drop of 'null return' from cumulative returns. The check of existence of the null return key, and the drop of said return on every single bar was adding unneeded CPU time when an algorithm was run with minute emissions. Instead, add the 0.0 return with an index of the trading day before the start date. The removal of the `null return` was mainly in place so that the period calculation was not crashing on a non-date index value; with the index as a date, the period return can also approximate volatility (even though the that volatility has high noise-to-signal strength because it uses only two values as an input.) --- zipline/finance/risk/cumulative.py | 40 ++++++++++-------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/zipline/finance/risk/cumulative.py b/zipline/finance/risk/cumulative.py index 7ebb455c..7574360d 100644 --- a/zipline/finance/risk/cumulative.py +++ b/zipline/finance/risk/cumulative.py @@ -110,6 +110,12 @@ class RiskMetricsCumulative(object): self.start_date, self.end_date) + # Hold on to the trading day before the start, + # used for index of the zero return value when forcing returns + # on the first day. + self.day_before_start = self.start_date - \ + trading.environment.trading_days.freq + last_day = normalize_date(sim_params.period_end) if last_day not in self.trading_days: last_day = pd.tseries.index.DatetimeIndex( @@ -199,7 +205,8 @@ class RiskMetricsCumulative(object): if self.create_first_day_stats: if len(self.algorithm_returns) == 1: self.algorithm_returns = pd.Series( - {'null return': 0.0}).append(self.algorithm_returns) + {self.day_before_start: 0.0}).append( + self.algorithm_returns) self.algorithm_cumulative_returns[dt] = \ self.calculate_cumulative_returns(self.algorithm_returns) @@ -220,9 +227,10 @@ class RiskMetricsCumulative(object): if self.create_first_day_stats: if len(self.mean_returns) == 1: self.mean_returns = pd.Series( - {'null return': 0.0}).append(self.mean_returns) + {self.day_before_start: 0.0}).append(self.mean_returns) self.annualized_mean_returns = pd.Series( - {'null return': 0.0}).append(self.annualized_mean_returns) + {self.day_before_start: 0.0}).append( + self.annualized_mean_returns) self.benchmark_returns_cont[dt] = benchmark_returns self.benchmark_returns = self.benchmark_returns_cont[:dt] @@ -230,7 +238,8 @@ class RiskMetricsCumulative(object): if self.create_first_day_stats: if len(self.benchmark_returns) == 1: self.benchmark_returns = pd.Series( - {'null return': 0.0}).append(self.benchmark_returns) + {self.day_before_start: 0.0}).append( + self.benchmark_returns) self.benchmark_cumulative_returns[dt] = \ self.calculate_cumulative_returns(self.benchmark_returns) @@ -295,29 +304,6 @@ algorithm_returns ({algo_count}) in range {start} : {end} on {dt}" self.max_drawdown = self.calculate_max_drawdown() self.max_drawdowns[dt] = self.max_drawdown - if self.create_first_day_stats: - # Remove placeholder 0 return - if 'null return' in self.algorithm_returns: - self.algorithm_returns = self.algorithm_returns.drop( - 'null return') - self.algorithm_returns.index = pd.to_datetime( - self.algorithm_returns.index) - if 'null return' in self.benchmark_returns: - self.benchmark_returns = self.benchmark_returns.drop( - 'null return') - self.benchmark_returns.index = pd.to_datetime( - self.benchmark_returns.index) - if 'null return' in self.mean_returns: - self.mean_returns = self.mean_returns.drop( - 'null return') - self.mean_returns.index = pd.to_datetime( - self.mean_returns.index) - if 'null return' in self.annualized_mean_returns: - self.annualized_mean_returns = \ - self.annualized_mean_returns.drop('null return') - self.annualized_mean_returns.index = pd.to_datetime( - self.mean_returns.index) - def to_dict(self): """ Creates a dictionary representing the state of the risk report.