MT5指标编译通过 · EX5 12KB 自动发布 10 1

供需区价格行为指标

lu·2 小时前发布

自动识别供应区和需求区,在价格触及关键位置时给出买卖箭头信号

供需区价格行为指标

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

SupplyDemandZones.mq5252 行
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
#property copyright   "XAUOF指标工坊"
#property version     "1.0"
#property strict
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4

// 供应区线(粉红色)
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDeepPink
#property indicator_width1  2
#property indicator_label1  "供应区"

// 需求区线(青绿色)
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrMediumTurquoise
#property indicator_width2  2
#property indicator_label2  "需求区"

// 卖出信号箭头(黄色向下)
#property indicator_type3   DRAW_ARROW
#property indicator_color3  clrGold
#property indicator_width3  2
#property indicator_label3  "卖出信号"

// 买入信号箭头(青绿向上)
#property indicator_type4   DRAW_ARROW
#property indicator_color4  clrMediumTurquoise
#property indicator_width4  2
#property indicator_label4  "买入信号"

//--- 输入参数
input int    SwingPeriod    = 5;      // 识别周期:判断局部高低点需要左右各N根K线,推荐5-10
input int    ZoneValidBars  = 50;     // 区域有效期:供需区在图上保持的K线数量,推荐30-100
input int    ZoneWidthPips  = 20;     // 区域宽度:允许的价格偏差(点数),推荐10-30
input int    ArrowGap       = 50;     // 箭头间距:箭头距离K线高低点的点数,推荐30-100

//--- 指标缓冲区
double SupplyBuffer[];      // 供应区(阻力位)
double DemandBuffer[];      // 需求区(支撑位)
double SellArrow[];         // 卖出箭头
double BuyArrow[];          // 买入箭头

//--- 全局变量,记录上一次标记的区域位置和时间
struct ZoneInfo {
   double price;            // 区域价格
   int    startBar;         // 开始K线索引
};

ZoneInfo lastSupplyZones[100];   // 最近的供应区
ZoneInfo lastDemandZones[100];   // 最近的需求区
int supplyCount = 0;
int demandCount = 0;

//+------------------------------------------------------------------+
//| 初始化函数                                                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // 绑定缓冲区
   SetIndexBuffer(0, SupplyBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, DemandBuffer, INDICATOR_DATA);
   SetIndexBuffer(2, SellArrow, INDICATOR_DATA);
   SetIndexBuffer(3, BuyArrow, INDICATOR_DATA);
   
   // 设置箭头样式
   PlotIndexSetInteger(2, PLOT_ARROW, 233);  // 向下箭头
   PlotIndexSetInteger(3, PLOT_ARROW, 234);  // 向上箭头
   
   // 设置空值
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   
   // 设置指标名称
   IndicatorSetString(INDICATOR_SHORTNAME, "供需区指标");
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 计算函数                                                           |
//+------------------------------------------------------------------+
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 < SwingPeriod * 2 + 1)
      return 0;
   
   // 确定计算起点
   int start = (prev_calculated > SwingPeriod) ? prev_calculated - 1 : SwingPeriod;
   
   // 首次运行,初始化所有缓冲区
   if(prev_calculated == 0)
   {
      ArrayInitialize(SupplyBuffer, EMPTY_VALUE);
      ArrayInitialize(DemandBuffer, EMPTY_VALUE);
      ArrayInitialize(SellArrow, EMPTY_VALUE);
      ArrayInitialize(BuyArrow, EMPTY_VALUE);
      supplyCount = 0;
      demandCount = 0;
   }
   
   // 主循环:从start开始逐根K线计算
   for(int i = start; i < rates_total && !IsStopped(); i++)
   {
      // 初始化当前K线的缓冲区
      SupplyBuffer[i] = EMPTY_VALUE;
      DemandBuffer[i] = EMPTY_VALUE;
      SellArrow[i] = EMPTY_VALUE;
      BuyArrow[i] = EMPTY_VALUE;
      
      // 边界检查:确保可以访问前后SwingPeriod根K线
      if(i < SwingPeriod || i >= rates_total - 1)
         continue;
      
      // 1. 识别局部高点(Swing High):当前K线的最高价比前后SwingPeriod根都高
      bool isSwingHigh = true;
      for(int j = 1; j <= SwingPeriod; j++)
      {
         if(i - j < 0 || i + j >= rates_total)
         {
            isSwingHigh = false;
            break;
         }
         if(high[i] <= high[i - j] || high[i] <= high[i + j])
         {
            isSwingHigh = false;
            break;
         }
      }
      
      // 如果是局部高点,记录供应区
      if(isSwingHigh)
      {
         double supplyPrice = high[i];
         
         // 在该价格附近画供应区线(持续ZoneValidBars根K线)
         int endBar = MathMin(i + ZoneValidBars, rates_total - 1);
         for(int k = i; k < endBar; k++)
         {
            SupplyBuffer[k] = supplyPrice;
         }
         
         // 记录到供应区数组(用于后续信号判断)
         if(supplyCount < 100)
         {
            lastSupplyZones[supplyCount].price = supplyPrice;
            lastSupplyZones[supplyCount].startBar = i;
            supplyCount++;
         }
      }
      
      // 2. 识别局部低点(Swing Low):当前K线的最低价比前后SwingPeriod根都低
      bool isSwingLow = true;
      for(int j = 1; j <= SwingPeriod; j++)
      {
         if(i - j < 0 || i + j >= rates_total)
         {
            isSwingLow = false;
            break;
         }
         if(low[i] >= low[i - j] || low[i] >= low[i + j])
         {
            isSwingLow = false;
            break;
         }
      }
      
      // 如果是局部低点,记录需求区
      if(isSwingLow)
      {
         double demandPrice = low[i];
         
         // 在该价格附近画需求区线(持续ZoneValidBars根K线)
         int endBar = MathMin(i + ZoneValidBars, rates_total - 1);
         for(int k = i; k < endBar; k++)
         {
            DemandBuffer[k] = demandPrice;
         }
         
         // 记录到需求区数组
         if(demandCount < 100)
         {
            lastDemandZones[demandCount].price = demandPrice;
            lastDemandZones[demandCount].startBar = i;
            demandCount++;
         }
      }
      
      // 3. 判断是否产生交易信号
      // 卖出信号:价格触及供应区后向下反转
      for(int s = 0; s < supplyCount; s++)
      {
         double zonePrice = lastSupplyZones[s].price;
         int zoneStart = lastSupplyZones[s].startBar;
         
         // 只检查有效期内的区域
         if(i > zoneStart && i <= zoneStart + ZoneValidBars)
         {
            double zonePips = ZoneWidthPips * _Point;
            
            // 当前K线触及供应区(最高价接近或超过区域价格)
            if(high[i] >= zonePrice - zonePips && high[i] <= zonePrice + zonePips)
            {
               // 并且收盘价回落(表示反转)
               if(i >= 1 && close[i] < close[i - 1] && close[i] < open[i])
               {
                  SellArrow[i] = high[i] + ArrowGap * _Point;
                  break;  // 只画一个箭头
               }
            }
         }
      }
      
      // 买入信号:价格触及需求区后向上反转
      for(int d = 0; d < demandCount; d++)
      {
         double zonePrice = lastDemandZones[d].price;
         int zoneStart = lastDemandZones[d].startBar;
         
         // 只检查有效期内的区域
         if(i > zoneStart && i <= zoneStart + ZoneValidBars)
         {
            double zonePips = ZoneWidthPips * _Point;
            
            // 当前K线触及需求区(最低价接近或低于区域价格)
            if(low[i] <= zonePrice + zonePips && low[i] >= zonePrice - zonePips)
            {
               // 并且收盘价反弹(表示反转)
               if(i >= 1 && close[i] > close[i - 1] && close[i] > open[i])
               {
                  BuyArrow[i] = low[i] - ArrowGap * _Point;
                  break;  // 只画一个箭头
               }
            }
         }
      }
   }
   
   return rates_total;
}
MT5 运行截图 · 完整视图带价格轴和时间轴的整张图表(约 150 根 H1 K 线),上面的封面是它最近 80 根 K 线的放大视图
供需区价格行为指标 在 MT5 上的真实截图

作品说明

我从图上识别到以下元素:

  1. 价格区域标记:粉红色水平带(供应区/阻力位)、青绿色水平带(需求区/支撑位)
  2. 交易信号:黄色向下箭头(卖出信号)、青绿色向上箭头(买入信号)
  3. 底部副图:成交量柱状图(青色/品红相间)

这是一套供需区交易系统,自动标记关键价格区域并在价格回踩时给出信号。我将复刻主图的核心逻辑:识别swing高低点,画出供需区,产生交易箭头。

使用说明

安装步骤:

  1. 将代码保存为 SupplyDemandZones.mq5,放入 MT5 的 MQL5/Indicators 目录
  2. 在 MetaEditor 中编译(F7键)
  3. 在 MT5 图表上,插入 → 指标 → 自定义 → SupplyDemandZones

参数调整:

  • 识别周期(SwingPeriod):5-10,越大识别的区域越少但越可靠,黄金推荐7
  • 区域有效期(ZoneValidBars):30-100,控制水平线在图上保持多久,推荐50
  • 区域宽度(ZoneWidthPips):10-30点,允许价格偏差范围,推荐20
  • 箭头间距(ArrowGap):30-100点,箭头距K线的距离,推荐50

信号解读:

  • 粉红色线:供应区(阻力位),价格回踩该区域容易遇阻下跌
  • 青绿色线:需求区(支撑位),价格回踩该区域容易获得支撑上涨
  • 黄色向下箭头:卖出信号,价格触及供应区并出现看跌K线
  • 青绿向上箭头:买入信号,价格触及需求区并出现看涨K线

注意事项:

  • 箭头信号是辅助参考,建议结合趋势、成交量等确认
  • 区域被价格强势突破后会失效,注意止损设置
  • 适合波动较大的品种(黄金、原油),小周期效果更明显
  • 首次加载会计算历史所有K线,可能需要几秒钟

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

这是什么

这是一个基于价格行为的 MT5 供需区指标,通过识别图表上的局部高点(Swing High)和低点(Swing Low)自动画出供应区(阻力位)和需求区(支撑位),并在价格回踩这些关键区域时生成箭头信号。粉红色线标记卖压可能出现的供应区,青绿色线标记买盘可能进场的需求区,黄色向下箭头提示潜在做空机会,青绿向上箭头提示潜在做多机会。

逻辑原理

指标的核心是识别 Swing 结构:当某根 K 线的最高价比前后各 SwingPeriod 根 K 线都高时,这根 K 线被标记为局部高点,它的最高价所在位置就是供应区;反之,当某根 K 线的最低价比前后各 SwingPeriod 根都低时,这根 K 线是局部低点,它的最低价位置就是需求区。

识别出区域后,指标会在图上画出水平线,持续显示 ZoneValidBars 根 K 线。当价格重新回到某个供应区附近(允许 ZoneWidthPips 点的偏差范围)且当前 K 线收盘价低于前一根收盘价、并且是阴线(收盘 < 开盘)时,触发卖出箭头;当价格回到需求区附近且当前 K 线收盘价高于前一根、并且是阳线(收盘 > 开盘)时,触发买入箭头。

这套逻辑不预测未来,只在价格真正触及区域并出现反转 K 线形态时才给信号,属于确认型而非预测型指标。

参数说明

  • SwingPeriod(默认 5):识别周期,决定判断局部高低点需要左右各多少根 K 线对比。值越大,识别出的区域越少但越可靠,适合大周期;值越小,区域越密集但噪音也多。黄金 H1 推荐 5-7,H4 推荐 7-10。
  • ZoneValidBars(默认 50):区域有效期,控制每条供需区线在图上保持多少根 K 线。设为 50 意味着区域会显示 50 根 K 线后自动消失。如果你希望历史区域保留更久,可以调大到 100;如果只关注最新的几个区域,可以调小到 30。
  • ZoneWidthPips(默认 20):区域宽度容差,允许价格在目标价位上下多少点范围内也算触及区域。黄金波动大,20 点(0.2 美元)比较合理;欧美这种波动小的可以降到 10 点。
  • ArrowGap(默认 50):箭头距离 K 线高低点的间距(点数),纯粹为了显示美观,不影响逻辑。如果图表缩放后箭头挡住 K 线,可以调大这个值。

怎么用

将代码保存为 SupplyDemandZones.mq5,放到 MT5 数据文件夹的 MQL5/Indicators 目录(文件 → 打开数据文件夹),在 MetaEditor 中打开并编译(F7)。回到 MT5 图表,插入 → 指标 → 自定义 → SupplyDemandZones,参数按上面说明调整。

指标挂在主图上,粉红线和青绿线会自动标记在价格附近,箭头出现在 K 线上方或下方。看到箭头时不要立即入场,先确认:当前趋势方向是否支持(做多看日线是否上升趋势,做空反之)、该区域之前是否被测试过多次(测试次数越多,下次突破概率越大)、成交量是否配合(回踩放量更可靠)。

建议配合均线或 MACD 过滤信号,只做顺势方向的箭头。止损放在区域另一侧外 20-30 点,止盈看下一个反向区域或 1:2 风报比。

适用场景

这套逻辑适合有明显波段结构、来回震荡的市场,比如黄金(XAUUSD)、原油(USOIL)、英镑系货币对。小周期(M15-H1)用来抓日内回调,大周期(H4-D1)用来抓波段拐点。

不适合单边趋势行情:牛市中供应区会被连续突破,指标会频繁给卖出信号但全部失败;同理熊市中需求区失效率高。也不适合波动极小的品种(比如 USDCNY)或者夜盘流动性差的时段,因为 Swing 结构不明显,识别出的区域质量低。

最佳用法是在区间震荡或趋势中的回调阶段,等价格回到关键位置再进场,而不是追涨杀跌。

风险提示

信号滞后:箭头只在当前 K 线收盘确认反转形态后才出现,如果你在 M5 图上看到箭头,那根 K 线可能已经走完,价格已经离开最佳入场点。可以把箭头当提示,然后去更小周期找精确入场位。

假突破:价格触及区域、给出箭头后,完全可能继续突破区域而不是反转。代码里只检查了一根 K 线的收盘形态,没有确认后续走势,所以止损必须严格设置。

区域重叠:代码允许同时存在最多 100 个供应区和 100 个需求区,当市场长时间横盘时,图上会画出很多条线,视觉混乱。这时可以减小 ZoneValidBars 或手动删除过时的区域。

参数敏感:SwingPeriod 从 5 改到 10,识别出的区域数量和位置会完全不同。建议在历史行情上回测不同参数组合,找到适合你交易品种和周期的设置,不要用默认值直接实盘。

不会重绘:代码在 K 线走完后才计算,历史上的箭头位置是固定的,这点比较诚实。但也意味着你看到箭头时机会可能已经过去,需要自己判断是否还能追。

常见问题

这个指标会重绘吗?
不会。代码在每根 K 线收盘后计算,历史上画出的箭头和区域位置不会改变。但箭头出现时那根 K 线已经走完,所以看到信号时需要判断是否还有入场价值。
可以用在 XAUUSD 以外的品种吗?
可以。代码没有限制品种,理论上任何有波段结构的品种都能用,比如原油、英镑、比特币。但需要根据品种波动特点调整 ZoneWidthPips 参数,波动大的调大,波动小的调小。
MT4 能用吗?
不能直接用。这是 MQL5 代码,MT4 使用 MQL4 语言,两者语法和函数不兼容。如果需要 MT4 版本,需要重写代码逻辑。
参数默认值适合什么周期?
默认参数(SwingPeriod=5, ZoneValidBars=50)适合 H1 到 H4 周期。M15 以下建议把 SwingPeriod 降到 3-4,D1 以上建议提高到 7-10,否则识别出的区域要么太密集要么太稀疏。
箭头出现后应该立即入场吗?
不建议。箭头只是提示价格触及了关键区域并出现反转 K 线,但不保证反转会持续。最好配合趋势方向、成交量、前期测试次数等因素综合判断,并严格设置止损。

Supply and Demand Zone Indicator for MT5

Automatically identifies supply and demand zones based on swing highs and lows, generates buy/sell arrow signals when price revisits key levels. Includes 4 adjustable parameters for sensitivity control.

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

评论

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

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