# 双均线交叉EA:完整MQL4源码免费下载
策略原理简介
本EA实现了经典的双均线交叉策略,是外汇趋势跟踪系统中最可靠的方法之一。当快线(短周期)上穿慢线(长周期)时开多单;当快线下穿慢线时开空单。
本EA专为MT4平台设计,无需任何外部依赖,直接在MetaEditor中编译即可使用。
核心功能一览
| 功能项 | 说明 |
| :--- | :--- |
| 策略类型 | 趋势跟踪(均线交叉) |
| 适用平台 | MT4(MQL4语言) |
| 交易方向 | 多空双向 |
| 资金管理 | 固定手数 + 可选止损止盈 |
| 可调参数 | 快线周期、慢线周期、手数、止损、止盈 |
完整源码(复制即用)
复制下方代码,打开MT4的MetaEditor(按F4键),新建一个EA,粘贴代码后编译即可。
```mql4
//+------------------------------------------------------------------+
//| DualMACrossoverEA.mq4 |
//| |
//| |
//+------------------------------------------------------------------+
#property copyright ""
#property link ""
#property version "1.00"
#property strict
// --- 输入参数(用户可调)---
input double LotSize = 0.1; // 每笔交易手数
input int FastMAPeriod = 5; // 快线周期
input int SlowMAPeriod = 20; // 慢线周期
input int MAPriceType = MODE_SMA; // 均线类型:SMA简单/EMA指数等
input int StopLoss = 50; // 止损点数(0为不设)
input int TakeProfit = 100; // 止盈点数(0为不设)
input int MagicNumber = 12345; // EA唯一识别码
// --- 全局变量 ---
double lastFastMA = 0;
double lastSlowMA = 0;
bool isBusy = false;
//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
if(FastMAPeriod >= SlowMAPeriod)
{
Print("错误:快线周期必须小于慢线周期");
return(INIT_PARAMETERS_INCORRECT);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| EA退出函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}
//+------------------------------------------------------------------+
//| EA核心Tick函数(每跳动一次执行一次) |
//+------------------------------------------------------------------+
void OnTick()
{
if(isBusy) return;
isBusy = true;
// 计算当前和前一根K线的均线值
double currentFastMA = iMA(NULL, 0, FastMAPeriod, 0, MAPriceType, PRICE_CLOSE, 1);
double currentSlowMA = iMA(NULL, 0, SlowMAPeriod, 0, MAPriceType, PRICE_CLOSE, 1);
double previousFastMA = iMA(NULL, 0, FastMAPeriod, 0, MAPriceType, PRICE_CLOSE, 2);
double previousSlowMA = iMA(NULL, 0, SlowMAPeriod, 0, MAPriceType, PRICE_CLOSE, 2);
// 检查是否已有同向仓位
int totalPositions = OrdersTotal();
bool hasBuy = false;
bool hasSell = false;
for(int i = 0; i < totalPositions; i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol())
{
if(OrderType() == OP_BUY) hasBuy = true;
if(OrderType() == OP_SELL) hasSell = true;
}
}
}
// --- 做多信号:快线上穿慢线 ---
if(previousFastMA <= previousSlowMA && currentFastMA > currentSlowMA)
{
if(!hasBuy)
{
CloseAllOrders(); // 先平反向单
OpenBuy();
}
}
// --- 做空信号:快线下穿慢线 ---
if(previousFastMA >= previousSlowMA && currentFastMA < currentSlowMA)
{
if(!hasSell)
{
CloseAllOrders();
OpenSell();
}
}
isBusy = false;
}
//+------------------------------------------------------------------+
//| 开多单函数 |
//+------------------------------------------------------------------+
void OpenBuy()
{
double slippage = 3;
double price = Ask;
double sl = (StopLoss > 0) ? price - StopLoss * Point : 0;
double tp = (TakeProfit > 0) ? price + TakeProfit * Point : 0;
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, price, slippage, sl, tp, "MA Crossover Buy", MagicNumber, 0, clrGreen);
if(ticket < 0)
Print("开多单失败:", GetLastError());
else
Print("多单已开,订单号:", ticket);
}
//+------------------------------------------------------------------+
//| 开空单函数 |
//+------------------------------------------------------------------+
void OpenSell()
{
double slippage = 3;
double price = Bid;
double sl = (StopLoss > 0) ? price + StopLoss * Point : 0;
double tp = (TakeProfit > 0) ? price - TakeProfit * Point : 0;
int ticket = OrderSend(Symbol(), OP_SELL, LotSize, price, slippage, sl, tp, "MA Crossover Sell", MagicNumber, 0, clrRed);
if(ticket < 0)
Print("开空单失败:", GetLastError());
else
Print("空单已开,订单号:", ticket);
}
//+------------------------------------------------------------------+
//| 平掉所有本EA的持仓 |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol())
{
bool closed = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 3, clrWhite);
if(!closed)
Print("平仓失败,订单号:", OrderTicket(), ",错误码:", GetLastError());
}
}
}
}
//+------------------------------------------------------------------+
```
参数详解
| 参数 | 默认值 | 说明 |
| :--- | :--- | :--- |
| `LotSize` | 0.1 | 每笔开仓手数。建议根据账户余额调整(单笔风险控制在1%以内) |
| `FastMAPeriod` | 5 | 快线周期。数值越小对价格变化越敏感 |
| `SlowMAPeriod` | 20 | 慢线周期。数值越大过滤噪音能力越强 |
| `MAPriceType` | MODE_SMA | 均线类型:MODE_SMA(简单移动平均)、MODE_EMA(指数加权)等 |
| `StopLoss` | 50 | 止损点数(4位报价平台下1点=0.0001) |
| `TakeProfit` | 100 | 止盈点数 |
| `MagicNumber` | 12345 | 魔术号,用于区分本EA与手工单或其他EA的单子 |
安装与测试步骤
1. 打开MetaEditor:在MT4中按`F4`键,或点击 工具 > MetaQuotes语言编辑器
2. 新建EA:文件 > 新建 > 智能交易系统 > 下一步 > 命名(如“双均线EA”)> 完成
3. 粘贴代码:全选默认代码,替换为上面的源码
4. 编译:按`F7`键或点击“编译”按钮
5. 挂载到图表:回到MT4主界面,将EA拖拽到任意图表(推荐EURUSD或GBPUSD)
6. 回测:打开策略测试器(Ctrl+R),选择本EA,设置日期范围,点击开始
回测建议
参数优化技巧
1. 避免过度拟合:用6个月数据优化,再用随后3个月数据验证
2. 使用EMA提高响应速度:将`MODE_SMA`改为`MODE_EMA`,均线对价格变化反应更快
3. 增加过滤条件:可考虑加入ADX指标(大于25时开仓),避免震荡市频繁止损
重要说明
本EA仅供学习和教育目的使用。实盘部署前请务必进行充分回测和模拟盘验证。均线交叉策略在趋势行情中表现良好,但在横盘震荡中会产生连续亏损。
需要更多高级EA? 订阅我们的邮件列表,每周免费获取源码,并优先体验我们的黄金EA产品。
---
参考来源:
1. MQL5官方文档 – 技术指标(iMA函数)
2. MetaQuotes – MQL4 OrderSend函数参考
3. 自主编译开源代码,仅供学习交流
```