use brk_error::Result; use brk_types::{Bitcoin, Dollars, Indexes, StoredF32}; use vecdb::Exit; use super::{Vecs, gini}; use crate::{distribution, internal::RatioDollarsBp32, market, mining, transactions}; impl Vecs { #[allow(clippy::too_many_arguments)] pub(crate) fn compute( &mut self, mining: &mining::Vecs, distribution: &distribution::Vecs, transactions: &transactions::Vecs, market: &market::Vecs, starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { self.db.sync_bg_tasks()?; // Puell Multiple: daily_subsidy_usd / sma_365d_subsidy_usd self.puell_multiple .bps .compute_binary::( starting_indexes.height, &mining.rewards.subsidy.block.usd, &mining.rewards.subsidy.average._1y.usd.height, exit, )?; // Gini coefficient (UTXO distribution inequality) gini::compute(&mut self.gini, distribution, starting_indexes, exit)?; // RHODL Ratio: 1d-1w realized cap / 1y-2y realized cap self.rhodl_ratio .bps .compute_binary::( starting_indexes.height, &distribution .utxo_cohorts .age_range ._1d_to_1w .metrics .realized .cap .usd .height, &distribution .utxo_cohorts .age_range ._1y_to_2y .metrics .realized .cap .usd .height, exit, )?; // NVT: market_cap / tx_volume_24h let market_cap = &distribution .utxo_cohorts .all .metrics .supply .total .usd .height; self.nvt .bps .compute_binary::( starting_indexes.height, market_cap, &transactions.volume.transfer_volume.sum._24h.usd.height, exit, )?; // Thermocap Multiple: market_cap / thermo_cap self.thermo_cap_multiple .bps .compute_binary::( starting_indexes.height, market_cap, &mining.rewards.subsidy.cumulative.usd.height, exit, )?; let all_metrics = &distribution.utxo_cohorts.all.metrics; let all_activity = &all_metrics.activity; let supply_total_sats = &all_metrics.supply.total.sats.height; // Supply-Adjusted CDD = sum_24h(CDD) / circulating_supply_btc self.coindays_destroyed_supply_adj .height .compute_transform2( starting_indexes.height, &all_activity.coindays_destroyed.sum._24h.height, supply_total_sats, |(i, cdd_24h, supply_sats, ..)| { let supply = f64::from(Bitcoin::from(supply_sats)); if supply == 0.0 { (i, StoredF32::from(0.0f32)) } else { (i, StoredF32::from((f64::from(cdd_24h) / supply) as f32)) } }, exit, )?; // Supply-Adjusted CYD = CYD / circulating_supply_btc self.coinyears_destroyed_supply_adj .height .compute_transform2( starting_indexes.height, &all_activity.coinyears_destroyed.height, supply_total_sats, |(i, cyd, supply_sats, ..)| { let supply = f64::from(Bitcoin::from(supply_sats)); if supply == 0.0 { (i, StoredF32::from(0.0f32)) } else { (i, StoredF32::from((f64::from(cyd) / supply) as f32)) } }, exit, )?; // Supply-Adjusted Dormancy = dormancy / circulating_supply_btc self.dormancy.supply_adj.height.compute_transform2( starting_indexes.height, &all_activity.dormancy._24h.height, supply_total_sats, |(i, dormancy, supply_sats, ..)| { let supply = f64::from(Bitcoin::from(supply_sats)); if supply == 0.0 { (i, StoredF32::from(0.0f32)) } else { (i, StoredF32::from((f64::from(dormancy) / supply) as f32)) } }, exit, )?; // Stock-to-Flow: supply / annual_issuance // annual_issuance ≈ subsidy_per_block × 52560 (blocks/year) self.stock_to_flow.height.compute_transform2( starting_indexes.height, supply_total_sats, &mining.rewards.subsidy.block.sats, |(i, supply_sats, subsidy_sats, ..)| { let annual_flow = subsidy_sats.as_u128() as f64 * 52560.0; if annual_flow == 0.0 { (i, StoredF32::from(0.0f32)) } else { ( i, StoredF32::from((supply_sats.as_u128() as f64 / annual_flow) as f32), ) } }, exit, )?; // Dormancy Flow: supply_btc / dormancy self.dormancy.flow.height.compute_transform2( starting_indexes.height, supply_total_sats, &all_activity.dormancy._24h.height, |(i, supply_sats, dormancy, ..)| { let d = f64::from(dormancy); if d == 0.0 { (i, StoredF32::from(0.0f32)) } else { let supply = f64::from(Bitcoin::from(supply_sats)); (i, StoredF32::from((supply / d) as f32)) } }, exit, )?; // Seller Exhaustion Constant: % supply_in_profit × 30d_volatility self.seller_exhaustion.height.compute_transform3( starting_indexes.height, &all_metrics.supply.in_profit.sats.height, &market.volatility._1m.height, supply_total_sats, |(i, profit_sats, volatility, total_sats, ..)| { let total = total_sats.as_u128() as f64; if total == 0.0 { (i, StoredF32::from(0.0f32)) } else { let pct_in_profit = profit_sats.as_u128() as f64 / total; ( i, StoredF32::from((pct_in_profit * f64::from(volatility)) as f32), ) } }, exit, )?; let exit = exit.clone(); self.db.run_bg(move |db| { let _lock = exit.lock(); db.compact_deferred_default() }); Ok(()) } }