//+------------------------------------------------------------------+
//|                                                  Synergy_APB.mq5 |
//|                                 Copyright © 2009-2026, CompassFX |
//|                                        http://www.compassfx.com  |
//+------------------------------------------------------------------+
#property copyright   "Copyright © 2009-2026, CompassFX"
#property link        "http://www.compassfx.com"
#property description "Synergy Average Price Bars (APB)"
#property version     "1.00"

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots   1

//--- Plot 1: APB Candlesticks
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrDodgerBlue, clrRed
#property indicator_label1  "APB Open;APB High;APB Low;APB Close"
#property indicator_width1  1

//+------------------------------------------------------------------+
//| Input Parameters                                                 |
//+------------------------------------------------------------------+
input group "=== APB Colors ==="
input color  InpBullColor            = clrDodgerBlue; // Bullish Candle Color
input color  InpBearColor            = clrRed;        // Bearish Candle Color

input group "=== Chart Display ==="
input bool   InpHideNativeCandles    = false;         // Hide Native Chart Candles (Line / None)

input group "=== Alerts on Direction Change ==="
input bool   InpSendAlert            = false;         // Popup Alert
input bool   InpPlaySound            = false;         // Play Sound
input string InpSoundFile            = "alert.wav";   // Sound File
input bool   InpSendNotification     = false;         // Mobile Push Notification
input bool   InpSendMail             = false;         // Send Email

//+------------------------------------------------------------------+
//| Indicator Buffers                                                |
//+------------------------------------------------------------------+
double ExtOBuffer[];
double ExtHBuffer[];
double ExtLBuffer[];
double ExtCBuffer[];
double ExtColorBuffer[];
double ExtTrendBuffer[];

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
datetime fx_lastAlertTime      = 0;
long     fx_chartModeOrig      = CHART_CANDLES;
long     fx_chartLineColorOrig = clrSilver;

//+------------------------------------------------------------------+
//| Custom Indicator Initialization                                  |
//+------------------------------------------------------------------+
int OnInit()
{
   // Map indicator buffers
   SetIndexBuffer(0, ExtOBuffer,     INDICATOR_DATA);
   SetIndexBuffer(1, ExtHBuffer,     INDICATOR_DATA);
   SetIndexBuffer(2, ExtLBuffer,     INDICATOR_DATA);
   SetIndexBuffer(3, ExtCBuffer,     INDICATOR_DATA);
   SetIndexBuffer(4, ExtColorBuffer, INDICATOR_COLOR_INDEX);
   SetIndexBuffer(5, ExtTrendBuffer, INDICATOR_CALCULATIONS);

   // Configure plot colors
   PlotIndexSetInteger(0, PLOT_DRAW_TYPE,     DRAW_COLOR_CANDLES);
   PlotIndexSetInteger(0, PLOT_COLOR_INDEXES, 2);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, InpBullColor);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, InpBearColor);
   PlotIndexSetDouble (0, PLOT_EMPTY_VALUE,   0.0);

   IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
   IndicatorSetString (INDICATOR_SHORTNAME, "Synergy APB");

   if(InpHideNativeCandles)
   {
      fx_chartModeOrig      = ChartGetInteger(0, CHART_MODE);
      fx_chartLineColorOrig = ChartGetInteger(0, CHART_COLOR_CHART_LINE);
      ChartSetInteger(0, CHART_MODE, CHART_LINE);
      ChartSetInteger(0, CHART_COLOR_CHART_LINE, clrNONE);
      ChartRedraw(0);
   }

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom Indicator Deinitialization                                |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   if(InpHideNativeCandles && (reason == REASON_REMOVE || reason == REASON_CHARTCLOSE))
   {
      ChartSetInteger(0, CHART_MODE, fx_chartModeOrig);
      ChartSetInteger(0, CHART_COLOR_CHART_LINE, fx_chartLineColorOrig);
      ChartRedraw(0);
   }
}

//+------------------------------------------------------------------+
//| Trigger Alerts                                                   |
//+------------------------------------------------------------------+
void CheckAlert(datetime barTime, int currentTrend, int prevTrend)
{
   if(barTime == fx_lastAlertTime) return;
   if(currentTrend == prevTrend || prevTrend == 0) return;

   string dirStr = (currentTrend == 1) ? "BULLISH (Blue)" : "BEARISH (Red)";
   string msg = StringFormat("[Synergy APB] %s %s: Trend changed to %s",
                             _Symbol, EnumToString((ENUM_TIMEFRAMES)_Period), dirStr);

   if(InpSendAlert)        Alert(msg);
   if(InpPlaySound)        PlaySound(InpSoundFile);
   if(InpSendNotification) SendNotification(msg);
   if(InpSendMail)         SendMail("Synergy APB Alert", msg);

   fx_lastAlertTime = barTime;
}

//+------------------------------------------------------------------+
//| Custom Indicator Iteration                                       |
//+------------------------------------------------------------------+
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 < 2) return(0);

   int start = 0;

   // First bar seed initialization
   if(prev_calculated == 0)
   {
      double ha_close_0  = (open[0] + high[0] + low[0] + close[0]) / 4.0;
      double apb_close_0 = (ha_close_0 + close[0]) / 2.0;
      double apb_open_0  = (open[0] + close[0]) / 2.0;
      double apb_high_0  = MathMax(high[0], MathMax(apb_open_0, apb_close_0));
      double apb_low_0   = MathMin(low[0], MathMin(apb_open_0, apb_close_0));

      ExtOBuffer[0] = NormalizeDouble(apb_open_0,  _Digits);
      ExtHBuffer[0] = NormalizeDouble(apb_high_0,  _Digits);
      ExtLBuffer[0] = NormalizeDouble(apb_low_0,   _Digits);
      ExtCBuffer[0] = NormalizeDouble(apb_close_0, _Digits);

      if(apb_open_0 < apb_close_0)
      {
         ExtColorBuffer[0] = 0.0; // Bullish (InpBullColor)
         ExtTrendBuffer[0] = 1.0;
      }
      else
      {
         ExtColorBuffer[0] = 1.0; // Bearish (InpBearColor)
         ExtTrendBuffer[0] = -1.0;
      }

      start = 1;
   }
   else
   {
      start = prev_calculated - 1;
   }

   // Main calculation loop
   for(int i = start; i < rates_total && !IsStopped(); i++)
   {
      // 1. Calculate Heikin-Ashi typical close
      double ha_close = (open[i] + high[i] + low[i] + close[i]) / 4.0;

      // 2. Synergy APB Close: average of HA close and actual bar close
      double apb_close = (ha_close + close[i]) / 2.0;

      // 3. Synergy APB Open: average of previous APB Open and previous APB Close
      double apb_open = (ExtOBuffer[i - 1] + ExtCBuffer[i - 1]) / 2.0;

      // 4. Synergy APB High & Low
      double apb_high = MathMax(high[i], MathMax(apb_open, apb_close));
      double apb_low  = MathMin(low[i], MathMin(apb_open, apb_close));

      ExtOBuffer[i] = NormalizeDouble(apb_open,  _Digits);
      ExtHBuffer[i] = NormalizeDouble(apb_high,  _Digits);
      ExtLBuffer[i] = NormalizeDouble(apb_low,   _Digits);
      ExtCBuffer[i] = NormalizeDouble(apb_close, _Digits);

      // 5. Determine Trend and Candle Color
      if(apb_open < apb_close)
      {
         ExtColorBuffer[i] = 0.0; // Bullish (InpBullColor)
         ExtTrendBuffer[i] = 1.0;
      }
      else
      {
         ExtColorBuffer[i] = 1.0; // Bearish (InpBearColor)
         ExtTrendBuffer[i] = -1.0;
      }
   }

   // 6. Check for trend-change alert on completed closed bar
   if(rates_total >= 3 && (InpSendAlert || InpPlaySound || InpSendNotification || InpSendMail))
   {
      int closedBar = rates_total - 2;
      int prevBar   = closedBar - 1;
      int curTrend  = (int)ExtTrendBuffer[closedBar];
      int prvTrend  = (int)ExtTrendBuffer[prevBar];

      CheckAlert(time[closedBar], curTrend, prvTrend);
   }

   return(rates_total);
}
//+------------------------------------------------------------------+
