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:
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.
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.
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:
- Bullish pullback: Price low touches or drops below EMA(20), but the close is above EMA(20) and above EMA(50). This indicates the trend is absorbing selling pressure.
- Bearish pullback: Price high touches or rises above EMA(20), but the close is below EMA(20) and below EMA(50). The trend is absorbing buying pressure.
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:
- The expansion state activates and persists for up to 30 bars (2.5 hours on 5M)
- The first pullback after expansion is skipped (the
forbid_first_pullbackrule) - Subsequent pullbacks within the expansion window are eligible for entry
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:
- BULL regime (regime = +1): Only long entries are considered. The engine scans for bullish pullbacks to EMA(20) and bullish BOS retests.
- BEAR regime (regime = -1): Only short entries are considered. The engine scans for bearish pullbacks to EMA(20) and bearish BOS retests.
- NEUTRAL (regime = 0): No entries. The engine waits for the first BOS event to establish direction.
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
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:
- BOS State: Last swing high, last swing low, current regime (+1/-1/0), current BOS level
- Expansion State: Whether expansion is active, which bar triggered it, whether the first pullback has been seen
- Retest Armed State: Whether price has moved beyond the BOS level (enabling retest entry)
- Signal State: Timestamp of last signal (for duplicate prevention and cooldown)
- Filtered Setup State: Last rejected setup (for dashboard display and analysis)
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.