// Asset Valuation System // 资产估值系统 - NAC原生实现 use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// 估值方法 #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ValuationMethod { /// 市场比较法 MarketComparison, /// 收益法 IncomeApproach, /// 成本法 CostApproach, /// AI估值模型 AIModel(String), /// 专家评估 ExpertAppraisal, /// 混合方法 Hybrid, } /// 资产类别(扩展的GNACS分类) #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum AssetCategory { /// 不动产 RealEstate, /// 动产 PersonalProperty, /// 金融资产 FinancialAsset, /// 知识产权 IntellectualProperty, /// 艺术品 Artwork, /// 贵金属 PreciousMetal, /// 大宗商品 Commodity, /// 数字资产 DigitalAsset, /// 其他 Other(String), } /// 估值结果 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ValuationResult { /// 估值ID pub valuation_id: String, /// 资产ID pub asset_id: String, /// 资产类别 pub asset_category: AssetCategory, /// 估值金额(XTZH单位) pub value_xtzh: u128, /// 估值金额(USD) pub value_usd: u128, /// 估值方法 pub method: ValuationMethod, /// 置信度 (0-100) pub confidence: u8, /// 估值师/模型 pub appraiser: String, /// 估值时间戳 pub valued_at: u64, /// 有效期(秒) pub validity_period: u64, /// 估值依据 pub rationale: String, /// 市场数据 pub market_data: Option, } /// 市场数据 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MarketData { /// 可比交易数量 pub comparable_transactions: u32, /// 平均市场价格 pub average_market_price: u128, /// 价格范围(最低-最高) pub price_range: (u128, u128), /// 市场流动性评分 (0-100) pub liquidity_score: u8, /// 数据来源 pub data_source: String, } /// 估值参数 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ValuationParams { /// 资产类别 pub asset_category: AssetCategory, /// 资产描述 pub description: String, /// 资产属性 pub attributes: HashMap, /// 司法辖区 pub jurisdiction: String, /// 估值目的 pub purpose: String, } /// 估值调整因子 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AdjustmentFactor { /// 因子名称 pub name: String, /// 调整比例(百分比,可为负) pub adjustment_percent: i32, /// 原因说明 pub reason: String, } /// 估值历史记录 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ValuationHistory { /// 资产ID pub asset_id: String, /// 历史估值列表 pub valuations: Vec, /// 平均估值 pub average_value: u128, /// 估值趋势(上升/下降百分比) pub trend_percent: i32, } /// 资产估值系统 pub struct AssetValuationSystem { /// 估值结果存储 (valuation_id -> ValuationResult) valuations: HashMap, /// 资产估值历史 (asset_id -> ValuationHistory) valuation_history: HashMap, /// 估值方法权重 (method -> weight) method_weights: HashMap, /// 类别调整因子 (category -> factors) category_adjustments: HashMap>, /// XTZH/USD汇率(18位小数) xtzh_usd_rate: u128, /// 统计信息 stats: ValuationStats, } /// 估值统计 #[derive(Debug, Clone, Default)] pub struct ValuationStats { /// 总估值次数 pub total_valuations: u64, /// 按类别统计 (category -> count) pub valuations_by_category: HashMap, /// 总估值金额(XTZH) pub total_value_xtzh: u128, /// 平均置信度 pub average_confidence: u8, } impl AssetValuationSystem { /// 创建新的估值系统 pub fn new(xtzh_usd_rate: u128) -> Self { let mut method_weights = HashMap::new(); // 设置默认权重 method_weights.insert(ValuationMethod::MarketComparison, 40); method_weights.insert(ValuationMethod::IncomeApproach, 30); method_weights.insert(ValuationMethod::CostApproach, 20); method_weights.insert(ValuationMethod::ExpertAppraisal, 10); Self { valuations: HashMap::new(), valuation_history: HashMap::new(), method_weights, category_adjustments: HashMap::new(), xtzh_usd_rate, stats: ValuationStats::default(), } } /// 执行估值 pub fn perform_valuation( &mut self, valuation_id: String, params: ValuationParams, method: ValuationMethod, base_value_usd: u128, confidence: u8, appraiser: String, validity_period: u64, rationale: String, market_data: Option, ) -> Result { if confidence == 0 || confidence > 100 { return Err("Invalid confidence level".to_string()); } let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); // 应用调整因子 let adjusted_value_usd = self.apply_adjustments(¶ms.asset_category, base_value_usd)?; // 转换为XTZH(先除后乘避免溢出) // value_xtzh = (value_usd * 10^18) / xtzh_usd_rate // = value_usd / (xtzh_usd_rate / 10^18) let xtzh_rate_normalized = self.xtzh_usd_rate / 1_000_000_000_000_000_000; let value_xtzh = if xtzh_rate_normalized > 0 { adjusted_value_usd / xtzh_rate_normalized } else { return Err("Invalid XTZH rate".to_string()); }; let result = ValuationResult { valuation_id: valuation_id.clone(), asset_id: params.description.clone(), // 简化处理 asset_category: params.asset_category.clone(), value_xtzh, value_usd: adjusted_value_usd, method, confidence, appraiser, valued_at: now, validity_period, rationale, market_data, }; // 保存估值结果 self.valuations.insert(valuation_id, result.clone()); // 更新历史记录 self.update_history(result.clone()); // 更新统计 self.stats.total_valuations += 1; self.stats.total_value_xtzh += value_xtzh; let category_key = format!("{:?}", params.asset_category); *self.stats.valuations_by_category.entry(category_key).or_insert(0) += 1; Ok(result) } /// 应用调整因子 fn apply_adjustments(&self, category: &AssetCategory, base_value: u128) -> Result { let mut adjusted_value = base_value as i128; if let Some(factors) = self.category_adjustments.get(category) { for factor in factors { let adjustment = (base_value as i128 * factor.adjustment_percent as i128) / 100; adjusted_value += adjustment; } } if adjusted_value < 0 { return Err("Adjusted value cannot be negative".to_string()); } Ok(adjusted_value as u128) } /// 更新估值历史 fn update_history(&mut self, result: ValuationResult) { let history = self.valuation_history .entry(result.asset_id.clone()) .or_insert_with(|| ValuationHistory { asset_id: result.asset_id.clone(), valuations: Vec::new(), average_value: 0, trend_percent: 0, }); history.valuations.push(result.clone()); // 计算平均估值 let total: u128 = history.valuations.iter().map(|v| v.value_xtzh).sum(); history.average_value = total / history.valuations.len() as u128; // 计算趋势 if history.valuations.len() >= 2 { let latest = history.valuations.last().unwrap().value_xtzh; let previous = history.valuations[history.valuations.len() - 2].value_xtzh; if previous > 0 { let change = (latest as i128 - previous as i128) * 10000 / previous as i128; history.trend_percent = (change / 100) as i32; } } } /// 获取估值结果 pub fn get_valuation(&self, valuation_id: &str) -> Option<&ValuationResult> { self.valuations.get(valuation_id) } /// 获取资产最新估值 pub fn get_latest_valuation(&self, asset_id: &str) -> Option<&ValuationResult> { self.valuation_history .get(asset_id) .and_then(|h| h.valuations.last()) } /// 获取估值历史 pub fn get_valuation_history(&self, asset_id: &str) -> Option<&ValuationHistory> { self.valuation_history.get(asset_id) } /// 检查估值是否有效 pub fn is_valuation_valid(&self, valuation_id: &str) -> bool { if let Some(valuation) = self.valuations.get(valuation_id) { let now = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); now - valuation.valued_at < valuation.validity_period } else { false } } /// 添加调整因子 pub fn add_adjustment_factor(&mut self, category: AssetCategory, factor: AdjustmentFactor) { self.category_adjustments .entry(category) .or_insert_with(Vec::new) .push(factor); } /// 设置方法权重 pub fn set_method_weight(&mut self, method: ValuationMethod, weight: u8) { self.method_weights.insert(method, weight); } /// 更新XTZH/USD汇率 pub fn update_xtzh_rate(&mut self, rate: u128) { self.xtzh_usd_rate = rate; } /// 获取统计信息 pub fn get_stats(&self) -> &ValuationStats { &self.stats } /// 批量估值 pub fn batch_valuation( &mut self, params_list: Vec<(String, ValuationParams, ValuationMethod, u128, u8, String)>, ) -> Vec> { params_list.into_iter().map(|(id, params, method, value, conf, appraiser)| { self.perform_valuation( id, params, method, value, conf, appraiser, 365 * 24 * 3600, // 1年有效期 "Batch valuation".to_string(), None, ) }).collect() } } impl Default for AssetValuationSystem { fn default() -> Self { Self::new(50_000_000_000_000_000_000) // 默认1 XTZH = $50 } } #[cfg(test)] mod tests { use super::*; #[test] fn test_valuation_system_creation() { let system = AssetValuationSystem::new(50_000_000_000_000_000_000); assert_eq!(system.xtzh_usd_rate, 50_000_000_000_000_000_000); } #[test] fn test_perform_valuation() { let mut system = AssetValuationSystem::new(50_000_000_000_000_000_000); let mut attributes = HashMap::new(); attributes.insert("location".to_string(), "New York".to_string()); attributes.insert("size".to_string(), "100 sqm".to_string()); let params = ValuationParams { asset_category: AssetCategory::RealEstate, description: "Luxury Apartment".to_string(), attributes, jurisdiction: "US-NY".to_string(), purpose: "Sale".to_string(), }; let result = system.perform_valuation( "val001".to_string(), params, ValuationMethod::MarketComparison, 1_000_000, // $1,000,000 (不带小数位) 90, "AI Model v1".to_string(), 365 * 24 * 3600, "Based on comparable sales".to_string(), None, ).unwrap(); assert_eq!(result.valuation_id, "val001"); assert_eq!(result.confidence, 90); assert!(result.value_xtzh > 0); } #[test] fn test_adjustment_factors() { let mut system = AssetValuationSystem::new(50_000_000_000_000_000_000); // 添加调整因子 system.add_adjustment_factor( AssetCategory::RealEstate, AdjustmentFactor { name: "Location Premium".to_string(), adjustment_percent: 10, // +10% reason: "Prime location".to_string(), }, ); let mut attributes = HashMap::new(); attributes.insert("location".to_string(), "Prime".to_string()); let params = ValuationParams { asset_category: AssetCategory::RealEstate, description: "Prime Property".to_string(), attributes, jurisdiction: "US-NY".to_string(), purpose: "Sale".to_string(), }; let result = system.perform_valuation( "val002".to_string(), params, ValuationMethod::MarketComparison, 1_000_000, // $1,000,000 (不带小数位) 85, "Expert".to_string(), 365 * 24 * 3600, "With location adjustment".to_string(), None, ).unwrap(); // 应该是 $1,100,000 (1,000,000 + 10%) assert_eq!(result.value_usd, 1_100_000); // 验证XTZH值:1,100,000 / 50 = 22,000 assert_eq!(result.value_xtzh, 22_000); } #[test] fn test_valuation_history() { let mut system = AssetValuationSystem::new(50_000_000_000_000_000_000); let params = ValuationParams { asset_category: AssetCategory::RealEstate, description: "Test Asset".to_string(), attributes: HashMap::new(), jurisdiction: "US".to_string(), purpose: "Test".to_string(), }; // 第一次估值 system.perform_valuation( "val001".to_string(), params.clone(), ValuationMethod::MarketComparison, 1_000_000, 90, "Appraiser 1".to_string(), 365 * 24 * 3600, "First valuation".to_string(), None, ).unwrap(); // 第二次估值 system.perform_valuation( "val002".to_string(), params, ValuationMethod::IncomeApproach, 1_100_000, 85, "Appraiser 2".to_string(), 365 * 24 * 3600, "Second valuation".to_string(), None, ).unwrap(); let history = system.get_valuation_history("Test Asset").unwrap(); assert_eq!(history.valuations.len(), 2); assert!(history.trend_percent > 0); // 价格上涨 } #[test] fn test_valuation_validity() { let mut system = AssetValuationSystem::new(50_000_000_000_000_000_000); let params = ValuationParams { asset_category: AssetCategory::RealEstate, description: "Test Asset".to_string(), attributes: HashMap::new(), jurisdiction: "US".to_string(), purpose: "Test".to_string(), }; system.perform_valuation( "val001".to_string(), params, ValuationMethod::MarketComparison, 1_000_000_000_000_000_000_000, 90, "Appraiser".to_string(), 3600, // 1小时有效期 "Test valuation".to_string(), None, ).unwrap(); assert!(system.is_valuation_valid("val001")); } #[test] fn test_batch_valuation() { let mut system = AssetValuationSystem::new(50_000_000_000_000_000_000); let params_list = vec![ ( "val001".to_string(), ValuationParams { asset_category: AssetCategory::RealEstate, description: "Asset 1".to_string(), attributes: HashMap::new(), jurisdiction: "US".to_string(), purpose: "Test".to_string(), }, ValuationMethod::MarketComparison, 1_000_000_000_000_000_000_000, 90, "AI".to_string(), ), ( "val002".to_string(), ValuationParams { asset_category: AssetCategory::FinancialAsset, description: "Asset 2".to_string(), attributes: HashMap::new(), jurisdiction: "US".to_string(), purpose: "Test".to_string(), }, ValuationMethod::IncomeApproach, 500_000, 85, "AI".to_string(), ), ]; let results = system.batch_valuation(params_list); assert_eq!(results.len(), 2); assert!(results[0].is_ok()); assert!(results[1].is_ok()); } }