美文网首页python自学解密大数据Python中文社区
用夏普比率分析股票的风险和回报 ——带着Python玩金融(7)

用夏普比率分析股票的风险和回报 ——带着Python玩金融(7)

作者: 鱼心DrFish | 来源:发表于2018-10-29 14:06 被阅读4次

    当你进行投资时,仅选择回报高的项目吗?当然不是,你还会综合考虑风险。风险和回报,就像硬币的两面,总是相伴而行的。那么如何来权衡这两者呢?本文将带你使用夏普比率这一金融工具,来评估股票的绩效表现,并在Python中进行实践。

    0. 什么是夏普比率?

    夏普比率(Sharpe Ratio)是由诺贝尔奖得主威廉·夏普提出的,用以帮助投资者比较投资的回报和风险。理性的投资者一般都是固定所能承受的风险,追求最大的回报;或者在固定预期回报,追去最小的风险。所以夏普比率计算的是,每承受一单位的总风险所产生的超额回报。计算公式如下:

    夏普比率 = \frac{R_p - R_f}{\sigma_p}

    其中 R_p 是预期回报率,R_f 是无风险利率,\sigma_p 是超额收益的标准差。

    分子计算了差值,说的是将某项投资与代表整个投资类别的基准进行比较,得到超额回报。分母标准差代表收益的波动率,对应着风险,因为波动越大预示着风险越高。

    1. 获取数据

    接下来,我们将通过Python编码,使用夏普比率来分析 Amazon 和 Facebook 这两家公司的股票,并将标普500指数做为比较的基准。

    首先导入相应的 Python 包,并进行一些设置。

    # 导入Python包
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    
    # 绘图设置
    %matplotlib inline
    %config InlineBackend.figure_format = 'retina' 
    plt.rcParams['font.sans-serif']=['SimHei'] 
    plt.rcParams['axes.unicode_minus']=False
    plt.style.use('fivethirtyeight')
    

    使用 pandas 读取股票数据标普500数据(点击连接获取原始数据)。

    # 读取股票数据
    stock_data = pd.read_csv("stock_data.csv",
                             parse_dates=['Date'],     # 将Date列解析为时间格式
                             index_col = ['Date']      # 设置Date列为索引
                            ).dropna()                 # 丢弃包含缺失值的行
    
    # 读取标普500数据
    benchmark_data = pd.read_csv("benchmark_data.csv",
                                 parse_dates=['Date'],
                                 index_col = ['Date']
                                ).dropna() 
    

    2. 了解数据

    让我们查看数据的基本信息以及前几行数据,从而对数据有个整体印象。

    # 显示股票数据
    print('Stocks\n')
    stock_data.info()          # 数据的基本信息
    print(stock_data.head())   # 输出前5行数据
    
    # 显示标普500数据
    print('\nBenchmarks\n')
    benchmark_data.info()
    print(benchmark_data.head())
    
    Stocks
    
    <class 'pandas.core.frame.DataFrame'>
    DatetimeIndex: 252 entries, 2016-01-04 to 2016-12-30
    Data columns (total 2 columns):
    Amazon      252 non-null float64
    Facebook    252 non-null float64
    dtypes: float64(2)
    memory usage: 5.9 KB
                    Amazon    Facebook
    Date                              
    2016-01-04  636.989990  102.220001
    2016-01-05  633.789978  102.730003
    2016-01-06  632.650024  102.970001
    2016-01-07  607.940002   97.919998
    2016-01-08  607.049988   97.330002
    
    Benchmarks
    
    <class 'pandas.core.frame.DataFrame'>
    DatetimeIndex: 252 entries, 2016-01-04 to 2016-12-30
    Data columns (total 1 columns):
    S&P 500    252 non-null float64
    dtypes: float64(1)
    memory usage: 3.9 KB
                S&P 500
    Date               
    2016-01-04  2012.66
    2016-01-05  2016.71
    2016-01-06  1990.26
    2016-01-07  1943.09
    2016-01-08  1922.03
    

    从中我们知道这里有2016年所有交易日的数据,包括 Amazon 和 Facebook 的股价以及标普500指数。

    3. 观察股票数据

    在比较股票数据和标普500指数之前,先让我们绘制股价随时间波动的折线图,以便更好地理解数据。

    # 股价可视化
    _ = stock_data.plot(subplots=True, title='股票数据')
    

    同时也观察下两只股票的统计量,包括均值、标准差、最大最小值,百分位数等。

    # 股价的统计量
    print(stock_data.describe())
    
               Amazon    Facebook
    count  252.000000  252.000000
    mean   699.523135  117.035873
    std     92.362312    8.899858
    min    482.070007   94.160004
    25%    606.929993  112.202499
    50%    727.875000  117.765000
    75%    767.882492  123.902503
    max    844.359985  133.279999
    

    4. 观察标普500数据

    让我们用同样的方法观察作为基准的标普500数据。

    # 绘图
    _ = benchmark_data.plot(title='标普500指数')
    
    # 统计量
    print(benchmark_data.describe())
    
               S&P 500
    count   252.000000
    mean   2094.651310
    std     101.427615
    min    1829.080000
    25%    2047.060000
    50%    2104.105000
    75%    2169.075000
    max    2271.720000
    

    5. 股票回报率

    要计算夏普比率,首先要知道股票的回报率,即当天股价减去前一天股价,得到的差值与前一天股价的比值。这里使用的是历史数据,只能算是马后炮了。

    # 计算每日股票回报率
    stock_returns = stock_data.pct_change()
    
    # 回报率绘图
    stock_returns.plot()
    
    # 回报率统计量
    print(stock_returns.describe())
    
               Amazon    Facebook
    count  251.000000  251.000000
    mean     0.000818    0.000626
    std      0.018383    0.017840
    min     -0.076100   -0.058105
    25%     -0.007211   -0.007220
    50%      0.000857    0.000879
    75%      0.009224    0.008108
    max      0.095664    0.155214
    

    6. 标普500指数回报率

    使用同样的方法,我们来查看标普500指数的回报率。

    sp_returns = benchmark_data['S&P 500'].pct_change()
    
    sp_returns.plot()
    
    print(sp_returns.describe())
    
    count    251.000000
    mean       0.000458
    std        0.008205
    min       -0.035920
    25%       -0.002949
    50%        0.000205
    75%        0.004497
    max        0.024760
    Name: S&P 500, dtype: float64
    

    7. 每日超额回报

    将股票收益和作为基准的标普500收益做比价,计算每日超额回报,即将股票回报率减去标普500的回报率。

    excess_returns = stock_returns.sub(sp_returns, axis=0)  # 做减法
    
    excess_returns.plot()
    
    print(excess_returns.describe())
    
               Amazon    Facebook
    count  251.000000  251.000000
    mean     0.000360    0.000168
    std      0.016126    0.015439
    min     -0.100860   -0.051958
    25%     -0.006229   -0.005663
    50%      0.000698   -0.000454
    75%      0.007351    0.005814
    max      0.100728    0.149686
    

    8. 超额回报的均值

    现在我们可以计算夏普比率公式中的分子部分,即每日超额回报的均值,使用 .mean() 方法。

    avg_excess_return = excess_returns.mean()
    print(avg_excess_return)
    
    Amazon      0.000360
    Facebook    0.000168
    dtype: float64
    

    将上述结果绘制成条形图便于直观比较,我们发现 Amazon 的回报更高。

    _ = avg_excess_return.plot.bar(title='超额回报的均值')
    

    9. 超额回报的标准差

    接着我们计算夏普比率公式的分母,即超额回报的标准差,使用 .std() 方法。

    # 计算标准差
    sd_excess_return = excess_returns.std() 
    print(sd_excess_return)
    
    Amazon      0.016126
    Facebook    0.015439
    dtype: float64
    

    同时,绘制标准差的条形图,我们发现 Amazon 和 Facebook 的标准差比较接近。

    _ = sd_excess_return.plot.bar(title='超额回报的标准差')
    

    10. 计算夏普比率

    现在万事俱备,只要将超额回报的均值除以其标准差,即可得到衡量回报和风险的夏普比率了。另外我们需再乘上 \sqrt{252}(一年有252个交易日),得到年化的夏普比率。

    # 日夏普比率(.div 做除法)
    daily_sharpe_ratio = avg_excess_return.div(sd_excess_return)  
    
    # 年化夏普比率(.mul 做乘法)
    annual_factor = np.sqrt(252)
    annual_sharpe_ratio = daily_sharpe_ratio.mul(annual_factor)
    print(annual_sharpe_ratio)
    
    Amazon      0.354283
    Facebook    0.172329
    dtype: float64
    

    计算得出 Amazon 的夏普比率差不多是 Facebook 的两倍。我们仍用条形图来可视化这一结果。

    _ = annual_sharpe_ratio.plot.bar(title='年化夏普比率')
    

    小结

    根据上述计算的夏普比率,我们应该投资哪只股票呢?当然是 Amazon 了,因为它的夏普比率是 Facebook 的两倍多。这也意味着承受相同风险的情况下,Amazon 的收益更高。当然这里作为练习使用的是历史数据,并不能当做实际投资的依据。


    注:本文基于 DataCamp 项目 Risk and Returns: The Sharpe Ratio 撰写而成。

    相关文章

      网友评论

        本文标题:用夏普比率分析股票的风险和回报 ——带着Python玩金融(7)

        本文链接:https://www.haomeiwen.com/subject/zgsbtqtx.html