MQL 语言介绍

MQL (MetaQuotes Language) 是 MetaQuotes 公司为 MT4/MT5 平台开发的专用编程语言,用于编写 EA(交易机器人)、自定义指标和脚本。

🤖

EA (Expert Advisor)

自动交易机器人,可执行开仓、平仓、止损止盈等操作

📈

Custom Indicator

自定义技术指标,在图表上显示独特的分析线和信号

⚡

Script

一次性执行的脚本,用于批量操作或特定任务

🔌

DLL 扩展

通过DLL调用外部C/C++函数,扩展MQL能力边界

MQL4 vs MQL5 对比
特性MQL4 (MT4)MQL5 (MT5)
订单模型单订单系统持仓+订单双系统
执行模式OnTick 事件驱动OnTick + 多事件模型
面向对象部分支持完整OOP支持
回测引擎单线程多线程遗传算法
市场深度有限完整DOM支持

开发环境搭建

MetaEditor 是 MT4/MT5 内置的集成开发环境,无需额外安装。

步骤
  1. 安装 MT4/MT5 客户端

    从交易商官网下载并安装 MetaTrader 客户端

  2. 打开 MetaEditor

    在 MT 菜单中点击 工具 → MetaQuotes 语言编辑器,或按 F4 快捷键

  3. 创建新项目

    在 Navigator 面板右键 → 新建 → 选择 EA/指标/脚本 → 按向导完成

第一个EA程序

让我们编写一个最简单的EA,在图表上打印信息。

//+------------------------------------------------------------------+
//|                                                  First_EA.mq4   |
//|                        Copyright 2024, 晓辉编程 eafxtech.com   |
//|                                             https://www.eafxtech.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, 晓辉编程"
#property link      "https://www.eafxtech.com"
#property version   "1.00"
#property strict

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   Print("EA 已加载: ", Symbol(), " - ", Period());
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Print("EA 已卸载");
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double bid = Bid;
   double ask = Ask;
   int spread = (int)((ask - bid) / Point);
   Comment("Bid=", bid, "  Ask=", ask, "  点差=", spread);
  }
//+------------------------------------------------------------------+

数据类型与变量

MQL 是强类型语言,变量使用前必须声明类型。

基本数据类型
类型说明示例
int32位整数int count = 10;
double双精度浮点数double price = 1.23456;
bool布尔值 true/falsebool isLong = true;
string字符串string name = "EURUSD";
datetime日期时间datetime now = TimeCurrent();
color颜色color c = clrRed;

流程控制

MQL 支持标准的条件判断和循环结构。

if-else 条件

double rsi = iRSI(_Symbol, _Period, 14, PRICE_CLOSE, 0);
if (rsi > 70)
  {
   Print("超买区域, RSI=", rsi);
  }
else if (rsi < 30)
  {
   Print("超卖区域, RSI=", rsi);
  }
else
  {
   Print("中性区域");
  }

for 循环

// 计算最近10根K线的收盘价均值
double sum = 0;
for (int i = 0; i < 10; i++)
  {
   sum += Close[i];
  }
double avg = sum / 10;

函数与参数

函数是MQL程序的基本构建块,支持传值和传引用。

// 计算移动平均线
double CalcMA(int period, int shift)
  {
   double sum = 0;
   for (int i = shift; i < shift + period; i++)
     {
      sum += Close[i];
     }
   return sum / period;
  }

// 使用引用参数返回多个值
void GetTradeInfo(int &orders, double &profit)
  {
   orders = OrdersTotal();
   profit = AccountProfit();
  }

数组操作

MQL 支持一维和多维数组,数组索引从0开始。

// 一维数组
double prices[100];

// 二维数组
double matrix[10][10];

// 动态数组 (MQL5)
double dynamicArray[];
ArrayResize(dynamicArray, 100);

// 数组排序
double arr[] = {5, 2, 8, 1, 9};
ArraySort(arr);  // 升序排序

账户信息

通过内置函数获取账户余额、净值、保证金等信息。

常用账户函数
函数说明
AccountBalance()账户余额
AccountEquity()账户净值 (余额+浮动盈亏)
AccountProfit()浮动盈亏
AccountFreeMargin()可用保证金
AccountMargin()已用保证金
AccountLeverage()杠杆倍数
AccountCurrency()账户币种

订单系统 (MQL4)

MQL4 使用订单编号系统,每张订单有唯一的 ticket 号。

订单类型

OP_BUY
市价买单
OP_SELL
市价卖单
OP_BUYLIMIT
限价买单
OP_SELLLIMIT
限价卖单
OP_BUYSTOP
止损买单
OP_SELLSTOP
止损卖单

交易函数

OrderSend 是 MQL4 中下单的核心函数。

// 市价买入示例
int ticket = OrderSend(
   Symbol(),          // 交易品种
   OP_BUY,            // 订单类型
   0.1,               // 手数
   Ask,               // 开仓价格
   3,                 // 滑点(点)
   Bid - 50*Point,    // 止损价
   Ask + 100*Point,   // 止盈价
   "My EA Order",     // 订单注释
   0,                 // 魔术号
   0,                 // 订单有效期
   clrGreen           // 箭头颜色
);

if (ticket > 0)
  {
   Print("下单成功, 订单号: ", ticket);
  }
else
  {
   Print("下单失败, 错误码: ", GetLastError());
  }

风控管理

风控是EA的生命线,必须在开仓前计算好仓位和止损。

资金管理核心公式
// 基于百分比风险计算手数
double CalcLotSize(double stopLossPoints)
  {
   double riskAmount = AccountBalance() * 0.02;
   double valuePerPoint = 10 * 0.01 / 0.0001;
   double lotSize = riskAmount / (stopLossPoints * valuePerPoint);
   
   lotSize = NormalizeDouble(lotSize, 2);
   
   double minLot = MarketInfo(_Symbol, MODE_MINLOT);
   double maxLot = MarketInfo(_Symbol, MODE_MAXLOT);
   lotSize = MathMax(minLot, MathMin(maxLot, lotSize));
   
   return lotSize;
  }
风控原则
  • 单笔交易风险不超过账户的 2%
  • 所有持仓总风险不超过账户的 10%
  • 强制止损,禁止无止损开仓
  • 动态仓位:根据波动率调整手数
  • 最大回撤熔断:亏损超20%暂停交易

多品种交易

高级EA通常需要监控多个品种,捕捉跨品种交易机会。

// 遍历所有交易品种
void ScanAllSymbols()
  {
   int total = SymbolsTotal(true);
   for (int i = 0; i < total; i++)
     {
      string symbol = SymbolName(i, true);
      double spread = SymbolInfoDouble(symbol, SYMBOL_SPREAD);
      double vol = CalcVolatility(symbol, 20);
      
      if (vol > 0.01 && spread < 20)
        {
         Print("关注品种: ", symbol, " 波动率: ", vol);
        }
     }
  }

性能优化

EA运行效率直接影响实盘表现,尤其是高频策略。

  • 减少 OnTick 中的计算量,只在必要时更新
  • 使用静态变量缓存计算结果
  • 避免在循环中调用耗时函数
  • 数组使用 ArraySetAsSeries 优化索引
  • 复杂计算放到独立函数,便于测试

调试技巧

Print() 和 Comment() 是 MQL 调试最常用的工具。

常用调试方法
方法用途注意事项
Print()输出到日志支持字符串+数字混合
Comment()图表左上角显示实时更新,方便观察变量
Alert()弹窗提示触发重要事件时使用
MessageBox()模态对话框会暂停EA执行
GetLastError()获取错误码交易失败后立即调用

代码规范

良好的代码风格是团队协作和长期维护的基础。

  • 使用有意义的变量名,避免 a1、b2 等无意义命名
  • 匈牙利命名法:int 前缀 i_,double 前缀 d_,bool 前缀 b_
  • 每个函数前加注释说明:功能、参数、返回值
  • 魔法数字用常量定义:#define STOP_LOSS 50
  • 代码缩进统一 2 或 3 个空格
  • 关键逻辑段加分隔注释线

常用设计模式

成熟的EA开发中常用的架构模式。

🏗 信号-执行分离

信号生成和订单执行解耦,便于独立测试和替换策略

🔄 状态机模式

用枚举管理交易状态:等待信号→挂单→持仓→平仓

🛡 风控中间件

所有开仓请求先过风控层,统一校验手数、止损、风险限额

📊 统计收集器

独立模块收集交易统计,输出CSV用于分析和复盘

常见坑点

新手最容易踩的坑,提前避坑少走弯路。

Top 5 坑点
  1. 1. 数组越界

    访问 iBarShift 或价格数组前,务必检查 Bars 数量是否足够

  2. 2. 滑点设置不当

    实盘点差波动大,滑点设太小会导致频繁下单失败,建议设 30-50 点

  3. 3. 重算 vs 未重算指标

    iMA 等指标第0根K线值会变化,策略信号应使用第1根及以后的K线

  4. 4. 四位数 vs 五位数平台

    Point 在五位数平台是 0.00001,止损计算要用 _Digits 判断

  5. 5. 订单选择状态混乱

    OrderSelect 后必须检查返回值,遍历订单时注意索引变化