价格行为分析工具包开发(第二部分):分析注释脚本·进阶篇
(2/3)·手动切图找前日高低点和量能对比太耗时?一个脚本把核心盘面信息压成图表注释
「把前一日盘面塞进MT5脚本」
做日内决策的人,往往卡在「昨天到底发生了什么」这件事上——高低点、开盘收盘、成交量,手动翻日线再记下来太慢。下面这段 MQ5 脚本直接把这些关键字段抓出来,往当前图表上贴一张表,并顺手标出支撑阻力线,适合开盘前花 30 秒过一遍。 脚本用 iBarShift 定位前一日的日线 bar,再取 iHigh / iLow / iOpen / iClose / iVolume。注意 prevDayIndex 若返回 -1 会直接 Print 报错并 return,所以历史数据不足(比如周一跑周五前的数据缺失)时不会瞎画。 输入参数里 TableXOffset=10、TableYOffset=50 控制表格左上角坐标,SupportColor 默认绿、ResistanceColor 默认红。你复制进 MT5 后,改这两个 color 就能让支撑阻力线配合自己的模板色,不至于和已有对象重叠看花眼。外汇与贵金属波动受杠杆放大,脚本只做展示不做下单,实盘仍属高风险。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| ACS.mq5 | class=class="str">"cmt">//| Copyright class="num">2024, MetaQuotes Software Corp. | class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "class="num">2024, MetaQuotes Software Corp." class="macro">#class="kw">property link "[MQL5官方文档] class="macro">#class="kw">property description "Script that displays previous day metrics on the current chart and predicts market direction." class="macro">#class="kw">property version "class="num">1.0" class="macro">#include <Trade\Trade.mqh> class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Input parameters | class=class="str">"cmt">//+------------------------------------------------------------------+ input class="type">class="kw">color TableTextColor = clrBlue; class=class="str">"cmt">// Text class="type">class="kw">color for the table input class="type">int TableXOffset = class="num">10; class=class="str">"cmt">// X offset for the table input class="type">int TableYOffset = class="num">50; class=class="str">"cmt">// Y offset for the table input class="type">class="kw">color SupportColor = clrGreen; class=class="str">"cmt">// Color for the support line input class="type">class="kw">color ResistanceColor = clrRed; class=class="str">"cmt">// Color for the resistance line class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Global variables | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double prevDayHigh, prevDayLow, prevDayOpen, prevDayClose, prevDayVolume; class="type">class="kw">double currentDayVolume; class="type">class="kw">double keySupport, keyResistance; class=class="str">"cmt">// Initialized but will be calculated class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Main function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart() { class=class="str">"cmt">//--- Get previous day&class="macro">#x27;s data class="type">int prevDayIndex = iBarShift(NULL, PERIOD_D1, iTime(NULL, PERIOD_D1, class="num">1)); if(prevDayIndex == -class="num">1) { Print("Error retrieving previous day&class="macro">#x27;s data."); class="kw">return; } prevDayHigh = iHigh(NULL, PERIOD_D1, prevDayIndex);
◍ 用前日高低与量能画出生死线
把前一日 K 线的基础数据抓出来,是日内区间交易的第一道工序。下面这段代码用 iLow / iOpen / iClose / iVolume 在日线周期上取 prevDayIndex 对应的低、开、收、量,再用 iVolume 取当日(索引 0)成交量,两个数字的差就是日内情绪的温度计。 prevDayLow = iLow(NULL, PERIOD_D1, prevDayIndex); prevDayOpen = iOpen(NULL, PERIOD_D1, prevDayIndex); prevDayClose = iClose(NULL, PERIOD_D1, prevDayIndex); prevDayVolume = iVolume(NULL, PERIOD_D1, prevDayIndex); //--- Get today's volume currentDayVolume = iVolume(NULL, PERIOD_D1, 0); // Current day's volume //--- Calculate key support and resistance keySupport = prevDayLow; // Support level can be set to the previous day's low keyResistance = prevDayHigh; // Resistance level can be set to the previous day's high //--- Manage existing lines (if any) //ObjectDelete("SupportLine"); //ObjectDelete("ResistanceLine"); //--- Create support line if(!ObjectCreate(0, "SupportLine", OBJ_HLINE, 0, 0, keySupport)) { Print("Failed to create SupportLine"); } ObjectSetInteger(0, "SupportLine", OBJPROP_COLOR, SupportColor); ObjectSetInteger(0, "SupportLine", OBJPROP_WIDTH, 2); // Set the width of the line //--- Create resistance line if(!ObjectCreate(0, "ResistanceLine", OBJ_HLINE, 0, 0, keyResistance)) { Print("Failed to create ResistanceLine"); } ObjectSetInteger(0, "ResistanceLine", OBJPROP_COLOR, ResistanceColor); ObjectSetInteger(0, "ResistanceLine", OBJPROP_WIDTH, 2); // Set the width of the line //--- Determine the day's nature (Bullish or Bearish) string marketNature; if(prevDayClose > prevDayOpen) { marketNature = "Bullish"; } else if(prevDayClose < prevDayOpen) { marketNature = "Bearish"; } else { marketNature = "Neutral"; } //--- Compare volumes and determine market sentiment string volumeCommentary; if(currentDayVolume > prevDayVolume) { volumeCommentary = "Current day volume is higher than previous day volume. Bullish sentiment may continue."; } else if(currentDayVolume < prevDayVolume) { volumeCommentary = "Current day volume is lower than previous day volume. Bearish sentiment may follow."; } else { volumeCommentary = "Current day volume is equal to previous day volume. Market sentiment remains uncertain."; } //--- Generate market movement commentary string marketCommentary; if(marketNature == "Bullish") { 逐行拆解:iLow(NULL, PERIOD_D1, prevDayIndex) 中 NULL 代表当前图表品种,PERIOD_D1 锁定日线,prevDayIndex 通常是 1(昨天);keySupport 直接赋前日低价,keyResistance 用前日高价,两根 OBJ_HLINE 水平线靠 ObjectCreate 推到图上,线宽写死 2、颜色由外部变量接。 市场性质靠 prevDayClose 与 prevDayOpen 比大小:收高于开判 Bullish,收低于开判 Bearish,相等则 Neutral。量能比较更直白——currentDayVolume 大于 prevDayVolume 时,脚本倾向认为多头情绪可能延续;低于则空头情绪可能跟进;相等就标不确定。外汇与贵金属波动受杠杆放大,这套判定只是概率倾向,实盘须自担高风险。 把这段直接塞进 EA 的 OnTick 或独立脚本里跑,打开 XAUUSD 的 MT5 日线图,就能看到前日高低自动划线。若发现 SupportLine 没出现,先查 Print 里的 Failed 报错,多半是对象名冲突或图表权限问题。
prevDayLow = iLow(NULL, PERIOD_D1, prevDayIndex); prevDayOpen = iOpen(NULL, PERIOD_D1, prevDayIndex); prevDayClose = iClose(NULL, PERIOD_D1, prevDayIndex); prevDayVolume = iVolume(NULL, PERIOD_D1, prevDayIndex); class=class="str">"cmt">//--- Get today&class="macro">#x27;s volume currentDayVolume = iVolume(NULL, PERIOD_D1, class="num">0); class=class="str">"cmt">// Current day&class="macro">#x27;s volume class=class="str">"cmt">//--- Calculate key support and resistance keySupport = prevDayLow; class=class="str">"cmt">// Support level can be set to the previous day&class="macro">#x27;s low keyResistance = prevDayHigh; class=class="str">"cmt">// Resistance level can be set to the previous day&class="macro">#x27;s high class=class="str">"cmt">//--- Manage existing lines(if any) class=class="str">"cmt">//ObjectDelete("SupportLine"); class=class="str">"cmt">//ObjectDelete("ResistanceLine"); class=class="str">"cmt">//--- Create support line if(!ObjectCreate(class="num">0, "SupportLine", OBJ_HLINE, class="num">0, class="num">0, keySupport)) { Print("Failed to create SupportLine"); } ObjectSetInteger(class="num">0, "SupportLine", OBJPROP_COLOR, SupportColor); ObjectSetInteger(class="num">0, "SupportLine", OBJPROP_WIDTH, class="num">2); class=class="str">"cmt">// Set the width of the line class=class="str">"cmt">//--- Create resistance line if(!ObjectCreate(class="num">0, "ResistanceLine", OBJ_HLINE, class="num">0, class="num">0, keyResistance)) { Print("Failed to create ResistanceLine"); } ObjectSetInteger(class="num">0, "ResistanceLine", OBJPROP_COLOR, ResistanceColor); ObjectSetInteger(class="num">0, "ResistanceLine", OBJPROP_WIDTH, class="num">2); class=class="str">"cmt">// Set the width of the line class=class="str">"cmt">//--- Determine the day&class="macro">#x27;s nature(Bullish or Bearish) class="type">class="kw">string marketNature; if(prevDayClose > prevDayOpen) { marketNature = "Bullish"; } else if(prevDayClose < prevDayOpen) { marketNature = "Bearish"; } else { marketNature = "Neutral"; } class=class="str">"cmt">//--- Compare volumes and determine market sentiment class="type">class="kw">string volumeCommentary; if(currentDayVolume > prevDayVolume) { volumeCommentary = "Current day volume is higher than previous day volume. Bullish sentiment may class="kw">continue."; } else if(currentDayVolume < prevDayVolume) { volumeCommentary = "Current day volume is lower than previous day volume. Bearish sentiment may follow."; } else { volumeCommentary = "Current day volume is equal to previous day volume. Market sentiment remains uncertain."; } class=class="str">"cmt">//--- Generate market movement commentary class="type">class="kw">string marketCommentary; if(marketNature == "Bullish") {
把前一日判定结果打印到图表
这段逻辑收口在「市场性质」的分支赋值:若前一日收高,marketCommentary 记为偏多情绪、提示关注延续形态;若收低则记为偏空、建议顺着趋势考虑仓位;若持平则提示中性、等待突破。外汇与贵金属波动受杠杆放大,这类文字只是概率倾向,不能直接当入场指令。 真正落地的是把前面算出的 Open/Close/High/Low 以及两天成交量、支撑阻力,用 DoubleToString 统一成固定小数位(价格 5 位、成交量 0 位)拼进 textOutput,最后一句 Comment(textOutput) 直接把整块字幕打到图表左上。你在 MT5 里按 F4 粘这段、编译后拖到 XAUUSD 的 H1,就能看到前日分析常驻屏上。 注意成交量字段用的是 prevDayVolume 与 currentDayVolume 两个变量,若你前期没给它们赋过值,图表会显示 0 或乱码——这是最常见的「代码能跑但没数」坑。
marketCommentary = "The market closed higher yesterday, indicating bullish sentiment. Look for potential continuation patterns."; } else if(marketNature == "Bearish") { marketCommentary = "The market closed lower yesterday, indicating bearish sentiment. Consider taking positions that align with this trend."; } else { marketCommentary = "The market showed neutrality with little change. Watch for potential breakout opportunities."; } class=class="str">"cmt">//--- Display the information in a table-like format on the chart class="type">class="kw">string textOutput = "Previous Day Analytics:\n"; textOutput += "Open: " + DoubleToString(prevDayOpen, class="num">5) + "\n"; textOutput += "Close: " + DoubleToString(prevDayClose, class="num">5) + "\n"; textOutput += "High: " + DoubleToString(prevDayHigh, class="num">5) + "\n"; textOutput += "Low: " + DoubleToString(prevDayLow, class="num">5) + "\n"; textOutput += "Volume(Prev Day): " + DoubleToString(prevDayVolume, class="num">0) + "\n"; textOutput += "Volume(Current Day): " + DoubleToString(currentDayVolume, class="num">0) + "\n"; textOutput += "Support: " + DoubleToString(keySupport, class="num">5) + "\n"; textOutput += "Resistance: " + DoubleToString(keyResistance, class="num">5) + "\n"; textOutput += "\nMarket Nature: " + marketNature + "\n"; textOutput += volumeCommentary + "\n"; textOutput += marketCommentary; class=class="str">"cmt">// Draw the text output on the chart Comment(textOutput); }
「在 MetaEditor 里把前日高低点脚本化」
用 MetaEditor 建一个脚本(Script)而不是 EA,是因为它只跑一次、不常驻,适合做「抓前日数据 + 画线 + 图表注释」这种轻量任务。脚本头部先写 #property 的 copyright、link、version,版本号留 1.0 方便你以后改完追踪变更,不至于把旧线稿和新逻辑搞混。 引入 <Trade\Trade.mqh> 后,把可调项丢进 input:支撑线颜色默认 clrGreen、阻力线 clrRed、表格文字 clrBlue,以及 X/Y 偏移 10 和 50。这样不用动底层代码,在 MT5 参数面板就能改配色和位置,黄金和欧美不同品种用不同颜色也好分辨。 主函数 OnStart 里先用 iBarShift 配 iTime(NULL, PERIOD_D1, 1) 定位「最后一个完整日 K」的索引;若返回 -1 就 Print 报错并 return,避免拿空数据往下算。随后 iHigh/iLow/iOpen/iClose/iVolume 把前日 OHLC 和成交量取回来,当日量用 iVolume(...,0)。 支撑直接等于前日最低、阻力等于前日最高,ObjectCreate 画 OBJ_HLINE 失败就打印。市场性质用 prevDayClose 与 prevDayOpen 比大小判 Bullish/Bearish/Neutral;当日量大于前日量时注释写「higher」、小于写「lower」。外汇和贵金属波动大、杠杆高,这类前日区间只作参考,实际突破概率随新闻面变化。 下面这段是核心片段,逐行看:#property 三行是脚本元信息;#include 引入交易库;五个 input 定义用户可调参数;全局 double 存前日与当日量价;OnStart 内 iBarShift 找前日索引,失败返 -1 即退出;之后取数、赋值 keySupport/Resistance、画水平线、判涨跌和量能。复制进 MetaEditor 按 F7 编译,拖到 XAUUSD 日图就能看到线和注释。
class="macro">#class="kw">property copyright "class="num">2024, MetaQuotes Software Corp" class="macro">#class="kw">property link "[MQL5官方文档] class="macro">#class="kw">property version "class="num">1.0" class="macro">#include <Trade\Trade.mqh> input class="type">class="kw">color TableTextColor = clrBlue; class=class="str">"cmt">// Text class="type">class="kw">color for the table input class="type">int TableXOffset = class="num">10; class=class="str">"cmt">// X offset for the table input class="type">int TableYOffset = class="num">50; class=class="str">"cmt">// Y offset for the table input class="type">class="kw">color SupportColor = clrGreen; class=class="str">"cmt">// Color for the support line input class="type">class="kw">color ResistanceColor = clrRed; class=class="str">"cmt">// Color for the resistance line class="type">class="kw">double prevDayHigh, prevDayLow, prevDayOpen, prevDayClose, prevDayVolume; class="type">class="kw">double currentDayVolume; class="type">class="kw">double keySupport, keyResistance; class=class="str">"cmt">// Initialized but will be calculated class="type">void OnStart() class="type">int prevDayIndex = iBarShift(NULL, PERIOD_D1, iTime(NULL, PERIOD_D1, class="num">1)); if (prevDayIndex == -class="num">1) { Print("Error retrieving previous day&class="macro">#x27;s data."); class="kw">return; } prevDayHigh = iHigh(NULL, PERIOD_D1, prevDayIndex); prevDayLow = iLow(NULL, PERIOD_D1, prevDayIndex); prevDayOpen = iOpen(NULL, PERIOD_D1, prevDayIndex); prevDayClose = iClose(NULL, PERIOD_D1, prevDayIndex); prevDayVolume = iVolume(NULL, PERIOD_D1, prevDayIndex); currentDayVolume = iVolume(NULL, PERIOD_D1, class="num">0); class=class="str">"cmt">// Current day&class="macro">#x27;s volume keySupport = prevDayLow; class=class="str">"cmt">// Support level can be set to the previous day&class="macro">#x27;s low keyResistance = prevDayHigh; class=class="str">"cmt">// Resistance level can be set to the previous day&class="macro">#x27;s high if (!ObjectCreate(class="num">0, "SupportLine", OBJ_HLINE, class="num">0, class="num">0, keySupport)) { Print("Failed to create SupportLine"); } if (prevDayClose > prevDayOpen) { marketNature = "Bullish"; } else if (prevDayClose < prevDayOpen) { marketNature = "Bearish"; } else { marketNature = "Neutral"; } if (currentDayVolume > prevDayVolume) { volumeCommentary = "Current day volume is higher..."; } else if (currentDayVolume < prevDayVolume) { volumeCommentary = "Current day volume is lower..."; }