【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
  • 概述:本文代碼示例演示瞭如何在WPF中使用LiveCharts庫創建動態條形圖。通過創建數據模型、ViewModel和在XAML中使用`CartesianChart`控制項,你可以輕鬆實現圖表的數據綁定和動態更新。我將通過清晰的步驟指南包括詳細的中文註釋,幫助你快速理解並應用這一功能。 先上效果: 在 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • 概述:本示例演示了在WPF應用程式中實現多語言支持的詳細步驟。通過資源字典和數據綁定,以及使用語言管理器類,應用程式能夠在運行時動態切換語言。這種方法使得多語言支持更加靈活,便於維護,同時提供清晰的代碼結構。 在WPF中實現多語言的一種常見方法是使用資源字典和數據綁定。以下是一個詳細的步驟和示例源代 ...
  • 描述(做一個簡單的記錄): 事件(event)的本質是一個委托;(聲明一個事件: public event TestDelegate eventTest;) 委托(delegate)可以理解為一個符合某種簽名的方法類型;比如:TestDelegate委托的返回數據類型為string,參數為 int和 ...
  • 1、AOT適合場景 Aot適合工具類型的項目使用,優點禁止反編 ,第一次啟動快,業務型項目或者反射多的項目不適合用AOT AOT更新記錄: 實實在在經過實踐的AOT ORM 5.1.4.117 +支持AOT 5.1.4.123 +支持CodeFirst和非同步方法 5.1.4.129-preview1 ...
  • 總說周知,UWP 是運行在沙盒裡面的,所有許可權都有嚴格限制,和沙盒外交互也需要特殊的通道,所以從根本杜絕了 UWP 毒瘤的存在。但是實際上 UWP 只是一個應用模型,本身是沒有什麼許可權管理的,許可權管理全靠 App Container 沙盒控制,如果我們脫離了這個沙盒,UWP 就會放飛自我了。那麼有沒... ...
  • 目錄條款17:讓介面容易被正確使用,不易被誤用(Make interfaces easy to use correctly and hard to use incorrectly)限制類型和值規定能做和不能做的事提供行為一致的介面條款19:設計class猶如設計type(Treat class de ...
  • title: 從零開始:Django項目的創建與配置指南 date: 2024/5/2 18:29:33 updated: 2024/5/2 18:29:33 categories: 後端開發 tags: Django WebDev Python ORM Security Deployment Op ...
  • 1、BOM對象 BOM:Broswer object model,即瀏覽器提供我們開發者在javascript用於操作瀏覽器的對象。 1.1、window對象 視窗方法 // BOM Browser object model 瀏覽器對象模型 // js中最大的一個對象.整個瀏覽器視窗出現的所有東西都 ...