【python量化交易】qteasy使用教程04 -使用內置交易策略,搭積木式創建複雜交易策略

来源:https://www.cnblogs.com/qteasy/p/18133643
-Advertisement-
Play Games

抽象工廠模式(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分別被dmamacdtrix代替,但如果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教程的下一節,我們將用一個例子來介紹如何創建一個自定義交易策略,如何定義策略的基本參數,如何定義策略所需的數據類型,如何設置交易信號的生成邏輯,等等

讓我們下期見!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 錨點鏈接 <a href="#Cat"></a> 點擊這個鏈接將為跳轉到這個頁面上id為Cat的頁面 利用這個功能,我們可以實現給一個頁面插眼的功能。 比如我們想建一個動物園的網站 <!-- 動物園導航欄--> <header> <ul> <li><a href="cat">Cats</a></li ...
  • 關於微信小程式轉發&保存圖片 已經好多年沒寫博客了,最近使用在用uniapp開發一個移動版管理後臺,記錄下自己踩過的一些坑 微信小程式圖片轉發保存簡單說明 微信小程式圖片轉發保存,依賴小程式的轉發api—— wx.showShareImageMenu(Object object) 通過調用這個api ...
  • 0x01 概述 API 是一些預先定義的函數,提供應用程式與開發人員基於某軟體或硬體訪問一組常式的能力 Web APIs 是 W3C 組織的標準,是 JS 獨有的部分 Web API 是瀏覽器提供的一套操作瀏覽器功能和頁面元素的 API,即 DOM 與 BOM 0x02 DOM (1)簡介 文檔對象 ...
  • 1、首先構造函數為中心 function Person() { } var p = new Person(); console.log('Person::', p) console.log(p.constructor Person) 列印如下: 可以看出構造函數通過new得到實例,實例可以通過【co ...
  • 今天我為大家帶來新的作品,iOS17桌面組件神器(Scriptable)原創腳本,精美作品分享!喜歡的話就點關註吧!更多腳本正在路上... * script : ONE-Progress.js * version : 1.0.0 * author : Nicolas-kings * date : 2 ...
  • 適配器模式(Adapter Pattern) 結構型設計模式,見名知意,就是兩個不相容的介面之間的橋梁。它結合了兩個獨立介面的功能。 主要解決:常常要將一些"現存的對象"放到新的環境中,而新環境要求的介面是現對象不能滿足的。 關鍵代碼:適配器繼承或依賴已有的對象,實現想要的目標介面。 優點: 1、可 ...
  • 領域驅動設計(DDD)裡面有一堆專業術語,比如領域、子域、核心域、通用域、支撐域等等,聽著是不是覺得挺嚇人?別怕,我來帶你輕鬆搞懂它們。 如何理解領域和子域? 領域是指一定的業務範圍或問題域。在解決業務問題時,DDD 會將業務領域進行細分,將問題範圍限定在一定的邊界內,在這個邊界內建立領域模型,用代 ...
  • 策略模式(Strategy Pattern) 指對象有某個行為,但是在不同的場景中,該行為有不同的實現演算法。將每個演算法封裝在獨立的類中,使得它們可以互相替換。可以在運行時根據需要選擇不同的演算法,而不需要修改客戶端代碼。 主要解決:在有多種演算法相似的情況下,使用 if...else 所帶來的複雜和難以 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...