Line 反覆運算器
為了參與操作,plaftorm使用 line 反覆運算器的概念。它們已經鬆散地模仿了Python的反覆運算器,但實際上與它們無關。
策略和指標是 line 反覆運算器。
line反覆運算器概念試圖描述以下內容:
-
Line反覆運算器踢從line反覆運算器,告訴他們反覆運算
-
然後, Line 反覆運算器循環訪問其自己聲明的命名 lines 設置值
反覆運算的關鍵,就像常規的Python迭代器一樣,是:
-
方法
next
它將在每次反覆運算時調用。
datas
line反覆運算器具有並用作邏輯/計算基礎的陣列已經被平臺移動到下一個索引(數據重放除外)在滿足line反覆運算器的最小週期時調用。下面對此進行更多介紹。
但是由於它們不是常規反覆運算器,因此存在兩種其他方法:
-
prenext
在滿足line反覆運算器“的最小期限之前調用。
-
nextstart
在滿足line反覆運算器“的最小週期時正好調用一次。
默認行為是將呼叫
next
轉接到,但如果需要,當然可以覆蓋。
指標的額外方法
為了加快操作速度,指標支援批處理操作模式,該模式被稱為 runonce。它不是嚴格需要的(一next
種方法就足夠了),但它大大減少了時間。
runonce 方法規則使索引為 0 的 get/set 點失效,並依賴於對保存數據的基礎陣列的直接訪問,併為每個狀態傳遞正確的索引。
定義的方法遵循下一個族的命名:
-
once(self, start, end)
在達到最小期限時調用。內部數位必須在開始和結束之間進行處理,從內部數位的開始開始為零
-
preonce(self, start, end)
在達到最小期限之前調用。
-
oncestart(self, start, end)
在滿足最小期限時正好調用一次 。
默認行為是將呼叫
once
轉接到,但如果需要,當然可以覆蓋。
最短期限
一張圖片勝過千言萬語,在這種情況下,也可能是一個例子。一個簡單的移動Average能夠解釋它:
class SimpleMovingAverage(Indicator): lines = ('sma',) params = dict(period=20) def __init__(self): ... # Not relevant for the explanation def prenext(self): print('prenext:: current period:', len(self)) def nextstart(self): print('nextstart:: current period:', len(self)) # emulate default behavior ... call next self.next() def next(self): print('next:: current period:', len(self))
實例化可能如下所示:
sma = btind.SimpleMovingAverage(self.data, period=25)
簡要說明:
-
假設傳遞到移動平均線的數據是標準 data feed 其預設週期是
1
: data feed 產生一個沒有初始延遲的柱。 -
然後,“period=25” 實例化移動平均線將調用其方法,如下所示:
-
prenext
24 次 -
nextstart
1次(依次通話next
) -
next
再增加 n 次,直到 data feed 用盡
-
讓我們來看看殺手級指標:一個 SimpleMovingAverage over 另一個 SimpleMovingAverage。實例化可能如下所示:
sma1 = btind.SimpleMovingAverage(self.data, period=25) sma2 = btind.SimpleMovingAverage(sma1, period=20)
現在發生了什麼:
-
同上
sma1
-
sma2
正在接收一個 data feed ,其最短期限為25,這是我們sma1
,因此 -
這些
sma2
方法的調用方式如下:-
prenext
前 25 + 18 次,共 43 次 -
25次讓
sma1
其產生1st 合理值 -
18次累積額外
sma1
價值 -
總共 19 個值(25 次呼叫后為 1,之後為 18 次)
-
nextstart
然後1次(依次呼叫next
) -
next
再增加 n 次,直到 data feed 用盡
-
當系統已經處理了 44 根柱線時,平臺正在調用next
。
最小週期已根據傳入數據自動調整。
策略和指標遵循以下行為:
- 僅當達到自動計算的最小週期時,才會
next
調用(除了對nextstart
) 的初始鉤子調用
注意
相同的規則適用於preonce
oncestart
運行批處理操作模式,once
注意
可以操縱最小周期 行為,但不建議這樣做。是否希望在策略或指標中使用該 setminperiod(minperiod)
方法
啟動並運行
啟動與執行至少涉及3個 Lines 物件:
-
Data feed
-
策略(實際上是從策略派生的類)
-
一 Cerebro (西班牙文中的大腦)
Data Feeds
顯然,這些物件提供的數據將通過應用計算(直接和/或指標)進行回溯測試
該平臺提供了幾個 data feeds:
-
幾種 CSV 格式和一個通用 CSV 閱讀器
-
雅虎在線獲取器
-
支援接收熊貓數據幀和火焰物件
-
與Interacive Brokers,Visual Chart和Oanda進行即時Data Feeds
該平臺對 data feed 的內容(例如時間幀和壓縮)不做任何假設。這些值與名稱一起可以提供,用於提供資訊和高級操作,例如 Data Feed 重新採樣(例如,將5分鐘的 Data Feed 轉換為每日 Data Feed)
設置雅虎財經 Data Feed的示例:
import backtrader as bt import backtrader.feeds as btfeeds ... datapath = 'path/to/your/yahoo/data.csv' data = btfeeds.YahooFinanceCSVData( dataname=datapath, reversed=True)
顯示 Yahoo 的可選reversed
參數,因為直接從 Yahoo 下載的 CSV 檔以最晚的日期開頭,而不是以最舊的日期開頭。
如果您的資料跨越了較大的時間範圍,則可以按如下方式限制實際載入的數據:
data = btfeeds.YahooFinanceCSVData( dataname=datapath, reversed=True fromdate=datetime.datetime(2014, 1, 1), todate=datetime.datetime(2014, 12, 31))
如果 data feed中存在,則起始日期和截止日期都將包括在內。
如前所述,可以添加壓縮和名稱:
data = btfeeds.YahooFinanceCSVData( dataname=datapath, reversed=True fromdate=datetime.datetime(2014, 1, 1), todate=datetime.datetime(2014, 12, 31) timeframe=bt.TimeFrame.Days, compression=1, name='Yahoo' )
如果繪製了數據,則將使用這些值。
策略(派生)類
注意
在繼續之前,對於更簡化的方法,如果不希望對策略進行子類化,請查看文檔的“信號”部分。
使用該平臺的任何人都的目標是回溯測試數據,這是在策略(派生類)內完成的。
有2種方法至少需要自定義:
-
__init__
-
next
在初始化期間,將創建數據和其他計算的指示器,以便為以後應用邏輯做好準備。
稍後調用下一個方法來為數據的每個條形應用邏輯。
注意
如果傳遞了不同時間幀的data feeds(因此傳遞了next
不同的柱計數),則將為主數據調用方法(傳遞給cerebro的第一個,見下文),該方法必須是具有較小時間幀的數據
注意
如果使用數據重播功能,則在next
重放柱的開發時,將為同一柱線多次調用該方法。
基本策略派生類:
class MyStrategy(bt.Strategy): def __init__(self): self.sma = btind.SimpleMovingAverage(self.data, period=20) def next(self): if self.sma > self.data.close: self.buy() elif self.sma < self.data.close: self.sell()
策略還有其他可以覆蓋的方法(或挂鉤點):
class MyStrategy(bt.Strategy): def __init__(self): self.sma = btind.SimpleMovingAverage(self.data, period=20) def next(self): if self.sma > self.data.close: submitted_order = self.buy() elif self.sma < self.data.close: submitted_order = self.sell() def start(self): print('Backtesting is about to start') def stop(self): print('Backtesting is finished') def notify_order(self, order): print('An order new/changed/executed/canceled has been received')
start
和 stop
方法應該是不言自明的。正如預期的那樣,在列印函數中的文本之後,notify_order
當策略需要通知時,將調用該方法。用例:
-
請求買入或賣出(如下圖所示)
買入/賣出將返回提交給經紀商的訂單。保留對此提交訂單的引用由調用方決定。
例如,它可用於確保在訂單仍處於待處理狀態時不會提交新訂單。
-
如果訂單被接受/執行/取消/更改,經紀人將通過 notify 方法將狀態更改(例如執行大小)通知回策略
快速入門指南在該方法中notify_order
提供了訂單管理的完整功能示例。
其他策略類可以做更多工作:
-
buy
/sell
/close
使用基礎經紀商和 sizer 向經紀商發送買入/賣出訂單
同樣可以通過手動創建訂單並將其傳遞給經紀人來完成。但該平臺旨在使使用它的人變得容易。
close
將獲得當前的市場地位並立即 close 。 -
getposition
(或屬性“位置”)返回當前市場位置
-
setsizer
/getsizer
(或財產“sizer”)這些允許設置/獲取標的權益 Sizer。可以對照 Sizers 檢查相同的邏輯,這些為相同情況提供不同的賭注(固定大小,與資本成比例,指數)
有很多文學作品,但Van K. Tharp有關於這個主題的優秀書籍。
策略是一個 Lines 對象和這些支持參數,這些參數是使用標準的 Python kwargs 參數收集的:
class MyStrategy(bt.Strategy): params = (('period', 20),) def __init__(self): self.sma = btind.SimpleMovingAverage(self.data, period=self.params.period) ... ...
請注意,不再SimpleMovingAverage
使用固定值 20 實例化 ,而是使用為策略定義的參數“period” 實例化。
Cerebro
一旦 Data Feeds 可用並且定義了戰略, Cerebro 實例就是將所有內容整合在一起並執行操作。實例化一個很容易:
cerebro = bt.Cerebro()
如果不希望有任何特殊情況,則預設會處理。
-
創建缺省代理
-
無傭金
-
Data Feeds 將被預載入
-
默認執行模式為runonce(批處理操作),這是更快的
所有指標必須支援
runonce
全速模式。平臺中包含的那些確實如此。自定義指標不需要實現 runonce 功能。
Cerebro
將類比它,這意味著那些與runonce不相容的指標將運行得更慢。但是,大多數系統仍將以批處理模式運行。
由於 Data feed 已經可用,並且策略也(更早創建)將其放在一起並使其啟動並運行的標準方法是:
cerebro.adddata(data) cerebro.addstrategy(MyStrategy, period=25) cerebro.run()
請注意以下幾點:
-
添加了 Data Feed “實例”
-
MyStrategy“類”與將傳遞給它的參數(kwargs)一起添加。
MyStrategy的實例化將由後台 cerebro 完成,並且“addstrategy”中的任何kwargs都將傳遞給它。
用戶可以根據需要添加任意數量的策略和 Data Feeds 。策略如何相互溝通以實現協調(如果願意的話)不受平台的執行/限制。
當然, Cerebro 還提供了更多的可能性:
-
確定預載入與操作模式:
cerebro = bt.Cerebro(runonce=True, preload=True)
這裡有一個約束:
runonce
需要預載入(如果沒有,則無法運行批處理操作)當然,預載入 Data Feeds 不會強制runonce
-
setbroker
/getbroker
(和經紀人財產)如果需要,可以設置自定義代理。也可以訪問實際的代理實例
-
標圖。在正常情況下,就像這樣簡單:
cerebro.run() cerebro.plot()
plot 為自定義取一些參數
-
numfigs=1
如果情節太密集,可能會分解為幾個情節
-
plotter=None
可以傳遞客戶繪圖儀實例,並且 cerebro 不會實例化默認繪圖儀實例
-
**kwargs
- 標準關鍵字參數這將傳遞給繪圖儀。
有關詳細資訊,請參閱繪圖部分。
-
-
策略優化。
如上所述, Cerebro 獲取一個 Strategy 派生類(不是實例)和關鍵字參數,這些參數將在實例化時傳遞給它,這將在調用“run”時發生。
這是為了實現優化。同一個 Strategy 類將根據需要使用新參數實例化多次。如果實體已傳遞給 cerebro ...這是不可能的。
優化請求如下:
cerebro.optstrategy(MyStrategy, period=xrange(10, 20))
該方法
optstrategy
具有與相同的簽名,addstrategy
但會執行額外的內務處理,以確保優化按預期運行。策略可能期望一個範圍作為策略的正常參數,並且addstrategy
不會對傳遞的參數做出任何假設。另一方面,
optstrategy
將理解可反覆運算是一組值,必須按順序傳遞給 Strategy 類的每個實例化。請注意,傳遞的值範圍不是單個值。在這個簡單的情況下,將為此策略嘗試 10 個值 10 -> 19(20 是上限)。
如果使用額外的參數開發更複雜的策略,則可以將它們全部傳遞給選擇策略。不得進行優化的參數可以直接傳遞,而無需最終用戶創建一個僅可反覆運算一個值的虛擬參數。例:
cerebro.optstrategy(MyStrategy, period=xrange(10, 20), factor=3.5)
該
optstrategy
方法看到因數,並在後台為具有單個元素的因數創建(所需的)可反覆運算的虛擬(在示例 3.5 中)注意
互動式Python shell和Windows下某些類型的凍結可執行檔在Python
multiprocessing
模組中存在問題請閱讀 Python 文件
multiprocessing
。