2025年4月10日 星期四

MT5 EA交易策略開發教學 [01] 說明

這篇使用針對 MT5 外匯商品 交易策略開發 [01] 內容作一些說明 有助於了解部落格後續文章內相關的 MT5 語法及架構

#include

這行指的是引入 MQL5 提供的交易類別庫,包含一系列預定義的功能,用於執行交易操作(如下單、修改訂單和平倉)。這使得交易邏輯的實現更加高效和簡潔。

#include

這行代表引入一個命名為 MagicMT5_函數庫V1.mqh 的自定義函數庫。此函數庫可能包含自定義的輔助工具或功能,專門用來加強交易策略、數據處理或特殊操作。如果這是您自己設計的函數庫,則可能已經加入了獨特的邏輯來支持您的算法需求。

ENUM_TIMEFRAMES 時間週期 = PERIOD_M20;

這行代碼創建一個 ENUM_TIMEFRAMES 類型的變數,名稱為 時間週期,並將其初始值設定為 PERIOD_M20

ENUM_TIMEFRAMES  MQL5 中的一個列舉類型,用來表示不同的時間週期(例如,1分鐘、5分鐘或小時級別的時間框架)。

PERIOD_M20 代表 20 分鐘的時間框架,這通常用於技術分析、指標計算或交易策略中的決策邏輯。

int OnInit()

OnInit()  MQL5 中的初始化事件函數,專門用來處理當程式(例如 Expert Advisor)被加載到圖表上時的初始化工作。

它的回傳型態為整數(int),通常表示初始化結果。

LoadEA = TimeCurrent();

此行將伺服器的當前時間(TimeCurrent())賦值給變數 LoadEA

TimeCurrent()  MQL5 的內建函數,提供以秒數表示的伺服器時間。

此操作常用於記錄 EA 啟動的時間,例如方便在後續的邏輯中進行時間相關的分析或操作。

return(INIT_SUCCEEDED);

INIT_SUCCEEDED  MQL5 定義的常數,用來表示初始化成功。

回傳值告訴系統 EA 已成功完成初始化,可進行正常運行。

若遇到初始化失敗的情況,您可以使用 return(INIT_FAILED) 等選項來反映問題。

OnTick 函數邏輯,主要用於處理每次市場資料更新(即每個新 Tick 到達時)執行的操作。

if(AccountInfoDouble(ACCOUNT_BALANCE) <= 資金風控)

此條件用於檢查帳戶的餘額是否低於「資金風控」的設定值。

若餘額不足,則觸發警報提示,並透過 return 終止後續操作。

使用 AccountInfoDouble(ACCOUNT_BALANCE) 函數,可以獲取帳戶目前的可用資金。

BarNumber = iBarShift(Symbol(),時間週期,LoadEA);

透過 iBarShift() 函數,獲得指定商品(Symbol())、指定時間週期(時間週期)自某一點時間(LoadEA)以來的 K 棒數量。

此變數主要用於回測區間內的 K 棒數分析。

BarSinceExit = BarNumber - CloseOrderNo;

計算自前一次交易平倉(CloseOrderNo)後至當前的 K 棒數量。

此變數可用於控制交易頻率或設置間隔限制。

if((BarNumber == 1 && BarNumber != JudgeNo))

判斷當前是否為第 1 K 棒(BarNumber == 1),且與上次判斷的 K 棒不同(BarNumber != JudgeNo)。

此條件可能是策略中判斷進場的觸發條件。

多單進場單號 = Buy_at_MARKET(Symbol(),Lots,0,0,"1st_K",MagicNumber);

呼叫自定義函數 Buy_at_MARKET(),進行多單進場操作。

輸入參數包括商品名稱(Symbol())、手數(Lots)、止損、止盈以及其他附加設定。

MagicNumber 是用於識別該交易的唯一標記。

LX_CloseByTicket(多單進場單號, Lots);

呼叫自定義函數 LX_CloseByTicket(),用來平倉指定單號(多單進場單號)的部分或全部倉位。

此處執行的是根據手數(Lots)進行平倉。

CloseOrderNo = iBarShift(Symbol(),時間週期,LoadEA);

更新平倉的 K 棒編號,用於後續的交易條件判斷。

FastSma = MathMin(LenA1, LenB1);

使用 MathMin() 函數,計算較短的均線周期,用於生成快速均線(FastSma)。

可能代表短期趨勢。

SlowSma = MathMax(LenA1, LenB1);

使用 MathMax() 函數,計算較長的均線周期,用於生成慢速均線(SlowSma)。

可能用於判斷長期趨勢。

 

if(BarNumber != JudgeNo)

條件判斷:檢查當前的 K 棒編號(BarNumber)是否與最後一次判斷的 K 棒(JudgeNo)不同。

若條件成立,執行以下操作:

K();:呼叫自定義函數,可能用來更新或切換 K 棒狀態。

允許交易時段 設定:透過 getTM_hour(TimeCurrent()) 函數,檢查當前時間是否在交易允許的範圍內(例如:早上 10 點至凌晨 2 點)。

Ask=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

獲取商品的最新買價(Ask)。

使用內建函數 SymbolInfoDouble() 來獲取指定商品的價格資訊。

Bid=SymbolInfoDouble(Symbol(),SYMBOL_BID);

獲取商品的最新賣價(Bid)。

同樣使用 SymbolInfoDouble(),針對商品的交易價格。

AccountBalance=AccountInfoDouble(ACCOUNT_BALANCE);

獲取帳戶的當前資金餘額。

此資訊通常用於進一步的風控或計算。

Tickvalue=SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE);

獲取商品的每 Tick 的價值(即價格波動最小單位的價值)。

此變數可能用於手數或風險計算。

SP = NormalizeDouble(MathAbs(Ask-Bid),Digits());

計算買賣價差(Spread),使用 MathAbs() 取得絕對值,並透過 NormalizeDouble() 格式化至商品的價格小數位數(Digits())。

這通常是用來判斷市場流動性或交易成本。

動態計算交易手數:

if(Lots_AutoCal == true)

檢查是否啟用自動計算手數(Lots_AutoCal)。

若啟用,執行以下操作:

Lots = get_dynamic_lot_size(Lots_Even,Symbol(),RiskPercent,AccountBalance,SL);

呼叫自定義函數 get_dynamic_lot_size(),根據以下參數動態計算手數:

Lots_Even:基準手數。

Symbol():商品符號。

RiskPercent:每筆交易的風險百分比。

AccountBalance:帳戶資金餘額。

SL:止損距離。

Lots = MathMin(0.3,MathMax(0.01,Lots));

限制計算出來的手數範圍:最低 0.01 手,最高 0.3 手。

使用 MathMin()  MathMax() 控制手數範圍。

  進場條件檢查

if(允許交易時段 == true)

檢查是否處於允許的交易時段。只有在交易時段內,此區塊的邏輯才會被執行。

這是防止非交易時段內的自動交易操作。

多單進場邏輯

LE_Cond = (_3GreatThanBBUp());

這是一個自定義條件(可能是技術指標),用於檢查是否滿足進場多單的條件。

假設 _3GreatThanBBUp() 是布林帶上軌突破等條件的檢查邏輯。

清倉空單:sell_order_close_all()

如果目前有空單(空單部位() > 0),並且 K 棒編號不等於上次交易的 K 棒(BarNumber != OrderBarNo),則將所有空單平倉。

多單建立:

買入價格 計算

透過 Highest_OHLC() 函數計算當日最高價格,加上一定的範圍偏移量(Range[1]*0.5),並格式化為指定小數位數(Digits())。

市價單進場:Buy_at_MARKET()

如果無持有多單(多單部位() == 0)且距離上次平倉超過 1 K 棒(BarSinceExit > 1),則執行市價多單進場。

使用自定義函數 Buy_at_MARKET(),進行市價買入操作,並保存該單的編號(多單進場單號)。

更新交易 K 棒編號:OrderBarNo

進場後,將交易的 K 棒編號更新,用於避免重複交易。

空單進場邏輯

SE_Cond = (DayBlack3Bar_LClose() && a_RSIA[1] > 50);

檢查是否滿足進場空單的條件:

DayBlack3Bar_LClose() 可能表示「日線三根黑棒」的條件檢查。

a_RSIA[1] > 50 表示 RSI 指標的某個值大於 50

清倉多單:buy_order_close_all()

如果目前有多單(多單部位() > 0),並且 K 棒編號不等於上次交易的 K 棒(BarNumber != OrderBarNo),則將所有多單平倉。

空單建立:

賣出價格 計算

透過 Lowest_OHLC() 函數計算當日最低價格,減去一定的範圍偏移量(Range[1]*0.5),並格式化為指定小數位數。

掛單空單進場:Short_at_STOP()

如果無持有空單(空單部位() == 0),且距離上次平倉超過 1 K 棒(BarSinceExit > 1),並且上一根收盤價大於計算的賣出價格(Close[1] > 賣出價格),則執行掛單賣出操作。

使用自定義函數 Short_at_STOP(),設定 Stop 掛單進行賣出。

更新交易 K 棒編號:OrderBarNo

掛單成功後,將交易的 K 棒編號更新。

功能概述:

進場條件檢查:

根據布林帶或技術指標等條件判斷多單或空單進場。

僅在允許的交易時段內執行邏輯。

多單與空單的動作互斥:

清倉對沖的倉位(如進多單前平空單,進空單前平多單)。

動態計算價格:

根據當日最高/最低價格,結合一定範圍偏移量計算進場價格。

交易限制:

通過 BarNumber  OrderBarNo 避免同一根 K 棒內重複交易。

通過 BarSinceExit 控制平倉後的進場間隔。

 

多單平倉邏輯

條件檢查

if(多單部位() > 0)

確保目前有多單部位(倉位數量大於零)時才執行平倉邏輯。

停利與停損的計算

多單進場價格 = LE_EntryPrice(MagicNumber,多單進場單號);

使用自定義函數 LE_EntryPrice(),根據進場單號(多單進場單號)和魔術號(MagicNumber)獲取多單的進場價格。

多單停利價格 = 多單進場價格 + TP * Point();

計算多單的停利價格(TP),即在進場價格的基礎上加上目標點數(TP)。

多單停損價格 = 多單進場價格 - SL * Point();

計算多單的停損價格(SL),即在進場價格的基礎上減去止損點數(SL)。

判斷平倉條件

LX_Cond 定義:

LX_Cond = ((Close[1] <= 多單停利價格 && Bid > 多單停利價格) || (Close[1] >= 多單停損價格 && Bid < 多單停損價格));

檢查多單是否達到停利或停損條件:

停利條件:上一根 K 棒收盤價低於或等於停利價格,且當前買價(Bid)超過停利價格。

停損條件:上一根收盤價高於或等於停損價格,且當前買價低於停損價格。

執行平倉

if(LX_Cond == true && BarNumber != CloseOrderNo)

確保符合平倉條件,且 K 棒編號不同於上次平倉時的 K 棒(避免重複執行)。

LX_CloseByTicket(多單進場單號, Lots);

呼叫自定義函數,將指定單號的多單進行平倉。

更新平倉 K 棒編號:

if(多單部位() == 0) { CloseOrderNo = iBarShift(Symbol(), 時間週期, LoadEA); }

平倉成功後,更新平倉時的 K 棒編號,避免重複執行平倉邏輯。

空單平倉邏輯

條件檢查

if(空單部位() > 0)

確保目前有空單部位時才執行平倉邏輯。

停利與停損的計算

空單進場價格 = SE_EntryPrice(MagicNumber, 空單進場單號);

使用自定義函數 SE_EntryPrice() 獲取空單進場價格。

空單停利價格  空單停損價格 計算:

空單停利價格 = MathMin(a_ICHI_SA[1], a_ICHI_SB[1]) - Range[1] * 2;

空單停損價格 = MathMax(a_ICHI_SA[1], a_ICHI_SB[1]) + Range[1] * 2;

a_ICHI_SA[1]  a_ICHI_SB[1] 可能是 Ichimoku 指標(基準線和轉換線)的值。

空單停利價格:取這些指標的較小值減去偏移範圍。

空單停損價格:取這些指標的較大值加上偏移範圍。

判斷平倉條件

SX_Cond 定義:

SXcond51 = (空單進場價格 > 空單停利價格 && Close[1] >= 空單停利價格 && Ask < 空單停利價格);

SXcond52 = (空單進場價格 < 空單停損價格 && Close[1] <= 空單停損價格 && Ask > 空單停損價格);

SX_Cond = (SXcond51 == true || SXcond52 == true);



判斷空單是否達到停利或停損條件:

停利條件:進場價格高於停利價格,且上一根收盤價大於或等於停利價格,並且賣價低於停利價格。

停損條件:進場價格低於停損價格,且上一根收盤價小於或等於停損價格,並且賣價高於停損價格。

執行平倉

if(SX_Cond == true && BarNumber != CloseOrderNo)

確保符合平倉條件,並避免重複執行。

SX_CloseByTicket(空單進場單號, Lots);

呼叫自定義函數,將指定單號的空單平倉。

更新平倉 K 棒編號:

if(空單部位() == 0) { CloseOrderNo = iBarShift(Symbol(), 時間週期, LoadEA); }

更新判斷編號

JudgeNo = iBarShift(Symbol(), 時間週期, LoadEA);

更新最後的判斷 K 棒編號,確保進場和平倉的邏輯同步。

 

多單部位

函數定義

int 多單部位()

 {

int count;

count = get_TradeCounts(Symbol(), MagicNumber, POSITION_TYPE_BUY);

return count;

}

功能: 計算當前多單的部位數量。

邏輯:

使用自定義函數 get_TradeCounts(),傳遞當前交易商品(Symbol())、專屬識別碼(MagicNumber)及多單類型(POSITION_TYPE_BUY)。

該函數返回多單部位的數量,並存入 count,最後回傳此值。

用途: 確認是否有持倉多單,供進場/平倉邏輯使用。

2. 空單部位

函數定義

int 空單部位()

{ int count;

count = get_TradeCounts(Symbol(), MagicNumber, POSITION_TYPE_SELL);

return count;

}

功能: 計算當前空單的部位數量。

邏輯:

 多單部位() 類似,不同點在於這裡判斷的是空單部位數量(POSITION_TYPE_SELL)。

用途: 確認是否有持倉空單,用於進場或平倉操作。

3. K

函數定義

void K()

{ // K棒刪除所有掛單

if(total_pending_order_count(Symbol(), MagicNumber, -1) != 0)

{

delete_pending_orders_all(Symbol(), MagicNumber, -1, 0x0000ff);

}

 Set_OHLC_Bar_Series();

Set_OHLC_Day_Series();

Get_OHLC_Bar(10);

Get_OHLC_Day(10);

set_BarInfo();

set_BBAND();

set_RSI();

set_ICHIMOKU();

}



功能解釋

刪除所有掛單

total_pending_order_count(Symbol(), MagicNumber, -1)

計算當前所有掛單的數量。

delete_pending_orders_all()

如果有掛單,則刪除所有掛單。

使用 MagicNumber 和商品符號(Symbol())進行過濾,確保只刪除與特定識別碼相關的掛單。

OHLC 資料更新

Set_OHLC_Bar_Series()  Set_OHLC_Day_Series()

更新當前 K 棒和日線的開高低收(OHLC)數據序列。

取得 OHLC

Get_OHLC_Bar(10)  Get_OHLC_Day(10)

抓取最近 10 K 棒及最近 10 天的 OHLC 值,用於後續邏輯。

技術指標設定

set_BarInfo():可能設定當前 K 棒的其他資訊。

set_BBAND():設定布林通道指標。

set_RSI():設定 RSI 指標。

set_ICHIMOKU():設定一目均衡表。

用途

此函數用於每當新 K 棒生成時,更新 OHLC 資料與技術指標,並清除舊掛單,確保交易環境整潔且邏輯一致。

 

 


沒有留言:

張貼留言