- C 70.7%
- Python 23.7%
- HTML 2.6%
- Shell 2.1%
- Makefile 0.7%
- Other 0.2%
| .claude | ||
| atys_web | ||
| brokers | ||
| configs | ||
| core | ||
| docs | ||
| src | ||
| tests | ||
| tools | ||
| vendor | ||
| .env.eodhd.template | ||
| .env.ibc.template | ||
| .env.template | ||
| .gitignore | ||
| atys.toml.template | ||
| CLAUDE.md | ||
| ibc_config.tmpl.patched | ||
| Makefile | ||
| README.md | ||
Atys — Moteur de trading algorithmique en C
~23 000 lignes C (moteur src + core + brokers) · 21 stratégies vtable · 27 indicateurs · 2 goldens SHA figés · 640+ tests
Atys est un moteur de trading algo monolithique en C, pensé pour faire
tourner la même boucle broker_next_tick → portfolio_engine → order_router
en backtest (data/atys_market.db SQLite) et en live IBKR paper (TCP
binaire via IB Gateway sur port 4002). La frontière d'abstraction est
exactement la vtable broker_t ; tout le reste du code métier est
partagé entre les deux modes.
Architecture
graph TB
CLI[atys backtest / atys live]:::cli
CTL[atys-ctl<br/>halt/resume/status]:::cli
subgraph Engine["core/portfolio_engine"]
PE[Portfolio Engine<br/>vtable strats · risk · CB · hooks]:::core
RM[Risk Manager<br/>daily/weekly loss + calmar + PF]:::core
TR[Strategy Registry<br/>21 strats vtable]:::core
AGG[Candle Aggregator<br/>ticks → bougies M1..W1]:::core
end
subgraph Routing["core/orders"]
ROUT[Order Router<br/>sim · broker vtable]:::core
SIM[Order Sim<br/>SL/TP/MTM/equity]:::core
end
subgraph Brokers["brokers/"]
TWS[TWS API native<br/>IBKR Gateway Docker]:::broker
end
subgraph Persist["core/persistence"]
DB[(SQLite<br/>positions / trades / state)]:::core
end
DBMKT[(data/atys_market.db<br/>160M bars, 12 GB)]:::data
CLI --> PE
CTL --> PE
PE --> RM
PE --> AGG
PE --> TR
TR --> ROUT
ROUT --> SIM
ROUT --> TWS
PE -.persistence.-> DB
PE -.backtest.-> DBMKT
TWS -.TCP 4002.-> Gateway([IBKR Gateway<br/>paper / live])
classDef core fill:#2d3748,stroke:#4a5568,color:#fff
classDef cli fill:#2b6cb0,stroke:#2c5282,color:#fff
classDef broker fill:#744210,stroke:#7b341e,color:#fff
classDef data fill:#22543d,stroke:#276749,color:#fff
Mental model
Backtest (atys backtest cfg.toml) : core/backtest/backtest.c lit
la DB SQLite via db_reader, feed le portfolio_engine bar par bar,
les ordres tapent directement dans order_sim (pas de broker réel).
Rapide (~300k bars/s sur Ryzen 9) et déterministe.
Live (atys live cfg.toml) : core/live_runner/live_runner.c appelle
broker_next_tick() sur le broker TWS en boucle, passe chaque tick au
candle_aggregator qui émet des bougies fermées au timeframe demandé,
lesquelles nourrissent le même portfolio_engine. Les ordres passent
par order_router qui les exécute en shadow sim + envoie au broker
réel via tws_place_order.
Même engine, même strats, même métriques — seule la source de ticks et la destination d'ordre changent. La parité est garantie par design : le code métier ne sait pas s'il est en backtest ou en live.
Quick start
# 1. Dépendances (Ubuntu/WSL)
sudo apt install -y build-essential libcurl4-openssl-dev libsqlite3-dev sqlite3
# 2. Build release
cd ~/atys && make
# → build/atys, build/atys-ctl, build/atys-fetch-history
# 3. Backtest golden (valide la stack)
./build/atys backtest configs/golden.toml
# Output: portfolio report + SHA du backtest_report.json
# Doit matcher tests/golden.sha256
# 4. Live IBKR paper (optionnel)
./tools/atys-prod.sh ibc-start # démarre IB Gateway Docker
./build/atys live configs/live_paper.toml # client_id=2, account DUQ273131
# 5. Dashboard web local (optionnel — observer + lancer tunes depuis browser)
./tools/atys-prod.sh web-start # FastAPI sur 0.0.0.0:8765
# → http://localhost:8765 (ou http://<LAN_IP>:8765 depuis un autre PC)
Détail workflow IBKR paper : voir feedback_atys_workflow.md dans la
mémoire Claude (pitfalls, client_id conventions, etc.).
Détail dashboard web : atys_web/README.md.
Layout du code
| Path | Contenu |
|---|---|
src/atys.c |
Point d'entrée : sous-commandes backtest / live |
core/portfolio_engine/ |
Engine partagé bt/live : dispatch strats, risk, circuit breaker |
core/strategy/ |
21 stratégies vtable (cf docs/strategies.md) |
core/indicators/ |
27 indicateurs (cf docs/indicators.md) |
core/tune/ + tools/tune/ |
Grid-search anti-overfit (cf docs/tune.md) — master DB persistante, 45 metrics, hiérarchie 6-tiers |
core/broker/ |
Interface broker abstraite (vtable) |
core/backtest/ |
Driver backtest (lit DB + simule ordres, pas de broker) |
core/live_runner/ |
Boucle live + socket commande /tmp/atys_paper.sock |
core/orders/ |
Order sim (P&L sim) + order router (shadow vs broker) |
core/data/ |
db_reader, db_writer, cascade TF — accès SQLite |
core/persistence/ |
Persistance session live (positions, trades, state) |
brokers/tws/ |
Adapter IBKR TWS (TCP binaire v198, reader thread + watchdog) |
atys_web/ |
Dashboard local FastAPI/Jinja/HTMX (port 8765, LAN-only) — cf atys_web/README.md |
tools/ |
Scripts Python (fetch data, tune, ibkr_probe) + atys-prod.sh |
configs/ |
Configs TOML backtest + live + tune |
data/ |
atys_market.db (160M bars) + atys_backtests.db (master tune, gitignore) |
reports/ |
live_paper.db session + outputs backtest scratch |
tests/ |
test_core.c (640+ verts) + goldens SHA |
docs/ |
Specs, plans, recherche, roadmap + tune.md, strategies.md, indicators.md |
Stratégies & indicateurs
- 21 stratégies en vtable dans
core/strategy/— groupées par famille (trend, mean-rev, breakout, carry, stat-arb, session, volatility). Catalogue détaillé :docs/strategies.md. - 27 indicateurs en composition directe dans
core/indicators/— 4 buckets (trend, vol, momentum, structure). Catalogue :docs/indicators.md. - 1 broker live supporté :
tws(IBKR TWS API binaire via IB Gateway Docker). - Timeframes : M1, M5, M15, M30, H1, H4, D1, W1 (aggregator unifié).
Tests & qualité
Pyramide de tests à 4 couches (suite broker 2026-04-24, cf docs/superpowers/specs/2026-04-24-broker-test-suite-design.md) :
| Couche | Contenu | Target | Déterministe |
|---|---|---|---|
| L0 | Core modules (test_core, test_tune*, test_db_*, test_tf_cascade) |
make test |
✅ |
| L1 | Broker handlers sur fixtures binaires IBKR (tests/c/test_broker_handlers.c + tests/fixtures/tws/*.bin) |
make test-broker-handlers |
✅ |
| L2 | Scenarios broker via mock TWS in-process (tests/c/test_broker_mock_tws.c + tests/c/mock_tws/) |
make test-broker-mock-tws |
✅ |
| L3 | E2E contre IBC paper Docker (tests/py/e2e/) — infra à venir |
make test-e2e |
❌ (flaky toléré) |
| L4 | Audit JSONL post-session (tools/broker-audit.py) |
CLI manuelle | n/a |
make test # L0 + L1 + L2 — déterministe, CI-friendly, <1 min
make test-golden # 2 goldens SHA figés (full portfolio + H1 isolé)
make debug # rebuild avec ASan + UBSan
# L3 (E2E) nécessite IBC UP : ./tools/atys-prod.sh ibc-start puis make test-e2e (roadmap)
# L4 : python3 tools/broker-audit.py --input logs/broker_orders.jsonl --output reports/audit.md
- Framework tests : maison, macros
TEST()/CHECK()danstest_core.c,test_broker_handlers.c,test_broker_mock_tws.c. - Principe TDD : les tests dictent, le code suit. Un test qui FAIL → on corrige le code broker, jamais le test. Les tests L1 dont les fixtures nécessitent un upgrade IBKR (Margin + Forex permission) sont explicitement SKIP avec pointeur vers
tests/fixtures/tws/TODO_pending_capture.md. - Golden 1 (
tests/golden.sha256) : backtest portfolio complet 2022-2026. - Golden 2 (
tests/golden_h1.sha256) : H1 isolé. - Bench release : ~307 k bars/s sur Ryzen 9 (backtest bulk).
- Build flags :
-Wall -Wextra -Werror -std=c11 -O3 -march=nativeen release,-fsanitize=address,undefineden test. - Instrumentation L4 : flag
[broker].jsonl_log_pathdans la config → chaque place_order / order_status / execution_data / err / cancel produit une ligne JSONL structurée. Zero-cost si flag vide. Consommé partools/broker-audit.pypour stats latence / rejects / slippage / orphans.
Roadmap & état
État au 2026-04-25 (cf docs/ROADMAP.md pour le détail) :
- ✅ Ce qui marche : live paper IBKR (5 paires forex Connors), backtest DB
SQLite 160M bars, tune anti-overfit (CPCV + DSR + walk-forward), watchdog
broker avec reconnect auto, persistance session live SQLite (D1), cascade
time-based + per-slot gap policy (skip/ffill), dashboard web
atys_web/(Sprint G mergé32e4de1) : observer live + commandes + lancer tunes + master DB explorer + candles viewer avec markers. - 🟡 En cours : Sprint G+1 polish (12 follow-ups identifiés par code review, cf ROADMAP).
- 📍 Prochaines étapes (🔥 hot dans
docs/ROADMAP.md) : Sprint F transition backtest↔live, valider 1er signal Connors paper, reprendre tune Connors 13 paires, 2e username IBKR (attente validation).
Dépendances
libcurl(EODHD / Ntfy HTTP)libsqlite3(DB market + persistance live)pthread(reader TWS + worker pool tune)libm(math)
Stack externe : IB Gateway Docker (via tools/atys-prod.sh ibc-start), EODHD
API (abonnement Extended), FRED (taux monétaires forex carry).
Tools & scripts
Outils Python et shell sous tools/. Convention : tout est lançable depuis
la racine du repo, scripts auto-documentés via --help.
Données (ingestion)
tools/fetch_eodhd.py— pull EODHD historical → DB SQLite (API principale)tools/fetch_yahoo.py— pull Yahoo finance (cross-check EODHD)tools/fetch_fred_rates.py— pull FRED rates pour FX carry signalstools/db_writer.py— wrapper SQLite writes utilisé par les fetchers
Cascade & timeframes
tools/tf_cascade.py— agrège M1 → M5/M15/M30/H1/H4/D1/W1tools/cascade_rebuild.py— rebuild la cascade complète sur tous instruments
Validation & parité
tools/parity_cascade_eodhd.py— valide cascade Atys vs EODHD natiftools/parity_live_eodhd.py— valide aggregator live ↔ EODHD M1tools/tests/cross_check_indicators.py— compare indicators C ↔ Pythontools/tests/invariants.py— invariants des stats anti-overfittools/tests/monte_carlo_shuffle.py— invariance shuffle (sanity check)tools/tests/ref_indicators.py— ref Python pourcross_check_indicators
Tune (grid-search anti-overfit)
tools/tune/tune_atys.py— orchestration (CPCV + DSR + walk-forward)tools/tune/post_phase.py— post-traitement (PBO + neighborhood + hierarchy)- Modules sous
tools/tune/(config,master_db,manifest,metrics,regime,sizing,stats/) — librairie partagée - Détail complet :
docs/tune.md
Broker / IBKR
tools/ibkr_probe.py— probe historical paper vs livetools/ibkr_probe_diff.py— diff CSV paper ↔ livetools/ibkr_probe.sh— orchestre paper + live + difftools/broker-audit.py— analyse JSONL broker logs (latence, rejects, slippage)tools/atys-prod.sh— ops Docker (IB Gateway start/stop, atys-web)
Helpers
tools/allocation.py— allocations pool daily/swing dynamiquestools/compute_carry_signals.py— pré-compute signaux FX carrytools/walk_forward.py+walk_forward_grid.py— walk-forwardtools/make_test_configs.py— régénèreconfigs/*.tomldepuis templatetools/benchmark.sh— bench backtest perf
Binaires C (compilés via make)
build/atys— entrée principale (sous-commandesbacktest/live)build/atys-ctl— client socket pour piloter un live runnerbuild/atys-fetch-history— fetch IBKR historical bars vers DB
Licence & contributeurs
Projet personnel, non publiquement licencié. Auteur : Tim.