【Python】使用tushare完成配对交易策略

发布时间 2023-03-24 19:59:07作者: shbear

 

 分析对象:茅台&五粮液,获取上述股票2020/1/1到2021/12/31的股票数据,
1.可视化价差spread、z-score
2.产生并可视化交易信号:上升交易信号、下降交易信号
3.计算策略的累计效益,可视化为折线图

代码如下:

1,端口准备

  1.  
    #端口准备
  2.  
    import tushare as ts
  3.  
    pro=ts.pro_api()
  4.  
    import pandas as pd
  5.  
    %matplotlib inline
  6.  
    import matplotlib.pyplot as plt
  7.  
    import matplotlib.ticker as ticker
  8.  
    import numpy as np
  9.  
    plt.rcParams['font.sans-serif']=['SimHei']
  10.  
    plt.rcParams['axes.unicode_minus']=False

2,使用tushare获取数据,注意:为方便做图要将交易日期设置为index并将index转化为datetime格式

  1.  
    #茅台日线数据
  2.  
    df = pro.daily(ts_code='600519.SH', start_date='20200101', end_date='20211231')
  3.  
    df = df.sort_values(by = 'trade_date')
  4.  
    df['trade_date'] = pd.to_datetime(df['trade_date'])
  5.  
    df.set_index("trade_date", inplace=True)
  6.  
     
  7.  
    #五粮液日线数据
  8.  
    df2 = pro.daily(ts_code='000858.SZ', start_date='20200101', end_date='20211231')
  9.  
    df2 = df2.sort_values(by = 'trade_date')
  10.  
    df2['trade_date'] = pd.to_datetime(df2['trade_date'])
  11.  
    df2.set_index("trade_date", inplace=True)

3,

  1.  
    #收盘价折线图对比
  2.  
    ax1=df.plot(y='close',label='茅台',figsize=(10,5)) # 茅台收盘价折线
  3.  
    df2.plot(ax=ax1,y='close',label='五粮液') # 五粮液收盘价折线
  4.  
    plt.title('收盘价对比')
  5.  
    plt.xlabel('日期')
  6.  
    plt.ylabel('收盘价')
  7.  
    plt.grid(True)

4,

  1.  
    #价差及其均值
  2.  
    df['spread']=df['close']-df2['close']
  3.  
    df['spread'].plot(figsize=(10,5))
  4.  
    plt.title('茅台与五粮液价差')
  5.  
    plt.xlabel('日期')
  6.  
    plt.ylabel('价差')
  7.  
    plt.axhline(df['spread'].mean())
  8.  
    plt.grid(True)

 

 5,z-score 是对时间序列偏离其均值程度的衡量,表示时间序列偏离了其均值多少倍的标 准差。一个序列在时间 t 的 z-score,是它在时间 t 的值,减去序列的均值,再除以序列的 标准差后得到的值。

  1.  
    #对价差进行标准化
  2.  
    df['zscore']=(df['spread']-np.mean(df['spread']))/np.std(df['spread'])
  3.  
    df['zscore'].plot(figsize=(10,5))
  4.  
    plt.title('茅台与五粮液价差Z值')
  5.  
    plt.xlabel('日期')
  6.  
    plt.ylabel('Z值')
  7.  
    plt.grid(True)

6,

  1.  
    #茅台交易信号
  2.  
    df['position1'] = np.where(df['zscore']>1,-1,np.nan) #大于1,做多
  3.  
    df['position1'] = np.where(df['zscore']<-1,1,df['position1']) #小于-1,做空
  4.  
    df['position1'] = np.where(abs(df['zscore'])<0.5,0,df['position1']) #在0.5范围区间,平仓
  5.  
    df['position1'] = df['position1'].ffill().fillna(0)
  6.  
    df['position1'].plot(ylim=[-1.1,1.1],title='茅台买卖信号',xlabel='日期',figsize=(10,5))

 

  1.  
    #五粮液交易信号
  2.  
    df['position2'] = -np.sign(df['position1']) #与茅台相反操作
  3.  
    df['position2'].plot(ylim=[-1.1,1.1],title='五粮液买卖信号',xlabel='日期',figsize=(10,5))

 

7,

  1.  
    #策略的累计收益率
  2.  
    df['茅台']=(np.log(df['close']/df['close'].shift(1))).fillna(0)
  3.  
    df['五粮液']=(np.log(df2['close']/df2['close'].shift(1))).fillna(0)
  4.  
    df['配对策略']=0.5*(df['position1'].shift(1)*df['茅台'])+0.5*(df['position2'].shift(1)*df['五粮液'])
  5.  
    df[['茅台','五粮液','配对策略']].dropna().cumsum().apply(np.exp).plot(figsize=(10,5))
  6.  
    plt.title('配对策略累计收益率')
  7.  
    plt.xlabel('日期')
  8.  
    plt.ylabel('累计收益率')
  9.  
    plt.grid(True)