自動交易的興起:交易標準普爾 500 指數的機器

已發表: 2022-03-11

如今,超過 60% 的不同資產(如股票、股指期貨、商品)的交易活動不再由“人類”交易者進行,而是依靠自動化交易。 有一些基於特定算法的專門程序可以在不同市場上自動買賣資產,以實現長期的正回報。

在本文中,我將向您展示如何準確地預測下一筆交易應該如何進行以獲得正收益。 在這個例子中,作為交易的標的資產,我選擇了標準普爾 500 指數,即 500 家市值較大的美國公司的加權平均值。 一個非常簡單的實施策略是在華爾街交易所上午 9:30 開始交易時買入標準普爾 500 指數,並在東部時間下午 4:00 收盤時賣出。 如果指數收盤價高於開盤價,則為正收益,而如果收盤價低於開盤價,則為負收益。 所以問題是:我們如何知道交易時段的收盤價是否會高於開盤價? 機器學習是完成如此復雜任務的強大工具,它可以成為支持我們做出交易決策的有用工具。

機器學習是許多有用的現實生活應用程序的新前沿。 金融交易就是其中之一,並且在該領域中經常使用。 關於機器學習的一個重要概念是我們不需要為每種可能的規則編寫代碼,例如模式識別。 這是因為與機器學習相關的每個模型都從數據本身中學習,然後可以在以後用於預測看不見的新數據。

免責聲明:本文的目的是展示如何訓練機器學習方法,並且在提供的代碼示例中並未解釋每個功能。 本文不打算讓一個人復制和粘貼所有代碼並運行提供的相同測試,因為缺少一些超出本文範圍的細節。 此外,還需要 Python 的基礎知識。 本文的主要目的是展示一個示例,說明機器學習如何有效地預測金融部門的買賣。 然而,用真錢交易意味著擁有許多其他技能,例如資金管理和風險管理。 這篇文章只是“大圖”的一小部分。

構建您的第一個財務數據自動交易程序

那麼,您想創建您的第一個程序來分析財務數據並預測正確的交易嗎? 讓我告訴你怎麼做。 我將使用 Python 進行機器學習代碼,我們將使用來自 Yahoo Finance 服務的歷史數據。 如前所述,在進行預測之前,需要歷史數據來訓練模型。

首先,我們需要安裝:

  • Python,特別是我建議使用 IPython notebook。
  • Yahoo Finance Python 包(確切名稱為yahoo-finance )通過終端命令: pip install yahoo-finance
  • 名為 GraphLab 的機器學習包的免費試用版。 隨意查看該庫的有用文檔。

請注意,GraphLab 只有一部分是開源的,即 SFrame,因此要使用整個庫,我們需要許可證。 學生或參加 Kaggle 比賽的人有 30 天的免費許可證和非商業許可證。 在我看來,GraphLab Create 是一個非常直觀且易於使用的庫,用於分析數據和訓練機器學習模型。

挖掘 Python 代碼

讓我們深入研究一些 Python 代碼,看看如何從 Internet 下載財務數據。 我建議使用 IPython notebook 來測試下面的代碼,因為 IPython 相比傳統的 IDE 有很多優勢,特別是當我們需要將源代碼、執行代碼、表格數據和圖表組合在同一個文檔上時。 有關使用 IPython Notebook 的簡要說明,請查看 IPython Notebook 簡介文章。

因此,讓我們創建一個新的 IPython 筆記本並編寫一些代碼來下載標準普爾 500 指數的歷史價格。 請注意,如果您更喜歡使用其他工具,則可以在首選 IDE 中從一個新的 Python 項目開始。

 import graphlab as gl from __future__ import division from datetime import datetime from yahoo_finance import Share # download historical prices of S&P 500 index today = datetime.strftime(datetime.today(), "%Y-%m-%d") stock = Share('^GSPC') # ^GSPC is the Yahoo finance symbol to refer S&P 500 index # we gather historical quotes from 2001-01-01 up to today hist_quotes = stock.get_historical('2001-01-01', today) # here is how a row looks like hist_quotes[0] {'Adj_Close': '2091.580078', 'Close': '2091.580078', 'Date': '2016-04-22', 'High': '2094.320068', 'Low': '2081.199951', 'Open': '2091.48999', 'Symbol': '%5eGSPC', 'Volume': '3790580000'}

這裡, hist_quotes是一個字典列表,每個字典對像是一個交易日,具有OpenHighLowCloseAdj_closeVolumeSymbolDate值。 在每個交易日,價格通常會從開盤價Open到收盤價Close變化,並達到最高和最低值HighLow 。 我們需要通讀它並創建每個最相關數據的列表。 此外,數據必須首先按最新值排序,因此我們需要將其反轉:

 l_date = [] l_open = [] l_high = [] l_low = [] l_close = [] l_volume = [] # reverse the list hist_quotes.reverse() for quotes in hist_quotes: l_date.append(quotes['Date']) l_open.append(float(quotes['Open'])) l_high.append(float(quotes['High'])) l_low.append(float(quotes['Low'])) l_close.append(float(quotes['Close'])) l_volume.append(int(quotes['Volume']))

我們可以將所有下載的報價打包到一個SFrame像中,這是一個高度可擴展的基於列的數據框,並且它是經過壓縮的。 優點之一是它也可以大於 RAM 的數量,因為它是磁盤支持的。 您可以查看文檔以了解有關 SFrame 的更多信息。

因此,讓我們存儲並檢查歷史數據:

 qq = gl.SFrame({'datetime' : l_date, 'open' : l_open, 'high' : l_high, 'low' : l_low, 'close' : l_close, 'volume' : l_volume}) # datetime is a string, so convert into datetime object qq['datetime'] = qq['datetime'].apply(lambda x:datetime.strptime(x, '%Y-%m-%d')) # just to check if data is sorted in ascending mode qq.head(3)
關閉約會時間高的低的打開體積
1283.27 2001-01-02 00:00:00 1320.28 1276.05 1320.28 1129400000
1347.56 2001-01-03 00:00:00 1347.76 1274.62 1283.27 1880700000
1333.34 2001-01-04 00:00:00 1350.24 1329.14 1347.56 2131000000

現在我們可以使用SFrame方法save將數據保存到磁盤,如下所示:

 qq.save(“SP500_daily.bin”) # once data is saved, we can use the following instruction to retrieve it qq = gl.SFrame(“SP500_daily.bin/”)

讓我們看看標準普爾 500 指數是什麼樣的

要查看加載的 S&P 500 數據的外觀,我們可以使用以下代碼:

 import matplotlib.pyplot as plt %matplotlib inline # only for those who are using IPython notebook plt.plot(qq['close'])

代碼的輸出如下圖:

標準普爾 500 指數圖表,通常隨著時間的推移而增長,如上述 Python 代碼所示。

訓練一些機器學習模型

添加結果

正如我在本文的介紹部分所述,每個模型的目標是預測收盤價是否會高於開盤價。 因此,在這種情況下,我們可以在購買標的資產時獲得正回報。 因此,我們需要在我們的數據上添加一個outcome列,這將是targetpredicted變量。 這個新列的每一行都將是:

  • +1對於Closing價高於Opening的上漲
  • -1表示Closing價低於Opening下跌日
 # add the outcome variable, 1 if the trading session was positive (close>open), 0 otherwise qq['outcome'] = qq.apply(lambda x: 1 if x['close'] > x['open'] else -1) # we also need to add three new columns 'ho' 'lo' and 'gain' # they will be useful to backtest the model, later qq['ho'] = qq['high'] - qq['open'] # distance between Highest and Opening price qq['lo'] = qq['low'] - qq['open'] # distance between Lowest and Opening price qq['gain'] = qq['close'] - qq['open']

由於我們需要在最後一個交易日之前的幾天進行評估,因此我們需要將數據滯後一天或多天。 對於這種滯後操作,我們需要 GraphLab 包中的另一個對象,稱為TimeSeriesTimeSeries有一個方法shift ,它使數據滯後一定數量的行。

 ts = gl.TimeSeries(qq, index='datetime') # add the outcome variable, 1 if the bar was positive (close>open), 0 otherwise ts['outcome'] = ts.apply(lambda x: 1 if x['close'] > x['open'] else -1) # GENERATE SOME LAGGED TIMESERIES ts_1 = ts.shift(1) # by 1 day ts_2 = ts.shift(2) # by 2 days # ...etc.... # it's an arbitrary decision how many days of lag are needed to create a good forecaster, so # everyone can experiment by his own decision

添加預測變量

預測變量是一組特徵變量,必須選擇這些變量來訓練模型並預測我們的結果。 因此,預測因素的選擇是至關重要的,即使不是最重要的,也是預測者的組成部分。

僅舉幾個例子,要考慮的一個因素可能是今天的收盤價是否高於昨天的收盤價,並且可能會延長前兩天的收盤價等。類似的選擇可以用以下代碼翻譯:

 ts['feat1'] = ts['close'] > ts_1['close'] ts['feat2'] = ts['close'] > ts_2['close']

如上所示,我在我們的數據集 ( ts ) 中添加了兩個新的特徵列, feat1feat2 ,如果比較為真,則為1 ,否則為0

本文旨在給出一個應用於金融領域的機器學習示例。 我更喜歡關注機器學習模型如何與金融數據一起使用,我們不會詳細介紹如何選擇合適的因素來訓練模型。 由於復雜性顯著增加,解釋為什麼相對於其他因素使用某些因素過於詳盡。 我的工作研究是研究選擇因素的許多假設以創建一個好的預測器。 因此,首先,我建議您嘗試許多不同的因素組合,看看它們是否可以提高模型的準確性。

 # add_features is a helper function, which is out of the scope of this article, # and it returns a tuple with: # ts: a timeseries object with, in addition to the already included columns, also lagged columns # as well as some features added to train the model, as shown above with feat1 and feat2 examples # l_features: a list with all features used to train Classifier models # l_lr_features: a list all features used to train Linear Regression models ts, l_features, l_lr_features = add_features(ts) # add the gain column, for trading operations with LONG only positions. # The gain is the difference between Closing price - Opening price ts['gain'] = ts['close'] - ts['open'] ratio = 0.8 # 80% of training set and 20% of testing set training = ts.to_sframe()[0:round(len(ts)*ratio)] testing = ts.to_sframe()[round(len(ts)*ratio):]

訓練決策樹模型

GraphLab Create 有一個非常乾淨的界面來實現機器學習模型。 每個模型都有一個方法create用於將模型與訓練數據集擬合。 典型參數為:

  • training - 它是一個包含特徵列和目標列的訓練集。
  • target - 它是包含目標變量的列的名稱。
  • validation_set - 它是用於監控模型泛化性能的數據集。 在我們的例子中,我們沒有validation_set
  • features - 它是用於訓練模型的特徵的列名稱列表。
  • verbose - 如果為true ,則在訓練期間打印進度信息。

而其他參數是模型本身的典型參數,例如:

  • max_depth - 它是樹的最大深度。

使用以下代碼,我們構建決策樹:

 max_tree_depth = 6 decision_tree = gl.decision_tree_classifier.create(training, validation_set=None, target='outcome', features=l_features, max_depth=max_tree_depth, verbose=False)

測量擬合模型的性能

準確度是評估預測者好壞的重要指標。 它是正確預測的數量除以總數據點的數量。 由於模型擬合了訓練數據,因此使用訓練集評估的準確度優於使用測試集獲得的準確度。

精確度是積極預測中積極的部分。 我們需要精確到接近1的數字,以達到“完美”的勝率。 我們的decision_tree ,作為 GraphLab Create 包中的另一個分類器,有它的方法evaluate來獲得擬合模型的許多重要指標。

Recall量化了分類器預測正例的能力。 召回率可以解釋為隨機選擇的正例被分類器正確識別的概率。 我們需要精確度接近1的數字,以實現“完美”勝率。

以下代碼將顯示擬合模型在訓練集和測試集上的準確性

 decision_tree.evaluate(training)['accuracy'], decision_tree.evaluate(testing)['accuracy'] (0.6077348066298343, 0.577373211963589)

如上所示,帶有測試集的模型的準確率約為 57%,這在某種程度上比拋硬幣(50%)要好。

預測數據

GraphLab Create 具有相同的界面來預測來自不同擬合模型的數據。 在我們的案例中,我們將使用predict方法,它需要一個測試集來預測目標outcome 。 現在,我們可以從測試集中預測數據:

 predictions = decision_tree.predict(testing) # and we add the predictions column in testing set testing['predictions'] = predictions # let's see the first 10 predictions, compared to real values (outcome column) testing[['datetime', 'outcome', 'predictions']].head(10)
約會時間結果預測
2013-04-05 00:00:00 -1 -1
2013-04-08 00:00:00 1 1
2013-04-09 00:00:00 1 1
2013-04-10 00:00:00 1 -1
2013-04-11 00:00:00 1 -1
2013-04-12 00:00:00 -1 -1
2013-04-15 00:00:00 -1 1
2013-04-16 00:00:00 1 1
2013-04-17 00:00:00 -1 -1
2013-04-18 00:00:00 -1 1

假陽性是模型預測為陽性結果而測試集的真實結果為陰性的情況。 反之亦然,假陰性是模型預測負結果的情況,而測試集的實際結果是正的。

我們的交易策略是等待一個積極的預測結果,以Opening買入標準普爾 500 指數,並以Closing價賣出,因此我們希望有最低的誤報率以避免損失。 換句話說,我們希望我們的模型具有最高的準確率。

我們可以看到,在前十個預測值中有兩個假陰性(2013-04-10 和 2013-04-11)和兩個假陽性(2013-04-15 和 2013-04-18)測試集。

通過一個簡單的計算,考慮這十個預測的小集合:

  • 準確度 = 6/10 = 0.6 或 60%
  • 精度 =3/5 = 0.6 或 60%
  • 召回率 = 3/5 = 0.6 或 60%

請注意,通常上面的數字彼此不同,但在這種情況下它們是相同的。

回測模型

我們現在模擬模型如何使用其預測值進行交易。 如果預測結果等於+1 ,則意味著我們預計會有一天。 對於上漲日,我們在交易日開始時買入指數,並在同一天交易日結束時賣出指數。 相反,如果預測結果等於-1 ,我們預計會出現下跌日,因此我們不會在那一天進行交易。

完整每日交易的盈虧 ( pnl ),也稱為回合,在此示例中由下式給出:

  • pnl = Close - Open (每個交易日)

使用下面顯示的代碼,我調用輔助函數plot_equity_chart來創建具有累積收益曲線(權益曲線)的圖表。 無需深入,它只需獲取一系列損益值併計算要繪製的一系列累積總和。

 pnl = testing[testing['predictions'] == 1]['gain'] # the gain column contains (Close - Open) values # I have written a simple helper function to plot the result of all the trades applied to the # testing set and represent the total return expressed by the index basis points # (not expressed in dollars $) plot_equity_chart(pnl,'Decision tree model') 

決策樹模型,通常向上和向右,如上述 Python 代碼所示。

 Mean of PnL is 1.843504 Sharpe is 1.972835 Round turns 511

這裡,夏普是年度夏普比率,是交易模型好壞的重要指標。

夏普比率等於 252 的平方根,然後乘以 pnl 的平均值除以 pnl 的標準差。

考慮到每天表示的交易,而mean是損益表的平均值, sd是標準差。 為簡單起見,上面描述的公式中,我認為無風險回報等於 0。

關於交易的一些基礎知識

交易指數需要購買直接來自指數的資產。 許多經紀商使用一種名為CFD (差價合約)的衍生產品複製標準普爾 500 指數,這是兩方之間交換合約開盤價和收盤價之間差價的協議。

示例:在Open時買入 1 份 CFD S&P 500(價值為 2000),在當天Close時賣出(價值為 2020)。 差異,因此增益,是 20 點。 如果每個點的價值為 25 美元:

  • 總收益20 points x $25 = $500

假設經紀人為自己的收入保留了 0.6 個點的滑點:

  • 淨收益(20 - 0.6) points x $25 = $485

另一個需要考慮的重要方面是避免交易中的重大損失。 當預測結果為+1但實際結果值為-1時,它們可能會發生,因此它是誤報。 在這種情況下,收盤價是下跌的一天,收盤價低於開盤價,我們就虧損了。

必須設置止損訂單以防止我們在交易中可以承受的最大損失,並且只要資產價格低於我們之前設定的固定價值,就會觸發此類訂單。

如果我們看一下本文開頭從雅虎財經下載的時間序列,每天都有一個Low ,即當天達到的最低價。 如果我們將止損水平設置為遠離Opening-3點,並且Low - Open = -5將觸發止損單,開倉頭寸將以-3點而不是-5點的損失平倉。 這是降低風險的簡單方法。 下面的代碼代表我的輔助函數來模擬止損水平的交易:

 # This is a helper function to trade 1 bar (for example 1 day) with a Buy order at opening session # and a Sell order at closing session. To protect against adverse movements of the price, a STOP order # will limit the loss to the stop level (stop parameter must be a negative number) # each bar must contains the following attributes: # Open, High, Low, Close prices as well as gain = Close - Open and lo = Low - Open def trade_with_stop(bar, slippage = 0, stop=None): """ Given a bar, with a gain obtained by the closing price - opening price it applies a stop limit order to limit a negative loss If stop is equal to None, then it returns bar['gain'] """ bar['gain'] = bar['gain'] - slippage if stop<>None: real_stop = stop - slippage if bar['lo']<=stop: return real_stop # stop == None return bar['gain']

交易成本

交易成本是買賣證券時發生的費用。 交易成本包括經紀人的佣金和點差(交易商為證券支付的價格與買方支付的價格之間的差額),如果我們想要回測我們的策略,就需要考慮它們,類似於真實場景。 當點差發生變化時,股票交易經常會出現滑點。 在本例中以及接下來的模擬中,交易成本固定為:

  • 滑點 = 0.6 點
  • 佣金 = 每筆交易 1 美元(一輪將花費 2 美元)

只是寫一些數字,如果我們的總收益是 10 點,1 點 = 25 美元,所以 250 美元包括交易成本,我們的淨收益將是(10 - 0.6)*$25 - 2 = $233

下面的代碼展示了一個模擬之前的交易策略,止損為-3點。 藍色曲線是累積收益曲線。 唯一考慮的成本是滑點(0.6 點),結果以基點表示(從雅虎財經下載的標準普爾 500 指數的相同基本單位)。

 SLIPPAGE = 0.6 STOP = -3 trades = testing[testing['predictions'] == 1][('datetime', 'gain', 'ho', 'lo', 'open', 'close')] trades['pnl'] = trades.apply(lambda x: trade_with_stop(x, slippage=SLIPPAGE, stop=STOP)) plot_equity_chart(trades['pnl'],'Decision tree model') print("Slippage is %s, STOP level at %s" % (SLIPPAGE, STOP)) 

決策樹模型,通常向上和向右,但尖峰不太明顯,如上述 Python 代碼所示。

 Mean of PnL is 2.162171 Sharpe is 3.502897 Round turns 511 Slippage is 0.6 STOP level at -3

以下代碼用於以稍微不同的方式進行預測。 請注意使用附加參數output_type = “probability”調用的predict方法。 此參數用於返回預測值的概率,而不是它們的類預測( +1表示正面預測的結果, -1表示負面預測的結果)。 大於或等於0.5的概率與預測值+1相關聯,而小於0.5的概率值與預測值-1相關聯。 概率越高,我們預測真正的Up Day的機會就越大。

 predictions_prob = decision_tree.predict(testing, output_type = 'probability') # predictions_prob will contain probabilities instead of the predicted class (-1 or +1)

現在我們使用名為backtest_ml_model的輔助函數對模型進行回測,該函數計算一系列累積回報,包括滑點和佣金,並繪製它們的值。 為簡潔起見,在不徹底解釋backtest_ml_model函數的情況下,要強調的重要細節是,不是像我們在前面的示例中那樣過濾那些預測outcome = 1的日子,現在我們過濾等於或大於threshold = 0.5的那些predictions_prob ,如下:

 trades = testing[predictions_prob>=0.5][('datetime', 'gain', 'ho', 'lo', 'open', 'close')]

請記住,每個交易日的淨收益為: Net gain = (Gross gain - SLIPPAGE) * MULT - 2 * COMMISSION

用於評估交易策略優劣的另一個重要指標是最大回撤。 一般來說,它衡量的是投資組合價值從峰值到底部的最大單次跌幅。 在我們的案例中,這是股票曲線從峰值到底部的最大跌幅(我們的投資組合中只有一項資產,標準普爾 500 指數)。 因此,給定一個SArray的損益pnl ,我們將回撤計算為:

 drawdown = pnl - pnl.cumulative_max() max_drawdown = min(drawdown)

在輔助函數backtest_summary內部計算:

  • 最大回撤(以美元計)如上所示。
  • 準確度,採用Graphlab.evaluation方法。
  • 精度,使用Graphlab.evaluation方法。
  • 回想一下,使用Graphlab.evaluation方法。

綜上所述,以下示例顯示了代表模型策略累積回報的股票曲線,所有價值均以美元表示。

 model = decision_tree predictions_prob = model.predict(testing, output_type="probability") THRESHOLD = 0.5 bt_1_1 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, MULT=25, SLIPPAGE=0.6, COMMISSION=1, plot_title='DecisionTree') backtest_summary(bt_1_1) 

決策樹圖,Y 軸標記為“美元”,最高可達 30,000,X 軸標記為“# of roundturns”並延伸到 600,如上述 Python 代碼所示。圖形數據本身與之前的渲染相同。

 Mean of PnL is 54.054286 Sharpe is 3.502897 Round turns 511 Name: DecisionTree Accuracy: 0.577373211964 Precision: 0.587084148728 Recall: 0.724637681159 Max Drawdown: -1769.00025

為了提高預測值的精度,我們選擇了更高的閾值,而不是標準概率0.5 (50%),以更有信心模型預測Up day

 THRESHOLD = 0.55 # it's the minimum threshold to predict an Up day so hopefully a good day to trade bt_1_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, MULT=25, SLIPPAGE=0.6, COMMISSION=1, plot_title='DecisionTree') backtest_summary(bt_1_2) 

決策樹圖,Y 軸標記為“美元”,最高可達 30,000,X 軸標記為“# of roundturns”,這次僅擴展到 250,如上述 Python 代碼所示。圖形數據本身與之前的渲染相似,但更加平滑。

 Mean of PnL is 118.244689 Sharpe is 6.523478 Round turns 234 Name: DecisionTree Accuracy: 0.560468140442 Precision: 0.662393162393 Recall: 0.374396135266 Max Drawdown: -1769.00025

從上圖我們可以看出,權益曲線比以前好得多(夏普是 6.5 而不是 3.5),即使回合數更少。

從這一點開始,我們將考慮閾值高於標準值的所有下一個模型。

訓練一個邏輯分類器

就像我們之前對決策樹所做的那樣,我們可以將我們的研究應用到邏輯分類器模型中。 GraphLab Create 與 Logistic Classifier 對象具有相同的接口,我們將調用create方法來構建具有相同參數列表的模型。 此外,我們更喜歡預測概率向量而不是預測的類向量(由+1表示正面結果, -1表示負面結果),因此我們將有一個大於0.5的閾值來實現更好的精度預測。

 model = gl.logistic_classifier.create(training, target='outcome', features=l_features, validation_set=None, verbose=False) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.6 bt_2_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_2_2) 

LogisticClassifier 圖,Y 軸標記為“美元”,這次上升到 50,000,X 軸標記為“# of roundturns”,現在擴展到 450,如上述 Python 代碼所示。圖表數據本身在整體趨勢上與之前的渲染相似。

 Mean of PnL is 112.704215 Sharpe is 6.447859 Round turns 426 Name: LogisticClassifier Accuracy: 0.638491547464 Precision: 0.659624413146 Recall: 0.678743961353 Max Drawdown: -1769.00025

在這種情況下,有一個與決策樹非常相似的摘要。 畢竟,這兩個模型都是分類器,它們只預測一類二元結果( +1-1 )。

訓練線性回歸模型

如前所述,該模型的主要區別在於它處理連續值而不是二元類。 我們不必使用目標變量為Up days等於+1Down days-1來訓練模型,我們的目標必須是一個連續變量。 由於我們想要預測正收益,或者換句話說,收盤價高於開盤價,現在目標必須是我們訓練集的收益列。 此外,特徵列表必須由連續值組成,例如前面的OpenClose等。

為簡潔起見,我不會詳細介紹如何選擇正確的特徵,因為這超出了本文的範圍,本文更傾向於展示我們應該如何在數據集上應用不同的機器學習模型。 傳遞給 create 方法的參數列表是:

  • training - 它是一個包含特徵列和目標列的訓練集。
  • target - 它是包含目標變量的列的名稱。
  • validation_set - 它是用於監控模型泛化性能的數據集。 在我們的例子中,我們沒有validation_set
  • features - 它是用於訓練模型的特徵的列名列表,對於這個模型,我們將使用另一個分類器模型的集合。
  • verbose - 如果為true ,它將在訓練期間打印進度信息。
  • max_iterations - 它是允許通過數據的最大次數。 更多的數據傳遞可以產生更準確的訓練模型。
 model = gl.linear_regression.create(training, target='gain', features = l_lr_features, validation_set=None, verbose=False, max_iterations=100) predictions = model.predict(testing) # a linear regression model, predict continuous values, so we need to make an estimation of their # probabilities of success and normalize all values in order to have a vector of probabilities predictions_max, predictions_min = max(predictions), min(predictions) predictions_prob = (predictions - predictions_min)/(predictions_max - predictions_min)

到目前為止,我們的預測是預測增益的SArray ,而predictions_probpredictions值歸一化的SArray 。 為了獲得良好的精度和一定數量的轉數,與以前的模型相比,我選擇了閾值0.4 。 對於predictions_prob小於0.4backtest_linear_model輔助函數將不會打開交易,因為預計會出現下跌日。 否則,將開啟交易。

 THRESHOLD = 0.4 bt_3_2 = backtest_linear_model(testing, predictions_prob, target='gain', threshold=THRESHOLD, STOP = -3, plot_title=model.name()) backtest_summary(bt_3_2) 

線性回歸圖,Y 軸標記為“美元”,最高可達 45,000,X 軸標記為“# of roundturns”並延伸到 350,如上述 Python 代碼所示。圖形數據本身再次與之前的渲染相似,但並不完全相同。

 Mean of PnL is 138.868280 Sharpe is 7.650187 Round turns 319 Name: LinearRegression Accuracy: 0.631989596879 Precision: 0.705329153605 Recall: 0.54347826087 Max Drawdown: -1769.00025

訓練增強樹

正如我們之前訓練決策樹一樣,現在我們將使用與其他分類器模型相同的參數來訓練提升樹分類器。 此外,我們設置max_iterations = 12以增加 boosting 的最大迭代次數。 每次迭代都會創建一個額外的樹。 我們還設置了高於0.5的閾值以提高精度。

 model = gl.boosted_trees_classifier.create(training, target='outcome', features=l_features, validation_set=None, max_iterations=12, verbose=False) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.7 bt_4_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_4_2) 

BoostedTreesClassifier 圖,Y 軸標記為“美元”,最高可達 25,000,X 軸標記為“# of roundturns”,延伸到 250,如上述 Python 代碼所示。圖形數據本身再次與之前的渲染相似,在 X 軸上增加了大約 175。

 Mean of PnL is 112.002338 Sharpe is 6.341981 Round turns 214 Name: BoostedTreesClassifier Accuracy: 0.563068920676 Precision: 0.682242990654 Recall: 0.352657004831 Max Drawdown: -1769.00025

訓練隨機森林

這是我們最後一次訓練的模型,一個隨機森林分類器,由一組決策樹組成。 模型中使用的最大樹數設置為num_trees = 10 ,以避免過於復雜和過度擬合。

 model = gl.random_forest_classifier.create(training, target='outcome', features=l_features, validation_set=None, verbose=False, num_trees = 10) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.6 bt_5_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_5_2) 

RandomForestClassifier 圖,Y 軸標記為“美元”,最高可達 40,000,X 軸標記為“# of roundturns”,延伸到 350,如上述 Python 代碼所示。圖形數據本身再次類似於之前的渲染。

 Mean of PnL is 114.786962 sharpe is 6.384243 Round turns 311 Name: RandomForestClassifier Accuracy: 0.598179453836 Precision: 0.668810289389 Recall: 0.502415458937 Max Drawdown: -1769.00025

一起收集所有模型

Now we can join all the strategies together and see the overall result. It's interesting to see the summary of all Machine Learning models, sorted by their precision.

姓名準確性精確round turns sharpe
LinearRegression 0.63 0.71 319 7.65
BoostedTreesClassifier 0.56 0.68 214 6.34
RandomForestClassifier 0.60 0.67 311 6.38
DecisionTree 0.56 0.66 234 6.52
LogisticClassifier 0.64 0.66 426 6.45

If we collect all the profit and loss for each one of the previous models in the array pnl , the following chart depicts the equity curve obtained by the sum of each profit and loss, day by day.

 Mean of PnL is 119.446463 Sharpe is 6.685744 Round turns 1504 First trading day 2013-04-09 Last trading day 2016-04-22 Total return 179647

Just to give some numbers, with about 3 years of trading, all models have a total gain of about 180,000 dollars. The maximum exposition is 5 CFD contracts in the market, but to reduce the risk they all are closed at the end of each day, so overnight positions are not allowed.

Statistics of the Aggregation of All Models Together

Since each model can open a trade, but we added 5 concurrent models together, during the same day there could be from 1 contract up to 5 CFD contracts. If all models agree to open trades during the same day, there is a high chance to have an Up day predicted. Moreover, we can group by the number of models that open a trade at the same time during the opening session of the day. Then we evaluate precision as a function of the number of concurrent models.

As we can see by the chart depicted above, the precision gets better as the number of models do agree to open a trade. The more models agree, the more precision we get. For instance, with 5 models triggered the same day, the chance to predict an Up day is greater than 85%.

結論

Even in the financial world, Machine Learning is welcomed as a powerful instrument to learn from data and give us great forecasting tools. Each model shows different values of accuracy and precision, but in general, all models can be aggregated to achieve a better result than each one of them taken singularly. GraphLab Create is a great library, easy to use, scalable and able to manage Big Data very quickly. It implements different scientific and forecasting models, and there is a free license for students and Kaggle competitions.

相關:機器學習理論及其應用簡介:帶有示例的可視化教程

Additional disclosure: This article has been prepared solely for information purposes, and is not an offer to buy or sell or a solicitation of an offer to buy or sell any security or instrument or to participate in any particular trading strategy. Examples presented on these sites are for educational purposes only. Past results are not necessarily indicative of future results.