金融市場的程式交易仰賴資料分析和策略回測。本文利用 Python 結合 yfinance 和 MetaTrader 5 平台,提供讀者從資料擷取、K 線圖模式辨識到策略回測的完整流程。讀者將學習如何運用 Python 建構演算法,自動辨識各種 K 線圖型態,並結合技術指標,產生交易訊號。最終透過回測驗證策略績效,並進行引數最佳化,開發更精準的交易模型。本文適合具備 Python 基礎和金融交易知識的讀者,並提供實務程式碼範例,引導讀者逐步建構自己的交易策略。
精通金融模式辨識:利用Python尋找與回測K線圖型態
在金融交易領域中,辨識模式是智慧的精髓。隨著科技的進步和金融資訊的去中心化,程式設計和自動化研究已成為交易世界不可或缺的一部分。任何掌握交易和程式設計藝術的人在市場中都擁有巨大的優勢。
為什麼這本文很重要?
本文作者Sofien Kaabar在金融領域投入了數年的時間研究交易策略、模式以及其他相關事務。他對K線圖型態有著特殊的熱情,不僅因為它們被廣泛採用,還因為它們展現出有趣的績效結果。在多年的研究中,他發現了一些新的K線圖型態,並在本文中與讀者分享。
本文的主要目標是全面介紹K線圖型態,包括作者個人發現的新型態,並展示如何使用Python編寫系統來對這些型態進行回測,跨越多種市場。
書籍內容與目標讀者
本文適合對K線圖型態辨識及其在金融領域的應用感興趣的學生、學者、好奇的讀者以及金融從業者。讀者將從本文中學習如何使用Python開發策略和技術指標。
本文假設讀者具備Python程式設計和金融交易的基本背景知識。作者採用清晰簡潔的方法,專注於關鍵概念,以便讀者理解每個思想的目的。
本文結構與內容
本文首先建立K線圖型態辨識演算法的結構,接著探討各種型態和策略。讀者將學習如何自動化資料匯入過程,並測試經典的K線圖型態,以客觀地評估它們的預測能力。
K線圖型態辨識演算法的建立
import pandas as pd
import yfinance as yf
# 下載資料
data = yf.download('AAPL', start='2020-01-01', end='2022-01-01')
# 計算K線圖
data['Open'] = data['Open']
data['High'] = data['High']
data['Low'] = data['Low']
data['Close'] = data['Close']
#### 內容解密:
此段程式碼首先匯入必要的函式庫,包括pandas和yfinance。然後,使用yfinance下載蘋果公司(AAPL)從2020年1月1日到2022年1月1日的股價資料。接著,將下載的資料分別指定給Open、High、Low和Close欄位,以準備進行K線圖的計算。
測試經典K線圖型態
# 定義一個函式來辨識特定的K線圖型態
def identify_pattern(data):
# 在這裡實作型態辨識邏輯
pass
# 使用函式來辨識資料中的型態
pattern_identified = identify_pattern(data)
#### 內容解密:
此函式identify_pattern用於辨識特定的K線圖型態。讀者需要根據所要辨識的型態,自行實作型態辨識邏輯。然後,將準備好的資料傳入此函式,以獲得型態辨識的結果。
結合技術指標與K線圖型態
讀者將學習如何編寫技術指標,並將其與K線圖型態結合,建立交易訊號。最後,將對這些訊號進行回測,並最佳化引數,以獲得一個完整的模式辨識策略。
# 定義一個簡單的移動平均線指標
def simple_moving_average(data, window):
return data['Close'].rolling(window=window).mean()
# 結合K線圖型態與移動平均線指標
data['SMA_50'] = simple_moving_average(data, 50)
#### 內容解密:
此段程式碼定義了一個簡單的移動平均線指標函式simple_moving_average,它計算收盤價在指定視窗期的平均值。然後,將這個指標應用於資料,生成50日移動平均線,並將結果儲存在新的欄位SMA_50中。
在Python中匯入與處理金融資料
本章旨在為透過程式設計分析金融資料奠定基礎。這需要一些準備工作,例如下載正確的軟體和建立能夠自動擷取歷史資料的演算法。 在本章結束時,您應該瞭解如何使用Python自動匯入歷史金融資料,這一技能應該能為您節省時間。讓我們開始吧。
安裝環境
第一步是準備環境和演算法成功所需的一切。為此,您需要兩個程式:
- 用於編寫和執行程式碼的Python直譯器
- 用作資料函式庫的圖表和金融軟體
讓我們從Python直譯器開始。我使用一個名為SPYDER的軟體。有些人可能更熟悉其他軟體,如Jupyter和PyCharm,但過程是相同的。您可以從官方網站下載SPYDER,或者更好的是,將其作為名為Anaconda的更大套件的一部分下載,這有助於安裝並提供更多工具。請注意,它是開源、免費使用的軟體。
SPYDER介面介紹
SPYDER的介面分為三個視窗,如圖1-1所示。左側的視窗用於編寫稍後執行的程式碼(告訴演算法執行並應用程式碼)。通常,您會在該區域看到多行程式碼。 右上方的視窗是變數資源管理器。每次儲存變數時,都可以在那裡看到它。右下方的視窗是控制檯,顯示程式碼的結果,無論是錯誤還是輸出。
資料型別
您可以在程式碼中定義和使用的資料型別分為幾類別:
- 整數(Integers):這些是整數,可以是正數或負數。例如-8和745。它們僅限於-2147483648和2147483647之間的範圍。任何超出此範圍的數字都被視為不同的資料型別,稱為長整數(long)。資料型別之間的差異與記憶體有關。整數的寬度為32位元,而長整數的寬度為64位元。
- 浮點數(Floats):這些是帶有小數點的實數,如18.54和311.52。
- 字串(Strings):這些是儲存在變數中的單詞。更科學地說,它們是一組結構化的字元(文字)。在Python中,您在單引號或雙引號之間寫入字串。
在圖1-1的程式碼第1行中,我定義了一個名為age的變數,並將其設定為13。當您執行此程式碼時,您應該在變數資源管理器中看到age的建立,其型別為int(整數),值為13。在第3行中,我執行了定義height變數並將其設定為184.50(因此,浮點數資料型別)的程式碼。
請注意,在變數定義旁邊,我寫了短語“in centimeters”,前面有一個井號(#)。這被稱為註解。註解在Python中對於解釋程式碼非常重要。因此,任何以#開頭的內容都不會被執行。在變數資源管理器中,您可以看到height變數,其型別為float。第5行定義了一個字串,在變數資源管理器中顯示為str型別(字串)。在控制檯中,您可以看到程式碼已成功執行,因為沒有錯誤,錯誤會以紅色顯示。
安裝圖表軟體
準備環境的下一步是安裝圖表軟體,以便將歷史資料匯入SPYDER。在本文中,我使用MetaTrader 5,這是一個被全球許多交易者使用的基準圖表程式。請按照以下步驟進行:
- 下載SPYDER並熟悉其操作方式。
- 下載MetaTrader 5軟體。
# 以下是一個簡單的Python範例,用於演示如何定義變數
age = 13 # 定義一個整數變數
height = 184.50 # 定義一個浮點數變數
name = "Sofien Kaabar" # 定義一個字串變數
print(age)
print(height)
print(name)
內容解密:
age = 13:這行程式碼定義了一個名為age的變數,並將其值設定為13。這是一個整數變數,因為它儲存了一個整數值。height = 184.50:這行程式碼定義了一個名為height的變數,並將其值設定為184.50。這是一個浮點數變數,因為它儲存了一個帶有小數點的實數。name = "Sofien Kaabar":這行程式碼定義了一個名為name的字串變數,並將其值設定為"Sofien Kaabar"。字串必須用引號括起來。print()函式用於輸出變數的值。這裡分別輸出age、height和name的值。
本章介紹瞭如何準備環境以進行金融資料分析,包括安裝Python直譯器和圖表軟體,並演示瞭如何在Python中定義和使用不同型別的變數。接下來的章節將探討如何使用Python匯入和處理金融資料。
使用SPYDER從MetaTrader 5匯入歷史價格資料
要使用SPYDER從MetaTrader 5匯入歷史價格,首先需要從官方網站下載並安裝MetaTrader 5。接著,建立一個模擬賬戶,這是一個使用虛擬貨幣的賬戶。模擬賬戶的特點是它不使用真實貨幣進行交易。
步驟一:安裝MetaTrader 5並建立模擬賬戶
- 下載並安裝MetaTrader 5。
- 開啟MetaTrader 5,選擇「檔案」>「開設賬戶」,然後選擇「MetaQuotes Software Corp」。
- 選擇第一個選項以開設模擬賬戶,這將允許您使用虛擬貨幣進行交易。
- 輸入基本資訊,如姓名、電子郵件和賬戶型別。
步驟二:組態MetaTrader 5介面
預設情況下,MetaTrader 5不會顯示所有可用的市場資料。因此,您需要使它們可存取以便匯入和視覺化。
- 點選「檢視」,然後選擇「市場監視」。
- 在新開啟的標籤頁中,右鍵單擊任何符號,然後選擇「顯示全部」。
建立匯入演算法
能夠自動取得任何時間框架的歷史資料是一項節省時間的功能,因為它允許您專注於研究和分析,而不是浪費寶貴的時間來取得和清理資料。
安裝MetaTrader 5 Python整合函式庫
在進行編碼之前,您需要在SPYDER中使用MetaTrader 5 Python整合函式庫。為此,請開啟Anaconda提示符並輸入以下命令:
pip install MetaTrader5
匯入必要的函式庫
import datetime
import pytz
import pandas as pd
import MetaTrader5 as mt5
import numpy as np
詳細解說:
datetime模組提供了處理日期和時間的工具。pytz函式庫提供了跨平台時區計算功能,這對於匯入資料是必要的。pandas和numpy函式庫用於資料操作和分析。MetaTrader5函式庫匯入了與MetaTrader 5軟體模組相關的功能,是匯入金融歷史資料的關鍵函式庫。
定義時間框架和資產
frame_M15 = mt5.TIMEFRAME_M15 # 15分鐘時間框架
frame_M30 = mt5.TIMEFRAME_M30 # 30分鐘時間框架
frame_H1 = mt5.TIMEFRAME_H1 # 小時時間框架
frame_H4 = mt5.TIMEFRAME_H4 # 4小時時間框架
frame_D1 = mt5.TIMEFRAME_D1 # 每日時間框架
frame_W1 = mt5.TIMEFRAME_W1 # 每週時間框架
frame_M1 = mt5.TIMEFRAME_MN1 # 每月時間框架
now = datetime.datetime.now() # 取得當前時間
assets = ['EURUSD', 'USDCHF', 'GBPUSD', 'USDCAD', 'BTCUSD',
'ETHUSD', 'XAUUSD', 'XAGUSD', 'SP500m', 'UK100'] # 定義資產列表
詳細解說:
- 定義了不同時間框架的變數,例如15分鐘、30分鐘、1小時等。
now變數儲存了當前日期和時間,用作匯入資料的參考點。assets列表包含了要進行回測的資產,包括貨幣對、加密貨幣、商品和股指。
匯入演算法結構
def get_quotes(time_frame, year=2005, month=1, day=1, asset="EURUSD"):
if not mt5.initialize():
print("initialize() failed, error code =", mt5.last_error())
詳細解說:
get_quotes函式用於取得指定資產和時間框架的報價資料。- 函式首先嘗試初始化MetaTrader 5連線。如果初始化失敗,則列印錯誤程式碼。
透過以上步驟,您可以成功地從MetaTrader 5匯入歷史價格資料到SPYDER中,並進行進一步的分析和回測。
資料匯入技術詳解:自動化與手動匯入方法
在金融資料分析領域,高效且準確的資料匯入技術至關重要。本文將探討使用Python進行金融資料匯入的兩種主要方法:自動化匯入與手動匯入,並詳細解析相關函式實作與技術細節。
自動化資料匯入實作
自動化資料匯入主要依賴MetaTrader 5(MT5)平台的Python API進行資料擷取。以下為關鍵函式的實作細節:
1. 匯入必要函式庫與初始化設定
import MetaTrader5 as mt5
import pytz
import pandas as pd
import numpy as np
# 初始化MT5連線
if not mt5.initialize():
print("MT5初始化失敗")
mt5.shutdown()
quit()
2. 資料擷取核心函式:get_quotes()
def get_quotes(time_frame, year, month, day, asset):
timezone = pytz.timezone("Europe/Paris")
time_from = datetime.datetime(year, month, day, tzinfo=timezone)
time_to = datetime.datetime.now(timezone) + datetime.timedelta(days=1)
rates = mt5.copy_rates_range(asset, time_frame, time_from, time_to)
rates_frame = pd.DataFrame(rates)
return rates_frame
內容解密:
- 使用
pytz函式庫設定時區,確保時間戳的正確性 time_from與time_to變數定義了資料擷取的時間範圍mt5.copy_rates_range()函式用於擷取指定時間範圍內的歷史資料- 將擷取的資料轉換為Pandas DataFrame格式
3. 大量資料匯入函式:mass_import()
def mass_import(asset, time_frame):
if time_frame == 'H1':
data = get_quotes(frame_H1, 2013, 1, 1, asset=assets[asset])
data = data.iloc[:, 1:5].values
data = data.round(decimals=5)
if time_frame == 'D1':
data = get_quotes(frame_D1, 2000, 1, 1, asset=assets[asset])
data = data.iloc[:, 1:5].values
data = data.round(decimals=5)
return data
內容解密:
- 根據不同的時間框架(H1或D1)呼叫
get_quotes()函式 - 資料擷取後,選取需要的欄位(開盤價、最高價、最低價、收盤價)
- 將資料轉換為NumPy陣列並進行小數點精確度處理
手動資料匯入方法
對於無法使用MT5 Python API的情況(如macOS環境),可採用手動匯入方式:
- 將金融資料儲存為Excel檔案
- 使用Pandas讀取Excel檔案:
my_data = pd.read_excel('my_data.xlsx') - 將DataFrame轉換為NumPy陣列:或直接使用:
my_data = np.array(my_data)my_data = pd.read_excel('my_data.xlsx').values
技術實務考量
- 自動化匯入方法依賴MT5平台的Python API,在Windows環境下運作最佳
- 資料匯入的時間範圍受限於MT5可擷取的歷史資料上限
- 手動匯入方法提供跨平台相容性,但需要手動下載資料
程式碼處理與基本函式設計
在進行金融資料分析和回測時,Python 提供了強大且快速的工具來自動化處理歷史 OHLC(開盤、最高、最低、收盤)資料。掌握這些技術可以大幅提升研究效率。
基本函式的重要性
基本函式(Primal Functions)是一組自定義函式,用於簡化資料陣列的操作。這些函式在分析和回測過程中發揮著重要作用。
新增欄位到陣列的函式
有時候需要在陣列中新增欄位來存放技術指標或交易訊號。例如,給定一個包含四個欄位(OHLC)的陣列,可以新增一個額外的欄位來存放計算出的技術指標,如簡單移動平均線,或是買賣訊號的代理值(例如,使用 1 表示買入訊號,-1 表示賣出訊號)。
import numpy as np
def add_column(data, times):
for i in range(1, times + 1):
new = np.zeros((len(data), 1), dtype=float)
data = np.append(data, new, axis=1)
return data
# #### 內容解密:
# 1. `add_column` 函式接受兩個引數:`data`(原始陣列)和 `times`(要新增的欄位數量)。
# 2. 使用 `np.zeros` 建立一個新的零值陣列,其大小與原始資料的列數相同。
# 3. 使用 `np.append` 將新陣列新增到原始資料的右側,從而增加欄位數量。
# 4. `axis=1` 表示沿著欄位方向進行操作,即新增欄位。
# 5. 該函式透過迴圈重複新增欄位,直到達到指定的 `times` 數量。
# 使用範例:
my_data = np.random.rand(10, 4) # 假設有10筆資料,每筆資料有4個欄位(OHLC)
my_data = add_column(my_data, 5) # 新增5個欄位
print(my_data.shape) # 輸出:(10, 9),表示10筆資料現在有9個欄位
從陣列中刪除欄位的函式
在計算複雜指標時,可能會產生一些中間計算結果的欄位,這些欄位在最終結果中並不需要。可以使用 delete_column 函式來刪除這些多餘的欄位,以保持陣列的整潔。
def delete_column(data, index, times):
for i in range(1, times + 1):
data = np.delete(data, index, axis=1)
return data
# #### 內容解密:
# 1. `delete_column` 函式接受三個引數:`data`(原始陣列)、`index`(要刪除的欄位索引)和 `times`(要刪除的欄位數量)。
# 2. 使用 `np.delete` 刪除指定索引的欄位,`axis=1` 表示沿著欄位方向進行操作。
# 3. 該函式透過迴圈重複刪除欄位,直到達到指定的 `times` 數量。
# 4. 注意:刪除欄位後,後續欄位的索引會自動調整,因此每次刪除都是針對當前狀態下的索引。
# 使用範例:
my_data = np.random.rand(10, 9) # 假設有10筆資料,每筆資料有9個欄位
my_data = delete_column(my_data, 4, 3) # 從索引4開始刪除3個欄位
print(my_data.shape)