Signal Engine
AI Driven Trading Platform

An options trading bot that shows its work.

Signal Engine trades short-dated SPY options on a trend-following signal, wraps every entry in seventeen independent guardrails, and streams the whole decision process to a live control plane. When it doesn't trade, it tells you exactly which rule stopped it, and what that restraint cost you.

Python engine + FastAPI control plane Tradier: multi-account, up to 15 SQLite telemetry, no external store WebSocket live stream Self-hosted behind nginx

The five-second loop

Every poll runs the same ten steps, in the same order.

No step is skippable and no step is silent. Each one writes to the telemetry database, which is why the dashboard can reconstruct why any given second did or didn't produce a trade.

  1. 01

    Check the kill switch and window

    Two independent halt triggers, plus the trading schedule gate.

  2. 02

    Fetch price and quote

    Underlying last price and NBBO quote, pulled in parallel.

  3. 03

    Read the tape

    SMA trend direction, ATR volatility, and spread metrics.

  4. 04

    Fetch equity and positions

    Account state, also parallelized, so sizing works on current numbers.

  5. 05

    Evaluate every guardrail

    All seventeen, in order. Any single failure ends the iteration here.

  6. 40,385 of 40,693 signals stopped at this line. Everything below runs for the other 0.8%.
  7. 06

    Select the contract

    Nearest ATM option in the DTE range, screened on bid, spread, NBBO size, open interest, volume, and max mark.

  8. 07

    Size the trade

    Risk budget is max_risk_per_trade_pct × equity, divided by the stop distance.

  9. 08

    Submit and await fill

    Limit order by default, priced at ask plus a slippage buffer.

  10. 09

    Monitor for exit

    The nine-rung exit ladder, re-evaluated on its own five-second poll.

  11. 10

    Record and cool down

    Trade written to SQLite, Slack notified, cooldown applied before the next entry.

Repeat every five seconds


Getting out, and not getting in

Nine ways to close a position. Seventeen reasons to never open one.

Exits are evaluated in strict priority order on every poll, so the most protective condition always wins. Guardrails run before any of that. The overwhelming majority of signals die here, on purpose.

Exit ladder

Checked in this order, every option_exit_poll_seconds.

Dollar stop
Absolute dollar loss against cost basis
Stop loss
Percentage stop, initial or post-hold
Take profit
Fixed percentage target
Trend target
Higher target, taken when the trend weakens
Trend flip
Trend reverses while the position is in profit
Trailing stop
Trails the high-water mark after activation
Partial TP
Closes half the position, lets the rest run
Time stop
Position is stagnant inside the P&L deadband
Max hold
Hard duration ceiling, no exceptions

Guardrails

Anything here blocks the entry. The four highlighted ones don't just block. They flatten open positions and halt.

Kill switch Daily loss limit Broker reconcile mismatch Max consecutive errors Daily profit cap Max drawdown Equity floor Max trades per day Underlying spread ATR minimum Trend filter Option spread Max option exposure Consecutive stop losses High block rate Stale quote burst Canary mode limits

The control plane

Seven views, each answering a different question.

Every panel is a draggable widget you can hide, reorder, or scope to a date range. Live PnL, trades, errors, and alerts arrive over a WebSocket, so the page never polls for what it can be told.

Home Overview

The at-a-glance session state: what the account is worth, what it did today, and what it decided not to do.

  • KPI Overview: balance, PnL, avg trade, win rate, fees, signal pass/block counts
  • Activity Feed: every entry, exit, win, loss, and session boundary, timestamped
  • Profit and Loss: cumulative trade-by-trade curve off a zero baseline
  • PnL Curve: daily bars against a cumulative line
  • Signal Blockers: which guardrail fired most, ranked
  • Exit Outcomes: donut of how positions actually closed
  • Execution Quality: slippage, hold time, option spread, delta
  • Decision Engine: trade score with its top drivers spelled out
  • Position Sizing and Regime Router: recommended risk and routing mode
  • Regime Timeline: session-by-session classification and pass rate
  • Trades: full paginated history with infinite scroll
Home / overview
Signal Engine Home view: KPI overview, activity feed, PnL charts, signal blockers, exit outcomes, execution quality, decision engine, regime timeline, and trade history.

Edge Where the money is

Post-hoc attribution. Not whether the strategy made money, but which conditions it made money under.

  • Regime Performance Cards: PnL, sessions, win rate, and ATR by market regime
  • Edge Summary: profit factor, expectancy per trade, average hold
  • Optimization Recommendations: plain-language suggestions derived from the window
  • Hourly, Weekday, and Spread Quality edge breakdowns
  • Execution Quality by Hour / by Spread: slippage against average PnL
  • Worst Slippage Trades: the individual fills that cost the most
  • Equity and Drawdown: cumulative curve with drawdown overlay
  • Blocker Opportunity Cost: estimated PnL left on the table per blocker
  • Strategy Version Leaderboard and Version Change Impact
  • Screening Funnel Pressure: where contracts get rejected
Edge / attribution and optimization
Edge view: regime performance cards, edge summary, optimization recommendations, hourly and weekday edge, execution quality, worst slippage trades, equity and drawdown, blocker opportunity cost.

Signals Why it didn't trade

The view most trading dashboards don't have. Forty thousand blocked signals are data, not noise.

  • No-Trade Waterfall: signals → blocked → passed → executed, as a funnel
  • Top Blockers: every rejection reason with its exact count and threshold
  • No Trade Inspector: drill into a single stage's runtime reasons
  • Recent Blocked Signals: per-signal detail: stage, reason, spreads, ATR, trend gap
  • Session Timeline: one row per session with trades, PnL, pass %, top blocker, top exit, and the full guardrail string
Signals / no-trade telemetry
Signals view: no-trade waterfall, top blockers with counts, no trade inspector, recent blocked signals table, and a session timeline.

Risk Command center

The panel you open when something feels wrong, and the one that tells you before it does.

  • Kill Switch: arm or disarm from the browser, with a stated reason
  • Risk Command Center: loss and profit limit utilization, drawdown, error count
  • Pre-Trade Checklist Gate: DB reachable, config readable, kill switch off, telemetry recent, schedule configured
  • Order Telemetry: slippage, hold time, and a ranked exit-reason breakdown
  • Runtime Watchdog: health, staleness, recovery attempts, broker reconcile, market hours, canary mode
  • Telemetry Freshness: per-stream SLA tracking with fresh/stale badges
  • Go-Live Readiness: critical vs. warning fails before real money
  • Strategy Health Alerts: active warnings with severity
Risk / guardrails and watchdog
Risk view: risk command center with kill switch controls, pre-trade checklist gate, order telemetry, runtime watchdog, telemetry freshness SLAs, go-live readiness, and strategy health alerts.

Retraining Governed tuning

A weekly tuner proposes parameter changes. It cannot promote them by itself.

  • Retraining Ops: last run, window, trades, PnL, win rate, applied changes
  • Retrain Governance: explicit human approval with a TTL and expiry, attributed to an account
  • Config Promotion Workflow: save draft, promote draft, roll back, each with a stated reason
  • Approve for live, approve for 7 days, or revoke approval outright
Retraining / tuner governance
Retraining view: retraining ops status, retrain governance with approval TTL and attribution, and the config promotion workflow with draft, promote, and rollback controls.

Config Audit

Edit the live strategy from the browser, but validate first, sign the change, and leave a trail.

  • Configuration Console: the whole config.ini in an editor, secrets masked
  • Validate before save, and saving requires an active admin session
  • Save Reason is mandatory, so every write is annotated
  • Audit Trail: logins, config and schedule changes, governance updates, account changes, IP grants, and access links, with timestamp and actor
Config / validated editing
Config view: the configuration console showing config.ini sections for slack, schedule, and strategy, with a save reason field and validate and save buttons.

Audit Every mutation, attributed

Config changes, governance approvals, and access grants are all one append-only record.

  • Timestamped to the microsecond, with the acting account
  • Event types include config_schedule_change, retrain_governance_update, account_update, ip_access_granted
  • Full before/after detail retained per entry
Audit / append-only trail
Audit view: an append-only audit trail table listing timestamp, event type, actor, and detail for logins, config changes, and governance updates.

Admin Host and fleet

Signal Engine runs one bot process per user. Admin is where you see and steer all of them.

  • System Health: CPU, memory, disk, database size, uptime, thread count
  • Users: status, email verification, admin flag, live-trading flag, broker count, bot state, last login
  • Bot Processes: PID, state, heartbeat age, start time, restart count
  • Start, stop, or kill any user's bot individually, or start and stop the whole fleet
  • Activate and deactivate accounts in place
Admin / system health and bot fleet
Admin view: system health metrics, a users table with status and bot state, and a bot processes table with start, stop, and kill controls.

Details that earn their keep

Two small things the dashboard gets right.

The trade calendar panel: a month grid where each day shows its trade count, coloured green for profit and red for loss, with a date range input, month navigation, and an Update button.

The trade calendar

Every day carries its own trade count, coloured by whether it made money. Click a day, shift-click for a range, or drag either end of an existing one. Type dates directly to jump months. Nothing loads until you click Update. A selection in progress costs no bandwidth, and the whole dashboard re-scopes at once.

The in-app issue reporter: a panel reading 'Found something interesting?' with an optional description field and a Submit Report button.

One-click issue reports

The reporter has already captured the state it needs: the view, the filters, the console. Submitting with an empty box is a complete report. The description field is there for anyone who wants to go further, not as a tax on the person who spotted the bug.


Operational safety

The parts that assume something will go wrong.

A trading bot fails in ways a web app doesn't: quietly, expensively, and while you're asleep. These are the systems that exist purely to notice.

Two independent kill switches

A STOP_TRADING file and a HALT_TRADING environment variable, either of which flattens positions and stops the loop. Neither depends on the other, or on the dashboard being up.

Runtime watchdog

Tracks heartbeat staleness, bad-quote bursts, and broker reconciliation. It records recovery attempts and their outcomes, so a self-healed incident still leaves evidence.

Telemetry SLAs

Quote, decision, trade-fill, and equity streams each carry their own freshness budget. A stream going quiet is itself an alert. Silence is never read as health.

Canary mode

Time-boxed reduced-risk trading with its own trade count, risk multiplier, and contract ceiling. The way a config change reaches live money without betting the account on it.

Go-live gate

A checklist separating critical fails from warnings. Governance approval, watchdog health, telemetry freshness, and retrain recency all have to line up.

Session auth and TOTP

Rate-limited login with lockout, optional TOTP, a dynamic IP allowlist with a 24-hour TTL, and magic-link email grants. Credentials are masked in every API response.


Under the hood

Eight modules, one SQLite file, no external dependencies at runtime.

The engine and the control plane share nothing but the database. Either can be restarted without the other noticing.

ComponentFilePurpose
Trading enginedaytrader.pyMain loop, signals, entries, exits, guardrails
Broker abstractionbroker.pyOne interface across Alpaca and Tradier
Control plane APIcontrol_plane/api.pyFastAPI REST routes and the WebSocket server
Analyticscontrol_plane/repository.pySQLite aggregations, regime classification, scoring
Auth and sessionscontrol_plane/security.pyLogin, sessions, IP allowlist, TOTP
Config managementcontrol_plane/config_store.pyVersioning, drafts, promotion, rollback
Process managercontrol_plane/process_manager.pyPer-user bot lifecycle
Dashboardweb/app.jsSingle-page app, live charts, draggable widgets

Design principle

A bot you can't audit is a bot you can't trust.

Signal Engine spends most of its compute deciding not to trade, and most of its storage explaining that decision afterward. The dashboard exists so that restraint is legible, so a flat day reads as forty thousand rules working rather than a system that might be broken.

Signal Engine Options day-trading platform Self-hosted · Python · FastAPI · SQLite Screenshots: paper account, Aug 2026