在匯率波動日益頻繁、企業與機構對風險管理要求不斷提高的背景下,外匯交易策略已成為資產配置與對沖操作的重要工具。其中,CTA 策略在外匯交易中具有非常重要的實際應用價值,在風險控制、趨勢捕捉、資金效率與交易實用性之間取得了良好平衡。
在投入實盤交易之前,利用市場的歷史數據對量化中高頻策略進行測試和評估是確保交易策略有效性和可行性的重要步驟。DolphinDB 憑借其高性能計算引擎和強大的數據處理能力,成為交易策略回測的理想選擇。本文將通過一個結合中高頻 CTA 邏輯與實時風控的外匯遠期交易策略案例,展示 DolphinDB 回測引擎的使用,以及其在實際應用中的應用優勢。
1. 背景介紹
本文將詳細展示如何結合多個技術分析指標,如 RSI (相對強弱指數),Bollinger Bands(布林帶),構建一個涵蓋買賣開倉邏輯的外匯 CTA 策略,并通過算法訂單實現具備實時止盈止損功能的風險控制機制。
在介紹該策略的實現過程之前,為幫助讀者更清晰地理解背景與應用場景,本章將簡要介紹外匯交易的基本特點、CTA 策略的核心思路,以及 DolphinDB 提供的回測解決方案。
1.1 外匯交易背景介紹
中國的外匯市場以銀行間外匯市場為核心,由中國外匯交易中心(CFETS)組織交易。交易品種主要包括即期外匯、遠期外匯、外匯掉期、期權等。不同于國際市場,中國尚未開放外匯期貨交易,遠期合約成為企業管理匯率風險的主要工具之一。外匯遠期合約(Forward FX)是指買賣雙方約定在未來某一時間以固定匯率交換一定數量貨幣的合約。它廣泛用于鎖定結匯成本、規避匯率波動。相比現貨交易,遠期合約具有非標準化、定制化、無交易所掛牌等特點。其價格通常基于即期匯率與利率平價理論計算而來,受利差、期限結構、市場預期等因素影響。盡管遠期交易以對沖為主,但在利差套利、匯率擇時、資金流動管理等領域也廣泛應用于策略化操作。通過歷史數據進行回測,可以系統評估策略的收益風險特征、參數穩定性以及對匯率變動的敏感性。
1.2 CTA 策略背景介紹
CTA 投資策略主要通過技術分析和系統化交易方法,對期貨、外匯、利率等衍生品進行交易。隨著全球金融市場的發展,CTA 策略已被廣泛應用于外匯市場,成為機構和量化交易者應對匯率波動、實現趨勢跟蹤與風險控制的重要工具之一。CTA 策略通常分為主觀 CTA 和量化 CTA 兩大類型。前者依賴交易員對宏觀經濟、政策事件等基本面的判斷進行主觀決策;而后者則基于量化模型,按照預設規則自動生成買賣信號并執行交易。尤其在量化 CTA 策略中,交易決策往往依托一系列技術指標,RSI、Bollinger Bands、平均真實范圍(ATR)等,來識別市場趨勢和交易機會。同時, CTA 策略高度重視風險管理。通過設置止盈止損、限制頭寸規模、控制最大浮虧等方式,量化 CTA 策略在追求趨勢收益的同時,也注重保護資金安全,提高策略在不同市場環境下的穩健性。
1.3 DolphinDB 中高頻回測解決方案概述
中高頻量化交易策略回測平臺的實現主要包括三個重要環節:行情數據按順序回放,委托訂單撮合,以及策略開發與策略回測績效評估。而在實現中高頻策略回測時往往面臨以下幾個挑戰:
首先,海量中高頻交易數據對回測引擎的查詢與計算性能提出了極高的要求。
其次,為確保策略評估和優化的有效性,回測過程中應盡可能模擬實際的交易過程,例如考慮訂單能否成交、成交價格、成交量以及市場沖擊等因素。
此外,回測引擎還應具有靈活的架構,能夠支持多種交易策略和技術指標的實現,并且易于擴展,以適應不同的市場和交易需求。
針對上述挑戰,DolphinDB 基于其高性能的分布式存儲和計算架構,為用戶提供了一個易擴展、性能優的中高頻量化交易策略回測解決方案。該方案實現了庫內行情回放、模擬撮合引擎和事件型中高頻回測引擎三大核心組件,支持通過 DLang、Python 或 C++語言完成中高頻策略的研發和測試。具體來說,該方案涵蓋以下三個模塊:
- 回放功能:支持將一個或多個不同結構的分布式表中的數據嚴格按照時間或者按指定多列排序順序回放到流表中,因此可以方便地解決因子計算和量化策略研發中研發和生產一體化的問題。
- 模擬撮合引擎插件:支持滬深交易所 Level-2 逐筆行情和快照行情,實現與交易所一致的?“價格優先,時間優先”?的高精度的撮合、基于多種行情數據的撮合模式、豐富的可用于模擬實盤環境的撮合配置。
- 回測插件:用戶可以在其中自定義指標,支持基于逐筆、快照、分鐘和日頻行情進行策略回測,獲取回測的收益、持倉、交易明細等信息。其中基于逐筆和快照行情進行高精度策略回測,用戶可以實現仿真和回測一體化的策略驗證。
值得一提的是,這三個模塊化解決方案與外部解決方案兼容性良好。即使用戶已經實現了某個環節的解決方案,DolphinDB 提供的解決方案也可以與其融合成一個完整的回測方案。
2. 基于 DolphinDB 的外匯 CTA 策略:中低頻交易與高頻風控融合實踐
在大部分的 CTA 策略中,高精度的訂單模擬撮合和實時風險控制是確保策略成功和有效執行的關鍵因素。策略的主要邏輯可能是基于分鐘等聚合的 K 線行情,訂單的成交依賴高精度的訂單撮合引擎或者策略止盈止損依賴實時的 tick 級高頻行情。DolphinDB 可以實現回測引擎以實時的 tick 行情作為回測引擎行情輸入,同時按配置的指定頻率觸發 onBar 行情回調方式回測。本案例基于 tick 級高頻行情數據,通過配置項 callbackForSnapshot 實時合成 1 小時 K 線,以實現一個基于布林帶突破與 RSI 指標的外匯 CTA 趨勢策略。具體的策略邏輯如下:
- 做多開倉:當前 RSI 大于 70 且布林帶正在上移并打破上軌
- 做空開倉:當前 RSI 小于 30 且布林帶正在下移并打破下軌
- 如果存在多頭或空頭委托訂單,在算法訂單中根據 tick 行情判斷是否撤單、止盈止損
2.1 編寫自定義策略
首先,基于 tick 行情數據定義重要的技術分析指標:RSI 和?Bollinger Bands。RSI 用來評估市場的超買或超賣狀態,Bollinger Bands 則用來判斷價格波動是否突破區間。為了滿足使用中高頻行情數據計算類似量價因子的需求,DolphinDB 回測引擎采用了響應式狀態引擎。這一引擎能夠實現流批統一計算,并有效處理帶有狀態的高頻因子,具體也可以參考響應式狀態引擎用戶手冊定義相應的指標。以下是定義技術指標 RSI 和 Bollinger Bands 的代碼示例:
@state
defg RSI(close, timePeriod=14) {deltaClose = deltas(close)up = iif(nullCompare(>, deltaClose, 0), deltaClose, 0)down = iif(nullCompare(>, deltaClose, 0), 0, -deltaClose)upAvg = wilder(up, timePeriod)downAvg = wilder(down, timePeriod)return 100.0 * upAvg / (upAvg + downAvg)
}
@state
def stddev(close, timePeriod=5, nbdev=1){return sqrt(var(close, timePeriod, nbdev)) * nbdev
}
@state
def bBands_(close, timePeriod=5, nbdevUp=2, nbdevDn=2, maType=0){mid =sma(close, timePeriod)md = stddev(close, timePeriod, 1)return ((mid + nbdevUp * md), mid, (mid - nbdevDn * md))
}
中高頻回測中,策略通常是事件驅動的,而一個策略邏輯通常需要涉及多種事件,比如新的行情到來、新的訂單成交等等。DolphinDB 回測引擎采用事件驅動機制,提供了全面的事件函數如策略初始化函數、盤前回調函數、行情回調函數、每日盤后回調函數等,用戶可以在相應的回調函數中編寫策略邏輯實現相應的策略。此外,自定義回調函數支持 JIT 技術,可以有效提升策略執行效率。后續本案例將會展示不同的事件函數是如何實現的。
在策略初始化函數中,首先訂閱指標 RSI 、Bollinger Bands。subscribeIndicator 接口獲取回測引擎名、需要計算的數據類型、需要計算的指標字典(key 為指標名,用于之后訪問;value 為指標計算的元代碼),之后計算結果將傳入?onBar
?策略回調函數。
def initialize(mutable context){print("initialize")d=dict(STRING,ANY)d["rsi"]=<ta::rsi(lastPrice, 11)>d["bhigh"]=<ta::bBands(lastPrice, 20, 2, 2, 0)[0]>d["bmid"]=<ta::bBands(lastPrice, 20, 2, 2, 0)[1]>d["blow"]=<ta::bBands(lastPrice, 20, 2, 2, 0)[2]>Backtest::subscribeIndicator(context["engine"], "snapshot_kline", d)}
在 K 線回調函數?onBar
?中,系統通過獲取訂閱的 RSI 和 布林帶 指標生成開倉信號。并通過算法訂單來實現止盈止損。onBar
?函數的?msg?參數,為回測引擎傳來的合成的 K 線行情,以及在?initialize
?中定義的指標計算結果。msg?是一個字典,字典的 key 為期貨標的名,而 value 為這支期貨標的對應的行情信息以及指標計算結果。以下代碼展示了買入開倉與賣出開倉的判斷邏輯:
def onBar(mutable context, msg,indicator){istock=msg.keys()[0]msg_=msg[istock]askPrice0=msg_.offerPrice[0]bidPrice0=msg_.bidPrice[0]spread=askPrice0-bidPrice0indicator_=indicator[istock]blow=indicator_.blowbhigh=indicator_.bhighif(spread>context["maxSpread"]){return }rsi_=indicator_.rsiif(isNull(rsi_)){return}close=msg_.lastPricebmid=indicator_.bmidopen=msg_.openistock=msg_.symbolposition=Backtest::getPosition(context["engine"],istock)longpos = position.longPositionshortpos = position.shortPositionif(rsi_>70. and askPrice0>bhigh and close>open and longpos <1){Backtest::submitOrder(context["engine"], (istock,msg_.symbolSource ,context["barTime"],5, round(askPrice0,5), askPrice0 -context["sl"]+context['Slippage'] , askPrice0+ context["tp"]+context['Slippage'], 2, 1,context['Slippage'], 0, context["barTime"]+36000000),"openBuy", 5)return}if(rsi_<30. and bidPrice0<blow and close<open and shortpos <1){Backtest::submitOrder(context["engine"], (istock,msg_.symbolSource,context["barTime"],5, round(bidPrice0,5), bidPrice0+context["sl"]-context['Slippage'], bidPrice0 - context["tp"]-context['Slippage'], 2, 2, context['Slippage'] , 0, context["barTime"]+36000000),"openSell", 5)return}
}
這里的?Backtest::submitOrder
?是回測引擎提供的下單接口,回測引擎內置了實時止盈止損的算法訂單,配置項 enableAlgoOrder 設置為 true 時,可以開啟算法訂單:
Backtest::submitOrder(engine, orderMsg, label="", orderType = 5)
orderMsg 為元組類型,包含的成員變量分別是標的代碼、交易所代碼、時間、訂單類型、委托訂單價格、止損價、止盈價、委托訂單數量、買賣方向、滑點、委托訂單有效性,以及委托訂單到期時間。算法訂單的類型 orderType 的取值包括限價止盈訂單(1),市價止盈訂單(2),限價止損訂單(3),市價止損訂單(4),限價止盈止損訂單(5),和市價止盈止損訂單(6)。
2.2 根據策略設置相應的配置參數
回測的開始與結束日期、初始資金、手續費和印花稅、行情類型、訂單延時等均可以通過參數進行配置。這些參數允許用戶靈活地調整回測條件,以模擬不同的市場環境和交易策略的效果。此外策略邏輯上下文 context 也可以通過參數設置策略中的全局變量,此案例中我們在 context 中設置了策略中需要的滑點、點差以及止盈止損價。具體的初始參數配置代碼示例如下:
startDate=2018.12.31
endDate=2019.12.31
userConfig=dict(STRING,ANY)
userConfig["startDate"]=startDate
userConfig["endDate"]=endDate
userConfig["strategyGroup"]="universal"
userConfig["frequency"]= 3600000
userConfig["cash"]= 10000000
userConfig["dataType"]=1
userConfig["depth"] = 1;
userConfig["enableAlgoOrder"]= true
userConfig["latency"]= 1
userConfig["callbackForSnapshot"]=2
userConfig["matchingMode"]=3
Context=dict(STRING,ANY)
Context["opens"]=false
Context["Slippage"]=0.00002
Context["tp"]=0.01
Context["sl"]=0.001
Context["orderId"]=0
Context["maxSpread"]=2.
userConfig["context"]=Context
我們通過配置項 callbackForSnapshot 和 frequency,按指定頻率觸發?onBar
?行情回調,從而驅動回測策略執行。以下是對這兩個配置項的具體說明:
配置項 | 配置項說明 |
---|---|
callbackForSnapshot = 0 | 表示 tick 行情:tick 行情觸發 onSnapshot 行情回調 |
callbackForSnapshot = 1,frequency > 0 | 表示 tick 行情:tick 行情觸發 onSnapshot 行情回調;tick 行情按指定 frequency 頻率合成的 K 線行情觸發 onBar 行情回調 |
callbackForSnapshot = 2,frequency > 0 | 表示 tick 行情:tick 行情按指定 frequency 頻率合成的 K 線行情觸發 onBar 行情回調 |
2.3 創建回測引擎
設置引擎名稱、引擎配置項、相應的回調函數、合約基本信息表等相應參數之后,通過接口?createBacktester
?創建模擬撮合引擎實例。其中,接口?createBacktester
?的第四個參數為表示是否開啟 JIT 優化。默認值為 false,表示不開啟,若需要開啟 JIT 優化,只需要設置此參數為 true 即可。
callbacks=dict(STRING,ANY)
callbacks["initialize"]=initialize
callbacks["beforeTrading"]=beforeTrading
callbacks["onBar"]=onBar
callbacks["onOrder"]=onOrder
callbacks["onTrade"]=onTrade
callbacks["afterTrading"]=afterTrading
callbacks["finalize"]=finalize
strategyName="ftxdemoStrategydemo333"
try{Backtest::dropBacktestEngine(strategyName)}catch(ex){print ex}
engine = Backtest::createBacktester(strategyName, userConfig, callbacks,false,basicInfo)
2.4 執行回測引擎
通過?Backtest::createBacktester
?創建回測引擎之后,可以通過以下方式執行回測。backtestdata_ 為相應的分鐘頻率行情數據,行情數據字段和類型說明參考?回測插件的接口文檔。
Backtest::appendQuotationMsg(engine, backtestdata_ )
2.5 獲取回測結果
回測運行結束之后,可以通過相應的接口獲取每日持倉、每日權益、收益概述、成交明細和策略中用戶自定義的邏輯上下文。回測插件提供的完整回測結果接口可以參閱?回測插件的接口文檔。下圖為本例獲得的交易明細結果:
3. 性能測試
為了更直觀地展示 DolphinDB 高頻回測引擎在實際場景下的執行性能,我們選取了一只外匯遠期合約的一年歷史數據作為測試樣本。在單線程、非 JIT 模式下運行該策略示例,共處理了 29,317,091 條行情數據,生成 168 筆訂單,整體回測耗時約為 8.2 秒。
4. 總結
在量化回測中,全面采用 tick 數據會帶來較高的計算成本,而純粹依賴中低頻策略又容易忽略實盤中的滑點影響與風控響應延遲問題。為兼顧回測性能與交易精度,本文展示了一種將中低頻決策邏輯與高頻風控機制相結合的策略架構:策略核心邏輯基于分鐘或小時級別的 K 線進行信號判斷與下單操作,關鍵的止盈止損則通過 tick 行情回調實時監控并觸發,從而更真實地還原實盤交易過程中的風控行為。展現了 DolphinDB 回測引擎優異的性能、豐富的策略觸發機制以及全面的回測結果信息。
5. 附錄
外匯 CTA 策略 demo 以及所需要的數據
- FXDemo.dos
- backtestdata_.zip