MT5指标编译通过 · EX5 14KB 自动发布 3 0

智能订单块自动识别指标

John·4 小时前发布

自动识别看涨看跌订单块画矩形,价格回踩弹窗提醒

智能订单块自动识别指标

MT5 真机运行截图 · 服务器把编译好的 EX5 挂到黄金 H1 图表上截的,你装上去看到的就是这个样子

OrderBlock_Indicator.mq5274 行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#property copyright "XAUOF 指标工坊"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0

// ==================== 输入参数 ====================
input int    InpLookback       = 300;             // 回溯K线数:扫描最近多少根K线寻找订单块,推荐 200-500
input int    InpMaxBlocks      = 5;               // 最大显示数量:图上最多同时保留几个订单块,推荐 3-10
input color  InpBullColor      = clrDodgerBlue;   // 看涨订单块颜色:推荐 DodgerBlue 或 LimeGreen
input color  InpBearColor      = clrCrimson;      // 看跌订单块颜色:推荐 Crimson 或 OrangeRed
input int    InpRectAlpha      = 40;              // 矩形透明度:0完全透明~255完全不透明,推荐 30-60
input bool   InpEnableAlert    = true;            // 是否开启弹窗提醒:价格回到订单块区域时弹窗
input int    InpAlertCooldown  = 10;              // 提醒冷却时间(分钟):同一订单块多久内不重复弹窗,推荐 5-15

// ==================== 全局变量 ====================
struct OrderBlock
{
   string   name;          // 图表对象名称
   bool     isBullish;     // true=看涨, false=看跌
   double   topPrice;      // 区域上沿价格
   double   bottomPrice;   // 区域下沿价格
   datetime startTime;     // 订单块起始时间
   bool     alerted;       // 本轮是否已提醒过
};

OrderBlock g_blocks[];     // 存储当前所有订单块的数组
string     g_prefix = "OB_XAUOF_"; // 对象名称前缀,防止与其他指标冲突

//+------------------------------------------------------------------+
//| 初始化函数                                                        |
//+------------------------------------------------------------------+
int OnInit()
{
   // 清除可能残留的旧对象
   ObjectsDeleteAll(0, g_prefix);
   ArrayFree(g_blocks);
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 反初始化函数:卸载指标时清理图表上的矩形                           |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   ObjectsDeleteAll(0, g_prefix);
}

//+------------------------------------------------------------------+
//| 主计算函数(MQL5 指标必须实现)                                    |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   if(rates_total < 5) return 0;

   // 只在每根新K线开盘时重新扫描一次,避免逐笔跳动导致频繁重绘和卡顿
   static datetime s_lastBarTime = 0;
   if(time[rates_total - 1] == s_lastBarTime)
   {
      // 非新K线时,仅检查价格是否进入已有订单块以触发提醒
      CheckAlerts(close[rates_total - 1], time[rates_total - 1]);
      return rates_total;
   }
   s_lastBarTime = time[rates_total - 1];

   // 第一步:删除旧的订单块对象和数组
   ObjectsDeleteAll(0, g_prefix);
   ArrayFree(g_blocks);

   // 第二步:扫描并识别新的订单块
   ScanOrderBlocks(rates_total, time, open, high, low, close);

   // 第三步:将识别到的订单块画到图表上
   DrawOrderBlocks();

   // 第四步:检查当前价格是否在某个订单块内,触发提醒
   CheckAlerts(close[rates_total - 1], time[rates_total - 1]);

   return rates_total;
}

//+------------------------------------------------------------------+
//| 核心逻辑:扫描历史K线,寻找看涨和看跌订单块                        |
//+------------------------------------------------------------------+
void ScanOrderBlocks(int rates_total,
                     const datetime &time[],
                     const double &open[],
                     const double &high[],
                     const double &low[],
                     const double &close[])
{
   // 确定扫描起点,防止数组越界
   int startIdx = rates_total - InpLookback;
   if(startIdx < 2) startIdx = 2;
   
   // 终点留一根K线余量,因为需要看后面的K线是否突破了它
   int endIdx = rates_total - 2;

   for(int i = startIdx; i <= endIdx; i++)
   {
      // 限制最大数量,达到上限就不再找了
      if(ArraySize(g_blocks) >= InpMaxBlocks) break;

      // --------------------------------------------------
      // 1. 寻找看涨订单块 (Bullish Order Block)
      // 条件:当前K线是阴线(收盘<开盘),且后面某根K线的收盘价突破了这根阴线的最高价
      // --------------------------------------------------
      if(close[i] < open[i]) 
      {
         bool broken = false;
         // 向后最多找 50 根 K 线看有没有突破
         int searchLimit = i + 50;
         if(searchLimit > rates_total - 1) searchLimit = rates_total - 1;
         
         for(int j = i + 1; j <= searchLimit; j++)
         {
            if(close[j] > high[i]) // 阳线实体突破阴线最高点,确认订单块有效
            {
               broken = true;
               break;
            }
         }
         
         if(broken)
         {
            AddBlock(true, high[i], low[i], time[i]);
         }
      }

      // --------------------------------------------------
      // 2. 寻找看跌订单块 (Bearish Order Block)
      // 条件:当前K线是阳线(收盘>开盘),且后面某根K线的收盘价跌破了这根阳线的最低价
      // --------------------------------------------------
      if(close[i] > open[i])
      {
         bool broken = false;
         int searchLimit = i + 50;
         if(searchLimit > rates_total - 1) searchLimit = rates_total - 1;
         
         for(int j = i + 1; j <= searchLimit; j++)
         {
            if(close[j] < low[i]) // 阴线实体跌破阳线最低点,确认订单块有效
            {
               broken = true;
               break;
            }
         }
         
         if(broken)
         {
            AddBlock(false, high[i], low[i], time[i]);
         }
      }
   }
}

//+------------------------------------------------------------------+
//| 辅助函数:将一个识别出的订单块加入数组(带去重判断)                 |
//+------------------------------------------------------------------+
void AddBlock(bool isBullish, double top, double bottom, datetime tStart)
{
   // 防止除数为0及无效价格
   if(top <= 0 || bottom <= 0 || top < bottom) return;

   // 简单去重:如果价格区间和时间与已有的高度重合,就不重复添加
   for(int k = 0; k < ArraySize(g_blocks); k++)
   {
      if(MathAbs(g_blocks[k].topPrice - top) < 10 * _Point && 
         g_blocks[k].startTime == tStart)
      {
         return; 
      }
   }

   int size = ArraySize(g_blocks);
   ArrayResize(g_blocks, size + 1);
   
   g_blocks[size].isBullish    = isBullish;
   g_blocks[size].topPrice     = top;
   g_blocks[size].bottomPrice  = bottom;
   g_blocks[size].startTime    = tStart;
   g_blocks[size].alerted      = false;
   g_blocks[size].name         = g_prefix + IntegerToString(tStart) + "_" + IntegerToString(size);
}

//+------------------------------------------------------------------+
//| 绘图函数:把数组里的订单块画成半透明矩形                            |
//+------------------------------------------------------------------+
void DrawOrderBlocks()
{
   for(int i = 0; i < ArraySize(g_blocks); i++)
   {
      string name   = g_blocks[i].name;
      color  rColor = g_blocks[i].isBullish ? InpBullColor : InpBearColor;
      
      // 矩形起点为订单块形成的K线时间,终点延伸到图表最右侧
      datetime t1 = g_blocks[i].startTime;
      datetime t2 = TimeCurrent() + PeriodSeconds() * 20; 

      // 创建矩形对象
      ObjectCreate(0, name, OBJ_RECTANGLE, 0, t1, g_blocks[i].topPrice, t2, g_blocks[i].bottomPrice);
      
      // 设置边框颜色和填充颜色一致
      ObjectSetInteger(0, name, OBJPROP_COLOR, rColor);
      ObjectSetInteger(0, name, OBJPROP_FILL, true);           // 开启填充
      ObjectSetInteger(0, name, OBJPROP_BACK, true);           // 放在K线背景层,不遮挡K线
      
      // 设置透明度 (0-255)
      int alpha = InpRectAlpha;
      if(alpha < 0) alpha = 0;
      if(alpha > 255) alpha = 255;
      ObjectSetInteger(0, name, OBJPROP_BGCOLOR, ColorToARGB(rColor, alpha));
      
      // 边框设为虚线更美观
      ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DASH);
      ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
      
      // 设置鼠标悬停时的提示文字
      string tip = (g_blocks[i].isBullish ? "【看涨订单块】" : "【看跌订单块】") + 
                   "\n上沿: " + DoubleToString(g_blocks[i].topPrice, _Digits) +
                   "\n下沿: " + DoubleToString(g_blocks[i].bottomPrice, _Digits);
      ObjectSetString(0, name, OBJPROP_TOOLTIP, tip);
   }
}

//+------------------------------------------------------------------+
//| 提醒函数:判断当前价格是否进入了某个订单块区域                      |
//+------------------------------------------------------------------+
void CheckAlerts(double currentPrice, datetime currentTime)
{
   if(!InpEnableAlert) return;

   for(int i = 0; i < ArraySize(g_blocks); i++)
   {
      double top = g_blocks[i].topPrice;
      double bot = g_blocks[i].bottomPrice;

      // 判断当前价格是否在订单块的上下沿之间
      if(currentPrice >= bot && currentPrice <= top)
      {
         if(!g_blocks[i].alerted)
         {
            string typeStr = g_blocks[i].isBullish ? "看涨(做多)" : "看跌(做空)";
            string msg = StringFormat("XAUOF订单块提醒: %s 价格已进入 %s 订单块区域! [%.2f - %.2f]", 
                                      _Symbol, typeStr, bot, top);
            
            Alert(msg);        // 弹窗提醒
            PlaySound("alert.wav"); // 播放声音
            
            g_blocks[i].alerted = true; // 标记为已提醒,防止疯狂弹窗
         }
      }
      else
      {
         // 价格离开订单块区域后,重置提醒状态,下次再进来还能提醒
         if(g_blocks[i].alerted)
         {
            // 可选:加入冷却时间判断,这里简化处理,离开即重置
            g_blocks[i].alerted = false;
         }
      }
   }
}
//+------------------------------------------------------------------+
MT5 运行截图 · 完整视图带价格轴和时间轴的整张图表(约 150 根 H1 K 线),上面的封面是它最近 80 根 K 线的放大视图
智能订单块自动识别指标 在 MT5 上的真实截图

作品说明

思路说明: 本指标基于 SMC(聪明钱概念)识别订单块。看涨 OB:下跌趋势中,最后一根阴线被后续阳线实体突破后,该阴线的最高/最低价构成支撑区;看跌 OB 反之。代码通过遍历 K 线寻找结构突破,用 OBJ_RECTANGLE 画半透明矩形,价格回踩时弹窗提醒。

使用说明

  1. 安装方法:
  • 打开 MetaTrader 5,点击菜单栏「文件」->「打开数据文件夹」。
  • 进入 MQL5\Indicators\ 目录,将上述代码保存为 OrderBlock_Indicator.mq5。
  • 回到 MT5,在「导航器」面板右键点击「指标」选择「刷新」,然后将其拖拽到图表上即可。
  1. 参数调节建议:
  • 回溯K线数 (`InpLookback`):决定指标往前看多远去寻找订单块。短线交易(如 M5/M15)建议设 100-200;长线(H4/D1)建议设 300-500。数值越大计算越慢。
  • 最大显示数量 (`InpMaxBlocks`):控制图上最多画几个矩形。建议保持 3-8 个,太多会导致图表杂乱失去参考价值。
  • 矩形透明度 (`InpRectAlpha`):范围 0~255。推荐设为 30-60,既能看清区域又不会完全遮挡背后的 K 线走势。
  • 提醒冷却:当价格进入矩形区域时会弹窗一次,价格离开该区域后重置。这避免了价格在区域内波动时连续疯狂弹窗。
  1. 信号怎么看:
  • 蓝色矩形(看涨订单块):代表机构曾在此处吸筹。当价格回调跌入该蓝色区域时,是潜在的做多机会,可结合 K 线反转形态(如锤子线、吞没)入场。
  • 红色矩形(看跌订单块):代表机构曾在此处派发。当价格反弹涨入该红色区域时,是潜在的做空机会。
  • 弹窗提醒:当实时价格触及这些关键区域时,MT5 会自动弹出警告窗口并发出提示音,防止你盯盘遗漏。
  1. 注意事项:
  • 订单块属于 SMC(聪明钱)体系中的左侧参考区域,不能无脑挂单。价格回到订单块后,务必切到小级别(如 M1/M5)观察是否有结构破坏(CHoCH)或动能衰竭再进场。
  • 如果订单块被大实体 K 线直接贯穿且没有停顿,说明该订单块已失效(被流动性猎取),指标会在下一次新 K 线刷新时自动将其剔除。
  • 本指标仅在图表上绘制矩形对象,不会自动执行任何买卖下单操作。

AI 解读根据源码逐行分析写成,供参考,以实际运行为准

这是什么

这是一个运行在 MetaTrader 5 上的图表指标,基于 SMC(聪明钱概念)自动寻找看涨和看跌订单块。它会在图表上画出半透明矩形标出这些关键区域,当实时价格回到矩形范围内时,会自动弹窗并发出声音提醒。解决的是手动找订单块费时费力、容易盯盘遗漏的问题。

逻辑原理

指标不画线,只画矩形对象。计算逻辑分四步:

  1. 每根新 K 线开盘时,往回扫描指定数量的历史 K 线。
  2. 找看涨订单块:如果某根 K 线是阴线(收盘价小于开盘价),且往后最多 50 根 K 线内有一根的收盘价突破了这根阴线的最高价,就把这根阴线的最高价和最低价记为一个看涨订单块。
  3. 找看跌订单块:反过来,阳线被后续 K 线收盘价跌破最低价,就记为看跌订单块。
  4. 用 OBJ_RECTANGLE 把找到的区域画成虚线边框的半透明矩形,起点是订单块形成的时间,终点延伸到图表右侧。同时检查当前价格是否在某个矩形内,如果在且没提醒过,就弹窗并播放 alert.wav;价格离开后重置状态,下次再进还能提醒。

参数说明

  • InpLookback(300):往前扫描多少根 K 线寻找订单块。数值越大找得越远,但计算量增加。短线可改小,长线可改大。
  • InpMaxBlocks(5):图表上最多同时保留几个订单块矩形。达到上限就不再找新的了。
  • InpBullColor(clrDodgerBlue):看涨订单块的矩形颜色。
  • InpBearColor(clrCrimson):看跌订单块的矩形颜色。
  • InpRectAlpha(40):矩形填充透明度,范围 0 到 255。0 是完全透明,255 是不透明。
  • InpEnableAlert(true):是否开启价格进入订单块时的弹窗提醒。
  • InpAlertCooldown(10):代码中声明了此参数作为冷却时间参考,但实际提醒重置逻辑是价格离开矩形区域即重置。

怎么用

打开 MT5,点击「文件」->「打开数据文件夹」,进入 MQL5\Indicators 目录,将源码保存为 .mq5 文件。回到 MT5 导航器面板右键刷新指标列表,把它拖到你想看的图表上即可。图上会出现蓝色或红色的半透明虚线矩形。鼠标悬停在矩形上能看到提示文字,显示这是看涨还是看跌以及上下沿价格。当价格走进矩形时,MT5 会弹出警告窗口并响铃。

适用场景

适合习惯用 SMC 体系交易的人,用来快速定位潜在的供需区。品种和周期代码里没有限制,外汇、黄金、指数都能挂。因为每次新 K 线都会重新扫描,短周期(如 M5、M15)配合较小的 InpLookback 值反应较快;长周期(H4、D1)可以把回溯数调大。不适合指望它直接给出买卖点的人,它只画区域,不判断进出场。

风险提示

第一,新 K 线出现时会删除旧矩形重新扫描,所以订单块的位置可能会变,这不是传统意义上的重绘,而是动态更新。第二,突破判定只看收盘价,盘中插针穿过不算,可能漏掉一些极端行情的订单块。第三,向后搜索突破最多只看 50 根 K 线,超过 50 根才突破的结构不会被识别。第四,提醒重置条件是价格离开矩形,如果价格在矩形边缘反复横跳,可能会频繁弹窗。第五,订单块只是参考区域,不能无脑挂单,需结合小级别走势自行判断。

常见问题

这个指标会重绘吗?
每根新K线开盘时会清除旧矩形重新扫描,订单块位置可能随新结构变化而更新,属于动态刷新而非恶意重绘。
可以用在XAUUSD以外的品种吗?
代码里没有品种限制,外汇、指数、加密货币等MT5支持的品种都可以挂上去测试。
MT4能用吗?
这是MQL5代码,只能在MetaTrader 5上使用,不能直接用于MT4。
参数默认值适合什么周期?
InpLookback默认300,适合H1或H4级别。如果是M5或M15短线,建议改小到100至200,避免计算过多无用历史。
弹窗太频繁怎么办?
代码里的重置逻辑是价格离开矩形区域就重置。如果嫌频繁,可以关掉InpEnableAlert,或者调小InpRectAlpha让视觉干扰少一点,自己盯盘。

Smart Order Block Auto Detection Indicator for MT5

This MT5 indicator automatically identifies bullish and bearish order blocks based on SMC concepts. It draws semi-transparent rectangles on the chart and triggers popup alerts when price returns to these zones.

Source code is shown above. Compiled EX5 files are available to VIP members.

评论

后可以留言,比如反馈用着怎么样、想加什么功能。

还没有人评论,来抢个沙发。