Skip to content

HT_TRENDMODE (Hilbert Transform - Trend vs Cycle Mode)

Overview

The Hilbert Transform - Trend vs Cycle Mode (HT_TRENDMODE) is a critical market regime detection indicator that determines whether the market is currently in a trending state or a cycling (oscillating) state. This binary indicator returns a value of 1 for trend mode and 0 for cycle mode, providing traders with essential information for strategy selection. By identifying the market's current regime, traders can avoid using oscillators during trending markets and trend-following strategies during ranging markets, significantly improving trading performance.

Parameters

Parameter Type Default Description
prices Array Required Array of price values (typically close prices)

Parameter Details

Note: Array elements should be ordered from oldest to newest (chronological order)

prices - Input data should be an array of closing prices - Minimum 32 data points required for reliable results (due to Hilbert Transform calculation requirements) - More data provides better accuracy in regime identification - Works best with at least 63+ data points for stable output - The indicator analyzes the frequency content of price movements to determine regime

Usage

Basic Usage

require 'sqa/tai'

# Calculate trend vs cycle mode
prices = [44.34, 44.09, 44.15, 43.61, 44.33, 44.83,
          45.10, 45.42, 45.84, 46.08, 46.03, 45.61,
          46.50, 47.20, 46.80, 47.50, 48.10, 48.30,
          # ... more data points ...
         ]

mode = SQA::TAI.ht_trendmode(prices)

# Check current market regime
current_mode = mode.last
if current_mode == 1
  puts "Market is in TREND MODE - use trend-following strategies"
else
  puts "Market is in CYCLE MODE - use mean-reversion strategies"
end

Practical Application

# Adapt your strategy based on market mode
mode = SQA::TAI.ht_trendmode(prices)
current_mode = mode.last

if current_mode == 1
  # TREND MODE: Use trend-following indicators
  puts "Using trend-following approach"

  # Use moving average crossovers
  fast_ma = SQA::TAI.ema(prices, period: 12)
  slow_ma = SQA::TAI.ema(prices, period: 26)

  # Use ADX for trend strength
  adx = SQA::TAI.adx(highs, lows, prices, period: 14)

  # Ignore oscillator signals
  puts "Ignoring RSI/Stochastic oscillations"

else
  # CYCLE MODE: Use mean-reversion indicators
  puts "Using mean-reversion approach"

  # Use oscillators for entry/exit
  rsi = SQA::TAI.rsi(prices, period: 14)
  stoch_k, stoch_d = SQA::TAI.stoch(highs, lows, prices)

  # Trade range boundaries
  bb_upper, bb_middle, bb_lower = SQA::TAI.bbands(prices, period: 20)

  puts "Trading oversold/overbought conditions"
end

Understanding the Indicator

What It Measures

HT_TRENDMODE measures the market regime - specifically whether price action exhibits trending characteristics or cyclical (oscillating) characteristics. The indicator uses Hilbert Transform mathematics to analyze the dominant frequency components in price movements:

  • Trend Mode (1): Price movements are dominated by directional momentum with minimal cyclical oscillation
  • Cycle Mode (0): Price movements are dominated by oscillations around a mean with no sustained direction

The indicator answers the fundamental question: "Should I be trend-following or mean-reverting right now?"

Why It's Important

Using the wrong strategy for the current market regime is a primary cause of trading losses:

In Trending Markets: - Oscillators generate false signals (constantly showing "overbought" or "oversold") - Mean-reversion strategies result in catching falling knives or fighting trends - The market can remain "overbought" or "oversold" for extended periods - Trend-following strategies perform best

In Cycling Markets: - Trend-following strategies generate whipsaws and false breakouts - Moving average crossovers produce excessive and unprofitable signals - Range-bound behavior creates ideal conditions for mean-reversion - Oscillators provide reliable entry and exit signals

HT_TRENDMODE helps you automatically select the appropriate strategy for current conditions, eliminating the guesswork and emotional decision-making that leads to poor strategy selection.

Calculation Method

The Hilbert Transform uses sophisticated digital signal processing to decompose price data:

  1. Apply Hilbert Transform to create a complex analytical signal from the price series
  2. Analyze the instantaneous frequency of the dominant price cycle
  3. Evaluate cycle consistency - how regular and persistent the cycles are
  4. Generate binary classification:
  5. If price shows sustained directional movement with weak cycles → Mode = 1 (Trend)
  6. If price shows strong, regular oscillations without sustained direction → Mode = 0 (Cycle)
  7. Apply smoothing logic to prevent excessive mode switching

Key Concept: Think of it like audio signal analysis - the indicator distinguishes between a sustained note (trend) and rapid oscillations (cycle). Just as music has both sustained tones and quick vibrations, markets alternate between trending and cycling regimes.

Indicator Characteristics

  • Range: Binary output (0 or 1 only)
  • Type: Market regime detection, classification indicator
  • Lag: Moderate - requires some confirmation before switching modes
  • Best Used: As a filter for strategy selection across all timeframes
  • Updates: Mode can change as market conditions evolve

Interpretation

Value Meanings

Mode = 1 (Trend Mode)

Market characteristics: - Sustained directional price movement - Weak or irregular cyclical components - Price can move far from mean without reverting - High probability of trend continuation - Momentum and directional indicators work well - Oscillators give false signals

What to do: - Use trend-following strategies - Employ moving averages, MACD, ADX - Trade breakouts and momentum - Avoid counter-trend trades - Ignore "overbought" or "oversold" oscillator readings - Let profits run, use trailing stops

Mode = 0 (Cycle Mode)

Market characteristics: - Price oscillates around a central value - Regular, repeating cycle patterns - Price tends to revert to mean - Breakouts often fail - Range-bound behavior dominates - Oscillators accurately identify turning points

What to do: - Use mean-reversion strategies - Employ RSI, Stochastic, Bollinger Bands - Trade range boundaries - Take profits at resistance, buy at support - Avoid trend-following indicators - Use tighter profit targets, faster exits

Mode Transitions

Transition from Cycle (0) to Trend (1): - Market is breaking out of range - Initiate or add to trend-following positions - Close mean-reversion positions - Expect sustained directional move - Raise stop losses to protect capital

Transition from Trend (1) to Cycle (0): - Trend is exhausting, range forming - Take profits on trend-following positions - Prepare for mean-reversion opportunities - Expect price to oscillate in range - Tighten stops, reduce position sizes

Mode Persistence

Stable Mode (few changes): - Market in consistent regime - Strategy selection reliable - Can commit to single approach

Frequent Mode Changes: - Market in transition or low signal quality - Use caution with any strategy - Reduce position sizes - Wait for mode stability before aggressive trading

Trading Signals

Strategy Selection System

Primary Use Case: Automatic strategy switching

# Get current market mode
mode = SQA::TAI.ht_trendmode(prices)
current_mode = mode.last

# Initialize strategy variables
strategy = nil
indicators_to_use = []

if current_mode == 1
  # TREND MODE STRATEGY
  strategy = :trend_following

  # Calculate trend indicators
  ema_fast = SQA::TAI.ema(prices, period: 12)
  ema_slow = SQA::TAI.ema(prices, period: 26)
  adx = SQA::TAI.adx(highs, lows, prices, period: 14)

  # Entry signal: MA crossover + strong ADX
  if ema_fast.last > ema_slow.last && adx.last > 25
    if ema_fast[-2] <= ema_slow[-2]  # Crossover just occurred
      puts "TREND MODE - BUY SIGNAL (Bullish Crossover)"
      puts "ADX: #{adx.last.round(2)} (Strong trend)"
    end
  elsif ema_fast.last < ema_slow.last && adx.last > 25
    if ema_fast[-2] >= ema_slow[-2]  # Crossover just occurred
      puts "TREND MODE - SELL SIGNAL (Bearish Crossover)"
      puts "ADX: #{adx.last.round(2)} (Strong trend)"
    end
  end

else
  # CYCLE MODE STRATEGY
  strategy = :mean_reversion

  # Calculate oscillator indicators
  rsi = SQA::TAI.rsi(prices, period: 14)
  bb_upper, bb_middle, bb_lower = SQA::TAI.bbands(prices, period: 20, nbdevup: 2, nbdevdn: 2)
  current_price = prices.last

  # Entry signal: RSI extremes + Bollinger Band touch
  if rsi.last < 30 && current_price < bb_lower.last
    puts "CYCLE MODE - BUY SIGNAL (Oversold + Lower BB)"
    puts "RSI: #{rsi.last.round(2)} (Oversold)"
    puts "Target: #{bb_middle.last.round(2)} (Middle BB)"

  elsif rsi.last > 70 && current_price > bb_upper.last
    puts "CYCLE MODE - SELL SIGNAL (Overbought + Upper BB)"
    puts "RSI: #{rsi.last.round(2)} (Overbought)"
    puts "Target: #{bb_middle.last.round(2)} (Middle BB)"
  end
end

puts "Current Strategy: #{strategy}"

Filtering False Signals

Use Case: Prevent oscillator whipsaws during trends

mode = SQA::TAI.ht_trendmode(prices)
rsi = SQA::TAI.rsi(prices, period: 14)

current_mode = mode.last
current_rsi = rsi.last

# Only act on RSI signals during cycle mode
if current_rsi < 30
  if current_mode == 0
    puts "VALID BUY: RSI oversold in CYCLE MODE"
  else
    puts "IGNORED: RSI oversold but market in TREND MODE"
    puts "Price may continue lower despite oversold reading"
  end

elsif current_rsi > 70
  if current_mode == 0
    puts "VALID SELL: RSI overbought in CYCLE MODE"
  else
    puts "IGNORED: RSI overbought but market in TREND MODE"
    puts "Price may continue higher despite overbought reading"
  end
end

Regime-Based Position Sizing

Use Case: Adjust risk based on market mode

mode = SQA::TAI.ht_trendmode(prices)
current_mode = mode.last

# Base position size
base_position = 100  # shares/contracts

# Mode-based position sizing
if current_mode == 1
  # TREND MODE: Larger positions, wider stops
  position_size = base_position * 1.5
  stop_multiplier = 2.5
  profit_target_multiplier = 4.0

  puts "Trend Mode Position Sizing:"
  puts "Position: #{position_size} units (150% of base)"
  puts "Stop: #{stop_multiplier}x ATR"
  puts "Target: #{profit_target_multiplier}x ATR (let winners run)"

else
  # CYCLE MODE: Smaller positions, tighter stops
  position_size = base_position
  stop_multiplier = 1.5
  profit_target_multiplier = 2.0

  puts "Cycle Mode Position Sizing:"
  puts "Position: #{position_size} units (100% of base)"
  puts "Stop: #{stop_multiplier}x ATR"
  puts "Target: #{profit_target_multiplier}x ATR (take profits faster)"
end

# Calculate actual levels
atr = SQA::TAI.atr(highs, lows, prices, period: 14)
current_atr = atr.last
current_price = prices.last

stop_distance = current_atr * stop_multiplier
target_distance = current_atr * profit_target_multiplier

puts "Stop Loss: #{(current_price - stop_distance).round(2)}"
puts "Take Profit: #{(current_price + target_distance).round(2)}"

Best Practices

Optimal Use Cases

When HT_TRENDMODE works best: - Strategy filtering: Primary use - deciding which indicators to trust - Automated trading systems: Programmatic strategy switching - Multi-strategy portfolios: Allocate capital between trend/cycle strategies - All market types: Works across stocks, forex, commodities, crypto - All timeframes: Effective from daily to intraday charts (with sufficient data)

Less effective in: - Very short timeframes (< 15 minute charts) - too much noise - Low-liquidity markets - erratic price action confuses regime detection - During major news events - sudden volatility can cause temporary misclassification - Markets in transition - mode may be unstable between regimes

Combining with Other Indicators

With HT_DCPERIOD:

# Use both indicators for comprehensive cycle analysis
mode = SQA::TAI.ht_trendmode(prices)
cycle = SQA::TAI.ht_dcperiod(prices)

current_mode = mode.last
current_cycle = cycle.last.round

if current_mode == 0
  # In cycle mode, use the detected cycle period
  puts "CYCLE MODE: Optimizing for #{current_cycle}-period cycle"
  rsi = SQA::TAI.rsi(prices, period: current_cycle)

  # Trade the cycle
  puts "Buy at cycle troughs, sell at cycle peaks"
  puts "Expected cycle duration: #{current_cycle} bars"

else
  # In trend mode, cycle period indicates trend strength
  if current_cycle > 30
    puts "TREND MODE: Long cycle (#{current_cycle}) = Strong trend"
  else
    puts "TREND MODE: Short cycle (#{current_cycle}) = Weak trend or emerging"
  end
end

With Trend Strength Indicators:

mode = SQA::TAI.ht_trendmode(prices)
adx = SQA::TAI.adx(highs, lows, prices, period: 14)

current_mode = mode.last
current_adx = adx.last

# Confirm trend mode with ADX
if current_mode == 1 && current_adx > 25
  puts "CONFIRMED STRONG TREND"
  puts "High confidence in trend-following strategies"

elsif current_mode == 1 && current_adx < 20
  puts "WARNING: Trend mode but weak ADX"
  puts "Possible transition period - use caution"

elsif current_mode == 0 && current_adx < 20
  puts "CONFIRMED RANGING MARKET"
  puts "High confidence in mean-reversion strategies"

else  # Mode = 0 but ADX > 25
  puts "CONFLICT: Cycle mode but high ADX"
  puts "Market may be transitioning - wait for clarity"
end

With Volatility Indicators:

mode = SQA::TAI.ht_trendmode(prices)
bb_upper, bb_middle, bb_lower = SQA::TAI.bbands(prices, period: 20)
bb_width = bb_upper.last - bb_lower.last

current_mode = mode.last

if current_mode == 1
  # Trend mode: Use BB for trend confirmation and entries on pullbacks
  if prices.last > bb_upper.last
    puts "Strong uptrend - price above upper BB"
  end
  puts "Wait for pullbacks to middle BB for entries"

else
  # Cycle mode: Use BB for range boundaries
  puts "Trade BB extremes:"
  puts "Buy near: #{bb_lower.last.round(2)}"
  puts "Sell near: #{bb_upper.last.round(2)}"
  puts "Target: #{bb_middle.last.round(2)}"
end

With Other Hilbert Transform Indicators: - HT_DCPERIOD: Use cycle period only when mode = 0 (cycle mode) - HT_DCPHASE: Phase is most useful in cycle mode (0) - HT_SINE: Sine/LeadSine signals work best in cycle mode - HT_PHASOR: In-phase and quadrature components for advanced analysis

Common Pitfalls

  1. Ignoring Mode Changes
  2. Don't continue trend-following when mode switches to 0
  3. Don't continue mean-reversion when mode switches to 1
  4. Always check current mode before taking signals
  5. Exit positions that conflict with current mode

  6. Over-Trading Mode Transitions

  7. Mode changes can produce brief whipsaws
  8. Wait for mode stability (same value for 2-3 bars)
  9. Don't reverse entire portfolio on single mode change
  10. Use mode as filter, not sole trigger

  11. Insufficient Data

  12. Need minimum 32-63 bars for reliable mode detection
  13. Initial values will be unstable or incorrect
  14. Don't trade based on mode with insufficient history
  15. Verify data quality and quantity

  16. Conflicting Signals

  17. Mode may say "trend" while visual inspection shows range
  18. Use additional confirmation indicators (ADX, volatility)
  19. Trust the mode more with longer data history
  20. Be cautious during mode disagreements

  21. Wrong Timeframe

  22. Mode on 5-minute chart may differ from daily chart
  23. Use appropriate timeframe for your trading style
  24. Consider multi-timeframe analysis
  25. Higher timeframe mode generally more reliable

Strategy Selection Guidelines

For Day Trading: - Use HT_TRENDMODE on 15-minute to 1-hour charts - Mode changes more frequently - confirm with volume - Quick strategy switches may be necessary - Keep tight stops regardless of mode

For Swing Trading: - Use HT_TRENDMODE on daily charts - Mode typically more stable - Ideal for switching between trend and range strategies - Adjust position holding time based on mode

For Position Trading: - Use HT_TRENDMODE on weekly charts - Mode changes are rare but significant - Major implications for portfolio allocation - Long-term trend mode = growth stocks, cycle mode = value stocks

Practical Example

Complete adaptive trading system:

require 'sqa/tai'

# Historical price data (need at least 63 bars)
prices = [
  # ... your price data ...
]
highs = [...]
lows = [...]

# Detect current market regime
mode = SQA::TAI.ht_trendmode(prices)
current_mode = mode.last

# Check mode stability (has it been consistent?)
recent_modes = mode.last(5)
mode_changes = recent_modes.each_cons(2).count { |a, b| a != b }
mode_stable = mode_changes <= 1

unless mode_stable
  puts "WARNING: Market regime is unstable (#{mode_changes} changes in 5 bars)"
  puts "Reducing position sizes and waiting for clarity"
end

puts "=" * 50
puts "MARKET REGIME ANALYSIS"
puts "=" * 50
puts "Current Mode: #{current_mode == 1 ? 'TREND' : 'CYCLE'}"
puts "Mode Stability: #{mode_stable ? 'STABLE' : 'UNSTABLE'}"
puts

# TREND MODE STRATEGY
if current_mode == 1
  puts "TREND MODE ACTIVE - Trend-Following Strategy"
  puts "-" * 50

  # Calculate trend indicators
  ema_12 = SQA::TAI.ema(prices, period: 12)
  ema_26 = SQA::TAI.ema(prices, period: 26)
  adx = SQA::TAI.adx(highs, lows, prices, period: 14)
  plus_di = SQA::TAI.plus_di(highs, lows, prices, period: 14)
  minus_di = SQA::TAI.minus_di(highs, lows, prices, period: 14)
  atr = SQA::TAI.atr(highs, lows, prices, period: 14)

  current_price = prices.last
  current_adx = adx.last
  current_atr = atr.last

  # Determine trend direction and strength
  bullish_trend = ema_12.last > ema_26.last && plus_di.last > minus_di.last
  bearish_trend = ema_12.last < ema_26.last && minus_di.last > plus_di.last
  strong_trend = current_adx > 25

  puts "EMA(12): #{ema_12.last.round(2)}"
  puts "EMA(26): #{ema_26.last.round(2)}"
  puts "ADX: #{current_adx.round(2)} #{strong_trend ? '(STRONG)' : '(WEAK)'}"
  puts "ATR: #{current_atr.round(2)}"
  puts

  # Generate trend-following signals
  if bullish_trend && strong_trend
    entry_price = current_price
    stop_loss = current_price - (2.5 * current_atr)
    take_profit = current_price + (4.0 * current_atr)

    puts "STRONG BULLISH TREND DETECTED"
    puts "=" * 50
    puts "ENTRY: BUY at #{entry_price.round(2)}"
    puts "STOP LOSS: #{stop_loss.round(2)} (2.5x ATR)"
    puts "TAKE PROFIT: #{take_profit.round(2)} (4.0x ATR)"
    puts "POSITION SIZE: 150% of base (trend mode)"
    puts
    puts "Strategy: Ride the trend with wide stop"
    puts "Management: Use trailing stop, let profits run"

  elsif bearish_trend && strong_trend
    entry_price = current_price
    stop_loss = current_price + (2.5 * current_atr)
    take_profit = current_price - (4.0 * current_atr)

    puts "STRONG BEARISH TREND DETECTED"
    puts "=" * 50
    puts "ENTRY: SELL at #{entry_price.round(2)}"
    puts "STOP LOSS: #{stop_loss.round(2)} (2.5x ATR)"
    puts "TAKE PROFIT: #{take_profit.round(2)} (4.0x ATR)"
    puts "POSITION SIZE: 150% of base (trend mode)"
    puts
    puts "Strategy: Ride the trend with wide stop"
    puts "Management: Use trailing stop, let profits run"

  else
    puts "NO CLEAR TREND SIGNAL"
    puts "Waiting for strong directional move and ADX > 25"
  end

  puts
  puts "IGNORED INDICATORS IN TREND MODE:"
  puts "- RSI (will show false overbought/oversold)"
  puts "- Stochastic (will generate whipsaw signals)"
  puts "- Bollinger Band extremes (price can stay outside bands)"

# CYCLE MODE STRATEGY
else
  puts "CYCLE MODE ACTIVE - Mean-Reversion Strategy"
  puts "-" * 50

  # Calculate mean-reversion indicators
  rsi = SQA::TAI.rsi(prices, period: 14)
  stoch_k, stoch_d = SQA::TAI.stoch(highs, lows, prices,
                                     fastk_period: 14,
                                     slowk_period: 3,
                                     slowd_period: 3)
  bb_upper, bb_middle, bb_lower = SQA::TAI.bbands(prices,
                                                   period: 20,
                                                   nbdevup: 2,
                                                   nbdevdn: 2)
  atr = SQA::TAI.atr(highs, lows, prices, period: 14)

  current_price = prices.last
  current_rsi = rsi.last
  current_stoch_k = stoch_k.last
  current_atr = atr.last

  puts "Current Price: #{current_price.round(2)}"
  puts "RSI: #{current_rsi.round(2)}"
  puts "Stochastic K: #{current_stoch_k.round(2)}"
  puts "BB Upper: #{bb_upper.last.round(2)}"
  puts "BB Middle: #{bb_middle.last.round(2)}"
  puts "BB Lower: #{bb_lower.last.round(2)}"
  puts "ATR: #{current_atr.round(2)}"
  puts

  # Generate mean-reversion signals
  oversold = current_rsi < 30 && current_stoch_k < 20
  overbought = current_rsi > 70 && current_stoch_k > 80
  near_lower_bb = current_price < bb_lower.last
  near_upper_bb = current_price > bb_upper.last

  if oversold && near_lower_bb
    entry_price = current_price
    stop_loss = current_price - (1.5 * current_atr)
    take_profit = bb_middle.last

    puts "OVERSOLD CONDITION DETECTED"
    puts "=" * 50
    puts "ENTRY: BUY at #{entry_price.round(2)}"
    puts "STOP LOSS: #{stop_loss.round(2)} (1.5x ATR)"
    puts "TAKE PROFIT: #{take_profit.round(2)} (Middle BB)"
    puts "POSITION SIZE: 100% of base (cycle mode)"
    puts
    puts "Strategy: Buy at lower extreme, target mean"
    puts "Management: Take profits at resistance/middle BB"

  elsif overbought && near_upper_bb
    entry_price = current_price
    stop_loss = current_price + (1.5 * current_atr)
    take_profit = bb_middle.last

    puts "OVERBOUGHT CONDITION DETECTED"
    puts "=" * 50
    puts "ENTRY: SELL at #{entry_price.round(2)}"
    puts "STOP LOSS: #{stop_loss.round(2)} (1.5x ATR)"
    puts "TAKE PROFIT: #{take_profit.round(2)} (Middle BB)"
    puts "POSITION SIZE: 100% of base (cycle mode)"
    puts
    puts "Strategy: Sell at upper extreme, target mean"
    puts "Management: Take profits at support/middle BB"

  else
    puts "NO EXTREME CONDITION"
    puts "Waiting for oversold (RSI<30, Stoch<20) at lower BB"
    puts "      or overbought (RSI>70, Stoch>80) at upper BB"
  end

  puts
  puts "IGNORED INDICATORS IN CYCLE MODE:"
  puts "- Moving average crossovers (will whipsaw)"
  puts "- Trend lines (will generate false breakouts)"
  puts "- ADX (not relevant in ranging market)"
end

# Monitor for mode changes
puts
puts "=" * 50
puts "REGIME MONITORING"
puts "=" * 50

if mode.size >= 10
  recent_10_modes = mode.last(10)
  trend_mode_pct = (recent_10_modes.count(1) / 10.0) * 100

  puts "Last 10 bars: #{trend_mode_pct.round}% trend mode, #{(100-trend_mode_pct).round}% cycle mode"

  if trend_mode_pct > 70
    puts "Market predominantly trending - bias toward trend-following"
  elsif trend_mode_pct < 30
    puts "Market predominantly cycling - bias toward mean-reversion"
  else
    puts "Market transitioning between regimes - use caution"
  end
end

Hilbert Transform Family

  • HT_DCPERIOD: Identifies the dominant cycle period - use with HT_TRENDMODE to optimize indicator periods in cycle mode
  • HT_DCPHASE: Shows current phase within the cycle - most useful when HT_TRENDMODE = 0
  • HT_SINE: Generates sine wave signals for timing - works best when HT_TRENDMODE = 0
  • HT_PHASOR: Provides in-phase and quadrature components for advanced cycle analysis
  • HT_TRENDLINE: Instantaneous trendline - works with HT_TRENDMODE for comprehensive analysis

Complementary Indicators

For Trend Mode (when HT_TRENDMODE = 1): - ADX: Confirm trend strength - MACD: Trend direction and momentum - EMA: Moving average crossovers and trends - PLUS_DI/MINUS_DI: Directional movement

For Cycle Mode (when HT_TRENDMODE = 0): - RSI: Overbought/oversold in ranges - STOCH: Oscillator for cycle extremes - BBANDS: Range boundaries and mean - CCI: Commodity Channel Index for ranges

For Mode Confirmation: - ATR: Volatility context for both modes - STDDEV: Statistical volatility measurement

Advanced Topics

Multi-Timeframe Regime Analysis

# Analyze regime across multiple timeframes
daily_prices = [...]   # Daily data
hourly_prices = [...]  # Hourly data

daily_mode = SQA::TAI.ht_trendmode(daily_prices).last
hourly_mode = SQA::TAI.ht_trendmode(hourly_prices).last

puts "Daily Mode: #{daily_mode == 1 ? 'TREND' : 'CYCLE'}"
puts "Hourly Mode: #{hourly_mode == 1 ? 'TREND' : 'CYCLE'}"

# Trading rules based on timeframe alignment
if daily_mode == 1 && hourly_mode == 1
  puts "ALIGNED TREND - Strongest trend-following setup"
  puts "High confidence long-term trend trades"

elsif daily_mode == 0 && hourly_mode == 0
  puts "ALIGNED CYCLE - Strongest mean-reversion setup"
  puts "High confidence range-trading opportunities"

elsif daily_mode == 1 && hourly_mode == 0
  puts "MIXED REGIME - Daily trend, hourly cycles"
  puts "Trade pullbacks within daily trend using hourly oscillators"

else  # daily_mode == 0 && hourly_mode == 1
  puts "MIXED REGIME - Daily range, hourly trend"
  puts "Trade intraday trends but respect daily range boundaries"
end

Portfolio Allocation by Regime

# Allocate capital based on market regime
mode = SQA::TAI.ht_trendmode(prices)
current_mode = mode.last

total_capital = 100_000  # Example portfolio size

if current_mode == 1
  # TREND MODE: Allocate to trend-following strategies
  trend_following_allocation = total_capital * 0.70
  mean_reversion_allocation = total_capital * 0.20
  cash_reserve = total_capital * 0.10

  puts "TREND MODE ALLOCATION:"
  puts "Trend Following: $#{trend_following_allocation.round(2)} (70%)"
  puts "Mean Reversion: $#{mean_reversion_allocation.round(2)} (20%)"
  puts "Cash: $#{cash_reserve.round(2)} (10%)"

else
  # CYCLE MODE: Allocate to mean-reversion strategies
  trend_following_allocation = total_capital * 0.20
  mean_reversion_allocation = total_capital * 0.70
  cash_reserve = total_capital * 0.10

  puts "CYCLE MODE ALLOCATION:"
  puts "Trend Following: $#{trend_following_allocation.round(2)} (20%)"
  puts "Mean Reversion: $#{mean_reversion_allocation.round(2)} (70%)"
  puts "Cash: $#{cash_reserve.round(2)} (10%)"
end

Mode Transition Detection

# Detect and act on mode changes
mode = SQA::TAI.ht_trendmode(prices)

if mode.size >= 2
  current_mode = mode.last
  previous_mode = mode[-2]

  if current_mode != previous_mode
    # Mode just changed
    if current_mode == 1
      puts "MODE CHANGE ALERT: CYCLE → TREND"
      puts "Actions:"
      puts "1. Close mean-reversion positions"
      puts "2. Exit range-trading strategies"
      puts "3. Prepare for breakout opportunities"
      puts "4. Widen stop losses"
      puts "5. Increase position holding time"

    else
      puts "MODE CHANGE ALERT: TREND → CYCLE"
      puts "Actions:"
      puts "1. Take profits on trend-following positions"
      puts "2. Exit momentum trades"
      puts "3. Prepare for range-bound trading"
      puts "4. Tighten stop losses"
      puts "5. Decrease position holding time"
    end
  end
end

Statistical Analysis of Modes

# Analyze mode history for regime characteristics
mode = SQA::TAI.ht_trendmode(prices)

if mode.size >= 50
  # Calculate mode statistics
  total_bars = mode.size
  trend_bars = mode.count(1)
  cycle_bars = mode.count(0)

  trend_percentage = (trend_bars.to_f / total_bars * 100).round(2)
  cycle_percentage = (cycle_bars.to_f / total_bars * 100).round(2)

  puts "REGIME STATISTICS (#{total_bars} bars)"
  puts "Trend Mode: #{trend_percentage}% of time"
  puts "Cycle Mode: #{cycle_percentage}% of time"

  # Find average regime duration
  regime_durations = []
  current_duration = 1

  mode.each_cons(2) do |prev, curr|
    if prev == curr
      current_duration += 1
    else
      regime_durations << current_duration
      current_duration = 1
    end
  end

  avg_duration = regime_durations.sum.to_f / regime_durations.size
  puts "Average Regime Duration: #{avg_duration.round(1)} bars"
  puts "Regime Changes: #{regime_durations.size} times"

  # Characterize market
  if trend_percentage > 60
    puts "Market Character: TRENDING (favors trend-following)"
  elsif cycle_percentage > 60
    puts "Market Character: RANGING (favors mean-reversion)"
  else
    puts "Market Character: BALANCED (mixed strategies needed)"
  end
end

References

  • "Rocket Science for Traders" by John F. Ehlers - Comprehensive coverage of Hilbert Transform and market regime detection
  • "Cybernetic Analysis for Stocks and Futures" by John F. Ehlers - Advanced applications of Hilbert Transform indicators
  • "Cycle Analytics for Traders" by John F. Ehlers - Detailed explanation of cycle vs trend identification
  • Original Research: John F. Ehlers pioneered the application of digital signal processing to financial markets
  • TA-Lib Documentation: HT_TRENDMODE Function

See Also

  • Strategy Selection Guide