Skip to content

Commit dc10b30

Browse files
committed
ENH: Add stat 'CAGR [%]' (compound annual growth rate)
1 parent aa2f0f1 commit dc10b30

File tree

4 files changed

+28
-21
lines changed

4 files changed

+28
-21
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Return [%] 589.35
6262
Buy & Hold Return [%] 703.46
6363
Return (Ann.) [%] 25.42
6464
Volatility (Ann.) [%] 38.43
65+
CAGR [%] 16.80
6566
Sharpe Ratio 0.66
6667
Sortino Ratio 1.30
6768
Calmar Ratio 0.77

backtesting/_stats.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ def _round_timedelta(value, _period=_data_period(index)):
9999
gmean_day_return: float = 0
100100
day_returns = np.array(np.nan)
101101
annual_trading_days = np.nan
102-
if isinstance(index, pd.DatetimeIndex):
102+
is_datetime_index = isinstance(index, pd.DatetimeIndex)
103+
if is_datetime_index:
103104
day_returns = equity_df['Equity'].resample('D').last().dropna().pct_change()
104105
gmean_day_return = geometric_mean(day_returns)
105106
annual_trading_days = float(
@@ -115,6 +116,9 @@ def _round_timedelta(value, _period=_data_period(index)):
115116
s.loc['Volatility (Ann.) [%]'] = np.sqrt((day_returns.var(ddof=int(bool(day_returns.shape))) + (1 + gmean_day_return)**2)**annual_trading_days - (1 + gmean_day_return)**(2*annual_trading_days)) * 100 # noqa: E501
116117
# s.loc['Return (Ann.) [%]'] = gmean_day_return * annual_trading_days * 100
117118
# s.loc['Risk (Ann.) [%]'] = day_returns.std(ddof=1) * np.sqrt(annual_trading_days) * 100
119+
if is_datetime_index:
120+
time_in_years = (s.loc['Duration'].days + s.loc['Duration'].seconds / 86400) / annual_trading_days
121+
s.loc['CAGR [%]'] = ((s.loc['Equity Final [$]'] / equity[0])**(1/time_in_years) - 1) * 100 if time_in_years else np.nan # noqa: E501
118122

119123
# Our Sharpe mismatches `empyrical.sharpe_ratio()` because they use arithmetic mean return
120124
# and simple standard deviation

backtesting/backtesting.py

+21-20
Original file line numberDiff line numberDiff line change
@@ -1145,31 +1145,32 @@ def run(self, **kwargs) -> pd.Series:
11451145
Start 2004-08-19 00:00:00
11461146
End 2013-03-01 00:00:00
11471147
Duration 3116 days 00:00:00
1148-
Exposure Time [%] 93.9944
1149-
Equity Final [$] 51959.9
1150-
Equity Peak [$] 75787.4
1151-
Return [%] 419.599
1152-
Buy & Hold Return [%] 703.458
1153-
Return (Ann.) [%] 21.328
1154-
Volatility (Ann.) [%] 36.5383
1155-
Sharpe Ratio 0.583718
1156-
Sortino Ratio 1.09239
1157-
Calmar Ratio 0.444518
1158-
Max. Drawdown [%] -47.9801
1148+
Exposure Time [%] 96.74115
1149+
Equity Final [$] 51422.99
1150+
Equity Peak [$] 75787.44
1151+
Return [%] 414.2299
1152+
Buy & Hold Return [%] 703.45824
1153+
Return (Ann.) [%] 21.18026
1154+
Volatility (Ann.) [%] 36.49391
1155+
CAGR [%] 14.15984
1156+
Sharpe Ratio 0.58038
1157+
Sortino Ratio 1.08479
1158+
Calmar Ratio 0.44144
1159+
Max. Drawdown [%] -47.98013
11591160
Avg. Drawdown [%] -5.92585
11601161
Max. Drawdown Duration 584 days 00:00:00
11611162
Avg. Drawdown Duration 41 days 00:00:00
1162-
# Trades 65
1163-
Win Rate [%] 46.1538
1164-
Best Trade [%] 53.596
1165-
Worst Trade [%] -18.3989
1166-
Avg. Trade [%] 2.35371
1163+
# Trades 66
1164+
Win Rate [%] 46.9697
1165+
Best Trade [%] 53.59595
1166+
Worst Trade [%] -18.39887
1167+
Avg. Trade [%] 2.53172
11671168
Max. Trade Duration 183 days 00:00:00
11681169
Avg. Trade Duration 46 days 00:00:00
1169-
Profit Factor 2.08802
1170-
Expectancy [%] 8.79171
1171-
SQN 0.916893
1172-
Kelly Criterion 0.6134
1170+
Profit Factor 2.16795
1171+
Expectancy [%] 3.27481
1172+
SQN 1.07662
1173+
Kelly Criterion 0.15187
11731174
_strategy SmaCross
11741175
_equity_curve Eq...
11751176
_trades Size EntryB...

backtesting/test/_test.py

+1
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ def test_compute_stats(self):
275275
'Return (Ann.) [%]': 21.180255813792282,
276276
'Return [%]': 414.2298999999996,
277277
'Volatility (Ann.) [%]': 36.49390889140787,
278+
'CAGR [%]': 14.159843619607383,
278279
'SQN': 1.0766187356697705,
279280
'Kelly Criterion': 0.1518705127029717,
280281
'Sharpe Ratio': 0.5803778344714113,

0 commit comments

Comments
 (0)