/home/jgrusewski/Work/foxhunt/config/src/schemas.rs
Line | Count | Source |
1 | | //! Configuration schemas and cloud storage configurations. |
2 | | //! |
3 | | //! This module defines configuration schemas for various cloud storage backends |
4 | | //! and configuration versioning. Primarily focused on S3-compatible storage |
5 | | //! for model artifacts and configuration management in the Foxhunt trading system. |
6 | | |
7 | | use chrono::{DateTime, Utc}; |
8 | | use serde::{Deserialize, Serialize}; |
9 | | use std::collections::HashMap; |
10 | | use std::time::Duration; |
11 | | use uuid::Uuid; |
12 | | |
13 | | /// Configuration schema metadata for versioning and tracking. |
14 | | /// |
15 | | /// Provides versioning and audit trail information for configuration schemas. |
16 | | /// Used to track configuration changes over time and maintain compatibility |
17 | | /// across different versions of the trading system. |
18 | | #[derive(Debug, Clone, Serialize, Deserialize)] |
19 | | pub struct ConfigSchema { |
20 | | /// Unique identifier for this configuration schema |
21 | | pub id: Uuid, |
22 | | /// Semantic version string (e.g., "1.2.3") |
23 | | pub version: String, |
24 | | /// Timestamp when this schema was created |
25 | | pub created_at: DateTime<Utc>, |
26 | | /// Timestamp when this schema was last updated |
27 | | pub updated_at: DateTime<Utc>, |
28 | | } |
29 | | |
30 | | /// Amazon S3 and S3-compatible storage configuration. |
31 | | /// |
32 | | /// Configures access to S3 or S3-compatible storage services for storing |
33 | | /// ML model artifacts, configuration backups, and other binary data. |
34 | | /// Supports various authentication methods and connection options. |
35 | | #[derive(Debug, Clone, Serialize, Deserialize)] |
36 | | pub struct S3Config { |
37 | | /// S3 bucket name for storing model artifacts and data |
38 | | pub bucket_name: String, |
39 | | /// AWS region or S3-compatible service region |
40 | | pub region: String, |
41 | | /// AWS access key ID (optional, can use IAM roles or environment variables) |
42 | | pub access_key_id: Option<String>, |
43 | | /// AWS secret access key (optional, can use IAM roles or environment variables) |
44 | | pub secret_access_key: Option<String>, |
45 | | /// AWS session token for temporary credentials (optional) |
46 | | pub session_token: Option<String>, |
47 | | /// Custom S3-compatible endpoint URL (e.g., MinIO, DigitalOcean Spaces) |
48 | | pub endpoint_url: Option<String>, |
49 | | /// Force path-style URLs instead of virtual-hosted-style URLs |
50 | | pub force_path_style: bool, |
51 | | /// Request timeout duration for S3 operations |
52 | | pub timeout: Duration, |
53 | | /// Maximum number of retry attempts for failed requests |
54 | | pub max_retry_attempts: u32, |
55 | | /// Enable SSL/TLS for S3 connections |
56 | | pub use_ssl: bool, |
57 | | } |
58 | | |
59 | | impl S3Config { |
60 | | /// Validates the S3 configuration for correctness. |
61 | | /// |
62 | | /// Performs validation checks on the S3 configuration to ensure all |
63 | | /// required fields are present and have valid values before attempting |
64 | | /// to establish connections to S3 services. |
65 | | /// |
66 | | /// # Errors |
67 | | /// |
68 | | /// Returns an error string if the configuration is invalid: |
69 | | /// - Empty bucket name |
70 | | /// - Empty region |
71 | | /// - Invalid endpoint URL format |
72 | 0 | pub fn validate(&self) -> Result<(), String> { |
73 | 0 | if self.bucket_name.is_empty() { |
74 | 0 | return Err("S3 bucket name cannot be empty".to_string()); |
75 | 0 | } |
76 | 0 | if self.region.is_empty() { |
77 | 0 | return Err("S3 region cannot be empty".to_string()); |
78 | 0 | } |
79 | 0 | Ok(()) |
80 | 0 | } |
81 | | } |
82 | | |
83 | | /// Asset classification configuration for sector and type categorization. |
84 | | /// |
85 | | /// Provides configuration-driven asset classification that replaces hardcoded |
86 | | /// symbol-based classification logic. Supports flexible categorization rules |
87 | | /// based on instrument properties rather than specific symbol names. |
88 | | #[derive(Debug, Clone, Serialize, Deserialize)] |
89 | | pub struct AssetClassificationConfig { |
90 | | /// Classification rules based on asset type patterns |
91 | | pub asset_type_rules: HashMap<String, String>, |
92 | | /// Default classifications for different asset categories |
93 | | pub default_sectors: HashMap<String, String>, |
94 | | /// Regex patterns for currency pair detection |
95 | | pub currency_patterns: Vec<String>, |
96 | | /// Regex patterns for cryptocurrency detection |
97 | | pub crypto_patterns: Vec<String>, |
98 | | } |
99 | | |
100 | | impl AssetClassificationConfig { |
101 | | /// Creates a new asset classification configuration with default rules. |
102 | 0 | pub fn new() -> Self { |
103 | 0 | let mut asset_type_rules = HashMap::new(); |
104 | 0 | asset_type_rules.insert("EQUITY".to_string(), "Equity".to_string()); |
105 | 0 | asset_type_rules.insert("FOREX".to_string(), "Currencies".to_string()); |
106 | 0 | asset_type_rules.insert("CRYPTO".to_string(), "Cryptocurrency".to_string()); |
107 | 0 | asset_type_rules.insert("COMMODITY".to_string(), "Commodities".to_string()); |
108 | 0 | asset_type_rules.insert("BOND".to_string(), "Fixed Income".to_string()); |
109 | | |
110 | 0 | let mut default_sectors = HashMap::new(); |
111 | 0 | default_sectors.insert("Equity".to_string(), "Other".to_string()); |
112 | 0 | default_sectors.insert("Currencies".to_string(), "Currencies".to_string()); |
113 | 0 | default_sectors.insert("Cryptocurrency".to_string(), "Cryptocurrency".to_string()); |
114 | 0 | default_sectors.insert("Commodities".to_string(), "Commodities".to_string()); |
115 | 0 | default_sectors.insert("Fixed Income".to_string(), "Fixed Income".to_string()); |
116 | | |
117 | 0 | Self { |
118 | 0 | asset_type_rules, |
119 | 0 | default_sectors, |
120 | 0 | currency_patterns: vec![ |
121 | 0 | r"^[A-Z]{3}[A-Z]{3}$".to_string(), // USDEUR format |
122 | 0 | r".*USD.*".to_string(), |
123 | 0 | r".*EUR.*".to_string(), |
124 | 0 | r".*GBP.*".to_string(), |
125 | 0 | r".*JPY.*".to_string(), |
126 | 0 | ], |
127 | 0 | crypto_patterns: vec![ |
128 | 0 | r".*BTC.*".to_string(), |
129 | 0 | r".*ETH.*".to_string(), |
130 | 0 | r".*CRYPTO.*".to_string(), |
131 | 0 | ], |
132 | 0 | } |
133 | 0 | } |
134 | | |
135 | | /// Classifies an instrument based on configuration rules. |
136 | 0 | pub fn classify_sector(&self, instrument_id: &str, asset_type: Option<&str>) -> String { |
137 | | // First try to classify based on asset type if provided |
138 | 0 | if let Some(asset_type) = asset_type { |
139 | 0 | if let Some(sector) = self.asset_type_rules.get(asset_type) { |
140 | 0 | return sector.clone(); |
141 | 0 | } |
142 | 0 | } |
143 | | |
144 | | // Check for currency patterns |
145 | 0 | for pattern in &self.currency_patterns { |
146 | 0 | if let Ok(regex) = regex::Regex::new(pattern) { |
147 | 0 | if regex.is_match(instrument_id) { |
148 | 0 | return "Currencies".to_string(); |
149 | 0 | } |
150 | 0 | } |
151 | | } |
152 | | |
153 | | // Check for crypto patterns |
154 | 0 | for pattern in &self.crypto_patterns { |
155 | 0 | if let Ok(regex) = regex::Regex::new(pattern) { |
156 | 0 | if regex.is_match(instrument_id) { |
157 | 0 | return "Cryptocurrency".to_string(); |
158 | 0 | } |
159 | 0 | } |
160 | | } |
161 | | |
162 | | // Default classification |
163 | 0 | "Other".to_string() |
164 | 0 | } |
165 | | } |
166 | | |
167 | | impl Default for AssetClassificationConfig { |
168 | 0 | fn default() -> Self { |
169 | 0 | Self::new() |
170 | 0 | } |
171 | | } |
172 | | |
173 | | impl Default for S3Config { |
174 | 0 | fn default() -> Self { |
175 | 0 | Self { |
176 | 0 | bucket_name: "foxhunt-models".to_string(), |
177 | 0 | region: "us-east-1".to_string(), |
178 | 0 | access_key_id: None, |
179 | 0 | secret_access_key: None, |
180 | 0 | session_token: None, |
181 | 0 | endpoint_url: None, |
182 | 0 | force_path_style: false, |
183 | 0 | timeout: Duration::from_secs(30), |
184 | 0 | max_retry_attempts: 3, |
185 | 0 | use_ssl: true, |
186 | 0 | } |
187 | 0 | } |
188 | | } |