ตัวอย่าง EA Trend Following
ในบทนี้ เราจะมาดูตัวอย่าง EA แบบ Trend Following ที่สมบูรณ์กัน EA นี้จะใช้ Moving Average (MA) เพื่อระบุแนวโน้มและสร้างสัญญาณการเทรด
ต่อไปนี้เป็นตัวอย่าง Code EA แบบ Trend Following พร้อมคำอธิบายองค์ประกอบหลัก:
คำอธิบายองค์ประกอบหลักของ EA:
- Input Parameters:
- FastMA และ SlowMA: ช่วงเวลาสำหรับ Moving Average เร็วและช้า
- LotSize: ขนาดล็อตในการเทรด
- StopLoss และ TakeProfit: ระยะ Stop Loss และ Take Profit ในหน่วย pips
- OnInit():
- สร้างและตั้งค่า Moving Average indicators
- จัดสรรหน่วยความจำสำหรับ indicator buffers
- OnDeinit():
- คืนทรัพยากรที่ใช้โดย indicators
- OnTick():
- ตรวจสอบการเปลี่ยนแปลงของแนวโน้มโดยเปรียบเทียบค่า MA
- เปิดหรือปิดออเดอร์ตามการเปลี่ยนแปลงของแนวโน้ม
- OpenBuyOrder() และ OpenSellOrder():
- เปิดออเดอร์ Buy หรือ Sell พร้อมกำหนด Stop Loss และ Take Profit
- CloseAllPositions():
- ปิดออเดอร์ที่เปิดอยู่ทั้งหมด
- PositionType():
- ตรวจสอบประเภทของตำแหน่งที่เปิดอยู่ (Buy หรือ Sell)
EA นี้ใช้การตัดกันของ Moving Average สองเส้นเพื่อระบุแนวโน้มและสร้างสัญญาณการเทรด โดยจะเปิด Buy เมื่อ Fast MA ตัดขึ้นบน Slow MA และเปิด Sell เมื่อ Fast MA ตัดลงใต้ Slow MA
//+------------------------------------------------------------------+
//| Trend Following EA.mq4 |
//| Copyright 2024, MetaQuotes Software Corp. |
//| https://www.forexduck.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Software Corp."
#property link "https://www.forexduck.com"
#property version "1.00"
#property strict
// Input parameters
input int FastMA = 10; // Fast Moving Average period
input int SlowMA = 50; // Slow Moving Average period
input double LotSize = 0.1; // Trading lot size
input int StopLoss = 50; // Stop Loss in pips
input int TakeProfit = 100; // Take Profit in pips
// Global variables
int maHandle1, maHandle2;
double maBuffer1[], maBuffer2[];
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize Moving Average indicators
maHandle1 = iMA(NULL, 0, FastMA, 0, MODE_SMA, PRICE_CLOSE);
maHandle2 = iMA(NULL, 0, SlowMA, 0, MODE_SMA, PRICE_CLOSE);
if (maHandle1 == INVALID_HANDLE || maHandle2 == INVALID_HANDLE)
{
Print("Error initializing MA indicators");
return(INIT_FAILED);
}
// Allocate memory for indicator buffers
ArraySetAsSeries(maBuffer1, true);
ArraySetAsSeries(maBuffer2, true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Release indicator handles
IndicatorRelease(maHandle1);
IndicatorRelease(maHandle2);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if we have enough bars to calculate MAs
if (Bars < SlowMA) return;
// Copy MA values to buffers
if (CopyBuffer(maHandle1, 0, 0, 2, maBuffer1) <= 0) return;
if (CopyBuffer(maHandle2, 0, 0, 2, maBuffer2) <= 0) return; // Check for trend change bool upTrend = maBuffer1[0] > maBuffer2[0] && maBuffer1[1] <= maBuffer2[1];
bool downTrend = maBuffer1[0] < maBuffer2[0] && maBuffer1[1] >= maBuffer2[1];
// Check if we have open positions
if (PositionsTotal() == 0)
{
// Open new position if trend changes
if (upTrend)
{
OpenBuyOrder();
}
else if (downTrend)
{
OpenSellOrder();
}
}
else
{
// Check if we need to close existing position
if (PositionType() == POSITION_TYPE_BUY && downTrend)
{
CloseAllPositions();
}
else if (PositionType() == POSITION_TYPE_SELL && upTrend)
{
CloseAllPositions();
}
}
}
//+------------------------------------------------------------------+
//| Function to open a buy order |
//+------------------------------------------------------------------+
void OpenBuyOrder()
{
double askPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double slPrice = askPrice - StopLoss * Point();
double tpPrice = askPrice + TakeProfit * Point();
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = LotSize;
request.type = ORDER_TYPE_BUY;
request.price = askPrice;
request.sl = slPrice;
request.tp = tpPrice;
request.deviation = 10;
request.magic = 123456; // Magic number for identification
if (!OrderSend(request, result))
{
Print("Error opening buy order: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Function to open a sell order |
//+------------------------------------------------------------------+
void OpenSellOrder()
{
double bidPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID);
double slPrice = bidPrice + StopLoss * Point();
double tpPrice = bidPrice - TakeProfit * Point();
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = Symbol();
request.volume = LotSize;
request.type = ORDER_TYPE_SELL;
request.price = bidPrice;
request.sl = slPrice;
request.tp = tpPrice;
request.deviation = 10;
request.magic = 123456; // Magic number for identification
if (!OrderSend(request, result))
{
Print("Error opening sell order: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Function to close all open positions |
//+------------------------------------------------------------------+
void CloseAllPositions()
{
for (int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if (ticket > 0)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.position = ticket;
request.symbol = PositionGetString(POSITION_SYMBOL);
request.volume = PositionGetDouble(POSITION_VOLUME);
request.type = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
request.price = PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ? SymbolInfoDouble(request.symbol, SYMBOL_BID) : SymbolInfoDouble(request.symbol, SYMBOL_ASK);
request.deviation = 10;
if (!OrderSend(request, result))
{
Print("Error closing position: ", GetLastError());
}
}
}
}
//+------------------------------------------------------------------+
//| Function to get current position type |
//+------------------------------------------------------------------+
ENUM_POSITION_TYPE PositionType()
{
for (int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if (ticket > 0)
{
return (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}
}
return POSITION_TYPE_NONE;
}
FOREXDUCK (นามปากกา) นักเขียนของเรามีประสบการณ์การเงินการลงทุนกว่า 10 ปี มีความเชี่ยวชาญในการวิเคราะห์ตลาด Forex และคริปโต โดยเฉพาะการวิเคราะห์ทางเทคนิค รวมถึงเทคนิคต่าง