global: snapshot part 6

This commit is contained in:
nym21
2026-03-20 17:02:32 +01:00
parent 17106f887a
commit f683adba13
34 changed files with 197 additions and 204 deletions

View File

@@ -13,7 +13,7 @@ impl Vecs {
exit: &Exit, exit: &Exit,
) -> Result<()> { ) -> Result<()> {
// Block count raw + cumulative // Block count raw + cumulative
self.total.base.height.compute_range( self.total.block.height.compute_range(
starting_indexes.height, starting_indexes.height,
&indexer.vecs.blocks.weight, &indexer.vecs.blocks.weight,
|h| (h, StoredU32::from(1_u32)), |h| (h, StoredU32::from(1_u32)),

View File

@@ -30,8 +30,8 @@ impl Vecs {
.compute(starting_indexes.height, exit, |vec| { .compute(starting_indexes.height, exit, |vec| {
vec.compute_subtract( vec.compute_subtract(
starting_indexes.height, starting_indexes.height,
&self.coinblocks_created.base.height, &self.coinblocks_created.block.height,
&distribution.coinblocks_destroyed.base.height, &distribution.coinblocks_destroyed.block.height,
exit, exit,
)?; )?;
Ok(()) Ok(())

View File

@@ -17,7 +17,7 @@ impl Vecs {
self.vocdd_median_1y.compute_rolling_median_from_starts( self.vocdd_median_1y.compute_rolling_median_from_starts(
starting_indexes.height, starting_indexes.height,
&blocks.lookback._1y, &blocks.lookback._1y,
&value.vocdd.base.height, &value.vocdd.block.height,
exit, exit,
)?; )?;

View File

@@ -25,7 +25,7 @@ impl Vecs {
vec.compute_multiply( vec.compute_multiply(
starting_indexes.height, starting_indexes.height,
&prices.spot.usd.height, &prices.spot.usd.height,
&coinblocks_destroyed.base.height, &coinblocks_destroyed.block.height,
exit, exit,
)?; )?;
Ok(()) Ok(())
@@ -36,7 +36,7 @@ impl Vecs {
vec.compute_multiply( vec.compute_multiply(
starting_indexes.height, starting_indexes.height,
&prices.spot.usd.height, &prices.spot.usd.height,
&activity.coinblocks_created.base.height, &activity.coinblocks_created.block.height,
exit, exit,
)?; )?;
Ok(()) Ok(())
@@ -47,7 +47,7 @@ impl Vecs {
vec.compute_multiply( vec.compute_multiply(
starting_indexes.height, starting_indexes.height,
&prices.spot.usd.height, &prices.spot.usd.height,
&activity.coinblocks_stored.base.height, &activity.coinblocks_stored.block.height,
exit, exit,
)?; )?;
Ok(()) Ok(())
@@ -61,7 +61,7 @@ impl Vecs {
vec.compute_transform3( vec.compute_transform3(
starting_indexes.height, starting_indexes.height,
&prices.spot.usd.height, &prices.spot.usd.height,
&coindays_destroyed.base.height, &coindays_destroyed.block.height,
circulating_supply, circulating_supply,
|(i, price, cdd, supply, _): (_, Dollars, StoredF64, Bitcoin, _)| { |(i, price, cdd, supply, _): (_, Dollars, StoredF64, Bitcoin, _)| {
let supply_f64 = f64::from(supply); let supply_f64 = f64::from(supply);

View File

@@ -113,39 +113,39 @@ impl ActivityCountVecs {
pub(crate) fn min_stateful_len(&self) -> usize { pub(crate) fn min_stateful_len(&self) -> usize {
self.reactivated self.reactivated
.base .block
.len() .len()
.min(self.sending.base.len()) .min(self.sending.block.len())
.min(self.receiving.base.len()) .min(self.receiving.block.len())
.min(self.both.base.len()) .min(self.both.block.len())
} }
pub(crate) fn par_iter_height_mut( pub(crate) fn par_iter_height_mut(
&mut self, &mut self,
) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> { ) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
[ [
&mut self.reactivated.base as &mut dyn AnyStoredVec, &mut self.reactivated.block as &mut dyn AnyStoredVec,
&mut self.sending.base as &mut dyn AnyStoredVec, &mut self.sending.block as &mut dyn AnyStoredVec,
&mut self.receiving.base as &mut dyn AnyStoredVec, &mut self.receiving.block as &mut dyn AnyStoredVec,
&mut self.both.base as &mut dyn AnyStoredVec, &mut self.both.block as &mut dyn AnyStoredVec,
] ]
.into_par_iter() .into_par_iter()
} }
pub(crate) fn reset_height(&mut self) -> Result<()> { pub(crate) fn reset_height(&mut self) -> Result<()> {
self.reactivated.base.reset()?; self.reactivated.block.reset()?;
self.sending.base.reset()?; self.sending.block.reset()?;
self.receiving.base.reset()?; self.receiving.block.reset()?;
self.both.base.reset()?; self.both.block.reset()?;
Ok(()) Ok(())
} }
#[inline(always)] #[inline(always)]
pub(crate) fn push_height(&mut self, counts: &BlockActivityCounts) { pub(crate) fn push_height(&mut self, counts: &BlockActivityCounts) {
self.reactivated.base.push(counts.reactivated.into()); self.reactivated.block.push(counts.reactivated.into());
self.sending.base.push(counts.sending.into()); self.sending.block.push(counts.sending.into());
self.receiving.base.push(counts.receiving.into()); self.receiving.block.push(counts.receiving.into());
self.both.base.push(counts.both.into()); self.both.block.push(counts.both.into());
} }
pub(crate) fn compute_rest( pub(crate) fn compute_rest(
@@ -206,10 +206,10 @@ impl AddrTypeToActivityCountVecs {
) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> { ) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
let mut vecs: Vec<&mut dyn AnyStoredVec> = Vec::new(); let mut vecs: Vec<&mut dyn AnyStoredVec> = Vec::new();
for type_vecs in self.0.values_mut() { for type_vecs in self.0.values_mut() {
vecs.push(&mut type_vecs.reactivated.base); vecs.push(&mut type_vecs.reactivated.block);
vecs.push(&mut type_vecs.sending.base); vecs.push(&mut type_vecs.sending.block);
vecs.push(&mut type_vecs.receiving.base); vecs.push(&mut type_vecs.receiving.block);
vecs.push(&mut type_vecs.both.base); vecs.push(&mut type_vecs.both.block);
} }
vecs.into_par_iter() vecs.into_par_iter()
} }

View File

@@ -342,7 +342,7 @@ impl UTXOCohorts<Rw> {
#[inline(always)] #[inline(always)]
pub(crate) fn push_maturation(&mut self, matured: &AgeRange<Sats>) { pub(crate) fn push_maturation(&mut self, matured: &AgeRange<Sats>) {
for (v, &sats) in self.matured.iter_mut().zip(matured.iter()) { for (v, &sats) in self.matured.iter_mut().zip(matured.iter()) {
v.base.sats.height.push(sats); v.block.sats.height.push(sats);
} }
} }
@@ -542,7 +542,7 @@ impl UTXOCohorts<Rw> {
.metrics .metrics
.activity .activity
.transfer_volume .transfer_volume
.base .block
.cents .cents
.height .height
.read_only_clone(); .read_only_clone();
@@ -553,7 +553,7 @@ impl UTXOCohorts<Rw> {
.realized .realized
.sopr .sopr
.value_destroyed .value_destroyed
.base .block
.height .height
.read_only_clone(); .read_only_clone();
@@ -714,8 +714,8 @@ impl UTXOCohorts<Rw> {
vecs.extend(self.profitability.collect_all_vecs_mut()); vecs.extend(self.profitability.collect_all_vecs_mut());
for v in self.matured.iter_mut() { for v in self.matured.iter_mut() {
let inner = &mut v.inner; let inner = &mut v.inner;
vecs.push(&mut inner.base.sats.height); vecs.push(&mut inner.block.sats.height);
vecs.push(&mut inner.base.cents.height); vecs.push(&mut inner.block.cents.height);
vecs.push(&mut inner.cumulative.sats.height); vecs.push(&mut inner.cumulative.sats.height);
vecs.push(&mut inner.cumulative.cents.height); vecs.push(&mut inner.cumulative.cents.height);
} }
@@ -734,7 +734,7 @@ impl UTXOCohorts<Rw> {
.chain( .chain(
self.matured self.matured
.iter() .iter()
.map(|v| Height::from(v.base.min_stateful_len())), .map(|v| Height::from(v.block.min_stateful_len())),
) )
.min() .min()
.unwrap_or_default() .unwrap_or_default()

View File

@@ -66,7 +66,7 @@ pub(crate) fn process_blocks(
let height_to_first_tx_index = &indexer.vecs.transactions.first_tx_index; let height_to_first_tx_index = &indexer.vecs.transactions.first_tx_index;
let height_to_first_txout_index = &indexer.vecs.outputs.first_txout_index; let height_to_first_txout_index = &indexer.vecs.outputs.first_txout_index;
let height_to_first_txin_index = &indexer.vecs.inputs.first_txin_index; let height_to_first_txin_index = &indexer.vecs.inputs.first_txin_index;
let height_to_tx_count = &transactions.count.total.base.height; let height_to_tx_count = &transactions.count.total.block.height;
let height_to_output_count = &outputs.count.total.sum.height; let height_to_output_count = &outputs.count.total.sum.height;
let height_to_input_count = &inputs.count.sum.height; let height_to_input_count = &inputs.count.sum.height;
let tx_index_to_output_count = &indexes.tx_index.output_count; let tx_index_to_output_count = &indexes.tx_index.output_count;
@@ -221,7 +221,7 @@ pub(crate) fn process_blocks(
.chain(vecs.addrs.empty.par_iter_height_mut()) .chain(vecs.addrs.empty.par_iter_height_mut())
.chain(vecs.addrs.activity.par_iter_height_mut()) .chain(vecs.addrs.activity.par_iter_height_mut())
.chain(rayon::iter::once( .chain(rayon::iter::once(
&mut vecs.coinblocks_destroyed.base.height as &mut dyn AnyStoredVec, &mut vecs.coinblocks_destroyed.block.height as &mut dyn AnyStoredVec,
)) ))
.try_for_each(|v| v.any_truncate_if_needed_at(start))?; .try_for_each(|v| v.any_truncate_if_needed_at(start))?;
} }
@@ -380,7 +380,7 @@ pub(crate) fn process_blocks(
blocks_old as u128 * u64::from(sent.spendable_supply.value) as u128 blocks_old as u128 * u64::from(sent.spendable_supply.value) as u128
}) })
.sum(); .sum();
vecs.coinblocks_destroyed.base.height.push( vecs.coinblocks_destroyed.block.height.push(
StoredF64::from(total_satblocks as f64 / Sats::ONE_BTC_U128 as f64), StoredF64::from(total_satblocks as f64 / Sats::ONE_BTC_U128 as f64),
); );
} }

View File

@@ -82,7 +82,7 @@ pub(crate) fn write(
.chain( .chain(
[ [
&mut vecs.supply_state as &mut dyn AnyStoredVec, &mut vecs.supply_state as &mut dyn AnyStoredVec,
&mut vecs.coinblocks_destroyed.base.height, &mut vecs.coinblocks_destroyed.block.height,
] ]
.into_par_iter(), .into_par_iter(),
) )

View File

@@ -40,9 +40,9 @@ impl ActivityCore {
pub(crate) fn min_len(&self) -> usize { pub(crate) fn min_len(&self) -> usize {
self.minimal self.minimal
.min_len() .min_len()
.min(self.coindays_destroyed.base.height.len()) .min(self.coindays_destroyed.block.height.len())
.min(self.transfer_volume_in_profit.base.sats.height.len()) .min(self.transfer_volume_in_profit.block.sats.height.len())
.min(self.transfer_volume_in_loss.base.sats.height.len()) .min(self.transfer_volume_in_loss.block.sats.height.len())
} }
#[inline(always)] #[inline(always)]
@@ -51,16 +51,16 @@ impl ActivityCore {
state: &CohortState<impl RealizedOps, impl CostBasisOps>, state: &CohortState<impl RealizedOps, impl CostBasisOps>,
) { ) {
self.minimal.push_state(state); self.minimal.push_state(state);
self.coindays_destroyed.base.height.push( self.coindays_destroyed.block.height.push(
StoredF64::from(Bitcoin::from(state.satdays_destroyed)), StoredF64::from(Bitcoin::from(state.satdays_destroyed)),
); );
self.transfer_volume_in_profit self.transfer_volume_in_profit
.base .block
.sats .sats
.height .height
.push(state.realized.sent_in_profit()); .push(state.realized.sent_in_profit());
self.transfer_volume_in_loss self.transfer_volume_in_loss
.base .block
.sats .sats
.height .height
.push(state.realized.sent_in_loss()); .push(state.realized.sent_in_loss());
@@ -68,11 +68,11 @@ impl ActivityCore {
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
let mut vecs = self.minimal.collect_vecs_mut(); let mut vecs = self.minimal.collect_vecs_mut();
vecs.push(&mut self.coindays_destroyed.base.height); vecs.push(&mut self.coindays_destroyed.block.height);
vecs.push(&mut self.transfer_volume_in_profit.inner.base.sats.height); vecs.push(&mut self.transfer_volume_in_profit.inner.block.sats.height);
vecs.push(&mut self.transfer_volume_in_profit.inner.base.cents.height); vecs.push(&mut self.transfer_volume_in_profit.inner.block.cents.height);
vecs.push(&mut self.transfer_volume_in_loss.inner.base.sats.height); vecs.push(&mut self.transfer_volume_in_loss.inner.block.sats.height);
vecs.push(&mut self.transfer_volume_in_loss.inner.base.cents.height); vecs.push(&mut self.transfer_volume_in_loss.inner.block.cents.height);
vecs vecs
} }
@@ -90,9 +90,9 @@ impl ActivityCore {
self.minimal self.minimal
.compute_from_stateful(starting_indexes, &minimal_refs, exit)?; .compute_from_stateful(starting_indexes, &minimal_refs, exit)?;
sum_others!(self, starting_indexes, others, exit; coindays_destroyed.base.height); sum_others!(self, starting_indexes, others, exit; coindays_destroyed.block.height);
sum_others!(self, starting_indexes, others, exit; transfer_volume_in_profit.base.sats.height); sum_others!(self, starting_indexes, others, exit; transfer_volume_in_profit.block.sats.height);
sum_others!(self, starting_indexes, others, exit; transfer_volume_in_loss.base.sats.height); sum_others!(self, starting_indexes, others, exit; transfer_volume_in_loss.block.sats.height);
Ok(()) Ok(())
} }

View File

@@ -24,7 +24,7 @@ impl ActivityMinimal {
pub(crate) fn min_len(&self) -> usize { pub(crate) fn min_len(&self) -> usize {
self.transfer_volume self.transfer_volume
.base .block
.sats .sats
.height .height
.len() .len()
@@ -35,14 +35,14 @@ impl ActivityMinimal {
&mut self, &mut self,
state: &CohortState<impl RealizedOps, impl CostBasisOps>, state: &CohortState<impl RealizedOps, impl CostBasisOps>,
) { ) {
self.transfer_volume.base.sats.height.push(state.sent); self.transfer_volume.block.sats.height.push(state.sent);
} }
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
let inner = &mut self.transfer_volume.inner; let inner = &mut self.transfer_volume.inner;
vec![ vec![
&mut inner.base.sats.height as &mut dyn AnyStoredVec, &mut inner.block.sats.height as &mut dyn AnyStoredVec,
&mut inner.base.cents.height, &mut inner.block.cents.height,
] ]
} }
@@ -52,11 +52,11 @@ impl ActivityMinimal {
others: &[&Self], others: &[&Self],
exit: &Exit, exit: &Exit,
) -> Result<()> { ) -> Result<()> {
self.transfer_volume.base.sats.height.compute_sum_of_others( self.transfer_volume.block.sats.height.compute_sum_of_others(
starting_indexes.height, starting_indexes.height,
&others &others
.iter() .iter()
.map(|v| &v.transfer_volume.base.sats.height) .map(|v| &v.transfer_volume.block.sats.height)
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
exit, exit,
)?; )?;

View File

@@ -128,8 +128,8 @@ impl AllCohortMetrics {
self.asopr.compute_rest_part2( self.asopr.compute_rest_part2(
starting_indexes, starting_indexes,
&self.activity.transfer_volume.base.cents.height, &self.activity.transfer_volume.block.cents.height,
&self.realized.core.sopr.value_destroyed.base.height, &self.realized.core.sopr.value_destroyed.block.height,
under_1h_value_created, under_1h_value_created,
under_1h_value_destroyed, under_1h_value_destroyed,
exit, exit,

View File

@@ -80,8 +80,8 @@ impl ExtendedAdjustedCohortMetrics {
self.asopr.compute_rest_part2( self.asopr.compute_rest_part2(
starting_indexes, starting_indexes,
&self.inner.activity.transfer_volume.base.cents.height, &self.inner.activity.transfer_volume.block.cents.height,
&self.inner.realized.core.sopr.value_destroyed.base.height, &self.inner.realized.core.sopr.value_destroyed.block.height,
under_1h_value_created, under_1h_value_created,
under_1h_value_destroyed, under_1h_value_destroyed,
exit, exit,

View File

@@ -34,13 +34,13 @@ impl AdjustedSopr {
under_1h_value_destroyed: &impl ReadableVec<Height, Cents>, under_1h_value_destroyed: &impl ReadableVec<Height, Cents>,
exit: &Exit, exit: &Exit,
) -> Result<()> { ) -> Result<()> {
self.transfer_volume.base.height.compute_subtract( self.transfer_volume.block.height.compute_subtract(
starting_indexes.height, starting_indexes.height,
base_transfer_volume, base_transfer_volume,
under_1h_transfer_volume, under_1h_transfer_volume,
exit, exit,
)?; )?;
self.value_destroyed.base.height.compute_subtract( self.value_destroyed.block.height.compute_subtract(
starting_indexes.height, starting_indexes.height,
base_value_destroyed, base_value_destroyed,
under_1h_value_destroyed, under_1h_value_destroyed,

View File

@@ -54,7 +54,7 @@ impl RealizedCore {
let neg_loss_base = LazyPerBlock::from_height_source::<NegCentsUnsignedToDollars>( let neg_loss_base = LazyPerBlock::from_height_source::<NegCentsUnsignedToDollars>(
&cfg.name("neg_realized_loss"), &cfg.name("neg_realized_loss"),
cfg.version + Version::ONE, cfg.version + Version::ONE,
minimal.loss.base.cents.height.read_only_boxed_clone(), minimal.loss.block.cents.height.read_only_boxed_clone(),
cfg.indexes, cfg.indexes,
); );
@@ -107,12 +107,12 @@ impl RealizedCore {
#[inline(always)] #[inline(always)]
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) { pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
self.minimal.push_state(state); self.minimal.push_state(state);
self.sopr.value_destroyed.base.height.push(state.realized.value_destroyed()); self.sopr.value_destroyed.block.height.push(state.realized.value_destroyed());
} }
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
let mut vecs = self.minimal.collect_vecs_mut(); let mut vecs = self.minimal.collect_vecs_mut();
vecs.push(&mut self.sopr.value_destroyed.base.height); vecs.push(&mut self.sopr.value_destroyed.block.height);
vecs vecs
} }
@@ -126,7 +126,7 @@ impl RealizedCore {
self.minimal self.minimal
.compute_from_stateful(starting_indexes, &minimal_refs, exit)?; .compute_from_stateful(starting_indexes, &minimal_refs, exit)?;
sum_others!(self, starting_indexes, others, exit; sopr.value_destroyed.base.height); sum_others!(self, starting_indexes, others, exit; sopr.value_destroyed.block.height);
Ok(()) Ok(())
} }
@@ -142,10 +142,10 @@ impl RealizedCore {
.value_destroyed .value_destroyed
.compute_rest(starting_indexes.height, exit)?; .compute_rest(starting_indexes.height, exit)?;
self.net_pnl.base.cents.height.compute_transform2( self.net_pnl.block.cents.height.compute_transform2(
starting_indexes.height, starting_indexes.height,
&self.minimal.profit.base.cents.height, &self.minimal.profit.block.cents.height,
&self.minimal.loss.base.cents.height, &self.minimal.loss.block.cents.height,
|(i, profit, loss, ..)| { |(i, profit, loss, ..)| {
( (
i, i,

View File

@@ -183,7 +183,7 @@ impl RealizedFull {
.len() .len()
.min(self.cap_raw.len()) .min(self.cap_raw.len())
.min(self.investor.cap_raw.len()) .min(self.investor.cap_raw.len())
.min(self.peak_regret.value.base.cents.height.len()) .min(self.peak_regret.value.block.cents.height.len())
} }
#[inline(always)] #[inline(always)]
@@ -203,7 +203,7 @@ impl RealizedFull {
.push(state.realized.investor_cap_raw()); .push(state.realized.investor_cap_raw());
self.peak_regret self.peak_regret
.value .value
.base .block
.cents .cents
.height .height
.push(state.realized.peak_regret()); .push(state.realized.peak_regret());
@@ -214,7 +214,7 @@ impl RealizedFull {
vecs.push(&mut self.investor.price.cents.height); vecs.push(&mut self.investor.price.cents.height);
vecs.push(&mut self.cap_raw as &mut dyn AnyStoredVec); 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.investor.cap_raw as &mut dyn AnyStoredVec);
vecs.push(&mut self.peak_regret.value.base.cents.height); vecs.push(&mut self.peak_regret.value.block.cents.height);
vecs vecs
} }
@@ -247,7 +247,7 @@ impl RealizedFull {
self.peak_regret self.peak_regret
.value .value
.base .block
.cents .cents
.height .height
.push(accum.peak_regret()); .push(accum.peak_regret());
@@ -307,7 +307,7 @@ impl RealizedFull {
.to_rcap .to_rcap
.compute_binary::<Cents, Cents, RatioCentsBp32>( .compute_binary::<Cents, Cents, RatioCentsBp32>(
starting_indexes.height, starting_indexes.height,
&self.core.minimal.profit.base.cents.height, &self.core.minimal.profit.block.cents.height,
&self.core.minimal.cap.cents.height, &self.core.minimal.cap.cents.height,
exit, exit,
)?; )?;
@@ -315,7 +315,7 @@ impl RealizedFull {
.to_rcap .to_rcap
.compute_binary::<Cents, Cents, RatioCentsBp32>( .compute_binary::<Cents, Cents, RatioCentsBp32>(
starting_indexes.height, starting_indexes.height,
&self.core.minimal.loss.base.cents.height, &self.core.minimal.loss.block.cents.height,
&self.core.minimal.cap.cents.height, &self.core.minimal.cap.cents.height,
exit, exit,
)?; )?;
@@ -323,16 +323,16 @@ impl RealizedFull {
.to_rcap .to_rcap
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>( .compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
starting_indexes.height, starting_indexes.height,
&self.core.net_pnl.base.cents.height, &self.core.net_pnl.block.cents.height,
&self.core.minimal.cap.cents.height, &self.core.minimal.cap.cents.height,
exit, exit,
)?; )?;
// Gross PnL // Gross PnL
self.gross_pnl.base.cents.height.compute_add( self.gross_pnl.block.cents.height.compute_add(
starting_indexes.height, starting_indexes.height,
&self.core.minimal.profit.base.cents.height, &self.core.minimal.profit.block.cents.height,
&self.core.minimal.loss.base.cents.height, &self.core.minimal.loss.block.cents.height,
exit, exit,
)?; )?;
self.gross_pnl.compute_rest(starting_indexes.height, exit)?; self.gross_pnl.compute_rest(starting_indexes.height, exit)?;
@@ -360,7 +360,7 @@ impl RealizedFull {
.to_rcap .to_rcap
.compute_binary::<Cents, Cents, RatioCentsBp32>( .compute_binary::<Cents, Cents, RatioCentsBp32>(
starting_indexes.height, starting_indexes.height,
&self.peak_regret.value.base.cents.height, &self.peak_regret.value.block.cents.height,
&self.core.minimal.cap.cents.height, &self.core.minimal.cap.cents.height,
exit, exit,
)?; )?;

View File

@@ -62,22 +62,22 @@ impl RealizedMinimal {
.cents .cents
.height .height
.len() .len()
.min(self.profit.base.cents.height.len()) .min(self.profit.block.cents.height.len())
.min(self.loss.base.cents.height.len()) .min(self.loss.block.cents.height.len())
} }
#[inline(always)] #[inline(always)]
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) { pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
self.cap.cents.height.push(state.realized.cap()); self.cap.cents.height.push(state.realized.cap());
self.profit.base.cents.height.push(state.realized.profit()); self.profit.block.cents.height.push(state.realized.profit());
self.loss.base.cents.height.push(state.realized.loss()); self.loss.block.cents.height.push(state.realized.loss());
} }
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
vec![ vec![
&mut self.cap.cents.height as &mut dyn AnyStoredVec, &mut self.cap.cents.height as &mut dyn AnyStoredVec,
&mut self.profit.base.cents.height, &mut self.profit.block.cents.height,
&mut self.loss.base.cents.height, &mut self.loss.block.cents.height,
] ]
} }
@@ -88,8 +88,8 @@ impl RealizedMinimal {
exit: &Exit, exit: &Exit,
) -> Result<()> { ) -> Result<()> {
sum_others!(self, starting_indexes, others, exit; cap.cents.height); sum_others!(self, starting_indexes, others, exit; cap.cents.height);
sum_others!(self, starting_indexes, others, exit; profit.base.cents.height); sum_others!(self, starting_indexes, others, exit; profit.block.cents.height);
sum_others!(self, starting_indexes, others, exit; loss.base.cents.height); sum_others!(self, starting_indexes, others, exit; loss.block.cents.height);
Ok(()) Ok(())
} }

View File

@@ -490,6 +490,6 @@ impl Vecs {
.min(Height::from(self.addrs.funded.min_stateful_len())) .min(Height::from(self.addrs.funded.min_stateful_len()))
.min(Height::from(self.addrs.empty.min_stateful_len())) .min(Height::from(self.addrs.empty.min_stateful_len()))
.min(Height::from(self.addrs.activity.min_stateful_len())) .min(Height::from(self.addrs.activity.min_stateful_len()))
.min(Height::from(self.coinblocks_destroyed.base.height.len())) .min(Height::from(self.coinblocks_destroyed.block.height.len()))
} }
} }

View File

@@ -21,7 +21,7 @@ impl Vecs {
.bps .bps
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>( .compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height, starting_indexes.height,
&mining.rewards.subsidy.base.usd.height, &mining.rewards.subsidy.block.usd.height,
&mining.rewards.subsidy_sma_1y.usd.height, &mining.rewards.subsidy_sma_1y.usd.height,
exit, exit,
)?; )?;
@@ -146,7 +146,7 @@ impl Vecs {
self.stock_to_flow.height.compute_transform2( self.stock_to_flow.height.compute_transform2(
starting_indexes.height, starting_indexes.height,
supply_total_sats, supply_total_sats,
&mining.rewards.subsidy.base.sats.height, &mining.rewards.subsidy.block.sats.height,
|(i, supply_sats, subsidy_sats, ..)| { |(i, supply_sats, subsidy_sats, ..)| {
let annual_flow = subsidy_sats.as_u128() as f64 * 52560.0; let annual_flow = subsidy_sats.as_u128() as f64 * 52560.0;
if annual_flow == 0.0 { if annual_flow == 0.0 {

View File

@@ -11,7 +11,7 @@ use crate::{
#[derive(Traversable)] #[derive(Traversable)]
pub struct AmountPerBlockCumulative<M: StorageMode = Rw> { pub struct AmountPerBlockCumulative<M: StorageMode = Rw> {
pub base: AmountPerBlock<M>, pub block: AmountPerBlock<M>,
pub cumulative: AmountPerBlock<M>, pub cumulative: AmountPerBlock<M>,
} }
@@ -27,7 +27,7 @@ impl AmountPerBlockCumulative {
let v = version + VERSION; let v = version + VERSION;
Ok(Self { Ok(Self {
base: AmountPerBlock::forced_import(db, name, v, indexes)?, block: AmountPerBlock::forced_import(db, name, v, indexes)?,
cumulative: AmountPerBlock::forced_import( cumulative: AmountPerBlock::forced_import(
db, db,
&format!("{name}_cumulative"), &format!("{name}_cumulative"),
@@ -46,11 +46,11 @@ impl AmountPerBlockCumulative {
self.cumulative self.cumulative
.sats .sats
.height .height
.compute_cumulative(max_from, &self.base.sats.height, exit)?; .compute_cumulative(max_from, &self.block.sats.height, exit)?;
self.base.cents.compute_binary::<Sats, Cents, SatsToCents>( self.block.cents.compute_binary::<Sats, Cents, SatsToCents>(
max_from, max_from,
&self.base.sats.height, &self.block.sats.height,
&prices.spot.cents.height, &prices.spot.cents.height,
exit, exit,
)?; )?;
@@ -58,7 +58,7 @@ impl AmountPerBlockCumulative {
self.cumulative self.cumulative
.cents .cents
.height .height
.compute_cumulative(max_from, &self.base.cents.height, exit)?; .compute_cumulative(max_from, &self.block.cents.height, exit)?;
Ok(()) Ok(())
} }

View File

@@ -67,7 +67,7 @@ impl AmountPerBlockCumulativeRolling {
exit: &Exit, exit: &Exit,
compute_sats: impl FnOnce(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>, compute_sats: impl FnOnce(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
) -> Result<()> { ) -> Result<()> {
compute_sats(&mut self.base.sats.height)?; compute_sats(&mut self.block.sats.height)?;
self.compute_rest(max_from, prices, exit) self.compute_rest(max_from, prices, exit)
} }

View File

@@ -54,15 +54,15 @@ impl AmountPerBlockFull {
exit: &Exit, exit: &Exit,
compute_sats: impl FnOnce(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>, compute_sats: impl FnOnce(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
) -> Result<()> { ) -> Result<()> {
compute_sats(&mut self.inner.base.sats.height)?; compute_sats(&mut self.inner.block.sats.height)?;
self.inner.compute_rest(max_from, prices, exit)?; self.inner.compute_rest(max_from, prices, exit)?;
self.distribution.compute( self.distribution.compute(
max_from, max_from,
windows, windows,
&self.inner.base.sats.height, &self.inner.block.sats.height,
&self.inner.base.cents.height, &self.inner.block.cents.height,
exit, exit,
)?; )?;

View File

@@ -29,7 +29,7 @@ where
T: NumericValue + JsonSchema, T: NumericValue + JsonSchema,
C: NumericValue + JsonSchema, C: NumericValue + JsonSchema,
{ {
pub base: PerBlock<T, M>, pub block: PerBlock<T, M>,
pub cumulative: PerBlock<C, M>, pub cumulative: PerBlock<C, M>,
pub sum: LazyRollingSumsFromHeight<C>, pub sum: LazyRollingSumsFromHeight<C>,
pub average: LazyRollingAvgsFromHeight<C>, pub average: LazyRollingAvgsFromHeight<C>,
@@ -47,7 +47,7 @@ where
indexes: &indexes::Vecs, indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts, cached_starts: &CachedWindowStarts,
) -> Result<Self> { ) -> Result<Self> {
let base = PerBlock::forced_import(db, name, version, indexes)?; let block = PerBlock::forced_import(db, name, version, indexes)?;
let cumulative = let cumulative =
PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?; PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?;
let sum = LazyRollingSumsFromHeight::new( let sum = LazyRollingSumsFromHeight::new(
@@ -66,7 +66,7 @@ where
); );
Ok(Self { Ok(Self {
base, block,
cumulative, cumulative,
sum, sum,
average, average,
@@ -83,7 +83,7 @@ where
where where
C: Default, C: Default,
{ {
compute_base(&mut self.base.height)?; compute_base(&mut self.block.height)?;
self.compute_rest(max_from, exit) self.compute_rest(max_from, exit)
} }
@@ -94,7 +94,7 @@ where
{ {
self.cumulative self.cumulative
.height .height
.compute_cumulative(max_from, &self.base.height, exit)?; .compute_cumulative(max_from, &self.block.height, exit)?;
Ok(()) Ok(())
} }
} }

View File

@@ -18,7 +18,7 @@ pub struct PerBlockFull<T, M: StorageMode = Rw>
where where
T: NumericValue + JsonSchema, T: NumericValue + JsonSchema,
{ {
pub base: PerBlock<T, M>, pub block: PerBlock<T, M>,
pub cumulative: PerBlock<T, M>, pub cumulative: PerBlock<T, M>,
#[traversable(flatten)] #[traversable(flatten)]
pub rolling: RollingComplete<T, M>, pub rolling: RollingComplete<T, M>,
@@ -35,7 +35,7 @@ where
indexes: &indexes::Vecs, indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts, cached_starts: &CachedWindowStarts,
) -> Result<Self> { ) -> Result<Self> {
let base = PerBlock::forced_import(db, name, version, indexes)?; let block = PerBlock::forced_import(db, name, version, indexes)?;
let cumulative = let cumulative =
PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?; PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?;
let rolling = RollingComplete::forced_import( let rolling = RollingComplete::forced_import(
@@ -48,7 +48,7 @@ where
)?; )?;
Ok(Self { Ok(Self {
base, block,
cumulative, cumulative,
rolling, rolling,
}) })
@@ -66,12 +66,12 @@ where
T: From<f64> + Default + Copy + Ord, T: From<f64> + Default + Copy + Ord,
f64: From<T>, f64: From<T>,
{ {
compute_base(&mut self.base.height)?; compute_base(&mut self.block.height)?;
self.cumulative self.cumulative
.height .height
.compute_cumulative(max_from, &self.base.height, exit)?; .compute_cumulative(max_from, &self.block.height, exit)?;
self.rolling self.rolling
.compute(max_from, windows, &self.base.height, exit)?; .compute(max_from, windows, &self.block.height, exit)?;
Ok(()) Ok(())
} }
} }

View File

@@ -19,7 +19,7 @@ pub struct PerBlockRollingAverage<T, M: StorageMode = Rw>
where where
T: NumericValue + JsonSchema, T: NumericValue + JsonSchema,
{ {
pub base: M::Stored<EagerVec<PcoVec<Height, T>>>, pub block: M::Stored<EagerVec<PcoVec<Height, T>>>,
#[traversable(hidden)] #[traversable(hidden)]
pub cumulative: M::Stored<EagerVec<PcoVec<Height, T>>>, pub cumulative: M::Stored<EagerVec<PcoVec<Height, T>>>,
#[traversable(flatten)] #[traversable(flatten)]
@@ -37,7 +37,7 @@ where
indexes: &indexes::Vecs, indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts, cached_starts: &CachedWindowStarts,
) -> Result<Self> { ) -> Result<Self> {
let base: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, version)?; let block: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, version)?;
let cumulative: EagerVec<PcoVec<Height, T>> = let cumulative: EagerVec<PcoVec<Height, T>> =
EagerVec::forced_import(db, &format!("{name}_cumulative"), version + Version::ONE)?; EagerVec::forced_import(db, &format!("{name}_cumulative"), version + Version::ONE)?;
let average = LazyRollingAvgsFromHeight::new( let average = LazyRollingAvgsFromHeight::new(
@@ -49,7 +49,7 @@ where
); );
Ok(Self { Ok(Self {
base, block,
cumulative, cumulative,
average, average,
}) })
@@ -62,14 +62,14 @@ where
exit: &Exit, exit: &Exit,
compute_height: impl FnOnce(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>, compute_height: impl FnOnce(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
) -> Result<()> { ) -> Result<()> {
compute_height(&mut self.base)?; compute_height(&mut self.block)?;
self.compute_rest(max_from, exit) self.compute_rest(max_from, exit)
} }
/// Compute cumulative from already-populated height data. Rolling averages are lazy. /// Compute cumulative from already-populated height data. Rolling averages are lazy.
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> { pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
self.cumulative self.cumulative
.compute_cumulative(max_from, &self.base, exit)?; .compute_cumulative(max_from, &self.block, exit)?;
Ok(()) Ok(())
} }
} }

View File

@@ -10,7 +10,7 @@ use crate::{
#[derive(Traversable)] #[derive(Traversable)]
pub struct FiatPerBlockCumulativeWithSums<C: CentsType, M: StorageMode = Rw> { pub struct FiatPerBlockCumulativeWithSums<C: CentsType, M: StorageMode = Rw> {
pub base: FiatPerBlock<C, M>, pub block: FiatPerBlock<C, M>,
pub cumulative: FiatPerBlock<C, M>, pub cumulative: FiatPerBlock<C, M>,
pub sum: LazyRollingSumsFiatFromHeight<C>, pub sum: LazyRollingSumsFiatFromHeight<C>,
} }
@@ -23,7 +23,7 @@ impl<C: CentsType> FiatPerBlockCumulativeWithSums<C> {
indexes: &indexes::Vecs, indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts, cached_starts: &CachedWindowStarts,
) -> Result<Self> { ) -> Result<Self> {
let base = FiatPerBlock::forced_import(db, name, version, indexes)?; let block = FiatPerBlock::forced_import(db, name, version, indexes)?;
let cumulative = FiatPerBlock::forced_import( let cumulative = FiatPerBlock::forced_import(
db, db,
&format!("{name}_cumulative"), &format!("{name}_cumulative"),
@@ -37,7 +37,7 @@ impl<C: CentsType> FiatPerBlockCumulativeWithSums<C> {
cached_starts, cached_starts,
indexes, indexes,
); );
Ok(Self { base, cumulative, sum }) Ok(Self { block, cumulative, sum })
} }
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()>
@@ -47,7 +47,7 @@ impl<C: CentsType> FiatPerBlockCumulativeWithSums<C> {
self.cumulative self.cumulative
.cents .cents
.height .height
.compute_cumulative(max_from, &self.base.cents.height, exit)?; .compute_cumulative(max_from, &self.block.cents.height, exit)?;
Ok(()) Ok(())
} }
} }

View File

@@ -81,10 +81,10 @@ impl Vecs {
r_coinbase?; r_coinbase?;
r_fees?; r_fees?;
self.subsidy.base.sats.height.compute_transform2( self.subsidy.block.sats.height.compute_transform2(
starting_indexes.height, starting_indexes.height,
&self.coinbase.base.sats.height, &self.coinbase.block.sats.height,
&self.fees.base.sats.height, &self.fees.block.sats.height,
|(height, coinbase, fees, ..)| { |(height, coinbase, fees, ..)| {
( (
height, height,
@@ -97,9 +97,9 @@ impl Vecs {
)?; )?;
self.subsidy.compute_rest(starting_indexes.height, prices, exit)?; self.subsidy.compute_rest(starting_indexes.height, prices, exit)?;
self.unclaimed.base.sats.height.compute_transform( self.unclaimed.block.sats.height.compute_transform(
starting_indexes.height, starting_indexes.height,
&self.subsidy.base.sats.height, &self.subsidy.block.sats.height,
|(height, subsidy, ..)| { |(height, subsidy, ..)| {
let halving = Halving::from(height); let halving = Halving::from(height);
let expected = Sats::FIFTY_BTC / 2_usize.pow(halving.to_usize() as u32); let expected = Sats::FIFTY_BTC / 2_usize.pow(halving.to_usize() as u32);
@@ -136,7 +136,7 @@ impl Vecs {
self.subsidy_sma_1y.cents.height.compute_rolling_average( self.subsidy_sma_1y.cents.height.compute_rolling_average(
starting_indexes.height, starting_indexes.height,
&lookback._1y, &lookback._1y,
&self.subsidy.base.cents.height, &self.subsidy.block.cents.height,
exit, exit,
)?; )?;

View File

@@ -93,8 +93,8 @@ impl Vecs {
|vec| { |vec| {
Ok(vec.compute_transform2( Ok(vec.compute_transform2(
starting_indexes.height, starting_indexes.height,
&self.base.blocks_mined.base.height, &self.base.blocks_mined.block.height,
&mining.rewards.coinbase.base.sats.height, &mining.rewards.coinbase.block.sats.height,
|(h, mask, val, ..)| (h, MaskSats::apply(mask, val)), |(h, mask, val, ..)| (h, MaskSats::apply(mask, val)),
exit, exit,
)?) )?)

View File

@@ -14,8 +14,8 @@ impl Vecs {
starting_indexes: &Indexes, starting_indexes: &Indexes,
exit: &Exit, exit: &Exit,
) -> Result<()> { ) -> Result<()> {
let op_return_height = &scripts.value.op_return.base.sats.height; let op_return_height = &scripts.value.op_return.block.sats.height;
let unclaimed_height = &mining.rewards.unclaimed.base.sats.height; let unclaimed_height = &mining.rewards.unclaimed.block.sats.height;
self.total.compute( self.total.compute(
starting_indexes.height, starting_indexes.height,

View File

@@ -21,7 +21,7 @@ impl Vecs {
self.native.height.compute_rolling_ratio( self.native.height.compute_rolling_ratio(
starting_indexes.height, starting_indexes.height,
&blocks.lookback._1y, &blocks.lookback._1y,
&transactions.volume.transfer_volume.base.sats.height, &transactions.volume.transfer_volume.block.sats.height,
&circulating_supply.sats.height, &circulating_supply.sats.height,
exit, exit,
)?; )?;
@@ -30,7 +30,7 @@ impl Vecs {
self.fiat.height.compute_rolling_ratio( self.fiat.height.compute_rolling_ratio(
starting_indexes.height, starting_indexes.height,
&blocks.lookback._1y, &blocks.lookback._1y,
&transactions.volume.transfer_volume.base.usd.height, &transactions.volume.transfer_volume.block.usd.height,
&circulating_supply.usd.height, &circulating_supply.usd.height,
exit, exit,
)?; )?;

View File

@@ -17,20 +17,20 @@ impl Vecs {
+ indexer.vecs.transactions.txid.version(); + indexer.vecs.transactions.txid.version();
for vec in [ for vec in [
&mut self.v1.base.height, &mut self.v1.block.height,
&mut self.v2.base.height, &mut self.v2.block.height,
&mut self.v3.base.height, &mut self.v3.block.height,
] { ] {
vec.validate_and_truncate(dep_version, starting_indexes.height)?; vec.validate_and_truncate(dep_version, starting_indexes.height)?;
} }
let skip = self let skip = self
.v1 .v1
.base .block
.height .height
.len() .len()
.min(self.v2.base.height.len()) .min(self.v2.block.height.len())
.min(self.v3.base.height.len()); .min(self.v3.block.height.len());
let first_tx_index = &indexer.vecs.transactions.first_tx_index; let first_tx_index = &indexer.vecs.transactions.first_tx_index;
let end = first_tx_index.len(); let end = first_tx_index.len();
@@ -39,9 +39,9 @@ impl Vecs {
} }
// Truncate all 3 to skip, then push (no per-element bounds checks). // Truncate all 3 to skip, then push (no per-element bounds checks).
self.v1.base.height.truncate_if_needed_at(skip)?; self.v1.block.height.truncate_if_needed_at(skip)?;
self.v2.base.height.truncate_if_needed_at(skip)?; self.v2.block.height.truncate_if_needed_at(skip)?;
self.v3.base.height.truncate_if_needed_at(skip)?; self.v3.block.height.truncate_if_needed_at(skip)?;
// Single cursor over tx_version — scanned once for all 3 version counts. // Single cursor over tx_version — scanned once for all 3 version counts.
let mut cursor = indexer.vecs.transactions.tx_version.cursor(); let mut cursor = indexer.vecs.transactions.tx_version.cursor();
@@ -69,23 +69,23 @@ impl Vecs {
} }
} }
self.v1.base.height.push(StoredU64::from(c1 as u64)); self.v1.block.height.push(StoredU64::from(c1 as u64));
self.v2.base.height.push(StoredU64::from(c2 as u64)); self.v2.block.height.push(StoredU64::from(c2 as u64));
self.v3.base.height.push(StoredU64::from(c3 as u64)); self.v3.block.height.push(StoredU64::from(c3 as u64));
if self.v1.base.height.batch_limit_reached() { if self.v1.block.height.batch_limit_reached() {
let _lock = exit.lock(); let _lock = exit.lock();
self.v1.base.height.write()?; self.v1.block.height.write()?;
self.v2.base.height.write()?; self.v2.block.height.write()?;
self.v3.base.height.write()?; self.v3.block.height.write()?;
} }
} }
{ {
let _lock = exit.lock(); let _lock = exit.lock();
self.v1.base.height.write()?; self.v1.block.height.write()?;
self.v2.base.height.write()?; self.v2.block.height.write()?;
self.v3.base.height.write()?; self.v3.block.height.write()?;
} }
// Derive cumulative + sums from base // Derive cumulative + sums from base

View File

@@ -11,7 +11,7 @@ impl Query {
let current_height = self.height().to_usize(); let current_height = self.height().to_usize();
let start = current_height.saturating_sub(time_period.block_count()); let start = current_height.saturating_sub(time_period.block_count());
let coinbase_vec = &computer.mining.rewards.coinbase.base.sats.height; let coinbase_vec = &computer.mining.rewards.coinbase.block.sats.height;
let timestamp_vec = &indexer.vecs.blocks.timestamp; let timestamp_vec = &indexer.vecs.blocks.timestamp;
match time_period { match time_period {

View File

@@ -12,9 +12,9 @@ impl Query {
let end_block = current_height; let end_block = current_height;
let start_block = Height::from(current_height.to_usize().saturating_sub(block_count - 1)); let start_block = Height::from(current_height.to_usize().saturating_sub(block_count - 1));
let coinbase_vec = &computer.mining.rewards.coinbase.base.sats.height; let coinbase_vec = &computer.mining.rewards.coinbase.block.sats.height;
let fee_vec = &computer.mining.rewards.fees.base.sats.height; let fee_vec = &computer.mining.rewards.fees.block.sats.height;
let tx_count_vec = &computer.transactions.count.total.base.height; let tx_count_vec = &computer.transactions.count.total.block.height;
let start = start_block.to_usize(); let start = start_block.to_usize();
let end = end_block.to_usize() + 1; let end = end_block.to_usize() + 1;

View File

@@ -268,7 +268,37 @@ export function simplePriceRatioTree({ pattern, title, legend, color }) {
} }
/** /**
* Create Price + Ratio charts with percentile bands (no SMAs/z-scores) * @template T
* @param {InvestorPercentilesPattern} p
* @param {(entry: InvestorPercentileEntry) => T} extract
*/
function percentileBands(p, extract) {
return [
{ name: "pct95", prop: extract(p.pct95), color: colors.ratioPct._95 },
{ name: "pct5", prop: extract(p.pct5), color: colors.ratioPct._5 },
{ name: "pct98", prop: extract(p.pct98), color: colors.ratioPct._98 },
{ name: "pct2", prop: extract(p.pct2), color: colors.ratioPct._2 },
{ name: "pct99", prop: extract(p.pct99), color: colors.ratioPct._99 },
{ name: "pct1", prop: extract(p.pct1), color: colors.ratioPct._1 },
];
}
/** @param {{ name: string, prop: AnyPricePattern, color: Color }[]} bands */
function priceBands(bands) {
return bands.map(({ name, prop, color }) =>
price({ series: prop, name, color, defaultActive: false, options: { lineStyle: 1 } }),
);
}
/** @param {{ name: string, prop: AnySeriesPattern, color: Color }[]} bands */
function ratioBands(bands) {
return bands.map(({ name, prop, color }) =>
line({ series: prop, name, color, defaultActive: false, unit: Unit.ratio, options: { lineStyle: 1 } }),
);
}
/**
* Price + Ratio charts with percentile bands
* @param {Object} args * @param {Object} args
* @param {PriceRatioPercentilesPattern} args.pattern * @param {PriceRatioPercentilesPattern} args.pattern
* @param {string} args.title * @param {string} args.title
@@ -285,22 +315,8 @@ export function priceRatioPercentilesTree({
priceReferences, priceReferences,
}) { }) {
const p = pattern.percentiles; const p = pattern.percentiles;
const pctUsd = [ const pctUsd = percentileBands(p, (e) => e.price);
{ name: "pct95", prop: p.pct95.price, color: colors.ratioPct._95 }, const pctRatio = percentileBands(p, (e) => e.ratio);
{ name: "pct5", prop: p.pct5.price, color: colors.ratioPct._5 },
{ name: "pct98", prop: p.pct98.price, color: colors.ratioPct._98 },
{ name: "pct2", prop: p.pct2.price, color: colors.ratioPct._2 },
{ name: "pct99", prop: p.pct99.price, color: colors.ratioPct._99 },
{ name: "pct1", prop: p.pct1.price, color: colors.ratioPct._1 },
];
const pctRatio = [
{ name: "pct95", prop: p.pct95.ratio, color: colors.ratioPct._95 },
{ name: "pct5", prop: p.pct5.ratio, color: colors.ratioPct._5 },
{ name: "pct98", prop: p.pct98.ratio, color: colors.ratioPct._98 },
{ name: "pct2", prop: p.pct2.ratio, color: colors.ratioPct._2 },
{ name: "pct99", prop: p.pct99.ratio, color: colors.ratioPct._99 },
{ name: "pct1", prop: p.pct1.ratio, color: colors.ratioPct._1 },
];
return [ return [
{ {
name: "Price", name: "Price",
@@ -308,15 +324,7 @@ export function priceRatioPercentilesTree({
top: [ top: [
price({ series: pattern, name: legend, color }), price({ series: pattern, name: legend, color }),
...(priceReferences ?? []), ...(priceReferences ?? []),
...pctUsd.map(({ name, prop, color }) => ...priceBands(pctUsd),
price({
series: prop,
name,
color,
defaultActive: false,
options: { lineStyle: 1 },
}),
),
], ],
}, },
{ {
@@ -324,15 +332,7 @@ export function priceRatioPercentilesTree({
title: `${title} Ratio`, title: `${title} Ratio`,
top: [ top: [
price({ series: pattern, name: legend, color }), price({ series: pattern, name: legend, color }),
...pctUsd.map(({ name, prop, color }) => ...priceBands(pctUsd),
price({
series: prop,
name,
color,
defaultActive: false,
options: { lineStyle: 1 },
}),
),
], ],
bottom: [ bottom: [
baseline({ baseline({
@@ -341,16 +341,7 @@ export function priceRatioPercentilesTree({
unit: Unit.ratio, unit: Unit.ratio,
base: 1, base: 1,
}), }),
...pctRatio.map(({ name, prop, color }) => ...ratioBands(pctRatio),
line({
series: prop,
name,
color,
defaultActive: false,
unit: Unit.ratio,
options: { lineStyle: 1 },
}),
),
], ],
}, },
]; ];
@@ -723,6 +714,7 @@ export function createPriceRatioCharts({
priceReferences, priceReferences,
}) { }) {
const titleFn = formatCohortTitle(context); const titleFn = formatCohortTitle(context);
const pctUsd = percentileBands(ratio.percentiles, (e) => e.price);
return [ return [
{ {
name: "Price", name: "Price",
@@ -730,6 +722,7 @@ export function createPriceRatioCharts({
top: [ top: [
price({ series: pricePattern, name: legend, color }), price({ series: pricePattern, name: legend, color }),
...(priceReferences ?? []), ...(priceReferences ?? []),
...priceBands(pctUsd),
], ],
}, },
createRatioChart({ createRatioChart({

View File

@@ -132,7 +132,7 @@
*/ */
/** /**
* Sell side risk rolling windows pattern * Sell side risk rolling windows pattern
* @typedef {Brk._1m1w1y24hPattern6} SellSideRiskPattern * @typedef {Brk._1m1w1y24hPattern7} SellSideRiskPattern
*/ */
/** /**
* Stats pattern: average, min, max, percentiles (height-only indexes, NO base) * Stats pattern: average, min, max, percentiles (height-only indexes, NO base)