价格行为分析工具包开发系列(第4部分):分析预测型EA·综合运用
◍ 把盘面状态推到 Telegram 的底层写法
想在 MT5 上把前一日高低、ATR、账户权益这些盯盘要素自动推到手机,核心是用 WebRequest 打 Telegram Bot 的 sendMessage 接口。下面这段就是直连 POST 的最小可用骨架,timeout 设 1000 毫秒,意味着网络抖动时大概率会走 error 分支而不是卡死 EA。
class="type">class="kw">string url = StringFormat("https:class=class="str">"cmt">//api.telegram.org/bot%s/sendMessage", TelegramToken); class="type">class="kw">string headers = "Content-Type: application/json\r\n"; class="type">int timeout = class="num">1000; class="type">class="kw">string postData = StringFormat("{\"chat_id\":\"%s\",\"text\":\"%s\"}", ChatID, message); class="type">char dataArray[]; StringToCharArray(postData, dataArray); class="type">char result[]; class="type">class="kw">string responseHeaders; class="type">int responseCode = WebRequest("POST", url, headers, timeout, dataArray, result, responseHeaders); if (responseCode == class="num">200) { Print("Message sent successfully! Response: ", CharArrayToString(result)); } else { PrintFormat("Error sending message. HTTP Response Code: %d. Error: %s", responseCode, GetLastError()); } }
class=class="str">"cmt">// Check if class="num">2 hours have passed since the last update if (TimeCurrent() - lastUpdateTime >= class="num">2 * class="num">3600) { class=class="str">"cmt">// ... [Code that fetches data and calculates support/resistance, etc.] }
class=class="str">"cmt">// Create the output class="type">class="kw">string, including pair name and last update time class="type">class="kw">string pairName = Symbol(); class=class="str">"cmt">// Get the current symbol name class="type">class="kw">string lastUpdateStr = TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES); class="type">class="kw">string infoStr = StringFormat("Pair: %s\nPrev Day Open: %.2f\nPrev Day Close: %.2f\n" "Prev Day High: %.2f\nPrev Day Low: %.2f\n" "Prev Day Volume: %.0f\nCurrent Day Volume: %.0f\n" "Market Direction: %s\nSupport: %.2f\nResistance: %.2f\n" "Account Balance: %.2f\nAccount Equity: %.2f\n" "Market Spread: %.2f\nMin Lot Size: %.2f, Max Lot Size: %.2f\n" "Market Volatility(ATR): %.2f\nLast Update Time: %s\nPossible Lot Size: %.2f", pairName, previousDayOpen, previousDayClose, previousDayHigh, previousDayLow, previousDayVolume, currentDayVolume, marketDirection, support, resistance, accountBalance, accountEquity, marketSpread, minLotSize, maxLotSize, atrValue, lastUpdateStr, lotSize); class=class="str">"cmt">// Log the information Print(infoStr); class=class="str">"cmt">// Here the information is logged for debugging class=class="str">"cmt">// Display information on the chart Comment(infoStr); class=class="str">"cmt">// Display the same information on the chart
class="type">class="kw">string url = StringFormat("https:class=class="str">"cmt">//api.telegram.org/bot%s/sendMessage", TelegramToken); class="type">class="kw">string headers = "Content-Type: application/json\r\n"; class="type">int timeout = class="num">1000; class="type">class="kw">string postData = StringFormat("{\"chat_id\":\"%s\",\"text\":\"%s\"}", ChatID, message); class="type">char dataArray[]; StringToCharArray(postData, dataArray); class="type">char result[]; class="type">class="kw">string responseHeaders; class="type">int responseCode = WebRequest("POST", url, headers, timeout, dataArray, result, responseHeaders); if (responseCode == class="num">200) { Print("Message sent successfully! Response: ", CharArrayToString(result)); } else { PrintFormat("Error sending message. HTTP Response Code: %d. Error: %s", responseCode, GetLastError()); } } class=class="str">"cmt">// Check if class="num">2 hours have passed since the last update if (TimeCurrent() - lastUpdateTime >= class="num">2 * class="num">3600) { class=class="str">"cmt">// ... [Code that fetches data and calculates support/resistance, etc.] } class=class="str">"cmt">// Create the output class="type">class="kw">string, including pair name and last update time class="type">class="kw">string pairName = Symbol(); class=class="str">"cmt">// Get the current symbol name class="type">class="kw">string lastUpdateStr = TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES); class="type">class="kw">string infoStr = StringFormat("Pair: %s\nPrev Day Open: %.2f\nPrev Day Close: %.2f\n" "Prev Day High: %.2f\nPrev Day Low: %.2f\n" "Prev Day Volume: %.0f\nCurrent Day Volume: %.0f\n" "Market Direction: %s\nSupport: %.2f\nResistance: %.2f\n" "Account Balance: %.2f\nAccount Equity: %.2f\n" "Market Spread: %.2f\nMin Lot Size: %.2f, Max Lot Size: %.2f\n" "Market Volatility(ATR): %.2f\nLast Update Time: %s\nPossible Lot Size: %.2f", pairName, previousDayOpen, previousDayClose, previousDayHigh, previousDayLow, previousDayVolume, currentDayVolume, marketDirection, support, resistance, accountBalance, accountEquity, marketSpread, minLotSize, maxLotSize, atrValue, lastUpdateStr, lotSize); class=class="str">"cmt">// Log the information Print(infoStr); class=class="str">"cmt">// Here the information is logged for debugging class=class="str">"cmt">// Display information on the chart Comment(infoStr); class=class="str">"cmt">// Display the same information on the chart
把信号推到 TG 前先卡一道开关
在 MT5 里做自动播报,最忌讳无脑外发。先拿一个布尔变量 SendTelegramAlerts 当总闸,只有它为真才允许调用 SendTelegramMessage,这样回测和实盘切换时不会把垃圾信息刷爆 TG。 发完消息必须更新 lastUpdateTime = TimeCurrent(),否则下一次触发会以为还停在旧周期,重复推送的概率会明显升高。 构造输出串时顺手用 Symbol() 取当前品种名,和最后更新时间拼在一起,复盘时一眼能看出是哪根品种哪秒出的信号。外汇与贵金属波动快、滑点大,这类提醒只作辅助,实盘下单前仍需人工核对,高风险品种尤甚。
class=class="str">"cmt">// Send Telegram notification if (SendTelegramAlerts) class=class="str">"cmt">// Check if sending alerts is enabled SendTelegramMessage(infoStr); class=class="str">"cmt">// Send the constructed message class=class="str">"cmt">// Update last update time lastUpdateTime = TimeCurrent(); class=class="str">"cmt">// Create the output class="type">class="kw">string, including pair name and last update time class="type">class="kw">string pairName = Symbol(); class=class="str">"cmt">// Get the current symbol name
「先给 MT5 放行 Web 请求」
在把任何信号推到 Telegram 之前,MT5 默认会拦截第三方 Web 请求,不先解掉这个限制,EA 里的 SendXML 或 WebRequest 调用会直接返回 0 且不报错。 实测中约 9 成推送失败案例都卡在“EA 交易”页面的 URL 白名单没填。打开 MT5,依次点「工具」>「选项」>「EA 交易」,把 Allow WebRequest for listed URL 勾上,并在下方列表加入 Telegram 的 API 域名(https://api.telegram.org)。 只勾选而不填具体域名,MT5 仍会拒绝外联;填错协议头(如漏掉 https://)也会静默失败。改完不用重启终端,下一tick 即生效。
◍ 让EA把信号推到Telegram
在MT5的选项里勾选“允许对已列出的URL进行WebRequest”,并把 https://api.telegram.org 加进白名单,EA才有权限向外发请求。不少人在MetaEditor里编译通过、拖到图上却没消息,八成是这一步的URL没填或拼错。 调试阶段可以把推送频率从默认的每2小时一次压到每15秒一次,这样不用干等就能在Telegram里看到连续回传。实盘记得调回合理间隔,避免无意义占用API额度。 编译完把EA拖到图表,Telegram里应很快收到更新;图里MT5图表信息与TG消息内容一致,说明通道通了。外汇与贵金属波动剧烈,自动推送只是辅助监控,不替代人工风控。 下面这段是更新节奏的判断核心:用TimeCurrent减去上次更新时间,够15秒才触发,测试时改这个数就能调频率。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Update metrics and display them | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void UpdateMetrics() { class=class="str">"cmt">// Check if class="num">15 seconds have passed since the last update if(TimeCurrent() - lastUpdateTime >= class="num">15)
工具迭代与时间线
Lynnchris 工具箱从 2024 年 10 月起连续出了四个版本:01/10 的图表展示器用重影覆盖前一日走势,18/11 的分析评论开始用表格给前一日数据并预测方向,27/11 的分析大师做到每两小时刷一次指标,到 02/12 的分析预测才把 Telegram 推送接进来,版本号走到 1.1、工具总数到 5。这条迭代链说明一件事:所谓预测型 EA,核心不是某次神准,而是把前一日高低、实时量能、支撑阻力计算和用户端通知拆成可独立交付的模块逐步补全。 把 EA 接上 Telegram 后,你在通勤时也能收到每两小时的市场指标更新,不用一直盯 MT5 终端。但外汇和贵金属杠杆高、滑点随机,推送只是缩短反应时间,不替你扛回撤。 真要验证这套逻辑,直接把文末 Analytics_Forecaster_EA.mq5 拖进 MT5 回测,重点看它在非农前后两小时的仓位手数是否随波动自动缩量,比读任何介绍都直白。