> ## Documentation Index
> Fetch the complete documentation index at: https://uncoded.ch/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Recipe — RSI Mean-Reversion on BTCUSDT 15m

> The textbook starter strategy. RSI(14) on 15-minute candles, buy when oversold and price is below trend filter. Reliable in chop, classic mean-reversion logic.

<Info>
  **RSI mean-reversion is the textbook starter recipe.** Buy when RSI is oversold and price is below a trend filter. Sell signals delegated to your existing mode (typically BasicMode). Reliable in chop and ranging markets, with a trend filter to avoid catching falling knives.
</Info>

## Goal

Capture short-term mean-reversion bounces in `BTCUSDT` on a `15-minute` timeframe, gated by a longer-period trend filter to avoid buying into sustained downtrends.

## When to pick this recipe

<CardGroup cols={2}>
  <Card title="Sideways or ranging markets" icon="wave-square">
    Mean-reversion thrives when price oscillates within a range. RSI captures the oscillation; the bounces are tradable.
  </Card>

  <Card title="You're running BasicMode and want gating" icon="filter">
    Run BasicMode continuously with `canBuy: false` by default; let this recipe flip `canBuy: true` only when conditions hold. Combines BasicMode's clean execution with custom entry timing.
  </Card>

  <Card title="You want a tested starter" icon="check-double">
    RSI mean-reversion is the most-documented strategy in technical analysis. Many operators have validated patterns that work.
  </Card>

  <Card title="Capital `$5,000+` paired with a mode" icon="circle-dollar">
    The recipe controls when the underlying mode buys. Capital sizing is determined by the mode, not the recipe.
  </Card>
</CardGroup>

## When NOT to pick this recipe

<Warning>
  * ❌ **Sustained sharp downtrends** — RSI gets stuck below `30` for extended periods; the recipe fires repeatedly into a falling market. The trend filter helps but doesn't eliminate this.
  * ❌ **Vertical melt-up rallies** — RSI rarely reaches oversold during strong uptrends; the recipe rarely fires.
  * ❌ **First-week operators** — let BasicMode run alone for at least a month before adding gating logic.
  * ❌ **Pairs with extreme volatility** — RSI thresholds calibrated for `BTCUSDT` may not transfer to high-volatility altcoins.
</Warning>

## Prerequisites

<Steps>
  <Step title="BasicMode (or other mode) running on BTCUSDT">
    The recipe controls when the mode is allowed to buy; it doesn't replace the mode. You need the mode running first.
  </Step>

  <Step title="SignalEditor and SignalsBot running">
    The recipe is a SignalEditor strategy that posts webhooks to the SignalsBot. Both must be running.
  </Step>

  <Step title="Capital allocated to the mode">
    `$15,000–$25,000` for BasicMode, `$3,000–$5,000` for LowMoney, etc.
  </Step>

  <Step title="Set the mode's canBuy default to false">
    Via the Dashboard's Modes panel. The recipe will flip this on/off based on conditions.
  </Step>
</Steps>

## Setup steps

<Steps>
  <Step title="Open the SignalEditor and create a new strategy">
    Click "New Strategy." Name it `rsi-mean-reversion-btcusdt-15m`.
  </Step>

  <Step title="Add a Price node">
    Drop a Price node on the canvas. Set:

    * Symbol: `BTCUSDT`
    * Timeframe: `15m`
  </Step>

  <Step title="Add an RSI(14) indicator">
    Drop an Indicator node. Choose RSI from the catalog. Set length to `14`.

    Connect the Price node to the RSI input.
  </Step>

  <Step title="Add an EMA(50) trend filter">
    Drop another Indicator node. Choose EMA from the catalog. Set length to `50`.

    Connect the Price node to the EMA input.
  </Step>

  <Step title="Add the entry condition">
    Drop a Condition node. Configure:

    * Sub-condition A: RSI `<` `30` (oversold).
    * Sub-condition B: Price `<` EMA(50) (below trend).
    * Logic: AND.
  </Step>

  <Step title="Attach a trigger">
    Drop a Trigger node. Set mode to **`once_per_bar_close`** — fires only on closed candles, prevents intra-bar noise.

    Connect the Condition node to the Trigger input.
  </Step>

  <Step title="Configure the webhook target">
    On the Trigger node, set:

    * Webhook URL: your SignalsBot's `/webhook` endpoint
    * Message template (JSON):
      ```text theme={null}
      {
        "secret": "<your-shared-secret>",
        "pair": "BTCUSDT",
        "mode": 4,
        "canBuy": true
      }
      ```

    This webhook flips the mode's `canBuy` to `true` when the condition fires.
  </Step>

  <Step title="Add an exit-flip strategy (mirror)">
    Create a second strategy: `rsi-mean-reversion-btcusdt-15m-exit`. Same Price + RSI + EMA, but condition is RSI `>` `70` OR price `>` EMA(50). Trigger writes `canBuy: false`.

    This pair of strategies (entry-flip-on, exit-flip-off) brackets the buying windows.
  </Step>

  <Step title="Preview both strategies">
    Hit Preview on each. Confirm:

    * Entry strategy fires occasionally (a few times per week typical on BTCUSDT 15m).
    * Exit strategy mirrors — fires when RSI rebounds above `70` or price rises above EMA.
    * Firing rate is sane (not 100x per hour, not zero).
  </Step>

  <Step title="Backtest the combined behavior">
    Run a Backtester job: BasicMode on BTCUSDT with 30 days of recent data, gated by `canBuy` flips at the times the recipe would have fired.

    The Backtester will show the equity curve under this combined regime. Compare against BasicMode-alone for the same window.
  </Step>

  <Step title="Forward-test on small capital">
    Allocate `$1,500` (a sub-account if you can) to BasicMode + this recipe pair. Run for 2 weeks. Watch the Dashboard daily.

    If forward-test behavior matches backtest, scale up. If it diverges, investigate.
  </Step>

  <Step title="Promote to full capital if validated">
    Move to `$15,000–$25,000` allocation for BasicMode, with the recipe pair gating buying.
  </Step>
</Steps>

## Expected behavior

<AccordionGroup>
  <Accordion title="Firing frequency" icon="clock">
    On `BTCUSDT 15m`, expect the entry condition to fire roughly **`2–6` times per week** in normal market regimes. More in choppy/declining markets, less in strong uptrends.
  </Accordion>

  <Accordion title="Hold duration" icon="hourglass">
    BasicMode's typical hold time (hours to days) applies once `canBuy` is flipped on. The recipe doesn't change BasicMode's exits — those happen via the sell ladder.
  </Accordion>

  <Accordion title="Net-of-fees performance vs BasicMode-alone" icon="chart-line">
    The recipe trades **fewer** round-trips than BasicMode-alone (because some buying windows are gated off). Per-trade selectivity is higher (better-timed entries).

    Net effect varies by regime. In sideways markets, gating helps slightly. In strong-trend markets, gating can underperform BasicMode-alone (you missed buying opportunities during sustained moves).

    Backtest on multiple windows to get a fair picture.
  </Accordion>
</AccordionGroup>

## Common mistakes

<AccordionGroup>
  <Accordion title="❌ Trigger mode set to `once_per_minute`" icon="ban">
    Causes the recipe to fire every minute the condition holds. RSI can stay below `30` for hours — that's `60+` flips per hour. Floods the SignalsBot.

    **Fix**: use `once_per_bar_close`. Fires once per closed `15-minute` candle.
  </Accordion>

  <Accordion title="❌ Forgetting the exit-flip strategy" icon="ban">
    Without the mirror strategy that flips `canBuy: false` when conditions clear, the entry strategy stays "buying allowed forever" once it fires. Defeats the purpose of gating.

    **Fix**: build both strategies as a pair.
  </Accordion>

  <Accordion title="❌ Tightening the RSI threshold to 20" icon="ban">
    Tighter threshold = fewer signals = thinner sample size. Sounds good but in practice the recipe almost never fires.

    **Fix**: stick with `< 30` for entry, `> 70` for exit. The classic thresholds work.
  </Accordion>

  <Accordion title="❌ Skipping the trend filter (only RSI condition)" icon="ban">
    Without the EMA(50) trend filter, the recipe fires on every RSI dip — including dips during sustained downtrends. You catch falling knives.

    **Fix**: keep the AND with EMA(50) filter.
  </Accordion>

  <Accordion title="❌ Not forward-testing before scaling" icon="ban">
    Backtest is necessary but not sufficient. Markets change. Forward-test on small capital for 2 weeks before committing full size.
  </Accordion>
</AccordionGroup>

## What's next

<CardGroup cols={2}>
  <Card title="EMA Cross Trend" icon="arrow-trend-up" href="/strategies/recipes/ema-cross-trend">
    Trend-following alternative recipe.
  </Card>

  <Card title="Multi-Timeframe" icon="layer-group" href="/strategies/recipes/multi-timeframe">
    More sophisticated composition pattern.
  </Card>

  <Card title="SignalEditor" icon="wand-magic-sparkles" href="/modules/signaleditor">
    The module where you build this recipe.
  </Card>

  <Card title="Backtester" icon="flask" href="/modules/backtester">
    Validate the combined behavior on historical data.
  </Card>
</CardGroup>
