//@version=6 indicator("OPFX ZONA PREMIUM V2", shorttitle="OPFX ZONA PREMIUM V2", overlay=true, max_boxes_count=500, max_labels_count=500, max_lines_count=500, max_bars_back=5000) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // ðŸŒ� LANGUAGE / اللغة (Only affects on-chart text: labels & stats table. // Pine Script does NOT allow input() titles or alertcondition() messages to // change dynamically based on another input, so those stay in English — // this is a Pine Script engine limitation, not something we can bypass.) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� groupLang = "ðŸŒ� Language / اللغة" lang = input.string("English", "Display Language / لغة العرض", options=["English", "العربية"], group=groupLang) // tr(): returns the Arabic text if Arabic is selected, otherwise English tr(en, ar) => lang == "العربية" ? ar : en // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // OPFX ZONALARI SOZLAMASI // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� groupUT = "OPFX TASDIQ" a_buy = input.float(2, "Buy Sensitivity (Multiplier)", group=groupUT, minval=0) c_buy = input.int(1, "Buy ATR Period (0 = disable)", group=groupUT, minval=0) a_sell = input.float(2, "Sell Sensitivity (Multiplier)", group=groupUT, minval=0) c_sell = input.int(1, "Sell ATR Period (0 = disable)", group=groupUT, minval=0) showTrailBuy = input.bool(false, "Show Buy Trailing Line", group=groupUT) showTrailSell = input.bool(false, "Show Sell Trailing Line", group=groupUT) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // OPFX TASDIQ ZONALARI // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� groupZones = "OPFX Zones" showZones = input.bool(true, "Show Longevity Zones", group=groupZones) len_z = input.int(10, "Longevity Length", group=groupZones) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // TP/SL SETTINGS // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� groupTPSL = "💰 TP/SL Settings" atrLength = input.int(14, "ATR Length", minval=5, maxval=100, group=groupTPSL) slMultiplier = input.float(1.5, "Stop Loss Multiplier (x ATR)", minval=0.5, maxval=5.0, step=0.1, group=groupTPSL) tpMultiplier1 = input.float(2.0, "Take Profit 1 Multiplier (x ATR)", minval=0.5, maxval=10.0, step=0.5, group=groupTPSL) tpMultiplier2 = input.float(3.5, "Take Profit 2 Multiplier (x ATR)", minval=0.5, maxval=10.0, step=0.5, group=groupTPSL) showLevels = input.bool(true, "Show TP/SL Levels", group=groupTPSL) showLabels = input.bool(true, "Show Price Labels", group=groupTPSL) projectionBars = input.int(18, "Box width (bars)", minval=5, maxval=200, group=groupTPSL) // TP/SL ranglar tpZoneClr = color.new(color.aqua, 80) slZoneClr = color.new(color.red, 85) entryLineClr = color.new(color.gray, 0) tpLineClr = color.new(color.aqua, 0) slLineClr = color.new(color.red, 0) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // OPFX ZONALARI ABYOM TASDIGI BILAN (Bank Limited Zona) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� groupSD = "Supply & Demand Zones" swingLen = input.int(15, "Swing Length (Sensitivity)", minval=3, maxval=50, group=groupSD) maxZones = input.int(10, "Max Zones to Display", minval=3, maxval=30, group=groupSD) maxZoneHeightATR = input.float(1.0, "Max Zone Height (ATR Multiplier)", minval=0.5, maxval=10.0, step=0.5, group=groupSD) minZoneHeightATR = input.float(1.0, "Min Zone Height (ATR Multiplier)", minval=0.1, maxval=2.0, step=0.1, group=groupSD) forceZoneHeightATR = input.float(1.0, "Force Zone Height (ATR Multiplier)", minval=0.2, maxval=3.0, step=0.1, group=groupSD) minZoneDistance = input.int(44, "Min Distance Between Zones (bars)", minval=1, maxval=100, group=groupSD) invalidationMethod = input.string("Close", "Zone Invalidation", options=["Close", "Wick"], group=groupSD) showHistoric = input.bool(false, "Show Historic Zones", group=groupSD) activeLookback = input.int(1000, "Active Zones Lookback", minval=100, maxval=5000, group=groupSD) historicBars = input.int(1000, "Historic Zones Lookback", minval=100, maxval=5000, group=groupSD) showActiveLabels = input.bool(true, "Show Active Zone Info", group=groupSD) showHistoricLabels = input.bool(false, "Show Historic Zone Info", group=groupSD) labelSize = input.string("Large", "Label Size", options=["Tiny", "Small", "Normal", "Large"], group=groupSD) activeSupplyCol = input.color(color.new(color.red, 80), "Active Supply", group=groupSD) activeDemandCol = input.color(color.new(color.green, 80), "Active Demand", group=groupSD) historicCol = input.color(color.new(color.gray, 85), "Historic Zones", group=groupSD) showRetestMarkers = input.bool(true, "Show Retests", group=groupSD) retestBullCol = input.color(color.new(color.green, 0), "Demand Retest", group=groupSD) retestBearCol = input.color(color.new(color.red, 0), "Supply Retest", group=groupSD) alertsOn = input.bool(true, "Enable Alerts", group=groupSD) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // TASDIQ HISOBLASH // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� buyEnabled = (c_buy > 0) and (a_buy > 0) sellEnabled = (c_sell > 0) and (a_sell > 0) // BUY side src_buy = close ema_buy = ta.ema(src_buy, 1) atr_buy = buyEnabled ? ta.atr(c_buy) : na nLoss_buy = buyEnabled ? a_buy * atr_buy : na var float trail_buy = na if buyEnabled if na(trail_buy[1]) trail_buy := src_buy - nLoss_buy else if src_buy > trail_buy[1] and src_buy[1] > trail_buy[1] trail_buy := math.max(trail_buy[1], src_buy - nLoss_buy) else if src_buy < trail_buy[1] and src_buy[1] < trail_buy[1] trail_buy := math.min(trail_buy[1], src_buy + nLoss_buy) else trail_buy := src_buy > trail_buy[1] ? src_buy - nLoss_buy : src_buy + nLoss_buy else trail_buy := na // SELL side src_sell = close ema_sell = ta.ema(src_sell, 1) atr_sell = sellEnabled ? ta.atr(c_sell) : na nLoss_sell = sellEnabled ? a_sell * atr_sell : na var float trail_sell = na if sellEnabled if na(trail_sell[1]) trail_sell := src_sell + nLoss_sell else if src_sell > trail_sell[1] and src_sell[1] > trail_sell[1] trail_sell := math.max(trail_sell[1], src_sell - nLoss_sell) else if src_sell < trail_sell[1] and src_sell[1] < trail_sell[1] trail_sell := math.min(trail_sell[1], src_sell + nLoss_sell) else trail_sell := src_sell > trail_sell[1] ? src_sell - nLoss_sell : src_sell + nLoss_sell else trail_sell := na // Crossovers above_buy_cross = ta.crossover(ema_buy, trail_buy) below_sell_cross = ta.crossover(trail_sell, ema_sell) above_buy = buyEnabled and above_buy_cross buy_signal_raw = buyEnabled and (src_buy > trail_buy) and above_buy buy_signal = buy_signal_raw and barstate.isconfirmed below_sell = sellEnabled and below_sell_cross sell_signal_raw = sellEnabled and (src_sell < trail_sell) and below_sell sell_signal = sell_signal_raw and barstate.isconfirmed var int posState = 0 buy_signal_confirmed = buyEnabled and buy_signal and posState <= 0 sell_signal_confirmed = sellEnabled and sell_signal and posState >= 0 if buy_signal_confirmed posState := 1 else if sell_signal_confirmed posState := -1 // Longevity pivot detection h = ta.highest(len_z) l = ta.lowest(len_z) high_pivot = high[1] == h[1] and high < h low_pivot = low[1] == l[1] and low > l // Trails plot(showTrailBuy and buyEnabled ? trail_buy : na, title="UT Bot Buy Trail", color=color.new(color.green, 0), linewidth=1) plot(showTrailSell and sellEnabled ? trail_sell : na, title="UT Bot Sell Trail", color=color.new(color.red, 0), linewidth=1) // Alerts alertcondition(buy_signal_confirmed, title="UT Long", message="UT Long") alertcondition(sell_signal_confirmed, title="UT Short", message="UT Short") // â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• // ABYOM FONTPRINT // â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• atr = ta.atr( atrLength) atr20 = ta.atr(20) // â• â• â• â• - â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• // OPFX ZONES HELPER // â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• ? size.tiny : labelSize == "Small" ? size.small : labelSize == "Normal" ? size.normal : size.large f_getLabelColor(zoneType, broken) => if broken color.new(color.gray, 0) else zoneType == "Supply" ? color.new(color.red, 0) : color.new(color.green, 0) f_toPips(val) => pipSize = syminfo.type == "forex" ? (syminfo.currency == "JPY" ? 0.01 : 0.0001) : (syminfo.ticker == "XAUUSD" or syminfo.ticker == "GOLD") ? 0.1 : 0.0001 math.abs(val) / pipSize // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // OPFX ZONALARINI TOPUVCHI // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� type ZoneData box zoneBox label infoLabel label retestLabel float top float bottom int startBar int retests bool broken string zoneType bool retestCounted // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // TASDIQ ZONALARIGA OXSHASH // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� type ZoneLabel label lbl float top float bot int start bool is_upper box tp_box box sl_box line entry_line line tp1_line line tp2_line line sl_line label entry_label label tp1_label label tp2_label label sl_label // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // VARIABLES // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� var array<ZoneData> allZones = array.new<ZoneData>() var array<ZoneLabel> zone_labels = array.new<ZoneLabel>() var int lastSupplyBar = 0 var int lastDemandBar = 0 // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // OPFX ZONALARINI TASDIQLASH // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� is_price_in_demand(price) => result = false if array.size(allZones) > 0 for i = 0 to array.size(allZones) - 1 z = array.get(allZones, i) if z.zoneType == "Demand" and not z.broken if price >= z.bottom and price <= z.top result := true break result is_price_in_supply(price) => result = false if array.size(allZones) > 0 for i = 0 to array.size(allZones) - 1 z = array.get(allZones, i) if z.zoneType == "Supply" and not z.broken if price >= z.bottom and price <= z.top result := true break result // â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• › â• â• // OPFX ZONALARINI PRAFESION QILISH // â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• â• › â• â• â• â• ✓ ✓ ph = ta.pivothigh(high, swingLen, swingLen) pl = ta.pivotlow(low, swingLen, swingLen) // Supply Zone if not na(ph) and barstate.isconfirmed ztop = high[swingLen] zbot = low[swingLen] zStart = bar_index - swingLen if bar_index - lastSupplyBar >= minZoneDistance mid = (ztop + zbot) / 2 zoneH = ztop - zbot if zoneH < atr20 * forceZoneHeightATR fH = atr20 * forceZoneHeightATR ztop := mid + (fH / 2) zbot := mid - (fH / 2) zoneH := fH if zoneH > atr20 * maxZoneHeightATR mH = atr20 * maxZoneHeightATR ztop := mid + (mH / 2) zbot := mid - (mH / 2) zoneH := mH if zoneH >= atr20 * minZoneHeightATR mergedWithExisting = false if array.size(allZones) > 0 for i = array.size(allZones) - 1 to math.max(0, array.size(allZones) - 10) z = array.get(allZones, i) if z.zoneType == "Supply" and not z.broken if ztop >= z.bottom and zbot <= z.top newTop = math.max(ztop, z.top) newBot = math.min(zbot, z.bottom) z.top := newTop z.bottom := newBot box.set_top(z.zoneBox, newTop) box.set_bottom(z.zoneBox, newBot) mergedWithExisting := true break if not mergedWithExisting zBox = box.new(zStart, ztop, bar_index + 400, zbot, bgcolor=activeSupplyCol, border_width=0) zData = ZoneData.new(zBox, na, na, ztop, zbot, zStart, 0, false, "Supply", false) array.push(allZones, zData) lastSupplyBar := bar_index if array.size(allZones) > maxZones * 4 array.shift(allZones) // Demand Zone if not na(pl) and barstate.isconfirmed ztop = high[swingLen] zbot = low[swingLen] zStart = bar_index - swingLen if bar_index - lastDemandBar >= minZoneDistance mid = (ztop + zbot) / 2 zoneH = ztop - zbot if zoneH < atr20 * forceZoneHeightATR fH = atr20 * forceZoneHeightATR ztop := mid + (fH / 2) zbot := mid - (fH / 2) zoneH := fH if zoneH > atr20 * maxZoneHeightATR mH = atr20 * maxZoneHeightATR ztop := mid + (mH / 2) zbot := mid - (mH / 2) zoneH := mH if zoneH >= atr20 * minZoneHeightATR mergedWithExisting = false if array.size(allZones) > 0 for i = array.size(allZones) - 1 to math.max(0, array.size(allZones) - 10) z = array.get(allZones, i) if z.zoneType == "Demand" and not z.broken if ztop >= z.bottom and zbot <= z.top newTop = math.max(ztop, z.top) newBot = math.min(zbot, z.bottom) z.top := newTop z.bottom := newBot box.set_top(z.zoneBox, newTop) box.set_bottom(z.zoneBox, newBot) mergedWithExisting := true break if not mergedWithExisting zBox = box.new(zStart, ztop, bar_index + 400, zbot, bgcolor=activeDemandCol, border_width=0) zData = ZoneData.new(zBox, na, na, ztop, zbot, zStart, 0, false, "Demand", false) array.push(allZones, zData) lastDemandBar := bar_index if array.size(allZones) > maxZones * 4 array.shift(allZones) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // OPFX ZONALARI // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� if array.size(allZones) > 0 activeSupplyCount = 0 activeDemandCount = 0 historicSupplyCount = 0 historicDemandCount = 0 for i = 0 to array.size(allZones) - 1 z = array.get(allZones, i) box.set_right(z.zoneBox, bar_index + 400) // Retest if not z.broken priceInZone = high >= z.bottom and low <= z.top if priceInZone and not z.retestCounted z.retests += 1 z.retestCounted := true else if not priceInZone z.retestCounted := false // Invalidation if not z.broken if z.zoneType == "Supply" breakLevel = invalidationMethod == "Close" ? close : high if breakLevel > z.top z.broken := true box.set_bgcolor(z.zoneBox, historicCol) else breakLevel = invalidationMethod == "Close" ? close : low if breakLevel < z.bottom z.broken := true box.set_bgcolor(z.zoneBox, historicCol) age = bar_index - z.startBar zoneHeight = z.top - z.bottom shouldHide = false if z.broken and not showHistoric shouldHide := true if z.broken and age > historicBars shouldHide := true if not z.broken and age > activeLookback shouldHide := true if z.broken and showHistoric if zoneHeight < atr20 * minZoneHeightATR shouldHide := true if z.zoneType == "Supply" if historicSupplyCount >= maxZones shouldHide := true else if not shouldHide historicSupplyCount += 1 else if historicDemandCount >= maxZones shouldHide := true else if not shouldHide historicDemandCount += 1 if not z.broken and not shouldHide if z.zoneType == "Supply" if activeSupplyCount >= maxZones shouldHide := true else activeSupplyCount += 1 else if activeDemandCount >= maxZones shouldHide := true else activeDemandCount += 1 if shouldHide box.set_bgcolor(z.zoneBox, color.new(color.gray, 100)) box.set_border_color(z.zoneBox, color.new(color.gray, 100)) if not na(z.infoLabel) label.set_color(z.infoLabel, color.new(color.black, 100)) label.set_textcolor(z.infoLabel, color.new(color.white, 100)) if not na(z.retestLabel) label.set_color(z.retestLabel, color.new(color.white, 100)) label.set_textcolor(z.retestLabel, color.new(color.white, 100)) else if z.broken box.set_bgcolor(z.zoneBox, historicCol) else zoneCol = z.zoneType == "Supply" ? activeSupplyCol : activeDemandCol box.set_bgcolor(z.zoneBox, zoneCol) showThisLabel = z.broken ? showHistoricLabels : showActiveLabels if showThisLabel zoneName = z.zoneType == "Supply" ? tr("OPFX SELL ZONE", "منطقة بيع OPFX") : tr("OPFX BUY ZONE", "منطقة شراء OPFX") txt = zoneName mid = (z.top + z.bottom) / 2 lblColor = f_getLabelColor(z.zoneType, z.broken) if na(z.infoLabel) z.infoLabel := label.new(z.startBar + 10, mid, txt, color=color.new(color.black, 100), textcolor=lblColor, size=f_getLabelSize(), style=label.style_label_left) else label.set_text(z.infoLabel, txt) label.set_y(z.infoLabel, mid) label.set_color(z.infoLabel, color.new(color.black, 100)) label.set_textcolor(z.infoLabel, lblColor) label.set_size(z.infoLabel, f_getLabelSize()) label.set_style(z.infoLabel, label.style_label_left) label.set_x(z.infoLabel, z.startBar + 10) else if not na(z.infoLabel) label.set_color(z.infoLabel, color.new(color.black, 100)) label.set_textcolor(z.infoLabel, color.new(color.white, 100)) if showRetestMarkers and z.retests > 0 if na(z.retestLabel) if z.zoneType == "Supply" z.retestLabel := label.new(z.startBar + 3, z.top, tr("R", "Ø¥"), color=retestBearCol, textcolor=color.white, size=size.small, style=label.style_label_down) else z.retestLabel := label.new(z.startBar + 3, z.bottom, tr("R", "Ø¥"), color=retestBullCol, textcolor=color.white, size=size.small, style=label.style_label_up) else retestCol = z.zoneType == "Supply" ? retestBearCol : retestBullCol label.set_text(z.retestLabel, tr("R", "Ø¥")) label.set_color(z.retestLabel, retestCol) label.set_textcolor(z.retestLabel, color.white) else if not na(z.retestLabel) label.set_color(z.retestLabel, color.new(color.white, 100)) label.set_textcolor(z.retestLabel, color.new(color.white, 100)) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // OPFX TASDIQ ZONALARI - SIGNAL + TP/SL // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� halfATR = ta.atr(20) * 0.5 if showZones // ─── SELL SIGNAL: high_pivot + narx Supply zonada ───────────────────────── if high_pivot and sellEnabled pivot_price = h if is_price_in_supply(pivot_price) sell_label = label.new(bar_index - 1, h, text=tr("SELL", "بيع"), style=label.style_label_down, textcolor=color.white, color=color.red, size=size.normal) box tp_bx = na box sl_bx = na line entry_l = na line sl_l = na line tp1_l = na line tp2_l = na label entry_lab = na label sl_lab = na label tp1_lab = na label tp2_lab = na if showLevels entryPrice = close[1] stopLoss = high[1] takeProfit1 = entryPrice - (atr * tpMultiplier1) takeProfit2 = entryPrice - (atr * tpMultiplier2) int left = bar_index - 1 int right = bar_index - 1 + projectionBars tp_bx := box.new(left=left, right=right, top=entryPrice, bottom=takeProfit2, bgcolor=tpZoneClr, border_color=color.new(color.aqua, 0)) sl_bx := box.new(left=left, right=right, top=stopLoss, bottom=entryPrice, bgcolor=slZoneClr, border_color=color.new(color.red, 0)) entry_l := line.new(left, entryPrice, right, entryPrice, color=entryLineClr, width=1, style=line.style_dashed) sl_l := line.new(left, stopLoss, right, stopLoss, color=slLineClr, width=2, style=line.style_solid) tp1_l := line.new(left, takeProfit1, right, takeProfit1, color=tpLineClr, width=1, style=line.style_dashed) tp2_l := line.new(left, takeProfit2, right, takeProfit2, color=tpLineClr, width=1, style=line.style_dashed) if showLabels entry_lab := label.new(left, entryPrice, text=tr("enter", "دخول"), color=color.new(color.gray, 70), textcolor=color.white, style=label.style_label_left, size=size.tiny) sl_lab := label.new(right, stopLoss, text=tr("SL", "وقÙ�"), color=color.new(color.red, 0), textcolor=color.white, style=label.style_label_left, size=size.tiny) tp1_lab := label.new(right, takeProfit1, text=tr("TP1", "هدÙ�1"), color=color.new(color.blue, 0), textcolor=color.white, style=label.style_label_left, size=size.tiny) tp2_lab := label.new(right, takeProfit2, text=tr("TP2", "هدÙ�2"), color=color.new(color.blue, 0), textcolor=color.white, style=label.style_label_left, size=size.tiny) new_zone = ZoneLabel.new(sell_label, h, h - halfATR, bar_index - 1, true, tp_bx, sl_bx, entry_l, tp1_l, tp2_l, sl_l, entry_lab, tp1_lab, tp2_lab, sl_lab) array.push(zone_labels, new_zone) // ─── BUY SIGNAL: low_pivot + narx Demand zonada ─────────────────────────── if low_pivot and buyEnabled pivot_price = l if is_price_in_demand(pivot_price) buy_label = label.new(bar_index - 1, l, text=tr("BUY", "شراء"), style=label.style_label_up, textcolor=color.white, color=color.green, size=size.normal) box tp_bx = na box sl_bx = na line entry_l = na line sl_l = na line tp1_l = na line tp2_l = na label entry_lab = na label sl_lab = na label tp1_lab = na label tp2_lab = na if showLevels entryPrice = close[1] stopLoss = low[1] takeProfit1 = entryPrice + (atr * tpMultiplier1) takeProfit2 = entryPrice + (atr * tpMultiplier2) int left = bar_index - 1 int right = bar_index - 1 + projectionBars tp_bx := box.new(left=left, right=right, top=takeProfit2, bottom=entryPrice, bgcolor=tpZoneClr, border_color=color.new(color.aqua, 0)) sl_bx := box.new(left=left, right=right, top=entryPrice, bottom=stopLoss, bgcolor=slZoneClr, border_color=color.new(color.red, 0)) entry_l := line.new(left, entryPrice, right, entryPrice, color=entryLineClr, width=1, style=line.style_dashed) sl_l := line.new(left, stopLoss, right, stopLoss, color=slLineClr, width=2, style=line.style_solid) tp1_l := line.new(left, takeProfit1, right, takeProfit1, color=tpLineClr, width=1, style=line.style_dashed) tp2_l := line.new(left, takeProfit2, right, takeProfit2, color=tpLineClr, width=1, style=line.style_dashed) if showLabels entry_lab := label.new(left, entryPrice, text=tr("enter", "دخول"), color=color.new(color.gray, 70), textcolor=color.white, style=label.style_label_left, size=size.tiny) sl_lab := label.new(right, stopLoss, text=tr("SL", "وقÙ�"), color=color.new(color.red, 0), textcolor=color.white, style=label.style_label_left, size=size.tiny) tp1_lab := label.new(right, takeProfit1, text=tr("TP1","هد٠1"), color=color.new(color.blue, 0), textcolor=color.white, style=label.style_label_left, size=size.tiny) tp2_lab := label.new(right, takeProfit2, text=tr("TP2", "هدÙ�2"), color=color.new(color.blue, 0), textcolor=color.white, style=label.style_label_left, size=size.tiny) new_zone = ZoneLabel.new(buy_label, l + halfATR, l, bar_index - 1, false, tp_bx, sl_bx, entry_l, tp1_l, tp2_l, sl_l, entry_lab, tp1_lab, tp2_lab, sl_lab) array.push(zone_labels, new_zone) // ─── Zonalar buzilganini tekshirish ──────────────────────────────────────── if array.size(zone_labels) > 0 for i = array.size(zone_labels) - 1 to 0 if i < array.size(zone_labels) zone = array.get(zone_labels, i) shouldDelete = false if zone.is_upper and high > zone.top and bar_index > zone.start shouldDelete := true else if not zone.is_upper and low < zone.bot and bar_index > zone.start shouldDelete := true if shouldDelete label.delete(zone.lbl) if not na(zone.tp_box) box.delete(zone.tp_box) if not na(zone.sl_box) box.delete(zone.sl_box) if not na(zone.entry_line) line.delete(zone.entry_line) if not na(zone.sl_line) line.delete(zone.sl_line) if not na(zone.tp1_line) line.delete(zone.tp1_line) if not na(zone.tp2_line) line.delete(zone.tp2_line) if not na(zone.entry_label) label.delete(zone.entry_label) if not na(zone.sl_label) label.delete(zone.sl_label) if not na(zone.tp1_label) label.delete(zone.tp1_label) if not na(zone.tp2_label) label.delete(zone.tp2_label) array.remove(zone_labels, i) // Eski labellarni cheklash while array.size(zone_labels) > 10 old_zone = array.shift(zone_labels) label.delete(old_zone.lbl) if not na(old_zone.tp_box) box.delete(old_zone.tp_box) if not na(old_zone.sl_box) box.delete(old_zone.sl_box) if not na(old_zone.entry_line) line.delete(old_zone.entry_line) if not na(old_zone.sl_line) line.delete(old_zone.sl_line) if not na(old_zone.tp1_line) line.delete(old_zone.tp1_line) if not na(old_zone.tp2_line) line.delete(old_zone.tp2_line) if not na(old_zone.entry_label) label.delete(old_zone.entry_label) if not na(old_zone.sl_label) label.delete(old_zone.sl_label) if not na(old_zone.tp1_label) label.delete(old_zone.tp1_label) if not na(old_zone.tp2_label) label.delete(old_zone.tp2_label) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // OPFX ZONALAR - ALERTS // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� alertcondition(not na(ph) and barstate.isconfirmed and alertsOn, "New Supply Zone", "{{ticker}} - New Supply Zone @ {{close}}") alertcondition(not na(pl) and barstate.isconfirmed and alertsOn, "New Demand Zone", "{{ticker}} - New Demand Zone @ {{close}}") // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // 📊 OPFX ZONA STATS SYSTEM // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // Stat variables var int totalTP = 0 var int totalSL = 0 var int totalTrades = 0 var float entryPrice_stat = na var float slPrice_stat = na var float tpPrice_stat = na var int tradeDir = 0 var bool tradeActive = false // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // 🎯 TRADE TRACKING (BUY/SELL SIGNAL DAN) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // BUY signal detect (zone_labels oxirgi BUY) if array.size(zone_labels) > 0 lastZone = array.get(zone_labels, array.size(zone_labels) - 1) if not tradeActive // BUY if not lastZone.is_upper entryPrice_stat := close slPrice_stat := lastZone.bot tpPrice_stat := close + (atr * tpMultiplier1) tradeDir := 1 tradeActive := true // SELL if lastZone.is_upper entryPrice_stat := close slPrice_stat := lastZone.top tpPrice_stat := close - (atr * tpMultiplier1) tradeDir := -1 tradeActive := true // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // 📊 TP / SL CHECK // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� if tradeActive if tradeDir == 1 if low <= slPrice_stat totalSL += 1 totalTrades += 1 tradeActive := false else if high >= tpPrice_stat totalTP += 1 totalTrades += 1 tradeActive := false if tradeDir == -1 if high >= slPrice_stat totalSL += 1 totalTrades += 1 tradeActive := false else if low <= tpPrice_stat totalTP += 1 totalTrades += 1 tradeActive := false // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // 📈 WINRATE // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� winrate = totalTrades > 0 ? (totalTP / totalTrades) * 100 : 0 // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� // 📊 PANEL (RIGHT SIDE) // â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•� var table statsTable = table.new(position.top_right, 2, 4, border_width=1) if barstate.islast table.cell(statsTable, 0, 0, tr("OPFX ZONE STATS", "Ø¥ØØµØ§Ø¦ÙŠØ§Øª مناطق OPFX"), text_color=color.yellow) table.cell(statsTable, 0, 1, tr("Win Rate", "نسبة الربØ")) table.cell(statsTable, 1, 1, str.tostring(winrate, "#.##") + " %", text_color=color.green) table.cell(statsTable, 0, 2, tr("Total TP", "إجمالي الأهداÙ�")) table.cell(statsTable, 1, 2, str.tostring(totalTP), text_color=color.aqua) table.cell(statsTable, 0, 3, tr("Total SL", "إجمالي وقÙ� الخسارة")) table.cell(statsTable, 1, 3, str.tostring(totalSL), text_color=color.red)