zoukankan      html  css  js  c++  java
  • 跨期套利策略

    策略想法:选取某一期货品种的主力合约和次主力合约,得到两个合约价格的价差,运用布林带指标,取前20分钟和2倍标准差,如果价差在布林带之外,入场,回到均值出场。

    如下为策略代码:

    #选取zn1701和zn1702合约的11月份交易分钟数据
    #数据经过excel处理,两个合约数据按时间合并
    #设置手续费和滑点为10元(两个合约买卖一次),平仓时扣除,
    import pandas as pd
    from pandas import Series,DataFrame
    import numpy as np
    import matplotlib.pyplot as plt
    from numpy import nan
    data=pd.read_excel('zn01_zn02.xlsx')
    data['spread']=data['ZN01']-data['ZN02']
    T=len(data.index)
    #记录每次交易收益率
    minute_return=[]
    up_cross_up_limit=False
    down_cross_down_limit=False
    result_up= DataFrame(columns=['ZN01', 'ZN02', 'spread', 'ZN01买卖方向', 'ZN01开平', 'ZN02买卖方向', 'ZN02开平'])
    result_down= DataFrame(columns=['ZN01', 'ZN02', 'spread', 'ZN01买卖方向', 'ZN01开平', 'ZN02买卖方向', 'ZN02开平'])
    total_mean_line=[]
    total_up_line=[]
    total_down_line=[]
    #生成T-20个元素为0列表,
    a=[0]*(T-20)
    for i in range(20,T):
    #得到第i个spread前20个数据,并计算均值、方差、up_line、down_line
    #计算结果均为整数
    data_spread=data.iloc[i-20:i,2].values
    # print(data_spread)
    mean_20day_spread=data_spread.mean()
    total_mean_line.append(mean_20day_spread)
    # print(mean_20day_spread)
    std_20day_spread=data_spread.std()
    up_line=mean_20day_spread+2*std_20day_spread
    total_up_line.append(up_line)
    down_line=mean_20day_spread-2*std_20day_spread
    total_down_line.append(down_line)
    #将第i个spread与前20个spread得到up_line比较,决定是否开仓
    if data.iloc[i,2]>up_line and not up_cross_up_limit:
    up_open=data.iloc[i:i+1,:]
    up_open = DataFrame(up_open,columns=['ZN01', 'ZN02', 'spread', 'ZN01买卖方向', 'ZN01开平', 'ZN02买卖方向', 'ZN02开平'])
    up_open['ZN01买卖方向'] = '卖出'
    up_open['ZN01开平'] = '开仓'
    up_open['ZN02买卖方向'] = '买入'
    up_open['ZN02开平'] = '开仓'
    #汇总
    result_up=pd.concat([result_up,up_open])
    #得到开仓spread
    hold_spread = data.iloc[i, 2]
    up_cross_up_limit=True
    #i从20开始
    a[i-20]=1
    # 将第i个spread与前20个spread得到mean_20day_spread比较,决定是否平仓
    elif data.iloc[i,2]<=mean_20day_spread and up_cross_up_limit:
    down_close=data.iloc[i:i+1,:]
    down_close = DataFrame(down_close,columns=['ZN01', 'ZN02', 'spread', 'ZN01买卖方向', 'ZN01开平', 'ZN02买卖方向', 'ZN02开平'])
    down_close['ZN01买卖方向'] = '买入'
    down_close['ZN01开平'] = '平仓'
    down_close['ZN02买卖方向'] = '卖出'
    down_close['ZN02开平'] = '平仓'
    result_up=pd.concat([result_up,down_close])
    profit_yield = (hold_spread - data.iloc[i, 2] - 20) / (data.iloc[i, 0] + data.iloc[i, 1])
    minute_return.append(profit_yield)
    up_cross_up_limit=False
    a[i-20] = 1
    # 将第i个spread与前20个spread得到down_line比较,决定是否开仓
    elif data.iloc[i,2]<down_line and not down_cross_down_limit:
    down_open=data.iloc[i:i+1,:]
    down_open = DataFrame(down_open,columns=['ZN01', 'ZN02', 'spread', 'ZN01买卖方向', 'ZN01开平', 'ZN02买卖方向', 'ZN02开平'])
    down_open['ZN01买卖方向'] = '买入'
    down_open['ZN01开平'] = '开仓'
    down_open['ZN02买卖方向'] = '卖出'
    down_open['ZN02开平'] = '开仓'
    #汇总
    result_down=pd.concat([result_down,down_open])
    hold_spread = data.iloc[i, 2]
    down_cross_down_limit=True
    a[i-20] = 1
    # 将第i个spread与前20个spread得到down_line比较,决定是否平仓
    elif data.iloc[i,2]>=mean_20day_spread and down_cross_down_limit:
    up_close=data.iloc[i:i+1,:]
    up_close = DataFrame(up_close,columns=['ZN01', 'ZN02', 'spread', 'ZN01买卖方向', 'ZN01开平', 'ZN02买卖方向', 'ZN02开平'])
    up_close['ZN01买卖方向'] = '卖出'
    up_close['ZN01开平'] = '平仓'
    up_close['ZN02买卖方向'] = '买入'
    up_close['ZN02开平'] = '平仓'
    result_down=pd.concat([result_down,up_close])
    profit_yield = (data.iloc[i, 2] - hold_spread - 20)/ (data.iloc[i, 0] + data.iloc[i, 1])
    minute_return.append(profit_yield)
    down_cross_down_limit=False
    a[i-20] = 1
    print('-------------')
    transation=pd.concat([result_up,result_down]).sort_index()
    # transation.to_csv('transation_detail.csv')

    #计算sharpe
    #计算总回报
    total_return=np.expm1(np.log1p(minute_return).sum())
    #计算年化回报
    annual_return=(1+total_return)**(365/30)-1
    risk_free_rate=0.015
    std=np.array(minute_return).std()
    volatility=std*(len(minute_return)**0.5)
    annual_factor=12
    annual_volatility=volatility*((annual_factor)**0.5)
    sharpe=(annual_return-risk_free_rate)/annual_volatility
    # print(total_return,annual_return,std,volatility,annual_volatility,sharpe)
    print('夏普比率:{}'.format(sharpe))

    #计算最大回撤
    #计算
    df_cum=np.exp(np.log1p(minute_return).cumsum())
    max_return=np.maximum.accumulate(df_cum)
    max_drawdown=((max_return-df_cum)/max_return).max()
    print('-----------------')
    print('最大回撤: {}'.format(max_drawdown))

    #计算盈亏比plr
    from collections import Counter
    # win_times=Counter(x>0 for x in minute_return)
    # loss_times=Counter(x<0 for x in minute_return)
    win_times=sum(x>0 for x in minute_return)
    loss_times=sum(x<0 for x in minute_return)
    plr=win_times/loss_times
    print('----------------------------')
    print('盈利次数:{}'.format(win_times))
    print('亏损次数:{}'.format(loss_times))
    print('盈亏比:{}'.format(plr))

    #画出净值走势图
    fig=plt.figure()
    ax1=fig.add_subplot(2,1,1)
    cum_net_worth,=plt.plot(df_cum,label='cum_net_worth')
    plt.legend([cum_net_worth],['cum_net_worth'])
    ax2=fig.add_subplot(2,1,2)
    spread=data.iloc[20:,2].values
    plt.plot(total_mean_line)
    plt.plot(total_up_line)
    plt.plot(total_down_line)
    plt.plot(spread)
    #标记进场、出场位置,先将格式转换为list
    spread_mark=spread.tolist()
    for i in range(T-20):
    if a[i]==0:
    spread_mark[i]=nan
    elif a[i]==1:
    spread_mark[i]=spread_mark[i]
    plt.plot(spread_mark,'*')
    plt.show()



    下面为运行结果图:

     进场出场放大图:







  • 相关阅读:
    idea找不到或无法加载主类
    Scala核心编程_第09章 面向对象编程(高级特性)
    spring源码:学习线索
    Redis
    spring源码:Aware接口
    spring源码:核心组件(li)
    java socket编程
    spring源码:ApplicationContext的增强功能(li)
    spring源码:web容器启动
    spring源码:BeanPostProcessor(li)
  • 原文地址:https://www.cnblogs.com/bawu/p/6789402.html
Copyright © 2011-2022 走看看