xuyuanzhao111 发表于 2026-5-11 22:28:17

【tradingview的订单块指标】自己写的

复制到pine脚本, 保存,添加即可使用;
采用吞没订单块策略。
//@version=5
indicator("订单块策略(仅供参考)", overlay=true, max_boxes_count=500, max_labels_count=500, max_lines_count=500)

// ———— SETTINGS ————
bull_ext_last = input.int(3, "Bullish OB", minval=1, inline="bull")
bg_bull_css = input.color(color.new(#ff1100, 80), "", inline="bull")
bull_css = input.color(#ff1100, "", inline="bull")
bull_avg_css = input.color(color.new(#9598a1, 37), "", inline="bull")

bear_ext_last = input.int(3, "Bearish OB", minval=1, inline="bear")
bg_bear_css = input.color(color.new(#169400, 80), "", inline="bear")
bear_css = input.color(#169400, "", inline="bear")
bear_avg_css = input.color(color.new(#9598a1, 37), "", inline="bear")

line_style = input.string("⎯⎯⎯", "Average Line Style", options=["⎯⎯⎯", "----", "····"])
line_width = input.int(1, "Average Line Width", minval=1)
mitigation = input.string("Wick", "Mitigation Methods", options=["Wick", "Close"])

// 吞没允许误差(默认0.2)
allow_error = input.float(0.2, "Engulfing Allow Error", step=0.1, minval=0.0)

label_bars_right = input.int(10, "Label Bars to the Right", minval=1)

// ———— 获取周期字符串 ————
get_interval() =>
    mins = timeframe.multiplier
    tf = timeframe.period
    res = ""
    if tf == "D"
      res := "1D"
    else if tf == "4H"
      res := "4H"
    else if tf == "1H"
      res := "1H"
    else if tf == "30"
      res := "30m"
    else if tf == "15"
      res := "15m"
    else if tf == "5"
      res := "5m"
    else if tf == "1"
      res := "1m"
    else
      res := str.tostring(mins) + "m"
    res

tf_label = get_interval()

// ———— FUNCTIONS ————
get_line_style(style) =>
    switch style
      "⎯⎯⎯" => line.style_solid
      "----" => line.style_dashed
      "····" => line.style_dotted

get_coordinates(condition, top, btm, ob_val)=>
    var ob_top= array.new_float(0)
    var ob_btm= array.new_float(0)
    var ob_avg= array.new_float(0)
    var ob_left = array.new_int(0)
    var ob_mitigated = array.new_bool(0)
    float ob = na
    if condition
      avg = math.avg(top, btm)
      array.unshift(ob_top, top)
      array.unshift(ob_btm, btm)
      array.unshift(ob_avg, avg)
      array.unshift(ob_left, time)
      array.unshift(ob_mitigated, false)
      ob := ob_val
   

remove_mitigated(ob_top, ob_btm, ob_left, ob_avg, target, bull,ob_mitigated)=>
    bool mitigated = false
    len = array.size(ob_top)
    if len > 0
      int i = len - 1
      while i >= 0
            top_val = array.get(ob_top, i)
            btm_val = array.get(ob_btm, i)
            if (bull and target < btm_val) or (not bull and target > top_val)
                mitigated := true
                array.set(ob_mitigated,i, true)
            i := i - 1
    mitigated

set_order_blocks(ob_top, ob_btm, ob_left, ob_avg, ext_last, bg_css, border_css, lvl_css,ob_mitigated)=>
    var ob_box = array.new_box(0)
    var ob_lvl = array.new_line(0)
    var ob_lbl = array.new_label(0)

    if barstate.isfirst
      for i = 0 to ext_last-1
            array.unshift(ob_box, box.new(na,na,na,na, xloc=xloc.bar_time, extend=extend.right, bgcolor=bg_css, border_color=color.new(border_css,70)))
            array.unshift(ob_lvl, line.new(na,na,na,na, xloc=xloc.bar_time, extend=extend.right, color=lvl_css, style=get_line_style(line_style), width=line_width))
            array.unshift(ob_lbl, label.new(na, na, "", xloc=xloc.bar_time, color=color.new(color.white, 50), textcolor=color.new(color.black, 50), style=label.style_label_center, size=size.normal))

    if barstate.islast
      array.clear(ob_box)
      array.clear(ob_lvl)
      array.clear(ob_lbl)

      for i = 0 to ext_last-1
            array.unshift(ob_box, box.new(na,na,na,na, xloc=xloc.bar_time, extend=extend.right, bgcolor=bg_css, border_color=color.new(border_css,70)))
            array.unshift(ob_lvl, line.new(na,na,na,na, xloc=xloc.bar_time, extend=extend.right, color=lvl_css, style=get_line_style(line_style), width=line_width))
            array.unshift(ob_lbl, label.new(na, na, "", xloc=xloc.bar_time, color=color.new(color.white, 50), textcolor=color.new(color.black, 50), style=label.style_label_center, size=size.normal))

      if array.size(ob_top) > 0
            max_i = math.min(ext_last-1, array.size(ob_top)-1)
            for i = 0 to max_i
                bx = array.get(ob_box, i)
                ln = array.get(ob_lvl, i)
                lb = array.get(ob_lbl, i)

                left_tm = array.get(ob_left, i)
                y_center = array.get(ob_avg, i)

                box.set_lefttop(bx, left_tm, array.get(ob_top, i))
                box.set_rightbottom(bx, left_tm, array.get(ob_btm, i))

                line.set_xy1(ln, left_tm, y_center)
                line.set_xy2(ln, left_tm+1, y_center)

                if(array.get(ob_mitigated, i))
                  label.set_xy(lb, time + label_bars_right * timeframe.multiplier * 60 * 1000, y_center)
                  label.set_text(lb, "broken")

// ———— KLINE PATTERN ————
bodyTop = math.max(open, close)
bodyBot = math.min(open, close)

// 看涨吞没(带允许误差),前一根K线为阴线,后一根K线为阳线,且阳线实体吞没阴线实体
bullish_pattern1 =
close < open and close > open and
bodyTop > bodyTop - allow_error and
bodyBot < bodyBot + allow_error

//十字星,前一根K线为十字星,后一根K线为阳线,且吞没前一根K线
bodyK = math.abs(close - open)
rangK = high - low
bullish_pattern2 = bodyK < 0.1*rangK and close > open and bodyTop > bodyTop - allow_error and bodyBot < bodyBot + allow_error
bullish_pattern = bullish_pattern1 or bullish_pattern2


// 看跌吞没(带允许误差),前一根K线为阳线,后一根K线为阴线,且阴线实体吞没阳线实体
bearish_pattern1 =
close > open and close < open and
bodyTop >= bodyTop - allow_error and
bodyBot <= bodyBot + allow_error

bearish_pattern2 = bodyK < 0.1*rangK and close < open and
bodyTop >= bodyTop - allow_error and
bodyBot <= bodyBot + allow_error

bearish_pattern = bearish_pattern1 or bearish_pattern2
target_bull = mitigation == "Close" ? close : low
target_bear = mitigation == "Close" ? close : high

// ———— ORDER BLOCKS ————
= get_coordinates(bullish_pattern, high, low, low)
= get_coordinates(bearish_pattern, high, low, high)

mitigated_bull = remove_mitigated(bull_top, bull_btm, bull_left, bull_avg, target_bull, true, bull_mitigated)
mitigated_bear = remove_mitigated(bear_top, bear_btm, bear_left, bear_avg, target_bear, false, bear_mitigated)

// ———— DRAW ————
set_order_blocks(bull_top, bull_btm, bull_left, bull_avg, bull_ext_last, bg_bull_css, bull_css, bull_avg_css,bull_mitigated)
set_order_blocks(bear_top, bear_btm, bear_left, bear_avg, bear_ext_last, bg_bear_css, bear_css, bear_avg_css,bear_mitigated)

// ———— ALERTS ————
alertcondition(bull_ob, "Bullish OB Formed", "Bullish order block detected")
alertcondition(bear_ob, "Bearish OB Formed", "Bearish order block detected")
alertcondition(mitigated_bull, "Bullish OB Mitigated", "Bullish order block mitigated")
alertcondition(mitigated_bear, "Bearish OB Mitigated", "Bearish order block mitigated")

// // ———— DEBUG 专用:支持回放,显示当前K线实体信息 ————
// var label debug_lbl = label.new(bar_index, high, "", style=label.style_label_left, size=size.normal)

// label.set_xy(debug_lbl, bar_index, high)
// label.set_text(debug_lbl,"bodyTop    = " + str.tostring(bodyTop) + "\n" + "bodyBot    = " + str.tostring(bodyBot) + "\n" + "bodyTop = " + str.tostring(bodyTop) + "\n" +    "bodyBot = " + str.tostring(bodyBot) + "\n" +    "abs_top_diff = " + str.tostring(math.abs(bodyTop - bodyTop)) + "\n" +    "abs_bot_diff = " + str.tostring(math.abs(bodyBot - bodyBot)))
// label.set_color(debug_lbl, color.new(#000000, 80))
// label.set_textcolor(debug_lbl, color.black)

zc123 发表于 2026-5-11 23:23:00

[玫瑰][玫瑰]

157142600 发表于 2026-5-13 13:43:14

订单块识别与Pine Script一致性:

吞没形态判断完全按照Pine脚本的逻辑,支持普通吞没和十字星吞没。

允许误差(EngulfError)实现为前一根K线波动的百分比。

订单块边界定义为吞没形态前一根K线的高/低(与Pine脚本中 high, low 一致)。

均线取块区域的中点。

突破检测(Mitigation)未在绘制中体现,但已保存在结构体中。

jackychan 发表于 2026-5-13 22:58:58

怎么用的

zzzz0759 发表于 2026-6-7 22:00:32

谢谢分享,楼主能不能贴张图,这样直观很多

zyl51314 发表于 2026-6-9 13:11:54

看起来很不错 我去试试看

2623885357 发表于 2026-6-12 03:35:44

MT4编译有错误,楼主改改呗

Chz2017 发表于 2026-7-10 11:54:49

用TV是不是要用梯子?有大佬教一下吗

19937673361 发表于 2026-7-10 16:59:02

感谢分享

zhibiao12 发表于 2026-8-21 13:33:39

这个复制到MT4上怎么有57处错误?大神,能改一下放在MT4上吗?

xubin0574 发表于 2026-8-22 09:15:34

进来学习了

mockoc 发表于 2026-8-22 11:16:57

有好多错误啊

mockoc 发表于 2026-8-22 11:19:39

//+------------------------------------------------------------------+
//|                                                OrderBlock.mq5|
//|                                    Copyright 2026, Your Name   |
//|                                             https://www.yoursite |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Your Name"
#property link      "https://www.yoursite"
#property version   "1.00"

//--- 指标显示在主图
#property indicator_chart_window

//--- 总共使用4个缓冲区(每个绘图占用2个)
#property indicator_buffers 4
#property indicator_plots   2

//--- 绘图1:看涨订单块(填充区域)
#property indicator_label1"Bullish OB"
#property indicator_type1   DRAW_FILLING
#property indicator_color1clrLimeGreen, clrLimeGreen   // 上下边界颜色(相同即纯色填充)
#property indicator_style1STYLE_SOLID
#property indicator_width11

//--- 绘图2:看跌订单块(填充区域)
#property indicator_label2"Bearish OB"
#property indicator_type2   DRAW_FILLING
#property indicator_color2clrRed, clrRed
#property indicator_style2STYLE_SOLID
#property indicator_width21

//+------------------------------------------------------------------+
//| 输入参数(用户可调整)                                           |
//+------------------------------------------------------------------+
input int      Lookback   = 10;          // 回溯周期(用于识别订单块)
input double   MinRange   = 0.001;       // 最小价格范围(点数,避免微小波动)
input bool   ShowLabels = true;      // 是否显示图例标签

//+------------------------------------------------------------------+
//| 缓冲区声明(用于存储上下边界)                                 |
//+------------------------------------------------------------------+
double BullOB_Upper[];   // 看涨订单块上边界
double BullOB_Lower[];   // 看涨订单块下边界
double BearOB_Upper[];   // 看跌订单块上边界
double BearOB_Lower[];   // 看跌订单块下边界

//+------------------------------------------------------------------+
//| 自定义指标初始化函数                                             |
//+------------------------------------------------------------------+
void OnInit()
{
   //--- 绑定缓冲区(顺序必须与 indicator_plots 对应)
   SetIndexBuffer(0, BullOB_Upper, INDICATOR_DATA);
   SetIndexBuffer(1, BullOB_Lower, INDICATOR_DATA);
   SetIndexBuffer(2, BearOB_Upper, INDICATOR_DATA);
   SetIndexBuffer(3, BearOB_Lower, INDICATOR_DATA);

   //--- 确保绘图类型为 DRAW_FILLING(与#property一致,可省略)
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_FILLING);
   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_FILLING);

   //--- 设置标签(如果ShowLabels为false则隐藏)
   if(!ShowLabels)
   {
      PlotIndexSetString(0, PLOT_LABEL, "");
      PlotIndexSetString(1, PLOT_LABEL, "");
   }

   //--- 初始化所有缓冲区为0(避免绘制未检测区域)
   ArrayInitialize(BullOB_Upper, 0);
   ArrayInitialize(BullOB_Lower, 0);
   ArrayInitialize(BearOB_Upper, 0);
   ArrayInitialize(BearOB_Lower, 0);
}

//+------------------------------------------------------------------+
//| 核心计算函数(每次新K线到来时执行)                              |
//+------------------------------------------------------------------+
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[])
{
   //--- 计算起始索引(避免重复计算已处理K线)
   int start = prev_calculated - 1;
   if(start < 0) start = 0;

   //--- 循环遍历每个K线(从最早到最新)
   for(int i = start; i < rates_total; i++)
   {
      // 默认清除该K线的绘制(设为0表示不填充)
      BullOB_Upper = 0;
      BullOB_Lower = 0;
      BearOB_Upper = 0;
      BearOB_Lower = 0;

      // ============================================================
      // ★★★ 在这里编写您的订单块识别逻辑 ★★★
      // 以下仅为示例:使用简单条件(阳线/阴线)演示填充区域
      // 实际使用时请替换为真正的订单块定义(如基于价格反转、成交量等)
      // ============================================================

      // 示例:如果当前K线是阳线(close>open)且满足最小范围,视为看涨订单块
      if(close > open && (high - low) >= MinRange)
      {
         // 订单块区域:从该K线最低价到最高价(可自定义,如使用前一根K线收盘等)
         BullOB_Upper = high;
         BullOB_Lower = low;
      }
      // 如果当前K线是阴线(close<open),视为看跌订单块
      else if(close < open && (high - low) >= MinRange)
      {
         BearOB_Upper = high;
         BearOB_Lower = low;
      }

      // 注意:DRAW_FILLING 只有在两个边界值不同时才会绘制填充,
      // 当上下边界都为0(或相同)时不绘制,因此上述逻辑有效。
      // 您也可以使用 EMPTY_VALUE,但0在价格范围之外通常足够。
   }

   //--- 返回最新已计算K线数
   return(rates_total);
}
//+------------------------------------------------------------------+

这是MT5修复版

Victor_777 发表于 2026-9-8 12:52:04

谢谢分享,现在就去试一试
页: [1]
查看完整版本: 【tradingview的订单块指标】自己写的