From 5ede3dc416f8fad73411e294506db00bc0c55728 Mon Sep 17 00:00:00 2001 From: nym21 Date: Tue, 10 Mar 2026 11:22:17 +0100 Subject: [PATCH] global: snapshot --- .../brk_computer/src/blocks/count/compute.rs | 8 +- .../src/cointime/activity/compute.rs | 6 +- .../src/cointime/reserve_risk/compute.rs | 2 +- .../src/cointime/value/compute.rs | 6 +- .../src/distribution/block/cohort/sent.rs | 3 +- .../src/distribution/cohorts/utxo/send.rs | 3 +- .../src/distribution/compute/block_loop.rs | 23 ++++- .../src/distribution/compute/write.rs | 10 +- .../src/distribution/metrics/activity/full.rs | 35 +------ .../src/distribution/metrics/realized/full.rs | 8 +- .../src/distribution/metrics/supply/core.rs | 96 +++++++++++++++++++ .../src/distribution/metrics/supply/mod.rs | 2 + .../src/distribution/state/cohort/address.rs | 1 - .../src/distribution/state/cohort/base.rs | 5 - .../src/distribution/state/cohort/utxo.rs | 1 - crates/brk_computer/src/distribution/vecs.rs | 18 +++- crates/brk_computer/src/indicators/compute.rs | 78 +++++++++++++++ .../src/{market => }/indicators/gini.rs | 0 crates/brk_computer/src/indicators/import.rs | 38 ++++++++ crates/brk_computer/src/indicators/mod.rs | 8 ++ crates/brk_computer/src/indicators/vecs.rs | 15 +++ .../internal/per_block/computed/cumulative.rs | 21 ++-- .../per_block/computed/cumulative_sum.rs | 27 +++--- .../src/internal/per_block/computed/full.rs | 21 ++-- .../src/internal/per_block/computed/sum.rs | 20 ++-- crates/brk_computer/src/lib.rs | 59 ++++++++---- crates/brk_computer/src/market/compute.rs | 11 +-- crates/brk_computer/src/market/import.rs | 6 +- crates/brk_computer/src/market/mod.rs | 6 +- .../{indicators => technical}/compute.rs | 65 +------------ .../{indicators => technical}/import.rs | 16 +--- .../market/{indicators => technical}/macd.rs | 0 .../market/{indicators => technical}/mod.rs | 1 - .../market/{indicators => technical}/rsi.rs | 0 .../market/{indicators => technical}/vecs.rs | 9 +- crates/brk_computer/src/pools/major.rs | 4 +- crates/brk_computer/src/scripts/adoption.rs | 4 +- .../brk_computer/src/scripts/count/compute.rs | 6 +- .../src/transactions/volume/compute.rs | 2 +- crates/brk_types/src/age.rs | 23 +---- 40 files changed, 408 insertions(+), 259 deletions(-) create mode 100644 crates/brk_computer/src/distribution/metrics/supply/core.rs create mode 100644 crates/brk_computer/src/indicators/compute.rs rename crates/brk_computer/src/{market => }/indicators/gini.rs (100%) create mode 100644 crates/brk_computer/src/indicators/import.rs create mode 100644 crates/brk_computer/src/indicators/mod.rs create mode 100644 crates/brk_computer/src/indicators/vecs.rs rename crates/brk_computer/src/market/{indicators => technical}/compute.rs (60%) rename crates/brk_computer/src/market/{indicators => technical}/import.rs (86%) rename crates/brk_computer/src/market/{indicators => technical}/macd.rs (100%) rename crates/brk_computer/src/market/{indicators => technical}/mod.rs (90%) rename crates/brk_computer/src/market/{indicators => technical}/rsi.rs (100%) rename crates/brk_computer/src/market/{indicators => technical}/vecs.rs (83%) diff --git a/crates/brk_computer/src/blocks/count/compute.rs b/crates/brk_computer/src/blocks/count/compute.rs index 62709a7aa..d03c820c3 100644 --- a/crates/brk_computer/src/blocks/count/compute.rs +++ b/crates/brk_computer/src/blocks/count/compute.rs @@ -15,8 +15,8 @@ impl Vecs { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - // Block count height + cumulative - self.block_count.height.compute_range( + // Block count raw + cumulative + self.block_count.raw.height.compute_range( starting_indexes.height, &indexer.vecs.blocks.weight, |h| (h, StoredU32::from(1_u32)), @@ -24,7 +24,7 @@ impl Vecs { )?; self.block_count.cumulative.height.compute_cumulative( starting_indexes.height, - &self.block_count.height, + &self.block_count.raw.height, exit, )?; @@ -33,7 +33,7 @@ impl Vecs { self.block_count.sum.compute_rolling_sum( starting_indexes.height, &ws, - &self.block_count.height, + &self.block_count.raw.height, exit, )?; diff --git a/crates/brk_computer/src/cointime/activity/compute.rs b/crates/brk_computer/src/cointime/activity/compute.rs index 10b13e9bb..b0c28df69 100644 --- a/crates/brk_computer/src/cointime/activity/compute.rs +++ b/crates/brk_computer/src/cointime/activity/compute.rs @@ -33,8 +33,8 @@ impl Vecs { .compute(starting_indexes.height, &window_starts, exit, |vec| { vec.compute_subtract( starting_indexes.height, - &self.coinblocks_created.height, - &all_metrics.activity.coinblocks_destroyed.raw.height, + &self.coinblocks_created.raw.height, + &distribution.coinblocks_destroyed.raw.height, exit, )?; Ok(()) @@ -42,7 +42,7 @@ impl Vecs { self.liveliness.height.compute_divide( starting_indexes.height, - &all_metrics.activity.coinblocks_destroyed.cumulative.height, + &distribution.coinblocks_destroyed.cumulative.height, &self.coinblocks_created.cumulative.height, exit, )?; diff --git a/crates/brk_computer/src/cointime/reserve_risk/compute.rs b/crates/brk_computer/src/cointime/reserve_risk/compute.rs index 1da180884..fe481e225 100644 --- a/crates/brk_computer/src/cointime/reserve_risk/compute.rs +++ b/crates/brk_computer/src/cointime/reserve_risk/compute.rs @@ -17,7 +17,7 @@ impl Vecs { self.vocdd_median_1y.compute_rolling_median_from_starts( starting_indexes.height, &blocks.lookback.height_1y_ago, - &value.vocdd.height, + &value.vocdd.raw.height, exit, )?; diff --git a/crates/brk_computer/src/cointime/value/compute.rs b/crates/brk_computer/src/cointime/value/compute.rs index eb3810a55..961d04176 100644 --- a/crates/brk_computer/src/cointime/value/compute.rs +++ b/crates/brk_computer/src/cointime/value/compute.rs @@ -19,7 +19,7 @@ impl Vecs { let window_starts = blocks.lookback.window_starts(); let all_metrics = &distribution.utxo_cohorts.all.metrics; - let coinblocks_destroyed = &all_metrics.activity.coinblocks_destroyed; + let coinblocks_destroyed = &distribution.coinblocks_destroyed; let coindays_destroyed = &all_metrics.activity.coindays_destroyed; let circulating_supply = &all_metrics.supply.total.btc.height; @@ -39,7 +39,7 @@ impl Vecs { vec.compute_multiply( starting_indexes.height, &prices.price.usd.height, - &activity.coinblocks_created.height, + &activity.coinblocks_created.raw.height, exit, )?; Ok(()) @@ -50,7 +50,7 @@ impl Vecs { vec.compute_multiply( starting_indexes.height, &prices.price.usd.height, - &activity.coinblocks_stored.height, + &activity.coinblocks_stored.raw.height, exit, )?; Ok(()) diff --git a/crates/brk_computer/src/distribution/block/cohort/sent.rs b/crates/brk_computer/src/distribution/block/cohort/sent.rs index f8dadcc58..c71709868 100644 --- a/crates/brk_computer/src/distribution/block/cohort/sent.rs +++ b/crates/brk_computer/src/distribution/block/cohort/sent.rs @@ -47,8 +47,7 @@ pub(crate) fn process_sent( for (receive_height, by_type) in sent_data.into_iter() { let prev_price = height_to_price[receive_height.to_usize()]; let prev_timestamp = height_to_timestamp[receive_height.to_usize()]; - let blocks_old = current_height.to_usize() - receive_height.to_usize(); - let age = Age::new(current_timestamp, prev_timestamp, blocks_old); + let age = Age::new(current_timestamp, prev_timestamp); // Compute peak price during holding period for peak regret // This is the max HIGH price between receive and send heights diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/send.rs b/crates/brk_computer/src/distribution/cohorts/utxo/send.rs index b72631c22..b67c62e10 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/send.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/send.rs @@ -43,8 +43,7 @@ impl UTXOCohorts { let block_state = &chain_state[receive_height.to_usize()]; let prev_price = block_state.price; - let blocks_old = chain_len - 1 - receive_height.to_usize(); - let age = Age::new(last_timestamp, block_state.timestamp, blocks_old); + let age = Age::new(last_timestamp, block_state.timestamp); // Compute peak price during holding period for peak regret // This is the max price between receive and send heights diff --git a/crates/brk_computer/src/distribution/compute/block_loop.rs b/crates/brk_computer/src/distribution/compute/block_loop.rs index f60facb89..081ebf954 100644 --- a/crates/brk_computer/src/distribution/compute/block_loop.rs +++ b/crates/brk_computer/src/distribution/compute/block_loop.rs @@ -2,12 +2,12 @@ use brk_cohort::ByAddressType; use brk_error::Result; use brk_indexer::Indexer; use brk_types::{ - Cents, Date, Height, ONE_DAY_IN_SEC, OutputType, Sats, Timestamp, TxIndex, TypeIndex, + Cents, Date, Height, ONE_DAY_IN_SEC, OutputType, Sats, StoredF64, Timestamp, TxIndex, TypeIndex, }; use rayon::prelude::*; use rustc_hash::FxHashSet; use tracing::{debug, info}; -use vecdb::{AnyVec, Exit, ReadableVec, VecIndex}; +use vecdb::{AnyVec, Exit, ReadableVec, VecIndex, WritableVec}; use crate::{ distribution::{ @@ -66,7 +66,7 @@ pub(crate) fn process_blocks( let height_to_first_txindex = &indexer.vecs.transactions.first_txindex; let height_to_first_txoutindex = &indexer.vecs.outputs.first_txoutindex; let height_to_first_txinindex = &indexer.vecs.inputs.first_txinindex; - let height_to_tx_count = &transactions.count.tx_count.height; + let height_to_tx_count = &transactions.count.tx_count.raw.height; let height_to_output_count = &outputs.count.total_count.full.sum; let height_to_input_count = &inputs.count.full.sum; let txindex_to_output_count = &indexes.txindex.output_count; @@ -353,6 +353,23 @@ pub(crate) fn process_blocks( timestamp, }); + // Compute total coinblocks destroyed (once globally, before send() consumes height_to_sent) + { + let h = height.to_usize(); + let total_satblocks: u128 = height_to_sent + .iter() + .filter(|(rh, _)| rh.to_usize() < h) + .map(|(rh, sent)| { + let blocks_old = h - rh.to_usize(); + blocks_old as u128 * u64::from(sent.spendable_supply.value) as u128 + }) + .sum(); + vecs.coinblocks_destroyed.raw.height.truncate_push( + height, + StoredF64::from(total_satblocks as f64 / Sats::ONE_BTC_U128 as f64), + )?; + } + // Record maturation (sats crossing age boundaries) vecs.utxo_cohorts.push_maturation(height, &matured)?; diff --git a/crates/brk_computer/src/distribution/compute/write.rs b/crates/brk_computer/src/distribution/compute/write.rs index 874f1b75d..474f1d32c 100644 --- a/crates/brk_computer/src/distribution/compute/write.rs +++ b/crates/brk_computer/src/distribution/compute/write.rs @@ -79,9 +79,13 @@ pub(crate) fn write( .chain(vecs.addr_count.par_iter_height_mut()) .chain(vecs.empty_addr_count.par_iter_height_mut()) .chain(vecs.address_activity.par_iter_height_mut()) - .chain(rayon::iter::once( - &mut vecs.supply_state as &mut dyn AnyStoredVec, - )) + .chain( + [ + &mut vecs.supply_state as &mut dyn AnyStoredVec, + &mut vecs.coinblocks_destroyed.raw.height, + ] + .into_par_iter(), + ) .chain(vecs.utxo_cohorts.par_iter_vecs_mut()) .chain(vecs.address_cohorts.par_iter_vecs_mut()) .try_for_each(|v| v.any_stamped_write_maybe_with_changes(stamp, with_changes))?; diff --git a/crates/brk_computer/src/distribution/metrics/activity/full.rs b/crates/brk_computer/src/distribution/metrics/activity/full.rs index 68610ac40..ca3a92a2a 100644 --- a/crates/brk_computer/src/distribution/metrics/activity/full.rs +++ b/crates/brk_computer/src/distribution/metrics/activity/full.rs @@ -2,7 +2,7 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Bitcoin, Height, Indexes, Sats, StoredF32, StoredF64, Version}; use derive_more::{Deref, DerefMut}; -use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, Rw, StorageMode, WritableVec}; +use vecdb::{AnyStoredVec, Exit, ReadableVec, Rw, StorageMode}; use crate::internal::{ComputedPerBlock, RollingWindowsFrom1w}; @@ -10,12 +10,6 @@ use crate::{blocks, distribution::{metrics::ImportConfig, state::{CohortState, R use super::ActivityCore; -#[derive(Traversable)] -pub struct ActivityCoinblocks { - pub raw: ComputedPerBlock, - pub cumulative: ComputedPerBlock, -} - #[derive(Deref, DerefMut, Traversable)] pub struct ActivityFull { #[deref] @@ -23,8 +17,6 @@ pub struct ActivityFull { #[traversable(flatten)] pub inner: ActivityCore, - pub coinblocks_destroyed: ActivityCoinblocks, - #[traversable(wrap = "coindays_destroyed", rename = "cumulative")] pub coindays_destroyed_cumulative: ComputedPerBlock, #[traversable(wrap = "coindays_destroyed", rename = "sum")] @@ -42,10 +34,6 @@ impl ActivityFull { let v1 = Version::ONE; Ok(Self { inner: ActivityCore::forced_import(cfg)?, - coinblocks_destroyed: ActivityCoinblocks { - raw: cfg.import("coinblocks_destroyed", v1)?, - cumulative: cfg.import("coinblocks_destroyed_cumulative", v1)?, - }, coindays_destroyed_cumulative: cfg.import("coindays_destroyed_cumulative", v1)?, coindays_destroyed_sum: cfg.import("coindays_destroyed", v1)?, sent_sum_extended: cfg.import("sent", v1)?, @@ -55,9 +43,7 @@ impl ActivityFull { } pub(crate) fn full_min_len(&self) -> usize { - self.inner - .min_len() - .min(self.coinblocks_destroyed.raw.height.len()) + self.inner.min_len() } pub(crate) fn full_truncate_push( @@ -65,17 +51,11 @@ impl ActivityFull { height: Height, state: &CohortState, ) -> Result<()> { - self.inner.truncate_push(height, state)?; - self.coinblocks_destroyed.raw.height.truncate_push( - height, - StoredF64::from(Bitcoin::from(state.satblocks_destroyed)), - )?; - Ok(()) + self.inner.truncate_push(height, state) } pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { let mut vecs = self.inner.collect_vecs_mut(); - vecs.push(&mut self.coinblocks_destroyed.raw.height as &mut dyn AnyStoredVec); vecs.push(&mut self.dormancy.height); vecs.push(&mut self.velocity.height); vecs @@ -100,15 +80,6 @@ impl ActivityFull { self.inner .compute_rest_part1(blocks, starting_indexes, exit)?; - self.coinblocks_destroyed - .cumulative - .height - .compute_cumulative( - starting_indexes.height, - &self.coinblocks_destroyed.raw.height, - exit, - )?; - self.coindays_destroyed_cumulative .height .compute_cumulative( diff --git a/crates/brk_computer/src/distribution/metrics/realized/full.rs b/crates/brk_computer/src/distribution/metrics/realized/full.rs index c06a9c716..33917b1f1 100644 --- a/crates/brk_computer/src/distribution/metrics/realized/full.rs +++ b/crates/brk_computer/src/distribution/metrics/realized/full.rs @@ -289,7 +289,7 @@ impl RealizedFull { .min(self.investor.price.cents.height.len()) .min(self.cap_raw.len()) .min(self.investor.cap_raw.len()) - .min(self.peak_regret.value.height.len()) + .min(self.peak_regret.value.raw.height.len()) } pub(crate) fn truncate_push( @@ -326,6 +326,7 @@ impl RealizedFull { .truncate_push(height, state.realized.investor_cap_raw())?; self.peak_regret .value + .raw .height .truncate_push(height, state.realized.peak_regret())?; @@ -341,7 +342,7 @@ impl RealizedFull { vecs.push(&mut self.investor.price.cents.height); vecs.push(&mut self.cap_raw as &mut dyn AnyStoredVec); vecs.push(&mut self.investor.cap_raw as &mut dyn AnyStoredVec); - vecs.push(&mut self.peak_regret.value.height); + vecs.push(&mut self.peak_regret.value.raw.height); vecs } @@ -400,6 +401,7 @@ impl RealizedFull { self.peak_regret .value + .raw .height .truncate_push(height, accum.peak_regret)?; @@ -609,7 +611,7 @@ impl RealizedFull { .rel_to_rcap .compute_binary::( starting_indexes.height, - &self.peak_regret.value.height, + &self.peak_regret.value.raw.height, &self.core.minimal.cap.cents.height, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/supply/core.rs b/crates/brk_computer/src/distribution/metrics/supply/core.rs new file mode 100644 index 000000000..b05137c07 --- /dev/null +++ b/crates/brk_computer/src/distribution/metrics/supply/core.rs @@ -0,0 +1,96 @@ +use brk_error::Result; +use brk_traversable::Traversable; +use brk_types::{Height, Indexes, Version}; +use derive_more::{Deref, DerefMut}; +use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec}; + +use crate::{distribution::state::UnrealizedState, prices}; + +use crate::internal::AmountPerBlock; + +use crate::distribution::metrics::ImportConfig; + +use super::SupplyBase; + +/// Core supply metrics: total + halved + in_profit/in_loss (4 stored vecs). +#[derive(Deref, DerefMut, Traversable)] +pub struct SupplyCore { + #[deref] + #[deref_mut] + #[traversable(flatten)] + pub base: SupplyBase, + + pub in_profit: AmountPerBlock, + pub in_loss: AmountPerBlock, +} + +impl SupplyCore { + pub(crate) fn forced_import(cfg: &ImportConfig) -> Result { + let v0 = Version::ZERO; + let base = SupplyBase::forced_import(cfg)?; + + Ok(Self { + base, + in_profit: cfg.import("supply_in_profit", v0)?, + in_loss: cfg.import("supply_in_loss", v0)?, + }) + } + + pub(crate) fn min_len(&self) -> usize { + self.base + .min_len() + .min(self.in_profit.sats.height.len()) + .min(self.in_loss.sats.height.len()) + } + + pub(crate) fn truncate_push_profitability( + &mut self, + height: Height, + state: &UnrealizedState, + ) -> Result<()> { + self.in_profit + .sats + .height + .truncate_push(height, state.supply_in_profit)?; + self.in_loss + .sats + .height + .truncate_push(height, state.supply_in_loss)?; + Ok(()) + } + + pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { + let mut vecs = self.base.collect_vecs_mut(); + vecs.push(&mut self.in_profit.sats.height as &mut dyn AnyStoredVec); + vecs.push(&mut self.in_profit.cents.height); + vecs.push(&mut self.in_loss.sats.height); + vecs.push(&mut self.in_loss.cents.height); + vecs + } + + pub(crate) fn compute( + &mut self, + prices: &prices::Vecs, + max_from: Height, + exit: &Exit, + ) -> Result<()> { + self.base.compute(prices, max_from, exit)?; + self.in_profit.compute(prices, max_from, exit)?; + self.in_loss.compute(prices, max_from, exit)?; + Ok(()) + } + + pub(crate) fn compute_from_stateful( + &mut self, + starting_indexes: &Indexes, + others: &[&Self], + exit: &Exit, + ) -> Result<()> { + let base_refs: Vec<&SupplyBase> = others.iter().map(|o| &o.base).collect(); + self.base + .compute_from_stateful(starting_indexes, &base_refs, exit)?; + sum_others!(self, starting_indexes, others, exit; in_profit.sats.height); + sum_others!(self, starting_indexes, others, exit; in_loss.sats.height); + Ok(()) + } +} diff --git a/crates/brk_computer/src/distribution/metrics/supply/mod.rs b/crates/brk_computer/src/distribution/metrics/supply/mod.rs index e8855dfb2..ddf44426f 100644 --- a/crates/brk_computer/src/distribution/metrics/supply/mod.rs +++ b/crates/brk_computer/src/distribution/metrics/supply/mod.rs @@ -1,5 +1,7 @@ mod base; +mod core; mod full; pub use base::SupplyBase; +pub use self::core::SupplyCore; pub use full::SupplyFull; diff --git a/crates/brk_computer/src/distribution/state/cohort/address.rs b/crates/brk_computer/src/distribution/state/cohort/address.rs index 2b35634f0..da6ed2491 100644 --- a/crates/brk_computer/src/distribution/state/cohort/address.rs +++ b/crates/brk_computer/src/distribution/state/cohort/address.rs @@ -28,7 +28,6 @@ impl AddressCohortState { self.addr_count = 0; self.inner.supply = SupplyState::default(); self.inner.sent = Sats::ZERO; - self.inner.satblocks_destroyed = Sats::ZERO; self.inner.satdays_destroyed = Sats::ZERO; self.inner.realized = R::default(); } diff --git a/crates/brk_computer/src/distribution/state/cohort/base.rs b/crates/brk_computer/src/distribution/state/cohort/base.rs index cc8dedba7..ee550acd2 100644 --- a/crates/brk_computer/src/distribution/state/cohort/base.rs +++ b/crates/brk_computer/src/distribution/state/cohort/base.rs @@ -53,7 +53,6 @@ pub struct CohortState { pub supply: SupplyState, pub realized: R, pub sent: Sats, - pub satblocks_destroyed: Sats, pub satdays_destroyed: Sats, cost_basis_data: CostBasisData, } @@ -64,7 +63,6 @@ impl CohortState { supply: SupplyState::default(), realized: R::default(), sent: Sats::ZERO, - satblocks_destroyed: Sats::ZERO, satdays_destroyed: Sats::ZERO, cost_basis_data: CostBasisData::create(path, name), } @@ -104,7 +102,6 @@ impl CohortState { pub(crate) fn reset_single_iteration_values(&mut self) { self.sent = Sats::ZERO; self.satdays_destroyed = Sats::ZERO; - self.satblocks_destroyed = Sats::ZERO; self.realized.reset_single_iteration_values(); } @@ -202,7 +199,6 @@ impl CohortState { ) { self.supply -= supply; self.sent += pre.sats; - self.satblocks_destroyed += pre.age.satblocks_destroyed(pre.sats); self.satdays_destroyed += pre.age.satdays_destroyed(pre.sats); self.realized @@ -246,7 +242,6 @@ impl CohortState { if supply.value > Sats::ZERO { self.sent += supply.value; - self.satblocks_destroyed += age.satblocks_destroyed(supply.value); self.satdays_destroyed += age.satdays_destroyed(supply.value); let sats = supply.value; diff --git a/crates/brk_computer/src/distribution/state/cohort/utxo.rs b/crates/brk_computer/src/distribution/state/cohort/utxo.rs index 52f8a2b39..6068159a6 100644 --- a/crates/brk_computer/src/distribution/state/cohort/utxo.rs +++ b/crates/brk_computer/src/distribution/state/cohort/utxo.rs @@ -23,7 +23,6 @@ impl UTXOCohortState { pub(crate) fn reset(&mut self) { self.0.supply = SupplyState::default(); self.0.sent = Sats::ZERO; - self.0.satblocks_destroyed = Sats::ZERO; self.0.satdays_destroyed = Sats::ZERO; self.0.realized = R::default(); } diff --git a/crates/brk_computer/src/distribution/vecs.rs b/crates/brk_computer/src/distribution/vecs.rs index 39009a71b..85fa5c573 100644 --- a/crates/brk_computer/src/distribution/vecs.rs +++ b/crates/brk_computer/src/distribution/vecs.rs @@ -5,7 +5,7 @@ use brk_indexer::Indexer; use brk_traversable::Traversable; use brk_types::{ Cents, EmptyAddressData, EmptyAddressIndex, FundedAddressData, FundedAddressIndex, Height, - Indexes, SupplyState, Timestamp, TxIndex, Version, + Indexes, StoredF64, SupplyState, Timestamp, TxIndex, Version, }; use tracing::{debug, info}; use vecdb::{ @@ -23,7 +23,7 @@ use crate::{ state::BlockState, }, indexes, inputs, - internal::{finalize_db, open_db}, + internal::{finalize_db, open_db, ComputedPerBlockCumulative}, outputs, prices, transactions, }; @@ -49,6 +49,8 @@ pub struct Vecs { pub utxo_cohorts: UTXOCohorts, pub address_cohorts: AddressCohorts, + pub coinblocks_destroyed: ComputedPerBlockCumulative, + pub addr_count: AddrCountsVecs, pub empty_addr_count: AddrCountsVecs, pub address_activity: AddressActivityVecs, @@ -159,6 +161,13 @@ impl Vecs { utxo_cohorts, address_cohorts, + coinblocks_destroyed: ComputedPerBlockCumulative::forced_import( + &db, + "coinblocks_destroyed", + version + Version::TWO, + indexes, + )?, + any_address_indexes: AnyAddressIndexesVecs::forced_import(&db, version)?, addresses_data: AddressesDataVecs { funded: fundedaddressindex_to_fundedaddressdata, @@ -390,6 +399,10 @@ impl Vecs { exit, )?; + // 5b. Compute coinblocks_destroyed cumulative from raw + self.coinblocks_destroyed + .compute_rest(starting_indexes.height, exit)?; + // 6. Compute rest part1 (day1 mappings) aggregates::compute_rest_part1( &mut self.utxo_cohorts, @@ -474,5 +487,6 @@ impl Vecs { .min(Height::from(self.addr_count.min_stateful_height())) .min(Height::from(self.empty_addr_count.min_stateful_height())) .min(Height::from(self.address_activity.min_stateful_height())) + .min(Height::from(self.coinblocks_destroyed.raw.height.len())) } } diff --git a/crates/brk_computer/src/indicators/compute.rs b/crates/brk_computer/src/indicators/compute.rs new file mode 100644 index 000000000..3106592f5 --- /dev/null +++ b/crates/brk_computer/src/indicators/compute.rs @@ -0,0 +1,78 @@ +use brk_error::Result; +use brk_types::{Dollars, Indexes}; +use vecdb::Exit; + +use super::{gini, Vecs}; +use crate::{distribution, internal::RatioDollarsBp32, mining, transactions}; + +impl Vecs { + pub(crate) fn compute( + &mut self, + mining: &mining::Vecs, + distribution: &distribution::Vecs, + transactions: &transactions::Vecs, + starting_indexes: &Indexes, + exit: &Exit, + ) -> Result<()> { + // Puell Multiple: daily_subsidy_usd / sma_365d_subsidy_usd + self.puell_multiple + .bps + .compute_binary::( + starting_indexes.height, + &mining.rewards.subsidy.base.usd.height, + &mining.rewards.subsidy_sma_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.sent_sum.rolling._24h.usd.height, + exit, + )?; + + let _lock = exit.lock(); + self.db.compact()?; + Ok(()) + } +} diff --git a/crates/brk_computer/src/market/indicators/gini.rs b/crates/brk_computer/src/indicators/gini.rs similarity index 100% rename from crates/brk_computer/src/market/indicators/gini.rs rename to crates/brk_computer/src/indicators/gini.rs diff --git a/crates/brk_computer/src/indicators/import.rs b/crates/brk_computer/src/indicators/import.rs new file mode 100644 index 000000000..9c22def80 --- /dev/null +++ b/crates/brk_computer/src/indicators/import.rs @@ -0,0 +1,38 @@ +use std::path::Path; + +use brk_error::Result; +use brk_types::Version; + +use super::Vecs; +use crate::{ + indexes, + internal::{finalize_db, open_db, PercentPerBlock, RatioPerBlock}, +}; + +const VERSION: Version = Version::new(1); + +impl Vecs { + pub(crate) fn forced_import( + parent_path: &Path, + parent_version: Version, + indexes: &indexes::Vecs, + ) -> Result { + let db = open_db(parent_path, super::DB_NAME, 100_000)?; + let v = parent_version + VERSION; + + let puell_multiple = RatioPerBlock::forced_import_raw(&db, "puell_multiple", v, indexes)?; + let nvt = RatioPerBlock::forced_import_raw(&db, "nvt", v, indexes)?; + let gini = PercentPerBlock::forced_import(&db, "gini", v, indexes)?; + let rhodl_ratio = RatioPerBlock::forced_import_raw(&db, "rhodl_ratio", v, indexes)?; + + let this = Self { + db, + puell_multiple, + nvt, + gini, + rhodl_ratio, + }; + finalize_db(&this.db, &this)?; + Ok(this) + } +} diff --git a/crates/brk_computer/src/indicators/mod.rs b/crates/brk_computer/src/indicators/mod.rs new file mode 100644 index 000000000..17adb2bbb --- /dev/null +++ b/crates/brk_computer/src/indicators/mod.rs @@ -0,0 +1,8 @@ +mod compute; +mod gini; +mod import; +mod vecs; + +pub use vecs::Vecs; + +pub const DB_NAME: &str = "indicators"; diff --git a/crates/brk_computer/src/indicators/vecs.rs b/crates/brk_computer/src/indicators/vecs.rs new file mode 100644 index 000000000..555fb4069 --- /dev/null +++ b/crates/brk_computer/src/indicators/vecs.rs @@ -0,0 +1,15 @@ +use brk_traversable::Traversable; +use brk_types::{BasisPoints16, BasisPoints32}; +use vecdb::{Database, Rw, StorageMode}; + +use crate::internal::{PercentPerBlock, RatioPerBlock}; + +#[derive(Traversable)] +pub struct Vecs { + #[traversable(skip)] + pub(crate) db: Database, + pub puell_multiple: RatioPerBlock, + pub nvt: RatioPerBlock, + pub gini: PercentPerBlock, + pub rhodl_ratio: RatioPerBlock, +} diff --git a/crates/brk_computer/src/internal/per_block/computed/cumulative.rs b/crates/brk_computer/src/internal/per_block/computed/cumulative.rs index 6d91232c7..7db01bf24 100644 --- a/crates/brk_computer/src/internal/per_block/computed/cumulative.rs +++ b/crates/brk_computer/src/internal/per_block/computed/cumulative.rs @@ -1,14 +1,13 @@ -//! ComputedPerBlockCumulative - stored height + LazyAggVec + cumulative (from height). +//! ComputedPerBlockCumulative - raw ComputedPerBlock + cumulative ComputedPerBlock. //! //! Like ComputedPerBlockCumulativeSum but without RollingWindows. //! Used for distribution metrics where rolling is optional per cohort. -//! Cumulative gets its own ComputedPerBlock so it has LazyAggVec index views. use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Height, Version}; use schemars::JsonSchema; -use vecdb::{Database, EagerVec, Exit, ImportableVec, PcoVec, Rw, StorageMode}; +use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode}; use crate::{ indexes, @@ -20,7 +19,7 @@ pub struct ComputedPerBlockCumulative where T: NumericValue + JsonSchema, { - pub height: M::Stored>>, + pub raw: ComputedPerBlock, pub cumulative: ComputedPerBlock, } @@ -34,35 +33,35 @@ where version: Version, indexes: &indexes::Vecs, ) -> Result { - let height: EagerVec> = EagerVec::forced_import(db, name, version)?; + let raw = ComputedPerBlock::forced_import(db, name, version, indexes)?; let cumulative = ComputedPerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?; - Ok(Self { height, cumulative }) + Ok(Self { raw, cumulative }) } - /// Compute height data via closure, then cumulative only (no rolling). + /// Compute raw data via closure, then cumulative only (no rolling). pub(crate) fn compute( &mut self, max_from: Height, exit: &Exit, - compute_height: impl FnOnce(&mut EagerVec>) -> Result<()>, + compute_raw: impl FnOnce(&mut EagerVec>) -> Result<()>, ) -> Result<()> where T: Default, { - compute_height(&mut self.height)?; + compute_raw(&mut self.raw.height)?; self.compute_rest(max_from, exit) } - /// Compute cumulative from already-filled height vec. + /// Compute cumulative from already-filled raw vec. pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> where T: Default, { self.cumulative .height - .compute_cumulative(max_from, &self.height, exit)?; + .compute_cumulative(max_from, &self.raw.height, exit)?; Ok(()) } } diff --git a/crates/brk_computer/src/internal/per_block/computed/cumulative_sum.rs b/crates/brk_computer/src/internal/per_block/computed/cumulative_sum.rs index c2fddd134..360ad9498 100644 --- a/crates/brk_computer/src/internal/per_block/computed/cumulative_sum.rs +++ b/crates/brk_computer/src/internal/per_block/computed/cumulative_sum.rs @@ -1,8 +1,7 @@ -//! ComputedPerBlockCumulativeSum - stored height + LazyAggVec + cumulative (from height) + RollingWindows (sum). +//! ComputedPerBlockCumulativeSum - raw ComputedPerBlock + cumulative ComputedPerBlock + RollingWindows (sum). //! //! Like ComputedPerBlockFull but with rolling sum only (no distribution). //! Used for count metrics where distribution stats aren't meaningful. -//! Cumulative gets its own ComputedPerBlock so it has LazyAggVec index views too. use std::ops::SubAssign; @@ -10,7 +9,7 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Height, Version}; use schemars::JsonSchema; -use vecdb::{Database, EagerVec, Exit, ImportableVec, PcoVec, Rw, StorageMode}; +use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode}; use crate::{ indexes, @@ -22,7 +21,7 @@ pub struct ComputedPerBlockCumulativeSum where T: NumericValue + JsonSchema, { - pub height: M::Stored>>, + pub raw: ComputedPerBlock, pub cumulative: ComputedPerBlock, pub sum: RollingWindows, } @@ -37,34 +36,34 @@ where version: Version, indexes: &indexes::Vecs, ) -> Result { - let height: EagerVec> = EagerVec::forced_import(db, name, version)?; + let raw = ComputedPerBlock::forced_import(db, name, version, indexes)?; let cumulative = ComputedPerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?; - let rolling = RollingWindows::forced_import(db, name, version, indexes)?; + let sum = RollingWindows::forced_import(db, name, version, indexes)?; Ok(Self { - height, + raw, cumulative, - sum: rolling, + sum, }) } - /// Compute height data via closure, then cumulative + rolling sum. + /// Compute raw data via closure, then cumulative + rolling sum. pub(crate) fn compute( &mut self, max_from: Height, windows: &WindowStarts<'_>, exit: &Exit, - compute_height: impl FnOnce(&mut EagerVec>) -> Result<()>, + compute_raw: impl FnOnce(&mut EagerVec>) -> Result<()>, ) -> Result<()> where T: Default + SubAssign, { - compute_height(&mut self.height)?; + compute_raw(&mut self.raw.height)?; self.compute_rest(max_from, windows, exit) } - /// Compute cumulative + rolling sum from already-populated height data. + /// Compute cumulative + rolling sum from already-populated raw data. pub(crate) fn compute_rest( &mut self, max_from: Height, @@ -76,9 +75,9 @@ where { self.cumulative .height - .compute_cumulative(max_from, &self.height, exit)?; + .compute_cumulative(max_from, &self.raw.height, exit)?; self.sum - .compute_rolling_sum(max_from, windows, &self.height, exit)?; + .compute_rolling_sum(max_from, windows, &self.raw.height, exit)?; Ok(()) } } diff --git a/crates/brk_computer/src/internal/per_block/computed/full.rs b/crates/brk_computer/src/internal/per_block/computed/full.rs index bef02487a..753b8c33d 100644 --- a/crates/brk_computer/src/internal/per_block/computed/full.rs +++ b/crates/brk_computer/src/internal/per_block/computed/full.rs @@ -1,7 +1,6 @@ -//! ComputedPerBlockFull - stored height + LazyAggVec + cumulative (from height) + RollingFull. +//! ComputedPerBlockFull - raw ComputedPerBlock + cumulative ComputedPerBlock + RollingFull. //! //! For metrics with stored per-block data, cumulative sums, and rolling windows. -//! Cumulative gets its own ComputedPerBlock so it has LazyAggVec index views too. use std::ops::SubAssign; @@ -9,7 +8,7 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Height, Version}; use schemars::JsonSchema; -use vecdb::{Database, EagerVec, Exit, ImportableVec, PcoVec, Rw, StorageMode}; +use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode}; use crate::{ indexes, @@ -21,7 +20,7 @@ pub struct ComputedPerBlockFull where T: NumericValue + JsonSchema, { - pub height: M::Stored>>, + pub raw: ComputedPerBlock, pub cumulative: ComputedPerBlock, #[traversable(flatten)] pub rolling: RollingFull, @@ -37,36 +36,36 @@ where version: Version, indexes: &indexes::Vecs, ) -> Result { - let height: EagerVec> = EagerVec::forced_import(db, name, version)?; + let raw = ComputedPerBlock::forced_import(db, name, version, indexes)?; let cumulative = ComputedPerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?; let rolling = RollingFull::forced_import(db, name, version, indexes)?; Ok(Self { - height, + raw, cumulative, rolling, }) } - /// Compute height data via closure, then cumulative + rolling. + /// Compute raw data via closure, then cumulative + rolling. pub(crate) fn compute( &mut self, max_from: Height, windows: &WindowStarts<'_>, exit: &Exit, - compute_height: impl FnOnce(&mut EagerVec>) -> Result<()>, + compute_raw: impl FnOnce(&mut EagerVec>) -> Result<()>, ) -> Result<()> where T: From + Default + SubAssign + Copy + Ord, f64: From, { - compute_height(&mut self.height)?; + compute_raw(&mut self.raw.height)?; self.cumulative .height - .compute_cumulative(max_from, &self.height, exit)?; + .compute_cumulative(max_from, &self.raw.height, exit)?; self.rolling - .compute(max_from, windows, &self.height, exit)?; + .compute(max_from, windows, &self.raw.height, exit)?; Ok(()) } } diff --git a/crates/brk_computer/src/internal/per_block/computed/sum.rs b/crates/brk_computer/src/internal/per_block/computed/sum.rs index 2c2920d51..cbad21aee 100644 --- a/crates/brk_computer/src/internal/per_block/computed/sum.rs +++ b/crates/brk_computer/src/internal/per_block/computed/sum.rs @@ -1,4 +1,4 @@ -//! ComputedPerBlockSum - stored height + RollingWindows (sum only). +//! ComputedPerBlockSum - raw ComputedPerBlock + RollingWindows (sum only). //! //! Like ComputedPerBlockCumulativeSum but without the cumulative vec. @@ -8,11 +8,11 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Height, Version}; use schemars::JsonSchema; -use vecdb::{Database, EagerVec, Exit, ImportableVec, PcoVec, Rw, StorageMode}; +use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode}; use crate::{ indexes, - internal::{NumericValue, RollingWindows, WindowStarts}, + internal::{ComputedPerBlock, NumericValue, RollingWindows, WindowStarts}, }; #[derive(Traversable)] @@ -20,7 +20,7 @@ pub struct ComputedPerBlockSum where T: NumericValue + JsonSchema, { - pub height: M::Stored>>, + pub raw: ComputedPerBlock, pub sum: RollingWindows, } @@ -34,26 +34,26 @@ where version: Version, indexes: &indexes::Vecs, ) -> Result { - let height: EagerVec> = EagerVec::forced_import(db, name, version)?; + let raw = ComputedPerBlock::forced_import(db, name, version, indexes)?; let sum = RollingWindows::forced_import(db, &format!("{name}_sum"), version, indexes)?; - Ok(Self { height, sum }) + Ok(Self { raw, sum }) } - /// Compute height data via closure, then rolling sum. + /// Compute raw data via closure, then rolling sum. pub(crate) fn compute( &mut self, max_from: Height, windows: &WindowStarts<'_>, exit: &Exit, - compute_height: impl FnOnce(&mut EagerVec>) -> Result<()>, + compute_raw: impl FnOnce(&mut EagerVec>) -> Result<()>, ) -> Result<()> where T: Default + SubAssign, { - compute_height(&mut self.height)?; + compute_raw(&mut self.raw.height)?; self.sum - .compute_rolling_sum(max_from, windows, &self.height, exit)?; + .compute_rolling_sum(max_from, windows, &self.raw.height, exit)?; Ok(()) } } diff --git a/crates/brk_computer/src/lib.rs b/crates/brk_computer/src/lib.rs index 38549e7bc..1f19626a4 100644 --- a/crates/brk_computer/src/lib.rs +++ b/crates/brk_computer/src/lib.rs @@ -14,6 +14,7 @@ mod blocks; mod cointime; mod constants; mod distribution; +mod indicators; pub mod indexes; mod inputs; mod internal; @@ -37,6 +38,7 @@ pub struct Computer { pub cointime: Box>, pub constants: Box, pub indexes: Box>, + pub indicators: Box>, pub market: Box>, pub pools: Box>, pub prices: Box>, @@ -174,28 +176,38 @@ impl Computer { }) })?; - // Market and distribution are independent; import in parallel. + // Market, indicators, and distribution are independent; import in parallel. // Supply depends on distribution so it runs after. - let (distribution, market) = timed("Imported distribution/market", || { - thread::scope(|s| -> Result<_> { - let market_handle = big_thread().spawn_scoped(s, || -> Result<_> { - Ok(Box::new(market::Vecs::forced_import( + let (distribution, market, indicators) = + timed("Imported distribution/market/indicators", || { + thread::scope(|s| -> Result<_> { + let market_handle = big_thread().spawn_scoped(s, || -> Result<_> { + Ok(Box::new(market::Vecs::forced_import( + &computed_path, + VERSION, + &indexes, + )?)) + })?; + + let indicators_handle = big_thread().spawn_scoped(s, || -> Result<_> { + Ok(Box::new(indicators::Vecs::forced_import( + &computed_path, + VERSION, + &indexes, + )?)) + })?; + + let distribution = Box::new(distribution::Vecs::forced_import( &computed_path, VERSION, &indexes, - )?)) - })?; + )?); - let distribution = Box::new(distribution::Vecs::forced_import( - &computed_path, - VERSION, - &indexes, - )?); - - let market = market_handle.join().unwrap()?; - Ok((distribution, market)) - }) - })?; + let market = market_handle.join().unwrap()?; + let indicators = indicators_handle.join().unwrap()?; + Ok((distribution, market, indicators)) + }) + })?; let supply = timed("Imported supply", || -> Result<_> { Ok(Box::new(supply::Vecs::forced_import( @@ -214,6 +226,7 @@ impl Computer { transactions, scripts, constants, + indicators, market, distribution, supply, @@ -240,6 +253,7 @@ impl Computer { scripts::DB_NAME, positions::DB_NAME, cointime::DB_NAME, + indicators::DB_NAME, indexes::DB_NAME, market::DB_NAME, pools::DB_NAME, @@ -408,6 +422,15 @@ impl Computer { &self.indexes, &self.prices, &self.blocks, + &starting_indexes, + exit, + ) + }) + }); + + let indicators = scope.spawn(|| { + timed("Computed indicators", || { + self.indicators.compute( &self.mining, &self.distribution, &self.transactions, @@ -431,6 +454,7 @@ impl Computer { })?; market.join().unwrap()?; + indicators.join().unwrap()?; Ok(()) })?; @@ -473,6 +497,7 @@ impl Computer { positions, cointime, constants, + indicators, indexes, market, pools, diff --git a/crates/brk_computer/src/market/compute.rs b/crates/brk_computer/src/market/compute.rs index 20fefd516..3e4258779 100644 --- a/crates/brk_computer/src/market/compute.rs +++ b/crates/brk_computer/src/market/compute.rs @@ -2,20 +2,16 @@ use brk_error::Result; use brk_types::Indexes; use vecdb::Exit; -use crate::{blocks, distribution, indexes, mining, prices, transactions}; +use crate::{blocks, indexes, prices}; use super::Vecs; impl Vecs { - #[allow(clippy::too_many_arguments)] pub(crate) fn compute( &mut self, indexes: &indexes::Vecs, prices: &prices::Vecs, blocks: &blocks::Vecs, - mining: &mining::Vecs, - distribution: &distribution::Vecs, - transactions: &transactions::Vecs, starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { @@ -63,14 +59,11 @@ impl Vecs { r4?; // Phase 3: Depends on returns, range, moving_average - self.indicators.compute( - &mining.rewards, + self.technical.compute( &self.returns, &self.range, prices, blocks, - distribution, - transactions, &self.moving_average, starting_indexes, exit, diff --git a/crates/brk_computer/src/market/import.rs b/crates/brk_computer/src/market/import.rs index f834a05ee..6e55ca779 100644 --- a/crates/brk_computer/src/market/import.rs +++ b/crates/brk_computer/src/market/import.rs @@ -9,7 +9,7 @@ use crate::{ }; use super::{ - AthVecs, DcaVecs, IndicatorsVecs, LookbackVecs, MovingAverageVecs, RangeVecs, ReturnsVecs, + AthVecs, DcaVecs, TechnicalVecs, LookbackVecs, MovingAverageVecs, RangeVecs, ReturnsVecs, Vecs, VolatilityVecs, }; @@ -29,7 +29,7 @@ impl Vecs { let range = RangeVecs::forced_import(&db, version, indexes)?; let moving_average = MovingAverageVecs::forced_import(&db, version, indexes)?; let dca = DcaVecs::forced_import(&db, version, indexes)?; - let indicators = IndicatorsVecs::forced_import(&db, version, indexes)?; + let technical = TechnicalVecs::forced_import(&db, version, indexes)?; let this = Self { db, @@ -40,7 +40,7 @@ impl Vecs { range, moving_average, dca, - indicators, + technical, }; finalize_db(&this.db, &this)?; Ok(this) diff --git a/crates/brk_computer/src/market/mod.rs b/crates/brk_computer/src/market/mod.rs index 23cf2c16c..ca0ae850e 100644 --- a/crates/brk_computer/src/market/mod.rs +++ b/crates/brk_computer/src/market/mod.rs @@ -2,7 +2,7 @@ pub mod ath; mod compute; pub mod dca; mod import; -pub mod indicators; +pub mod technical; pub mod lookback; pub mod moving_average; pub mod range; @@ -14,7 +14,7 @@ use vecdb::{Database, Rw, StorageMode}; pub use ath::Vecs as AthVecs; pub use dca::Vecs as DcaVecs; -pub use indicators::Vecs as IndicatorsVecs; +pub use technical::Vecs as TechnicalVecs; pub use lookback::Vecs as LookbackVecs; pub use moving_average::Vecs as MovingAverageVecs; pub use range::Vecs as RangeVecs; @@ -33,5 +33,5 @@ pub struct Vecs { pub range: RangeVecs, pub moving_average: MovingAverageVecs, pub dca: DcaVecs, - pub indicators: IndicatorsVecs, + pub technical: TechnicalVecs, } diff --git a/crates/brk_computer/src/market/indicators/compute.rs b/crates/brk_computer/src/market/technical/compute.rs similarity index 60% rename from crates/brk_computer/src/market/indicators/compute.rs rename to crates/brk_computer/src/market/technical/compute.rs index faa7c0b2a..493b2b5f5 100644 --- a/crates/brk_computer/src/market/indicators/compute.rs +++ b/crates/brk_computer/src/market/technical/compute.rs @@ -4,9 +4,9 @@ use vecdb::Exit; use super::{ super::{moving_average, range, returns}, - Vecs, gini, macd, rsi, + Vecs, macd, rsi, }; -use crate::{blocks, distribution, internal::RatioDollarsBp32, mining, prices, transactions}; +use crate::{blocks, internal::RatioDollarsBp32, prices}; const TF_MULTIPLIERS: [usize; 4] = [1, 7, 30, 365]; @@ -14,27 +14,15 @@ impl Vecs { #[allow(clippy::too_many_arguments)] pub(crate) fn compute( &mut self, - rewards: &mining::RewardsVecs, returns: &returns::Vecs, range: &range::Vecs, prices: &prices::Vecs, blocks: &blocks::Vecs, - distribution: &distribution::Vecs, - transactions: &transactions::Vecs, moving_average: &moving_average::Vecs, starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - self.puell_multiple - .bps - .compute_binary::( - starting_indexes.height, - &rewards.subsidy.base.usd.height, - &rewards.subsidy_sma_1y.usd.height, - exit, - )?; - - // Stochastic Oscillator: K = (close - low_2w) / (high_2w - low_2w), stored as ratio (0–1) + // Stochastic Oscillator: K = (close - low_2w) / (high_2w - low_2w), stored as ratio (0-1) { let price = &prices.price.usd.height; self.stoch_k.bps.height.compute_transform3( @@ -101,53 +89,6 @@ impl Vecs { )?; } - // Gini (per height) - 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.sent_sum.rolling._24h.usd.height, - exit, - )?; - // Pi Cycle: sma_111d / sma_350d_x2 self.pi_cycle .bps diff --git a/crates/brk_computer/src/market/indicators/import.rs b/crates/brk_computer/src/market/technical/import.rs similarity index 86% rename from crates/brk_computer/src/market/indicators/import.rs rename to crates/brk_computer/src/market/technical/import.rs index 0565943f6..51470e8d6 100644 --- a/crates/brk_computer/src/market/indicators/import.rs +++ b/crates/brk_computer/src/market/technical/import.rs @@ -5,7 +5,7 @@ use vecdb::Database; use super::{MacdChain, RsiChain, Vecs}; use crate::{ indexes, - internal::{ComputedPerBlock, RatioPerBlock, PercentPerBlock, Windows}, + internal::{ComputedPerBlock, PercentPerBlock, RatioPerBlock, Windows}, }; const VERSION: Version = Version::new(2); @@ -106,34 +106,20 @@ impl Vecs { ) -> Result { let v = version + VERSION; - let nvt = RatioPerBlock::forced_import_raw(db, "nvt", v, indexes)?; - let rsi = Windows::try_from_fn(|tf| RsiChain::forced_import(db, tf, v, indexes))?; let macd = Windows::try_from_fn(|tf| MacdChain::forced_import(db, tf, v, indexes))?; let stoch_k = PercentPerBlock::forced_import(db, "stoch_k", v, indexes)?; let stoch_d = PercentPerBlock::forced_import(db, "stoch_d", v, indexes)?; - let gini = PercentPerBlock::forced_import(db, "gini", v, indexes)?; let pi_cycle = RatioPerBlock::forced_import_raw(db, "pi_cycle", v, indexes)?; - let rhodl_ratio = RatioPerBlock::forced_import_raw(db, "rhodl_ratio", v, indexes)?; - Ok(Self { - puell_multiple: RatioPerBlock::forced_import_raw( - db, - "puell_multiple", - v, - indexes, - )?, - nvt, rsi, stoch_k, stoch_d, pi_cycle, macd, - gini, - rhodl_ratio, }) } } diff --git a/crates/brk_computer/src/market/indicators/macd.rs b/crates/brk_computer/src/market/technical/macd.rs similarity index 100% rename from crates/brk_computer/src/market/indicators/macd.rs rename to crates/brk_computer/src/market/technical/macd.rs diff --git a/crates/brk_computer/src/market/indicators/mod.rs b/crates/brk_computer/src/market/technical/mod.rs similarity index 90% rename from crates/brk_computer/src/market/indicators/mod.rs rename to crates/brk_computer/src/market/technical/mod.rs index 4b8b68f48..23f01b74d 100644 --- a/crates/brk_computer/src/market/indicators/mod.rs +++ b/crates/brk_computer/src/market/technical/mod.rs @@ -1,5 +1,4 @@ mod compute; -mod gini; mod import; mod macd; mod rsi; diff --git a/crates/brk_computer/src/market/indicators/rsi.rs b/crates/brk_computer/src/market/technical/rsi.rs similarity index 100% rename from crates/brk_computer/src/market/indicators/rsi.rs rename to crates/brk_computer/src/market/technical/rsi.rs diff --git a/crates/brk_computer/src/market/indicators/vecs.rs b/crates/brk_computer/src/market/technical/vecs.rs similarity index 83% rename from crates/brk_computer/src/market/indicators/vecs.rs rename to crates/brk_computer/src/market/technical/vecs.rs index 6bd40a884..3a0ec9516 100644 --- a/crates/brk_computer/src/market/indicators/vecs.rs +++ b/crates/brk_computer/src/market/technical/vecs.rs @@ -2,7 +2,7 @@ use brk_traversable::Traversable; use brk_types::{BasisPoints16, BasisPoints32, StoredF32}; use vecdb::{Rw, StorageMode}; -use crate::internal::{ComputedPerBlock, RatioPerBlock, PercentPerBlock, Windows}; +use crate::internal::{ComputedPerBlock, PercentPerBlock, RatioPerBlock, Windows}; #[derive(Traversable)] pub struct RsiChain { @@ -29,9 +29,6 @@ pub struct MacdChain { #[derive(Traversable)] pub struct Vecs { - pub puell_multiple: RatioPerBlock, - pub nvt: RatioPerBlock, - pub rsi: Windows>, pub stoch_k: PercentPerBlock, @@ -40,8 +37,4 @@ pub struct Vecs { pub pi_cycle: RatioPerBlock, pub macd: Windows>, - - pub gini: PercentPerBlock, - - pub rhodl_ratio: RatioPerBlock, } diff --git a/crates/brk_computer/src/pools/major.rs b/crates/brk_computer/src/pools/major.rs index b7c79d1d9..9a2c2802e 100644 --- a/crates/brk_computer/src/pools/major.rs +++ b/crates/brk_computer/src/pools/major.rs @@ -75,7 +75,7 @@ impl Vecs { self.blocks_mined_sum.compute_rolling_sum( starting_indexes.height, &window_starts, - &self.base.blocks_mined.height, + &self.base.blocks_mined.raw.height, exit, )?; @@ -101,7 +101,7 @@ impl Vecs { |vec| { Ok(vec.compute_transform2( starting_indexes.height, - &self.base.blocks_mined.height, + &self.base.blocks_mined.raw.height, &mining.rewards.coinbase.base.sats.height, |(h, mask, val, ..)| (h, MaskSats::apply(mask, val)), exit, diff --git a/crates/brk_computer/src/scripts/adoption.rs b/crates/brk_computer/src/scripts/adoption.rs index b4f966b36..5e3884b7f 100644 --- a/crates/brk_computer/src/scripts/adoption.rs +++ b/crates/brk_computer/src/scripts/adoption.rs @@ -38,14 +38,14 @@ impl Vecs { ) -> Result<()> { self.taproot.compute_binary::<_, _, RatioU64Bp16>( starting_indexes.height, - &count.p2tr.height, + &count.p2tr.raw.height, &outputs_count.total_count.full.sum, exit, )?; self.segwit.compute_binary::<_, _, RatioU64Bp16>( starting_indexes.height, - &count.segwit.height, + &count.segwit.raw.height, &outputs_count.total_count.full.sum, exit, )?; diff --git a/crates/brk_computer/src/scripts/count/compute.rs b/crates/brk_computer/src/scripts/count/compute.rs index 2dbe024b6..252c68a45 100644 --- a/crates/brk_computer/src/scripts/count/compute.rs +++ b/crates/brk_computer/src/scripts/count/compute.rs @@ -141,9 +141,9 @@ impl Vecs { .compute(starting_indexes.height, &window_starts, exit, |v| { Ok(v.compute_transform3( starting_indexes.height, - &self.p2wpkh.height, - &self.p2wsh.height, - &self.p2tr.height, + &self.p2wpkh.raw.height, + &self.p2wsh.raw.height, + &self.p2tr.raw.height, |(h, p2wpkh, p2wsh, p2tr, ..)| (h, StoredU64::from(*p2wpkh + *p2wsh + *p2tr)), exit, )?) diff --git a/crates/brk_computer/src/transactions/volume/compute.rs b/crates/brk_computer/src/transactions/volume/compute.rs index 9228210c3..9c6bec525 100644 --- a/crates/brk_computer/src/transactions/volume/compute.rs +++ b/crates/brk_computer/src/transactions/volume/compute.rs @@ -71,7 +71,7 @@ impl Vecs { .height .compute_binary::<_, Timestamp, PerSec>( starting_indexes.height, - &count_vecs.tx_count.height, + &count_vecs.tx_count.raw.height, &blocks.interval.height, exit, )?; diff --git a/crates/brk_types/src/age.rs b/crates/brk_types/src/age.rs index 2d9605783..f83045118 100644 --- a/crates/brk_types/src/age.rs +++ b/crates/brk_types/src/age.rs @@ -6,8 +6,6 @@ use crate::{Sats, Term, Timestamp}; pub struct Age { /// Age in hours (primary internal unit for cohort boundaries) hours: usize, - /// Age in blocks (for satblocks_destroyed calculation) - blocks: usize, /// Age in days as float (for satdays_destroyed - established terminology) days: f64, } @@ -15,10 +13,9 @@ pub struct Age { impl Age { /// Create from timestamps and block count #[inline] - pub fn new(current_timestamp: Timestamp, prev_timestamp: Timestamp, blocks: usize) -> Self { + pub fn new(current_timestamp: Timestamp, prev_timestamp: Timestamp) -> Self { Self { hours: current_timestamp.difference_in_hours_between(prev_timestamp), - blocks, days: current_timestamp.difference_in_days_between_float(prev_timestamp), } } @@ -29,12 +26,6 @@ impl Age { self.hours } - /// Blocks old (for satblocks_destroyed calculation) - #[inline] - pub fn blocks(&self) -> usize { - self.blocks - } - /// Days old as float (for satdays_destroyed - established terminology) #[inline] pub fn days(&self) -> f64 { @@ -51,21 +42,9 @@ impl Age { } } - /// Calculate satblocks destroyed for given supply - #[inline] - pub fn satblocks_destroyed(&self, supply: Sats) -> Sats { - if self.blocks == 0 { - return Sats::ZERO; - } - Sats::from(u64::from(supply) * self.blocks as u64) - } - /// Calculate satdays destroyed for given supply #[inline] pub fn satdays_destroyed(&self, supply: Sats) -> Sats { - if self.blocks == 0 { - return Sats::ZERO; - } Sats::from((u64::from(supply) as f64 * self.days).floor() as u64) } }