創建交易策略並評價回測結果

qteasy中的所有交易策略都是通過qteast.Operator(交易員)對象來實現回測和運行的,Operator對象是一個策略容器,一個交易員可以同時 管理多個不同的交易策略,哪怕這些交易策略有不同的運行時機和運行頻率,或者不同的用途,例如一個策略用於選股、另一個策略用於大盤擇時,再一個策 略用於風險控制,用戶可以非常靈活地添加或修改Operator對象中的策略。

將策略交給Operator後,只要設置好交易的資產類別,資產池的大小,設定好每個策略的運行時機和頻率後,Operator對象就會在合適的時間啓動相應的 交易策略,生成策略信號,並將所有的策略信號混合(blend)後解析成爲交易信號。

關於Operator對象的更多介紹,請參見qteasy文檔

qteasy提供了兩種方式創建交易策略:

  • 使用內置交易策略組合

    • qteasy提供多種內置交易策略可供用戶使用,不需要手工創建。通過引用內置策略的名稱(關於所有內置策略的介紹,請參 見詳細文檔)用戶可以快速建立策略,還可以通過多個簡單的策略混合成較爲複雜的複合策略。

  • 通過策略類自行創建策略

    • 當用戶的策略非常複雜時,可以通過qteasy.Strategy類來自定義一個策略。

創建交易策略,並且使用歷史數據回溯測試交易策略的交易結果,並對交易結果進行評價是qteasy的核心功能之一。 qteasy通過一個交易員對象(Operator)彙總一系列的交易策略,並且通過qt.run()函數在一段設定好的歷史時間段內模擬交易策略的運行,生成交易信號,使用歷史價格進行模擬交易,生成交易結果,計算評價指標,並以可視化形式輸出爲圖表。

本章節以一個最常見的基金擇時投資策略爲例子,演示了以下內容:

  • 創建一個簡單的dma擇時投資策略,創建一個交易員對象使用這個策略,演示如何修改、添加策略

  • 通過qt.configure()設置相關的環境變量,使用過去10年的滬深300指數歷史數據,回測策略表現

  • 通過對過去10年左右的滬深300指數歷史數據,對策略進行參數尋優,最終演示尋優後的結果

首先我們導入qteasy模塊 爲了在線列印圖表,使用matplotlib inline設置圖表列印模式爲在線列印

創建Strategy對象和Operator對象

qteasy中的每一個交易策略都被定義爲交易策略(Strategy)對象。每個交易對象包含了一系列的交易規則,這些規則包括三個方面:

  1. 策略運行規則,包括策略運行的頻率,所使用的歷史數據類型,歷史數據窗口長度,定義了策略如何運行以及如何使用歷史數據

  2. 信號生成規則,交易信號的生成規則,即如何根據相關歷史數據生成何種交易信號,這是交易策略的核心

  3. 交易信號類型,交易信號的不同類型決定了模擬交易模塊如何處理交易信號

qteasy中,交易策略是由交易員對象(Operator)執行的,同一時間只能有一個Operator對象在運行,但是同一個交易員可以同時執行一個或多個交易策略,這些交易策略可以針對同一個投資組合進行交易,用戶可以定義特定的“混合”方法,把多個簡單交易策略混合成爲一個複雜交易策略運行。

創建Strategy對象

創建Strategy對象的最簡單方法是使用qt.built_in模塊, 也可以在創建Operator對象的時候同時創建。

import qteasy as qt
# 通过qt内置策略模块创建一个DMA则时策略
stg = qt.built_in.DMA()
# 通过stg.info()可以查看策略的主要信息:
stg.info()
Strategy_type:      RuleIterator
Strategy name:      DMA
Description:        Quick DMA strategy, determine long/short position according to differences of moving average prices with simple timing strategy
Strategy Parameter: (12, 26, 9)

Strategy Properties     Property Value
-------------------------------------------------
Param. count            3
Param. types            ['int', 'int', 'int']
Param. range            [(10, 250), (10, 250), (5, 250)]
Run parameters          d @ close
Data types              ['close']
Data parameters         270 d

從上面的輸出可以看到這個交易策略的基本資訊。除了名稱、描述以外,比較重要的資訊包括:

  • 策略參數 Strategy Parameter。策略參數是策略運行過程中所需的外部參數,根據策略規則的不同,策略使用的參數也不同,這些參數對策略的運行過程產生影響,不同的參數會影響策略的輸出。例如,在雙均線則時策略中,長均線的計算週期和短均線的計算週期就是兩個策略參數。

  • 參數類型/範圍 Parameter Types / Range: 不同的策略參數會極大地影響一個策略的最終結果,設置好參數的取值範圍和類型之後,qteasy可以通過不同方法在參數空間內搜索最佳參數,使策略的性能達到最佳。

  • 策略數據頻率和運行頻率 Data Frequcney / Sample Frequency。策略運行的頻率以及所需數據的頻率,例如每週執行一次,每月執行一次或每分鐘執行一次等等,一般來說數據頻率與執行頻率相關

  • 數據類型 Data Types:運行策略所需要讀取的歷史數據類型。對DMA策略來說,僅需要收盤價即可。

也要查看所有的內置策略,可以使用qt.built_ins()函數,如果不給出函數的參數,則會顯示所有內置策略的列表,如果給出參數,則會顯示指定內置策略的詳細資訊。 例如:

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)]
    策略不支持参考数据,不支持交易数据

更多關於內置策略的函數包括:

qt.built_ins(stg_id=None)

如果stg_id=None,顯示所有內置策略的列表,否則顯示指定內置策略的詳細資訊

qt.built_in_list(stg_id=None)

如果stg_id=None,返回所有內置策略的列表,否則返回指定內置策略的詳細資訊

qt.built_in_strategies(stg_id=None)

如果stg_id=None,返回所有內置策略的列表,否則返回指定內置策略的詳細資訊

qt.get_built_in_strategy(stg_id)

根據給出的內置策略ID,返回內置策略對象

創建Operator對象

使用qt.Operator()可以創建Operator對象。 創建一個Operator對象後,所有的交易策略都由交易員對象來負責運行。創建交易員對象時可以指定交易信號的處理方式以及交易運行的方式:

qt.Operator(strategies=None, signal_type=None, op_type=None)

  • strategies: 交易員對象中的交易策略,可以是一個或多個交易策略,也可以是一個交易策略的列表。如果不指定交易策略,則創建一個空的交易員對象,交易策略可以事後添加或刪除。一旦添加了交易策略,交易員對象會爲每一個交易策略賦予一個唯一的ID,這個ID可以用來引用這個交易策略。同時,交易員對象會根據策略的運行頻率和運行時機,自動爲每一個交易策略分配一個運行時機,只有在運行時機到來時,交易員對象纔會執行這個交易策略,生成交易信號。

  • signal_type: 交易信號的類型,可以是'pt''ps'或者'vs',默認'pt',分別代表目標持倉比例信號,百分比交易信號和數量交易信號。不同的交易信號類型決定了交易員對象如何處理交易信號,以及交易員對象如何將多個交易策略的交易信號混合成爲一個交易信號。

  • op_type: 交易員對象的運行模式,可以是'batch'或者'realtime',默認'batch',分別代表批量運行模式和實時運行模式。在批量運行模式下,交易員對象會在回測或者優化模式下,預先生成交易信號,再批量進行模擬交易,運行速度較快。在實時運行模式下,交易員對象會生成交易信號立即模擬交易,產生模擬交易結果後,再進行下一次交易信號生成,適用於實盤交易運行模式,或特殊情況下的回測模式。

對於qteasy來說,交易策略的交易信號和股票/基金的交易訂單是兩個不同的概念。

所有的交易策略都是基於歷史數據生成的交易信號,而交易員對象則根據交易信號生成交易訂單,然後模擬交易員的交易行爲,最終生成交易結果。

策略的三種信號類型

在qteasy中,交易信號是一個浮點數,同一個交易信號可以代表不同的含義,從而被交易員對象解讀爲不同的交易訂單。交易信號的含義由交易員對象的信號類型決定,交易員對象的信號類型可以是'pt''ps'或者'vs',分別代表目標持倉比例信號,百分比交易信號和數量交易信號。

交易信號的類型包括三類:

  • PT: 此時交易信號代表目標持倉比例,也就是說持有的股票的價值佔總資產的比例,例如當前總資產爲100萬元時,0.2代表控制當前某股票或基金的持有數量,使其市值爲100萬元的20%也就是20萬元。在這種情況下,買入或賣出股票的數量取決於當前持有的股票的數量,如果當前持有的股票數量爲0,則買入20萬元的股票,如果當前持有的股票價值爲30萬元,則需要賣出10萬元。

  • PS: 此時交易信號直接代表買賣比例,在這種情況下,買入或賣出股票的數量與當前持有的股票的數量無關,只與總資產有關。如果總資產爲100萬元時,0.2代表買入20萬元的股票。

  • VS: 此時交易信號直接代表買賣數量,在這種情況下,買入或賣出股票的數量與總資產或持股數量無關。2000代表買入2000股的股票。

不僅如此,如果根據交易員操作的賬戶類型不同(如股票賬戶或期貨賬戶),生成的交易訂單也會不同。具體的說明如下表:

账户类型 信号类型 交易信号 信号含义 信号举例 交易订单举例
股票账户 PT sig > 0 持有该资产,并使持有资产的市值为总资产的sig倍 0.5 根据当前持有的资产比例确定交易订单,如果已经满仓持有,则卖掉50%仓位,如果持仓为0,则买入至50%仓位
sig = 0 清空全部持有的资产,持有资产为0 0 根据当前持有的资产比例确定交易订单,如果持仓则卖掉全部持仓,如果没有持仓则不交易
sig < 0 无意义 N/A N/A
PS sig > 0 买入该资产,买入的金额占总资产的比例为sig 0.5 总资产为100,000,则此时花费50,000元金额买入资产(含手续费)
sig = 0 不进行任何操作 0 不进行任何操作
sig < 0 卖出该资产,卖出的部分占当前持有数量的比例为sig -0.5 假设当前持有1000股,则此时应卖出500股
VS sig > 0 买入该资产,买入的数量为sig 500 买入500股
sig = 0 不进行任何操作 0 不进行任何操作
sig < 0 卖出该资产,卖出的数量为abs(sig) -500 卖出500股
期货账户 (未实现) PT sig > 0 平掉所有空仓,开多仓,并使持有合约价值为总资产的sig倍 1.5 假设总资产为100,000,开多仓持有总价150,000的合约
*当保证金比例<1时,持仓比例可以大于100%
sig = 0 平掉全部持有的仓位,持有头寸为0 0 平掉所有持有的多仓和空仓
sig < 0 平掉所有多仓,开空仓,并使持有合约价值为总资产的sig倍 -1.5 总资产为100,000,则开空仓持有总价150,000的合约
* 如果保证金比例<1时,持空仓比例可以大于100%
PS sig > 0 如果持有空仓:平部分空仓,平空仓的数量占总持有的比例为sig 0.5 如果总持仓为1,000手,则此时平仓500手
* 此时sig必须小于等于1
如果持有多仓:开多仓,开仓的合约价值占总资产的比例为sig 1.5 如果总资产为100,000,则开多仓持有总价150,000元的合约
* 如果保证金比例<1时,sig可以大于1
sig = 0 不进行任何操作 0 不进行任何操作
sig < 0 如果持有多仓:平部分多仓,平仓的数量占总持有的比例为sig 0.5 如果总持仓为1,000手,则此时平仓500手
* 此时sig必须小于等于1
如果持有空仓:开空仓,开仓的合约价值占总资产的比例为sig 1.5 如果总资产为100,000,则开空仓持有总价150,000元的合约
* 如果保证金比例<1时,sig可以大于1
VS sig > 0 平空仓或开多仓,开平仓的数量为sig。如果持有空头数量超过sig则忽略剩余部分 1500 如果持有1500手以上空头仓位,则平仓1500手,如果当前没有持仓,则开多仓持有1500手合约
sig = 0 不进行任何操作 0 不进行任何操作
sig < 0 平多仓或开空仓,开平仓的数量为sig。如果持有多头数量超过sig则忽略剩余部分 -500 如果持有1500手以上多头仓位,则平仓1500手,如果当前没有持仓,则开空仓持有1500手合约

交易信號的混合

儘管同一個Operator對象同時只能生成一種類型的信號,但由於Operator對象能容納無限多個不同的交易策略,因而Operator對象 也能產生無限多組同類型的交易策略。爲了節省交易回測時的計算開銷,避免衝突的交易信號或重複的交易信號佔用計算資源,同時也 爲了增加交易信號的靈活度,應該將所有交易信號首先混合成一組,再送入回測程式進行回測。

不過,在一個Operator對象中,不同策略生成的交易信號可能運行的交易價格是不同的,例如,某些策略生成開盤價交易信號,而另一 些策略生成的是收盤價交易策略,那麼不同的交易價格信號當然不應該混合。但除此之外,只要是交易價格相同的信號,都應該全部混合。

交易信號的混合即交易信號的各種運算或函數,從簡單的邏輯運算、加減運算一直到複雜的自定義函數,只要能夠應用於一個ndarray的 函數,理論上都可以用於混合交易信號,只要最終輸出的交易信號有意義即可。

交易信號的混合基於一系列事先定義的運算和函數,這些函數或運算都被稱爲」原子函數」或」算子」,用戶利用這些」算子」來操作 Operator對象生成的交易信號,並將多個交易信號組變換成一個唯一的交易信號組,同時保持其形狀不變,數字有意義。

交易信號的混合是由一個混合表達式blender來確定的,例如s0 and (s1 + s2) * avg(s3, s4)

blender表達式中支持的函數如下:

元素

示例

說明

策略序號

s1

以s開頭,數字結尾的字符串,數字爲Operator中的策略的序號,代表這個策略生成的交易信號

數字

-1.35

任何合法的數字,參與表達式運算的數字

運算符

+

包括'+-*/^'等四則運算符

邏輯運算符

and

支持'&|~'以及'and/or/not'形式的邏輯運算符

函數

sum()

支持的函數參見後表

括號

()

組合運算

關於更多的混合表達式的例子,請參見qteasy Tutorial 04 - 使用內置交易策略

op = qt.Operator()
OPERATOR INFO:
=========================
Information of the Module
=========================
Total 0 operation strategies, requiring 0 types of historical data:

0 types of back test price types:
[]

交易員對象是一個策略容器,在一個Operator對象中可以添加任意多個交易策略,同時,在Operator對象中,可以管理交易策略的混合方式(blender),交易信號的處理方式以及交易運行的方式。

常用的Operator屬性及方法如下:

獲取Operator對象的基本資訊

op.info()

列印Operator對象的重要資訊

op.strategies

獲取Operator對象中所有交易策略的清單

op.strategy_ids

獲取Operator對象中所有交易策略的ID

op.strategy_count

獲取Operator對象中交易策略的數量

op.signal_type

Operator對象的信號類型,代表交易信號的含義及處理方式:

  • pt: 目標持倉比例信號,在這個模式下,交易員關注一個投資組合中各個成份股票的持倉比例,通過適時的買入和買出,維持各個成份股的持倉比例在一個目標值上;

  • ps: 百分比交易信號,在這個模式下,交易員關注定時產生的比例交易信號,根據交易信號按比例買入或買出股票

  • vs: 數量交易信號,在這個模式下,交易員關注定時產生的交易信號,按照交易信號買入或買出一定數量的股票

op.op_type

Operator對象的運行模式:

  • batch: 批量運行模式,在回測模式或優化模式下,預先生成交易清單,再批量進行模擬交易,運行速度較快

  • realtime: 實時運行模式,生成交易信號立即模擬交易,產生模擬交易結果後,再進行下一次交易信號生成,適用於實時運行模式,或特殊情況下的回測模式

獲取交易策略

op.get_stg(stg_id)

通過策略ID獲取策略對象,下面的方法效果相同,且可以通過數字序號來獲取策略

stg = op.get_stg(stg_id)
stg = op[stg_id] 
stg = op[stg_idx]

添加或修改交易策略

op.add_strategy(stg, **kwargs)

添加一個策略到Operator,添加策略的同時可以同時設置策略參數

op.add_strategies(strategies)

批量添加一系列策略到Operator,添加的同時不能同時設置策略參數

op.remove_strategy(id_or_pos=None)

從Operator中刪除一個策略

op.clear_strategies()

清除Operator中的所有交易策略

設置策略參數或Operator參數

op.set_parameter(stg_id, pars=None, opt_tag=None, par_range=None, par_types=None, data_freq=None, run_freq=None, window_length=None, data_types=None, strategy_run_timing=None, **kwargs)

指定一個交易策略的ID,設置這個交易策略的策略參數或其他屬性

op.set_blender(price_type=None, blender=None)

設置交易策略的混合方式。當Operator中有多個交易策略時,每個交易策略分別運行生成多組交易信號,再按照用戶定義的規則混合後輸出一組交易信號,用於交易

我們可以用下面的代碼將剛創建的DMA策略加入到Operator中去,並設置必要的策略參數

所有的參數設置都可以使用operator.set_parameter方法,可以同時傳入多個參數 通過設置策略的opt_tag可以控制策略是否參與優化,而par_range參數定義了策略優化時需要用到的參數空間 在此時我們並不知道對於過去15年的滬深300指數來說,最優的DMA擇時參數是什麼,因此可以輸入幾個隨機的參數,進行一次回測,看看結果如何

op.clear_strategies()
op.add_strategy(stg, pars=(26, 35, 189), opt_tag=1)
print(f'Operator strategies: {op.strategies}')
print(f'Strategy IDs are: {op.strategy_ids}')
op.info(verbose=True)
Operator strategies: [RULE-ITER(DMA)]
Strategy IDs are: ['custom']
OPERATOR INFO:
=========================
Information of the Module
=========================
Total 1 operation strategies, requiring 1 types of historical data:
close
1 types of back test price types:
['close']
for backtest histoty price type - close: 
[RULE-ITER(DMA)]:
no blender
Parameters of GeneralStg Strategies:
Strategy_type:      RuleIterator
Strategy name:      DMA
Description:        Quick DMA strategy, determine long/short position according to differences of moving average prices with simple timing strategy
Strategy Parameter: (26, 35, 189)

Strategy Properties     Property Value
---------------------------------------
Parameter count         3
Parameter types         ['int', 'int', 'int']
Parameter range         [(10, 250), (10, 250), (10, 250)]
Data frequency          d
Sample frequency        d
Window length           270
Data types              ['close']

=========================

配置qteasy的回測參數

Operator對象創建好並添加策略後就可以開始進行回測了

qteasy提供了豐富的環境參數以控制回測的具體過程 所有的環境參數變量值都可以通過qt.Configuration()查看,並通過qt.Configure()來設置。

qt.configuration()

查看qteasy運行環境變量

qt.configure()

設置qteasy運行環境變量

與回測相關的主要環境變量參數包括:

  • 回測交易的目標股票/指數

  • 回測交易的起止時間段

  • 回測交易的初始投資金額

  • 回測交易的交易費用和交易規則

  • 交易結果評價的基準指數

以上所有回測交易參數都可以通過qt.configure()設置:

qt.configure(
    mode=1,  # 设置运行模式为:1-回测模式
    benchmark_asset = '000300.SH',  # 设置交易评价基准(类型由系统根据代码自动推断)
    asset_pool = '000300.SH',  # 设置交易资产组合
    asset_type = 'IDX',  # 交易资产组合的资产类型
    trade_batch_size = 0.01,  # 设置允许最小交易批量(最小0.01)
    invest_start = '20100105',  # 设置交易开始日期
    invest_end = '20201231',  # 设置交易终止日期
    invest_cash_amounts = [1000000],  # 设置初始交易投资金额为十万元
    visual=True  # 输出可视化交易结果图表
)

啓動qteasy並開始運行Operator

qt.run(operator, **config)

開始運行Operator,根據運行的mode,qteasy會進入到不同的運行模式,輸出不同的結果:

  • mode 0 實時模式:讀取最近的(實時)數據,生成當前最新的交易信號。再此模式下,可以設置qteasy定期執行,定期讀取最新數據,定期生成實時交易信號

  • mode 1 回測模式:讀取過去一段時間內的歷史數據,使用該數據生成交易信號並模擬交易,輸出模擬交易的結果

  • mode 2 優化模式:讀取過去一段時間內的歷史數據,通過反覆運行同一套交易策略但使用不同的參數組合,搜索在這段時間內表現最佳的策略參數

只要運行qteasy.run(operator, **config)就可以開始運行Operator了,其中**config是測試環境參數,在qt.run()中以參數形式傳入的環境變量僅僅在本次運行中有效,但是在qt.configure()中設置的環境變量將一直有效,直到下次改變爲止

回測最終資產爲19萬元,年化收益率只有4.83%,夏普率只有0.0783,收益率低於同期滬深300指數

qt.run(op)

運行qteasy後,系統會自動讀取歷史數據,進行回測,完成結果評價並列印回測報告。

回測報告會包含以下資訊:

  • 回測計算耗時

  • 回測區間開始日期及結束日期、持續時間等資訊

  • 交易統計資訊:如買入次數、賣出次數,滿倉比例,空倉比例、總交易費用等

  • 收益資訊:初始投資額,最終資產額,總收益率,年化收益率,基準總收益率,基準年化收益率,收益率的峯度和偏度

  • 投資組合評價指標:Alpha,Beta、夏普率、資訊比率、波動率以及最大回撤

         ====================================
         |                                  |
         |       BACK TESTING RESULT        |
         |                                  |
         ====================================
    
    qteasy running mode: 1 - History back testing
    time consumption for operate signal creation: 1s 164.2ms
    time consumption for operation back looping:  6s 720.2ms
    
    investment starts on      2010-01-05 00:00:00
    ends on                   2020-12-31 00:00:00
    Total looped periods:     11.0 years.
    
    -------------operation summary:------------
    
              Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
    000300.SH    53       53    106   54.0%      0.0%     46.0%   
    
    Total operation fee:     ¥   20,382.34
    total investment amount: ¥1,000,000.00
    final value:              ¥1,052,696.57
    Total return:                     5.27% 
    Avg Yearly return:                0.47%
    Skewness:                         -0.76
    Kurtosis:                         11.44
    Benchmark return:                46.22% 
    Benchmark Yearly return:          3.52%
    
    ------strategy loop_results indicators------ 
    alpha:                           -0.047
    Beta:                             1.000
    Sharp ratio:                     -0.077
    Info ratio:                      -0.018
    250 day volatility:               0.156
    Max drawdown:                    46.12% 
        peak / valley:        2010-11-08 / 2014-06-19
        recovered on:         2015-04-17
     
    ===========END OF REPORT=============

除了回測報告以外,一張可視化圖表也會被列印出來,顯示整個回測過程的詳細資訊。

在這張資訊圖中,會顯示以下資訊:

  • 整個回測歷史的收益率曲線圖(同時顯示持倉區間、賣賣點、基準收益率曲線和最大回撤區間)

  • 對數比例收益率曲線和基準收益率對比圖

  • 每日收益變動圖

  • 滾動夏普率和alpha率變動圖(投資組合盈利能力評價)

  • 滾動波動率(Volatility)和Beta率變動圖(投資組合風險評價)

  • 歷史回撤分析圖(潛水圖)

  • 月度、年度收益率熱力圖和條形圖

  • 月度收益率統計頻率直方圖

png

qteasy模擬的交易過程中,可以設置豐富的參數,例如:

  • 投入資金的數量、日期、或者設置分批多次投入資金;

  • 買入和賣出交易的費用、包括佣金費率、最低費用、固定費用、以及滑點。各種費率都可以針對買入和賣出分別設定

  • 買入和賣出交易的交割時間,也就是T+N日交割制度

  • 買入和賣出交易的最小批量,例如是否允許分數份額交易、還是必須整數份額、甚至整百份交易

最終列印的回測結果是考慮上述所有交易參數之後的最終結果,因此可以看到總交易成本。詳細的交易參數設置請參見詳細文檔。

另外,qteasy還給給出了關於策略表現的幾個指標: 如alpha和beta分別是0.067和1.002,而夏普率爲0.041。最大回撤發生在2009年8月3日到2014年7月10日,回撤了35.0%,且到了2014年12月16日才翻盤。

在上面的回測結果中我們給出了參數visual=False,如果令visual=True,就能得到可視化的回測結果,以圖表的形式給出,並提供可視化資訊:

  • 投資策略的歷史資金曲線

  • 參考數據(滬深300指數)的歷史曲線

  • 買點和賣點(在參考數據上以紅色、綠色箭頭顯示)

  • 持倉區間(綠色表示持倉)

  • 投資策略的評價指標(alpha、sharp等)

  • 歷史回撤分析(顯示五次最大的回撤)

  • 歷史收益率熱力圖、山積圖等圖表

qteasy提供了豐富的策略回測選項,例如:

  • 回測開始結束日期

  • 回測結果評價指標

  • 回測時是否允許持有負數倉位(用於模擬期貨交易賣空行爲,也可以使用專門的期貨交易模擬算法)

更多的選項請參見詳細文檔

單擇時策略的優化

顯然,沒有經過優化的參數無法得到理想的回測結果,因此我們需要進行一次優化

通過設置context對象的各個參數,我們可以設置優化方式並控制優化過程: 以下參數的含義分別如下:

  • 優化方法設置爲1,使用蒙特卡洛優化,對於較大的參數空間有較好的尋優能力

  • 輸出結果數量設置爲30

  • 優化過程迭代次數爲1000次

  • parallel參數設置爲True會使用多核處理器的所有核心進行並行計算節省時間

最後開始優化,使用perfs_dmapars_dma兩個變量來存儲優化結果 優化過程中會顯示進度條,結束後會顯示優化結果

pars_dma = qt.run(op, 
                  mode=2,
                  opti_method=1,
                  opti_sample_count=1000,
                  opti_start='20101231',
                  opti_end='20201231',
                  opti_cash_dates='20101231',
                  test_start='20101231',
                  test_end='20201231',
                  test_cash_dates='20101231',
                  parallel=True)
print(f'optimization completed, 50 parameters found, they are\n'
      f'{pars_dma}')
[########################################]1000/1000-100.0%  best performance: 340613.629
Optimization completed, total time consumption: 38"247
[########################################]30/30-100.0%  best performance: 340613.629
==================================== 
|                                  |
|       OPTIMIZATION RESULT        |
|                                  |
====================================

qteasy running mode: 2 - Strategy Parameter Optimization

investment starts on 2010-12-31 00:00:00
ends on 2020-12-31 00:00:00
Total looped periods: 10.0 years.
total investment amount: ¥   100,000.00
Reference index type is 000300.SH at IDX
Total Benchmark rtn: 66.59% 
Average Yearly Benchmark rtn rate: 5.23%
statistical analysis of optimal strategy messages indicators: 
total return:        161.24% ± 29.73%
annual return:       10.01% ± 1.18%
alpha:               0.048 ± 0.014
Beta:                1.001 ± 0.001
Sharp ratio:         0.625 ± 0.089
Info ratio:          0.013 ± 0.004
250 day volatility:  0.151 ± 0.006
other messages indicators are listed in below table

    Strategy items  Sell-outs Buy-ins ttl-fee      FV      ROI   Benchmark rtn  MDD 
0    (147, 157, 57)    25.0     25.0  1,213.16 231,710.13 131.7%     66.6%     38.1%
1    (88, 108, 127)    16.0     15.0  1,009.93 233,554.10 133.6%     66.6%     44.3%
2    (105, 160, 29)    21.0     20.0  1,344.78 232,247.09 132.2%     66.6%     26.4%
3    (149, 194, 24)    19.0     19.0  1,062.61 233,932.11 133.9%     66.6%     33.4%
4    (105, 185, 25)    18.0     17.0  1,094.07 236,171.54 136.2%     66.6%     40.6%
5    (86, 147, 107)    11.0     10.0    668.08 234,827.39 134.8%     66.6%     39.7%
6    (88, 157, 101)    11.0     10.0    715.01 236,851.09 136.9%     66.6%     31.6%
7    (144, 181, 57)    19.0     19.0  1,093.20 240,445.16 140.4%     66.6%     33.8%
8     (94, 165, 78)    12.0     11.0    724.66 240,825.90 140.8%     66.6%     38.1%
9    (68, 113, 142)    13.0     12.0    819.42 244,805.70 144.8%     66.6%     42.5%
10     (80, 64, 57)    30.0     30.0  1,767.04 245,084.54 145.1%     66.6%     28.8%
11   (101, 124, 65)    23.0     22.0  1,726.89 245,504.45 145.5%     66.6%     30.7%
12   (150, 189, 33)    20.0     20.0  1,142.62 246,185.41 146.2%     66.6%     34.3%
13   (119, 200, 30)    12.0     11.0    705.66 248,111.42 148.1%     66.6%     24.1%
14   (52, 111, 136)    14.0     13.0    810.29 254,764.49 154.8%     66.6%     40.5%
15    (55, 151, 87)    14.0     13.0    896.37 248,370.33 148.4%     66.6%     38.2%
16    (98, 129, 45)    22.0     21.0  1,480.50 252,764.13 152.8%     66.6%     37.1%
17    (101, 59, 50)    27.0     26.0  1,505.08 255,487.88 155.5%     66.6%     28.8%
18   (179, 240, 25)    19.0     19.0  1,149.62 259,380.09 159.4%     66.6%     33.8%
19   (82, 127, 144)    12.0     11.0    810.46 268,321.59 168.3%     66.6%     37.4%
20   (44, 135, 117)    13.0     12.0    741.60 268,837.16 168.8%     66.6%     42.6%
21   (103, 127, 57)    22.0     21.0  1,628.33 269,776.04 169.8%     66.6%     30.3%
22   (128, 152, 92)    15.0     15.0    883.81 272,170.16 172.2%     66.6%     32.6%
23    (91, 198, 13)    17.0     16.0  1,209.55 277,214.25 177.2%     66.6%     43.3%
24  (102, 110, 129)    26.0     25.0  2,056.58 311,876.36 211.9%     66.6%     33.4%
25   (129, 204, 16)    14.0     14.0    840.49 279,142.60 179.1%     66.6%     32.6%
26    (90, 185, 45)    11.0     10.0    735.84 279,320.37 179.3%     66.6%     40.6%
27  (104, 111, 107)    30.0     29.0  2,207.23 317,371.14 217.4%     66.6%     41.0%
28   (101, 150, 24)    23.0     22.0  2,012.97 331,442.65 231.4%     66.6%     26.4%
29   (104, 142, 87)    15.0     14.0  1,044.25 340,613.63 240.6%     66.6%     23.5%

===========END OF REPORT=============

[########################################]30/30-100.0%  best performance: 340613.629
==================================== 
|                                  |
|       OPTIMIZATION RESULT        |
|                                  |
====================================

qteasy running mode: 2 - Strategy Parameter Optimization

investment starts on 2010-12-31 00:00:00
ends on 2020-12-31 00:00:00
Total looped periods: 10.0 years.
total investment amount: ¥   100,000.00
Reference index type is 000300.SH at IDX
Total Benchmark rtn: 66.59% 
Average Yearly Benchmark rtn rate: 5.23%
statistical analysis of optimal strategy messages indicators: 
total return:        161.24% ± 29.73%
annual return:       10.01% ± 1.18%
alpha:               0.048 ± 0.014
Beta:                1.001 ± 0.001
Sharp ratio:         0.625 ± 0.089
Info ratio:          0.013 ± 0.004
250 day volatility:  0.151 ± 0.006
other messages indicators are listed in below table

    Strategy items  Sell-outs Buy-ins ttl-fee      FV      ROI   Benchmark rtn  MDD 
0    (105, 160, 29)    21.0     20.0  1,344.78 232,247.09 132.2%     66.6%     26.4%
1    (88, 108, 127)    16.0     15.0  1,009.93 233,554.10 133.6%     66.6%     44.3%
2    (147, 157, 57)    25.0     25.0  1,213.16 231,710.13 131.7%     66.6%     38.1%
3    (105, 185, 25)    18.0     17.0  1,094.07 236,171.54 136.2%     66.6%     40.6%
4    (88, 157, 101)    11.0     10.0    715.01 236,851.09 136.9%     66.6%     31.6%
5    (149, 194, 24)    19.0     19.0  1,062.61 233,932.11 133.9%     66.6%     33.4%
6    (144, 181, 57)    19.0     19.0  1,093.20 240,445.16 140.4%     66.6%     33.8%
7    (86, 147, 107)    11.0     10.0    668.08 234,827.39 134.8%     66.6%     39.7%
8    (68, 113, 142)    13.0     12.0    819.42 244,805.70 144.8%     66.6%     42.5%
9     (94, 165, 78)    12.0     11.0    724.66 240,825.90 140.8%     66.6%     38.1%
10   (150, 189, 33)    20.0     20.0  1,142.62 246,185.41 146.2%     66.6%     34.3%
11   (101, 124, 65)    23.0     22.0  1,726.89 245,504.45 145.5%     66.6%     30.7%
12     (80, 64, 57)    30.0     30.0  1,767.04 245,084.54 145.1%     66.6%     28.8%
13   (119, 200, 30)    12.0     11.0    705.66 248,111.42 148.1%     66.6%     24.1%
14    (55, 151, 87)    14.0     13.0    896.37 248,370.33 148.4%     66.6%     38.2%
15    (98, 129, 45)    22.0     21.0  1,480.50 252,764.13 152.8%     66.6%     37.1%
16   (52, 111, 136)    14.0     13.0    810.29 254,764.49 154.8%     66.6%     40.5%
17    (101, 59, 50)    27.0     26.0  1,505.08 255,487.88 155.5%     66.6%     28.8%
18   (179, 240, 25)    19.0     19.0  1,149.62 259,380.09 159.4%     66.6%     33.8%
19   (82, 127, 144)    12.0     11.0    810.46 268,321.59 168.3%     66.6%     37.4%
20   (44, 135, 117)    13.0     12.0    741.60 268,837.16 168.8%     66.6%     42.6%
21   (103, 127, 57)    22.0     21.0  1,628.33 269,776.04 169.8%     66.6%     30.3%
22   (128, 152, 92)    15.0     15.0    883.81 272,170.16 172.2%     66.6%     32.6%
23    (91, 198, 13)    17.0     16.0  1,209.55 277,214.25 177.2%     66.6%     43.3%
24   (129, 204, 16)    14.0     14.0    840.49 279,142.60 179.1%     66.6%     32.6%
25    (90, 185, 45)    11.0     10.0    735.84 279,320.37 179.3%     66.6%     40.6%
26  (104, 111, 107)    30.0     29.0  2,207.23 317,371.14 217.4%     66.6%     41.0%
27  (102, 110, 129)    26.0     25.0  2,056.58 311,876.36 211.9%     66.6%     33.4%
28   (101, 150, 24)    23.0     22.0  2,012.97 331,442.65 231.4%     66.6%     26.4%
29   (104, 142, 87)    15.0     14.0  1,044.25 340,613.63 240.6%     66.6%     23.5%

===========END OF REPORT=============

png

optimization completed, 50 parameters found, they are
[(147, 157, 57), (105, 160, 29), (88, 108, 127), (149, 194, 24), (86, 147, 107), (105, 185, 25), (88, 157, 101), (144, 181, 57), (94, 165, 78), (68, 113, 142), (80, 64, 57), (101, 124, 65), (150, 189, 33), (119, 200, 30), (55, 151, 87), (98, 129, 45), (52, 111, 136), (101, 59, 50), (179, 240, 25), (82, 127, 144), (44, 135, 117), (103, 127, 57), (128, 152, 92), (91, 198, 13), (129, 204, 16), (90, 185, 45), (102, 110, 129), (104, 111, 107), (101, 150, 24), (104, 142, 87)]

優化結束後,可以看到三十組最佳參數,其中最差的一組也能實現最終資產6萬元以上。我們可以手動選取其中最佳的參數,再進行一次回測:

能發現終值從上次回測的1.9萬暴漲至12.4萬,年化收益18.9%,夏普率也上升到了0.833

op.set_parameter('dma', pars=(104, 142, 87))
qt.run(op,
      mode=1, visual=True)

輸出回測結果如下:

     ====================================
     |                                  |
     |       BACK TESTING RESULT        |
     |                                  |
     ====================================

qteasy running mode: 1 - History back testing
time consumption for operate signal creation: 55.7ms
time consumption for operation back looping:  885.7ms

investment starts on      2010-12-31 00:00:00
ends on                   2020-12-31 00:00:00
Total looped periods:     10.0 years.

-------------operation summary:------------

          Sell Cnt Buy Cnt Total Long pct Short pct Empty pct
000300.SH    15       14     29   52.6%      0.0%     47.4%   

Total operation fee:     ¥    1,044.25
total investment amount: ¥  100,000.00
final value:              ¥  340,613.63
Total return:                   240.61% 
Avg Yearly return:               13.03%
Skewness:                         -0.78
Kurtosis:                         13.36
Benchmark return:                66.59% 
Benchmark Yearly return:          5.23%

------strategy loop_results indicators------ 
alpha:                            0.087
Beta:                             1.001
Sharp ratio:                      0.751
Info ratio:                       0.020
250 day volatility:               0.140
Max drawdown:                    23.53% 
    peak / valley:        2015-12-31 / 2016-01-28
    recovered on:         2017-08-28

===========END OF REPORT=============

png

創建一個自定義策略

使用qteasy不僅可以使用內置策略,也可以創建自定義策略。下面有一個簡單的例子,定義了一個簡單的輪動交易策略