Wire the ctrader-openapi client behind the BrokerInterface trait for
live order routing, position queries, and execution streaming.
Feature-gated behind `icmarkets` flag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add rate limiter (50/s + 5/s historical), symbol mapper, order builders,
account queries, market data subscriptions, and high-level CTraderClient
that orchestrates the full connect/auth/symbol-load lifecycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MessageDispatcher spawns a reader task that routes responses to pending
requests by clientMsgId (UUID + oneshot channels), and broadcasts
server-pushed events (executions, spots, errors) via tokio broadcast.
Handles connection closure with pending request cleanup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HTTP OAuth2 flow (auth code exchange + refresh) via reqwest, plus
protobuf-level two-phase auth (ApplicationAuth → AccountAuth) over
the TCP connection. Error extraction from OA error responses.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CTraderConnection establishes TCP+TLS via tokio-native-tls, wraps in
framed codec, splits into shared sender + exclusive receiver, and
spawns a heartbeat task at configurable interval (default 10s).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CTraderCodec implements tokio_util Decoder+Encoder with 4-byte BE length
prefix framing. Handles partial frames, multiple frames in buffer, and
rejects oversized frames (16 MiB max). 5 unit tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Downloads 4 proto files from spotware/openapi-proto-messages (MIT license),
compiles with prost-build, and adds payload-type constants + dispatch helpers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New workspace crate for cTrader Open API client (Protobuf over TCP+TLS).
Adds CTraderConfig (environment, credentials, timeouts), CTraderError
enum covering all failure modes, and lib.rs module structure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New workspace crate for cTrader Open API client (Protobuf over TCP+TLS).
Includes CTraderConfig, CTraderEnvironment, CTraderError, and RateLimitBucket types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove 45+ AGENT_*, WAVE_*, and completion report files that were
one-time swarm deliverables with no living documentation value.
Remove reports/2025-11-16_17_hyperopt_analysis/ (55 files, code
changes already landed). Content preserved in git history.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ml_training_service: health check now validates orchestrator readiness
via AtomicBool flag instead of always returning "healthy"
- broker_gateway_service: replace hardcoded $100k account data with
explicit FAILED_PRECONDITION errors for unimplemented broker queries
- data_acquisition_service: spawn background download task instead of
leaving jobs stuck in Pending, add real health check with job counts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap Model Cards, Ensemble Panel, Training Progress in ComponentErrorBoundary
- Wrap Configuration Form in ComponentErrorBoundary
- Prevents full-page crash if individual sections throw render errors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add VALID_TOPICS whitelist to WS handler, reject unknown topic subscriptions
- Add per-connection rate limit (50 topic changes/min) and max 20 subscriptions
- Remove wildcard "*" subscription (security risk)
- Add tracing::info! audit logging to all 8 mutation handlers
- Add 30s AbortController timeout to frontend API calls
- Fix clippy: rename _claims → claims in handlers that now use it
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add validate_backtest(): strategy_name, symbols format, date range,
initial_capital checks with 6 unit tests
- Add model_type validation against known types (dqn, ppo, tft, mamba2)
with 1 integration test
- Add error banner to ConfigDashboard for failed config fetch
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace all hardcoded hex colors in chart components with CSS custom
properties (getCssVar helper), making charts respect theme changes
- Add scope="col" to all table headers (PositionsTable, OrdersTable,
BacktestingDashboard trade list)
- Connect form labels to inputs via htmlFor/id pairs (OrderForm,
BacktestingDashboard)
- Add role="alert" to validation error messages
- Add aria-label to cancel button, progressbar role to backtest progress
- Add WsManager.reconnect() method with backoff reset
- Add Reconnect button to StatusBar when WS disconnected
- Add shimmer skeleton loading states to CandlestickChart and PnLChart
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add isTokenExpired() / getTokenExpiry() JWT helpers to auth.ts
- Pre-flight token expiry check in apiFetch (60s margin)
- Graceful 401 handling: set session_expired flag before redirect
- LoginPage shows "session expired" banner when flag is set
- OrdersTable cancel button: add pending state + inline error display
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Token-bucket rate limiter (no new dependencies) with three tiers:
- Auth routes: 10 req/min, burst 5 (brute-force protection)
- Trading/read routes: 200 req/min, burst 20
- Compute routes (backtest/training/tune): 30 req/min, burst 5
Includes background cleanup task for stale entries and 7 unit tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add X-Request-Id middleware with UUID v4 generation and header propagation
- Convert 6 dashboard routes to React.lazy() with Suspense for code splitting
- Add inline validation errors to OrderForm (symbol, quantity, price)
- Add date range + symbol validation to BacktestingDashboard form
- Fix !Send future issue: use .instrument(span) instead of span.entered()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix all 98 clippy warnings (0 remaining with -D warnings)
- Add 30s default gRPC timeout on all channels via Endpoint::timeout()
- Replace readiness probe is_some() with actual gRPC health check (returns 503 when degraded)
- Add responsive Tailwind breakpoints to all 5 dashboard pages
- Add ComponentErrorBoundary for crash-prone chart components
- Log JWT validation errors at debug level instead of silently discarding
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Require JWT_SECRET >= 32 characters at startup (prevents weak secrets)
- Add SECURITY comment documenting auth.rs login as dev-only stub
- Add symbol input validation in OrderForm: uppercase, alphanumeric
with dots/hyphens/underscores, max 20 chars, visual error state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Respond to WebSocket Ping frames with Pong for keepalive detection
- Refactor WS handler to share sender between broadcast and recv tasks
via Arc<Mutex> (required for pong responses from recv task)
- Add vite production build config: source maps, manual chunk splitting
for vendor/charts/query bundles
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend:
- Fail fast on empty JWT_SECRET at startup
- Restrict CORS to explicit methods (GET/POST/PUT/DELETE/OPTIONS) and
headers (Authorization, Content-Type) instead of Any
- Add 1MB request body size limit (DefaultBodyLimit)
- Add gRPC status mappings: DeadlineExceeded->408, Cancelled->499,
AlreadyExists->409, ResourceExhausted->429, Unavailable->503
Frontend:
- Guard ErrorBoundary console.error behind import.meta.env.DEV
- Read VITE_API_URL and VITE_WS_URL from env vars with fallbacks
- Add max reconnect attempts (50) to WebSocket manager
- Tune React Query: staleTime 10s, refetchInterval 15s,
disable refetchOnWindowFocus to prevent thundering herd
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Axum 0.7 uses :id path param syntax, not {id} (which is 0.8+).
The {id} routes silently returned 404 at runtime with no compile error.
Also adds comprehensive handler tests across all 6 remaining route
modules (ml, training, backtesting, performance, config, tune) covering
auth gating, no-service errors, and body validation — 37 new tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Trading tests (7): auth gating, no-service 500, order body validation, cancel/account paths
Risk tests (5): auth gating, no-service 500, emergency stop body validation
Total: 61 tests (up from 49)
Also adds web-dashboard/.env.example for production deployment configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- EmergencyControls: aria-label on all buttons and confirmation input
- OrderForm: aria-label and aria-pressed on buy/sell toggle buttons
- DashboardLayout: aria-label on navigation
- StatusBar: aria-live on connection status, aria-hidden on decorative indicator dot
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- api.ts: intercept 401 responses, clear tokens, redirect to /login
- websocket.ts: fix backoff ordering (increase before scheduling retry)
- All dashboards: add error banners with retry buttons when API queries fail
- MLDashboard: replace hardcoded regime data with WebSocket metrics stream
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Display logged-in username (from JWT sub claim) in status bar
- Add Sign Out button that clears tokens and disconnects WebSocket
- Fix useWebSocket hook with stable empty topics reference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ErrorBoundary: catches unhandled render errors, shows recovery UI
- ProtectedRoute: redirects to /login when not authenticated
- LoginPage: username/password form that calls /api/auth/login
- All dashboard routes now require authentication
- Login page redirects to /trading on success
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ConfigDashboard: merge fetched API config over defaults instead of ignoring it
- TradingDashboard: wire OrderBook with market_data WebSocket topic
- BacktestingDashboard: wire active backtest status polling and trade results
- PerformanceDashboard: wire sortino_ratio from API, add to PerformanceMetrics type
- Remove unused Vite scaffold react.svg asset
- Set page title to "Foxhunt Trading System"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace two .expect() calls on HashMap lookups with safe if-let pattern
to comply with deny(clippy::expect_used) rule.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace redundant closures with function references in correlation.rs
- Use unwrap_or_default() instead of unwrap_or_else(T::new)
- Allow clippy::infinite_loop on intentional reconnect/heartbeat loops
- Allow clippy::empty_structs_with_brackets in generated proto code
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace placeholder futures with actual gRPC streaming client calls for
market data, order updates, risk alerts, and metrics. Each bridge
reconnects with exponential backoff on disconnection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removed error!() call that logged the full JWT token on decode failure.
This was a security risk - tokens should never appear in logs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire Mamba2 model type into the gRPC model loading match in enhanced_ml.rs.
All four model types (DQN, PPO, TFT, Mamba2) now have real loading paths.
The wildcard arm now returns invalid_argument instead of unimplemented.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace last 2 stub gRPC handlers with real implementations:
- GenerateOrders: loads allocation, generates orders via OrderGenerator with
ML signal context, contract price estimation, and dynamic stop-loss
- SubmitAgentOrders: validates orders, supports dry_run mode, persists to
agent_orders table with full metadata
Trading agent service: 15/15 endpoints now have real implementations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Status::unimplemented() with real streaming implementations:
- stream_va_r_updates: periodic VaR recalculation with change detection
- stream_risk_alerts: kill switch status + VaR breach monitoring
- stream_system_status: real-time health, CPU/memory/disk metrics
- stream_metrics: trading performance counters (connections, requests, latency)
- stream_alerts: operational alerts for health/CPU/memory/disk anomalies
All use tokio::time::interval with graceful client disconnect handling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- api_gateway: DATABASE_URL now required (was fallback to hardcoded dev password)
- broker_gateway: DATABASE_URL now required (was fallback to hardcoded dev password)
- broker_gateway: add deny(clippy::unwrap_used, clippy::expect_used) to lib.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire EnsembleCoordinator with 4 candle-backed inference adapters:
- DQN (0.30 weight), PPO (0.30), TFT (0.20), Mamba2 (0.20)
Add InferenceAdapterBridge to convert ModelInferenceAdapter→MLModel trait.
Models initialize with random weights; production checkpoints hot-loaded
via ModelRegistry shadow-buffer swap. PredictionGenerationLoop now active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace 4 stub gRPC handlers with real implementations:
- GetAllocation: re-computes allocation from latest asset selection via PortfolioAllocator
- RebalancePortfolio: compares target vs current positions, generates drift-based actions
- GetAgentPerformance: queries agent_orders for P&L, win rate, Sharpe, max drawdown
- StreamAgentActivity: sends 5-second heartbeat events until client disconnects
Trading agent service: 14/15 endpoints now have real implementations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Compute real values for 5 previously-zero risk metrics:
- current_drawdown: from unrealized PnL vs market value
- volatility: annualized std dev from execution price returns
- sharpe_ratio: excess return / volatility * sqrt(252)
- sortino_ratio: excess return / downside deviation * sqrt(252)
- position_risks: per-position VaR contribution and concentration
Wire get_position_risk() to real positions with filtering.
beta/alpha remain 0.0 (requires benchmark data integration).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace 2 stub gRPC handlers with real implementations:
- SelectAssets: scores instruments via MLFeatureExtractor, ranks with
AssetSelector (TopN/Threshold/Quantile modes), persists to DB
- GetSelectedAssets: loads latest selection from asset_selections table
Add helper methods: score_instrument, store/load_asset_selection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>