/////////////////////////////////////////////////////// // // SaherElm IT Center XBand Indicator // --------------------------------------------- // saherelm implementation of xBand 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 XBND Indicator" #property strict // #include "../Libraries/x-saherelm.lib.mq4" #include "../Libraries/x-saherelm.draw.lib.mq4" // // START Inputs ... // input int marketLength = 5; // Averaging Length input int ignoreLastCross = 4; // Ignore Last Cross input int shift = 0; // Averaging Shift input ENUM_MA_METHOD method = MODE_SMA; // Averaging Mode // // END Inputs ... // // // START Global Definitions: Variables, Properties and etc ... // // #property indicator_chart_window // #property indicator_buffers 4 // // Declare Buffers ... // // High ... #property indicator_width1 1 #property indicator_color1 clrAqua #property indicator_type1 DRAW_LINE #property indicator_style1 STYLE_DASHDOT // // Open ... #property indicator_width2 1 #property indicator_color2 clrGreen #property indicator_type2 DRAW_LINE #property indicator_style2 STYLE_DASH // // Close ... #property indicator_width3 1 #property indicator_color3 clrRed #property indicator_type3 DRAW_LINE #property indicator_style3 STYLE_DASH // // Low ... #property indicator_width4 1 #property indicator_color4 clrFuchsia #property indicator_type4 DRAW_LINE #property indicator_style4 STYLE_DASHDOT // #define highBufferIndex 0 #define openBufferIndex 1 #define closeBufferIndex 2 #define lowBufferIndex 3 // double highBuffer[]; double openBuffer[]; double closeBuffer[]; double lowBuffer[]; // datetime lastCrossTime; // // END Global Definitions: Variables, Properties and etc ... // // // Start Event Handlers ... // // // Initialization ... int OnInit() { // // Initialize what we want ... // // Validating Input Parameters ... if ( marketLength < 2 || ignoreLastCross < 0 ) { return INIT_PARAMETERS_INCORRECT; } // // here we specify logging enabled or not ... enableLogging = true; // // this is a Tag which attached to our Logger ... logTag = "XBND"; // // High ... string highLabel = StringConcatenate( "High(", marketLength, ")" ); SetIndexBuffer(highBufferIndex, highBuffer); SetIndexLabel(highBufferIndex, highLabel); // // Open ... string openLabel = StringConcatenate( "Open(", marketLength, ")" ); SetIndexBuffer(openBufferIndex, openBuffer); SetIndexLabel(openBufferIndex, openLabel); // // Close ... string closeLabel = StringConcatenate( "Close(", marketLength, ")" ); SetIndexBuffer(closeBufferIndex, closeBuffer); SetIndexLabel(closeBufferIndex, closeLabel); // // Low ... string lowLabel = StringConcatenate( "Low(", marketLength, ")" ); SetIndexBuffer(lowBufferIndex, lowBuffer); SetIndexLabel(lowBufferIndex, lowLabel); // // initialization done ... return INIT_SUCCEEDED; } // // DeInitialization ... void OnDeinit(const int reason) { RemoveDraws(logTag); } // // Do Calculation ... 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[] ) { // // this counts Available Bars ... int limit; // // 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 ... int maxLength = MathMax(0, marketLength); // // input variable, we return 0 means nothing passed ... if (rates_total < maxLength) { return 0; } // // found which candles calculated before ... limit = (prev_calculated == 0) ? rates_total - maxLength - 1 : rates_total - prev_calculated + 1; // // this is the main loop of calculations, for each bar index ... for (int i = limit - 1; i >= 0; i--) { // // Start Calculation here ... // i is bar_index ... // // Calculate Buffers ... CalculateBuffers(i); // // Calculate Market Changes ... CalculateInfo(i); } // return rates_total; } // // END Event Handlers ... // // // START Functions ... // void CalculateBuffers( const int bar_index ) { // // High ... double high = iMA( _Symbol, _Period, marketLength, shift, method, PRICE_HIGH, bar_index ); // highBuffer[bar_index] = high; // // Open ... double open = iMA( _Symbol, _Period, marketLength, shift, method, PRICE_OPEN, bar_index ); // openBuffer[bar_index] = open; // // Close ... double close = iMA( _Symbol, _Period, marketLength, shift, method, PRICE_CLOSE, bar_index ); // closeBuffer[bar_index] = close; // // Low ... double low = iMA( _Symbol, _Period, marketLength, shift, method, PRICE_LOW, bar_index ); // lowBuffer[bar_index] = low; } // void CalculateInfo( const int bar_index ) { // XOHCL pCandle = GetCandleModel(bar_index); // bool isTrendingUp = pCandle.low > highBuffer[bar_index] && pCandle.high > highBuffer[bar_index]; // bool isTrendingDown = pCandle.high < lowBuffer[bar_index] && pCandle.low < lowBuffer[bar_index]; // bool isOpenCrossOverClose = true // && // ( // pCandle.high > highBuffer[bar_index + 1] // || pCandle.low < lowBuffer[bar_index + 1] // ) && openBuffer[bar_index + 1] > closeBuffer[bar_index + 1] && !(openBuffer[bar_index + 2] >= closeBuffer[bar_index + 2]) ; // bool isOpenCrossUnderClose = true // && // ( // pCandle.high > highBuffer[bar_index + 1] // || pCandle.low < lowBuffer[bar_index + 1] // ) && openBuffer[bar_index + 1] < closeBuffer[bar_index + 1] && !(openBuffer[bar_index + 2] <= closeBuffer[bar_index + 2]) ; // isTrendingUp = isOpenCrossUnderClose; isTrendingDown = isOpenCrossOverClose; // datetime time = iTime( _Symbol, _Period, bar_index ); // if ( isTrendingUp || isTrendingDown ) { // if (lastCrossTime == 0) { lastCrossTime = time; } else { // int lastCrossBarIndex = iBarShift( _Symbol, _Period, lastCrossTime ); // int diff = lastCrossBarIndex - bar_index; if (diff <= ignoreLastCross) { return; } else { lastCrossTime = time; } } } // string lbl = StringConcatenate( logTag, "_Arrow_", isTrendingUp ? "UP" : "Down", "_", time ); // color clr = isTrendingUp ? clrAqua : clrFuchsia; // ENUM_ARROW_ANCHOR anchor = isTrendingUp ? ANCHOR_BOTTOM : ANCHOR_TOP; // uchar arrowCode = isTrendingUp ? SYMBOL_ARROWUP : SYMBOL_ARROWDOWN; // double price = isTrendingUp ? pCandle.low - 20 * _Point : pCandle.high + 20 * _Point; // if (isTrendingUp) { // // this means Market Going Up ... } // if (isTrendingDown) { // // this means Market Going Downm ... } // if ( isTrendingUp || isTrendingDown ) { // bool isDrawn = DrawArrow( 0, lbl, 0, time, price, arrowCode, anchor, clr ); } } // // END Functions ... //