無論是回溯測試還是交易,能夠分析交易系統的性能是瞭解是否不僅獲得了利潤,而且是否在風險太大的情況下實現了利潤,或者與參考資產(或無風險資產)相比,是否真的值得付出努力的關鍵。
這就是物件家族的用武之Analyzer
地:提供對所發生事件甚至實際發生的事情的分析。
analyzers的性質
該介面是根據 Lines 物件(例如next
方法)的介面建模的,但有一個主要區別:
-
Analyzers
不要握住 lines。這意味著它們在記憶體方面並不昂貴,因為即使在分析了數千個價格柱之後,它們仍然可能只是在記憶體中保存單個結果。
在生態系統中的位置
Analyzer
物件(如策略、 observers 和數據)通過 cerebro
實例添加到系統中:
addanalyzer(ancls, *args, **kwargs)
但是,當涉及到操作期間cerebro.run
,系統中存在的每個策略將發生以下情況
-
ancls
將在*args
**kwargs
cerebro.run
-
實例
ancls
將附加到策略
這意味著:
- 例如,如果回溯測試運行包含 3 個策略,則將創建 3 個實例,每個實例
ancls
將附加到不同的策略。
綜述:分析器分析單個策略的性能,而不是整個系統的性能
其他位置
某些Analyzer
對象實際上可能使用其他 analyzers 來完成其工作。例如: SharpeRatio
使用的 TimeReturn
輸出進行計算。
這些子analyzers 或從analyzers 也將插入到與創建它們的策略相同的策略中。但它們對用戶來說是完全不可見的。
屬性
為了執行預期的工作,Analyzer
物件提供了一些預設屬性,這些屬性會自動傳遞並在實例中設置,以便於使用:
-
self.strategy
:引用分析器物件在其中操作的策略子類。策略可訪問的任何內容也可以由分析器訪問 -
self.datas[x]
:策略中存在的 data feeds 陣列。儘管可以通過策略參考訪問這一點,但快捷方式使工作更加舒適。 -
self.data
:為增加舒適度而快捷鍵self.datas[0]
。 -
self.dataX
:不同self.datas[x]
其他一些別名可用,儘管它們可能有些過分:
* `self.dataX_Y` where X is a reference to `self.datas[X]` and `Y` refers to the line, finally pointing to: `self.datas[X].lines[Y]`
如果 line 具有名稱,則以下選項也可用:
* `self.dataX_Name` which resolves to `self.datas[X].Name` returning the line by name rather than by index
對於第一個數據, last 兩個快捷方式在沒有初始X
數位參考的情況下可用。例如:
* `self.data_2` refers to `self.datas[0].lines[2]`
和
* `self.data_close` refers to `self.datas[0].close`
返回分析
Analyzer 基類創建一個self.rets
(類型collections.OrderedDict
為 )成員屬性以返回分析。這是在方法中完成的,如果創建自定義analyzers,則該方法create_analysis
可由子類覆蓋。
做法
雖然Analyzer
物件不是 Lines 物件,因此不會反覆運算 lines,但它們被設計為遵循相同的操作模式。
-
在系統啟動之前實例化(因此呼叫
__init__
) -
發出開始操作的信號
start
-
prenext
/nextstart
/next
將在指標工作的策略的計算最短周期之後被調用。的預設
nextstart
行為prenext
是調用 next,因為分析器可能從系統處於活動狀態的第一刻起就開始分析。習慣上調用
len(self)
Lines對象來檢查實際的柱數。這也通過返回值來工作Analyzers
self.strategy
-
訂單和交易將像
notify_order
通過和notify_trade
-
現金和價值也將被通知,就像策略完成的方法一
notify_cashvalue
樣 -
現金,價值和基金價值以及基金份額也將被通知,就像使用方法的策略
notify_fund
一樣 -
stop
將被調用以指示操作結束
一旦常規操作週期完成, analyzers 具有提取/輸出資訊的其他方法
-
get_analysis
:理想情況下(不強制)返回包含dict
分析結果的類似物件。 -
print
使用標準backtrader.WriterFile
(除非被覆蓋)從get_analysis
寫入分析結果。 -
pprint
(漂亮的列印)使用Pythonpprint
模組來列印get_analysis
resutls。
最後:
-
get_analysis
創建一個成員屬性self.ret
(類型collections.OrderedDict
), analyzers 向該屬性寫入分析結果。Analyzer 的子類可以重寫此方法以更改此行為
分析器模式
平臺中 Analyzer 物件的backtrader
開發揭示了生成分析的 2 種不同使用模式:
-
在執行過程中,通過在 和
next
方法中notify_xxx
收集資訊,並在next
TradeAnalyzer
例如,僅使用該notify_trade
方法來生成統計資訊。 -
收集(或不收集)上述資訊,但在方法過程中
stop
一次性生成分析SQN
(系統質量編號)在方法期間notify_trade
收集交易資訊,但在方法期間stop
生成統計資訊
一個簡單的例子
盡可能簡單:
from __future__ import (absolute_import, division, print_function, unicode_literals) import datetime import backtrader as bt import backtrader.analyzers as btanalyzers import backtrader.feeds as btfeeds import backtrader.strategies as btstrats cerebro = bt.Cerebro() # data dataname = '../datas/sample/2005-2006-day-001.txt' data = btfeeds.BacktraderCSVData(dataname=dataname) cerebro.adddata(data) # strategy cerebro.addstrategy(btstrats.SMA_CrossOver) # Analyzer cerebro.addanalyzer(btanalyzers.SharpeRatio, _name='mysharpe') thestrats = cerebro.run() thestrat = thestrats[0] print('Sharpe Ratio:', thestrat.analyzers.mysharpe.get_analysis())
執行它(已將其analyzer-test.py
儲存在:
$ ./analyzer-test.py Sharpe Ratio: {'sharperatio': 11.647332609673256}
沒有繪圖,因為在SharpeRatio
計算結束時是單個值。
分析儀的取證分析
讓我們重複一遍,Analyzers
這不是 Lines 物件,而是將它們無縫集成到生態系統中 backtrader
,遵循幾個 Lines 對象的內部API約定(實際上是它們的 混合 體)。
注意
的SharpeRatio
代碼已經發展到例如考慮年化,這裡的版本應該只是一個參考。
請查看 Analyzers 參考
另外還有一個SharpeRatio_A
,它以年化形式直接提供價值,而不管所尋求的時間範圍如何
代碼作為SharpeRatio
基礎(簡化版本)
from __future__ import (absolute_import, division, print_function, unicode_literals) import operator from backtrader.utils.py3 import map from backtrader import Analyzer, TimeFrame from backtrader.mathsupport import average, standarddev from backtrader.analyzers import AnnualReturn class SharpeRatio(Analyzer): params = (('timeframe', TimeFrame.Years), ('riskfreerate', 0.01),) def __init__(self): super(SharpeRatio, self).__init__() self.anret = AnnualReturn() def start(self): # Not needed ... but could be used pass def next(self): # Not needed ... but could be used pass def stop(self): retfree = [self.p.riskfreerate] * len(self.anret.rets) retavg = average(list(map(operator.sub, self.anret.rets, retfree))) retdev = standarddev(self.anret.rets) self.ratio = retavg / retdev def get_analysis(self): return dict(sharperatio=self.ratio)
代碼可以分解為:
-
params
聲明儘管未使用聲明的物件(作為示例),但 Analyzers 與支持參數中的大多數
backtrader
其他對象一樣 -
__init__
方法就像策略聲明指標一
__init__
樣,支持物件 analyzers 也是如此。在這種情況下:使用
SharpeRatio
年度申報表計算。計算將是自動的,並SharpeRatio
可用於自己的計算。注意
實際實現
SharpeRatio
使用更通用和後來開發的TimeReturn
分析儀 -
next
方法SharpeRatio
不需要它,但此方法將在每次調用父策略后調用next
-
start
方法在回溯測試開始之前調用。可用於額外的初始化任務。夏普不需要它
-
stop
方法在回溯測試結束后立即調用。像
SharpeRatio
這樣,它可以用來完成/進行計算 -
get_analysis
方法(返回字典)外部呼叫者可以訪問生成的分析
返回:帶有分析的字典。
參考
backtrader類 .分析儀()
分析器基類。所有 analyzers 都是這個的子類
Analyzer 實例在策略的框架中運行,併為該策略提供分析。
自動設定成員屬性:
-
self.strategy
(允許存取策略以及從中存取的任何內容) -
self.datas[x]
允許訪問系統中存在的 data feeds 數位,也可以通過策略參考訪問 -
self.data
,授予訪問許可權self.datas[0]
-
self.dataX
->self.datas[X]
-
self.dataX_Y
->self.datas[X].lines[Y]
-
self.dataX_name
->self.datas[X].name
-
self.data_name
->self.datas[0].name
-
self.data_Y
->self.datas[0].lines[Y]
這不是一個 Lines 物件,但方法和操作遵循相同的設計
-
__init__
在實例化和初始設置期間 -
start
/stop
發出操作開始和結束的信號 -
prenext
/nextstart
/next
遵循策略中對相同方法的調用的方法系列 -
notify_trade
/notify_order
/notify_cashvalue
notify_fund
接收與策略的等效方法相同的通知
操作模式 open ,不首選任何模式。因此,分析可以通過next
調用生成,在操作期間 stop
甚至使用單個方法,例如 notify_trade
重要的是重寫get_analysis
以返回包含分析結果的類似字典的物件(實際格式取決於實現)
開始()
調用以指示操作的開始,使分析器有時間設置所需的內容
停止()
調用以指示操作結束,使分析器有時間關閉所需的內容
prenext()
針對策略的每次前置點調用調用,直到達到策略的最小週期
分析器的預設行為是調用next
nextstart()
在策略的下一個啟動調用時僅調用一次,此時首次達到最小週期
下一步()
在策略的每次下一次調用時調用,一旦達到策略的最小值
notify_cashvalue(現金,價值)
在每個下一個週期之前收到現金/價值通知
notify_fund(現金、價值、基金價值、股份)
接收當前現金、價值、基金價值和基金份額
notify_order(訂貨)
在每個下一個週期之前接收訂單通知
notify_trade(貿易)
在每個下一個週期之前接收交易通知
get_analysis()
返回類似 dict 的物件以及分析結果
字典中分析結果的鍵和格式取決於實現。
甚至沒有強制要求結果是一個類似字典的物件,只是約定
默認實現返回由預設方法創建的預設 create_analysis
OrderedDictrets
create_analysis()
意味著被子類覆蓋。提供創建保存分析的結構的機會。
默認行為是創建一個OrderedDict
named rets
print(*args, **kwargs)
列印通過標準Writerfile
物件返回get_analysis
的結果,該對象預設將內容寫入標準輸出
pprint(*args, **kwargs)
列印使用漂亮的列印 Python 模組 (pprint) 傳回get_analysis
的結果
倫()
len
通過實際返回分析器操作的策略的當前長度來支援調用analyzers