四分位数分析

四分位数分析

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.


posted @ 2017-01-05 00:14  duanqs  阅读(3702)  评论(0编辑  收藏  举报