//+------------------------------------------------------------------+
//| 66_Sparse_Section_Visibility_Toggle_v1_00.mq5                  |
//| Connects confirmed sparse pivots and safely hides markers.      |
//+------------------------------------------------------------------+
#property copyright "FXおもしろラボ"
#property version   "1.00"
#property strict
#property description "DRAW_SECTION and DRAW_NONE visibility example."

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3

#property indicator_label1 "Confirmed sparse section"
#property indicator_type1  DRAW_SECTION
#property indicator_color1 clrDeepSkyBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 3

#property indicator_label2 "Confirmed high marker"
#property indicator_type2  DRAW_ARROW
#property indicator_color2 clrLime
#property indicator_width2 2

#property indicator_label3 "Confirmed low marker"
#property indicator_type3  DRAW_ARROW
#property indicator_color3 clrOrangeRed
#property indicator_width3 2

input int InpWing = 3;               // 左右何本で局所高値・安値を確定するか
input bool InpShowMarkers = false;   // 確定点の丸印を表示するか

double g_section[];
double g_high_marker[];
double g_low_marker[];

bool IsConfirmedHigh(
   const int index,
   const double &high[],
   const int rates_total)
{
   if(index < InpWing || index + InpWing >= rates_total)
      return false;

   const double center = high[index];
   if(center <= 0.0 || !MathIsValidNumber(center))
      return false;

   for(int offset = 1; offset <= InpWing; ++offset)
   {
      if(center <= high[index - offset] || center <= high[index + offset])
         return false;
   }
   return true;
}

bool IsConfirmedLow(
   const int index,
   const double &low[],
   const int rates_total)
{
   if(index < InpWing || index + InpWing >= rates_total)
      return false;

   const double center = low[index];
   if(center <= 0.0 || !MathIsValidNumber(center))
      return false;

   for(int offset = 1; offset <= InpWing; ++offset)
   {
      if(center >= low[index - offset] || center >= low[index + offset])
         return false;
   }
   return true;
}

void ClearAt(const int index)
{
   g_section[index] = EMPTY_VALUE;
   g_high_marker[index] = EMPTY_VALUE;
   g_low_marker[index] = EMPTY_VALUE;
}

int OnInit()
{
   if(InpWing < 1 || InpWing > 100)
      return INIT_PARAMETERS_INCORRECT;

   SetIndexBuffer(0, g_section, INDICATOR_DATA);
   SetIndexBuffer(1, g_high_marker, INDICATOR_DATA);
   SetIndexBuffer(2, g_low_marker, INDICATOR_DATA);
   ArraySetAsSeries(g_section, true);
   ArraySetAsSeries(g_high_marker, true);
   ArraySetAsSeries(g_low_marker, true);

   for(int plot = 0; plot < 3; ++plot)
   {
      PlotIndexSetInteger(plot, PLOT_DRAW_BEGIN, InpWing);
      PlotIndexSetDouble(plot, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   }

   PlotIndexSetInteger(1, PLOT_ARROW, 159);
   PlotIndexSetInteger(2, PLOT_ARROW, 159);
   PlotIndexSetInteger(1, PLOT_ARROW_SHIFT, -8);
   PlotIndexSetInteger(2, PLOT_ARROW_SHIFT, 8);

   const ENUM_DRAW_TYPE marker_type =
      InpShowMarkers ? DRAW_ARROW : DRAW_NONE;
   PlotIndexSetInteger(1, PLOT_DRAW_TYPE, marker_type);
   PlotIndexSetInteger(2, PLOT_DRAW_TYPE, marker_type);

   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
   IndicatorSetString(
      INDICATOR_SHORTNAME,
      StringFormat(
         "Sparse Section v1.00 (wing=%d, markers=%s)",
         InpWing,
         InpShowMarkers ? "on" : "off"));
   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 < InpWing * 2 + 2)
      return 0;

   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);

   if(prev_calculated == 0)
   {
      ArrayInitialize(g_section, EMPTY_VALUE);
      ArrayInitialize(g_high_marker, EMPTY_VALUE);
      ArrayInitialize(g_low_marker, EMPTY_VALUE);
   }

   int limit = rates_total - InpWing - 1;
   if(prev_calculated > 0)
   {
      const int refreshed = rates_total - prev_calculated + InpWing + 1;
      limit = MathMin(limit, refreshed);
   }

   for(int index = limit; index >= 0; --index)
   {
      ClearAt(index);
      if(index < InpWing)
         continue;

      if(IsConfirmedHigh(index, high, rates_total))
      {
         g_section[index] = high[index];
         g_high_marker[index] = high[index];
      }
      else if(IsConfirmedLow(index, low, rates_total))
      {
         g_section[index] = low[index];
         g_low_marker[index] = low[index];
      }
   }

   return rates_total;
}
//+------------------------------------------------------------------+
