供需区价格行为指标
自动识别供应区和需求区,在价格触及关键位置时给出买卖箭头信号
MT5 真机运行截图 · 服务器把编译好的 EX5 挂到黄金 H1 图表上截的,你装上去看到的就是这个样子
#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;
}作品说明
我从图上识别到以下元素:
- 价格区域标记:粉红色水平带(供应区/阻力位)、青绿色水平带(需求区/支撑位)
- 交易信号:黄色向下箭头(卖出信号)、青绿色向上箭头(买入信号)
- 底部副图:成交量柱状图(青色/品红相间)
这是一套供需区交易系统,自动标记关键价格区域并在价格回踩时给出信号。我将复刻主图的核心逻辑:识别swing高低点,画出供需区,产生交易箭头。
使用说明
安装步骤:
- 将代码保存为
SupplyDemandZones.mq5,放入 MT5 的MQL5/Indicators目录 - 在 MetaEditor 中编译(F7键)
- 在 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.
评论
还没有人评论,来抢个沙发。