股票回測(cè)引擎
歡迎使用MindGo量化交易平臺(tái),本文檔詳細(xì)介紹了MindGo平臺(tái)的股票回測(cè)引擎,內(nèi)容較多,您可通過(guò)Ctrl+F進(jìn)行關(guān)鍵字搜索。
如果您在使用過(guò)程中遇到幫助中無(wú)法解答的問(wèn)題,您可以:
編寫(xiě)股票交易策略step 1.導(dǎo)航欄中,依次點(diǎn)擊"我的策略"—"策略創(chuàng)作"—"策略研究" step 2.新建"股票期貨"策略,點(diǎn)擊進(jìn)入"策略編輯"頁(yè)面,如下圖 step 3.左側(cè)編譯環(huán)境內(nèi)使用python 3.5 實(shí)現(xiàn)策略邏輯 交易股票:貴州茅臺(tái)
買入:5日均線上穿20日均線
賣出:5日均線下穿20日均線
step 4.右側(cè)選擇回測(cè)時(shí)間區(qū)間,并進(jìn)行回測(cè)
 策略源碼:
#初始化賬戶
def init(context):
g.index='600519.SH'
def handle_bar(context,bar_dict):
close = history(g.index, ['close'], 20, '1d', False, fq = 'pre', is_panel=0)
MA5 = close['close'].values[-5:].mean()
#計(jì)算二十日均線價(jià)格
MA20 = close['close'].values.mean()
#如果五日均線大于二十日均線
if MA5 > MA20:
#使用所有現(xiàn)金買入證券
order_target_percent(g.index,1)
#記錄本次買入
log.info("全倉(cāng)買入{0}".format(g.index))
#如果五日均線小于二十日均線
if MA5 < MA20 :
#賣出所有證券
order_target_percent(g.index,0)
#記錄本次賣出
log.info("全倉(cāng)賣出{0}".format(g.index))
回測(cè)環(huán)境回測(cè)引擎運(yùn)行在Python3.5之上, 請(qǐng)您使用Python3.5來(lái)實(shí)現(xiàn)策略邏輯 我們支持所有的Python標(biāo)準(zhǔn)庫(kù)和部分常用第三方庫(kù), 具體請(qǐng)看: Python庫(kù) 同時(shí),我們也支持自定義Python庫(kù),只需將您的.py文件存放于“我的研究”根目錄, 即可在回測(cè)中直接調(diào)用, 具體說(shuō)明請(qǐng)參見(jiàn)常見(jiàn)問(wèn)題-如何調(diào)用自定義Python庫(kù)? 支持代碼調(diào)試功能,具體請(qǐng)看:代碼調(diào)試
編譯運(yùn)行
1.您的策略必須在init()和handle_bar()函數(shù)框架下實(shí)現(xiàn): 2.完成策略編寫(xiě)后,選定回測(cè)開(kāi)始日期和結(jié)束日期,選擇初始資金、運(yùn)行頻率(每日或每分鐘)等參數(shù),點(diǎn)擊"編譯運(yùn)行";
 3.回測(cè)引擎根據(jù)您選擇的運(yùn)行頻率調(diào)用handle_bar函數(shù),也就是執(zhí)行該函數(shù)下的代碼?;販y(cè)引擎會(huì)實(shí)時(shí)顯示策略當(dāng)前時(shí)間的數(shù)據(jù),如收益、風(fēng)險(xiǎn)指標(biāo)、持倉(cāng)等信息;
 4.回測(cè)引擎會(huì)根據(jù)您所使用的下單方式進(jìn)行下單,并根據(jù)后續(xù)實(shí)際成交情況進(jìn)行訂單處理; 5.您可以在任何時(shí)候調(diào)用log.info函數(shù)來(lái)打印需要輸出的日志;通過(guò)record函數(shù)輸出自定義圖形。 
#初始化賬戶
def init(context):
g.index='600519.SH'
def handle_bar(context,bar_dict):
close = history(g.index, ['close'], 20, '1d', False, fq = 'pre', is_panel=0)
MA5 = close['close'].values[-5:].mean()
#計(jì)算二十日均線價(jià)格
MA20 = close['close'].values.mean()
#設(shè)置交易信號(hào)
trade_signal=0
#如果五日均線大于二十日均線
if MA5 > MA20:
#使用所有現(xiàn)金買入證券
order_target_percent(g.index,1)
#記錄本次買入
log.info("全倉(cāng)買入{0}".format(g.index))
#記錄買入信號(hào)
trade_signal=1
#如果五日均線小于二十日均線
if MA5 < MA20 :
#賣出所有證券
order_target_percent(g.index,0)
#記錄本次賣出
log.info("全倉(cāng)賣出{0}".format(g.index))
#記錄賣出信號(hào)
trade_signal=-1
log.info(trade_signal)
record(trade_signal=trade_signal)
策略回測(cè)如果策略能成功完成編譯運(yùn)行,則說(shuō)明策略代碼在指定歷史區(qū)間是可運(yùn)行的。 一般而言,策略回測(cè)是將可運(yùn)行的策略代碼進(jìn)行歷史區(qū)間回測(cè),并獲取策略回測(cè)詳情報(bào)告:交易明細(xì)、歷史持倉(cāng)、收益&風(fēng)險(xiǎn)指標(biāo)分析、組合歸因等。 步驟1.將可運(yùn)行的策略代碼,點(diǎn)擊"開(kāi)始回測(cè)"
 步驟2.在策略詳情頁(yè)面,查看收益概況、交易明細(xì)、歷史持倉(cāng)及相關(guān)分析結(jié)果,如下圖:

數(shù)據(jù)MindGo提供海量?jī)?yōu)質(zhì)的金融數(shù)據(jù),以便您能實(shí)現(xiàn)策略邏輯 股票數(shù)據(jù)、指數(shù)數(shù)據(jù)、基金數(shù)據(jù)、行情數(shù)據(jù)、財(cái)務(wù)數(shù)據(jù)、因子數(shù)據(jù)、行業(yè)數(shù)據(jù)、概念數(shù)據(jù)、商品期貨數(shù)據(jù)、股指期貨數(shù)據(jù)、外匯數(shù)據(jù)等等 數(shù)據(jù)提取——詳見(jiàn)股票API文檔 數(shù)據(jù)詳情查看——詳見(jiàn)數(shù)據(jù)文檔
運(yùn)行頻率在"開(kāi)始回測(cè)"左側(cè)選擇運(yùn)行頻率參數(shù),參數(shù)分"每日"和"分鐘"兩種。 選擇"每日",則系統(tǒng)按"日回測(cè)"進(jìn)行回測(cè),即每個(gè)交易日09:30運(yùn)行一次 選擇"分鐘",則系統(tǒng)按"分鐘回測(cè)"進(jìn)行回測(cè),即每個(gè)交易日內(nèi)每分鐘都會(huì)運(yùn)行一次
運(yùn)行時(shí)間
1.開(kāi)盤(pán)前(9:00)運(yùn)行: before_trading函數(shù) 2.盤(pán)中運(yùn)行: handle_bar函數(shù) >日回測(cè)(9:31:00)運(yùn)行一次 >分鐘回測(cè)(9:31:00-11:30,13:01:00-15:00:00),每分鐘運(yùn)行一次 >tick回測(cè)(9:30:03-11:30,13:00:03-15:00:00),每3秒鐘運(yùn)行一次 3.收盤(pán)后(15:30)運(yùn)行: after_trading函數(shù) 傭金與印花稅
券商傭金默認(rèn)值為萬(wàn)分之二點(diǎn)五,即0.025%,最少5元,雙邊收費(fèi); 印花稅默認(rèn)值為千分之一,即0.1%,賣出時(shí)收費(fèi); 您還可以通過(guò)set_commission來(lái)設(shè)置具體的手續(xù)費(fèi)參數(shù)。
滑點(diǎn)
在實(shí)戰(zhàn)交易中,往往最終成交價(jià)和預(yù)期價(jià)格有一定偏差,因此我們提供兩種滑點(diǎn)模式來(lái)幫助您更好地模擬真實(shí)市場(chǎng)的表現(xiàn): 設(shè)置固定滑點(diǎn),即最終成交價(jià)和委托價(jià)之差為固定值。 設(shè)置可變滑點(diǎn),即最終成交價(jià)和預(yù)期價(jià)格之比為固定百分比。默認(rèn)為可變滑點(diǎn)0.2%,即買入成交價(jià)為委托價(jià)上浮0.1%,賣出成交價(jià)為委托價(jià)下調(diào)0.1%。 默認(rèn)無(wú)滑點(diǎn),不過(guò)您可通過(guò)set_slippage函數(shù)來(lái)設(shè)置回測(cè)具體的滑點(diǎn)參數(shù)。
拆分合并與分紅
當(dāng)股票發(fā)生拆分,合并或者分紅時(shí),股價(jià)會(huì)出現(xiàn)跳空缺口,為了消除這種價(jià)格變化對(duì)回測(cè)結(jié)果的影響,我們會(huì)根據(jù)個(gè)股除權(quán)除息信息對(duì)賬戶中的現(xiàn)金或持股數(shù)量進(jìn)行相應(yīng)的調(diào)整修正,并自動(dòng)更新到您的context信息中。 為了使回測(cè)結(jié)果更加準(zhǔn)確,更加貼近實(shí)盤(pán)場(chǎng)景,我們做了如下處理: 回測(cè)所用價(jià)格數(shù)據(jù)與下單所用價(jià)格數(shù)據(jù)是獨(dú)立的。即在回測(cè)過(guò)程中,您可采用前復(fù)權(quán)/不復(fù)權(quán)或后復(fù)權(quán)價(jià)格來(lái)計(jì)算交易下單信號(hào),回測(cè)引擎均采用真實(shí)價(jià)格(即不復(fù)權(quán)價(jià)格)下單; 回測(cè)引擎會(huì)在除權(quán)除息當(dāng)日,調(diào)用before_trading_start函數(shù)之前,自動(dòng)處理并更新您的賬戶信息。 前復(fù)權(quán)數(shù)據(jù)采用動(dòng)態(tài)復(fù)權(quán)模式,即在回測(cè)過(guò)程中,輪循至某個(gè)股除權(quán)除息日,則按除權(quán)后價(jià)格對(duì)之前的價(jià)格數(shù)據(jù)進(jìn)行調(diào)整。
訂單處理
對(duì)于您在某個(gè)單位時(shí)間下的單,我們會(huì)做如下處理:
1.按天回測(cè)
A.交易價(jià)格: >市價(jià)單:開(kāi)盤(pán)價(jià)+滑點(diǎn)。 >限價(jià)單:委托價(jià)。 B.最大成交量: >默認(rèn)為下單當(dāng)日總成交量的25%,該比例可通過(guò)市場(chǎng)參與度函數(shù)set_volume_limit進(jìn)行調(diào)整。 >若下單量低于最大成交量,則按下單量成交;若下單量大于最大成交量,則按最大成交量成交。 C.撮合方式: >市價(jià)單:開(kāi)盤(pán)下單,一次性撮合,不成交或未成交部分不再撮合。 >限價(jià)單:開(kāi)盤(pán)下單,一次性撮合,不成交或未成交部分不再撮合。
2.分鐘回測(cè)
A.交易價(jià)格: >市價(jià)單:當(dāng)前分鐘起始價(jià)+滑點(diǎn) >限價(jià)單:委托價(jià) B.最大成交量: >默認(rèn)為下單當(dāng)前分鐘總成交量的25%,該比例可通過(guò)市場(chǎng)參與度函數(shù)set_volume_limit進(jìn)行調(diào)整。 >若下單量低于最大成交量,則按下單量成交;若下單量大于最大成交量,則按最大成交量成交。 C.撮合方式: >市價(jià)單:分鐘起始點(diǎn)下單,一次性撮合,不成交或未成交部分即刻取消委托。 >限價(jià)單:分鐘起始點(diǎn)下單,之后每分鐘均按分鐘價(jià)量撮合一次,未成交部分順延至下一分鐘進(jìn)行撮合,直到完全成交或者當(dāng)天收盤(pán)為止。
3.注意: 1.一天結(jié)束后, 所有未完成的訂單會(huì)被取消。
2.每次訂單完成(完全成交)或者取消后,我們會(huì)根據(jù)成交量計(jì)算交易費(fèi)(參見(jiàn)set_commission), 減少您的現(xiàn)金。
風(fēng)險(xiǎn)模型風(fēng)險(xiǎn)模型主要提供證券的風(fēng)險(xiǎn)預(yù)測(cè)與業(yè)績(jī)歸因的作用。在此過(guò)程中,風(fēng)險(xiǎn)模型需要對(duì)股票收益建立因子模型,對(duì)組合過(guò)去歷史的收益來(lái)源進(jìn)行歸因,依據(jù)統(tǒng)計(jì)方法和經(jīng)驗(yàn)對(duì)股票未來(lái)風(fēng)險(xiǎn)形成推斷與預(yù)測(cè)。對(duì)風(fēng)險(xiǎn)的度量要滿足靈活性,準(zhǔn)確性等要求。風(fēng)險(xiǎn)模型使用標(biāo)準(zhǔn)差來(lái)度量風(fēng)險(xiǎn),且統(tǒng)計(jì)特征清晰,隨時(shí)間變化穩(wěn)定。對(duì)風(fēng)險(xiǎn)的預(yù)測(cè)有很多種方式,MindGo風(fēng)險(xiǎn)模型建立在多因子模型的基礎(chǔ)上,認(rèn)為股票收益率與多個(gè)因子之間存在線性的關(guān)系,即:
r=α+βf+μ
其中:r為股票收益率向量,β為因子暴露,μ為特質(zhì)收益,f為因子收益率
當(dāng)股票特質(zhì)收益率與公共因子不相關(guān)時(shí),組合預(yù)期風(fēng)險(xiǎn)可以分解為公共因子解釋的風(fēng)險(xiǎn)及特質(zhì)風(fēng)險(xiǎn):
wΣw′=wβΩβ′w′+wΔw′
其中:w為組合成份股權(quán)重,Ω為因子收益率的協(xié)方差矩陣,Δ為股票的特質(zhì)風(fēng)險(xiǎn)矩陣,我們假設(shè)股票的特質(zhì)風(fēng)險(xiǎn)之間也互不相關(guān),所以Δ是一個(gè)對(duì)角矩陣
組合優(yōu)化器組合優(yōu)化器函數(shù)查詢:OptimizePort,opt.add_constraint
優(yōu)化方式 組合優(yōu)化器優(yōu)化方式暫定為三種:最大化夏普比(MVO)、最大化信息比率、效用最大化(剔除成本影響)優(yōu)化方式后期持續(xù)增加,例如L-B模型、風(fēng)險(xiǎn)平價(jià)模型等常用的資產(chǎn)配置模型。 MVO算法 公式:
 使用最優(yōu)化算法求解,使target最大。R為一系列個(gè)股預(yù)期收益值[r1,r2,...rn],n為股票數(shù)量,為函數(shù)輸入?yún)?shù)項(xiàng),可以選擇使用歷史平均收益作為預(yù)期收益,需輸入股票代碼。W為各個(gè)股票的權(quán)重,為優(yōu)化器所要計(jì)算的未知量[w1,w2,...wn],n為股票數(shù)量?!茷閭€(gè)股協(xié)方差矩陣(nXn),使用個(gè)股歷史漲跌幅計(jì)算,取數(shù)范圍為前120個(gè)周期,例如日頻數(shù)據(jù),則選取前120個(gè)交易日的漲跌幅,如為周頻,則使用日頻數(shù)據(jù)進(jìn)行轉(zhuǎn)換。
最大化信息比率 公式:
 使用最優(yōu)化算法求解,使target最大。R,W,∑定義同1.1.1中描述。Wb為個(gè)股在所選基準(zhǔn)中所占的權(quán)重,為[wb1,wb2,...wbn],n為股票數(shù)量,當(dāng)個(gè)股沒(méi)有在基準(zhǔn)中時(shí),wb為0。基準(zhǔn)可自由選擇,作為函數(shù)輸入項(xiàng),默認(rèn)為中證500。
效用最大化 公式:
 使用最優(yōu)化算法求解,使target最大。R,W,∑定義同1.1中描述。γ 為風(fēng)險(xiǎn)厭惡系數(shù),函數(shù)輸入?yún)?shù)項(xiàng),默認(rèn)為0.5。λ為交易成本,函數(shù)輸入?yún)?shù)項(xiàng),默認(rèn)為0。Wi,t-1 為股票初始權(quán)重,可自定義輸入,也可選擇初始權(quán)重都為0。
約束條件 目前暫定七個(gè)約束條件:換手率、跟蹤誤差、組合風(fēng)險(xiǎn)、個(gè)股權(quán)重、風(fēng)格因子主動(dòng)暴露、行業(yè)因子主動(dòng)暴露、行業(yè)中性。 換手率約束 約束條件: Wi,t 為函數(shù)求解值,個(gè)股優(yōu)化后的權(quán)重;Wi,t-1 為股票初始權(quán)重,可自定義輸入,也可選擇初始權(quán)重都為0。Uplimit為輸入的換手率限制值,不可小于0,最大值為100(默認(rèn)單位%)。
跟蹤誤差 約束條件: W和Wb為組合中的股票和基準(zhǔn)中的股票做并集后的權(quán)重向量。例如組合中有股票A,B,C,基準(zhǔn)包含的股票為A,B,D,則W和Wb兩個(gè)向量都有四個(gè)元素[WA,WB,WC,WD]和[WbA,WbB,WbC,WbD],且WD和WbC 為0。[WA,WB,WC]為組合中股票的權(quán)重,為優(yōu)化器所要求解的未知量[w1,w2,...wn],n為股票數(shù)量?!茷閭€(gè)股協(xié)方差矩陣(nXn),n為組合和基準(zhǔn)股票的并集,算法同1.1.1中描述。基準(zhǔn)可自由選擇,作為函數(shù)輸入項(xiàng),默認(rèn)為中證500。Downlimt和uplimit作為輸入的跟蹤誤差上下限,downlimt不可小于0。
組合風(fēng)險(xiǎn) 約束條件: W為各個(gè)股票的權(quán)重,為優(yōu)化器所要求解的未知量[w1,w2,...wn],n為股票數(shù)量?!茷閭€(gè)股協(xié)方差矩陣(nXn),計(jì)算同1.1中描述。Downlimt和uplimit作為輸入的組合風(fēng)險(xiǎn)上下限,downlimt不可小于0。
個(gè)股權(quán)重 約束條件: 可針對(duì)每個(gè)股票做單獨(dú)的權(quán)重約束,downlimt和uplimt為所對(duì)應(yīng)股票的權(quán)重上下限,可自由輸入。函數(shù)輸入項(xiàng)包含個(gè)股代碼及所要約束的上下限值,輸入的股票數(shù)量0<=w<=n(優(yōu)化目標(biāo)中所輸入的股票總數(shù))。每個(gè)股票需在優(yōu)化目標(biāo)中輸入的股票列表中,否則報(bào)錯(cuò)。為內(nèi)置權(quán)重約束,所有股票的權(quán)重值加起來(lái)等于1。
風(fēng)格因子主動(dòng)暴露度 約束條件: Downlimt和uplimit為自定義輸入的某個(gè)因子的暴露度約束上下限,輸入方式為因子名稱、下限值、上限值。當(dāng)前共有十個(gè)風(fēng)格因子,如需針對(duì)全部因子做限制,則需要輸入十個(gè)相對(duì)應(yīng)的風(fēng)格因子暴露度上下限值。Xstyle 為個(gè)股對(duì)該風(fēng)格因子的暴露度,為[x1 style1,x2style1,...xnstyle1]該數(shù)據(jù)由風(fēng)險(xiǎn)模型模塊計(jì)算得出(目前易源博每日會(huì)更新該數(shù)據(jù))。W為各個(gè)股票的權(quán)重,為優(yōu)化器所要求解的未知量[w1,w2,...wn]。
行業(yè)因子主動(dòng)暴露度 約束條件: Downlimt和uplimit為自定義輸入的某個(gè)行業(yè)因子的暴露度約束上下限,輸入方式為行業(yè)因子名稱、下限值、上限值。當(dāng)前共有29個(gè)行業(yè)因子(中信一級(jí)),如需針對(duì)全部因子做限制,則需要輸入29個(gè)相對(duì)應(yīng)的行業(yè)因子暴露度上下限值。Xindustry 為個(gè)股對(duì)該行業(yè)的暴露度(即該個(gè)股是否屬于該行業(yè),屬于為1,不屬于為0)。W為各個(gè)股票的權(quán)重,為優(yōu)化器所要求解的未知量[w1,w2,...wn]。 Windustry為該行業(yè)在基準(zhǔn)中所占的權(quán)重,不是矩陣,為數(shù)值。
行業(yè)中性 約束條件: Xindustry 為個(gè)股對(duì)該行業(yè)的暴露度(即該個(gè)股是否屬于該行業(yè),屬于為1,不屬于為0)。W為各個(gè)股票的權(quán)重,為優(yōu)化器所要求解的未知量[w1,w2,...wn]。 Windustry為該行業(yè)在基準(zhǔn)中所占的權(quán)重,不是矩陣,為數(shù)值。
組合歸因組合歸因是對(duì)資產(chǎn)組合進(jìn)行分析,將其回報(bào)和風(fēng)險(xiǎn)歸到提前設(shè)定的可能的原因上。目前該功能可實(shí)現(xiàn)對(duì)股票型策略進(jìn)行收益及風(fēng)險(xiǎn)拆分,主要分為Brinson分析和風(fēng)格分析。 我們首先會(huì)對(duì)每一期的持倉(cāng)表進(jìn)行單期歸因,然后將多期的結(jié)果使用進(jìn)行累計(jì)。下面我們會(huì)介紹單期歸因的算法和累計(jì)歸因所得到的結(jié)果。 策略成功回測(cè)后,在回測(cè)詳情頁(yè)面點(diǎn)擊組合歸因功能,如下圖:
 組合歸因詳解一、Brinson組合歸因Brinson 是目前最為人知的歸因方案。除了需要組合持倉(cāng)內(nèi)容之外,還設(shè)定一個(gè)基準(zhǔn)。最初的brinson模型是把收益拆解為行業(yè)選擇收益、個(gè)股選擇收益和交叉收益,我們?cè)趥鹘y(tǒng)模型基礎(chǔ)上做了進(jìn)一步的擴(kuò)展,拆分出配置收益和交易收益。 
對(duì)于各個(gè)拆分收益的計(jì)算如下:
 上述指標(biāo)的計(jì)算只針對(duì)單期的brinson拆解,為了分析策略在一個(gè)周期里的收益歸類,我們使用Carino簡(jiǎn)化因子調(diào)整。
Carino簡(jiǎn)化因子的計(jì)算方式如下:
 Rt,bt為t期策略和基準(zhǔn)的收益率;r,b為區(qū)間內(nèi)策略和基準(zhǔn)收益率。
使用簡(jiǎn)化因子對(duì)多期收益分解進(jìn)行加和:
 At,St,It為t期收益的分解項(xiàng)。
把收益按行業(yè)拆分,查看每個(gè)策略在每個(gè)行業(yè)是否帶來(lái)了主動(dòng)收益。圖中主動(dòng)收益展示的也是多期的收益率,通過(guò)Carino因子進(jìn)行調(diào)整。主動(dòng)風(fēng)險(xiǎn)計(jì)算的是多期主動(dòng)風(fēng)險(xiǎn)的方差,衡量多期主動(dòng)收益的穩(wěn)定性。主動(dòng)權(quán)重是統(tǒng)計(jì)整個(gè)回測(cè)區(qū)間內(nèi)各行業(yè)主動(dòng)權(quán)重的均值。
 二、風(fēng)格分析風(fēng)格因子代碼 | 因子名稱 | 含義 | 備注 |
---|
beta | beta | 上市公司與指數(shù)之間的協(xié)同性 | 個(gè)股的Beta值,指數(shù)收益使用HS300 | bp | 估值 | 記賬價(jià)值和市值的比值 | 市凈率=總市值/歸屬于母公司所有者權(quán)益合計(jì) | earnings_yield | 盈利 | 分析師預(yù)測(cè)與過(guò)去財(cái)年收益統(tǒng)計(jì) |
| growth | 成長(zhǎng) | 由銷售額及盈利統(tǒng)計(jì)。 |
| leverage | 杠桿 | 上市公司的使用杠桿的情況。 |
| liquidity | 流動(dòng)性 | 由交易量和頻率不同而帶來(lái)的收益 |
| momentum | 動(dòng)量 | 能量性指標(biāo),表示相對(duì)強(qiáng)度 | 從過(guò)去某一天開(kāi)始,向過(guò)去再推504天,計(jì)算其每天的超額收益對(duì)數(shù)值,再針對(duì)這504天進(jìn)行加權(quán)平均 | non_linear_size | 非線性市值 | 上市公司的規(guī)模處于中等的程度 |
| size | 市值 | 上市公司的規(guī)模,即該公司是大盤(pán)股的程度 | 對(duì)數(shù)市值 | volatility | 波動(dòng)率 | 對(duì)大盤(pán)偏離的不確定性 |
|
風(fēng)格歸因效果圖:
 其中主動(dòng)收益是多期的收益率,通過(guò)Carino因子進(jìn)行調(diào)整。主動(dòng)風(fēng)險(xiǎn)計(jì)算的是多期主動(dòng)風(fēng)險(xiǎn)的方差,衡量多期主動(dòng)收益的穩(wěn)定性。 策略和基準(zhǔn)風(fēng)格對(duì)比圖:
 衡量回測(cè)期內(nèi)策略整體風(fēng)格和基準(zhǔn)的差異,點(diǎn)擊特定的風(fēng)格因子柱狀圖可查看策略及基準(zhǔn)的歷史風(fēng)格變化,如下圖:
 組合風(fēng)格穩(wěn)定性:

選取策略組合在回測(cè)期間的四個(gè)界面查看其當(dāng)期的主動(dòng)收益、主動(dòng)風(fēng)險(xiǎn)及主動(dòng)暴露度。相關(guān)的計(jì)算公式如下:



收益&風(fēng)險(xiǎn)指標(biāo)—評(píng)定策略的優(yōu)劣策略收益率—Returns
策略年化收益率—Annualized Returns
基準(zhǔn)收益率—Benchmark Returns
基準(zhǔn)年化收益率—Annualized Benchmark Returns
超額收益率—Excess Return
非系統(tǒng)性風(fēng)險(xiǎn)—Alpha
系統(tǒng)風(fēng)險(xiǎn)—Beta
夏普比率—Sharpe
收益波動(dòng)率—Volatility
信息比率—Information Ratio
最大回撤—Max Drawdown
索提諾比率—Sortino
跟蹤誤差—Tracking error
下行波動(dòng)率—Downside Risk
調(diào)試功能 在策略編輯器左側(cè),點(diǎn)擊"行號(hào)",設(shè)置斷點(diǎn)后,點(diǎn)擊"編譯運(yùn)行"啟動(dòng)調(diào)試程序。

 調(diào)試程序簡(jiǎn)介 1.啟動(dòng)調(diào)試程序后,代碼會(huì)自動(dòng)運(yùn)行到第一個(gè)斷點(diǎn)處,如上圖,第一個(gè)斷點(diǎn)是行7,代碼當(dāng)前已運(yùn)行完行7(行8還未運(yùn)行) 2.調(diào)試程序右上角顯示的時(shí)間是回測(cè)系統(tǒng)的運(yùn)行時(shí)間 3.調(diào)試程序上方菜單欄,從左到右共6個(gè)按鈕,分別為:恢復(fù)執(zhí)行代碼(跳至下一個(gè)斷點(diǎn)),執(zhí)行下一步(不運(yùn)行函數(shù)),執(zhí)行下一步(運(yùn)行函數(shù)),跳出此函數(shù),清空console,結(jié)束調(diào)試?yán)^續(xù)編譯 4.調(diào)試程序左側(cè)即為console面板,右側(cè)為監(jiān)控屬性面板 5.1分鐘內(nèi)不使用調(diào)試程序,則自動(dòng)關(guān)閉調(diào)試程序 6.調(diào)試時(shí),程序無(wú)視注釋內(nèi)容
菜單欄按鈕介紹 1.恢復(fù)執(zhí)行代碼(跳至下一個(gè)斷點(diǎn)):直接運(yùn)行至下一個(gè)斷點(diǎn)處 2.執(zhí)行下一步(不運(yùn)行函數(shù)):運(yùn)行下一行代碼,如果下一行代碼調(diào)用函數(shù),則直接運(yùn)行完該函數(shù),接著準(zhǔn)備下一行代碼 3.執(zhí)行下一步(運(yùn)行函數(shù)):運(yùn)行下一行代碼,如果下一行代碼調(diào)用函數(shù),則會(huì)進(jìn)入函數(shù)內(nèi),執(zhí)行函數(shù)內(nèi)第一行代碼 4.跳出此函數(shù):如果當(dāng)前行處于函數(shù)中,則直接運(yùn)行完該函數(shù) 5.清空console:清空左側(cè)console面板的所有內(nèi)容 6.結(jié)束調(diào)試?yán)^續(xù)編譯:關(guān)閉調(diào)試程序,策略繼續(xù)編譯
如何使用console面板? 輸入變量,“Enter”輸出變量值(無(wú)法修改參數(shù)) 變量之間運(yùn)算,“Enter”輸出結(jié)果 判斷變量是否滿足條件,“Enter”輸出結(jié)果 
如何監(jiān)控變量? 調(diào)試程序右側(cè)監(jiān)控屬性,點(diǎn)擊"+添加",輸入變量名,點(diǎn)擊“完成”,即可進(jìn)行監(jiān)控  監(jiān)控面板顯示當(dāng)前監(jiān)控的變量及變量值,繼續(xù)運(yùn)行代碼  運(yùn)行代碼的過(guò)程中,監(jiān)控面板實(shí)時(shí)顯示監(jiān)控變量及變量值,便于您進(jìn)行觀察,不需要print打印函數(shù)來(lái)逐一輸出。 
對(duì)比功能一般而言,量化策略會(huì)存在一個(gè)或多個(gè)參數(shù),在驗(yàn)證策略邏輯的過(guò)程中,寬客們往往會(huì)嘗試用不同的參數(shù)進(jìn)行回測(cè),比如在2018年,對(duì)平安銀行采用雙均線策略,采用不同周期的兩條均線會(huì)使策略收益截然不同哦~ 如何啟動(dòng)回測(cè)對(duì)比?
策略回測(cè)列表中,選取相應(yīng)的回測(cè),點(diǎn)擊左上角的對(duì)比按鈕,即可啟動(dòng)~

 如何使用回測(cè)對(duì)比?
對(duì)比功能,包括:概況、累積收益、回撤、源碼。 其中概況頁(yè)面,詳細(xì)展示了所選回測(cè)的回測(cè)指標(biāo),我們以平安銀行雙均線策略為例,創(chuàng)建3組參數(shù),分別為(5,20),(10,55),(20,60)。
 累積收益頁(yè)面,詳細(xì)展示了所選回測(cè)的收益走勢(shì),可以發(fā)現(xiàn)(20,60)參數(shù)組的累積收益較高,參數(shù)周期越短,交易次數(shù)越多,收益反而越差,可能與18年的暴跌行情相關(guān)。
 回撤頁(yè)面,詳細(xì)展示了所選回測(cè)的回撤情況,可以發(fā)現(xiàn)(20,60)參數(shù)組的回撤較低,參數(shù)周期越短,交易次數(shù)越多,回撤反而越大,可能與18年的暴跌行情相關(guān)。
 源碼頁(yè)面,詳細(xì)展示了所選回測(cè)的源碼,同時(shí)只能選取兩個(gè)回測(cè)進(jìn)行對(duì)比

python庫(kù)MindGo平臺(tái)支持所有Python的基礎(chǔ)庫(kù)(https://docs./3.5/library/index.html),并支持目前流行的第三方庫(kù),例如NumPy,pandas,Ta-Lib,scikit-learn,TuShare等。主要模塊介紹如下表所示。 為了保障MindGo平臺(tái)的安全,以下的python包和功能已被禁用,如有不便敬請(qǐng)見(jiàn)諒: 包 | 屬性和方法 |
---|
os | __builtins__ | sys | __import__ | six | get_ipython | subprocess | exec | pickle | eval | socket |
| ast |
| IPython |
| ipykernel |
|
【案例】MACD交易策略#導(dǎo)入talib庫(kù)
import talib
#初始化函數(shù)
def init(context):
#輸入股票代碼
g.security = '600519.SH'
#設(shè)置MACD模型參數(shù)
#短周期平滑均線參數(shù)
g.Short = 12
#長(zhǎng)周期平滑均線參數(shù)
g.Long = 26
#DIFF的平滑均線參數(shù)
g.M = 9
#每日運(yùn)行函數(shù)
def handle_bar(context, bar_dict):
#調(diào)用MACD計(jì)算函數(shù),獲取MACD值
macd = get_macd(g.security)
#判斷金叉,且無(wú)持倉(cāng)
if macd[-1]>0 and macd[-2]<0 and context.portfolio.market_value == 0:
#執(zhí)行全倉(cāng)買入
order_value(g.security,context.portfolio.available_cash)
#打印日志
log.info("買入 %s" % (g.security))
#判斷死叉,且有持倉(cāng)
if macd[-2]>0 and macd[-1]<0 and context.portfolio.market_value > 0:
#執(zhí)行清倉(cāng)
order_target(g.security,0)
#打印日志
log.info("賣出 %s" % (g.security))
#MACD計(jì)算函數(shù)
def get_macd(stock):
#獲取數(shù)據(jù)
price = history(stock, ['close'], 500, '1d', True, 'pre', is_panel=1)['close']
#talib庫(kù)調(diào)用MACD計(jì)算方法
DIFF, DEA, MACD = talib.MACD(price.values,
fastperiod = g.Short, slowperiod = g.Long, signalperiod = g.M)
#輸出MACD值
return MACD
【案例】三因子選股模型import pandas as pd
import numpy as np
import datetime
def init(context):
# 設(shè)置最大持股數(shù)
context.max_stocks = 10
#記錄天數(shù),隔20個(gè)交易日調(diào)倉(cāng)
g.day = 0
def handle_bar(context, bar_dict):
if g.day%20 !=0:
return None
g.day = g.day +1
# 每個(gè)調(diào)倉(cāng)日先清倉(cāng)持有的股票
for security in list(context.portfolio.positions.keys()):
order_target(security, 0)
# 首先獲得當(dāng)前日期
time = get_datetime()
date = time.strftime('%Y%m%d')
# 獲得股票池列表
sample = get_index_stocks('000300.SH',date)
# 創(chuàng)建字典用于存儲(chǔ)因子值
df = {'security':[], 1:[], 2:[], 3:[], 'score':[]}
# 因子選擇
for security in sample:
q=query(
profit.roic,# 投資回報(bào)率
valuation.pb,# 市凈率
valuation.ps_ttm,# 市銷率
).filter(
profit.symbol==security
)
# 缺失值填充為0
fdmt = get_fundamentals(q, date=date).fillna(0)
# 判斷是否有數(shù)據(jù)
if (not (fdmt['profit_roic'].empty or
fdmt['valuation_pb'].empty or
fdmt['valuation_ps_ttm'].empty)):
# 計(jì)算并填充因子值
df['security'].append(security)
df[1].append(fdmt['profit_roic'][0])# 因子1:投資回報(bào)率
df[2].append(fdmt['valuation_pb'][0])# 因子2:市凈率
df[3].append(fdmt['valuation_ps_ttm'][0])#因子3:市銷率
for i in range(1, 4):
# 因子極值處理,中位數(shù)去極值法
m = np.mean(df[i])
s = np.std(df[i])
for j in range(len(df[i])):
if df[i][j] <= m-3*s:
df[i][j] = m-3*s
if df[i][j] >= m+3*s:
df[i][j] = m+3*s
m = np.mean(df[i])
s = np.std(df[i])
# 因子無(wú)量綱處理,標(biāo)準(zhǔn)化法
for j in range(len(df[i])):
df[i][j] = (df[i][j]-m)/s
# 計(jì)算綜合因子得分
for i in range(len(df['security'])):
# 等權(quán)重計(jì)算(注意因子方向)
s = (df[1][i]-df[2][i]-df[3][i])
df['score'].append(s)
# 按綜合因子得分由大到小排序
df = pd.DataFrame(df).sort_values(by ='score', ascending=False)
# 等權(quán)重分配資金
cash = context.portfolio.available_cash/context.max_stocks
# 買入新調(diào)倉(cāng)股票
for security in df[:context.max_stocks]['security']:
order_target_value(security, cash)
|