Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Improvement Suggestions

The provided script, “TSI Adaptive Scalper v4.2,” is an exceptionally well-structured indicator that demonstrates a sophisticated understanding of confluence. It has already incorporated several professional-grade features, including adaptive parameters via a matrix, dynamic OB/OS thresholds, and a comprehensive scoring system.

The following roadmap outlines three additive levels of evolution to transition this indicator from a high-quality signal generator into a fully autonomous, robust, and institutional-grade trading system. The focus is on enhancing statistical expectancy (Expected Value) and survivability across diverse market regimes.


Level 1: Parameter Optimization & Dynamic Adaptability

The current script uses a static matrix to select parameters based on asset class and timeframe. While this is a significant step beyond hard-coding, true robustness comes from real-time adaptation to market character. This level focuses on replacing static lookups with dynamic, volatility-driven calculations.

Suggested Upgrades:

  1. Dynamic Lookback Periods for TSI & EMA: The core lookback periods for the TSI (fLong, fShort) and the trend EMA (emaLenFinal) are currently selected from a fixed table. These should adapt to the market’s cyclicality. A faster, more volatile market has shorter cycles, demanding shorter lookbacks.

    • Technical Logic: Use a normalized volatility metric, such as the ratio of a fast ATR to a slow ATR (which the script already calculates as clampedVol), to modulate the base lookback periods.

    • Pine Script Logic:

      // Replace static lookups with dynamic modulation
      float volatilityFactor = 1.0 / clampedVol // Inverse relationship: high vol = shorter lookback
      int dynamicLong = math.round(baseLong * volatilityFactor)
      int dynamicShort = math.round(baseShort * volatilityFactor)
      int dynamicEMALen = math.round(baseEMA * volatilityFactor)
      
      // Use these dynamic lengths in calculations
      int fLong = useManual ? manLong : dynamicLong
      // ... and so on for fShort and emaLenFinal
  2. Implement a True Trailing Stop-Loss Mechanism: The current TP/SL Zones are excellent for visualization but represent a static risk-reward framework. A professional system must protect profits dynamically.

    • Technical Logic: Replace the fixed TP/SL price levels with a volatility-based trailing stop, such as a Chandelier Exit. This places the stop-loss at a multiple of the Average True Range (ATR) below the highest high (for longs) or above the lowest low (for shorts) since the trade was initiated.

    • Pine Script Logic (Conceptual for a strategy script):

      // In a strategy script, on trade entry:
      float trailStopPrice = 0.0
      if (strategy.position_size > 0)
          highestHighSinceEntry = ta.highest(high, bars_since_entry)
          trailStopPrice := highestHighSinceEntry - ta.atr(14) * 3.0
          strategy.exit("Long Exit", from_entry="Long Entry", stop=trailStopPrice)

Quantitative Benefit:


Level 2: Secondary Confluence & Noise Filtration

The script’s scoring system is strong, but its filters are largely independent. This level introduces more sophisticated, second-order filters that analyze the context of the signal, dramatically improving the signal-to-noise ratio.

Suggested Upgrades:

  1. Volume-Weighted Average Price (VWAP) as a Directional Filter: The current relative volume filter is good for confirming momentum on a single candle. A VWAP filter provides a much deeper insight into the session’s institutional bias.

    • Technical Logic: For intraday strategies, only validate long signals that occur at or below the daily VWAP, and short signals that occur at or above the VWAP. This ensures the strategy is buying at a “discount” relative to the average price paid by all participants during the session and selling at a “premium.” A strong bonus can be added to the score if a long signal bounces off the VWAP.

    • Pine Script Logic:

      // Add to the confluence score calculation
      float vwapValue = ta.vwap(hlc3)
      bool vwapBullishBias = close > vwapValue
      bool vwapBearishBias = close < vwapValue
      
      // In the scoring section:
      if (bullSignal)
          if (close <= vwapValue) // Entry is at a discount
              rawScoreBull += 1.5
          if (low[1] < vwapValue and close > vwapValue) // Bounced off VWAP
              rawScoreBull += 1.0
  2. Higher-Timeframe (HTF) Structural & Momentum Alignment: The script uses an MTF TSI, which is a good start. This should be expanded to a full HTF regime check, confirming that the lower-timeframe signal is not fighting a larger, more powerful opposing trend.

    • Technical Logic: Before validating a long signal on the execution timeframe (e.g., M15), the system must confirm that the price on the higher timeframe (e.g., H4) is above its own 50-period EMA and that the HTF structureBias is not bearish. This acts as a master “permission slip” from the higher-order trend.

    • Pine Script Logic:

      // Request HTF data
      [htf_close, htf_ema, htf_structureBias] = request.security(syminfo.tickerid, "240", [close, ta.ema(close, 50), structureBias], lookahead=barmerge.lookahead_off)
      
      // In the signal validation logic:
      bool htfPermissionBull = htf_close > htf_ema and htf_structureBias >= 0
      bool htfPermissionBear = htf_close < htf_ema and htf_structureBias <= 0
      
      // A signal is only valid if it has HTF permission
      bool bullSignalFinal = bullSignal and htfPermissionBull

Quantitative Benefit:


Level 3: Structural Architecture & Regime Detection

This is the ultimate evolution, transforming the script from a single-purpose system into an adaptive machine that changes its core logic based on the market’s personality. The current “Anti-Whipsaw” module dampens signals in ranges; this level teaches the system to trade the range differently.

Suggested Upgrades:

  1. Implement a Quantitative Market Regime Filter: The system must first be able to mathematically distinguish between a trending and a non-trending (mean-reverting) environment.

    • Technical Logic: Use a robust metric to classify the market state. While the Hurst Exponent is the academic standard, a highly effective and simpler proxy can be built using indicators already in the script. A combination of ADX and the Normalized Bollinger Band Width (bbWidth) is ideal.

    • Pine Script Logic:

      // Define regimes
      enum Regime { Trend, Range, Undefined }
      Regime currentRegime = Regime.Undefined
      
      // Use a smoothed ADX and percentile-ranked BBW
      float bbWidthP50 = ta.percentile_linear_interpolation(bbWidth, 200, 50) // 50th percentile of BBW over 200 bars
      
      if (adxVal > 25 and bbWidth > bbWidthP50)
          currentRegime := Regime.Trend
      else if (adxVal < 18 and bbWidth < bbWidthP50)
          currentRegime := Regime.Range
  2. Develop a Secondary “Mean Reversion” Engine: Once the regime is identified as Range, the system should switch from its primary “pullback-in-trend” logic to a dedicated mean-reversion engine.

    • Technical Logic: In a Range regime, the objective is to sell strength and buy weakness at the boundaries of the range. The Bollinger Bands become the primary signal generator.

      • Short Entry: Price touches the upper Bollinger Band AND the TSI is in its overbought zone (inOBZone). The target is the BB basis (the 20-period SMA).

      • Long Entry: Price touches the lower Bollinger Band AND the TSI is in its oversold zone (inOSZone). The target is the BB basis.

    • Pine Script Logic (Conceptual):

      // Main execution block
      if (currentRegime == Regime.Trend)
          // --- EXECUTE EXISTING TSI PULLBACK LOGIC (LEVEL 1 & 2) ---
          // ... bullSignal, bearSignal, scoring, etc.
      else if (currentRegime == Regime.Range)
          // --- EXECUTE NEW MEAN REVERSION LOGIC ---
          bool rangeLongSignal = ta.crossunder(low, bbLower) and inOSZone
          bool rangeShortSignal = ta.crossover(high, bbUpper) and inOBZone
          // ... trigger trades with target at bbBasis

Quantitative Benefit: