价格行为分析工具包开发(第十五部分):引入四分位理论(1)——四分位绘图脚本
内容
概述
所有市场中,价格均呈周期性波动。无论价格处于上涨还是下跌趋势,均会在特定区间内反复震荡。长期以来,交易者已提出了多种理论来解释这些价格模式。在我们持续推出的系列文章中,正着力构建一套全面的价格行为分析工具包。今天,我们将介绍一种创新方法,并通过MQL5实现自动化,以简化应用流程并取得显著成效。
本文聚焦于四分位理论。该理论由伊利安·约托夫(Ilian Yotov)提出,他因在交易者电视网的工作而成为数千名外汇交易者和策略师熟知的行业专家。伊利安创立了AllThingsForex.com和TraderTape.com网站,并主持广受欢迎的日播节目《All Things Forex》。其理论指出,重大价格波动通常发生在两个“大四分位点”之间,且以250点(PIPs)为增量逐步推进。该方法为识别关键支撑位与阻力位提供了明确标志,同时为交易者提供了实用的市场洞察。
本文为四分位理论系列的首篇。在本期内容中,我们将聚焦于通过“四分位绘图脚本”构建四分位水平线。通过自动化绘制这些关键价位,我们为交易者提供了一个直观的起点,助力其识别潜在的反转与延续区域。随着对四分位理论的深入探索,我们将开发更强大的工具,以支持信号生成与高级市场分析。
理念概述
四分位理论是一种技术分析方法,它将重要的价格区间划分为更小、更具意义的细分段。在该框架中,“主步长”(MajorStep)——例如,欧元兑美元(EUR/USD)等货币对中的0.1000,定义了主要整数价位之间的差值(如1.2000至1.3000)。随后,这一区间被均分为四个部分,称为大四分位线。每条大四分位线代表一个关键价位,价格可能在此暂停、反转或加速,为交易者提供潜在的支撑与阻力区域。
四分位理论的核心要素
- 主要整数价位: 这些是构成交易区间框架的基础价位(如1.2000、1.3000)。用于构建理论的精细结构。
- 大四分位线: 两个主要整数价位之间的区间被均分为四个部分。这些线标示出中间价位,往往在价格行为中发挥重要作用。交易者利用这些价位预测潜在的转折点或盘整区域。
- 小四分位线: 为进一步提升精度,每个100点(pip)的区间可进一步细分为更小的部分,即小四分位线。尽管这些线提供了更细致的层级,但核心关注点仍在于大四分位线。
- 超调/欠调区域: 在每条大四分位线周围,绘制微小的偏移区域(超调与欠调),以标示价格可能短暂突破或未达预期价位的区域。这些区域有助于识别潜在的修正或反转信号。
如需更深入的理解,请参考以下图示

图例1. 四分位

图例2. 四分位
通过在图表上直观地标示出这些关键价位,四分位理论为交易者提供了一种结构化评估价格动态的方法。该理论通过脚本“四分位绘图工具”(Quarters Drawer)得以实现,该脚本以不同样式和颜色绘制清晰的线条,确保主要价位线、大四分位线和小四分位线等各组价位均易于区分。这一可视化工具通过清晰凸显关键价格区间,进一步强化了四分位理论的应用效果。
MQL5实现
脚本的首个代码块包含一个头部注释,该注释提供了脚本名称、版本、版权信息以及指向 作者个人主页的链接等关键细节。随后,属性声明部分嵌入了重要元数据(如版权和版本信息),并启用了严格的编译设置。这种组合既确立了脚本的唯一标识,又确保其遵循了严谨的编码规范。
//+------------------------------------------------------------------+ //| Quarters Drawer.mql5| //| Copyright 2025, Christian Benjamin| //| https://www.mql5.com/en/users/lynnchris| //+------------------------------------------------------------------+ #property copyright "Christian Benjamin" #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.0" #property strict
接下来,通过定义输入参数,赋予用户对脚本行为和外观的完全控制权。例如,您可通过类似MajorStep的参数设定主要价格区间间隔,并使用布尔标识控制大四分位线、小四分位线以及超调/欠调标记的绘制。如果将DrawLargeQuarters设置为true,脚本将绘制大四分位线;设置为false则隐藏这些线条。
同理,对于DrawSmallQuarters和DrawOvershootAreas,如果您不想显示小四分位线或超调区域,只需将其值设为false即可。这种设计使得用户无需修改核心逻辑即可轻松定制显示效果。此外,脚本还为每种线条提供了颜色设置、线型及粗细选项,方便交易者根据个人偏好和交易策略调整视觉输出。
//---- Input parameters ------------------------------------------------- input double MajorStep = 0.1000; // Difference between major whole numbers. input bool DrawLargeQuarters = true; // Draw intermediate large quarter lines. input bool DrawSmallQuarters = true; // Draw small quarter lines. input bool DrawOvershootAreas = true; // Mark overshoot/undershoot areas for large quarter lines. //---- Color settings --------------------------------------------------- input color MajorColor = 0x2F4F4F; // Dark Slate Gray for major lines. input color LargeQuarterColor = 0x8B0000; // Dark Red for large quarter lines. input color SmallQuarterColor = 0x00008B; // Dark Blue for small quarter lines. input color OvershootColor = clrRed; // Red for overshoot/undershoot lines. //---- Group style and thickness settings ------------------------------- input ENUM_LINE_STYLE MajorLineStyle = STYLE_SOLID; input int MajorLineWidth = 4; input ENUM_LINE_STYLE LargeQuarterLineStyle = STYLE_DOT; input int LargeQuarterLineWidth = 3; input ENUM_LINE_STYLE OvershootLineStyle = STYLE_DASH; input int OvershootLineWidth = 1; input ENUM_LINE_STYLE SmallQuarterLineStyle = STYLE_SOLID; input int SmallQuarterLineWidth = 1;
当您在脚本中看到十六进制颜色代码时,它们通过组合红、绿、蓝(RGB)分量值来表示特定颜色。例如:
- 0x2F4F4F —— 该代码对应深石板灰(Dark Slate Gray)。其中,每两位十六进制数分别代表红、绿、蓝分量。这里“2F”(十进制为47)表示红色,“4F”(十进制为79)同时表示绿色和蓝色,最终形成一种柔和的冷灰色调,非常适合作为图表中的主线条颜色。
- 0x8B0000 —— 该代码表示深红色(Dark Red)。其中,“8B”(十进制为139)是强烈的红色分量,绿色和蓝色分量均为“00”(零),从而呈现出深邃浓郁的红色。脚本中用此颜色突出显示大四分位线。
- 0x00008B —— 该代码代表深蓝色(Dark Blue)。其中,红色和绿色分量均为“00”,蓝色分量为“8B”(十进制为139),最终生成深蓝色。脚本将其应用于小四分位线,以形成鲜明的视觉对比。
除这些硬编码的十六进制值外,脚本还使用了预定义常量clrRed。无需手动指定十六进制代码,直接使用此内置常量即可(通常表示RGB值为(255, 0, 0)的红色)。例如,脚本中超调区域的颜色设置如下:
input color OvershootColor = clrRed;
根据输入内容,该脚本包含一个专门用于在图表上绘制水平线的函数。此函数首先会检查是否已存在指定名称的线条,如果已存在,则将其移除,以避免重复绘制。接着,该函数会在指定的价格水平位置创建一条新的水平线,并应用预先定义的颜色、样式和线宽。通过确保每条线都能横跨整个图表,这一模块化函数简化了在整个脚本中统一绘制多条水平线的过程。
//+------------------------------------------------------------------+ //| DrawHorizontalLine: Creates or replaces a horizontal line | //+------------------------------------------------------------------+ void DrawHorizontalLine(string name, double price, color lineColor, int width, ENUM_LINE_STYLE style) { // Delete the object if it already exists if(ObjectFind(0, name) != -1) ObjectDelete(0, name); // Create a new horizontal line object if(!ObjectCreate(0, name, OBJ_HLINE, 0, 0, price)) { Print("Failed to create line: ", name); return; } // Set properties: color, style, width, and extension to the right ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor); ObjectSetInteger(0, name, OBJPROP_STYLE, style); ObjectSetInteger(0, name, OBJPROP_WIDTH, width); ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, true); }
脚本的主执行流程始于OnStart函数,在该函数中,脚本会获取当前交易品种及其买入价。这一步至关重要,因为所有后续计算均依赖于有效的市场价格。如果无法获取买入价,脚本将提前退出,以防止出现任何错误,从而确保仅在数据有效的情况下才执行进一步操作。
void OnStart() { // Get current symbol price string symbol = _Symbol; double currentPrice = SymbolInfoDouble(symbol, SYMBOL_BID); if(currentPrice == 0) return;
一旦获取当前价格后,脚本会计算主要价格水平,这些水平将作为主要的参考点。通过将当前价格向下取整至由MajorStep定义的最近间隔来确定较低水平,然后通过加上相同的间隔值来计算较高水平。这样计算得出的水平构建了一个结构化框架,为其余可视化网格设定了明确的边界。
// Calculate the major range based on the current price and MajorStep double lowerMajor = MathFloor(currentPrice / MajorStep) * MajorStep; double upperMajor = lowerMajor + MajorStep;
利用这些主要价格水平,脚本随后在下边界和上边界处绘制两条醒目的水平线。这些主要线条采用特定的颜色、粗细和线型样式进行设计,使其在图表上易于辨识。它们构成了图表视觉结构的骨干,有助于交易者快速发现重要的支撑位和阻力位区域。
// Draw Major Whole Number lines at lower and upper boundaries DrawHorizontalLine("MajorLower", lowerMajor, MajorColor, MajorLineWidth, MajorLineStyle); DrawHorizontalLine("MajorUpper", upperMajor, MajorColor, MajorLineWidth, MajorLineStyle);
如果启用了绘制大四分位线的选项,脚本会将主要价格区间细分为四个相等的部分。其会在主要边界之间计算中间水平位置,并在这些点上绘制水平线。此外,如果同时启用了上冲/下探(overshoot/undershoot)标记功能,还会在每条大四分位线的上方和下方额外绘制线条。这些附加的标记用于突出显示价格可能暂时超出预期范围的位置,为交易者提供有关潜在价格反转的宝贵认知。
// Draw Large Quarter lines and overshoot/undershoot lines if enabled if(DrawLargeQuarters) { double LQIncrement = MajorStep / 4.0; for(int i = 1; i < 4; i++) { double level = lowerMajor + i * LQIncrement; string objName = "LargeQuarter_" + IntegerToString(i); DrawHorizontalLine(objName, level, LargeQuarterColor, LargeQuarterLineWidth, LargeQuarterLineStyle); if(DrawOvershootAreas) { double smallQuarter = MajorStep / 40.0; DrawHorizontalLine("Overshoot_" + IntegerToString(i) + "_up", level + smallQuarter, OvershootColor, OvershootLineWidth, OvershootLineStyle); DrawHorizontalLine("Undershoot_" + IntegerToString(i) + "_down", level - smallQuarter, OvershootColor, OvershootLineWidth, OvershootLineStyle); } } }
如果启用了绘制小四分位线的选项,脚本还能绘制更为精细的线条。其将主要价格区间划分为十个等份,随后再将每个等份进一步细分为更小的子区间。如此一来,便形成了一个更为精细的网格系统,能够捕捉到价格的微小波动,为交易者提供详尽的视图,尤其有助于确定精确的入场和出场点位。
// Draw Small Quarter lines if enabled if(DrawSmallQuarters) { double segStep = MajorStep / 10.0; double smallQuarter = segStep / 4.0; for(int seg = 0; seg < 10; seg++) { double segStart = lowerMajor + seg * segStep; for(int j = 1; j < 4; j++) { double level = segStart + j * smallQuarter; string objName = "SmallQuarter_" + IntegerToString(seg) + "_" + IntegerToString(j); DrawHorizontalLine(objName, level, SmallQuarterColor, SmallQuarterLineWidth, SmallQuarterLineStyle); } } }
为了完善视觉增强效果,脚本还会在图表上添加一个持久显示的标签(或徽标)。该标签会展示脚本的名称、版本及作者信息,既可作为对创作者的署名,也能为用户提供快速参考。在放置标签前,脚本会检查是否已存在相同标签以避免重复,随后将标签定位在图表右上角,并精心设置字体大小和颜色,以确保其清晰可见。
// Create a persistent label (logo) in the top-right corner if(ObjectFind(0, "ScriptLogo") != -1) ObjectDelete(0, "ScriptLogo"); if(ObjectCreate(0, "ScriptLogo", OBJ_LABEL, 0, 0, 0)) { string logoText = "Script: DrawQuarters_DarkBold\nv1.04\nby Christian Benjamin"; ObjectSetString(0, "ScriptLogo", OBJPROP_TEXT, logoText); ObjectSetInteger(0, "ScriptLogo", OBJPROP_COLOR, clrYellow); ObjectSetInteger(0, "ScriptLogo", OBJPROP_FONTSIZE, 14); ObjectSetInteger(0, "ScriptLogo", OBJPROP_CORNER, CORNER_RIGHT_UPPER); ObjectSetInteger(0, "ScriptLogo", OBJPROP_XDISTANCE, 80); ObjectSetInteger(0, "ScriptLogo", OBJPROP_YDISTANCE, 10); }
最后,脚本通过重绘命令刷新图表,确保所有绘制的对象(线条和标签)能够立即显示。最后的这一步至关重要,因为它会更新显示内容,以反映最新的市场数据和自定义设置,从而为技术分析提供一个完整且最新的可视化工具。
// Redraw the chart to display all objects ChartRedraw(); }
MQL5代码
//+------------------------------------------------------------------+ //| Quarters Drawer.mql5| //| Copyright 2025, Christian Benjamin| //| https://www.mql5.com/en/users/lynnchris| //+------------------------------------------------------------------+ #property copyright "Christian Benjamin" #property link "https://www.mql5.com/en/users/lynnchris" #property version "1.0" #property strict //---- Input parameters ------------------------------------------------- input double MajorStep = 0.1000; // Difference between major whole numbers. input bool DrawLargeQuarters = true; // Draw intermediate large quarter lines. input bool DrawSmallQuarters = true; // Draw small quarter lines. input bool DrawOvershootAreas = true; // Mark overshoot/undershoot areas for large quarter lines. //---- Color settings --------------------------------------------------- input color MajorColor = 0x2F4F4F; // Dark Slate Gray for major lines. input color LargeQuarterColor = 0x8B0000; // Dark Red for large quarter lines. input color SmallQuarterColor = 0x00008B; // Dark Blue for small quarter lines. input color OvershootColor = clrRed; // Red for overshoot/undershoot lines. //---- Group style and thickness settings ------------------------------- input ENUM_LINE_STYLE MajorLineStyle = STYLE_SOLID; input int MajorLineWidth = 4; input ENUM_LINE_STYLE LargeQuarterLineStyle = STYLE_DOT; input int LargeQuarterLineWidth = 3; input ENUM_LINE_STYLE OvershootLineStyle = STYLE_DASH; input int OvershootLineWidth = 1; // For small quarter lines, we now use a continuous (solid) style. input ENUM_LINE_STYLE SmallQuarterLineStyle = STYLE_SOLID; input int SmallQuarterLineWidth = 1; //+------------------------------------------------------------------+ //| DrawHorizontalLine: Creates or replaces a horizontal line | //+------------------------------------------------------------------+ void DrawHorizontalLine(string name, double price, color lineColor, int width, ENUM_LINE_STYLE style) { if(ObjectFind(0, name) != -1) ObjectDelete(0, name); if(!ObjectCreate(0, name, OBJ_HLINE, 0, 0, price)) { Print("Failed to create line: ", name); return; } ObjectSetInteger(0, name, OBJPROP_COLOR, lineColor); ObjectSetInteger(0, name, OBJPROP_STYLE, style); ObjectSetInteger(0, name, OBJPROP_WIDTH, width); ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, true); } //+------------------------------------------------------------------+ //| Script entry point | //+------------------------------------------------------------------+ void OnStart() { // Get current symbol price string symbol = _Symbol; double currentPrice = SymbolInfoDouble(symbol, SYMBOL_BID); if(currentPrice == 0) return; // Calculate the major range double lowerMajor = MathFloor(currentPrice / MajorStep) * MajorStep; double upperMajor = lowerMajor + MajorStep; // Draw Major Whole Number lines DrawHorizontalLine("MajorLower", lowerMajor, MajorColor, MajorLineWidth, MajorLineStyle); DrawHorizontalLine("MajorUpper", upperMajor, MajorColor, MajorLineWidth, MajorLineStyle); // Draw Large Quarter lines and their overshoot/undershoot lines if(DrawLargeQuarters) { double LQIncrement = MajorStep / 4.0; for(int i = 1; i < 4; i++) { double level = lowerMajor + i * LQIncrement; string objName = "LargeQuarter_" + IntegerToString(i); DrawHorizontalLine(objName, level, LargeQuarterColor, LargeQuarterLineWidth, LargeQuarterLineStyle); if(DrawOvershootAreas) { double smallQuarter = MajorStep / 40.0; DrawHorizontalLine("Overshoot_" + IntegerToString(i) + "_up", level + smallQuarter, OvershootColor, OvershootLineWidth, OvershootLineStyle); DrawHorizontalLine("Undershoot_" + IntegerToString(i) + "_down", level - smallQuarter, OvershootColor, OvershootLineWidth, OvershootLineStyle); } } } // Draw Small Quarter lines if enabled (continuous lines, without overshoot/undershoot) if(DrawSmallQuarters) { double segStep = MajorStep / 10.0; double smallQuarter = segStep / 4.0; for(int seg = 0; seg < 10; seg++) { double segStart = lowerMajor + seg * segStep; for(int j = 1; j < 4; j++) { double level = segStart + j * smallQuarter; string objName = "SmallQuarter_" + IntegerToString(seg) + "_" + IntegerToString(j); DrawHorizontalLine(objName, level, SmallQuarterColor, SmallQuarterLineWidth, SmallQuarterLineStyle); } } } // Create a persistent label (logo) in the top-right corner if(ObjectFind(0, "ScriptLogo") != -1) ObjectDelete(0, "ScriptLogo"); if(ObjectCreate(0, "ScriptLogo", OBJ_LABEL, 0, 0, 0)) { string logoText = "Script: DrawQuarters_DarkBold\nv1.04\nby Christian Benjamin"; ObjectSetString(0, "ScriptLogo", OBJPROP_TEXT, logoText); ObjectSetInteger(0, "ScriptLogo", OBJPROP_COLOR, clrYellow); ObjectSetInteger(0, "ScriptLogo", OBJPROP_FONTSIZE, 14); ObjectSetInteger(0, "ScriptLogo", OBJPROP_CORNER, CORNER_RIGHT_UPPER); ObjectSetInteger(0, "ScriptLogo", OBJPROP_XDISTANCE, 80); ObjectSetInteger(0, "ScriptLogo", OBJPROP_YDISTANCE, 10); } ChartRedraw(); } //+------------------------------------------------------------------+
成果
在结果探讨之前,我们先来了解如何创建和编译该脚本。打开MetaEditor,选择“新建”,然后选择“脚本”。为脚本输入一个名称,并开始编写代码。编译脚本。如果出现错误,请修正错误,直至编译成功。编译完成后,在图表上测试您的脚本。由于它不是智能交易系统(EA),您可以运行在模拟账户或真实账户的实时图表上,而不会影响你的账户余额。
在本节中,我提供了几张图表以帮助理解。我将逐步引导您解读每张图表。第一张图表展示了在澳元兑美元(AUD/USD)货币对上的测试结果。在该测试中,我启用了DrawLargeQuarters功能,并显示了上冲和下探区域,同时将DrawSmallQuarters设置为false。
//---- Input parameters ------------------------------------------------- input double MajorStep = 0.1000; // Difference between major whole numbers. input bool DrawLargeQuarters = true; // Draw intermediate large quarter lines. input bool DrawSmallQuarters = false; // Draw small quarter lines. input bool DrawOvershootAreas = true; // Mark overshoot/undershoot areas for large quarter lines.
让我们来回顾下图2。该图展示了我添加脚本后所记录的结果。我们可以看到价格是如何与四分位线以及它们的上冲和下探区域相互作用的。

图例2. 澳元兑美元四分位线
以下是同一货币对的截图。我在图表上高亮了四分位线的影响。结果显而易见:市场在我们的较大四分位线水平处找到了支撑和阻力。我将上冲线和较小四分位线选项设置为false,以便更清晰地观察这些较大四分位线的作用。
//---- Input parameters ------------------------------------------------- input double MajorStep = 0.1000; // Difference between major whole numbers. input bool DrawLargeQuarters = true; // Draw intermediate large quarter lines. input bool DrawSmallQuarters = false; // Draw small quarter lines. input bool DrawOvershootAreas = false; // Mark overshoot/undershoot areas for large quarter lines.
参见下图3

图例3. 较大四分位
我已经进一步放大了图表,以便您能清晰看到价格与较大四位线的交互情况,包括价格下探和上冲的情形。

图例4. 上冲和下探
最后,让我们来看看该脚本在欧元兑美元货币对上的表现。每个外汇交易者都在寻找的关键价位,通过四分位线水平都能清晰地识别出来。

图例5. 欧元兑美元四分位
请参考书籍:《四分位理论 - 伊利安·约托夫》(The_Quarters_Theory_-_Ilian_Yotov)
结论
我相信大家都能看到这个脚本的影响力。其能够绘制四分位线,并进行会耗费大量时间的手动计算。值得注意的是,四分位线可作为支撑位和反转位。较大四分位线,即主要的低位和高位水平,起着重要的阻力位和支撑位作用,而较小四分位线则作为次要价位水平。这种初步方法为自动化分析奠定了坚实的基础。随着我们深入探究这一理论,我们期待开发出更多的工具。如果您有任何建议或意见,请不吝分享。
| 日期 | 工具名 | 描述 | 版本 | 更新 | 备注 |
|---|---|---|---|---|---|
| 01/10/24 | 图表展示器 | 以重影效果覆盖前一日价格走势的脚本 | 1.0 | 初始版本 | 工具1 |
| 18/11/24 | 分析评论 | 以表格形式提供前一日的信息,并预测市场的未来方向 | 1.0 | 初始版本 | 工具2 |
| 27/11/24 | 分析大师 | 每两小时定期更新市场指标 | 1.01 | 第二个版本 | 工具3 |
| 02/12/24 | 分析预测 | 集成Telegram通知功能,每两小时定时更新市场指标 | 1.1 | 第三个版本 | 工具4 |
| 09/12/24 | 波动率导航仪 | 该EA通过布林带、RSI和ATR三大指标综合分析市场状况 | 1.0 | 初始版本 | 工具5 |
| 19/12/24 | 均值回归信号收割器 | 运用均值回归策略分析市场并提供交易信号 | 1.0 | 初始版本 | 工具6 |
| 9/01/25 | 信号脉冲 | 多时间框架分析器 | 1.0 | 初始版本 | 工具7 |
| 17/01/25 | 指标看板 | 带分析按钮的控制面板 | 1.0 | 初始版本 | 工具8 |
| 21/01/25 | 外部数据流 | 通过外部库进行分析 | 1.0 | 初始版本 | 工具9 |
| 27/01/25 | VWAP | 成交量加权平均价 | 1.3 | 初始版本 | 工具10 |
| 02/02/25 | Heikin Ashi | 平滑趋势和反转信号识别 | 1.0 | 初始版本 | 工具11 |
| 04/02/25 | FibVWAP | 通过python分析生成信号 | 1.0 | 初始版本 | 工具12 |
| 14/02/25 | RSI背离 | 价格走势与RSI背离 | 1.0 | 初始版本 | 工具13 |
| 17/02/25 | 抛物线止损与反转指标 (PSAR) | 自动化PSAR策略 | 1.0 | 初始版本 | 工具14 |
| 20/02/25 | 四分位绘制脚本 | 在图表上绘制四分位水平 | 1.0 | 初始版本 | 工具15 |
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/17250
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
MQL5自动化交易策略(第九部分):构建亚洲盘突破策略的智能交易系统(EA)
使用MQL5经济日历进行交易(第六部分):利用新闻事件分析和倒计时器实现交易入场自动化
市场模拟(第一部分):跨期订单(一)