VELOX / Docs · Architecture ← Back to site Launch Terminal →

Architecture

Velox is a four-component pipeline with Redis as the shared bus. Every component can run independently; none is responsible for more than one concern.

High-level diagram

Velox architecture Browser talks to Upstash Redis; four Vercel cron jobs (scanner, monitor, evaluator, optimizer) read and write the same Redis bus. CLIENT Browser terminal Svelte 5 + Vite · direct AI calls localStorage · same-origin read / write UPSTASH REDIS · SHARED BUS dual_portfolio_data · ai_signal_log · optimization_config signal:{SYMBOL} · 24–48h TTL CRON · 01 300s Scanner /api/scan */10 * * * * 80 pairs · 3 models CRON · 02 300s Monitor monitor-positions */2 * * * * TP · trail · BE CRON · 03 300s Evaluator evaluate-positions */30 * * * * Claude · HOLD/TIGHTEN/EXIT CRON · 04 300s Optimizer /api/optimize 0 */6 * * * weights · ±20% cap FEEDBACK cron node feedback node read / write Redis primary path writeback

Fig. 01 · Browser calls AI APIs directly; all persistence flows through Redis; four crons coordinate asynchronously

The cron pipeline

Four independent cron jobs form a pipeline. Each reads state written by the previous.

CronPathScheduleTimeoutWrites
Scanner/api/scan*/10 * * * *300sdual_portfolio_data, ai_signal_log
Monitor/api/monitor-positions*/2 * * * *300sdual_portfolio_data, trade lessons
Evaluator/api/evaluate-positions*/30 * * * *300sdual_portfolio_data
Optimizer/api/optimize0 */6 * * *300soptimization_config

All four functions are env-gated at runtime by CRONS_ENABLED. When unset, scheduled invocations return a 200 skip response immediately; manual HTTP calls still run. See the API reference for details.

Two parallel execution environments

The same trading logic runs in two independent environments:

  1. Browser (Svelte app) — runs when the tab is open. Pulls market data, calls three AI APIs directly from the browser, manages trades in localStorage.
  2. Vercel cron — runs headlessly 24/7. Calls the same AIs server-side, manages trades in Redis.

Both write to the same Redis keys. There is no conflict resolution — last write wins. This is intentional: the browser and the cron should converge because they're running the same logic against the same data. Any divergence is a bug we want to be loud.

Redis as the shared bus

All inter-component state lives in Redis:

  • dual_portfolio_data — authoritative portfolio state (trades, balances, equity)
  • optimization_config — live optimizer parameters, written by optimizer every 6h
  • ai_signal_log — per-model signal history with shadow P&L
  • signal:{SYMBOL} — per-coin cooldown tracking (24–48h TTL)

Risk sizing chain

Position sizing applies four multipliers in sequence, hard-capped at 40% of portfolio:

final_risk_pct = base_risk × Kelly × Anti-Martingale × Regime × Confidence
               = min(final_risk_pct, 0.40)
  • Kelly — classic Kelly criterion from win-rate + payoff ratio
  • Anti-Martingale — scales up after wins, down after losses
  • Regime — risk-on vs. risk-off detection; blocks CHOPPY regimes
  • Confidence — per-model confidence weight from the optimizer

On top of sizing, seven circuit breakers can block trade opening entirely:

  1. Daily loss limit
  2. Weekly loss limit
  3. Drawdown kill switch
  4. Max exposure ratio
  5. Extreme funding rate filter
  6. BTC dominance filter
  7. Optimizer pause (after N consecutive losses)

AI prompt architecture

All three models receive an identical prompt built by the scanner. The prompt includes:

  • Each model's rolling track record (self-learning feedback loop)
  • Discord community-call context (opt-in channel ingest)
  • Social sentiment data
  • Full indicator pack for all 80 coins (1H / 4H / Daily timeframes)

The consensus mechanism averages entry / SL / TP across agreeing models and weights confidence by the optimizer-tuned per-model weights.

The optimizer feedback loop

Every 6 hours the optimizer:

  1. Reads closed trades since the last cycle
  2. Computes per-model win rate, average R, and contribution-to-portfolio-return
  3. Adjusts per-model weights, risk caps, and blocked-regime set — capped at ±20% change per cycle
  4. Writes the new config to Redis
  5. The scanner picks up the new config on the next run

This closes the loop: bad decisions a month ago shrink that model's weight today.

Why this shape?

Every design choice above is load-bearing.

  • Consensus over ensemble averaging — averaging probabilities produces smooth noise. Requiring unanimous-ish agreement produces discrete signals where disagreement is the valuable output, not a bug.
  • Redis as the bus, not a queue — we don't need delivery guarantees; we need last-write-wins convergence. Redis fits.
  • Dual virtual portfolios — one aggressive, one conservative. Compares outcomes under identical signals to discover which risk posture actually produces Sharpe.
  • Cron, not event loop — scheduled scans are idempotent and trivially restartable. A crashed cron just waits 10 minutes and runs again.