Python 使用 Pandas 或 NumPy 滚动夏普比率
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49091044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python rolling Sharpe ratio with Pandas or NumPy
提问by edesz
I am trying to generate a plot of the 6-month rollingSharpe ratio using Python with Pandas/NumPy.
我正在尝试使用 Python 和 Pandas/NumPy生成 6 个月滚动夏普比率的图。
My input data is below:
我的输入数据如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("whitegrid")
# Generate sample data
d = pd.date_range(start='1/1/2008', end='12/1/2015')
df = pd.DataFrame(d, columns=['Date'])
df['returns'] = np.random.rand(d.size, 1)
df = df.set_index('Date')
print(df.head(20))
returns
Date
2008-01-01 0.232794
2008-01-02 0.957157
2008-01-03 0.079939
2008-01-04 0.772999
2008-01-05 0.708377
2008-01-06 0.579662
2008-01-07 0.998632
2008-01-08 0.432605
2008-01-09 0.499041
2008-01-10 0.693420
2008-01-11 0.330222
2008-01-12 0.109280
2008-01-13 0.776309
2008-01-14 0.079325
2008-01-15 0.559206
2008-01-16 0.748133
2008-01-17 0.747319
2008-01-18 0.936322
2008-01-19 0.211246
2008-01-20 0.755340
What I want
我想要的是
The type of plot I am trying to produce is thisor the first plot from here(see below).
My attempt
我的尝试
Here is the equation I am using:
这是我正在使用的等式:
def my_rolling_sharpe(y):
return np.sqrt(126) * (y.mean() / y.std()) # 21 days per month X 6 months = 126
# Calculate rolling Sharpe ratio
df['rs'] = calc_sharpe_ratio(df['returns'])
fig, ax = plt.subplots(figsize=(10, 3))
df['rs'].plot(style='-', lw=3, color='indianred', label='Sharpe')\
.axhline(y = 0, color = "black", lw = 3)
plt.ylabel('Sharpe ratio')
plt.legend(loc='best')
plt.title('Rolling Sharpe ratio (6-month)')
fig.tight_layout()
plt.show()
The problem is that I am getting a horizontal line since my function is giving a single value for the Sharpe ratio. This value is the same for all the Dates. In the example plots, they appear to be showing many ratios.
问题是我得到了一条水平线,因为我的函数为夏普比率提供了一个值。该值对于所有日期都是相同的。在示例图中,它们似乎显示了许多比率。
Question
题
Is it possible to plot a 6-month rolling Sharpe ratio that changes from one day to the next?
是否可以绘制从一天到下一天变化的 6 个月滚动夏普比率?
采纳答案by Peter Leimbigler
Approximately correct solution using df.rolling
and a fixed window size of 180 days:
大约正确的解决方案使用df.rolling
和 180 天的固定窗口大小:
df['rs'] = df['returns'].rolling('180d').apply(my_rolling_sharpe)
This window isn't exactly 6 calendar months wide because rolling
requires a fixed window size, so trying window='6MS'
(6 Month Starts) throws a ValueError.
这个窗口是不完全的6个日历月宽,因为rolling
需要一个固定的窗口大小,所以尝试window='6MS'
(6中号onth小号挞)抛出一个ValueError。
To calculate the Sharpe ratio for a window exactly 6 calendar months wide, I'll copy this super cool answerby SO user Mike:
要计算正好 6 个日历月宽的窗口的夏普比率,我将复制SO 用户 Mike 的这个超级酷的答案:
df['rs2'] = [my_rolling_sharpe(df.loc[d - pd.offsets.DateOffset(months=6):d, 'returns'])
for d in df.index]
# Compare the two windows
df.plot(y=['rs', 'rs2'], linewidth=0.5)
回答by Lautaro Parada Opazo
I have prepared an alternative solution to your question, this one is based on using solely the window functionsfrom pandas.
我已经为您的问题准备了一个替代解决方案,这个解决方案仅基于使用Pandas的窗口函数。
Here I have defined "on the fly" the calculation of the Sharpe Ratio, please consider for your solution the following parameters:
在这里,我定义了“即时”夏普比率的计算,请考虑以下参数作为您的解决方案:
- I have used a Risk Free rate of 2%
- The dash line is just a Benchmark for the rolling Sharpe Ratio, the value is 1.6
- 我使用了2%的无风险利率
- 虚线只是滚动夏普比率的基准,值为1.6
So the code is the following
所以代码如下
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style("whitegrid")
# Generate sample data
d = pd.date_range(start='1/1/2008', end='12/1/2015')
df = pd.DataFrame(d, columns=['Date'])
df['returns'] = np.random.rand(d.size, 1)
df = df.set_index('Date')
df['rolling_SR'] = df.returns.rolling(180).apply(lambda x: (x.mean() - 0.02) / x.std(), raw = True)
df.fillna(0, inplace = True)
df[df['rolling_SR'] > 0].rolling_SR.plot(style='-', lw=3, color='orange',
label='Sharpe', figsize = (10,7))\
.axhline(y = 1.6, color = "blue", lw = 3,
linestyle = '--')
plt.ylabel('Sharpe ratio')
plt.legend(loc='best')
plt.title('Rolling Sharpe ratio (6-month)')
plt.show()
print('---------------------------------------------------------------')
print('In case you want to check the result data\n')
print(df.tail()) # I use tail, beacause of the size of your window.
You should get something similar to this picture
你应该得到类似于这张图片的东西