/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Indicator // --------------------------------------------- // Name: X121_XCHE // Description: Chandelier Exit Indicator ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm X121_XCHE Indicator" #property strict // // START Constants ... // // #define ShortName "X121_XCHE" // // END Constants ... // // // START Inputs ... // // input group "Market"; input int length = 35; // Length input int loopback = 26; // Loopback input double multiplier1 = 3.0; // 1st Multiplier input double multiplier2 = 3.5; // 2nd Multiplier // input group "Calculation"; input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Zone Applied to input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Zone Applied to // input group "Presentation"; input bool showLongExit1Line = true; // Show 1st Long Exit input bool showShortExit1Line = true; // Show 1st Short Exit input bool showLongExit2Line = true; // Show 2st Long Exit input bool showShortExit2Line = true; // Show 2st Short Exit // // END Inputs ... // // // START Includes and Imports ... // // // Includes Common Library ... #include "../Libraries/x-saherelm.common.lib.mq5" // // END Includes and Imports ... // // // START Buffers ... // // #property indicator_chart_window // #property indicator_buffers 8 #property indicator_plots 8 // // Long Exit 1 ... #define longExit1BufferIndex 0 double longExit1Buffer[]; // #property indicator_label1 "X121_XCHE LE 1" #property indicator_type1 DRAW_LINE #property indicator_color1 clrLime #property indicator_style1 STYLE_DOT // // Short Exit 1 ... #define shortExit1BufferIndex 1 double shortExit1Buffer[]; // #property indicator_label2 "X121_XCHE SE 1" #property indicator_type2 DRAW_LINE #property indicator_style2 STYLE_DOT #property indicator_color2 clrRed // // Long Exit 2 ... #define longExit2BufferIndex 2 double longExit2Buffer[]; // #property indicator_label3 "X121_XCHE LE 2" #property indicator_type3 DRAW_LINE #property indicator_style2 STYLE_DOT #property indicator_color3 clrAqua // // Short Exit 2 ... #define shortExit2BufferIndex 3 double shortExit2Buffer[]; // #property indicator_label4 "X121_XCHE SE 2" #property indicator_type4 DRAW_LINE #property indicator_style2 STYLE_DOT #property indicator_color4 clrMagenta // // START Arrows ... // // Long Exit 1 Start ... #define longExit1StartBufferIndex 4 double longExit1StartBuffer[]; // #property indicator_label5 "X121_XCHE LES 1" #property indicator_type5 DRAW_ARROW #property indicator_color5 clrLime // // Short Exit 1 Start ... #define shortExit1StartBufferIndex 5 double shortExit1StartBuffer[]; // #property indicator_label6 "X121_XCHE SES 1" #property indicator_type6 DRAW_ARROW #property indicator_color6 clrRed // // Long Exit 2 Start ... #define longExit2StartBufferIndex 6 double longExit2StartBuffer[]; // #property indicator_label7 "X121_XCHE LES 2" #property indicator_type7 DRAW_ARROW #property indicator_color7 clrAqua // // Short Exit 2 Start ... #define shortExit2StartBufferIndex 7 double shortExit2StartBuffer[]; // #property indicator_label8 "X121_XCHE SES 2" #property indicator_type8 DRAW_ARROW #property indicator_color8 clrMagenta // // END Buffers ... // // // START Global Definitions: Variables, Properties and etc ... // // int maxLength; // // Working Array ... double work[][6]; #define hi1Idx 0 #define lo1Idx 1 #define hi2Idx 2 #define lo2Idx 3 #define trend1Idx 4 #define trend2Idx 5 // // END Global Definitions: Variables, Properties and etc ... // // // START Event Handlers ... // // // Initialization ... int OnInit() { // // Validate Inputs ... if (!ValidateInputs()) { return INIT_PARAMETERS_INCORRECT; } // // because in some cases we may have more than one input for // calculation and we must prevent any calculation // untill we pass the biggest input length, here we get max Input length // and then wait until pass it ... maxLength = ExtractMaxLengthOfInputs(); // // Define Index Buffers ... DefineBuffers(); // // Set Indicator ShortName ... SetIndicatorName(); // // Init Succeed ... return INIT_SUCCEEDED; } // // DeInitialization ... void OnDeinit(const int reason) { // // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function // REASON_REMOVE 1 Program removed from a chart // REASON_RECOMPILE 2 Program recompiled // REASON_CHARTCHANGE 3 A symbol or a chart mPeriod is changed // REASON_CHARTCLOSE 4 Chart closed // REASON_PARAMETERS 5 Inputs changed by a user // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings // REASON_TEMPLATE 7 Another chart template applied // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value // REASON_CLOSE 9 Terminal closed } // // Calculating what we want ... int OnCalculate( // // total Candles on chart ... const int rates_total, // // total calculated Candles on charts ... const int prev_calculated, // // history of Candles Open Time ... const datetime &time[], // // history of Candles Open Price ... const double &open[], // // history of Candles High Price ... const double &high[], // // history of Candles Low Price ... const double &low[], // // history of Candles Close Price ... const double &close[], // // history of Tick Volumes on Candle ... const long &tick_volume[], // // history of Trade Volumes ... const long &volume[], // // history of Candles Spread Price ... const int &spread[]) { // if (Bars(_Symbol, _Period) < rates_total) { return (prev_calculated); } // if (ArrayRange(work, 0) != rates_total) { ArrayResize(work, rates_total); } // // this counts Available Bars ... int limit; // limit = prev_calculated - 1; if (limit < 0) { limit = 0; } // // Main Loop ... for (int i = limit; i < rates_total && !IsStopped(); i++) { CalculateBuffers( i, prev_calculated, rates_total, // open, high, low, close); } // return rates_total; } // // END Event Handlers ... // // // START Functions ... // // // Validate Input Args for Initialization ... bool ValidateInputs() { // bool result = true; // result = length >= 9 && loopback >= 0; // return result; } // // Retrieve all Exists Input Max Length ... // use for Start Of Drawing ... int ExtractMaxLengthOfInputs() { // int result = 0; // result = MathMax(length, loopback); // return result; } // // Set Indicator Short Name and also we can define Buffers Labels ... void SetIndicatorName() { IndicatorSetString(INDICATOR_SHORTNAME, ShortName); } // // Define Indexes and Styles ... void DefineBuffers() { // uint arrowCode = 159; // // LEVEL 1 ... // // Long Exit 1 ... // // Draw Type ... ENUM_DRAW_TYPE longExit1DrawType = showLongExit1Line ? DRAW_LINE : DRAW_NONE; ENUM_DRAW_TYPE longExit1StartDrawType = showLongExit1Line ? DRAW_ARROW : DRAW_NONE; // // Buffer ... SetIndexBuffer(longExit1BufferIndex, longExit1Buffer, INDICATOR_DATA); PlotIndexSetInteger(longExit1BufferIndex, PLOT_SHOW_DATA, showLongExit1Line); PlotIndexSetInteger(longExit1BufferIndex, PLOT_DRAW_TYPE, longExit1DrawType); // // Start Buffer ... SetIndexBuffer(longExit1StartBufferIndex, longExit1StartBuffer, INDICATOR_DATA); PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_ARROW, arrowCode); PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_SHOW_DATA, false); PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_DRAW_TYPE, longExit1StartDrawType); // // Short Exit 1 ... // // Draw Type ... ENUM_DRAW_TYPE shortExit1DrawType = showShortExit1Line ? DRAW_LINE : DRAW_NONE; ENUM_DRAW_TYPE shortExit1StartDrawType = showShortExit1Line ? DRAW_ARROW : DRAW_NONE; // // Buffer ... SetIndexBuffer(shortExit1BufferIndex, shortExit1Buffer, INDICATOR_DATA); PlotIndexSetInteger(shortExit1BufferIndex, PLOT_SHOW_DATA, showShortExit1Line); PlotIndexSetInteger(shortExit1BufferIndex, PLOT_DRAW_TYPE, shortExit1DrawType); // // Start Buffer ... SetIndexBuffer(shortExit1StartBufferIndex, shortExit1StartBuffer, INDICATOR_DATA); PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_ARROW, arrowCode); PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_SHOW_DATA, false); PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_DRAW_TYPE, shortExit1StartDrawType); // // LEVEL 2 ... // // Long Exit 2 ... // // Draw Type ... ENUM_DRAW_TYPE longExit2DrawType = showLongExit2Line ? DRAW_LINE : DRAW_NONE; ENUM_DRAW_TYPE longExit2StartDrawType = showLongExit2Line ? DRAW_ARROW : DRAW_NONE; // // Buffer ... SetIndexBuffer(longExit2BufferIndex, longExit2Buffer, INDICATOR_DATA); PlotIndexSetInteger(longExit2BufferIndex, PLOT_SHOW_DATA, showLongExit2Line); PlotIndexSetInteger(longExit2BufferIndex, PLOT_DRAW_TYPE, longExit2DrawType); // // Start Buffer ... SetIndexBuffer(longExit2StartBufferIndex, longExit2StartBuffer, INDICATOR_DATA); PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_ARROW, arrowCode); PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_SHOW_DATA, false); PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_DRAW_TYPE, longExit2StartDrawType); // // Short Exit 2 ... // // Draw Type ... ENUM_DRAW_TYPE shortExit2DrawType = showShortExit2Line ? DRAW_LINE : DRAW_NONE; ENUM_DRAW_TYPE shortExit2StartDrawType = showShortExit2Line ? DRAW_ARROW : DRAW_NONE; // // Buffer ... SetIndexBuffer(shortExit2BufferIndex, shortExit2Buffer, INDICATOR_DATA); PlotIndexSetInteger(shortExit2BufferIndex, PLOT_SHOW_DATA, showShortExit2Line); PlotIndexSetInteger(shortExit2BufferIndex, PLOT_DRAW_TYPE, shortExit2DrawType); // // Start Buffer ... SetIndexBuffer(shortExit2StartBufferIndex, shortExit2StartBuffer, INDICATOR_DATA); PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_ARROW, arrowCode); PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_SHOW_DATA, false); PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_DRAW_TYPE, shortExit2StartDrawType); } // // Calculate Buffers ... void CalculateBuffers( int bar_index, // Selected Bar Index int prevCalculated, // Previous Calculated int ratesTotal, // Total Rates const double &open[], // Rates Open ... const double &high[], // Rates High ... const double &low[], // Rates Low ... const double &close[] // Rates Close ... ) { // // Cleanup Buffers ... longExit1Buffer[bar_index] = longExit1StartBuffer[bar_index] = shortExit1Buffer[bar_index] = shortExit1StartBuffer[bar_index] = EMPTY_VALUE; longExit2Buffer[bar_index] = longExit2StartBuffer[bar_index] = shortExit2Buffer[bar_index] = shortExit2StartBuffer[bar_index] = EMPTY_VALUE; // int start = MathMax(bar_index - loopback, 0); // // Calculate ATR Value ... double atrValue = 0; for (int k = 1; k <= length && (bar_index - k - 1) >= 0; k++) { // atrValue += MathMax(high[bar_index - k], close[MathMax(bar_index - k - 1, 0)]) - MathMin(low[bar_index - k], close[MathMax(bar_index - k - 1, 0)]); } atrValue /= (double)length; // // Retrieve Highest High and Lowest Lows ... double loopbackMax = high[ArrayMaximum(high, start, loopback)]; double loopbackMin = low[ArrayMinimum(low, start, loopback)]; // // Fill Multi Dimesional Working Array ... work[bar_index][hi1Idx] = loopbackMax - multiplier1 * atrValue; work[bar_index][lo1Idx] = loopbackMin + multiplier1 * atrValue; work[bar_index][hi2Idx] = loopbackMax - multiplier2 * atrValue; work[bar_index][lo2Idx] = loopbackMin + multiplier2 * atrValue; work[bar_index][trend1Idx] = (bar_index > 0) ? work[bar_index - 1][trend1Idx] : 0; work[bar_index][trend2Idx] = (bar_index > 0) ? work[bar_index - 1][trend2Idx] : 0; // if (bar_index > 0) { // // Calculate Trends ... if (close[bar_index] > work[bar_index - 1][lo1Idx]) { work[bar_index][trend1Idx] = 1; } // if (close[bar_index] < work[bar_index - 1][hi1Idx]) { work[bar_index][trend1Idx] = -1; } // if (close[bar_index] > work[bar_index - 1][lo2Idx]) { work[bar_index][trend2Idx] = 1; } // if (close[bar_index] < work[bar_index - 1][hi2Idx]) { work[bar_index][trend2Idx] = -1; } // // Calculate Exit Values ... // // Exit 1 ... // // Long ... if (multiplier1 > 0 && work[bar_index][trend1Idx] == 1) { // if (work[bar_index][hi1Idx] < work[bar_index - 1][hi1Idx]) { work[bar_index][hi1Idx] = work[bar_index - 1][hi1Idx]; } // longExit1Buffer[bar_index] = work[bar_index][hi1Idx]; // if (longExit1Buffer[bar_index - 1] == EMPTY_VALUE) { longExit1StartBuffer[bar_index] = longExit1Buffer[bar_index]; } } // // Short ... if (multiplier1 > 0 && work[bar_index][trend1Idx] == -1) { // if (work[bar_index][lo1Idx] > work[bar_index - 1][lo1Idx]) { work[bar_index][lo1Idx] = work[bar_index - 1][lo1Idx]; } // shortExit1Buffer[bar_index] = work[bar_index][lo1Idx]; // if (shortExit1Buffer[bar_index - 1] == EMPTY_VALUE) { shortExit1StartBuffer[bar_index] = shortExit1Buffer[bar_index]; } } // // Exit 2 ... // // Long ... if (multiplier2 > 0 && work[bar_index][trend2Idx] == 1) { if (work[bar_index][hi2Idx] < work[bar_index - 1][hi2Idx]) { work[bar_index][hi2Idx] = work[bar_index - 1][hi2Idx]; } // longExit2Buffer[bar_index] = work[bar_index][hi2Idx]; // if (longExit2Buffer[bar_index - 1] == EMPTY_VALUE) { longExit2StartBuffer[bar_index] = longExit2Buffer[bar_index]; } } // // Short ... if (multiplier2 > 0 && work[bar_index][trend2Idx] == -1) { // if (work[bar_index][lo2Idx] > work[bar_index - 1][lo2Idx]) { work[bar_index][lo2Idx] = work[bar_index - 1][lo2Idx]; } // shortExit2Buffer[bar_index] = work[bar_index][lo2Idx]; // if (shortExit2Buffer[bar_index - 1] == EMPTY_VALUE) { shortExit2StartBuffer[bar_index] = shortExit2Buffer[bar_index]; } } } } // // END Functions ... //