mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
computer: snapshot
This commit is contained in:
@@ -17,7 +17,7 @@ use crate::{
|
||||
metrics::{
|
||||
AllCohortMetrics, BasicCohortMetrics, CohortMetricsBase, CoreCohortMetrics,
|
||||
ExtendedAdjustedCohortMetrics, ExtendedCohortMetrics, ImportConfig,
|
||||
MinimalCohortMetrics, ProfitabilityMetrics, SupplyMetrics,
|
||||
MinimalCohortMetrics, ProfitabilityMetrics, RealizedFullAccum, SupplyMetrics,
|
||||
},
|
||||
state::UTXOCohortState,
|
||||
},
|
||||
@@ -44,6 +44,7 @@ pub struct UTXOCohorts<M: StorageMode = Rw> {
|
||||
pub ge_amount: ByGreatEqualAmount<UTXOCohortVecs<MinimalCohortMetrics<M>>>,
|
||||
pub amount_range: ByAmountRange<UTXOCohortVecs<MinimalCohortMetrics<M>>>,
|
||||
pub lt_amount: ByLowerThanAmount<UTXOCohortVecs<MinimalCohortMetrics<M>>>,
|
||||
#[traversable(rename = "type")]
|
||||
pub type_: BySpendableType<UTXOCohortVecs<MinimalCohortMetrics<M>>>,
|
||||
pub profitability: ProfitabilityMetrics<M>,
|
||||
pub matured: ByAgeRange<ValueFromHeight<M>>,
|
||||
@@ -707,7 +708,7 @@ impl UTXOCohorts<Rw> {
|
||||
.try_for_each(|v| v.write_state(height, cleanup))
|
||||
}
|
||||
|
||||
/// Get minimum height from all separate cohorts' + profitability height-indexed vectors.
|
||||
/// Get minimum height from all separate cohorts' + profitability + overlapping realized height-indexed vectors.
|
||||
pub(crate) fn min_separate_stateful_height_len(&self) -> Height {
|
||||
self.iter_separate()
|
||||
.map(|v| Height::from(v.min_stateful_height_len()))
|
||||
@@ -715,6 +716,9 @@ impl UTXOCohorts<Rw> {
|
||||
.min()
|
||||
.unwrap_or_default()
|
||||
.min(Height::from(self.profitability.min_stateful_height_len()))
|
||||
.min(Height::from(self.all.metrics.realized.min_stateful_height_len()))
|
||||
.min(Height::from(self.sth.metrics.realized.min_stateful_height_len()))
|
||||
.min(Height::from(self.lth.metrics.realized.min_stateful_height_len()))
|
||||
}
|
||||
|
||||
/// Import state for all separate cohorts at or before given height.
|
||||
@@ -761,6 +765,38 @@ impl UTXOCohorts<Rw> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Aggregate RealizedFull fields from age_range states and push to all/sth/lth.
|
||||
/// Called during the block loop after separate cohorts' truncate_push but before reset.
|
||||
pub(crate) fn push_overlapping_realized_full(&mut self, height: Height) -> Result<()> {
|
||||
let Self {
|
||||
all, sth, lth, age_range, ..
|
||||
} = self;
|
||||
|
||||
let sth_filter = &sth.metrics.filter;
|
||||
|
||||
let mut all_acc = RealizedFullAccum::default();
|
||||
let mut sth_acc = RealizedFullAccum::default();
|
||||
let mut lth_acc = RealizedFullAccum::default();
|
||||
|
||||
for ar in age_range.iter() {
|
||||
if let Some(state) = ar.state.as_ref() {
|
||||
let r = &state.realized;
|
||||
all_acc.add(r);
|
||||
if sth_filter.includes(&ar.metrics.filter) {
|
||||
sth_acc.add(r);
|
||||
} else {
|
||||
lth_acc.add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
all.metrics.realized.push_from_accum(&all_acc, height)?;
|
||||
sth.metrics.realized.push_from_accum(&sth_acc, height)?;
|
||||
lth.metrics.realized.push_from_accum(<h_acc, height)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Filter source cohorts by an optional filter.
|
||||
|
||||
@@ -157,10 +157,6 @@ impl<M: CohortMetricsBase + Traversable> DynCohortVecs for UTXOCohortVecs<M> {
|
||||
) -> Result<()> {
|
||||
self.metrics
|
||||
.compute_rest_part1(blocks, prices, starting_indexes, exit)?;
|
||||
if self.state.is_some() {
|
||||
self.metrics
|
||||
.compute_net_sentiment_height(starting_indexes, exit)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -506,6 +506,7 @@ fn push_cohort_states(
|
||||
height_price: Cents,
|
||||
is_day_boundary: bool,
|
||||
) -> Result<()> {
|
||||
// Phase 1: push + unrealized (no reset yet — states still needed for aggregation)
|
||||
let (r1, r2) = rayon::join(
|
||||
|| {
|
||||
utxo_cohorts
|
||||
@@ -517,7 +518,6 @@ fn push_cohort_states(
|
||||
height_price,
|
||||
is_day_boundary,
|
||||
)?;
|
||||
v.reset_single_iteration_values();
|
||||
Ok(())
|
||||
})
|
||||
},
|
||||
@@ -531,12 +531,23 @@ fn push_cohort_states(
|
||||
height_price,
|
||||
is_day_boundary,
|
||||
)?;
|
||||
v.reset_single_iteration_values();
|
||||
Ok(())
|
||||
})
|
||||
},
|
||||
);
|
||||
r1?;
|
||||
r2?;
|
||||
|
||||
// Phase 2: aggregate age_range realized states → push to overlapping cohorts' RealizedFull
|
||||
utxo_cohorts.push_overlapping_realized_full(height)?;
|
||||
|
||||
// Phase 3: reset per-block values
|
||||
utxo_cohorts
|
||||
.iter_separate_mut()
|
||||
.for_each(|v| v.reset_single_iteration_values());
|
||||
address_cohorts
|
||||
.iter_separate_mut()
|
||||
.for_each(|v| v.reset_single_iteration_values());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ pub struct ExtendedAdjustedCohortMetrics<M: StorageMode = Rw> {
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub inner: ExtendedCohortMetrics<M>,
|
||||
#[traversable(flatten)]
|
||||
pub adjusted: Box<RealizedAdjusted<M>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ pub use cost_basis::CostBasis;
|
||||
pub use profitability::ProfitabilityMetrics;
|
||||
pub use outputs::OutputsMetrics;
|
||||
pub use realized::{
|
||||
RealizedAdjusted, RealizedBase, RealizedCore, RealizedFull, RealizedLike, RealizedMinimal,
|
||||
RealizedAdjusted, RealizedBase, RealizedCore, RealizedFull, RealizedFullAccum, RealizedLike,
|
||||
RealizedMinimal,
|
||||
};
|
||||
pub use relative::{
|
||||
RelativeForAll, RelativeToAll, RelativeWithExtended,
|
||||
@@ -189,16 +190,9 @@ pub trait CohortMetricsBase: CohortMetricsState<Realized = RealizedState> + Send
|
||||
self.unrealized_mut()
|
||||
.compute_rest(prices, starting_indexes, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_net_sentiment_height(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.unrealized_mut()
|
||||
.compute_net_sentiment_height(starting_indexes, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -298,6 +298,47 @@ impl RealizedFull {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn push_from_accum(
|
||||
&mut self,
|
||||
accum: &RealizedFullAccum,
|
||||
height: Height,
|
||||
) -> Result<()> {
|
||||
self.profit_value_created
|
||||
.height
|
||||
.truncate_push(height, accum.profit_value_created)?;
|
||||
self.profit_value_destroyed
|
||||
.height
|
||||
.truncate_push(height, accum.profit_value_destroyed)?;
|
||||
self.loss_value_created
|
||||
.height
|
||||
.truncate_push(height, accum.loss_value_created)?;
|
||||
self.loss_value_destroyed
|
||||
.height
|
||||
.truncate_push(height, accum.loss_value_destroyed)?;
|
||||
self.cap_raw.truncate_push(height, accum.cap_raw)?;
|
||||
self.investor_cap_raw
|
||||
.truncate_push(height, accum.investor_cap_raw)?;
|
||||
|
||||
let investor_price = {
|
||||
let cap = accum.cap_raw.as_u128();
|
||||
if cap == 0 {
|
||||
Cents::ZERO
|
||||
} else {
|
||||
Cents::new((accum.investor_cap_raw / cap) as u64)
|
||||
}
|
||||
};
|
||||
self.investor_price
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, investor_price)?;
|
||||
|
||||
self.peak_regret
|
||||
.height
|
||||
.truncate_push(height, accum.peak_regret)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
@@ -626,3 +667,26 @@ impl RealizedFull {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RealizedFullAccum {
|
||||
pub(crate) profit_value_created: Cents,
|
||||
pub(crate) profit_value_destroyed: Cents,
|
||||
pub(crate) loss_value_created: Cents,
|
||||
pub(crate) loss_value_destroyed: Cents,
|
||||
pub(crate) cap_raw: CentsSats,
|
||||
pub(crate) investor_cap_raw: CentsSquaredSats,
|
||||
pub(crate) peak_regret: Cents,
|
||||
}
|
||||
|
||||
impl RealizedFullAccum {
|
||||
pub(crate) fn add(&mut self, state: &RealizedState) {
|
||||
self.profit_value_created += state.profit_value_created();
|
||||
self.profit_value_destroyed += state.profit_value_destroyed();
|
||||
self.loss_value_created += state.loss_value_created();
|
||||
self.loss_value_destroyed += state.loss_value_destroyed();
|
||||
self.cap_raw += state.cap_raw();
|
||||
self.investor_cap_raw += state.investor_cap_raw();
|
||||
self.peak_regret += state.peak_regret();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ mod minimal;
|
||||
pub use adjusted::RealizedAdjusted;
|
||||
pub use base::RealizedBase;
|
||||
pub use self::core::RealizedCore;
|
||||
pub use full::RealizedFull;
|
||||
pub use full::{RealizedFull, RealizedFullAccum};
|
||||
pub use minimal::RealizedMinimal;
|
||||
|
||||
use brk_error::Result;
|
||||
|
||||
Reference in New Issue
Block a user