您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)VNPY中基于Ta-lib的KDJ策略怎樣實(shí)現(xiàn),小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。
VNPY自帶演示策略中,沒(méi)有kdj策略,作為一個(gè)國(guó)內(nèi)常用策略,這里講講怎么實(shí)現(xiàn)。
首先,Ta-lib這個(gè)python庫(kù)里面并沒(méi)有提供kdj策略,估計(jì)主要因?yàn)檫@個(gè)策略主要在流行,不過(guò)ta-lib提供了類(lèi)似的方法STOCH()??梢詫?shí)現(xiàn)KD效果。
那么首先為class ArrayManager新增一個(gè)方法kdj,來(lái)輸出KDJ值。我是直接修改ctaTemplate.py 文件,更合適方法是繼承class ArrayManager。
def kdj(self, fastk_period, slowk_period, slowk_matype ,slowd_period ,slowd_matype, array=False):
"""KDJ指標(biāo)"""
slowk, slowd = talib.STOCH(self.high,self.low,self.close,fastk_period, slowk_period,
slowk_matype, slowd_period ,slowd_matype)
# 求出J值,J = (3 * D) - (2 * K)
slowj = list(map(lambda x,y: 3 * x - 2 * y, slowk, slowd))
if array:
return slowk, slowd, slowj
return slowk[-1], slowd[-1], slowj[-1]
上面是新增的kdj功能,首先是利用SHOCH計(jì)算出kd,在利用kd算出j,輸出kdj三個(gè)指標(biāo)。
SHOCH計(jì)算需要每條k線中的最高值,最低值,和結(jié)束值參數(shù),作為list數(shù)列提供;這個(gè)直接使用ArraManger提供值;然后是fastK_period, slowk_period和slowd_period, 這個(gè)就是kdj設(shè)定中常見(jiàn)的N,M1,M2三個(gè)窗口參數(shù), 通常設(shè)置是(9,3,3)。
然后是slowk_matype, slowd_matype就是平均算法類(lèi)型,這里可以用SMA滑動(dòng)平均或EMA指數(shù)平滑移動(dòng)平均等。為了和文華一致,用了SMA。
#MA_Type: 0=SMA, 1=EMA, 2=WMA, 3=DEMA, 4=TEMA, 5=TRIMA, 6=KAMA, 7=MAMA, 8=T3 (Default=SMA)
這個(gè)后來(lái)發(fā)現(xiàn)不是一回事,Ta-lib中的SMA中S是simple簡(jiǎn)單的意思,SMA是簡(jiǎn)單移動(dòng)平均。和文華SMA不一樣,文華SMA是指數(shù)加權(quán)移動(dòng)平均線,這樣的化用EWMA更合適。但是Ta-lib本身并不提供提供EWMA;按照下圖發(fā)現(xiàn)默認(rèn)權(quán)重為1; EMA或者較為合適,不過(guò)此時(shí)權(quán)重為2。
后來(lái)看著此文又不是一回事,以后有空填這個(gè)坑。
https://www.joinquant.com/post/7920
j值不提供直接只算,直接用kd值,用3*k-2*d算出j值。對(duì)了這些返回都是一堆kdj組list,就是可以畫(huà)成一個(gè)線。如果是array是false就返回一個(gè)點(diǎn)的kdj值。
好了上面就是對(duì) ArrayManager增加一個(gè)kdj方法,在下來(lái)就是繼承CtaTemplate, 生成策略,這里基本就是
買(mǎi)入思想就是k或d小于某個(gè)閾值時(shí)候?yàn)槌u(mài),當(dāng)k大于d,就是描述里面K線上穿d線時(shí)候,開(kāi)多單。反之k或d值大于閾值多超買(mǎi),那么此時(shí)k小于d,開(kāi)空單。。
如果持有多頭,那么因?yàn)閖更加敏感,用j值來(lái)做平倉(cāng)指標(biāo). 如果持有多單,,如果j小于d,即j線下穿d線時(shí)候賣(mài)出多單,或者j值快速下降,下降幅度大于定好的jlimit。。
如果持有空頭,同理,如果j大于d,或者j快速增大則平倉(cāng)。
代碼如下:
# encoding: UTF-8
"""
這里的Demo是一個(gè)kdj策略實(shí)現(xiàn)
"""
from __future__ import division
from vnpy.trader.vtConstant import EMPTY_STRING, EMPTY_FLOAT
from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate,
BarGenerator,
ArrayManager)
from talib import MA_Type
########################################################################
class KDJStrategy(CtaTemplate):
"""KDJ策略Demo"""
className = 'KDJStrategy'
author = u'BillyZhang'
# 策略參數(shù)
fastk_period = 9
slowk_period = 3
slowk_matype = MA_Type.EMA
slowd_period = 3
slowd_matype = MA_Type.EMA
kdlimit = 20
jlimit = 10
initDays = 10
fixedSize = 1
barmins = 15
# 策略變量
k = 0
d = 0
j = 0
# 參數(shù)列表,保存了參數(shù)的名稱
paramList = ['name',
'className',
'author',
'vtSymbol',
'fastk_period',
'slowk_period',
'slowk_matype',
'slowd_period',
'slowd_matype',
'fixedSize'
'barmins'
]
# 變量列表,保存了變量的名稱
varList = ['inited',
'pos',
'k',
'd',
'j']
# 同步列表,保存了需要保存到數(shù)據(jù)庫(kù)的變量名稱
syncList = ['pos']
# ----------------------------------------------------------------------
def __init__(self, ctaEngine, setting):
"""Constructor"""
super(KDJStrategy, self).__init__(ctaEngine, setting)
self.bg = BarGenerator(self.onBar, self.barmins, self.onXminBar)
self.am = ArrayManager()
# 注意策略類(lèi)中的可變對(duì)象屬性(通常是list和dict等),在策略初始化時(shí)需要重新創(chuàng)建,
# 否則會(huì)出現(xiàn)多個(gè)策略實(shí)例之間數(shù)據(jù)共享的情況,有可能導(dǎo)致潛在的策略邏輯錯(cuò)誤風(fēng)險(xiǎn),
# 策略類(lèi)中的這些可變對(duì)象屬性可以選擇不寫(xiě),全都放在__init__下面,寫(xiě)主要是為了閱讀
# 策略時(shí)方便(更多是個(gè)編程習(xí)慣的選擇)
# ----------------------------------------------------------------------
def onInit(self):
"""初始化策略(必須由用戶繼承實(shí)現(xiàn))"""
self.writeCtaLog(u'KDJ策略初始化')
initData = self.loadBar(self.initDays)
for bar in initData:
self.onBar(bar)
self.putEvent()
# ----------------------------------------------------------------------
def onStart(self):
"""啟動(dòng)策略(必須由用戶繼承實(shí)現(xiàn))"""
self.writeCtaLog(u'KDJ策略啟動(dòng)')
self.putEvent()
# ----------------------------------------------------------------------
def onStop(self):
"""停止策略(必須由用戶繼承實(shí)現(xiàn))"""
self.writeCtaLog(u'KDJ策略停止')
self.putEvent()
# ----------------------------------------------------------------------
def onTick(self, tick):
"""收到行情T(mén)ICK推送(必須由用戶繼承實(shí)現(xiàn))"""
self.bg.updateTick(tick)
# ----------------------------------------------------------------------
def onBar(self, bar):
"""收到Bar推送(必須由用戶繼承實(shí)現(xiàn))"""
self.bg.updateBar(bar)
# ----------------------------------------------------------------------
def onXminBar(self, bar):
"""收到Bar推送(必須由用戶繼承實(shí)現(xiàn))"""
am = self.am
am.updateBar(bar)
if not am.inited:
return
# 計(jì)算kdj數(shù)值
slowk, slowd, slowj = am.kdj(self.fastk_period, self.slowk_period, self.slowk_matype,
self.slowd_period, self.slowd_matype, array=True)
self.k = slowk[-1]
self.d = slowd[-1]
self.j = slowj[-1]
self.jdif = slowj[-1] - slowj[-2]
tradeindictor = 0
if self.k > (100 - self.kdlimit) or self.d > (100 - self.kdlimit):
tradeindictor = -1
if self.k < self.kdlimit or self.d < self.kdlimit:
tradeindictor = 1
# 當(dāng)前無(wú)倉(cāng)位,發(fā)送開(kāi)倉(cāng)委托
if self.pos == 0:
self.intraTradeHigh = bar.high
self.intraTradeLow = bar.low
# 如果k值大于d值均線,開(kāi)多單;反之,如果如果k值小于d值時(shí)候開(kāi)空單
if self.k > self.d and tradeindictor == 1:
self.buy(bar.close, self.fixedSize, False)
elif self.k < self.d and tradeindictor == -1:
self.short(bar.close, self.fixedSize, False)
# 持有多頭倉(cāng)位; 如果j小于d,或者j最近兩個(gè)k線,j值下跌超過(guò)jlimi平倉(cāng), :
elif self.pos > 0:
if self.j < self.d or self.jdif < -1 *self.jlimit:
self.sell(bar.close * 1.03, abs(self.pos))
# 持有空頭倉(cāng)位;如果j大于d,或j快速上揚(yáng) 平倉(cāng);
elif self.pos < 0:
if self.j > self.d or self.jdif > self.jlimit:
self.cover(bar.close * 0.97, abs(self.pos))
# 同步數(shù)據(jù)到數(shù)據(jù)庫(kù)
self.saveSyncData()
# 發(fā)出狀態(tài)更新事件
self.putEvent()
# ----------------------------------------------------------------------
def onOrder(self, order):
"""收到委托變化推送(必須由用戶繼承實(shí)現(xiàn))"""
# 對(duì)于無(wú)需做細(xì)粒度委托控制的策略,可以忽略onOrder
pass
# ----------------------------------------------------------------------
def onTrade(self, trade):
"""收到成交推送(必須由用戶繼承實(shí)現(xiàn))"""
# 對(duì)于無(wú)需做細(xì)粒度委托控制的策略,可以忽略onOrder
pass
# ----------------------------------------------------------------------
def onStopOrder(self, so):
"""停止單推送"""
pass
以上就是VNPY中基于Ta-lib的KDJ策略怎樣實(shí)現(xiàn),小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。