- Consolidated multiline string formatting into single-line for SQL queries in multiple files. - Adjusted argument formatting in function calls for better alignment and readability. - Removed unnecessary line breaks and improved spacing in various sections of the codebase. - Updated test cases to maintain consistency in formatting and improve clarity.
Arbitrade
Low-latency cryptocurrency arbitrage bot scaffold for Kraken.
Current stack:
- Python 3.12+
- FastAPI + HTMX/Jinja2
- DuckDB for dev/test/prod
- Native Kraken WebSocket planned for market-data hot path
- Gitea Actions + Gitea container registry
Project plan lives in PLAN.md. Task checklist lives in .github/instructions/TODO.md. Coolify deployment runbooks live in docs/DEPLOYMENT.md.
Current Status
Bootstrap complete for foundation layer:
- repo initialized
- typed settings and env loading
- structured logging
- encrypted secret helpers
- DuckDB connection + base schema
- FastAPI app with health endpoint
- Gitea Actions CI scaffold
- Docker / docker-compose scaffold
Not implemented yet:
- Kraken REST client
- Kraken native WebSocket client
- arbitrage detection engine
- trade execution
- dashboard beyond health/bootstrap page
Configuration Management
The arbitrage trading bot now includes a complete configuration management system that allows users to configure trading behavior, currency pairings, fees, and other application settings through a web interface. All user-configurable settings are persisted in the database while system variables remain in environment variables as per the settings split plan.
Key features include:
- Web-based configuration interface at
/dashboard/config/ - Runtime hot-reloading of configuration changes
- Complete CRUD operations for all configuration entities
- Input validation and error handling
- Audit logging for all configuration changes
- Backtesting parameter configuration
- Fee configuration by pairing and market type
Templates
Full page templates (src/arbitrade/web/templates/):
| Template | Route | Purpose |
|---|---|---|
base.html |
— (root layout) | Dark theme, .shell container, HTMX, CSS variables |
dashboard.html |
/, /dashboard |
Main dashboard: metrics, overview, controls, charts |
config.html |
/dashboard/config |
Full configuration: fees, runtime, alerts, Kraken, risk |
audit.html |
/dashboard/audit |
Audit trail with auto-refresh via HTMX |
backtesting.html |
/dashboard/backtesting |
Backtesting panel with replay/sweep forms |
health.html |
/health |
System health check |
Dashboard partials (src/arbitrade/web/templates/partials/):
| Partial | In page | Content |
|---|---|---|
metrics.html |
Dashboard | 6 KPI cards: P&L, win rate, avg duration, trade count, success %, profit factor |
overview.html |
Dashboard | Status, balances, fee tier, open trades list, opportunity feed |
controls.html |
Dashboard | Runtime status, kill switch, config snapshot, alerting status, execution controls (Start/Stop/Kill) |
charts.html |
Dashboard | Opportunity trend chart (Chart.js, Alpine toggle) |
config.html |
Config page | Config form: Runtime, Alerts, Kraken, Risk, Strategy sections |
config_fees.html |
Config page | Pair fee table + add/edit form |
backtesting_panel.html |
Backtesting page | Run status, replay/sweep forms, recent runs |
audit.html |
Audit page | Audit trail table: time, actor, event, decision, payload |
Legacy templates (src/arbitrade/web/templates/dashboard/):
config_settings.html,config_pairs.html,config_fees.html— superseded by config page; retained for reference
Prerequisites
- Python 3.12+
uvfor env/package management- Git
- Docker Desktop or Docker Engine
- Gitea account on
git.allucanget.bizfor push/CI/registry access
Optional:
- PowerShell 7 on Windows
Repository Setup
Clone repo:
git clone https://git.allucanget.biz/allucanget/arbitrade.git
Set-Location arbitrade
If repo already exists locally, confirm remote:
git remote -v
Expected origin:
https://git.allucanget.biz/allucanget/arbitrade.git
Local Development Setup
Create virtualenv with uv:
uv venv
Activate env on Windows:
.\.venv\Scripts\Activate.ps1
Install app + dev dependencies:
uv pip install -e .[dev]
Dependency source of truth:
- Runtime dependencies live in
requirements/latest-runtime.in. - Dev dependencies live in
requirements/latest-dev.in. pyproject.tomlreads both files dynamically during package install.
Create local env file:
Copy-Item .env.example .env
Minimum .env values:
APP_ENV=dev
APP_HOST=0.0.0.0
APP_PORT=9090
LOG_LEVEL=INFO
LOG_JSON=true
DUCKDB_PATH=./data/arbitrade.duckdb
FERNET_KEY=
KRAKEN_API_KEY=
KRAKEN_API_SECRET=
KRAKEN_API_KEY_PERMISSIONS=query,trade
Notes:
- Leave Kraken creds empty until Kraken integration lands.
- If Kraken creds are set, both key and secret are required.
KRAKEN_API_KEY_PERMISSIONSmust includequery,tradeand must not include withdrawal scope.FERNET_KEYoptional. If empty, keyring-backed key generation used by secret helper.- On Windows, app falls back to default
asyncioloop. On non-Windows,uvloopinstalls automatically.
Run App
Start app:
python -m arbitrade.main
Health endpoints:
- HTML:
http://localhost:9090/ - JSON:
http://localhost:9090/health
Database
DuckDB used everywhere: local dev, tests, production.
Default database file:
./data/arbitrade.duckdb
Schema bootstrap runs automatically on app startup.
Current tables:
schema_migrationsopportunitiestradesportfolio_snapshots
Audit trail table:
audit_events(append-only operational decision log)
Audit retention and compaction guidance:
- Keep at least 30 days of
audit_eventsin active DB for incident triage. - Archive older rows to a timestamped export file before deletion.
- Example monthly archive workflow:
COPY (
SELECT *
FROM audit_events
WHERE occurred_at < NOW() - INTERVAL 30 DAY
) TO 'data/audit_events_archive_YYYYMM.parquet' (FORMAT PARQUET);
DELETE FROM audit_events
WHERE occurred_at < NOW() - INTERVAL 30 DAY;
- Back up archive files and the main DuckDB file together.
- For production, run archive + backup as scheduled maintenance (cron/task scheduler).
Quality Checks
Run tests:
pytest -q
Run Ruff:
ruff check .
Run Black check:
black --check .
Run mypy:
mypy src
Run dependency vulnerability audit:
pip-audit -r requirements/latest-runtime.in
Run secret scan (worktree + git history):
python scripts/security_scan.py
Generate latency profile baseline:
python scripts/profile_latency.py --iterations 600 --output ops/performance/latency_baseline.json
Run latency regression guardrails:
python scripts/check_latency_regression.py --baseline ops/performance/latency_baseline.json --thresholds ops/performance/latency_thresholds.json --iterations 600
Install pre-commit hooks:
pre-commit install
Run hooks manually:
pre-commit run --all-files
Docker
Build locally:
docker build -t arbitrade:local .
Container dependency install flow:
- Docker installs runtime dependencies from
requirements/latest-runtime.in. - Docker then installs the package with
--no-depsso dependency resolution is driven by requirements files.
Run with compose:
docker compose up --build
Compose mounts local data/ folder into container at /app/data.
Important:
- docker-compose.yml uses
git.allucanget.biz/allucanget/arbitrade:latestas the default image reference.
Coolify Deployment (Prebuilt Image)
Use this when deploying from the image published by CI instead of building from Git inside Coolify.
1) Create application in Coolify
- In Coolify, create a new
ApplicationusingDocker Image/Public Image/Private Registry Image. - Image:
git.allucanget.biz/allucanget/arbitrade:latest - Registry:
git.allucanget.biz - If registry auth is required, configure the same registry credentials in Coolify.
2) Configure build and start behavior
Set these in Coolify application settings:
- Build Command: leave empty.
- Install Command: leave empty.
- Start Command: leave empty unless you explicitly want to override the image default.
- Port:
9090(coolify uses8000internally)
3) Configure health check and networking
- Health Check Path:
/health - Exposed Port:
9090 - Use Coolify-generated domain or attach your own domain.
4) Configure persistent storage
Add a persistent volume in Coolify:
- Mount Path:
/app/data
This preserves DuckDB and other runtime artifacts across restarts/redeploys.
5) Configure environment variables
Add runtime environment variables in Coolify (UI: Environment Variables):
APP_ENV=prodAPP_HOST=0.0.0.0APP_PORT=9090DUCKDB_PATH=/app/data/arbitrade.duckdbLOG_LEVEL=INFOLOG_JSON=trueKRAKEN_API_KEY=...KRAKEN_API_SECRET=...KRAKEN_API_KEY_PERMISSIONS=query,trade
Recommended:
- Configure
FERNET_KEYin Coolify secrets (do not commit it). - Keep all exchange keys/secrets in Coolify secret variables only.
Coolify should own runtime configuration through environment variables. CI only publishes the image.
6) Deploy and verify
- Trigger deploy in Coolify after CI publishes
git.allucanget.biz/allucanget/arbitrade:latest. - Verify app boot logs show startup completed.
- Verify
GET /healthreturns success on deployed URL.
Gitea CI / Registry Setup
CI file:
Required Gitea Actions secrets:
REGISTRY_USERNAMEREGISTRY_TOKEN
Example registry login:
docker login git.allucanget.biz
Example pushed image tag shape:
git.allucanget.biz/allucanget/arbitrade:latest
Architecture Docs
Implementation detail moved into docs:
- architecture overview - system context, building blocks, runtime, deployment, quality goals, risks.
- current implementation snapshot - codebase state, active routes, backtesting, strategy flags, deployment flow.
For navigation from README, use the docs above instead of this file for deep architecture detail.