MQL5 细则手册:MetaTrader 5 交易事件的声音通知·综合运用
(3/3)· 用 #resource 把 wav 封进 ex5,分发 EA 不再附带散装音频文件
用声音把成交结果钉进耳朵
EA 里把声音事件拆成了独立枚举:盈利平仓代号 3,亏损平仓代号 4,配合错误、开仓、改单共 5 类提示音。这样分离后,交易动作和反馈解耦,你想换音效只改字符串变量,不用动逻辑。 PlaySoundByID() 这个函数只在实时环境且 UseSound 为真时才响。它用 switch 把传入的 id 映射到具体 wav:比如 SOUND_CLOSE_WITH_PROFIT 就播 SoundCloseWithProfit,SOUND_CLOSE_WITH_LOSS 播 SoundCloseWithLoss,漏掉一个 case 就静音。 开仓函数 OpenPosition() 先把魔数设 0、滑点按品种精度修正为 10 点(CorrectValueBySymbolDigits(10))。关键点在执行模式判断:当 symb.execution_mode 是 INSTANT 或 MARKET 时,SL/TP 可在开仓同时提交——MT5 build 803 之后 MARKET 模式才支持这点,老版本会直接失败。 外汇和贵金属波动剧烈,滑点 10 点只是基准值,极端行情可能扩到数十点,声音提醒不能替代对风险的盯盘。
SOUND_CLOSE_WITH_PROFIT = class="num">3, class=class="str">"cmt">// Position closing at profit SOUND_CLOSE_WITH_LOSS = class="num">4 class=class="str">"cmt">// Position closing at loss }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Playing sounds | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void PlaySoundByID(ENUM_SOUNDS id) { class=class="str">"cmt">//--- If it is the real-time mode and sounds are enabled if(IsRealtime() && UseSound) { class=class="str">"cmt">//--- Play the sound based on the identifier passed class="kw">switch(id) { case SOUND_ERROR : PlaySound(SoundError); break; case SOUND_OPEN_POSITION : PlaySound(SoundOpenPosition); break; case SOUND_ADJUST_ORDER : PlaySound(SoundAdjustOrder); break; case SOUND_CLOSE_WITH_PROFIT : PlaySound(SoundCloseWithProfit); break; case SOUND_CLOSE_WITH_LOSS : PlaySound(SoundCloseWithLoss); break; } } } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Opening a position | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OpenPosition(class="type">class="kw">double lot, ENUM_ORDER_TYPE order_type, class="type">class="kw">double price, class="type">class="kw">double sl, class="type">class="kw">double tp, class="type">class="kw">string comment) { class=class="str">"cmt">//--- Set the magic number in the trading structure trade.SetExpertMagicNumber(class="num">0); class=class="str">"cmt">//--- Set the slippage in points trade.SetDeviationInPoints(CorrectValueBySymbolDigits(class="num">10)); class=class="str">"cmt">//--- The Instant Execution and Market Execution modes class=class="str">"cmt">// *** Starting with build class="num">803, Stop Loss and Take Profit *** class=class="str">"cmt">// *** can be set upon opening a position in the SYMBOL_TRADE_EXECUTION_MARKET mode *** if(symb.execution_mode==SYMBOL_TRADE_EXECUTION_INSTANT || symb.execution_mode==SYMBOL_TRADE_EXECUTION_MARKET) { class=class="str">"cmt">//--- If the position failed to open if(!trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,comment)) { class=class="str">"cmt">//--- Play the error sound and print the relevant message PlaySoundByID(SOUND_ERROR);
「用成交回history给平仓上声音锁」
EA 想在真实盘面里给平仓动作挂个提示音,核心不是监听 OrderSend 返回值,而是回头扫 HistoryDealsTotal 里的成交单。逻辑里用 static ulong last_ticket 记住上一次扫到的票号,避免同一笔平仓被重复播报——这是实盘里最容易漏的细节。 代码先 HistorySelect(0, TimeCurrent()+1000) 把截至当前+1000秒的成交全拉进列表,再从尾向前遍历。只处理 deal.symbol==_Symbol 的条目,且 deal.entry 属于 DEAL_ENTRY_OUT 或 DEAL_ENTRY_INOUT(即平仓、减仓、反手)才触发声音判断。 若 ticket==last_ticket 或 last_ticket==0(首次初始化),就更新 last_ticket 并退出。外汇与贵金属波动剧烈,这类声音告警只能当辅助,不能替代你对点差与滑点的实时判断,误触发概率始终存在。 让小布替你跑这套 把 UseSound 开关接进你的面板参数,回测时关掉、实盘只留平仓提示,能少听一半噪音。
class="type">void SoundNotification() { class=class="str">"cmt">//--- If it is the real-time mode and sounds are enabled if(IsRealtime() && UseSound) { class="type">class="kw">ulong ticket =class="num">0; class=class="str">"cmt">// Deal ticket class="type">int total =class="num">0; class=class="str">"cmt">// Total deals class="kw">static class="type">class="kw">ulong last_ticket =class="num">0; class=class="str">"cmt">// Last ticket prior to this check class=class="str">"cmt">//--- Get the complete history if(!HistorySelect(class="num">0,TimeCurrent()+class="num">1000)) class="kw">return; class=class="str">"cmt">//--- Get the number of deals in the obtained list total=HistoryDealsTotal(); class=class="str">"cmt">//--- In the obtained list, iterate over all deals from the last one to the first one for(class="type">int i=total-class="num">1; i>=class="num">0; i--) { class=class="str">"cmt">//--- If the deal ticket by its position in the list has been obtained if((ticket=HistoryDealGetTicket(i))>class="num">0) { class=class="str">"cmt">//--- get the symbol of the deal GetHistoryDealProperties(ticket,D_SYMBOL); class=class="str">"cmt">//--- If the symbol of the deal and the current symbol are the same if(deal.symbol==_Symbol) { class=class="str">"cmt">//--- get the direction of the deal GetHistoryDealProperties(ticket,D_ENTRY); class=class="str">"cmt">//--- If it is position closing, volume decrease or reversal if(deal.entry==DEAL_ENTRY_OUT || deal.entry==DEAL_ENTRY_INOUT) { class=class="str">"cmt">//--- If the ticket of the current deal from the list(the last deal for the symbol) is equal to the previous ticket class=class="str">"cmt">// or this is the initialization of the ticket of the last deal if(ticket==last_ticket || last_ticket==class="num">0) { class=class="str">"cmt">//--- Save the ticket and exit
◍ 平仓盈亏的声音反馈与初始化钩子
这段逻辑把每笔成交的盈亏结果直接映射到声音提示上。在 SoundNotification() 里,先通过 GetHistoryDealProperties(ticket,D_PROFIT) 取出该 ticket 的浮动/已实现盈亏,再用 deal.profit>=0 和 deal.profit<0 两个分支决定播放 SOUND_CLOSE_WITH_PROFIT 还是 SOUND_CLOSE_WITH_LOSS,同时把 last_ticket 记下来并 return,避免重复处理同一单。
初始化阶段 OnInit() 只做两件事:调用 CheckNewBar() 重置新 K 线状态,以及跑一次 SoundNotification() 把当前品种的历史末单 ticket 同步进 last_ticket,返回 INIT_SUCCEEDED 即代表加载无误。
实时监听靠 OnTrade() 事件,只要终端发生成交或平仓,就会再次触发 SoundNotification()。外汇与贵金属杠杆高、滑点可能让 deal.profit 与预期有偏差,声音提示仅作辅助,不能替代对账单核对。
开 MT5 把下面代码贴进 EA 的对应函数,改 SOUND_CLOSE_WITH_PROFIT 为你自定义的 wav 名,就能在黄金剥头皮时靠耳朵分辨平仓方向。
last_ticket=ticket; class="kw">return; } class=class="str">"cmt">//--- Get the result of the deal GetHistoryDealProperties(ticket,D_PROFIT); class=class="str">"cmt">//--- In case of profit if(deal.profit>=class="num">0) { class=class="str">"cmt">//--- Profit sound PlaySoundByID(SOUND_CLOSE_WITH_PROFIT); class=class="str">"cmt">//--- Save the ticket number last_ticket=ticket; class="kw">return; } class=class="str">"cmt">//--- In case of loss if(deal.profit<class="num">0) { class=class="str">"cmt">//--- Loss sound PlaySoundByID(SOUND_CLOSE_WITH_LOSS); class=class="str">"cmt">//--- Save the ticket number last_ticket=ticket; class="kw">return; } } } } } } } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Initialization | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- Initialize the new bar CheckNewBar(); class=class="str">"cmt">//--- Initialize tickets of the last deals for the symbol SoundNotification(); class=class="str">"cmt">//--- Initialization completed successfully class="kw">return(INIT_SUCCEEDED); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Monitoring trade events | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTrade() { class=class="str">"cmt">//--- Sound notification SoundNotification(); }
别急着下结论
这套把交易事件映射成声音的思路,附件里给了可直接拖进 MT5 的 soundpanel.mq5(14.07 KB)和两组音频包 sounds.zip(321.8 KB)、soundtradeevents.zip(17.29 KB),实测在终端 Sounds 目录下丢进文件就能被 EA 调用。 想玩进阶的,代码库里搜 CMIDI 这个类能直接在 MetaTrader 5 播 MIDI,把报警写成一段旋律也不是不行,外汇和贵金属波动剧烈,声音提醒只是辅助,真下单前还是得自己看盘口。 读者常卡在两个地方:脚本和 EA 分不清——脚本拖上图表只跑一次 OnStart,EA 才吃每个 tick;声音文件找不到就认准 C:\Program Files\平台目录\Sounds,别在杂乱子目录里乱塞。