NAC_Blockchain/nvm_v2/nvm-l1/src/value_scale/asset_valuation.rs

570 lines
17 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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<MarketData>,
}
/// 市场数据
#[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<String, String>,
/// 司法辖区
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<ValuationResult>,
/// 平均估值
pub average_value: u128,
/// 估值趋势(上升/下降百分比)
pub trend_percent: i32,
}
/// 资产估值系统
pub struct AssetValuationSystem {
/// 估值结果存储 (valuation_id -> ValuationResult)
valuations: HashMap<String, ValuationResult>,
/// 资产估值历史 (asset_id -> ValuationHistory)
valuation_history: HashMap<String, ValuationHistory>,
/// 估值方法权重 (method -> weight)
method_weights: HashMap<ValuationMethod, u8>,
/// 类别调整因子 (category -> factors)
category_adjustments: HashMap<AssetCategory, Vec<AdjustmentFactor>>,
/// 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<String, u64>,
/// 总估值金额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<MarketData>,
) -> Result<ValuationResult, String> {
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(&params.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<u128, String> {
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<Result<ValuationResult, String>> {
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());
}
}