รวมตัวอย่าง Code MQL4
MQL4 เป็นภาษาโปรแกรมสำหรับ MetaTrader 4 ที่ใช้เขียน Expert Advisors (EA), Custom Indicators และ Scripts บทความนี้รวมตัวอย่าง Code ที่ใช้งานบ่อยที่สุด พร้อมคำอธิบายทีละบรรทัด สามารถนำไปใช้งานได้ทันที
ตัวอย่างครอบคลุม Order Management, Custom Indicators, Risk Management, Multi-timeframe Analysis และ Utility Functions ที่จำเป็นสำหรับทุก EA
Order Management Functions
//+------------------------------------------------------------------+
//| OrderManager.mqh — ฟังก์ชันจัดการ Orders |
//+------------------------------------------------------------------+
#property strict
// Magic Number สำหรับแยก Orders ของ EA นี้
#define EA_MAGIC 20250101
//+------------------------------------------------------------------+
//| เปิด Buy Order |
//+------------------------------------------------------------------+
int OpenBuy(double lots, int slPips, int tpPips, string comment="")
{
double price = Ask;
double point = MarketInfo(Symbol(), MODE_POINT);
int digits = (int)MarketInfo(Symbol(), MODE_DIGITS);
// ปรับ Point สำหรับ 5-digit broker
double pip = (digits == 3 || digits == 5) ? point * 10 : point;
double sl = (slPips > 0) ? NormalizeDouble(price - slPips * pip, digits) : 0;
double tp = (tpPips > 0) ? NormalizeDouble(price + tpPips * pip, digits) : 0;
int ticket = OrderSend(Symbol(), OP_BUY, lots, price, 3,
sl, tp, comment, EA_MAGIC, 0, clrGreen);
if(ticket > 0)
Print("Buy opened: Ticket=", ticket, " Lots=", lots,
" Price=", price, " SL=", sl, " TP=", tp);
else
Print("Buy failed: Error=", GetLastError());
return ticket;
}
//+------------------------------------------------------------------+
//| เปิด Sell Order |
//+------------------------------------------------------------------+
int OpenSell(double lots, int slPips, int tpPips, string comment="")
{
double price = Bid;
double point = MarketInfo(Symbol(), MODE_POINT);
int digits = (int)MarketInfo(Symbol(), MODE_DIGITS);
double pip = (digits == 3 || digits == 5) ? point * 10 : point;
double sl = (slPips > 0) ? NormalizeDouble(price + slPips * pip, digits) : 0;
double tp = (tpPips > 0) ? NormalizeDouble(price - tpPips * pip, digits) : 0;
int ticket = OrderSend(Symbol(), OP_SELL, lots, price, 3,
sl, tp, comment, EA_MAGIC, 0, clrRed);
if(ticket > 0)
Print("Sell opened: Ticket=", ticket);
else
Print("Sell failed: Error=", GetLastError());
return ticket;
}
//+------------------------------------------------------------------+
//| ปิด Order ทั้งหมดของ Symbol นี้ |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != EA_MAGIC) continue;
bool result = false;
if(OrderType() == OP_BUY)
result = OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrYellow);
else if(OrderType() == OP_SELL)
result = OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrYellow);
if(!result)
Print("Close failed: Ticket=", OrderTicket(), " Error=", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Trailing Stop |
//+------------------------------------------------------------------+
void TrailingStop(int trailPips, int trailStep=1)
{
double point = MarketInfo(Symbol(), MODE_POINT);
int digits = (int)MarketInfo(Symbol(), MODE_DIGITS);
double pip = (digits == 3 || digits == 5) ? point * 10 : point;
double trailDistance = trailPips * pip;
double stepDistance = trailStep * pip;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != EA_MAGIC) continue;
if(OrderType() == OP_BUY)
{
double newSL = NormalizeDouble(Bid - trailDistance, digits);
if(Bid - OrderOpenPrice() > trailDistance)
{
if(OrderStopLoss() < newSL - stepDistance || OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL,
OrderTakeProfit(), 0, clrGreen);
}
}
else if(OrderType() == OP_SELL)
{
double newSL = NormalizeDouble(Ask + trailDistance, digits);
if(OrderOpenPrice() - Ask > trailDistance)
{
if(OrderStopLoss() > newSL + stepDistance || OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL,
OrderTakeProfit(), 0, clrRed);
}
}
}
}
//+------------------------------------------------------------------+
//| Break Even — ย้าย SL ไปที่จุดเปิด |
//+------------------------------------------------------------------+
void BreakEven(int triggerPips, int lockPips=1)
{
double point = MarketInfo(Symbol(), MODE_POINT);
int digits = (int)MarketInfo(Symbol(), MODE_DIGITS);
double pip = (digits == 3 || digits == 5) ? point * 10 : point;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != EA_MAGIC) continue;
if(OrderType() == OP_BUY)
{
if(Bid - OrderOpenPrice() >= triggerPips * pip)
{
double newSL = NormalizeDouble(OrderOpenPrice() + lockPips * pip, digits);
if(OrderStopLoss() < newSL)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL,
OrderTakeProfit(), 0, clrBlue);
}
}
else if(OrderType() == OP_SELL)
{
if(OrderOpenPrice() - Ask >= triggerPips * pip)
{
double newSL = NormalizeDouble(OrderOpenPrice() - lockPips * pip, digits);
if(OrderStopLoss() > newSL || OrderStopLoss() == 0)
OrderModify(OrderTicket(), OrderOpenPrice(), newSL,
OrderTakeProfit(), 0, clrBlue);
}
}
}
}
//+------------------------------------------------------------------+
//| นับ Orders ตาม Type |
//+------------------------------------------------------------------+
int CountOrders(int orderType=-1)
{
int count = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != EA_MAGIC) continue;
if(orderType == -1 || OrderType() == orderType)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| คำนวณ Total Profit ของ Orders ที่เปิดอยู่ |
//+------------------------------------------------------------------+
double TotalProfit()
{
double profit = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != EA_MAGIC) continue;
profit += OrderProfit() + OrderSwap() + OrderCommission();
}
return profit;
}
Risk Management และ Position Sizing
//+------------------------------------------------------------------+
//| RiskManager.mqh — Risk Management Functions |
//+------------------------------------------------------------------+
#property strict
//+------------------------------------------------------------------+
//| คำนวณ Lot Size ตาม Risk % |
//+------------------------------------------------------------------+
double CalcLotByRisk(double riskPercent, int slPips)
{
// คำนวณจำนวนเงินที่ยอมเสีย
double balance = AccountBalance();
double riskAmount = balance * riskPercent / 100.0;
// ดึงข้อมูล Symbol
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
double tickSize = MarketInfo(Symbol(), MODE_TICKSIZE);
double point = MarketInfo(Symbol(), MODE_POINT);
int digits = (int)MarketInfo(Symbol(), MODE_DIGITS);
// ปรับสำหรับ 5-digit
double pip = (digits == 3 || digits == 5) ? point * 10 : point;
double pipValue = tickValue * pip / tickSize;
// คำนวณ Lot
double lot = 0;
if(pipValue > 0 && slPips > 0)
lot = riskAmount / (slPips * pipValue);
// Normalize ตาม Broker
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
lot = MathMax(minLot, MathMin(maxLot, lot));
lot = NormalizeDouble(MathFloor(lot / lotStep) * lotStep, 2);
return lot;
}
//+------------------------------------------------------------------+
//| คำนวณ Max Drawdown |
//+------------------------------------------------------------------+
double CalcMaxDrawdown()
{
double peak = 0;
double maxDD = 0;
double balance = AccountBalance();
for(int i = OrdersHistoryTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
if(OrderMagicNumber() != EA_MAGIC) continue;
balance += OrderProfit() + OrderSwap() + OrderCommission();
if(balance > peak) peak = balance;
double dd = (peak - balance) / peak * 100;
if(dd > maxDD) maxDD = dd;
}
return maxDD;
}
//+------------------------------------------------------------------+
//| ตรวจสอบว่าปลอดภัยที่จะเทรดหรือไม่ |
//+------------------------------------------------------------------+
bool IsSafeToTrade(double maxDDPercent=30, int maxOrders=5)
{
// ตรวจสอบ Drawdown
double equity = AccountEquity();
double balance = AccountBalance();
double currentDD = (balance - equity) / balance * 100;
if(currentDD >= maxDDPercent)
{
Print("Trading paused: Drawdown ", DoubleToStr(currentDD, 1),
"% exceeds limit ", DoubleToStr(maxDDPercent, 1), "%");
return false;
}
// ตรวจสอบจำนวน Orders
if(CountOrders() >= maxOrders)
{
Print("Max orders reached: ", CountOrders());
return false;
}
// ตรวจสอบ Free Margin
double freeMargin = AccountFreeMargin();
if(freeMargin < 100)
{
Print("Low free margin: ", DoubleToStr(freeMargin, 2));
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| สรุปผลการเทรด |
//+------------------------------------------------------------------+
void PrintTradeReport()
{
int totalTrades = 0, wins = 0, losses = 0;
double totalProfit = 0, totalLoss = 0;
double grossProfit = 0, grossLoss = 0;
for(int i = OrdersHistoryTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
if(OrderMagicNumber() != EA_MAGIC) continue;
if(OrderType() > OP_SELL) continue; // ข้าม Pending Orders
totalTrades++;
double profit = OrderProfit() + OrderSwap() + OrderCommission();
if(profit >= 0)
{
wins++;
grossProfit += profit;
}
else
{
losses++;
grossLoss += MathAbs(profit);
}
}
double winRate = totalTrades > 0 ? (double)wins / totalTrades * 100 : 0;
double profitFactor = grossLoss > 0 ? grossProfit / grossLoss : 0;
double netProfit = grossProfit - grossLoss;
Print("=== Trade Report ===");
Print("Total Trades: ", totalTrades);
Print("Win Rate: ", DoubleToStr(winRate, 1), "%");
Print("Net Profit: $", DoubleToStr(netProfit, 2));
Print("Profit Factor: ", DoubleToStr(profitFactor, 2));
Print("Max Drawdown: ", DoubleToStr(CalcMaxDrawdown(), 1), "%");
}
Custom Indicator ตัวอย่าง
//+------------------------------------------------------------------+
//| TrendStrength.mq4 — Custom Indicator วัดความแรงของ Trend |
//+------------------------------------------------------------------+
#property strict
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 clrDodgerBlue // Trend Strength
#property indicator_color2 clrLime // Bullish Signal
#property indicator_color3 clrRed // Bearish Signal
#property indicator_width1 2
input int InpPeriod = 14; // Period
input int InpSmoothing = 3; // Smoothing
double TrendBuffer[];
double BullBuffer[];
double BearBuffer[];
int OnInit()
{
SetIndexBuffer(0, TrendBuffer);
SetIndexBuffer(1, BullBuffer);
SetIndexBuffer(2, BearBuffer);
SetIndexStyle(0, DRAW_LINE);
SetIndexStyle(1, DRAW_HISTOGRAM);
SetIndexStyle(2, DRAW_HISTOGRAM);
SetIndexLabel(0, "Trend Strength");
SetIndexLabel(1, "Bullish");
SetIndexLabel(2, "Bearish");
IndicatorShortName("Trend Strength (" + IntegerToString(InpPeriod) + ")");
return(INIT_SUCCEEDED);
}
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
int limit = rates_total - prev_calculated;
if(prev_calculated == 0) limit = rates_total - InpPeriod - InpSmoothing;
for(int i = limit - 1; i >= 0; i--)
{
// คำนวณ Directional Movement
double upMove = 0, downMove = 0;
for(int j = 0; j < InpPeriod; j++)
{
int idx = i + j;
if(idx + 1 >= rates_total) continue;
double diff = close[idx] - close[idx + 1];
if(diff > 0)
upMove += diff;
else
downMove += MathAbs(diff);
}
// Trend Strength = (UpMove - DownMove) / (UpMove + DownMove) * 100
double total = upMove + downMove;
double strength = (total > 0) ? (upMove - downMove) / total * 100 : 0;
TrendBuffer[i] = strength;
// Signal Bars
if(strength > 0)
{
BullBuffer[i] = strength;
BearBuffer[i] = 0;
}
else
{
BullBuffer[i] = 0;
BearBuffer[i] = strength;
}
}
return(rates_total);
}
Multi-timeframe Analysis
//+------------------------------------------------------------------+
//| MTFSignal.mqh — Multi-timeframe Signal Analysis |
//+------------------------------------------------------------------+
#property strict
// ตรวจสอบ Trend จากหลาย Timeframe
int GetMTFSignal()
{
int bullCount = 0;
int bearCount = 0;
int timeframes[] = {PERIOD_M15, PERIOD_H1, PERIOD_H4, PERIOD_D1};
for(int t = 0; t < ArraySize(timeframes); t++)
{
double ma20 = iMA(Symbol(), timeframes[t], 20, 0, MODE_EMA, PRICE_CLOSE, 0);
double ma50 = iMA(Symbol(), timeframes[t], 50, 0, MODE_EMA, PRICE_CLOSE, 0);
double price = iClose(Symbol(), timeframes[t], 0);
// Price above both MAs = Bullish
if(price > ma20 && ma20 > ma50)
bullCount++;
// Price below both MAs = Bearish
else if(price < ma20 && ma20 < ma50)
bearCount++;
}
// ต้องอย่างน้อย 3 จาก 4 Timeframes เห็นด้วย
if(bullCount >= 3) return 1; // Strong Buy
if(bearCount >= 3) return -1; // Strong Sell
return 0; // No Clear Signal
}
// ตรวจสอบ Key Level จาก Daily
bool IsNearDailyLevel(double &support, double &resistance)
{
double dayHigh = iHigh(Symbol(), PERIOD_D1, 1);
double dayLow = iLow(Symbol(), PERIOD_D1, 1);
double dayClose = iClose(Symbol(), PERIOD_D1, 1);
// Pivot Points
double pp = (dayHigh + dayLow + dayClose) / 3;
support = 2 * pp - dayHigh;
resistance = 2 * pp - dayLow;
double price = Bid;
double pip = MarketInfo(Symbol(), MODE_POINT) * 10;
double threshold = 10 * pip; // ภายใน 10 pips
return (MathAbs(price - support) < threshold ||
MathAbs(price - resistance) < threshold);
}
MQL4 Code Examples มีอะไรบ้าง
รวม Code สำหรับ Order Management (เปิด/ปิด/แก้ไข Order), Custom Indicators, Risk Management (Position Sizing, Trailing Stop), Multi-timeframe Analysis และ Utility Functions ทุกตัวอย่างมีคำอธิบายพร้อมใช้งาน
วิธีเขียน Custom Indicator ใน MQL4 ทำอย่างไร
สร้างไฟล์ .mq4 กำหนด indicator_buffers, indicator_color ใช้ OnCalculate() คำนวณค่าสำหรับแท่งเทียน เก็บลง Buffer Array MT4 วาดกราฟอัตโนมัติ ใช้ SetIndexStyle กำหนดรูปแบบแสดงผล
วิธีจัดการ Orders ใน MQL4 ทำอย่างไร
ใช้ OrderSend() เปิด, OrderClose() ปิด, OrderModify() แก้ SL/TP ใช้ OrderSelect() เลือก Order ตรวจสอบด้วย OrdersTotal() ใช้ Magic Number แยก Order ของแต่ละ EA วนลูปจากท้ายไปหน้าเมื่อปิด Order
Position Sizing คำนวณอย่างไร
Balance คูณ Risk % หารด้วย SL pips คูณ Pip Value เช่น $1000 Risk 2% = $20 SL 50 pips Pip Value $10 = 0.04 Lot ตรวจสอบ Min/Max Lot และ Lot Step ของ Broker ก่อนส่ง Order
สรุป
ตัวอย่าง Code MQL4 ที่รวมไว้ครอบคลุมทุกฟังก์ชันที่จำเป็นสำหรับเขียน Expert Advisor ตั้งแต่ Order Management ที่จัดการเปิด ปิด แก้ไข Order, Risk Management ที่คำนวณ Position Size ตาม Risk %, Trailing Stop, Break Even, Custom Indicator ที่วัด Trend Strength และ Multi-timeframe Analysis สามารถนำ Code เหล่านี้ไปใช้เป็นพื้นฐานสร้าง EA ของตัวเองได้
