🚀 Wave 34: 12 Parallel Agents - 88% Error Reduction (200→24)
Agent Results: ✅ Agent 1: Verified ML CheckpointMetadata (no errors found) ✅ Agent 2: Fixed 12 ML error handling issues (E0533, E0277, E0282) ✅ Agent 3: Fixed 10 ML type mismatches (E0308) ✅ Agent 4: Fixed 5 trading service test errors (E0599, E0308) ✅ Agent 5: Restored 5 tests crate infrastructure types ✅ Agent 6: Fixed 3 tests dependencies (OrderSide/Status, tempfile) ✅ Agent 7: Fixed TradingEventType re-export ✅ Agent 8: Fixed 7 E2E test files (proto namespaces) ✅ Agent 9: Verified ML crate clean compilation ✅ Agent 10: Fixed 4 trading service/engine errors ✅ Agent 11: Completed integration test analysis ✅ Agent 12: Generated comprehensive verification report Files Modified: 30 files Error Reduction: ~200 errors → 24 errors (88%) Remaining: 16 ML + 5 E2E + 3 tests = 24 errors Documentation: - WAVE34_COMPLETION_REPORT.md (447 lines) - WAVE35_ACTION_PLAN.md (detailed fixes) Next: Wave 35 with 3 targeted agents to achieve 0 errors
This commit is contained in:
@@ -66,6 +66,9 @@ influxdb2 = { workspace = true, optional = true }
|
||||
tracing.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
|
||||
# File system utilities (needed for non-test modules that create temp files)
|
||||
tempfile = "3.8"
|
||||
|
||||
# Memory profiling (optional)
|
||||
dhat = { version = "0.3", optional = true }
|
||||
jemalloc_pprof = { version = "0.4", optional = true }
|
||||
|
||||
@@ -13,6 +13,7 @@ fn main() -> Result<()> {
|
||||
&[
|
||||
"../../services/trading_service/proto/trading.proto",
|
||||
"../../services/trading_service/proto/config.proto",
|
||||
"../../services/trading_service/proto/risk.proto",
|
||||
"../../services/ml_training_service/proto/ml_training.proto",
|
||||
],
|
||||
&[
|
||||
|
||||
@@ -6,4 +6,5 @@
|
||||
pub mod backtesting;
|
||||
pub mod config;
|
||||
pub mod ml_training;
|
||||
pub mod risk;
|
||||
pub mod trading;
|
||||
|
||||
946
tests/e2e/src/proto/risk.rs
Normal file
946
tests/e2e/src/proto/risk.rs
Normal file
@@ -0,0 +1,946 @@
|
||||
// This file is @generated by prost-build.
|
||||
/// Request to calculate portfolio VaR
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct GetVaRRequest {
|
||||
/// Symbols to include in VaR calculation (empty = all positions)
|
||||
#[prost(string, repeated, tag = "1")]
|
||||
pub symbols: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
|
||||
/// Confidence level (e.g., 0.95 for 95% VaR)
|
||||
#[prost(double, tag = "2")]
|
||||
pub confidence_level: f64,
|
||||
/// Historical data period for calculation
|
||||
#[prost(int32, tag = "3")]
|
||||
pub lookback_days: i32,
|
||||
/// VaR calculation method (historical, parametric, Monte Carlo)
|
||||
#[prost(enumeration = "VaRMethod", tag = "4")]
|
||||
pub method: i32,
|
||||
}
|
||||
/// Response containing VaR calculation results
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct GetVaRResponse {
|
||||
/// Total portfolio VaR value
|
||||
#[prost(double, tag = "1")]
|
||||
pub portfolio_var: f64,
|
||||
/// Individual symbol VaR contributions
|
||||
#[prost(message, repeated, tag = "2")]
|
||||
pub symbol_vars: ::prost::alloc::vec::Vec<SymbolVaR>,
|
||||
/// Confidence level used in calculation
|
||||
#[prost(double, tag = "3")]
|
||||
pub confidence_level: f64,
|
||||
/// Historical period used
|
||||
#[prost(int32, tag = "4")]
|
||||
pub lookback_days: i32,
|
||||
/// Calculation method used
|
||||
#[prost(enumeration = "VaRMethod", tag = "5")]
|
||||
pub method: i32,
|
||||
/// Calculation timestamp (nanoseconds)
|
||||
#[prost(int64, tag = "6")]
|
||||
pub calculated_at: i64,
|
||||
}
|
||||
/// Request to stream real-time VaR updates
|
||||
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
|
||||
pub struct StreamVaRRequest {
|
||||
/// Confidence level for VaR calculation
|
||||
#[prost(double, tag = "1")]
|
||||
pub confidence_level: f64,
|
||||
/// How often to send updates
|
||||
#[prost(int32, tag = "2")]
|
||||
pub update_frequency_seconds: i32,
|
||||
}
|
||||
/// VaR contribution for a specific symbol
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct SymbolVaR {
|
||||
/// Trading symbol
|
||||
#[prost(string, tag = "1")]
|
||||
pub symbol: ::prost::alloc::string::String,
|
||||
/// VaR value for this symbol
|
||||
#[prost(double, tag = "2")]
|
||||
pub var_value: f64,
|
||||
/// Current position size
|
||||
#[prost(double, tag = "3")]
|
||||
pub position_size: f64,
|
||||
/// Percentage contribution to total portfolio VaR
|
||||
#[prost(double, tag = "4")]
|
||||
pub contribution_pct: f64,
|
||||
}
|
||||
/// Request for position risk analysis
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct GetPositionRiskRequest {
|
||||
/// Filter by symbol (all symbols if not specified)
|
||||
#[prost(string, optional, tag = "1")]
|
||||
pub symbol: ::core::option::Option<::prost::alloc::string::String>,
|
||||
/// Filter by account (all accounts if not specified)
|
||||
#[prost(string, optional, tag = "2")]
|
||||
pub account_id: ::core::option::Option<::prost::alloc::string::String>,
|
||||
}
|
||||
/// Response containing position risk analysis
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct GetPositionRiskResponse {
|
||||
/// Risk analysis for each position
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub position_risks: ::prost::alloc::vec::Vec<PositionRisk>,
|
||||
/// Overall portfolio risk score (0-100)
|
||||
#[prost(double, tag = "2")]
|
||||
pub portfolio_risk_score: f64,
|
||||
}
|
||||
/// Request to validate order against risk limits
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ValidateOrderRequest {
|
||||
/// Trading symbol
|
||||
#[prost(string, tag = "1")]
|
||||
pub symbol: ::prost::alloc::string::String,
|
||||
/// Order quantity
|
||||
#[prost(double, tag = "2")]
|
||||
pub quantity: f64,
|
||||
/// Order price
|
||||
#[prost(double, tag = "3")]
|
||||
pub price: f64,
|
||||
/// Buy or sell
|
||||
#[prost(string, tag = "4")]
|
||||
pub side: ::prost::alloc::string::String,
|
||||
/// Trading account
|
||||
#[prost(string, tag = "5")]
|
||||
pub account_id: ::prost::alloc::string::String,
|
||||
}
|
||||
/// Response containing order validation results
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct ValidateOrderResponse {
|
||||
/// True if order passes all risk checks
|
||||
#[prost(bool, tag = "1")]
|
||||
pub is_valid: bool,
|
||||
/// List of risk violations (if any)
|
||||
#[prost(message, repeated, tag = "2")]
|
||||
pub violations: ::prost::alloc::vec::Vec<RiskViolation>,
|
||||
/// Risk assessment for this order
|
||||
#[prost(message, optional, tag = "3")]
|
||||
pub risk_score: ::core::option::Option<RiskScore>,
|
||||
/// Human-readable validation message
|
||||
#[prost(string, tag = "4")]
|
||||
pub message: ::prost::alloc::string::String,
|
||||
}
|
||||
/// Request for comprehensive risk metrics
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct GetRiskMetricsRequest {
|
||||
/// Portfolio identifier (default portfolio if not specified)
|
||||
#[prost(string, optional, tag = "1")]
|
||||
pub portfolio_id: ::core::option::Option<::prost::alloc::string::String>,
|
||||
}
|
||||
/// Response containing comprehensive risk metrics
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct GetRiskMetricsResponse {
|
||||
/// Complete risk metrics and statistics
|
||||
#[prost(message, optional, tag = "1")]
|
||||
pub metrics: ::core::option::Option<RiskMetrics>,
|
||||
/// Metrics calculation timestamp (nanoseconds)
|
||||
#[prost(int64, tag = "2")]
|
||||
pub calculated_at: i64,
|
||||
}
|
||||
/// Request to stream real-time risk alerts
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct StreamRiskAlertsRequest {
|
||||
/// Minimum alert severity to receive
|
||||
#[prost(enumeration = "RiskAlertSeverity", tag = "1")]
|
||||
pub min_severity: i32,
|
||||
/// Types of alerts to receive (empty = all types)
|
||||
#[prost(enumeration = "RiskAlertType", repeated, tag = "2")]
|
||||
pub alert_types: ::prost::alloc::vec::Vec<i32>,
|
||||
}
|
||||
/// Request to trigger emergency stop
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct EmergencyStopRequest {
|
||||
/// Type of emergency stop (all trading, symbol, account, etc.)
|
||||
#[prost(enumeration = "EmergencyStopType", tag = "1")]
|
||||
pub stop_type: i32,
|
||||
/// Reason for emergency stop
|
||||
#[prost(string, tag = "2")]
|
||||
pub reason: ::prost::alloc::string::String,
|
||||
/// Symbol to stop (for symbol-specific stops)
|
||||
#[prost(string, optional, tag = "3")]
|
||||
pub symbol: ::core::option::Option<::prost::alloc::string::String>,
|
||||
/// Account to stop (for account-specific stops)
|
||||
#[prost(string, optional, tag = "4")]
|
||||
pub account_id: ::core::option::Option<::prost::alloc::string::String>,
|
||||
}
|
||||
/// Response after emergency stop execution
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct EmergencyStopResponse {
|
||||
/// True if emergency stop was successful
|
||||
#[prost(bool, tag = "1")]
|
||||
pub success: bool,
|
||||
/// Status message or error description
|
||||
#[prost(string, tag = "2")]
|
||||
pub message: ::prost::alloc::string::String,
|
||||
/// Emergency stop timestamp (nanoseconds)
|
||||
#[prost(int64, tag = "3")]
|
||||
pub timestamp: i64,
|
||||
/// List of order IDs affected by the stop
|
||||
#[prost(string, repeated, tag = "4")]
|
||||
pub affected_orders: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
|
||||
}
|
||||
/// Request for circuit breaker status
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct GetCircuitBreakerStatusRequest {
|
||||
/// Filter by symbol (all symbols if not specified)
|
||||
#[prost(string, optional, tag = "1")]
|
||||
pub symbol: ::core::option::Option<::prost::alloc::string::String>,
|
||||
}
|
||||
/// Response containing circuit breaker status
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct GetCircuitBreakerStatusResponse {
|
||||
/// Status of all circuit breakers
|
||||
#[prost(message, repeated, tag = "1")]
|
||||
pub circuit_breakers: ::prost::alloc::vec::Vec<CircuitBreakerStatus>,
|
||||
}
|
||||
/// Risk analysis for a specific position
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct PositionRisk {
|
||||
/// Trading symbol
|
||||
#[prost(string, tag = "1")]
|
||||
pub symbol: ::prost::alloc::string::String,
|
||||
/// Current position size
|
||||
#[prost(double, tag = "2")]
|
||||
pub position_size: f64,
|
||||
/// Market value of position
|
||||
#[prost(double, tag = "3")]
|
||||
pub market_value: f64,
|
||||
/// Contribution to portfolio VaR
|
||||
#[prost(double, tag = "4")]
|
||||
pub var_contribution: f64,
|
||||
/// Position concentration risk (0-100)
|
||||
#[prost(double, tag = "5")]
|
||||
pub concentration_risk: f64,
|
||||
/// Liquidity risk score (0-100)
|
||||
#[prost(double, tag = "6")]
|
||||
pub liquidity_risk: f64,
|
||||
/// Overall risk assessment
|
||||
#[prost(message, optional, tag = "7")]
|
||||
pub overall_score: ::core::option::Option<RiskScore>,
|
||||
/// Additional risk metrics
|
||||
#[prost(message, repeated, tag = "8")]
|
||||
pub metrics: ::prost::alloc::vec::Vec<RiskMetric>,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct RiskViolation {
|
||||
#[prost(enumeration = "RiskViolationType", tag = "1")]
|
||||
pub violation_type: i32,
|
||||
#[prost(string, tag = "2")]
|
||||
pub description: ::prost::alloc::string::String,
|
||||
#[prost(double, tag = "3")]
|
||||
pub current_value: f64,
|
||||
#[prost(double, tag = "4")]
|
||||
pub limit_value: f64,
|
||||
#[prost(enumeration = "RiskAlertSeverity", tag = "5")]
|
||||
pub severity: i32,
|
||||
}
|
||||
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
|
||||
pub struct RiskScore {
|
||||
#[prost(double, tag = "1")]
|
||||
pub overall_score: f64,
|
||||
#[prost(double, tag = "2")]
|
||||
pub concentration_score: f64,
|
||||
#[prost(double, tag = "3")]
|
||||
pub liquidity_score: f64,
|
||||
#[prost(double, tag = "4")]
|
||||
pub volatility_score: f64,
|
||||
#[prost(double, tag = "5")]
|
||||
pub correlation_score: f64,
|
||||
#[prost(enumeration = "RiskLevel", tag = "6")]
|
||||
pub risk_level: i32,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct RiskMetrics {
|
||||
#[prost(double, tag = "1")]
|
||||
pub portfolio_var_1d: f64,
|
||||
#[prost(double, tag = "2")]
|
||||
pub portfolio_var_5d: f64,
|
||||
#[prost(double, tag = "3")]
|
||||
pub portfolio_var_30d: f64,
|
||||
#[prost(double, tag = "4")]
|
||||
pub max_drawdown: f64,
|
||||
#[prost(double, tag = "5")]
|
||||
pub current_drawdown: f64,
|
||||
#[prost(double, tag = "6")]
|
||||
pub sharpe_ratio: f64,
|
||||
#[prost(double, tag = "7")]
|
||||
pub sortino_ratio: f64,
|
||||
#[prost(double, tag = "8")]
|
||||
pub beta: f64,
|
||||
#[prost(double, tag = "9")]
|
||||
pub alpha: f64,
|
||||
#[prost(double, tag = "10")]
|
||||
pub volatility: f64,
|
||||
#[prost(message, repeated, tag = "11")]
|
||||
pub position_risks: ::prost::alloc::vec::Vec<PositionRisk>,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct RiskMetric {
|
||||
#[prost(string, tag = "1")]
|
||||
pub name: ::prost::alloc::string::String,
|
||||
#[prost(double, tag = "2")]
|
||||
pub value: f64,
|
||||
#[prost(string, tag = "3")]
|
||||
pub unit: ::prost::alloc::string::String,
|
||||
#[prost(enumeration = "RiskLevel", tag = "4")]
|
||||
pub risk_level: i32,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct CircuitBreakerStatus {
|
||||
#[prost(string, tag = "1")]
|
||||
pub name: ::prost::alloc::string::String,
|
||||
#[prost(bool, tag = "2")]
|
||||
pub is_triggered: bool,
|
||||
#[prost(string, optional, tag = "3")]
|
||||
pub trigger_reason: ::core::option::Option<::prost::alloc::string::String>,
|
||||
#[prost(int64, optional, tag = "4")]
|
||||
pub triggered_at: ::core::option::Option<i64>,
|
||||
#[prost(int64, optional, tag = "5")]
|
||||
pub reset_at: ::core::option::Option<i64>,
|
||||
#[prost(enumeration = "CircuitBreakerType", tag = "6")]
|
||||
pub breaker_type: i32,
|
||||
}
|
||||
/// Event Messages
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct VaREvent {
|
||||
#[prost(double, tag = "1")]
|
||||
pub portfolio_var: f64,
|
||||
#[prost(message, repeated, tag = "2")]
|
||||
pub symbol_vars: ::prost::alloc::vec::Vec<SymbolVaR>,
|
||||
#[prost(enumeration = "VaRChangeType", tag = "3")]
|
||||
pub change_type: i32,
|
||||
#[prost(int64, tag = "4")]
|
||||
pub timestamp: i64,
|
||||
}
|
||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||
pub struct RiskAlertEvent {
|
||||
#[prost(string, tag = "1")]
|
||||
pub alert_id: ::prost::alloc::string::String,
|
||||
#[prost(enumeration = "RiskAlertType", tag = "2")]
|
||||
pub alert_type: i32,
|
||||
#[prost(enumeration = "RiskAlertSeverity", tag = "3")]
|
||||
pub severity: i32,
|
||||
#[prost(string, tag = "4")]
|
||||
pub message: ::prost::alloc::string::String,
|
||||
#[prost(string, optional, tag = "5")]
|
||||
pub symbol: ::core::option::Option<::prost::alloc::string::String>,
|
||||
#[prost(string, optional, tag = "6")]
|
||||
pub account_id: ::core::option::Option<::prost::alloc::string::String>,
|
||||
#[prost(map = "string, string", tag = "7")]
|
||||
pub metadata: ::std::collections::HashMap<
|
||||
::prost::alloc::string::String,
|
||||
::prost::alloc::string::String,
|
||||
>,
|
||||
#[prost(int64, tag = "8")]
|
||||
pub timestamp: i64,
|
||||
}
|
||||
/// VaR calculation methodology
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum VaRMethod {
|
||||
/// Default/unknown method
|
||||
VarMethodUnspecified = 0,
|
||||
/// Historical simulation method
|
||||
VarMethodHistorical = 1,
|
||||
/// Parametric (variance-covariance) method
|
||||
VarMethodParametric = 2,
|
||||
/// Monte Carlo simulation method
|
||||
VarMethodMonteCarlo = 3,
|
||||
}
|
||||
impl VaRMethod {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::VarMethodUnspecified => "VAR_METHOD_UNSPECIFIED",
|
||||
Self::VarMethodHistorical => "VAR_METHOD_HISTORICAL",
|
||||
Self::VarMethodParametric => "VAR_METHOD_PARAMETRIC",
|
||||
Self::VarMethodMonteCarlo => "VAR_METHOD_MONTE_CARLO",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"VAR_METHOD_UNSPECIFIED" => Some(Self::VarMethodUnspecified),
|
||||
"VAR_METHOD_HISTORICAL" => Some(Self::VarMethodHistorical),
|
||||
"VAR_METHOD_PARAMETRIC" => Some(Self::VarMethodParametric),
|
||||
"VAR_METHOD_MONTE_CARLO" => Some(Self::VarMethodMonteCarlo),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum RiskViolationType {
|
||||
Unspecified = 0,
|
||||
PositionLimit = 1,
|
||||
Concentration = 2,
|
||||
VarLimit = 3,
|
||||
Drawdown = 4,
|
||||
Liquidity = 5,
|
||||
Correlation = 6,
|
||||
}
|
||||
impl RiskViolationType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Unspecified => "RISK_VIOLATION_TYPE_UNSPECIFIED",
|
||||
Self::PositionLimit => "RISK_VIOLATION_TYPE_POSITION_LIMIT",
|
||||
Self::Concentration => "RISK_VIOLATION_TYPE_CONCENTRATION",
|
||||
Self::VarLimit => "RISK_VIOLATION_TYPE_VAR_LIMIT",
|
||||
Self::Drawdown => "RISK_VIOLATION_TYPE_DRAWDOWN",
|
||||
Self::Liquidity => "RISK_VIOLATION_TYPE_LIQUIDITY",
|
||||
Self::Correlation => "RISK_VIOLATION_TYPE_CORRELATION",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"RISK_VIOLATION_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
|
||||
"RISK_VIOLATION_TYPE_POSITION_LIMIT" => Some(Self::PositionLimit),
|
||||
"RISK_VIOLATION_TYPE_CONCENTRATION" => Some(Self::Concentration),
|
||||
"RISK_VIOLATION_TYPE_VAR_LIMIT" => Some(Self::VarLimit),
|
||||
"RISK_VIOLATION_TYPE_DRAWDOWN" => Some(Self::Drawdown),
|
||||
"RISK_VIOLATION_TYPE_LIQUIDITY" => Some(Self::Liquidity),
|
||||
"RISK_VIOLATION_TYPE_CORRELATION" => Some(Self::Correlation),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Risk assessment levels
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum RiskLevel {
|
||||
/// Default/unknown level
|
||||
Unspecified = 0,
|
||||
/// Low risk (green)
|
||||
Low = 1,
|
||||
/// Medium risk (yellow)
|
||||
Medium = 2,
|
||||
/// High risk (orange)
|
||||
High = 3,
|
||||
/// Critical risk (red)
|
||||
Critical = 4,
|
||||
}
|
||||
impl RiskLevel {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Unspecified => "RISK_LEVEL_UNSPECIFIED",
|
||||
Self::Low => "RISK_LEVEL_LOW",
|
||||
Self::Medium => "RISK_LEVEL_MEDIUM",
|
||||
Self::High => "RISK_LEVEL_HIGH",
|
||||
Self::Critical => "RISK_LEVEL_CRITICAL",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"RISK_LEVEL_UNSPECIFIED" => Some(Self::Unspecified),
|
||||
"RISK_LEVEL_LOW" => Some(Self::Low),
|
||||
"RISK_LEVEL_MEDIUM" => Some(Self::Medium),
|
||||
"RISK_LEVEL_HIGH" => Some(Self::High),
|
||||
"RISK_LEVEL_CRITICAL" => Some(Self::Critical),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Severity levels for risk alerts
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum RiskAlertSeverity {
|
||||
/// Default/unknown severity
|
||||
Unspecified = 0,
|
||||
/// Informational alert
|
||||
Info = 1,
|
||||
/// Warning alert
|
||||
Warning = 2,
|
||||
/// Critical alert requiring attention
|
||||
Critical = 3,
|
||||
/// Emergency alert requiring immediate action
|
||||
Emergency = 4,
|
||||
}
|
||||
impl RiskAlertSeverity {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Unspecified => "RISK_ALERT_SEVERITY_UNSPECIFIED",
|
||||
Self::Info => "RISK_ALERT_SEVERITY_INFO",
|
||||
Self::Warning => "RISK_ALERT_SEVERITY_WARNING",
|
||||
Self::Critical => "RISK_ALERT_SEVERITY_CRITICAL",
|
||||
Self::Emergency => "RISK_ALERT_SEVERITY_EMERGENCY",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"RISK_ALERT_SEVERITY_UNSPECIFIED" => Some(Self::Unspecified),
|
||||
"RISK_ALERT_SEVERITY_INFO" => Some(Self::Info),
|
||||
"RISK_ALERT_SEVERITY_WARNING" => Some(Self::Warning),
|
||||
"RISK_ALERT_SEVERITY_CRITICAL" => Some(Self::Critical),
|
||||
"RISK_ALERT_SEVERITY_EMERGENCY" => Some(Self::Emergency),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Types of risk alerts
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum RiskAlertType {
|
||||
/// Default/unknown type
|
||||
Unspecified = 0,
|
||||
/// VaR limit breach
|
||||
VarBreach = 1,
|
||||
/// Position size limit breach
|
||||
PositionLimit = 2,
|
||||
/// Drawdown limit breach
|
||||
Drawdown = 3,
|
||||
/// Portfolio concentration risk
|
||||
Concentration = 4,
|
||||
/// Liquidity risk alert
|
||||
Liquidity = 5,
|
||||
/// Correlation risk alert
|
||||
Correlation = 6,
|
||||
}
|
||||
impl RiskAlertType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Unspecified => "RISK_ALERT_TYPE_UNSPECIFIED",
|
||||
Self::VarBreach => "RISK_ALERT_TYPE_VAR_BREACH",
|
||||
Self::PositionLimit => "RISK_ALERT_TYPE_POSITION_LIMIT",
|
||||
Self::Drawdown => "RISK_ALERT_TYPE_DRAWDOWN",
|
||||
Self::Concentration => "RISK_ALERT_TYPE_CONCENTRATION",
|
||||
Self::Liquidity => "RISK_ALERT_TYPE_LIQUIDITY",
|
||||
Self::Correlation => "RISK_ALERT_TYPE_CORRELATION",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"RISK_ALERT_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
|
||||
"RISK_ALERT_TYPE_VAR_BREACH" => Some(Self::VarBreach),
|
||||
"RISK_ALERT_TYPE_POSITION_LIMIT" => Some(Self::PositionLimit),
|
||||
"RISK_ALERT_TYPE_DRAWDOWN" => Some(Self::Drawdown),
|
||||
"RISK_ALERT_TYPE_CONCENTRATION" => Some(Self::Concentration),
|
||||
"RISK_ALERT_TYPE_LIQUIDITY" => Some(Self::Liquidity),
|
||||
"RISK_ALERT_TYPE_CORRELATION" => Some(Self::Correlation),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Types of emergency stops
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum EmergencyStopType {
|
||||
/// Default/unknown type
|
||||
Unspecified = 0,
|
||||
/// Stop all trading activity
|
||||
AllTrading = 1,
|
||||
/// Stop trading for specific symbol
|
||||
Symbol = 2,
|
||||
/// Stop trading for specific account
|
||||
Account = 3,
|
||||
/// Stop specific trading strategy
|
||||
Strategy = 4,
|
||||
}
|
||||
impl EmergencyStopType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Unspecified => "EMERGENCY_STOP_TYPE_UNSPECIFIED",
|
||||
Self::AllTrading => "EMERGENCY_STOP_TYPE_ALL_TRADING",
|
||||
Self::Symbol => "EMERGENCY_STOP_TYPE_SYMBOL",
|
||||
Self::Account => "EMERGENCY_STOP_TYPE_ACCOUNT",
|
||||
Self::Strategy => "EMERGENCY_STOP_TYPE_STRATEGY",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"EMERGENCY_STOP_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
|
||||
"EMERGENCY_STOP_TYPE_ALL_TRADING" => Some(Self::AllTrading),
|
||||
"EMERGENCY_STOP_TYPE_SYMBOL" => Some(Self::Symbol),
|
||||
"EMERGENCY_STOP_TYPE_ACCOUNT" => Some(Self::Account),
|
||||
"EMERGENCY_STOP_TYPE_STRATEGY" => Some(Self::Strategy),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum CircuitBreakerType {
|
||||
Unspecified = 0,
|
||||
PortfolioLoss = 1,
|
||||
SymbolVolatility = 2,
|
||||
PositionSize = 3,
|
||||
Drawdown = 4,
|
||||
}
|
||||
impl CircuitBreakerType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Unspecified => "CIRCUIT_BREAKER_TYPE_UNSPECIFIED",
|
||||
Self::PortfolioLoss => "CIRCUIT_BREAKER_TYPE_PORTFOLIO_LOSS",
|
||||
Self::SymbolVolatility => "CIRCUIT_BREAKER_TYPE_SYMBOL_VOLATILITY",
|
||||
Self::PositionSize => "CIRCUIT_BREAKER_TYPE_POSITION_SIZE",
|
||||
Self::Drawdown => "CIRCUIT_BREAKER_TYPE_DRAWDOWN",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"CIRCUIT_BREAKER_TYPE_UNSPECIFIED" => Some(Self::Unspecified),
|
||||
"CIRCUIT_BREAKER_TYPE_PORTFOLIO_LOSS" => Some(Self::PortfolioLoss),
|
||||
"CIRCUIT_BREAKER_TYPE_SYMBOL_VOLATILITY" => Some(Self::SymbolVolatility),
|
||||
"CIRCUIT_BREAKER_TYPE_POSITION_SIZE" => Some(Self::PositionSize),
|
||||
"CIRCUIT_BREAKER_TYPE_DRAWDOWN" => Some(Self::Drawdown),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
|
||||
#[repr(i32)]
|
||||
pub enum VaRChangeType {
|
||||
VarChangeTypeUnspecified = 0,
|
||||
VarChangeTypeIncreased = 1,
|
||||
VarChangeTypeDecreased = 2,
|
||||
VarChangeTypeBreach = 3,
|
||||
}
|
||||
impl VaRChangeType {
|
||||
/// String value of the enum field names used in the ProtoBuf definition.
|
||||
///
|
||||
/// The values are not transformed in any way and thus are considered stable
|
||||
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
|
||||
pub fn as_str_name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::VarChangeTypeUnspecified => "VAR_CHANGE_TYPE_UNSPECIFIED",
|
||||
Self::VarChangeTypeIncreased => "VAR_CHANGE_TYPE_INCREASED",
|
||||
Self::VarChangeTypeDecreased => "VAR_CHANGE_TYPE_DECREASED",
|
||||
Self::VarChangeTypeBreach => "VAR_CHANGE_TYPE_BREACH",
|
||||
}
|
||||
}
|
||||
/// Creates an enum from field names used in the ProtoBuf definition.
|
||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
||||
match value {
|
||||
"VAR_CHANGE_TYPE_UNSPECIFIED" => Some(Self::VarChangeTypeUnspecified),
|
||||
"VAR_CHANGE_TYPE_INCREASED" => Some(Self::VarChangeTypeIncreased),
|
||||
"VAR_CHANGE_TYPE_DECREASED" => Some(Self::VarChangeTypeDecreased),
|
||||
"VAR_CHANGE_TYPE_BREACH" => Some(Self::VarChangeTypeBreach),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Generated client implementations.
|
||||
#[allow(unused_qualifications)]
|
||||
pub mod risk_service_client {
|
||||
#![allow(
|
||||
unused_variables,
|
||||
dead_code,
|
||||
missing_docs,
|
||||
clippy::wildcard_imports,
|
||||
clippy::let_unit_value,
|
||||
)]
|
||||
use tonic::codegen::*;
|
||||
use tonic::codegen::http::Uri;
|
||||
/// Risk Management Service provides comprehensive risk assessment, monitoring, and control capabilities
|
||||
/// for high-frequency trading operations. This service integrates real-time VaR calculations,
|
||||
/// position risk analysis, compliance monitoring, and emergency controls.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RiskServiceClient<T> {
|
||||
inner: tonic::client::Grpc<T>,
|
||||
}
|
||||
impl RiskServiceClient<tonic::transport::Channel> {
|
||||
/// Attempt to create a new client by connecting to a given endpoint.
|
||||
pub async fn connect<D>(dst: D) -> Result<Self, tonic::transport::Error>
|
||||
where
|
||||
D: TryInto<tonic::transport::Endpoint>,
|
||||
D::Error: Into<StdError>,
|
||||
{
|
||||
let conn = tonic::transport::Endpoint::new(dst)?.connect().await?;
|
||||
Ok(Self::new(conn))
|
||||
}
|
||||
}
|
||||
impl<T> RiskServiceClient<T>
|
||||
where
|
||||
T: tonic::client::GrpcService<tonic::body::BoxBody>,
|
||||
T::Error: Into<StdError>,
|
||||
T::ResponseBody: Body<Data = Bytes> + std::marker::Send + 'static,
|
||||
<T::ResponseBody as Body>::Error: Into<StdError> + std::marker::Send,
|
||||
{
|
||||
pub fn new(inner: T) -> Self {
|
||||
let inner = tonic::client::Grpc::new(inner);
|
||||
Self { inner }
|
||||
}
|
||||
pub fn with_origin(inner: T, origin: Uri) -> Self {
|
||||
let inner = tonic::client::Grpc::with_origin(inner, origin);
|
||||
Self { inner }
|
||||
}
|
||||
pub fn with_interceptor<F>(
|
||||
inner: T,
|
||||
interceptor: F,
|
||||
) -> RiskServiceClient<InterceptedService<T, F>>
|
||||
where
|
||||
F: tonic::service::Interceptor,
|
||||
T::ResponseBody: Default,
|
||||
T: tonic::codegen::Service<
|
||||
http::Request<tonic::body::BoxBody>,
|
||||
Response = http::Response<
|
||||
<T as tonic::client::GrpcService<tonic::body::BoxBody>>::ResponseBody,
|
||||
>,
|
||||
>,
|
||||
<T as tonic::codegen::Service<
|
||||
http::Request<tonic::body::BoxBody>,
|
||||
>>::Error: Into<StdError> + std::marker::Send + std::marker::Sync,
|
||||
{
|
||||
RiskServiceClient::new(InterceptedService::new(inner, interceptor))
|
||||
}
|
||||
/// Compress requests with the given encoding.
|
||||
///
|
||||
/// This requires the server to support it otherwise it might respond with an
|
||||
/// error.
|
||||
#[must_use]
|
||||
pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self {
|
||||
self.inner = self.inner.send_compressed(encoding);
|
||||
self
|
||||
}
|
||||
/// Enable decompressing responses.
|
||||
#[must_use]
|
||||
pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self {
|
||||
self.inner = self.inner.accept_compressed(encoding);
|
||||
self
|
||||
}
|
||||
/// Limits the maximum size of a decoded message.
|
||||
///
|
||||
/// Default: `4MB`
|
||||
#[must_use]
|
||||
pub fn max_decoding_message_size(mut self, limit: usize) -> Self {
|
||||
self.inner = self.inner.max_decoding_message_size(limit);
|
||||
self
|
||||
}
|
||||
/// Limits the maximum size of an encoded message.
|
||||
///
|
||||
/// Default: `usize::MAX`
|
||||
#[must_use]
|
||||
pub fn max_encoding_message_size(mut self, limit: usize) -> Self {
|
||||
self.inner = self.inner.max_encoding_message_size(limit);
|
||||
self
|
||||
}
|
||||
/// Value at Risk (VaR) Calculations
|
||||
/// Calculate current portfolio VaR using specified method and parameters
|
||||
pub async fn get_va_r(
|
||||
&mut self,
|
||||
request: impl tonic::IntoRequest<super::GetVaRRequest>,
|
||||
) -> std::result::Result<tonic::Response<super::GetVaRResponse>, tonic::Status> {
|
||||
self.inner
|
||||
.ready()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tonic::Status::unknown(
|
||||
format!("Service was not ready: {}", e.into()),
|
||||
)
|
||||
})?;
|
||||
let codec = tonic::codec::ProstCodec::default();
|
||||
let path = http::uri::PathAndQuery::from_static("/risk.RiskService/GetVaR");
|
||||
let mut req = request.into_request();
|
||||
req.extensions_mut().insert(GrpcMethod::new("risk.RiskService", "GetVaR"));
|
||||
self.inner.unary(req, path, codec).await
|
||||
}
|
||||
/// Stream real-time VaR updates as market conditions change
|
||||
pub async fn stream_va_r_updates(
|
||||
&mut self,
|
||||
request: impl tonic::IntoRequest<super::StreamVaRRequest>,
|
||||
) -> std::result::Result<
|
||||
tonic::Response<tonic::codec::Streaming<super::VaREvent>>,
|
||||
tonic::Status,
|
||||
> {
|
||||
self.inner
|
||||
.ready()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tonic::Status::unknown(
|
||||
format!("Service was not ready: {}", e.into()),
|
||||
)
|
||||
})?;
|
||||
let codec = tonic::codec::ProstCodec::default();
|
||||
let path = http::uri::PathAndQuery::from_static(
|
||||
"/risk.RiskService/StreamVaRUpdates",
|
||||
);
|
||||
let mut req = request.into_request();
|
||||
req.extensions_mut()
|
||||
.insert(GrpcMethod::new("risk.RiskService", "StreamVaRUpdates"));
|
||||
self.inner.server_streaming(req, path, codec).await
|
||||
}
|
||||
/// Position Risk Analysis
|
||||
/// Get comprehensive risk analysis for current positions
|
||||
pub async fn get_position_risk(
|
||||
&mut self,
|
||||
request: impl tonic::IntoRequest<super::GetPositionRiskRequest>,
|
||||
) -> std::result::Result<
|
||||
tonic::Response<super::GetPositionRiskResponse>,
|
||||
tonic::Status,
|
||||
> {
|
||||
self.inner
|
||||
.ready()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tonic::Status::unknown(
|
||||
format!("Service was not ready: {}", e.into()),
|
||||
)
|
||||
})?;
|
||||
let codec = tonic::codec::ProstCodec::default();
|
||||
let path = http::uri::PathAndQuery::from_static(
|
||||
"/risk.RiskService/GetPositionRisk",
|
||||
);
|
||||
let mut req = request.into_request();
|
||||
req.extensions_mut()
|
||||
.insert(GrpcMethod::new("risk.RiskService", "GetPositionRisk"));
|
||||
self.inner.unary(req, path, codec).await
|
||||
}
|
||||
/// Validate order against risk limits before execution
|
||||
pub async fn validate_order(
|
||||
&mut self,
|
||||
request: impl tonic::IntoRequest<super::ValidateOrderRequest>,
|
||||
) -> std::result::Result<
|
||||
tonic::Response<super::ValidateOrderResponse>,
|
||||
tonic::Status,
|
||||
> {
|
||||
self.inner
|
||||
.ready()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tonic::Status::unknown(
|
||||
format!("Service was not ready: {}", e.into()),
|
||||
)
|
||||
})?;
|
||||
let codec = tonic::codec::ProstCodec::default();
|
||||
let path = http::uri::PathAndQuery::from_static(
|
||||
"/risk.RiskService/ValidateOrder",
|
||||
);
|
||||
let mut req = request.into_request();
|
||||
req.extensions_mut()
|
||||
.insert(GrpcMethod::new("risk.RiskService", "ValidateOrder"));
|
||||
self.inner.unary(req, path, codec).await
|
||||
}
|
||||
/// Risk Metrics and Monitoring
|
||||
/// Get comprehensive portfolio risk metrics and statistics
|
||||
pub async fn get_risk_metrics(
|
||||
&mut self,
|
||||
request: impl tonic::IntoRequest<super::GetRiskMetricsRequest>,
|
||||
) -> std::result::Result<
|
||||
tonic::Response<super::GetRiskMetricsResponse>,
|
||||
tonic::Status,
|
||||
> {
|
||||
self.inner
|
||||
.ready()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tonic::Status::unknown(
|
||||
format!("Service was not ready: {}", e.into()),
|
||||
)
|
||||
})?;
|
||||
let codec = tonic::codec::ProstCodec::default();
|
||||
let path = http::uri::PathAndQuery::from_static(
|
||||
"/risk.RiskService/GetRiskMetrics",
|
||||
);
|
||||
let mut req = request.into_request();
|
||||
req.extensions_mut()
|
||||
.insert(GrpcMethod::new("risk.RiskService", "GetRiskMetrics"));
|
||||
self.inner.unary(req, path, codec).await
|
||||
}
|
||||
/// Stream real-time risk alerts and violations
|
||||
pub async fn stream_risk_alerts(
|
||||
&mut self,
|
||||
request: impl tonic::IntoRequest<super::StreamRiskAlertsRequest>,
|
||||
) -> std::result::Result<
|
||||
tonic::Response<tonic::codec::Streaming<super::RiskAlertEvent>>,
|
||||
tonic::Status,
|
||||
> {
|
||||
self.inner
|
||||
.ready()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tonic::Status::unknown(
|
||||
format!("Service was not ready: {}", e.into()),
|
||||
)
|
||||
})?;
|
||||
let codec = tonic::codec::ProstCodec::default();
|
||||
let path = http::uri::PathAndQuery::from_static(
|
||||
"/risk.RiskService/StreamRiskAlerts",
|
||||
);
|
||||
let mut req = request.into_request();
|
||||
req.extensions_mut()
|
||||
.insert(GrpcMethod::new("risk.RiskService", "StreamRiskAlerts"));
|
||||
self.inner.server_streaming(req, path, codec).await
|
||||
}
|
||||
/// Emergency Controls and Circuit Breakers
|
||||
/// Trigger emergency stop to halt trading activities
|
||||
pub async fn emergency_stop(
|
||||
&mut self,
|
||||
request: impl tonic::IntoRequest<super::EmergencyStopRequest>,
|
||||
) -> std::result::Result<
|
||||
tonic::Response<super::EmergencyStopResponse>,
|
||||
tonic::Status,
|
||||
> {
|
||||
self.inner
|
||||
.ready()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tonic::Status::unknown(
|
||||
format!("Service was not ready: {}", e.into()),
|
||||
)
|
||||
})?;
|
||||
let codec = tonic::codec::ProstCodec::default();
|
||||
let path = http::uri::PathAndQuery::from_static(
|
||||
"/risk.RiskService/EmergencyStop",
|
||||
);
|
||||
let mut req = request.into_request();
|
||||
req.extensions_mut()
|
||||
.insert(GrpcMethod::new("risk.RiskService", "EmergencyStop"));
|
||||
self.inner.unary(req, path, codec).await
|
||||
}
|
||||
/// Get status of all circuit breakers and safety mechanisms
|
||||
pub async fn get_circuit_breaker_status(
|
||||
&mut self,
|
||||
request: impl tonic::IntoRequest<super::GetCircuitBreakerStatusRequest>,
|
||||
) -> std::result::Result<
|
||||
tonic::Response<super::GetCircuitBreakerStatusResponse>,
|
||||
tonic::Status,
|
||||
> {
|
||||
self.inner
|
||||
.ready()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tonic::Status::unknown(
|
||||
format!("Service was not ready: {}", e.into()),
|
||||
)
|
||||
})?;
|
||||
let codec = tonic::codec::ProstCodec::default();
|
||||
let path = http::uri::PathAndQuery::from_static(
|
||||
"/risk.RiskService/GetCircuitBreakerStatus",
|
||||
);
|
||||
let mut req = request.into_request();
|
||||
req.extensions_mut()
|
||||
.insert(GrpcMethod::new("risk.RiskService", "GetCircuitBreakerStatus"));
|
||||
self.inner.unary(req, path, codec).await
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ impl ComprehensiveTradingWorkflows {
|
||||
// Step 2: Subscribe to real-time market data
|
||||
if let Some(trading_client) = client.trading() {
|
||||
let symbols = vec!["AAPL".to_string(), "GOOGL".to_string(), "MSFT".to_string()];
|
||||
let mut stream = trading_client.subscribe_market_data(symbols).await?;
|
||||
let mut stream = trading_client.stream_market_data(symbols).await?;
|
||||
info!("✓ Market data stream established");
|
||||
|
||||
// Collect initial market data for feature generation
|
||||
@@ -135,8 +135,6 @@ impl ComprehensiveTradingWorkflows {
|
||||
quantity: 100.0,
|
||||
price: None,
|
||||
stop_price: None,
|
||||
time_in_force: "IOC".to_string(), // Immediate or Cancel for HFT
|
||||
client_order_id: format!("HFT_ORDER_{}", Uuid::new_v4()),
|
||||
};
|
||||
|
||||
let response = trading_client.submit_order(order_request).await?;
|
||||
@@ -192,7 +190,7 @@ impl ComprehensiveTradingWorkflows {
|
||||
);
|
||||
|
||||
let account_info = trading_client
|
||||
.get_account_info("TEST_ACCOUNT_HFT".to_string())
|
||||
.get_portfolio_summary("TEST_ACCOUNT_HFT".to_string())
|
||||
.await?;
|
||||
metrics.insert("account_value".to_string(), account_info.total_value);
|
||||
info!(
|
||||
@@ -642,7 +640,7 @@ impl ComprehensiveTradingWorkflows {
|
||||
// Step 1: Portfolio initialization
|
||||
if let Some(trading_client) = client.trading() {
|
||||
let account_info = trading_client
|
||||
.get_account_info("MULTI_ASSET_TEST".to_string())
|
||||
.get_portfolio_summary("MULTI_ASSET_TEST".to_string())
|
||||
.await?;
|
||||
metrics.insert("initial_balance".to_string(), account_info.cash_balance);
|
||||
info!(
|
||||
@@ -682,8 +680,6 @@ impl ComprehensiveTradingWorkflows {
|
||||
quantity: 50.0 + (i as f64 * 10.0),
|
||||
price: None,
|
||||
stop_price: None,
|
||||
time_in_force: "DAY".to_string(),
|
||||
client_order_id: format!("MULTI_{}_{}", symbol, Uuid::new_v4()),
|
||||
};
|
||||
|
||||
let response = trading_client.submit_order(order_request).await?;
|
||||
@@ -726,8 +722,6 @@ impl ComprehensiveTradingWorkflows {
|
||||
} else {
|
||||
None
|
||||
},
|
||||
time_in_force: tif.to_string(),
|
||||
client_order_id: format!("LIMIT_{}_{}", symbol, Uuid::new_v4()),
|
||||
};
|
||||
|
||||
let response = trading_client.submit_order(order_request).await?;
|
||||
@@ -806,7 +800,7 @@ impl ComprehensiveTradingWorkflows {
|
||||
// Step 7: Real-time P&L calculation
|
||||
if let Some(trading_client) = client.trading() {
|
||||
let account_info = trading_client
|
||||
.get_account_info("MULTI_ASSET_TEST".to_string())
|
||||
.get_portfolio_summary("MULTI_ASSET_TEST".to_string())
|
||||
.await?;
|
||||
let current_balance = account_info.cash_balance;
|
||||
let initial_balance = metrics.get("initial_balance").copied().unwrap_or(0.0);
|
||||
@@ -903,7 +897,7 @@ impl ComprehensiveTradingWorkflows {
|
||||
if let Some(trading_client) = client.trading() {
|
||||
// Subscribe briefly to market data to analyze impact
|
||||
match trading_client
|
||||
.subscribe_market_data(symbols.iter().map(|s| s.to_string()).collect())
|
||||
.stream_market_data(symbols.iter().map(|s| s.to_string()).collect())
|
||||
.await
|
||||
{
|
||||
Ok(mut stream) => {
|
||||
@@ -1066,8 +1060,6 @@ impl ComprehensiveTradingWorkflows {
|
||||
quantity: 100.0,
|
||||
price: Some(150.0 + (i as f64)),
|
||||
stop_price: None,
|
||||
time_in_force: "GTC".to_string(),
|
||||
client_order_id: format!("EMERGENCY_TEST_{}", i),
|
||||
};
|
||||
|
||||
match trading_client.submit_order(order_request).await {
|
||||
@@ -1103,8 +1095,6 @@ impl ComprehensiveTradingWorkflows {
|
||||
quantity: 1_000_000.0, // Intentionally huge to trigger risk limits
|
||||
price: None,
|
||||
stop_price: None,
|
||||
time_in_force: "DAY".to_string(),
|
||||
client_order_id: format!("RISK_BREACH_TEST_{}", Uuid::new_v4()),
|
||||
};
|
||||
|
||||
match trading_client.submit_order(large_order).await {
|
||||
@@ -1243,7 +1233,7 @@ impl ComprehensiveTradingWorkflows {
|
||||
// Step 7: Test market data continuity during emergency
|
||||
if let Some(trading_client) = client.trading() {
|
||||
match trading_client
|
||||
.subscribe_market_data(vec!["AAPL".to_string()])
|
||||
.stream_market_data(vec!["AAPL".to_string()])
|
||||
.await
|
||||
{
|
||||
Ok(mut stream) => {
|
||||
@@ -1292,8 +1282,6 @@ impl ComprehensiveTradingWorkflows {
|
||||
quantity: 100.0,
|
||||
price: None,
|
||||
stop_price: None,
|
||||
time_in_force: "DAY".to_string(),
|
||||
client_order_id: format!("EMERGENCY_ATTEMPT_{}", Uuid::new_v4()),
|
||||
};
|
||||
|
||||
match trading_client.submit_order(emergency_order).await {
|
||||
@@ -1412,8 +1400,6 @@ impl ComprehensiveTradingWorkflows {
|
||||
quantity: 1.0, // Very small order for recovery test
|
||||
price: Some(120.0), // Below market to avoid immediate fill
|
||||
stop_price: None,
|
||||
time_in_force: "IOC".to_string(), // Will cancel if not immediately filled
|
||||
client_order_id: format!("RECOVERY_TEST_{}", Uuid::new_v4()),
|
||||
};
|
||||
|
||||
match trading_client.submit_order(recovery_test_order).await {
|
||||
|
||||
@@ -39,7 +39,7 @@ e2e_test!(
|
||||
|
||||
// Step 3: Subscribe to configuration changes
|
||||
info!("📡 Subscribing to configuration change notifications");
|
||||
let config_stream_request = tli::proto::trading::SubscribeConfigRequest {};
|
||||
let config_stream_request = e2e_tests::proto::trading::SubscribeConfigRequest {};
|
||||
let mut config_stream = trading_client
|
||||
.subscribe_config(config_stream_request)
|
||||
.await?
|
||||
@@ -48,7 +48,7 @@ e2e_test!(
|
||||
// Step 4: Get initial configuration state
|
||||
info!("📋 Getting initial configuration state");
|
||||
let initial_config = trading_client
|
||||
.get_config(tli::proto::trading::GetConfigRequest {})
|
||||
.get_config(e2e_tests::proto::trading::GetConfigRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -98,7 +98,7 @@ e2e_test!(
|
||||
update_params.len()
|
||||
);
|
||||
let update_response = trading_client
|
||||
.update_parameters(tli::proto::trading::UpdateParametersRequest {
|
||||
.update_parameters(e2e_tests::proto::trading::UpdateParametersRequest {
|
||||
parameters: update_params.clone(),
|
||||
})
|
||||
.await?
|
||||
@@ -174,7 +174,7 @@ e2e_test!(
|
||||
// Step 7: Verify updated configuration via direct query
|
||||
info!("🔍 Verifying updated configuration");
|
||||
let updated_config = trading_client
|
||||
.get_config(tli::proto::trading::GetConfigRequest {})
|
||||
.get_config(e2e_tests::proto::trading::GetConfigRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -208,7 +208,7 @@ e2e_test!(
|
||||
invalid_params.insert("max_position_size".to_string(), "not_a_number".to_string()); // Invalid number format
|
||||
|
||||
let invalid_update_response = trading_client
|
||||
.update_parameters(tli::proto::trading::UpdateParametersRequest {
|
||||
.update_parameters(e2e_tests::proto::trading::UpdateParametersRequest {
|
||||
parameters: invalid_params,
|
||||
})
|
||||
.await;
|
||||
@@ -235,7 +235,7 @@ e2e_test!(
|
||||
|
||||
// Check service system status before configuration change
|
||||
let pre_reload_status = trading_client
|
||||
.get_system_status(tli::proto::trading::GetSystemStatusRequest {})
|
||||
.get_system_status(e2e_tests::proto::trading::GetSystemStatusRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -249,7 +249,7 @@ e2e_test!(
|
||||
);
|
||||
|
||||
let hot_reload_response = trading_client
|
||||
.update_parameters(tli::proto::trading::UpdateParametersRequest {
|
||||
.update_parameters(e2e_tests::proto::trading::UpdateParametersRequest {
|
||||
parameters: hot_reload_params,
|
||||
})
|
||||
.await?
|
||||
@@ -265,7 +265,7 @@ e2e_test!(
|
||||
|
||||
// Check service status after configuration change
|
||||
let post_reload_status = trading_client
|
||||
.get_system_status(tli::proto::trading::GetSystemStatusRequest {})
|
||||
.get_system_status(e2e_tests::proto::trading::GetSystemStatusRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -298,7 +298,7 @@ e2e_test!(
|
||||
);
|
||||
|
||||
let rollback_response = trading_client
|
||||
.update_parameters(tli::proto::trading::UpdateParametersRequest {
|
||||
.update_parameters(e2e_tests::proto::trading::UpdateParametersRequest {
|
||||
parameters: original_values,
|
||||
})
|
||||
.await?
|
||||
@@ -312,7 +312,7 @@ e2e_test!(
|
||||
|
||||
// Verify rollback
|
||||
let rollback_config = trading_client
|
||||
.get_config(tli::proto::trading::GetConfigRequest {})
|
||||
.get_config(e2e_tests::proto::trading::GetConfigRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -421,7 +421,7 @@ e2e_test!(
|
||||
info!("📋 Getting initial configurations from multiple services");
|
||||
|
||||
let trading_config = trading_client
|
||||
.get_config(tli::proto::trading::GetConfigRequest {})
|
||||
.get_config(e2e_tests::proto::trading::GetConfigRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -440,7 +440,7 @@ e2e_test!(
|
||||
|
||||
// Update configuration via trading service
|
||||
let sync_response = trading_client
|
||||
.update_parameters(tli::proto::trading::UpdateParametersRequest {
|
||||
.update_parameters(e2e_tests::proto::trading::UpdateParametersRequest {
|
||||
parameters: sync_params,
|
||||
})
|
||||
.await?
|
||||
@@ -456,7 +456,7 @@ e2e_test!(
|
||||
|
||||
// Verify the configuration is synchronized across services
|
||||
let updated_trading_config = trading_client
|
||||
.get_config(tli::proto::trading::GetConfigRequest {})
|
||||
.get_config(e2e_tests::proto::trading::GetConfigRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -492,7 +492,7 @@ e2e_test!(
|
||||
|
||||
for i in 0..retrieval_count {
|
||||
let config = trading_client
|
||||
.get_config(tli::proto::trading::GetConfigRequest {})
|
||||
.get_config(e2e_tests::proto::trading::GetConfigRequest {})
|
||||
.await?;
|
||||
|
||||
assert!(
|
||||
@@ -533,7 +533,7 @@ e2e_test!(
|
||||
);
|
||||
|
||||
let update_response = trading_client
|
||||
.update_parameters(tli::proto::trading::UpdateParametersRequest {
|
||||
.update_parameters(e2e_tests::proto::trading::UpdateParametersRequest {
|
||||
parameters: params,
|
||||
})
|
||||
.await?
|
||||
|
||||
@@ -96,7 +96,7 @@ impl DataFlowPerformanceTests {
|
||||
|
||||
if let Some(trading_client) = client.trading() {
|
||||
match trading_client
|
||||
.subscribe_market_data(symbols.iter().map(|s| s.to_string()).collect())
|
||||
.stream_market_data(symbols.iter().map(|s| s.to_string()).collect())
|
||||
.await
|
||||
{
|
||||
Ok(mut stream) => {
|
||||
|
||||
@@ -24,14 +24,12 @@ e2e_test!(
|
||||
|
||||
// Test 1: Empty symbol
|
||||
info!("Testing empty symbol rejection");
|
||||
let invalid_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let invalid_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 100.0,
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: "INVALID_SYMBOL_TEST".to_string(),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(invalid_order).await;
|
||||
@@ -49,14 +47,12 @@ e2e_test!(
|
||||
|
||||
// Test 2: Zero quantity
|
||||
info!("Testing zero quantity rejection");
|
||||
let zero_qty_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let zero_qty_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 0.0,
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: "ZERO_QTY_TEST".to_string(),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(zero_qty_order).await;
|
||||
@@ -74,14 +70,12 @@ e2e_test!(
|
||||
|
||||
// Test 3: Negative price
|
||||
info!("Testing negative price rejection");
|
||||
let negative_price_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let negative_price_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Limit as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Limit as i32,
|
||||
quantity: 100.0,
|
||||
price: Some(-150.0),
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: "NEGATIVE_PRICE_TEST".to_string(),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(negative_price_order).await;
|
||||
@@ -99,14 +93,12 @@ e2e_test!(
|
||||
|
||||
// Test 4: Invalid symbol format
|
||||
info!("Testing invalid symbol format rejection");
|
||||
let invalid_symbol_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let invalid_symbol_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "INVALID@SYMBOL#123".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 100.0,
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: "INVALID_SYMBOL_FORMAT_TEST".to_string(),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(invalid_symbol_order).await;
|
||||
@@ -157,7 +149,7 @@ e2e_test!(
|
||||
// This should complete quickly
|
||||
let result = tokio::time::timeout(
|
||||
Duration::from_secs(5),
|
||||
trading_client.get_account_info(tli::proto::trading::GetAccountInfoRequest {}),
|
||||
trading_client.get_portfolio_summary(e2e_tests::proto::trading::GetPortfolioSummaryRequest {}),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -288,25 +280,21 @@ e2e_test!(
|
||||
// Mix of valid and invalid orders
|
||||
let order = if i % 3 == 0 {
|
||||
// Invalid order - zero quantity
|
||||
tli::proto::trading::SubmitOrderRequest {
|
||||
e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: format!("TEST{}", i),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 0.0,
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("CONCURRENT_INVALID_{}", i),
|
||||
}
|
||||
} else {
|
||||
// Valid order
|
||||
tli::proto::trading::SubmitOrderRequest {
|
||||
e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: format!("TEST{}", i),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 100.0,
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("CONCURRENT_VALID_{}", i),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -383,14 +371,12 @@ e2e_test!(
|
||||
|
||||
// Test 1: Very large quantity
|
||||
info!("Testing very large quantity handling");
|
||||
let large_qty_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let large_qty_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 1_000_000_000.0,
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: "LARGE_QTY_TEST".to_string(),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(large_qty_order).await;
|
||||
@@ -411,14 +397,12 @@ e2e_test!(
|
||||
|
||||
// Test 2: Very high price
|
||||
info!("Testing very high price handling");
|
||||
let high_price_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let high_price_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Limit as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Limit as i32,
|
||||
quantity: 100.0,
|
||||
price: Some(1_000_000.0),
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: "HIGH_PRICE_TEST".to_string(),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(high_price_order).await;
|
||||
@@ -439,14 +423,12 @@ e2e_test!(
|
||||
|
||||
// Test 3: Special characters in client order ID
|
||||
info!("Testing special characters in order ID");
|
||||
let special_char_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let special_char_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 100.0,
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: "TEST<>?/\\|!@#$%".to_string(),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(special_char_order).await;
|
||||
|
||||
@@ -39,13 +39,16 @@ e2e_test!(
|
||||
|
||||
// Step 3: Subscribe to market data
|
||||
info!("📊 Subscribing to market data for AAPL");
|
||||
let market_data_request = tli::proto::trading::SubscribeMarketDataRequest {
|
||||
let market_data_request = e2e_tests::proto::trading::StreamMarketDataRequest {
|
||||
symbols: vec!["AAPL".to_string()],
|
||||
data_types: vec!["trades".to_string(), "quotes".to_string()],
|
||||
data_types: vec![
|
||||
e2e_tests::proto::trading::MarketDataType::MarketDataTypeTrade as i32,
|
||||
e2e_tests::proto::trading::MarketDataType::MarketDataTypeQuote as i32,
|
||||
],
|
||||
};
|
||||
|
||||
let mut market_data_stream = trading_client
|
||||
.subscribe_market_data(market_data_request)
|
||||
.stream_market_data(market_data_request)
|
||||
.await
|
||||
.context("Failed to subscribe to market data")?
|
||||
.into_inner();
|
||||
@@ -61,7 +64,7 @@ e2e_test!(
|
||||
Some(Ok(market_event)) => {
|
||||
info!("📈 Received market data: {:?}", market_event);
|
||||
if let Some(event) = market_event.event {
|
||||
if let tli::proto::trading::market_data_event::Event::Tick(tick) = event {
|
||||
if let e2e_tests::proto::trading::market_data_event::Event::Tick(tick) = event {
|
||||
last_price = tick.price;
|
||||
market_data_received = true;
|
||||
info!("Current AAPL price: ${:.2}", last_price);
|
||||
@@ -85,7 +88,7 @@ e2e_test!(
|
||||
// Step 5: Get initial account information
|
||||
info!("💼 Getting initial account information");
|
||||
let initial_account = trading_client
|
||||
.get_account_info(tli::proto::trading::GetAccountInfoRequest {})
|
||||
.get_portfolio_summary(e2e_tests::proto::trading::GetPortfolioSummaryRequest {})
|
||||
.await
|
||||
.context("Failed to get initial account info")?
|
||||
.into_inner();
|
||||
@@ -100,7 +103,7 @@ e2e_test!(
|
||||
// Step 6: Check initial positions
|
||||
info!("📊 Getting initial positions");
|
||||
let initial_positions = trading_client
|
||||
.get_positions(tli::proto::trading::GetPositionsRequest {})
|
||||
.get_positions(e2e_tests::proto::trading::GetPositionsRequest {})
|
||||
.await
|
||||
.context("Failed to get initial positions")?
|
||||
.into_inner();
|
||||
@@ -116,20 +119,18 @@ e2e_test!(
|
||||
|
||||
// Step 7: Create and validate order
|
||||
info!("📝 Creating test order");
|
||||
let test_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let test_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 100.0,
|
||||
price: None, // Market order
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("TEST_ORDER_{}", chrono::Utc::now().timestamp_millis()),
|
||||
};
|
||||
|
||||
// Step 8: Validate order with risk management
|
||||
info!("⚖️ Validating order with risk management");
|
||||
let validation_response = trading_client
|
||||
.validate_order(tli::proto::trading::ValidateOrderRequest {
|
||||
.validate_order(e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: test_order.symbol.clone(),
|
||||
side: test_order.side,
|
||||
quantity: test_order.quantity,
|
||||
@@ -164,12 +165,12 @@ e2e_test!(
|
||||
|
||||
// Step 10: Subscribe to order updates
|
||||
info!("📡 Subscribing to order updates");
|
||||
let order_updates_request = tli::proto::trading::SubscribeOrderUpdatesRequest {
|
||||
let order_updates_request = e2e_tests::proto::trading::StreamOrdersRequest {
|
||||
filter_by_symbol: Some("AAPL".to_string()),
|
||||
};
|
||||
|
||||
let mut order_updates_stream = trading_client
|
||||
.subscribe_order_updates(order_updates_request)
|
||||
.stream_orders(order_updates_request)
|
||||
.await
|
||||
.context("Failed to subscribe to order updates")?
|
||||
.into_inner();
|
||||
@@ -187,7 +188,7 @@ e2e_test!(
|
||||
Some(Ok(order_update)) => {
|
||||
info!("📋 Order update: {:?}", order_update);
|
||||
if order_update.order_id == order_id {
|
||||
if order_update.status == tli::proto::trading::OrderStatus::Filled as i32 {
|
||||
if order_update.status == e2e_tests::proto::trading::OrderStatus::Filled as i32 {
|
||||
order_filled = true;
|
||||
fill_price = order_update.last_fill_price;
|
||||
filled_quantity = order_update.filled_quantity;
|
||||
@@ -217,7 +218,7 @@ e2e_test!(
|
||||
// Step 12: Verify order status
|
||||
info!("🔍 Checking final order status");
|
||||
let order_status = trading_client
|
||||
.get_order_status(tli::proto::trading::GetOrderStatusRequest {
|
||||
.get_order_status(e2e_tests::proto::trading::GetOrderStatusRequest {
|
||||
order_id: order_id.clone(),
|
||||
})
|
||||
.await
|
||||
@@ -231,7 +232,7 @@ e2e_test!(
|
||||
// Step 13: Verify position update
|
||||
info!("📊 Verifying position update");
|
||||
let updated_positions = trading_client
|
||||
.get_positions(tli::proto::trading::GetPositionsRequest {})
|
||||
.get_positions(e2e_tests::proto::trading::GetPositionsRequest {})
|
||||
.await
|
||||
.context("Failed to get updated positions")?
|
||||
.into_inner();
|
||||
@@ -261,7 +262,7 @@ e2e_test!(
|
||||
// Step 14: Verify account balance update
|
||||
info!("💰 Verifying account balance update");
|
||||
let final_account = trading_client
|
||||
.get_account_info(tli::proto::trading::GetAccountInfoRequest {})
|
||||
.get_portfolio_summary(e2e_tests::proto::trading::GetPortfolioSummaryRequest {})
|
||||
.await
|
||||
.context("Failed to get final account info")?
|
||||
.into_inner();
|
||||
@@ -286,7 +287,7 @@ e2e_test!(
|
||||
// Step 15: Check risk metrics after trade
|
||||
info!("⚖️ Checking risk metrics after trade");
|
||||
let risk_metrics = trading_client
|
||||
.get_risk_metrics(tli::proto::trading::GetRiskMetricsRequest {})
|
||||
.get_risk_metrics(e2e_tests::proto::risk::GetRiskMetricsRequest {})
|
||||
.await
|
||||
.context("Failed to get risk metrics")?
|
||||
.into_inner();
|
||||
@@ -349,14 +350,12 @@ e2e_test!(
|
||||
let trading_client = framework.get_trading_client().await?;
|
||||
|
||||
// Submit a limit order that won't fill immediately
|
||||
let test_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let test_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Limit as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Limit as i32,
|
||||
quantity: 100.0,
|
||||
price: Some(50.0), // Very low price that won't fill
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("CANCEL_TEST_{}", chrono::Utc::now().timestamp_millis()),
|
||||
};
|
||||
|
||||
info!("📝 Submitting limit order that won't fill");
|
||||
@@ -374,7 +373,7 @@ e2e_test!(
|
||||
|
||||
// Check order status - should be pending
|
||||
let order_status = trading_client
|
||||
.get_order_status(tli::proto::trading::GetOrderStatusRequest {
|
||||
.get_order_status(e2e_tests::proto::trading::GetOrderStatusRequest {
|
||||
order_id: order_id.clone(),
|
||||
})
|
||||
.await?
|
||||
@@ -385,7 +384,7 @@ e2e_test!(
|
||||
// Cancel the order
|
||||
info!("❌ Cancelling order");
|
||||
let cancel_response = trading_client
|
||||
.cancel_order(tli::proto::trading::CancelOrderRequest {
|
||||
.cancel_order(e2e_tests::proto::trading::CancelOrderRequest {
|
||||
order_id: order_id.clone(),
|
||||
})
|
||||
.await?
|
||||
@@ -396,7 +395,7 @@ e2e_test!(
|
||||
|
||||
// Verify cancellation
|
||||
let final_status = trading_client
|
||||
.get_order_status(tli::proto::trading::GetOrderStatusRequest {
|
||||
.get_order_status(e2e_tests::proto::trading::GetOrderStatusRequest {
|
||||
order_id: order_id.clone(),
|
||||
})
|
||||
.await?
|
||||
@@ -416,20 +415,18 @@ e2e_test!(
|
||||
let trading_client = framework.get_trading_client().await?;
|
||||
|
||||
// Try to submit a very large order that should be rejected
|
||||
let large_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let large_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 1000000.0, // 1 million shares - should be rejected
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("RISK_TEST_{}", chrono::Utc::now().timestamp_millis()),
|
||||
};
|
||||
|
||||
// First validate the order - should be rejected
|
||||
info!("🚫 Validating large order (should be rejected)");
|
||||
let validation = trading_client
|
||||
.validate_order(tli::proto::trading::ValidateOrderRequest {
|
||||
.validate_order(e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: large_order.symbol.clone(),
|
||||
side: large_order.side,
|
||||
quantity: large_order.quantity,
|
||||
|
||||
@@ -177,13 +177,15 @@ e2e_test!(
|
||||
let trading_client = framework.get_trading_client().await?;
|
||||
|
||||
// Subscribe to market data
|
||||
let market_data_request = tli::proto::trading::SubscribeMarketDataRequest {
|
||||
let market_data_request = e2e_tests::proto::trading::StreamMarketDataRequest {
|
||||
symbols: vec!["AAPL".to_string()],
|
||||
data_types: vec!["trades".to_string()],
|
||||
data_types: vec![
|
||||
e2e_tests::proto::trading::MarketDataType::MarketDataTypeTrade as i32,
|
||||
],
|
||||
};
|
||||
|
||||
let mut market_stream = trading_client
|
||||
.subscribe_market_data(market_data_request)
|
||||
.stream_market_data(market_data_request)
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -199,7 +201,7 @@ e2e_test!(
|
||||
market_event = market_stream.next() => {
|
||||
match market_event {
|
||||
Some(Ok(event)) => {
|
||||
if let Some(tli::proto::trading::market_data_event::Event::Tick(tick)) = event.event {
|
||||
if let Some(e2e_tests::proto::trading::market_data_event::Event::Tick(tick)) = event.event {
|
||||
let inference_start = Instant::now();
|
||||
|
||||
// Convert to our MarketTick format
|
||||
|
||||
@@ -105,19 +105,19 @@ e2e_test!(
|
||||
info!("🎯 ML signal strong enough to generate trading order");
|
||||
|
||||
let side = if prediction.signal > 0.0 {
|
||||
tli::proto::trading::OrderSide::Buy
|
||||
e2e_tests::proto::trading::OrderSide::Buy
|
||||
} else {
|
||||
tli::proto::trading::OrderSide::Sell
|
||||
e2e_tests::proto::trading::OrderSide::Sell
|
||||
};
|
||||
|
||||
// Validate potential order with risk management
|
||||
let validation = trading_client
|
||||
.validate_order(tli::proto::trading::ValidateOrderRequest {
|
||||
.validate_order(e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: side as i32,
|
||||
quantity: 100.0,
|
||||
price: 150.0,
|
||||
order_type: tli::proto::trading::OrderType::Limit as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Limit as i32,
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
@@ -166,7 +166,7 @@ e2e_test!(
|
||||
|
||||
// Get current trading configuration
|
||||
let trading_config = trading_client
|
||||
.get_config(tli::proto::trading::GetConfigRequest {})
|
||||
.get_config(e2e_tests::proto::trading::GetConfigRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -270,9 +270,9 @@ e2e_test!(
|
||||
for symbol in &symbols {
|
||||
if prediction.signal.abs() > 0.5 {
|
||||
let side = if prediction.signal > 0.0 {
|
||||
tli::proto::trading::OrderSide::Buy
|
||||
e2e_tests::proto::trading::OrderSide::Buy
|
||||
} else {
|
||||
tli::proto::trading::OrderSide::Sell
|
||||
e2e_tests::proto::trading::OrderSide::Sell
|
||||
};
|
||||
|
||||
orders_to_execute.push((symbol.to_string(), side, 100.0));
|
||||
@@ -286,12 +286,12 @@ e2e_test!(
|
||||
|
||||
for (symbol, side, quantity) in orders_to_execute {
|
||||
let validation = trading_client
|
||||
.validate_order(tli::proto::trading::ValidateOrderRequest {
|
||||
.validate_order(e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: symbol.clone(),
|
||||
side: side as i32,
|
||||
quantity,
|
||||
price: 150.0,
|
||||
order_type: tli::proto::trading::OrderType::Limit as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Limit as i32,
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -29,18 +29,16 @@ e2e_test!(
|
||||
let mut failed_orders = 0;
|
||||
|
||||
for i in 0..num_orders {
|
||||
let order = tli::proto::trading::SubmitOrderRequest {
|
||||
let order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: if i % 2 == 0 {
|
||||
tli::proto::trading::OrderSide::Buy
|
||||
e2e_tests::proto::trading::OrderSide::Buy
|
||||
} else {
|
||||
tli::proto::trading::OrderSide::Sell
|
||||
e2e_tests::proto::trading::OrderSide::Sell
|
||||
} as i32,
|
||||
order_type: tli::proto::trading::OrderType::Limit as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Limit as i32,
|
||||
quantity: 100.0,
|
||||
price: Some(150.0 + (i as f64 * 0.1)),
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("THROUGHPUT_TEST_{}", i),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(order).await;
|
||||
@@ -117,14 +115,12 @@ e2e_test!(
|
||||
|
||||
let handle = tokio::spawn(async move {
|
||||
for order_id in 0..orders_per_user {
|
||||
let order = tli::proto::trading::SubmitOrderRequest {
|
||||
let order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "MSFT".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 50.0 + (order_id as f64 * 10.0),
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("CONCURRENT_U{}_O{}", user_id, order_id),
|
||||
};
|
||||
|
||||
match client.submit_order(order).await {
|
||||
@@ -325,12 +321,12 @@ e2e_test!(
|
||||
let start = Instant::now();
|
||||
|
||||
let _result = trading_client
|
||||
.validate_order(tli::proto::trading::ValidateOrderRequest {
|
||||
.validate_order(e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
quantity: 100.0,
|
||||
price: 150.0,
|
||||
order_type: tli::proto::trading::OrderType::Limit as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Limit as i32,
|
||||
})
|
||||
.await;
|
||||
|
||||
@@ -417,7 +413,7 @@ e2e_test!(
|
||||
|
||||
while start.elapsed() < test_duration {
|
||||
let _result = trading_client
|
||||
.get_account_info(tli::proto::trading::GetAccountInfoRequest {})
|
||||
.get_portfolio_summary(e2e_tests::proto::trading::GetPortfolioSummaryRequest {})
|
||||
.await;
|
||||
|
||||
match _result {
|
||||
|
||||
@@ -32,7 +32,7 @@ e2e_test!(
|
||||
// Step 2: Get initial risk metrics baseline
|
||||
info!("📊 Getting initial risk metrics baseline");
|
||||
let initial_metrics = trading_client
|
||||
.get_risk_metrics(tli::proto::trading::GetRiskMetricsRequest {})
|
||||
.get_risk_metrics(e2e_tests::proto::risk::GetRiskMetricsRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -62,7 +62,7 @@ e2e_test!(
|
||||
// Step 3: Test portfolio VaR calculation
|
||||
info!("💼 Testing portfolio VaR calculation");
|
||||
let var_response = trading_client
|
||||
.get_va_r(tli::proto::trading::GetVaRRequest {})
|
||||
.get_va_r(e2e_tests::proto::trading::GetVaRRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -82,7 +82,7 @@ e2e_test!(
|
||||
// Step 4: Test position risk assessment
|
||||
info!("🎯 Testing position risk assessment");
|
||||
let position_risk = trading_client
|
||||
.get_position_risk(tli::proto::trading::GetPositionRiskRequest {
|
||||
.get_position_risk(e2e_tests::proto::trading::GetPositionRiskRequest {
|
||||
symbol: Some("AAPL".to_string()),
|
||||
})
|
||||
.await?
|
||||
@@ -121,12 +121,12 @@ e2e_test!(
|
||||
|
||||
// Test a normal order that should pass
|
||||
let normal_order_validation = trading_client
|
||||
.validate_order(tli::proto::trading::ValidateOrderRequest {
|
||||
.validate_order(e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
quantity: 100.0,
|
||||
price: 150.0,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
@@ -142,12 +142,12 @@ e2e_test!(
|
||||
|
||||
// Test a large order that might be rejected
|
||||
let large_order_validation = trading_client
|
||||
.validate_order(tli::proto::trading::ValidateOrderRequest {
|
||||
.validate_order(e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
quantity: 100000.0, // Very large order
|
||||
price: 150.0,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
@@ -183,7 +183,7 @@ e2e_test!(
|
||||
// Step 6: Test real-time risk alerts
|
||||
info!("🚨 Testing real-time risk alert system");
|
||||
|
||||
let risk_alerts_request = tli::proto::trading::SubscribeRiskAlertsRequest {};
|
||||
let risk_alerts_request = e2e_tests::proto::trading::SubscribeRiskAlertsRequest {};
|
||||
let mut risk_alerts_stream = trading_client
|
||||
.subscribe_risk_alerts(risk_alerts_request)
|
||||
.await?
|
||||
@@ -238,14 +238,12 @@ e2e_test!(
|
||||
let test_orders = 5;
|
||||
|
||||
for i in 0..test_orders {
|
||||
let large_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let large_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 50000.0, // Large quantity
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("CIRCUIT_TEST_{}", i),
|
||||
};
|
||||
|
||||
let result = trading_client.submit_order(large_order).await;
|
||||
@@ -290,7 +288,7 @@ e2e_test!(
|
||||
|
||||
// Trigger emergency stop
|
||||
let emergency_response = trading_client
|
||||
.emergency_stop(tli::proto::trading::EmergencyStopRequest {})
|
||||
.emergency_stop(e2e_tests::proto::trading::EmergencyStopRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -319,14 +317,12 @@ e2e_test!(
|
||||
info!("🔍 Verifying system state after emergency stop");
|
||||
|
||||
// Try to submit an order after emergency stop - should be rejected
|
||||
let post_emergency_order = tli::proto::trading::SubmitOrderRequest {
|
||||
let post_emergency_order = e2e_tests::proto::trading::SubmitOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
quantity: 100.0,
|
||||
price: None,
|
||||
time_in_force: tli::proto::trading::TimeInForce::Day as i32,
|
||||
client_order_id: format!("POST_EMERGENCY_TEST"),
|
||||
};
|
||||
|
||||
let post_emergency_result = trading_client.submit_order(post_emergency_order).await;
|
||||
@@ -351,7 +347,7 @@ e2e_test!(
|
||||
// Step 10: Test final risk metrics
|
||||
info!("📈 Getting final risk metrics");
|
||||
let final_metrics = trading_client
|
||||
.get_risk_metrics(tli::proto::trading::GetRiskMetricsRequest {})
|
||||
.get_risk_metrics(e2e_tests::proto::risk::GetRiskMetricsRequest {})
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
@@ -424,12 +420,12 @@ e2e_test!(
|
||||
info!("🎯 Testing scenario: {}", scenario.name);
|
||||
|
||||
let validation = trading_client
|
||||
.validate_order(tli::proto::trading::ValidateOrderRequest {
|
||||
.validate_order(e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: scenario.symbol.clone(),
|
||||
side: tli::proto::trading::OrderSide::Buy as i32,
|
||||
side: e2e_tests::proto::trading::OrderSide::Buy as i32,
|
||||
quantity: scenario.quantity,
|
||||
price: 100.0,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
@@ -475,16 +471,16 @@ e2e_test!(
|
||||
let mut failed_validations = 0;
|
||||
|
||||
for i in 0..validation_count {
|
||||
let validation_request = tli::proto::trading::ValidateOrderRequest {
|
||||
let validation_request = e2e_tests::proto::risk::ValidateOrderRequest {
|
||||
symbol: "AAPL".to_string(),
|
||||
side: if i % 2 == 0 {
|
||||
tli::proto::trading::OrderSide::Buy as i32
|
||||
e2e_tests::proto::trading::OrderSide::Buy as i32
|
||||
} else {
|
||||
tli::proto::trading::OrderSide::Sell as i32
|
||||
e2e_tests::proto::trading::OrderSide::Sell as i32
|
||||
},
|
||||
quantity: 100.0 + (i as f64 * 10.0),
|
||||
price: 150.0,
|
||||
order_type: tli::proto::trading::OrderType::Market as i32,
|
||||
order_type: e2e_tests::proto::trading::OrderType::Market as i32,
|
||||
};
|
||||
|
||||
match trading_client.validate_order(validation_request).await {
|
||||
@@ -537,7 +533,7 @@ e2e_test!(
|
||||
let client = framework.get_trading_client().await?.clone();
|
||||
let handle = tokio::spawn(async move {
|
||||
client
|
||||
.get_risk_metrics(tli::proto::trading::GetRiskMetricsRequest {})
|
||||
.get_risk_metrics(e2e_tests::proto::risk::GetRiskMetricsRequest {})
|
||||
.await
|
||||
.map(|r| r.into_inner())
|
||||
});
|
||||
|
||||
@@ -365,8 +365,7 @@ pub mod config {
|
||||
///
|
||||
/// # Returns
|
||||
/// A string in the format "TEST_{counter}"
|
||||
#[allow(dead_code)]
|
||||
fn generate_test_id() -> String {
|
||||
pub fn generate_test_id() -> String {
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
static COUNTER: AtomicU64 = AtomicU64::new(1);
|
||||
format!("TEST_{}", COUNTER.fetch_add(1, Ordering::SeqCst))
|
||||
@@ -374,6 +373,10 @@ fn generate_test_id() -> String {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::TestConfig;
|
||||
use crate::mocks::MockMarketDataProvider;
|
||||
use rust_decimal::Decimal;
|
||||
|
||||
#[test]
|
||||
fn test_lib_imports() {
|
||||
|
||||
@@ -24,16 +24,7 @@ pub fn init_test_logging() {
|
||||
|
||||
/// Test configuration constants
|
||||
pub mod constants {
|
||||
use common::error::CommonError;
|
||||
use common::error::CommonResult;
|
||||
use common::database::DatabaseConfig;
|
||||
use common::database::DatabasePool;
|
||||
use common::Order;
|
||||
use common::Position;
|
||||
use common::Symbol;
|
||||
use common::Price;
|
||||
use common::Quantity;
|
||||
use common::HftTimestamp;
|
||||
use rust_decimal::Decimal;
|
||||
use std::time::Duration;
|
||||
|
||||
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
|
||||
Reference in New Issue
Block a user