346 lines
8.7 KiB
Rust
346 lines
8.7 KiB
Rust
//! Application state -- view-model structs consumed by every cockpit.
|
|
//!
|
|
//! These are intentionally decoupled from protobuf types so the TUI layer
|
|
//! has zero coupling to the gRPC schema.
|
|
|
|
use std::collections::VecDeque;
|
|
use std::time::Instant;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Connection status
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Connection state for the gRPC streaming layer.
|
|
#[derive(Debug, Clone)]
|
|
pub enum ConnectionStatus {
|
|
Connecting,
|
|
Connected,
|
|
Reconnecting { attempt: u32 },
|
|
Error(String),
|
|
}
|
|
|
|
impl Default for ConnectionStatus {
|
|
fn default() -> Self {
|
|
Self::Connecting
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Top-level state
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Root state shared across all seven cockpit views.
|
|
pub struct AppState {
|
|
/// Active cockpit index (0..=6).
|
|
pub current_cockpit: usize,
|
|
/// Whether the help overlay is visible.
|
|
pub show_help: bool,
|
|
/// ML training sessions.
|
|
pub training_sessions: Vec<TrainingSessionData>,
|
|
/// GPU telemetry.
|
|
pub gpu: GpuData,
|
|
/// Service health statuses.
|
|
pub services: Vec<ServiceData>,
|
|
/// Open trading positions.
|
|
pub positions: Vec<PositionData>,
|
|
/// Recent trade executions (ring buffer).
|
|
pub executions: VecDeque<ExecutionData>,
|
|
/// Recent order events (ring buffer).
|
|
pub orders: VecDeque<OrderEventData>,
|
|
/// Account-level summary.
|
|
pub account: AccountData,
|
|
/// Aggregated risk metrics.
|
|
pub risk: RiskData,
|
|
/// Recent risk alerts (ring buffer).
|
|
pub risk_alerts: VecDeque<RiskAlertData>,
|
|
/// ML model statuses.
|
|
pub model_statuses: Vec<ModelStatusData>,
|
|
/// Host / cluster resource usage.
|
|
pub system_resources: SystemResources,
|
|
/// Live data-feed information.
|
|
pub data_feeds: Vec<DataFeedData>,
|
|
/// Data cache statistics.
|
|
pub data_cache: DataCacheData,
|
|
/// System alerts from monitoring (ring buffer).
|
|
pub alerts: VecDeque<AlertData>,
|
|
/// K8s pod groups (from SubscribeClusterPods).
|
|
pub pods: Vec<PodGroupData>,
|
|
/// Currently selected pod group index.
|
|
pub selected_pod_group: Option<usize>,
|
|
/// Whether the selected pod group is expanded.
|
|
pub pod_group_expanded: bool,
|
|
/// Timestamp of the last data refresh.
|
|
pub last_update: Instant,
|
|
/// gRPC connection status.
|
|
pub connection_status: ConnectionStatus,
|
|
}
|
|
|
|
impl Default for AppState {
|
|
fn default() -> Self {
|
|
Self {
|
|
current_cockpit: 0,
|
|
show_help: false,
|
|
training_sessions: Vec::new(),
|
|
gpu: GpuData::default(),
|
|
services: Vec::new(),
|
|
positions: Vec::new(),
|
|
executions: VecDeque::new(),
|
|
orders: VecDeque::new(),
|
|
account: AccountData::default(),
|
|
risk: RiskData::default(),
|
|
risk_alerts: VecDeque::new(),
|
|
model_statuses: Vec::new(),
|
|
system_resources: SystemResources::default(),
|
|
data_feeds: Vec::new(),
|
|
data_cache: DataCacheData::default(),
|
|
alerts: VecDeque::new(),
|
|
pods: Vec::new(),
|
|
selected_pod_group: None,
|
|
pod_group_expanded: false,
|
|
last_update: Instant::now(),
|
|
connection_status: ConnectionStatus::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Data sub-structs
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// A single ML training session.
|
|
pub struct TrainingSessionData {
|
|
pub model: String,
|
|
pub fold: u32,
|
|
pub epoch: u32,
|
|
pub max_epochs: u32,
|
|
pub loss: f64,
|
|
pub val_loss: f64,
|
|
pub batches_per_sec: f64,
|
|
pub sharpe: f64,
|
|
pub sortino: f64,
|
|
pub win_rate: f64,
|
|
pub max_dd: f64,
|
|
}
|
|
|
|
/// GPU telemetry snapshot.
|
|
pub struct GpuData {
|
|
pub name: String,
|
|
pub utilization: f64,
|
|
pub memory_used_gb: f64,
|
|
pub memory_total_gb: f64,
|
|
pub temperature_c: u32,
|
|
pub power_watts: u32,
|
|
pub power_limit_watts: u32,
|
|
}
|
|
|
|
impl Default for GpuData {
|
|
fn default() -> Self {
|
|
Self {
|
|
name: "N/A".into(),
|
|
utilization: 0.0,
|
|
memory_used_gb: 0.0,
|
|
memory_total_gb: 0.0,
|
|
temperature_c: 0,
|
|
power_watts: 0,
|
|
power_limit_watts: 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A backend microservice.
|
|
pub struct ServiceData {
|
|
pub name: String,
|
|
pub healthy: bool,
|
|
pub uptime: String,
|
|
pub version: String,
|
|
/// Health-check round-trip latency in milliseconds.
|
|
pub latency_ms: f64,
|
|
}
|
|
|
|
/// An open trading position.
|
|
pub struct PositionData {
|
|
pub symbol: String,
|
|
pub qty: i64,
|
|
pub entry_price: f64,
|
|
pub market_price: f64,
|
|
pub unrealized_pnl: f64,
|
|
}
|
|
|
|
/// A recent trade execution.
|
|
pub struct ExecutionData {
|
|
pub time: String,
|
|
pub symbol: String,
|
|
pub side: String,
|
|
pub qty: i64,
|
|
pub price: f64,
|
|
pub status: String,
|
|
}
|
|
|
|
/// Account-level financials.
|
|
pub struct AccountData {
|
|
pub equity: f64,
|
|
pub cash: f64,
|
|
pub margin_used: f64,
|
|
pub daily_pnl: f64,
|
|
pub total_pnl: f64,
|
|
}
|
|
|
|
impl Default for AccountData {
|
|
fn default() -> Self {
|
|
Self {
|
|
equity: 0.0,
|
|
cash: 0.0,
|
|
margin_used: 0.0,
|
|
daily_pnl: 0.0,
|
|
total_pnl: 0.0,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Kill-switch, drawdown, circuit-breaker, and position-limit data.
|
|
pub struct RiskData {
|
|
pub global_kill_switch: Option<bool>,
|
|
pub portfolio_kill_switch: Option<bool>,
|
|
pub strategy_kill_switch: Option<bool>,
|
|
pub instrument_kill_switch: Option<bool>,
|
|
pub current_drawdown_pct: f64,
|
|
pub max_drawdown_pct: f64,
|
|
pub high_water_mark: f64,
|
|
pub circuit_breakers: Vec<CircuitBreakerData>,
|
|
pub position_limits: Vec<PositionLimitData>,
|
|
}
|
|
|
|
impl Default for RiskData {
|
|
fn default() -> Self {
|
|
Self {
|
|
global_kill_switch: None,
|
|
portfolio_kill_switch: None,
|
|
strategy_kill_switch: None,
|
|
instrument_kill_switch: None,
|
|
current_drawdown_pct: 0.0,
|
|
max_drawdown_pct: 0.0,
|
|
high_water_mark: 0.0,
|
|
circuit_breakers: Vec::new(),
|
|
position_limits: Vec::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A single circuit breaker.
|
|
pub struct CircuitBreakerData {
|
|
pub name: String,
|
|
pub threshold: Option<f64>,
|
|
pub current: Option<f64>,
|
|
pub tripped: bool,
|
|
}
|
|
|
|
/// Position-limit on a single instrument.
|
|
pub struct PositionLimitData {
|
|
pub symbol: String,
|
|
pub max_qty: i64,
|
|
pub current_qty: i64,
|
|
}
|
|
|
|
/// System resource metrics.
|
|
pub struct SystemResources {
|
|
pub cpu_usage_pct: f64,
|
|
pub ram_used_gb: f64,
|
|
pub ram_total_gb: f64,
|
|
pub gpu_cluster_utilization: f64,
|
|
}
|
|
|
|
impl Default for SystemResources {
|
|
fn default() -> Self {
|
|
Self {
|
|
cpu_usage_pct: 0.0,
|
|
ram_used_gb: 0.0,
|
|
ram_total_gb: 0.0,
|
|
gpu_cluster_utilization: 0.0,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A single live data feed.
|
|
pub struct DataFeedData {
|
|
pub symbol: String,
|
|
pub records_per_sec: u64,
|
|
pub latency_us: u64,
|
|
pub status: String,
|
|
}
|
|
|
|
/// Aggregate data cache statistics.
|
|
pub struct DataCacheData {
|
|
pub total_records: u64,
|
|
pub cache_hit_rate: f64,
|
|
pub disk_usage_gb: f64,
|
|
pub oldest_date: String,
|
|
pub newest_date: String,
|
|
}
|
|
|
|
impl Default for DataCacheData {
|
|
fn default() -> Self {
|
|
Self {
|
|
total_records: 0,
|
|
cache_hit_rate: 0.0,
|
|
disk_usage_gb: 0.0,
|
|
oldest_date: String::new(),
|
|
newest_date: String::new(),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An order lifecycle event.
|
|
pub struct OrderEventData {
|
|
pub time: String,
|
|
pub order_id: String,
|
|
pub symbol: String,
|
|
pub side: String,
|
|
pub status: String,
|
|
pub qty: f64,
|
|
pub filled_qty: f64,
|
|
}
|
|
|
|
/// A risk alert from the risk service.
|
|
pub struct RiskAlertData {
|
|
pub time: String,
|
|
pub severity: String,
|
|
pub alert_type: String,
|
|
pub message: String,
|
|
}
|
|
|
|
/// ML model operational status.
|
|
pub struct ModelStatusData {
|
|
pub model_name: String,
|
|
pub state: String,
|
|
pub health: String,
|
|
pub last_prediction: String,
|
|
}
|
|
|
|
/// A system-level alert from monitoring.
|
|
pub struct AlertData {
|
|
pub time: String,
|
|
pub severity: String,
|
|
pub service: String,
|
|
pub title: String,
|
|
}
|
|
|
|
/// A single K8s pod.
|
|
pub struct PodData {
|
|
pub name: String,
|
|
pub service: String,
|
|
pub status: String,
|
|
pub restarts: i32,
|
|
pub age: String,
|
|
pub node: String,
|
|
pub ready: bool,
|
|
pub version: String,
|
|
}
|
|
|
|
/// Pods grouped by service.
|
|
pub struct PodGroupData {
|
|
pub service: String,
|
|
pub pods: Vec<PodData>,
|
|
pub ready_count: usize,
|
|
pub total_count: usize,
|
|
}
|