//+------------------------------------------------------------------+
//|                                  Reversal_Trap_Probability_Bands|
//|                                                   Copyright 2026 |
//|                                                        BigBeluga |
//|                                      Converted for MT4 New Build |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, BigBeluga"
#property link      "https://creativecommons.org"
#property version   "1.00"
#property strict

#property indicator_chart_window
#property indicator_buffers 5

// 定义指示器颜色与线型
#property indicator_color1 clrDarkGray     // Basis 中线
#property indicator_color2 clrCrimson      // Upper Band 上轨
#property indicator_color3 clrTeal         // Lower Band 下轨
#property indicator_color4 clrTeal         // Bull Trap 向上信号箭头
#property indicator_color5 clrCrimson      // Bear Trap 向下信号箭头

#property indicator_width1 1
#property indicator_width2 3
#property indicator_width3 3
#property indicator_width4 2
#property indicator_width5 2

#property indicator_style1 STYLE_DOT
#property indicator_style2 STYLE_SOLID
#property indicator_style3 STYLE_SOLID

//--- 输入参数 (INPUTS)
input int      envelope_len = 55;          // Envelope Smoothness
input double   multiplier   = 4.0;         // Envelope Width
input int      trap_window  = 10;          // Trap Window (Candles)
input int      signal_gap   = 10;          // Minimum Bars Between Signals
input double   stop_mult    = 0.5;         // ATR Stop Multiplier

//--- 指标缓冲区映射
double BufferBasis[];
double BufferUpper[];
double BufferLower[];
double BufferBullArrow[];
double BufferBearArrow[];

//--- 内部状态变量（对应 Pine Script 中的 var int）
int close_above_envelope_count[];
int close_below_envelope_count[];
int last_signal_bar = -1000;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   // 缓冲区绑定
   SetIndexBuffer(0, BufferBasis);
   SetIndexBuffer(1, BufferUpper);
   SetIndexBuffer(2, BufferLower);
   SetIndexBuffer(3, BufferBullArrow);
   SetIndexBuffer(4, BufferBearArrow);
   
   // 设置箭头样式
   SetIndexStyle(3, DRAW_ARROW);
   SetIndexArrow(3, 233); // 向上箭头
   SetIndexStyle(4, DRAW_ARROW);
   SetIndexArrow(4, 234); // 向下箭头
   
   // 标签设置
   SetIndexLabel(0, "Envelope Baseline");
   SetIndexLabel(1, "Envelope Ceiling");
   SetIndexLabel(2, "Envelope Floor");
   SetIndexLabel(3, "Bull Trap Signal");
   SetIndexLabel(4, "Bear Trap Signal");

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 <= envelope_len + 100) return(0);

   // 动态调整状态计数数组的大小，以匹配图表总 K 线数量
   if(ArraySize(close_above_envelope_count) != rates_total)
   {
      ArrayResize(close_above_envelope_count, rates_total);
      ArrayResize(close_below_envelope_count, rates_total);
      ArrayInitialize(close_above_envelope_count, 0);
      ArrayInitialize(close_below_envelope_count, 0);
      last_signal_bar = rates_total; // 重置信号位置
   }

   // 计算未初始化的历史柱线（从过去往现在计算，MQL4 倒序索引 0 是最新柱线）
   int limit = rates_total - prev_calculated;
   if(limit > rates_total - envelope_len - 2) 
      limit = rates_total - envelope_len - 2;

   // 1. 核心计算循环（计算通道边界）
   for(int i = limit; i >= 0; i--)
   {
      // 计算 EMA (Basis Line)
      BufferBasis[i] = iMA(NULL, 0, envelope_len, 0, MODE_EMA, PRICE_CLOSE, i);
      
      // 计算 ATR (Volatility)
      double vola = iATR(NULL, 0, envelope_len, i);
      
      // 计算 Upper & Lower Bands
      BufferUpper[i] = BufferBasis[i] + (multiplier * vola);
      BufferLower[i] = BufferBasis[i] - (multiplier * vola);
      
      // 初始化信号缓冲为默认空值
      BufferBullArrow[i] = EMPTY_VALUE;
      BufferBearArrow[i] = EMPTY_VALUE;
   }

   // 2. 状态递推与信号逻辑（由于状态有前置依赖关系close_above_envelope_count[1]，必须严格由远及近递推）
   for(int i = limit; i >= 0; i--)
   {
      // 模拟 Pine 里的历史索引 [1] 状态递推
      int prev_idx = i + 1; 
      if(prev_idx >= rates_total) prev_idx = rates_total - 1;

      // 提取前一个周期的状态
      int prev_above_count = close_above_envelope_count[prev_idx];
      int prev_below_count = close_below_envelope_count[prev_idx];

      // --- Bear Trap 逻辑 ---
      bool raw_bear_trap = false;
      if(close[i] < BufferUpper[i])
      {
         if(high[i] > BufferUpper[i] && close[prev_idx] < BufferUpper[prev_idx] && prev_above_count <= trap_window)
            raw_bear_trap = true;
         else if(close[prev_idx] > BufferUpper[prev_idx] && prev_above_count <= trap_window)
            raw_bear_trap = true;
      }

      // 更新 Bear 计数器状态
      if(high[i] > BufferUpper[i])
         close_above_envelope_count[i] = prev_above_count + 1;
      else
         close_above_envelope_count[i] = 0;

      // --- Bull Trap 逻辑 ---
      bool raw_bull_trap = false;
      if(close[i] > BufferLower[i])
      {
         if(low[i] < BufferLower[i] && close[prev_idx] > BufferLower[prev_idx] && prev_below_count <= trap_window)
            raw_bull_trap = true;
         else if(close[prev_idx] < BufferLower[prev_idx] && prev_below_count <= trap_window)
            raw_bull_trap = true;
      }

      // 更新 Bull 计数器状态
      if(low[i] < BufferLower[i])
         close_below_envelope_count[i] = prev_below_count + 1;
      else
         close_below_envelope_count[i] = 0;

      // --- 冷却过滤与信号输出 ---
      // 在 MQL4 逆序时间轴中，柱线编号更小代表更新，所以间隔为：last_signal_bar - i
      bool can_fire = (last_signal_bar - i) >= signal_gap;

      if(raw_bull_trap && can_fire)
      {
         double atr_100 = iATR(NULL, 0, 100, i);
         BufferBullArrow[i] = low[i] - (atr_100 * stop_mult);
         last_signal_bar = i;
      }
      else if(raw_bear_trap && can_fire)
      {
         double atr_100 = iATR(NULL, 0, 100, i);
         BufferBearArrow[i] = high[i] + (atr_100 * stop_mult);
         last_signal_bar = i;
      }
   }

   return(rates_total);
}
//+------------------------------------------------------------------+
