MQL5 函數庫實作:建立可重複使用的交易工具箱

📌 本文重點:將常用 MQL5 函數封裝成 .mqh 函數庫,實現開倉/平倉/查詢持倉/日誌記錄等可重複使用的模組。

為什麼需要函數庫?

開發多個 EA 時,開倉、平倉、計算手數等程式碼重複出現。將通用函數封裝成 .mqh 標頭檔,一行 #include 即可在任何 EA 中使用,大幅提升開發效率。

建立函數庫檔案

MetaEditor:「文件」→「新建」→「Include(.mqh)」→ 命名 TradeUtils.mqh,儲存至 MQL5/Include/TradeUtils.mqh

核心模組:開倉函數

#pragma once

bool OpenMarketOrder(ENUM_ORDER_TYPE type, double lots,
                     double slPips=0, double tpPips=0,
                     long magic=0, string comment="")
{
    double pt    = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
    double price = (type == ORDER_TYPE_BUY)
                   ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
                   : SymbolInfoDouble(_Symbol, SYMBOL_BID);
    double sl = 0, tp = 0;
    if (slPips > 0) sl = (type==ORDER_TYPE_BUY) ? price-slPips*pt : price+slPips*pt;
    if (tpPips > 0) tp = (type==ORDER_TYPE_BUY) ? price+tpPips*pt : price-tpPips*pt;
    MqlTradeRequest req = {}; MqlTradeResult res = {};
    req.action=TRADE_ACTION_DEAL; req.symbol=_Symbol; req.volume=lots;
    req.type=type; req.price=price; req.deviation=10;
    req.sl=NormalizeDouble(sl,_Digits); req.tp=NormalizeDouble(tp,_Digits);
    req.magic=magic; req.comment=comment;
    return OrderSend(req,res);
}

持倉查詢模組

int CountPositions(long magic=-1)
{
    int count = 0;
    for (int i = PositionsTotal()-1; i >= 0; i--)
    {
        if (PositionGetSymbol(i) != _Symbol) continue;
        if (magic != -1 && PositionGetInteger(POSITION_MAGIC) != magic) continue;
        count++;
    }
    return count;
}

double GetTotalProfit(long magic=-1)
{
    double total = 0;
    for (int i = PositionsTotal()-1; i >= 0; i--)
    {
        if (PositionGetSymbol(i) != _Symbol) continue;
        if (magic != -1 && PositionGetInteger(POSITION_MAGIC) != magic) continue;
        total += PositionGetDouble(POSITION_PROFIT);
    }
    return total;
}

在 EA 中使用函數庫

#include <TradeUtils.mqh>

input double InpLots  = 0.1;
input int    InpMagic = 11111;

void OnTick()
{
    if (CountPositions(InpMagic) == 0)
        OpenMarketOrder(ORDER_TYPE_BUY, InpLots, 50, 100, InpMagic, "策略A");
    if (GetTotalProfit(InpMagic) >= 100.0)
        CloseAllPositions(InpMagic);
}

設計建議

  • 使用 #pragma once 防止重複引用
  • 提供預設參數讓函數更靈活
  • 每個函數都要有錯誤處理和 Print 輸出
  • 命名規範:動詞+名詞,如 OpenMarketOrder

本文由 James Lee 撰寫。

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *