金融市場的程式交易仰賴資料分析和策略回測。本文利用 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日的股價資料接著將下載的資料分別指定給OpenHighLow和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自動匯入歷史金融資料,這一技能應該能為您節省時間。讓我們開始吧。

安裝環境

第一步是準備環境和演算法成功所需的一切。為此,您需要兩個程式:

  1. 用於編寫和執行程式碼的Python直譯器
  2. 用作資料函式庫的圖表和金融軟體

讓我們從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,這是一個被全球許多交易者使用的基準圖表程式。請按照以下步驟進行:

  1. 下載SPYDER並熟悉其操作方式。
  2. 下載MetaTrader 5軟體。
# 以下是一個簡單的Python範例,用於演示如何定義變數
age = 13  # 定義一個整數變數
height = 184.50  # 定義一個浮點數變數
name = "Sofien Kaabar"  # 定義一個字串變數

print(age)
print(height)
print(name)

內容解密:

  1. age = 13:這行程式碼定義了一個名為age的變數,並將其值設定為13。這是一個整數變數,因為它儲存了一個整數值。
  2. height = 184.50:這行程式碼定義了一個名為height的變數,並將其值設定為184.50。這是一個浮點數變數,因為它儲存了一個帶有小數點的實數。
  3. name = "Sofien Kaabar":這行程式碼定義了一個名為name的字串變數,並將其值設定為"Sofien Kaabar"。字串必須用引號括起來。
  4. print()函式用於輸出變數的值。這裡分別輸出ageheightname的值。

本章介紹瞭如何準備環境以進行金融資料分析,包括安裝Python直譯器和圖表軟體,並演示瞭如何在Python中定義和使用不同型別的變數。接下來的章節將探討如何使用Python匯入和處理金融資料。

使用SPYDER從MetaTrader 5匯入歷史價格資料

要使用SPYDER從MetaTrader 5匯入歷史價格,首先需要從官方網站下載並安裝MetaTrader 5。接著,建立一個模擬賬戶,這是一個使用虛擬貨幣的賬戶。模擬賬戶的特點是它不使用真實貨幣進行交易。

步驟一:安裝MetaTrader 5並建立模擬賬戶

  1. 下載並安裝MetaTrader 5。
  2. 開啟MetaTrader 5,選擇「檔案」>「開設賬戶」,然後選擇「MetaQuotes Software Corp」。
  3. 選擇第一個選項以開設模擬賬戶,這將允許您使用虛擬貨幣進行交易。
  4. 輸入基本資訊,如姓名、電子郵件和賬戶型別。

步驟二:組態MetaTrader 5介面

預設情況下,MetaTrader 5不會顯示所有可用的市場資料。因此,您需要使它們可存取以便匯入和視覺化。

  1. 點選「檢視」,然後選擇「市場監視」。
  2. 在新開啟的標籤頁中,右鍵單擊任何符號,然後選擇「顯示全部」。

建立匯入演算法

能夠自動取得任何時間框架的歷史資料是一項節省時間的功能,因為它允許您專注於研究和分析,而不是浪費寶貴的時間來取得和清理資料。

安裝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函式庫提供了跨平台時區計算功能,這對於匯入資料是必要的。
  • pandasnumpy函式庫用於資料操作和分析。
  • 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

內容解密:

  1. 使用pytz函式庫設定時區,確保時間戳的正確性
  2. time_fromtime_to變數定義了資料擷取的時間範圍
  3. mt5.copy_rates_range()函式用於擷取指定時間範圍內的歷史資料
  4. 將擷取的資料轉換為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

內容解密:

  1. 根據不同的時間框架(H1或D1)呼叫get_quotes()函式
  2. 資料擷取後,選取需要的欄位(開盤價、最高價、最低價、收盤價)
  3. 將資料轉換為NumPy陣列並進行小數點精確度處理

手動資料匯入方法

對於無法使用MT5 Python API的情況(如macOS環境),可採用手動匯入方式:

  1. 將金融資料儲存為Excel檔案
  2. 使用Pandas讀取Excel檔案:
    my_data = pd.read_excel('my_data.xlsx')
    
  3. 將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)