Skip to content

Commit 70a2c33

Browse files
authored
ENH: Add Alpha & Beta stats (#1221)
* added beta & alpha / resolved merge conflict * simplified beta calculation * remove DS_store * move beta & alpha / use log return * Update backtesting/_stats.py * Update backtesting/_stats.py * alpha & beta test * #noqa: E501 * add space * update docs * Revert unrelated change * Add comment
1 parent 5e68bba commit 70a2c33

File tree

4 files changed

+13
-0
lines changed

4 files changed

+13
-0
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ CAGR [%] 16.80
6868
Sharpe Ratio 0.66
6969
Sortino Ratio 1.30
7070
Calmar Ratio 0.77
71+
Alpha [%] 450.62
72+
Beta 0.02
7173
Max. Drawdown [%] -33.08
7274
Avg. Drawdown [%] -5.58
7375
Max. Drawdown Duration 688 days 00:00:00

backtesting/_stats.py

+7
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ def _round_timedelta(value, _period=_data_period(index)):
152152
s.loc['Sortino Ratio'] = (annualized_return - risk_free_rate) / (np.sqrt(np.mean(day_returns.clip(-np.inf, 0)**2)) * np.sqrt(annual_trading_days)) # noqa: E501
153153
max_dd = -np.nan_to_num(dd.max())
154154
s.loc['Calmar Ratio'] = annualized_return / (-max_dd or np.nan)
155+
equity_log_returns = np.log(equity[1:] / equity[:-1])
156+
market_log_returns = np.log(c[1:] / c[:-1])
157+
cov_matrix = np.cov(equity_log_returns, market_log_returns)
158+
beta = cov_matrix[0, 1] / cov_matrix[1, 1]
159+
# Jensen CAPM Alpha: can be strongly positive when beta is negative and B&H Return is large
160+
s.loc['Alpha [%]'] = s.loc['Return [%]'] - risk_free_rate * 100 - beta * (s.loc['Buy & Hold Return [%]'] - risk_free_rate * 100) # noqa: E501
161+
s.loc['Beta'] = beta
155162
s.loc['Max. Drawdown [%]'] = max_dd * 100
156163
s.loc['Avg. Drawdown [%]'] = -dd_peaks.mean() * 100
157164
s.loc['Max. Drawdown Duration'] = _round_timedelta(dd_dur.max())

backtesting/backtesting.py

+2
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,8 @@ def run(self, **kwargs) -> pd.Series:
12621262
Sharpe Ratio 0.58038
12631263
Sortino Ratio 1.08479
12641264
Calmar Ratio 0.44144
1265+
Alpha [%] 394.37391
1266+
Beta 0.03803
12651267
Max. Drawdown [%] -47.98013
12661268
Avg. Drawdown [%] -5.92585
12671269
Max. Drawdown Duration 584 days 00:00:00

backtesting/test/_test.py

+2
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ def test_compute_stats(self):
317317
'Start': pd.Timestamp('2004-08-19 00:00:00'),
318318
'Win Rate [%]': 46.96969696969697,
319319
'Worst Trade [%]': -18.39887353835481,
320+
'Alpha [%]': 394.37391142027462,
321+
'Beta': 0.03803390709192,
320322
})
321323

322324
def almost_equal(a, b):

0 commit comments

Comments
 (0)