mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snap
This commit is contained in:
@@ -67,14 +67,14 @@ pub(crate) fn process_funded_addrs(
|
||||
|
||||
// Pure pushes - no holes remain
|
||||
addrs_data.funded.reserve_pushed(pushes_iter.len());
|
||||
let mut next_index = addrs_data.funded.len();
|
||||
for (addr_type, type_index, data) in pushes_iter {
|
||||
for (next_index, (addr_type, type_index, data)) in
|
||||
(addrs_data.funded.len()..).zip(pushes_iter)
|
||||
{
|
||||
addrs_data.funded.push(data);
|
||||
result.get_mut(addr_type).unwrap().insert(
|
||||
type_index,
|
||||
AnyAddrIndex::from(FundedAddrIndex::from(next_index)),
|
||||
);
|
||||
next_index += 1;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
@@ -138,14 +138,14 @@ pub(crate) fn process_empty_addrs(
|
||||
|
||||
// Pure pushes - no holes remain
|
||||
addrs_data.empty.reserve_pushed(pushes_iter.len());
|
||||
let mut next_index = addrs_data.empty.len();
|
||||
for (addr_type, type_index, data) in pushes_iter {
|
||||
for (next_index, (addr_type, type_index, data)) in
|
||||
(addrs_data.empty.len()..).zip(pushes_iter)
|
||||
{
|
||||
addrs_data.empty.push(data);
|
||||
result.get_mut(addr_type).unwrap().insert(
|
||||
type_index,
|
||||
AnyAddrIndex::from(EmptyAddrIndex::from(next_index)),
|
||||
);
|
||||
next_index += 1;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
||||
@@ -542,17 +542,14 @@ impl UTXOCohorts<Rw> {
|
||||
}
|
||||
|
||||
/// Second phase of post-processing: compute relative metrics.
|
||||
pub(crate) fn compute_rest_part2<HM>(
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_market_cap: &HM,
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
HM: ReadableVec<Height, Dollars> + Sync,
|
||||
{
|
||||
) -> Result<()> {
|
||||
// Get under_1h value sources for adjusted computation (cloned to avoid borrow conflicts).
|
||||
let under_1h_value_created = self
|
||||
.age_range
|
||||
|
||||
@@ -258,6 +258,7 @@ pub(crate) fn process_blocks(
|
||||
.chain(vecs.addrs.activity.par_iter_height_mut())
|
||||
.chain(vecs.addrs.reused.par_iter_height_mut())
|
||||
.chain(vecs.addrs.exposed.par_iter_height_mut())
|
||||
.chain(vecs.addrs.avg_amount.par_iter_height_mut())
|
||||
.chain(rayon::iter::once(
|
||||
&mut vecs.coinblocks_destroyed.block as &mut dyn AnyStoredVec,
|
||||
))
|
||||
|
||||
@@ -156,6 +156,7 @@ impl AllCohortMetrics {
|
||||
starting_indexes.height,
|
||||
&self.supply,
|
||||
&self.unrealized,
|
||||
&self.realized,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -132,6 +132,7 @@ impl ExtendedCohortMetrics {
|
||||
starting_indexes.height,
|
||||
&self.supply,
|
||||
&self.unrealized,
|
||||
&self.realized,
|
||||
height_to_market_cap,
|
||||
all_supply_sats,
|
||||
&self.supply.total.usd.height,
|
||||
|
||||
@@ -133,7 +133,7 @@ pub use realized::{
|
||||
AdjustedSopr, RealizedCore, RealizedFull, RealizedFullAccum, RealizedLike, RealizedMinimal,
|
||||
};
|
||||
pub use relative::{RelativeForAll, RelativeToAll, RelativeWithExtended};
|
||||
pub use supply::{SupplyBase, SupplyCore};
|
||||
pub use supply::{AvgAmountMetrics, SupplyBase, SupplyCore};
|
||||
pub use unrealized::{
|
||||
UnrealizedBasic, UnrealizedCore, UnrealizedFull, UnrealizedLike, UnrealizedMinimal,
|
||||
};
|
||||
|
||||
@@ -118,11 +118,11 @@ impl RealizedMinimal {
|
||||
|(i, cap_cents, supply, ..)| {
|
||||
let cap = cap_cents.as_u128();
|
||||
let supply_sats = Sats::from(supply).as_u128();
|
||||
if supply_sats == 0 {
|
||||
(i, Cents::ZERO)
|
||||
} else {
|
||||
(i, Cents::from(cap * Sats::ONE_BTC_U128 / supply_sats))
|
||||
}
|
||||
let cents = (cap * Sats::ONE_BTC_U128)
|
||||
.checked_div(supply_sats)
|
||||
.map(Cents::from)
|
||||
.unwrap_or(Cents::ZERO);
|
||||
(i, cents)
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
|
||||
@@ -4,9 +4,9 @@ use brk_types::{Dollars, Height};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, SupplyCore, UnrealizedFull};
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedFull, SupplyCore, UnrealizedFull};
|
||||
|
||||
use super::{RelativeExtendedOwnPnl, RelativeFull};
|
||||
use super::{RelativeExtendedOwnPnl, RelativeFull, RelativeInvestedCapital};
|
||||
|
||||
/// Relative metrics for the "all" cohort (base + own_pnl, NO rel_to_all).
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
@@ -17,6 +17,8 @@ pub struct RelativeForAll<M: StorageMode = Rw> {
|
||||
pub base: RelativeFull<M>,
|
||||
#[traversable(flatten)]
|
||||
pub extended_own_pnl: RelativeExtendedOwnPnl<M>,
|
||||
#[traversable(flatten)]
|
||||
pub invested_capital: RelativeInvestedCapital<M>,
|
||||
}
|
||||
|
||||
impl RelativeForAll {
|
||||
@@ -24,6 +26,7 @@ impl RelativeForAll {
|
||||
Ok(Self {
|
||||
base: RelativeFull::forced_import(cfg)?,
|
||||
extended_own_pnl: RelativeExtendedOwnPnl::forced_import(cfg)?,
|
||||
invested_capital: RelativeInvestedCapital::forced_import(cfg)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,6 +35,7 @@ impl RelativeForAll {
|
||||
max_from: Height,
|
||||
supply: &SupplyCore,
|
||||
unrealized: &UnrealizedFull,
|
||||
realized: &RealizedFull,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
@@ -43,6 +47,8 @@ impl RelativeForAll {
|
||||
&unrealized.gross_pnl.usd.height,
|
||||
exit,
|
||||
)?;
|
||||
self.invested_capital
|
||||
.compute(max_from, unrealized, realized, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, Cents, Height, Version};
|
||||
use vecdb::{Exit, Rw, StorageMode};
|
||||
|
||||
use crate::internal::{PercentPerBlock, RatioCentsBp16};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedFull, UnrealizedFull};
|
||||
|
||||
/// Shares of invested capital in profit / in loss relative to own realized cap.
|
||||
/// Present for cohorts with `UnrealizedFull` (all, sth, lth).
|
||||
#[derive(Traversable)]
|
||||
pub struct RelativeInvestedCapital<M: StorageMode = Rw> {
|
||||
#[traversable(wrap = "invested_capital/in_profit", rename = "to_own")]
|
||||
pub in_profit_to_own: PercentPerBlock<BasisPoints16, M>,
|
||||
#[traversable(wrap = "invested_capital/in_loss", rename = "to_own")]
|
||||
pub in_loss_to_own: PercentPerBlock<BasisPoints16, M>,
|
||||
}
|
||||
|
||||
impl RelativeInvestedCapital {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
Ok(Self {
|
||||
in_profit_to_own: cfg.import("invested_capital_in_profit_to_own", v0)?,
|
||||
in_loss_to_own: cfg.import("invested_capital_in_loss_to_own", v0)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedFull,
|
||||
realized: &RealizedFull,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let realized_cap = &realized.core.minimal.cap.cents.height;
|
||||
self.in_profit_to_own
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp16>(
|
||||
max_from,
|
||||
&unrealized.invested_capital.in_profit.cents.height,
|
||||
realized_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.in_loss_to_own
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp16>(
|
||||
max_from,
|
||||
&unrealized.invested_capital.in_loss.cents.height,
|
||||
realized_cap,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ mod extended_own_market_cap;
|
||||
mod extended_own_pnl;
|
||||
mod for_all;
|
||||
mod full;
|
||||
mod invested_capital;
|
||||
mod to_all;
|
||||
mod with_extended;
|
||||
|
||||
@@ -9,5 +10,6 @@ pub use extended_own_market_cap::RelativeExtendedOwnMarketCap;
|
||||
pub use extended_own_pnl::RelativeExtendedOwnPnl;
|
||||
pub use for_all::RelativeForAll;
|
||||
pub use full::RelativeFull;
|
||||
pub use invested_capital::RelativeInvestedCapital;
|
||||
pub use to_all::RelativeToAll;
|
||||
pub use with_extended::RelativeWithExtended;
|
||||
|
||||
@@ -4,9 +4,12 @@ use brk_types::{Dollars, Height, Sats};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, SupplyCore, UnrealizedFull};
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedFull, SupplyCore, UnrealizedFull};
|
||||
|
||||
use super::{RelativeExtendedOwnMarketCap, RelativeExtendedOwnPnl, RelativeFull, RelativeToAll};
|
||||
use super::{
|
||||
RelativeExtendedOwnMarketCap, RelativeExtendedOwnPnl, RelativeFull, RelativeInvestedCapital,
|
||||
RelativeToAll,
|
||||
};
|
||||
|
||||
/// Full extended relative metrics (base + rel_to_all + own_market_cap + own_pnl).
|
||||
/// Used by: sth, lth cohorts.
|
||||
@@ -22,6 +25,8 @@ pub struct RelativeWithExtended<M: StorageMode = Rw> {
|
||||
pub extended_own_market_cap: RelativeExtendedOwnMarketCap<M>,
|
||||
#[traversable(flatten)]
|
||||
pub extended_own_pnl: RelativeExtendedOwnPnl<M>,
|
||||
#[traversable(flatten)]
|
||||
pub invested_capital: RelativeInvestedCapital<M>,
|
||||
}
|
||||
|
||||
impl RelativeWithExtended {
|
||||
@@ -31,6 +36,7 @@ impl RelativeWithExtended {
|
||||
rel_to_all: RelativeToAll::forced_import(cfg)?,
|
||||
extended_own_market_cap: RelativeExtendedOwnMarketCap::forced_import(cfg)?,
|
||||
extended_own_pnl: RelativeExtendedOwnPnl::forced_import(cfg)?,
|
||||
invested_capital: RelativeInvestedCapital::forced_import(cfg)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,6 +46,7 @@ impl RelativeWithExtended {
|
||||
max_from: Height,
|
||||
supply: &SupplyCore,
|
||||
unrealized: &UnrealizedFull,
|
||||
realized: &RealizedFull,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
all_supply_sats: &impl ReadableVec<Height, Sats>,
|
||||
own_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
@@ -57,6 +64,8 @@ impl RelativeWithExtended {
|
||||
&unrealized.gross_pnl.usd.height,
|
||||
exit,
|
||||
)?;
|
||||
self.invested_capital
|
||||
.compute(max_from, unrealized, realized, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Sats, StoredU64, Version};
|
||||
use vecdb::{AnyStoredVec, Database, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{indexes, internal::AmountPerBlock, prices};
|
||||
|
||||
/// Average amount held per UTXO and per funded address.
|
||||
///
|
||||
/// `utxo = supply / utxo_count`, `addr = supply / funded_addr_count`.
|
||||
#[derive(Traversable)]
|
||||
pub struct AvgAmountMetrics<M: StorageMode = Rw> {
|
||||
pub utxo: AmountPerBlock<M>,
|
||||
pub addr: AmountPerBlock<M>,
|
||||
}
|
||||
|
||||
impl AvgAmountMetrics {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
prefix: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let name = |suffix: &str| {
|
||||
if prefix.is_empty() {
|
||||
suffix.to_string()
|
||||
} else {
|
||||
format!("{prefix}_{suffix}")
|
||||
}
|
||||
};
|
||||
Ok(Self {
|
||||
utxo: AmountPerBlock::forced_import(db, &name("avg_utxo_amount"), version, indexes)?,
|
||||
addr: AmountPerBlock::forced_import(db, &name("avg_addr_amount"), version, indexes)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.utxo.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.utxo.cents.height,
|
||||
&mut self.addr.sats.height,
|
||||
&mut self.addr.cents.height,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn reset_height(&mut self) -> Result<()> {
|
||||
self.utxo.sats.height.reset()?;
|
||||
self.utxo.cents.height.reset()?;
|
||||
self.addr.sats.height.reset()?;
|
||||
self.addr.cents.height.reset()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
supply_sats: &impl ReadableVec<Height, Sats>,
|
||||
utxo_count: &impl ReadableVec<Height, StoredU64>,
|
||||
funded_addr_count: &impl ReadableVec<Height, StoredU64>,
|
||||
max_from: Height,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.utxo
|
||||
.sats
|
||||
.height
|
||||
.compute_divide(max_from, supply_sats, utxo_count, exit)?;
|
||||
self.utxo.compute(prices, max_from, exit)?;
|
||||
|
||||
self.addr
|
||||
.sats
|
||||
.height
|
||||
.compute_divide(max_from, supply_sats, funded_addr_count, exit)?;
|
||||
self.addr.compute(prices, max_from, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ impl SupplyBase {
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.total.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.total.cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.total.cents.height,
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mod avg_amount;
|
||||
mod base;
|
||||
mod core;
|
||||
|
||||
pub use avg_amount::AvgAmountMetrics;
|
||||
pub use self::core::SupplyCore;
|
||||
pub use base::SupplyBase;
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
},
|
||||
indexes, inputs,
|
||||
internal::{
|
||||
PerBlockCumulativeRolling, WindowStartVec, Windows,
|
||||
PerBlockCumulativeRolling, WindowStartVec, Windows, WithAddrTypes,
|
||||
db_utils::{finalize_db, open_db},
|
||||
},
|
||||
outputs, prices, transactions,
|
||||
@@ -37,6 +37,7 @@ use super::{
|
||||
AddrActivityVecs, AddrCountsVecs, DeltaVecs, ExposedAddrVecs, NewAddrCountVecs,
|
||||
ReusedAddrVecs, TotalAddrCountVecs,
|
||||
},
|
||||
metrics::AvgAmountMetrics,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::new(23);
|
||||
@@ -51,6 +52,7 @@ pub struct AddrMetricsVecs<M: StorageMode = Rw> {
|
||||
pub reused: ReusedAddrVecs<M>,
|
||||
pub exposed: ExposedAddrVecs<M>,
|
||||
pub delta: DeltaVecs,
|
||||
pub avg_amount: WithAddrTypes<AvgAmountMetrics<M>>,
|
||||
#[traversable(wrap = "indexes", rename = "funded")]
|
||||
pub funded_index:
|
||||
LazyVecFrom1<FundedAddrIndex, FundedAddrIndex, FundedAddrIndex, FundedAddrData>,
|
||||
@@ -170,6 +172,9 @@ impl Vecs {
|
||||
// Growth rate: delta change + rate (global + per-type)
|
||||
let delta = DeltaVecs::new(version, &addr_count, cached_starts, indexes);
|
||||
|
||||
// Average amount (supply / utxo_count, supply / funded_addr_count) for `all` and per addr type.
|
||||
let avg_amount = WithAddrTypes::<AvgAmountMetrics>::forced_import(&db, version, indexes)?;
|
||||
|
||||
let this = Self {
|
||||
supply_state: BytesVec::forced_import_with(
|
||||
vecdb::ImportOptions::new(&db, "supply_state", version)
|
||||
@@ -185,6 +190,7 @@ impl Vecs {
|
||||
reused: reused_addr_count,
|
||||
exposed: exposed_addr_vecs,
|
||||
delta,
|
||||
avg_amount,
|
||||
funded_index: funded_addr_index,
|
||||
empty_index: empty_addr_index,
|
||||
},
|
||||
@@ -302,6 +308,7 @@ impl Vecs {
|
||||
self.addrs.activity.reset_height()?;
|
||||
self.addrs.reused.reset_height()?;
|
||||
self.addrs.exposed.reset_height()?;
|
||||
self.addrs.avg_amount.reset_height()?;
|
||||
reset_state(
|
||||
&mut self.any_addr_indexes,
|
||||
&mut self.addrs_data,
|
||||
@@ -490,6 +497,34 @@ impl Vecs {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Average amount (supply / utxo_count, supply / funded_addr_count) for `all` and per addr type.
|
||||
let all_m = &self.utxo_cohorts.all.metrics;
|
||||
self.addrs.avg_amount.all.compute(
|
||||
prices,
|
||||
&all_m.supply.total.sats.height,
|
||||
&all_m.outputs.unspent_count.height,
|
||||
&self.addrs.funded.all.height,
|
||||
starting_indexes.height,
|
||||
exit,
|
||||
)?;
|
||||
for ((ot, avg), (_, funded)) in self
|
||||
.addrs
|
||||
.avg_amount
|
||||
.by_addr_type
|
||||
.iter_mut()
|
||||
.zip(self.addrs.funded.by_addr_type.iter())
|
||||
{
|
||||
let type_m = &t.get(ot).metrics;
|
||||
avg.compute(
|
||||
prices,
|
||||
&type_m.supply.total.sats.height,
|
||||
&type_m.outputs.unspent_count.height,
|
||||
&funded.height,
|
||||
starting_indexes.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
// 6c. Compute total_addr_count = addr_count + empty_addr_count
|
||||
self.addrs.total.compute(
|
||||
starting_indexes.height,
|
||||
|
||||
@@ -267,7 +267,7 @@ impl<T: NumericValue + JsonSchema> PerBlockDistribution<T> {
|
||||
vec.push(zero);
|
||||
}
|
||||
} else {
|
||||
weighted.sort_unstable_by(|a, b| a.0.cmp(&b.0));
|
||||
weighted.sort_unstable_by_key(|a| a.0);
|
||||
|
||||
max.push(weighted.last().unwrap().0);
|
||||
pct90.push(get_weighted_percentile(&weighted, 0.90));
|
||||
|
||||
@@ -24,9 +24,9 @@ pub use derived::{
|
||||
RatioCents64, TimesSqrt,
|
||||
};
|
||||
pub use ratio::{
|
||||
RatioCentsBp32, RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDiffCentsBps32,
|
||||
RatioDiffDollarsBps32, RatioDiffF32Bps32, RatioDollarsBp16, RatioDollarsBp32,
|
||||
RatioDollarsBps32, RatioSatsBp16, RatioU64Bp16, RatioU64F32,
|
||||
RatioCentsBp16, RatioCentsBp32, RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32,
|
||||
RatioDiffCentsBps32, RatioDiffDollarsBps32, RatioDiffF32Bps32, RatioDollarsBp16,
|
||||
RatioDollarsBp32, RatioDollarsBps32, RatioSatsBp16, RatioU64Bp16, RatioU64F32,
|
||||
};
|
||||
pub use specialized::{
|
||||
BlockCountTarget1m, BlockCountTarget1w, BlockCountTarget1y, BlockCountTarget24h,
|
||||
|
||||
@@ -43,6 +43,19 @@ impl BinaryTransform<Cents, Cents, BasisPoints32> for RatioCentsBp32 {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RatioCentsBp16;
|
||||
|
||||
impl BinaryTransform<Cents, Cents, BasisPoints16> for RatioCentsBp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Cents, denominator: Cents) -> BasisPoints16 {
|
||||
if denominator == Cents::ZERO {
|
||||
BasisPoints16::ZERO
|
||||
} else {
|
||||
BasisPoints16::from(numerator.inner() as f64 / denominator.inner() as f64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RatioDollarsBp16;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPoints16> for RatioDollarsBp16 {
|
||||
|
||||
@@ -17,6 +17,8 @@ use super::{
|
||||
WindowStartVec, Windows,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::AvgAmountMetrics;
|
||||
|
||||
/// `all` aggregate plus per-`AddrType` breakdown.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct WithAddrTypes<T> {
|
||||
@@ -246,6 +248,42 @@ impl WithAddrTypes<AmountPerBlock> {
|
||||
}
|
||||
}
|
||||
|
||||
impl WithAddrTypes<AvgAmountMetrics> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let all = AvgAmountMetrics::forced_import(db, "", version, indexes)?;
|
||||
let by_addr_type = ByAddrType::new_with_name(|type_name| {
|
||||
AvgAmountMetrics::forced_import(db, type_name, version, indexes)
|
||||
})?;
|
||||
Ok(Self { all, by_addr_type })
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.all.collect_vecs_mut();
|
||||
for v in self.by_addr_type.values_mut() {
|
||||
vecs.extend(v.collect_vecs_mut());
|
||||
}
|
||||
vecs
|
||||
}
|
||||
|
||||
pub(crate) fn par_iter_height_mut(
|
||||
&mut self,
|
||||
) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
|
||||
self.collect_vecs_mut().into_par_iter()
|
||||
}
|
||||
|
||||
pub(crate) fn reset_height(&mut self) -> Result<()> {
|
||||
self.all.reset_height()?;
|
||||
for v in self.by_addr_type.values_mut() {
|
||||
v.reset_height()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BpsType> WithAddrTypes<PercentPerBlock<B>> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
|
||||
Reference in New Issue
Block a user