use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
use crate::finance::agent::AgentId;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OffspringTraits {
pub inherited_cost_multiplier: f32,
pub risk_tolerance: f32,
pub aggressiveness: f32,
pub diversification: f32,
pub estimated_win_rate: f32,
pub mutation_rate: f32,
}
impl OffspringTraits {
pub fn inherit_from_parent(
parent_cost_multiplier: f32,
parent_win_rate: f32,
mutation_rate: f32,
) -> Self {
let mutation = (rand::random::<f32>() - 0.5) * mutation_rate;
OffspringTraits {
inherited_cost_multiplier: parent_cost_multiplier,
risk_tolerance: (parent_win_rate / 100.0 * 0.8 + mutation.abs()).clamp(0.0, 1.0),
aggressiveness: (parent_win_rate / 100.0 * 0.6 + mutation.abs()).clamp(0.0, 1.0),
diversification: 0.5 + mutation * 0.1,
estimated_win_rate: parent_win_rate,
mutation_rate,
}
}
pub fn mutate(&mut self) {
let mutation = (rand::random::<f32>() - 0.5) * self.mutation_rate;
self.risk_tolerance = (self.risk_tolerance + mutation).clamp(0.0, 1.0);
self.aggressiveness = (self.aggressiveness + mutation).clamp(0.0, 1.0);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum InheritanceStrategy {
Identical,
LowMutation,
MediumMutation,
HighMutation,
Exploration,
}
impl InheritanceStrategy {
pub fn mutation_rate(&self) -> f32 {
match self {
InheritanceStrategy::Identical => 0.0,
InheritanceStrategy::LowMutation => 0.05,
InheritanceStrategy::MediumMutation => 0.15,
InheritanceStrategy::HighMutation => 0.30,
InheritanceStrategy::Exploration => 0.50,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpawningRequirement {
pub min_capital: u64,
pub cost_percentage: f32,
pub min_win_rate: f32,
pub min_trades: u64,
pub max_scars: u32,
}
impl Default for SpawningRequirement {
fn default() -> Self {
SpawningRequirement {
min_capital: 10000,
cost_percentage: 25.0,
min_win_rate: 55.0,
min_trades: 10,
max_scars: 2,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SpawnResult {
Created {
offspring_id: AgentId,
inherited_capital: u64,
traits: OffspringTraits,
},
Rejected { reason: String },
NotReady { reason: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Offspring {
pub id: AgentId,
pub parent_id: AgentId,
pub spawn_time: DateTime<Utc>,
pub generation: u32,
pub traits: OffspringTraits,
pub initial_capital: u64,
pub strategy_name: String,
pub inheritance_strategy: InheritanceStrategy,
}
impl Offspring {
pub fn validate_spawn(
parent_capital: u64,
parent_win_rate: f32,
parent_trades: u64,
parent_scars: u32,
requirement: &SpawningRequirement,
) -> Result<u64, String> {
if parent_capital < requirement.min_capital {
return Err(format!(
"Insufficient capital: {} < {}",
parent_capital, requirement.min_capital
));
}
if parent_win_rate < requirement.min_win_rate {
return Err(format!(
"Win rate too low: {:.2}% < {:.2}%",
parent_win_rate, requirement.min_win_rate
));
}
if parent_trades < requirement.min_trades {
return Err(format!(
"Insufficient trade history: {} < {}",
parent_trades, requirement.min_trades
));
}
if parent_scars > requirement.max_scars {
return Err(format!(
"Too many scars: {} > {}",
parent_scars, requirement.max_scars
));
}
let spawn_cost = (parent_capital as f32 * (requirement.cost_percentage / 100.0)) as u64;
Ok(spawn_cost)
}
pub fn create_offspring(
id: AgentId,
parent_id: AgentId,
generation: u32,
traits: OffspringTraits,
initial_capital: u64,
strategy_name: String,
inheritance_strategy: InheritanceStrategy,
) -> Self {
Offspring {
id,
parent_id,
spawn_time: Utc::now(),
generation,
traits,
initial_capital,
strategy_name,
inheritance_strategy,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LineageTree {
pub parent_map: std::collections::HashMap<String, String>,
pub offspring_records: Vec<Offspring>,
pub total_spawns: u64,
pub successful_lineages: u64,
}
impl LineageTree {
pub fn new() -> Self {
LineageTree {
parent_map: std::collections::HashMap::new(),
offspring_records: Vec::new(),
total_spawns: 0,
successful_lineages: 0,
}
}
pub fn record_spawn(&mut self, parent_id: AgentId, offspring: Offspring) {
self.parent_map.insert(
offspring.id.to_string(),
parent_id.to_string(),
);
self.offspring_records.push(offspring);
self.total_spawns += 1;
}
pub fn get_lineage_chain(&self, agent_id: AgentId) -> Vec<String> {
let mut chain = vec![agent_id.to_string()];
let mut current = agent_id.to_string();
while let Some(parent) = self.parent_map.get(¤t) {
chain.push(parent.clone());
current = parent.clone();
}
chain
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_offspring_traits_inheritance() {
let traits = OffspringTraits::inherit_from_parent(1.05, 60.0, 0.1);
assert!(traits.risk_tolerance >= 0.0);
assert!(traits.risk_tolerance <= 1.0);
}
#[test]
fn test_spawn_validation() {
let req = SpawningRequirement::default();
let result = Offspring::validate_spawn(20000, 60.0, 20, 1, &req);
assert!(result.is_ok());
}
}