Backtrader實際使用方式

  |  

最後,似乎已經付出了開發 backtrader是值得的。

在觀察 last 周的歐洲市場時,似乎世界末日了,一位朋友問我是否可以看看我們圖表包中的數據,看看與以前類似情況相比,下跌幅度如何。

當然可以,但我說我可以做的不僅僅是查看圖表,因為我可以快速:

  • 創建一個快速LegDown 指示器來測量跌落的範圍。它也可能被命名為 HighLowRangeHiLoRange。幸運的是,如果這被認為是必要的,可以通過以下方式解決 alias

  • 創建一個LegDownAnalyzer 將收集結果並對其進行排序的

這導致了一個額外的請求:

  • 未來5天,10天,15天,20天跌后的復甦(交易...

    通過一個LegUp 指標解決,該指標將值寫回以與相應的“LegDown”對齊

工作很快完成(在我的空閒時間內),並與請求者分享了結果。但。。。作為我看到的唯一問題:

  • 自動化方面的改進bt-run.py

    • 多種策略/observers/analyzers ,具有分離的kwargs

    • 將指標直接注入策略,每個指標都有 kwargs

    • 單一情節論證也接受瓦格斯

  • API 中的Analyzer 改進,使結果具有自動 列印 功能(作為 dict 類似 -的實例返回)並具有直接 data 訪問別名

儘管如此:

  • 由於我編寫的實現組合,出現了一個晦澀的錯誤,通過混合聲明和附加使用來對齊LegDownLegUpnext

    引入該錯誤是為了簡化單個數據與多個Lines數據的傳遞,以便 Indicators 可以作為單個數據對每個 lines 進行操作

後者將我推入:

  • 添加一個與LineDelay “展望”“未來”相反的背景物件

    這實際上意味著實際值被寫入過去的陣列位置

一旦上述所有問題都到位,就該重新測試上述請求帶來的(小?)挑戰可以更容易,更快地(在實現時間內)解決得有多好。

最後,從1998年到今天,Eurostoxx 50 Future的執行和結果:

bt-run.py \
    --csvformat vchartcsv \
    --data ../datas/sample/1998-2015-estx50-vchart.txt \
    --analyzer legdownup \
    --pranalyzer \
    --nostdstats \
    --plot

====================
== Analyzers
====================
##########
legdownupanalyzer
##########
Date,LegDown,LegUp_5,LegUp_10,LegUp_15,LegUp_20
2008-10-10,901.0,331.0,69.0,336.0,335.0
2001-09-11,889.0,145.0,111.0,239.0,376.0
2008-01-22,844.0,328.0,360.0,302.0,344.0
2001-09-21,813.0,572.0,696.0,816.0,731.0
2002-07-24,799.0,515.0,384.0,373.0,572.0
2008-01-23,789.0,345.0,256.0,319.0,290.0
2001-09-17,769.0,116.0,339.0,405.0,522.0
2008-10-09,768.0,102.0,0.0,120.0,208.0
2001-09-12,764.0,137.0,126.0,169.0,400.0
2002-07-23,759.0,331.0,183.0,285.0,421.0
2008-10-16,758.0,102.0,222.0,310.0,201.0
2008-10-17,740.0,-48.0,219.0,218.0,116.0
2015-08-24,731.0,nan,nan,nan,nan
2002-07-22,729.0,292.0,62.0,262.0,368.0
...
...
...
2001-10-05,-364.0,228.0,143.0,286.0,230.0
1999-01-04,-370.0,219.0,99.0,-7.0,191.0
2000-03-06,-382.0,-60.0,-127.0,-39.0,-161.0
2000-02-14,-393.0,-92.0,90.0,340.0,230.0
2000-02-09,-400.0,-22.0,-46.0,96.0,270.0
1999-01-05,-438.0,3.0,5.0,-107.0,5.0
1999-01-07,-446.0,-196.0,-6.0,-82.0,-50.0
1999-01-06,-536.0,-231.0,-42.0,-174.0,-129.0

2015年8月的回合排名第13。顯然,一個不常見的現象,儘管發生了更大的情況。

對於靜態主義者和聰明的數學頭腦來說,從指向上方的後續腿中該做什麼比我多得多。

有關實現的詳細資訊(請參閱末尾的整個模組代碼):LegUpDownAnalyzer

  • 它像其他對象一__init__ 樣創建指標: StrategiesIndicators 通常是通常的嫌疑人

    這些指標會自動註冊到分析器所附加到的策略中

  • 就像策略一樣,Analyzer 它有 self.datas (一個數據數位)和別名: self.dataself.data0self.data1 ...

  • 再次像策略:nexstartstop 鉤子(指標中不存在這些鉤子)

    在這種情況下,用於:

    • nextstart:記錄策略的初始起點

    • stop:因為事情已經完成而進行最終計算

  • 注意:其他方法,如startnextprenext在這種情況下不需要

  • LegDownUpAnalyzer 方法 print 已被覆蓋,不再調用該 pprint 方法,而是創建計算的CSV列印輸出

經過多次交談,由於我們加入了--plot 混合...圖表。

最後是由legupdown 載入的 bt-run模組。

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import itertools
import operator

import six
from six.moves import map, xrange, zip

import backtrader as bt
import backtrader.indicators as btind
from backtrader.utils import OrderedDict


class LegDown(bt.Indicator):
    '''
    Calculates what the current legdown has been using:
      - Current low
      - High from ``period`` bars ago
    '''
    lines = ('legdown',)
    params = (('period', 10),)

    def __init__(self):
        self.lines.legdown = self.data.high(-self.p.period) - self.data.low


class LegUp(bt.Indicator):
    '''
    Calculates what the current legup has been using:
      - Current high
      - Low from ``period`` bars ago

    If param ``writeback`` is True the value will be written
    backwards ``period`` bars ago
    '''
    lines = ('legup',)
    params = (('period', 10), ('writeback', True),)

    def __init__(self):
        self.lu = self.data.high - self.data.low(-self.p.period)
        self.lines.legup = self.lu(self.p.period * self.p.writeback)


class LegDownUpAnalyzer(bt.Analyzer):
    params = (
        # If created indicators have to be plotteda along the data
        ('plotind', True),
        # period to consider for a legdown
        ('ldown', 10),
        # periods for the following legups after a legdown
        ('lups', [5, 10, 15, 20]),
        # How to sort: date-asc, date-desc, legdown-asc, legdown-desc
        ('sort', 'legdown-desc'),
    )

    sort_options = ['date-asc', 'date-des', 'legdown-desc', 'legdown-asc']

    def __init__(self):
        # Create the legdown indicator
        self.ldown = LegDown(self.data, period=self.p.ldown)
        self.ldown.plotinfo.plot = self.p.plotind

        # Create the legup indicators indicator - writeback is not touched
        # so the values will be written back the selected period and therefore
        # be aligned with the end of the legdown
        self.lups = list()
        for lup in self.p.lups:
            legup = LegUp(self.data, period=lup)
            legup.plotinfo.plot = self.p.plotind
            self.lups.append(legup)

    def nextstart(self):
        self.start = len(self.data) - 1

    def stop(self):
        # Calculate start and ending points with values
        start = self.start
        end = len(self.data)
        size = end - start

        # Prepare dates (key in the returned dictionary)
        dtnumslice = self.strategy.data.datetime.getzero(start, size)
        dtslice = map(lambda x: bt.num2date(x).date(), dtnumslice)
        keys = dtslice

        # Prepare the values, a list for each key item
        # leg down
        ldown = self.ldown.legdown.getzero(start, size)
        # as many legs up as requested
        lups = [up.legup.getzero(start, size) for up in self.lups]

        # put legs down/up together and interleave (zip)
        vals = [ldown] + lups
        zvals = zip(*vals)

        # Prepare sorting options
        if self.p.sort == 'date-asc':
            reverse, item = False, 0
        elif self.p.sort == 'date-desc':
            reverse, item = True, 0
        elif self.p.sort == 'legdown-asc':
            reverse, item = False, 1
        elif self.p.sort == 'legdown-desc':
            reverse, item = True, 1
        else:
            # Default ordering - date-asc
            reverse, item = False, 0

        # Prepare a sorted array of 2-tuples
        keyvals_sorted = sorted(zip(keys, zvals),
                                reverse=reverse,
                                key=operator.itemgetter(item))

        # Use it to build an ordereddict
        self.ret = OrderedDict(keyvals_sorted)

    def get_analysis(self):
        return self.ret

    def print(self, *args, **kwargs):
        # Overriden to change default behavior (call pprint)
        # provides a CSV printout of the legs down/up
        header_items = ['Date', 'LegDown']
        header_items.extend(['LegUp_%d' % x for x in self.p.lups])
        header_txt = ','.join(header_items)
        print(header_txt)

        for key, vals in six.iteritems(self.ret):
            keytxt = key.strftime('%Y-%m-%d')
            txt = ','.join(itertools.chain([keytxt], map(str, vals)))
            print(txt)

推薦閱讀

相關文章

Backtrader對逐筆報價數據重新取樣

backtrader 已經可以從分鐘數據中重新採樣。接受價格變動數據不是問題,只需將 4 個常用欄位(open、 high、 low、 close)設置為價格變動值。 但是傳遞要重新採樣的逐筆報價數據再次生成相同的數據。作為或版本 1.1.11.88,情況已不再如此。

Backtrader改進代碼

時不時地,帶有 backtrader 代碼的示例會在互聯網上彈出。在我看來,有幾個是中國人。最新的一個在這裡: 標題是: backtrader-學習筆記2,這顯然(感謝谷歌)翻譯成 backtrader- 學習筆記2。

Backtrader實際使用方式

最後,似乎已經付出了開發 backtrader是值得的。 在觀察 last 周的歐洲市場時,似乎世界末日了,一位朋友問我是否可以看看我們圖表包中的數據,看看與以前類似情況相比,下跌幅度如何。 當然可以,但我說我可以做的不僅僅是查看圖表,因為我可以快速: 創建一個快速LegDown 指示器來測量跌落的範圍。

Backtrader繪製日期範圍

該版本1.9.31.x 增加了製作部分繪圖的功能。 使用策略實例中保存的完整時間戳陣列的索引 或者使用實際datetime.date 或 datetime.datetime 實例來限制必須繪製的內容。 一切都超過標準cerebro.plot。

Backtrader迪克森移動平均線

下面的reddit帖子以自己的作者Nathan Dickson(reddit句柄)命名了這個平均值Dickson移動平均線。 在一次對reddit Algotrading 的定期訪問中,我發現了一篇關於移動平均線的帖子,該移動平均線試圖模仿Jurik移動平均線(又名JMA)。

Backtrader條形同步

文獻和/或行業中缺乏標準公式不是問題,因為問題實際上可以總結為: 條形同步 工單 #23 提出了一些問題,即是否可以 backtrader 考慮計算 相對體積 指標。 請求者需要將給定時刻的 volume 與前一個交易日的相同時刻進行比較。

Backtrader Python隐藏的细节

只有當遇到 backtrader 的真實使用者時,人們才能意識到平臺中使用的抽象和Python功能是否有意義。 在不撇開python的座右銘的情況下, backtrader 試圖為使用者提供盡可能多的控制權,同時通過將Python提供的隱藏功能付諸行動來簡化使用。 第一個示例是系列文章的第一篇。

Backtrader多數據範例

社區中的幾個主題似乎以如何跟蹤訂單為導向,特別是當幾個data feeds在起作用時,還包括當多個訂單一起工作時,

Backtrader開場作弊

“發佈”1.9.44.116 添加了對 Cheat-On-Open的支援。這似乎是那些全力以赴的人的需求功能,他們在酒吧 close 后進行了計算,但希望與 open 價格相匹配。 當開盤價跳空(上漲或下跌,取決於是否buysell有效)並且現金不足以進行全面運營時,這樣的用例就會失敗。這將強制代理拒絕該操作。

Backtrader信貸利息

在某些情況下,真實經紀人的現金金額可能會減少,因為資產操作包括利率。例子: 賣空股票 交易所買賣基金包括多頭和空頭 這意味著不僅交易構成了系統的盈利能力,因為信貸上的利息在帳戶上佔有一席之地。 為了涵蓋這種情況, backtrader 包括(從發佈1.8.8.96開始)功能來考慮這一點。