量化策略初探——使用tushare进行沪深300ETF双均线策略

使用tushare采集沪深300ETF数据,并对沪深300ETF采用简单移动平均、指数移动平均、进行双均线策略,最后使用backtrader进行回测。

一、基本概念

双均线策略:运用两条不同周期的移动平均线,即短周期移动平均线和长周期移动平均线的相对大小,研判买进与卖出时机的策略。由短周期均线自下向上穿越长周期均线,所形成的交点,称为金叉。当短周期均线自上而下穿越长周期均线,所形成的交点,称为死叉。

简单移动平均法:对指定期间内的数据做算术平均,新旧数据的权重一样。
指数移动平均法:对指定期间的数据赋予不同的权重,每天数据的权重系数以指数等比形式缩小。

从tushare获取沪深300ETF数据

import pandas as pd
import numpy as np
import backtrader as bt
import datetime,time
import tushare as ts

def get_data(ts_code):
    #获取沪深300ETF数据
    pro = ts.pro_api('your token')
    try :
        df = pro.fund_daily(ts_code=ts_code)
    except : 
        time.sleep(0.5)
        print('获取数据失败')
    else :
        print('获取数据成功')
        
    #对数据进行处理符合backtrader格式
    columns = ['trade_date','open','high','low','close','vol']
    df = df[columns]
    #转换日期格式
    df['trade_date'] = df['trade_date'].apply(lambda x: pd.to_datetime(str(x)))
    bt_col_dict = {
    
    'vol':'volume','trade_date':'datetime'}
    df = df.rename(columns = bt_col_dict)
    df = df.set_index('datetime')
    #openinterest 默认为0
    df['openinterest'] = 0
    #由于获取的数据的第一行是最新数据,需要重新排列,否则最新日期的均线数据为空
    df=df.sort_index()
    return df
    
df=get_data('510300.SH')  

策略准备

当前策略先计算简单移动平均,后续计算指数移动平均使用bt.indicators.EMA()

class MYstrategy(bt.Strategy):
    params = dict(
        pfast = 20,  # 快周期
        pslow = 50)   # 慢周期
    
    def __init__(self):     
        self.dataclose = self.datas[0].close     
        # Order变量包含持仓数据与状态
        self.order = None     
        # 初始化移动平均数据     
        self.slow_sma = bt.indicators.SMA(self.datas[0],                                       
                    period = self.params.pslow)     
        self.fast_sma = bt.indicators.SMA(self.datas[0], 
                    period = self.params.pfast)
        #backtrader内置函数,可以判断两线的交叉点
        self.crossover = bt.ind.CrossOver(self.fast_sma, self.fast_sma)
        
    #订单相关    
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
        #主动买卖的订单提交或接受时  - 不触发
            return
        #验证订单是否完成
        if order.status in [order.Completed]:
            self.bar_executed = len(self)   
        #重置订单
        self.order = None

    #next包含所有交易逻辑
    def next(self):
        # 检测是否有未完成订单
        if self.order:
            return
        #验证是否有持仓
        if not self.position:
        #如果没有持仓,寻找开仓信号
            #SMA快线突破SMA慢线
            if self.crossover > 0:
                self.order = self.buy()
            #SMA快线跌破SMA慢线
            elif self.crossover < 0:
                self.order = self.sell()
        else:
        # 如果已有持仓,寻找平仓信号,此地方选择10日之后平仓
            if len(self) >= (self.bar_executed + 10):
                self.order = self.close()
                

策略执行——backtrader回测

def execute_strategy(pfast,pslow):
	#初始化
    cerebro = bt.Cerebro(optreturn=False)
    #设置数据的参数
    data = bt.feeds.PandasDirectData(dataname=df)
    cerebro.adddata(data)
    #加载策略
    cerebro.addstrategy(MYstrategy,pslow=pslow,pfast=pfast)  
    #设置初始现金
    cerebro.broker.set_cash(1000000.0)
    #设置佣金率
    cerebro.broker.setcommission(commission=0.0001)
    #设置固定的购买股数
    #cerebro.addsizer(bt.sizers.FixedSize, stake=100)
    #分析框架夏普比率和回撤
    cerebro.addanalyzer(bt.analyzers.SharpeRatio,_name = 'SharpeRatio')
    cerebro.addanalyzer(bt.analyzers.DrawDown, _name = 'DW')
    #初始现金
    start_cash = cerebro.broker.getvalue()
    #运行
    result = cerebro.run()
    #最终现金
    end_cash=cerebro.broker.getvalue()
    #利润计算
    profit = end_cash-start_cash
    strategy = result[0]
    SR=strategy.analyzers.SharpeRatio.get_analysis()
    DW=strategy.analyzers.DW.get_analysis()
    return profit,SR['sharperatio'],DW.drawdown,DW.max.drawdown

策略优化

period = [1,5,10,20,30,60,120,250]
final_results_list = []
for i in period:
    for j in period:
        if i < j :
            result=execute_strategy(i,j)
            final_results_list.append([i,j,result[0],result[1],result[2],result[3]])
            
pd.DataFrame(final_results_list,columns = ['pfast','pslow','profit','SR','DW','max_DW'])

策略结果

SMA运行结果
在这里插入图片描述

EMA运行结果
在这里插入图片描述

部分回测图展示在这里插入图片描述
从结果上可以看到,指数移动平均法相比于移动平均法更能反映出短期的价格波动情况,其利润的波动更大,但同时最大回撤也更大。后续也可以用遍历形势求出收益最优组合。

猜你喜欢

转载自blog.csdn.net/DYN100001/article/details/109997265
今日推荐