[Add]新增BollChannelStrategy策略,适合螺纹钢15分钟
This commit is contained in:
parent
fb1dac6e3c
commit
4d49bf3ae3
File diff suppressed because one or more lines are too long
199
examples/CtaBacktesting/backtesting_rb.ipynb
Normal file
199
examples/CtaBacktesting/backtesting_rb.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -10,4 +10,5 @@ from vnpy.trader.app.ctaStrategy.ctaHistoryData import loadMcCsv
|
||||
|
||||
if __name__ == '__main__':
|
||||
loadMcCsv('IF0000_1min.csv', MINUTE_DB_NAME, 'IF0000')
|
||||
loadMcCsv('rb0000_1min.csv', MINUTE_DB_NAME, 'rb0000')
|
||||
|
||||
|
@ -416,4 +416,40 @@ class BarManager(object):
|
||||
self.xminBar.openInterest = bar.openInterest
|
||||
self.xminBar.volume += int(bar.volume)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def updateBar(self, bar):
|
||||
"""1分钟K线更新"""
|
||||
# 尚未创建对象
|
||||
if not self.xminBar:
|
||||
self.xminBar = VtBarData()
|
||||
|
||||
self.xminBar.vtSymbol = bar.vtSymbol
|
||||
self.xminBar.symbol = bar.symbol
|
||||
self.xminBar.exchange = bar.exchange
|
||||
|
||||
self.xminBar.open = bar.open
|
||||
self.xminBar.high = bar.high
|
||||
self.xminBar.low = bar.low
|
||||
# 累加老K线
|
||||
else:
|
||||
self.xminBar.high = max(self.xminBar.high, bar.high)
|
||||
self.xminBar.low = min(self.xminBar.low, bar.low)
|
||||
|
||||
# 通用部分
|
||||
self.xminBar.close = bar.close
|
||||
self.xminBar.datetime = bar.datetime
|
||||
self.xminBar.openInterest = bar.openInterest
|
||||
self.xminBar.volume += int(bar.volume)
|
||||
|
||||
# X分钟已经走完
|
||||
if not bar.datetime.minute % self.xmin: # 可以用X整除
|
||||
# 生成上一X分钟K线的时间戳
|
||||
self.xminBar.datetime = self.xminBar.datetime.replace(second=0, microsecond=0) # 将秒和微秒设为0
|
||||
self.xminBar.date = self.xminBar.datetime.strftime('%Y%m%d')
|
||||
self.xminBar.time = self.xminBar.datetime.strftime('%H:%M:%S.%f')
|
||||
|
||||
# 推送
|
||||
self.onXminBar(self.xminBar)
|
||||
|
||||
# 清空老K线缓存对象
|
||||
self.xminBar = None
|
||||
|
218
vnpy/trader/app/ctaStrategy/strategy/strategyBollChannel.py
Normal file
218
vnpy/trader/app/ctaStrategy/strategy/strategyBollChannel.py
Normal file
@ -0,0 +1,218 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
"""
|
||||
感谢Darwin Quant贡献的策略思路。
|
||||
知乎专栏原文:https://zhuanlan.zhihu.com/p/24448511
|
||||
|
||||
策略逻辑:
|
||||
1. 布林通道(信号)
|
||||
2. CCI指标(过滤)
|
||||
3. ATR指标(止损)
|
||||
|
||||
适合品种:螺纹钢
|
||||
适合周期:15分钟
|
||||
|
||||
这里的策略是作者根据原文结合vn.py实现,对策略实现上做了一些修改,仅供参考。
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import division
|
||||
|
||||
import talib
|
||||
import numpy as np
|
||||
|
||||
from vnpy.trader.vtObject import VtBarData
|
||||
from vnpy.trader.vtConstant import EMPTY_STRING
|
||||
from vnpy.trader.app.ctaStrategy.ctaTemplate import CtaTemplate, BarManager
|
||||
|
||||
|
||||
########################################################################
|
||||
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 # 每次交易的数量
|
||||
|
||||
# 策略变量
|
||||
bufferSize = 100 # 需要缓存的数据的大小
|
||||
bufferCount = 0 # 目前已经缓存了的数据的计数
|
||||
highArray = np.zeros(bufferSize) # K线最高价的数组
|
||||
lowArray = np.zeros(bufferSize) # K线最低价的数组
|
||||
closeArray = np.zeros(bufferSize) # K线收盘价的数组
|
||||
|
||||
bollMid = 0 # 布林通道中轨
|
||||
bollStd = 0 # 布林通道标准差
|
||||
bollUp = 0 # 布林通道上轨
|
||||
bollDown = 0 # 布林通道下轨
|
||||
cciValue = 0 # CCI指标数值
|
||||
atrValue = 0 # ATR指标数值
|
||||
|
||||
intraTradeHigh = 0 # 持仓期内的最高点
|
||||
intraTradeLow = 0 # 持仓期内的最低点
|
||||
longStop = 0 # 多头止损
|
||||
shortStop = 0 # 空头止损
|
||||
|
||||
orderList = [] # 保存委托代码的列表
|
||||
|
||||
# 参数列表,保存了参数的名称
|
||||
paramList = ['name',
|
||||
'className',
|
||||
'author',
|
||||
'vtSymbol',
|
||||
'bollWindow',
|
||||
'bollDev',
|
||||
'cciWindow',
|
||||
'atrWindow',
|
||||
'slMultiplier',
|
||||
'initDays',
|
||||
'fixedSize']
|
||||
|
||||
# 变量列表,保存了变量的名称
|
||||
varList = ['inited',
|
||||
'trading',
|
||||
'pos',
|
||||
'bollMid',
|
||||
'bollStd',
|
||||
'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线合成器对象
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
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线"""
|
||||
# 撤销之前发出的尚未成交的委托(包括限价单和停止单)
|
||||
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.closeArray[-1] = bar.close
|
||||
self.highArray[-1] = bar.high
|
||||
self.lowArray[-1] = bar.low
|
||||
|
||||
self.bufferCount += 1
|
||||
if self.bufferCount < self.bufferSize:
|
||||
return
|
||||
|
||||
# 计算指标数值
|
||||
self.bollMid = self.closeArray[-self.bollWindow:].mean()
|
||||
self.bollStd = self.closeArray[-self.bollWindow:].std()
|
||||
self.bollUp = self.bollMid + self.bollStd * self.bollDev
|
||||
self.bollDown = self.bollMid - self.bollStd * self.bollDev
|
||||
|
||||
self.cciValue = talib.CCI(self.highArray,
|
||||
self.lowArray,
|
||||
self.closeArray,
|
||||
self.cciWindow)[-1]
|
||||
self.atrValue = talib.ATR(self.highArray,
|
||||
self.lowArray,
|
||||
self.closeArray,
|
||||
self.atrWindow)[-1]
|
||||
|
||||
# 判断是否要进行交易
|
||||
|
||||
# 当前无仓位,发送OCO开仓委托
|
||||
if self.pos == 0:
|
||||
self.intraTradeHigh = bar.high
|
||||
self.intraTradeLow = bar.low
|
||||
|
||||
if self.cciValue > 0:
|
||||
l = self.buy(self.bollUp, self.fixedSize, True)
|
||||
self.orderList.extend(l)
|
||||
elif self.cciValue < 0:
|
||||
l = self.short(self.bollDown, self.fixedSize, True)
|
||||
self.orderList.extend(l)
|
||||
|
||||
# 持有多头仓位
|
||||
elif self.pos > 0:
|
||||
self.intraTradeHigh = max(self.intraTradeHigh, bar.high)
|
||||
self.intraTradeLow = bar.low
|
||||
self.longStop = self.intraTradeHigh - self.atrValue * self.slMultiplier
|
||||
|
||||
l = self.sell(self.longStop, abs(self.pos), True)
|
||||
self.orderList.extend(l)
|
||||
|
||||
# 持有空头仓位
|
||||
elif self.pos < 0:
|
||||
self.intraTradeHigh = bar.high
|
||||
self.intraTradeLow = min(self.intraTradeLow, bar.low)
|
||||
self.shortStop = self.intraTradeLow + self.atrValue * self.slMultiplier
|
||||
|
||||
l = self.cover(self.shortStop, abs(self.pos), True)
|
||||
self.orderList.extend(l)
|
||||
|
||||
# 发出状态更新事件
|
||||
self.putEvent()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def onOrder(self, order):
|
||||
"""收到委托变化推送(必须由用户继承实现)"""
|
||||
pass
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def onTrade(self, trade):
|
||||
# 发出状态更新事件
|
||||
self.putEvent()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def onStopOrder(self, so):
|
||||
"""停止单推送"""
|
||||
pass
|
@ -112,7 +112,6 @@ class KkStrategy(CtaTemplate):
|
||||
#----------------------------------------------------------------------
|
||||
def onFiveBar(self, bar):
|
||||
"""收到5分钟K线"""
|
||||
print bar.datetime, bar.open, bar.high, bar.low, bar.close
|
||||
# 撤销之前发出的尚未成交的委托(包括限价单和停止单)
|
||||
for orderID in self.orderList:
|
||||
self.cancelOrder(orderID)
|
||||
|
Loading…
Reference in New Issue
Block a user