抽象工廠模式(Abstract Factory Pattern): 是圍繞一個超級工廠創建其他工廠。該超級工廠又稱為其他工廠的工廠。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。 在抽象工廠模式中,介面是負責創建一個相關對象的工廠,不需要顯式指定它們的類。每個生成的工廠都能按照工 ...
@
目錄使用內置交易策略,組合成複雜策略
qteasy
是一個完全本地化部署和運行的量化交易分析工具包,Github地址在這裡,具備以下功能:
- 金融數據的獲取、清洗、存儲以及處理、可視化、使用
- 量化交易策略的創建,並提供大量內置基本交易策略
- 向量化的高速交易策略回測及交易結果評價
- 交易策略參數的優化以及評價
- 交易策略的部署、實盤運行
通過本系列教程,您將會通過一系列的實際示例,充分瞭解qteasy
的主要功能以及使用方法。
開始前的準備工作
在開始本節教程前,請先確保您已經掌握了下麵的內容:
- 安裝、配置
qteasy
—— 詳情請參閱QTEASY教程1 - 設置了一個本地數據源,並已經將足夠的歷史數據下載到本地(包括交易日曆、股票/基金/指數基本信息、股票/基金/指數的價格數據以及財務指標或其他財務數據——詳情請參閱QTEASY教程2
- 學會創建交易員對象,使用一個內置交易策略並回測其歷史表現,檢查回測日誌、明白如何調整策略的運行參數或可調參數,改進策略的表現——QTEASY教程3
在QTEASY文檔中,還能找到更多關於如何創建交易員對象運行策略,使用歷史數據回測策略,檢查回測交易記錄,修改策略等等相關內容。對qteasy
的基本使用方法還不熟悉的同學,可以移步那裡查看更多詳細說明。
本節的目標
在本節中,我們將瞭解如何使用qteasy
中更多的內置策略,如何使交易員同時運行多個交易策略,如何使用策略混合器blender
來使用交易策略生成不同的組合策略,
目前qteasy
支持超過70種內置交易策略,全部都是開箱即用,完整的內置交易策略清單請參見參考文檔:
# 獲取內置交易策略的清單
stg_list = qt.built_ins('dma')
列印如下信息:
DMA擇時策略
策略參數:
s, int, 短均線周期
l, int, 長均線周期
d, int, DMA周期
信號類型:
PS型:百分比買賣交易信號
信號規則:
在下麵情況下產生買入信號:
1, DMA在AMA上方時,多頭區間,即DMA線自下而上穿越AMA線後,輸出為1
2, DMA在AMA下方時,空頭區間,即DMA線自上而下穿越AMA線後,輸出為0
3, DMA與股價發生背離時的交叉信號,可信度較高
策略屬性預設值:
預設參數:(12, 26, 9)
數據類型:close 收盤價,單數據輸入
採樣頻率:天
視窗長度:270
參數範圍:[(10, 250), (10, 250), (8, 250)]
策略不支持參考數據,不支持交易數據
下麵清單羅列了部分qteasy
內置開箱即用的交易策略,完整的清單請參見參考文檔
ID | 策略名稱 | 說明 |
---|---|---|
crossline |
TimingCrossline |
crossline擇時策略類,利用長短均線的交叉確定多空狀態 1,當短均線位於長均線上方,且距離大於l*m%時,設置倉位目標為1 2,當短均線位於長均線下方,且距離大於l*m%時,設置倉位目標為-1 3,當長短均線之間的距離不大於l*m%時,設置倉位目標為0 |
macd |
TimingMACD |
MACD擇時策略類,運用MACD均線策略,生成目標倉位百分比: 1,當MACD值大於0時,設置倉位目標為1 2,當MACD值小於0時,設置倉位目標為0 |
dma |
TimingDMA |
DMA擇時策略 1, DMA在AMA上方時,多頭區間,即DMA線自下而上穿越AMA線後,輸出為1 2, DMA在AMA下方時,空頭區間,即DMA線自上而下穿越AMA線後,輸出為0 |
trix |
TimingTRIX |
TRIX擇時策略,使用股票價格的三重平滑指數移動平均價格進行多空判斷: 計算價格的三重平滑指數移動平均價TRIX,再計算M日TRIX的移動平均: 1, TRIX位於MATRIX上方時,設置倉位目標為1 2, TRIX位於MATRIX下方時,設置倉位目標位-1 |
cdl |
TimingCDL |
CDL擇時策略,在K線圖中找到符合要求的cdldoji模式 搜索歷史數據視窗內出現的cdldoji模式(匹配度0~100之間),加總後/100,計算 等效cdldoji匹配數量,以匹配數量為交易信號。 |
bband |
TimingBBand |
布林帶線交易策略,根據股價與布林帶上軌和布林帶下軌之間的關係確定多空,在價格上穿或下穿布林帶線上下軌時產生交易信號。布林帶線的均線類型不可選 1,當價格上穿上軌時,產生全倉買入信號 2,當價格下穿下軌時,產生全倉賣出信號 |
s-bband |
SoftBBand |
布林帶線漸進交易策略,根據股價與布林帶上軌和布林帶下軌之間的關係確定多空,交易信號不是一次性產生的,而是逐步漸進買入和賣出。計算BBAND,檢查價格是否超過BBAND的上軌或下軌: 1,當價格大於上軌後,每天產生10%的比例買入交易信號 2,當價格低於下軌後,每天產生33%的比例賣出交易信號 |
sarext |
TimingSAREXT |
擴展拋物線SAR策略,當指標大於0時發出買入信號,當指標小於0時發出賣出信號 |
ssma |
SCRSSMA |
單均線交叉策略——SMA均線(簡單移動平均線):根據股價與SMA均線的相對位置設定持倉比例 |
sdema |
SCRSDEMA |
單均線交叉策略——DEMA均線(雙重指數平滑移動平均線):根據股價與DEMA均線的相對位置設定持倉比例 |
sema |
SCRSEMA |
單均線交叉策略——EMA均線(指數平滑移動均線):根據股價與EMA均線的相對位置設定持倉比例 |
... | ... | 完整的內置策略清單請見參考文檔 |
如果需要查看每一個內置交易策略的詳細解釋,例如策略參數的含義、信號生成規則,可以查看每一個交易策略的doc-string
:
例如:
qt.built_ins('Crossline')
可以看到
Init signature: qt.built_in.TimingCrossline(pars:tuple=(35, 120, 0.02))
Docstring:
crossline擇時策略類,利用長短均線的交叉確定多空狀態
策略參數:
s: int, 短均線計算日期;
l: int, 長均線計算日期;
m: float, 均線邊界寬度(百分比);
信號類型:
PT型:目標倉位百分比
信號規則:
1,當短均線位於長均線上方,且距離大於l*m%時,設置倉位目標為1
2,當短均線位於長均線下方,且距離大於l*mM時,設置倉位目標為-1
3,當長短均線之間的距離不大於l*m%時,設置倉位目標為0
策略屬性預設值:
預設參數:(35, 120, 0.02)
數據類型:close 收盤價,單數據輸入
採樣頻率:天
視窗長度:270
參數範圍:[(10, 250), (10, 250), (0, 1)]
策略不支持參考數據,不支持交易數據
File: ~/qteasy/qteasy/built_in.py
Type: type
Subclasses:
在ipython
等互動式python
環境中,也可以使用?
來顯示內置交易策略的詳細信息,例如:
qt.built_in.SelectingNDayRateChange?
可以看到:
Init signature: qt.built_in.SelectingNDayRateChange(pars=(14,))
Docstring:
基礎選股策略:根據股票以前n天的股價變動比例作為選股因數
策略參數:
n: int, 股票歷史數據的選擇期
信號類型:
PT型:百分比持倉比例信號
信號規則:
在每個選股周期使用以前n天的股價變動比例作為選股因數進行選股
通過以下策略屬性控制選股方法:
*max_sel_count: float, 選股限額,表示最多選出的股票的數量,預設值:0.5,表示選中50%的股票
*condition: str , 確定股票的篩選條件,預設值'any'
'any' :預設值,選擇所有可用股票
'greater' :篩選出因數大於ubound的股票
'less' :篩選出因數小於lbound的股票
'between' :篩選出因數介於lbound與ubound之間的股票
'not_between':篩選出因數不在lbound與ubound之間的股票
*lbound: float, 執行條件篩選時的指標下界, 預設值np.-inf
*ubound: float, 執行條件篩選時的指標上界, 預設值np.inf
*sort_ascending: bool, 排序方法,預設值: False,
True: 優先選擇因數最小的股票,
False, 優先選擇因數最大的股票
*weighting: str , 確定如何分配選中股票的權重
預設值: 'even'
'even' :所有被選中的股票都獲得同樣的權重
'linear' :權重根據因數排序線性分配
'distance' :股票的權重與他們的指標與最低之間的差值(距離)成比例
'proportion' :權重與股票的因數分值成正比
策略屬性預設值:
預設參數:(14,)
數據類型:close 收盤價,單數據輸入
採樣頻率:月
視窗長度:150
參數範圍:[(2, 150)]
策略不支持參考數據,不支持交易數據
File: ~/qteasy/qteasy/built_in.py
Type: type
Subclasses:
多重策略以及策略組合
在qteasy
中,一個Operator
交易員對象可以同時運行多個交易策略。這些交易策略在運行的時候,都會分別提取各自所需的歷史數據,獨立生成不同的交易信號,這些交易信號會被組合成一組交易信號,統一執行。
利用這種特性,用戶可以在一個交易員對象中同時運行多個各有側重的交易策略,例如,一個交易策略監控個股的股價,根據股價產生擇信號,第二個交易策略專門負責監控大盤走勢,通過大盤走勢決定整體倉位。第三個交易策略專門負責止盈止損,在特定時刻止損。最終的交易信號以第一個交易策略為主,但受到第二個策略的節制,必要時會被第三個策略完全控制。
或者,用戶也可以很容易地制定出一個“委員會”策略,在一個綜合性策略中由多個策略獨立地做出交易決策,最終的交易信號由所有子策略組成的”委員會“投票決定,投票的方式可以是簡單多數、絕對多數、加權投票結果等等。
上述交易策略組合中,每一個獨立的交易策略都很簡單,很容易定義,而將他們組合起來,又能發揮更大的作用。同時每一個子策略都是獨立的,可以自由組合出複雜的綜合性交易策略。這樣可以避免不斷地重覆開發策略,只需要對子策略重新排列組合,重新定義組合方式,就可以快速地搭建一系列的複雜綜合性交易策略。相信這樣能夠極大地提高交易策略的搭建效率,縮短周期。時間就是金錢。
不過,在一個Operator
對象中,不同策略生成的交易信號可能運行的時機是不同的,例如,某些策略在開盤時運行,生成開盤價交易信號,而另一些策略在收盤前運行,生成的是收盤價交易信號,那麼運行在不同時機的策略,生成的信號當然不應該混合。但只要是同時運行的交易策略生成的信號,都應該全部混合。
交易信號的混合即交易信號的各種運算或函數,從簡單的邏輯運算、加減運算一直到複雜的自定義函數,只要能夠應用於一個ndarray
的函數,理論上都可以用於混合交易信號,只要最終輸出的交易信號有意義即可。
定義策略組合方式blender
qteasy
中的組合策略是由blender
實現的。在一個Operator
中,如果策略的數量多於1個,就必須定義一個blender
。如果沒有明確定義blender
,而策略的數量超過1個時,qteasy
會在運行Operator
的時候創建一個預設的blender
,但是為了讓多重策略正確運行,用戶需要自行定義blender
。
blender expression
是用戶自行定義的一個組合表達式,用戶使用這個表達式確定不同交易策略的組合方式。這個組合表達式使用四則運算符、邏輯運算符、函數等符號規定策略信號是如何組合的。blender
表達式中可以包括以下元素:
blender
表達式中支持的函數如下:
元素 | 示例 | 說明 |
---|---|---|
策略序號 | s0, s1... |
以s開頭,數字結尾的字元串,數字為Operator 中的策略的序號,代表這個策略生成的交易信號 |
數字 | -1.35 |
任何合法的數字,參與表達式運算的數字 |
運算符 | + |
包括+-*/^ 等數學運算符 |
邏輯運算符 | and |
支持& /~ 以及and /or /not 形式的邏輯運算符 |
函數 | sum() |
表達式支持多種函數,支持的函數參見後表 |
括弧 | () |
組合運算 |
blender
示例
當一個Operator
對象中有三個交易策略時(其序號分別為s0
/s1
/s2
),按照以下方式定義的blender
都是合法可用的,同時使用Operator.set_blender()
來設置blender
:
使用四則運算符定義blender表達式
's0 + s1 + s2'
此時三個交易策略生成的交易信號會被加起來,成為最終的交易信號,如果策略0的結果為買入10%,策略1結果為買入10%,策略2結果為買入30%,則最終的結果為買入50%
使用邏輯運算符定義blender表達式:
's0 and s1 and s2'
表示只有當交易策略1、2、3都出現交易信號的時候,才會最終形成交易信號。如策略1的結果為買入,策略2結果為買入,而策略3沒有交易信號,則最終的結果為沒有交易信號。
blender表達式中還可以包含括弧和一些函數:
'max(s0, s1) + s2'
表示策略1、2的結果中最大值與策略3的結果相加,成為最終交易信號。如果策略1的結果為買入10%,策略2結果為買入20%,策略3結果為買入30%,最終的結果為買入50%
blender 表達式中每個策略可以出現不止一次,也可以出現純數字:
'(0.5 * s0 + 1.0 * s1 + 1.5 * s2) / 3 * min(s0, s1, s2)'
上面的blender表達式表示:首先計算三個策略信號的加權平均(權重分別為0.5、1.0、1.5),然後再乘以三個信號的最小值
blender 表達式中函數的操作參數在函數名中定義:
'clip_-0.5_0.5(s0 + s1 + s2) + pos_2_0.2(s0, s1, s2)'
上面的blender表達式定義了兩種不同的函數操作,分別得到結果後相加得到最終結果。第一個函數是範圍剪切,將三組策略信號相加後,剪切掉小於-0.5的信號值以及大於0.5的信號值,得到計算結果;第二個函數是倉位判斷函數,統計三組信號中持倉大於0.2的時間段,將其定義為“多頭”,然後再統計每一個時間段三個策略中持多頭建議的數量,如果超過兩個策略持多頭建議,則輸出滿倉多頭,否則輸出空倉。
blender表達式中支持的函數如下:
函數 | 表達式示例 | 說明 |
---|---|---|
abs |
abs(s0, s1, s2) |
絕對值函數 計算所有交易信號的絕對值 輸入信號的數量不限 |
avg |
avg(s0, s1, s2) |
平均值函數 計算所有交易信號的平均值 輸入信號的數量不限 |
avgpos |
avgpos_N_T(s0, s1, s2) |
平均值累計函數 當交易信號為持倉目標信號時,統計同一時間產生非空倉信號(輸出信號絕對值>T)的個數,當空頭/多頭信號的數量大於N時,輸出所有空頭/多頭信號的平均值,否則輸出0. 輸入信號的數量不限 |
ceil |
ceil(s0) |
向上取整函數 交易信號向上取整 只能輸入一個交易信號 |
clip |
clip_U_L(s0) |
範圍剪切函數 剪切超過範圍的信號值,剪切上下範圍在函數名中定義 只能輸入一個交易信號 |
combo |
combo(s0, s1, s2) |
組合值函數 輸出所有交易信號加總的值 輸入信號的數量不限 |
committee |
cmt_N_T(s0, s1, s2) |
委員會函數(等同於累計持倉函數)) 當交易信號為持倉目標信號時,統計同一時間產生非空倉信號(輸出信號絕對值>T)的個數數,當多頭/空頭信號的數量大於N時,輸出-1/1,否則輸出0. 輸入信號的數量不限 |
exp |
exp(s0) |
exp函數 計算e的信號次冪 只能輸入一個交易信號 |
floor |
floor(s0) |
向下取整函數 交易信號向下取整 只能輸入一個交易信號 |
log |
log(s0) |
對數函數 計算以e為底的對數值 只能輸入一個交易信號 |
log10 |
log10(s0) |
以10為底的對數函數 計算以10為底的對數值 只能輸入一個交易信號 |
max |
max(s0, s1, s2) |
最大值函數 計算所有交易信號的最大值 輸入信號的數量不限 |
min |
min(s0, s1, s2) |
最小值函數 計算所有交易信號的最小值 輸入信號的數量不限 |
pos |
pos_N_T(s0, s1, s2) |
累計持倉函數 當交易信號為持倉目標信號時,統計同一時間產生非空倉信號(輸出信號絕對值>T)的個數數,當多頭/空頭信號的數量大於N時,輸出-1/1,否則輸出0. 輸入信號的數量不限 |
position |
position_N_T(s0, s1, s2) |
累計持倉函數 當交易信號為持倉目標信號時,統計同一時間產生非空倉信號(輸出信號絕對值>T)的個數數,當多頭/空頭信號的數量大於N時,輸出-1/1,否則輸出0. 輸入信號的數量不限 |
pow |
pow(s0, s1, s2) |
冪函數 計算第一個交易信號的第二個信號次冪即sig0^sig1 輸入信號的數量只能為兩個 |
power |
power(s0, s1, s2) |
冪函數 計算第一個交易信號的第二個信號次冪即sig0^sig1 輸入信號的數量只能為兩個 |
sqrt |
sqrt(s0) |
平方根函數 交易信號的平方根 只能輸入一個交易信號 |
str |
str_T(s0, s1, s2) |
強度累計函數 將所有交易信號加總,當信號強度超過T時,輸出1,否則輸出0 輸入信號的數量不限 |
strength |
strength_T(s0, s1, s2) |
強度累計函數 將所有交易信號加總,當信號強度超過T時,輸出1,否則輸出0 輸入信號的數量不限 |
sum |
sum(s0, s1, s2) |
組合值函數 輸出所有交易信號加總的值 輸入信號的數量不限 |
unify |
unify(s0) |
均一化函數 均一化交易信號,等比縮放同一行的交易信號使每一行的總和為1 只能輸入一個交易信號 |
vote |
vote_N_T(s0, s1, s2) |
委員會投票函數(等同於累計持倉函數) 當交易信號為持倉目標信號時,統計同一時間產生非空倉信號(輸出信號絕對值>T)的個數數,當多頭/空頭信號的數量大於N時,輸出-1/1,否則輸出0. 輸入信號的數量不限 |
以下方法可以被用來設置或獲取策略的blender
operator.set_blender(blender=None, price_type=None)
設置blender
,直接傳入一個表達式blender expression
,這個表達式會被自動解析後用於組合交易策略。
operator.view_blender()
查看blender
, 註意此時為了便於人眼識別,混合器表達式中的策略代碼s0
,s1
,s2
會被自動替換為具體的策略ID,如下麵例子所示:
>>> op = qt.Operator('dma, macd, trix')
>>> op.set_blender('(0.5 * s0 + 1.0 * s1 + 1.5 * s2) / 3 * min(s0, s1, s2)')
>>> op.view_blender('close')
'(0.5 * dma + 1.0 * macd + 1.5 * trix) / 3 * min(dma, macd, trix)'
上面例子中的s0
,s1
,s2
分別被dma
、macd
、trix
代替,但如果Operator
中包含多個相同的策略,它們會被自動分配不同的策略ID,以示區別:
>>> op = qt.Operator('dma, dma, dma')
>>> op.set_blender('(0.5 * s0 + 1.0 * s1 + 1.5 * s2) / 3 * min(s0, s1, s2)')
>>> op.view_blender('close')
'(0.5 * dma + 1.0 * dma_1 + 1.5 * dma_2) / 3 * min(dma, dma_1, dma_2)'
blender
使用示例
下麵使用一個例子來演示blender
的工作方式:
我們生成一個交易員對象,同時運行五個DMA
交易策略,但五個交易策略分別有不同的可調參數,這時,我們可以理解為這個交易員同時運行五個同樣的交易邏輯,但這五個交易邏輯被配置了不同的參數,因此在同樣的輸入條件下,產生不同的交易信號,意味著五個交易策略各有側重,有的擅長於抓取長期變數,有的善於追蹤短期趨勢。
下麵,同樣是這五個交易策略,但我們會用三個不同的例子,來展示三種不同的混合方式,向您展示,即使完全相同的交易策略和交易參數,在同一段歷史區間,不同的混合方式同樣能影響最終的交易結果。
第一種混合方式:加權平均混合
第一種混合方式將五個交易策略的結果進行加權平均,混合表達式如下,其中的權值可以自行調整:
(0.8*s0+1.2*s1+2*s2+0.5*s3+1.5*s4)/5
# 創建一個交易員對象,同時運行五個相同的dma交易策略,這些交易策略運行方式相同,但是設置不同的參數後,會產生不同的交易信號。我們通過不同的策略組合方式,得到不同的回測結果
op = qt.Operator('dma, dma, dma, dma, dma')
# 分別給五個不同的交易策略設置不同的策略參數,使他們產生不同的交易信號
op.set_parameter(stg_id=0, pars=(132, 200, 24))
op.set_parameter(stg_id=1, pars=(124, 187, 51))
op.set_parameter(stg_id=2, pars=(103, 81, 16))
op.set_parameter(stg_id=3, pars=(48, 111, 148))
op.set_parameter(stg_id=4, pars=(104, 127, 58))
# 第一種組合方式:加權平均方式:分別給每一個不同的策略設置不同的權重:
# s0: 權重0.8
# s0: 權重1.2
# s0: 權重2.0
# s0: 權重0.5
# s0: 權重1.5
# 將五個交易策略生成的交易信號加權平均後得到最終的交易信號
op.set_blender('(0.8*s0+1.2*s1+2*s2+0.5*s3+1.5*s4)/5')
# 運行策略
res = qt.run(op, mode=1)
# 得到結果如下:年化收益12.19,夏普率1.053
====================================
| |
| BACK TESTING RESULT |
| |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 130.5ms
time consumption for operation back looping: 523.8ms
investment starts on 2016-04-05 00:00:00
ends on 2021-02-01 00:00:00
Total looped periods: 4.8 years.
-------------operation summary:------------
Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH 478 421 899 89.7% 0.0% 10.3%
Total operation fee: ¥ 2,615.40
total investment amount: ¥ 100,000.00
final value: ¥ 174,263.46
Total return: 74.26%
Avg Yearly return: 12.19%
Skewness: -0.31
Kurtosis: 10.31
Benchmark return: 65.96%
Benchmark Yearly return: 11.06%
------strategy loop_results indicators------
alpha: 0.007
Beta: 1.408
Sharp ratio: 1.053
Info ratio: 0.000
250 day volatility: 0.111
Max drawdown: 12.26%
peak / valley: 2019-04-19 / 2020-02-03
recovered on: 2020-07-06
===========END OF REPORT=============
如果仔細觀察上面生成的收益曲線圖,可以註意到圖示的背景上繪製了深淺不同的綠色條紋,這些條紋代表該段時間段里的持倉比例,白色代表空倉持幣,即完全不持有任何股票,而最深的綠色代表100%持股,介於中間的綠色代表0~100%之間的持股比例,持股比例越高,條紋的顏色越深。
從圖中可以看到,整個交易歷史區間存在著深淺不一的綠色,如果您非常仔細地檢查每一個持股區間,會發現這些區間的持股比例正好對應著當時五個交易策略的混合結果:當全部交易策略都"一致決定"全倉買入時,它們的加權平均結果就是100%買入,但只要有一個或多個策略決定持有空倉,最終加權平均的結果就是持有一定百分比的股票,這個百分比等於五個策略信號的加權平均結果。最終的結果就是持倉比例在0%~100%之間波動,完全空倉和完全滿倉的時間都不長。
這也意味著我們不能通過空倉來完全避免單邊下跌行情,不過,始終保持一定倉位卻能更好地抓住上升通道。
同時,您也應該可以觀察到,由於倉位是靈活調整的,在單邊下跌行情中的倉位(綠色的深淺幅度)明顯更低,上漲行情倉位更高,這正是我們所期望的。
接下來,讓我們來看下一種完全不同的混合方式:
第二種混合方式:委員會投票
這種方式讓同樣五個交易策略組成一個"委員會",通過平等投票來決定倉位,且倉位必須是"非黑即白"的兩種結果之一:要麼滿倉,要麼空倉。其表達式如下:
pos_3_0(s0, s1, s2, s3, s4)
# 第二種組合方式:將五個交易策略看成一個“委員會”,最終的持倉倉位由委員會投票決定:
# 當同一時間累計五個策略中至少三個輸出多頭滿倉使,輸出多頭滿倉,否則空倉
op.set_blender('pos_3_0(s0, s1, s2, s3, s4)')
# 運行策略
res = qt.run(op, mode=1)
# 得到結果如下:年化收益13.39,夏普率1.075
====================================
| |
| BACK TESTING RESULT |
| |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 540.1ms
time consumption for operation back looping: 435.8ms
investment starts on 2016-04-05 00:00:00
ends on 2021-02-01 00:00:00
Total looped periods: 4.8 years.
-------------operation summary:------------
Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH 11 10 21 55.4% 0.0% 44.6%
Total operation fee: ¥ 585.88
total investment amount: ¥ 100,000.00
final value: ¥ 183,485.41
Total return: 83.49%
Avg Yearly return: 13.39%
Skewness: -0.43
Kurtosis: 14.75
Benchmark return: 65.96%
Benchmark Yearly return: 11.06%
------strategy loop_results indicators------
alpha: 0.046
Beta: 1.003
Sharp ratio: 1.075
Info ratio: 0.006
250 day volatility: 0.124
Max drawdown: 15.71%
peak / valley: 2019-04-19 / 2020-02-03
recovered on: 2020-07-31
===========END OF REPORT=============
您一定看到了,這一次的輸出結果跟前一次有了很大區別:上一次回測時持倉是漸變的,而這一次是非黑即白的,要麼是滿倉,要麼是純粹空倉,您如果仔細分析交易日誌,會發現只有當三個交易策略舉手贊成滿倉時,才會滿倉,其餘時間空倉。因此在單邊下跌行情中的收益曲線是一條直線。但滿倉時如果股票下跌,也沒有辦法通過適當減倉來降低損失。
接下來,我們仍然使用這個委員會,但是現在只要有兩票投滿倉時,最終就會滿倉:
第三種混合方式:委員會投票
# 第三種組合方式:同樣是委員會策略,但輸出滿倉多頭的投票門檻變為2票,即只要有兩個策略認為輸出多頭即可
op.set_blender('pos_2_0(s0, s1, s2, s3, s4)')
# 運行策略
res = qt.run(op, mode=1)
# 得到結果如下:年化收益12.88,夏普率0.824
====================================
| |
| BACK TESTING RESULT |
| |
====================================
qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 133.8ms
time consumption for operation back looping: 500.0ms
investment starts on 2016-04-05 00:00:00
ends on 2021-02-01 00:00:00
Total looped periods: 4.8 years.
-------------operation summary:------------
Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH 15 14 29 71.4% 0.0% 28.6%
Total operation fee: ¥ 707.30
total investment amount: ¥ 100,000.00
final value: ¥ 179,532.76
Total return: 79.53%
Avg Yearly return: 12.88%
Skewness: -0.45
Kurtosis: 10.45
Benchmark return: 65.96%
Benchmark Yearly return: 11.06%
------strategy loop_results indicators------
alpha: 0.029
Beta: 1.000
Sharp ratio: 0.824
Info ratio: 0.007
250 day volatility: 0.144
Max drawdown: 15.94%
peak / valley: 2018-01-24 / 2019-01-03
recovered on: 2019-02-25
===========END OF REPORT=============
對比第二張圖表和第三張圖表,您可以發現,滿倉的區間明顯變長了,這是因為原來需要三張贊成票才能滿倉的策略,現在只要兩張贊成票就可以了,因此更容易出現滿倉的結果
本篇回顧
好了,相信到了這裡,您應該會對交易策略的混合有了一個基本的理解了。我們的教程還會繼續,qteasy
還有更多的方式實現您希望的交易策略,實際上,儘管qteasy
的內核被設計為一個有利於高速回測和高速執行的向量化的策略內核,但仍然考慮到了足夠的靈活性,理論上您可以實現您所設想的任何類型的交易策略。
同時,qteasy
的回測框架也做了相當多的特殊設計,可以完全避免您無意中在交易策略中導入"未來函數",確保您的交易策略在回測時完全基於過去的數據,同時也使用了很多預處理技術以及JIT技術對內核關鍵函數進行了編譯,以實現不亞於C語言的運行速度。
不過,為了實現理論上無限可能的交易策略,僅僅使用內置交易策略以及策略混合就不一定夠用了,一些特定的交易策略,或者一些特別複雜的交易策略是無法通過內置策略混合而成的,這就需要我們使用qteasy
提供的Strategy
基類,基於一定的規則創建一個自定義交易策略了。
在QTEASY
教程的下一節,我們將用一個例子來介紹如何創建一個自定義交易策略,如何定義策略的基本參數,如何定義策略所需的數據類型,如何設置交易信號的生成邏輯,等等
讓我們下期見!