价格行为分析工具包开发(第十五部分):引入四分位理论(1)四分位绘图脚本·进阶篇
📘

价格行为分析工具包开发(第十五部分):引入四分位理论(1)四分位绘图脚本·进阶篇

第 2/3 篇

「先给水平线定好样式与画法」

做整数位与四分位参考线,第一步是把线的样式和粗细参数暴露给输入变量,方便在 MT5 属性框里直接调。下面这组 input 把主线、大四分位、溢出线、小四分位分别定义了线型与宽度:主线用实线宽 4,大四分位用点线宽 3,溢出线用虚线宽 1,小四分位用实线宽 1;溢出线颜色单独设为红色(clrRed),用来标记价格越过整数边界后的回测区。 核心画图靠 DrawHorizontalLine 这个函数:先用 ObjectFind 查重,若存在就 ObjectDelete 删掉旧对象,再 ObjectCreate 建 OBJ_HLINE 水平线。注意创建时传的日期参数是 0、价格为传入的 price,说明它不绑定时点,纯水平。 建完立刻用 ObjectSetInteger 写四个属性:颜色、线型、宽度、以及 OBJPROP_RAY_RIGHT 置 true,让线向右无限延伸。这样每次 OnStart 重跑,线会被覆盖刷新而不是越画越多。 OnStart 里取 _Symbol 的 SYMBOL_BID 作当前价,用 MathFloor(currentPrice / MajorStep) * MajorStep 算出下边界整数区,加 MajorStep 得上边界。以 XAUUSD 为例,若 MajorStep=100、现价 2034.5,下边界 2000、上边界 2100,两条主线就落在这两个整数上;DrawLargeQuarters 开启时,再按 MajorStep/4 循环画 3 条大四分位线(i=1,2,3)。外汇与贵金属波动剧烈,这类参考线仅作区域概率判断,实盘须自担高风险。

MQL5 / C++
input ENUM_LINE_STYLE MajorLineStyle        = STYLE_SOLID;
input class="type">int    MajorLineWidth                 = class="num">4;
input ENUM_LINE_STYLE LargeQuarterLineStyle = STYLE_DOT;
input class="type">int    LargeQuarterLineWidth          = class="num">3;
input ENUM_LINE_STYLE OvershootLineStyle    = STYLE_DASH;
input class="type">int    OvershootLineWidth             = class="num">1;
input ENUM_LINE_STYLE SmallQuarterLineStyle = STYLE_SOLID;
input class="type">int    SmallQuarterLineWidth          = class="num">1;

input class="type">class="kw">color OvershootColor = clrRed;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| DrawHorizontalLine: Creates or replaces a horizontal line        |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void DrawHorizontalLine(class="type">class="kw">string name, class="type">class="kw">double price, class="type">class="kw">color lineColor, class="type">int width, ENUM_LINE_STYLE style)
{
   class=class="str">"cmt">// Delete the object if it already exists
   if(ObjectFind(class="num">0, name) != -class="num">1)
      ObjectDelete(class="num">0, name);
   class=class="str">"cmt">// Create a new horizontal line object
   if(!ObjectCreate(class="num">0, name, OBJ_HLINE, class="num">0, class="num">0, price))
   {
      Print("Failed to create line: ", name);
      class="kw">return;
   }
   class=class="str">"cmt">// Set properties: class="type">class="kw">color, style, width, and extension to the right
   ObjectSetInteger(class="num">0, name, OBJPROP_COLOR, lineColor);
   ObjectSetInteger(class="num">0, name, OBJPROP_STYLE, style);
   ObjectSetInteger(class="num">0, name, OBJPROP_WIDTH, width);
   ObjectSetInteger(class="num">0, name, OBJPROP_RAY_RIGHT, true);
}
class="type">void OnStart()
{
   class=class="str">"cmt">// Get current symbol price
   class="type">class="kw">string symbol = _Symbol;
   class="type">class="kw">double currentPrice = SymbolInfoDouble(symbol, SYMBOL_BID);
   if(currentPrice == class="num">0)
      class="kw">return;
   class=class="str">"cmt">// Calculate the major range based on the current price and MajorStep
   class="type">class="kw">double lowerMajor = MathFloor(currentPrice / MajorStep) * MajorStep;
   class="type">class="kw">double upperMajor = lowerMajor + MajorStep;
   class=class="str">"cmt">// Draw Major Whole Number lines at lower and upper boundaries
   DrawHorizontalLine("MajorLower", lowerMajor, MajorColor, MajorLineWidth, MajorLineStyle);
   DrawHorizontalLine("MajorUpper", upperMajor, MajorColor, MajorLineWidth, MajorLineStyle);
   class=class="str">"cmt">// Draw Large Quarter lines and overshoot/undershoot lines if enabled
   if(DrawLargeQuarters)
   {
      class="type">class="kw">double LQIncrement = MajorStep / class="num">4.0;
      for(class="type">int i = class="num">1; i < class="num">4; i++)
      {
         class="type">class="kw">double level = lowerMajor + i * LQIncrement;

大季度线之外的偏移区与小季度线绘制

大季度水平线画完后,若开关 DrawOvershootAreas 为真,会在每条大季度线上下各推一个微小区间。这个微小量取 MajorStep 的 1/40,即把主阶等分成 40 份后的单份宽度,用来标记价格可能短暂刺穿大季度位的「过冲 / 下冲」地带。 小季度线的粒度更细:先算 segStep = MajorStep / 10.0,再取 smallQuarter = segStep / 4.0,也就是主阶的 1/40。循环把每个主阶切成 10 段,每段内部在 1/4、2/4、3/4 处落三条线,最终每主阶出 30 条小季度线。 图表右上角会常驻一个 OBJ_LABEL 文本标签,内容写死版本与作者信息,距右边 80 像素、上边 10 像素、字号 14、黄色。每次重跑脚本先 ObjectFind 删旧标签再建新的,避免堆叠。 所有对象画完调用 ChartRedraw() 强制刷新。外汇与贵金属价格行为受事件驱动,这些参考线仅辅助读位,刺穿概率随波动率变化,实盘请自验。

MQL5 / C++
class="type">class="kw">string objName = "LargeQuarter_" + IntegerToString(i);
DrawHorizontalLine(objName, level, LargeQuarterColor, LargeQuarterLineWidth, LargeQuarterLineStyle);
if(DrawOvershootAreas)
{
   class="type">class="kw">double smallQuarter = MajorStep / class="num">40.0;
   DrawHorizontalLine("Overshoot_" + IntegerToString(i) + "_up", level + smallQuarter, OvershootColor, OvershootLineWidth, OvershootLineStyle);
   DrawHorizontalLine("Undershoot_" + IntegerToString(i) + "_down", level - smallQuarter, OvershootColor, OvershootLineWidth, OvershootLineStyle);
}
class=class="str">"cmt">// Draw Small Quarter lines if enabled
if(DrawSmallQuarters)
{
   class="type">class="kw">double segStep = MajorStep / class="num">10.0;
   class="type">class="kw">double smallQuarter = segStep / class="num">4.0;
   for(class="type">int seg = class="num">0; seg < class="num">10; seg++)
   {
      class="type">class="kw">double segStart = lowerMajor + seg * segStep;
      for(class="type">int j = class="num">1; j < class="num">4; j++)
      {
         class="type">class="kw">double level = segStart + j * smallQuarter;
         class="type">class="kw">string objName = "SmallQuarter_" + IntegerToString(seg) + "_" + IntegerToString(j);
         DrawHorizontalLine(objName, level, SmallQuarterColor, SmallQuarterLineWidth, SmallQuarterLineStyle);
      }
   }
}
class=class="str">"cmt">// Create a persistent label(logo) in the top-right corner
if(ObjectFind(class="num">0, "ScriptLogo") != -class="num">1)
   ObjectDelete(class="num">0, "ScriptLogo");
if(ObjectCreate(class="num">0, "ScriptLogo", OBJ_LABEL, class="num">0, class="num">0, class="num">0))
{
   class="type">class="kw">string logoText = "Script: DrawQuarters_DarkBold\nv1.class="num">04\nby Christian Benjamin";
   ObjectSetString(class="num">0, "ScriptLogo", OBJPROP_TEXT, logoText);
   ObjectSetInteger(class="num">0, "ScriptLogo", OBJPROP_COLOR, clrYellow);
   ObjectSetInteger(class="num">0, "ScriptLogo", OBJPROP_FONTSIZE, class="num">14);
   ObjectSetInteger(class="num">0, "ScriptLogo", OBJPROP_CORNER, CORNER_RIGHT_UPPER);
   ObjectSetInteger(class="num">0, "ScriptLogo", OBJPROP_XDISTANCE, class="num">80);
   ObjectSetInteger(class="num">0, "ScriptLogo", OBJPROP_YDISTANCE, class="num">10);
}
class=class="str">"cmt">// Redraw the chart to display all objects
ChartRedraw();

◍ 把整数位与四分位画进图表

这套指标把价格轴按「整数大关 + 大四分位 + 小四分位」三层结构铺到 MT5 图上,MajorStep 默认 0.1000,意味着每 100 点画一条暗石板灰的实心主线,适合 EURUSD 这类报价精确到小数点后四位的品种。 大四分位(暗红点线)和小四分位(深蓝实线,宽 1)分别由 DrawLargeQuarters、DrawSmallQuarters 开关控制;前者把每个整数段再切 4 份,后者继续切细。OvershootColor 用纯红标出大四分位附近的穿越区,线型为虚线、宽 1,帮你肉眼捕捉假突破。 DrawHorizontalLine 是核心函数:先 ObjectFind 查重,若已存在同名对象就 ObjectDelete 清掉再重画,避免历史线堆积。下面这段代码是函数头部与查重逻辑,直接拷进 MQ5 文件就能用。 外汇与贵金属杠杆高、滑点大,这类辅助线只提示结构位,进出场仍要结合实时盘口与风控。

MQL5 / C++
class=class="str">"cmt">//|                    Copyright class="num">2025, Christian Benjamin|
class=class="str">"cmt">//|             [MQL5官方文档]
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Christian Benjamin"
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.0"
class="macro">#class="kw">property strict
class=class="str">"cmt">//---- Input parameters -------------------------------------------------
input class="type">class="kw">double MajorStep           = class="num">0.1000;   class=class="str">"cmt">// Difference between major whole numbers.
input class="type">bool   DrawLargeQuarters   = true;     class=class="str">"cmt">// Draw intermediate large quarter lines.
input class="type">bool   DrawSmallQuarters   = true;     class=class="str">"cmt">// Draw small quarter lines.
input class="type">bool   DrawOvershootAreas = true;     class=class="str">"cmt">// Mark overshoot/undershoot areas for large quarter lines.
class=class="str">"cmt">//---- Color settings ---------------------------------------------------
input class="type">class="kw">color  MajorColor          = 0x2F4F4F; class=class="str">"cmt">// Dark Slate Gray for major lines.
input class="type">class="kw">color  LargeQuarterColor   = 0x8B0000; class=class="str">"cmt">// Dark Red for large quarter lines.
input class="type">class="kw">color  SmallQuarterColor   = 0x00008B; class=class="str">"cmt">// Dark Blue for small quarter lines.
input class="type">class="kw">color  OvershootColor      = clrRed;   class=class="str">"cmt">// Red for overshoot/undershoot lines.
class=class="str">"cmt">//---- Group style and thickness settings -------------------------------
input ENUM_LINE_STYLE MajorLineStyle        = STYLE_SOLID;
input class="type">int    MajorLineWidth                 = class="num">4;
input ENUM_LINE_STYLE LargeQuarterLineStyle = STYLE_DOT;
input class="type">int    LargeQuarterLineWidth          = class="num">3;
input ENUM_LINE_STYLE OvershootLineStyle    = STYLE_DASH;
input class="type">int    OvershootLineWidth             = class="num">1;
class=class="str">"cmt">// For small quarter lines, we now use a continuous(solid) style.
input ENUM_LINE_STYLE SmallQuarterLineStyle = STYLE_SOLID;
input class="type">int    SmallQuarterLineWidth          = class="num">1;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| DrawHorizontalLine: Creates or replaces a horizontal line          |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void DrawHorizontalLine(class="type">class="kw">string name, class="type">class="kw">double price, class="type">class="kw">color lineColor, class="type">int width, ENUM_LINE_STYLE style)
  {
   if(ObjectFind(class="num">0, name) != -class="num">1)
      ObjectDelete(class="num">0, name);

「把价位网格画进图表的那段入口逻辑」

OnStart 是脚本跑起来的唯一入口,先抓当前品种的 BID 价:SymbolInfoDouble(_Symbol, SYMBOL_BID) 拿到后若返回 0 直接 return,避免在非交易时段或离线图表上瞎画。 以 MajorStep 为中枢,用 MathFloor(currentPrice / MajorStep) * MajorStep 向下取整得到下边界 lowerMajor,再加一步得 upperMajor,这两条大数线就是整数关卡的上下沿。 大四分之一线按 MajorStep/4.0 切三刀(i=1,2,3),若开了 DrawLargeQuarters 就逐条 DrawHorizontalLine;同时若 DrawOvershootAreas 为真,会在每个大四分之一线正负 MajorStep/40.0 处补画 overshoot/undershoot 辅助线,用来观察价格刺穿后的回归概率。 小四分之一线走的是 MajorStep/10.0 分十段、每段再除 4.0 的更密逻辑,仅画连续线不画刺穿区,适合 EURUSD 这类点差小的品种做微观支撑阻力参考。外汇与贵金属杠杆高,网格仅作结构参考,实盘须自担滑点与跳空风险。

MQL5 / C++
  if(!ObjectCreate(class="num">0, name, OBJ_HLINE, class="num">0, class="num">0, price))
    {
      Print("Failed to create line: ", name);
      class="kw">return;
    }
  ObjectSetInteger(class="num">0, name, OBJPROP_COLOR, lineColor);
  ObjectSetInteger(class="num">0, name, OBJPROP_STYLE, style);
  ObjectSetInteger(class="num">0, name, OBJPROP_WIDTH, width);
  ObjectSetInteger(class="num">0, name, OBJPROP_RAY_RIGHT, true);
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script entry point                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
class=class="str">"cmt">// Get current symbol price
  class="type">class="kw">string symbol = _Symbol;
  class="type">class="kw">double currentPrice = SymbolInfoDouble(symbol, SYMBOL_BID);
  if(currentPrice == class="num">0)
    class="kw">return;
class=class="str">"cmt">// Calculate the major range
  class="type">class="kw">double lowerMajor = MathFloor(currentPrice / MajorStep) * MajorStep;
  class="type">class="kw">double upperMajor = lowerMajor + MajorStep;
class=class="str">"cmt">// Draw Major Whole Number lines
  DrawHorizontalLine("MajorLower", lowerMajor, MajorColor, MajorLineWidth, MajorLineStyle);
  DrawHorizontalLine("MajorUpper", upperMajor, MajorColor, MajorLineWidth, MajorLineStyle);
class=class="str">"cmt">// Draw Large Quarter lines and their overshoot/undershoot lines
  if(DrawLargeQuarters)
    {
      class="type">class="kw">double LQIncrement = MajorStep / class="num">4.0;
      for(class="type">int i = class="num">1; i < class="num">4; i++)
        {
          class="type">class="kw">double level = lowerMajor + i * LQIncrement;
          class="type">class="kw">string objName = "LargeQuarter_" + IntegerToString(i);
          DrawHorizontalLine(objName, level, LargeQuarterColor, LargeQuarterLineWidth, LargeQuarterLineStyle);
          if(DrawOvershootAreas)
            {
              class="type">class="kw">double smallQuarter = MajorStep / class="num">40.0;
              DrawHorizontalLine("Overshoot_" + IntegerToString(i) + "_up", level + smallQuarter, OvershootColor, OvershootLineWidth, OvershootLineStyle);
              DrawHorizontalLine("Undershoot_" + IntegerToString(i) + "_down", level - smallQuarter, OvershootColor, OvershootLineWidth, OvershootLineStyle);
            }
        }
    }
class=class="str">"cmt">// Draw Small Quarter lines if enabled(continuous lines, without overshoot/undershoot)
  if(DrawSmallQuarters)
    {
      class="type">class="kw">double segStep = MajorStep / class="num">10.0;
      class="type">class="kw">double smallQuarter = segStep / class="num">4.0;
      for(class="type">int seg = class="num">0; seg < class="num">10; seg++)
        {
          class="type">class="kw">double segStart = lowerMajor + seg * segStep;
          for(class="type">int j = class="num">1; j < class="num">4; j++)
            {

常见问题

在脚本里给不同四分位单独设 clr 颜色和 STYLE_DASH 线型,大季度线用实线、小季度线用虚线,一眼能区分层级。
在偏移区循环里把基础价位加减偏移步长后传入画线函数,步长设成季度区间的 1/4 即可生成上下小季度线。
可以,小布盯盘的 AIGC 已内置该绘图逻辑,打开对应品种页就能直接加载四分位与整数位网格,不用自己跑脚本。
多半是入口没先判断图表品种是否有足够历史K线,先在 OnStart 里用 Bars() 做存在性校验再调绘制函数即可。
要改,贵金属点值大、波动区间宽,偏移步长建议按品种真实振幅的 1/4 重算,直接套外汇参数会画得太密。