SiamCafe.net Blog
Technology

MQL5 Book — คู่มือเทรด Forex ฉบับสมบูรณ์ 2026

mql5 book
MQL5 Book — คู่มือเทรด Forex ฉบับสมบูรณ์ 2026 | SiamCafe Blog
2026-03-21· อ. บอม — SiamCafe.net· 11,733 คำ

MQL5 คืออะไร

MQL5 (MetaQuotes Language 5) เป็นภาษาโปรแกรมสำหรับพัฒนา Trading Applications บน MetaTrader 5 ซึ่งเป็นแพลตฟอร์มเทรดที่นิยมที่สุดในโลก MQL5 รองรับ Object-Oriented Programming (OOP) เต็มรูปแบบ มี Standard Library ที่ครบครัน และ Strategy Tester ที่ทรงพลังสำหรับ Backtest

เมื่อเทียบกับ MQL4 ที่เป็น Procedural เป็นหลัก MQL5 มีความสามารถมากกว่า รองรับ Classes, Inheritance, Polymorphism, Templates และ Event-driven Programming ทำให้เขียน Code ที่ซับซ้อนได้ง่ายขึ้น

โครงสร้างพื้นฐาน MQL5 Expert Advisor

//+------------------------------------------------------------------+
//| BasicEA.mq5 — โครงสร้างพื้นฐาน Expert Advisor                    |
//+------------------------------------------------------------------+
#property copyright "SiamCafe Blog"
#property version   "1.0"
#property strict

// Include Standard Library
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Indicators\Trend.mqh>

// Input Parameters
input group "=== Trading Settings ==="
input double   InpLotSize    = 0.01;     // Lot Size
input int      InpStopLoss   = 50;       // Stop Loss (points)
input int      InpTakeProfit = 100;      // Take Profit (points)
input int      InpMagic      = 12345;    // Magic Number

input group "=== Indicator Settings ==="
input int      InpFastMA     = 10;       // Fast MA Period
input int      InpSlowMA     = 20;       // Slow MA Period
input ENUM_MA_METHOD InpMAMethod = MODE_EMA; // MA Method

input group "=== Risk Management ==="
input double   InpMaxRisk    = 2.0;      // Max Risk % per Trade
input int      InpMaxTrades  = 3;        // Max Open Trades

// Global Objects
CTrade         trade;
CPositionInfo  posInfo;
CSymbolInfo    symInfo;

// Indicator Handles
int handleFastMA;
int handleSlowMA;

// Buffers
double fastMA[];
double slowMA[];

//+------------------------------------------------------------------+
//| Expert initialization function                                     |
//+------------------------------------------------------------------+
int OnInit()
{
   // ตั้งค่า Trade Object
   trade.SetExpertMagicNumber(InpMagic);
   trade.SetDeviationInPoints(10);
   trade.SetTypeFilling(ORDER_FILLING_FOK);

   // สร้าง Indicator Handles
   handleFastMA = iMA(_Symbol, PERIOD_CURRENT, InpFastMA, 0,
                       InpMAMethod, PRICE_CLOSE);
   handleSlowMA = iMA(_Symbol, PERIOD_CURRENT, InpSlowMA, 0,
                       InpMAMethod, PRICE_CLOSE);

   if(handleFastMA == INVALID_HANDLE || handleSlowMA == INVALID_HANDLE)
   {
      Print("Error creating indicator handles");
      return(INIT_FAILED);
   }

   // Set arrays as series
   ArraySetAsSeries(fastMA, true);
   ArraySetAsSeries(slowMA, true);

   Print("EA initialized successfully");
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Release indicator handles
   IndicatorRelease(handleFastMA);
   IndicatorRelease(handleSlowMA);
   Print("EA deinitialized. Reason: ", reason);
}

//+------------------------------------------------------------------+
//| Expert tick function                                               |
//+------------------------------------------------------------------+
void OnTick()
{
   // ตรวจสอบ New Bar
   if(!IsNewBar())
      return;

   // Copy indicator data
   if(CopyBuffer(handleFastMA, 0, 0, 3, fastMA) < 3) return;
   if(CopyBuffer(handleSlowMA, 0, 0, 3, slowMA) < 3) return;

   // Update Symbol Info
   symInfo.Name(_Symbol);
   symInfo.RefreshRates();

   // ตรวจสอบ Signal
   int signal = GetSignal();

   // จัดการ Positions
   ManagePositions(signal);

   // เปิด Position ใหม่
   if(signal != 0 && CountPositions() < InpMaxTrades)
      OpenPosition(signal);
}

//+------------------------------------------------------------------+
//| ตรวจสอบ New Bar                                                    |
//+------------------------------------------------------------------+
bool IsNewBar()
{
   static datetime lastBarTime = 0;
   datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);

   if(currentBarTime != lastBarTime)
   {
      lastBarTime = currentBarTime;
      return true;
   }
   return false;
}

//+------------------------------------------------------------------+
//| คำนวณ Signal                                                       |
//+------------------------------------------------------------------+
int GetSignal()
{
   // MA Crossover
   bool fastAboveSlow = fastMA[1] > slowMA[1];
   bool fastBelowSlow = fastMA[1] < slowMA[1];
   bool prevFastAbove = fastMA[2] > slowMA[2];
   bool prevFastBelow = fastMA[2] < slowMA[2];

   // Golden Cross — Buy Signal
   if(fastAboveSlow && prevFastBelow)
      return 1;

   // Death Cross — Sell Signal
   if(fastBelowSlow && prevFastAbove)
      return -1;

   return 0;
}

//+------------------------------------------------------------------+
//| เปิด Position                                                      |
//+------------------------------------------------------------------+
void OpenPosition(int signal)
{
   double price, sl, tp;
   double point = symInfo.Point();

   double lot = CalculateLotSize();
   if(lot <= 0) return;

   if(signal == 1) // Buy
   {
      price = symInfo.Ask();
      sl = price - InpStopLoss * point;
      tp = price + InpTakeProfit * point;
      trade.Buy(lot, _Symbol, price, sl, tp, "MA Cross Buy");
   }
   else if(signal == -1) // Sell
   {
      price = symInfo.Bid();
      sl = price + InpStopLoss * point;
      tp = price - InpTakeProfit * point;
      trade.Sell(lot, _Symbol, price, sl, tp, "MA Cross Sell");
   }

   if(trade.ResultRetcode() == TRADE_RETCODE_DONE)
      Print("Position opened: ", signal == 1 ? "BUY" : "SELL",
            " Lot: ", lot);
   else
      Print("Trade failed: ", trade.ResultRetcodeDescription());
}

//+------------------------------------------------------------------+
//| คำนวณ Lot Size ตาม Risk %                                         |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   double riskAmount = balance * InpMaxRisk / 100.0;
   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);

   if(tickValue == 0 || tickSize == 0) return InpLotSize;

   double lot = riskAmount / (InpStopLoss * tickValue / tickSize);

   // Normalize
   double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   lot = MathMax(minLot, MathMin(maxLot, lot));
   lot = MathRound(lot / lotStep) * lotStep;

   return NormalizeDouble(lot, 2);
}

//+------------------------------------------------------------------+
//| นับ Positions ของ EA นี้                                           |
//+------------------------------------------------------------------+
int CountPositions()
{
   int count = 0;
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(posInfo.SelectByIndex(i))
         if(posInfo.Symbol() == _Symbol && posInfo.Magic() == InpMagic)
            count++;
   }
   return count;
}

//+------------------------------------------------------------------+
//| จัดการ Positions (Trailing Stop)                                   |
//+------------------------------------------------------------------+
void ManagePositions(int signal)
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(!posInfo.SelectByIndex(i)) continue;
      if(posInfo.Symbol() != _Symbol || posInfo.Magic() != InpMagic) continue;

      // ปิด Position ถ้า Signal กลับทิศ
      if(posInfo.PositionType() == POSITION_TYPE_BUY && signal == -1)
         trade.PositionClose(posInfo.Ticket());
      else if(posInfo.PositionType() == POSITION_TYPE_SELL && signal == 1)
         trade.PositionClose(posInfo.Ticket());
   }
}

OOP Design Pattern สำหรับ MQL5

//+------------------------------------------------------------------+
//| TradingStrategy.mqh — Strategy Pattern สำหรับ MQL5               |
//+------------------------------------------------------------------+

// Base Strategy Interface
class CStrategy
{
protected:
   string         m_name;
   string         m_symbol;
   ENUM_TIMEFRAMES m_period;
   int            m_magic;

public:
   CStrategy(string name, string symbol, ENUM_TIMEFRAMES period, int magic)
      : m_name(name), m_symbol(symbol), m_period(period), m_magic(magic) {}

   virtual ~CStrategy() {}

   // Pure Virtual Methods — ต้อง Override
   virtual bool   Init()          = 0;
   virtual void   Deinit()        = 0;
   virtual int    GetSignal()     = 0;
   virtual double GetLotSize()    = 0;
   virtual double GetStopLoss(int signal)   = 0;
   virtual double GetTakeProfit(int signal) = 0;

   string GetName() { return m_name; }
};

// RSI Strategy Implementation
class CRSIStrategy : public CStrategy
{
private:
   int      m_rsiHandle;
   int      m_rsiPeriod;
   double   m_rsiOverbought;
   double   m_rsiOversold;
   double   m_rsiBuffer[];

public:
   CRSIStrategy(string symbol, ENUM_TIMEFRAMES period, int magic,
                int rsiPeriod=14, double ob=70, double os=30)
      : CStrategy("RSI Strategy", symbol, period, magic),
        m_rsiPeriod(rsiPeriod), m_rsiOverbought(ob), m_rsiOversold(os)
   {
      ArraySetAsSeries(m_rsiBuffer, true);
   }

   bool Init() override
   {
      m_rsiHandle = iRSI(m_symbol, m_period, m_rsiPeriod, PRICE_CLOSE);
      return (m_rsiHandle != INVALID_HANDLE);
   }

   void Deinit() override
   {
      IndicatorRelease(m_rsiHandle);
   }

   int GetSignal() override
   {
      if(CopyBuffer(m_rsiHandle, 0, 0, 3, m_rsiBuffer) < 3)
         return 0;

      // RSI Cross Oversold → Buy
      if(m_rsiBuffer[2] < m_rsiOversold && m_rsiBuffer[1] >= m_rsiOversold)
         return 1;

      // RSI Cross Overbought → Sell
      if(m_rsiBuffer[2] > m_rsiOverbought && m_rsiBuffer[1] <= m_rsiOverbought)
         return -1;

      return 0;
   }

   double GetLotSize() override { return 0.01; }
   double GetStopLoss(int signal) override { return 50 * _Point; }
   double GetTakeProfit(int signal) override { return 100 * _Point; }
};

// Strategy Manager — จัดการหลาย Strategies
class CStrategyManager
{
private:
   CStrategy* m_strategies[];
   CTrade     m_trade;

public:
   ~CStrategyManager()
   {
      for(int i = 0; i < ArraySize(m_strategies); i++)
         delete m_strategies[i];
   }

   void AddStrategy(CStrategy* strategy)
   {
      int size = ArraySize(m_strategies);
      ArrayResize(m_strategies, size + 1);
      m_strategies[size] = strategy;
   }

   bool InitAll()
   {
      for(int i = 0; i < ArraySize(m_strategies); i++)
         if(!m_strategies[i].Init())
            return false;
      return true;
   }

   void ProcessAll()
   {
      for(int i = 0; i < ArraySize(m_strategies); i++)
      {
         int signal = m_strategies[i].GetSignal();
         if(signal != 0)
            Print(m_strategies[i].GetName(), " Signal: ", signal);
      }
   }
};

Python — Backtest Analysis

# mt5_backtest.py — วิเคราะห์ผล Backtest จาก MT5
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
from datetime import datetime

class MT5BacktestAnalyzer:
    """วิเคราะห์ผลการเทรดจาก MetaTrader 5"""

    def __init__(self):
        if not mt5.initialize():
            raise RuntimeError(f"MT5 init failed: {mt5.last_error()}")

    def get_deals(self, from_date, to_date, magic=None):
        """ดึงประวัติการเทรด"""
        deals = mt5.history_deals_get(from_date, to_date)
        if deals is None:
            return pd.DataFrame()

        df = pd.DataFrame(list(deals), columns=deals[0]._asdict().keys())

        if magic:
            df = df[df["magic"] == magic]

        df["time"] = pd.to_datetime(df["time"], unit="s")
        return df

    def calculate_metrics(self, deals_df):
        """คำนวณ Performance Metrics"""
        trades = deals_df[deals_df["entry"] == 1]  # Exit deals

        if len(trades) == 0:
            return {}

        profits = trades["profit"].values
        wins = profits[profits > 0]
        losses = profits[profits < 0]

        total_profit = profits.sum()
        win_rate = len(wins) / len(profits) * 100
        avg_win = wins.mean() if len(wins) > 0 else 0
        avg_loss = abs(losses.mean()) if len(losses) > 0 else 0
        profit_factor = wins.sum() / abs(losses.sum()) if len(losses) > 0 else float("inf")

        # Max Drawdown
        cumulative = np.cumsum(profits)
        peak = np.maximum.accumulate(cumulative)
        drawdown = peak - cumulative
        max_dd = drawdown.max()

        # Sharpe Ratio (annualized)
        daily_returns = pd.Series(profits).groupby(
            trades["time"].dt.date
        ).sum()
        sharpe = (daily_returns.mean() / daily_returns.std() *
                  np.sqrt(252)) if daily_returns.std() > 0 else 0

        return {
            "Total Trades": len(profits),
            "Win Rate": f"{win_rate:.1f}%",
            "Total Profit": f"",
            "Avg Win": f"",
            "Avg Loss": f"",
            "Profit Factor": f"{profit_factor:.2f}",
            "Max Drawdown": f"",
            "Sharpe Ratio": f"{sharpe:.2f}",
            "Expectancy": f"",
        }

    def print_report(self, metrics):
        """แสดงรายงาน"""
        print("=" * 40)
        print("Backtest Performance Report")
        print("=" * 40)
        for key, value in metrics.items():
            print(f"  {key:<20} {value}")

    def __del__(self):
        mt5.shutdown()

# ตัวอย่าง
# analyzer = MT5BacktestAnalyzer()
# deals = analyzer.get_deals(
#     datetime(2024, 1, 1), datetime(2024, 12, 31), magic=12345
# )
# metrics = analyzer.calculate_metrics(deals)
# analyzer.print_report(metrics)

แหล่งเรียนรู้ MQL5

MQL5 คืออะไร

MQL5 เป็นภาษาโปรแกรมสำหรับ MetaTrader 5 ใช้เขียน Expert Advisors, Custom Indicators, Scripts ไวยากรณ์คล้าย C++ รองรับ OOP เต็มรูปแบบ มี Standard Library และ Strategy Tester ที่ทรงพลัง

MQL5 ต่างจาก MQL4 อย่างไร

MQL5 รองรับ OOP เต็มรูปแบบ มี Event-driven Model ดีกว่า รองรับ Netting และ Hedging, Multi-currency Tester, Built-in Indicators มากกว่า ประสิทธิภาพสูงกว่า MQL4 ที่เป็น Procedural เป็นหลัก

เริ่มต้นเรียน MQL5 ต้องทำอย่างไร

ดาวน์โหลด MT5 เปิด MetaEditor เริ่มจากโครงสร้างโปรแกรม OnInit OnTick OnDeinit ฝึกเขียน Script ง่ายๆ ค่อยเขียน Indicator แล้ว EA ศึกษาจาก MQL5 Reference และ CodeBase

Strategy Tester ใน MT5 ใช้งานอย่างไร

เปิด Strategy Tester (Ctrl+R) เลือก EA Symbol Period Date Range เลือก Modeling Mode รัน Backtest ดู Report ใช้ Optimization หา Parameter ที่ดีที่สุด รองรับ Multi-currency และ Forward Testing

สรุป

MQL5 เป็นภาษาที่ทรงพลังสำหรับพัฒนา Trading Applications บน MetaTrader 5 รองรับ OOP เต็มรูปแบบ มี Standard Library ที่ครบครัน Strategy Tester ที่ดีเยี่ยม เริ่มจากเรียนรู้โครงสร้างพื้นฐาน แล้วใช้ OOP Design Patterns เขียน Code ที่ดูแลรักษาง่าย ใช้ Python ร่วมกับ MetaTrader5 Library สำหรับ Data Analysis และ Backtest Evaluation

📖 บทความที่เกี่ยวข้อง

arimbi mql5อ่านบทความ → copy trade mql5อ่านบทความ → smart money concepts bookอ่านบทความ → candlestick patterns bookอ่านบทความ → smart money concept bookอ่านบทความ →

📚 ดูบทความทั้งหมด →