1use serde::{Deserialize, Serialize};
10use chrono::{DateTime, Utc};
11use crate::finance::agent::AgentId;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct OffspringTraits {
16 pub inherited_cost_multiplier: f32,
18
19 pub risk_tolerance: f32,
21
22 pub aggressiveness: f32,
24
25 pub diversification: f32,
27
28 pub estimated_win_rate: f32,
30
31 pub mutation_rate: f32,
33}
34
35impl OffspringTraits {
36 pub fn inherit_from_parent(
38 parent_cost_multiplier: f32,
39 parent_win_rate: f32,
40 mutation_rate: f32,
41 ) -> Self {
42 let mutation = (rand::random::<f32>() - 0.5) * mutation_rate;
44
45 OffspringTraits {
46 inherited_cost_multiplier: parent_cost_multiplier,
47 risk_tolerance: (parent_win_rate / 100.0 * 0.8 + mutation.abs()).clamp(0.0, 1.0),
48 aggressiveness: (parent_win_rate / 100.0 * 0.6 + mutation.abs()).clamp(0.0, 1.0),
49 diversification: 0.5 + mutation * 0.1,
50 estimated_win_rate: parent_win_rate,
51 mutation_rate,
52 }
53 }
54
55 pub fn mutate(&mut self) {
57 let mutation = (rand::random::<f32>() - 0.5) * self.mutation_rate;
58 self.risk_tolerance = (self.risk_tolerance + mutation).clamp(0.0, 1.0);
59 self.aggressiveness = (self.aggressiveness + mutation).clamp(0.0, 1.0);
60 }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
65pub enum InheritanceStrategy {
66 Identical,
68
69 LowMutation,
71
72 MediumMutation,
74
75 HighMutation,
77
78 Exploration,
80}
81
82impl InheritanceStrategy {
83 pub fn mutation_rate(&self) -> f32 {
85 match self {
86 InheritanceStrategy::Identical => 0.0,
87 InheritanceStrategy::LowMutation => 0.05,
88 InheritanceStrategy::MediumMutation => 0.15,
89 InheritanceStrategy::HighMutation => 0.30,
90 InheritanceStrategy::Exploration => 0.50,
91 }
92 }
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct SpawningRequirement {
98 pub min_capital: u64,
100
101 pub cost_percentage: f32,
103
104 pub min_win_rate: f32,
106
107 pub min_trades: u64,
109
110 pub max_scars: u32,
112}
113
114impl Default for SpawningRequirement {
115 fn default() -> Self {
116 SpawningRequirement {
117 min_capital: 10000,
118 cost_percentage: 25.0,
119 min_win_rate: 55.0,
120 min_trades: 10,
121 max_scars: 2,
122 }
123 }
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub enum SpawnResult {
129 Created {
131 offspring_id: AgentId,
132 inherited_capital: u64,
133 traits: OffspringTraits,
134 },
135
136 Rejected { reason: String },
138
139 NotReady { reason: String },
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct Offspring {
146 pub id: AgentId,
148
149 pub parent_id: AgentId,
151
152 pub spawn_time: DateTime<Utc>,
154
155 pub generation: u32,
157
158 pub traits: OffspringTraits,
160
161 pub initial_capital: u64,
163
164 pub strategy_name: String,
166
167 pub inheritance_strategy: InheritanceStrategy,
169}
170
171impl Offspring {
172 pub fn validate_spawn(
174 parent_capital: u64,
175 parent_win_rate: f32,
176 parent_trades: u64,
177 parent_scars: u32,
178 requirement: &SpawningRequirement,
179 ) -> Result<u64, String> {
180 if parent_capital < requirement.min_capital {
181 return Err(format!(
182 "Insufficient capital: {} < {}",
183 parent_capital, requirement.min_capital
184 ));
185 }
186
187 if parent_win_rate < requirement.min_win_rate {
188 return Err(format!(
189 "Win rate too low: {:.2}% < {:.2}%",
190 parent_win_rate, requirement.min_win_rate
191 ));
192 }
193
194 if parent_trades < requirement.min_trades {
195 return Err(format!(
196 "Insufficient trade history: {} < {}",
197 parent_trades, requirement.min_trades
198 ));
199 }
200
201 if parent_scars > requirement.max_scars {
202 return Err(format!(
203 "Too many scars: {} > {}",
204 parent_scars, requirement.max_scars
205 ));
206 }
207
208 let spawn_cost = (parent_capital as f32 * (requirement.cost_percentage / 100.0)) as u64;
209 Ok(spawn_cost)
210 }
211
212 pub fn create_offspring(
214 id: AgentId,
215 parent_id: AgentId,
216 generation: u32,
217 traits: OffspringTraits,
218 initial_capital: u64,
219 strategy_name: String,
220 inheritance_strategy: InheritanceStrategy,
221 ) -> Self {
222 Offspring {
223 id,
224 parent_id,
225 spawn_time: Utc::now(),
226 generation,
227 traits,
228 initial_capital,
229 strategy_name,
230 inheritance_strategy,
231 }
232 }
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct LineageTree {
238 pub parent_map: std::collections::HashMap<String, String>,
240
241 pub offspring_records: Vec<Offspring>,
243
244 pub total_spawns: u64,
246 pub successful_lineages: u64,
247}
248
249impl LineageTree {
250 pub fn new() -> Self {
251 LineageTree {
252 parent_map: std::collections::HashMap::new(),
253 offspring_records: Vec::new(),
254 total_spawns: 0,
255 successful_lineages: 0,
256 }
257 }
258
259 pub fn record_spawn(&mut self, parent_id: AgentId, offspring: Offspring) {
261 self.parent_map.insert(
262 offspring.id.to_string(),
263 parent_id.to_string(),
264 );
265 self.offspring_records.push(offspring);
266 self.total_spawns += 1;
267 }
268
269 pub fn get_lineage_chain(&self, agent_id: AgentId) -> Vec<String> {
271 let mut chain = vec![agent_id.to_string()];
272 let mut current = agent_id.to_string();
273
274 while let Some(parent) = self.parent_map.get(¤t) {
275 chain.push(parent.clone());
276 current = parent.clone();
277 }
278
279 chain
280 }
281}
282
283#[cfg(test)]
284mod tests {
285 use super::*;
286
287 #[test]
288 fn test_offspring_traits_inheritance() {
289 let traits = OffspringTraits::inherit_from_parent(1.05, 60.0, 0.1);
290 assert!(traits.risk_tolerance >= 0.0);
291 assert!(traits.risk_tolerance <= 1.0);
292 }
293
294 #[test]
295 fn test_spawn_validation() {
296 let req = SpawningRequirement::default();
297 let result = Offspring::validate_spawn(20000, 60.0, 20, 1, &req);
298 assert!(result.is_ok());
299 }
300}