use crate::internal::domain::{AccountId, ErrorCode, GatewayError};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct LiveTradingConfig {
pub enabled: bool,
pub allowed_accounts: Vec<AccountId>,
pub risk_policy_id: Option<String>,
pub paper_to_live_checklist_acknowledged: bool,
#[serde(default = "default_live_reconciler_interval_seconds")]
pub reconciler_interval_seconds: u64,
}
impl Default for LiveTradingConfig {
fn default() -> Self {
Self {
enabled: false,
allowed_accounts: Vec::new(),
risk_policy_id: None,
paper_to_live_checklist_acknowledged: false,
reconciler_interval_seconds: default_live_reconciler_interval_seconds(),
}
}
}
pub fn validate_live_trading_config(
config: &LiveTradingConfig,
safety_live_enabled: bool,
) -> Result<(), GatewayError> {
if safety_live_enabled && !config.enabled {
return Err(live_config_error(
"Live trading safety flag is enabled but live trading config is disabled",
"Enable live_trading.enabled or disable safety.live_trading_enabled",
));
}
if config.enabled && !safety_live_enabled {
return Err(live_config_error(
"Live trading requires the independent safety flag",
"Set safety.live_trading_enabled only after completing live readiness checks",
));
}
if config.enabled && config.allowed_accounts.is_empty() {
return Err(live_config_error(
"Live trading requires an explicit account allowlist",
"Add at least one live account id to the allowlist",
));
}
if config.enabled && config.risk_policy_id.is_none() {
return Err(live_config_error(
"Live trading requires an explicit risk policy id",
"Configure live_trading.risk_policy_id",
));
}
if config.enabled && !config.paper_to_live_checklist_acknowledged {
return Err(live_config_error(
"Live trading requires paper-to-live checklist acknowledgement",
"Complete and acknowledge the paper-to-live checklist",
));
}
Ok(())
}
const fn default_live_reconciler_interval_seconds() -> u64 {
5
}
fn live_config_error(message: &str, user_action: &str) -> GatewayError {
GatewayError::new(
ErrorCode::ConfigLiveTradingForbidden,
message,
false,
Some(user_action.to_string()),
)
}