交易知識就在—— ALPHA ZONE-HOM E ,由自營交易室機構交易員主導,理論結合實踐,助力金融知識變現!
回測是將交易策略構想應用於歷史數據,以確定過去其表現的研究過程。然而,回測器不能保證該策略的未來表現。但是,它們是策略研究過程的重要組成部分,以在將策略投入生產之前將其過濾掉。
在本文中,將概述使用Python編寫的面向對象的基礎回測器。這個早期的系統將主要是“教學輔助工具”,用於演示回測器的不同組件。隨著文章的逐漸深入,將探索其更複雜的功能。
回測概述
設計強大的回測器的過程非常困難。有效地模擬影響算法交易系統性能的所有組件是非常具有挑戰性的事情。不良的數據粒度,經紀商發送訂單的不透明性,訂單等待時間以及無數其他因素共同導致策略的“真實”性能與回測的性能不同。
在開發回測器時,很容易想不斷“從頭開始重寫”,因為發現更多因素對於評估性能至關重要。在開發過程中必須在某個時間點做出判斷,即係統已經捕獲了足夠的因素,沒有回測器可以完成這件事。
考慮到這些問題,此處介紹的回測器將有些簡化。隨著我們探索更多問題(投資組合優化,風險管理,交易成本處理),回測器將變得更加強大。
回測系統的類型
通常有兩種類型的回測器將是您感興趣的。第一種是基於研究的,主要用於早期階段,在此階段將測試許多策略,以選擇經過嚴格評估的策略。這些研究回測器通常用Python,R或MatLab編寫,因為在此階段,開發速度比執行速度更為重要。
第二種回測器是基於事件的。也就是說,它在類似於交易執行系統本身的執行循環中執行回測過程。它將對市場數據和訂單執行過程建模,以便對策略進行更嚴格的評估。
後者的系統通常是用高性能語言(例如C ++或Java)編寫的,在這些語言中,執行速度至關重要。對於使用頻率較低的策略(儘管仍在盤中),使用Python綽綽有餘(在此文中)。
Python中的面向對象研究回測器
現在將討論基於對象和研究的回測環境的設計和實現。出於以下原因,面向對像被選作為軟件設計範例:
· 可以預先指定使用每個組件的接口,而隨著項目的進行,可以修改(或替換)每個組件的內部
· 通過預先指定接口,可以有效地測試每個組件的行為(通過單元測試)
· 擴展系統時,可以通過組合在其他組件之上構造新組件
在此階段,回測器的設計易於實現,並具有一定程度的靈活性,但要以犧牲市場準確性為代價。該回測器將只能處理應用於單個工具的策略。稍後,回測器將進行修改以處理各種儀器。對於初始回測器,需要以下組件:
缺少了什麼?
可以看出,該回測器不包含投資組合/風險管理,執行處理(即無限制訂單)的任何參考,也不會提供交易成本的複雜建模。在現階段這不是什麼大問題。它使我們能夠熟悉創建面向對象的反向測試器和Pandas / NumPy庫的過程。隨著時間推移,它將得到改善。
現在,我們將概述每個對象的實施過程:
戰略
在此階段,策略對象必須非常通用,因為它將處理預測,均值回歸,動量和波動率策略。這裡考慮的策略將始終基於時間序列,即“價格驅動”。此回測器的早期要求是派生的策略接受條形圖列表(OHLCV)作為輸入,而不是報價(逐筆交易價格)或訂單簿數據。因此,此處考慮的最細粒度為1秒柱。
策略類也將始終產生信號建議。這意味著它將建議做多/做空或持有頭寸。這種靈活性將使我們能夠創建多個策略“顧問”,以提供一組信號,更高級的投資組合類別可以接受這些信號,以確定所輸入的實際頭寸。
接口將通過抽象基類方法來實施。抽象基類是無法實例化的對象,因此只能創建派生類。在名為backtest.py的文件中提供了Python代碼。策略類要求任何子類別都可以實現該generate_signals方法。
為了防止直接實例化策略類(因為它是抽象的!),必須使用abc模塊中ABCMeta的和abstractmethod對象。我們設置該類的一個屬性,該屬性稱為metaclass,等同於ABCMeta,用abstractmethod嵌入generate_signals方法之中。
儘管上面的程序很簡單,但是為每種特定的策略繼承此類時,它將變得更加複雜。最終,在此設置中,策略類的目標是為要發送到投資組合的每種工具提供多頭/空頭/持有信號的列表。
投資組合
投資組合類是大多數交易邏輯所在的位置。對於該研究回測器,投資組合負責確定頭寸規模,風險分析,交易成本管理和執行處理(即開市價,平倉價定單)。在稍後的階段,這些任務將分解為單獨的組件。現在,他們將分為同一類。
此類充分利用了pandas,並提供了一個很好的示例(庫可以在其中節省大量時間,尤其是在“樣板”數據處理方面)。順便說一句,pandas和NumPy的主要技巧是避免使用for d in ...語法迭代任何數據集。這是因為NumPy(作為pandas的基礎)通過矢量化操作優化了循環。因此,使用pandas時,您將看到很少(如果有的話)直接迭代。
投資組合類的目標是最終產生一系列交易和一個資產曲線,然後由績效類進行分析。為了實現這一點,必須為它提供來自策略對象的交易建議列表。在以後,這將成為一組策略對象。
投資組合類將需要被告知如何將資金用於特定的一組交易信號,如何處理交易成本以及將使用哪種形式的訂單。策略對像是基於數據條操作的,因此必須對執行訂單時獲得的價格做出假設。
由於任何數據條的高/低價格都是先驗未知的,因此只能使用開盤價和收盤價進行交易。實際上,無法保證使用市場定單時將以這些特定價格之一執行定單,因此充其量只能是近似值。
除了關於已執行訂單的假設外,該回測器還將忽略保證金/經紀約束,並假設可以在沒有任何流動性約束的情況下,在任何工具中自由做多或做空。這顯然是一個非常不現實的假設,但是以後可以放寬條件。
以下繼續backtest.py:
在這一階段,已經引入了策略和投資組合抽象基類。我們現在可以完成一些具體派生的類的實施,以便產生一個可行的“玩具策略”。
我們將首先生成一個名為RandomForecastStrategy的策略子類,其唯一任務是產生隨機選擇的長/短信號!儘管這顯然是一種荒謬的交易策略,但它將通過演示面向對象的回測框架來滿足我們的需求。因此,我們將撰寫一個名為random_forecast.py的新文件,其中的隨機預測器陳列如下:
現在我們有了一個“具體”的預測系統,我們必須實施一個投資組合對象。該對象將包含大多數回測代碼。它旨在創建兩個單獨的數據框架,第一個是positions框架,用於存儲在任何特定柱上持有的每種工具的數量。第二個,portfolio實際上包含每條上所有持倉的市場價格,以及現金的總計(假設有初始資本)。這最終提供了一條評估戰略績效的資產曲線。
投資組合對象雖然在界面上非常靈活,但是在如何處理交易成本,市場訂單等方面需要有特定的選擇。在這個基本示例中,我認為可以輕鬆地做多/做空而沒有受到任何限制。保證金,直接以柱線的開盤價買賣,交易成本為零(包括滑點,費用和市場影響),並指定了每筆交易可直接購買的庫存數量。
接下來仍然是random_forecast.py:
這為我們提供了基於該系統生成資產曲線所需的一切。最後一步是將所有main功能與一個函數綁定在一起:
程序的輸出如下。根據您選擇的日期範圍和使用的隨機種子,您的輸出將與下面的輸出不同:
在這種情況下,該策略虧損了,鑑於預測者的隨機性,這並不奇怪!下一步是創建一個Performance對象,該對象接受Portfolio,並提供性能指標列表,基於這些指標可以決定是否過濾策略。
我們還可以改進Portfolio對象,以更現實地處理交易成本(例如,盈透證券佣金和滑點)。我們還可以直接將預測引擎包含到策略對像中,這將(希望能)產生更好的結果。在以下文章中,我們將更深入地探討這些概念。
本文翻譯整理自quantstart,侵刪。