变量和数据类型是MQL5编程的基石。刚开始学的时候觉得概念枯燥,写多了才发现,很多bug其实都是变量没声明对、类型搞混或者作用域没搞清楚导致的。这篇笔记把重点知识点和容易踩的坑都梳理了一下。
变量就是一个有名字的内存格子,用来存数据,运行期间可以改变值。
声明:告诉编译器“我要用个变量”,得说清楚类型和名字。
int orderCount; // 声明一个整数变量,叫orderCount
double currentPrice; // 声明一个浮点数变量,叫currentPrice初始化:声明的同时给个初始值。
int lotSize = 1; // 声明 + 赋值为1
string symbolName = "EURUSD"; // 声明 + 赋值为"EURUSD"也可以分开写:
int errorCode; // 先声明
errorCode = 4050; // 后赋值💡 小建议:声明的顺手就给个初始值,不然可能拿到一个随机值(垃圾数据),容易出bug。

作用域决定了变量在代码的哪些地方能“看得见”。这个概念很关键,搞错了经常出现“变量未定义”的编译错误。
局部变量:在函数内部声明的,只能在那个函数里用。函数跑完了,它就失效了。
voidOnTick()
{
int localVar = 5; // 局部变量,只在OnTick()里有效
// ... 这里能用localVar
}
// 出了这个函数,localVar就被销毁了全局变量:在所有函数外面声明的,从声明那一行开始,整个程序文件都能用。
int globalCounter = 0; // 全局变量
voidOnTick()
{
globalCounter++; // 函数里可以访问和修改
}静态变量:在函数里面用static关键字声明。和局部变量很像,区别是——函数执行完了,它的值不会被清掉,下次再调用这个函数时,还能接着用。
voidMyFunction()
{
staticint callCount = 0; // 静态变量,只初始化一次
callCount++;
Print("这个函数被调用了 ", callCount, " 次");
}
// 第一次调用:callCount变成1
// 第二次调用:callCount变成2
// 每次都会递增,不会被重置成0从论坛讨论里看到一个有意思的讨论:静态变量的生命周期和EA是一样的——EA加载到图表上时分配内存,EA被卸载(或者调用OnDeinit())之后才被销毁。所以如果在EA里用了静态变量,它会在EA运行的整个期间一直存在。
MQL5是强类型语言——每个变量都得有明确的类型,编译器会检查。

用来存整数,没有小数部分。
int | ||
long |
用途:订单数、K线数量、魔法数、周期参数等。
int bars = 100;
long bigNumber = 123456789012345;⚠️ 注意:
int和long都是有符号的,如果需要正数但不想用负值,可以用uint或ulong,但一般默认的int和long够用了。
用来存带小数点的数字——价格、止盈止损这些都靠它。
double | ||
float |
double askPrice = 1.35647;
double pointValue = 0.00001;⚠️ 踩坑预警:浮点数在计算机里是二进制存的,有些十进制小数没法精确表示。
错误写法:
if (price == 1.23456) // 可能永远不会成立!正确做法:用
NormalizeDouble()处理后再比较,或者用整数表示(点数)。
只有两个值:true(真)或false(假)。主要用在条件判断、标志位、开关设置。
bool isTrendUp = true;
bool tradeAllowed = false;
if (isTrendUp && tradeAllowed)
{
// 做多逻辑
}用string存文本,字符串常量用双引号括起来。
string symbol = "GBPUSD";
string message = "订单已发送";
string path = "C:\\Data\\file.csv"; // 反斜杠需要转义存单个字符,用单引号括起来。
char firstLetter = 'A';实际开发中字符串用得比字符多得多。
存日期和时间。底层是一个无符号长整数,存的是从1970年1月1日(Unix纪元)到现在的秒数。
声明方式:
datetime expiry = D'2015.12.31';
datetime now = D'2015.10.22 16:45:30';用途:订单开仓时间、计时器、K线时间比较。
从这个类型也能看出来,两个时间“相减”得到的是秒数差,是个整数。
给图表上的线条、文字、图形对象上色用的。本质是一个4字节的无符号整数,存的是RGB格式——红、绿、蓝三个分量各占1个字节(0~255)。
三种赋值方式:
color lineColor = clrGreen; // 方式1:预定义颜色常量
color bgColor = C'0xEF,0xEF,0xEF'; // 方式2:C'分量'形式
color buyColor = 0xFF0000; // 方式3:RGB十六进制整数(红色)预定义的颜色常量有很多,比如clrRed、clrBlue、clrAliceBlue等等,完整列表去MetaEditor帮助里能找到。偷懒的话直接用常量最省事。
用enum定义一组命名的整数常量,让代码更好读懂。比如订单类型用数字0、1、2来表示,谁记得住哪个是哪个?但用ORDER_TYPE_BUY就一目了然了。
enumENUM_ORDER_TYPE
{
ORDER_TYPE_BUY, // 值为 0
ORDER_TYPE_SELL, // 值为 1
ORDER_TYPE_BUY_LIMIT // 值为 2
};
// 使用枚举
ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY;MQL5系统自带的枚举很多,比如ENUM_TIMEFRAMES、ENUM_INDICATOR等等,直接拿来用就行。
用struct把多个不同类型的变量打包成一个逻辑单元。很适合表示一条完整的数据记录。
structMqlTick
{
datetime time; // 最后更新时间
double bid; // 当前买价
double ask; // 当前卖价
// ... 还有其他成员
};
// 声明结构体变量
MqlTick lastTick;
lastTick.bid = 1.23456;
double currentAsk = lastTick.ask;MqlTick是系统内置的结构体,存的是某个交易品种的最新报价信息。用SymbolInfoTick()函数可以拿到它。
有时候需要把一种类型转成另一种。MQL5支持两种方式。
编译器自动完成,通常是把小范围类型转成大范围类型,不会有数据损失。
int intValue = 100;
double doubleValue = intValue; // int自动转成double,结果是100.0程序员手动强制转换,用(目标类型)或者目标类型(值)的写法。
// 写法1:传统C风格
double result = a / (double)b;
// 写法2:函数风格
double result = a / double(b);
// 把double转成int(小数部分直接砍掉)
int points = (int)(StopLoss / _Point);需要小心的地方:

显式转换可能导致精度丢失。比如double转成int,小数部分直接截断,不是四舍五入。想要四舍五入的话用MathRound()。
看个例子:
double g = 9.8;
int round_g = (int)g; // 结果是9(截断)
int math_round_g = MathRound(g); // 结果是10(四舍五入)另外,long(64位)转int(32位)也可能数据溢出。论坛上有人遇到过这个情况:SymbolInfoInteger()返回的是long类型,直接赋值给int变量,编译器会报警告“possible loss of data”。强制转换一下就能解决:
// 有警告的写法
int spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
// 没警告的写法(显式转换)
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);常量的值在程序运行期间不能改。
声明时必须初始化,之后不能修改。
constdouble pi = 3.1415926535;
constint max_orders = 10;在编译前进行文本替换。严格来说它不算是变量,就是个替换规则。
#define COMPANY_NAME "Easy Expert Forex"
#define MAX_BARS 5000
// 编译时,COMPANY_NAME会被替换成"Easy Expert Forex"MetaTrader 5提供了一些可以直接用的变量:
_Symbol | |
_Period | |
_Point | |
_Digits |
比如EURUSD是5位小数,_Digits = 5,_Point = 0.00001。
这些变量在程序启动前就被客户端设置好了,程序里不能修改它们(_LastError是个例外,可以用ResetLastError()重置)。

intlong | intlong | ||
double | ==直接比较;价格用double就行 | ||
bool | truefalse | ||
string | |||
char | |||
datetime | |||
color | clrRed这种常量最方便 | ||
enum | |||
struct | MqlTick这种 |
上面这些是目前学到的核心内容。类型这个东西,用顺手了也就不觉得麻烦了,关键是写代码的时候想清楚“我要存什么数据”和“这个数据会在哪里用”。
📝 备注:这篇笔记是学习过程中的复盘整理,用于个人复习和代码参考。