分享一个螺纹钢30分钟均线策略

作者:爱茶语 ;     来源:维恩的派论坛

  • 原文测试时间区间是20120111--20171117,样本内夏普比率达1.35。
  • 今进行样本外测试,时间区间20130111--20190102,夏普比率为0.78。

结果显示尽管参数不多,但是模型还是过拟合了。但是在策略内实现Tick数据聚合成X分钟K线还是值得学习一下
 

回测设置

# 设置回测使用的数据
engine.setBacktestingMode(engine.BAR_MODE)    # 设置引擎的回测模式为K线
engine.setDatabase(MINUTE_DB_NAME, 'RB99')  # RQDATA一分钟期货指数数据
engine.setStartDate('20130101')               # 设置回测用的数据起始日期

# 配置回测引擎参数
engine.setSlippage(1)      # 设置滑点为1跳
engine.setRate(1/1000)    # 设置手续费
engine.setSize(10)         # 设置合约大小 
engine.setPriceTick(1)     # 设置最小价格变动   
engine.setCapital(200000)   # 设置回测本金

回测效果

策略代码如下:

# encoding: UTF-8


import talib
import numpy as np

from vnpy.trader.vtObject import VtBarData
from vnpy.trader.vtConstant import EMPTY_INT,EMPTY_STRING
from vnpy.trader.app.ctaStrategy.ctaTemplate import CtaTemplate

########################################################################
class RBMAStrategy(CtaTemplate):
    """结合MA的一个30分钟线交易策略"""
    className = 'RBMAStrategy'
    author = 'xldistance'

    #策略参数

    initDays = 33    # 初始化数据所用的天数默认35
    open_pos = 10   #每次交易的手数
    OCM = 30      #操作分钟周期(1,60)默认30
    # 策略变量
    bar = None                  # K线对象
    barMinute = EMPTY_STRING    # K线当前的分钟
    minutebar = None        # minuteK线对象
    ma_windows1 = 20    #默认20
    ma_windows2 = 200    #默认200
    # 参数列表,保存了参数的名称
    paramList = ['name',
                 'className',
                 'author',
                 'vtSymbol',
                 'open_pos']

    # 变量列表,保存了变量的名称
    varList = ['inited',
               'trading',
               'pos',
               'OCM',
               'ma20_value',
               'ma200_value']
    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(RBMAStrategy, self).__init__(ctaEngine, setting)
        """
        如果是多合约实例的话,变量需要放在__init__里面
        """
        #self.orderList = []
        self.barList = []
        self.bufferSize = 201                    # 需要缓存的数据的大小
        self.bufferCount = 0                     # 目前已经缓存了的数据的计数
        self.highArray = np.zeros(self.bufferSize)    # K线最高价的数组
        self.lowArray = np.zeros(self.bufferSize)     # K线最低价的数组
        self.closeArray = np.zeros(self.bufferSize)   # K线收盘价的数组
        self.openArray = np.zeros(self.bufferSize)   # K线开盘价的数组
        self.LongEnterable = False
        self.ShortEnterable = False
        self.ma20_value = 0
        self.ma200_value = 0
    def onInit(self):
        self.writeCtaLog('%s策略初始化' %self.name)

        # 载入历史数据,并采用回放计算的方式初始化策略数值
        initData = self.loadBar(self.initDays)
        for bar in initData:
            self.onBar(bar)

        self.putEvent()

    #----------------------------------------------------------------------
    def onStart(self):
        """启动策略(必须由用户继承实现)"""
        self.writeCtaLog('%s策略启动' %self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onStop(self):
        """停止策略(必须由用户继承实现)"""
        self.writeCtaLog('%s策略停止' %self.name)
        self.putEvent()

    #----------------------------------------------------------------------
    def onTick(self, tick):
        """收到行情TICK推送(必须由用户继承实现)"""


        tickMinute = tick.datetime.minute
        if tickMinute != self.barMinute:
            if self.bar:
                self.onBar(self.bar)

            bar = VtBarData()
            bar.vtSymbol = tick.vtSymbol
            bar.symbol = tick.symbol
            bar.exchange = tick.exchange

            bar.open = tick.lastPrice
            bar.high = tick.lastPrice
            bar.low = tick.lastPrice
            bar.close = tick.lastPrice

            bar.date = tick.date
            bar.time = tick.time
            bar.datetime = tick.datetime    # K线的时间设为第一个Tick的时间

            self.bar = bar                  # 这种写法为了减少一层访问,加快速度
            self.barMinute = tickMinute     # 更新当前的分钟
        else:                               # 否则继续累加新的K线
            bar = self.bar                  # 写法同样为了加快速度

            bar.high = max(bar.high, tick.lastPrice)
            bar.low = min(bar.low, tick.lastPrice)
            bar.close = tick.lastPrice

   #----------------------------------------------------------------------
    def onBar(self, bar):
        """收到Bar推送(必须由用户继承实现)"""

        if self.LongEnterable:
            if self.pos == 0:# and bar.close > self.dayOpen
                self.buy(bar.close,self.open_pos,True)
            elif self.pos < 0 :
                self.cover(bar.close,abs(self.pos),True)
        if self.ShortEnterable:
            if self.pos ==0:#and bar.close < self.dayOpen
                self.short(bar.close,self.open_pos,True)
            elif self.pos > 0:
                self.sell(bar.close,abs(self.pos),True)

        if bar.datetime.minute  % self.OCM == 0:
            # 如果已经有聚合minuteK线
            if self.minutebar:
                # 将最新分钟的数据更新到目前minute线中
                minutebar = self.minutebar
                minutebar.high = max(minutebar.high, bar.high)
                minutebar.low = min(minutebar.low, bar.low)
                minutebar.close = bar.close

                # 推送minute线数据
                self.onminutebar(minutebar)

                # 清空minute线数据缓存
                self.minutebar = None
        else:
            # 如果没有缓存则新建
            if not self.minutebar:
                minutebar = VtBarData()

                minutebar.vtSymbol = bar.vtSymbol
                minutebar.symbol = bar.symbol
                minutebar.exchange = bar.exchange

                minutebar.open = bar.open
                minutebar.high = bar.high
                minutebar.low = bar.low
                minutebar.close = bar.close

                minutebar.date = bar.date
                minutebar.time = bar.time
                minutebar.datetime = bar.datetime

                self.minutebar = minutebar
            else:
                minutebar = self.minutebar
                minutebar.high = max(minutebar.high, bar.high)
                minutebar.low = min(minutebar.low, bar.low)
                minutebar.close = bar.close
        # 发出状态更新事件
        self.putEvent()

    #----------------------------------------------------------------------
    def onminutebar(self,bar):
        """收到Bar推送(必须由用户继承实现)"""
        # 撤销之前发出的尚未成交的委托(包括限价单和停止单)
        #for orderID in self.orderList:
            #self.cancelOrder(orderID)
        #self.orderList = []

        # 保存K线数据
        self.closeArray[0:self.bufferSize-1] = self.closeArray[1:self.bufferSize]
        self.highArray[0:self.bufferSize-1] = self.highArray[1:self.bufferSize]
        self.lowArray[0:self.bufferSize-1] = self.lowArray[1:self.bufferSize]
        self.openArray[0:self.bufferSize-1] = self.openArray[1:self.bufferSize]
        self.closeArray[-1] = bar.close
        self.highArray[-1] = bar.high
        self.lowArray[-1] = bar.low
        self.openArray[-1] = bar.open
        self.bufferCount += 1
        if self.bufferCount < self.bufferSize:
            return
        # 计算指标数值
        ma_20 = talib.EMA(self.closeArray,timeperiod = self.ma_windows1)
        ma_200 = talib.EMA(self.closeArray,timeperiod = self.ma_windows2)
        self.ma20_value = ma_20[-1]
        self.ma200_value = ma_200[-1]
        self.LongEnterable = ma_20[-1] > ma_200[-1] and ma_20[-2] < ma_200[-2]
        self.ShortEnterable = ma_20[-1] < ma_200[-1] and ma_20[-2] > ma_200[-2]

        # 发出状态更新事件
        self.putEvent()

    #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委托变化推送(必须由用户继承实现)"""
        pass

    #----------------------------------------------------------------------
    def onTrade(self, trade):
        # 发出状态更新事件
        self.putEvent()
    def onStopOrder(self, so):
        """停止单推送"""
        pass

推荐阅读:

1.一个量化策略师的自白(好文强烈推荐)

2.股票期货经典的量化交易策略都在这里了!(源码)

3.期货/股票数据大全查询(历史/实时/Tick/财务等)

4.三分钟弄明白为什么贝叶斯是量化工作者最常用的工具

5.学习Python有哪些书籍?这里有一份书单送给你

6.江湖中常说的“网格交易法”到底是什么?

7.10种经典的日内交易策略模型思路

8.干货 | 量化选股策略模型大全

9.量化金融经典理论、重要模型、发展简史大全

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值