帳戶監控 EA:每日虧損限制與自動停止交易
📌 本文重點
建立 MQL5 帳戶監控 EA:每日最大虧損限制、最大回撤保護、自動停止交易,以及帳戶狀態通知功能。
建立 MQL5 帳戶監控 EA:每日最大虧損限制、最大回撤保護、自動停止交易,以及帳戶狀態通知功能。
為什麼需要帳戶監控?
即使策略有止損,在特殊市場條件(如跳空、流動性不足)下,單日虧損仍可能超出預期。帳戶監控 EA 作為最後一道防線,當虧損達到設定上限時自動停止所有交易。
input double InpMaxDailyLoss = 3.0; // 最大每日虧損(帳戶餘額%)
input double InpMaxTotalDD = 10.0; // 最大總回撤(%)
input double InpMaxDailyProfit = 5.0; // 每日獲利上限(%,達到後停止)
input bool InpCloseOnLimit = true; // 達到限制時自動平倉
input bool InpSendAlert = true; // 發送警報
double g_dayStartBalance = 0;
datetime g_lastDay = 0;
bool g_tradingStopped = false;
int OnInit()
{
g_dayStartBalance = AccountInfoDouble(ACCOUNT_BALANCE);
return INIT_SUCCEEDED;
}
void OnTick()
{
// 每天重置
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
datetime today = TimeCurrent() - dt.hour*3600 - dt.min*60 - dt.sec;
if (today != g_lastDay)
{
g_lastDay = today;
g_dayStartBalance = AccountInfoDouble(ACCOUNT_BALANCE);
g_tradingStopped = false;
Print("新交易日開始,起始餘額: $", g_dayStartBalance);
}
if (g_tradingStopped) return;
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
double highWater = MathMax(balance, g_dayStartBalance); // 歷史最高點
// 每日虧損計算(以每日起始餘額為基準)
double dailyPnL = balance - g_dayStartBalance;
double dailyPnLPct = (g_dayStartBalance > 0) ? dailyPnL / g_dayStartBalance * 100 : 0;
// 總回撤計算(以歷史最高點為基準)
double totalDD = highWater - equity;
double totalDDPct = (highWater > 0) ? totalDD / highWater * 100 : 0;
bool shouldStop = false;
string stopReason = "";
if (dailyPnLPct <= -InpMaxDailyLoss)
{
shouldStop = true;
stopReason = StringFormat("每日虧損達到 %.1f%%(限制: %.1f%%)", MathAbs(dailyPnLPct), InpMaxDailyLoss);
}
else if (totalDDPct >= InpMaxTotalDD)
{
shouldStop = true;
stopReason = StringFormat("總回撤達到 %.1f%%(限制: %.1f%%)", totalDDPct, InpMaxTotalDD);
}
else if (dailyPnLPct >= InpMaxDailyProfit)
{
shouldStop = true;
stopReason = StringFormat("每日獲利達到 %.1f%%,鎖定獲利", dailyPnLPct);
}
if (shouldStop)
{
g_tradingStopped = true;
Print("⚠️ 交易停止!原因: ", stopReason);
if (InpSendAlert) Alert("MQL5 監控警報!
", stopReason);
if (InpCloseOnLimit) CloseAllPositions();
}
// 每 5 分鐘在圖表顯示狀態
static datetime lastUpdate = 0;
if (TimeCurrent() - lastUpdate >= 300)
{
lastUpdate = TimeCurrent();
Comment(StringFormat(
"帳戶監控狀態
今日盈虧: %+.2f%% ($%+.2f)
總回撤: %.2f%%
狀態: %s",
dailyPnLPct, dailyPnL, totalDDPct,
g_tradingStopped ? "⛔ 已停止" : "✅ 運行中"
));
}
}
void CloseAllPositions()
{
MqlTradeRequest req={}; MqlTradeResult res={};
for (int i = PositionsTotal()-1; i >= 0; i--)
{
string sym = PositionGetSymbol(i);
ulong ticket = PositionGetInteger(POSITION_TICKET);
int type = (int)PositionGetInteger(POSITION_TYPE);
req.action = TRADE_ACTION_DEAL;
req.symbol = sym;
req.volume = PositionGetDouble(POSITION_VOLUME);
req.position = ticket;
req.type = (type == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
req.price = (req.type == ORDER_TYPE_SELL) ? SymbolInfoDouble(sym, SYMBOL_BID) : SymbolInfoDouble(sym, SYMBOL_ASK);
req.deviation = 20;
OrderSend(req, res);
}
Print("所有持倉已平倉");
}
本文由 James Lee 撰寫。內容僅供教育目的,不構成投資建議。