Knowledge · Strategies · Anatomy of a Strategy: The Four Pillars

Anatomy of a Strategy: The Four Pillars

Botty-Architektur (strategies/conditions/)
Strategy anatomy Evidence: Very strong all crypto
10/10
Relevance for Botty
Botty has no fixed strategies — only freely combinable building blocks. Every run = exactly ONE entry + any number of filters + position sizing + any number of exits. This entry explains the four pillars, lists every building block per category (with links to the indicator/concept entries), and shows which entry fits which market regime.
In Botty a strategy is not a monolithic package but a composition of four interchangeable pillars: ① Entry (exactly one per run — the trigger), ② Filter (any number — they trigger nothing, they only veto), ③ Position sizing (how large the position becomes relative to risk), and ④ Exit (any number — stops, targets, trailing — that balance profit and risk). The runner chains them together via resolve_signal(). Crucial: the entry type must fit the market regime, and the filters must fit the entry.
Relevance Score 10/10
Fundamental overview of how every Botty strategy is built. The building blocks come 1:1 from strategies/conditions/registry.py — the single source of truth. Anyone building a new strategy or configuring a mega-sweep starts here.
NameTyp. valueDescription
Entry 1 pro Run The trigger. Exactly one entry condition is active. Trend entries (Donchian, EMA cross) vs. mean-reversion entries (BB Extreme, RSI-MR) serve opposite regimes.
Filter 0..n Veto only. Each filter can block the trade, none triggers it. More filters = fewer bad trades, but also a smaller sample and greater overfitting risk.
Position Sizing risk% / Stop-Distanz How much capital is risked per trade. Capped by MAX_POSITION_USD. According to the ML findings, volatility-based sizing is the most robust edge.
Exit 0..n Stops (ATR trailing, swing, fixed), targets (swing high, ATR multiple), and time/signal exits. They balance profit-taking against risk.

Pros

  • Combinatorial: every entry × every filter set × every exit set — the mega-sweep searches exactly this space
  • Reusable: a new filter is immediately combinable with every entry, without any strategy code
  • Regime-aware: entry type and filters can be tuned specifically to trend or range phases
  • A single source of truth (registry.py) — UI, runner, mega-sweep, and experiment tracking read the same defaults/ranges

Cons

  • The combination space is huge → overfitting risk; every additional filter shrinks the sample
  • A wrong pairing (mean-reversion entry + trend filter) is self-destructive and not prevented automatically
  • Many building blocks died in walk-forward validation (sweep:False) — availability ≠ edge
This IS Botty's architecture. Every live strategy and every backtest is an instance of these four pillars.

Botty has no 'strategies' — only building blocks

The most important point first: in Botty there is no fixed strategy object like 'the Donchian strategy'. There are only conditions that the runner freely assembles per run. 'Donchian' is therefore not a strategy but an entry condition that you combine with any filters, a sizing, and any exits (strategies/conditions/registry.py is the single source of truth).

Every strategy = exactly one entry + any number of filters + position sizing + any number of exits, chained via resolve_signal().

(Tip: the linked building blocks below lead to the respective indicator/concept entry in the knowledge base.)

The four pillars on a single trade

The four pillars of a strategy on an example trade

Pillar Role Mnemonic
① Entry The trigger. Exactly one per run. "When do I enter?"
② Filter Conditions that all must agree on. They only veto — none triggers a trade. "When do I not enter?"
③ Position Sizing How large the position becomes, usually risk% ÷ stop distance. "How much do I risk?"
④ Exit Stops, trailing, targets, time/signal exits. "When do I exit — with profit or a capped loss?"

In the image: the filters form a gate before entry (yellow). Only once all pass does the entry trigger fire (light blue). The stop distance is the risk unit from which the position size is derived (purple). The trailing stop (teal) follows the price upward and locks in the profit until it is hit on the pullback.

Pillar ①: Entry conditions (exactly one per run)

This list comes live from the condition registry (strategies/conditions/registry.py) — new entries appear here automatically. Which entry fits which market regime is shown in the regime table further down.

Baustein Bezeichnung Beschreibung Parameter
adx_dmi_regime ADX/DMI Regime Trend-Onset Frischer Trendbeginn: ADX/DMI-Regime kippt mit Hysterese auf Trend. adx_period (default 14, 2–40), regime_range_enter (default 20.0, 10–30), regime_trend_enter (default 25.0, 18–40)
bb_extreme Bollinger Band Extreme (Mean Reversion) Mean reversion: entry at the Bollinger band extreme, target back to the band midline. bb_std (default 2.0, 1.5–3.0), bb_period (default 20, 10–50)
burj_khalifa Burj-Khalifa Reversal (Pifagor) Reversal at LMACD+RSI+EMA200 confluence (Pifagor rebuild). bk_vol_mult (default 1.2, 0.5–3.0), bk_rsi_threshold (default 35.0, 20–55)
donchian_breakout Donchian Channel Breakout Breakout above the N-period high/low (Turtle-style trend following). dc_period (default 20, 10–100)
elliott_wave_w3 Elliott Wave 3 Entry ⛔ sweep:False Entry into the presumed Elliott wave 3 after a wave 1/2 structure. fib_max (default 0.786, 0.3–1.0), fib_min (default 0.382, 0.1–0.7), min_w1_pct (default 0.02, 0.005–0.15), max_w2_bars (default 50, 5–300), zz_threshold (default 0.03, 0.01–0.15)
ema_crossover EMA Crossover Schnelle EMA kreuzt langsame — klassischer Trendfolge-Einstieg. ema_fast (default 9, 2–50), ema_slow (default 21, 5–200)
fibdiv FibDiv Fibonacci Retracement (Pifagor) Fibonacci retracement zone + divergence confirmation (Pifagor rebuild). fibdiv_max_bars (default 30, 5–100), fibdiv_threshold (default 0.03, 0.01–0.1), fibdiv_stop_level (default 0.8, 0.7–0.95), fibdiv_entry_level (default 0.618, 0.5–0.75), fibdiv_min_impulse (default 0.02, 0.005–0.1)
funding_rate_extreme Funding Rate Extreme (Contrarian) Contrarian: extremes Perp-Funding wird gefadet. funding_long_threshold (default -1e-05, -0.001–-1e-06), funding_short_threshold (default 5e-05, 1e-05–0.0005)
holy_grail_pullback Holy Grail EMA20 Pullback Raschke Holy Grail: Pullback an die EMA20 im starken ADX-Trend. lookback (default 5, 2–20), adx_threshold (default 30.0, 10–60)
macd_crossover MACD Zero-Line Crossover ⛔ sweep:False MACD crosses the zero line — trend-momentum entry. ema_fast (default 9, 2–50), ema_slow (default 21, 5–200)
micro_pullback Micro Pullback (Ross Cameron) Impuls (Squeeze) -> flacher Pullback -> Einstieg auf der ersten Candle mit neuem Hoch. Momentum-Continuation, long. min_impulse_pct (default 0.004, 0.001–0.02), impulse_lookback (default 10, 5–30), pullback_min_pct (default 0.001, 0.0–0.01)
outside_inside_day Outside-Inside Breakout (Raschke) Raschke 3-bar pattern: inside day after outside day, breakout entry.
regime_switch Regime-Switch (SFP im Trend / BB-Extreme im Range) Regime-adaptiv: SFP-Entries im Trend, BB-Extreme in der Range (ADX/DMI als Schalter). bb_std (default 2.0, 1.5–3.0), bb_period (default 20, 10–50), adx_period (default 14, 2–40), sfp_lookback (default 20, 5–100), regime_range_enter (default 20.0, 10–30), regime_trend_enter (default 25.0, 18–40)
rsi_mean_reversion RSI Mean Reversion (Sideways) RSI extreme in sideways phases: buy oversold, short overbought. rsi_oversold (default 30.0, 10–45), rsi_overbought (default 70.0, 55–90), rsi_min_bars_in_extreme (default 1, 1–5)
sfp Swing Failure Pattern (Hsaka) Swing failure pattern (Hsaka): a failed breakout above the swing high/low is faded. sfp_lookback (default 20, 5–100)
zscore_dislocation Z-Score Dislocation (Mean Reversion) Fades a statistically abnormal price spike (>N σ) — mean reversion on a dislocation. zscore_period (default 20, 10–100), zscore_threshold (default 2.0, 1.5–4.0)
zscore_momentum Z-Score Momentum (Continuation) Goes WITH a statistically abnormal spike (>N σ) — continuation instead of mean reversion. zscore_period (default 20, 10–100), zscore_threshold (default 2.0, 1.5–4.0)

Pillar ②: Filters (any number — veto only)

Baustein Bezeichnung Beschreibung Parameter
adx_filter ADX Trend Strength Minimum ADX — trade only when a trend is present. min_adx (default 0.0, 0–60), adx_period (default 14, 2–40)
adx_rising_filter ADX Rising (Raschke) ADX slope must be positive — the trend is gaining strength (Raschke). adx_period (default 14, 2–40), min_adx_slope (default 0.0, 0–5)
atr_pct_filter ATR% Volatility Filter ATR as % of price must be within the allowed volatility band. min_atr_pct (default 0.0, 0–5)
big_guy_filter Big Guy Whale Volume (Pifagor) Requires a whale volume spike in the trade direction (Pifagor Big Guy). big_guy_vol_mult (default 2.5, 1.5–5.0)
bocpd_filter BOCPD Fresh-Change-Point Filter Bayesian Online Changepoint Detection — trade only shortly after a fresh structural break. bocpd_max_p_short (default 0.3, 0.1–0.95)
choppiness_filter Choppiness Index (Trend vs Range) Choppiness Index — vetot Entries in zerhacktem Markt. chop_period (default 14, 5–60), max_choppiness (default 100.0, 30–100), min_choppiness (default 0.0, 0–70)
cooldown Post-Trade Cooldown Locks out re-entries for N candles after a stop-out. cooldown_candles (default 0, 0–20)
cvd_align_filter CVD/OFI Direction-Alignment Filter Cumulative Volume Delta / order flow must confirm the trade direction. ofi_min_for_long (default 0.0, 0.0–0.5)
cvd_divergence_filter CVD Divergence Filter Vetoes entries on divergence between CVD and price. divergence_threshold (default 0.0, -0.3–0.3)
efficiency_filter Efficiency Ratio (Trend Quality) Kaufman efficiency ratio as a trend-quality gate (ensemble partner to the ADX). er_period (default 20, 5–60), min_efficiency (default 0.0, 0.0–0.8)
ema200_filter EMA 200 Trend Filter Allows trades only in the direction of the EMA200. ema200_filter (default False)
ew_w3_filter Elliott Wave W3 Structure Filter Elliott-Welle-3-Struktur als Kontext-Veto. ew_fib_max (default 0.786, 0.3–1.0), ew_fib_min (default 0.5, 0.1–0.7), ew_min_w1_pct (default 0.02, 0.005–0.15), ew_max_w2_bars (default 25, 5–200), ew_zz_threshold (default 0.05, 0.01–0.15)
funding_rate_filter Funding Rate Contrarian Filter Vetoes entries on unfavorable perp funding (contrarian band). max_funding_for_long (default 0.001, 0.0001–0.01), min_funding_for_short (default -0.001, -0.01–-0.0001)
hurst_regime_filter Hurst Regime Filter (Trending Only) Hurst-Exponent muss ein Trending-Regime anzeigen (Persistenz). hurst_lag (default 10, 2–30), hurst_min (default 0.55, 0.45–0.7), hurst_window (default 100, 50–300)
lmacd_pink_filter LMACD Pink/Orange Signal (Pifagor) LMACD-Signalfarbe (Pink/Orange) als Momentum-Gate (Pifagor). lmacd_lookback (default 1, 1–5)
mfi_pifagor_filter MFI Pifagor Filter Money Flow Index per Pifagor rules. mfi_long_threshold (default -9.0, -50–0), mfi_short_threshold (default 9.0, 0–50)
money_waterfall_filter Money Waterfall Capital Flow (Pifagor) Capital-flow filter: long only in the contrarian buy zone of the waterfall (Pifagor). mw_long_max (default 0.0, -0.5–0.5), mw_short_min (default 0.0, -0.5–0.5)
obv_organic_filter OBV Organic Movement Filter (Pifagor Histogram) Blocks entries when OBV momentum diverges from price (Pifagor).
range_filter Range Market Filter (max ADX) Maximum ADX — trade only in sideways phases (counterpart to the ADX filter). max_adx (default 25.0, 15–50), adx_period (default 14, 2–40)
regime_ensemble_filter Regime-Ensemble (ADX+ER+CHOP Mehrheitsvotum) Majority vote from ADX, efficiency ratio and choppiness on trend vs. range. ens_er (default 0.3, 0.1–0.6), ens_adx (default 22.0, 15–35), ens_chop (default 55.0, 35–65), ens_range_votes (default 0, 0–3), ens_trend_votes (default 0, 0–3)
rsi_filter RSI Momentum Filter Vetoes entries when the RSI is outside the allowed band. rsi_long_max (default None, 0–100), rsi_short_min (default None, 0–100)
session_filter Trading Session (UTC hours) Trades only within defined UTC hour windows. session_hour_end (default 24, 1–24), session_hour_start (default 0, 0–23)
volume_filter Volume vs Rolling Average Volume must be above the rolling average. volume_lookback (default 20, 5–100), min_volume_ratio (default 1.0, 0.1–5)
vrp_filter VRP Min-Percentile Filter (DVOL/RV) Volatility risk premium (DVOL vs. realized vol) must be above the minimum percentile. vrp_min_percentile (default 0.2, 0.0–0.8)

Rule of thumb: the filter must fit the entry. A trend filter (adx_filter) belongs with a trend entry; a range_filter (max ADX) belongs with mean-reversion entries like bb_extreme. Example from the code: the bocpd_filter helps bb_extreme (+17%) but hurts Donchian (−15%).

Pillar ③: Position Sizing

Baustein Bezeichnung Beschreibung Parameter
equity_throttle Equity-Curve Throttle (Turtle) Drawdown brake per Turtle rule: reduce trade size by cut% per dd_step of drawdown from the equity high; normalizes with the recovery — pushes risk of ruin toward zero. throttle_cut (default 0.2, 0.1–0.5), throttle_dd_step (default 0.1, 0.05–0.25)
risk_sizing Risk-Based Sizing Position size = account × risk% ÷ stop distance — constant equity loss per stop-out. risk_pct (default 1.0, 0.1–5.0)
Baustein Bezeichnung Beschreibung Parameter
pyramid_entry Turtle Pyramiding (price-based adds) Scales up winning positions: one more unit per +step×ATR above the last fill, until max_units is reached; the stop trails with every add. Anti-martingale — never into the losing direction. pyramid_step_atr (default 0.5, 0.25–2.0), pyramid_max_units (default 3, 2–5), pyramid_stop_mult (default 1.0, 0.5–4.0), pyramid_regime_gate (default 0, 0–1)
staggered_entry Staggered Entry ⛔ sweep:False ⚰️ Buried (2026-06-11): pure timing smoothing with no return evidence — the EV-relevant variant is pyramid_entry. Entry in N equal tranches across consecutive candles (Pifagor: 5). entry_parts (default 3, 2–5)

Plus the global caps from execution/config.py — live values:

Parameter Live value
POSITION_SIZE_PCT 1.0
Position cap 100% der Equity (MAX_POSITION_PCT = 1.0, MAX_POSITION_USD = 12.0)
LEVERAGE 3x
Vol-target sizing advisory mode (off)
Equity throttle (Turtle brake) active: −30% size per −10% drawdown from the equity high

According to Botty's ML findings, volatility-based sizing is the most robust edge of all — the vol regime is predictable, the direction is not.

Pillar ④: Exits (any number)

Baustein Bezeichnung Beschreibung Parameter
atr_profit_target ATR Profit Target Profit target as an ATR multiple — makes the R:R explicit. atr_target_mult (default 2.0, 0.5–5.0)
atr_trailing_stop ATR Trailing Stop Initial-Stop + nachgezogener Stop, beide als ATR-Multiple. atr_stop_mult (default 1.5, 0.1–10), atr_trail_mult (default 2.0, 0.1–10)
bailout_exit Bailout Exit (Williams) Williams' Bailout: Ausstieg am ersten profitablen Open. bailout_min_bars (default 1, 1–20)
ema_cross_exit EMA Crossover Exit (signal-based) Exit on the opposite crossover of the EMAs. exit_ema_fast (default 9, 2–50), exit_ema_slow (default 21, 5–200)
fixed_stop Fixed % Stop Fixed stop as % of the entry price. fixed_stop_pct (default 1.0, 0.1–10)
macd_cross_exit MACD Zero-Line Exit (signal-based) Exit when the MACD crosses back over the zero line.
partial_tp Partial TP (3-stage) Three-stage partial exits at % targets, the remainder rides on the trailing stop. tp1_pct (default 1.8, 0.5–20.0), tp2_pct (default 2.7, 0.5–20.0), tp3_pct (default 6.1, 0.5–30.0), tp1_size (default 0.33, 0.1–0.9), tp2_size (default 0.33, 0.1–0.9), tp3_size (default 0.34, 0.1–1.0)
profit_target Swing High/Low Target Profit target at the opposite swing high/low. target_lookback (default 20, 5–50)
swing_stop Swing Stop (Touching Candle) Stop am letzten Swing-Tief/-Hoch (Touching Candle).
time_stop Time Stop Exit after N candles, regardless of price. time_stop_bars (default 3, 1–20)

Which entry for which regime?

This is the key that holds the mental model together: trend entries and mean-reversion entries serve opposite regimes. A Donchian breakout wants a trend; BB Extreme wants a range. Confuse the two and you trade against yourself.

Entry Trend ↑ Trend ↓ Range Reversal Maturity Note / open question
donchian_breakout 🟢 live (DONCHIAN_20, wallet 1); stop-robustness sweep winner
ema_crossover 🟡 in the sweep pool; whipsaw-prone, not a live winner
adx_dmi_regime new — no completed sweep yet
holy_grail_pullback 🟡 tested, no live use (yet)
macd_crossover 🔴 sweep:False — negative in 10/11 WF windows
elliott_wave_w3 🔴 sweep:False — worst performer
fibdiv Pifagor replica, not conclusively validated
sfp 🟡 in the pool, verdict open
bb_extreme 🟢 live (BB_EXTREME_1/2); 7/9 OOS windows, the most thoroughly tested
rsi_mean_reversion 🟡 own sweep run, verdict open
burj_khalifa Pifagor replica, open
funding_rate_extreme open

Regime suitability: ✅ fits well · ➖ neutral / conditional · ❌ unsuitable

Maturity: 🟢 validated (live-ready) · 🟡 under review · ⚪ untested · 🔴 discarded. What the levels mean and which metrics (mega-sweep score, walk-forward, PBO, Monte Carlo …) decide them is explained under Live readiness: when is a backtest live-ready?. The maturity column is a living field and is continuously extended.

The pattern is clear: trend entries (top) and mean-reversion/reversal entries (bottom) serve opposite regimes — the green cells form a diagonal, and the opposite corner is red in each case. Botty detects the regimes themselves via the ADX/DMI filter (see /regime); what other methods exist for this is described in the research entry Detecting & predicting market regimes.

To look up yourself

  • Building blocks + defaults/ranges: strategies/conditions/registry.py
  • Chaining: strategies/conditions/resolver.py (resolve_signal)
  • Combinatorial search: backtesting/megasweep.py
  • Regime classifier: indicators/regime.py → UI /regime