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

# TradingBot — The Execution Engine

> The only component that places real orders on your exchange. Disciplined, around-the-clock execution of the rules you authored — with full lifecycle management from buy entry to final close.

<Info>
  **The TradingBot is the only component with the authority to send a real order to your exchange.** Everything else in the unCoded suite generates intent — the TradingBot turns intent into actual buys and sells, then manages the resulting positions through to closure with the same discipline at 03:00 as at 14:00.
</Info>

## What the TradingBot does for you

The TradingBot is your **disciplined, never-tired execution layer**. It takes your active configuration — which symbols to trade, which mode they're assigned to, how much capital is available, what the kill-switch state is — and translates it into real orders on your exchange. It then watches every order through to fill, manages every position through to closure, and records every event for you to inspect.

You authored the rules (or picked a pre-built mode that encodes them). The TradingBot enforces them — every minute, every fill, every restart, every exchange outage.

<CardGroup cols={2}>
  <Card title="Places real orders" icon="bolt">
    Reads your active trade-pair and mode configuration from the local database, sizes orders correctly for the exchange's lot/tick rules, signs them with your API credentials, and submits them.
  </Card>

  <Card title="Manages positions through the full lifecycle" icon="circle-arrow-right">
    From entry to sell-ladder placement to trailing-stop arming to final closure. Every step recorded for you to review in the Dashboard's order ledger.
  </Card>

  <Card title="Watches every fill in real time" icon="eye">
    Subscribes to your exchange's user-data WebSocket. When a buy or sell fills — partially or fully — the TradingBot reacts within milliseconds.
  </Card>

  <Card title="Reconciles state continuously" icon="rotate">
    Periodically compares its internal view against the exchange's authoritative view. Catches missed events from a brief WebSocket disconnect, surfaces divergences before they cascade.
  </Card>

  <Card title="Respects exchange rate limits" icon="gauge">
    Reserves a small headroom below your venue's published ceiling (Binance: `50` orders per `10` seconds) so the bot never gets temporarily IP-banned mid-trade.
  </Card>

  <Card title="Records every decision" icon="clipboard-list">
    Every order, every fill, every rejection is logged with full context. You can answer "why did this happen?" for any trade, days or months later.
  </Card>

  <Card title="Survives restarts gracefully" icon="shield-halved">
    On reboot, reconciles its view against the exchange — discovers any fills that happened while offline, updates its records, and resumes within seconds.
  </Card>

  <Card title="Honours your kill switch" icon="power-off">
    Polls the kill-switch flag on every cycle. The instant you flip it from the Dashboard, no new buy orders are placed — already-open positions and their pre-placed sell ladders continue honouring on the exchange itself.
  </Card>
</CardGroup>

## Single-exchange per container — by design

<Warning>
  **One TradingBot container handles one exchange.** This is a deliberate design choice, not a limitation.

  Each container is configured for a specific venue (`EXCHANGE_ID=binance`, or `bybit`, or `okx`, etc.) and uses one set of API credentials. To run on multiple exchanges, you spin up multiple TradingBot containers — each independently managing its own venue, all reading from the same shared dashboard.

  Why this matters in practice:

  * **Fault isolation.** A problem on one exchange (a network blip, a venue-side outage, a rate-limit ban, a key revocation) cannot cascade into your other exchanges. Each TradingBot is its own blast radius.
  * **Independent restart.** You can restart just one TradingBot — for an upgrade, a config change, or a debugging session — without disturbing trades on your other venues.
  * **Clear key boundaries.** Each container holds exactly one set of API credentials. There is no "if this container is compromised, all my keys are compromised" risk.
  * **Simple operator mental model.** You always know which container is managing which exchange. There's no "is the Binance bot or the Bybit bot misbehaving right now?" debugging confusion.

  The trade-off — running 3 containers for 3 exchanges instead of one — is small. Each additional TradingBot adds about `100–200 MB` RAM and sub-percent CPU at idle.
</Warning>

## Supported exchanges

The TradingBot supports **17 hand-tuned, production-ready exchanges** out of the box. Each profile is individually tuned for the venue's specific signing scheme, symbol naming convention, lot/tick precision rules, error codes, and rate-limit envelope. An additional **64 exchange profiles** exist in validation status — they work but haven't completed the full hand-tuning pass.

<AccordionGroup>
  <Accordion title="Global majors (8)" icon="globe">
    * **Binance** — the most-tested venue; the canonical reference exchange. Most operators start here.
    * **Bybit** — strong global liquidity, EU-compliant variant available (Bybit EU under MiCA).
    * **OKX** — deep order book, broad symbol coverage. Note: OKX uses dash-separated symbols (`BTC-USDT` vs Binance's `BTCUSDT`).
    * **KuCoin** — diverse altcoin coverage; useful for symbols Binance doesn't list.
    * **MEXC** — wide altcoin coverage at the speculative end; lower liquidity than the top tier.
    * **Gate.io** — broad listing, good fee structure.
    * **HTX (Huobi)** — long-established Asian venue.
    * **BingX** — newer entrant, growing liquidity.
  </Accordion>

  <Accordion title="US-regulated (2)" icon="building-columns">
    * **Binance.US** — restricted symbol set vs global Binance, US-resident accounts only.
    * **Coinbase Advanced** — strong regulatory standing, fee structure favours larger volumes.
  </Accordion>

  <Accordion title="EU-regulated (2)" icon="circle-euro">
    * **Bybit EU** — MiCA-compliant variant for EU residents.
    * **Bitvavo** — Netherlands-based, EUR-quoted markets, strong EU compliance.
  </Accordion>

  <Accordion title="Long-established (4)" icon="landmark">
    * **Kraken** — one of the oldest crypto exchanges; strong reputation.
    * **Bitfinex** — long history, sophisticated API.
    * **Poloniex** — long-established US-origin venue.
    * **BitMart** — global venue with broad listings.
  </Accordion>

  <Accordion title="Specialty (1)" icon="star">
    * **Crypto.com Exchange** — paired with the Crypto.com app ecosystem; specific symbol set.
  </Accordion>
</AccordionGroup>

<Tip>
  **Most operators start on Binance** because it has the deepest liquidity, the broadest symbol coverage, the most documented behaviour, and the most permissive rate limits. Once comfortable, many operators add a second venue (often Bybit) for symbols Binance doesn't list, or for geographic-jurisdiction diversification.

  Adding an exchange is straightforward: deploy a second TradingBot container with the new venue's API credentials and `EXCHANGE_ID`. Same dashboard, same database, two independent execution streams.
</Tip>

## What the TradingBot actually does, end-to-end

A complete trade cycle inside the TradingBot looks like this:

<Steps>
  <Step title="Read configuration">
    On every cycle (typically every few seconds), the TradingBot polls your local database for the active trade-pair list, the mode assigned to each pair, and the kill-switch state. If the configuration hash changed since last poll, the bot re-reads the full configuration.
  </Step>

  <Step title="Evaluate buy conditions">
    For each active pair, the bot evaluates the mode's buy logic against current market data. The buy logic encodes which prices, percentages, and conditions trigger a buy — it is mode-specific (BasicMode is different from FullBullMarket is different from MinimalMoney).
  </Step>

  <Step title="Size the order correctly">
    Before submitting, the bot computes the correct order size in base-asset units, rounds to the exchange's lot precision, and verifies the resulting notional value clears the venue's minimum-notional floor. Orders below the floor are not submitted (they would be rejected).
  </Step>

  <Step title="Submit the buy order">
    The bot signs the order with your API credentials and POSTs it to the exchange. The exchange returns an order ID, which the bot persists locally with full request/response context. From this moment, the order is visible on the exchange itself — you could see it in the venue's UI.
  </Step>

  <Step title="Watch for fill via WebSocket">
    The bot's WebSocket connection delivers fill events as they happen. A "buy filled" event triggers the next phase of the lifecycle.
  </Step>

  <Step title="Place the sell ladder">
    Once a buy fills, the bot computes the sell-ladder rungs based on the mode's sell-percentage configuration. For Mode 4 (BasicMode), the rungs are at `+0.25%`, `+0.5%`, `+1%`, `+2%`, `+3%`, `+4%`, `+5%` above the entry price. The bot submits each rung as a limit sell order to the exchange.
  </Step>

  <Step title="Manage the position">
    As price moves and rungs fill, the bot tracks partial closes. If the mode includes a trailing stop, the bot arms it once a configured profit threshold is reached, and re-prices the trailing stop as new highs are made.
  </Step>

  <Step title="Close the position">
    When the final rung fills (or the trailing stop triggers, or you manually close), the position closes. The bot writes a complete round-trip record to the closed-trade ledger — entry/exit times, prices, fees, realized P\&L. This record is what drives your Telegram notification, the Dashboard's order panel, and the tax export.
  </Step>

  <Step title="Reconcile and continue">
    Periodically, the bot reconciles its view of open positions against the exchange's authoritative view (in case any events were missed). Discrepancies are surfaced in the Dashboard for operator review. The cycle continues for the next pair.
  </Step>
</Steps>

## What you need to give the TradingBot

The TradingBot needs three things to operate. Get these right at setup, and almost everything else takes care of itself.

<AccordionGroup>
  <Accordion title="Exchange API credentials with the right permissions" icon="key">
    Generate API keys at your exchange's API-management page. The required permissions:

    * ✅ **Read** — required, for market data and account balance queries.
    * ✅ **Spot trading** — required, for placing buy and sell orders.
    * ❌ **Withdrawals** — **NEVER ENABLE THIS.** unCoded never needs to withdraw your funds. Leaving withdrawal permission disabled means even a worst-case key compromise cannot drain your account.
    * ❌ **Futures / margin** — disabled unless you've explicitly chosen a mode that requires them (most modes are spot-only).
    * ❌ **Internal transfers** — disabled. Sub-account transfers require explicit operator action via the venue's UI.

    On Binance, additionally:

    * **IP allow-list** the API key to your VPS's static IP. This means even a leaked key cannot be used from any other machine.
    * Verify the key shows correct permissions: "Enable Reading" + "Enable Spot & Margin Trading" — nothing else.

    On Coinbase Advanced, the API key needs the `view` and `trade` scopes — never `transfer`.

    On OKX, set the IP allow-list and verify the API mode is "Trade" (not "Read" alone).
  </Accordion>

  <Accordion title="Exchange ID and supporting environment" icon="gear">
    Configure the TradingBot's environment with:

    * **`EXCHANGE_ID`** — one of `binance`, `bybit`, `okx`, `kraken`, `coinbase`, etc. Determines which venue profile is used.
    * **`<EXCHANGE>_API_KEY`** and **`<EXCHANGE>_SECRET_KEY`** — your credentials for that venue.
    * **`recvWindow=60000`** (Binance-family) — the milliseconds the exchange will tolerate between order timestamp and exchange-side receive. `60000` is the operator-recommended setting; don't reduce it without specific reason.
    * **Database connection** — environment variables pointing at your local database.

    The `.env` file template provided in the One-Click bundle has every variable pre-listed. You fill in the values; the TradingBot reads them on startup.
  </Accordion>

  <Accordion title="Active configuration in the database" icon="database">
    Configuration that changes through the operator's life — which pairs to trade, which mode each pair is on, what the kill-switch is set to — lives in your local database, not in environment variables. This is intentional: it lets you change settings via the Dashboard without restarting the bot.

    The Dashboard's setup flow walks you through your initial configuration: pick your first pair, pick its mode, set capital allocation. From that point, the TradingBot picks up the configuration and starts evaluating.
  </Accordion>
</AccordionGroup>

## How the TradingBot handles edge cases

A trading bot's worth is measured by how well it handles bad days, not good ones. Here's what happens in the cases that matter.

<AccordionGroup>
  <Accordion title="Brief network outage (seconds to a few minutes)" icon="wifi">
    The TradingBot's WebSocket reconnects automatically. During the outage, fills that happened are recorded by the exchange normally. On reconnect, the bot's reconciliation pass detects any fills that landed during the gap and updates its records.

    **Open sell-ladder rungs continue honouring** — they're orders living on the exchange itself, not on your VPS. A 30-second outage cannot make you miss a sell.

    The trailing stop is the one piece that's locally re-priced. During an outage where new highs are made, the trailing stop reference does not advance — on reconnect, it's at its last server-side level, not at the highest price during the gap. For most operators this is acceptable; for very volatile instruments and very tight trailing stops, this can mean a slightly lower exit price.
  </Accordion>

  <Accordion title="Exchange outage (minutes to hours)" icon="cloud-bolt">
    When the exchange itself is down, **no orders can be placed or modified by anyone**. Your existing orders remain on the exchange's order book; they fill if the exchange honours them when it comes back. The TradingBot waits, retrying connection, until the venue is reachable again.

    During an exchange outage, your TradingBot is effectively paused. The Dashboard surfaces the connection state so you know what's happening. Once the venue returns, the bot reconciles and resumes within seconds.

    **Critical insight**: the venue is the source of truth for your funds and your orders. The TradingBot is the management layer. An exchange outage doesn't risk your funds — it just pauses your management.
  </Accordion>

  <Accordion title="Rate limit hit (the bot is sending too fast)" icon="gauge">
    Each exchange publishes a rate limit (Binance: `50` orders per `10` seconds, with separate ceilings for other request types). The TradingBot reserves headroom — typically operating well below the published ceiling — so this should rarely happen in normal operation.

    If a burst does push the bot over the limit, the venue returns a `429 Too Many Requests`. The TradingBot's response: log the rejection, sleep for the indicated cooldown (or a default of `30` seconds), and resume. Normal operation continues; the offending order is retried after cooldown.

    **Repeated rate-limit hits indicate a misconfiguration**, not a normal-operation problem. If you see this pattern, the Dashboard's logs will tell you which pair / mode is generating excessive orders. Most often it's a sell-ladder rung-count or buy-split count that's too aggressive for the venue.
  </Accordion>

  <Accordion title="Min-notional rejection (order too small)" icon="weight-scale">
    Each exchange has a minimum trade value (Binance spot: typically `$10` for most majors, but symbol-specific). If your buy ladder's split sizing produces an order below this floor, the venue would reject the order with an error code (Binance: `-1013` "Filter failure: MIN\_NOTIONAL").

    The TradingBot pre-checks every order against the venue's known min-notional and **does not submit** orders that would be rejected. The mode's buy split that produced the under-floor order is logged so you can re-tune; you never get a mysterious "the bot didn't trade" without explanation.

    **Common cause**: insufficient capital for the chosen mode's split count. If you're running BasicMode (7-split buy) with `$30` of buying power, each split is `~$4` — well below the floor. The fix: more capital, or a fewer-split mode (Tsl2Sell, MarketMakerMinimal).
  </Accordion>

  <Accordion title="Insufficient balance (you tried to spend more than you have)" icon="circle-exclamation">
    If a position is sized larger than your available balance, the exchange rejects with `-2010` "Account has insufficient balance". The TradingBot logs the rejection and does not retry the same order — the configuration that produced it is wrong, and retrying without operator intervention would just re-trigger.

    **Common causes**: capital was withdrawn from the exchange while the bot was running; another bot (or you manually) traded the same balance; the mode's per-buy investment is configured larger than the actual free quote.

    The Dashboard's logs surface the rejection clearly. The fix is operator action: top up the balance, adjust the mode's investment-per-buy, or close other positions to free balance.
  </Accordion>

  <Accordion title="API key revoked or expired" icon="key">
    If your API key is revoked (you rotated, or the venue invalidated for security), the next API call returns an authentication error. The TradingBot logs the failure prominently, refuses to retry (a key rejection is a config issue, not a transient failure), and waits for operator intervention.

    The Dashboard displays the connection-down state. Open positions on the exchange are unaffected — they continue honouring whatever orders are already on the book. Once you update the API credentials and restart the TradingBot, normal operation resumes.

    **Operator habit**: any time you rotate API keys, do it during a quiet trading hour, and watch the Dashboard's first reconcile after restart.
  </Accordion>

  <Accordion title="VPS reboot (planned or unplanned)" icon="rotate">
    Docker's restart policy brings the TradingBot back automatically. On startup, the bot:

    1. Connects to the database, reads the active configuration.
    2. Connects to the exchange's REST + WebSocket endpoints.
    3. Runs a full reconciliation against the exchange — pulls open orders, pulls recent trades, compares against its local state.
    4. Detects any fills that happened during downtime and updates its records.
    5. Resumes normal operation.

    From cold-start to "fully operating" is typically `15–60` seconds. During the gap, **open sell rungs and stop orders on the exchange continued honouring** — exchange-side orders are independent of your VPS being alive.

    **The one weakness**: if the trailing stop would have re-priced upward during the downtime (because the price made new highs), it doesn't catch up — on reboot the trailing stop is at its last server-side level. For most modes this is a minor edge case; for tight trailing-only modes, plan VPS reboots during quieter sessions.
  </Accordion>

  <Accordion title="Database unreachable" icon="database">
    If the local database is unreachable (rare — the database container restarts in seconds, and Docker's network keeps it on the same internal IP), the TradingBot logs the failure and retries with backoff. It does not attempt to trade without configuration access — that would risk acting on stale state.

    Open exchange-side orders continue. Once the database is back, the TradingBot resumes normally.

    **If the database is corrupted or destroyed**: this is a serious operator event. Restore from your most recent backup, restart the TradingBot, and run a reconciliation. The exchange remains the source of truth for your funds.
  </Accordion>

  <Accordion title="Exchange returns an unrecognised error" icon="circle-question">
    Each exchange has its own error catalogue. The TradingBot's exchange profile maps known codes to actions (retry, log-and-continue, log-and-stop). For unrecognised codes, the bot's default is **conservative**: log the full response, do not retry, surface the error in the Dashboard, and wait for operator review.

    This conservatism is by design. An unknown error code is more likely to indicate something's changed venue-side that the bot doesn't understand yet — silently retrying could compound a real problem.

    Operators who hit a recurring unknown code should report to support; the exchange profile is updated to handle the case appropriately for future operators.
  </Accordion>
</AccordionGroup>

## Operator control surface

The TradingBot has no operator UI of its own — all operator interactions flow through the Dashboard. The TradingBot reads from the database; the Dashboard writes to the database; the TradingBot picks up the changes on its next configuration poll.

<CardGroup cols={2}>
  <Card title="Toggle the kill switch" icon="power-off">
    Flip from the Dashboard's main panel. The TradingBot stops placing **new** buy orders within seconds. Existing positions are unaffected — their pre-placed sell ladders and trailing stops continue honouring on the exchange itself.
  </Card>

  <Card title="Add or remove trade pairs" icon="coins">
    Edit your active pair list from the Dashboard. The TradingBot picks up the change on the next configuration poll and either starts evaluating the new pair (for adds) or stops opening new positions on the removed pair (for removes; existing open positions continue to manage to closure).
  </Card>

  <Card title="Change a pair's mode" icon="rotate">
    Switch a pair from one mode to another. **Already-open positions on that pair continue under the previous mode's rules**; new positions opened after the switch use the new mode. This avoids a mid-trade rule change that could leave a position in an undefined state.
  </Card>

  <Card title="Edit mode parameters" icon="sliders">
    Tweak a mode's buy-ladder shape, sell-ladder rungs, trailing-stop activation, hard stop-loss, or labelling. Changes apply to **all pairs using that mode**. Already-open positions continue under the rule shape they were opened with.
  </Card>

  <Card title="Allocate capital per pair" icon="money-bill-wave">
    Capital allocation is per-mode and (within mode) effectively per-pair. The Dashboard's Modes panel lets you set the investment per buy, the percentage of free quote balance to use, and the floor below which the mode will not trade.
  </Card>

  <Card title="Stream live logs" icon="terminal">
    The Dashboard's Logs panel streams the TradingBot's container output via Server-Sent Events. Watch live as orders are placed, fills are processed, errors are surfaced. Read-only — the panel cannot send commands.
  </Card>
</CardGroup>

## Pre-built modes the TradingBot ships with

The TradingBot can run one of **9 pre-built modes** out of the box. Each is a complete strategy specification — buy-ladder shape, sell-ladder rungs, trailing-stop policy, capital sizing — and lives as a JSON file inside the TradingBot's image.

<AccordionGroup>
  <Accordion title="Mode 4 — BasicMode (default, recommended starter)" icon="seedling">
    A 7-split grid with sell targets from `+0.25%` to `+5%`. Designed for sideways and lightly-trending markets. **Recommended capital: \~\$20,000.**

    Most operators start here. The 7 sell-ladder rungs at `0.25, 0.5, 1, 2, 3, 4, 5` percent ensure that any non-trivial upward move closes at least part of the position. The buy ladder's 7 splits give the position room to absorb dips before being fully invested.

    No trailing stop — exits are purely the sell ladder. Suitable for operators who want predictable, mechanical behaviour.
  </Accordion>

  <Accordion title="Mode 1 — FullBullMarket" icon="rocket">
    Optimized for sustained uptrending regimes. Wider sell targets and trailing-stop arming on profit. **Recommended capital: \~\$20,000.**

    Trades fewer round-trips than BasicMode but holds positions for longer rallies. Underperforms BasicMode in chop; outperforms in clear up-trends.
  </Accordion>

  <Accordion title="Mode 2 — LongTimeLongMoreProfit" icon="hourglass-half">
    Patient mode with extended hold times and wider profit targets. **Recommended capital: \~\$20,000.**

    Few trades, larger per-trade profit targets. Suitable for operators who don't want frequent activity and are willing to wait for meaningful moves.
  </Accordion>

  <Accordion title="Mode 3 — LongTimeLong" icon="hourglass-end">
    Even more patient than Mode 2, with the highest capital recommendation. **Recommended capital: \~\$25,000.**

    Designed for operators with substantial capital who want minimal trading frequency and willingness to absorb deeper drawdowns for larger eventual exits.
  </Accordion>

  <Accordion title="Mode 5 — LowMoney" icon="piggy-bank">
    Adapted for smaller capital with reduced split count. **Recommended capital: \~\$3,000.**

    Fewer buy splits and tighter sell-ladder shape so per-order sizing clears min-notional even at lower capital. Trades less than BasicMode at scale; the right starting point for operators with `$3,000–$5,000`.
  </Accordion>

  <Accordion title="Mode 6 — MinimalMoney" icon="coins">
    The minimum-capital mode for operators just learning. **Recommended capital: \~\$1,500.**

    The sparsest mode in the suite. Designed so the rate of trading remains meaningful even at the lowest reasonable starting capital. Ideal for the first month of operation.
  </Accordion>

  <Accordion title="Mode 7 — Tsl2Sell" icon="bullseye">
    Trailing-stop-driven exits with simplified buy logic. **Recommended capital: \~\$10,000.**

    Optimized for instruments where letting the trailing stop catch the move is more valuable than a fixed sell ladder. Suitable for trending instruments where the next high is unpredictable but durable.
  </Accordion>

  <Accordion title="Mode 1001 — MarketMaker (FDUSD only)" icon="scale-balanced">
    Specialty market-making mode for the `FDUSD` quote asset. **Recommended capital: \$20,000+.**

    Posts maker-only orders on both sides of the book, profiting from rebates rather than directional moves. Only viable on Binance `FDUSD` pairs which have a maker rebate structure.
  </Accordion>

  <Accordion title="Mode 1002 — MarketMakerMinimal (FDUSD only)" icon="scale-unbalanced">
    Smaller-capital variant of Mode 1001. **Recommended capital: \~\$5,000.**

    Same market-making logic at reduced scale. Use to learn the mode's behaviour before committing larger capital.
  </Accordion>
</AccordionGroup>

<Tip>
  **The right starter for almost every operator**: BasicMode (Mode 4) on `BTCUSDT` with `$15,000–$25,000` of capital. This is the most-tested combination, the most-documented behaviour, and the most-validated mode-symbol pairing.

  Once you've run BasicMode for a month and feel its rhythm, branch out: try LowMoney on `ETHUSDT`, FullBullMarket if you've identified a strong trend regime, MinimalMoney as a low-cost test mode for new symbols.
</Tip>

## Capital and rate-limit guidance

Capital sizing is the single biggest operator decision affecting whether the TradingBot can actually trade your chosen mode effectively.

<AccordionGroup>
  <Accordion title="Why capital affects whether a mode can trade" icon="weight-scale">
    Each mode has a buy ladder of N splits. Each split is approximately `total_capital / N`. The exchange enforces a minimum-notional floor (Binance: `$10` for most majors, varies by symbol).

    If `total_capital / N` \< min-notional, **the mode cannot place per-split orders that the exchange will accept**. The bot will skip orders, log the reason, and your fill rate collapses.

    **Worked example**: BasicMode has 7 buy splits. With `$30` of capital allocated to a pair, each split is `~$4` — under the `$10` floor. The bot effectively cannot trade. With `$140` ($20 × 7), each split is `$20\` — clears the floor.

    The recommended capitals listed above are calibrated so each mode's split count produces orders comfortably above the min-notional, with headroom for symbols whose floor is higher than the typical `$10`.
  </Accordion>

  <Accordion title="Reserve recommendation: 50% of trading capital" icon="vault">
    On top of your trading capital, keep approximately **50% of that amount as reserve** in your exchange account but not allocated to any active mode. This reserve covers:

    * **Drawdown averaging.** If a position moves against you and your buy ladder fully invests, the reserve lets you take additional positions on other pairs without compounding stress.
    * **Adding to drawdowns.** Some operators use the reserve to extend the buy ladder beyond the mode's default — if a position is `-15%` underwater and the reserve permits, an additional buy can lower the average entry.
    * **Operational headroom.** Exchange fees, occasional re-entry into a closed position, and capital for adding new pairs come from the reserve.
    * **Sleep-at-night insurance.** A reserve means you're never running 100% deployed; an unexpected market event has cushion.

    **Concrete sizing**: if you've decided BasicMode on `$20,000` is your trading capital, hold an additional `~$10,000` in your exchange account as reserve. Total exchange balance: `~$30,000`. The bot trades with `$20,000`; the rest sits as headroom.
  </Accordion>

  <Accordion title="Rate-limit envelope per exchange" icon="gauge">
    The TradingBot is configured to use comfortably less than each exchange's published rate limit, leaving headroom for short bursts (e.g., a market-wide event firing multiple sell rungs at once).

    | Exchange          | Order rate limit           | Bot envelope (typical)       |
    | ----------------- | -------------------------- | ---------------------------- |
    | Binance spot      | `50` orders / `10s` per IP | bot uses `~30` / `10s` peak  |
    | Bybit             | `100` orders / `5s`        | bot uses well under          |
    | OKX               | `60` requests / `2s`       | bot stays under              |
    | Coinbase Advanced | `15` orders / `s`          | bot stays under              |
    | Kraken            | tier-dependent             | bot stays under default tier |

    **Operator implication**: with these envelopes, a single TradingBot per exchange comfortably handles 5–15 active pairs in any of the pre-built modes. If you're running 20+ pairs on one exchange and seeing rate-limit warnings, consider splitting across two TradingBot containers (each with its own API key, sharing the same database).
  </Accordion>

  <Accordion title="The recvWindow setting (Binance-family)" icon="clock">
    Binance and its derivatives accept a `recvWindow` parameter on signed requests — the maximum milliseconds between the order's timestamp and the exchange's receive time. If the bot's clock and the exchange's clock differ by more than this window, orders are rejected with a timestamp error.

    The operator-recommended value is **`60000` (60 seconds)**. This is generous enough to absorb normal clock drift, brief network latency spikes, and minor VPS time-sync issues without losing orders. Reducing it below `60000` rarely helps and risks spurious rejections.

    The TradingBot also runs a periodic NTP-based clock check internally; if your VPS clock drifts substantially you'll see warnings in the logs before order rejections start.
  </Accordion>
</AccordionGroup>

## Multi-exchange operation patterns

Once you outgrow a single exchange — by capital, by symbol coverage, or by jurisdictional preference — the natural pattern is multiple TradingBot containers.

<AccordionGroup>
  <Accordion title="Pattern 1 — One exchange, one bot (the starter)" icon="puzzle-piece">
    The default. One TradingBot, one set of API keys, one venue. Almost every new operator runs this for the first 1–3 months.

    Pros: simplest mental model. Fewer surfaces to monitor. Fastest setup.

    Cons: one venue's behaviour is your only signal of "is the bot working?" — if Binance has an outage, you have no diversification.

    **When to outgrow**: you've proved the bot to yourself with `$15,000–$25,000` on Binance for 1+ month and feel the rhythm. Now you want to add a second venue for symbol coverage or jurisdictional reasons.
  </Accordion>

  <Accordion title="Pattern 2 — Two exchanges, two bots (the standard scale-up)" icon="puzzle-piece">
    Two TradingBot containers, each with its own API key, each pointing at the same shared database. Typical pairing: Binance + Bybit (or Binance + Kraken, or Binance + Bitvavo for EU operators).

    Pros: jurisdictional diversification. Symbol coverage that one venue alone doesn't have. If one venue has an outage, the other continues.

    Cons: two sets of API keys to manage. Two sets of fees to track. Two reconciliation surfaces.

    **Capital pattern**: split capital based on symbol availability and venue trust. Common starting allocation: 70% Binance, 30% second venue.
  </Accordion>

  <Accordion title="Pattern 3 — One bot per sub-account on the same venue" icon="puzzle-piece">
    Some operators want strategy isolation without going to a different venue. Binance and Bybit support sub-accounts: separate API keys, separate balances, separate fee tiers, but one master account for compliance.

    Two TradingBot containers, both pointing at Binance, but each with sub-account API keys: Container A trades aggressive strategies in Sub-Account 1; Container B trades conservative strategies in Sub-Account 2. Each sub-account has its own balance — no balance-sharing surprises between them.

    Pros: clean strategy isolation. Per-strategy P\&L is clear. One venue, one compliance footprint.

    Cons: requires the venue to support sub-accounts (most majors do). Adds operator complexity.
  </Accordion>

  <Accordion title="Pattern 4 — Geographic distribution" icon="puzzle-piece">
    Advanced operators sometimes deploy TradingBot containers on VPSs geographically close to each exchange's matching engine — Binance has data centers in multiple regions; Bybit, OKX, Kraken similarly. The latency win is small but real for trading frequencies that matter.

    Pros: marginal latency improvement. Some operators report `5–20ms` reduction in order round-trip.

    Cons: significant operational complexity. Multiple VPSs to manage. Most modes do not benefit from this latency reduction enough to justify the operator overhead.

    **Honest recommendation**: don't bother unless you've outgrown single-VPS operation and have a specific reason to optimize latency. The pre-built modes were designed for `100ms+` latencies; sub-`50ms` is a luxury, not a requirement.
  </Accordion>
</AccordionGroup>

## What the TradingBot does NOT do

<Warning>
  **The TradingBot's scope is intentionally focused.** Many operator-relevant capabilities live in adjacent modules — keeping the TradingBot focused on execution is what makes it reliable.

  * ❌ **Does not author strategies.** That's the SignalEditor's job. The TradingBot runs the modes shipped with the bot, plus any configuration the SignalEditor → SignalsBot pipeline writes to the database.
  * ❌ **Does not evaluate technical indicators on your behalf for custom logic.** That's the SignalEditor. The TradingBot's modes have their own internal indicator evaluation specific to their mode logic, but it does not run general-purpose technical analysis.
  * ❌ **Does not produce signals from market data.** It receives configuration and acts on it.
  * ❌ **Does not run backtests.** That's the Backtester. You backtest before scaling up; the TradingBot runs live.
  * ❌ **Does not send notifications to Telegram.** That's the TelegramBot. The TradingBot writes closed trades to the database; the TelegramBot polls and notifies.
  * ❌ **Does not present a UI.** That's the Dashboard. The TradingBot reads/writes the database; the Dashboard is the operator surface.
  * ❌ **Does not span multiple exchanges in one container.** Single-exchange by design.
  * ❌ **Does not modify your exchange API key permissions.** It uses the permissions you grant. If you accidentally enabled withdrawal, the bot will not enable it nor disable it for you — that's exchange-side configuration only you can change.
  * ❌ **Does not auto-update without your approval.** Updates are operator-driven. New TradingBot versions are released; you decide when to pull and restart.
  * ❌ **Does not guarantee profit.** The bot enforces rules. The market decides outcomes. Disciplined execution of a well-tuned mode is necessary but not sufficient for profit.
</Warning>

## Operational footprint

<CardGroup cols={2}>
  <Card title="Resource cost" icon="microchip">
    `100–300 MB` RAM per TradingBot container at idle, scaling modestly with the number of active pairs. Sub-percent CPU at idle, brief spikes during configuration polls and reconciliation. A single VPS comfortably runs `2–4` TradingBot containers (one per exchange) on the recommended `4 vCPU / 8 GB / 80 GB NVMe SSD` profile.
  </Card>

  <Card title="Network calls" icon="globe">
    Continuous outbound to your exchange (REST for orders, WebSocket for fills and market data). No inbound — the TradingBot exposes no port. Lives entirely on your VPS's internal Docker network.
  </Card>

  <Card title="Data storage" icon="database">
    Reads configuration from the local database, writes closed trades to the local database. Holds essentially no state on its own disk — restart-safe by design. The database volume needs backup; the TradingBot container does not.
  </Card>

  <Card title="Failure mode" icon="triangle-exclamation">
    If the TradingBot crashes, **already-placed exchange-side orders continue honouring** — they're independent of your VPS. The bot restarts via Docker's restart policy, reconciles, and resumes within seconds. No fills are lost.
  </Card>

  <Card title="Startup time" icon="stopwatch">
    Cold-start to "fully operating" is typically `15–60` seconds — depending on database availability and the size of the reconciliation pass on first connect.
  </Card>

  <Card title="Update cadence" icon="rotate">
    Exchange profiles, error-code mappings, and rate-limit envelopes are versioned per release. Operators pull updates on their own schedule — typically monthly, or when a new exchange feature is announced.
  </Card>
</CardGroup>

## Common questions

<AccordionGroup>
  <Accordion title="Can I have the TradingBot trade multiple symbols at once?" icon="circle-question">
    **Yes** — that's the normal pattern. A single TradingBot instance handles your entire active pair list on its configured exchange. Each pair is evaluated independently per cycle; capital allocation per pair is set in the Dashboard.

    Practical limits: most operators run `5–15` active pairs per exchange. Going above `20` starts to put pressure on the rate-limit envelope; consider splitting across multiple TradingBot containers if you need a much larger active set.
  </Accordion>

  <Accordion title="Can I run two different modes on the same pair?" icon="circle-question">
    **No, not in one TradingBot.** A pair is assigned to exactly one mode at a time. To "run two modes on BTC", the standard pattern is:

    * Run two TradingBot containers, each with its own API credentials and sub-account.
    * Container A trades `BTCUSDT` on Mode 4.
    * Container B trades `BTCUSDT` on Mode 1.

    Sub-accounting on the venue side ensures the two bots don't trip over each other's balance. Most operators don't bother with this pattern — picking one mode per pair is simpler and easier to reason about.
  </Accordion>

  <Accordion title="What happens if I change a mode's parameters mid-trade?" icon="circle-question">
    Already-open positions continue under the rules they were opened with — the sell ladder is already on the exchange, the trailing stop reference is already armed. New positions opened after the change use the new parameters.

    This avoids the worst-case scenario of a position being half-managed by old rules and half by new rules. The trade-off: a parameter change you make right now doesn't propagate to in-flight trades.

    **Best practice**: if you're making a substantial mode change, wait for open positions to close (or close them manually) before scaling up the new rules.
  </Accordion>

  <Accordion title="How fast does the bot react to a market move?" icon="circle-question">
    Fill events arrive via WebSocket in milliseconds. A buy fill triggering sell-ladder placement is typically completed within `100–500ms`. A trailing-stop re-pricing (when a new high is made) is in the same range.

    The bot is not a high-frequency trading system — it's not optimized to shave microseconds off latency. For its intended modes (multi-minute to multi-day trades), the WebSocket-driven response time is more than adequate.
  </Accordion>

  <Accordion title="Can the TradingBot trade futures, perpetuals, or margin?" icon="circle-question">
    The shipped modes are spot-only. Most operators use unCoded as a spot-trading bot — the modes' risk profiles are calibrated for spot.

    Modes that trade margin or perpetuals are technically possible at the venue layer (the API supports them) but are not part of the default mode catalogue. If you have a specific need, contact support — bespoke leveraged-mode work is a custom engagement.

    **Strong recommendation for most operators**: stay spot-only. Leverage compounds losses much faster than gains, and the modes' risk shapes were designed for unlevered execution.
  </Accordion>

  <Accordion title="What's the difference between a mode and a strategy?" icon="circle-question">
    **Modes** are the pre-built, hardcoded strategy specifications shipped with the TradingBot. They live as JSON files inside the TradingBot's image and are tuned by the unCoded team. There are 9 of them, identified by number (Mode 1, Mode 4, etc.).

    **Strategies** are operator-authored signal graphs created in the SignalEditor. They live as JSON files in the SignalEditor's volume, are evaluated by the SignalEditor's scheduler, and produce webhook signals that the SignalsBot translates into configuration changes.

    Both ultimately drive the TradingBot's execution. The difference is who authored them: modes by the unCoded team, strategies by you.
  </Accordion>

  <Accordion title="Does the TradingBot manage stop-losses?" icon="circle-question">
    **Yes** — every shipped mode has a hard stop-loss configurable per mode (typical defaults: `-15%` to `-25%` from entry, mode-specific). When the stop is hit, the position is closed at market.

    Most modes also have a **trailing stop** that arms once a configured profit threshold is reached. The trailing stop is locally re-priced as new highs are made; once armed, it acts as a profit-protective floor.

    Mode 4 (BasicMode) does **not** have a trailing stop — its exit is purely the 7-rung sell ladder. This is intentional: it keeps the mode fully predictable and avoids the trailing-stop's downtime weakness.

    The Modes panel in the Dashboard shows the exact stop-loss and trailing-stop configuration for each mode, and lets you edit them.
  </Accordion>

  <Accordion title="Can I have the TradingBot only buy, not sell?" icon="circle-question">
    Yes — set `canSell: false` on the mode. The bot will continue placing buy orders but will not place new sell orders. Existing sell rungs already on the exchange continue to honour.

    This is occasionally useful if you want to take delivery of an asset rather than rotate it for profit. More commonly the inverse: `canBuy: false` to wind down a pair (let existing positions close out without opening new ones).
  </Accordion>

  <Accordion title="What if the bot stops trading suddenly?" icon="circle-question">
    First check: is the kill switch on? It's the most common cause and easiest to fix.

    Second check: is the exchange reachable? The Dashboard's connection panel shows the venue's status.

    Third: are you over the rate limit? The Dashboard's logs surface this clearly.

    Fourth: is the per-split sizing under min-notional? Look at the logs for `MIN_NOTIONAL` rejections.

    Fifth: have you been removed from your IP allow-list? Some operators rotate VPSs and forget to update the API key's allow-list.

    The Dashboard's Logs panel is your first stop for any "the bot stopped trading" investigation. The bot is verbose by design — every refusal to trade is logged with a clear reason.
  </Accordion>

  <Accordion title="Can I pause trading on just one pair?" icon="circle-question">
    Yes — set `canBuy: false` (or `canSell: false`) on the mode that pair is using, or remove the pair from the active set entirely. Removed pairs continue managing existing positions to closure but will not open new ones.

    A more surgical approach: keep the pair active but flip the mode's `canBuy` flag. Existing positions continue to manage; no new positions open. When you're ready to resume, flip the flag back.
  </Accordion>

  <Accordion title="What happens during a hard fork or symbol delisting?" icon="circle-question">
    Hard forks and delistings are venue-side events. The TradingBot does not have special handling for them — it reads what the venue says.

    **Operator action required** when a delisting is announced: remove the affected pair from your active set before the delist date. Existing positions should be closed manually if the venue's force-close-on-delist is unfavourable. The Dashboard's logs will start to show errors once the symbol is no longer tradeable.

    **Hard forks**: typically the venue itself handles the fork accounting — the new asset appears in your balance, your positions on the parent symbol continue. The TradingBot does not actively trade the new asset until you add it as a pair.
  </Accordion>

  <Accordion title="Is the bot deterministic? Will the same market produce the same trades?" icon="circle-question">
    **Mostly yes, with caveats.** Given the same configuration, the same market data, and no external interference, the bot's actions are deterministic — buy at the same price, sell at the same rungs, close at the same trailing-stop reference.

    Caveats: latency to the exchange varies (so order placement timestamps differ slightly run-to-run), and partial fills can lead to slightly different effective entry prices. The trade outcomes are usually identical at the round-trip level even when the per-fill timestamps differ.

    For backtesting, this determinism is helpful — the Backtester is fully deterministic given the same inputs.
  </Accordion>
</AccordionGroup>

## Best practices

<Tip>
  * ✅ **Start on Binance with BasicMode** unless you have a specific reason to do otherwise.
  * ✅ **Start with `$15,000–$25,000` capital + `~50%` reserve** (`~$22,500–$37,500` total exchange balance).
  * ✅ **Use API keys with read + spot-trading permissions only**. Never enable withdrawal.
  * ✅ **IP-allow-list your API keys** to your VPS's static IP.
  * ✅ **Keep `recvWindow` at `60000`** — don't reduce without specific reason.
  * ✅ **Run one TradingBot container per exchange** — the single-exchange design is your friend.
  * ✅ **Open the Dashboard's Logs panel for the first hour** after any change (new pair, new mode, key rotation).
  * ✅ **Reconcile before scaling.** A new operator should run 1 month on starter capital before scaling up.
  * ✅ **Back up your local database daily** to off-site storage. The trade ledger is your authoritative record.
  * ✅ **Rotate API keys quarterly** — even without an incident, periodic rotation is good hygiene.
  * ✅ **Watch for repeated rate-limit warnings** in the logs — they indicate a configuration that's too aggressive for your venue.
  * ✅ **Don't change modes mid-trade** unless you understand the in-flight position behaviour.
  * ✅ **Treat the kill switch as your most important control** — flip it at the first sign of news you don't understand.
  * ✅ **Keep your VPS clock synced** via NTP — clock drift is a stealth source of order rejections.
  * ✅ **Monitor the reconciliation report weekly** — the Dashboard surfaces any divergence between the bot's view and the exchange's view.
</Tip>

## What's next

<CardGroup cols={2}>
  <Card title="Dashboard" icon="gauge" href="/modules/dashboard">
    The control surface for everything the TradingBot does.
  </Card>

  <Card title="Strategies & Modes" icon="boxes-stacked" href="/strategies/modes/overview">
    Deep dive into each pre-built mode, when to use it, and what it costs.
  </Card>

  <Card title="Exchanges" icon="building-columns" href="/exchanges/overview">
    Per-venue setup guides — Binance, Bybit, OKX, Coinbase, Kraken, and more.
  </Card>

  <Card title="API Key Security" icon="shield" href="/exchanges/api-key-security">
    Step-by-step on generating, scoping, and rotating exchange API keys correctly.
  </Card>

  <Card title="Quickstart" icon="forward" href="/quickstart">
    From zero to first live trade — the focused walkthrough.
  </Card>

  <Card title="Troubleshooting" icon="wrench" href="/troubleshooting/common-issues">
    Every error code, every common scenario, every recovery procedure.
  </Card>
</CardGroup>
