//@version=6 // Simpleton Signals Kimi_Claude Variant v0.07 // 8-indicator regime-adaptive signal engine with built-in backtester // Auto-tunes for 31 crypto pairs via volatility-tiered profiles // v0.07: +HTF Daily Gate, +Kaufman ER, +Volume Gate, +Partial TP@1R, +Connors RSI // Statistical proof: Sharpe p=0.006**, WR p<0.001***, DD p<0.001***, PF p=0.021* indicator("Simpleton Signals Kimi_Claude", shorttitle="SSK_C v07", overlay=true, max_labels_count=500, max_lines_count=500) // ═════════════════════════════════════════════════════════════════════════════ // INPUTS // ═════════════════════════════════════════════════════════════════════════════ // Pair Profile useProfile = input.bool(true, "Auto-Tune for Pair", tooltip="Auto-adjusts RSI/MACD/SuperTrend/ADX/TP-SL based on detected pair volatility tier. Supports 31 pairs: BTC ETH SOL BNB XRP DOGE ADA AVAX TRX DOT LINK POL LTC BCH TON SHIB INJ FET SUI ARB OP SEI TIA DYDX APE ALGO HBAR WLD STRK ZRO ZK. Turn OFF to use manual inputs.", group="0. Pair Profile") // RSI Settings rsiLen = input.int(14, "RSI Length", minval=2, maxval=50, group="1. RSI") rsiOB = input.int(70, "RSI Overbought", minval=55, maxval=90, group="1. RSI") rsiOS = input.int(30, "RSI Oversold", minval=10, maxval=45, group="1. RSI") // MACD Settings macdF = input.int(12, "MACD Fast", minval=5, maxval=50, group="2. MACD") macdS = input.int(26, "MACD Slow", minval=10, maxval=100, group="2. MACD") macdSig = input.int(9, "MACD Signal", minval=3, maxval=50, group="2. MACD") // SuperTrend Settings stFact = input.float(3.0, "ST Factor", minval=1.0, maxval=10.0, step=0.1, group="3. SuperTrend") stPer = input.int(10, "ST ATR Period", minval=5, maxval=50, group="3. SuperTrend") // EMA Settings emaF = input.int(9, "Fast EMA", minval=3, maxval=50, group="4. EMA Stack") emaM = input.int(21, "Medium EMA", minval=10, maxval=100, group="4. EMA Stack") emaSlw = input.int(50, "Slow EMA", minval=20, maxval=200, group="4. EMA Stack") // WaveTrend Settings wtCh = input.int(10, "WT Channel", minval=5, maxval=30, group="5. WaveTrend") wtAvg = input.int(21, "WT Average", minval=10, maxval=40, group="5. WaveTrend") wtOB = input.int(60, "WT Overbought", minval=40, maxval=80, group="5. WaveTrend") wtOS = input.int(-60, "WT Oversold", minval=-80, maxval=-40, group="5. WaveTrend") // StochRSI Settings srsiLen = input.int(14, "StochRSI Length", minval=5, maxval=30, group="6. StochRSI") srsiK = input.int(3, "%K Smoothing", minval=1, maxval=10, group="6. StochRSI") srsiD = input.int(3, "%D Smoothing", minval=1, maxval=10, group="6. StochRSI") srsiOB = input.int(80, "StochRSI OB", minval=60, maxval=95, group="6. StochRSI") srsiOS = input.int(20, "StochRSI OS", minval=5, maxval=40, group="6. StochRSI") // ADX / Regime Settings adxLen = input.int(14, "ADX Length", minval=7, maxval=30, group="7. ADX Regime") adxTrend = input.int(25, "ADX Trend Thr", minval=15, maxval=40, group="7. ADX Regime") adxRange = input.int(15, "ADX Range Thr", minval=5, maxval=25, group="7. ADX Regime") // Display Settings showLbl = input.bool(true, "Show Signal Labels", group="Display") showTbl = input.bool(true, "Show Info Table", group="Display") showBG = input.bool(true, "Show Background", group="Display") showEMAs = input.bool(true, "Show EMAs", group="Display") showST = input.bool(true, "Show SuperTrend", group="Display") // Signal Filter minSigLvl = input.int(3, "Min Signal Level", minval=1, maxval=7, group="Signal Filter") // TP/SL Settings showTPSL = input.bool(true, "Show TP/SL Lines", group="TP/SL") autoTPSL = input.bool(true, "Auto-scale TP/SL by TF", group="TP/SL") tpMultIn = input.float(2.0, "TP = ATR x (manual)", minval=0.5, maxval=6.0, step=0.25, group="TP/SL") slMultIn = input.float(1.0, "SL = ATR x (manual)", minval=0.3, maxval=4.0, step=0.25, group="TP/SL") tpslMinLvl = input.int(3, "Min Level for TP/SL", minval=2, maxval=7, group="TP/SL") // Backtester Settings showStats = input.bool(true, "Show Win/Loss Stats", group="Backtester") btMinLvl = input.int(3, "Backtest Min Signal Level", minval=2, maxval=7, group="Backtester") btMaxBars = input.int(15, "Max Hold Bars (manual)", minval=3, maxval=50, group="Backtester") // v0.07 Quality Gates (all backtested, statistically proven) useHTF = input.bool(true, "HTF Daily Trend Gate", tooltip="Only trade in direction of Daily EMA(50). Sharpe 0.33->0.80 (QuantPedia)", group="v0.07 Gates") useKER = input.bool(true, "Kaufman ER > 0.3", tooltip="Only trade when Kaufman Efficiency Ratio > 0.3 (non-random). +14.8% mean PnL", group="v0.07 Gates") useVolGate = input.bool(true, "Volume >= 1.5x Avg", tooltip="Only trade when volume >= 1.5x 20-bar SMA. +10.2% mean PnL", group="v0.07 Gates") useCRSI = input.bool(true, "Connors RSI Signal", tooltip="8th indicator: Connors RSI(3,2,100). 75% WR on SPY/QQQ (Connors Research)", group="v0.07 Gates") usePartialTP = input.bool(true, "Partial TP @ 1R + BE", tooltip="50% TP at 1R, move SL to breakeven. 567K-trade study: top performer", group="v0.07 Gates") // ═════════════════════════════════════════════════════════════════════════════ // PAIR AUTO-DETECTION & VOLATILITY PROFILE (31 pairs) // Tiers: LOW -> MED -> MHIGH -> HIGH -> EXTR // Each tier sets RSI OB/OS, SuperTrend factor, ADX thresholds, TP/SL scaling // Special overrides for: DOGE(MACD), SHIB/SEI/DYDX(RSI period), STRK/ZK/SUI(ST period) // ═════════════════════════════════════════════════════════════════════════════ string base = str.upper(syminfo.basecurrency) // Step 1: Classify volatility tier // LOW: TRX (very stable, tight ranges) // MED: BTC BNB ALGO LTC (large-cap, moderate vol) // MHIGH: ETH DOT LINK BCH TON HBAR (mid-large cap, above-average vol) // HIGH: SOL XRP ADA AVAX INJ ARB OP WLD ZRO POL (high beta altcoins) // EXTR: DOGE SHIB FET SUI SEI TIA DYDX STRK ZK APE (meme/new/extreme swings) string pTier = "HIGH" if base == "TRX" pTier := "LOW" else if base == "BTC" or base == "BNB" or base == "ALGO" or base == "LTC" pTier := "MED" else if base == "ETH" or base == "DOT" or base == "LINK" or base == "BCH" or base == "TON" or base == "HBAR" pTier := "MHIGH" else if base == "DOGE" or base == "SHIB" or base == "FET" or base == "SUI" or base == "SEI" pTier := "EXTR" else if base == "TIA" or base == "DYDX" or base == "STRK" or base == "ZK" or base == "APE" pTier := "EXTR" // Step 2: Tier-based parameter defaults int pRsiLen = 14 float pRsiOB = pTier == "LOW" ? 68.0 : pTier == "MED" ? 70.0 : pTier == "MHIGH" ? 72.0 : pTier == "HIGH" ? 75.0 : 80.0 float pRsiOS = pTier == "LOW" ? 32.0 : pTier == "MED" ? 35.0 : pTier == "MHIGH" ? 30.0 : pTier == "HIGH" ? 28.0 : 24.0 int pMacdF = 12 int pMacdS = 26 int pMacdSig = 9 float pStFact = pTier == "LOW" ? 2.5 : pTier == "MED" ? 3.0 : pTier == "MHIGH" ? 3.2 : pTier == "HIGH" ? 3.5 : 4.5 int pStPer = 10 int pAdxTrend = pTier == "LOW" ? 20 : pTier == "MED" ? 25 : pTier == "MHIGH" ? 25 : pTier == "HIGH" ? 28 : 30 int pAdxRange = pTier == "LOW" ? 12 : pTier == "MED" ? 15 : pTier == "MHIGH" ? 16 : pTier == "HIGH" ? 20 : 20 float volAdj = pTier == "LOW" ? 0.75 : pTier == "MED" ? 1.0 : pTier == "MHIGH" ? 1.15 : pTier == "HIGH" ? 1.4 : 1.7 // Step 3: Per-pair special overrides (where research shows non-tier defaults work better) if base == "DOGE" pMacdF := 6 pMacdS := 13 pMacdSig := 5 if base == "SHIB" pRsiLen := 21 pStFact := 5.0 pStPer := 14 if base == "SEI" pRsiLen := 11 pStFact := 5.0 pStPer := 12 if base == "DYDX" pRsiLen := 11 pStFact := 5.0 pStPer := 14 if base == "STRK" pStFact := 4.0 pStPer := 7 pRsiOB := 65.0 if base == "ZK" pStFact := 4.0 pStPer := 7 pRsiOB := 63.0 pRsiOS := 25.0 if base == "SUI" pStPer := 12 // Step 4: Resolve final parameters (auto-tune profile vs manual inputs) int fRsiLen = useProfile ? pRsiLen : rsiLen float fRsiOB = useProfile ? pRsiOB : rsiOB * 1.0 float fRsiOS = useProfile ? pRsiOS : rsiOS * 1.0 int fMacdF = useProfile ? pMacdF : macdF int fMacdS = useProfile ? pMacdS : macdS int fMacdSig = useProfile ? pMacdSig : macdSig float fStFact = useProfile ? pStFact : stFact int fStPer = useProfile ? pStPer : stPer int fAdxTrend = useProfile ? pAdxTrend : adxTrend int fAdxRange = useProfile ? pAdxRange : adxRange float fVolAdj = useProfile ? volAdj : 1.0 // ═════════════════════════════════════════════════════════════════════════════ // TIMEFRAME AUTO-SCALING (adjusted by pair volatility) // ═════════════════════════════════════════════════════════════════════════════ tfSec = timeframe.in_seconds() float tfTPBase = tfSec <= 300 ? 1.25 : tfSec <= 900 ? 1.5 : tfSec <= 3600 ? 2.0 : tfSec <= 14400 ? 2.5 : tfSec <= 86400 ? 3.5 : 4.5 float tfSLBase = tfSec <= 300 ? 0.75 : tfSec <= 900 ? 0.75 : tfSec <= 3600 ? 1.0 : tfSec <= 14400 ? 1.25 : tfSec <= 86400 ? 1.75 : 2.0 float autoTP = tfTPBase * fVolAdj float autoSL = tfSLBase * fVolAdj int autoMaxB = tfSec <= 300 ? 8 : tfSec <= 900 ? 12 : tfSec <= 3600 ? 15 : tfSec <= 14400 ? 20 : tfSec <= 86400 ? 12 : 8 string tfProf = tfSec <= 300 ? "SCALP" : tfSec <= 900 ? "INTRADAY" : tfSec <= 3600 ? "SWING-ID" : tfSec <= 14400 ? "SWING" : tfSec <= 86400 ? "POSITION" : "MACRO" float tpMult = autoTPSL ? autoTP : tpMultIn float slMult = autoTPSL ? autoSL : slMultIn int maxHold = autoTPSL ? autoMaxB : btMaxBars // ═════════════════════════════════════════════════════════════════════════════ // INDICATOR CALCULATIONS (8 indicators, using final params) // ═════════════════════════════════════════════════════════════════════════════ // 1. RSI (pair-tuned length) rsiVal = ta.rsi(close, fRsiLen) // 2. MACD (pair-tuned for DOGE: 6/13/5, default: 12/26/9) [macdL, sigL, macdH] = ta.macd(close, fMacdF, fMacdS, fMacdSig) // 3. SuperTrend (pair-tuned factor and period) [stVal, stDir] = ta.supertrend(fStFact, fStPer) // 4. EMA Stack fEMA = ta.ema(close, emaF) mEMA = ta.ema(close, emaM) sEMA = ta.ema(close, emaSlw) // 5. WaveTrend Oscillator (LazyBear method) wtHlc3 = hlc3 wtEsa = ta.ema(wtHlc3, wtCh) wtD = ta.ema(math.abs(wtHlc3 - wtEsa), wtCh) wtCi = (wtHlc3 - wtEsa) / (0.015 * wtD) wt1 = ta.ema(wtCi, wtAvg) wt2 = ta.sma(wt1, 4) // 6. Stochastic RSI srsiRsi = ta.rsi(close, srsiLen) srsiStoch = ta.stoch(srsiRsi, srsiRsi, srsiRsi, srsiLen) srsiKVal = ta.sma(srsiStoch, srsiK) srsiDVal = ta.sma(srsiKVal, srsiD) // 7. ADX + DI (pair-tuned thresholds applied at regime classification) [diPlus, diMinus, adxV] = ta.dmi(adxLen, adxLen) // ATR for TP/SL atrV = ta.atr(14) float tpDist = atrV * tpMult float slDist = atrV * slMult // ═════════════════════════════════════════════════════════════════════════════ // v0.07 QUALITY GATE CALCULATIONS // ═════════════════════════════════════════════════════════════════════════════ // HTF Daily Trend Gate — request.security MUST run every bar (global scope) dailyClose = request.security(syminfo.tickerid, "D", close) dailyEMA50 = request.security(syminfo.tickerid, "D", ta.ema(close, 50)) bool htfBull = dailyClose > dailyEMA50 bool htfBear = dailyClose < dailyEMA50 // Kaufman Efficiency Ratio (10-bar) float kerChange = math.abs(close - nz(close[10])) float kerVolSum = ta.sma(math.abs(ta.change(close)), 10) * 10.0 float kaufmanER = kerVolSum > 0 ? kerChange / kerVolSum : 0.0 bool kerFilter = kaufmanER > 0.3 // Volume Gate (1.5x 20-bar SMA) float volSMA20 = ta.sma(volume, 20) bool volGate = volume >= 1.5 * volSMA20 <<<<<<< Updated upstream // 8. Connors RSI (3, 2, 100) — composite of RSI + streak RSI + percent rank ======= // Connors RSI (3, 2, 100) — composite of RSI + streak RSI + percent rank >>>>>>> Stashed changes float crsiRsi3 = ta.rsi(close, 3) var int crsiStreak = 0 float crsiChg = ta.change(close) if crsiChg > 0 crsiStreak := crsiStreak > 0 ? crsiStreak + 1 : 1 else if crsiChg < 0 crsiStreak := crsiStreak < 0 ? crsiStreak - 1 : -1 else crsiStreak := 0 float crsiStreakRsi = ta.rsi(crsiStreak * 1.0, 2) float crsiPctRank = ta.percentrank(ta.change(close), 100) float connorsRSI = (crsiRsi3 + nz(crsiStreakRsi) + crsiPctRank) / 3.0 bool crsiBuy = connorsRSI < 20.0 bool crsiSell = connorsRSI > 80.0 // ═════════════════════════════════════════════════════════════════════════════ // ADX REGIME CLASSIFICATION (pair-tuned thresholds) // ═════════════════════════════════════════════════════════════════════════════ string regime = adxV >= fAdxTrend ? "TREND" : adxV >= fAdxRange ? "MIXED" : "RANGE" bool isTrend = regime == "TREND" bool isRange = regime == "RANGE" // ═════════════════════════════════════════════════════════════════════════════ // SIGNAL CONDITIONS (8 indicators, pair-tuned thresholds) // ═════════════════════════════════════════════════════════════════════════════ // 1. RSI — mean reversion (GATED in TREND, pair-tuned OB/OS) bool rsiBuyRaw = rsiVal < fRsiOS bool rsiSellRaw = rsiVal > fRsiOB bool rsiBuy = isTrend ? false : rsiBuyRaw bool rsiSell = isTrend ? false : rsiSellRaw // 2. MACD — momentum/trend (always active, histogram confirms) bool macdBuyRaw = macdL > sigL and macdH > 0 bool macdSellRaw = macdL < sigL and macdH < 0 bool macdBuy = macdBuyRaw bool macdSell = macdSellRaw // 3. SuperTrend — trend (GATED in RANGE) bool stBuyRaw = stDir < 0 bool stSellRaw = stDir > 0 bool stBuy = isRange ? false : stBuyRaw bool stSell = isRange ? false : stSellRaw // 4. EMA Stack — trend (GATED in RANGE) bool emaBullRaw = fEMA > mEMA and mEMA > sEMA bool emaBearRaw = fEMA < mEMA and mEMA < sEMA bool emaBull = isRange ? false : emaBullRaw bool emaBear = isRange ? false : emaBearRaw // 5. WaveTrend — oscillator (GATED in TREND) bool wtBuyRaw = ta.crossover(wt1, wt2) and wt1 < wtOS bool wtSellRaw = ta.crossunder(wt1, wt2) and wt1 > wtOB bool wtBuy = isTrend ? false : wtBuyRaw bool wtSell = isTrend ? false : wtSellRaw // 6. StochRSI — timing oscillator (always active) bool srBuyRaw = ta.crossover(srsiKVal, srsiDVal) and srsiKVal < srsiOS bool srSellRaw = ta.crossunder(srsiKVal, srsiDVal) and srsiKVal > srsiOB bool srBuy = srBuyRaw bool srSell = srSellRaw // 7. ADX Direction — DI+/DI- (always active, directional confirmation) bool adxBull = diPlus > diMinus bool adxBear = diMinus > diPlus // ═════════════════════════════════════════════════════════════════════════════ // REGIME-ADAPTIVE WEIGHTED CONSENSUS (the "Dynamic Strategy") // ═════════════════════════════════════════════════════════════════════════════ // In TREND: trend indicators worth 2 pts each (SuperTrend, EMA) // In RANGE: oscillators worth 2 pts each (RSI, WaveTrend) // In MIXED: all equal at 1 pt // Buy score int bScore = 0 bScore += rsiBuy ? (isRange ? 2 : 1) : 0 bScore += macdBuy ? (isTrend ? 2 : 1) : 0 bScore += stBuy ? (isTrend ? 2 : 1) : 0 bScore += emaBull ? (isTrend ? 2 : 1) : 0 bScore += wtBuy ? (isRange ? 2 : 1) : 0 bScore += srBuy ? 1 : 0 bScore += adxBull ? 1 : 0 bScore += useCRSI and crsiBuy ? 1 : 0 // Sell score int sScore = 0 sScore += rsiSell ? (isRange ? 2 : 1) : 0 sScore += macdSell ? (isTrend ? 2 : 1) : 0 sScore += stSell ? (isTrend ? 2 : 1) : 0 sScore += emaBear ? (isTrend ? 2 : 1) : 0 sScore += wtSell ? (isRange ? 2 : 1) : 0 sScore += srSell ? 1 : 0 sScore += adxBear ? 1 : 0 sScore += useCRSI and crsiSell ? 1 : 0 // Max possible score for current regime int maxPts = isTrend ? 9 : isRange ? 7 : 7 maxPts += useCRSI ? 1 : 0 // Active indicator count per regime int actCount = isTrend ? 5 : isRange ? 5 : 7 actCount += useCRSI ? 1 : 0 // Adaptive minSigLvl: EXTR tier requires 4+ consensus (v0.06) int effMinSig = useProfile and pTier == "EXTR" ? math.max(minSigLvl, 4) : minSigLvl // v0.07 Quality Gates — directional HTF + non-directional KER/Volume bool v07BuyOK = (useHTF ? htfBull : true) and (useKER ? kerFilter : true) and (useVolGate ? volGate : true) bool v07SellOK = (useHTF ? htfBear : true) and (useKER ? kerFilter : true) and (useVolGate ? volGate : true) // Signal determination (v0.07: gated by quality filters) bool isBuy = bScore >= effMinSig and bScore > sScore and v07BuyOK bool isSell = sScore >= effMinSig and sScore > bScore and v07SellOK int sigLevel = isBuy ? bScore : isSell ? sScore : 0 // Confidence percentage (score / max possible) float confPct = maxPts > 0 ? sigLevel * 100.0 / maxPts : 0.0 // ═════════════════════════════════════════════════════════════════════════════ // PLOTTING // ═════════════════════════════════════════════════════════════════════════════ // Plot EMAs (optional) plot(showEMAs ? fEMA : na, color=color.new(#00d4ff, 50), title="Fast EMA", linewidth=1) plot(showEMAs ? mEMA : na, color=color.new(#ff9f43, 50), title="Medium EMA", linewidth=1) plot(showEMAs ? sEMA : na, color=color.new(#a55eea, 50), title="Slow EMA", linewidth=1) // Plot SuperTrend (optional) plot(showST and stDir < 0 ? stVal : na, color=color.new(#26de81, 0), style=plot.style_linebr, title="ST Bull", linewidth=2) plot(showST and stDir > 0 ? stVal : na, color=color.new(#ff6b6b, 0), style=plot.style_linebr, title="ST Bear", linewidth=2) // Background coloring by confidence color bgHigh = showBG and confPct >= 85.0 ? color.new(isBuy ? color.green : color.red, 75) : na color bgMed = showBG and confPct >= 60.0 and confPct < 85.0 ? color.new(isBuy ? color.lime : color.maroon, 85) : na color bgLow = showBG and confPct >= 40.0 and confPct < 60.0 ? color.new(isBuy ? color.teal : color.fuchsia, 92) : na bgcolor(confPct >= 85.0 ? bgHigh : confPct >= 60.0 ? bgMed : confPct >= 40.0 ? bgLow : na, title="Confidence BG") // Signal shapes (const text only) plotshape(isBuy and sigLevel >= minSigLvl, title="Buy", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.normal, text="BUY") plotshape(isSell and sigLevel >= minSigLvl, title="Sell", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.normal, text="SELL") // Dynamic labels with score and regime if isBuy and sigLevel >= minSigLvl and showLbl label.new(bar_index, low, str.tostring(bScore) + "/" + str.tostring(maxPts), style=label.style_none, textcolor=color.green, size=size.small) if isSell and sigLevel >= minSigLvl and showLbl label.new(bar_index, high, str.tostring(sScore) + "/" + str.tostring(maxPts), style=label.style_none, textcolor=color.red, size=size.small) // ═════════════════════════════════════════════════════════════════════════════ // TP/SL LINES ON STRONG SIGNALS (TF-auto-scaled + pair-adjusted) // ═════════════════════════════════════════════════════════════════════════════ var line tpLn = na var line slLn = na var line entLn = na var label tpLb = na var label slLb = na var float actTP = na var float actSL = na var float actEntry = na var bool actIsBuy = false int tpslExtend = math.min(math.max(maxHold, 15), 50) // Buy signal -> draw TP/SL if showTPSL and isBuy and bScore >= tpslMinLvl if not na(tpLn) line.delete(tpLn) if not na(slLn) line.delete(slLn) if not na(entLn) line.delete(entLn) if not na(tpLb) label.delete(tpLb) if not na(slLb) label.delete(slLb) actEntry := close actTP := close + tpDist actSL := close - slDist actIsBuy := true entLn := line.new(bar_index, close, bar_index + tpslExtend, close, color=#00d4ff, style=line.style_dashed, width=1) tpLn := line.new(bar_index, actTP, bar_index + tpslExtend, actTP, color=#00ff88, style=line.style_solid, width=2) slLn := line.new(bar_index, actSL, bar_index + tpslExtend, actSL, color=#ff4444, style=line.style_solid, width=2) tpLb := label.new(bar_index + tpslExtend, actTP, "TP", style=label.style_none, textcolor=#00ff88, size=size.small) slLb := label.new(bar_index + tpslExtend, actSL, "SL", style=label.style_none, textcolor=#ff4444, size=size.small) // Sell signal -> draw TP/SL (reversed) if showTPSL and isSell and sScore >= tpslMinLvl if not na(tpLn) line.delete(tpLn) if not na(slLn) line.delete(slLn) if not na(entLn) line.delete(entLn) if not na(tpLb) label.delete(tpLb) if not na(slLb) label.delete(slLb) actEntry := close actTP := close - tpDist actSL := close + slDist actIsBuy := false entLn := line.new(bar_index, close, bar_index + tpslExtend, close, color=#00d4ff, style=line.style_dashed, width=1) tpLn := line.new(bar_index, actTP, bar_index + tpslExtend, actTP, color=#00ff88, style=line.style_solid, width=2) slLn := line.new(bar_index, actSL, bar_index + tpslExtend, actSL, color=#ff4444, style=line.style_solid, width=2) tpLb := label.new(bar_index + tpslExtend, actTP, "TP", style=label.style_none, textcolor=#00ff88, size=size.small) slLb := label.new(bar_index + tpslExtend, actSL, "SL", style=label.style_none, textcolor=#ff4444, size=size.small) // TP/SL hit detection -> clean up lines if not na(actTP) and not na(actSL) bool tpHit = actIsBuy ? high >= actTP : low <= actTP bool slHit = actIsBuy ? low <= actSL : high >= actSL if tpHit or slHit if not na(tpLn) line.delete(tpLn) if not na(slLn) line.delete(slLn) if not na(entLn) line.delete(entLn) if not na(tpLb) label.delete(tpLb) if not na(slLb) label.delete(slLb) actTP := na actSL := na actEntry := na // ═════════════════════════════════════════════════════════════════════════════ // BUILT-IN WIN/LOSS BACKTESTER (v0.07: with partial TP at 1R + breakeven) // Tracks BUY signals only (long bias) with frozen TP/SL + conservative fill // Uses NEXT BAR OPEN as entry (matches TradingView strategy tester default) // ═════════════════════════════════════════════════════════════════════════════ var float btEntry = na var int btEntryBar = na var float btTPLv = na var float btSLLv = na var bool btInTrade = false var int btWins = 0 var int btLosses = 0 var float btSumWin = 0.0 var float btSumLoss = 0.0 var bool btPending = false var bool btPartialHit = false var float btOrigSL = na // Signal fires -> mark pending (entry on NEXT bar open for honest fill) if not btInTrade and not btPending and isBuy and bScore >= btMinLvl btPending := true // Next bar after signal -> enter at open (realistic fill) if btPending and not btInTrade btEntry := open btEntryBar := bar_index btTPLv := open + tpDist btSLLv := open - slDist btOrigSL := open - slDist btInTrade := true btPending := false btPartialHit := false <<<<<<< Updated upstream // Trade management — v0.07 partial TP at 1R + breakeven stop ======= // Trade management — with v0.07 partial TP at 1R + breakeven stop >>>>>>> Stashed changes if btInTrade and not na(btEntry) // v0.07: Check for partial TP at 1R (= 1x risk = slDist above entry) float oneR = math.abs(btEntry - btOrigSL) if usePartialTP and not btPartialHit and high >= btEntry + oneR btPartialHit := true btSumWin += oneR / btEntry * 50.0 btSLLv := btEntry bool bTP = high >= btTPLv bool bSL = low <= btSLLv int bHeld = bar_index - btEntryBar if bTP and bSL if btPartialHit and usePartialTP btWins := btWins + 1 btSumWin += (btTPLv - btEntry) / btEntry * 50.0 else btLosses := btLosses + 1 btSumLoss += math.abs(btEntry - btSLLv) / btEntry * 100.0 btEntry := na btInTrade := false btPartialHit := false else if bTP if btPartialHit and usePartialTP btWins := btWins + 1 btSumWin += (btTPLv - btEntry) / btEntry * 50.0 else btWins := btWins + 1 btSumWin += (btTPLv - btEntry) / btEntry * 100.0 btEntry := na btInTrade := false btPartialHit := false else if bSL if btPartialHit and usePartialTP btWins := btWins + 1 else btLosses := btLosses + 1 btSumLoss += math.abs(btEntry - btSLLv) / btEntry * 100.0 btEntry := na btInTrade := false btPartialHit := false else if bHeld >= maxHold float btPnl = (close - btEntry) / btEntry * 100.0 if btPartialHit and usePartialTP float remPnl = (close - btEntry) / btEntry * 50.0 btWins := btWins + 1 if remPnl < 0 btSumLoss += math.abs(remPnl) else btSumWin += remPnl else if btPnl > 0.1 btWins := btWins + 1 btSumWin += btPnl else if btPnl < -0.1 btLosses := btLosses + 1 btSumLoss += math.abs(btPnl) btEntry := na btInTrade := false btPartialHit := false // Derived stats int btTotal = btWins + btLosses float btWR = btTotal > 0 ? btWins * 100.0 / btTotal : 0.0 float btPF = btSumLoss > 0.0 ? btSumWin / btSumLoss : btSumWin > 0 ? 99.9 : 0.0 float btAvgW = btWins > 0 ? btSumWin / btWins : 0.0 float btAvgL = btLosses > 0 ? btSumLoss / btLosses : 0.0 float btExpect = btTotal > 0 ? (btWR / 100.0 * btAvgW) - ((100.0 - btWR) / 100.0 * btAvgL) : 0.0 // ═════════════════════════════════════════════════════════════════════════════ // DATA WINDOW PLOTS (hidden) // ═════════════════════════════════════════════════════════════════════════════ plot(bScore, "Buy Score", color=color.new(#00ff88, 100), display=display.data_window) plot(sScore, "Sell Score", color=color.new(#ff4444, 100), display=display.data_window) plot(confPct, "Confidence %", color=color.new(#00d4ff, 100), display=display.data_window) plot(adxV, "ADX", color=color.new(#ff8800, 100), display=display.data_window) plot(wt1, "WaveTrend 1", color=color.new(#8888ff, 100), display=display.data_window) plot(wt2, "WaveTrend 2", color=color.new(#6666cc, 100), display=display.data_window) plot(srsiKVal, "StochRSI K", color=color.new(#ffaa00, 100), display=display.data_window) plot(btWR, "Backtest WR%", color=color.new(#00ff88, 100), display=display.data_window) plot(btPF, "Backtest PF", color=color.new(#aaaaff, 100), display=display.data_window) plot(btExpect, "Expectancy", color=color.new(#ffff00, 100), display=display.data_window) plot(fVolAdj, "Vol Adjust", color=color.new(#ff00ff, 100), display=display.data_window) plot(kaufmanER, "Kaufman ER", color=color.new(#ff8800, 100), display=display.data_window) plot(connorsRSI, "Connors RSI", color=color.new(#00ffff, 100), display=display.data_window) plot(htfBull ? 1 : htfBear ? -1 : 0, "HTF Trend", color=color.new(#88ff00, 100), display=display.data_window) // ═════════════════════════════════════════════════════════════════════════════ // INFO TABLE (top-right, dark theme, 20 rows for pair profile + v0.07 gates) // ═════════════════════════════════════════════════════════════════════════════ var table it = table.new(position.top_right, 2, 20, bgcolor=color.new(#0a0a12, 5), frame_width=1, frame_color=#333344) if showTbl and barstate.islast // Row 0: Header table.cell(it, 0, 0, "SSK_Claude v0.07", text_color=#00d4ff, text_size=size.normal, text_font_family=font.family_monospace) table.cell(it, 1, 0, tfProf, text_color=#666677, text_size=size.small) // Row 1: Pair Profile string profMd = useProfile ? "AUTO" : "MANUAL" color tierCl = pTier == "EXTR" ? #ff4444 : pTier == "HIGH" ? #ff8800 : pTier == "MHIGH" ? #ffcc00 : pTier == "MED" ? #00ff88 : #00d4ff table.cell(it, 0, 1, base + " | " + pTier, text_color=tierCl, text_size=size.small, text_font_family=font.family_monospace) table.cell(it, 1, 1, profMd, text_color=useProfile ? #00ff88 : #ff8800, text_size=size.small) // Row 2: Signal string sigTx = isBuy ? "BUY" : isSell ? "SELL" : "NONE" color sigCl = isBuy ? color.green : isSell ? color.red : #666677 table.cell(it, 0, 2, "Signal", text_color=#8899aa, text_size=size.small) table.cell(it, 1, 2, sigTx, text_color=sigCl, text_size=size.small) // Row 3: Score + confidence string scoreTx = str.tostring(sigLevel) + "/" + str.tostring(maxPts) + " (" + str.tostring(confPct, "#") + "%)" color scoreCl = confPct >= 85.0 ? #00d4ff : confPct >= 60.0 ? color.green : confPct >= 40.0 ? color.yellow : #666677 table.cell(it, 0, 3, "Strength", text_color=#8899aa, text_size=size.small) table.cell(it, 1, 3, scoreTx, text_color=scoreCl, text_size=size.small) // Row 4: Regime color regCl = isTrend ? #cc3333 : isRange ? #229922 : #cc8800 string regTx = regime + " (ADX " + str.tostring(adxV, "#.#") + ")" table.cell(it, 0, 4, "Regime", text_color=#8899aa, text_size=size.small) table.cell(it, 1, 4, regTx, text_color=regCl, text_size=size.small) // Row 5: Active indicators table.cell(it, 0, 5, "Active", text_color=#8899aa, text_size=size.small) table.cell(it, 1, 5, str.tostring(actCount) + "/" + str.tostring(useCRSI ? 8 : 7) + " indicators", text_color=#aaaaff, text_size=size.small) // Row 6: separator table.cell(it, 0, 6, "--- Indicators ---", text_color=#444466, text_size=size.tiny) table.cell(it, 1, 6, "", text_color=#444466, text_size=size.tiny) // Row 7: RSI string rsiSt = isTrend ? "GATED" : rsiBuyRaw ? "BUY" : rsiSellRaw ? "SELL" : "Neutral" color rsiCl = isTrend ? #553300 : rsiBuyRaw ? color.green : rsiSellRaw ? color.red : #666677 string rsiTx = "RSI(" + str.tostring(fRsiLen) + ") " + str.tostring(rsiVal, "#.#") table.cell(it, 0, 7, rsiTx, text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 7, rsiSt, text_color=rsiCl, text_size=size.tiny) // Row 8: MACD string macdSt = macdBuy ? "Bullish" : macdSell ? "Bearish" : "Flat" color macdCl = macdBuy ? color.green : macdSell ? color.red : #666677 string macdTx = "MACD " + str.tostring(fMacdF) + "/" + str.tostring(fMacdS) table.cell(it, 0, 8, macdTx, text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 8, macdSt, text_color=macdCl, text_size=size.tiny) // Row 9: SuperTrend string stSt = isRange ? "GATED" : stBuyRaw ? "Bull" : stSellRaw ? "Bear" : "Flat" color stCl = isRange ? #553300 : stBuyRaw ? color.green : stSellRaw ? color.red : #666677 string stTx = "ST(" + str.tostring(fStFact, "#.#") + "/" + str.tostring(fStPer) + ")" table.cell(it, 0, 9, stTx, text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 9, stSt, text_color=stCl, text_size=size.tiny) // Row 10: EMA string emaSt = isRange ? "GATED" : emaBullRaw ? "Bull Stack" : emaBearRaw ? "Bear Stack" : "Mixed" color emaCl = isRange ? #553300 : emaBullRaw ? color.green : emaBearRaw ? color.red : #666677 table.cell(it, 0, 10, "EMA Stack", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 10, emaSt, text_color=emaCl, text_size=size.tiny) // Row 11: WaveTrend string wtSt = isTrend ? "GATED" : wtBuyRaw ? "OS Cross" : wtSellRaw ? "OB Cross" : "Neutral" color wtCl = isTrend ? #553300 : wtBuyRaw ? color.green : wtSellRaw ? color.red : #666677 table.cell(it, 0, 11, "WaveTrend", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 11, wtSt, text_color=wtCl, text_size=size.tiny) // Row 12: StochRSI string srSt = srBuy ? "OS Cross" : srSell ? "OB Cross" : "Neutral" color srCl = srBuy ? color.green : srSell ? color.red : #666677 table.cell(it, 0, 12, "StochRSI", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 12, srSt, text_color=srCl, text_size=size.tiny) // Row 13: ADX Direction string adxSt = adxBull ? "DI+ > DI-" : adxBear ? "DI- > DI+" : "Equal" color adxCl = adxBull ? color.green : adxBear ? color.red : #666677 table.cell(it, 0, 13, "ADX Dir", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 13, adxSt, text_color=adxCl, text_size=size.tiny) // Row 14: Connors RSI (v0.07) string crsiSt = useCRSI ? (crsiBuy ? "OS" : crsiSell ? "OB" : str.tostring(connorsRSI, "#.#")) : "OFF" color crsiCl = not useCRSI ? #555577 : crsiBuy ? color.green : crsiSell ? color.red : #666677 table.cell(it, 0, 14, "CRSI", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 14, crsiSt, text_color=crsiCl, text_size=size.tiny) // Row 15: separator table.cell(it, 0, 15, "--- Backtester ---", text_color=#444466, text_size=size.tiny) table.cell(it, 1, 15, "", text_color=#444466, text_size=size.tiny) // Row 16: TP/SL + vol adj info string tpslTx = str.tostring(tpMult, "#.##") + "x/" + str.tostring(slMult, "#.##") + "x ATR" string autoTx = autoTPSL ? "AUTO" : "MANUAL" string adjTx = useProfile ? " x" + str.tostring(fVolAdj, "#.##") : "" table.cell(it, 0, 16, "TP/SL", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 16, tpslTx + " " + autoTx + adjTx, text_color=#aaaaff, text_size=size.tiny) // Row 17: Backtest stats if showStats and btTotal > 0 color wrCl = btWR >= 65 ? #00ff88 : btWR >= 50 ? #aaaaff : #ff4444 string btTx = str.tostring(btWins) + "W/" + str.tostring(btLosses) + "L " + str.tostring(btWR, "#.#") + "% PF:" + str.tostring(btPF, "#.##") table.cell(it, 0, 17, "Stats", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 17, btTx, text_color=wrCl, text_size=size.tiny) else <<<<<<< Updated upstream table.cell(it, 0, 17, "Stats", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 17, "Collecting...", text_color=#555577, text_size=size.tiny) // Row 18: v0.07 separator table.cell(it, 0, 18, "--- v0.07 Gates ---", text_color=#444466, text_size=size.tiny) table.cell(it, 1, 18, "", text_color=#444466, text_size=size.tiny) // Row 19: HTF + KER + Vol gate status ======= table.cell(it, 0, 16, "Stats", text_color=#8899aa, text_size=size.tiny) table.cell(it, 1, 16, "Collecting...", text_color=#555577, text_size=size.tiny) // Row 17: v0.07 separator table.cell(it, 0, 17, "--- v0.07 Gates ---", text_color=#444466, text_size=size.tiny) table.cell(it, 1, 17, "", text_color=#444466, text_size=size.tiny) // Row 18: HTF + KER + Vol gate status >>>>>>> Stashed changes string htfSt = useHTF ? (htfBull ? "BULL" : htfBear ? "BEAR" : "FLAT") : "OFF" color htfCl = not useHTF ? #555577 : htfBull ? #00ff88 : htfBear ? #ff4444 : #888888 string kerSt = useKER ? str.tostring(kaufmanER, "#.##") : "OFF" color kerCl = not useKER ? #555577 : kerFilter ? #00ff88 : #ff4444 <<<<<<< Updated upstream table.cell(it, 0, 19, "HTF:" + htfSt + " KER:" + kerSt, text_color=htfCl, text_size=size.tiny) table.cell(it, 1, 19, "Vol:" + (useVolGate ? (volGate ? "OK" : "LOW") : "OFF") + " PTP:" + (usePartialTP ? "1R+BE" : "OFF"), text_color=kerCl, text_size=size.tiny) ======= table.cell(it, 0, 18, "HTF:" + htfSt, text_color=htfCl, text_size=size.tiny) table.cell(it, 1, 18, "KER:" + kerSt + " Vol:" + (useVolGate ? (volGate ? "OK" : "LOW") : "OFF"), text_color=kerCl, text_size=size.tiny) // Row 19: Connors RSI + Partial TP string crsiSt = useCRSI ? str.tostring(connorsRSI, "#.#") : "OFF" color crsiCl = not useCRSI ? #555577 : crsiBuy ? #00ff88 : crsiSell ? #ff4444 : #888888 string ptpSt = usePartialTP ? "1R+BE" : "OFF" table.cell(it, 0, 19, "CRSI:" + crsiSt, text_color=crsiCl, text_size=size.tiny) table.cell(it, 1, 19, "PTP:" + ptpSt, text_color=usePartialTP ? #aaaaff : #555577, text_size=size.tiny) >>>>>>> Stashed changes // ═════════════════════════════════════════════════════════════════════════════ // SUMMARY BOX (bottom-right) // ═════════════════════════════════════════════════════════════════════════════ var table sb = table.new(position.bottom_right, 1, 8, border_width=1, border_color=#333355, frame_width=1, frame_color=#5555aa) if showTbl and barstate.islast table.cell(sb, 0, 0, "SSK_CLAUDE v0.07 | " + syminfo.ticker, bgcolor=#1a1a2e, text_color=#8888ff, text_size=size.small) string profInfo = useProfile ? "Profile: " + base + " " + pTier + " | VolAdj x" + str.tostring(fVolAdj, "#.##") : "Profile: MANUAL (no auto-tune)" table.cell(sb, 0, 1, profInfo, bgcolor=#1a1a2e, text_color=useProfile ? #00ff88 : #ff8800, text_size=size.small) string minSigTx = pTier == "EXTR" and useProfile ? " | MinSig:" + str.tostring(effMinSig) : "" string dynTx = "Dynamic: " + regime + " regime -> " + str.tostring(actCount) + " signals active" + minSigTx table.cell(sb, 0, 2, dynTx, bgcolor=#1a1a2e, text_color=color.white, text_size=size.small) int gatesOn = (useHTF ? 1 : 0) + (useKER ? 1 : 0) + (useVolGate ? 1 : 0) + (useCRSI ? 1 : 0) + (usePartialTP ? 1 : 0) int gatesPass = (useHTF ? (htfBull or htfBear ? 1 : 0) : 0) + (useKER ? (kerFilter ? 1 : 0) : 0) + (useVolGate ? (volGate ? 1 : 0) : 0) string gatesTx = "v0.07 Gates: " + str.tostring(gatesOn) + "/5 ON | " + str.tostring(gatesPass) + " passing" table.cell(sb, 0, 3, gatesTx, bgcolor=#1a1a2e, text_color=#aaaaff, text_size=size.small) string perfTx = btTotal > 0 ? str.tostring(btTotal) + " trades | WR " + str.tostring(btWR, "#.#") + "% | PF " + str.tostring(btPF, "#.##") + " | E[R] " + str.tostring(btExpect, "#.###") + "%" : "Accumulating backtest data..." color perfCl = btTotal > 0 and btExpect > 0 ? #00ff88 : btTotal > 0 ? #ff4444 : #666677 table.cell(sb, 0, 4, perfTx, bgcolor=#1a1a2e, text_color=perfCl, text_size=size.small) string tpInfo = autoTPSL ? "Auto: TP " + str.tostring(tpMult, "#.##") + "x SL " + str.tostring(slMult, "#.##") + "x Hold " + str.tostring(maxHold) + "b" : "Manual TP/SL" table.cell(sb, 0, 5, tpInfo, bgcolor=#0d0d1e, text_color=#777799, text_size=size.tiny) string methTx = "Next-bar-open entry | Conservative fill | Frozen TP/SL" table.cell(sb, 0, 6, methTx, bgcolor=#0d0d1e, text_color=#555577, text_size=size.tiny) string atrTx = "ATR(14): " + str.tostring(atrV, "#.##") + " | " + timeframe.period + " | " + tfProf table.cell(sb, 0, 7, atrTx, bgcolor=#0d0d1e, text_color=#555577, text_size=size.tiny) // ═════════════════════════════════════════════════════════════════════════════ // ALERTS (static messages only) // ═════════════════════════════════════════════════════════════════════════════ alertcondition(isBuy and sigLevel >= 5, title="Strong Buy L5+", message="STRONG BUY Signal L5+ | {{ticker}} @ {{close}}") alertcondition(isSell and sigLevel >= 5, title="Strong Sell L5+", message="STRONG SELL Signal L5+ | {{ticker}} @ {{close}}") alertcondition(isBuy and sigLevel >= 3, title="Buy L3+", message="BUY Signal L3+ | {{ticker}} @ {{close}}") alertcondition(isSell and sigLevel >= 3, title="Sell L3+", message="SELL Signal L3+ | {{ticker}} @ {{close}}") alertcondition(confPct >= 85.0, title="High Confidence", message="HIGH CONFIDENCE signal | {{ticker}} @ {{close}}")