matitos 9c3bee87ac
CI/CD / backend (push) Successful in 5m18s
CI/CD / frontend (push) Successful in 5m2s
CI/CD / build (push) Successful in 34s
CI/CD / cleanup (push) Successful in 6s
CI/CD / deploy (push) Successful in 22s
Crypto trading bot: engine, brokers, backtester, dashboard, deploy
FastAPI backend with a single-strategy async engine, paper and Binance
brokers, pure-python indicators, a backtester that shares the engine's
portfolio math, and a Vue dashboard with a live WebSocket feed. Adds the
Gitea Actions CI/CD workflow that deploys to Traefik via docker_default.
2026-09-18 17:02:33 +00:00

Crypto Trader

A small, hackable crypto trading bot with a web dashboard. Describe a strategy, drop in one Python file, run it, and watch positions and P&L live.

  • Backend: FastAPI, SQLAlchemy, SQLite (Postgres optional), pure-Python indicators, httpx for market data.
  • Frontend: Vue 3 + Vite + Tailwind dashboard with a live WebSocket feed.
  • Brokers: paper (simulated fills, default) and binance (live spot).
  • Market data: Binance public REST (no API key needed).
  • Backtesting: replay historical candles through the same strategy interface, with return/drawdown/win-rate/Sharpe metrics — so what you test is what runs.

Paper trading is the default. Live mode places real orders and is opt-in. This is experimental software. Never trade more than you can afford to lose.

How it works

Binance REST ──▶ MarketData ──▶ TradingEngine ──▶ Broker (paper | binance)
                                     │
                           Strategy.on_candle(ctx)
                                     │
                     REST /api + WebSocket /api/ws ──▶ Vue dashboard

The engine runs one strategy at a time. Each tick it fetches candles, updates the mark price, enforces stop-loss/take-profit, calls the strategy, executes the resulting intents, and persists orders, equity snapshots and events.

Quickstart (local)

# 1. Config
cp .env.example .env

# 2. Backend
python3 -m venv .venv
.venv/bin/pip install -r backend/requirements-dev.txt
cd backend && ../.venv/bin/python -m uvicorn app.main:app --reload --port 8000

# 3. Frontend (new terminal)
cd frontend && npm install && npm run dev

Open http://localhost:5173. API docs are at http://localhost:8000/docs.

Quickstart (Docker, local)

cp .env.example .env
docker compose -f docker-compose.local.yml up --build
# dashboard: http://localhost:8080   API docs: http://localhost:8000/docs

The default docker-compose.yml is the deployment stack (Traefik + docker_default); use docker-compose.local.yml for a self-contained local run.

Deployment

Merging to main triggers .gitea/workflows/deploy.yml, which tests, builds both images, and rolls the stack out on the shared Traefik host:

  • The frontend joins the external docker_default network and is published at crypto.${BASE_DOMAIN} (default crypto.matitos.org) via Traefik, with a Let's Encrypt cert (certresolver=myresolvercd).
  • The backend stays on the internal network only; the frontend nginx proxies /api (including the /api/ws WebSocket) to it, so API keys are never directly exposed.
  • The WebUI is protected by fail-closed Basic auth: the deploy aborts unless CRYPTO_FRONTEND_AUTH_USERS is set (falling back to the shared SCA_FRONTEND_AUTH_USERS). Generate a value with htpasswd -nbB user 'password'.
  • A new release is rolled back automatically if healthchecks fail.

Repo/org variables and secrets used by the deploy:

Name Kind Purpose
CRYPTO_FRONTEND_AUTH_USERS var/secret htpasswd string for the WebUI (required)
BASE_DOMAIN secret Base domain (default matitos.org)
CRYPTO_MODE var paper (default) or live
CRYPTO_EXCHANGE / CRYPTO_SYMBOL / CRYPTO_TIMEFRAME var Trading defaults
CRYPTO_STARTING_BALANCE / CRYPTO_POLL_INTERVAL var Paper account + tick rate
CRYPTO_EXCHANGE_API_KEY / CRYPTO_EXCHANGE_API_SECRET secret Required only for live
CRYPTO_EXCHANGE_SANDBOX var Use the Binance testnet
CRYPTO_CORS_ORIGINS var Defaults to https://crypto.<BASE_DOMAIN>
CRYPTO_DATA_DIR / PERSISTENT_MOUNT var Host path for the SQLite DB
DOCKERHUB_USERNAME / DOCKERHUB_TOKEN secret Optional; for authenticated pulls

Configuration

All settings are environment variables (see .env.example):

Variable Default Purpose
MODE paper paper or live
EXCHANGE binance Market data / execution venue
SYMBOL BTC/USDT Default trading pair
TIMEFRAME 1m Candle interval
POLL_INTERVAL 5 Seconds between ticks
STARTING_BALANCE 10000 Paper account size
FEE_BPS / SLIPPAGE_BPS 10 / 5 Paper fill model
DATABASE_URL sqlite:///./data/trader.db Postgres: postgresql+psycopg://...
EXCHANGE_API_KEY / EXCHANGE_API_SECRET — Required only for live
EXCHANGE_SANDBOX false Use Binance testnet

Adding a strategy

Drop a file in backend/app/engine/strategies/ — it is auto-discovered and appears in the UI immediately. See AGENTS.md for the full template and the StrategyContext API. Two examples ship in the repo: sma_cross and rsi_reversion.

API

Method Path Description
GET /api/status Bot status, equity, P&L
GET /api/strategies Available strategies + parameter specs
POST /api/bot/start Start a strategy
POST /api/bot/stop Stop the bot
POST /api/backtest Backtest a strategy on historical candles
GET /api/positions Positions (with unrealized P&L when open)
GET /api/orders Order history
GET /api/events Activity log
GET /api/equity Equity curve points
POST /api/orders Manual market order
POST /api/positions/{id}/close Close the open position
WS /api/ws Live status + event stream

Tests & lint

make test     # backend pytest + frontend vitest
make lint     # ruff
make build    # frontend production build

Project layout

backend/
  app/
    engine/            trading loop, indicators, strategies/
    broker/            paper + binance execution
    market/            binance + fake data feeds
    api/routes.py      REST + WebSocket
    models.py          positions, orders, equity, events
    store.py           persistence
  tests/
frontend/
  src/                 Vue dashboard
S
Description
No description provided
Readme
579 KiB
0 Stars 1 Watchers 0 Forks
Languages
Python 74.7%
Vue 17.4%
JavaScript 6.7%
Dockerfile 0.4%
Makefile 0.3%
Other 0.5%