[Mod]修改CTA自带策略使用ArrayManager,技术指标函数支持返回数组

This commit is contained in:
vn.py 2017-10-07 22:36:23 +08:00
parent b901e579ae
commit ce65a32159
9 changed files with 178 additions and 471 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"collapsed": false
},
@ -16,7 +16,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {
"collapsed": false
},
@ -28,7 +28,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {
"collapsed": false
},
@ -42,7 +42,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {
"collapsed": true
},
@ -58,7 +58,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {
"collapsed": true
},
@ -71,25 +71,11 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2017-10-07 18:16:51.192000\t开始载入数据\n",
"2017-10-07 18:16:51.306000\t载入完成数据量332899\n",
"2017-10-07 18:16:51.306000\t开始回测\n",
"2017-10-07 18:16:51.306000\t策略初始化完成\n",
"2017-10-07 18:16:51.306000\t策略启动完成\n",
"2017-10-07 18:16:51.306000\t开始回放数据\n",
"2017-10-07 18:17:04.696000\t数据回放结束\n"
]
}
],
"outputs": [],
"source": [
"# 运行回测\n",
"engine.runBacktesting()"

View File

@ -486,34 +486,73 @@ class ArrayManager(object):
return self.volumeArray
#----------------------------------------------------------------------
def sma(self, n, shift=0):
"""均线"""
return talib.SMA(self.close, n)[-1-shift]
def sma(self, n, array=False):
"""简单均线"""
result = talib.SMA(self.close, n)
if array:
return result
return result[-1]
#----------------------------------------------------------------------
def std(self, n, shift=0):
def std(self, n, array=False):
"""标准差"""
return talib.STDDEV(self.close, n)[-1-shift]
result = talib.STDDEV(self.close, n)
if array:
return result
return result[-1]
#----------------------------------------------------------------------
def boll(self, n, dev, shift=0):
def cci(self, n, array=False):
"""CCI指标"""
result = talib.CCI(self.high, self.low, self.close, n)
if array:
return result
return result[-1]
#----------------------------------------------------------------------
def atr(self, n, array=False):
"""ATR指标"""
result = talib.ATR(self.high, self.low, self.close, n)
if array:
return result
return result[-1]
#----------------------------------------------------------------------
def rsi(self, n, array=False):
"""RSI指标"""
result = talib.RSI(self.close, n)
if array:
return result
return result[-1]
#----------------------------------------------------------------------
def boll(self, n, dev, array=False):
"""布林通道"""
mid = self.sma(n, shift)
std = self.std(n, shift)
mid = self.sma(n, array)
std = self.std(n, array)
up = mid + std * dev
down = mid - std * dev
return up, down
#----------------------------------------------------------------------
def keltner(self, n, dev, array=False):
"""肯特纳通道"""
mid = self.sma(n, array)
atr = self.atr(n, array)
up = mid + atr * dev
down = mid - atr * dev
return up, down
#----------------------------------------------------------------------
def cci(self, n, shift=0):
"""CCI指标"""
return talib.CCI(self.high, self.low, self.close, n)[-1-shift]
def donchian(self, n, array=False):
"""唐奇安通道"""
up = talib.MAX(self.high, n)
down = talib.MIN(self.low, n)
#----------------------------------------------------------------------
def atr(self, n, shift=0):
"""ATR指标"""
return talib.ATR(self.high, self.low, self.close, n)[-1-shift]
if array:
return up, down
return up[-1], down[-1]

View File

@ -10,12 +10,11 @@
"""
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
from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate,
BarManager,
ArrayManager)
########################################################################
@ -34,17 +33,8 @@ class AtrRsiStrategy(CtaTemplate):
fixedSize = 1 # 每次交易的数量
# 策略变量
bufferSize = 100 # 需要缓存的数据的大小
bufferCount = 0 # 目前已经缓存了的数据的计数
highArray = np.zeros(bufferSize) # K线最高价的数组
lowArray = np.zeros(bufferSize) # K线最低价的数组
closeArray = np.zeros(bufferSize) # K线收盘价的数组
atrCount = 0 # 目前已经缓存了的ATR的计数
atrArray = np.zeros(bufferSize) # ATR指标的数组
atrValue = 0 # 最新的ATR指标数值
atrMa = 0 # ATR移动平均的数值
rsiValue = 0 # RSI指标的数值
rsiBuy = 0 # RSI买开阈值
rsiSell = 0 # RSI卖开阈值
@ -81,6 +71,7 @@ class AtrRsiStrategy(CtaTemplate):
# 创建K线合成器对象
self.bm = BarManager(self.onBar)
self.am = ArrayManager()
# 注意策略类中的可变对象属性通常是list和dict等在策略初始化时需要重新创建
# 否则会出现多个策略实例之间数据共享的情况,有可能导致潜在的策略逻辑错误风险,
@ -129,34 +120,17 @@ class AtrRsiStrategy(CtaTemplate):
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:
am = self.am
am.updateBar(bar)
if not am.inited:
return
# 计算指标数值
self.atrValue = talib.ATR(self.highArray,
self.lowArray,
self.closeArray,
self.atrLength)[-1]
self.atrArray[0:self.bufferSize-1] = self.atrArray[1:self.bufferSize]
self.atrArray[-1] = self.atrValue
self.atrCount += 1
if self.atrCount < self.bufferSize:
return
self.atrMa = talib.MA(self.atrArray,
self.atrMaLength)[-1]
self.rsiValue = talib.RSI(self.closeArray,
self.rsiLength)[-1]
atrArray = am.atr(self.atrLength, array=True)
self.atrValue = atrArray[-1]
self.atrMa = atrArray[-self.atrMaLength:].mean()
self.rsiValue = am.rsi(self.rsiLength)
# 判断是否要进行交易

View File

@ -18,9 +18,6 @@
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,

View File

@ -1,7 +1,7 @@
# encoding: UTF-8
"""
这里的Demo是一个最简单的策略实现并未考虑太多实盘中的交易细节
这里的Demo是一个最简单的双均线策略实现并未考虑太多实盘中的交易细节
1. 委托价格超出涨跌停价导致的委托失败
2. 委托未成交需要撤单后重新委托
3. 断网后恢复交易状态
@ -13,28 +13,28 @@
from __future__ import division
from vnpy.trader.vtObject import VtBarData
#from vnpy.trader.vtObject import VtBarData
from vnpy.trader.vtConstant import EMPTY_STRING, EMPTY_FLOAT
from vnpy.trader.app.ctaStrategy.ctaTemplate import CtaTemplate, BarManager
from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate,
BarManager,
ArrayManager)
########################################################################
class EmaDemoStrategy(CtaTemplate):
class DoubleMaStrategy(CtaTemplate):
"""双指数均线策略Demo"""
className = 'EmaDemoStrategy'
className = 'DoubleMaStrategy'
author = u'用Python的交易员'
# 策略参数
fastK = 0.9 # 快速EMA参数
slowK = 0.1 # 慢速EMA参数
fastWindow = 10 # 快速均线参数
slowWindow = 60 # 慢速均线参数
initDays = 10 # 初始化数据所用的天数
# 策略变量
fastMa = [] # 快速EMA均线数组
fastMa0 = EMPTY_FLOAT # 当前最新的快速EMA
fastMa1 = EMPTY_FLOAT # 上一根的快速EMA
slowMa = [] # 与上面相同
slowMa0 = EMPTY_FLOAT
slowMa1 = EMPTY_FLOAT
@ -43,8 +43,8 @@ class EmaDemoStrategy(CtaTemplate):
'className',
'author',
'vtSymbol',
'fastK',
'slowK']
'fastWindow',
'slowWindow']
# 变量列表,保存了变量的名称
varList = ['inited',
@ -58,16 +58,15 @@ class EmaDemoStrategy(CtaTemplate):
#----------------------------------------------------------------------
def __init__(self, ctaEngine, setting):
"""Constructor"""
super(EmaDemoStrategy, self).__init__(ctaEngine, setting)
super(DoubleMaStrategy, self).__init__(ctaEngine, setting)
self.bm = BarManager(self.onBar)
self.am = ArrayManager()
# 注意策略类中的可变对象属性通常是list和dict等在策略初始化时需要重新创建
# 否则会出现多个策略实例之间数据共享的情况,有可能导致潜在的策略逻辑错误风险,
# 策略类中的这些可变对象属性可以选择不写全都放在__init__下面写主要是为了阅读
# 策略时方便(更多是个编程习惯的选择)
self.fastMa = []
self.slowMa = []
#----------------------------------------------------------------------
def onInit(self):
@ -100,23 +99,20 @@ class EmaDemoStrategy(CtaTemplate):
#----------------------------------------------------------------------
def onBar(self, bar):
"""收到Bar推送必须由用户继承实现"""
am = self.am
am.updateBar(bar)
if not am.inited:
return
# 计算快慢均线
if not self.fastMa0:
self.fastMa0 = bar.close
self.fastMa.append(self.fastMa0)
else:
self.fastMa1 = self.fastMa0
self.fastMa0 = bar.close * self.fastK + self.fastMa0 * (1 - self.fastK)
self.fastMa.append(self.fastMa0)
if not self.slowMa0:
self.slowMa0 = bar.close
self.slowMa.append(self.slowMa0)
else:
self.slowMa1 = self.slowMa0
self.slowMa0 = bar.close * self.slowK + self.slowMa0 * (1 - self.slowK)
self.slowMa.append(self.slowMa0)
fastMa = am.sma(self.fastWindow, array=True)
self.fastMa0 = fastMa[-1]
self.fastMa1 = fastMa[-2]
slowMa = am.sma(self.slowWindow, array=True)
self.slowMa0 = slowMa[-1]
self.slowMa1 = slowMa[-2]
# 判断买卖
crossOver = self.fastMa0>self.slowMa0 and self.fastMa1<self.slowMa1 # 金叉上穿
crossBelow = self.fastMa0<self.slowMa0 and self.fastMa1>self.slowMa1 # 死叉下穿

View File

@ -12,12 +12,11 @@
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
from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate,
BarManager,
ArrayManager)
########################################################################
@ -34,14 +33,6 @@ class KkStrategy(CtaTemplate):
fixedSize = 1 # 每次交易的数量
# 策略变量
bufferSize = 100 # 需要缓存的数据的大小
bufferCount = 0 # 目前已经缓存了的数据的计数
highArray = np.zeros(bufferSize) # K线最高价的数组
lowArray = np.zeros(bufferSize) # K线最低价的数组
closeArray = np.zeros(bufferSize) # K线收盘价的数组
atrValue = 0 # 最新的ATR指标数值
kkMid = 0 # KK通道中轨
kkUp = 0 # KK通道上轨
kkDown = 0 # KK通道下轨
intraTradeHigh = 0 # 持仓期内的最高点
@ -63,8 +54,6 @@ class KkStrategy(CtaTemplate):
varList = ['inited',
'trading',
'pos',
'atrValue',
'kkMid',
'kkUp',
'kkDown']
@ -74,6 +63,7 @@ class KkStrategy(CtaTemplate):
super(KkStrategy, self).__init__(ctaEngine, setting)
self.bm = BarManager(self.onBar, 5, self.onFiveBar) # 创建K线合成器对象
self.am = ArrayManager()
#----------------------------------------------------------------------
def onInit(self):
@ -118,27 +108,14 @@ class KkStrategy(CtaTemplate):
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:
am = self.am
am.updateBar(bar)
if not am.inited:
return
# 计算指标数值
self.atrValue = talib.ATR(self.highArray,
self.lowArray,
self.closeArray,
self.kkLength)[-1]
self.kkMid = talib.MA(self.closeArray, self.kkLength)[-1]
self.kkUp = self.kkMid + self.atrValue * self.kkDev
self.kkDown = self.kkMid - self.atrValue * self.kkDev
self.kkUp, self.kkDown = am.keltner(self.kkLength, self.kkDev)
# 判断是否要进行交易
# 当前无仓位发送OCO开仓委托