/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Indicator // ------------------------------------------------- // Name: X121 XCHE // Description: XCHE ... // // // 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 // // Definitions ... // #define ShortName "X121 XCHE" // // Includes Common Library ... #include "../Libraries/x-saherelm.common.lib.mq5" // // Inputs ... // // Market ... input group "Market"; input int cheLength = 35; // Length input int cheLoopback = 26; // Loopback input double cheMultiplier1 = 3.0; // 1st Multiplier input double cheMultiplier2 = 3.5; // 2nd Multiplier input ENUM_APPLIED_PRICE cheUpperAppliedTo = PRICE_HIGH; // Upper Zone Applied to input ENUM_APPLIED_PRICE cheLowerAppliedTo = PRICE_LOW; // Lower Zone Applied to // input group "Presentation"; // input int cheArrowCode = 159; // CHE Arrow Code // input bool showLE1 = true; // Show 1st Long Exit input bool showSE1 = true; // Show 1st Short Exit input bool showLE2 = true; // Show 2st Long Exit input bool showSE2 = true; // Show 2st Short Exit // // Buffers ... // #define hideColorIDX 0 #define bullishColorIDX 1 #define bearishColorIDX 2 #define neuturalColorIDX 3 // #property indicator_chart_window // #property indicator_buffers 8 #property indicator_plots 8 // // Exit 1 ... // // LONG ... // #define le1BufferIndex 0 double le1Buffer[]; #property indicator_label1 "X121 LE1" #property indicator_type1 DRAW_LINE #property indicator_color1 clrAqua #property indicator_style1 STYLE_DOT #property indicator_width1 1 // // SHORT ... // #define se1BufferIndex 1 double se1Buffer[]; #property indicator_label2 "X121 SE1" #property indicator_type2 DRAW_LINE #property indicator_color2 clrMagenta #property indicator_style2 STYLE_DOT #property indicator_width2 1 // // Exit 2 ... // // LONG ... // #define le2BufferIndex 2 double le2Buffer[]; #property indicator_label3 "X121 LE2" #property indicator_type3 DRAW_LINE #property indicator_color3 clrAqua #property indicator_style3 STYLE_SOLID #property indicator_width3 1 // // SHORT ... // #define se2BufferIndex 3 double se2Buffer[]; #property indicator_label4 "X121 SE2" #property indicator_type4 DRAW_LINE #property indicator_color4 clrMagenta #property indicator_style4 STYLE_SOLID #property indicator_width4 1 // // Start Buffers ... // #define le1StartBufferIndex 4 double le1StartBuffer[]; // #property indicator_label5 "X121 LE1 S" #property indicator_type5 DRAW_ARROW #property indicator_color5 clrLime // #define se1StartBufferIndex 5 double se1StartBuffer[]; // #property indicator_label6 "X121 SE1 S" #property indicator_type6 DRAW_ARROW #property indicator_color6 clrRed // #define le2StartBufferIndex 6 double le2StartBuffer[]; // #property indicator_label7 "X121 LE2 S" #property indicator_type7 DRAW_ARROW #property indicator_color7 clrLime // #define se2StartBufferIndex 7 double se2StartBuffer[]; // #property indicator_label8 "X121 SE2 S" #property indicator_type8 DRAW_ARROW #property indicator_color8 clrRed // // Variables, Properties and etc ... // // this counts Available Bars ... int limit; // 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 // // Event Handlers ... /** * Initialize Indicator ... * * @return ( int ) */ 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 cheLength, here we get max Input cheLength // and then wait until pass it ... maxLength = ExtractMaxLengthOfInputs(); // // Define Index Buffers ... DefineBuffers(); // // Set Indicator ShortName ... SetIndicatorName(); // // Init Succeed ... return INIT_SUCCEEDED; } /** * De Initialize Indicator ... * * @param reason: Integer, De Initialization Reason ... */ 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 period 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 } /** * Calculate Bars ... * * @param rates_total: Integer, Total Bars on Chart ... * @param prev_calculated: Integer, Total Calculated Bars on Charts ... * @param time: DateTime Array, History of Open Time ... * @param open: Double Array, History of Open Prices ... * @param high: Double Array, History of High Prices ... * @param low: Double Array, History of Low Prices ... * @param close: Double Array, History of Close Prices ... * @param tick_volume: Long, History of Tick Volumes on Bar ... * @param volume: Long, History of Trade Volumes ... * @param spread: Double, History of Spread Price ... * * @return ( int ) */ 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 (Bars(_Symbol, _Period) < rates_total) { return (prev_calculated); } // if (ArrayRange(work, 0) != rates_total) { ArrayResize(work, rates_total); } // // this counts Available Bars ... // 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; } // // Functions ... /** * Validate Input Args for Initialization ... * * @return ( bool ) */ bool ValidateInputs() { // bool result = true; // result = cheLength >= 9 && cheLoopback >= 0; // return result; } /** * Extract Max Length of Inputs ... * * @return ( int ) */ int ExtractMaxLengthOfInputs() { // int result = 0; // result = MathMax(cheLength, cheLoopback); // return result; } /** * Define Required Buffers ... */ void DefineBuffers() { // // LEVEL 1 ... // // Long Exit 1 ... // // Draw Type ... ENUM_DRAW_TYPE le1DrawType = showLE1 ? DRAW_LINE : DRAW_NONE; ENUM_DRAW_TYPE le1StartDrawType = showLE1 ? DRAW_ARROW : DRAW_NONE; // // Buffer ... SetIndexBuffer(le1BufferIndex, le1Buffer, INDICATOR_DATA); PlotIndexSetInteger(le1BufferIndex, PLOT_SHOW_DATA, showLE1); PlotIndexSetInteger(le1BufferIndex, PLOT_DRAW_TYPE, le1DrawType); // // Start Buffer ... SetIndexBuffer(le1StartBufferIndex, le1StartBuffer, INDICATOR_DATA); PlotIndexSetInteger(le1StartBufferIndex, PLOT_SHOW_DATA, false); PlotIndexSetInteger(le1StartBufferIndex, PLOT_DRAW_TYPE, le1StartDrawType); PlotIndexSetInteger(le1StartBufferIndex, PLOT_ARROW, cheArrowCode); // // Short Exit 1 ... // // Draw Type ... ENUM_DRAW_TYPE se1DrawType = showSE1 ? DRAW_LINE : DRAW_NONE; ENUM_DRAW_TYPE se1StartDrawType = showSE1 ? DRAW_ARROW : DRAW_NONE; // // Buffer ... SetIndexBuffer(se1BufferIndex, se1Buffer, INDICATOR_DATA); PlotIndexSetInteger(se1BufferIndex, PLOT_SHOW_DATA, showSE1); PlotIndexSetInteger(se1BufferIndex, PLOT_DRAW_TYPE, se1DrawType); // // Start Buffer ... SetIndexBuffer(se1StartBufferIndex, se1StartBuffer, INDICATOR_DATA); PlotIndexSetInteger(se1StartBufferIndex, PLOT_SHOW_DATA, false); PlotIndexSetInteger(se1StartBufferIndex, PLOT_DRAW_TYPE, se1StartDrawType); PlotIndexSetInteger(se1StartBufferIndex, PLOT_ARROW, cheArrowCode); // // LEVEL 2 ... // // Long Exit 2 ... // // Draw Type ... ENUM_DRAW_TYPE le2DrawType = showLE2 ? DRAW_LINE : DRAW_NONE; ENUM_DRAW_TYPE le2StartDrawType = showLE2 ? DRAW_ARROW : DRAW_NONE; // // Buffer ... SetIndexBuffer(le2BufferIndex, le2Buffer, INDICATOR_DATA); PlotIndexSetInteger(le2BufferIndex, PLOT_SHOW_DATA, showLE2); PlotIndexSetInteger(le2BufferIndex, PLOT_DRAW_TYPE, le2DrawType); // // Start Buffer ... SetIndexBuffer(le2StartBufferIndex, le2StartBuffer, INDICATOR_DATA); PlotIndexSetInteger(le2StartBufferIndex, PLOT_SHOW_DATA, false); PlotIndexSetInteger(le2StartBufferIndex, PLOT_DRAW_TYPE, le2StartDrawType); PlotIndexSetInteger(le2StartBufferIndex, PLOT_ARROW, cheArrowCode); // // Short Exit 2 ... // // Draw Type ... ENUM_DRAW_TYPE se2DrawType = showSE2 ? DRAW_LINE : DRAW_NONE; ENUM_DRAW_TYPE se2StartDrawType = showSE2 ? DRAW_ARROW : DRAW_NONE; // // Buffer ... SetIndexBuffer(se2BufferIndex, se2Buffer, INDICATOR_DATA); PlotIndexSetInteger(se2BufferIndex, PLOT_SHOW_DATA, showSE2); PlotIndexSetInteger(se2BufferIndex, PLOT_DRAW_TYPE, se2DrawType); // // Start Buffer ... SetIndexBuffer(se2StartBufferIndex, se2StartBuffer, INDICATOR_DATA); PlotIndexSetInteger(se2StartBufferIndex, PLOT_SHOW_DATA, false); PlotIndexSetInteger(se2StartBufferIndex, PLOT_DRAW_TYPE, se2StartDrawType); PlotIndexSetInteger(se2StartBufferIndex, PLOT_ARROW, cheArrowCode); } /** * Set Indicator Short Name and also we can define Buffers Labels ... */ void SetIndicatorName() { IndicatorSetString(INDICATOR_SHORTNAME, ShortName); } /** * 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 ... le1Buffer[bar_index] = le1StartBuffer[bar_index] = se1Buffer[bar_index] = se1StartBuffer[bar_index] = EMPTY_VALUE; le2Buffer[bar_index] = le2StartBuffer[bar_index] = se2Buffer[bar_index] = se2StartBuffer[bar_index] = EMPTY_VALUE; // int start = MathMax(bar_index - cheLoopback, 0); // // Calculate ATR Value ... double atrValue = 0; for (int k = 1; k <= cheLength && (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)cheLength; // // Retrieve Highest High and Lowest Lows ... double cheLoopbackMax = high[ArrayMaximum(high, start, cheLoopback)]; double cheLoopbackMin = low[ArrayMinimum(low, start, cheLoopback)]; // // Fill Multi Dimesional Working Array ... work[bar_index][hi1Idx] = cheLoopbackMax - cheMultiplier1 * atrValue; work[bar_index][lo1Idx] = cheLoopbackMin + cheMultiplier1 * atrValue; work[bar_index][hi2Idx] = cheLoopbackMax - cheMultiplier2 * atrValue; work[bar_index][lo2Idx] = cheLoopbackMin + cheMultiplier2 * 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 (cheMultiplier1 > 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]; } // le1Buffer[bar_index] = work[bar_index][hi1Idx]; // if (le1Buffer[bar_index - 1] == EMPTY_VALUE) { le1StartBuffer[bar_index] = le1Buffer[bar_index]; } } // // Short ... if (cheMultiplier1 > 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]; } // se1Buffer[bar_index] = work[bar_index][lo1Idx]; // if (se1Buffer[bar_index - 1] == EMPTY_VALUE) { se1StartBuffer[bar_index] = se1Buffer[bar_index]; } } // // Exit 2 ... // // Long ... if (cheMultiplier2 > 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]; } // le2Buffer[bar_index] = work[bar_index][hi2Idx]; // if (le2Buffer[bar_index - 1] == EMPTY_VALUE) { le2StartBuffer[bar_index] = le2Buffer[bar_index]; } } // // Short ... if (cheMultiplier2 > 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]; } // se2Buffer[bar_index] = work[bar_index][lo2Idx]; // if (se2Buffer[bar_index - 1] == EMPTY_VALUE) { se2StartBuffer[bar_index] = se2Buffer[bar_index]; } } } } //