SiamCafe.net Blog
Technology

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

mql5 tutorial
MQL5 Tutorial — คู่มือเทรด Forex ฉบับสมบูรณ์ 2026 | SiamCafe Blog
2026-05-02· อ. บอม — SiamCafe.net· 1,792 คำ

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

MQL5 (MetaQuotes Language 5) เป็นภาษา programming สำหรับเขียน Expert Advisors (EA), indicators และ scripts บน MetaTrader 5 ซึ่งเป็น trading platform ยอดนิยมสำหรับ Forex, CFDs, futures และ stocks MQL5 เป็นภาษาที่คล้าย C++ รองรับ OOP (Object-Oriented Programming) มี built-in functions สำหรับ technical analysis, order management และ chart operations บทความนี้เป็นคู่มือ MQL5 ฉบับสมบูรณ์ ตั้งแต่พื้นฐานจนถึง advanced EA development

MQL5 Basics

//+------------------------------------------------------------------+
//| mql5_basics.mq5 — MQL5 fundamentals                              |
//+------------------------------------------------------------------+

// 1. Data Types
void DataTypes()
{
    int    count    = 10;           // Integer
    double price    = 1.08523;     // Double (price)
    string symbol   = "EURUSD";    // String
    bool   isActive = true;        // Boolean
    datetime now    = TimeCurrent(); // Date/time
    
    // Arrays
    double prices[];
    ArrayResize(prices, 100);
    
    // Enumerations
    ENUM_TIMEFRAMES tf = PERIOD_H1;  // 1-hour timeframe
    ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY;
}

// 2. Getting Market Data
void MarketData()
{
    // Current price
    double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    double spread = ask - bid;
    
    // OHLC data
    double open  = iOpen(_Symbol, PERIOD_H1, 0);   // Current bar open
    double high  = iHigh(_Symbol, PERIOD_H1, 0);   // Current bar high
    double low   = iLow(_Symbol, PERIOD_H1, 0);    // Current bar low
    double close = iClose(_Symbol, PERIOD_H1, 1);  // Previous bar close
    
    // Volume
    long volume = iVolume(_Symbol, PERIOD_H1, 0);
    
    // Account info
    double balance  = AccountInfoDouble(ACCOUNT_BALANCE);
    double equity   = AccountInfoDouble(ACCOUNT_EQUITY);
    double margin   = AccountInfoDouble(ACCOUNT_MARGIN);
    
    PrintFormat("Ask: %.5f | Bid: %.5f | Spread: %.1f pips",
                ask, bid, spread / _Point / 10);
}

// 3. Technical Indicators
void Indicators()
{
    // Moving Average
    int ma_handle = iMA(_Symbol, PERIOD_H1, 20, 0, MODE_SMA, PRICE_CLOSE);
    double ma_buffer[];
    CopyBuffer(ma_handle, 0, 0, 3, ma_buffer);
    
    // RSI
    int rsi_handle = iRSI(_Symbol, PERIOD_H1, 14, PRICE_CLOSE);
    double rsi_buffer[];
    CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer);
    
    // MACD
    int macd_handle = iMACD(_Symbol, PERIOD_H1, 12, 26, 9, PRICE_CLOSE);
    double macd_main[], macd_signal[];
    CopyBuffer(macd_handle, 0, 0, 3, macd_main);
    CopyBuffer(macd_handle, 1, 0, 3, macd_signal);
    
    PrintFormat("MA(20): %.5f | RSI(14): %.1f | MACD: %.5f",
                ma_buffer[0], rsi_buffer[0], macd_main[0]);
}

Expert Advisor (EA) Development

//+------------------------------------------------------------------+
//| simple_ea.mq5 — Simple Moving Average Crossover EA               |
//+------------------------------------------------------------------+
#property copyright "MQL5 Tutorial"
#property version   "1.00"

// Input parameters
input int    FastMA_Period = 10;       // Fast MA Period
input int    SlowMA_Period = 20;       // Slow MA Period
input double LotSize       = 0.01;    // Lot Size
input int    StopLoss      = 100;     // Stop Loss (points)
input int    TakeProfit    = 200;     // Take Profit (points)
input int    MagicNumber   = 12345;   // Magic Number

// Global variables
int fast_ma_handle, slow_ma_handle;
double fast_ma[], slow_ma[];

//+------------------------------------------------------------------+
//| Expert initialization                                             |
//+------------------------------------------------------------------+
int OnInit()
{
    fast_ma_handle = iMA(_Symbol, PERIOD_CURRENT, FastMA_Period, 0, MODE_SMA, PRICE_CLOSE);
    slow_ma_handle = iMA(_Symbol, PERIOD_CURRENT, SlowMA_Period, 0, MODE_SMA, PRICE_CLOSE);
    
    if(fast_ma_handle == INVALID_HANDLE || slow_ma_handle == INVALID_HANDLE)
    {
        Print("Error creating MA indicators");
        return INIT_FAILED;
    }
    
    ArraySetAsSeries(fast_ma, true);
    ArraySetAsSeries(slow_ma, true);
    
    Print("EA initialized successfully");
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick()
{
    // Copy indicator values
    if(CopyBuffer(fast_ma_handle, 0, 0, 3, fast_ma) < 3) return;
    if(CopyBuffer(slow_ma_handle, 0, 0, 3, slow_ma) < 3) return;
    
    // Check for crossover (using previous completed bars)
    bool bullish_cross = fast_ma[1] > slow_ma[1] && fast_ma[2] <= slow_ma[2];
    bool bearish_cross = fast_ma[1] < slow_ma[1] && fast_ma[2] >= slow_ma[2];
    
    // Check if we have open positions
    bool has_buy  = HasPosition(POSITION_TYPE_BUY);
    bool has_sell = HasPosition(POSITION_TYPE_SELL);
    
    // Trading logic
    if(bullish_cross && !has_buy)
    {
        if(has_sell) CloseAllPositions(POSITION_TYPE_SELL);
        OpenPosition(ORDER_TYPE_BUY);
    }
    else if(bearish_cross && !has_sell)
    {
        if(has_buy) CloseAllPositions(POSITION_TYPE_BUY);
        OpenPosition(ORDER_TYPE_SELL);
    }
}

//+------------------------------------------------------------------+
//| Open a position                                                   |
//+------------------------------------------------------------------+
bool OpenPosition(ENUM_ORDER_TYPE type)
{
    MqlTradeRequest request = {};
    MqlTradeResult  result  = {};
    
    double price = (type == ORDER_TYPE_BUY) ? 
                   SymbolInfoDouble(_Symbol, SYMBOL_ASK) :
                   SymbolInfoDouble(_Symbol, SYMBOL_BID);
    
    double sl = (type == ORDER_TYPE_BUY) ?
                price - StopLoss * _Point :
                price + StopLoss * _Point;
    
    double tp = (type == ORDER_TYPE_BUY) ?
                price + TakeProfit * _Point :
                price - TakeProfit * _Point;
    
    request.action    = TRADE_ACTION_DEAL;
    request.symbol    = _Symbol;
    request.volume    = LotSize;
    request.type      = type;
    request.price     = price;
    request.sl        = sl;
    request.tp        = tp;
    request.magic     = MagicNumber;
    request.deviation = 10;
    request.comment   = "MA Crossover EA";
    
    if(!OrderSend(request, result))
    {
        PrintFormat("OrderSend error: %d", GetLastError());
        return false;
    }
    
    PrintFormat("Position opened: %s at %.5f, SL: %.5f, TP: %.5f",
                EnumToString(type), price, sl, tp);
    return true;
}

//+------------------------------------------------------------------+
//| Check if position exists                                          |
//+------------------------------------------------------------------+
bool HasPosition(ENUM_POSITION_TYPE type)
{
    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if(PositionGetSymbol(i) == _Symbol &&
           PositionGetInteger(POSITION_MAGIC) == MagicNumber &&
           PositionGetInteger(POSITION_TYPE) == type)
            return true;
    }
    return false;
}

//+------------------------------------------------------------------+
//| Close all positions of given type                                 |
//+------------------------------------------------------------------+
void CloseAllPositions(ENUM_POSITION_TYPE type)
{
    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if(PositionGetSymbol(i) == _Symbol &&
           PositionGetInteger(POSITION_MAGIC) == MagicNumber &&
           PositionGetInteger(POSITION_TYPE) == type)
        {
            ulong ticket = PositionGetInteger(POSITION_TICKET);
            MqlTradeRequest request = {};
            MqlTradeResult  result  = {};
            
            request.action = TRADE_ACTION_DEAL;
            request.symbol = _Symbol;
            request.volume = PositionGetDouble(POSITION_VOLUME);
            request.type   = (type == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
            request.price  = (type == POSITION_TYPE_BUY) ?
                             SymbolInfoDouble(_Symbol, SYMBOL_BID) :
                             SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            request.position = ticket;
            request.deviation = 10;
            
            OrderSend(request, result);
        }
    }
}

Risk Management

//+------------------------------------------------------------------+
//| risk_management.mq5 — Position sizing and risk management        |
//+------------------------------------------------------------------+

class CRiskManager
{
private:
    double m_riskPercent;
    int    m_maxPositions;
    double m_maxDrawdown;
    
public:
    CRiskManager(double riskPct=1.0, int maxPos=3, double maxDD=10.0)
    {
        m_riskPercent  = riskPct;
        m_maxPositions = maxPos;
        m_maxDrawdown  = maxDD;
    }
    
    // Calculate lot size based on risk percentage
    double CalculateLotSize(string symbol, double slPoints)
    {
        double balance    = AccountInfoDouble(ACCOUNT_BALANCE);
        double riskAmount = balance * m_riskPercent / 100.0;
        
        double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
        double tickSize  = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
        double pointValue = tickValue / tickSize * _Point;
        
        double lotSize = riskAmount / (slPoints * pointValue);
        
        // Normalize lot size
        double minLot  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
        double maxLot  = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
        double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
        
        lotSize = MathFloor(lotSize / lotStep) * lotStep;
        lotSize = MathMax(minLot, MathMin(maxLot, lotSize));
        
        return lotSize;
    }
    
    // Check if we can open new position
    bool CanOpenPosition()
    {
        // Max positions check
        if(PositionsTotal() >= m_maxPositions)
        {
            Print("Max positions reached");
            return false;
        }
        
        // Drawdown check
        double balance = AccountInfoDouble(ACCOUNT_BALANCE);
        double equity  = AccountInfoDouble(ACCOUNT_EQUITY);
        double dd = (balance - equity) / balance * 100;
        
        if(dd >= m_maxDrawdown)
        {
            PrintFormat("Max drawdown reached: %.1f%%", dd);
            return false;
        }
        
        // Margin check
        double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
        if(freeMargin < 100)
        {
            Print("Insufficient free margin");
            return false;
        }
        
        return true;
    }
    
    // Calculate trailing stop
    double TrailingStop(ulong ticket, double trailPoints)
    {
        if(!PositionSelectByTicket(ticket)) return 0;
        
        double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
        double currentSL = PositionGetDouble(POSITION_SL);
        double currentPrice;
        
        if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
        {
            currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            double newSL = currentPrice - trailPoints * _Point;
            
            if(newSL > currentSL && newSL > openPrice)
                return newSL;
        }
        else
        {
            currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            double newSL = currentPrice + trailPoints * _Point;
            
            if((newSL < currentSL || currentSL == 0) && newSL < openPrice)
                return newSL;
        }
        
        return 0;  // No update needed
    }
};

Backtesting & Optimization

# backtesting.py — Python analysis of MQL5 backtest results
import json
import random

class BacktestAnalysis:
    CODE = """
# analyze_backtest.py — Analyze MT5 backtest results
import pandas as pd
import numpy as np
from datetime import datetime

class BacktestAnalyzer:
    def __init__(self, trades_csv):
        self.df = pd.read_csv(trades_csv)
        self.df['time'] = pd.to_datetime(self.df['time'])
    
    def calculate_metrics(self):
        profits = self.df['profit']
        
        total_trades = len(profits)
        winners = profits[profits > 0]
        losers = profits[profits < 0]
        
        win_rate = len(winners) / total_trades * 100
        avg_win = winners.mean() if len(winners) > 0 else 0
        avg_loss = abs(losers.mean()) if len(losers) > 0 else 0
        
        profit_factor = winners.sum() / abs(losers.sum()) if losers.sum() != 0 else float('inf')
        
        # Maximum drawdown
        cumulative = profits.cumsum()
        peak = cumulative.cummax()
        drawdown = (cumulative - peak)
        max_dd = drawdown.min()
        
        # Sharpe ratio (annualized)
        daily_returns = profits.resample('D', on=self.df['time']).sum() if 'time' in self.df else profits
        sharpe = np.sqrt(252) * daily_returns.mean() / daily_returns.std() if daily_returns.std() > 0 else 0
        
        return {
            'total_trades': total_trades,
            'win_rate': round(win_rate, 1),
            'profit_factor': round(profit_factor, 2),
            'avg_win': round(avg_win, 2),
            'avg_loss': round(avg_loss, 2),
            'max_drawdown': round(max_dd, 2),
            'net_profit': round(profits.sum(), 2),
            'sharpe_ratio': round(sharpe, 2),
        }

# analyzer = BacktestAnalyzer('backtest_results.csv')
# metrics = analyzer.calculate_metrics()
# print(json.dumps(metrics, indent=2))
"""

    def show_code(self):
        print("=== Backtest Analyzer ===")
        print(self.CODE[:600])

    def sample_results(self):
        print(f"\n=== Sample Backtest Results (MA Crossover EA) ===")
        print(f"  Period: 2024-01-01 to 2024-12-31")
        print(f"  Symbol: EURUSD H1")
        print(f"  Total trades: {random.randint(80, 200)}")
        print(f"  Win rate: {random.uniform(45, 65):.1f}%")
        print(f"  Profit factor: {random.uniform(1.1, 2.5):.2f}")
        print(f"  Net profit: ")
        print(f"  Max drawdown: ")
        print(f"  Sharpe ratio: {random.uniform(0.5, 2.0):.2f}")

bt = BacktestAnalysis()
bt.show_code()
bt.sample_results()

Advanced Topics

# advanced.py — Advanced MQL5 topics
import json

class AdvancedMQL5:
    TOPICS = {
        "multi_tf": {
            "name": "Multi-Timeframe Analysis",
            "description": "วิเคราะห์หลาย timeframes — trend จาก Daily, entry จาก H1, timing จาก ",
            "tip": "ใช้ iMA/iRSI กับ timeframe ต่างกัน → confirm ก่อน entry",
        },
        "news_filter": {
            "name": "News Event Filter",
            "description": "หยุดเทรดก่อน/หลัง high-impact news — ป้องกัน volatility spike",
            "tip": "ใช้ MQL5 Calendar functions: CalendarValueHistory()",
        },
        "portfolio": {
            "name": "Portfolio EA (Multi-Symbol)",
            "description": "เทรดหลายคู่เงินพร้อมกัน — diversification ลด risk",
            "tip": "ใช้ OnTimer() + loop ผ่าน symbols array",
        },
        "ml_integration": {
            "name": "Machine Learning Integration",
            "description": "ส่ง data จาก MT5 ไป Python → ML predict → ส่ง signal กลับ",
            "tip": "ใช้ MetaTrader5 Python package: pip install MetaTrader5",
        },
        "custom_indicator": {
            "name": "Custom Indicators",
            "description": "สร้าง indicator เอง — plot บน chart, ใช้ใน EA",
            "tip": "ใช้ OnCalculate() + SetIndexBuffer() สำหรับ custom indicator",
        },
    }

    PYTHON_MT5 = """
# python_mt5.py — Python integration with MetaTrader 5
import MetaTrader5 as mt5
import pandas as pd

# Initialize MT5
mt5.initialize()

# Get account info
account = mt5.account_info()
print(f"Balance: {account.balance}, Equity: {account.equity}")

# Get OHLCV data
rates = mt5.copy_rates_from_pos("EURUSD", mt5.TIMEFRAME_H1, 0, 1000)
df = pd.DataFrame(rates)
df['time'] = pd.to_datetime(df['time'], unit='s')

# Send order
request = {
    "action": mt5.TRADE_ACTION_DEAL,
    "symbol": "EURUSD",
    "volume": 0.01,
    "type": mt5.ORDER_TYPE_BUY,
    "price": mt5.symbol_info_tick("EURUSD").ask,
    "sl": mt5.symbol_info_tick("EURUSD").ask - 0.0050,
    "tp": mt5.symbol_info_tick("EURUSD").ask + 0.0100,
    "comment": "Python EA",
}
result = mt5.order_send(request)
print(f"Order: {result.comment}")

mt5.shutdown()
"""

    def show_topics(self):
        print("=== Advanced Topics ===\n")
        for key, topic in self.TOPICS.items():
            print(f"[{topic['name']}]")
            print(f"  {topic['description']}")
            print()

    def show_python(self):
        print("=== Python + MT5 ===")
        print(self.PYTHON_MT5[:500])

adv = AdvancedMQL5()
adv.show_topics()
adv.show_python()

FAQ - คำถามที่พบบ่อย

Q: MQL5 เรียนยากไหม?

A: ปานกลาง — ถ้ามีพื้นฐาน C/C++/Java จะเรียนเร็ว ถ้าเป็นมือใหม่: ใช้เวลา 2-4 สัปดาห์สำหรับ basics, 2-3 เดือนสำหรับ EA development แหล่งเรียน: mql5.com/docs (official), YouTube tutorials, MQL5 forum เริ่มจาก: Script ง่ายๆ → Custom Indicator → Simple EA → Advanced EA

Q: EA ทำกำไรได้จริงไหม?

A: ได้ แต่ไม่ง่าย: EA ส่วนใหญ่ที่ขายตาม market = ไม่ทำกำไรระยะยาว สิ่งสำคัญ: backtest ดี ≠ forward test ดี (overfitting) ต้อง: risk management ดี, walk-forward optimization, realistic expectations คำแนะนำ: อย่าหวังรวยเร็ว, เริ่มจาก demo account, ทดสอบอย่างน้อย 6 เดือน

Q: MQL5 กับ Pine Script อันไหนดี?

A: MQL5: full programming language, OOP, เขียน EA auto-trade ได้, backtesting ครบ Pine Script (TradingView): ง่ายกว่า, visualization ดี, community ใหญ่, แต่ auto-trade จำกัด เลือก MQL5: ถ้าต้องการ automated trading จริงจัง เลือก Pine Script: ถ้าต้องการ indicator + manual trading + charting

Q: ใช้ Python แทน MQL5 ได้ไหม?

A: ได้บางส่วน: Python + MetaTrader5 package: ดึงข้อมูล, ส่ง orders, backtest ด้วย Python libraries ข้อดี Python: ML/AI libraries (scikit-learn, TensorFlow), data analysis (pandas) ข้อจำกัด: ต้องรัน Python script แยก, latency สูงกว่า native MQL5 แนะนำ: ใช้ร่วมกัน — Python สำหรับ analysis/ML, MQL5 สำหรับ execution

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

copy trade mql5อ่านบทความ → mql5 web terminalอ่านบทความ → forex trade tutorial for beginnersอ่านบทความ → day trading tutorialอ่านบทความ → mql5 codingอ่านบทความ →

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