forked from LengKundee/NUNA
253 lines
11 KiB
MQL5
253 lines
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. |
|
||
|
|
//+------------------------------------------------------------------+
|