# Cookbook Practical strategy recipes built on Wickra's streaming indicators. Each recipe is a small, runnable snippet you can drop into a backtest loop or a live trading bot. Both paths share the same indicator state, so the same recipe works in either mode — see [Streaming vs Batch](Streaming-vs-Batch.md). ## 1. RSI mean reversion Enter when RSI crosses out of an extreme; flatten when it returns to neutral. ```python import wickra as ta rsi = ta.RSI(14) position = 0 # 0 flat, +1 long, −1 short for price in price_feed: v = rsi.update(price) if v is None: continue if position == 0 and v < 30: position = 1 print(f"BUY at {price:.2f}") elif position == 1 and v > 50: position = 0 print(f"EXIT long at {price:.2f}") elif position == 0 and v > 70: position = -1 print(f"SHORT at {price:.2f}") elif position == -1 and v < 50: position = 0 print(f"COVER short at {price:.2f}") ``` ## 2. MACD histogram crossover Trade in the direction of a MACD-histogram sign change. Zero-crossings of the histogram (`MACD − signal`) are the canonical trigger and lead the slower MACD-vs-signal line cross. ```rust use wickra::{Indicator, MacdIndicator}; let mut macd = MacdIndicator::classic(); // (12, 26, 9) let mut last_hist: Option = None; for &price in &prices { if let Some(v) = macd.update(price) { if let Some(prev) = last_hist { if prev <= 0.0 && v.histogram > 0.0 { println!("BUY: MACD histogram turned positive at {price:.2}"); } else if prev >= 0.0 && v.histogram < 0.0 { println!("SELL: MACD histogram turned negative at {price:.2}"); } } last_hist = Some(v.histogram); } } ``` ## 3. Bollinger band breakout Trade in the direction of a band-piercing close, taking the bands as a dynamic support / resistance. ```python import wickra as ta bb = ta.BollingerBands(20, 2.0) for price in price_feed: out = bb.update(price) if out is None: continue upper, _middle, lower, _stddev = out if price > upper: print(f"BREAKOUT (long): {price:.2f} > upper {upper:.2f}") elif price < lower: print(f"BREAKOUT (short): {price:.2f} < lower {lower:.2f}") ``` ## 4. ADX-gated trend filter Take EMA-crossover signals only when ADX confirms a trend is in place. This is a textbook way to silence whipsaws in a ranging market. ```python import wickra as ta ema_fast = ta.EMA(20) ema_slow = ta.EMA(50) adx = ta.ADX(14) for high, low, close in candle_feed: f = ema_fast.update(close) s = ema_slow.update(close) a = adx.update(high, low, close) # (plus_di, minus_di, adx) or None if f is None or s is None or a is None: continue _, _, adx_v = a if adx_v < 25: continue # ranging market — skip if f > s: print(f"LONG: EMA20 > EMA50, ADX={adx_v:.1f}") elif f < s: print(f"SHORT: EMA20 < EMA50, ADX={adx_v:.1f}") ``` ## 5. Multi-timeframe confirmation Only take a 1-minute entry when the 1-hour trend agrees. With Wickra you keep one streaming indicator per timeframe and feed each only the candles that belong to it. `wickra-data`'s [`Resampler`](Data-Layer.md) rolls one candle stream up into a coarser one; the canonical example is `examples/rust/src/bin/multi_timeframe.rs`. ```rust use wickra::{Indicator, Rsi}; let mut rsi_1m = Rsi::new(14)?; let mut rsi_1h = Rsi::new(14)?; for candle in one_min_candles { let fast = rsi_1m.update(candle.close); if candle.is_hour_close { let slow = rsi_1h.update(candle.close); if let (Some(f), Some(s)) = (fast, slow) { if f > 70.0 && s > 50.0 { println!("strong overbought (1m {f:.1} / 1h {s:.1})"); } else if f < 30.0 && s < 50.0 { println!("strong oversold (1m {f:.1} / 1h {s:.1})"); } } } } ``` ## 6. SuperTrend trailing stop `SuperTrend` is a single-line ATR-banded trailing stop with explicit flip logic — drop it into a long-only loop to manage exits: ```python import wickra as ta st = ta.SuperTrend(10, 3.0) position = 0 # 0 flat, +1 long for high, low, close in candle_feed: out = st.update(high, low, close) if out is None: continue value, direction = out if direction > 0 and position == 0: position = 1 print(f"BUY at {close:.2f}, stop={value:.2f}") elif direction < 0 and position == 1: position = 0 print(f"EXIT at {close:.2f} (SuperTrend flipped)") ``` ## 7. Chained indicators When you want an indicator computed *over the output of another*, use the Rust `Chain` combinator. The chain itself implements `Indicator`, so you can nest, stack, and feed it into anything that takes an indicator. ```rust use wickra::{BatchExt, Chain, Ema, Rsi}; // RSI(7) of EMA(14)-smoothed closes. let mut chain = Chain::new(Ema::new(14)?, Rsi::new(7)?); let out: Vec> = chain.batch(&prices); ``` See [Indicator Chaining](Indicator-Chaining.md) for the chained-warmup rule and three-stage examples. ## See also - [Indicators Overview](Indicators-Overview.md) — pick the right indicator for the question you are asking. - [Streaming vs Batch](Streaming-vs-Batch.md) — why these recipes work bit-identically in both modes. - [Data Layer](Data-Layer.md) — `Resampler` and the bundled BTCUSDT datasets for live multi-timeframe work.