Commit Graph

1059 Commits

Author SHA1 Message Date
jgrusewski
eef58e5c6a feat(ml): multi-GPU config + NCCL gradient sync for data parallelism
- MultiGpuConfig::detect() probes CUDA ordinals 0..8, returns None
  on single-GPU/CPU setups
- shard_indices() splits dataset across devices with remainder handling
- NcclGradientSync (behind `nccl` feature flag) for all-reduce averaging
- Feature: `nccl = ["cuda"]` — requires NCCL library on system

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
a8c4473812 feat(ml): BF16 benchmark variants for DQN and TFT
Add test configs validating BF16 mixed precision setup:
- DQN: MixedPrecisionConfig::for_ampere() (BF16, loss_scale=1.0)
- TFT: mixed_precision=true + use_mixed_precision=true

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
1a6834fff2 feat(ml): parallel ensemble inference via rayon — sub-ms multi-model predictions
Replace sequential for-loop over ModelInferenceAdapters with rayon
par_iter(). Each adapter's predict() runs on a separate thread,
then results are aggregated sequentially (fast arithmetic).

ModelInferenceAdapter: Send + Sync makes this safe for parallel execution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
33a0656248 feat(ml): wire EpochPrefetcher + GpuBufferPool into DQN trainer
- Add prefetcher field (Option<EpochPrefetcher>) for background disk I/O
  during walk-forward fold transitions
- Add buffer_pool field (Option<GpuBufferPool>) auto-initialized on CUDA
  with pre-allocated staging buffers (100k bars, 51 features, 4 targets)
- Add set_prefetcher() and take_prefetched_data() public API methods

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
18845baf9b feat(ml): tensor core alignment for DQN/PPO hidden dims
Applies align_to_tensor_cores() (round up to multiple of 8) to hidden
dims from hyperopt. No-op for default values (already aligned), but
protects against non-aligned values discovered during hyperopt search.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
c48d98525a feat(ml): Mamba2 dynamic GPU validation — replaces hardcoded 4GB constraints
Uses HardwareBudget::detect() to scale VRAM limits and batch size caps
dynamically based on detected GPU. Same code now works on RTX 3050 Ti
(4GB), L40S (48GB), and H100 (80GB) without manual tuning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
92771539a7 fix(ml): TLOB eval detach + real gradient/parameter norm — remove stubs
- Detach predictions and loss in validate_epoch() to save VRAM
- Replace clip_gradients() stub with real norm check + warning
- Replace calculate_gradient_norm() stub (Ok(0.001)) with L2 parameter
  norm computed from VarMap

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
d974b32aaf fix(ml): Liquid eval detach — prevent gradient graph leak in validation
Adds .detach() to forward pass output and loss in evaluate() to prevent
gradient graph accumulation across the entire validation set, saving VRAM.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
98e698118b feat(ml): wire PPO accumulation_steps from hyperparams to PPOConfig
Exposes gradient_accumulation_steps in PpoHyperparameters so hyperopt
and training binaries can configure effective batch scaling. The actual
accumulation logic already existed in PPO::update_mlp().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
6deaf86643 feat(ml): PPO mixed precision auto-detection — BF16 on A100/H100
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
5d390037e5 feat(ml): wire train_baseline_rl PPO to PpoTrainer — enables GPU optimizations
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:31:38 +01:00
jgrusewski
95dfd4ad1a feat(ml): wire train_baseline_rl DQN to DQNTrainer — enables all GPU optimizations
Replace raw DQN::new() + manual training loop in the walk-forward
training binary with DQNTrainer, which automatically activates:
- Mixed precision (BF16/F16 auto-detected from GPU)
- Dynamic batch sizing (AutoBatchSizer + HardwareBudget)
- Gradient accumulation
- Full Rainbow DQN (PER, dueling, C51, noisy nets, n-step)
- Regime-conditional Q-networks
- Portfolio tracking, Kelly sizing, entropy regularization

The walk-forward fold structure (data loading, feature extraction,
window generation, normalization) stays in the binary — only per-fold
training delegates to DQNTrainer::train_with_preloaded_data().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:27:10 +01:00
jgrusewski
632c780c00 feat(ml): GPU max performance phase 2 — C51 re-enabled, buffer pooling, kernel sizing
Phase 2 GPU optimizations for L4→H100 scaling:

- Re-enable C51 distributional RL (BUG #36 scatter_add gradient flow VERIFIED)
- Add GpuBufferPool for zero-alloc walk-forward fold transitions
- Add DoubleBufferedLoader for CUDA stream overlap during fold swaps
- Add EpochPrefetcher for background data preparation (overlaps I/O with GPU)
- Add optimal_launch_dims() for dynamic CUDA kernel block/grid sizing (32→256)
- Wire real INT8 quantization into QuantizedTFT via quantize_varmap_parallel()
- Wire DoubleBufferedLoader + EpochPrefetcher into DQN trainer
- Wire optimal_launch_dims into DQN + PPO GPU experience collectors
- Fix flaky hot_swap latency test (100μs→2ms threshold for debug builds)
- Fix missing mixed_precision field in trading_service PPOConfig

Full Rainbow DQN now enabled by default (all 6 components + IQN + CQL).
2,437 ml tests pass, 0 failures. Workspace compiles clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:25:36 +01:00
jgrusewski
71f2fb1ec3 feat(ml): dynamic GPU batch sizing + tensor core alignment utility
- DQN: Scale UP batch_size on large GPUs (HardwareBudget::detect), raise static cap 4096→8192
- PPO: Scale UP batch_size from conservative 64 when GPU supports more
- Add align_to_tensor_cores() utility (round up to multiple of 8)
- Hidden dim_base rounding already aligned (nearest 256 = multiples of 8)
- Tests: 2422 pass, 0 failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 21:25:36 +01:00
jgrusewski
4a3f387860 fix(ml): Arc<Vec<OHLCVBar>> → Arc<[OHLCVBar]> in hyperopt adapters
Fixes clippy::rc_buffer lint in 8 hyperopt adapter files.
Arc<[T]> avoids double indirection vs Arc<Vec<T>>.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:59:21 +01:00
jgrusewski
89f6c0e914 refactor: delete unused compliance scaffolding (-34K lines)
Remove entire trading_engine/src/compliance/ directory (9 files, 16,068 LOC)
and 18 associated test files (18,069 LOC). Comprehensive audit confirmed
zero external callers for all types (ISO 27001, SOX, MiFID II, best
execution, automated reporting). Remove unused cron dependency.

Independent compliance modules in risk/ and risk-data/ are preserved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:33:25 +01:00
jgrusewski
c2118b3073 refactor: split common/types.rs (4909 LOC) into 10 focused modules
Split god file into: aliases.rs, domain.rs, events.rs, identifiers.rs,
market_data.rs, market.rs, service.rs, trading_enums.rs, type_error.rs.
Re-exports via mod.rs maintain backward compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:32:52 +01:00
jgrusewski
7a602274cd refactor: consolidate RetryConfig to common::resilience
The storage crate had its own RetryConfig struct (max_attempts,
initial_delay, max_delay, backoff_multiplier) duplicating
common::resilience::retry::RetryConfig.

Added backoff_multiplier field to common's RetryConfig and updated
storage to re-export and use common's version with its field names
(max_retries, base_delay). Updated all storage tests accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:45:59 +01:00
jgrusewski
61950e4c05 refactor: consolidate ErrorSeverity to common crate
Three duplicate ErrorSeverity enums (data/error.rs, data/validation.rs,
database/error.rs) with variants Low/Medium/High/Critical now use the
canonical definition in common::error::ErrorSeverity.

Extended common's ErrorSeverity with Low, Medium, High variants (alongside
existing Debug, Info, Warn, Error, Critical) and added PartialOrd/Ord derives
so both severity models coexist in a single type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:39:54 +01:00
jgrusewski
08a0e1d036 refactor: delete duplicate RetryStrategy from trading_engine
The RetryStrategy enum in trading_engine/src/types/error.rs was an exact
duplicate of common::error::RetryStrategy with zero callers in the crate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:33:10 +01:00
jgrusewski
378438f9a1 Merge branch 'feature/ml-inference-cleanup' 2026-03-01 19:09:28 +01:00
jgrusewski
e9177095b7 fix(ml): use named generic to satisfy impl_trait_in_params lint
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:07:24 +01:00
jgrusewski
4eb710785f feat(ml): add EnsembleModelAdapter + build_production_strategy(), harden metrics server
- Create EnsembleModelAdapter in ml::ensemble wrapping model IDs
- Add build_production_strategy() factory: 10-model ensemble with
  ProductionFeatureExtractorAdapter + graceful degradation (zero confidence
  when no checkpoints loaded)
- Wire backtesting_service to use the factory function
- Harden metrics HTTP server: 5s read timeout, 8KB request limit,
  correct Content-Type charset=utf-8

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:55:56 +01:00
jgrusewski
5401723118 refactor(common): delete MLFeatureExtractor + SimpleDQNAdapter, refactor SharedMLStrategy
- Delete MLFeatureExtractor (1,294 lines) and SimpleDQNAdapter (235 lines)
- Delete 830 lines of inline tests for deleted types
- Remove legacy_feature_extractor field from SharedMLStrategy
- Replace new() and new_with_production_extractor() with new(extractor, models, threshold)
- Single constructor accepts injected models via Vec<Box<dyn MLModelAdapter>>
- Update all callers: backtesting_service, 2 integration tests, 2 trading_service tests
- Fix doc comments referencing MLFeatureExtractor
- Fix feature count test: real extractor produces 51 features, not 225

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:47:32 +01:00
jgrusewski
680c12d2c0 refactor: delete 4,800 lines of dead ML code and remove MLFeatureExtractor dependency
- Delete push_metrics.rs (Pushgateway client, zero consumers)
- Delete 5 legacy test/bench files for MLFeatureExtractor + SimpleDQNAdapter
- Remove MLFeatureExtractor from trading_agent_service, use direct bar scoring
- Remove with_feature_extractor() method and Arc<MLFeatureExtractor> parameter
- Remove bench target from common/Cargo.toml

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:29:43 +01:00
jgrusewski
ed1a9fa59d feat(ml): wire dead GPU optimizations — data preloading + PPO mixed precision forward
Quality audit found 2 dead code paths in the GPU optimization commit:

1. Data caching: preload_data() was defined on all 10 hyperopt adapters
   but never called. Now wired in both hyperopt binaries (RL + supervised)
   before the trial loop. Each model preloads training data once into
   Arc<Vec<...>>, eliminating per-trial disk I/O.

2. PPO mixed precision: config.mixed_precision was stored but never used
   in forward passes. Added forward_mixed() to PolicyNetwork and
   ValueNetwork (same BF16/FP16 pattern as DQN's NetworkLayers). Stored
   on network structs and auto-applied via forward(). Wired in
   PPO::with_device() for MLP networks.

Also fixes missing mixed_precision field in 2 test files and
trading_service PPOConfig literal.

5 files changed, +152/-20. 2418 tests pass, workspace compiles clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:23:03 +01:00
jgrusewski
b91fa43b32 Merge branch 'worktree-gpu-max-performance'
# Conflicts:
#	crates/ml/examples/hyperopt_baseline_rl.rs
2026-03-01 18:00:10 +01:00
jgrusewski
2b2ff4ffa5 feat(ml): maximize GPU utilization — BF16 mixed precision, dynamic sizing, sync reduction
Wire BF16/FP16 mixed precision end-to-end for DQN and PPO with auto-detection
from GPU name (Ampere+ → BF16, Volta/Turing → FP16). Add hidden_dim_base to
hyperopt and wire through training/eval binaries. Reduce GPU sync points: make
DQN NaN checks periodic (every 100 steps), replace PPO GAE GPU round-trip with
pure CPU implementation. Cache training data across hyperopt trials for all 10
models via Arc. Batch DQN experience storage (128x fewer lock acquisitions).
Correct VRAM constants and batch bounds for all 9 supervised model adapters.

28 files changed, +1207/-208 lines. 2418 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:54:25 +01:00
jgrusewski
3da361b5b8 fix(common): resolve all clippy errors in test targets
- Fix 36 manual_range_contains: x >= lo && x <= hi → (lo..=hi).contains(&x)
- Fix 10 useless_vec: vec![...] → [...] where array suffices
- Fix 10 unused variables: for i in → for _ in
- Fix 6 missing .unwrap() on Result-returning constructors
- Fix 4 float_cmp: wrap in .abs() for epsilon comparisons
- Fix 2 assertions_on_constants: remove assert!(true)
- Fix 2 collapsible_if: merge nested ifs with &&
- Fix 1 clamp pattern: .max().min() → .clamp()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:02:50 +01:00
jgrusewski
7a01618e86 fix(infra): upgrade OpenTelemetry 0.27→0.31 to align tonic versions, fix DCGM scheduling
OTLP fix: opentelemetry-otlp 0.27 bundled tonic 0.12 while the workspace
uses tonic 0.14, making with_channel() impossible (type mismatch). Upgrading
to otel-otlp 0.31 aligns both on tonic 0.14, enabling explicit Channel
construction that respects http:// scheme (no spurious TLS negotiation).

API migrations (otel 0.27→0.31):
- TracerProvider → SdkTracerProvider
- with_batch_exporter(exporter, runtime) → with_batch_exporter(exporter)
- Resource::new(vec![...]) → Resource::builder().with_service_name().build()
- global::shutdown_tracer_provider() removed (Drop-based shutdown)
- opentelemetry-otlp feature "tonic" → "grpc-tonic"

DCGM fix: remove runtimeClassName: nvidia from DaemonSet — Scaleway Kapsule
GPU pools use nvidia runtime as default containerd handler. The RuntimeClass
CRD is only created by the full GPU Operator, not the device plugin alone.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:31:22 +01:00
jgrusewski
a86ec4f6d1 fix(rl): PPO NaN detection every mini-batch, delete dead DQN clipping code
PPO was only checking for NaN losses every 10th epoch, allowing NaN
to propagate for up to 9 epochs and corrupt model weights before
detection. Now checks every mini-batch in both MLP and LSTM paths.

Delete three dead gradient clipping methods from DQN agent:
- compute_gradients_and_clip (never called, hardcoded max_norm=1.0)
- clip_gradients (returns error, deprecated)
- clip_gradients_map (computes clip factor but never applies it)

Active DQN training uses AdamOptimizer::backward_step_with_monitoring
which correctly delegates to gradient_utils::clip_grad_norm.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:04:00 +01:00
jgrusewski
7744becdd5 feat(training): move metrics to common::metrics, fix all clippy errors
Move Prometheus training metrics from example-local baseline_common/
to common::metrics::{server,training_metrics} following the existing
grpc_metrics.rs pattern. Fix 29 let_underscore_must_use clippy errors
in push_metrics.rs, 3 shadow lint errors in training binaries, and
demote gradient clipping log from warn to debug.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:56:43 +01:00
jgrusewski
097a8a1819 feat(training): instrument hyperopt binaries with Prometheus metrics
Add metrics server lifecycle (init, port 9094, active_workers) to both
hyperopt_baseline_rl and hyperopt_baseline_supervised. All 18 metrics
are registered and exposed; inner PSO trial loops can be instrumented
incrementally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:04:30 +01:00
jgrusewski
cfafc0d13e feat(training): add Prometheus metrics export to training binaries
Create shared baseline_common/metrics.rs module that registers all 18
dashboard-expected metrics (11 gauges, 5 counters, 2 histograms) and
spawns a lightweight HTTP metrics server on port 9094.

Instrument train_baseline_supervised and train_baseline_rl with:
- Epoch progress, training/validation loss gauges
- Checkpoint save timing, size, and failure counters
- NaN/gradient explosion detection counters
- Data loading latency histograms
- Active workers lifecycle (1 on start, 0 on exit)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:01:33 +01:00
jgrusewski
74a572a5c4 feat(infra): enable MinIO TLS with self-signed CA for in-cluster HTTPS
Switch all MinIO communication from HTTP to HTTPS across the entire stack:
- MinIO deployment: mount TLS secret, tcpSocket probes, HTTPS init-buckets
- 11 service YAMLs: HTTPS rclone endpoint + CA cert volume mount
- Training job template + train.sh: HTTPS for fetch-binaries and uploader
- CI pipeline (.gitlab-ci.yml): all 7 rclone exports use HTTPS + CA cert
- GitLab runner values: minio-ca-cert ConfigMap volume for CI pods
- Rust: CA cert loading via MINIO_CA_CERT_PATH in training_uploader,
  storage backend, data_acquisition uploader, and k8s_dispatcher
- Cert generation script (infra/scripts/generate-minio-tls.sh)

Fixes training uploader S3 upload failures caused by with_allow_http(false)
connecting to an HTTP endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:56:06 +01:00
jgrusewski
9b85b9efd5 feat(ml): add Pushgateway metrics client for training jobs
Training jobs are short-lived K8s Jobs that can't be reliably scraped
by Prometheus. This adds a TrainingMetricsPusher that pushes epoch-level
metrics (loss, accuracy, throughput, gradient health, checkpoints) to
the Pushgateway so they persist for Prometheus to scrape.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:36:05 +01:00
jgrusewski
a958582eaa feat(common): add gRPC metrics Tower layer for automatic instrumentation
Add a reusable GrpcMetricsLayer that can be applied to any tonic server
via Server::builder().layer() to automatically emit three Prometheus
metric families for every gRPC handler: started_total, handled_total
(with status code), and handling_seconds histogram.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:23:36 +01:00
jgrusewski
f0c653ab63 feat(web-gateway): add Prometheus metrics server on port 9098
Adds a dedicated Prometheus metrics endpoint on port 9098 (configurable
via METRICS_PORT env var) with counters for HTTP requests, histograms for
request duration, gauges for uptime and active WebSocket connections, and
counters for WebSocket messages. Metrics are registered using once_cell
Lazy statics with abort-on-failure to satisfy the crate's deny(unwrap)
lint policy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 02:14:08 +01:00
jgrusewski
561e2bd299 fix: repair broken use statement in ml/deployment/endpoints.rs
The #[instrument] import was incorrectly inserted inside a `use super {}`
block by the previous commit, causing syntax errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:55:51 +01:00
jgrusewski
2ef89ceb02 feat(observability): wire init_observability into all 5 remaining services
Replace direct tracing_subscriber::fmt::init() calls with the unified
common::observability::init_observability() in api_gateway, web-gateway,
data_acquisition_service, broker_gateway_service, and trading_agent_service.
All 8 services now emit JSON logs + OTLP traces to Tempo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:39:29 +01:00
jgrusewski
0c7f6362d9 fix(observability): combine fmt + OTLP layers in single subscriber
Previously init_observability() called init_json_logger() (which set the
global subscriber with a fmt layer) and then init_tracing() (which only
set the global tracer provider). Because no tracing_opentelemetry::layer()
was ever added to the subscriber, #[instrument] spans never reached Tempo.

Now init_observability() builds a single Registry subscriber that
composes an EnvFilter, a JSON fmt layer, and an optional OTLP layer
(via tracing_opentelemetry). The OTLP layer gracefully degrades to None
when Tempo is unavailable, so logging always works.

Also adds build_otel_tracer() to tracing_config.rs which returns
Option<Tracer> for the caller to wrap in an OpenTelemetryLayer inside
their subscriber stack, letting the S type parameter be inferred
correctly by the compiler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:32:35 +01:00
jgrusewski
7de84bb723 fix(web-gateway): add service-to-service JWT auth for gRPC calls to api-gateway
Web-gateway routes through api-gateway for the foxhunt.tli proto, but
api-gateway requires JWT Bearer auth on all gRPC requests. This adds a
service_auth module that mints short-lived service JWTs (matching the
api-gateway's expected claims: iss, aud, roles, permissions) and injects
them into all 15 REST proxy calls and 4 gRPC stream bridges.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:01:53 +01:00
jgrusewski
1aef51f99b fix(stubs): implement 15 production stubs, fix routing, delete placeholders
Web-gateway routing:
- Point TRADING_SERVICE_URL at api-gateway (proto mismatch fix)
  Web-gateway uses foxhunt.tli.TradingService proto but was connecting
  directly to trading-service which implements trading.TradingService.
  api-gateway already proxies Subscribe* → Stream* correctly.

GitLab KAS:
- Disable gitlab_kas in appConfig to stop sidekiq NotifyGitPushWorker
  errors (KAS pod was already disabled but Rails still tried to connect)

Trading service monitoring (3 stubs → real):
- AcknowledgeAlert: real alert lookup + state mutation in shared store
- GetActiveAlerts: returns actual active alerts from in-memory store
- StreamAlerts: now persists generated alerts (capped at 1000 entries)

Trading service ML streams (2 stubs → real):
- StreamModelMetrics: emits real inference_count, error_count, latency
  per model every N seconds from the RuntimeModelInfo registry
- StreamSignalStrength: emits per-symbol signal aggregation from model
  ensemble weights and latency confidence

Backtesting service:
- stop_backtest: real CancellationToken cancellation (was no-op)
  Tokens stored per-backtest, execute_backtest wraps strategy call
  in tokio::select! for immediate cancellation

Deleted 7 empty placeholder files:
- 4 Wave D regime stubs (dynamic_stops, ensemble, performance_tracker,
  position_sizer) — comment-only files, never wired
- 2 Wave 3 feature stubs (microstructure, statistical)
- 1 PPO stub (unified_ppo.rs — empty struct definitions)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:47:31 +01:00
jgrusewski
8ee1f810e6 fix(production): resolve all runtime errors and add CI migration automation
- Add ohlcv_bars table migration (050) for trading_service prediction loop
- Fix kube-state-metrics RBAC: add admissionregistration.k8s.io and
  certificates.k8s.io API groups to suppress forbidden errors
- Fix web-gateway gRPC stream reconnect: detect Unimplemented via both
  status code and error message text (proxy may remap codes)
- Add automated migration step to CI deploy pipeline with tracking table
  (_applied_migrations) so migrations are applied before service rollouts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:26:43 +01:00
jgrusewski
6b94045bcd fix(observability): switch to containerd stdout logging, fix stream retry
- Disable file logging in init_observability — use console-only (stdout).
  Containerd captures stdout, Promtail ships to Loki. Eliminates
  "Failed to create log directory: Permission denied" errors on 3 services.
- Remove LOG_DIR env vars and /app/logs emptyDir volumes from 5 deployments.
- Add OTEL_EXPORTER_OTLP_ENDPOINT=tempo to 5 services that were missing it
  (api-gateway, web-gateway, data-acquisition, trading-agent, broker-gateway).
- Make OTLP tracing init non-fatal — services degrade gracefully if Tempo is
  unavailable instead of failing entire observability stack.
- Stop web-gateway gRPC stream retry on Unimplemented status. When trading-service
  doesn't implement streaming endpoints, log once and stop instead of retrying
  every 60s indefinitely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:49:57 +01:00
jgrusewski
5d3efbd2cc feat(hyperopt): auto-scale PSO particles to GPU capacity
Remove artificial swarm_size cap from plan_hyperopt() that limited
concurrent trials to n_particles (default 20). Now concurrency is
purely VRAM-driven with a hardware cap of 128 threads.

optimize_parallel() auto-scales n_particles to match GPU budget:
- L4 24GB: ~65 concurrent DQN trials (was 20)
- H100 80GB: 128 concurrent DQN trials (was 20)
- CPU/small GPU: falls back to configured n_particles

max_trials scales proportionally to ensure 3+ PSO iterations
for convergence with larger swarms.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:12:11 +01:00
jgrusewski
c0b47d6657 feat(hyperopt): cap parallel threads by VRAM budget in hyperopt binary
Auto-detect now considers both CPU count and GPU VRAM when choosing
concurrent trial count. Prevents OOM on smaller GPUs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:47:33 +01:00
jgrusewski
4cc15d4496 feat(hyperopt): VRAM-aware parallel trial concurrency with OOM protection
optimize_parallel() now uses HardwareBudget::plan_hyperopt() to compute
max concurrent trials based on model VRAM footprint. Includes ramp-up
(start at half concurrency), VRAM watchdog (check free memory before
spawning), and graceful degradation to sequential.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:44:39 +01:00
jgrusewski
25141c4b90 feat(hyperopt): add HyperoptStrategy and HardwareBudget::plan_hyperopt()
Computes optimal (concurrency, batch_size_bounds) based on model memory
footprint vs detected GPU VRAM. Scales from CPU-only (sequential) through
H100 80GB (full swarm parallel). 20% safety margin for CUDA allocator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:34:24 +01:00
jgrusewski
ad8ab79f5e fix(hyperopt): remove hardcoded batch_size=160 clamp from DQN adapter
PSO now controls batch_size within [64, 4096] range. HardwareBudget
adjusts upper bound based on detected VRAM. The .min(160.0) clamp was
silently overriding PSO's choices on any GPU larger than 3050 Ti.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:30:06 +01:00