global: adding support for safe lengths

This commit is contained in:
nym21
2026-05-06 15:33:07 +02:00
parent da7671744f
commit 086bfd9938
177 changed files with 2445 additions and 2049 deletions
+16 -13
View File
@@ -1,5 +1,6 @@
use brk_error::Result;
use brk_types::{Bitcoin, Dollars, Indexes, StoredF32};
use brk_indexer::Indexer;
use brk_types::{Bitcoin, Dollars, StoredF32};
use vecdb::Exit;
use super::{Vecs, gini};
@@ -9,33 +10,35 @@ impl Vecs {
#[allow(clippy::too_many_arguments)]
pub(crate) fn compute(
&mut self,
indexer: &Indexer,
mining: &mining::Vecs,
distribution: &distribution::Vecs,
transactions: &transactions::Vecs,
market: &market::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.db.sync_bg_tasks()?;
let starting_lengths = indexer.safe_lengths();
// Puell Multiple: daily_subsidy_usd / sma_365d_subsidy_usd
self.puell_multiple
.bps
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height,
starting_lengths.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)?;
gini::compute(&mut self.gini, distribution, indexer, exit)?;
// RHODL Ratio: 1d-1w realized cap / 1y-2y realized cap
self.rhodl_ratio
.bps
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height,
starting_lengths.height,
&distribution
.utxo_cohorts
.age_range
@@ -69,7 +72,7 @@ impl Vecs {
self.nvt
.bps
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height,
starting_lengths.height,
market_cap,
&transactions.volume.transfer_volume.sum._24h.usd.height,
exit,
@@ -79,7 +82,7 @@ impl Vecs {
self.thermo_cap_multiple
.bps
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height,
starting_lengths.height,
market_cap,
&mining.rewards.subsidy.cumulative.usd.height,
exit,
@@ -93,7 +96,7 @@ impl Vecs {
self.coindays_destroyed_supply_adj
.height
.compute_transform2(
starting_indexes.height,
starting_lengths.height,
&all_activity.coindays_destroyed.sum._24h.height,
supply_total_sats,
|(i, cdd_24h, supply_sats, ..)| {
@@ -111,7 +114,7 @@ impl Vecs {
self.coinyears_destroyed_supply_adj
.height
.compute_transform2(
starting_indexes.height,
starting_lengths.height,
&all_activity.coinyears_destroyed.height,
supply_total_sats,
|(i, cyd, supply_sats, ..)| {
@@ -127,7 +130,7 @@ impl Vecs {
// Supply-Adjusted Dormancy = dormancy / circulating_supply_btc
self.dormancy.supply_adj.height.compute_transform2(
starting_indexes.height,
starting_lengths.height,
&all_activity.dormancy._24h.height,
supply_total_sats,
|(i, dormancy, supply_sats, ..)| {
@@ -144,7 +147,7 @@ impl Vecs {
// Stock-to-Flow: supply / annual_issuance
// annual_issuance ≈ subsidy_per_block × 52560 (blocks/year)
self.stock_to_flow.height.compute_transform2(
starting_indexes.height,
starting_lengths.height,
supply_total_sats,
&mining.rewards.subsidy.block.sats,
|(i, supply_sats, subsidy_sats, ..)| {
@@ -163,7 +166,7 @@ impl Vecs {
// Dormancy Flow: supply_btc / dormancy
self.dormancy.flow.height.compute_transform2(
starting_indexes.height,
starting_lengths.height,
supply_total_sats,
&all_activity.dormancy._24h.height,
|(i, supply_sats, dormancy, ..)| {
@@ -180,7 +183,7 @@ impl Vecs {
// Seller Exhaustion Constant: % supply_in_profit × 30d_volatility
self.seller_exhaustion.height.compute_transform3(
starting_indexes.height,
starting_lengths.height,
&all_metrics.supply.in_profit.sats.height,
&market.volatility._1m.height,
supply_total_sats,
+5 -7
View File
@@ -1,5 +1,6 @@
use brk_error::Result;
use brk_types::{BasisPoints16, Indexes, Sats, StoredU64, Version};
use brk_indexer::Indexer;
use brk_types::{BasisPoints16, Sats, StoredU64, Version};
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, VecIndex, WritableVec};
use crate::{distribution, internal::PercentPerBlock};
@@ -7,9 +8,10 @@ use crate::{distribution, internal::PercentPerBlock};
pub(super) fn compute(
gini: &mut PercentPerBlock<BasisPoints16>,
distribution: &distribution::Vecs,
starting_indexes: &Indexes,
indexer: &Indexer,
exit: &Exit,
) -> Result<()> {
let starting_height = indexer.safe_lengths().height;
let amount_range = &distribution.utxo_cohorts.amount_range;
let supply_vecs: Vec<&_> = amount_range
@@ -36,11 +38,7 @@ pub(super) fn compute(
.height
.validate_computed_version_or_reset(source_version)?;
let min_len = gini
.bps
.height
.len()
.min(starting_indexes.height.to_usize());
let min_len = gini.bps.height.len().min(starting_height.to_usize());
gini.bps.height.truncate_if_needed_at(min_len)?;
@@ -1,6 +1,7 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{Cents, Height, Indexes, StoredI8, Version};
use brk_types::{Cents, Height, StoredI8, Version};
use vecdb::{AnyVec, Database, Exit, ReadableVec, Rw, StorageMode, WritableVec};
use crate::{
@@ -47,60 +48,61 @@ impl RarityMeterInner {
&mut self,
models: &[&RatioPerBlockPercentiles],
spot: &impl ReadableVec<Height, Cents>,
starting_indexes: &Indexes,
indexer: &Indexer,
exit: &Exit,
) -> Result<()> {
let starting_height = indexer.safe_lengths().height;
let gather = |f: fn(&RatioPerBlockPercentiles) -> &_| -> Vec<_> {
models.iter().map(|m| f(m)).collect()
};
// Lower percentiles: max across all models (tightest lower bound)
self.pct0_5.cents.height.compute_max_of_others(
starting_indexes.height,
starting_height,
&gather(|m| &m.pct0_5.price.cents.height),
exit,
)?;
self.pct1.cents.height.compute_max_of_others(
starting_indexes.height,
starting_height,
&gather(|m| &m.pct1.price.cents.height),
exit,
)?;
self.pct2.cents.height.compute_max_of_others(
starting_indexes.height,
starting_height,
&gather(|m| &m.pct2.price.cents.height),
exit,
)?;
self.pct5.cents.height.compute_max_of_others(
starting_indexes.height,
starting_height,
&gather(|m| &m.pct5.price.cents.height),
exit,
)?;
// Upper percentiles: min across all models (tightest upper bound)
self.pct95.cents.height.compute_min_of_others(
starting_indexes.height,
starting_height,
&gather(|m| &m.pct95.price.cents.height),
exit,
)?;
self.pct98.cents.height.compute_min_of_others(
starting_indexes.height,
starting_height,
&gather(|m| &m.pct98.price.cents.height),
exit,
)?;
self.pct99.cents.height.compute_min_of_others(
starting_indexes.height,
starting_height,
&gather(|m| &m.pct99.price.cents.height),
exit,
)?;
self.pct99_5.cents.height.compute_min_of_others(
starting_indexes.height,
starting_height,
&gather(|m| &m.pct99_5.price.cents.height),
exit,
)?;
self.compute_index(spot, starting_indexes, exit)?;
self.compute_index(spot, indexer, exit)?;
self.compute_score(models, spot, starting_indexes, exit)?;
self.compute_score(models, spot, indexer, exit)?;
Ok(())
}
@@ -108,9 +110,10 @@ impl RarityMeterInner {
fn compute_index(
&mut self,
spot: &impl ReadableVec<Height, Cents>,
starting_indexes: &Indexes,
indexer: &Indexer,
exit: &Exit,
) -> Result<()> {
let starting_height = indexer.safe_lengths().height;
let bands = [
&self.pct0_5.cents.height,
&self.pct1.cents.height,
@@ -128,9 +131,7 @@ impl RarityMeterInner {
self.index
.height
.validate_computed_version_or_reset(dep_version)?;
self.index
.height
.truncate_if_needed(starting_indexes.height)?;
self.index.height.truncate_if_needed(starting_height)?;
self.index.height.repeat_until_complete(exit, |vec| {
let skip = vec.len();
@@ -186,9 +187,10 @@ impl RarityMeterInner {
&mut self,
models: &[&RatioPerBlockPercentiles],
spot: &impl ReadableVec<Height, Cents>,
starting_indexes: &Indexes,
indexer: &Indexer,
exit: &Exit,
) -> Result<()> {
let starting_height = indexer.safe_lengths().height;
let dep_version: Version = models
.iter()
.map(|p| {
@@ -207,9 +209,7 @@ impl RarityMeterInner {
self.score
.height
.validate_computed_version_or_reset(dep_version)?;
self.score
.height
.truncate_if_needed(starting_indexes.height)?;
self.score.height.truncate_if_needed(starting_height)?;
self.score.height.repeat_until_complete(exit, |vec| {
let skip = vec.len();
@@ -1,8 +1,9 @@
mod inner;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{Indexes, Version};
use brk_types::Version;
use vecdb::{Database, Exit, Rw, StorageMode};
use crate::{distribution, indexes, prices};
@@ -34,9 +35,9 @@ impl RarityMeter {
pub(crate) fn compute(
&mut self,
indexer: &Indexer,
distribution: &distribution::Vecs,
prices: &prices::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let realized = &distribution.utxo_cohorts.all.metrics.realized;
@@ -55,7 +56,7 @@ impl RarityMeter {
&lth_realized.capitalized.price.percentiles,
],
spot,
starting_indexes,
indexer,
exit,
)?;
@@ -66,7 +67,7 @@ impl RarityMeter {
&sth_realized.capitalized.price.percentiles,
],
spot,
starting_indexes,
indexer,
exit,
)?;
@@ -79,7 +80,7 @@ impl RarityMeter {
&lth_realized.capitalized.price.percentiles,
],
spot,
starting_indexes,
indexer,
exit,
)?;