用 Python 機器學習預測黃金價格

語言: CN / TW / HK

讀取黃金 ETF 資料

本文使用機器學習方法來預測最重要的貴金屬之一黃金的價格。我們將建立一個線性迴歸模型,該模型從過去的黃金 ETF (GLD) 價格中獲取資訊,並返回對第二天黃金 ETF 價格的預測。GLD是直接投資實物黃金的最大ETF。(掃描本文最下方二維碼獲取全部完整原始碼和Jupyter Notebook 檔案打包下載。)

首先要做的是:匯入所有必要庫。

# LinearRegression 是一個用於線性迴歸的機器學習庫  
from sklearn.linear_model import LinearRegression  
# pandas 和 numpy 用於資料操作  
import pandas as pd  
import numpy as np  
# matplotlib 和 seaborn 用於繪製圖形  
import matplotlib.pyplot as plt  
%matplotlib inline  
plt.style.use('seaborn-darkgrid')  
# yahoo Finance用於獲取資料  
import yfinance as yf 

然後,我們讀取過去 12 年的每日黃金 ETF 價格資料並將其儲存在 Df 中。我們刪除不相關的列並使用 dropna() 函式刪除 NaN 值。然後,我們繪製黃金 ETF 收盤價。

Df = yf.download('GLD', '2008-01-01', '2020-6-22', auto_adjust=True)  
DfDf = Df[['Close']]  
DfDf = Df.dropna()  
Df.Close.plot(figsize=(10, 7),color='r')  
plt.ylabel("Gold ETF Prices")  
plt.title("Gold ETF Price Series")  
plt.show() 

定義解釋變數

解釋變數是一個被操縱以確定第二天黃金 ETF 價格的變數。簡單地說,它們是我們想要用來預測黃金 ETF 價格的特徵。

該策略中的解釋變數是過去 3 天和 9 天的移動平均線。我們使用 dropna() 函式刪除 NaN 值並將特徵變數儲存在 X 中。

但是,您可以向 X 新增更多您認為對預測黃金 ETF 價格有用的變數。這些變數可以是技術指標、其他 ETF 的價格,例如黃金礦工 ETF (GDX) 或石油 ETF (USO),或美國經濟資料。

定義因變數

同樣,因變數取決於解釋變數的值。簡而言之,這是我們試圖預測的黃金 ETF 價格。我們將黃金 ETF 價格儲存在 y 中。

Df['S_3'] = Df['Close'].rolling(window=3).mean()  
Df['S_9'] = Df['Close'].rolling(window=9).mean() 
Df['next_day_price'] = Df['Close'].shift(-1)  
DfDf = Df.dropna()  
X = Df[['S_3', 'S_9']]  
y = Df['next_day_price'] 

將資料拆分為訓練和測試資料集

在這一步中,我們將預測變數和輸出資料拆分為訓練資料和測試資料。通過將輸入與預期輸出配對,訓練資料用於建立線性迴歸模型。

測試資料用於估計模型的訓練效果。

•前 80% 的資料用於訓練,剩餘的資料用於測試

•X_train & y_train 是訓練資料集

•X_test & y_test 是測試資料集

t = .8  
t = int(t*len(Df))  
XX_train = X[:t]  
yy_train = y[:t]  
XX_test = X[t:]  
yy_test = y[t:] 

建立線性迴歸模型

我們現在將建立一個線性迴歸模型。但是,什麼是線性迴歸?

如果我們試圖捕捉“x”和“y”變數之間的數學關係,通過對散點圖擬合一條線,“最好”根據“x”的觀察值解釋“y”的觀察值,那麼這樣的方程 x 和 y 之間的關係稱為線性迴歸分析。

為了進一步分解,迴歸用自變數解釋了因變數的變化。因變數“y”是您要預測的變數。自變數“x”是您用來預測因變數的解釋變數。以下回歸方程描述了這種關係:

Y = m1 * X1 + m2 * X2 + C  
Gold ETF price = m1 * 3 days moving average + m2 * 15 days moving average + c  

然後我們使用擬合方法擬合自變數和因變數(x 和 y)以生成迴歸係數和常數。

linear = LinearRegression().fit(X_train, y_train)  
print("Linear Regression model")  
print("Gold ETF Price (y) = %.2f * 3 Days Moving Average (x1) \  
+ %.2f * 9 Days Moving Average (x2) \  
+ %.2f (constant)" % (linear.coef_[0], linear.coef_[1], linear.intercept_)) 

輸出線性迴歸模型:

黃金 ETF 價格 (y) = 1.20 * 3 天移動平均線 (x1) + -0.21 * 9 天移動平均線 (x2) + 0.43(常數)

預測黃金ETF價格

現在,是時候檢查模型是否在測試資料集中工作了。我們使用使用訓練資料集建立的線性模型來預測黃金 ETF 價格。預測方法找到給定解釋變數 X 的黃金 ETF 價格 (y)。

predicted_price = linear.predict(X_test)  
predicted_price = pd.DataFrame(  
    predicted_price, index=y_test.index, columns=['price'])  
predicted_price.plot(figsize=(10, 7))  
y_test.plot()  
plt.legend(['predicted_price', 'actual_price'])  
plt.ylabel("Gold ETF Price")  
plt.show() 

該圖顯示了黃金 ETF 的預測價格和實際價格。

現在,讓我們使用 score() 函式計算擬合優度。

r2_score = linear.score(X[t:], y[t:])*100  
float("{0:.2f}".format(r2_score)) 

輸出:

99.21

可以看出,模型的 R 平方為 99.21%。R 平方始終介於 0 和 100% 之間。接近 100% 的分數表明該模型很好地解釋了黃金 ETF 的價格。

繪製累積收益

讓我們計算一下這個策略的累積收益來分析它的表現。

累計收益計算步驟如下:

•  生成黃金價格的每日百分比變化

•  當第二天的預測價格高於當天的預測價格時,建立一個以“1”表示的買入交易訊號

•  通過將每日百分比變化乘以交易訊號來計算策略回報。

•  最後,我們將繪製累積收益圖

gold = pd.DataFrame()  
gold['price'] = Df[t:]['Close']  
gold['predicted_price_next_day'] = predicted_price  
gold['actual_price_next_day'] = y_test  
gold['gold_returns'] = gold['price'].pct_change().shift(-1)  
gold['signal'] = np.where(gold.predicted_price_next_day.shift(1) < gold.predicted_price_next_day,1,0)  
gold['strategy_returns'] = gold.signal * gold['gold_returns']  
((gold['strategy_returns']+1).cumprod()).plot(figsize=(10,7),color='g')  
plt.ylabel('Cumulative Returns')  
plt.show() 

輸出如下:

我們還將計算夏普比:

sharpe = gold['strategy_returns'].mean()/gold['strategy_returns'].std()*(252**0.5)  
'Sharpe Ratio %.2f' % (sharpe)  

輸出如下:

'Sharpe Ratio 1.06'

預測每日價格

您可以使用以下程式碼來預測黃金價格,並給出我們應該購買 GLD 還是不持倉的交易訊號:

import datetime as dt  
current_date = dt.datetime.now()  
data = yf.download('GLD', '2008-06-01', current_date, auto_adjust=True)  
data['S_3'] = data['Close'].rolling(window=3).mean()  
data['S_9'] = data['Close'].rolling(window=9).mean()  
datadata = data.dropna()  
data['predicted_gold_price'] = linear.predict(data[['S_3', 'S_9']])  
data['signal'] = np.where(data.predicted_gold_price.shift(1) < data.predicted_gold_price,"Buy","No Position")  
data.tail(1)[['signal','predicted_gold_price']].T 

輸出如下:

鴻蒙官方戰略合作共建——HarmonyOS技術社群

【責任編輯:龐桂玉 TEL:(010)68476606】