Files
momentum-system/deploy
momentum devandClaude Fable 5 b3a47d775d feat(019): discovery on its own thread + tuner heartbeat (honest stale alert)
Telemetry: discovery took 6-30s ON the single scheduler, freezing ingest/arm
so the trigger read stale bars — the real 'late edge detection'. Now discovery
runs on its own daemon thread with a dedicated DB connection; the watchlist it
mutates is a lock-guarded Watchlist (list-like drop-in, no torn reads); the
scheduler discover step auto-disables (single-writer). Loop is now 3 fast
threads (entries/exits/discovery) + slow scheduler for tolerant work.

Also: nightly_tune writes a heartbeat every run, so the boot alert distinguishes
'tuner not running' (real) from 'ran, no profitable ORB config, kept params'
(expected — the strategy has no edge). Kills the misleading Telegram alarm.
543 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 08:44:10 -05:00
..

Deploying Momentum

Three supported shapes, one image/codebase. Pick by where it runs:

Mode Status Use when Docs
Docker Compose ✅ canonical (production since 2026-07-09) Any always-on Linux host; TrueNAS SCALE docker/README.md, docker-compose.yml (root), docker/truenas-compose.yml
Local (systemd) ✅ maintained Development machine, WSL, bare metal without Docker systemd/README.md + unit templates in deploy/systemd/
Helm / Kubernetes 🚧 planned refresh Future k8s hosting helm/ — the chart predates the 2026-07 architecture; starting point, not deployable

Docker Compose (canonical)

The root docker-compose.yml runs the full stack self-contained: postgres 18, trading loop, dashboard (:8765), admin panel (:8767), telegram bot, transcripts pipeline, nightly scheduler, on-demand jobs, optional Grafana. The image is published to docker.io/fez5587/momentum-app and ghcr.io/fez5587/momentum-app by CI on every master push.

For TrueNAS SCALE use docker/truenas-compose.yml (pull-only, dataset host paths, inline env). Read the gotchas in docker/README.md before editing the YAML — anchor expansion, per-service env, and path case-sensitivity have each caused an outage.

Local (systemd user services)

The original deployment: unit templates in deploy/systemd/ running a git checkout + venv, config from .env. Still the best loop for development — tests, backtests, and research scripts run here. Keep the units disabled while the compose stack owns production: two loops against one Alpaca account create duplicate orders.

Helm (future)

deploy/helm/ holds the original chart (single app deployment + CronJobs). It predates the service split, the session gate, and the env-flag inventory; the refresh is tracked in GitHub issues. Until then, compose is the way.

Config in all modes

  • .env.example (committed, sanitized) is the full variable inventory and says which layer each belongs in.
  • Behavior flags that MUST be set explicitly in any deployment — silent defaults bite: TRADING_AUTO_APPROVE=1 (else entries queue for manual approval), ALPACA_DATA_FEED=sip, OLLAMA_ENABLED=true (catalyst engine), FMP_API_KEY (float cache). TRADING_SESSION_ONLY defaults ON in deployed configs (bars after-hours entries).
  • Runtime overrides: the admin panel writes data/overrides.env, which every service loads over its baked env at boot (runtime/env_overrides.py).