188 lines
6.4 KiB
Python
188 lines
6.4 KiB
Python
|
# encoding: UTF-8
|
|||
|
|
|||
|
"""
|
|||
|
感谢Darwin Quant贡献的策略思路。
|
|||
|
知乎专栏原文:https://zhuanlan.zhihu.com/p/24448511
|
|||
|
|
|||
|
策略逻辑:
|
|||
|
1. 布林通道(信号)
|
|||
|
2. CCI指标(过滤)
|
|||
|
3. ATR指标(止损)
|
|||
|
|
|||
|
适合品种:螺纹钢
|
|||
|
适合周期:15分钟
|
|||
|
|
|||
|
这里的策略是作者根据原文结合vn.py实现,对策略实现上做了一些修改,仅供参考。
|
|||
|
|
|||
|
"""
|
|||
|
|
|||
|
from __future__ import division
|
|||
|
|
|||
|
from vnpy.trader.vtObject import VtBarData
|
|||
|
from vnpy.trader.vtConstant import EMPTY_STRING
|
|||
|
from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate,
|
|||
|
BarManager,
|
|||
|
ArrayManager)
|
|||
|
|
|||
|
|
|||
|
########################################################################
|
|||
|
class BollChannelStrategy(CtaTemplate):
|
|||
|
"""基于布林通道的交易策略"""
|
|||
|
className = 'BollChannelStrategy'
|
|||
|
author = u'用Python的交易员'
|
|||
|
|
|||
|
# 策略参数
|
|||
|
bollWindow = 18 # 布林通道窗口数
|
|||
|
bollDev = 3.4 # 布林通道的偏差
|
|||
|
cciWindow = 10 # CCI窗口数
|
|||
|
atrWindow = 30 # ATR窗口数
|
|||
|
slMultiplier = 5.2 # 计算止损距离的乘数
|
|||
|
initDays = 10 # 初始化数据所用的天数
|
|||
|
fixedSize = 1 # 每次交易的数量
|
|||
|
|
|||
|
# 策略变量
|
|||
|
bollUp = 0 # 布林通道上轨
|
|||
|
bollDown = 0 # 布林通道下轨
|
|||
|
cciValue = 0 # CCI指标数值
|
|||
|
atrValue = 0 # ATR指标数值
|
|||
|
|
|||
|
intraTradeHigh = 0 # 持仓期内的最高点
|
|||
|
intraTradeLow = 0 # 持仓期内的最低点
|
|||
|
longStop = 0 # 多头止损
|
|||
|
shortStop = 0 # 空头止损
|
|||
|
|
|||
|
# 参数列表,保存了参数的名称
|
|||
|
paramList = ['name',
|
|||
|
'className',
|
|||
|
'author',
|
|||
|
'vtSymbol',
|
|||
|
'bollWindow',
|
|||
|
'bollDev',
|
|||
|
'cciWindow',
|
|||
|
'atrWindow',
|
|||
|
'slMultiplier',
|
|||
|
'initDays',
|
|||
|
'fixedSize']
|
|||
|
|
|||
|
# 变量列表,保存了变量的名称
|
|||
|
varList = ['inited',
|
|||
|
'trading',
|
|||
|
'pos',
|
|||
|
'bollUp',
|
|||
|
'bollDown',
|
|||
|
'cciValue',
|
|||
|
'atrValue',
|
|||
|
'intraTradeHigh',
|
|||
|
'intraTradeLow',
|
|||
|
'longStop',
|
|||
|
'shortStop']
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def __init__(self, ctaEngine, setting):
|
|||
|
"""Constructor"""
|
|||
|
super(BollChannelStrategy, self).__init__(ctaEngine, setting)
|
|||
|
|
|||
|
self.bm = BarManager(self.onBar, 15, self.onXminBar) # 创建K线合成器对象
|
|||
|
self.am = ArrayManager()
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onInit(self):
|
|||
|
"""初始化策略(必须由用户继承实现)"""
|
|||
|
self.writeCtaLog(u'%s策略初始化' %self.name)
|
|||
|
|
|||
|
# 载入历史数据,并采用回放计算的方式初始化策略数值
|
|||
|
initData = self.loadBar(self.initDays)
|
|||
|
for bar in initData:
|
|||
|
self.onBar(bar)
|
|||
|
|
|||
|
self.putEvent()
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onStart(self):
|
|||
|
"""启动策略(必须由用户继承实现)"""
|
|||
|
self.writeCtaLog(u'%s策略启动' %self.name)
|
|||
|
self.putEvent()
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onStop(self):
|
|||
|
"""停止策略(必须由用户继承实现)"""
|
|||
|
self.writeCtaLog(u'%s策略停止' %self.name)
|
|||
|
self.putEvent()
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onTick(self, tick):
|
|||
|
"""收到行情TICK推送(必须由用户继承实现)"""
|
|||
|
self.bm.updateTick(tick)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onBar(self, bar):
|
|||
|
"""收到Bar推送(必须由用户继承实现)"""
|
|||
|
self.bm.updateBar(bar)
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onXminBar(self, bar):
|
|||
|
"""收到X分钟K线"""
|
|||
|
# 全撤之前发出的委托
|
|||
|
self.cancelAll()
|
|||
|
|
|||
|
# 保存K线数据
|
|||
|
am = self.am
|
|||
|
|
|||
|
am.updateBar(bar)
|
|||
|
|
|||
|
if not am.inited:
|
|||
|
return
|
|||
|
|
|||
|
# 计算指标数值
|
|||
|
self.bollUp, self.bollDown = am.boll(self.bollWindow, self.bollDev)
|
|||
|
self.cciValue = am.cci(self.cciWindow)
|
|||
|
self.atrValue = am.atr(self.atrWindow)
|
|||
|
|
|||
|
# 判断是否要进行交易
|
|||
|
|
|||
|
# 当前无仓位,发送开仓委托
|
|||
|
if self.pos == 0:
|
|||
|
self.intraTradeHigh = bar.high
|
|||
|
self.intraTradeLow = bar.low
|
|||
|
|
|||
|
if self.cciValue > 0:
|
|||
|
self.buy(self.bollUp, self.fixedSize, True)
|
|||
|
|
|||
|
elif self.cciValue < 0:
|
|||
|
self.short(self.bollDown, self.fixedSize, True)
|
|||
|
|
|||
|
# 持有多头仓位
|
|||
|
elif self.pos > 0:
|
|||
|
self.intraTradeHigh = max(self.intraTradeHigh, bar.high)
|
|||
|
self.intraTradeLow = bar.low
|
|||
|
self.longStop = self.intraTradeHigh - self.atrValue * self.slMultiplier
|
|||
|
|
|||
|
self.sell(self.longStop, abs(self.pos), True)
|
|||
|
|
|||
|
# 持有空头仓位
|
|||
|
elif self.pos < 0:
|
|||
|
self.intraTradeHigh = bar.high
|
|||
|
self.intraTradeLow = min(self.intraTradeLow, bar.low)
|
|||
|
self.shortStop = self.intraTradeLow + self.atrValue * self.slMultiplier
|
|||
|
|
|||
|
self.cover(self.shortStop, abs(self.pos), True)
|
|||
|
|
|||
|
# 发出状态更新事件
|
|||
|
self.putEvent()
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onOrder(self, order):
|
|||
|
"""收到委托变化推送(必须由用户继承实现)"""
|
|||
|
pass
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onTrade(self, trade):
|
|||
|
# 发出状态更新事件
|
|||
|
self.putEvent()
|
|||
|
|
|||
|
#----------------------------------------------------------------------
|
|||
|
def onStopOrder(self, so):
|
|||
|
"""停止单推送"""
|
|||
|
pass
|
|||
|
|