Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 70a2c33

Browse files
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 7 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /