NUNA_FORK/Logs/Indicators/Downloads/supertrend.mq5
2026-01-06 05:44:21 +00:00

253 lines
No EOL
11 KiB
MQL5

//+------------------------------------------------------------------+
//| supertrend.mq5 |
//| Salman Soltaniyan |
//| https://www.mql5.com/en/users/salmansoltaniyan |
//+------------------------------------------------------------------+
#property copyright "Salman Soltaniyan"
#property link "https://www.mql5.com/en/users/salmansoltaniyan"
#property version "1.01"
#property indicator_chart_window
#property indicator_plots 2
#property indicator_buffers 3
#property indicator_type1 DRAW_COLOR_LINE
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_color1 clrGreen, clrRed // Green for uptrend, Red for downtrend
#property indicator_type2 DRAW_NONE
//+------------------------------------------------------------------+
//| DESCRIPTION: |
//| The SuperTrend indicator helps identify the current market trend |
//| and potential reversal points. It plots a line above or below |
//| the price based on ATR volatility and serves as dynamic |
//| support/resistance levels. |
//+------------------------------------------------------------------+
//--- Input Parameters ---
input int ATRPeriod = 22; // Period for ATR calculation
input double Multiplier = 3.0; // ATR multiplier for band calculation
input ENUM_APPLIED_PRICE SourcePrice = PRICE_MEDIAN; // Price source for calculations
input bool TakeWicksIntoAccount = true; // Include wicks in calculations
//--- Indicator Handles ---
int atrHandle; // Handle for ATR indicator
//--- Indicator Buffers ---
double SuperTrendBuffer[]; // Main SuperTrend line values
double SuperTrendColorBuffer[]; // Color index buffer (0 = Green, 1 = Red)
double SuperTrendDirectionBuffer[]; // Direction buffer (1 = Up, -1 = Down)
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Create ATR indicator handle
atrHandle = iATR(NULL, 0, ATRPeriod);
if(atrHandle == INVALID_HANDLE)
{
Print("Error creating ATR indicator. Error code: ", GetLastError());
return INIT_FAILED;
}
//--- Set indicator buffers mapping ---
SetIndexBuffer(0, SuperTrendBuffer, INDICATOR_DATA);
SetIndexBuffer(1, SuperTrendColorBuffer, INDICATOR_COLOR_INDEX);
SetIndexBuffer(2, SuperTrendDirectionBuffer, INDICATOR_DATA);
//--- Set the indicator labels ---
PlotIndexSetString(0, PLOT_LABEL, "SuperTrend");
PlotIndexSetString(2, PLOT_LABEL, "SuperTrend direction");
//--- Set array direction ---
ArraySetAsSeries(SuperTrendBuffer, false);
ArraySetAsSeries(SuperTrendDirectionBuffer, false);
ArraySetAsSeries(SuperTrendColorBuffer, false);
//--- Initialization is finished ---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Release ATR handle to free resources ---
IndicatorRelease(atrHandle);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(
const int rates_total, // Size of input time series
const int prev_calculated, // Number of handled bars at the previous call
const datetime& time[], // Time array
const double& open[], // Open array
const double& high[], // High array
const double& low[], // Low array
const double& close[], // Close array
const long& tick_volume[], // Tick Volume array
const long& volume[], // Real Volume array
const int& spread[] // Spread array
)
{
// Set all arrays as not series (default indexing)
ArraySetAsSeries(time, false);
ArraySetAsSeries(open, false);
ArraySetAsSeries(high, false);
ArraySetAsSeries(low, false);
ArraySetAsSeries(close, false);
// Buffer for ATR values
double atrBuffer[];
ArraySetAsSeries(atrBuffer, false);
// Variables for SuperTrend calculation
double srcPrice; // Source price based on input parameter
double highPrice; // High price (may consider wicks or not)
double lowPrice; // Low price (may consider wicks or not)
double atr; // Current ATR value
double longStop; // Support level (used during uptrend)
double longStopPrev; // Previous support level
double shortStop; // Resistance level (used during downtrend)
double shortStopPrev; // Previous resistance level
int supertrend_dir = 1; // Initial SuperTrend direction (1 = up, -1 = down)
// Calculate for each bar starting from prev_calculated
for(int i = prev_calculated; i < rates_total; i++)
{
//--- 1. Calculate source price based on selected price type ---
switch(SourcePrice)
{
case PRICE_CLOSE:
srcPrice = close[i];
break;
case PRICE_OPEN:
srcPrice = open[i];
break;
case PRICE_HIGH:
srcPrice = high[i];
break;
case PRICE_LOW:
srcPrice = low[i];
break;
case PRICE_MEDIAN:
srcPrice = (high[i] + low[i]) / 2.0;
break;
case PRICE_TYPICAL:
srcPrice = (high[i] + low[i] + close[i]) / 3.0;
break;
default: // PRICE_WEIGHTED
srcPrice = (high[i] + low[i] + close[i] + close[i]) / 4.0;
break;
}
//--- 2. Define high and low prices based on "TakeWicksIntoAccount" setting ---
highPrice = TakeWicksIntoAccount ? high[i] : close[i];
lowPrice = TakeWicksIntoAccount ? low[i] : close[i];
//--- 3. Get ATR value for the current bar ---
if(CopyBuffer(atrHandle, 0, rates_total - i - 1, 1, atrBuffer) == -1)
{
Print("Error copying ATR buffer. Error code: ", GetLastError());
// Continue calculation with potentially old ATR value
}
atr = atrBuffer[0];
//--- 4. Calculate long stop (support during uptrend) ---
longStop = srcPrice - Multiplier * atr;
longStopPrev = i > 0 ? SuperTrendBuffer[i - 1] : longStop;
// Adjust long stop based on previous values and current prices
if(longStop > 0)
{
// If it's a doji (all prices are equal), use previous stop value
if(open[i] == close[i] && open[i] == low[i] && open[i] == high[i])
longStop = longStopPrev;
else
// Trailing stop logic - only move stop up, never down during uptrend
longStop = (lowPrice > longStopPrev ? MathMax(longStop, longStopPrev) : longStop);
}
else
longStop = longStopPrev;
//--- 5. Calculate short stop (resistance during downtrend) ---
shortStop = srcPrice + Multiplier * atr;
shortStopPrev = i > 0 ? SuperTrendBuffer[i - 1] : shortStop;
// Adjust short stop based on previous values and current prices
if(shortStop > 0)
{
// If it's a doji (all prices are equal), use previous stop value
if(open[i] == close[i] && open[i] == low[i] && open[i] == high[i])
shortStop = shortStopPrev;
else
// Trailing stop logic - only move stop down, never up during downtrend
shortStop = (highPrice < shortStopPrev ? MathMin(shortStop, shortStopPrev) : shortStop);
}
else
shortStop = shortStopPrev;
//--- 6. Determine SuperTrend direction based on price crossing stops ---
if(i > 0)
{
// Get previous direction
supertrend_dir = (i > 1) ? (int)SuperTrendDirectionBuffer[i-1] : 1;
// Change from down to up if price breaks above the short stop
if(supertrend_dir == -1 && highPrice > shortStopPrev)
supertrend_dir = 1;
// Change from up to down if price breaks below the long stop
else if(supertrend_dir == 1 && lowPrice < longStopPrev)
supertrend_dir = -1;
}
//--- 7. Set SuperTrend values based on the direction ---
if(supertrend_dir == 1)
{
// Uptrend - use long stop as SuperTrend value
SuperTrendBuffer[i] = longStop;
SuperTrendDirectionBuffer[i] = 1;
SuperTrendColorBuffer[i] = 0; // Green color for uptrend
}
else
{
// Downtrend - use short stop as SuperTrend value
SuperTrendBuffer[i] = shortStop;
SuperTrendDirectionBuffer[i] = -1;
SuperTrendColorBuffer[i] = 1; // Red color for downtrend
}
}
//--- Return value of prev_calculated for next call
return(rates_total-1);
}
//+------------------------------------------------------------------+
//| MIT License |
//+------------------------------------------------------------------+
//| Copyright (c) 2024 Salman Soltaniyan |
//| |
//| Permission is hereby granted, free of charge, to any person |
//| obtaining a copy of this software and associated documentation |
//| files (the "Software"), to deal in the Software without |
//| restriction, including without limitation the rights to use, |
//| copy, modify, merge, publish, distribute, sublicense, and/or |
//| sell copies of the Software, and to permit persons to whom the |
//| Software is furnished to do so, subject to the following |
//| conditions: |
//| |
//| The above copyright notice and this permission notice shall be |
//| included in all copies or substantial portions of the Software. |
//| |
//| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
//| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
//| OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
//| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
//| HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
//| WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
//| FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
//| OTHER DEALINGS IN THE SOFTWARE. |
//+------------------------------------------------------------------+