Files

640 lines
22 KiB
Rust

//! # Application 6: Anti-Cascade Financial Systems
//!
//! Transactions, leverage, or derivatives that increase systemic incoherence
//! are throttled or blocked automatically.
//!
//! ## Problem
//! Financial cascades (2008, flash crashes) happen when local actions
//! destroy global coherence faster than the system can respond.
//!
//! ## Δ-Behavior Solution
//! Every transaction must preserve or improve systemic coherence.
//! High-risk operations face exponential energy costs.
//!
//! ## Exotic Result
//! A financial system that cannot cascade into collapse by construction.
use std::collections::{HashMap, VecDeque};
/// A financial system with coherence-enforced stability
pub struct AntiCascadeFinancialSystem {
/// Market participants
participants: HashMap<String, Participant>,
/// Open positions
positions: Vec<Position>,
/// Systemic coherence (1.0 = stable, 0.0 = collapse)
coherence: f64,
/// Coherence thresholds
warning_threshold: f64,
critical_threshold: f64,
lockdown_threshold: f64,
/// Maximum allowed leverage system-wide
max_system_leverage: f64,
/// Current aggregate leverage
current_leverage: f64,
/// Transaction queue (pending during high stress)
pending_transactions: Vec<Transaction>,
/// Circuit breaker state
circuit_breaker: CircuitBreakerState,
/// Historical coherence for trend analysis
coherence_history: VecDeque<f64>,
/// Cached coherence factors (updated when underlying data changes)
cached_leverage_factor: f64,
cached_depth_factor: f64,
}
#[derive(Clone)]
pub struct Participant {
pub id: String,
pub capital: f64,
pub exposure: f64,
pub risk_rating: f64, // 0.0 = safe, 1.0 = risky
pub interconnectedness: f64, // How many counterparties
}
#[derive(Clone)]
pub struct Position {
pub holder: String,
pub counterparty: String,
pub notional: f64,
pub leverage: f64,
pub derivative_depth: u8, // 0 = spot, 1 = derivative, 2 = derivative of derivative, etc.
}
#[derive(Clone)]
pub struct Transaction {
pub id: u64,
pub from: String,
pub to: String,
pub amount: f64,
pub transaction_type: TransactionType,
pub timestamp: u64,
}
#[derive(Clone, Debug)]
pub enum TransactionType {
/// Simple transfer
Transfer,
/// Open leveraged position
OpenLeverage { leverage: f64 },
/// Close position
ClosePosition { position_id: usize },
/// Create derivative
CreateDerivative { underlying_position: usize },
/// Margin call
MarginCall { participant: String },
}
#[derive(Debug, Clone, PartialEq)]
pub enum CircuitBreakerState {
/// Normal operation
Open,
/// Elevated monitoring
Cautious,
/// Only risk-reducing transactions allowed
Restricted,
/// All transactions halted
Halted,
}
#[derive(Debug)]
pub enum TransactionResult {
/// Transaction executed
Executed {
coherence_impact: f64,
fee_multiplier: f64,
},
/// Transaction queued for later
Queued { reason: String },
/// Transaction rejected
Rejected { reason: String },
/// System halted
SystemHalted,
}
impl AntiCascadeFinancialSystem {
pub fn new() -> Self {
let mut history = VecDeque::with_capacity(100);
history.push_back(1.0);
Self {
participants: HashMap::new(),
positions: Vec::new(),
coherence: 1.0,
warning_threshold: 0.7,
critical_threshold: 0.5,
lockdown_threshold: 0.3,
max_system_leverage: 10.0,
current_leverage: 1.0,
pending_transactions: Vec::new(),
circuit_breaker: CircuitBreakerState::Open,
coherence_history: history,
cached_leverage_factor: 0.9, // 1.0 - (1.0 / 10.0) for initial leverage
cached_depth_factor: 1.0, // No positions initially
}
}
pub fn add_participant(&mut self, id: &str, capital: f64) {
self.participants.insert(id.to_string(), Participant {
id: id.to_string(),
capital,
exposure: 0.0,
risk_rating: 0.0,
interconnectedness: 0.0,
});
}
/// Calculate systemic coherence based on multiple risk factors
/// Optimized: Single-pass calculation for participant metrics
fn calculate_coherence(&self) -> f64 {
if self.participants.is_empty() {
return 1.0;
}
// Use pre-computed cached factors for leverage and depth
let leverage_factor = self.cached_leverage_factor;
let depth_factor = self.cached_depth_factor;
// Single-pass calculation for interconnectedness, exposure, and capital
let (sum_interconnect, total_exposure, total_capital) = self.participants.values()
.fold((0.0, 0.0, 0.0), |(ic, exp, cap), p| {
(ic + p.interconnectedness, exp + p.exposure, cap + p.capital)
});
// Factor 3: Interconnectedness risk (contagion potential)
let avg_interconnectedness = sum_interconnect / self.participants.len() as f64;
let interconnect_factor = 1.0 / (1.0 + avg_interconnectedness * 0.1);
// Factor 4: Capital adequacy
let capital_factor = if total_exposure > 0.0 {
(total_capital / total_exposure).min(1.0)
} else {
1.0
};
// Factor 5: Coherence trend (declining coherence is worse)
let trend_factor = if self.coherence_history.len() >= 5 {
// VecDeque allows efficient back access
let len = self.coherence_history.len();
let newest = self.coherence_history[len - 1];
let oldest_of_five = self.coherence_history[len - 5];
let trend = newest - oldest_of_five;
if trend < 0.0 {
1.0 + trend // Penalize declining trend
} else {
1.0
}
} else {
1.0
};
// Geometric mean of factors (more sensitive to low values)
let product = leverage_factor * depth_factor * interconnect_factor
* capital_factor * trend_factor;
product.powf(0.2).clamp(0.0, 1.0)
}
/// Update cached coherence factors when positions or leverage change
fn update_cached_factors(&mut self) {
// Factor 1: Leverage concentration
self.cached_leverage_factor = 1.0 - (self.current_leverage / self.max_system_leverage).min(1.0);
// Factor 2: Derivative depth (single pass over positions)
let max_depth = self.positions.iter()
.map(|p| p.derivative_depth)
.max()
.unwrap_or(0);
self.cached_depth_factor = 1.0 / (1.0 + max_depth as f64 * 0.2);
}
/// Calculate the energy cost for a transaction (higher for risky transactions)
fn transaction_energy_cost(&self, tx: &Transaction) -> f64 {
let base_cost = match &tx.transaction_type {
TransactionType::Transfer => 1.0,
TransactionType::OpenLeverage { leverage } => {
// Exponential cost for leverage
(1.0 + leverage).powf(2.0)
}
TransactionType::ClosePosition { .. } => 0.5, // Closing is cheap (reduces risk)
TransactionType::CreateDerivative { underlying_position } => {
// Cost increases with derivative depth
let depth = self.positions.get(*underlying_position)
.map(|p| p.derivative_depth)
.unwrap_or(0);
(2.0_f64).powf(depth as f64 + 1.0)
}
TransactionType::MarginCall { .. } => 0.1, // Emergency actions are cheap
};
// Multiply by inverse coherence (lower coherence = higher costs)
let coherence_multiplier = 1.0 / self.coherence.max(0.1);
// Circuit breaker multiplier
let circuit_multiplier = match self.circuit_breaker {
CircuitBreakerState::Open => 1.0,
CircuitBreakerState::Cautious => 2.0,
CircuitBreakerState::Restricted => 10.0,
CircuitBreakerState::Halted => f64::INFINITY,
};
base_cost * coherence_multiplier * circuit_multiplier
}
/// Predict coherence impact of a transaction
fn predict_coherence_impact(&self, tx: &Transaction) -> f64 {
match &tx.transaction_type {
TransactionType::Transfer => 0.0, // Neutral
TransactionType::OpenLeverage { leverage } => {
-0.01 * leverage // Leverage reduces coherence
}
TransactionType::ClosePosition { .. } => 0.02, // Closing improves coherence
TransactionType::CreateDerivative { .. } => -0.05, // Derivatives hurt coherence
TransactionType::MarginCall { .. } => 0.03, // Margin calls improve coherence
}
}
/// Process a transaction through the Δ-behavior filter
pub fn process_transaction(&mut self, tx: Transaction) -> TransactionResult {
// Update circuit breaker state
self.update_circuit_breaker();
// Check if system is halted
if self.circuit_breaker == CircuitBreakerState::Halted {
return TransactionResult::SystemHalted;
}
// Calculate energy cost
let energy_cost = self.transaction_energy_cost(&tx);
// Predict coherence impact
let predicted_impact = self.predict_coherence_impact(&tx);
let predicted_coherence = self.coherence + predicted_impact;
// CORE Δ-BEHAVIOR: Reject if would cross lockdown threshold
if predicted_coherence < self.lockdown_threshold {
return TransactionResult::Rejected {
reason: format!(
"Transaction would reduce coherence to {:.3} (threshold: {:.3})",
predicted_coherence, self.lockdown_threshold
),
};
}
// In restricted mode, only allow risk-reducing transactions
if self.circuit_breaker == CircuitBreakerState::Restricted {
match &tx.transaction_type {
TransactionType::ClosePosition { .. } | TransactionType::MarginCall { .. } => {}
_ => {
return TransactionResult::Queued {
reason: "System in restricted mode - only risk-reducing transactions allowed".to_string(),
};
}
}
}
// Execute the transaction
self.execute_transaction(&tx);
// Update coherence
self.coherence = self.calculate_coherence();
self.coherence_history.push_back(self.coherence);
// Keep history bounded - O(1) with VecDeque instead of O(n) with Vec
if self.coherence_history.len() > 100 {
self.coherence_history.pop_front();
}
TransactionResult::Executed {
coherence_impact: predicted_impact,
fee_multiplier: energy_cost,
}
}
fn execute_transaction(&mut self, tx: &Transaction) {
match &tx.transaction_type {
TransactionType::Transfer => {
// Simple transfer logic
if let Some(from) = self.participants.get_mut(&tx.from) {
from.capital -= tx.amount;
}
if let Some(to) = self.participants.get_mut(&tx.to) {
to.capital += tx.amount;
}
}
TransactionType::OpenLeverage { leverage } => {
// Create leveraged position
self.positions.push(Position {
holder: tx.from.clone(),
counterparty: tx.to.clone(),
notional: tx.amount * leverage,
leverage: *leverage,
derivative_depth: 0,
});
// Update metrics
self.current_leverage = (self.current_leverage + leverage) / 2.0;
// Update participant exposure
if let Some(holder) = self.participants.get_mut(&tx.from) {
holder.exposure += tx.amount * leverage;
holder.interconnectedness += 1.0;
}
if let Some(counterparty) = self.participants.get_mut(&tx.to) {
counterparty.interconnectedness += 1.0;
}
// Update cached factors since leverage/positions changed
self.update_cached_factors();
}
TransactionType::ClosePosition { position_id } => {
if *position_id < self.positions.len() {
let pos = self.positions.remove(*position_id);
// Reduce leverage
self.current_leverage = (self.current_leverage - pos.leverage * 0.1).max(1.0);
// Update participant exposure
if let Some(holder) = self.participants.get_mut(&pos.holder) {
holder.exposure = (holder.exposure - pos.notional).max(0.0);
}
// Update cached factors since leverage/positions changed
self.update_cached_factors();
}
}
TransactionType::CreateDerivative { underlying_position } => {
if let Some(underlying) = self.positions.get(*underlying_position) {
self.positions.push(Position {
holder: tx.from.clone(),
counterparty: tx.to.clone(),
notional: underlying.notional * 0.5,
leverage: underlying.leverage * 1.5,
derivative_depth: underlying.derivative_depth + 1,
});
// Update cached factors since positions changed (derivative depth may increase)
self.update_cached_factors();
}
}
TransactionType::MarginCall { participant } => {
// Force close risky positions for participant using retain() - O(n) instead of O(n^2)
let initial_len = self.positions.len();
self.positions.retain(|p| !(&p.holder == participant && p.leverage > 5.0));
// Update cached factors if positions were removed
if self.positions.len() != initial_len {
self.update_cached_factors();
}
}
}
}
fn update_circuit_breaker(&mut self) {
self.circuit_breaker = match self.coherence {
c if c >= self.warning_threshold => CircuitBreakerState::Open,
c if c >= self.critical_threshold => CircuitBreakerState::Cautious,
c if c >= self.lockdown_threshold => CircuitBreakerState::Restricted,
_ => CircuitBreakerState::Halted,
};
}
/// Process pending transactions (called when coherence improves)
pub fn process_pending(&mut self) -> Vec<TransactionResult> {
if self.circuit_breaker == CircuitBreakerState::Halted
|| self.circuit_breaker == CircuitBreakerState::Restricted {
return Vec::new();
}
let pending = std::mem::take(&mut self.pending_transactions);
pending.into_iter()
.map(|tx| self.process_transaction(tx))
.collect()
}
pub fn coherence(&self) -> f64 {
self.coherence
}
pub fn circuit_breaker_state(&self) -> &CircuitBreakerState {
&self.circuit_breaker
}
pub fn status(&self) -> String {
format!(
"Coherence: {:.3} | Circuit Breaker: {:?} | Leverage: {:.2}x | Positions: {} | Pending: {}",
self.coherence,
self.circuit_breaker,
self.current_leverage,
self.positions.len(),
self.pending_transactions.len()
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_anti_cascade_basic() {
let mut system = AntiCascadeFinancialSystem::new();
system.add_participant("bank_a", 1000.0);
system.add_participant("bank_b", 1000.0);
system.add_participant("hedge_fund", 500.0);
// Normal transaction should succeed
let tx = Transaction {
id: 1,
from: "bank_a".to_string(),
to: "bank_b".to_string(),
amount: 100.0,
transaction_type: TransactionType::Transfer,
timestamp: 0,
};
let result = system.process_transaction(tx);
assert!(matches!(result, TransactionResult::Executed { .. }));
println!("After transfer: {}", system.status());
}
#[test]
fn test_leverage_throttling() {
let mut system = AntiCascadeFinancialSystem::new();
system.add_participant("bank_a", 1000.0);
system.add_participant("bank_b", 1000.0);
// Open multiple leveraged positions - costs should increase
let mut costs = Vec::new();
for i in 0..5 {
let tx = Transaction {
id: i,
from: "bank_a".to_string(),
to: "bank_b".to_string(),
amount: 100.0,
transaction_type: TransactionType::OpenLeverage { leverage: 5.0 },
timestamp: i,
};
if let TransactionResult::Executed { fee_multiplier, .. } = system.process_transaction(tx) {
costs.push(fee_multiplier);
println!("Position {}: cost multiplier = {:.2}", i, fee_multiplier);
}
println!(" Status: {}", system.status());
}
// Costs should generally increase as coherence drops
// (though relationship isn't strictly monotonic due to multiple factors)
println!("Cost progression: {:?}", costs);
}
#[test]
fn test_derivative_depth_limit() {
let mut system = AntiCascadeFinancialSystem::new();
system.add_participant("bank_a", 10000.0);
system.add_participant("bank_b", 10000.0);
// Create base position
let tx = Transaction {
id: 0,
from: "bank_a".to_string(),
to: "bank_b".to_string(),
amount: 100.0,
transaction_type: TransactionType::OpenLeverage { leverage: 2.0 },
timestamp: 0,
};
system.process_transaction(tx);
// Try to create derivatives of derivatives
for i in 0..5 {
let tx = Transaction {
id: i + 1,
from: "bank_a".to_string(),
to: "bank_b".to_string(),
amount: 50.0,
transaction_type: TransactionType::CreateDerivative { underlying_position: i as usize },
timestamp: i + 1,
};
let result = system.process_transaction(tx);
println!("Derivative layer {}: {:?}", i, result);
println!(" Status: {}", system.status());
// Eventually should be rejected or system should halt
if matches!(result, TransactionResult::Rejected { .. } | TransactionResult::SystemHalted) {
println!("System prevented excessive derivative depth at layer {}", i);
return;
}
}
}
#[test]
fn test_cascade_prevention() {
let mut system = AntiCascadeFinancialSystem::new();
// Create interconnected network
for i in 0..10 {
system.add_participant(&format!("bank_{}", i), 1000.0);
}
// Try to create a cascade scenario
let mut rejected_count = 0;
let mut queued_count = 0;
let mut halted = false;
for i in 0..50 {
let from = format!("bank_{}", i % 10);
let to = format!("bank_{}", (i + 1) % 10);
let tx = Transaction {
id: i,
from,
to,
amount: 200.0,
transaction_type: TransactionType::OpenLeverage { leverage: 8.0 },
timestamp: i,
};
match system.process_transaction(tx) {
TransactionResult::Rejected { reason } => {
rejected_count += 1;
println!("Transaction {} rejected: {}", i, reason);
}
TransactionResult::SystemHalted => {
halted = true;
println!("System halted at transaction {}", i);
break;
}
TransactionResult::Queued { reason } => {
queued_count += 1;
println!("Transaction {} queued: {}", i, reason);
}
TransactionResult::Executed { .. } => {}
}
}
println!("\n=== Final Status ===");
println!("{}", system.status());
println!("Rejected: {}, Queued: {}, Halted: {}", rejected_count, queued_count, halted);
// System should have prevented the cascade (via rejection, queueing, or halt)
assert!(rejected_count > 0 || queued_count > 0 || halted, "System should prevent cascade");
}
#[test]
fn test_margin_call_improves_coherence() {
let mut system = AntiCascadeFinancialSystem::new();
system.add_participant("risky_fund", 500.0);
system.add_participant("counterparty", 5000.0);
// Open risky positions
for i in 0..3 {
let tx = Transaction {
id: i,
from: "risky_fund".to_string(),
to: "counterparty".to_string(),
amount: 100.0,
transaction_type: TransactionType::OpenLeverage { leverage: 7.0 },
timestamp: i,
};
system.process_transaction(tx);
}
let coherence_before = system.coherence();
println!("Before margin call: {}", system.status());
// Issue margin call
let margin_tx = Transaction {
id: 100,
from: "system".to_string(),
to: "risky_fund".to_string(),
amount: 0.0,
transaction_type: TransactionType::MarginCall { participant: "risky_fund".to_string() },
timestamp: 100,
};
system.process_transaction(margin_tx);
let coherence_after = system.coherence();
println!("After margin call: {}", system.status());
// Coherence should improve after margin call
assert!(
coherence_after >= coherence_before,
"Margin call should improve or maintain coherence"
);
}
}