【量化金融】量化指标的Python实现——Sterling比率、Calmar比率、Alpha&Beta、Treynor比率

环境准备

测试用数据:demo_close_price_data点击下载

1
2
3
4
5
6
7
8
import pandas as pd
import numpy as np

cp = pd.read_csv('close_price_demo.csv', encoding='gbk', index_col='date')
cp.index = pd.to_datetime(cp.index)
ret = cp.pct_change().iloc[1::]
cum_ret = (1+ret).cumprod()
cum_ret.plot(figsize=(10, 4))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 计算年(季/月/周)化收益的相关常数
BDAYS_PER_YEAR = 252
BDAYS_PER_QTRS = 63
BDAYS_PER_MONTH = 21
BDAYS_PER_WEEK = 5

DAYS_PER_YEAR = 365
DAYS_PER_QTRS = 90
DAYS_PER_MONTH = 30
DAYS_PER_WEEK = 7

MONTHS_PER_YEAR = 12
WEEKS_PER_YEAR = 52
QTRS_PER_YEAR = 4

def get_period_days(period):
period_days = {
'yearly': BDAYS_PER_YEAR, 'quarterly': BDAYS_PER_QTRS,
'monthly': BDAYS_PER_MONTH, 'weekly': BDAYS_PER_WEEK, 'daily': 1,

'monthly2yearly': MONTHS_PER_YEAR,
'quarterly2yearly': QTRS_PER_YEAR,
'weekly2yearly': WEEKS_PER_YEAR,
}
return period_days[period]

Calmar比率

Calmar比率描述的是收益和最大回撤之间的关系。计算方式为年化收益率与历史最大回撤之间的比值。Calmar比率数值越大,策略的业绩表现越好。反之,策略的表现越差。

Python实现

1
2
3
4
5
6
def calmar_ratio(returns_df):
annual_ret = annual_return(returns_df, period)['annual_return']
mdd = maximum_drawdown(returns_df)['max_drawdown']
cr = annual_ret / mdd
res_dict = {'calmar_ratio': cr}
return res_dict

其中annual_return与maximum_drawdown函数见文章:

Sterling比率

Sterling比率是衡量投资组合风险调整后回报的指标,这个指标有很多定义方式,但是总体的思路与特征是一致的,在这里我选取一种个人感觉最好的计算方式进行分享。
$$
sterling_ratio=\frac{r_p-r_f}{average_maxdrawdown}
$$
将之与Calmar比率进行对比,sterling比率使用近三年最大回撤的均值,更具有普遍性,对异常值更加鲁棒。

Python实现方式

1
2
3
4
5
6
7
8
9
10
def sterling_ratio(returns_df, period='yearly'):
period_days = get_period_days(period)
s = 0
for i in range(3):
returns_df_y = returns_df.iloc[-1-(i+1)*period_days:-1-i*period_days]
s += maximum_drawdown(returns_df_y)[0]
s = s / 3 + 0.1
slr = annual_return(returns_df, period=period) / s
res_dict = {'sterling_ratio': slr}
return res_dict

Alpha&Beta

这是学习金融课程是最先接触的几个概念之一,确实不应该放在这么后面来分享。

其中,Alpha衡量策略相对于市场的超额收益,即策略的独立收益部分。Beta衡量策略相对于市场指数的敏感性,Beta值大于1表示策略波动性大于市场,小于1表示波动性小于市场。

Python数学方法实现

1
2
3
4
5
6
def alpha_beta(ret_i, ret_m, risk_free=0, period='yearly'):
period_days = get_period_days(period)
beta = ret_i.cov(ret_m)/ret_m.var()
alpha = ((ret_i.mean()-risk_free-beta*(ret_m-risk_free).mean())+1)**period_days-1
res_dict = {'alpha': alpha, 'Beta': beta}
return res_dict

Python回归方法实现

1
2
3
4
5
6
7
8
9
from sklearn.linear_model import LinearRegression
def alpha_beta(ret_i, ret_m, risk_free=0, period='yearly'):
period_days = get_period_days(period)
LR = LinearRegression()
LR.fit(pd.DataFrame(ret_m-risk_free), pd.DataFrame(ret_i-risk_free))
beta = LR.coef_[0][0]
alpha = (1+LR.intercept_[0])**period_days-1
res_dict = {'alpha': alpha, 'Beta': beta}
return res_dict

Treynor比率

Treynor比率(特雷诺比率),也称为回报与波动率比率,和夏普比率类似,用于描述投资组合承担的每个风险单位产生了多少超额回报,只是特雷诺比率中的风险是指以投资组合的贝塔系数衡量的系统性风险,而不是组合收益的方差。

较高的Treynor比率结果意味着投资组合是更合适的投资。
$$
treynor_ratio=\frac{r_p-r_f}{\beta_p}
$$

Python实现

1
2
3
4
5
6
7
def treynor_ratio(returns_df, ret_m, risk_free=0, period='yearly'):
period_days = get_period_days(period)
rp_f = (returns_df.mean() - risk_free)
beta = alpha_beta(returns_df, ret_m, risk_free, period)['beta']
tr = rp_f * (period_days ** 0.5) / beta
res_dict = {'treynor_ratio': tr}
return res_dict