37c3a8f4d72ed1c58fe6e2972e98f902cf1c1bc7
Foundation for replacing the static `--auto-horizon-weights` formula (`min(1, K/h)`) with a signal-driven per-horizon gradient scaler. Per `feedback_isv_for_adaptive_bounds.md`: adaptive bounds live in ISV, not hardcoded constants. Per `pearl_adam_normalizes_loss_weights.md`: Adam normalizes per-loss weight lifts (SP13 saw 13× aux_w produce only 0.6%/epoch divergence), so the effective lever is scaling the GRADIENT into the shared trunk, not the BCE coefficient. This commit sets up the EMA + lambda infrastructure; Phase 3 (wiring lambda into heads_bwd to actually scale the trunk gradient) is gated on the 3-fold CV results fromeb51c0f9c. Phase 1 — BCE kernel emits per-horizon UNWEIGHTED mean BCE: cuda/bce_loss_multi_horizon.cu: - New output buffer `loss_per_horizon[N_HORIZONS=5]`. - Per-horizon shared-mem accumulators (sloss_h, svalid_h) with block tree-reduce — no atomicAdd, per `feedback_no_atomicadd.md`. - Hardcoded N_HORIZONS_BCE=5; total shared-mem usage ~13 KiB (comfortable under any SM smem limit). - The aggregate `loss_out` is still the externally-weighted mean callers use for reporting; the new buffer is the UNWEIGHTED signal an EMA layer needs. Phase 2 — EMA + lambda kernel: cuda/horizon_lambda.cu (new): - Single-thread kernel (5 horizons, fixed-size loop — trivial). - First-observation bootstrap via sentinel = 0 per `pearl_first_observation_bootstrap.md`; replaces directly when `loss_ema_h <= 0` (safer than `== 0` under --use_fast_math). - Fixed α = 0.1 EMA for now; Wiener-optimal α follow-up flagged (`pearl_wiener_optimal_adaptive_alpha.md`). - lambda_h = clamp(loss_ema_h / mean(loss_ema), 0.5, 2.0). - Ratio gives natural "under-trained → boost" signal. - Clamp prevents winner-take-all per `pearl_controller_amplifies_dominant_magnitude_trap.md` and bounded-modifier safety per `pearl_audit_unboundedness_for_implicit_asymmetry.md`. Trainer wiring (trainer/perception.rs): - 3 new fields: `loss_per_horizon_d`, `loss_ema_d`, `lambda_d` (all 5-element f32 CudaSlices; pre-allocated, zero-initialised). - Cached `horizon_lambda_fn` + module handle per the `BiasKernels`-style pattern (no per-call cuModuleLoadData). - BCE callsite (train + eval paths) updated to pass `loss_per_horizon_d`. - `dispatch_train_step` launches `horizon_ema_and_lambda` right after BCE, BEFORE the K-loop backward. Inside the captured graph; per-step launch overhead is ~1 µs. - `loss_ema_snapshot()` + `lambda_snapshot()` test-only accessors (mapped-pinned readback, not for hot path) for diagnostics. Smoke test — `horizon_ema_and_lambda_track_after_training`: - Verifies pre-step EMA + lambda are zero (sentinel). - After 5 training steps: loss_ema = [0.59, 0.66, 0.45, 0.62, 0.50] — finite + positive. lambda = [1.05, 1.16, 0.80, 1.10, 0.89] — mean ≈ 1.0, all inside the [0.5, 2.0] clamp envelope. - Lower per-horizon BCE → lower lambda (de-emphasize); higher BCE → higher lambda (boost). Exactly the ISV semantics we want. Validation: 6 perception_overfit tests pass, synthetic overfit still shrinks (0.33 → 0.0006), 26 ml-alpha lib + 23 integration tests green. lambda_d is computed every step but NOT YET CONSUMED by heads_bwd; training behavior is bit-identical to3a196382f. Phase 3 (consume lambda_d in heads_bwd_batched to scale the per-horizon gradient into the trunk) follows once CV confirms the foundation is stable. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Foxhunt
Production HFT trading system in Rust.
Architecture
The workspace contains 32 crates organized as follows:
Core Libraries (16)
| Crate | Purpose |
|---|---|
trading_engine |
Order processing, FIX 4.4, IB TWS, SIMD, RDTSC timing |
risk |
VaR, Kelly, circuit breakers, kill switches, compliance |
risk-data |
Risk data types and shared structures |
trading-data |
Trading data types |
ml |
DQN Rainbow, PPO, TFT, Mamba2, ensemble inference |
ml-data |
ML data types and feature definitions |
data |
Market data ingestion and storage |
backtesting |
Replay engine, strategy tester |
adaptive-strategy |
Ensemble execution, microstructure analysis |
common |
Shared types, resilience, error handling |
storage |
S3 and local model storage |
model_loader |
Model serialization and loading |
market-data |
Market data feed handlers |
database |
PostgreSQL access layer (SQLx) |
config |
Configuration management |
tli |
CLI commands and tooling |
Services (8)
| Service | Purpose |
|---|---|
backtesting_service |
gRPC backtesting service |
broker_gateway_service |
FIX routing, broker connectivity |
trading_service |
Core trading operations |
ml_training_service |
Model training orchestration |
data_acquisition_service |
Market data acquisition |
trading_agent_service |
Autonomous trading agents |
api_gateway |
gRPC API gateway with auth |
web-gateway |
Axum REST + WebSocket gateway |
Frontend
web-dashboard/ -- React 19 + TypeScript + Vite + TradingView charts.
Building
# Check compilation (no PostgreSQL required)
SQLX_OFFLINE=true cargo check --workspace
# Run tests for a specific crate
SQLX_OFFLINE=true cargo test -p <crate> --lib
# Clippy
SQLX_OFFLINE=true cargo clippy --workspace
ML Models
Four production model architectures on Candle v0.9.1 with CUDA:
- DQN Rainbow -- Deep Q-Network with prioritized replay, dueling heads, noisy nets
- PPO -- Proximal Policy Optimization with GAE and LSTM policies
- TFT -- Temporal Fusion Transformer for multi-horizon forecasting
- Mamba2 -- State space model for sequence prediction
Each model has a standalone trainer and a UnifiedTrainable adapter for the hyperopt pipeline.
Infrastructure
- Git: Gitea at
git.fxhnt.ai(Tailscale-only), Scaleway DEV1-S - Observability: OpenTelemetry OTLP (env
OTEL_EXPORTER_OTLP_ENDPOINT) - Database: PostgreSQL with SQLx offline mode for CI
License
Proprietary. All rights reserved.
Description
Languages
Rust
88.2%
Cuda
7.7%
Python
1.3%
Shell
1.1%
PLpgSQL
0.8%
Other
0.8%