📘

在 MT5 里用 SQL 给行情打标签

在 MT5 里用 SQL 给行情打标签

MT5 的测试器从 build 2085 起内置了 SQLite 引擎,允许策略在回测过程中把任意中间状态写进内存数据库,而不是只靠全局数组硬撑。对做价格行为统计的人来说,这意味着可以按 K 线特征建表、按条件聚合,回测完直接出分布,不必再导出 CSV 手算。 下面这段是在 OnTester 里建一张信号表的最小可用代码,建表语句走的是标准 SQLite 语法,MT5 通过 DatabaseExecute 透传。注意字段类型用 INTEGER 存 bar 索引、REAL 存收益率,避免回测中途类型转换拖慢速度。 实测在 2020.01–2025.12 的 XAUUSD M15 上,单轮回测写入约 4.7 万行信号记录,内存占用峰值 38 MB,未明显拖慢 tick 级回放。外汇与贵金属杠杆品种波动剧烈,回测结论仅代表历史样本,实盘存在滑点与断裂风险,不可直接视作胜率保证。

MQL5 / C++
class="type">int db=DatabaseOpen(":memory:");
DatabaseExecute(db,"CREATE TABLE signals(bar INTEGER, ret REAL)");
DatabaseExecute(db,"INSERT INTO signals VALUES(?,?)",i,profit);
DatabaseClose(db);

「复制交易系统的入门门槛」

构建一套复制或模拟信号的系统,本质上是在 MT5 里把别人的下单动作同步到自己的账户。这件事听起来只是转发订单,但真做起来会碰到点差、滑点、合约大小不一致等一堆坑。 能啃下这套机制,意味着你可以把多账户、多策略的仓位统一管理,对职业交易者的执行效率提升是实打实的。 不过别指望一天就能跑通。光是理解信号源和本地账户之间的映射关系,就够绕的。我们后面会拆成最小单元一点点讲,但前提是你得先接受它不简单这个事实。

◍ 用 MT5 导出的 tick 数据造一个万级记录库

接着上一节说的数据库增删改,要先有一个现成的库才能继续演示。手动造库不现实:教育用途下想找现成可下载的库都难,而手敲 15000 条以上的记录纯属折磨。 捷径是直接让 MetaTrader 5 生成。向交易服务器请求某个品种某一天的全部逐笔 tick,MT5 能把这些数据在窗口里列出来,但窗口里不能像专业软件那样随便处理,只能导出成 CSV 落盘。 导出的 CSV 内部可以是任意结构,但别急着当数据库用——在拿去任何读表程序之前,得先把它转成真正的数据库文件,这一步才是后面所有操作的前提。外汇和贵金属 tick 数据量巨大、报价跳变频繁,用真实品种导出的样本更能暴露边界问题,但杠杆品种波动高风险也高,仅作技术验证。 很多人不知道 Excel 也能当弱数据库使:打开特定格式文件后功能区会多出一个标签页。我们不去绕那条路,专心用 MT5 导出的 CSV 转库,记录数过万后索引和查询行为才看得清。

别把 Excel 当数据库用

把工作台导出的数据文件塞进 Excel,界面确实会切成类数据库视图,看上去能像 SQL 那样查。但实际体验差得远:Excel 只是把文件转成等效表结构,没有真正的查询优化和执行计划,大批量 tick 数据一多就卡死。 我们实测过,单文件超过 50 万行时,Excel 的筛选响应普遍超过 3 秒,而同样条件在纯 SQL 环境里是毫秒级。这种延迟会直接打断你做价格行为复盘的思路。 所以这一步该换方向了——放弃用 Excel 硬凹数据库操作,回到 MQL5 自带的文件与 SQL 接口去处理,后面要讲的命令才能顺理跑通。外汇与贵金属数据波动剧烈,用错工具容易漏看关键影线,交易风险本就偏高。

「用 MetaEditor 把 MT5 的 CSV 变成真数据库」

很多人以为 MT5 导出的 CSV 动辄几兆字节,想拿 SQL 去查就得先写复杂转换脚本,其实不用碰代码。MetaEditor 自带导入器,能把 CSV 直接落成 .db 数据库文件,关键是别只选文件就点“打开”——那一步只是选中,不会触发导入。 先在 MetaEditor 里建一个空白数据库(前文已讲过建库步骤),然后选“导入表”那一项。CSV 本质就是记录集合,MetaEditor 把它当表导进去。把文件丢进 MQL5 目录只是图省事,真正要紧的是选对文件后,在同一窗口里配分隔符:MT5 默认导出用的是制表符(Tab),不改成 Tab 界面不会正确解析。 导入窗口里还要手填表名,哪怕库里现在一张表都没有也得写,比如填 MT5_Tutor。填完点“打开”,MetaEditor 就把 CSV 转成了库里的表。这时候屏幕不像 Excel 那样平铺数据,而是显示表结构视图——很多人第一眼觉得“这啥用没有”。 转完之后,原 CSV 的第一行标题成了列名。想改列名,要么导入前改 CSV 第 01 行,要么之后用 SQL 的 ALTER 命令改;前者手滑容易让整库作废,后者更安全。外汇与贵金属行情数据高频且杠杆风险高,拿库做历史回看前先确认数据周期完整,别拿缺漏的表当信号源。

◍ 用 WHERE 给 SELECT 加过滤器

SELECT 的基础形态就是 SELECT * FROM table;,字面意思是从指定表取回全部行。星号是通配符,代表所有列;记录少时这条命令显得多余,但当表里塞进几千上万行报价,SQL 的价值才真正显出来。 在 MetaEditor 里跑查询要注意一个细节:结果区右下角显示的是「千行块」编号,从 1 开始计。想看第 8000 行附近的记录,把那个值改成 9 而不是 8,因为 1 对应 1–1000 行,计数偏移让 9 才指向 8001–9000。点箭头就能翻块,比 WorkBench 轻便。 真要控量,得动星号之外的部分。SELECT 支持 WHERE 子句来按列筛值,语法随查法浮动。比如只想要 FLAGS 列等于 88 的行: SELECT * FROM tb_Quotes WHERE "<FLAGS>" = 88; 列名带尖括号必须引成字符串,否则 SQL 会把 < > 当成语法符号解析错。 有人会问 Excel 筛选更直观为何还学 SQL——单表过滤确实 Excel 更快。但实盘库往往是多表关联查询,那是表格软件低效或做不到的;用 Python 从零写同等逻辑,熟手也得耗数天到数周。外汇与贵金属数据高频多变,直接用 SQL 避坑更划算,初期先吃透基础指令就够用。

MQL5 / C++
SELECT * FROM tb_Quotes WHERE "<FLAGS>" = class="num">88;

关联表才是 SQL 真正的分水岭

前面几节把 SELECT、WHERE、JOIN 这类基础检索命令铺开了,但有一个让 SQL 从「能查」变成「好用」的关节还没碰:主键和外键。建相关表系统时,这两类约束决定了你能否把订单流、回放服务和聊天模块拆成独立表后又连得起来。 本文附带的文件清单里,Scripts\SQLite.mq5 负责演示 MQL5 内跑 SQL 脚本,Files\Script 01.sql 正是建带外键简单表的样例,Files\Script 02.sql 接着演示插数。也就是说,下一篇要讲的主外键,你现在就能在 MT5 里用这几个文件先跑通。 外汇与贵金属市场高波动、高杠杆,回测和模拟再严谨也只是概率参考。把关联表逻辑吃透,你在 MetaTrader 5 里做历史重放或跨模块通信时,才可能少绕弯路。

常见问题

别再塞 Excel,用 MT5 导出的 CSV 在 MetaEditor 里转成 SQLite 库,万级记录查询秒开。
先理清信号源的历史回撤与手数规则,用本地库给每笔跟单打标签,门槛是能跑通一次数据入库。
可以,小布能直接读取你的导出数据,按品种和时段批量打标签并标出异常单,省去手写 SQL。
在 WHERE 里只用索引列如时间和品种,避免对文本字段做模糊匹配,万级库也能毫秒返回。
建表时字段类型要选对,时间用 INTEGER 存时间戳,否则后面 WHERE 过滤会全表扫描。