71eab9a253c2aecb2e26864b602aee5ee54706fa
Two `gpu_backtest_validation` tests were failing with bit-identical
deterministic values for 2+ months: `test_always_long_on_downtrend`
(expected negative PnL, got +0.00023627281) and
`test_multiple_windows_produce_results` (uptrend < downtrend instead
of > ).
Root cause: SP21 Phase 8.5 (2026-05-12) wired the factored 4-3-3-3
action decoder into the eval (`backtest_state_gather` + env_step),
but the test's hardcoded `constant_action_model(4, ...)` integer
literal wasn't migrated. Pre-Phase-8.5 the eval used a flat
4-action enum where `4` reportedly meant Long100; the factored
decoder now interprets `4` as:
decode_direction_4b(4, b1=3, b2=3, b3=3) = 4 / 27 = 0 = DIR_SHORT
decode_magnitude_4b(4, b1=3, b2=3, b3=3) = (4/9) % 3 = 0 = MAG_QUARTER
So the test was running Short-Quarter (-0.25 position) on the trend
fixtures. On random-walk synthetic prices with drift ±0.001 vs σ=0.01
noise per bar, the 24-step eval window has S/N ≈ 0.49 — specific
seeds can produce net-against-drift trajectories, making the actual
short-quarter PnL small but deterministic, with sign flipped relative
to test intent.
Fix: change `constant_action_model(4, ...)` → `constant_action_model(72, ...)`
in the 2 failing tests. Action 72 = dir=LONG (2) * 27 + mag=FULL (2)
* 9 + 0 + 0 — the actual "Long100" under 4-3-3-3 factoring. Both
tests now pass; no regressions on the 4 previously-passing tests.
Verification
────────────
- gpu_backtest_validation pre-fix: 4 passed, 2 failed
- gpu_backtest_validation post-fix: 6 passed, 0 failed
Out of scope for this commit (follow-up audit needed)
─────────────────────────────────────────────────────
Three other tests in the same file have the same stale `4` constant
with misleading "Always Long100" comments, but currently pass
incidentally:
- `test_always_long_on_uptrend` (line 218): asserts `total_pnl > 0`.
Currently passes BY ACCIDENT — action=4 (Short-Quarter) on seed-42's
net-down 24-bar trajectory produces +PnL, satisfying the assertion
for the wrong reason. Fixing to action=72 alone would break this
test (true Long100 on seed-42's net-down trajectory is negative);
the test needs BOTH the action fix AND a seed/window change so the
"uptrend" trajectory actually trends up over the eval window
(e.g., 250-bar window or drift=0.01).
- `test_extended_metrics_populated` (line 465) and
`test_active_model_records_trades` (line 524): assertions are
direction-agnostic (VaR/CVaR/Calmar/Omega NaN-check + CVaR≤VaR;
total_trades > 0 + win_rate range), so they pass legitimately
under whatever-direction action=4 produces. The "Long100" comments
are misleading but the tests are correctly covering their stated
behavior.
A separate audit-and-fix pass should address all three at once:
either correct the action constants + adjust seed/window to ensure
each test's named trajectory direction is statistically reliable,
or introduce a named constant (e.g., LONG100_ACTION) and helper to
prevent the same drift recurring.
Refs
────
- SP21 T2.2 Phase 8.5 commit 5694eb4df: "wire factored-action branch
sizes into closure-based eval (atomic)"
- crates/ml/src/cuda_pipeline/trade_physics.cuh: `decode_direction_4b`,
`decode_magnitude_4b` — canonical factored action decoders
- crates/ml/src/cuda_pipeline/gpu_backtest_evaluator.rs:189:
`DqnBacktestConfig::from_network_dims` — sets branch_sizes (4,3,3,3)
Co-Authored-By: Claude Opus 4.7 (1M context) <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%