zoukankan      html  css  js  c++  java
  • 四分位数分析

    四分位数分析

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import datetime as dt
    from pandas import Series,DataFrame
    from datetime import datetime
    from dateutil.parser import parse
    import time
    from pandas.tseries.offsets import Hour,Minute,Day,MonthEnd
    import pytz
    import random;random.seed(0)
    import string
    from numpy.random import rand
    ###  import pandas.io.data as web  # old version
    from pandas_datareader import data, wb
    
    import tushare as ts
    
    %matplotlib inline
    
    def to_index(rets): # 转换为收益率指数(隔夜收益率)
        index = (1 + rets).cumprod()
        #下面是将第一个有效值的位置拿出来
    #     first_loc = max(index.notnull().argmax() - 1,0)
    #     index.values[first_loc] = 1
        first_ix = index.notnull().argmax() - pd.Timedelta(3,unit='D')
        index[first_ix] = 1
        return index
    
    def trend_signal(rets,lookback,lag):
    #     signal = pd.rolling_sum(rets,lookback,min_periods = lookback - 5)
    #     pd.rolling_sum is deprecated for Series and will be removed in a future version, 
    #     replace with Series.rolling(min_periods=95,window=100,center=False).sum()
        signal = rets.rolling(lookback, min_periods=lookback-5).sum() # 相当于通达信的 SUM(roc1,lookback)
        return signal.shift(lag)
    

    数据下载和规整化

    • 从tushare网下载数据:
      • 以研究为目的话, 一定要用ts.get_k_data()接口函数
    • 恼人的数据规整化:
      • 一直遭受者数据不规整的折磨, 主要表现为:
        • 1号轴上的ohlc的排列顺序不统一, 需要规整为dohlcv的顺序
        • 0号轴上的数据格式不统一, 需要规整为datetimeIndex类型
          • 用到的方法: 传入设定的index: index=pd.to_datetime(df.date.values)
      • 严格遵守上述规则, 否则自己的udf无法执行或者得不到预期的结果
    # df=ts.get_hist_data('002242','2010-01-01', '2016-12-31')
    # df=df.sort_index()
    # 实际上得不到6年的日线数据
    # 这种方式获取数据的特点: 期数不能超过500, 列数还包括3条均线+3条成交量的均线, 0轴是降序排列的
    df=ts.get_k_data('002242', '2010-01-01','2016-12-31',ktype='D')
    # 这种方式获取数据的特点: 7列+0轴是序号, 升序排列, 
    # 很适合做历史数据的研究
    # date    open   close    high     low     volume    code
    # 重构数据框: 按照常规的dohlcv顺序+常规索引转为时间索引
    df= DataFrame({
            'open'  :df.open.values, 
            'high'  :df.high.values,
            'low'   :df.low.values,
            'close' :df.close.values,
            'volume':df.volume.values,
            'code'  :df.code.values },
            index= pd.to_datetime(df.date.values),
            columns=['open','high','low','close', 'volume', 'code'],
            )
    iclose = df.close
    iroc1  = iclose.pct_change(); iroc1.name='roc1'
    ipnl   = (1+iroc1).cumprod(); ipnl.name='pnl_index'
    
    iclose.plot()
    
    <matplotlib.axes._subplots.AxesSubplot at 0x6cb9d30>
    

    png

    ipnl.plot()
    

    signal=trend_signal(iroc1, 100,3)
    trade_friday=signal.resample('W-FRI').mean().resample('B').ffill()
    trade_rets = trade_friday.shift(1) * iroc1
    trade_friday.plot()
    
    <matplotlib.axes._subplots.AxesSubplot at 0x6edfc30>
    

    png

    trade_rets.plot()
    
    <matplotlib.axes._subplots.AxesSubplot at 0x706cd50>
    

    png

    #然后将该策略的收益率转换为一个收益指数,并绘制一张图表
    profit_index = to_index(trade_rets)
    profit_index.plot()
    # plt.show()
    
    <matplotlib.axes._subplots.AxesSubplot at 0x7061dd0>
    

    png

    四分位分析

    需要解决的问题是: 依据波动性把隔夜波动率或者策略的收益率划分出4个阶段(4个分组), 该策略的绩效在哪个分组里表现最好呢?

    假设: 这里衡量策略绩效的标准为夏普比, 我们需要分组聚合Sharpe.
    详细步骤如下:

    • 计算波动性volatile
    • 计算四分位数的分组键: key = pd.qcut(volatile,4)
    • 计算分组对象: grouper = data.groupby(by=key)
    • 构造计算夏普比的udf: sharpe
    • 在分组的基础上应用(实施--apply aggregate function)聚合函数: grouper.agg(sharpe)
    # 假如希望将该策略的性能按不同大小的交易期波幅进行划分。
    # 年度标准差是计算波幅的一种简单办法,
    # 可以通过计算夏普比率来观察不同波动机制下的风险收益率:
    # vol = pd.rolling_std(returns,250,min_periods = 200) * np.sqrt(250)
    volatile = iroc1.rolling(window=250,min_periods = 200, 
                          center=False).std() * np.sqrt(250) # 年化波动性
    volatile.name='volatility'
    # pd.rolling_std is deprecated for Series and will be removed in a future version, 
    # replace with: Series.rolling(min_periods=200,window=250,center=False).std()
    def sharpe(rets,ann = 250):
        return rets.mean() / rets.std() * np.sqrt(ann)
    isharpe = iroc1.groupby(by=pd.qcut(volatile,4)).agg(sharpe); isharpe.name='sharpe'
    # print isharpe
    isharpe
    
    volatility
    [0.231, 0.312]    0.208484
    (0.312, 0.41]     0.696361
    (0.41, 0.513]     0.493069
    (0.513, 0.797]    0.097292
    Name: sharpe, dtype: float64
    
    isharpe.index
    
    CategoricalIndex([u'[0.231, 0.312]', u'(0.312, 0.41]', u'(0.41, 0.513]',
                      u'(0.513, 0.797]'],
                     categories=[u'[0.231, 0.312]', u'(0.312, 0.41]', u'(0.41, 0.513]', u'(0.513, 0.797]'], ordered=True, name=u'volatility', dtype='category')
    

    对聚合结果的分析和结论

    由上述聚合数据表可知: 第二四分位对应的夏普比最高. 也就是说: 对于九阳股份而言, 当它的年化波动性位于(0.312, 0.41]之区间时, 夏普比达到最佳值, 这时汇聚得到的sharpe值为0.69.

    
    
  • 相关阅读:
    Leetcode 217 存在重复
    Leetcode 125验证回文串
    HTML标签
    Having dreams is what makes life tolerable.
    Database数据库——MySQL简述
    Python实践之路8——选课系统
    Python学习之路16——线程、进程和协程
    Python实践之路7——计算器
    Python学习之路14——Socket
    Python学习之路13——异常处理
  • 原文地址:https://www.cnblogs.com/duan-qs/p/6250773.html
Copyright © 2011-2022 走看看