//+------------------------------------------------------------------+ //| TriDivergenceEA.mq5 | //| Copyright 2025, Teenodi Ltd. | //| https://www.jukwaese.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Teenodi Ltd." #property link "val.chioke@gmail.com" #property version "1.00" #property description "EA that trades based on divergence signals from RSI, Stochastic, and Klinger indicators" #property strict //============================ Enums =============================== enum SIGNAL_TYPE { SIGNAL_NULL, // No Signal SIGNAL_BUY, // Buy Signal SIGNAL_SELL // Sell Signal }; enum VOLUME_TYPE { VOLUME_FIXED = 1, // Fixed Lots VOLUME_RISK = 2 // Percentage Risk }; enum POSITION_TYPE_FILTER { POSITION_BUY_ONLY = 1, // Buy Only POSITION_SELL_ONLY = 2, // Sell Only POSITION_BOTH = 3 // Both }; enum TRAILING_TYPE { TRAIL_CONTINUOUS, // Continuous Trail TRAIL_STEP // Step Trail }; //============================ Structures =========================== struct SignalInfo { SIGNAL_TYPE signal; int shift; SignalInfo() { signal = SIGNAL_NULL; shift = -1; } }; //============================ Inputs =============================== input group "Magicnumber and Comment Setting" input int Magic = 12345; // Magic number for trade identification (12345-123450) input string comentar = "DivergenceEA"; // Trade comment field input group "Risk- and Moneymanagement" input VOLUME_TYPE volumetype = VOLUME_FIXED; // Volume type: 1=FIXED, 2=PROCENT input double Risk = 0.1; // Risk percentage per trade (0.1-30%) input double Lots = 0.01; // Fixed lot size (0.01-100) input int Sl_Point_pip = 100; // Stop loss in pips (10-10000) input int Tp_Point_pip = 200; // Take profit in pips (10-10000) input group "Pending Orders Strategy" input bool PendingOrder = false; // Enable pending orders input group "Condition 1" input group "Position" input POSITION_TYPE_FILTER Position = POSITION_BOTH; // 1=BUY_ONLY, 2=SELL_ONLY, 3=BUY_or_SELL input string CANDLESTICKS = "HIGHER_HIGH_OR_LOWER_LOW"; // Candlestick validation description input int Numberofcandles_Back = 20; // Lookback period for candlestick validation (1-100) input group "Condition 2" input group "INDICATORS DIVERGENCE:" input group "Klinger Oscillator KO INDICATOR" input bool KO = true; // Enable Klinger Oscillator input int KLINGER_LENGHT1 = 34; // First Klinger parameter (0-100) input int KLINGER_LENGHT2 = 55; // Second Klinger parameter (0-100) input int SIGNAL_LONG = 13; // Klinger signal length (0-100) input int Numberofcandles_Back_KO = 20; // KO lookback period for analysis (1-100) input group "Condition 3" input group "RSI INDICATOR" input bool RSI = true; // Enable RSI indicator input int RSI_UPPER = 70; // RSI upper threshold (0-100) input int RSI_LOWER = 30; // RSI lower threshold (0-100) input int RSI_LONG = 14; // RSI signal length (0-100) input int Numberofcandles_Back_RSI = 20; // RSI lookback period for analysis (1-100) input group "Condition 4" input group "STOCH INDICATOR" input bool STOCH = true; // Enable Stochastic indicator input int K = 5; // Stochastic %K value (0-100) input int D = 3; // Stochastic %D value (0-100) input int STOCHASTIC_LONG = 5; // Stochastic signal length (0-100) input int Numberofcandles_Back_STOCH = 20; // STOCH lookback period for analysis (1-100) input group "BreakEven Settings" input bool BreakEven = true; // Enable breakeven function input int BreakEvenShift = 10; // Distance to move stop above breakeven (in pips) (1-100) input int StopNachzienWenn = 50; // Profit level to trigger breakeven (in pips) (1-100) input group "Trallingstop Settings" input bool Trall = false; // Enable trailing stop input TRAILING_TYPE traillingstop = TRAIL_CONTINUOUS; // Trailing algorithm type: 1=continuous, 2=step input int TralStop = 30; // Trailing distance behind price (in pips) (1-2000) input int TralStep = 10; // Minimum move before trail adjusts (in pips) (1-2000) input group "Visual Settings" input color RectangleColor = clrLimeGreen; // Rectangle color //============================ Global Variables ===================== int rsiDivergenceHandle = INVALID_HANDLE; int stochasticsDivergenceHandle = INVALID_HANDLE; int klingerDivergenceHandle = INVALID_HANDLE; datetime prevBarTime = 0; int globalConfluenceCount; string rectangleName = "LookbackRectangle"; double pointValue; ENUM_ORDER_TYPE_FILLING orderFill; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Check autotrading if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Alert("Please enable autotrading on terminal to take trades"); //return INIT_FAILED; } // Initialize point value pointValue = SymbolInfoDouble(_Symbol, SYMBOL_POINT); // Set filling policy uint filling = (uint)SymbolInfoInteger(_Symbol, SYMBOL_FILLING_MODE); if((filling & SYMBOL_FILLING_FOK) == SYMBOL_FILLING_FOK) { orderFill = ORDER_FILLING_FOK; } else if((filling & SYMBOL_FILLING_IOC) == SYMBOL_FILLING_IOC) { orderFill = ORDER_FILLING_IOC; } else { orderFill = ORDER_FILLING_RETURN; } // Initialize confluence count (automatically calculated from enabled indicators) int enabledIndicators = 0; if(RSI) enabledIndicators++; if(STOCH) enabledIndicators++; if(KO) enabledIndicators++; if(enabledIndicators == 0) { Alert("At least one indicator must be enabled!"); return INIT_FAILED; } // Set confluence count: require at least 1 signal, up to all enabled indicators globalConfluenceCount = MathMax(1, MathMin(2, enabledIndicators)); // Create indicator handles if(RSI) { rsiDivergenceHandle = iCustom(_Symbol, PERIOD_CURRENT, "Divergence RSI"); if(rsiDivergenceHandle == INVALID_HANDLE) { Print("Failed to create RSI Divergence indicator handle"); return INIT_FAILED; } ChartIndicatorAdd(0,1,rsiDivergenceHandle); } if(STOCH) { stochasticsDivergenceHandle = iCustom(_Symbol, PERIOD_CURRENT, "StochasticsDivergence"); if(stochasticsDivergenceHandle == INVALID_HANDLE) { Print("Failed to create Stochastics Divergence indicator handle"); return INIT_FAILED; } ChartIndicatorAdd(0,2,stochasticsDivergenceHandle); } if(KO) { klingerDivergenceHandle = iCustom(_Symbol, PERIOD_CURRENT, "KlingerDivergence"); if(klingerDivergenceHandle == INVALID_HANDLE) { Print("Failed to create Klinger Divergence indicator handle"); return INIT_FAILED; } ChartIndicatorAdd(0,3,klingerDivergenceHandle); } // Initialize previous bar time prevBarTime = iTime(_Symbol, PERIOD_CURRENT, 0); // Draw initial rectangle DrawLookbackRectangle(); Print("DivergenceEA initialized successfully"); Print("Enabled indicators: RSI=", RSI, " STOCH=", STOCH, " KO=", KO); Print("Confluence count: ", globalConfluenceCount); Print("Candlestick validation period: ", Numberofcandles_Back, " bars"); Print("Magic number: ", Magic, ", Volume type: ", (volumetype == VOLUME_FIXED ? "FIXED" : "PROCENT")); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Release indicator handles if(rsiDivergenceHandle != INVALID_HANDLE) { IndicatorRelease(rsiDivergenceHandle); } if(stochasticsDivergenceHandle != INVALID_HANDLE) { IndicatorRelease(stochasticsDivergenceHandle); } if(klingerDivergenceHandle != INVALID_HANDLE) { IndicatorRelease(klingerDivergenceHandle); } // Delete rectangle ObjectDelete(0, rectangleName); Print("DivergenceEA deinitialized, reason: ", reason); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Trade management (runs on every tick) ManageOpenPositions(); // Check for new bar if(IsNewBar()) { Print("New bar detected, analyzing signals..."); // Create signal array and analyze SignalInfo signals[]; AnalyzeSignals(signals); // Check for entry signals CheckEntrySignals(signals); // Update rectangle DrawLookbackRectangle(); } } //+------------------------------------------------------------------+ //| Check if new bar formed | //+------------------------------------------------------------------+ bool IsNewBar() { datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0); if(currentBarTime != prevBarTime) { prevBarTime = currentBarTime; return true; } return false; } //+------------------------------------------------------------------+ //| Analyze signals from all enabled indicators | //+------------------------------------------------------------------+ void AnalyzeSignals(SignalInfo &signals[]) { int signalCount = 0; // Count enabled indicators if(RSI) signalCount++; if(STOCH) signalCount++; if(KO) signalCount++; ArrayResize(signals, signalCount); int index = 0; // Analyze RSI Divergence if(RSI && rsiDivergenceHandle != INVALID_HANDLE) { signals[index] = GetLatestSignal(rsiDivergenceHandle, 0, 1); // Buy buffer 0, Sell buffer 1 index++; } // Analyze Stochastics Divergence if(STOCH && stochasticsDivergenceHandle != INVALID_HANDLE) { signals[index] = GetLatestSignal(stochasticsDivergenceHandle, 1, 2); // Buy buffer 1, Sell buffer 2 index++; } // Analyze Klinger Divergence if(KO && klingerDivergenceHandle != INVALID_HANDLE) { signals[index] = GetLatestSignal(klingerDivergenceHandle, 2, 3); // Buy buffer 2, Sell buffer 3 index++; } } //+------------------------------------------------------------------+ //| Get latest signal from indicator within lookback period | //+------------------------------------------------------------------+ SignalInfo GetLatestSignal(int handle, int buyBuffer, int sellBuffer) { SignalInfo signal; double buyValues[], sellValues[]; // Determine lookback period based on indicator type int lookbackPeriod = 20; // default string indicatorName = "Unknown"; if(handle == rsiDivergenceHandle) { lookbackPeriod = Numberofcandles_Back_RSI; indicatorName = "RSI"; } else if(handle == stochasticsDivergenceHandle) { lookbackPeriod = Numberofcandles_Back_STOCH; indicatorName = "STOCH"; } else if(handle == klingerDivergenceHandle) { lookbackPeriod = Numberofcandles_Back_KO; indicatorName = "KLINGER"; } Print("Checking ", indicatorName, " indicator (Handle=", handle, ") buffers ", buyBuffer, "/", sellBuffer, " over ", lookbackPeriod, " bars"); // Copy buffers for the lookback period int buyCount = CopyBuffer(handle, buyBuffer, 1, lookbackPeriod, buyValues); int sellCount = CopyBuffer(handle, sellBuffer, 1, lookbackPeriod, sellValues); if(buyCount <= 0 || sellCount <= 0) { Print("ERROR: Failed to copy ", indicatorName, " buffers - Buy copied: ", buyCount, ", Sell copied: ", sellCount); return signal; } Print("Successfully copied ", indicatorName, " buffers - Buy: ", buyCount, ", Sell: ", sellCount); // Search for latest signal (starting from most recent) for(int i = 0; i < lookbackPeriod; i++) { // Check for buy signal if(buyValues[i] != EMPTY_VALUE && buyValues[i] != 0) { Print(indicatorName, " BUY signal found at shift ", i+1, " with value ", NormalizeDouble(buyValues[i], 5)); signal.signal = SIGNAL_BUY; signal.shift = i + 1; // Adjust for the fact we're looking at completed bars break; } // Check for sell signal if(sellValues[i] != EMPTY_VALUE && sellValues[i] != 0) { Print(indicatorName, " SELL signal found at shift ", i+1, " with value ", NormalizeDouble(sellValues[i], 5)); signal.signal = SIGNAL_SELL; signal.shift = i + 1; break; } } if(signal.signal == SIGNAL_NULL) Print("No ", indicatorName, " signals found in ", lookbackPeriod, " bars"); return signal; } //+------------------------------------------------------------------+ //| Check entry signals and execute trades | //+------------------------------------------------------------------+ void CheckEntrySignals(SignalInfo &signals[]) { int buySignals = 0; int sellSignals = 0; bool hasRecentBuySignal = false; bool hasRecentSellSignal = false; Print("=== SIGNAL ANALYSIS START ==="); Print("Total signals to analyze: ", ArraySize(signals)); Print("Required confluence count: ", globalConfluenceCount); // Count signals and check for recent signals on last formed candle (shift = 1) for(int i = 0; i < ArraySize(signals); i++) { Print("Signal[", i, "]: Type=", EnumToString(signals[i].signal), " Shift=", signals[i].shift); if(signals[i].signal == SIGNAL_BUY) { buySignals++; if(signals[i].shift == 1) hasRecentBuySignal = true; } else if(signals[i].signal == SIGNAL_SELL) { sellSignals++; if(signals[i].shift == 1) hasRecentSellSignal = true; } } Print("Signal count - Buy: ", buySignals, " (recent: ", hasRecentBuySignal, "), Sell: ", sellSignals, " (recent: ", hasRecentSellSignal, ")"); Print("Position filter: ", EnumToString(Position)); // Execute buy trade (with candlestick validation) if(hasRecentBuySignal && buySignals >= globalConfluenceCount && (Position == POSITION_BOTH || Position == POSITION_BUY_ONLY)) { Print("BUY conditions met - checking candlestick validation..."); // Check for lower low condition if(ValidateCandlestickCondition(ORDER_TYPE_BUY)) { Print(">>> EXECUTING BUY TRADE <<<"); ExecuteTrade(ORDER_TYPE_BUY); } else { Print("BUY signals detected but candlestick validation failed - trade rejected"); } } else { Print("BUY conditions NOT met: recentSignal=", hasRecentBuySignal, " signalCount>=", buySignals, ">=" , globalConfluenceCount, " positionFilter=", (Position == POSITION_BOTH || Position == POSITION_BUY_ONLY)); } // Execute sell trade (with candlestick validation) if(hasRecentSellSignal && sellSignals >= globalConfluenceCount && (Position == POSITION_BOTH || Position == POSITION_SELL_ONLY)) { Print("SELL conditions met - checking candlestick validation..."); // Check for higher high condition if(ValidateCandlestickCondition(ORDER_TYPE_SELL)) { Print(">>> EXECUTING SELL TRADE <<<"); ExecuteTrade(ORDER_TYPE_SELL); } else { Print("SELL signals detected but candlestick validation failed - trade rejected"); } } else { Print("SELL conditions NOT met: recentSignal=", hasRecentSellSignal, " signalCount>=", sellSignals, ">=" , globalConfluenceCount, " positionFilter=", (Position == POSITION_BOTH || Position == POSITION_SELL_ONLY)); } Print("=== SIGNAL ANALYSIS END ==="); } //+------------------------------------------------------------------+ //| Execute trade | //+------------------------------------------------------------------+ void ExecuteTrade(ENUM_ORDER_TYPE orderType) { double volume = CalculateVolume(); if(volume <= 0) { Print("Invalid volume calculated: ", volume); return; } double price, sl, tp; if(orderType == ORDER_TYPE_BUY) { price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); sl = price - Sl_Point_pip * pointValue * 10; tp = price + Tp_Point_pip * pointValue * 10; } else { price = SymbolInfoDouble(_Symbol, SYMBOL_BID); sl = price + Sl_Point_pip * pointValue * 10; tp = price - Tp_Point_pip * pointValue * 10; } MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_DEAL; request.symbol = _Symbol; request.volume = NormalizeDouble(volume, 2); request.type = orderType; request.price = price; request.sl = NormalizeDouble(sl, _Digits); request.tp = NormalizeDouble(tp, _Digits); request.deviation = 10; request.type_filling = orderFill; request.magic = Magic; request.comment = comentar; bool success = OrderSend(request, result); if(success && result.retcode == TRADE_RETCODE_DONE) { Print("Trade executed successfully - ", (orderType == ORDER_TYPE_BUY ? "BUY" : "SELL"), " Volume: ", volume, " Price: ", price); } else { Print("Trade execution failed - Result code: ", result.retcode, " Comment: ", result.comment); } } //+------------------------------------------------------------------+ //| Calculate volume based on risk management | //+------------------------------------------------------------------+ double CalculateVolume() { double volume = Lots; if(volumetype == VOLUME_RISK) { double balance = AccountInfoDouble(ACCOUNT_BALANCE); double riskAmount = balance * Risk / 100.0; double slPoints = Sl_Point_pip * pointValue * 10; double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); if(slPoints > 0 && tickValue > 0) { volume = riskAmount / (slPoints * tickValue / pointValue); } } // Normalize volume double minVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double maxVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double volumeStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); volume = MathMax(volume, minVolume); volume = MathMin(volume, maxVolume); volume = NormalizeDouble(MathRound(volume / volumeStep) * volumeStep, 2); return volume; } //+------------------------------------------------------------------+ //| Manage open positions (breakeven and trailing stop) | //+------------------------------------------------------------------+ void ManageOpenPositions() { for(int i = 0; i < PositionsTotal(); i++) { ulong ticket = PositionGetTicket(i); if(PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == Magic) { // Apply breakeven if(BreakEven) { ApplyBreakeven(ticket); } // Apply trailing stop if(Trall) { ApplyTrailingStop(ticket); } } } } //+------------------------------------------------------------------+ //| Apply breakeven to position | //+------------------------------------------------------------------+ void ApplyBreakeven(ulong ticket) { if(!PositionSelectByTicket(ticket)) return; double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); double currentSL = PositionGetDouble(POSITION_SL); double currentTP = PositionGetDouble(POSITION_TP); ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double currentPrice = (posType == POSITION_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK); double profitPoints = MathAbs(currentPrice - openPrice) / (pointValue * 10); if(profitPoints >= StopNachzienWenn) { double newSL = 0; bool shouldModify = false; if(posType == POSITION_TYPE_BUY) { newSL = openPrice + BreakEvenShift * pointValue * 10; if(newSL > currentSL) shouldModify = true; } else { newSL = openPrice - BreakEvenShift * pointValue * 10; if(newSL < currentSL || currentSL == 0) shouldModify = true; } if(shouldModify) { ModifyPosition(ticket, newSL, currentTP); } } } //+------------------------------------------------------------------+ //| Apply trailing stop to position | //+------------------------------------------------------------------+ void ApplyTrailingStop(ulong ticket) { if(!PositionSelectByTicket(ticket)) return; double currentSL = PositionGetDouble(POSITION_SL); double currentTP = PositionGetDouble(POSITION_TP); ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double currentPrice = (posType == POSITION_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK); double newSL = 0; bool shouldModify = false; if(posType == POSITION_TYPE_BUY) { newSL = currentPrice - TralStop * pointValue * 10; if(traillingstop == TRAIL_STEP) { double moveRequired = TralStep * pointValue * 10; if((newSL - currentSL) >= moveRequired) shouldModify = true; } else { if(newSL > currentSL) shouldModify = true; } } else { newSL = currentPrice + TralStop * pointValue * 10; if(traillingstop == TRAIL_STEP) { double moveRequired = TralStep * pointValue * 10; if((currentSL - newSL) >= moveRequired || currentSL == 0) shouldModify = true; } else { if(newSL < currentSL || currentSL == 0) shouldModify = true; } } if(shouldModify) { ModifyPosition(ticket, newSL, currentTP); } } //+------------------------------------------------------------------+ //| Modify position stop loss and take profit | //+------------------------------------------------------------------+ bool ModifyPosition(ulong ticket, double newSL, double tp) { MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_SLTP; request.position = ticket; request.symbol = _Symbol; request.sl = NormalizeDouble(newSL, _Digits); request.tp = NormalizeDouble(tp, _Digits); bool success = OrderSend(request, result); if(!success || result.retcode != TRADE_RETCODE_DONE) { Print("Failed to modify position SL. Error: ", GetLastError(), " Result code: ", result.retcode); return false; } return true; } //+------------------------------------------------------------------+ //| Validate candlestick condition for entry | //+------------------------------------------------------------------+ bool ValidateCandlestickCondition(ENUM_ORDER_TYPE orderType) { if(Numberofcandles_Back <= 0) { return true; // Skip validation if period is 0 or negative } // Get current candle (shift 1 = last completed candle) price levels double currentHigh = iHigh(_Symbol, PERIOD_CURRENT, 1); double currentLow = iLow(_Symbol, PERIOD_CURRENT, 1); if(orderType == ORDER_TYPE_SELL) { // For sell signal: current candle high should be higher than all previous X candle highs for(int i = 2; i <= Numberofcandles_Back + 1; i++) { double compareHigh = iHigh(_Symbol, PERIOD_CURRENT, i); if(currentHigh <= compareHigh) { Print("Sell candlestick validation failed: Current high (", DoubleToString(currentHigh, _Digits), ") not higher than candle at shift ", i, " high (", DoubleToString(compareHigh, _Digits), ")"); return false; } } Print("Sell candlestick validation passed: Current high (", DoubleToString(currentHigh, _Digits), ") is higher than all ", Numberofcandles_Back, " previous highs"); return true; } else if(orderType == ORDER_TYPE_BUY) { // For buy signal: current candle low should be lower than all previous X candle lows for(int i = 2; i <= Numberofcandles_Back + 1; i++) { double compareLow = iLow(_Symbol, PERIOD_CURRENT, i); if(currentLow >= compareLow) { Print("Buy candlestick validation failed: Current low (", DoubleToString(currentLow, _Digits), ") not lower than candle at shift ", i, " low (", DoubleToString(compareLow, _Digits), ")"); return false; } } Print("Buy candlestick validation passed: Current low (", DoubleToString(currentLow, _Digits), ") is lower than all ", Numberofcandles_Back, " previous lows"); return true; } return false; } //+------------------------------------------------------------------+ //| Draw lookback rectangle | //+------------------------------------------------------------------+ void DrawLookbackRectangle() { datetime currentTime = iTime(_Symbol, PERIOD_CURRENT, 0); datetime lookbackTime = iTime(_Symbol, PERIOD_CURRENT, MathMax(Numberofcandles_Back_RSI, MathMax(Numberofcandles_Back_STOCH, Numberofcandles_Back_KO))); double highPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) * 1.1; // Chart top double lowPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID) * 0.9; // Chart bottom // Delete existing rectangle if it exists ObjectDelete(0, rectangleName); // Create new rectangle if(ObjectCreate(0, rectangleName, OBJ_RECTANGLE, 0, lookbackTime, lowPrice, currentTime, highPrice)) { ObjectSetInteger(0, rectangleName, OBJPROP_COLOR, RectangleColor); ObjectSetInteger(0, rectangleName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, rectangleName, OBJPROP_WIDTH, 1); ObjectSetInteger(0, rectangleName, OBJPROP_BACK, true); ObjectSetInteger(0, rectangleName, OBJPROP_FILL, true); ObjectSetInteger(0, rectangleName, OBJPROP_HIDDEN, true); int maxLookback = MathMax(Numberofcandles_Back_RSI, MathMax(Numberofcandles_Back_STOCH, Numberofcandles_Back_KO)); ObjectSetString(0, rectangleName, OBJPROP_TOOLTIP, "Max Lookback Period: " + IntegerToString(maxLookback) + " candles"); // Make it almost transparent color rectColor = RectangleColor; ObjectSetInteger(0, rectangleName, OBJPROP_COLOR, ColorToARGB(rectColor, 20)); // 20 out of 255 alpha } ChartRedraw(0); } //+------------------------------------------------------------------+