Skip to main content

lineage/finance/
spawning.rs

1//! Spawning and Inheritance System - Evolutionary propagation
2//!
3//! Successful agents spawn offspring that inherit optimized traits:
4//! - Requires minimum capital (immutable cost)
5//! - Offspring inherit parent's cost multiplier
6//! - Strategy parameters can be inherited with mutations
7//! - Creates agent dynasties and lineages
8
9use serde::{Deserialize, Serialize};
10use chrono::{DateTime, Utc};
11use crate::finance::agent::AgentId;
12
13/// Strategy parameters that can be inherited
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct OffspringTraits {
16    /// Inherited cost multiplier from parent's scars
17    pub inherited_cost_multiplier: f32,
18    
19    /// Risk tolerance (0-1, affects leverage)
20    pub risk_tolerance: f32,
21    
22    /// Aggressiveness of strategy (0-1)
23    pub aggressiveness: f32,
24    
25    /// Diversification ratio (0-1)
26    pub diversification: f32,
27    
28    /// Base win rate estimate from parent
29    pub estimated_win_rate: f32,
30    
31    /// Mutation factor applied to parameters
32    pub mutation_rate: f32,
33}
34
35impl OffspringTraits {
36    /// Create offspring traits from parent metrics
37    pub fn inherit_from_parent(
38        parent_cost_multiplier: f32,
39        parent_win_rate: f32,
40        mutation_rate: f32,
41    ) -> Self {
42        // Mutation affects inherited traits slightly
43        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    /// Apply mutation to create variation
56    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/// Strategy for inheriting traits to offspring
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
65pub enum InheritanceStrategy {
66    /// Exact copy of parent traits
67    Identical,
68    
69    /// Inherit with small mutations (5% variance)
70    LowMutation,
71    
72    /// Inherit with medium mutations (15% variance)
73    MediumMutation,
74    
75    /// Inherit with high mutations (30% variance)
76    HighMutation,
77    
78    /// Random traits within successful range
79    Exploration,
80}
81
82impl InheritanceStrategy {
83    /// Get mutation rate for this strategy
84    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/// Spawning requirement validation
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct SpawningRequirement {
98    /// Minimum capital required
99    pub min_capital: u64,
100    
101    /// Capital cost percentage (is lost in spawn)
102    pub cost_percentage: f32,
103    
104    /// Minimum win rate required
105    pub min_win_rate: f32,
106    
107    /// Minimum number of trades
108    pub min_trades: u64,
109    
110    /// Maximum scars allowed
111    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/// Result of spawn operation
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub enum SpawnResult {
129    /// Offspring successfully created
130    Created {
131        offspring_id: AgentId,
132        inherited_capital: u64,
133        traits: OffspringTraits,
134    },
135    
136    /// Spawning rejected - not eligible
137    Rejected { reason: String },
138    
139    /// Spawning not yet possible
140    NotReady { reason: String },
141}
142
143/// Offspring record
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub struct Offspring {
146    /// Unique offspring ID (assigned at birth)
147    pub id: AgentId,
148    
149    /// Parent's ID
150    pub parent_id: AgentId,
151    
152    /// When offspring was spawned
153    pub spawn_time: DateTime<Utc>,
154    
155    /// Generation (parent_gen + 1)
156    pub generation: u32,
157    
158    /// Inherited traits
159    pub traits: OffspringTraits,
160    
161    /// Capital given to offspring
162    pub initial_capital: u64,
163    
164    /// Strategy name
165    pub strategy_name: String,
166    
167    /// Inheritance strategy used
168    pub inheritance_strategy: InheritanceStrategy,
169}
170
171impl Offspring {
172    /// Validate if parent can spawn
173    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    /// Create new offspring
213    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/// Lineage tree tracking family history
236#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct LineageTree {
238    /// Mapping of agent IDs to parent IDs
239    pub parent_map: std::collections::HashMap<String, String>,
240    
241    /// Offspring records
242    pub offspring_records: Vec<Offspring>,
243    
244    /// Statistics about evolutionary success
245    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    /// Record an offspring creation
260    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    /// Get lineage chain (ancestors)
270    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(&current) {
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}