> ## 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.

# SignalEditor — Author and Run Custom Strategies

> Compose strategies visually on a canvas, preview them on historical data, and run them live — all without writing a line of code. The same engine evaluates your preview and your live run.

<Info>
  **The SignalEditor lets you build trading strategies visually — and then runs them for you.** You drag indicators, conditions, and triggers onto a canvas, connect them up, preview against history, and hit "Start." From that point, the SignalEditor evaluates your strategy against live market data on a schedule and emits signals when your conditions fire.
</Info>

## What the SignalEditor does for you

The SignalEditor is **two tools in one container** — and that's the entire point.

It's both:

* A **visual strategy authoring environment** — a node-graph canvas where you compose strategies by clicking and connecting blocks.
* A **live strategy evaluator** — once you "Start" a strategy, the same engine that powered your preview now runs against live data on a schedule, posting webhook signals to the SignalsBot when triggers fire.

Same engine, same evaluation logic, same indicator catalog. **What you previewed on history is what runs live.** No translation, no impedance mismatch, no "the live version behaves differently than the preview" surprises.

This single property — preview-equals-live — is the SignalEditor's most important feature. Every other strategy-authoring tool we've seen in the space has *some* gap between "what the backtester showed" and "what the live system did." The SignalEditor closes that gap by simply running the same engine for both.

<CardGroup cols={2}>
  <Card title="Visual strategy authoring" icon="diagram-project">
    Drag indicators, conditions, and triggers onto a canvas. Connect them with lines. See your logic as a graph instead of a script.
  </Card>

  <Card title="Live preview against history" icon="chart-line">
    Run any in-progress strategy against the last hours, days, or weeks of market data. See exactly when it would have fired and at what prices.
  </Card>

  <Card title="Same engine for preview and live" icon="equals">
    The preview is not a simulation — it's the actual evaluator running on historical klines. Confidence in preview means confidence in live.
  </Card>

  <Card title="Per-strategy scheduler" icon="clock-rotate-left">
    Each started strategy runs as its own scheduled job. Start, stop, and inspect each independently from the dashboard.
  </Card>

  <Card title="Per-trigger webhook routing" icon="paper-plane">
    Each trigger node in your graph can post to a different webhook URL with its own message template — fan out signals across multiple destinations if you need to.
  </Card>

  <Card title="No code required" icon="ban">
    Indicators, conditions, and triggers are pre-built blocks. You wire them. You never write Python, JavaScript, or any other language.
  </Card>

  <Card title="Strategies are JSON files" icon="file-code">
    Each strategy is a portable, version-controllable JSON file. Share with another operator by sending the file. Roll back to a previous version by restoring an old file.
  </Card>

  <Card title="Re-anchorable to any symbol" icon="rotate">
    A strategy authored against `BTCUSDT` can be re-pointed at `ETHUSDT`, `SOLUSDT`, or any other symbol by editing one field — no rewrite needed.
  </Card>
</CardGroup>

## The full block catalog

The SignalEditor's catalog is broad because real-world strategies need real-world building blocks. Here's the complete map.

<AccordionGroup>
  <Accordion title="136 indicators across 9 categories" icon="chart-line">
    The indicator catalog covers every major technical-analysis family.

    **Moving averages** — SMA, EMA, WMA, DEMA, TEMA, HMA, KAMA, T3, ZLEMA, McGinley Dynamic, ALMA, FRAMA, and others. The bread-and-butter of trend identification and smoothing.

    **Momentum** — RSI, Stochastic, Stochastic RSI, CCI, Williams %R, ROC, Momentum, TSI, Awesome Oscillator, Chande Momentum Oscillator, KST, RVI. For mean-reversion, overbought/oversold detection, and divergence patterns.

    **Trend** — MACD (with all signal-line variants), ADX (with directional indicators), Parabolic SAR, Aroon, Vortex, DPO, Mass Index, Ichimoku Cloud components, TRIX. For confirming trend strength and direction.

    **Volatility** — Bollinger Bands (price, width, percent-B), ATR, Keltner Channels, Donchian Channels, Ulcer Index, Standard Deviation, Historical Volatility. For sizing positions, identifying squeeze setups, and detecting regime changes.

    **Volume** — OBV, MFI, CMF, A/D Line, Volume Profile, EOM, Force Index, VWAP, NVI, PVI, Klinger Oscillator. For confirming whether a price move is supported by participation.

    **Pattern** — The CDL family of candlestick patterns: engulfing (bullish/bearish), doji, hammer, hanging man, harami (bullish/bearish), shooting star, morning/evening star, three white soldiers / three black crows, dark cloud cover, piercing line, abandoned baby, and more.

    **Statistics** — z-score, Pearson correlation, linear regression slope, beta, R-squared, percentile rank, autocorrelation, kurtosis, skewness. For statistical-arbitrage style strategies and rigorous mean-reversion thresholds.

    **Cycle** — Hilbert Transform variants: Sine Wave, Trend vs Cycle Mode, Dominant Cycle Period, Dominant Cycle Phase, Trendline. For operators who want to think in cycle terms rather than time-window terms.

    **Math transforms** — Accumulation, distribution, log, exp, square root, percent change, absolute value, scaling functions. For composing custom indicator-of-indicators.

    Every indicator runs on the timeframe of the price node feeding it. The same indicator on a `1m` price node and on a `1d` price node produces independent values.
  </Accordion>

  <Accordion title="41 condition types across 9 categories" icon="filter">
    Conditions are the predicates that turn indicator outputs into "fire / don't fire" decisions. The catalog is wide enough that almost any tradable thesis can be expressed without composing custom logic.

    **Comparison** — `greater-than`, `less-than`, `equal-to`, `greater-than-or-equal`, `less-than-or-equal`, `crossover`, `crossunder`. The foundation. Use `crossover` and `crossunder` for the classic signal-on-cross patterns; use the inequalities for thresholds and breakouts.

    **Range** — `within-range`, `outside-range`, `between` (two indicator values). Useful for "RSI between 30 and 70" or "price within 2 ATR of EMA."

    **Trend** — `rising` (over N bars), `falling` (over N bars), `flat` (over N bars). For confirming directional context before acting on faster signals.

    **Pattern** — `higher-highs`, `lower-lows`, `double-bottom`, `breakout-above-resistance`, `breakdown-below-support`. Pre-built versions of the most-used chart patterns.

    **Logic** — `AND`, `OR`, `NOT`, `XOR`. Compose multiple conditions into one. The most common pattern: a "trend filter" condition (long-period MA rising) AND an "entry trigger" condition (RSI oversold + price below short-period MA).

    **Time** — `within-window` (e.g., 09:00–17:00), `after-time`, `before-time`. Disable trading during illiquid hours, news windows, or weekends. Critical for venues with thin off-hours liquidity.

    **Volume** — `above-average`, `surge` (N-multiple of average), `dry-up` (below threshold). For volume-confirmation patterns.

    **Volatility** — `within-band`, `outside-band`, `contracting`, `expanding`. Bollinger-squeeze setups, volatility-regime detection.

    **Statistical** — `z-score-above`, `z-score-below`, `percentile-threshold`. Rigorous mean-reversion thresholds tied to actual recent distribution.
  </Accordion>

  <Accordion title="4 trigger modes" icon="bolt">
    Triggers are the gating logic — they decide *when* a fired condition produces a signal. Without trigger gating, a "RSI \< 30" condition would fire on every tick the condition holds, producing dozens of signals per minute.

    * **`once`** — fire once for the lifetime of the strategy run. Use for "the first time the condition is true after I start the strategy, signal once, then never again." Rare; useful for one-shot setups.
    * **`once_per_bar`** — fire at most once per candle. Useful when you want to reset firing eligibility on each new bar, but want intra-bar firing if the condition flips quickly.
    * **`once_per_bar_close`** — fire only on bar-close. The most-used mode for clean, predictable behaviour. Most operators default here. No intra-bar noise; one decision per closed candle.
    * **`once_per_minute`** — fire at most once per minute, regardless of how many bars passed. Useful when you want very-frequent firing rate-limited (e.g., a 1-minute timeframe strategy where you want at most one signal per real minute).

    These prevent the most common strategy bug: an oscillator that crosses a threshold and stays there, firing every tick.
  </Accordion>

  <Accordion title="15 timeframes" icon="clock">
    Every strategy is anchored to a timeframe at the price node:

    `1m`, `3m`, `5m`, `15m`, `30m`, `1h`, `2h`, `4h`, `6h`, `8h`, `12h`, `1d`, `3d`, `1w`, `1M`.

    A single strategy is one timeframe — to combine signals from multiple timeframes (e.g., daily trend filter + 15-minute entry), you compose them as separate strategies that talk to the same downstream consumer (or use multi-strategy patterns described below).
  </Accordion>
</AccordionGroup>

## Common strategy patterns

The most-asked question from new SignalEditor users: "what should I build first?" Here are the patterns operators have validated and turned into reliable production strategies.

<AccordionGroup>
  <Accordion title="RSI mean-reversion (the textbook starter)" icon="circle-down">
    The classic. RSI(14) on a `15m` price node. Condition: RSI `< 30`. Trigger: `once_per_bar_close`. Sends a "buy signal" webhook.

    Optional refinement: AND price `< EMA(50)` (only buy when price is also below its medium-term mean — avoids buying RSI dips during a fast falling knife).

    Strengths: intuitive, well-tested, works in choppy and ranging markets.

    Weaknesses: can fire repeatedly during sustained downtrends. The trend-filter AND condition mitigates this.

    **Capital recommendation**: pair with a mode that can absorb 3–5 consecutive entry signals (BasicMode's 7-split buy ladder works well).
  </Accordion>

  <Accordion title="EMA crossover (the trend-following classic)" icon="arrow-trend-up">
    EMA(20) and EMA(50) on a `1h` price node. Condition: `crossover` of EMA(20) over EMA(50). Trigger: `once_per_bar_close`. Sends a "buy signal" webhook on the cross-up; optionally sends a "sell signal" webhook on the cross-down.

    Strengths: well-known, easy to reason about, works in trending markets.

    Weaknesses: late entries (the cross happens after the move has started), whipsaws in chop.

    **Refinement**: add an ADX `> 25` condition (only act on the cross when the trend is strong enough). This filters out chop-driven false crosses.
  </Accordion>

  <Accordion title="Bollinger squeeze breakout" icon="compress">
    Bollinger Bands width on a `1h` price node. Condition: width is in the bottom 20th percentile of the last 100 bars (a `percentile-threshold` condition). Combined AND with a price `crossover` of the upper band.

    Trigger: `once_per_bar_close`.

    Strengths: identifies low-volatility setups before they break out. When the breakout happens, you're already positioned.

    Weaknesses: false breakouts. The condition needs to be strict (high enough percentile) to filter noise.

    **Mode pairing**: works well with FullBullMarket if the breakout is to the upside; less so with a fixed sell-ladder mode.
  </Accordion>

  <Accordion title="Multi-timeframe trend + entry" icon="layer-group">
    A two-strategy pattern. **Strategy A**: daily-timeframe trend filter (EMA 50 rising over 5 days). When the condition holds, write a "trend filter ON" flag to the database via webhook.

    **Strategy B**: `15m` entry trigger (RSI oversold). Conditioned on the trend-filter flag being ON. Only fires when both timeframes agree.

    Strengths: faster entry timing without giving up trend context.

    Weaknesses: more moving parts. Requires custom webhook handling for the flag pattern.

    **Operator effort**: this is a "level 2" SignalEditor pattern. Master the single-strategy patterns first.
  </Accordion>

  <Accordion title="Volume-confirmed breakout" icon="chart-column">
    Price `breakout-above-resistance` (where resistance is, e.g., the 20-bar Donchian high) AND volume `surge` (current volume is 2x the 20-bar average).

    Trigger: `once_per_bar_close`.

    Strengths: filters out unconfirmed breakouts (price moves up but with no volume — usually fakeouts).

    Weaknesses: misses fast breakouts that happen on average volume.
  </Accordion>

  <Accordion title="Time-of-day filter" icon="clock-rotate-left">
    Almost any of the above strategies, plus a `within-window` time condition.

    Why: many crypto markets have predictable liquidity patterns. London open, US open, US close — these are higher-liquidity moments. Asian overnight (for some symbols) is thinner, more prone to wicks.

    Operators who add a time filter typically gate trading to high-liquidity windows. The filter prevents over-aggressive bot behaviour during low-liquidity hours when slippage is higher.
  </Accordion>

  <Accordion title="The 'do not trade' filter" icon="ban">
    A surprisingly powerful pattern: a strategy whose only job is to **disable buying** when conditions are bad.

    Example: ADX `< 15` (low trend strength) AND ATR is rising (volatility expanding). When both hold, write `canBuy: false` to the affected modes via webhook. When conditions return to normal, write `canBuy: true`.

    This is the "operator rule, automated" pattern — most experienced operators have a rule like "don't buy during major news," "don't buy when VIX is high," etc. The SignalEditor lets you encode that rule and let it run automatically.
  </Accordion>
</AccordionGroup>

## How a strategy flows through the SignalEditor

<Steps>
  <Step title="Author on the canvas">
    Open the SignalEditor in your browser. Drop a **Price node** for your symbol and timeframe. Add **Indicator nodes** for the metrics you care about (e.g., RSI(14) and EMA(50)). Add **Condition nodes** to express your logic (e.g., `RSI < 30 AND price < EMA(50)`). Add a **Trigger node** with the firing mode you want.
  </Step>

  <Step title="Preview against history">
    Hit "Preview." The SignalEditor fetches recent historical klines for your symbol and runs the entire graph against them. The preview pane shows you exactly when your strategy would have fired, at what prices, and how often.

    This is your sanity check: if your strategy fires 100 times in an hour, the trigger gating is too loose. If it never fires, your conditions are too tight or contradictory.
  </Step>

  <Step title="Iterate based on preview">
    Most strategies need 3–10 preview iterations before they're production-ready. Common iteration patterns:

    * Tighten conditions (RSI threshold from `30` to `25`) when firing rate is too high.
    * Loosen conditions when firing rate is zero.
    * Add a trend filter when chop is producing false signals.
    * Add a time-of-day window when low-liquidity hours are causing bad fills.

    The preview is fast (seconds for a few weeks of `15m` candles), so iterate freely.
  </Step>

  <Step title="Configure the webhook target">
    On each Trigger node, you specify the **webhook URL** (default: your local SignalsBot) and a **message template** with placeholders for `{{action}}`, `{{price}}`, `{{symbol}}`, `{{timestamp}}`. The default template produces the standard JSON shape the SignalsBot expects.
  </Step>

  <Step title="Save and start">
    Save the strategy. Click "Start." The SignalEditor's scheduler registers a job that re-evaluates your graph at a regular cadence (anchored to your price-node timeframe). Each evaluation looks at the latest market data, runs the graph, and — if any trigger fires — posts a webhook to the configured target.
  </Step>

  <Step title="Inspect live behavior">
    The Dashboard's **SignalEditor panel** shows you which strategies are running, when each was last evaluated, and when each last fired a signal. Open the panel any time to confirm "yes, my strategy is alive and is checking market data on schedule."
  </Step>

  <Step title="Forward-test on small capital">
    Before scaling a strategy up, run it against a small subset of capital for at least a week. Compare live behavior to preview behavior — they should agree. If they don't, something's off (often the strategy is reacting to market data the preview didn't have, e.g., a particularly volatile recent week).
  </Step>

  <Step title="Stop or edit">
    Stop a strategy at any time. Edit it (a stopped strategy can be reshaped on the canvas) and start it again. Stopping mid-run is safe — open positions on your TradingBot are unaffected; the SignalEditor only emits future signals.
  </Step>
</Steps>

## What the SignalEditor does NOT do

<Warning>
  **The SignalEditor authors and emits signals. It does not place trades.**

  * ❌ The SignalEditor never sends an order to your exchange.
  * ❌ The SignalEditor does not have your exchange API keys.
  * ❌ The SignalEditor does not directly modify your TradingBot's active configuration.
  * ❌ The SignalEditor does not subscribe to your exchange's user-data WebSocket — it only reads public market data.
  * ❌ The SignalEditor does not own positions, balances, or ledger entries.

  Instead, it emits webhook signals to the SignalsBot. The SignalsBot validates those signals and writes the resulting configuration changes (e.g., "enable buying on BTCUSDT") to your local database. The TradingBot then reads the updated configuration and acts on it.

  This separation is intentional — it means a bug in your strategy graph cannot directly cause an unintended trade. There are validated checkpoints between the strategy author's intent and a real order.
</Warning>

## What "live evaluation" actually does

When you start a strategy, the SignalEditor's scheduler creates a periodic job for it. On each scheduled tick:

1. Load the strategy graph from disk (so any saved edits propagate immediately).
2. Fetch the latest market data for the price node's symbol and timeframe.
3. Evaluate every indicator node against the fresh data.
4. Evaluate every condition node using the indicator outputs.
5. For every trigger node, decide whether the upstream conditions justify firing under the trigger's mode.
6. For each fired trigger, POST a webhook to the configured URL with the templated payload.
7. Update the strategy's `last_check` timestamp; if any trigger fired, also `last_signal`.

<Tip>
  **Only the last 5 signals from any single evaluation are sent**. This is a deliberate cap — if you start a strategy and the historical data has a long backlog of would-have-fired moments, the SignalEditor sends at most 5 of the most recent ones, not 500. This protects your downstream from being flooded by historical replay.
</Tip>

## Strategy lifecycle management

A strategy has a lifecycle that's worth being explicit about — most operator confusion comes from blurring stages.

<AccordionGroup>
  <Accordion title="Draft — work in progress, never started" icon="pen-ruler">
    A draft strategy is one you've authored on the canvas but never hit "Start." It exists as a JSON file but is not actively evaluating anything live.

    Drafts are fine to leave in the editor for as long as you want. They consume zero compute. Many operators have 5–10 drafts at any given time — half-baked ideas to refine later.
  </Accordion>

  <Accordion title="Previewed — validated against history" icon="chart-line">
    A previewed strategy is one whose preview has been run and the operator has reviewed the firing pattern. Preview is non-destructive — it does not affect anything live.

    Most strategies live in this state for several preview cycles before promoting to live. Iterate freely.
  </Accordion>

  <Accordion title="Started — running live, may emit signals" icon="play">
    A started strategy has a scheduled job. On every cycle, it evaluates the latest market data and may emit signals. Started strategies are visible in the Dashboard with their `last_check` and `last_signal` timestamps.

    Starting is reversible — you can stop at any time. Already-emitted signals don't un-emit, but no further signals will fire after stop.
  </Accordion>

  <Accordion title="Stopped — paused, can be restarted" icon="pause">
    A stopped strategy is no longer evaluating. The graph is preserved, the JSON file is unchanged. Restart re-creates the scheduled job from where you left off.

    Stop is the right move when you're going to edit substantially. Edit a stopped strategy, preview the changes, then restart.
  </Accordion>

  <Accordion title="Archived — no longer in use, file kept" icon="box-archive">
    Some operators move retired strategies to an `archive/` subdirectory of the strategies volume. They're not visible in the canvas listing but the JSON files are kept for reference.

    Useful when a strategy worked for a regime that's now passed — you might want it back later, but you don't want it cluttering your active strategy list.
  </Accordion>

  <Accordion title="Deleted — gone forever" icon="trash">
    Permanent. Delete only when you're sure. Most operators archive instead of delete.
  </Accordion>
</AccordionGroup>

## Operational footprint

<CardGroup cols={2}>
  <Card title="Resource cost" icon="microchip">
    `300–500 MB` RAM for the backend and scheduler. Frontend is static assets — sub-percent CPU at idle. Each running strategy adds modest CPU during evaluation ticks.
  </Card>

  <Card title="Network calls" icon="globe">
    Outbound to your exchange's public market-data API (read-only) and outbound to your webhook targets (typically the local SignalsBot). Inbound on the operator's private network for the browser canvas.
  </Card>

  <Card title="Data storage" icon="database">
    Strategy definitions are JSON files on the SignalEditor's disk volume. Back up this volume with your other operator data. There is no separate strategy database.
  </Card>

  <Card title="Failure mode" icon="triangle-exclamation">
    If the SignalEditor crashes, **running strategies stop emitting signals** until restart. Your TradingBot continues honoring its existing configuration — already-open positions are unaffected. New signal-driven changes pause.
  </Card>

  <Card title="Concurrency" icon="layer-group">
    Multiple strategies can run in parallel — each as its own scheduled job. The scheduler's overhead is small; operators with `5–10` running strategies are well within normal envelope.
  </Card>

  <Card title="Frontend exposure" icon="lock">
    The canvas is for the operator's private network. The default API has no authentication; do not expose to the public internet. Behind your reverse proxy with proper auth, the canvas can be remote-accessible.
  </Card>
</CardGroup>

## Common questions

<AccordionGroup>
  <Accordion title="Do I need to run the SignalEditor to use unCoded?" icon="circle-question">
    **No.** The SignalEditor is optional. If you only want to run unCoded's pre-built modes (BasicMode, FullBullMarket, LowMoney, etc.), you don't need the SignalEditor at all — those modes are mode-config files in the TradingBot itself.

    The SignalEditor is for operators who want **custom strategies** beyond the pre-built modes. Most operators start without it, then turn it on once they have an itch the pre-builts don't scratch.
  </Accordion>

  <Accordion title="Can I share or export a strategy?" icon="circle-question">
    Strategies are JSON files. To share with a fellow operator, send them the file. They drop it into their `signal-editor/strategies/` directory, restart the SignalEditor, and the strategy appears in their canvas.

    Strategies are **not exchange-coupled** — a strategy authored against `BTCUSDT` on Binance can be re-pointed at `BTC-USDT` on OKX by editing the price node's symbol field.
  </Accordion>

  <Accordion title="What happens if my strategy fires too often?" icon="circle-question">
    The most common cause is a trigger mode that's too permissive. Switch the trigger from `once_per_minute` to `once_per_bar_close`, and your strategy will fire only on closed candles — usually a 5-100x reduction in firing rate.

    The SignalsBot also has rate limits — if it's flooded with signals from a misconfigured strategy, it will start rejecting them (and the Dashboard will show the rejections). This is a safety net, not a substitute for tuning your trigger correctly.
  </Accordion>

  <Accordion title="Can I evaluate the same strategy on multiple symbols?" icon="circle-question">
    The SignalEditor model is **one strategy per symbol**. To evaluate the same logic across `BTCUSDT`, `ETHUSDT`, `SOLUSDT`, you create three separate strategies — typically by duplicating the first and changing only the price node's symbol.

    This is intentional: it makes per-symbol behavior individually inspectable. If `BTCUSDT` is firing oddly but `ETHUSDT` is fine, you can disable just the misbehaving one.

    Some operators write small scripts to bulk-duplicate a strategy across many symbols. This is a normal pattern — a "template strategy" duplicated 10 times for 10 symbols.
  </Accordion>

  <Accordion title="Can I write my own indicator?" icon="circle-question">
    **Not from the canvas.** Indicators are pre-built and live in the engine. If you have a strong need for a custom indicator (a proprietary smoothing function, a domain-specific oscillator), contact support — adding new indicators to the engine is a normal feature request and several have been added on operator request.

    For most operators, the existing 136 indicators across 9 categories are sufficient — almost every classic strategy can be expressed without custom code.
  </Accordion>

  <Accordion title="Can the SignalEditor make me trade automatically?" icon="circle-question">
    The SignalEditor emits **signals**. The SignalsBot translates signals into **configuration changes** in your local database (e.g., `enabledForBuy = true`). The TradingBot then **acts on configuration**.

    So yes — a fully automated pipeline is possible: strategy fires → webhook → configuration update → TradingBot trades. But the chain has validated checkpoints, and you remain the operator who started the strategy in the first place.
  </Accordion>

  <Accordion title="What about backtesting?" icon="circle-question">
    The preview pane is fast historical replay over recent windows (hours to weeks). For deeper, longer, or more rigorous backtesting — months or years of data, parameter sweeps, equity curves — use the **Backtester** module. The Backtester reads the same strategy JSON files, runs them against deeper historical data, and produces full performance reports.
  </Accordion>

  <Accordion title="What's the relationship between strategies and modes?" icon="circle-question">
    Modes are pre-built rule sets shipped with the TradingBot — they encode complete strategies (buy ladder + sell ladder + trailing stop + risk caps). They're tuned by the unCoded team.

    Strategies are operator-authored signal graphs that **influence** mode behaviour. A strategy might say "when this signal fires, enable buying on Mode 4 for `BTCUSDT`." It doesn't replace the mode — it controls when the mode is allowed to act.

    A common pattern: run BasicMode (Mode 4) on `BTCUSDT` continuously, with `canBuy: false` by default, and let a SignalEditor strategy flip `canBuy` to true only when its conditions hold. This way you get BasicMode's clean execution with custom entry timing.
  </Accordion>

  <Accordion title="How fast do strategies evaluate?" icon="circle-question">
    Evaluation cadence is anchored to the price node's timeframe. A `1m` strategy evaluates approximately every minute. A `1h` strategy approximately every hour. A `1d` strategy approximately every day.

    Inside each evaluation, the actual computation is fast — typically milliseconds per evaluation. The cadence, not the speed, is the dominant timing factor.
  </Accordion>

  <Accordion title="Can I have a strategy that uses indicators from multiple symbols?" icon="circle-question">
    The standard graph has one Price node feeding the indicators. Cross-symbol strategies (e.g., "buy BTC when ETH-USDT-volume surges") are not directly supported in a single graph.

    The pattern: build two strategies. Strategy A monitors ETH and posts a webhook when ETH-volume surges. Strategy B's downstream config update enables BTC buying when the flag is set.

    Multi-symbol strategies are a "level 3" pattern — get comfortable with single-symbol patterns first.
  </Accordion>

  <Accordion title="What if my strategy disagrees with itself across previews?" icon="circle-question">
    Two previews of the same strategy on the same data should produce identical results. If they don't, something's wrong — most often it's a network blip during one preview that fetched slightly different historical data.

    If the disagreement persists, contact support. Determinism is a feature; non-determinism is a bug.
  </Accordion>

  <Accordion title="Can I version-control my strategies?" icon="circle-question">
    Yes — strategies are JSON files. Many operators commit their strategies directory to a private Git repo. This gives you:

    * History of every change to every strategy.
    * The ability to roll back a strategy edit that performed worse than the prior version.
    * A backup that survives VPS loss.

    Add a `.gitignore` for any sensitive fields if your strategy configuration accidentally embeds credentials.
  </Accordion>
</AccordionGroup>

## Best practices

<Tip>
  * ✅ **Start with a known-good preview** — never start a strategy live until the preview shows behavior you understand.
  * ✅ **Use `once_per_bar_close` triggers by default** — only loosen to `once_per_minute` if you specifically want intra-bar firing.
  * ✅ **Keep strategies focused** — one strategy per symbol per timeframe. Compose, don't conflate.
  * ✅ **Review running strategies weekly** in the Dashboard — confirm `last_check` is recent and `last_signal` matches your expectations.
  * ✅ **Back up `signal-editor/strategies/`** along with your local database — losing a tuned strategy graph is a real loss.
  * ✅ **Don't expose the SignalEditor port to the public internet** — it has no authentication on its API by default, and the canvas is intended for your private network only.
  * ✅ **Forward-test on small capital before scaling** — even a strategy that previewed beautifully should be observed live for a week before getting full capital allocation.
  * ✅ **Version-control your strategies** in a private Git repo for history and disaster recovery.
  * ✅ **Iterate freely on the preview** — preview is fast and non-destructive. Use it.
  * ✅ **Add a trend-filter condition** to mean-reversion strategies — avoid buying dips in sustained downtrends.
  * ✅ **Consider time-of-day filters** for venues with predictable liquidity patterns.
  * ✅ **Stop a strategy before substantial edits** — edit the stopped graph, preview, then restart.
</Tip>

## What's next

<CardGroup cols={2}>
  <Card title="SignalsBot" icon="satellite-dish" href="/modules/signalsbot">
    The downstream consumer of every signal your strategies fire — and what turns signals into configuration.
  </Card>

  <Card title="Backtester" icon="flask" href="/modules/backtester">
    Run your strategies against deep historical data for serious validation.
  </Card>

  <Card title="TradingBot" icon="robot" href="/modules/tradingbot">
    The downstream actor that ultimately acts on the configuration your strategies produce.
  </Card>

  <Card title="Dashboard" icon="gauge" href="/modules/dashboard">
    Where you start, stop, and monitor running strategies.
  </Card>

  <Card title="Strategy Recipes" icon="book" href="/strategies/recipes">
    More worked-example strategies with full graph configurations.
  </Card>

  <Card title="Indicator Reference" icon="list" href="/strategies/indicators">
    The full 136-indicator catalog with usage notes.
  </Card>
</CardGroup>
