VNPY 一種基於統計的交易策略簡易實現
交易思維是基於歷史資料中,一組資料比如100天中,K線中最高點或者最低點相對於開始價位價差點差,再利用numpy的函式numpy.percentile(), 計算在比如95%機會,最高點或者最低點的點差數字。如果點差是5個點,就可以認為下一根K線也有95%機率有5個點受益。
嘗試在VNPY實現。
思路整理:
1 . 入場:如果最近 N ( 30 )個 D 分鐘 k 線,透過下面程式碼計算,分析對於機率prb比如90%,如果存在一個點差大於TickValueLimit 一個值 TickValue ,說明過去 N 個分鐘,有 P 的機率, bar 開始下單,在 bar 中有最高點或者最低點獲得 TickValue 。那麼在下個 bar 開始時候,買入。
2 . 出場,如果到達持有價格POSprice +/- TickValue, 則賣出;重新進行入場分析。如果這個 bar 中間沒到達目標價格,在 bar 結束時候分析是否還滿足入場條件,如果繼續滿足則持有,否則平倉,如果是反向,則反向開單。
3.止損,如果在持有時候,下跌到反向POSPrice +/- Multiple * TickValue 價格時候,平倉。Multiple 隨著時間增加逐漸減少。
示例程式碼如下,最後很遺憾,回測效果非常不好。
from __future__ import division from vnpy.trader.vtConstant import EMPTY_STRING, EMPTY_FLOAT, OFFSET_OPEN,OFFSET_CLOSE from vnpy.trader.app.ctaStrategy.ctaTemplate import (CtaTemplate, BarGenerator, ArrayManager) import numpy as np from datetime import datetime, time ######################################################################## class PercentileStrategy(CtaTemplate): """MACD策略Demo""" className = 'PercentileStrategy' author = u'BillyZhang' fixedSize = 1 # 策略引數 calWindow = 15 percentile = 95 tickValueLimit = 5 Multiple = 0.8 # 策略變數 p = 0 tickValue = 0 tradeSign = 0 tickValueHigh = 0 tickValueLow = 0 longStop = 0 # 多頭止損 shortStop = 0 # 空頭止損 margin = 0 lowerLimit = 0 upperLimit = 50000 # 時間 initDays = 0 DAY_START = time(9, 10) # 日盤啟動和停止時間 DAY_END = time(14, 55) NIGHT_START = time(21, 10) # 夜盤啟動和停止時間 NIGHT_END = time(10, 55) # 引數列表,儲存了引數的名稱 paramList = ['name', 'className', 'author', 'vtSymbol', 'initDays', 'fixedSize', 'calWindow', 'percentile', 'tickValueLimit', 'Multiple' ] # 變數列表,儲存了變數的名稱 varList = ['inited', 'trading', 'pos', 'longStop', 'shortStop', 'posPrice', 'lowerLimit', 'p', 'tickValue', 'tradeSign', 'tickValueHigh', 'tickValueLow' ] # 同步列表,儲存了需要儲存到資料庫的變數名稱 syncList = ['pos', 'posPrice', 'longStop', 'shortStop' ] # ---------------------------------------------------------------------- def __init__(self, ctaEngine, setting): """Constructor""" super(PercentileStrategy, self).__init__(ctaEngine, setting) self.am = ArrayManager(size = self.calWindow) # 注意策略類中的可變物件屬性(通常是list和dict等),在策略初始化時需要重新建立, # 否則會出現多個策略例項之間資料共享的情況,有可能導致潛在的策略邏輯錯誤風險, # 策略類中的這些可變物件屬性可以選擇不寫,全都放在__init__下面,寫主要是為了閱讀 # 策略時方便(更多是個程式設計習慣的選擇) # ---------------------------------------------------------------------- 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): """啟動策略(必須由使用者繼承實現)""" if self.pos == 0: self.writeCtaLog(u'%s策略啟動' % self.name) # 當前無倉位,傳送開倉委託 # 持有多頭倉位 self.putEvent() # ---------------------------------------------------------------------- def onStop(self): """停止策略(必須由使用者繼承實現)""" self.writeCtaLog(u'%s策略停止' % self.name) self.putEvent() # ---------------------------------------------------------------------- def onTick(self, tick): """收到行情TICK推送(必須由使用者繼承實現)""" if self.lowerLimit == 0 or self.upperLimit == 0: self.lowerLimit = tick.lowerLimit self.upperLimit = tick.upperLimit self.bg.updateTick(tick) # ---------------------------------------------------------------------- def onBar(self, bar): """收到Bar推送(必須由使用者繼承實現)""" #如果是當然最後5分鐘,略過 am = self.am am.updateBar(bar) if not am.inited: return # currentTime = datetime.now().time() currentTime = time(9,20) #計算p,和tickValue MaxHigh = am.high / am.open MaxLow = am.low / am.open MaxClose = am.close / am.open lpHigh = np.percentile(MaxHigh, 100 - self.percentile) lpLow = np.percentile(MaxLow, self.percentile) self.tickValueHigh = abs(bar.open - bar.open*lpHigh) self.tickValueLow = abs(bar.open - bar.open * lpLow) if self.tickValueHigh > self.tickValueLow and self.tickValueHigh > self.tickValueLimit: self.tradeSign = 1 elif self.tickValueHigh < self.tickValueLow and self.tickValueLow > self.tickValueLimit: self.tradeSign = -1 else: self.tradeSign = 0 # 平當日倉位, 如果當前時間是結束前日盤15點28分鐘,或者夜盤10點58分鐘,如果有持倉,平倉。 if ((currentTime >= self.DAY_START and currentTime <= self.DAY_END) or (currentTime >= self.NIGHT_START and currentTime <= self.NIGHT_END)): if self.pos == 0: if self.tradeSign == 0: pass elif self.tradeSign == 1 and bar.close > self.lowerLimit: self.buy(bar.close + 5,self.fixedSize,False) elif self.tradeSign == -1 and bar.close < self.upperLimit: self.short(bar.close - 5,self.fixedSize,False) elif self.pos > 0: if self.tradeSign == 1 or self.tradeSign == 0: pass elif self.tradeSign == -1: self.sell(bar.close-5, abs(self.pos), False) elif self.pos < 0: if self.tradeSign == -1 or self.tradeSign == 0: pass elif self.tradeSign ==1: self.cover(bar.close+5, abs(self.pos), False) else: if self.pos > 0: self.sell(bar.close-5, abs(self.pos), False) elif self.pos < 0: self.cover(bar.close+5, abs(self.pos), False) elif self.pos == 0: return # ---------------------------------------------------------------------- def onOrder(self, order): """收到委託變化推送(必須由使用者繼承實現)""" # 對於無需做細粒度委託控制的策略,可以忽略onOrder pass # ---------------------------------------------------------------------- def onTrade(self, trade): # 發出狀態更新事件 """收到成交推送(必須由使用者繼承實現)""" # 對於無需做細粒度委託控制的策略,可以忽略onOrder if trade.offset == OFFSET_OPEN: self.posPrice = trade.price if self.tradeSign == 1: self.sell(self.posPrice + self.tickValueHigh,abs(self.pos),False) self.sell(self.posPrice - self.Multiple*self.tickValueHigh, abs(self.pos), True) elif self.tradeSign == -1: self.cover(self.posPrice - self.tickValueLow, abs(self.pos), False) self.cover(self.posPrice + self.Multiple*self.tickValueLow, abs(self.pos),True) elif trade.offset == OFFSET_CLOSE: self.cancelAll() self.tradeSign = 0 # 同步資料到資料庫 self.saveSyncData() # ---------------------------------------------------------------------- def onStopOrder(self, so): """停止單推送""" pass
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22259926/viewspace-2212833/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- VNPY 基於SAR和肯特納的交易策略
- VNPY 單品種期貨的網格交易策略的實現
- VNPY 中基於Ta-lib的KDJ策略實現
- 基於Vue的簡易MVVM實現VueMVVM
- 基於Websocket的簡易webshell實現Webshell
- 基於react的hash路由簡易實現React路由
- VNPY中 Tick級別準高頻交易簡單策略
- 基於vue全家桶實現的簡易商城Vue
- 基於long pull實現簡易的訊息系統參考
- 基於 Mysql 實現一個簡易版搜尋引擎MySql
- 基於redis實現的四種常見的限流策略Redis
- 基於 WPF 的酷炫 GUI 視窗的簡易實現GUI
- JavaScript實現一個簡易的計算器JavaScript
- 基於“結構體”實現簡易版學生管理系統(Golang)結構體Golang
- 基於AOP和Redis實現的簡易版分散式鎖Redis分散式
- 實現一個簡易的響應式系統
- 實現一個簡易的vueVue
- Python基於Socket實現簡易多人聊天室Python
- 基於FFmpeg和Qt實現簡易影片播放器QT播放器
- 用兩種方式實現基於源地址的策略路由(轉)路由
- 基於LinkedBlockingQueue實現股票交易系統BloC
- 基於 Twirp RPC 的簡易 JSON Api Gateway 實現RPCJSONAPIGateway
- VNPY 交易所返回委託和交易狀態到策略的原始碼分析原始碼
- 快捷簡易統計圖表模型設計與實現模型
- 前端 JavaScript 實現一個簡易計算器前端JavaScript
- JS_實現一個簡易計算器JS
- 基於函式計算一鍵部署簡易論壇函式
- 簡易實現一個expressExpress
- python 的 Tkinter實現一個簡易計算器Python
- 基於迴歸幅度的反轉交易策略
- 手寫實現java棧結構,並實現簡易的計算器(基於字尾演算法)Java演算法
- iOS中一種字串關鍵字檢索高亮的簡易實現iOS字串
- 基於React搭建一個簡易版豆瓣React
- 基於vue搭建一個簡易版豆瓣Vue
- VNPY 自帶跨時間週期交易策略MultiTimeframeStrategy 分析
- 實現一個簡易版WebpackWeb
- 來實現一個簡易版的 PromisePromise
- 新框架ES-MAML:基於進化策略、簡易的元學習方法框架