MQL5 列舉(Enum)與結構(Struct)完整指南

📌 本文重點
深入了解 MQL5 的 enum 與 struct:定義自訂列舉類型、結構體數據封裝,以及在 EA 中的實際應用場景。

列舉(Enum):給數字一個名字

Enum 讓你用有意義的名稱代替魔術數字,讓程式碼更易讀。

// 宣告 enum(必須在使用前宣告)
enum ENUM_SIGNAL
{
    SIGNAL_NONE  = 0,
    SIGNAL_BUY   = 1,
    SIGNAL_SELL  = -1,
    SIGNAL_CLOSE = 2
};

enum ENUM_STRATEGY_STATE
{
    STATE_IDLE,       // 閒置
    STATE_LOOKING,    // 尋找信號
    STATE_IN_TRADE,   // 持倉中
    STATE_CLOSING     // 平倉中
};

// 使用 enum
ENUM_SIGNAL GetSignal()
{
    double fast = iMA(_Symbol, _Period, 10, 0, MODE_SMA, PRICE_CLOSE, 1);
    double slow = iMA(_Symbol, _Period, 30, 0, MODE_SMA, PRICE_CLOSE, 1);
    double fastPrev = iMA(_Symbol, _Period, 10, 0, MODE_SMA, PRICE_CLOSE, 2);
    double slowPrev = iMA(_Symbol, _Period, 30, 0, MODE_SMA, PRICE_CLOSE, 2);

    if (fastPrev <= slowPrev && fast > slow) return SIGNAL_BUY;
    if (fastPrev >= slowPrev && fast < slow) return SIGNAL_SELL;
    return SIGNAL_NONE;
}

// enum 轉字串(除錯用)
string SignalToString(ENUM_SIGNAL sig)
{
    switch(sig)
    {
        case SIGNAL_BUY:   return "BUY";
        case SIGNAL_SELL:  return "SELL";
        case SIGNAL_CLOSE: return "CLOSE";
        default:           return "NONE";
    }
}

結構(Struct):將相關數據打包

// 交易設定結構體
struct TradeSetup
{
    ENUM_ORDER_TYPE type;      // 方向
    double          price;     // 進場價格
    double          stopLoss;  // 止損價格
    double          takeProfit;// 止盈價格
    double          lots;      // 手數
    string          comment;   // 備註

    // 計算風險報酬比
    double GetRRRatio()
    {
        double risk   = MathAbs(price - stopLoss);
        double reward = MathAbs(takeProfit - price);
        return (risk > 0) ? reward / risk : 0;
    }
};

// K線數據結構
struct BarData
{
    datetime time;
    double   open, high, low, close;
    long     volume;

    bool IsBullish() { return close > open; }
    bool IsBearish() { return close < open; }
    double BodySize() { return MathAbs(close - open); }
    double Range()    { return high - low; }
};

// 取得最近 N 根 K 線數據
int GetBarData(BarData &bars[], int count = 3)
{
    ArrayResize(bars, count);
    for (int i = 0; i < count; i++)
    {
        bars[i].time   = iTime(_Symbol, _Period, i);
        bars[i].open   = iOpen(_Symbol, _Period, i);
        bars[i].high   = iHigh(_Symbol, _Period, i);
        bars[i].low    = iLow(_Symbol, _Period, i);
        bars[i].close  = iClose(_Symbol, _Period, i);
        bars[i].volume = iVolume(_Symbol, _Period, i);
    }
    return count;
}

Enum + Struct 實戰:狀態機 EA

ENUM_STRATEGY_STATE g_state = STATE_IDLE;
TradeSetup          g_setup;

void OnTick()
{
    switch (g_state)
    {
        case STATE_IDLE:
        case STATE_LOOKING:
        {
            ENUM_SIGNAL sig = GetSignal();
            if (sig == SIGNAL_BUY || sig == SIGNAL_SELL)
            {
                double pt = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
                g_setup.type       = (sig == SIGNAL_BUY) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
                g_setup.price      = (sig == SIGNAL_BUY)
                                     ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
                                     : SymbolInfoDouble(_Symbol, SYMBOL_BID);
                g_setup.stopLoss   = g_setup.price - (sig==SIGNAL_BUY?1:-1) * 50 * pt;
                g_setup.takeProfit = g_setup.price + (sig==SIGNAL_BUY?1:-1) * 100 * pt;
                g_setup.lots       = 0.1;
                Print("信號: ", SignalToString(sig), " | RR: ", g_setup.GetRRRatio());
                g_state = STATE_IN_TRADE;
            }
            break;
        }
        case STATE_IN_TRADE:
            if (PositionsTotal() == 0) g_state = STATE_IDLE;
            break;
    }
}

本文由 James Lee 撰寫。內容僅供教育目的,不構成投資建議。

Similar Posts

發佈留言

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