2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | //| supertrendPro.mq5 |
|
| | | //| Copyright 2026, MetaQuotes Ltd. Developer: Gloria Diana |
|
| | | //| https://www.mql5.com/en/users/gloriadiana |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | #property copyright "Copyright 2026, MetaQuotes Ltd. Developer is Chacha Ian"
|
| | | #property link "https://www.mql5.com/en/users/chachaian"
|
| | | #property version "1.00"
|
| | |
|
| | | #property indicator_chart_window
|
| | | #property indicator_buffers 8
|
| | | #property indicator_plots 3
|
| | |
|
| | | #property indicator_type1 DRAW_COLOR_CANDLES
|
| | | #property indicator_type2 DRAW_LINE
|
| | | #property indicator_type3 DRAW_LINE
|
| | |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | //| Input parameters |
|
| | | //+------------------------------------------------------------------+
|
| | | input group "Supertrend Settings"
|
| | | input int InpATRPeriod = 10; // ATR calculation period
|
| | | input double InpATRMultiplier = 1.5; // ATR multiplier used to position the Supertrend bands
|
| | |
|
| | | input group "Notifications"
|
| | | input bool InpEnablePushNotifications = true; // Send mobile push notifications on confirmed trend changes
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Trend states exposed through Buffer 7 |
|
| | | //+------------------------------------------------------------------+
|
| | | const double TREND_BULLISH = 1.0; // Confirmed bullish trend
|
| | | const double TREND_BEARISH = 0.0; // Confirmed bearish trend
|
| | | const double TREND_NEUTRAL = -1.0; // Initial unresolved trend state
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Indicator theme colors |
|
| | | //+------------------------------------------------------------------+
|
| | | const color COLOR_BACKGROUND = clrWhiteSmoke; // Main chart background
|
| | | const color COLOR_FOREGROUND = clrBlack; // Chart text and scale labels
|
| | | const color COLOR_BULLISH = clrSeaGreen; // Bullish candles, bands, and Bid line
|
| | | const color COLOR_BEARISH = clrCrimson; // Bearish candles, bands, and Ask line
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Stores the chart appearance before Supertrend Pro changes it |
|
| | | //+------------------------------------------------------------------+
|
| | | struct SChartAppearance
|
| | | {
|
| | | long backgroundColor; // Original chart background color
|
| | | long foregroundColor; // Original chart text and scale color
|
| | | long showGrid; // Original grid visibility
|
| | | long chartMode; // Original chart drawing mode
|
| | | long chartUpColor; // Original bullish chart color
|
| | | long chartDownColor; // Original bearish chart color
|
| | | long candleBullColor; // Original bullish candle color
|
| | | long candleBearColor; // Original bearish candle color
|
| | | long bidColor; // Original Bid line color
|
| | | long askColor; // Original Ask line color
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Global variables |
|
| | | //+------------------------------------------------------------------+
|
| | | int g_atrHandle = INVALID_HANDLE; // Handle of the ATR indicator
|
| | | double g_atrValues[]; // Working array for copied ATR values
|
| | | SChartAppearance g_chartAppearance; // Chart appearance saved before applying the theme
|
| | | bool g_chartAppearanceSaved = false; // Confirms that restoration data is available
|
| | | datetime g_lastNotifiedBarTime = 0; // Open time of the last bar that generated a push notification
|
| | | datetime g_lastObservedLiveBarTime = 0; // Live bar tracked during the previous successful calculation
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Public indicator buffers |
|
| | | //+------------------------------------------------------------------+
|
| | | double g_candleOpen[]; // Buffer 0: trend-colored candle Open
|
| | | double g_candleHigh[]; // Buffer 1: trend-colored candle High
|
| | | double g_candleLow[]; // Buffer 2: trend-colored candle Low
|
| | | double g_candleClose[]; // Buffer 3: trend-colored candle Close
|
| | | double g_candleColor[]; // Buffer 4: candle trend color index
|
| | |
|
| | | double g_upperBand[]; // Buffer 5: upper/bearish Supertrend band
|
| | | double g_lowerBand[]; // Buffer 6: lower/bullish Supertrend band
|
| | |
|
| | | double g_trendState[]; // Buffer 7: 1.0 bullish, 0.0 bearish, -1.0 neutral
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Custom indicator initialization function |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
| | | int OnInit()
|
| | | {
|
2026-09-18 17:37:34 +03:00 | | | //--- Validate all user-configurable Supertrend parameters before
|
| | | //--- allocating or configuring indicator resources.
|
| | | if(!ValidateInputs())
|
| | | return(INIT_PARAMETERS_INCORRECT);
|
| | |
|
| | | //--- Reset notification tracking so every initialization establishes
|
| | | //--- a fresh live-bar baseline before any push alert can be generated.
|
| | | g_lastNotifiedBarTime=0;
|
| | | g_lastObservedLiveBarTime=0;
|
| | |
|
| | | //--- Bind the declared arrays to their permanent indicator buffer
|
| | | //--- indexes before configuring their visual plots.
|
| | | if(!ConfigureIndicatorBuffers())
|
| | | {
|
| | | Print("Failed to configure Supertrend Pro indicator buffers.");
|
| | | return(INIT_FAILED);
|
| | | }
|
| | |
|
| | | //--- Configure the candle and Supertrend plots that present the
|
| | | //--- calculated trend state on the chart.
|
| | | if(!ConfigureIndicatorPlots())
|
| | | {
|
| | | Print("Failed to configure Supertrend Pro indicator plots.");
|
| | | return(INIT_FAILED);
|
| | | }
|
| | |
|
| | | //--- Create the ATR handle used by the Supertrend calculation.
|
| | | g_atrHandle=iATR(_Symbol,PERIOD_CURRENT,InpATRPeriod);
|
| | | if(g_atrHandle==INVALID_HANDLE)
|
| | | {
|
| | | PrintFormat("Failed to create ATR handle. Error=%d",GetLastError());
|
| | | return(INIT_FAILED);
|
| | | }
|
| | |
|
| | | //--- Preserve the user's current chart appearance before applying
|
| | | //--- the mandatory Supertrend Pro visual theme.
|
| | | if(!SaveChartAppearance())
|
| | | {
|
| | | Print("Failed to save the current chart appearance.");
|
| | | return(INIT_FAILED);
|
| | | }
|
| | |
|
| | | //--- Apply the Supertrend Pro theme after the original appearance
|
| | | //--- has been stored successfully.
|
| | | if(!ApplyIndicatorTheme())
|
| | | {
|
| | | Print("Failed to apply the Supertrend Pro chart theme.");
|
| | |
|
| | | //--- Restore any chart properties changed before theme setup failed.
|
| | | RestoreChartAppearance();
|
| | | return(INIT_FAILED);
|
| | | }
|
| | |
|
2026-09-18 17:23:49 +03:00 | | | return(INIT_SUCCEEDED);
|
| | | }
|
2026-09-18 17:37:34 +03:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| 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[])
|
| | | {
|
| | | //--- Explicitly use chronological indexing throughout the indicator.
|
| | | ArraySetAsSeries(time,false);
|
| | | ArraySetAsSeries(open,false);
|
| | | ArraySetAsSeries(high,false);
|
| | | ArraySetAsSeries(low,false);
|
| | | ArraySetAsSeries(close,false);
|
| | | ArraySetAsSeries(tick_volume,false);
|
| | | ArraySetAsSeries(volume,false);
|
| | | ArraySetAsSeries(spread,false);
|
| | |
|
| | | //--- Wait until enough price history exists to calculate the ATR.
|
| | | if(rates_total<InpATRPeriod)
|
| | | return(prev_calculated);
|
| | |
|
| | | //--- Separate the forming bar from the latest confirmed bar.
|
| | | int liveIndex=rates_total-1;
|
| | | int lastClosedIndex=rates_total-2;
|
| | | int firstValidIndex=InpATRPeriod-1;
|
| | | int start=0;
|
| | |
|
| | | if(lastClosedIndex<firstValidIndex)
|
| | | return(prev_calculated);
|
| | |
|
| | | //--- A notification is eligible only when exactly one new bar has
|
| | | //--- opened since the previous successful calculation and the bar that
|
| | | //--- has just closed was previously tracked as the live bar.
|
| | | bool liveTrendChange=false;
|
| | |
|
| | | if(prev_calculated>0 &&
|
| | | rates_total==prev_calculated+1 &&
|
| | | g_lastObservedLiveBarTime!=0 &&
|
| | | time[lastClosedIndex]==g_lastObservedLiveBarTime)
|
| | | liveTrendChange=true;
|
| | |
|
| | | //--- Rebuild the complete Supertrend state when previous calculations
|
| | | //--- cannot be reused. Historical reconstruction never generates alerts.
|
| | | if(prev_calculated==0)
|
| | | {
|
| | | //--- Clear all public buffers before reconstructing history.
|
| | | ArrayInitialize(g_candleOpen,EMPTY_VALUE);
|
| | | ArrayInitialize(g_candleHigh,EMPTY_VALUE);
|
| | | ArrayInitialize(g_candleLow,EMPTY_VALUE);
|
| | | ArrayInitialize(g_candleClose,EMPTY_VALUE);
|
| | | ArrayInitialize(g_candleColor,0.0);
|
| | | ArrayInitialize(g_upperBand,EMPTY_VALUE);
|
| | | ArrayInitialize(g_lowerBand,EMPTY_VALUE);
|
| | | ArrayInitialize(g_trendState,EMPTY_VALUE);
|
| | |
|
| | | //--- ATR data is required from the first valid seed bar onward.
|
| | | start=firstValidIndex;
|
| | | }
|
| | | else
|
| | | {
|
| | | //--- Resume from the bar that was live during the previous
|
| | | //--- calculation and may now have become confirmed.
|
| | | start=prev_calculated-1;
|
| | |
|
| | | if(start<firstValidIndex+1)
|
| | | start=firstValidIndex+1;
|
| | | }
|
| | |
|
| | | //--- Copy ATR values only for confirmed bars that require calculation.
|
| | | if(start<=lastClosedIndex)
|
| | | {
|
| | | if(!GetATRValues(start,lastClosedIndex,rates_total))
|
| | | return(prev_calculated);
|
| | | }
|
| | |
|
| | | //--- Seed the neutral state only during a complete historical rebuild.
|
| | | if(prev_calculated==0)
|
| | | {
|
| | | double barMidpoint=(high[firstValidIndex]+low[firstValidIndex])/2.0;
|
| | |
|
| | | g_upperBand[firstValidIndex]=barMidpoint+
|
| | | g_atrValues[firstValidIndex]*InpATRMultiplier;
|
| | | g_lowerBand[firstValidIndex]=barMidpoint-
|
| | | g_atrValues[firstValidIndex]*InpATRMultiplier;
|
| | | g_trendState[firstValidIndex]=TREND_NEUTRAL;
|
| | |
|
| | | //--- The seed bar is complete, so subsequent bars can enter
|
| | | //--- the unified Supertrend state machine.
|
| | | start=firstValidIndex+1;
|
| | | }
|
| | |
|
| | | //--- Process every newly confirmed bar through the common Supertrend
|
| | | //--- state machine, including any bars recovered after inactivity.
|
| | | for(int i=start;i<=lastClosedIndex;i++)
|
| | | CalculateBar(i,open,high,low,close);
|
| | |
|
| | | //--- Notify only when the newest confirmed bar was genuinely observed
|
| | | //--- forming during the preceding successful indicator calculation.
|
| | | if(liveTrendChange)
|
| | | NotifyConfirmedTrendChange(lastClosedIndex,time);
|
| | |
|
| | | //--- Keep the forming bar outside the confirmed indicator state.
|
| | | g_candleOpen[liveIndex]=EMPTY_VALUE;
|
| | | g_candleHigh[liveIndex]=EMPTY_VALUE;
|
| | | g_candleLow[liveIndex]=EMPTY_VALUE;
|
| | | g_candleClose[liveIndex]=EMPTY_VALUE;
|
| | | g_candleColor[liveIndex]=0.0;
|
| | | g_upperBand[liveIndex]=EMPTY_VALUE;
|
| | | g_lowerBand[liveIndex]=EMPTY_VALUE;
|
| | | g_trendState[liveIndex]=EMPTY_VALUE;
|
| | |
|
| | | //--- Record the current live bar only after this calculation completes
|
| | | //--- successfully. It becomes eligible for notification after it closes.
|
| | | g_lastObservedLiveBarTime=time[liveIndex];
|
| | |
|
| | | return(rates_total);
|
| | | }
|
| | |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | //| Custom indicator deinitialization function |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
| | | void OnDeinit(const int reason)
|
| | | {
|
2026-09-18 17:37:34 +03:00 | | | //--- Restore the user's previous chart appearance before the
|
| | | //--- Supertrend Pro instance leaves the chart.
|
| | | if(g_chartAppearanceSaved)
|
| | | RestoreChartAppearance();
|
| | |
|
| | | //--- Release the ATR resource only when a valid handle was created.
|
| | | if(g_atrHandle!=INVALID_HANDLE)
|
| | | {
|
| | | IndicatorRelease(g_atrHandle);
|
| | | g_atrHandle=INVALID_HANDLE;
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Validates the Supertrend input parameters |
|
| | | //+------------------------------------------------------------------+
|
| | | bool ValidateInputs()
|
| | | {
|
| | | //--- The ATR period must contain at least one bar.
|
| | | if(InpATRPeriod < 1)
|
| | | {
|
| | | Print("Invalid ATR period. InpATRPeriod must be greater than or equal to 1.");
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- The ATR multiplier must be positive because zero or negative
|
| | | //--- values cannot produce valid Supertrend band distances.
|
| | | if(InpATRMultiplier <= 0.0)
|
| | | {
|
| | | Print("Invalid ATR multiplier. InpATRMultiplier must be greater than 0.");
|
| | | return(false);
|
| | | }
|
| | |
|
| | | return(true);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Binds all arrays to their permanent indicator buffer indexes |
|
| | | //+------------------------------------------------------------------+
|
| | | bool ConfigureIndicatorBuffers()
|
| | | {
|
| | | //--- Buffers 0-3 provide the OHLC values required by the
|
| | | //--- DRAW_COLOR_CANDLES plot used for trend-colored candles.
|
| | | if(!SetIndexBuffer(0,g_candleOpen,INDICATOR_DATA))
|
| | | {
|
| | | Print("Failed to bind candle Open buffer. Error: ",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!SetIndexBuffer(1,g_candleHigh,INDICATOR_DATA))
|
| | | {
|
| | | Print("Failed to bind candle High buffer. Error: ",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!SetIndexBuffer(2,g_candleLow,INDICATOR_DATA))
|
| | | {
|
| | | Print("Failed to bind candle Low buffer. Error: ",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!SetIndexBuffer(3,g_candleClose,INDICATOR_DATA))
|
| | | {
|
| | | Print("Failed to bind candle Close buffer. Error: ",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Buffer 4 stores the color index used to select the bullish
|
| | | //--- or bearish candle color for each calculated bar.
|
| | | if(!SetIndexBuffer(4,g_candleColor,INDICATOR_COLOR_INDEX))
|
| | | {
|
| | | Print("Failed to bind candle color buffer. Error: ",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Buffers 5 and 6 remain separate so bearish and bullish
|
| | | //--- Supertrend segments are never visually joined at reversals.
|
| | | if(!SetIndexBuffer(5,g_upperBand,INDICATOR_DATA))
|
| | | {
|
| | | Print("Failed to bind upper Supertrend band buffer. Error: ",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!SetIndexBuffer(6,g_lowerBand,INDICATOR_DATA))
|
| | | {
|
| | | Print("Failed to bind lower Supertrend band buffer. Error: ",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Buffer 7 exposes the numerical trend state for programmatic
|
| | | //--- access by Expert Advisors and other MQL5 applications.
|
| | | if(!SetIndexBuffer(7,g_trendState,INDICATOR_DATA))
|
| | | {
|
| | | Print("Failed to bind trend-state buffer. Error: ",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Explicitly keep every indicator buffer in chronological order.
|
| | | //--- Index 0 represents the oldest available bar and higher indexes
|
| | | //--- progress toward the current bar.
|
| | | if(!ArraySetAsSeries(g_candleOpen,false) ||
|
| | | !ArraySetAsSeries(g_candleHigh,false) ||
|
| | | !ArraySetAsSeries(g_candleLow,false) ||
|
| | | !ArraySetAsSeries(g_candleClose,false) ||
|
| | | !ArraySetAsSeries(g_candleColor,false) ||
|
| | | !ArraySetAsSeries(g_upperBand,false) ||
|
| | | !ArraySetAsSeries(g_lowerBand,false) ||
|
| | | !ArraySetAsSeries(g_trendState,false))
|
| | | {
|
| | | Print("Failed to configure chronological indexing for indicator buffers.");
|
| | | return(false);
|
| | | }
|
| | |
|
| | | return(true);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Applies the Supertrend Pro visual theme to the chart |
|
| | | //+------------------------------------------------------------------+
|
| | | bool ApplyIndicatorTheme()
|
| | | {
|
| | | //--- Apply the neutral chart background and foreground colors.
|
| | | if(!ChartSetInteger(0,CHART_COLOR_BACKGROUND,COLOR_BACKGROUND))
|
| | | {
|
| | | PrintFormat("Failed to set chart background color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_COLOR_FOREGROUND,COLOR_FOREGROUND))
|
| | | {
|
| | | PrintFormat("Failed to set chart foreground color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Remove the chart grid to keep the trend candles and Supertrend
|
| | | //--- bands visually dominant against the WhiteSmoke background.
|
| | | if(!ChartSetInteger(0,CHART_SHOW_GRID,false))
|
| | | {
|
| | | PrintFormat("Failed to configure chart grid visibility. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Use candle-chart mode throughout the Supertrend Pro presentation.
|
| | | if(!ChartSetInteger(0,CHART_MODE,CHART_CANDLES))
|
| | | {
|
| | | PrintFormat("Failed to set candle chart mode. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Apply the bullish theme to native bullish chart elements.
|
| | | if(!ChartSetInteger(0,CHART_COLOR_CHART_UP,COLOR_BULLISH))
|
| | | {
|
| | | PrintFormat("Failed to set bullish chart color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_COLOR_CANDLE_BULL,COLOR_BULLISH))
|
| | | {
|
| | | PrintFormat("Failed to set bullish candle color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Apply the bearish theme to native bearish chart elements.
|
| | | if(!ChartSetInteger(0,CHART_COLOR_CHART_DOWN,COLOR_BEARISH))
|
| | | {
|
| | | PrintFormat("Failed to set bearish chart color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_COLOR_CANDLE_BEAR,COLOR_BEARISH))
|
| | | {
|
| | | PrintFormat("Failed to set bearish candle color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Match Bid and Ask line colors to the directional theme.
|
| | | if(!ChartSetInteger(0,CHART_COLOR_BID,COLOR_BULLISH))
|
| | | {
|
| | | PrintFormat("Failed to set Bid line color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_COLOR_ASK,COLOR_BEARISH))
|
| | | {
|
| | | PrintFormat("Failed to set Ask line color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Refresh the chart after applying the complete visual theme.
|
| | | ChartRedraw(0);
|
| | |
|
| | | return(true);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Saves the chart appearance before applying the indicator theme |
|
| | | //+------------------------------------------------------------------+
|
| | | bool SaveChartAppearance()
|
| | | {
|
| | | //--- Read the chart colors that Supertrend Pro will temporarily replace.
|
| | | if(!ChartGetInteger(0,CHART_COLOR_BACKGROUND,0,g_chartAppearance.backgroundColor))
|
| | | {
|
| | | PrintFormat("Failed to read chart background color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartGetInteger(0,CHART_COLOR_FOREGROUND,0,g_chartAppearance.foregroundColor))
|
| | | {
|
| | | PrintFormat("Failed to read chart foreground color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartGetInteger(0,CHART_COLOR_CHART_UP,0,g_chartAppearance.chartUpColor))
|
| | | {
|
| | | PrintFormat("Failed to read bullish chart color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartGetInteger(0,CHART_COLOR_CHART_DOWN,0,g_chartAppearance.chartDownColor))
|
| | | {
|
| | | PrintFormat("Failed to read bearish chart color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartGetInteger(0,CHART_COLOR_CANDLE_BULL,0,g_chartAppearance.candleBullColor))
|
| | | {
|
| | | PrintFormat("Failed to read bullish candle color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartGetInteger(0,CHART_COLOR_CANDLE_BEAR,0,g_chartAppearance.candleBearColor))
|
| | | {
|
| | | PrintFormat("Failed to read bearish candle color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartGetInteger(0,CHART_COLOR_BID,0,g_chartAppearance.bidColor))
|
| | | {
|
| | | PrintFormat("Failed to read Bid line color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartGetInteger(0,CHART_COLOR_ASK,0,g_chartAppearance.askColor))
|
| | | {
|
| | | PrintFormat("Failed to read Ask line color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Preserve the non-color chart properties changed by the theme.
|
| | | if(!ChartGetInteger(0,CHART_SHOW_GRID,0,g_chartAppearance.showGrid))
|
| | | {
|
| | | PrintFormat("Failed to read chart grid visibility. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ChartGetInteger(0,CHART_MODE,0,g_chartAppearance.chartMode))
|
| | | {
|
| | | PrintFormat("Failed to read chart mode. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- The complete appearance snapshot is now safe to restore later.
|
| | | g_chartAppearanceSaved=true;
|
| | |
|
| | | return(true);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Restores the chart appearance saved before theme application |
|
| | | //+------------------------------------------------------------------+
|
| | | bool RestoreChartAppearance()
|
| | | {
|
| | | bool restored=true;
|
| | |
|
| | | //--- Restore the original background and foreground colors.
|
| | | if(!ChartSetInteger(0,CHART_COLOR_BACKGROUND,g_chartAppearance.backgroundColor))
|
| | | {
|
| | | PrintFormat("Failed to restore chart background color. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_COLOR_FOREGROUND,g_chartAppearance.foregroundColor))
|
| | | {
|
| | | PrintFormat("Failed to restore chart foreground color. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | //--- Restore the original grid visibility and chart drawing mode.
|
| | | if(!ChartSetInteger(0,CHART_SHOW_GRID,g_chartAppearance.showGrid))
|
| | | {
|
| | | PrintFormat("Failed to restore chart grid visibility. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_MODE,g_chartAppearance.chartMode))
|
| | | {
|
| | | PrintFormat("Failed to restore chart mode. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | //--- Restore the original bullish chart and candle colors.
|
| | | if(!ChartSetInteger(0,CHART_COLOR_CHART_UP,g_chartAppearance.chartUpColor))
|
| | | {
|
| | | PrintFormat("Failed to restore bullish chart color. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_COLOR_CANDLE_BULL,g_chartAppearance.candleBullColor))
|
| | | {
|
| | | PrintFormat("Failed to restore bullish candle color. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | //--- Restore the original bearish chart and candle colors.
|
| | | if(!ChartSetInteger(0,CHART_COLOR_CHART_DOWN,g_chartAppearance.chartDownColor))
|
| | | {
|
| | | PrintFormat("Failed to restore bearish chart color. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_COLOR_CANDLE_BEAR,g_chartAppearance.candleBearColor))
|
| | | {
|
| | | PrintFormat("Failed to restore bearish candle color. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | //--- Restore the original Bid and Ask line colors.
|
| | | if(!ChartSetInteger(0,CHART_COLOR_BID,g_chartAppearance.bidColor))
|
| | | {
|
| | | PrintFormat("Failed to restore Bid line color. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | if(!ChartSetInteger(0,CHART_COLOR_ASK,g_chartAppearance.askColor))
|
| | | {
|
| | | PrintFormat("Failed to restore Ask line color. Error=%d",GetLastError());
|
| | | restored=false;
|
| | | }
|
| | |
|
| | | //--- Refresh the chart after restoring all saved appearance properties.
|
| | | ChartRedraw(0);
|
| | |
|
| | | //--- Clear the saved-state flag only after a successful restoration.
|
| | | if(restored)
|
| | | g_chartAppearanceSaved=false;
|
| | |
|
| | | return(restored);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Configures the visual plots used by Supertrend Pro |
|
| | | //+------------------------------------------------------------------+
|
| | | bool ConfigureIndicatorPlots()
|
| | | {
|
| | | //--- Configure Plot 0 as two-color candles. Color index 0 represents
|
| | | //--- bearish candles and color index 1 represents bullish candles.
|
| | | if(!PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_COLOR_CANDLES))
|
| | | {
|
| | | PrintFormat("Failed to set the candle plot type. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,2))
|
| | | {
|
| | | PrintFormat("Failed to configure candle color indexes. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,COLOR_BEARISH))
|
| | | {
|
| | | PrintFormat("Failed to set bearish candle color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,COLOR_BULLISH))
|
| | | {
|
| | | PrintFormat("Failed to set bullish candle color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE))
|
| | | {
|
| | | PrintFormat("Failed to set the candle plot empty value. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetString(0,PLOT_LABEL,
|
| | | "Supertrend Open;Supertrend High;Supertrend Low;Supertrend Close"))
|
| | | {
|
| | | PrintFormat("Failed to set the candle plot label. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Configure Plot 1 as the bearish upper Supertrend band.
|
| | | if(!PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_LINE))
|
| | | {
|
| | | PrintFormat("Failed to set upper Supertrend plot type. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(1,PLOT_LINE_STYLE,STYLE_SOLID))
|
| | | {
|
| | | PrintFormat("Failed to set upper Supertrend line style. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(1,PLOT_LINE_WIDTH,2))
|
| | | {
|
| | | PrintFormat("Failed to set upper Supertrend line width. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(1,PLOT_LINE_COLOR,COLOR_BEARISH))
|
| | | {
|
| | | PrintFormat("Failed to set upper Supertrend line color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,EMPTY_VALUE))
|
| | | {
|
| | | PrintFormat("Failed to set upper Supertrend empty value. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetString(1,PLOT_LABEL,"Bearish Supertrend"))
|
| | | {
|
| | | PrintFormat("Failed to set upper Supertrend plot label. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Configure Plot 2 as the bullish lower Supertrend band.
|
| | | if(!PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_LINE))
|
| | | {
|
| | | PrintFormat("Failed to set lower Supertrend plot type. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(2,PLOT_LINE_STYLE,STYLE_SOLID))
|
| | | {
|
| | | PrintFormat("Failed to set lower Supertrend line style. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(2,PLOT_LINE_WIDTH,2))
|
| | | {
|
| | | PrintFormat("Failed to set lower Supertrend line width. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetInteger(2,PLOT_LINE_COLOR,COLOR_BULLISH))
|
| | | {
|
| | | PrintFormat("Failed to set lower Supertrend line color. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,EMPTY_VALUE))
|
| | | {
|
| | | PrintFormat("Failed to set lower Supertrend empty value. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!PlotIndexSetString(2,PLOT_LABEL,"Bullish Supertrend"))
|
| | | {
|
| | | PrintFormat("Failed to set lower Supertrend plot label. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Prevent plotting before enough bars exist to produce the first
|
| | | //--- ATR value required by the Supertrend calculation.
|
| | | int drawBegin=InpATRPeriod-1;
|
| | |
|
| | | if(!PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,drawBegin) ||
|
| | | !PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,drawBegin) ||
|
| | | !PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,drawBegin))
|
| | | {
|
| | | PrintFormat("Failed to configure the plot starting position. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- Configure the indicator identity and displayed price precision.
|
| | | if(!IndicatorSetString(INDICATOR_SHORTNAME,"Supertrend Pro"))
|
| | | {
|
| | | PrintFormat("Failed to set indicator short name. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!IndicatorSetInteger(INDICATOR_DIGITS,_Digits))
|
| | | {
|
| | | PrintFormat("Failed to set indicator precision. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | return(true);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Copies ATR values required for the current calculation range |
|
| | | //+------------------------------------------------------------------+
|
| | | bool GetATRValues(const int startIndex,
|
| | | const int lastClosedIndex,
|
| | | const int ratesTotal)
|
| | | {
|
| | | //--- Determine how many confirmed ATR values are required.
|
| | | int valuesRequired=lastClosedIndex-startIndex+1;
|
| | |
|
| | | if(valuesRequired<=0)
|
| | | return(true);
|
| | |
|
| | | //--- Confirm that the ATR handle has calculated enough recent values
|
| | | //--- to cover the requested closed-bar range.
|
| | | int calculatedBars=BarsCalculated(g_atrHandle);
|
| | | if(calculatedBars<valuesRequired+1)
|
| | | return(false);
|
| | |
|
| | | //--- Keep the persistent ATR array aligned with the complete price
|
| | | //--- history so each ATR value uses the same chronological bar index.
|
| | | if(ArraySize(g_atrValues)!=ratesTotal)
|
| | | {
|
| | | if(ArrayResize(g_atrValues,ratesTotal)!=ratesTotal)
|
| | | {
|
| | | PrintFormat("Failed to resize the ATR working array to %d elements.",
|
| | | ratesTotal);
|
| | | return(false);
|
| | | }
|
| | |
|
| | | if(!ArraySetAsSeries(g_atrValues,false))
|
| | | {
|
| | | Print("Failed to configure chronological indexing for ATR values.");
|
| | | return(false);
|
| | | }
|
| | | }
|
| | |
|
| | | //--- Create a temporary array for only the recent ATR values required
|
| | | //--- by this calculation pass.
|
| | | double atrValues[];
|
| | |
|
| | | if(ArrayResize(atrValues,valuesRequired)!=valuesRequired)
|
| | | {
|
| | | PrintFormat("Failed to resize the temporary ATR array to %d elements.",
|
| | | valuesRequired);
|
| | | return(false);
|
| | | }
|
| | |
|
| | | ArraySetAsSeries(atrValues,false);
|
| | |
|
| | | //--- Start from shift 1 because the current live bar is intentionally
|
| | | //--- excluded from confirmed Supertrend calculations.
|
| | | ResetLastError();
|
| | |
|
| | | int copiedValues=CopyBuffer(g_atrHandle,0,1,valuesRequired,atrValues);
|
| | | if(copiedValues<0)
|
| | | {
|
| | | PrintFormat("Failed to copy ATR values. Error=%d",GetLastError());
|
| | | return(false);
|
| | | }
|
| | |
|
| | | //--- A partial copy means the requested ATR range is not fully ready.
|
| | | if(copiedValues!=valuesRequired)
|
| | | return(false);
|
| | |
|
| | | //--- Transfer the copied ATR segment into its matching chronological
|
| | | //--- positions in the persistent ATR working array.
|
| | | for(int i=0;i<valuesRequired;i++)
|
| | | g_atrValues[startIndex+i]=atrValues[i];
|
| | |
|
| | | return(true);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Calculates one bar according to the previous Supertrend state |
|
| | | //+------------------------------------------------------------------+
|
| | | void CalculateBar(const int index,
|
| | | const double &open[],
|
| | | const double &high[],
|
| | | const double &low[],
|
| | | const double &close[])
|
| | | {
|
| | | int previousIndex=index-1;
|
| | |
|
| | | //--- Continue resolving the initial neutral state until price
|
| | | //--- establishes the first confirmed directional trend.
|
| | | if(g_trendState[previousIndex]==TREND_NEUTRAL)
|
| | | {
|
| | | CalculateNeutralState(index,high,low,close);
|
| | |
|
| | | //--- Color the bar only after the neutral state resolves into
|
| | | //--- a confirmed bullish or bearish trend.
|
| | | if(g_trendState[index]==TREND_BULLISH)
|
| | | SetBullishCandle(index,open,high,low,close);
|
| | | else
|
| | | if(g_trendState[index]==TREND_BEARISH)
|
| | | SetBearishCandle(index,open,high,low,close);
|
| | |
|
| | | return;
|
| | | }
|
| | |
|
| | | //--- Apply bullish continuation or bearish reversal logic when the
|
| | | //--- preceding confirmed bar belongs to an established bullish trend.
|
| | | if(g_trendState[previousIndex]==TREND_BULLISH)
|
| | | {
|
| | | CalculateBullishState(index,open,high,low,close);
|
| | | return;
|
| | | }
|
| | |
|
| | | //--- Apply bearish continuation or bullish reversal logic when the
|
| | | //--- preceding confirmed bar belongs to an established bearish trend.
|
| | | if(g_trendState[previousIndex]==TREND_BEARISH)
|
| | | CalculateBearishState(index,open,high,low,close);
|
2026-09-18 17:23:49 +03:00 | | | }
|
2026-09-18 17:37:34 +03:00 | | |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | //| Processes one bar while the Supertrend state remains neutral |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | bool CalculateNeutralState(const int index,
|
| | | const double &high[],
|
| | | const double &low[],
|
| | | const double &close[])
|
2026-09-18 17:23:49 +03:00 | | | {
|
2026-09-18 17:37:34 +03:00 | | | //--- Calculate the raw ATR-based bands for the current closed bar.
|
| | | double barMidpoint=(high[index]+low[index])/2.0;
|
| | | double upperBandValue=barMidpoint+
|
| | | g_atrValues[index]*InpATRMultiplier;
|
| | | double lowerBandValue=barMidpoint-
|
| | | g_atrValues[index]*InpATRMultiplier;
|
| | |
|
| | | int previousIndex=index-1;
|
| | |
|
| | | //--- Establish the first bullish trend when price closes above the
|
| | | //--- previous neutral upper band.
|
| | | if(close[index]>g_upperBand[previousIndex])
|
| | | {
|
| | | g_trendState[index]=TREND_BULLISH;
|
| | | g_upperBand[index]=EMPTY_VALUE;
|
| | | g_lowerBand[index]=lowerBandValue;
|
| | |
|
| | | return(true);
|
| | | }
|
| | |
|
| | | //--- Establish the first bearish trend when price closes below the
|
| | | //--- previous neutral lower band.
|
| | | if(close[index]<g_lowerBand[previousIndex])
|
| | | {
|
| | | g_trendState[index]=TREND_BEARISH;
|
| | | g_lowerBand[index]=EMPTY_VALUE;
|
| | | g_upperBand[index]=upperBandValue;
|
| | |
|
| | | return(true);
|
| | | }
|
| | |
|
| | | //--- Keep the state neutral while price remains between both bands.
|
| | | //--- The upper band may only move downward during this stage.
|
| | | if(upperBandValue<g_upperBand[previousIndex])
|
| | | g_upperBand[index]=upperBandValue;
|
| | | else
|
| | | g_upperBand[index]=g_upperBand[previousIndex];
|
| | |
|
| | | //--- The lower band may only move upward while the initial trend
|
| | | //--- remains unresolved.
|
| | | if(lowerBandValue>g_lowerBand[previousIndex])
|
| | | g_lowerBand[index]=lowerBandValue;
|
| | | else
|
| | | g_lowerBand[index]=g_lowerBand[previousIndex];
|
| | |
|
| | | //--- Preserve the neutral state until either boundary is breached.
|
| | | g_trendState[index]=TREND_NEUTRAL;
|
| | |
|
| | | return(false);
|
2026-09-18 17:23:49 +03:00 | | | }
|
2026-09-18 17:37:34 +03:00 | | |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | //| Processes one bar when the previous trend state is bullish |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | void CalculateBullishState(const int index,
|
| | | const double &open[],
|
| | | const double &high[],
|
| | | const double &low[],
|
| | | const double &close[])
|
2026-09-18 17:23:49 +03:00 | | | {
|
2026-09-18 17:37:34 +03:00 | | | //--- Calculate the raw ATR-based bands for the current confirmed bar.
|
| | | double barMidpoint=(high[index]+low[index])/2.0;
|
| | | double upperBandValue=barMidpoint+
|
| | | g_atrValues[index]*InpATRMultiplier;
|
| | | double lowerBandValue=barMidpoint-
|
| | | g_atrValues[index]*InpATRMultiplier;
|
| | |
|
| | | int previousIndex=index-1;
|
| | |
|
| | | //--- Reverse to bearish when price closes below the previous active
|
| | | //--- lower band. The upper band becomes active from this bar onward.
|
| | | if(close[index]<g_lowerBand[previousIndex])
|
| | | {
|
| | | g_trendState[index]=TREND_BEARISH;
|
| | | g_lowerBand[index]=EMPTY_VALUE;
|
| | | g_upperBand[index]=upperBandValue;
|
| | |
|
| | | //--- Recolor the reversal bar immediately as part of the new
|
| | | //--- confirmed bearish trend.
|
| | | SetBearishCandle(index,open,high,low,close);
|
| | | return;
|
| | | }
|
| | |
|
| | | //--- Preserve the bullish trend while allowing the lower band to
|
| | | //--- tighten upward without moving back down.
|
| | | if(lowerBandValue>g_lowerBand[previousIndex])
|
| | | g_lowerBand[index]=lowerBandValue;
|
| | | else
|
| | | g_lowerBand[index]=g_lowerBand[previousIndex];
|
| | |
|
| | | //--- Keep the bearish upper band inactive while bullish control remains.
|
| | | g_upperBand[index]=EMPTY_VALUE;
|
| | | g_trendState[index]=TREND_BULLISH;
|
| | |
|
| | | //--- Draw the confirmed bar using the bullish candle color.
|
| | | SetBullishCandle(index,open,high,low,close);
|
2026-09-18 17:23:49 +03:00 | | | }
|
2026-09-18 17:37:34 +03:00 | | |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | //| Processes one bar when the previous trend state is bearish |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | void CalculateBearishState(const int index,
|
| | | const double &open[],
|
| | | const double &high[],
|
| | | const double &low[],
|
| | | const double &close[])
|
2026-09-18 17:23:49 +03:00 | | | {
|
2026-09-18 17:37:34 +03:00 | | | //--- Calculate the raw ATR-based bands for the current confirmed bar.
|
| | | double barMidpoint=(high[index]+low[index])/2.0;
|
| | | double upperBandValue=barMidpoint+
|
| | | g_atrValues[index]*InpATRMultiplier;
|
| | | double lowerBandValue=barMidpoint-
|
| | | g_atrValues[index]*InpATRMultiplier;
|
| | |
|
| | | int previousIndex=index-1;
|
| | |
|
| | | //--- Reverse to bullish when price closes above the previous active
|
| | | //--- upper band. The lower band becomes active from this bar onward.
|
| | | if(close[index]>g_upperBand[previousIndex])
|
| | | {
|
| | | g_trendState[index]=TREND_BULLISH;
|
| | | g_upperBand[index]=EMPTY_VALUE;
|
| | | g_lowerBand[index]=lowerBandValue;
|
| | |
|
| | | //--- Recolor the reversal bar immediately as part of the new
|
| | | //--- confirmed bullish trend.
|
| | | SetBullishCandle(index,open,high,low,close);
|
| | | return;
|
| | | }
|
| | |
|
| | | //--- Preserve the bearish trend while allowing the upper band to
|
| | | //--- tighten downward without moving back upward.
|
| | | if(upperBandValue<g_upperBand[previousIndex])
|
| | | g_upperBand[index]=upperBandValue;
|
| | | else
|
| | | g_upperBand[index]=g_upperBand[previousIndex];
|
| | |
|
| | | //--- Keep the bullish lower band inactive while bearish control remains.
|
| | | g_lowerBand[index]=EMPTY_VALUE;
|
| | | g_trendState[index]=TREND_BEARISH;
|
| | |
|
| | | //--- Draw the confirmed bar using the bearish candle color.
|
| | | SetBearishCandle(index,open,high,low,close);
|
2026-09-18 17:23:49 +03:00 | | | }
|
2026-09-18 17:37:34 +03:00 | | |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | //| Populates the candle buffers for a confirmed bullish bar |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | void SetBullishCandle(const int index,
|
| | | const double &open[],
|
| | | const double &high[],
|
| | | const double &low[],
|
| | | const double &close[])
|
2026-09-18 17:23:49 +03:00 | | | {
|
2026-09-18 17:37:34 +03:00 | | | //--- Copy the original OHLC values so the indicator can redraw the
|
| | | //--- completed candle using the bullish color index.
|
| | | g_candleOpen[index]=open[index];
|
| | | g_candleHigh[index]=high[index];
|
| | | g_candleLow[index]=low[index];
|
| | | g_candleClose[index]=close[index];
|
| | | g_candleColor[index]=1.0;
|
2026-09-18 17:23:49 +03:00 | | | }
|
2026-09-18 17:37:34 +03:00 | | |
|
2026-09-18 17:23:49 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-18 17:37:34 +03:00 | | | //| Populates the candle buffers for a confirmed bearish bar |
|
| | | //+------------------------------------------------------------------+
|
| | | void SetBearishCandle(const int index,
|
| | | const double &open[],
|
| | | const double &high[],
|
| | | const double &low[],
|
| | | const double &close[])
|
| | | {
|
| | | //--- Copy the original OHLC values so the indicator can redraw the
|
| | | //--- completed candle using the bearish color index.
|
| | | g_candleOpen[index]=open[index];
|
| | | g_candleHigh[index]=high[index];
|
| | | g_candleLow[index]=low[index];
|
| | | g_candleClose[index]=close[index];
|
| | | g_candleColor[index]=0.0;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Sends a push notification for a confirmed directional reversal |
|
| | | //+------------------------------------------------------------------+
|
| | | void NotifyConfirmedTrendChange(const int index,
|
| | | const datetime &time[])
|
| | | {
|
| | | if(!InpEnablePushNotifications)
|
| | | return;
|
| | |
|
| | | //--- A previous confirmed bar is required to determine whether the
|
| | | //--- current state represents an actual trend change.
|
| | | if(index<1)
|
| | | return;
|
| | |
|
| | | int previousIndex=index-1;
|
| | |
|
| | | //--- Ignore the first directional trend established from the neutral
|
| | | //--- startup state because it is not a bullish-to-bearish reversal.
|
| | | if(g_trendState[previousIndex]==TREND_NEUTRAL)
|
| | | return;
|
| | |
|
| | | //--- Ignore bars whose directional state did not change.
|
| | | if(g_trendState[index]==g_trendState[previousIndex])
|
| | | return;
|
| | |
|
| | | //--- Only confirmed bullish and bearish states are valid notification
|
| | | //--- targets.
|
| | | if(g_trendState[index]!=TREND_BULLISH &&
|
| | | g_trendState[index]!=TREND_BEARISH)
|
| | | return;
|
| | |
|
| | | //--- Prevent recalculation of the same confirmed bar from generating
|
| | | //--- another push notification.
|
| | | if(time[index]==g_lastNotifiedBarTime)
|
| | | return;
|
| | |
|
| | | //--- Build a concise message containing the symbol, timeframe, and
|
| | | //--- newly confirmed Supertrend direction.
|
| | | string trendText=(g_trendState[index]==TREND_BULLISH) ?
|
| | | "BULLISH" :
|
| | | "BEARISH";
|
| | |
|
| | | string message=StringFormat("Supertrend | %s %s | Trend changed to %s",
|
| | | _Symbol,
|
| | | EnumToString((ENUM_TIMEFRAMES)_Period),
|
| | | trendText);
|
| | |
|
| | | //--- Send the notification and record the bar only after MetaTrader
|
| | | //--- confirms that the message was accepted for delivery.
|
| | | ResetLastError();
|
| | |
|
| | | if(!SendNotification(message))
|
| | | {
|
| | | PrintFormat("Failed to send Supertrend push notification. Error=%d",
|
| | | GetLastError());
|
| | | return;
|
| | | }
|
| | |
|
| | | g_lastNotifiedBarTime=time[index];
|
| | | }
|
| | | //+------------------------------------------------------------------+
|