为 MetaTrader 打造的高级 EA 构造器 - botbrains·综合运用
EA 模块化的函数骨架长这样
把一套 MT5 自动交易逻辑拆成小块函数,是降低维护成本的直接办法。下面这段从实盘机器人里抽出的代码,每个 block_ 函数对应一个动作节点:打印快线数值、翻倍手数、发 TG 截图、平掉持仓,彼此用函数调用串起来。
比如 block_bQMre45Bd 里先算前一根 K 的快线 SMA:moving_average(..., 1) 取 shift=1,再连调五个子块去刷新界面文字、跑后续判断。手数控制分两路:block_bPlXoF1uA 把 __full_lot 设成 __lot * 2,block_bYUS6GLT0 则原样赋值,意味着加仓和首仓可以走不同仓位逻辑。
截图推送的参数是写死的:2160×720 像素发往 __admin_id,回测时若没填这个 ID,电报块会静默失效。外汇与贵金属波动剧烈,这类市价单模块上线前务必在策略测试器跑至少 3 个月 Tick 数据。
class="type">void block_bO7LNEs4m(){ print_debug_info(( to_string(to_double("ma_fast = ")) + DoubleToString(__ma_fast, class="num">2) )); } class=class="str">"cmt">//Function of the block bPlXoF1uA(set_complex_variable_value): class="type">void block_bPlXoF1uA(){ vset(__full_lot, ( __lot * to_double("class="num">2") )); } class=class="str">"cmt">//Function of the block bQ4zsFoIh(log): class="type">void block_bQ4zsFoIh(){ log_to_file("Open class="type">long!"); block_bMgaVnT74(); } class=class="str">"cmt">//Function of the block bQMre45Bd(set_complex_variable_value): class="type">void block_bQMre45Bd(){ vset(__ma_fast_prev, ( moving_average(to_string(__symbol), PERIOD_CURRENT, (class="type">int)__fast_ma_period, MODE_SMA, PRICE_CLOSE, class="num">1) )); block_bRUr8MnXh(); block_b1VYatoxs(); block_b3UJfY74N(); block_bofgi9HOT(); } class=class="str">"cmt">//Function of the block bRUr8MnXh(interface_element_modify): class="type">void block_bRUr8MnXh(){ modify_text("bj6MtjhZF", DoubleToString(__ma_fast_prev, class="num">2) ); } class=class="str">"cmt">//Function of the block bS1JODjZj(print_debug_info): class="type">void block_bS1JODjZj(){ print_debug_info(( to_string(to_double("ma_slow_prev = ")) + DoubleToString(__ma_slow_prev, class="num">2) )); } class=class="str">"cmt">//Function of the block bT8xv0qGj(buy_signal_sound): class="type">void block_bT8xv0qGj(){ play_sound("buy_signal"); block_bPlXoF1uA(); } class=class="str">"cmt">//Function of the block bTonyumSN(print_debug_info): class="type">void block_bTonyumSN(){ print_debug_info(( to_string(to_double("ma_slow = ")) + DoubleToString(__ma_slow, class="num">2) )); } class=class="str">"cmt">//Function of the block bTs8fZtAO(telegram_send_chart_screenshot): class="type">void block_bTs8fZtAO(){ telegram_send_chart_screenshot(to_string(__symbol), class="num">2160, class="num">720, (class="type">int)__admin_id); } class=class="str">"cmt">//Function of the block bUySCvh6M(place_market_order): class="type">void block_bUySCvh6M(){ place_market_order(to_string(__symbol), "BUY", __full_lot); block_bfrp6ajWk(); block_bjBTLJMym(); block_boX0sSwri(); block_bQ4zsFoIh(); } class=class="str">"cmt">//Function of the block bWkG0nSQa(telegram_send_message): class="type">void block_bWkG0nSQa(){ telegram_send_message("Open class="type">class="kw">short!", (class="type">int)__admin_id); } class=class="str">"cmt">//Function of the block bX2tY0y68(terminal_print): class="type">void block_bX2tY0y68(){ terminal_print("Open class="type">class="kw">short!"); } class=class="str">"cmt">//Function of the block bXRrICVna(close_position): class="type">void block_bXRrICVna(){ close_position(to_string(__symbol)); } class=class="str">"cmt">//Function of the block bYGEhpZDM(place_market_order): class="type">void block_bYGEhpZDM(){ place_market_order(to_string(__symbol), "SELL", __lot); } class=class="str">"cmt">//Function of the block bYUS6GLT0(set_complex_variable_value): class="type">void block_bYUS6GLT0(){ vset(__full_lot, ( __lot )); } class=class="str">"cmt">//Function of the block bYi6ikfde(terminal_print): class="type">void block_bYi6ikfde(){ terminal_print("Робот запущен!"); } class=class="str">"cmt">//Function of the block bfrp6ajWk(terminal_print): class="type">void block_bfrp6ajWk(){ terminal_print("Open class="type">long!"); } class=class="str">"cmt">//Function of the block biLE3RJAD(sell_signal_sound): class="type">void block_biLE3RJAD(){ play_sound("sell_signal"); block_bPlXoF1uA(); } class=class="str">"cmt">//Function of the block bjBTLJMym(telegram_send_message): class="type">void block_bjBTLJMym(){ telegram_send_message("Open class="type">long!", (class="type">int)__admin_id); } class=class="str">"cmt">//Function of the block boHVNlqnO(set_complex_variable_value): class="type">void block_boHVNlqnO(){ vset(__ma_slow, ( moving_average(to_string(__symbol), PERIOD_CURRENT, (class="type">int)__slow_ma_period, MODE_SMA, PRICE_CLOSE, class="num">0) )); block_b0Wkfq6OD(); } class=class="str">"cmt">//Function of the block boX0sSwri(telegram_send_chart_screenshot): class="type">void block_boX0sSwri(){ telegram_send_chart_screenshot(to_string(__symbol), class="num">2160, class="num">720, (class="type">int)__admin_id); } class=class="str">"cmt">//Function of the block bofgi9HOT(interface_element_modify): class="type">void block_bofgi9HOT(){
◍ 慢快线死叉触发卖单的分块逻辑
这段 MQL5 把「慢快均线死叉」拆成了四个互相调用的函数块,核心判定在 block_bvIvs7SMe 里:当快线跌破慢线、且上一根 K 线还是快线在上的状态,同时同品种当前无卖出持仓,才去跑下单流程。 下单函数 block_bugmLdNsU 先以 SELL 方向、整手数开市价单,随后连续调用四个后缀块(bX2tY0y68 / bWkG0nSQa / bTs8fZtAO / b3crj4ayK),这些块大概率负责挂止损、改注释、刷面板等收尾动作,原文未展开。 死叉条件用 __ma_fast_prev > __ma_slow_prev 做「上一根反向」过滤,能砍掉一部分本根内反复穿插的假信号;pause(1000) 在 bzVyOb4tW 里硬等 1 秒再回流 biLE3RJAD,避免同 tick 内高频重判。外汇与贵金属波动剧烈,这种裸方向市价单在高滑点时段可能直接吃亏,上 MT5 把 __full_lot 调小到 0.01 先跑一周模拟再谈实盘。
modify_text("bLcIIkYqO", DoubleToString(__ma_slow, class="num">2) ); } class=class="str">"cmt">//Function of the block bugmLdNsU(place_market_order): class="type">void block_bugmLdNsU(){ place_market_order(to_string(__symbol), "SELL", __full_lot); block_bX2tY0y68(); block_bWkG0nSQa(); block_bTs8fZtAO(); block_b3crj4ayK(); } class=class="str">"cmt">//Function of the block bvIvs7SMe(condition): class="type">void block_bvIvs7SMe(){ if (( __ma_fast < __ma_slow ) && ( __ma_fast_prev > __ma_slow_prev ) && ( get_position_info(to_string(__symbol), "POSITION_DIRECTION") != SELL_DIRECTION )){ block_bugmLdNsU(); } } class=class="str">"cmt">//Function of the block bzVyOb4tW(pause): class="type">void block_bzVyOb4tW(){ pause(class="num">1000); block_biLE3RJAD(); }
「BotBrains 里能直接拖的 140 多个积木」
BotBrains 编辑器内置超过 140 个可用模块,按功能被切成了事件、条件、循环、趋势指标、振荡器、比尔·威廉姆斯、图表分析、业务、变量、声音、信心、枚举、历史、Telegram、其它、界面元素、数学与逻辑运算符、调试等近二十类。做可视化策略时,先认清楚每类模块触发时机和输出类型,比硬背文档更高效。 事件类里最常用的是 New tick(新报价触发)和 Timer(按秒周期触发),前者适合做即时价行为判断,后者适合做固定频率扫描。条件只用「If」一个块,1 进 2 出,真走绿色分支、假走红色分支。 循环和枚举容易踩坑:列举有效限价或停损订单前,必须先放 Request active orders list;拉历史成交前必须先用 Request history。跳过这一步,循环里读到的票据大概率是上一轮的残留数据。 趋势与振荡器覆盖了 Adaptive MA、布林带、Ichimoku、MACD、RSI、Stochastic 等三十余个指标,比尔·威廉姆斯系单独成类(Alligator、Fractals、AO 等)。业务类直接挂 Market order / Limit order / Stop order 和下单后平仓、删单模块,配合「信心」类读账户与持仓信息,就能在 MT5 里拼出一条完整闭环。 数学运算符含 + - * / √ ^ % 及比较符,逻辑只有 AND / OR / NOT 三种。调试用 Print debug info 把变量值和模块返回值打到终端日志,是排查可视化逻辑错乱的最快手段。外汇与贵金属波动剧烈、杠杆风险高,模块拼出来的策略未经历史回测和实盘验证前,实盘触发概率和滑点损耗都只是推测。
关于这套可视化编程思路的延伸阅读
BotBrains 这套可视化搭建思路在读者反馈里争议挺明显:2022 年 12 月 Ivan Titov 就指出,普通人用不了,因为它本质还是要懂 MQL5 编程,界面繁琐程度不比直接写 EA 低。2023 年 1 月 vbymrf 更直接——纯可视化代码和语言编程一样难学,因为语言构造绕不掉。 想继续深挖概率与组合数学在交易里的落地,同作者还有几篇连贯文章可对照看:伯努利逻辑那篇讲如何用 Bernoulli 方案描述交易数据数组并做自适应系统;回归模型续篇用三种动态暂态函数印证价格变化形态;曲线分析篇则把多状态系统往双状态系统化简,给可伸缩算法打底。 对程序员来说,这类自动模块生成界面仍有参考价值,但别指望零基础拼出能跑的机器人。外汇和贵金属波动极快,任何可视化策略未经 MT5 历史回测验证,实盘都只是概率游戏。