智能货币订单块与结构突破信号
自动识别订单块区域并在市场结构突破时显示买卖箭头信号
MT5 真机运行截图 · 服务器把编译好的 EX5 挂到黄金 H1 图表上截的,你装上去看到的就是这个样子
#property copyright "XAUOF指标工坊"
#property version "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
// 买入箭头
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrDodgerBlue
#property indicator_width1 3
#property indicator_label1 "买入信号"
// 卖出箭头
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrRed
#property indicator_width2 3
#property indicator_label2 "卖出信号"
//--- 输入参数
input int SwingPeriod = 5; // 摆动周期:识别高低点的K线数量,推荐5-10
input int ArrowOffset = 50; // 箭头偏移:距离K线的点数,推荐30-100
input bool ShowBullishOB = true; // 显示看涨订单块(蓝色)
input bool ShowBearishOB = true; // 显示看跌订单块(橙色)
input color BullishOBColor = clrDodgerBlue; // 看涨订单块颜色
input color BearishOBColor = clrOrange; // 看跌订单块颜色
input int OBTransparency = 80; // 订单块透明度:0=不透明,90=很透明
input int MaxOBToShow = 10; // 最多显示订单块数量:避免图表过于混乱
//--- 指标缓冲区
double BuyArrowBuffer[];
double SellArrowBuffer[];
//--- 全局变量
struct OrderBlockInfo {
datetime time_start;
datetime time_end;
double price_high;
double price_low;
bool is_bullish; // true=看涨OB,false=看跌OB
};
OrderBlockInfo OBList[];
int OBCount = 0;
//+------------------------------------------------------------------+
//| 初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
// 绑定指标缓冲区
SetIndexBuffer(0, BuyArrowBuffer, INDICATOR_DATA);
SetIndexBuffer(1, SellArrowBuffer, INDICATOR_DATA);
// 设置箭头符号:233=上箭头,234=下箭头
PlotIndexSetInteger(0, PLOT_ARROW, 233);
PlotIndexSetInteger(1, PLOT_ARROW, 234);
// 设置空值
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
// 初始化数组
ArrayResize(OBList, MaxOBToShow);
OBCount = 0;
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(BuyArrowBuffer, EMPTY_VALUE);
ArrayInitialize(SellArrowBuffer, EMPTY_VALUE);
// 清除旧的图形对象
ObjectsDeleteAll(0, "OB_");
}
// 逐根K线扫描
for(int i = start; i < rates_total && !IsStopped(); i++)
{
// 重置当前K线的箭头
BuyArrowBuffer[i] = EMPTY_VALUE;
SellArrowBuffer[i] = EMPTY_VALUE;
// 需要足够的历史数据
if(i < SwingPeriod * 2)
continue;
// 检查是否形成摆动高点(Swing High)
if(IsSwingHigh(high, i, SwingPeriod))
{
// 找到摆动高点前的最后一根看涨K线作为看跌订单块
int obIndex = FindLastBullishCandle(open, close, i, SwingPeriod);
if(obIndex > 0 && ShowBearishOB)
{
// 创建看跌订单块
CreateOrderBlock(time[obIndex], time[i], high[obIndex], low[obIndex], false, i);
}
// 检查是否突破了之前的高点(结构突破)
if(IsBOS_High(high, i, SwingPeriod * 2))
{
// 显示卖出箭头
SellArrowBuffer[i] = high[i] + ArrowOffset * _Point;
}
}
// 检查是否形成摆动低点(Swing Low)
if(IsSwingLow(low, i, SwingPeriod))
{
// 找到摆动低点前的最后一根看跌K线作为看涨订单块
int obIndex = FindLastBearishCandle(open, close, i, SwingPeriod);
if(obIndex > 0 && ShowBullishOB)
{
// 创建看涨订单块
CreateOrderBlock(time[obIndex], time[i], high[obIndex], low[obIndex], true, i);
}
// 检查是否突破了之前的低点(结构突破)
if(IsBOS_Low(low, i, SwingPeriod * 2))
{
// 显示买入箭头
BuyArrowBuffer[i] = low[i] - ArrowOffset * _Point;
}
}
}
return rates_total;
}
//+------------------------------------------------------------------+
//| 判断是否为摆动高点 |
//+------------------------------------------------------------------+
bool IsSwingHigh(const double &high[], int index, int period)
{
if(index < period || index >= ArraySize(high) - 1)
return false;
double centerHigh = high[index];
// 检查左侧period根K线
for(int i = 1; i <= period; i++)
{
if(high[index - i] >= centerHigh)
return false;
}
// 检查右侧period根K线(实时K线不检查右侧)
for(int i = 1; i <= period && index + i < ArraySize(high); i++)
{
if(high[index + i] > centerHigh)
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| 判断是否为摆动低点 |
//+------------------------------------------------------------------+
bool IsSwingLow(const double &low[], int index, int period)
{
if(index < period || index >= ArraySize(low) - 1)
return false;
double centerLow = low[index];
// 检查左侧period根K线
for(int i = 1; i <= period; i++)
{
if(low[index - i] <= centerLow)
return false;
}
// 检查右侧period根K线(实时K线不检查右侧)
for(int i = 1; i <= period && index + i < ArraySize(low); i++)
{
if(low[index + i] < centerLow)
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| 找到摆动点之前最后一根看涨K线 |
//+------------------------------------------------------------------+
int FindLastBullishCandle(const double &open[], const double &close[], int swingIndex, int lookback)
{
for(int i = swingIndex - 1; i >= swingIndex - lookback && i >= 0; i--)
{
if(close[i] > open[i]) // 阳线
return i;
}
return -1;
}
//+------------------------------------------------------------------+
//| 找到摆动点之前最后一根看跌K线 |
//+------------------------------------------------------------------+
int FindLastBearishCandle(const double &open[], const double &close[], int swingIndex, int lookback)
{
for(int i = swingIndex - 1; i >= swingIndex - lookback && i >= 0; i--)
{
if(close[i] < open[i]) // 阴线
return i;
}
return -1;
}
//+------------------------------------------------------------------+
//| 检查是否突破了之前的高点(向上BOS) |
//+------------------------------------------------------------------+
bool IsBOS_High(const double &high[], int index, int lookback)
{
if(index < lookback + 1)
return false;
double currentHigh = high[index];
// 检查是否突破了lookback范围内的最高点
double maxHigh = high[index - 1];
for(int i = index - lookback; i < index; i++)
{
if(high[i] > maxHigh)
maxHigh = high[i];
}
return (currentHigh > maxHigh);
}
//+------------------------------------------------------------------+
//| 检查是否突破了之前的低点(向下BOS) |
//+------------------------------------------------------------------+
bool IsBOS_Low(const double &low[], int index, int lookback)
{
if(index < lookback + 1)
return false;
double currentLow = low[index];
// 检查是否突破了lookback范围内的最低点
double minLow = low[index - 1];
for(int i = index - lookback; i < index; i++)
{
if(low[i] < minLow)
minLow = low[i];
}
return (currentLow < minLow);
}
//+------------------------------------------------------------------+
//| 创建订单块矩形 |
//+------------------------------------------------------------------+
void CreateOrderBlock(datetime timeStart, datetime timeEnd, double priceHigh, double priceLow, bool isBullish, int barIndex)
{
// 限制订单块数量
if(OBCount >= MaxOBToShow)
return;
// 生成唯一的对象名称
string objName = "OB_" + IntegerToString(barIndex) + "_" + (isBullish ? "Bull" : "Bear");
// 如果对象已存在,先删除
if(ObjectFind(0, objName) >= 0)
ObjectDelete(0, objName);
// 创建矩形对象
if(!ObjectCreate(0, objName, OBJ_RECTANGLE, 0, timeStart, priceHigh, timeEnd + PeriodSeconds(PERIOD_CURRENT) * 50, priceLow))
{
Print("创建订单块失败: ", GetLastError());
return;
}
// 设置矩形属性
color obColor = isBullish ? BullishOBColor : BearishOBColor;
ObjectSetInteger(0, objName, OBJPROP_COLOR, obColor);
ObjectSetInteger(0, objName, OBJPROP_FILL, true);
ObjectSetInteger(0, objName, OBJPROP_BACK, true); // 放在背景层
ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, objName, OBJPROP_SELECTED, false);
ObjectSetInteger(0, objName, OBJPROP_HIDDEN, true);
ObjectSetInteger(0, objName, OBJPROP_WIDTH, 1);
// 设置透明度(0-255,值越大越不透明,这里转换一下)
int alpha = (int)((100 - OBTransparency) * 255 / 100);
if(alpha < 0) alpha = 0;
if(alpha > 255) alpha = 255;
// 修改颜色的Alpha通道(注意:MQL5的颜色格式是0xAABBGGRR)
color transparentColor = (color)((alpha << 24) | (obColor & 0x00FFFFFF));
ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, transparentColor);
// 添加到列表
OBList[OBCount].time_start = timeStart;
OBList[OBCount].time_end = timeEnd;
OBList[OBCount].price_high = priceHigh;
OBList[OBCount].price_low = priceLow;
OBList[OBCount].is_bullish = isBullish;
OBCount++;
}
//+------------------------------------------------------------------+
//| 清理函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// 删除所有订单块对象
ObjectsDeleteAll(0, "OB_");
}作品说明
从图上识别到的元素:
这是一套SMC智能货币概念指标,包含以下核心组件:
- 彩色订单块(Order Block):橙色、紫色、蓝色、青色等矩形区域,标记关键的供需区域
- 买卖箭头信号:蓝色向上箭头标记买入机会,红色向下箭头标记卖出机会
- 水平虚线:黄色OP线和红色EOH线,标记关键价格位
- 文本标签:OB(订单块)、QB、BOS(结构突破)、CHoCH(结构变化)等
指标逻辑:识别摆动高低点→绘制突破前的最后一根反向K线作为订单块→在价格突破结构时生成信号箭头。我会实现订单块识别、矩形绘制和箭头信号这三个核心功能。
使用说明
安装步骤:
- 将代码保存为
SMC_OrderBlock_Arrows.mq5,放入MQL5/Indicators目录 - 在MT5的导航器中编译(双击文件自动编译)
- 拖到XAUUSD或任意品种的图表上
参数调节:
- 摆动周期:默认5,越小越灵敏(信号多但噪音大),越大越稳定(信号少但质量高)
- 箭头偏移:调整箭头与K线的距离,图表缩放后可能需要调大此值
- 订单块颜色:看涨用蓝色、看跌用橙色,可根据个人喜好修改
- 透明度:80表示20%不透明度,避免矩形遮挡K线;调小此值可让订单块更明显
- 最多显示数量:默认10个,避免历史订单块太多导致图表混乱
信号解读:
- 蓝色向上箭头:价格突破前期低点,形成看涨结构突破(BOS),可考虑做多
- 红色向下箭头:价格突破前期高点,形成看跌结构突破,可考虑做空
- 蓝色矩形:看涨订单块(买方力量聚集区),价格回调到此区域可能获得支撑
- 橙色矩形:看跌订单块(卖方力量聚集区),价格反弹到此区域可能遇到阻力
注意事项:
- 订单块是机构可能留下的未成交订单区域,价格再次触及时容易产生反应
- 结合更大周期的订单块使用效果更好(例如H1图表参考H4的订单块)
- 箭头仅为结构突破提示,实际交易需结合其他确认信号(如价格行为、成交量)
- 本指标不含止损止盈逻辑,务必自行设置风险管理
- 历史信号会重绘(因为需要右侧K线确认摆动点),实盘使用时注意实时K线的确认
AI 解读根据源码逐行分析写成,供参考,以实际运行为准
这是什么
这是一个基于智能货币概念(SMC)的MT5指标,自动在图表上标记订单块(Order Block)区域,并在价格突破市场结构时显示买卖箭头信号。订单块是机构可能留下大量未成交订单的价格区域,价格回到这些区域时容易产生反应。指标用蓝色矩形标记看涨订单块,橙色矩形标记看跌订单块,在结构突破时显示蓝色向上箭头(做多)或红色向下箭头(做空)。
逻辑原理
指标通过三步识别信号:
- 识别摆动点:扫描K线找出摆动高点和摆动低点。摆动高点是指某根K线的最高价高于左右各N根K线(N由摆动周期参数决定),摆动低点则相反。
- 绘制订单块:找到摆动点后,向前回溯,找到摆动点之前最后一根反向K线。例如形成摆动高点前的最后一根阳线(收盘价>开盘价)作为看跌订单块,形成摆动低点前的最后一根阴线作为看涨订单块,用矩形画出该K线的高低价范围。
- 显示突破箭头:当价格突破前N根K线的最高点(向上BOS)时在K线上方显示红色向下箭头,突破最低点(向下BOS)时在下方显示蓝色向上箭头。
矩形会一直延伸到当前,透明度可调,避免遮挡K线。
参数说明
- SwingPeriod(默认5):识别摆动高低点的K线数量。设为5表示中间K线的高/低点必须高于/低于左右各5根K线才算摆动点。数值越小信号越多但噪音大,越大则信号越稳定但反应慢,推荐5-10。
- ArrowOffset(默认50):箭头距离K线最高/最低价的点数,用于调整箭头位置避免重叠。图表缩放后可能需要调大此值,推荐30-100。
- ShowBullishOB(默认true):是否显示看涨订单块(蓝色矩形)。
- ShowBearishOB(默认true):是否显示看跌订单块(橙色矩形)。
- BullishOBColor(默认蓝色):看涨订单块的颜色。
- BearishOBColor(默认橙色):看跌订单块的颜色。
- OBTransparency(默认80):订单块透明度,0表示完全不透明,90表示非常透明。数值越大矩形越淡,推荐70-85。
- MaxOBToShow(默认10):图表上最多同时显示多少个订单块,避免历史订单块太多导致混乱。
怎么用
将代码保存为 SMC_OrderBlock_Arrows.mq5,放入MT5数据文件夹的 MQL5/Indicators 目录(文件→打开数据文件夹),在导航器窗口中双击文件自动编译。编译成功后拖到任意品种的图表上(推荐H1或H4周期),弹出参数窗口可调节上述参数。
看信号:蓝色向上箭头表示价格突破前期低点形成看涨结构,可考虑做多;红色向下箭头表示突破前期高点形成看跌结构,可考虑做空。蓝色矩形是潜在支撑区(买方力量聚集),橙色矩形是潜在阻力区(卖方力量聚集),价格回到这些区域时可能产生反应。
适用场景
适合品种:XAUUSD、EURUSD、GBPUSD等主流货币对和指数,任何有明显波动的品种都可用。
适合周期:H1、H4、D1。M15和M5也能用但信号较多,需结合更大周期的订单块过滤。日内剥头皮不适合此逻辑。
适合行情:趋势行情和震荡突破行情。在明确趋势中,订单块可作为回调入场点;在震荡区间突破时,箭头提示结构改变。不适合无方向的窄幅震荡,会产生大量假突破信号。
风险提示
- 重绘问题:摆动点需要右侧K线确认,历史信号会随新K线出现而改变位置或消失。实盘使用时,当前未走完的K线上的箭头和订单块可能在下一根K线刷新后消失。
- 滞后性:箭头信号出现时价格已经突破,可能错过最佳入场点。建议结合订单块回调入场,而不是追着箭头直接开仓。
- 假突破:小周期上的结构突破可能只是大周期的正常回调,单独使用此指标容易被反向扫损。务必结合更大周期的趋势和订单块判断。
- 无止损逻辑:指标只显示信号,不包含止损止盈和仓位管理。必须自行设置止损(建议放在订单块另一侧或摆动点外),严格控制单笔风险。
- 订单块可能失效:价格多次触碰订单块后该区域的订单可能已消耗殆尽,不能盲目依赖历史订单块。代码中订单块会一直显示直到被新订单块替代,需自行判断有效性。
常见问题
- 这个指标会重绘吗
- 会。因为摆动高低点需要右侧K线确认,历史信号的位置和订单块会随新K线出现而调整。实盘时注意当前K线上的箭头可能在下一根K线消失。
- 默认参数适合什么周期
- 默认摆动周期5适合H1和H4周期。如果用在M15需要调小到3,用在D1可以调大到7-10,否则信号太少。
- 可以用在XAUUSD以外的品种吗
- 可以。代码里没有品种限制,任何有波动的品种都能用,包括外汇、指数、商品。但不同品种的点值和波动幅度不同,箭头偏移参数可能需要调整。
- 箭头出现后可以直接开仓吗
- 不建议。箭头只是结构突破提示,出现时价格已经走了一段。更稳妥的做法是等价格回调到订单块区域再入场,或结合其他确认信号(如K线形态、成交量)。
- MT4能用这个指标吗
- 不能直接用。这是MQL5代码,只能在MT5上运行。MT4使用MQL4语言,语法和函数不同,需要重写代码才能移植。
SMC Order Block & Structure Breakout Indicator for MT5
An MT5 indicator based on Smart Money Concepts that automatically identifies swing highs/lows, draws order block rectangles, and displays buy/sell arrows on market structure breakouts (BOS). Adjustable sensitivity and display limits included.
Source code is shown above. Compiled EX5 files are available to VIP members.
评论
还没有人评论,来抢个沙发。