iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 27
1

基礎需求

依據指標,設計一套規則判斷進場或出場,並以事件方式提供註冊對象。

模組實作

基底類別

首先定義一個抽象類別規範每個策略運行模組都應提供的事件與應實作的函數。

Strategy.py

import abc

import events

class Strategy(abc.ABC, events.Events):
    __events__ = ('OnBuy', 'OnSell')

    # 待實作函數:提供指標給策略
    @abc.abstractmethod
    def Feed(self, data):
        return NotImplemented

Buy3RK1BKAndSell3BK1RK.py

from Strategy import *

# 策略目標
# 買進:連續 3 隻紅 K 後出現 1 隻黑 K
# 賣出:連續 3 隻黑 K 後出現 1 隻紅 K
class Buy3RK1BKAndSell3BK1RK(Strategy):

    def __init__(self):
        # 存放過去 3 隻 K 棒的類型
        self.Bars = []
    
    # 實作函數:提供指標給策略
    def Feed(self, data):
        # 開小於收為 +1(黑 K)
        # 開收相等為 0
        # 開大於收為 -1(紅 K)
        status = 0
        # 判斷黑 K
        if data.open > data.close:
            status = +1
        # 判斷紅 K
        if data.open < data.close:
            status = -1
        # 判斷買進條件符合並發出事件
        if sum(self.Bars) == -3 and status == +1:
            if self.OnBuy is not None:
                self.OnBuy(self, data)
        # 判斷賣出條件符合並發出事件
        if sum(self.Bars) == +3 and status == -1:
            if self.OnSell is not None:
                self.OnSell(self, data)
        # 保存 K 棒類型
        self.Bars.append(status)
        # 若保存超過 3 隻 K 棒,則移除第 1 隻 K 棒
        if len(self.Bars) > 3:
            self.Bars.pop(0)

DataSource.py

import abc

import events
import munch

class DataSource(abc.ABC, events.Events):
    __events__ = ('OnData')

    def __init__(self, name, option):
        self.Name = name
        self.Option = munch.munchify(option)
        self.Sequence = []

    @abc.abstractmethod
    def Setup(self):
        return NotImplemented

    @abc.abstractmethod
    def Start(self):
        return NotImplemented

MongoDataSource.py

import munch
import pymongo

class MongoDataSource(DataSource):

    def Setup(self):
        self.Client = pymongo.MongoClient(
            f'mongodb://{self.Option.Username}:{self.Option.Password}@{self.Option.Host}:{self.Option.Port}/'
        )
        self.Database = self.Client[self.Option.Database]

    def Start(self):
        cursor = self.Database[self.Option.Collection].find().sort([('created', 1)])
        for doc in cursor:
            doc = munch.munchify(doc)
            self.Sequence.append(doc)
            if self.OnData is not None:
                self.OnData(self, doc)

main.py

from MongoDataSource import *
from TimeSeriesManager import *
from Buy3RK1BKAndSell3BK1RK import *

def main():

    def OnData(ds, data):
        # 若為 1 分 K 訊號,則提供給策略執行模組
        if ds.Name == 'TXF-1MINK':
            strategy.Feed(data)

    def OnBuy(ds, data):
        print(f'[BUY]\n{data}\n')

    def OnSell(ds, data):
        print(f'[SELL]\n{data}\n')

    # 建立策略執行模組並轉接買賣訊號事件
    strategy = Buy3RK1BKAndSell3BK1RK()
    strategy.OnBuy += OnBuy
    strategy.OnSell += OnSell

    tsm = TimeSeriesManager()
    tsm.DataSources.append(MongoDataSource(
        name='TXF-1MINK',
        option={
            'Username': 'root',
            'Password': 'root',
            'Host': 'localhost',
            'Port': 27017,
            'Database': 'backtest',
            'Collection': 'k1min'
        }
    ))
    tsm.OnData = OnData
    tsm.Setup()
    tsm.Start()

if __name__ == '__main__':
    main()

執行結果

目前已可從策略運行模組獲得進出場訊號,接下來就是透過交易執行模組決定如何進出場,以及進出場實際在回測模組中應考量的現實交易層面問題。


團隊系列文:

CSScoke - 金魚都能懂的這個網頁畫面怎麼切 - 金魚都能懂了你還怕學不會嗎
Clarence - LINE bot 好好玩 30 天玩轉 LINE API
Hina Hina - 陣列大亂鬥
King Tzeng - IoT沒那麼難!新手用JavaScript入門做自己的玩具
Vita Ora - 好 Js 不學嗎 !? JavaScript 入門中的入門。
TaTaMo - 用Python開發的網頁不能放到Github上?Lektor說可以!!


上一篇
Day-26 回測系統:時序運行模組
下一篇
Day-28 回測系統:交易執行模組
系列文
Python 程式交易 30 天新手入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言