//@version=6 // ╔══════════════════════════════════════════════════════════════════════════════╗ // ║ QC_MomentumConfluence v13.0 (v12 + level-1 fixes, 17 Sep 2026) ║ // ║ v13: Hurst R/S on LOG RETURNS (was on price levels → H≈0.91 always, ║ // ║ 'TREND' permanent, MR never) · sessions in America/New_York, LBMA ║ // ║ windows in Europe/London, CME window in New York (DST-safe) · ║ // ║ defaults = user's live H1 settings (TFH1 build) ║ // ║ Pine Script v6 | CE:0 RE:0 CW:0 | Standalone Pane ║ // ║ © Zeiierman (MLMI Core) | © QuantAlgo (QA Engine) | QC Integration ║ // ║ v5→v10 Upgrades: ║ // ║ ⑪ Ehlers Fisher Transform — Gaussian OB/OS at ±1.618φ ║ // ║ ⑫ Hurst Exponent Regime Meta — Trend/MR/Random regime background ║ // ║ ⑬ Adaptive SMI (Hilbert DC) — K period adapts to dominant cycle ║ // ║ ⑭ CVD Oscillator Normalized — Delta z-score + MLMI divergence ║ // ║ ── v11 FIXES & ENHANCEMENTS ──────────────────────────────────────────── ║ // ║ ⑮ Base TF selector — MLMI kNN now uses user-selectable TF (M5/15/H1/H4) ║ // ║ ⑯ Fisher OB/OS Level Lines — now actually plotted (were invisible in v10) ║ // ║ ⑰ Dynamic chart-TF labels — "M5" hardcode replaced with actual TF name ║ // ║ ── v12 (3-primitives momentum layer) ─────────────────────────────────── ║ // ║ ⑱ MOMENTUM STATE — Expansion/Fade + Fast-RSI (DISPLAY-ONLY, 0 budget): ║ // ║ EXPANDING = SMI accelerating (breakout/trend); FADING = SMI rolling ║ // ║ over ("exit when momentum disappears"); Fast-RSI(2) OB/OS = MR timing. ║ // ║ Corner table + pane markers (fade▼▲ / R-OB / R-OS). Label+table only ║ // ║ → no plots/fills/alerts added (QC hit RE10140 before). No signal/gate. ║ // ╚══════════════════════════════════════════════════════════════════════════════╝ indicator( title = "QC_MomentumConfluence v13.0 TFH1 | MLMI+SMI+MACD+QA+AMT+MTF+DIV+Delta+Fisher+Hurst+AdaptSMI+CVD+MomState", shorttitle= "QC_MoConf v13.0 TFH1", overlay = false, precision = 2, max_labels_count = 500, max_bars_back = 2000) import TradingView/ta/12 as taLib // ═══════════════════════════════════════════════════════════════════════════════ // §1 INPUTS // ═══════════════════════════════════════════════════════════════════════════════ var string G_MLMI = "① MLMI" numNeighbors = input.int(987, "Prediction Data (k)", group=G_MLMI, minval=10, maxval=2000) momentumWindow = input.int(10, "Trend Length", group=G_MLMI, step=2, minval=10, maxval=200) i_mlmi_cap = input.int(2500, "Max Stored Trades (perf cap)", group=G_MLMI, minval=300, maxval=10000, tooltip="RE-FIX: bounds the kNN trade memory so each instance (M5+H1+H4) cannot grow unbounded.\nKeeps the most-recent N crossover trades. Must be ≥ k. 2500 ≫ default k=200, so prediction is effectively unchanged while memory/exec-time stay bounded.") // v11 ⑮ — Base TF selector: MLMI kNN crossover detection + price reference uses this TF i_base_tf = input.timeframe("", "Base TF (blank=chart TF)", group=G_MLMI, tooltip="Leave blank to use the current chart timeframe (default).\nExamples: '5'=M5 '15'=M15 '60'=H1 '240'=H4\nOnly affects MLMI kNN crossovers and price reference.\nSMI, MACD, Fisher, Hurst, CVD continue to use chart close.") col_mlmi_pred = input.color(color.rgb(255, 0, 255, 0), "Prediction Line", group=G_MLMI) col_mlmi_wma = input.color(color.rgb(255, 255, 255, 0), "WMA Line", group=G_MLMI) col_mlmi_mid = input.color(color.new(color.gray,50), "Mid Level", group=G_MLMI) var string G_SMI = "② SMI" lengthK = input.int(10, "%K Length", group=G_SMI, minval=1) lengthD = input.int(3, "%D Length", group=G_SMI, minval=1) lengthEMA = input.int(3, "EMA Length", group=G_SMI, minval=1) col_smi_line = input.color(color.rgb(89, 255, 0, 0), "SMI Line", group=G_SMI) col_smi_ema = input.color(color.rgb(216, 255, 59, 0), "SMI EMA", group=G_SMI) col_smi_band = input.color(color.new(color.gray,50), "OB/OS Lines", group=G_SMI) var string G_MACD = "③ MACD" i_show_macd = input.bool(true, "Show MACD", group=G_MACD) fastLength = input.int(12, "Fast", group=G_MACD) slowLength = input.int(26, "Slow", group=G_MACD) signalLength = input.int(9, "Signal", group=G_MACD) col_macd = input.color(color.rgb(255, 255, 255, 0), "MACD Line", group=G_MACD) col_sig_macd = input.color(color.new(#FF6D00,0), "Signal Line", group=G_MACD) col_grow_above = input.color(color.new(#26A69A,50), "Hist GA", group=G_MACD) col_fall_above = input.color(color.new(#B2DFDB,50), "Hist FA", group=G_MACD) col_grow_below = input.color(color.new(#FFCDD2,50), "Hist GB", group=G_MACD) col_fall_below = input.color(color.new(#EF5350,50), "Hist FB", group=G_MACD) var string G_QA = "④ QA Volume Bubbles" qa_detect = input.string("Delta Only", "Detection", group=G_QA, options=["Volume Only", "Delta Only", "Volume + Delta", "Volume OR Delta"]) qa_classify = input.string("Delta Direction", "Classification", group=G_QA, options=["Candle Direction", "Delta Direction", "Both"]) qa_small_pct = input.float(86.0, "Small %ile", group=G_QA, step=1.0) qa_med_pct = input.float(93.0, "Medium %ile", group=G_QA, step=1.0) qa_big_pct = input.float(97.0, "Big %ile", group=G_QA, step=1.0) qa_consensus = input.string("Majority (2 of 3)","Consensus", group=G_QA, options=["Any Window","Majority (2 of 3)","All Windows (strictest)"]) qa_short_len = input.int(20, "Short Window", group=G_QA) qa_mid_len = input.int(50, "Medium Window", group=G_QA) qa_long_len = input.int(100, "Long Window", group=G_QA) qa_show_sm = input.bool(false, "Show Small", group=G_QA) qa_show_md = input.bool(false, "Show Medium", group=G_QA) qa_show_bg = input.bool(true, "Show Big", group=G_QA) qa_show_lbl = input.bool(true, "Show Numbers",group=G_QA) qa_c_buy = input.color(color.new(#00ffaa,40),"Buy Color", group=G_QA) qa_c_sell = input.color(color.new(#ff0000,20),"Sell Color", group=G_QA) qa_c_mix = input.color(color.new(#ffd600,30),"Mixed", group=G_QA) var string G_AMT = "⑤ AMT Bubbles" i_show_bub = input.bool(true, "Show AMT Bubbles", group=G_AMT) i_bub_lo = input.float(2.5, "Thr ASIA (xSMA50)", group=G_AMT, step=0.1) i_bub_hi = input.float(3.5, "Thr LON/NY (xSMA50)", group=G_AMT, step=0.1) i_bub_abs = input.bool(true, "Show Absorption", group=G_AMT) i_bub_acc = input.bool(true, "Show Acceptance", group=G_AMT) i_bub_cnt = input.bool(true, "Show Contrarian", group=G_AMT) i_bub_rej = input.bool(true, "Show Rejection", group=G_AMT) i_hl_rej = input.bool(true, "Highlight Rejection BG", group=G_AMT) i_wick_rej = input.float(0.40, "Rejection Wick %", group=G_AMT, step=0.05) i_wick_abs = input.float(0.15, "Absorption Wick %", group=G_AMT, step=0.05) i_vol_dom = input.float(1.50, "Volume Dom Ratio", group=G_AMT, step=0.10) i_show_ice = input.bool(true, "Show Iceberg/VWAP Rej", group=G_AMT) var string G_MTF = "⑥ MTF OB/OS" i_mtf_en = input.bool(true, "Enable MTF", group=G_MTF) i_mtf_tf1 = input.timeframe("240", "Higher TF 1 (H1)", group=G_MTF) i_mtf_tf2 = input.timeframe("1D", "Higher TF 2 (H4)", group=G_MTF) i_mtf_k = input.int(89, "MTF kNN k", group=G_MTF, minval=5, maxval=200) i_mtf_mw = input.int(34, "MTF Momentum Window", group=G_MTF, minval=5) i_mtf_lbl = input.bool(false, "Show Labels", group=G_MTF) i_mtf_offset = input.float(0.15,"Label Offset (%)", group=G_MTF, step=0.05, minval=0.0) col_mtf_c0 = input.color(color.new(#FF9800,95),"Single OB", group=G_MTF) col_mtf_c1 = input.color(color.new(#FF6F00,90),"Double OB", group=G_MTF) col_mtf_c2 = input.color(color.new(#FF1744,82),"Triple OB", group=G_MTF) col_mtf_c3 = input.color(color.new(#00E676,82),"Triple OS", group=G_MTF) col_mtf_c4 = input.color(color.new(#00BCD4,90),"Double OS", group=G_MTF) col_mtf_c5 = input.color(color.new(#4CAF50,95),"Single OS", group=G_MTF) var string G_DIV = "⑦ Divergence" i_div_en = input.bool(true, "Enable Divergence", group=G_DIV) i_div_lb = input.int(5, "Pivot Lookback", group=G_DIV, minval=2, maxval=20) i_div_show_lbl = input.bool(true, "Show Labels", group=G_DIV) col_div_bear = input.color(color.new(#FF1744,0),"Bear Div",group=G_DIV) col_div_bull = input.color(color.new(#00E676,0),"Bull Div",group=G_DIV) var string G_SESS = "⑧ Session + Fix" i_show_sess = input.bool(true, "Show Session BG", group=G_SESS) i_show_fix = input.bool(true, "Show Fix Window", group=G_SESS) i_utc = input.int(0, "Extra hour offset (normally 0)", group=G_SESS, minval=-2, maxval=2) col_sess_asia= input.color(color.new(#607D8B,96),"ASIA", group=G_SESS) col_sess_lon = input.color(color.new(#00BCD4,97),"LON", group=G_SESS) col_sess_ny = input.color(color.new(#FF9800,97),"NY", group=G_SESS) col_fix_win = input.color(color.new(#FFD700,88),"Fix", group=G_SESS) var string G_DTBL = "⑨ Delta / Volume Table" i_dtbl_en = input.bool(false, "Show Table", group=G_DTBL) i_dtbl_n = input.int(20, "Bars to display", group=G_DTBL, minval=5, maxval=40) i_dtbl_pos = input.string("middle_right","Position", group=G_DTBL, options=["middle_right","middle_left","middle_center","bottom_right","bottom_left","bottom_center"]) i_dtbl_sz = input.string("Tiny","Cell Text Size", group=G_DTBL, options=["Tiny","Small"]) i_dtbl_cum_lb = input.int(100, "Cum Delta Lookback (bars)", group=G_DTBL, minval=10, maxval=500) i_dtbl_thresh = input.float(1.5, "Highlight Threshold (x stdev)", group=G_DTBL, step=0.1) i_dtbl_sess_reset = input.bool(true, "Reset CumDelta at session open", group=G_DTBL, tooltip="Resets at London+NY open. OFF = accumulates from indicator load.") i_dtbl_show_mx = input.bool(true, "Show MaxDelta / MinDelta rows", group=G_DTBL) i_dtbl_show_v = input.bool(true, "Show Volume row", group=G_DTBL) i_dtbl_show_r = input.bool(true, "Show Dlt/Vol% row", group=G_DTBL) col_dtbl_pos = input.color(color.new(#00E676,0), "Positive Color", group=G_DTBL) col_dtbl_neg = input.color(color.new(#FF1744,0), "Negative Color", group=G_DTBL) col_dtbl_neu = input.color(color.new(#607D8B,0), "Neutral Color", group=G_DTBL) var string G_SIG = "⑩ Delta Signal Labels" i_sig_en = input.bool(true, "Enable Signal Labels", group=G_SIG) i_sig_thresh = input.float(5.0, "Delta Threshold", group=G_SIG, step=0.5, minval=0.0, tooltip="BUY: OS_H4 + CumDelta>thr + MaxDlt>thr + MinDlt>-thr\nSELL: OB_H4 + CumDelta<-thr + MinDlt<-thr + MaxDlt)", group=G_HURST, step=0.05, minval=0.50, maxval=0.85) i_hurst_mr_thr = input.float(0.40, "Mean-Rev Threshold (H <)", group=G_HURST, step=0.05, minval=0.20, maxval=0.50) col_hurst_trend = input.color(color.new(#00E676,94), "Trending BG", group=G_HURST) col_hurst_mr = input.color(color.new(#00BCD4,94), "Mean-Rev BG", group=G_HURST) col_hurst_rand = input.color(color.new(#607D8B,97), "Random BG", group=G_HURST) var string G_ASMI = "⑬ Adaptive SMI (Hilbert DC)" i_asmi_en = input.bool(true, "Enable Adaptive SMI K Period", group=G_ASMI, tooltip="Uses Ehlers Homodyne Discriminator to adapt SMI K length to the dominant market cycle.\nFast market (DC~15) → K~7. Slow market (DC~40) → K~20.\nD and EMA lengths stay fixed.") i_asmi_k_mult = input.float(0.50, "K Period Multiplier (×DC)", group=G_ASMI, step=0.05, minval=0.20, maxval=1.50, tooltip="Adaptive K = round(DC × this). Default 0.5 = half the dominant cycle.") i_asmi_d_mult = input.float(0.10, "D Period Multiplier (×DC)", group=G_ASMI, step=0.01, minval=0.05, maxval=0.30, tooltip="Adaptive D = round(DC × this). Default 0.1 = one-tenth the cycle.") i_asmi_show_dc= input.bool(true, "Show DC Period Label", group=G_ASMI) var string G_CVD = "⑭ CVD Oscillator (Normalized)" i_cvd_en = input.bool(true, "Enable CVD Oscillator", group=G_CVD, tooltip="Normalizes per-bar delta as z-score. Shows buying/selling pressure relative to recent history.") i_cvd_len = input.int(50, "Z-Score Lookback (bars)", group=G_CVD, minval=10, maxval=200) i_cvd_div_thr = input.float(0.5, "Divergence Threshold (|Z|>)", group=G_CVD, step=0.1, minval=0.2, maxval=2.0, tooltip="CVD/MLMI divergence shown when |CVD z-score| exceeds this AND MLMI direction conflicts.") i_cvd_show_div = input.bool(false, "Highlight MLMI/CVD Divergence", group=G_CVD) col_cvd_pos = input.color(color.new(#00E676,50), "Positive CVD", group=G_CVD) col_cvd_neg = input.color(color.new(#FF1744,50), "Negative CVD", group=G_CVD) col_cvd_div = input.color(color.new(#FFD700,0), "Divergence Color",group=G_CVD) // ═══════════════════════════════════════════════════════════════════════════════ // §2 HELPER FUNCTIONS // ═══════════════════════════════════════════════════════════════════════════════ emaEma(float src, int len) => ta.ema(ta.ema(src, len), len) f_qa_fmtn(float v) => float av = math.abs(v) string sg = v < 0.0 ? "-" : "" string r = sg + str.tostring(av,"#") if av >= 1000000000.0 r := sg + str.tostring(av/1000000000.0,"#.##") + "B" else if av >= 1000000.0 r := sg + str.tostring(av/1000000.0,"#.##") + "M" else if av >= 1000.0 r := sg + str.tostring(av/1000.0,"#.##") + "K" r f_qa_cons(bool pS, bool pM, bool pL, string mode) => int hits = (pS?1:0)+(pM?1:0)+(pL?1:0) switch mode "Any Window" => hits >= 1 "All Windows (strictest)" => hits >= 3 => hits >= 2 f_qa_detect(bool vHit, bool dHit, string method) => switch method "Volume Only" => vHit "Delta Only" => dHit "Volume + Delta" => vHit and dHit => vHit or dHit f_dtbl_fmt(float v) => float av = math.abs(v) string sg = v < 0.0 ? "-" : "+" string r = sg + str.tostring(av,"#") if av >= 1000000.0 r := sg + str.tostring(av/1000000.0,"#.#") + "M" else if av >= 1000.0 r := sg + str.tostring(av/1000.0,"#.#") + "K" r f_dtbl_fmtv(float v) => float av = math.abs(v) string r = str.tostring(av,"#") if av >= 1000000.0 r := str.tostring(av/1000000.0,"#.#") + "M" else if av >= 1000.0 r := str.tostring(av/1000.0,"#.#") + "K" r // Hurst Exponent via R/S (Rescaled Range) Analysis f_hurst(float src, int len) => // v13: rescaled range of LOG RETURNS of src (v12 ran R/S on the price LEVEL, which is an integrated series → // H saturated at ≈0.91 on 99.8% of bars, even on a synthetic random walk). Same formula as Gold Session. float _mean = 0.0 for _k = 0 to len - 1 _mean += nz(math.log(src[_k] / src[_k + 1])) _mean /= float(len) float _max_dev = -1e20 float _min_dev = 1e20 float _cum = 0.0 float _sq_sum = 0.0 for _i = 0 to len - 1 float _dev = nz(math.log(src[_i] / src[_i + 1])) - _mean _cum += _dev _max_dev := math.max(_max_dev, _cum) _min_dev := math.min(_min_dev, _cum) _sq_sum += _dev * _dev float _std = math.sqrt(math.max(_sq_sum / float(len), 0.0)) float _rs = _std > 0.0 ? (_max_dev - _min_dev) / _std : na (na(_rs) or _rs <= 0.0 or len <= 2) ? 0.5 : math.log(_rs) / math.log(float(len)) // v11 ⑰ — convert timeframe string to readable label f_tf_name(string tf) => switch tf "1" => "M1" "3" => "M3" "5" => "M5" "15" => "M15" "30" => "M30" "45" => "M45" "60" => "H1" "120" => "H2" "180" => "H3" "240" => "H4" "D" => "D1" "W" => "W1" "M" => "MN" => tf // ═══════════════════════════════════════════════════════════════════════════════ // §3 SESSION + FIX WINDOW // ═══════════════════════════════════════════════════════════════════════════════ // v13: session boundaries are NEW YORK clock times (Asia 20:00–02:59 = Tokyo day · London 03:00–07:59 · NY 08:00–16:59); // v12 read them as UTC (no DST, US afternoon 17:00–20:00 UTC fell into "ASIA"). LBMA windows in London time, CME in NY. int _hm = (hour(time,"America/New_York") + i_utc)*100 + minute(time,"America/New_York") int _hm_ldn = (hour(time,"Europe/London") + i_utc)*100 + minute(time,"Europe/London") bool _s_asia = _hm >= 2000 or _hm < 300 bool _s_lon = _hm >= 300 and _hm < 800 bool _s_ny = _hm >= 800 and _hm < 2000 bool _in_am = _hm_ldn >= 1000 and _hm_ldn < 1030 bool _in_pm = _hm_ldn >= 1500 and _hm_ldn < 1515 bool _in_cme = _hm >= 1320 and _hm < 1330 bool _in_fix = _in_am or _in_pm or _in_cme string _fix_nm = _in_am ? "LBMA AM" : _in_pm ? "LBMA PM" : _in_cme ? "CME NY" : "" float _bub_thr = _s_asia ? i_bub_lo : i_bub_hi // ═══════════════════════════════════════════════════════════════════════════════ // §3b HILBERT TRANSFORM — DOMINANT CYCLE (Ehlers Homodyne Discriminator) // Used by §5 Adaptive SMI and §13f CVD Z-score context // ═══════════════════════════════════════════════════════════════════════════════ var float _ht10_smooth = 0.0 var float _ht10_dtr = 0.0 var float _ht10_I1 = 0.0 var float _ht10_Q1 = 0.0 var float _ht10_jI = 0.0 var float _ht10_jQ = 0.0 var float _ht10_I2 = 0.0 var float _ht10_Q2 = 0.0 var float _ht10_Re = 0.0 var float _ht10_Im = 0.0 var float _ht10_per = 20.0 var float _ht10_dc = 20.0 float _htc = 0.075 * nz(_ht10_dc, 20.0) + 0.54 _ht10_smooth := (4.0*close + 3.0*nz(close[1]) + 2.0*nz(close[2]) + nz(close[3])) / 10.0 _ht10_dtr := (0.0962*_ht10_smooth + 0.5769*nz(_ht10_smooth[2]) - 0.5769*nz(_ht10_smooth[4]) - 0.0962*nz(_ht10_smooth[6])) * _htc _ht10_I1 := nz(_ht10_dtr[3]) _ht10_Q1 := (0.0962*_ht10_dtr + 0.5769*nz(_ht10_dtr[2]) - 0.5769*nz(_ht10_dtr[4]) - 0.0962*nz(_ht10_dtr[6])) * _htc _ht10_jI := (0.0962*_ht10_I1 + 0.5769*nz(_ht10_I1[2]) - 0.5769*nz(_ht10_I1[4]) - 0.0962*nz(_ht10_I1[6])) * _htc _ht10_jQ := (0.0962*_ht10_Q1 + 0.5769*nz(_ht10_Q1[2]) - 0.5769*nz(_ht10_Q1[4]) - 0.0962*nz(_ht10_Q1[6])) * _htc _ht10_I2 := 0.2*(_ht10_I1 - _ht10_jQ) + 0.8*nz(_ht10_I2[1]) _ht10_Q2 := 0.2*(_ht10_Q1 + _ht10_jI) + 0.8*nz(_ht10_Q2[1]) _ht10_Re := 0.2*(_ht10_I2*nz(_ht10_I2[1]) + _ht10_Q2*nz(_ht10_Q2[1])) + 0.8*nz(_ht10_Re[1]) _ht10_Im := 0.2*(_ht10_I2*nz(_ht10_Q2[1]) - _ht10_Q2*nz(_ht10_I2[1])) + 0.8*nz(_ht10_Im[1]) if _ht10_Im != 0.0 and _ht10_Re != 0.0 _ht10_per := 2.0 * math.acos(-1.0) / math.atan(_ht10_Im / _ht10_Re) if _ht10_per > 1.5 * nz(_ht10_per[1], 20.0) _ht10_per := 1.5 * nz(_ht10_per[1], 20.0) if _ht10_per < 0.67 * nz(_ht10_per[1], 20.0) _ht10_per := 0.67 * nz(_ht10_per[1], 20.0) _ht10_per := math.max(6.0, math.min(50.0, _ht10_per)) _ht10_dc := 0.2 * _ht10_per + 0.8 * nz(_ht10_dc[1]) int _dc10 = math.max(6, math.min(50, math.round(_ht10_dc))) // Adaptive SMI parameters derived from DC int smi_k_eff = i_asmi_en ? math.max(3, math.min(50, math.round(float(_dc10) * i_asmi_k_mult))) : lengthK int smi_d_eff = i_asmi_en ? math.max(2, math.min(10, math.round(float(_dc10) * i_asmi_d_mult))) : lengthD // ═══════════════════════════════════════════════════════════════════════════════ // §3c BASE TF DATA — v11 ⑮ // Fetches MLMI kNN inputs from user-selected base TF via request.security. // When i_base_tf="" the effective TF equals timeframe.period (no change). // ═══════════════════════════════════════════════════════════════════════════════ string _btf = i_base_tf == "" ? timeframe.period : i_base_tf [_b_close, _b_maq, _b_mas, _b_rq, _b_rs] = request.security( syminfo.tickerid, _btf, [close, ta.wma(close, 5), ta.wma(close, 20), ta.wma(ta.rsi(close, 5), momentumWindow), ta.wma(ta.rsi(close, 20), momentumWindow)], barmerge.gaps_off, barmerge.lookahead_off) // Dynamic display name for base TF (used in labels, replaces hardcoded "M5") string _tf0_display = f_tf_name(_btf) // ═══════════════════════════════════════════════════════════════════════════════ // §4 MLMI CORE // ═══════════════════════════════════════════════════════════════════════════════ // Uses base TF data (_b_*) — defaults to chart close when i_base_tf="" float MA_quick = _b_maq float MA_slow = _b_mas float rsi_quick = _b_rq float rsi_slow = _b_rs bool pos = ta.crossover(_b_maq, _b_mas) bool neg = ta.crossunder(_b_maq, _b_mas) type MLMIData array parameter1 array parameter2 array priceArray array resultArray var mlmi_d = MLMIData.new( array.new_float(1,0.0), array.new_float(1,0.0), array.new_float(1,0.0), array.new_float(1,0.0)) method storeTrade(MLMIData d, float p1, float p2, float p_price) => d.parameter1.push(d.parameter1.get(d.parameter1.size()-1)) d.parameter2.push(d.parameter2.get(d.parameter2.size()-1)) d.priceArray.push(d.priceArray.get(d.priceArray.size()-1)) d.resultArray.push(p_price >= d.priceArray.get(d.priceArray.size()-1) ? 1.0 : -1.0) d.parameter1.set(d.parameter1.size()-1, p1) d.parameter2.set(d.parameter2.size()-1, p2) d.priceArray.set(d.priceArray.size()-1, p_price) // RE-FIX ①: bound memory — drop oldest trades beyond cap (keeps recent regime) int _cap = math.max(i_mlmi_cap, 300) if d.parameter1.size() > _cap d.parameter1.shift() d.parameter2.shift() d.priceArray.shift() d.resultArray.shift() method knnPredict(MLMIData d, float p1, float p2, int k) => distances = array.new_float(0) int n = d.parameter1.size()-1 for i = 0 to n distances.push(math.sqrt(math.pow(p1-d.parameter1.get(i),2.0)+math.pow(p2-d.parameter2.get(i),2.0))) sortedD = distances.copy() sortedD.sort() float mx = sortedD.slice(0, math.min(k, sortedD.size())).max() nb = array.new_float(0) for i = 0 to distances.size()-1 if distances.get(i) <= mx nb.push(d.resultArray.get(i)) nb.sum() if pos or neg mlmi_d.storeTrade(rsi_slow, rsi_quick, _b_close) float prediction = mlmi_d.knnPredict(rsi_slow, rsi_quick, numNeighbors) float prediction_ma = ta.wma(prediction, 20) float upper = ta.highest(prediction, 2000) float lower = ta.lowest(prediction, 2000) float upper_ = upper - ta.ema(ta.stdev(prediction,20),20) float lower_ = lower + ta.ema(ta.stdev(prediction,20),20) float pane_range = upper - lower bool cur_ob = prediction >= upper_ bool cur_os = prediction <= lower_ // ═══════════════════════════════════════════════════════════════════════════════ // §5 SMI // ═══════════════════════════════════════════════════════════════════════════════ // Adaptive K: loop-based highest/lowest (supports variable length) // RE-FIX ③: nz fallback → current bar value (neutral for max/min) so missing // history on early bars cannot collapse _lL_ad to 0 (price-domain garbage) float _hH_ad = high float _lL_ad = low if i_asmi_en and smi_k_eff > 1 for _ki = 1 to smi_k_eff - 1 _hH_ad := math.max(_hH_ad, nz(high[_ki], high)) _lL_ad := math.min(_lL_ad, nz(low[_ki], low)) float hH = i_asmi_en ? _hH_ad : ta.highest(high, lengthK) float lL = i_asmi_en ? _lL_ad : ta.lowest(low, lengthK) float hLR = hH - lL float relRange = close - (hH+lL)/2.0 float _eer = emaEma(relRange, lengthD) float _eeh = emaEma(hLR, lengthD) float smi_raw = (hLR > 0.0 and _eeh != 0.0) ? 200.0*(_eer/_eeh) : 0.0 float smi_e_raw= ta.ema(smi_raw, lengthEMA) float smi_sp = upper_/40.0 float smi_sn = lower_/-40.0 float smi_sc = smi_raw > 0.0 ? smi_raw *smi_sp : smi_raw *smi_sn float smi_esc = smi_e_raw> 0.0 ? smi_e_raw*smi_sp : smi_e_raw*smi_sn // ═══════════════════════════════════════════════════════════════════════════════ // §6 MACD // ═══════════════════════════════════════════════════════════════════════════════ float mf = ta.ema(close, fastLength) float ms = ta.ema(close, slowLength) float macd_raw = mf - ms float sig_raw = ta.ema(macd_raw, signalLength) float hist_raw = macd_raw - sig_raw float mx_m = ta.highest(math.abs(macd_raw),200) float _mx = na(mx_m) or mx_m==0.0 ? 1.0 : mx_m float msp = upper*0.8 float msn = math.abs(lower)*0.8 float macd_sc = macd_raw > 0.0 ? (macd_raw/_mx)*msp : (macd_raw/_mx)*msn float sig_sc = sig_raw > 0.0 ? (sig_raw /_mx)*msp : (sig_raw /_mx)*msn float hist_sc = hist_raw > 0.0 ? (hist_raw/_mx)*msp : (hist_raw/_mx)*msn color hist_col = hist_sc>=0.0 ? (hist_sc[1] "1S" timeframe.isintraday => "1" timeframe.isdaily => "5" => "60" [_, _, _, qa_last_d] = taLib.requestVolumeDelta(_qa_ltf) bool qa_dok = not na(qa_last_d) float qa_nd = nz(qa_last_d) float qa_ad = math.abs(qa_nd) float vSS=ta.percentile_linear_interpolation(volume,qa_short_len,qa_small_pct) float vSM=ta.percentile_linear_interpolation(volume,qa_mid_len, qa_small_pct) float vSL=ta.percentile_linear_interpolation(volume,qa_long_len, qa_small_pct) float vMS=ta.percentile_linear_interpolation(volume,qa_short_len,qa_med_pct) float vMM=ta.percentile_linear_interpolation(volume,qa_mid_len, qa_med_pct) float vML=ta.percentile_linear_interpolation(volume,qa_long_len, qa_med_pct) float vBS=ta.percentile_linear_interpolation(volume,qa_short_len,qa_big_pct) float vBM=ta.percentile_linear_interpolation(volume,qa_mid_len, qa_big_pct) float vBL=ta.percentile_linear_interpolation(volume,qa_long_len, qa_big_pct) float dSS=ta.percentile_linear_interpolation(qa_ad,qa_short_len,qa_small_pct) float dSM=ta.percentile_linear_interpolation(qa_ad,qa_mid_len, qa_small_pct) float dSL=ta.percentile_linear_interpolation(qa_ad,qa_long_len, qa_small_pct) float dMS=ta.percentile_linear_interpolation(qa_ad,qa_short_len,qa_med_pct) float dMM=ta.percentile_linear_interpolation(qa_ad,qa_mid_len, qa_med_pct) float dML=ta.percentile_linear_interpolation(qa_ad,qa_long_len, qa_med_pct) float dBS=ta.percentile_linear_interpolation(qa_ad,qa_short_len,qa_big_pct) float dBM=ta.percentile_linear_interpolation(qa_ad,qa_mid_len, qa_big_pct) float dBL=ta.percentile_linear_interpolation(qa_ad,qa_long_len, qa_big_pct) bool qa_vbig = f_qa_cons(volume>=vBS,volume>=vBM,volume>=vBL,qa_consensus) bool qa_vmed = not qa_vbig and f_qa_cons(volume>=vMS,volume>=vMM,volume>=vML,qa_consensus) bool qa_vsm = not qa_vbig and not qa_vmed and f_qa_cons(volume>=vSS,volume>=vSM,volume>=vSL,qa_consensus) bool qa_dbig = f_qa_cons(qa_ad>=dBS,qa_ad>=dBM,qa_ad>=dBL,qa_consensus) bool qa_dmed = not qa_dbig and f_qa_cons(qa_ad>=dMS,qa_ad>=dMM,qa_ad>=dML,qa_consensus) bool qa_dsm = not qa_dbig and not qa_dmed and f_qa_cons(qa_ad>=dSS,qa_ad>=dSM,qa_ad>=dSL,qa_consensus) string qa_em = qa_dok ? qa_detect : "Volume Only" bool qa_big = f_qa_detect(qa_vbig, qa_dbig, qa_em) bool qa_med = not qa_big and f_qa_detect(qa_vmed or qa_vbig, qa_dmed or qa_dbig, qa_em) bool qa_small = not qa_big and not qa_med and f_qa_detect(qa_vsm or qa_vmed or qa_vbig, qa_dsm or qa_dmed or qa_dbig, qa_em) bool qa_is_buy = switch qa_classify "Candle Direction" => close >= open "Delta Direction" => qa_dok ? qa_nd > 0.0 : close >= open => qa_dok ? (close >= open and qa_nd > 0.0) : close >= open bool qa_is_sell = switch qa_classify "Candle Direction" => close < open "Delta Direction" => qa_dok ? qa_nd < 0.0 : close < open => qa_dok ? (close < open and qa_nd < 0.0) : close < open bool qa_vs = qa_small and qa_show_sm bool qa_vm = qa_med and qa_show_md bool qa_vb = qa_big and qa_show_bg bool qa_av = qa_vs or qa_vm or qa_vb float qa_y = na if qa_av if qa_is_sell qa_y := upper else if qa_is_buy qa_y := lower else qa_y := 0.0 color qa_col = qa_is_buy ? qa_c_buy : qa_is_sell ? qa_c_sell : qa_c_mix float qa_avol = ta.sma(volume, qa_mid_len) float qa_ratio = qa_avol > 0.0 ? volume / qa_avol : 0.0 // ═══════════════════════════════════════════════════════════════════════════════ // §8 ICEBERG + VWAP REJECTION // ═══════════════════════════════════════════════════════════════════════════════ float _vma50 = ta.sma(volume, 50) float _mass = _vma50 > 0.0 ? volume/_vma50 : 1.0 float _mmean = ta.vwma(close, 50) float _mdev = ta.stdev(close, 50)*1.5 float _mvah = _mmean + _mdev float _mval = _mmean - _mdev float _tolz = _mdev*0.1 bool _ice_vah = math.abs(close-_mvah)<=_tolz and _mass>1.8 and close<=_mvah bool _ice_val = math.abs(close-_mval)<=_tolz and _mass>1.8 and close>=_mval bool _rej_top = high>_mvah and close<_mvah and not _ice_vah bool _rej_bot = low <_mval and close>_mval and not _ice_val bool _is_ice = _ice_vah or _ice_val // ═══════════════════════════════════════════════════════════════════════════════ // §9 AMT BUBBLE PATTERN ENGINE // ═══════════════════════════════════════════════════════════════════════════════ float _brng = math.max(high-low, syminfo.mintick) float _bwup = (high-math.max(close,open))/_brng float _bwdn = (math.min(close,open)-low)/_brng float _bbvol = volume*((close-low)/_brng) float _bsvol = volume*((high-close)/_brng) bool _bbull = close >= open bool _bact = i_show_bub and volume > _vma50*_bub_thr string _apat = "" float _ay = na color _acol = na string _atxt = "●" string _astl = label.style_label_center bool _rej_bull = false bool _rej_bear = false if _bact if _bbull if i_bub_rej and _bwup >= i_wick_rej _apat:="REJECTION SELL" _ay:=upper _acol:=color.new(#9C27B0,0) _atxt:="▼" _astl:=label.style_label_down _rej_bear:=true else if i_bub_cnt and _bsvol>_bbvol*(i_vol_dom*0.8) and _bwup>=i_wick_abs _apat:="ABS CONTRARIAN" _ay:=0.0 _acol:=color.new(#009688,0) _astl:=label.style_label_center else if i_bub_abs and _bbvol>_bsvol*i_vol_dom and _bwdn>=i_wick_abs _apat:="ABSORPTION BUY" _ay:=lower _acol:=color.new(#7B1FA2,20) _atxt:="▲" _astl:=label.style_label_up else if i_bub_acc _apat:="ACCEPTANCE BUY" _ay:=lower+math.abs(lower)*0.15 _acol:=color.new(#00BCD4,0) _atxt:="▲" _astl:=label.style_label_up else if i_bub_rej and _bwdn >= i_wick_rej _apat:="REJECTION BUY" _ay:=lower _acol:=color.new(#009688,0) _atxt:="▲" _astl:=label.style_label_up _rej_bull:=true else if i_bub_cnt and _bbvol>_bsvol*(i_vol_dom*0.8) and _bwdn>=i_wick_abs _apat:="ABS CONTRARIAN" _ay:=0.0 _acol:=color.new(#9C27B0,0) _astl:=label.style_label_center else if i_bub_abs and _bsvol>_bbvol*i_vol_dom and _bwup>=i_wick_abs _apat:="ABSORPTION SELL" _ay:=upper _acol:=color.new(#00BCD4,60) _atxt:="▼" _astl:=label.style_label_down else if i_bub_acc _apat:="ACCEPTANCE SELL" _ay:=upper-upper*0.15 _acol:=color.new(#E91E63,0) _atxt:="▼" _astl:=label.style_label_down // ═══════════════════════════════════════════════════════════════════════════════ // §10 MTF MLMI // ═══════════════════════════════════════════════════════════════════════════════ [c1,maq1,mas1,rq1,rs1] = request.security(syminfo.tickerid, i_mtf_tf1, [close,ta.wma(close,5),ta.wma(close,20),ta.wma(ta.rsi(close,5),i_mtf_mw),ta.wma(ta.rsi(close,20),i_mtf_mw)], barmerge.gaps_off, barmerge.lookahead_off) [c2,maq2,mas2,rq2,rs2] = request.security(syminfo.tickerid, i_mtf_tf2, [close,ta.wma(close,5),ta.wma(close,20),ta.wma(ta.rsi(close,5),i_mtf_mw),ta.wma(ta.rsi(close,20),i_mtf_mw)], barmerge.gaps_off, barmerge.lookahead_off) var mlmi_tf1 = MLMIData.new(array.new_float(1,0.0),array.new_float(1,0.0),array.new_float(1,0.0),array.new_float(1,0.0)) var mlmi_tf2 = MLMIData.new(array.new_float(1,0.0),array.new_float(1,0.0),array.new_float(1,0.0),array.new_float(1,0.0)) bool pos1 = ta.crossover(maq1,mas1) bool neg1 = ta.crossunder(maq1,mas1) if pos1 or neg1 mlmi_tf1.storeTrade(rs1, rq1, c1) bool pos2 = ta.crossover(maq2,mas2) bool neg2 = ta.crossunder(maq2,mas2) if pos2 or neg2 mlmi_tf2.storeTrade(rs2, rq2, c2) float pred1 = mlmi_tf1.knnPredict(rs1, rq1, i_mtf_k) float up1 = ta.highest(pred1, 2000) float lo1 = ta.lowest(pred1, 2000) float up1_ = up1 - ta.ema(ta.stdev(pred1,200),200) float lo1_ = lo1 + ta.ema(ta.stdev(pred1,200),200) float pred2 = mlmi_tf2.knnPredict(rs2, rq2, i_mtf_k) float up2 = ta.highest(pred2, 2000) float lo2 = ta.lowest(pred2, 2000) float up2_ = up2 - ta.ema(ta.stdev(pred2,200),200) float lo2_ = lo2 + ta.ema(ta.stdev(pred2,200),200) bool mtf1_ob = not na(pred1) and not na(up1_) and pred1 >= up1_ bool mtf1_os = not na(pred1) and not na(lo1_) and pred1 <= lo1_ bool mtf2_ob = not na(pred2) and not na(up2_) and pred2 >= up2_ bool mtf2_os = not na(pred2) and not na(lo2_) and pred2 <= lo2_ // MTF Confluence: Base TF + up to 2 higher TFs // Single = Base TF only // Double = Base TF + exactly ONE of TF1 / TF2 // Triple = Base TF + TF1 + TF2 (all three aligned) bool mtf_ob_any = i_mtf_en and cur_ob bool mtf_ob_double = i_mtf_en and cur_ob and (mtf1_ob or mtf2_ob) and not (mtf1_ob and mtf2_ob) bool mtf_ob_triple = i_mtf_en and cur_ob and mtf1_ob and mtf2_ob bool mtf_os_any = i_mtf_en and cur_os bool mtf_os_double = i_mtf_en and cur_os and (mtf1_os or mtf2_os) and not (mtf1_os and mtf2_os) bool mtf_os_triple = i_mtf_en and cur_os and mtf1_os and mtf2_os float _ds = pane_range*0.12 float _ob_m5 = upper-(_ds*0.5) float _ob_h1 = upper-(_ds*1.5) float _ob_h4 = upper-(_ds*2.5) float _os_m5 = lower+(_ds*0.5) float _os_h1 = lower+(_ds*1.5) float _os_h4 = lower+(_ds*2.5) float _lbl_off = pane_range*i_mtf_offset float _ob_y = upper+_lbl_off float _os_y = lower-_lbl_off // Dynamic TF names for MTF labels string _tf1n = f_tf_name(i_mtf_tf1) string _tf2n = f_tf_name(i_mtf_tf2) // ═══════════════════════════════════════════════════════════════════════════════ // §11 DIVERGENCE // ═══════════════════════════════════════════════════════════════════════════════ float _ph = ta.pivothigh(high, i_div_lb, i_div_lb) float _pl = ta.pivotlow(low, i_div_lb, i_div_lb) var float _prev_ph = na var float _prev_mlmi_ph = na var float _prev_pl = na var float _prev_mlmi_pl = na bool _bear_div = false bool _bull_div = false if not na(_ph) float _mlmi_at_ph = prediction[i_div_lb] if not na(_prev_ph) and not na(_prev_mlmi_ph) _bear_div := _ph > _prev_ph and _mlmi_at_ph < _prev_mlmi_ph _prev_ph := _ph _prev_mlmi_ph := _mlmi_at_ph if not na(_pl) float _mlmi_at_pl = prediction[i_div_lb] if not na(_prev_pl) and not na(_prev_mlmi_pl) _bull_div := _pl < _prev_pl and _mlmi_at_pl > _prev_mlmi_pl _prev_pl := _pl _prev_mlmi_pl := _mlmi_at_pl bool div_bear = i_div_en and _bear_div bool div_bull = i_div_en and _bull_div float _div_bear_y = div_bear ? prediction[i_div_lb] : na float _div_bull_y = div_bull ? prediction[i_div_lb] : na // ═══════════════════════════════════════════════════════════════════════════════ // §12 DELTA TABLE — DATA // ═══════════════════════════════════════════════════════════════════════════════ // CONFIRMED BARS — use taLib delta (accurate, updates on bar close) // LIVE BAR (col 0) — ALWAYS use wick proxy (updates every tick, real-time) // Reason: taLib.requestVolumeDelta returns last CLOSED LTF bar delta // → appears frozen between LTF closes (up to 1 min lag on M5) // Wick proxy updates on every price tick → true real-time for live column float _wbrng = math.max(high - low, syminfo.mintick) float _wbvol = volume * ((close - low) / _wbrng) // estimated buy volume float _wsvol = volume * ((high - close) / _wbrng) // estimated sell volume // Confirmed bar delta (taLib when available) float _bar_dlt = qa_dok ? nz(qa_last_d) : _wbvol - _wsvol float _bar_maxd = _wbvol // max buy pressure proxy float _bar_mind = -_wsvol // max sell pressure proxy (negative) // Live bar delta (wick proxy — updates every tick) float _live_dlt = _wbvol - _wsvol float _live_maxd = _wbvol float _live_mind = -_wsvol float _live_vol = volume // Rolling arrays for confirmed bars var array _dt_dlt = array.new_float(0) var array _dt_maxd = array.new_float(0) var array _dt_mind = array.new_float(0) var array _dt_vol = array.new_float(0) var array _dt_cumd = array.new_float(0) var float _dt_cum = 0.0 var int _dt_sess = -1 // Session reset for CumDelta int _sess_now = _s_lon ? 2 : _s_ny ? 3 : 1 if i_dtbl_sess_reset and _sess_now != _dt_sess and (_sess_now == 2 or _sess_now == 3) _dt_cum := 0.0 _dt_sess := _sess_now // Push confirmed bar data if barstate.isconfirmed _dt_cum += _bar_dlt array.push(_dt_dlt, _bar_dlt) array.push(_dt_maxd, _bar_maxd) array.push(_dt_mind, _bar_mind) array.push(_dt_vol, volume) array.push(_dt_cumd, _dt_cum) int _keep = math.max(i_dtbl_n, i_dtbl_cum_lb) + 10 if array.size(_dt_dlt) > _keep array.shift(_dt_dlt) array.shift(_dt_maxd) array.shift(_dt_mind) array.shift(_dt_vol) array.shift(_dt_cumd) // Live CumDelta (confirmed sum + current wick proxy) float _live_cum = _dt_cum + _live_dlt // ═══════════════════════════════════════════════════════════════════════════════ // §13 DELTA SIGNAL LOGIC // ═══════════════════════════════════════════════════════════════════════════════ // BUY: OS_TF2 + CumDelta > thresh + MaxDlt > thresh + MinDlt > -thresh // SELL: OB_TF2 + CumDelta < -thresh + MinDlt < -thresh + MaxDlt < thresh // Uses live values so signal reacts to current bar real-time bool _sig_buy = i_sig_en and i_sig_show_b and mtf2_os and _live_cum > i_sig_thresh and _live_maxd > i_sig_thresh and _live_mind > -i_sig_thresh bool _sig_sell = i_sig_en and i_sig_show_s and mtf2_ob and _live_cum < -i_sig_thresh and _live_mind < -i_sig_thresh and _live_maxd < i_sig_thresh // ═══════════════════════════════════════════════════════════════════════════════ // §13b SMI CONFLUENCE SIGNAL // ═══════════════════════════════════════════════════════════════════════════════ // BUY: Triple OS + SMI crosses above SMI EMA + both below prediction & prediction_ma // SELL: Triple OB + SMI crosses below SMI EMA + both above prediction & prediction_ma bool _smi_xup = ta.crossover(smi_sc, smi_esc) bool _smi_xdn = ta.crossunder(smi_sc, smi_esc) bool _smi_below_mlmi = smi_sc < prediction and smi_sc < prediction_ma and smi_esc < prediction and smi_esc < prediction_ma bool _smi_above_mlmi = smi_sc > prediction and smi_sc > prediction_ma and smi_esc > prediction and smi_esc > prediction_ma bool _conf_buy = mtf_os_triple and _smi_xup and _smi_below_mlmi bool _conf_sell = mtf_ob_triple and _smi_xdn and _smi_above_mlmi // ═══════════════════════════════════════════════════════════════════════════════ // §13c EHLERS FISHER TRANSFORM // ═══════════════════════════════════════════════════════════════════════════════ var float _fish_val1 = 0.0 float _fish_hi = ta.highest(close, i_fish_len) float _fish_lo = ta.lowest(close, i_fish_len) float _fish_rng = math.max(_fish_hi - _fish_lo, syminfo.mintick) float _fish_raw = 2.0 * ((close - _fish_lo) / _fish_rng - 0.5) _fish_val1 := math.max(math.min(0.33 * _fish_raw + 0.67 * nz(_fish_val1[1]), 0.999), -0.999) var float _fisher = 0.0 _fisher := 0.5 * math.log((1.0 + _fish_val1) / (1.0 - _fish_val1)) + 0.5 * nz(_fisher[1]) float _fish_trig = nz(_fisher[1]) // Scale to MLMI pane range (Fisher ≈ ±3 maps to ±60% of pane) float _fish_sc_pos = upper * 0.6 float _fish_sc_neg = math.abs(lower) * 0.6 float _fish_sc = i_fish_en ? (_fisher > 0.0 ? _fisher / 3.0 * _fish_sc_pos : _fisher / 3.0 * _fish_sc_neg) : na float _fish_trig_sc = i_fish_en ? (_fish_trig > 0.0 ? _fish_trig / 3.0 * _fish_sc_pos : _fish_trig / 3.0 * _fish_sc_neg) : na // v11 ⑯ — OB/OS level lines: computed and now actually plotted (were invisible hlines in v10) float _fish_ob_sc = (i_fish_ob / 3.0) * _fish_sc_pos float _fish_os_sc = (i_fish_os / 3.0) * _fish_sc_neg // i_fish_os negative, _fish_sc_neg positive → result negative // Fisher crossover signals bool _fish_bull_cross = ta.crossover(_fish_sc, _fish_trig_sc) bool _fish_bear_cross = ta.crossunder(_fish_sc, _fish_trig_sc) bool _fish_ob_zone = i_fish_en and _fisher >= i_fish_ob bool _fish_os_zone = i_fish_en and _fisher <= i_fish_os // Fisher Double Confirmation signals bool _fish_conf_buy = i_fish_en and _fish_bull_cross and _fish_os_zone and cur_os bool _fish_conf_sell = i_fish_en and _fish_bear_cross and _fish_ob_zone and cur_ob // ═══════════════════════════════════════════════════════════════════════════════ // §13d HURST EXPONENT // ═══════════════════════════════════════════════════════════════════════════════ float _hurst_h = i_hurst_en ? f_hurst(close, i_hurst_len) : 0.5 bool _hurst_trend = i_hurst_en and _hurst_h > i_hurst_trend_thr bool _hurst_mr = i_hurst_en and _hurst_h < i_hurst_mr_thr bool _hurst_rand = i_hurst_en and not _hurst_trend and not _hurst_mr string _hurst_regime = _hurst_trend ? "TREND" : _hurst_mr ? "MR" : "RANDOM" color _hurst_bg_col = _hurst_trend ? col_hurst_trend : _hurst_mr ? col_hurst_mr : col_hurst_rand // Regime change detection bool _hurst_trend_new = _hurst_trend and not _hurst_trend[1] bool _hurst_mr_new = _hurst_mr and not _hurst_mr[1] bool _hurst_rand_new = _hurst_rand and not _hurst_rand[1] // ═══════════════════════════════════════════════════════════════════════════════ // §13e CVD OSCILLATOR — NORMALIZED (z-score of per-bar wick-weighted delta) // Re-uses _bar_dlt (from §12) — no new RS call needed // ═══════════════════════════════════════════════════════════════════════════════ float _cvd_mean = ta.sma(_bar_dlt, i_cvd_len) float _cvd_std = ta.stdev(_bar_dlt, i_cvd_len) float _cvd_z = i_cvd_en and _cvd_std > 0.0 ? (_bar_dlt - _cvd_mean) / _cvd_std : 0.0 // Scale CVD z-score to MLMI pane (±3σ maps to ±15% of pane range) float _cvd_scale = pane_range * 0.15 / 3.0 float _cvd_sc = i_cvd_en ? _cvd_z * _cvd_scale : na // MLMI/CVD Divergence // Bear div: MLMI bullish (prediction > prediction_ma) but CVD is negative and strong // Bull div: MLMI bearish (prediction < prediction_ma) but CVD is positive and strong bool _cvd_div_bear = i_cvd_en and i_cvd_show_div and prediction > prediction_ma and _cvd_z < -i_cvd_div_thr bool _cvd_div_bull = i_cvd_en and i_cvd_show_div and prediction < prediction_ma and _cvd_z > i_cvd_div_thr color _cvd_bar_col = _cvd_div_bear ? col_cvd_div : _cvd_div_bull ? col_cvd_div : _cvd_z >= 0.0 ? col_cvd_pos : col_cvd_neg // ═══════════════════════════════════════════════════════════════════════════════ // §14 PLOTS // ═══════════════════════════════════════════════════════════════════════════════ // RE10140-FIX ①: 5 series-color bgcolor() calls (10u) merged into 1 (2u). All 5 // conditions preserved; overlapping backgrounds now resolve by priority instead of // transparency-stacking. Priority: Fix > Rejection > MTF stack > Hurst > Session. bgcolor( i_show_fix and _in_fix ? col_fix_win : i_hl_rej and _rej_bull ? color.new(#009688,85) : i_hl_rej and _rej_bear ? color.new(#9C27B0,85) : mtf_ob_triple ? col_mtf_c2 : mtf_ob_double ? col_mtf_c1 : mtf_ob_any ? col_mtf_c0 : mtf_os_triple ? col_mtf_c3 : mtf_os_double ? col_mtf_c4 : mtf_os_any ? col_mtf_c5 : i_hurst_en and i_hurst_show_bg ? _hurst_bg_col : i_show_sess and _s_asia ? col_sess_asia : i_show_sess and _s_lon ? col_sess_lon : i_show_sess and _s_ny ? col_sess_ny : na, title="Confluence BG (merged)") pred_plot = plot(prediction, "MLMI Prediction", color=col_mlmi_pred) plot(prediction_ma, "MLMI WMA", color=col_mlmi_wma) hline(0, "Mid Level", color=col_mlmi_mid) ch_u = plot(upper, color=na, editable=false, display=display.none) ch_l = plot(lower, color=na, editable=false, display=display.none) ch_m = plot(0, color=na, editable=false, display=display.none) // RE10140-FIX ⑤: Upper/Lower channel fills flattened gradient→flat (range already spanned // full half-pane, so visual is near-identical). 2u → saves 2u toward the 64u budget. fill(ch_m, ch_u, color=color.new(color.lime,80), title="Upper Fill") fill(ch_m, ch_l, color=color.new(color.red,80), title="Lower Fill") fill(pred_plot, ch_m, top_value=upper, bottom_value=upper_, top_color=color.new(color.lime,0), bottom_color=color.new(color.green,100), title="OB Gradient") fill(pred_plot, ch_m, top_value=lower_, bottom_value=lower, top_color=color.new(color.red,100), bottom_color=color.new(color.red,0), title="OS Gradient") smi_ob_p = plot(upper_, "SMI OB", color=col_smi_band, display=display.none) smi_os_p = plot(lower_, "SMI OS", color=col_smi_band, display=display.none) fill(smi_ob_p, smi_os_p, title="SMI BG", color=color.new(color.blue,95)) smi_p = plot(smi_sc, "SMI Line", color=col_smi_line, linewidth=1) smi_ep= plot(smi_esc, "SMI EMA", color=col_smi_ema, linewidth=1) // RE10140-FIX ⑥: 2 SMI band gradient fills (4u) merged into 1 sign-based fill (2u). // Green above mid / red below mid — clean filled-oscillator look, saves 2u. fill(smi_p, ch_m, color=smi_sc >= 0.0 ? color.new(#4caf4f,75) : color.new(color.red,75), title="SMI Fill") plot(i_show_macd ? hist_sc : na, "MACD Hist", style=plot.style_columns, color=hist_col, display=display.none) plot(i_show_macd ? macd_sc : na, "MACD Line", color=col_macd, linewidth=1, style=plot.style_columns) plot(i_show_macd ? sig_sc : na, "Signal Line", color=col_sig_macd, linewidth=1, display=display.none) // RE10140-FIX ②: QA volume bubbles → label drawings (free of 64u plot budget). // Tier preserved via label size. Note: labels are capped at max_labels_count=500, // so on very deep history only the most-recent bubbles render (fine for live M5). if qa_vs or qa_vm or qa_vb label.new(bar_index, qa_y, "", yloc=yloc.price, style=label.style_circle, color=qa_col, size=(qa_vb ? size.huge : qa_vm ? size.large : size.normal)) // RE10140-FIX ③: Iceberg / rejection markers → label drawings (free of 64u budget; // these were text-bearing plotshapes = 2u each). Same glyphs, same y-anchors. if i_show_ice and _is_ice label.new(bar_index, 0.0, "Ice", yloc=yloc.price, style=label.style_label_up, color=color.new(color.white,100), textcolor=color.new(#00BCD4,0), size=size.small) if i_show_ice and _rej_top label.new(bar_index, upper, "🟨", yloc=yloc.price, style=label.style_label_down, color=color.new(color.white,100), textcolor=color.new(#FFD700,0), size=size.small) if i_show_ice and _rej_bot label.new(bar_index, lower, "🟨", yloc=yloc.price, style=label.style_label_up, color=color.new(color.white,100), textcolor=color.new(#FFD700,0), size=size.small) plotshape(i_mtf_en and cur_ob ? _ob_m5 : na, "Base OB", shape.circle, location.absolute, color.new(#FF5252,0), size=size.tiny, display=display.none) plotshape(i_mtf_en and mtf1_ob ? _ob_h1 : na, "TF1 OB", shape.circle, location.absolute, color.new(#FF1744,0), size=size.tiny, display=display.none) plotshape(i_mtf_en and mtf2_ob ? _ob_h4 : na, "TF2 OB", shape.circle, location.absolute, color.new(#B71C1C,0), size=size.tiny, display=display.none) plotshape(i_mtf_en and cur_os ? _os_m5 : na, "Base OS", shape.circle, location.absolute, color.new(#69F0AE,0), size=size.tiny, display=display.none) plotshape(i_mtf_en and mtf1_os ? _os_h1 : na, "TF1 OS", shape.circle, location.absolute, color.new(#00E676,0), size=size.tiny, display=display.none) plotshape(i_mtf_en and mtf2_os ? _os_h4 : na, "TF2 OS", shape.circle, location.absolute, color.new(#00796B,0), size=size.tiny, display=display.none) // v11 ⑯ — Fisher OB/OS Level Lines: now rendered via plot() (were invisible hlines in v10) // i_fish_show_lvl toggle controls visibility correctly plot(i_fish_en and i_fish_show_lvl ? _fish_ob_sc : na, "Fisher OB Level", color=color.new(col_fish_ob, 30), linewidth=2, style=plot.style_line) plot(i_fish_en and i_fish_show_lvl ? _fish_os_sc : na, "Fisher OS Level", color=color.new(col_fish_ob, 30), linewidth=2, style=plot.style_line) // Fisher plots p_fish = plot(i_fish_en ? _fish_sc : na, "Fisher", color=col_fish_line, linewidth=1, display=display.none) p_fish_trg = plot(i_fish_en ? _fish_trig_sc : na, "FishTrig", color=col_fish_trig, linewidth=1, display=display.none) fill(p_fish, p_fish_trg, color=_fish_bull_cross ? color.new(col_fish_line,85) : _fish_bear_cross ? color.new(col_fish_trig,85) : na, title="Fisher Fill") // RE10140-FIX ④: Fisher OB/OS zone-entry markers → label drawings (free of 64u budget). // Drawn on the Fisher line (_fish_sc) at the entry bar; fires only on zone transition. if i_fish_en and i_fish_show_lvl and _fish_ob_zone and not _fish_ob_zone[1] label.new(bar_index, _fish_sc, "", yloc=yloc.price, style=label.style_circle, color=color.new(col_fish_ob,0), size=size.tiny) if i_fish_en and i_fish_show_lvl and _fish_os_zone and not _fish_os_zone[1] label.new(bar_index, _fish_sc, "", yloc=yloc.price, style=label.style_circle, color=color.new(col_fish_ob,0), size=size.tiny) // CVD Oscillator plot plot(i_cvd_en ? _cvd_sc : na, "CVD Z-Score", style=plot.style_columns, color=_cvd_bar_col, linewidth=1, display=display.none) // ═══════════════════════════════════════════════════════════════════════════════ // §15 LABELS // ═══════════════════════════════════════════════════════════════════════════════ if qa_av and qa_show_lbl string _fv = f_qa_fmtn(volume) string _fd = f_qa_fmtn(qa_nd) int _qlvl= qa_vb?3:qa_vm?2:1 string _qls = _qlvl==3?"BIG":_qlvl==2?"MEDIUM":"SMALL" string _qss = qa_is_buy?"BUY":qa_is_sell?"SELL":"MIXED" bool _dpS = _qlvl==3?qa_ad>=dBS:_qlvl==2?qa_ad>=dMS:qa_ad>=dSS bool _dpM = _qlvl==3?qa_ad>=dBM:_qlvl==2?qa_ad>=dMM:qa_ad>=dSM bool _dpL = _qlvl==3?qa_ad>=dBL:_qlvl==2?qa_ad>=dML:qa_ad>=dSL string _dw = (_dpS?"S":"·")+" "+(_dpM?"M":"·")+" "+(_dpL?"L":"·") string _tip = "── "+_qls+" "+_qss+" ──\nVol: "+_fv+"\nDelta: "+(qa_dok?_fd:"n/a")+"\nRatio: "+str.tostring(qa_ratio,"#.##")+"x\nWindows: ["+_dw+"]\nFix: "+(_in_fix?_fix_nm:"none")+" Sess: "+(_s_lon?"LON":_s_ny?"NY":"ASIA") label.new(bar_index, qa_y, _fv, style=label.style_label_center, color=color.new(chart.fg_color,100), textcolor=chart.fg_color, size=size.small, tooltip=_tip) var array