484 lines
16 KiB
Rust
484 lines
16 KiB
Rust
// ACC-Reserve: 黄金储备管理协议
|
||
// 管理XTZH的1.25倍黄金永续合约储备机制
|
||
//
|
||
// 核心设计:
|
||
// - 80%资金进入托管账户用于黄金永续合约
|
||
// - 20%资金进入风险准备金
|
||
// - 实际黄金储备覆盖率 = 80% × 1.25 × 78.125% = 78.125%
|
||
// - 加上20%风险准备金,总覆盖率达到98.125%
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
|
||
/// 黄金储备账户
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct GoldReserveAccount {
|
||
/// 账户ID
|
||
pub account_id: String,
|
||
/// 托管账户余额(USDT)
|
||
pub custody_balance: u128,
|
||
/// 风险准备金余额(USDT)
|
||
pub risk_reserve_balance: u128,
|
||
/// 黄金永续合约持仓量(盎司)
|
||
pub gold_perpetual_position: u128,
|
||
/// 黄金永续合约平均开仓价格(USDT/盎司)
|
||
pub avg_entry_price: u128,
|
||
/// 当前黄金市场价格(USDT/盎司)
|
||
pub current_gold_price: u128,
|
||
/// 未实现盈亏(USDT)
|
||
pub unrealized_pnl: i128,
|
||
/// 强制平仓价格(USDT/盎司)
|
||
pub liquidation_price: u128,
|
||
}
|
||
|
||
/// 储备操作记录
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct ReserveOperation {
|
||
/// 操作ID
|
||
pub operation_id: String,
|
||
/// 操作类型
|
||
pub operation_type: OperationType,
|
||
/// 金额(USDT)
|
||
pub amount: u128,
|
||
/// 黄金价格(USDT/盎司)
|
||
pub gold_price: u128,
|
||
/// 时间戳
|
||
pub timestamp: u64,
|
||
/// 操作者
|
||
pub operator: String,
|
||
}
|
||
|
||
/// 操作类型
|
||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||
pub enum OperationType {
|
||
/// 注入资金
|
||
Deposit,
|
||
/// 开仓黄金永续合约
|
||
OpenPosition,
|
||
/// 平仓黄金永续合约
|
||
ClosePosition,
|
||
/// 再平衡
|
||
Rebalance,
|
||
/// 补充风险准备金
|
||
AddRiskReserve,
|
||
/// 使用风险准备金
|
||
UseRiskReserve,
|
||
}
|
||
|
||
/// 储备状态
|
||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||
pub enum ReserveStatus {
|
||
/// 健康(GCR >= 125%)
|
||
Healthy,
|
||
/// 预警(110% <= GCR < 125%)
|
||
Warning,
|
||
/// 危险(100% <= GCR < 110%)
|
||
Danger,
|
||
/// 临界(GCR < 100%)
|
||
Critical,
|
||
}
|
||
|
||
/// 黄金储备协议管理器
|
||
#[derive(Debug, Clone)]
|
||
pub struct GoldReserveProtocol {
|
||
/// 储备账户
|
||
pub account: GoldReserveAccount,
|
||
/// 操作记录
|
||
pub operations: Vec<ReserveOperation>,
|
||
/// 当前状态
|
||
pub status: ReserveStatus,
|
||
/// 目标黄金覆盖率(百分比,125表示125%)
|
||
pub target_gcr: u16,
|
||
/// 最低黄金覆盖率(百分比,100表示100%)
|
||
pub min_gcr: u16,
|
||
/// 托管账户资金比例(百分比,80表示80%)
|
||
pub custody_ratio: u8,
|
||
/// 风险准备金比例(百分比,20表示20%)
|
||
pub risk_reserve_ratio: u8,
|
||
/// 黄金永续合约杠杆(125表示1.25倍)
|
||
pub leverage: u16,
|
||
}
|
||
|
||
impl GoldReserveProtocol {
|
||
/// 创建新的黄金储备协议实例
|
||
pub fn new(account_id: String) -> Self {
|
||
Self {
|
||
account: GoldReserveAccount {
|
||
account_id,
|
||
custody_balance: 0,
|
||
risk_reserve_balance: 0,
|
||
gold_perpetual_position: 0,
|
||
avg_entry_price: 0,
|
||
current_gold_price: 2000_00, // 初始黄金价格$2000/盎司
|
||
unrealized_pnl: 0,
|
||
liquidation_price: 0,
|
||
},
|
||
operations: Vec::new(),
|
||
status: ReserveStatus::Healthy,
|
||
target_gcr: 125,
|
||
min_gcr: 100,
|
||
custody_ratio: 80,
|
||
risk_reserve_ratio: 20,
|
||
leverage: 125, // 1.25倍杠杆
|
||
}
|
||
}
|
||
|
||
/// 注入资金
|
||
pub fn deposit(&mut self, amount: u128, timestamp: u64, operator: &str) -> Result<(), String> {
|
||
// 按比例分配资金
|
||
let custody_amount = amount * self.custody_ratio as u128 / 100;
|
||
let risk_reserve_amount = amount * self.risk_reserve_ratio as u128 / 100;
|
||
|
||
self.account.custody_balance += custody_amount;
|
||
self.account.risk_reserve_balance += risk_reserve_amount;
|
||
|
||
// 记录操作
|
||
self.operations.push(ReserveOperation {
|
||
operation_id: format!("deposit_{}", timestamp),
|
||
operation_type: OperationType::Deposit,
|
||
amount,
|
||
gold_price: self.account.current_gold_price,
|
||
timestamp,
|
||
operator: operator.to_string(),
|
||
});
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 开仓黄金永续合约
|
||
pub fn open_position(
|
||
&mut self,
|
||
gold_price: u128,
|
||
timestamp: u64,
|
||
operator: &str,
|
||
) -> Result<(), String> {
|
||
if self.account.custody_balance == 0 {
|
||
return Err("No custody balance available".to_string());
|
||
}
|
||
|
||
// 计算可开仓数量(使用1.25倍杠杆)
|
||
let position_value = self.account.custody_balance * self.leverage as u128 / 100;
|
||
let position_size = position_value / gold_price;
|
||
|
||
// 更新持仓
|
||
self.account.gold_perpetual_position += position_size;
|
||
self.account.avg_entry_price = gold_price;
|
||
self.account.current_gold_price = gold_price;
|
||
|
||
// 计算强制平仓价格(下跌30%触发强平,保留70%本金)
|
||
self.account.liquidation_price = gold_price * 70 / 100;
|
||
|
||
// 记录操作
|
||
self.operations.push(ReserveOperation {
|
||
operation_id: format!("open_position_{}", timestamp),
|
||
operation_type: OperationType::OpenPosition,
|
||
amount: position_value,
|
||
gold_price,
|
||
timestamp,
|
||
operator: operator.to_string(),
|
||
});
|
||
|
||
// 更新状态
|
||
self.update_status();
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 更新黄金市场价格
|
||
pub fn update_gold_price(&mut self, new_price: u128) -> Result<(), String> {
|
||
self.account.current_gold_price = new_price;
|
||
|
||
// 计算未实现盈亏
|
||
if self.account.gold_perpetual_position > 0 {
|
||
let position_value_at_entry =
|
||
self.account.gold_perpetual_position * self.account.avg_entry_price;
|
||
let position_value_at_current =
|
||
self.account.gold_perpetual_position * new_price;
|
||
self.account.unrealized_pnl =
|
||
position_value_at_current as i128 - position_value_at_entry as i128;
|
||
}
|
||
|
||
// 检查是否触发强制平仓
|
||
if new_price <= self.account.liquidation_price {
|
||
return Err(format!(
|
||
"Liquidation triggered! Current price {} <= Liquidation price {}",
|
||
new_price, self.account.liquidation_price
|
||
));
|
||
}
|
||
|
||
// 更新状态
|
||
self.update_status();
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 计算当前黄金覆盖率(GCR)
|
||
pub fn calculate_gcr(&self) -> u16 {
|
||
if self.account.gold_perpetual_position == 0 {
|
||
return 0;
|
||
}
|
||
|
||
// 当前黄金持仓价值
|
||
let gold_value = self.account.gold_perpetual_position * self.account.current_gold_price;
|
||
|
||
// 总储备价值 = 黄金持仓价值 + 风险准备金
|
||
let total_reserve_value = gold_value + self.account.risk_reserve_balance;
|
||
|
||
// 需要覆盖的XTZH价值(假设等于托管账户初始余额)
|
||
let xtzh_value = self.account.custody_balance * 100 / self.custody_ratio as u128;
|
||
|
||
// GCR = 总储备价值 / XTZH价值 * 100
|
||
(total_reserve_value * 100 / xtzh_value) as u16
|
||
}
|
||
|
||
/// 更新储备状态
|
||
fn update_status(&mut self) {
|
||
let gcr = self.calculate_gcr();
|
||
|
||
self.status = if gcr >= self.target_gcr {
|
||
ReserveStatus::Healthy
|
||
} else if gcr >= 110 {
|
||
ReserveStatus::Warning
|
||
} else if gcr >= self.min_gcr {
|
||
ReserveStatus::Danger
|
||
} else {
|
||
ReserveStatus::Critical
|
||
};
|
||
}
|
||
|
||
/// 再平衡(当GCR偏离目标时)
|
||
pub fn rebalance(&mut self, timestamp: u64, operator: &str) -> Result<(), String> {
|
||
let current_gcr = self.calculate_gcr();
|
||
|
||
if current_gcr >= self.target_gcr - 5 && current_gcr <= self.target_gcr + 5 {
|
||
return Ok(()); // GCR在目标范围内,无需再平衡
|
||
}
|
||
|
||
// 记录再平衡操作
|
||
self.operations.push(ReserveOperation {
|
||
operation_id: format!("rebalance_{}", timestamp),
|
||
operation_type: OperationType::Rebalance,
|
||
amount: 0,
|
||
gold_price: self.account.current_gold_price,
|
||
timestamp,
|
||
operator: operator.to_string(),
|
||
});
|
||
|
||
// 更新状态
|
||
self.update_status();
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 使用风险准备金(当GCR低于100%时)
|
||
pub fn use_risk_reserve(
|
||
&mut self,
|
||
amount: u128,
|
||
timestamp: u64,
|
||
operator: &str,
|
||
) -> Result<(), String> {
|
||
if self.account.risk_reserve_balance < amount {
|
||
return Err("Insufficient risk reserve balance".to_string());
|
||
}
|
||
|
||
if self.status != ReserveStatus::Critical {
|
||
return Err("Can only use risk reserve when status is Critical".to_string());
|
||
}
|
||
|
||
self.account.risk_reserve_balance -= amount;
|
||
|
||
// 记录操作
|
||
self.operations.push(ReserveOperation {
|
||
operation_id: format!("use_risk_reserve_{}", timestamp),
|
||
operation_type: OperationType::UseRiskReserve,
|
||
amount,
|
||
gold_price: self.account.current_gold_price,
|
||
timestamp,
|
||
operator: operator.to_string(),
|
||
});
|
||
|
||
// 更新状态
|
||
self.update_status();
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 获取储备统计信息
|
||
pub fn get_reserve_stats(&self) -> ReserveStats {
|
||
ReserveStats {
|
||
total_custody_balance: self.account.custody_balance,
|
||
total_risk_reserve: self.account.risk_reserve_balance,
|
||
gold_position_size: self.account.gold_perpetual_position,
|
||
gold_position_value: self.account.gold_perpetual_position
|
||
* self.account.current_gold_price,
|
||
unrealized_pnl: self.account.unrealized_pnl,
|
||
current_gcr: self.calculate_gcr(),
|
||
status: self.status.clone(),
|
||
liquidation_price: self.account.liquidation_price,
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 储备统计信息
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct ReserveStats {
|
||
/// 托管账户总余额
|
||
pub total_custody_balance: u128,
|
||
/// 风险准备金总额
|
||
pub total_risk_reserve: u128,
|
||
/// 黄金持仓数量
|
||
pub gold_position_size: u128,
|
||
/// 黄金持仓价值
|
||
pub gold_position_value: u128,
|
||
/// 未实现盈亏
|
||
pub unrealized_pnl: i128,
|
||
/// 当前黄金覆盖率
|
||
pub current_gcr: u16,
|
||
/// 储备状态
|
||
pub status: ReserveStatus,
|
||
/// 强制平仓价格
|
||
pub liquidation_price: u128,
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_reserve_protocol_creation() {
|
||
let protocol = GoldReserveProtocol::new("reserve_001".to_string());
|
||
assert_eq!(protocol.account.account_id, "reserve_001");
|
||
assert_eq!(protocol.target_gcr, 125);
|
||
assert_eq!(protocol.custody_ratio, 80);
|
||
assert_eq!(protocol.risk_reserve_ratio, 20);
|
||
}
|
||
|
||
#[test]
|
||
fn test_deposit() {
|
||
let mut protocol = GoldReserveProtocol::new("reserve_001".to_string());
|
||
|
||
// 注入100万USDT
|
||
protocol.deposit(1000000_00, 1700000000, "operator_001").unwrap();
|
||
|
||
// 验证资金分配
|
||
assert_eq!(protocol.account.custody_balance, 800000_00); // 80%
|
||
assert_eq!(protocol.account.risk_reserve_balance, 200000_00); // 20%
|
||
}
|
||
|
||
#[test]
|
||
fn test_open_position() {
|
||
let mut protocol = GoldReserveProtocol::new("reserve_001".to_string());
|
||
|
||
// 注入资金
|
||
protocol.deposit(1000000_00, 1700000000, "operator_001").unwrap();
|
||
|
||
// 开仓黄金永续合约,黄金价格$2000/盎司
|
||
protocol.open_position(2000_00, 1700000001, "operator_001").unwrap();
|
||
|
||
// 验证持仓
|
||
// 托管账户80万USDT,1.25倍杠杆 = 100万USDT持仓价值
|
||
// 100万USDT / $2000/盎司 = 500盎司
|
||
assert_eq!(protocol.account.gold_perpetual_position, 500);
|
||
assert_eq!(protocol.account.avg_entry_price, 2000_00);
|
||
|
||
// 验证强制平仓价格(下跌30%)
|
||
assert_eq!(protocol.account.liquidation_price, 1400_00);
|
||
}
|
||
|
||
#[test]
|
||
fn test_calculate_gcr() {
|
||
let mut protocol = GoldReserveProtocol::new("reserve_001".to_string());
|
||
|
||
// 注入100万USDT
|
||
protocol.deposit(1000000_00, 1700000000, "operator_001").unwrap();
|
||
|
||
// 开仓黄金永续合约
|
||
protocol.open_position(2000_00, 1700000001, "operator_001").unwrap();
|
||
|
||
// 计算GCR
|
||
// 黄金持仓价值:500盎司 × $2000 = 100万USDT
|
||
// 风险准备金:20万USDT
|
||
// 总储备:120万USDT
|
||
// XTZH价值:100万USDT
|
||
// GCR = 120万 / 100万 = 120%
|
||
let gcr = protocol.calculate_gcr();
|
||
assert_eq!(gcr, 120);
|
||
}
|
||
|
||
#[test]
|
||
fn test_update_gold_price() {
|
||
let mut protocol = GoldReserveProtocol::new("reserve_001".to_string());
|
||
|
||
// 注入资金并开仓
|
||
protocol.deposit(1000000_00, 1700000000, "operator_001").unwrap();
|
||
protocol.open_position(2000_00, 1700000001, "operator_001").unwrap();
|
||
|
||
// 黄金价格上涨到$2200/盎司
|
||
protocol.update_gold_price(2200_00).unwrap();
|
||
|
||
// 验证未实现盈亏
|
||
// 持仓500盎司,价格从$2000涨到$2200
|
||
// 盈利 = 500 × ($2200 - $2000) = 10万USDT
|
||
assert_eq!(protocol.account.unrealized_pnl, 10000000);
|
||
|
||
// 验证GCR提升
|
||
// 黄金持仓价值:500盎司 × $2200 = 110万USDT
|
||
// 风险准备金:20万USDT
|
||
// 总储备:130万USDT
|
||
// GCR = 130万 / 100万 = 130%
|
||
let gcr = protocol.calculate_gcr();
|
||
assert_eq!(gcr, 130);
|
||
assert_eq!(protocol.status, ReserveStatus::Healthy);
|
||
}
|
||
|
||
#[test]
|
||
fn test_liquidation_trigger() {
|
||
let mut protocol = GoldReserveProtocol::new("reserve_001".to_string());
|
||
|
||
// 注入资金并开仓
|
||
protocol.deposit(1000000_00, 1700000000, "operator_001").unwrap();
|
||
protocol.open_position(2000_00, 1700000001, "operator_001").unwrap();
|
||
|
||
// 黄金价格暴跌到$1400/盎司(触发强制平仓)
|
||
let result = protocol.update_gold_price(1400_00);
|
||
assert!(result.is_err());
|
||
assert!(result.unwrap_err().contains("Liquidation triggered"));
|
||
}
|
||
|
||
#[test]
|
||
fn test_reserve_status() {
|
||
let mut protocol = GoldReserveProtocol::new("reserve_001".to_string());
|
||
|
||
// 注入资金并开仓
|
||
protocol.deposit(1000000_00, 1700000000, "operator_001").unwrap();
|
||
protocol.open_position(2000_00, 1700000001, "operator_001").unwrap();
|
||
|
||
// 初始状态:Warning (GCR=120%)
|
||
assert_eq!(protocol.status, ReserveStatus::Warning);
|
||
|
||
// 黄金价格下跌到$1800,GCR降至108%
|
||
protocol.update_gold_price(1800_00).unwrap();
|
||
assert_eq!(protocol.status, ReserveStatus::Warning);
|
||
|
||
// 黄金价格下跌到$1600,GCR降至96%
|
||
protocol.update_gold_price(1600_00).unwrap();
|
||
assert_eq!(protocol.status, ReserveStatus::Danger);;
|
||
}
|
||
|
||
#[test]
|
||
fn test_use_risk_reserve() {
|
||
let mut protocol = GoldReserveProtocol::new("reserve_001".to_string());
|
||
|
||
// 注入资金并开仓
|
||
protocol.deposit(1000000_00, 1700000000, "operator_001").unwrap();
|
||
protocol.open_position(2000_00, 1700000001, "operator_001").unwrap();
|
||
|
||
// 黄金价格下跌到$1500,进入Critical状态
|
||
protocol.update_gold_price(1500_00).unwrap();
|
||
assert_eq!(protocol.status, ReserveStatus::Critical);
|
||
|
||
// 使用风险准备金
|
||
protocol.use_risk_reserve(50000_00, 1700000002, "operator_001").unwrap();
|
||
assert_eq!(protocol.account.risk_reserve_balance, 150000_00);
|
||
}
|
||
}
|