Local-first trading system focused on execution safety, state integrity, and human-in-the-loop control. The current scope targets Alpaca (paper/live) with a minimal desktop setup and a clear path to future expansion.
- Engine: subscribes to Alpaca trading WebSocket, maintains state, enforces risk controls, and syncs positions to SQLite.
- Market data daemon: owns the Alpaca market data WebSocket and caches quotes/trades/bars in Redis.
- FastAPI: control plane; reads state for the UI, accepts commands, and orchestrates draft/confirm/kill-switch flows.
- Streamlit: read-only UI for monitoring positions and issuing commands; never talks to the broker directly.
Shared domain and interfaces live in core/, with concrete implementations in adapters/.
- Internal notes:
docs/README_CN.md - Roadmap:
docs/roadmap.md - External API references:
docs/external_api/alpaca_doc.md
- Alpaca-py for trading REST and
trade_updatesWebSocket. - Alpaca-py market data WebSocket (IEX) with Redis cache for watchlist quotes/trades/bars.
- FastAPI as the control plane (state queries + command orchestration).
- Streamlit + Altair for a read-only desktop UI.
- SQLite + SQLAlchemy + Alembic for local state; Postgres in Docker Compose.
- Redis for command queueing between FastAPI and Engine.
- Pydantic settings for configuration via environment variables.
- Alpaca integration only (paper/live).
- Position distribution and PnL visualization in the GUI.
- Watchlist market data (Level 1 quotes, last trade, 1-min bars) via the market data daemon.
- Kill switch with a confirmation step for live trading.
- Trailing stop buy/sell (default 2%); auto-protect adds trailing stop loss on filled buys.
- No external data sources yet; local default is SQLite while Docker uses Postgres.
- Structured logs for key actions and environment context.
- Python 3.13+
- uv (Python package manager)
- Alpaca account and API keys
- Redis (local or container)
- SQLite (local file)
- Docker + Docker Compose (optional)
Optional keys (only if you use the related scripts): FMP/Finnhub/Benzinga/Google/iCloud.
cd /path/to/AlpacaTrading
uv venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
uv pip install -e .Use environment variables. Minimal set:
ALPACA_API_KEY=xxx
ALPACA_API_SECRET=xxx
ALPACA_TRADING_BASE_URL=https://paper-api.alpaca.markets
ALPACA_PAPER_TRADING=true
ALPACA_DATA_FEED=iex
DATABASE_URL=sqlite:///./data/engine.db
REDIS_URL=redis://localhost:6379/0
ENGINE_POLL_INTERVAL_SECONDS=10
ENGINE_SYNC_MIN_INTERVAL_SECONDS=3
ENGINE_ENABLE_TRADING_WS=true
ENGINE_TRADING_WS_MAX_BACKOFF_SECONDS=30
ENGINE_TRAILING_DEFAULT_PERCENT=2
ENGINE_TRAILING_BUY_TIF=day
ENGINE_TRAILING_SELL_TIF=gtc
ENGINE_AUTO_PROTECT_ENABLED=true
ENGINE_AUTO_PROTECT_ORDER_TYPES=market,limit,stop,stop_limit,trailing_stop
MARKETDATA_STREAM_ENABLED=true
MARKETDATA_SYMBOLS=AAPL,MSFT
MARKETDATA_MAX_SYMBOLS=30
MARKETDATA_SUBSCRIBE_QUOTES=true
MARKETDATA_SUBSCRIBE_TRADES=true
MARKETDATA_SUBSCRIBE_BARS=true
MARKETDATA_BAR_TIMEFRAME=1Min
MARKETDATA_BARS_MAX=120
MARKETDATA_CACHE_TTL_SECONDS=30
MARKETDATA_CACHE_NAMESPACE=marketdata
MARKETDATA_WS_URL=
MARKETDATA_WS_MAX_BACKOFF_SECONDS=30
ENGINE_TRAILING_DEFAULT_PERCENT and trail_percent are expressed in percent points (2 = 2%).
Note: Alpaca requires fractional trailing stop orders to use DAY TIF; the engine will override GTC when needed.
Free plan note: realtime market data WebSocket uses IEX with a ~30 symbol limit.
Migrations:
alembic upgrade headFastAPI:
uvicorn apps.api.main:app --reloadEngine:
python -m apps.engine.mainMarket data daemon:
python -m apps.marketdata.mainStreamlit UI:
streamlit run apps/ui/main.pyCreate env files:
cp deploy/env/common.env.example deploy/env/common.env
cp deploy/env/paper.env.example deploy/env/paper.env
cp deploy/env/live.env.example deploy/env/live.envFill in shared keys in deploy/env/common.env plus profile overrides, then run the profile you need.
Docker builds ignore deploy/env/*.env to keep secrets out of images.
docker compose -f deploy/docker-compose.yml --profile paper run --rm migrate-paper
docker compose -f deploy/docker-compose.yml --profile paper up -dLive profile (separate containers and ports):
docker compose -f deploy/docker-compose.yml --profile live run --rm migrate-live
docker compose -f deploy/docker-compose.yml --profile live up -dPorts: paper API :8000, paper UI :8501; live API :8001, live UI :8502.
Note: the market data daemon starts with the profile and needs MARKETDATA_SYMBOLS set.
Note: UI talks to FastAPI only; Engine owns the broker/WebSocket connection.
GET /healthhealth checkGET /state/profileactive profile and environmentGET /state/positionsposition snapshot (from Engine + SQLite)GET /market-data/watchlistwatchlist symbolsGET /market-data/quoteslatest quotes (cache)GET /market-data/tradeslatest trades (cache)GET /market-data/barsrecent bars (cache)POST /commands/draftstage a commandPOST /commands/confirmconfirm staged commandPOST /commands/kill-switchemergency liquidation requestPOST /commands/trailing-stop-buysubmit a trailing stop buy (default 2%)POST /commands/trailing-stop-losssubmit a trailing stop loss (default 2%)
- Engine owns the single trading WebSocket connection (free-plan friendly).
trade_updatestriggers an immediate position refresh; periodic polling remains as reconciliation.- Filled buy orders trigger auto-protect (submit trailing stop loss) when enabled.
- Position sync is throttled by
ENGINE_SYNC_MIN_INTERVAL_SECONDSto respect rate limits. - WebSocket reconnect uses exponential backoff with jitter (
ENGINE_TRADING_WS_MAX_BACKOFF_SECONDS). - Market data daemon owns the single market data WebSocket and caches snapshots in Redis.
- UI uses FastAPI only and never talks directly to the broker.
- Earnings calendar:
earnings-calendar(seeconfig/events_to_google_calendar.toml). - ARK holdings automation:
py_scripts/ark_holdings/.
make build
make lint
make test
make coverageCoverage threshold: 80% on runtime modules (apps/api, apps/engine, apps/marketdata, core, adapters, toolkits).
apps/entrypoints (api/engine/ui)apps/marketdata/market data daemoncore/domain models and portsadapters/external system adapters (broker/storage/messaging)storage/database migrations and schematoolkits/shared business logicpy_scripts/CLI scriptsconfig/TOML configuration (includesconfig/ci/for CI variables)deploy/Docker artifacts (Compose, Dockerfile, env examples)docs/internal docs and referencestests/pytest testsscripts/CI and automationsecrets/local credentials (only.gitkeepis committed)
See docs/roadmap.md for long-term planning and milestones.