Move 17 library crates into crates/, CLI binary into bin/fxt, consolidate 10 test crates into testing/, split config crate from deployment config files. Root directory reduced from 38+ to ~17 directories. All Cargo.toml paths and build.rs proto refs updated. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
231 lines
8.5 KiB
Rust
231 lines
8.5 KiB
Rust
//! Configuration schemas and cloud storage configurations.
|
|
//!
|
|
//! This module defines configuration schemas for various cloud storage backends
|
|
//! and configuration versioning. Primarily focused on S3-compatible storage
|
|
//! for model artifacts and configuration management in the Foxhunt trading system.
|
|
|
|
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::collections::HashMap;
|
|
use std::time::Duration;
|
|
use uuid::Uuid;
|
|
|
|
/// Configuration schema metadata for versioning and tracking.
|
|
///
|
|
/// Provides versioning and audit trail information for configuration schemas.
|
|
///
|
|
/// Used to track configuration changes over time and maintain compatibility
|
|
/// across different versions of the trading system.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ConfigSchema {
|
|
/// Unique identifier for this configuration schema
|
|
pub id: Uuid,
|
|
/// Semantic version string (e.g., "1.2.3")
|
|
pub version: String,
|
|
/// Timestamp when this schema was created
|
|
pub created_at: DateTime<Utc>,
|
|
/// Timestamp when this schema was last updated
|
|
pub updated_at: DateTime<Utc>,
|
|
}
|
|
|
|
/// Amazon S3 and S3-compatible storage configuration.
|
|
///
|
|
/// Configures access to S3 or S3-compatible storage services for storing
|
|
///
|
|
/// ML model artifacts, configuration backups, and other binary data.
|
|
///
|
|
/// Supports various authentication methods and connection options.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct S3Config {
|
|
/// S3 bucket name for storing model artifacts and data
|
|
pub bucket_name: String,
|
|
/// AWS region or S3-compatible service region
|
|
pub region: String,
|
|
/// AWS access key ID (optional, can use IAM roles or environment variables)
|
|
pub access_key_id: Option<String>,
|
|
/// AWS secret access key (optional, can use IAM roles or environment variables)
|
|
pub secret_access_key: Option<String>,
|
|
/// AWS session token for temporary credentials (optional)
|
|
pub session_token: Option<String>,
|
|
/// Custom S3-compatible endpoint URL (e.g., MinIO, DigitalOcean Spaces)
|
|
pub endpoint_url: Option<String>,
|
|
/// Force path-style URLs instead of virtual-hosted-style URLs
|
|
pub force_path_style: bool,
|
|
/// Request timeout duration for S3 operations
|
|
pub timeout: Duration,
|
|
/// Maximum number of retry attempts for failed requests
|
|
pub max_retry_attempts: u32,
|
|
/// Enable SSL/TLS for S3 connections
|
|
pub use_ssl: bool,
|
|
}
|
|
|
|
impl S3Config {
|
|
/// Validates the S3 configuration for correctness.
|
|
///
|
|
/// Performs validation checks on the S3 configuration to ensure all
|
|
/// required fields are present and have valid values before attempting
|
|
/// to establish connections to S3 services.
|
|
///
|
|
/// # Errors
|
|
///
|
|
/// Returns an error string if the configuration is invalid:
|
|
/// - Empty bucket name
|
|
///
|
|
/// - Empty region
|
|
/// - Invalid endpoint URL format
|
|
pub fn validate(&self) -> Result<(), String> {
|
|
if self.bucket_name.is_empty() {
|
|
return Err("S3 bucket name cannot be empty".to_owned());
|
|
}
|
|
if self.region.is_empty() {
|
|
return Err("S3 region cannot be empty".to_owned());
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Create S3Config for testing purposes (generic testing)
|
|
#[cfg(test)]
|
|
pub fn default_for_testing(bucket: &str) -> Self {
|
|
Self {
|
|
bucket_name: bucket.to_owned(),
|
|
region: "us-east-1".to_owned(),
|
|
access_key_id: None,
|
|
secret_access_key: None,
|
|
session_token: None,
|
|
endpoint_url: None,
|
|
force_path_style: false,
|
|
timeout: Duration::from_secs(30),
|
|
max_retry_attempts: 3,
|
|
use_ssl: true,
|
|
}
|
|
}
|
|
|
|
/// Create S3Config for MinIO testing (real S3-compatible testing)
|
|
///
|
|
/// Available in test mode or when test-utils feature is enabled
|
|
pub fn for_minio_testing(bucket: &str) -> Self {
|
|
Self {
|
|
bucket_name: bucket.to_owned(),
|
|
region: "us-east-1".to_owned(),
|
|
access_key_id: Some("foxhunt_test".to_owned()),
|
|
secret_access_key: Some("foxhunt_test_password".to_owned()),
|
|
session_token: None,
|
|
endpoint_url: Some("http://localhost:9000".to_owned()),
|
|
force_path_style: true, // MinIO requires path-style
|
|
timeout: Duration::from_secs(30),
|
|
max_retry_attempts: 3,
|
|
use_ssl: false, // Local MinIO uses HTTP
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Schema-level asset classification configuration for sector and type categorization.
|
|
///
|
|
/// Provides configuration-driven asset classification that replaces hardcoded
|
|
/// symbol-based classification logic. Supports flexible categorization rules
|
|
/// based on instrument properties rather than specific symbol names.
|
|
///
|
|
/// **Note**: This is a simpler schema-level config. For full asset classification
|
|
/// with volatility profiles and pattern rules, use `structures::AssetClassificationConfig`.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AssetClassificationSchema {
|
|
/// Classification rules based on asset type patterns
|
|
pub asset_type_rules: HashMap<String, String>,
|
|
/// Default classifications for different asset categories
|
|
pub default_sectors: HashMap<String, String>,
|
|
/// Regex patterns for currency pair detection
|
|
pub currency_patterns: Vec<String>,
|
|
/// Regex patterns for cryptocurrency detection
|
|
pub crypto_patterns: Vec<String>,
|
|
}
|
|
|
|
impl AssetClassificationSchema {
|
|
/// Creates a new asset classification schema with default rules.
|
|
pub fn new() -> Self {
|
|
let mut asset_type_rules = HashMap::new();
|
|
asset_type_rules.insert("EQUITY".to_owned(), "Equity".to_owned());
|
|
asset_type_rules.insert("FOREX".to_owned(), "Currencies".to_owned());
|
|
asset_type_rules.insert("CRYPTO".to_owned(), "Cryptocurrency".to_owned());
|
|
asset_type_rules.insert("COMMODITY".to_owned(), "Commodities".to_owned());
|
|
asset_type_rules.insert("BOND".to_owned(), "Fixed Income".to_owned());
|
|
|
|
let mut default_sectors = HashMap::new();
|
|
default_sectors.insert("Equity".to_owned(), "Other".to_owned());
|
|
default_sectors.insert("Currencies".to_owned(), "Currencies".to_owned());
|
|
default_sectors.insert("Cryptocurrency".to_owned(), "Cryptocurrency".to_owned());
|
|
default_sectors.insert("Commodities".to_owned(), "Commodities".to_owned());
|
|
default_sectors.insert("Fixed Income".to_owned(), "Fixed Income".to_owned());
|
|
|
|
Self {
|
|
asset_type_rules,
|
|
default_sectors,
|
|
currency_patterns: vec![
|
|
r"^[A-Z]{3}[A-Z]{3}$".to_owned(), // USDEUR format
|
|
r".*USD.*".to_owned(),
|
|
r".*EUR.*".to_owned(),
|
|
r".*GBP.*".to_owned(),
|
|
r".*JPY.*".to_owned(),
|
|
],
|
|
crypto_patterns: vec![
|
|
r".*BTC.*".to_owned(),
|
|
r".*ETH.*".to_owned(),
|
|
r".*CRYPTO.*".to_owned(),
|
|
],
|
|
}
|
|
}
|
|
|
|
/// Classifies an instrument based on configuration rules.
|
|
pub fn classify_sector(&self, instrument_id: &str, asset_type: Option<&str>) -> String {
|
|
// First try to classify based on asset type if provided
|
|
if let Some(asset_type) = asset_type {
|
|
if let Some(sector) = self.asset_type_rules.get(asset_type) {
|
|
return sector.clone();
|
|
}
|
|
}
|
|
|
|
// Check for currency patterns
|
|
for pattern in &self.currency_patterns {
|
|
if let Ok(regex) = regex::Regex::new(pattern) {
|
|
if regex.is_match(instrument_id) {
|
|
return "Currencies".to_owned();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check for crypto patterns
|
|
for pattern in &self.crypto_patterns {
|
|
if let Ok(regex) = regex::Regex::new(pattern) {
|
|
if regex.is_match(instrument_id) {
|
|
return "Cryptocurrency".to_owned();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Default classification
|
|
"Other".to_owned()
|
|
}
|
|
}
|
|
|
|
impl Default for AssetClassificationSchema {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Default for S3Config {
|
|
fn default() -> Self {
|
|
Self {
|
|
bucket_name: "foxhunt-models".to_owned(),
|
|
region: "us-east-1".to_owned(),
|
|
access_key_id: None,
|
|
secret_access_key: None,
|
|
session_token: None,
|
|
endpoint_url: None,
|
|
force_path_style: false,
|
|
timeout: Duration::from_secs(30),
|
|
max_retry_attempts: 3,
|
|
use_ssl: true,
|
|
}
|
|
}
|
|
}
|