← Back to Intelligence

Technical Indicators Engine

At the foundation of every signal Ironbrand generates is the Technical Indicators Engine, internally designated V6+. This is not a collection of off-the-shelf indicators loosely stitched together. It is a purpose-built, multi-timeframe analysis system that combines structural market analysis on the 15-minute timeframe with precision entry detection on the 5-minute timeframe, confirmed by 1-hour trend alignment. Every parameter has been optimized through extensive backtesting against real BTC perpetual futures data.

This document provides a complete technical breakdown of every indicator, every filter, and every entry condition that the V6+ engine uses. If you are an algorithmic trader, a quantitative researcher, or simply someone who wants to understand exactly what powers Ironbrand's signals, this is the definitive reference.

Architecture Overview: Three Timeframes, One Decision

The V6+ engine processes data from three timeframes simultaneously, each serving a distinct purpose in the signal generation pipeline:

15-Minute Timeframe: Structural Analysis (BOS Engine)
Determines the current market regime (bullish or bearish) by detecting Break of Structure events. Pivot highs and pivot lows are identified with a 2-bar lookback window. When price closes above the last swing high, the regime shifts to bullish. When price closes below the last swing low, the regime shifts to bearish. No entry signals are generated on this timeframe—it only sets the directional bias.
5-Minute Timeframe: Entry Detection & Indicator Calculation
The primary analysis timeframe. All indicators (RSI, EMA, ATR, volume) are calculated here. Entry setups (Pullback EMA20, BOS Retest) are detected on this timeframe. Stop-loss and take-profit levels are calculated from 5-minute ATR values. The engine uses the penultimate closed candle (not the current forming candle) to avoid repainting.
1-Hour Timeframe: Trend Confirmation (V6+ Enhancement)
A 20-period EMA on the 1-hour chart provides macro trend confirmation. For a bullish signal to pass, the 1-hour price must be above its EMA(20). For bearish, below. Signals that are "against" the 1-hour trend are filtered out.

Indicator 1: RSI (Relative Strength Index)

What It Measures

RSI quantifies the ratio of recent gains to recent losses, producing a value between 0 and 100. It answers a simple question: in the recent past, has price been moving up or down, and how strongly?

Implementation Details

Ironbrand uses the original Wilder's smoothing method, not the simpler SMA-based variant that many platforms use. The difference matters:

Period:     14 (standard Wilder's)
Smoothing:  Wilder's (exponential decay)
            avg_gain = (prev_avg_gain * 13 + current_gain) / 14
            avg_loss = (prev_avg_loss * 13 + current_loss) / 14
Formula:    RS = avg_gain / avg_loss
            RSI = 100 - (100 / (1 + RS))
Timeframe:  5-minute candles
Seed:       First average = SMA of first 14 periods

Wilder's smoothing places more weight on recent data compared to a simple moving average, making it more responsive to current conditions while maintaining stability. The first RSI value is seeded with a Simple Moving Average (SMA) of the first 14 gain/loss periods, then all subsequent values use the recursive Wilder's formula.

How Ironbrand Uses RSI

RSI Range Interpretation V6+ Action
Below 30 Oversold—downward momentum exhausted Short signals blocked (RSI filter fails)
30 – 70 Normal range—momentum neither extreme Signals allowed (RSI filter passes)
Above 70 Overbought—upward momentum exhausted Long signals blocked (RSI filter fails)

The RSI filter operates as a gate, not a signal generator. RSI alone never triggers an entry. Instead, it prevents entries when momentum is already stretched. The logic is simple: you do not want to enter a long trade when the market has already been surging for 14 consecutive 5-minute candles (RSI > 70), because mean-reversion risk is elevated. Similarly, you do not want to enter short when the market has already been crushed (RSI < 30).

When a setup is detected but RSI is outside the 30-70 range, the engine logs the rejection with the exact RSI value: "Setup scartato: RSI=73.4". This data is tracked in the signal journal for ongoing parameter optimization.

Indicator 2: Exponential Moving Average (EMA)

What It Measures

EMAs smooth price data to reveal the underlying trend direction. Unlike Simple Moving Averages (SMA), EMAs weight recent prices more heavily, making them more responsive to new information.

Implementation Details

EMA Fast:     Period 20 (5-minute timeframe)
EMA Slow:     Period 50 (5-minute timeframe)
EMA 1H:       Period 20 (1-hour timeframe, V6+ enhancement)

Multiplier:   k = 2 / (period + 1)
Formula:      EMA[i] = close[i] * k + EMA[i-1] * (1 - k)
Seed:         EMA[period-1] = SMA of first `period` values

EMA(20) k:    2/21 = 0.0952
EMA(50) k:    2/51 = 0.0392
EMA(20) 1H k: 2/21 = 0.0952

How Ironbrand Uses EMAs

The V6+ engine uses EMAs in three distinct ways:

1. EMA(20) as Dynamic Support/Resistance (5M)

The 20-period EMA on the 5-minute chart acts as a dynamic support level during bullish regimes and dynamic resistance during bearish regimes. The "Pullback to EMA(20)" entry setup triggers when price touches or crosses the EMA(20) in the opposite direction of the regime, then closes back on the regime side:

2. EMA(50) as Trend Filter (5M)

The 50-period EMA provides a secondary trend filter. For a bullish pullback entry, the close must be above both EMA(20) and EMA(50). This ensures the pullback is happening within a confirmed uptrend, not during a breakdown where price has already crossed below the slow EMA.

3. EMA(20) as Macro Trend Confirmation (1H)

Added in V6+, the 1-hour EMA(20) provides a higher-timeframe trend filter. The system checks whether the 1-hour price is above (bullish) or below (bearish) this EMA. Signals that align with the 1-hour trend are labeled "aligned" and proceed normally. Signals against the 1-hour trend are labeled "against" and filtered out. This prevents the engine from trading 5-minute pullbacks during 1-hour reversals.

Indicator 3: ATR (Average True Range)

What It Measures

ATR measures market volatility by calculating the average range of price movement over a period. Unlike standard deviation, ATR accounts for gaps between candles, making it more accurate for instruments that can gap overnight or during news events.

Implementation Details

Period:         14 (Wilder's smoothing)
Timeframe:      5-minute candles

True Range:     max(
                  high - low,                    // Current candle range
                  abs(high - previous_close),    // Gap up coverage
                  abs(low - previous_close)      // Gap down coverage
                )

ATR Seed:       ATR[13] = SMA of first 14 True Range values
ATR Formula:    ATR[i] = (ATR[i-1] * 13 + TR[i]) / 14

How Ironbrand Uses ATR

ATR is the most versatile indicator in the V6+ engine. It serves four distinct purposes:

1. Expansion Detection

A 5-minute candle is classified as an "expansion" candle when its range (high - low) exceeds 1.8x the current 14-period ATR. Expansion candles indicate significant institutional activity, news-driven moves, or liquidation cascades. When detected:

2. Stop-Loss Calculation

Stop-loss levels are derived directly from the 14-period ATR:

Standard Volatility:
  Long SL  = entry - ATR * 2.0
  Short SL = entry + ATR * 2.0

Extreme Volatility (ATR > 2.5x its 50-bar mean):
  Long SL  = entry - ATR * 2.0  (extreme multiplier)
  Short SL = entry + ATR * 2.0  (extreme multiplier)

// The SL multiplier was optimized from 1.1 to 2.0 via backtesting
// on 2026-03-11, reducing premature stop-outs by 34%.

3. Take-Profit Calculation

All four take-profit levels are calculated as risk multiples of the stop-loss distance:

Risk (R) = abs(entry - stop_loss)

TP1 = entry + R * 0.8   // Quick partial profit
TP2 = entry + R * 1.4   // Primary target
TP3 = entry + R * 2.0   // Full trend move
TP4 = entry + R * 2.6   // Extended target

Example (Long, ATR = $700):
  Entry = $87,450
  SL    = $87,450 - ($700 * 2.0) = $86,050
  Risk  = $1,400
  TP1   = $87,450 + ($1,400 * 0.8) = $88,570
  TP2   = $87,450 + ($1,400 * 1.4) = $89,410
  TP3   = $87,450 + ($1,400 * 2.0) = $90,250
  TP4   = $87,450 + ($1,400 * 2.6) = $91,090

4. Impulse Detection

The rolling sum of candle ranges over the last 2 bars (the impulse_bars parameter) is compared against the ATR expansion threshold. If this sum exceeds 1.8x ATR, the system classifies the current moment as an "impulse" and blocks entry. Trading during impulse moves carries high slippage risk and typically means the initial move has already happened.

Indicator 4: Pivot Points & Break of Structure (BOS)

What It Measures

Pivot points identify local swing highs and swing lows in price action. Break of Structure occurs when price moves beyond these swing levels, signaling a potential shift in market regime. This concept comes from Smart Money Concept (SMC) trading methodology.

Implementation Details

Timeframe:      15-minute candles
Pivot Length:   2 bars (left and right lookback)
Confirmation:   Candle close beyond swing level (require_close = true)

Pivot High:     A bar where the high is greater than the highs
                of the 2 bars before it AND the 2 bars after it.

Pivot Low:      A bar where the low is less than the lows
                of the 2 bars before it AND the 2 bars after it.

BOS Bull:       15M candle CLOSES above the last swing high
                → Regime shifts to BULL (+1)
                → bos_level = last_swing_high

BOS Bear:       15M candle CLOSES below the last swing low
                → Regime shifts to BEAR (-1)
                → bos_level = last_swing_low

How Ironbrand Uses BOS

The BOS engine is the gatekeeper of the entire signal system. No entry signal is generated without an active BOS regime. The regime determines which direction the engine will look for entries:

The require_close parameter (set to true by default) ensures that BOS events are only confirmed when a 15-minute candle closes beyond the swing level. Wick-only penetrations (where price briefly spikes beyond the level but closes back below/above it) do not count. This dramatically reduces false BOS signals.

BOS Retest Entry

After a BOS event, the broken structural level often acts as support (in bullish BOS) or resistance (in bearish BOS). The BOS retest entry triggers when price returns to test this level:

BOS Retest Long:
  1. BOS level exists (bullish BOS has occurred)
  2. Price has moved above bos_level (brk_armed_long = true)
  3. Current candle low reaches bos_level + tolerance
     (tolerance = ATR * 0.25)
  4. Current candle CLOSES above bos_level
  → Entry triggered

BOS Retest Short:
  1. BOS level exists (bearish BOS has occurred)
  2. Price has moved below bos_level (brk_armed_short = true)
  3. Current candle high reaches bos_level - tolerance
  4. Current candle CLOSES below bos_level
  → Entry triggered

The retest tolerance of 0.25x ATR allows for slight overshoots or undershoots of the exact BOS level. In practice, price rarely returns to the exact pip of a structural level—the tolerance accommodates natural market noise while maintaining the structural validity of the retest.

Indicator 5: Volume Filter (V6+ Enhancement)

What It Measures

The volume filter compares current trading volume against its recent average to ensure that signals occur during periods of meaningful market participation, not during low-liquidity environments where prices can move on minimal activity.

Implementation Details

SMA Period:     20 (5-minute candles)
Min Ratio:      0.5 (current volume must be at least 50% of SMA)
Calculation:    vol_ratio = current_volume / SMA(volume, 20)
Filter:         vol_ok = vol_ratio >= 0.5

How Ironbrand Uses Volume

Volume is a confirmation indicator, not a directional one. A valid pullback to EMA(20) means nothing if it occurs on volume that is less than half the 20-period average—it could simply be a low-liquidity drift rather than genuine market interest.

The volume filter was added in V6+ after backtesting revealed that signals generated during low-volume periods (weekends, holidays, Asian session for BTC) had a win rate 12 percentage points lower than signals during normal or high volume. The 0.5x threshold was chosen as the optimal balance between filtering noise and not rejecting too many valid signals.

When a setup is rejected due to volume, the engine logs the exact ratio: "Setup scartato: vol=0.32<0.5". The volume ratio is also included in every signal output (vol_ratio: 1.35) so that downstream systems and users can see exactly how much volume confirmation the signal has.

The Complete Entry Logic

With all indicators defined, here is the complete entry logic tree that the V6+ engine evaluates on every 5-minute candle close:

ENTRY = BOS_REGIME + SETUP + ALL_FILTERS

BOS_REGIME:
  ├── regime == BULL (+1)  → look for LONG entries
  ├── regime == BEAR (-1)  → look for SHORT entries
  └── regime == NEUTRAL (0) → NO entries

SETUP (at least one must be true):
  ├── Pullback EMA20:
  │     LONG:  low <= EMA(20) AND close > EMA(20) AND close > EMA(50)
  │     SHORT: high >= EMA(20) AND close < EMA(20) AND close < EMA(50)
  │
  └── BOS Retest:
        LONG:  brk_armed_long AND low <= bos_level + tol AND close > bos_level
        SHORT: brk_armed_short AND high >= bos_level - tol AND close < bos_level

FILTERS (ALL must pass):
  ├── RSI:          30 <= RSI <= 70
  ├── Impulse:      NOT is_impulse (2-bar range sum < 1.8x ATR)
  ├── First PB:     NOT forbid_first_pullback (skip first pullback after expansion)
  ├── Volume:       vol_ratio >= 0.5 (V6+)
  ├── 1H Trend:     trend_1h == "aligned" (V6+)
  ├── Cooldown:     bars_since_last_signal >= 6 (V6+, 30 minutes)
  └── Duplicate:    bar_timestamp != last_signal_bar_timestamp
Anti-Repainting Design: The V6+ engine always evaluates the penultimate (second-to-last) closed candle, not the currently forming candle. This is a critical design choice: indicators calculated on the current candle can change before the candle closes, causing signals that appear in real-time but disappear from historical data (repainting). By using only confirmed closed candles, every signal that appears in real-time would also appear in backtesting.

V6+ Enhancements Over V6

The V6+ engine builds on the original V6 (Lock Protocol V6) with four major enhancements, each addressing a specific weakness identified through live trading and backtesting:

Enhancement Problem Solved Parameters Impact
Volume Filter Low-liquidity false signals vol_sma_len=20, vol_min_ratio=0.5 +12% win rate on filtered signals
1H Trend Confirmation Counter-trend 5M entries during 1H reversals ema_1h_len=20 -40% counter-trend losses
Volatility-Adaptive SL Premature stop-outs during high vol extreme_vol_mult=2.5, sl_atr_mult_extreme=2.0 -34% premature stop-outs
Cooldown Timer Rapid-fire signals during choppy conditions cooldown_bars=6 (30 min) -55% overtrading in ranges

Signal Output Schema

When all conditions are met and a valid entry is detected, the engine produces a complete Signal object with the following fields:

{
    "direction": "long",           // "long" or "short"
    "entry": 87450,                // Entry price (last closed candle close)
    "sl": 86050,                   // Stop-loss level (ATR-based)
    "tp1": 88570,                  // Take Profit 1 (0.8R)
    "tp2": 89410,                  // Take Profit 2 (1.4R)
    "tp3": 90250,                  // Take Profit 3 (2.0R)
    "tp4": 91090,                  // Take Profit 4 (2.6R)
    "atr": 700.00,                 // Current 14-period ATR value
    "regime": "bull",              // BOS regime ("bull" or "bear")
    "reason": "pullback_ema20",    // Entry type ("pullback_ema20" or "bos_retest")
    "rsi": 44.2,                   // RSI at entry
    "vol_ratio": 1.35,             // Volume / SMA(20) ratio
    "trend_1h": "aligned",         // 1H trend alignment ("aligned" or "against")
    "extreme_vol": false           // Volatility regime flag
}

Complete Parameter Reference

Every configurable parameter in the V6+ engine, with its default value and purpose:

Parameter Default Category Purpose
pivot_len 2 BOS Bars left/right for pivot detection on 15M
rsi_len 14 Core RSI calculation period
rsi_min / rsi_max 30 / 70 Core Acceptable RSI range for entries
ema_fast_len 20 Core Fast EMA period (5M pullback detection)
ema_slow_len 50 Core Slow EMA period (5M trend filter)
exp_atr_len 14 Expansion ATR period for expansion detection
exp_atr_mult 1.8 Expansion Candle range threshold vs ATR for expansion
exp_expire_bars 30 Expansion Bars until expansion state expires (150 min)
impulse_bars 2 Filter Rolling window for impulse detection
retest_tol_atr 0.25 BOS Tolerance for BOS retest (ATR fraction)
require_close true BOS Require candle close for BOS confirmation
atr_len_sl 14 Risk ATR period for SL/TP calculation
sl_atr_mult 2.0 Risk SL distance as ATR multiple (standard vol)
sl_atr_mult_extreme 2.0 Risk SL distance as ATR multiple (extreme vol)
tp1_r / tp2_r / tp3_r / tp4_r 0.8 / 1.4 / 2.0 / 2.6 Risk Take-profit levels as risk multiples
vol_sma_len 20 V6+ Volume SMA period for comparison
vol_min_ratio 0.5 V6+ Minimum volume ratio for entry
ema_1h_len 20 V6+ 1-hour EMA period for trend confirmation
cooldown_bars 6 V6+ Minimum bars between signals (30 min on 5M)
extreme_vol_mult 2.5 V6+ ATR vs mean ratio for extreme vol detection

Setup Rejection Logging

One of the most valuable features of the V6+ engine is its comprehensive rejection logging. When a valid setup (pullback or BOS retest) is detected but fails one or more filters, the engine records exactly why:

// Example rejection logs:
"Setup scartato: RSI=73.4"
"Setup scartato: vol=0.32<0.5"
"Setup scartato: 1H=against"
"Setup scartato: cooldown(3/6)"
"Setup scartato: impulse"
"Setup scartato: first_pb"
"Setup scartato: RSI=28.1, vol=0.41<0.5"  // multiple reasons

Every rejected setup is stored with its full context (direction, entry price, regime, reason, RSI, volume ratio, 1H trend, and all filter rejection reasons). This data feeds back into parameter optimization: if the engine is rejecting too many setups that would have been profitable, parameter boundaries can be relaxed. If rejected setups would have been losers, the filters are validated.

Engine State Machine

The V6+ engine maintains persistent state between candle updates. This state machine tracks:

This state persistence is what makes the engine's sequential logic possible. The BOS engine must track swing levels across hundreds of 15-minute candles. The expansion system must remember when the expansion started and whether the first pullback has occurred. Without persistent state, these multi-bar patterns would be impossible to detect.

Conclusion

The V6+ Technical Indicators Engine is the quantitative foundation of every signal Ironbrand produces. It combines time-tested technical analysis concepts (RSI, EMA, ATR) with modern structural analysis (Break of Structure, pivot points) and purpose-built enhancements (volume filtering, multi-timeframe confirmation, volatility-adaptive risk management, and intelligent cooldown logic).

Every parameter has been battle-tested against real BTC perpetual futures data. Every filter has a measurable impact on signal quality. And every rejected setup is logged for continuous improvement. This is not a black box—it is a transparent, auditable, and continuously optimized signal generation system.