mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snapshot
This commit is contained in:
@@ -16,12 +16,12 @@ impl Vecs {
|
||||
) -> Result<()> {
|
||||
self.inflation_rate.bps.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&activity.liveliness.height,
|
||||
&activity.ratio.height,
|
||||
&supply.inflation_rate.bps.height,
|
||||
|(h, liveliness, inflation, ..)| {
|
||||
|(h, a2vr, inflation, ..)| {
|
||||
(
|
||||
h,
|
||||
BasisPointsSigned32::from(f64::from(liveliness) * f64::from(inflation)),
|
||||
BasisPointsSigned32::from(f64::from(a2vr) * f64::from(inflation)),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
|
||||
@@ -18,7 +18,7 @@ impl Vecs {
|
||||
inflation_rate: PercentPerBlock::forced_import(
|
||||
db,
|
||||
"cointime_adj_inflation_rate",
|
||||
version,
|
||||
version + Version::ONE,
|
||||
indexes,
|
||||
)?,
|
||||
tx_velocity_native: PerBlock::forced_import(
|
||||
|
||||
@@ -166,6 +166,7 @@ impl DynCohortVecs for AddrCohortVecs {
|
||||
.push(state.addr_count.into());
|
||||
self.metrics.supply.push_state(&state.inner);
|
||||
self.metrics.outputs.push_state(&state.inner);
|
||||
self.metrics.activity.push_state(&state.inner);
|
||||
self.metrics.realized.push_state(&state.inner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,8 +540,7 @@ impl UTXOCohorts<Rw> {
|
||||
.age_range
|
||||
.under_1h
|
||||
.metrics
|
||||
.realized
|
||||
.minimal
|
||||
.activity
|
||||
.transfer_volume
|
||||
.base
|
||||
.cents
|
||||
|
||||
@@ -39,6 +39,7 @@ impl DynCohortVecs for UTXOCohortVecs<MinimalCohortMetrics> {
|
||||
if let Some(state) = self.state.as_ref() {
|
||||
self.metrics.supply.push_state(state);
|
||||
self.metrics.outputs.push_state(state);
|
||||
self.metrics.activity.push_state(state);
|
||||
self.metrics.realized.push_state(state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ impl DynCohortVecs for UTXOCohortVecs<TypeCohortMetrics> {
|
||||
if let Some(state) = self.state.as_ref() {
|
||||
self.metrics.supply.push_state(state);
|
||||
self.metrics.outputs.push_state(state);
|
||||
self.metrics.activity.push_state(state);
|
||||
self.metrics.realized.push_state(state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Indexes, StoredF64, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
@@ -9,9 +10,15 @@ use crate::{
|
||||
prices,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
use super::ActivityMinimal;
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct ActivityCore<M: StorageMode = Rw> {
|
||||
pub transfer_volume: AmountPerBlockCumulativeWithSums<M>,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub minimal: ActivityMinimal<M>,
|
||||
|
||||
pub coindays_destroyed: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
#[traversable(wrap = "transfer_volume", rename = "in_profit")]
|
||||
pub transfer_volume_in_profit: AmountPerBlockCumulativeWithSums<M>,
|
||||
@@ -23,7 +30,7 @@ impl ActivityCore {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v1 = Version::ONE;
|
||||
Ok(Self {
|
||||
transfer_volume: cfg.import("transfer_volume", v1)?,
|
||||
minimal: ActivityMinimal::forced_import(cfg)?,
|
||||
coindays_destroyed: cfg.import("coindays_destroyed", v1)?,
|
||||
transfer_volume_in_profit: cfg.import("transfer_volume_in_profit", v1)?,
|
||||
transfer_volume_in_loss: cfg.import("transfer_volume_in_loss", v1)?,
|
||||
@@ -31,11 +38,8 @@ impl ActivityCore {
|
||||
}
|
||||
|
||||
pub(crate) fn min_len(&self) -> usize {
|
||||
self.transfer_volume
|
||||
.base
|
||||
.sats
|
||||
.height
|
||||
.len()
|
||||
self.minimal
|
||||
.min_len()
|
||||
.min(self.coindays_destroyed.base.height.len())
|
||||
.min(self.transfer_volume_in_profit.base.sats.height.len())
|
||||
.min(self.transfer_volume_in_loss.base.sats.height.len())
|
||||
@@ -46,7 +50,7 @@ impl ActivityCore {
|
||||
&mut self,
|
||||
state: &CohortState<impl RealizedOps, impl CostBasisOps>,
|
||||
) {
|
||||
self.transfer_volume.base.sats.height.push(state.sent);
|
||||
self.minimal.push_state(state);
|
||||
self.coindays_destroyed.base.height.push(
|
||||
StoredF64::from(Bitcoin::from(state.satdays_destroyed)),
|
||||
);
|
||||
@@ -63,15 +67,13 @@ impl ActivityCore {
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.transfer_volume.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.transfer_volume.base.cents.height,
|
||||
&mut self.coindays_destroyed.base.height,
|
||||
&mut self.transfer_volume_in_profit.base.sats.height,
|
||||
&mut self.transfer_volume_in_profit.base.cents.height,
|
||||
&mut self.transfer_volume_in_loss.base.sats.height,
|
||||
&mut self.transfer_volume_in_loss.base.cents.height,
|
||||
]
|
||||
let mut vecs = self.minimal.collect_vecs_mut();
|
||||
vecs.push(&mut self.coindays_destroyed.base.height);
|
||||
vecs.push(&mut self.transfer_volume_in_profit.base.sats.height);
|
||||
vecs.push(&mut self.transfer_volume_in_profit.base.cents.height);
|
||||
vecs.push(&mut self.transfer_volume_in_loss.base.sats.height);
|
||||
vecs.push(&mut self.transfer_volume_in_loss.base.cents.height);
|
||||
vecs
|
||||
}
|
||||
|
||||
pub(crate) fn validate_computed_versions(&mut self, _base_version: Version) -> Result<()> {
|
||||
@@ -84,14 +86,9 @@ impl ActivityCore {
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.transfer_volume.base.sats.height.compute_sum_of_others(
|
||||
starting_indexes.height,
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| &v.transfer_volume.base.sats.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
let minimal_refs: Vec<&ActivityMinimal> = others.iter().map(|o| &o.minimal).collect();
|
||||
self.minimal
|
||||
.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; transfer_volume_in_profit.base.sats.height);
|
||||
@@ -106,8 +103,8 @@ impl ActivityCore {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.transfer_volume
|
||||
.compute_rest(starting_indexes.height, prices, exit)?;
|
||||
self.minimal
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.coindays_destroyed
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
Ok(())
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Indexes, StoredF32, StoredF64, Version};
|
||||
use brk_types::{Indexes, StoredF32, StoredF64, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, Exit, ReadableCloneableVec, Rw, StorageMode};
|
||||
|
||||
use crate::internal::{Identity, LazyPerBlock, PerBlock};
|
||||
use crate::internal::{Identity, LazyPerBlock, PerBlock, Windows};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
@@ -22,7 +22,7 @@ pub struct ActivityFull<M: StorageMode = Rw> {
|
||||
|
||||
pub coinyears_destroyed: LazyPerBlock<StoredF64, StoredF64>,
|
||||
|
||||
pub dormancy: PerBlock<StoredF32, M>,
|
||||
pub dormancy: Windows<PerBlock<StoredF32, M>>,
|
||||
}
|
||||
|
||||
impl ActivityFull {
|
||||
@@ -37,10 +37,19 @@ impl ActivityFull {
|
||||
cfg.indexes,
|
||||
);
|
||||
|
||||
let dormancy = Windows::try_from_fn(|suffix| {
|
||||
PerBlock::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name(&format!("dormancy_{suffix}")),
|
||||
cfg.version + v1,
|
||||
cfg.indexes,
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
inner,
|
||||
coinyears_destroyed,
|
||||
dormancy: cfg.import("dormancy", v1)?,
|
||||
dormancy,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -58,7 +67,9 @@ impl ActivityFull {
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.inner.collect_vecs_mut();
|
||||
vecs.push(&mut self.dormancy.height);
|
||||
for d in self.dormancy.as_mut_array() {
|
||||
vecs.push(&mut d.height);
|
||||
}
|
||||
vecs
|
||||
}
|
||||
|
||||
@@ -86,20 +97,28 @@ impl ActivityFull {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.dormancy.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.inner.coindays_destroyed.base.height,
|
||||
&self.inner.transfer_volume.base.sats.height,
|
||||
|(i, cdd, sent_sats, ..)| {
|
||||
let sent_btc = f64::from(Bitcoin::from(sent_sats));
|
||||
if sent_btc == 0.0 {
|
||||
(i, StoredF32::from(0.0f32))
|
||||
} else {
|
||||
(i, StoredF32::from((f64::from(cdd) / sent_btc) as f32))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
for ((dormancy, cdd_sum), tv_sum) in self
|
||||
.dormancy
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.inner.coindays_destroyed.sum.as_array())
|
||||
.zip(self.inner.minimal.transfer_volume.sum.0.as_array())
|
||||
{
|
||||
dormancy.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&cdd_sum.height,
|
||||
&tv_sum.btc.height,
|
||||
|(i, rolling_cdd, rolling_btc, ..)| {
|
||||
let btc = f64::from(rolling_btc);
|
||||
if btc == 0.0 {
|
||||
(i, StoredF32::from(0.0f32))
|
||||
} else {
|
||||
(i, StoredF32::from((f64::from(rolling_cdd) / btc) as f32))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Indexes, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
internal::AmountPerBlockCumulativeWithSums,
|
||||
prices,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct ActivityMinimal<M: StorageMode = Rw> {
|
||||
pub transfer_volume: AmountPerBlockCumulativeWithSums<M>,
|
||||
}
|
||||
|
||||
impl ActivityMinimal {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v1 = Version::ONE;
|
||||
Ok(Self {
|
||||
transfer_volume: cfg.import("transfer_volume", v1)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_len(&self) -> usize {
|
||||
self.transfer_volume
|
||||
.base
|
||||
.sats
|
||||
.height
|
||||
.len()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(
|
||||
&mut self,
|
||||
state: &CohortState<impl RealizedOps, impl CostBasisOps>,
|
||||
) {
|
||||
self.transfer_volume.base.sats.height.push(state.sent);
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.transfer_volume.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.transfer_volume.base.cents.height,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.transfer_volume.base.sats.height.compute_sum_of_others(
|
||||
starting_indexes.height,
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| &v.transfer_volume.base.sats.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.transfer_volume
|
||||
.compute_rest(starting_indexes.height, prices, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
mod core;
|
||||
mod full;
|
||||
mod minimal;
|
||||
|
||||
pub use self::core::ActivityCore;
|
||||
pub use full::ActivityFull;
|
||||
pub use minimal::ActivityMinimal;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_types::{Indexes, Version};
|
||||
|
||||
@@ -116,6 +116,7 @@ impl AllCohortMetrics {
|
||||
starting_indexes,
|
||||
&self.supply.total.btc.height,
|
||||
height_to_market_cap,
|
||||
&self.activity.transfer_volume,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -128,7 +129,7 @@ impl AllCohortMetrics {
|
||||
|
||||
self.asopr.compute_rest_part2(
|
||||
starting_indexes,
|
||||
&self.realized.minimal.transfer_volume.base.cents.height,
|
||||
&self.activity.transfer_volume.base.cents.height,
|
||||
&self.realized.core.sopr.value_destroyed.base.height,
|
||||
under_1h_value_created,
|
||||
under_1h_value_destroyed,
|
||||
|
||||
@@ -75,6 +75,7 @@ impl BasicCohortMetrics {
|
||||
prices,
|
||||
starting_indexes,
|
||||
&self.supply.total.btc.height,
|
||||
&self.activity.transfer_volume.sum._24h.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ impl CoreCohortMetrics {
|
||||
vecs
|
||||
}
|
||||
|
||||
/// Aggregate Core-tier fields from CohortMetricsBase sources (e.g. age_range → under_age/over_age).
|
||||
/// Aggregate Core-tier fields from CohortMetricsBase sources (e.g. age_range -> under_age/over_age).
|
||||
pub(crate) fn compute_from_base_sources<T: CohortMetricsBase>(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
@@ -114,7 +114,7 @@ impl CoreCohortMetrics {
|
||||
.compute_sent_profitability(prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.unrealized.compute_rest(starting_indexes, exit)?;
|
||||
|
||||
@@ -132,6 +132,7 @@ impl CoreCohortMetrics {
|
||||
prices,
|
||||
starting_indexes,
|
||||
&self.supply.total.btc.height,
|
||||
&self.activity.transfer_volume.sum._24h.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ impl ExtendedCohortMetrics {
|
||||
starting_indexes,
|
||||
&self.supply.total.btc.height,
|
||||
height_to_market_cap,
|
||||
&self.activity.transfer_volume,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ impl ExtendedAdjustedCohortMetrics {
|
||||
|
||||
self.asopr.compute_rest_part2(
|
||||
starting_indexes,
|
||||
&self.inner.realized.minimal.transfer_volume.base.cents.height,
|
||||
&self.inner.activity.transfer_volume.base.cents.height,
|
||||
&self.inner.realized.core.sopr.value_destroyed.base.height,
|
||||
under_1h_value_created,
|
||||
under_1h_value_destroyed,
|
||||
|
||||
@@ -6,7 +6,7 @@ use vecdb::{AnyStoredVec, Exit, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
distribution::metrics::{
|
||||
ImportConfig, OutputsBase, RealizedMinimal, SupplyBase, UnrealizedMinimal,
|
||||
ActivityMinimal, ImportConfig, OutputsBase, RealizedMinimal, SupplyBase, UnrealizedMinimal,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -21,6 +21,7 @@ pub struct MinimalCohortMetrics<M: StorageMode = Rw> {
|
||||
pub filter: Filter,
|
||||
pub supply: Box<SupplyBase<M>>,
|
||||
pub outputs: Box<OutputsBase<M>>,
|
||||
pub activity: Box<ActivityMinimal<M>>,
|
||||
pub realized: Box<RealizedMinimal<M>>,
|
||||
pub unrealized: Box<UnrealizedMinimal<M>>,
|
||||
}
|
||||
@@ -31,6 +32,7 @@ impl MinimalCohortMetrics {
|
||||
filter: cfg.filter.clone(),
|
||||
supply: Box::new(SupplyBase::forced_import(cfg)?),
|
||||
outputs: Box::new(OutputsBase::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityMinimal::forced_import(cfg)?),
|
||||
realized: Box::new(RealizedMinimal::forced_import(cfg)?),
|
||||
unrealized: Box::new(UnrealizedMinimal::forced_import(cfg)?),
|
||||
})
|
||||
@@ -40,6 +42,7 @@ impl MinimalCohortMetrics {
|
||||
self.supply
|
||||
.min_len()
|
||||
.min(self.outputs.min_len())
|
||||
.min(self.activity.min_len())
|
||||
.min(self.realized.min_stateful_len())
|
||||
}
|
||||
|
||||
@@ -47,6 +50,7 @@ impl MinimalCohortMetrics {
|
||||
let mut vecs: Vec<&mut dyn AnyStoredVec> = Vec::new();
|
||||
vecs.extend(self.supply.collect_vecs_mut());
|
||||
vecs.extend(self.outputs.collect_vecs_mut());
|
||||
vecs.extend(self.activity.collect_vecs_mut());
|
||||
vecs.extend(self.realized.collect_vecs_mut());
|
||||
vecs
|
||||
}
|
||||
@@ -71,6 +75,14 @@ impl MinimalCohortMetrics {
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.activity.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| v.activity.as_ref())
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.realized.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others
|
||||
@@ -89,8 +101,10 @@ impl MinimalCohortMetrics {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.supply.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized
|
||||
self.activity
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use vecdb::{AnyStoredVec, Exit, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
distribution::metrics::{
|
||||
ImportConfig, OutputsBase, RealizedMinimal, SupplyCore, UnrealizedBasic,
|
||||
ActivityMinimal, ImportConfig, OutputsBase, RealizedMinimal, SupplyCore, UnrealizedBasic,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -20,6 +20,7 @@ pub struct TypeCohortMetrics<M: StorageMode = Rw> {
|
||||
pub filter: Filter,
|
||||
pub supply: Box<SupplyCore<M>>,
|
||||
pub outputs: Box<OutputsBase<M>>,
|
||||
pub activity: Box<ActivityMinimal<M>>,
|
||||
pub realized: Box<RealizedMinimal<M>>,
|
||||
pub unrealized: Box<UnrealizedBasic<M>>,
|
||||
}
|
||||
@@ -30,6 +31,7 @@ impl TypeCohortMetrics {
|
||||
filter: cfg.filter.clone(),
|
||||
supply: Box::new(SupplyCore::forced_import(cfg)?),
|
||||
outputs: Box::new(OutputsBase::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityMinimal::forced_import(cfg)?),
|
||||
realized: Box::new(RealizedMinimal::forced_import(cfg)?),
|
||||
unrealized: Box::new(UnrealizedBasic::forced_import(cfg)?),
|
||||
})
|
||||
@@ -39,6 +41,7 @@ impl TypeCohortMetrics {
|
||||
self.supply
|
||||
.min_len()
|
||||
.min(self.outputs.min_len())
|
||||
.min(self.activity.min_len())
|
||||
.min(self.realized.min_stateful_len())
|
||||
.min(self.unrealized.min_stateful_len())
|
||||
}
|
||||
@@ -47,6 +50,7 @@ impl TypeCohortMetrics {
|
||||
let mut vecs: Vec<&mut dyn AnyStoredVec> = Vec::new();
|
||||
vecs.extend(self.supply.collect_vecs_mut());
|
||||
vecs.extend(self.outputs.collect_vecs_mut());
|
||||
vecs.extend(self.activity.collect_vecs_mut());
|
||||
vecs.extend(self.realized.collect_vecs_mut());
|
||||
vecs.extend(self.unrealized.collect_vecs_mut());
|
||||
vecs
|
||||
@@ -59,8 +63,10 @@ impl TypeCohortMetrics {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.supply.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized
|
||||
self.activity
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ mod relative;
|
||||
mod supply;
|
||||
mod unrealized;
|
||||
|
||||
pub use activity::{ActivityCore, ActivityFull, ActivityLike};
|
||||
pub use activity::{ActivityCore, ActivityFull, ActivityLike, ActivityMinimal};
|
||||
pub use cohort::{
|
||||
AllCohortMetrics, BasicCohortMetrics, CoreCohortMetrics, ExtendedAdjustedCohortMetrics,
|
||||
ExtendedCohortMetrics, MinimalCohortMetrics, TypeCohortMetrics,
|
||||
@@ -228,7 +228,7 @@ pub trait CohortMetricsBase:
|
||||
.compute_sent_profitability(prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized_mut()
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.unrealized_mut()
|
||||
.compute_rest(prices, starting_indexes, exit)?;
|
||||
|
||||
@@ -132,12 +132,11 @@ impl RealizedCore {
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.minimal
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.sopr
|
||||
.value_destroyed
|
||||
@@ -164,6 +163,7 @@ impl RealizedCore {
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
transfer_volume_sum_24h_cents: &impl ReadableVec<Height, Cents>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.minimal
|
||||
@@ -177,7 +177,7 @@ impl RealizedCore {
|
||||
._24h
|
||||
.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&self.minimal.transfer_volume.sum._24h.cents.height,
|
||||
transfer_volume_sum_24h_cents,
|
||||
&self.sopr.value_destroyed.sum._24h.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -5,18 +5,14 @@ use brk_types::{
|
||||
Dollars, Height, Indexes, StoredF64, Version,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, BytesVec, Exit, ReadableVec, Rw, StorageMode,
|
||||
WritableVec,
|
||||
};
|
||||
use vecdb::{AnyStoredVec, AnyVec, BytesVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
blocks,
|
||||
distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState},
|
||||
distribution::state::{CohortState, CostBasisData, RealizedState, WithCapital},
|
||||
internal::{
|
||||
FiatPerBlockCumulativeWithSums,
|
||||
PercentPerBlock, PercentRollingWindows,
|
||||
PriceWithRatioExtendedPerBlock, RatioCents64, RatioCentsBp32,
|
||||
AmountPerBlockCumulativeWithSums, FiatPerBlockCumulativeWithSums, PercentPerBlock,
|
||||
PercentRollingWindows, PriceWithRatioExtendedPerBlock, RatioCents64, RatioCentsBp32,
|
||||
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDollarsBp32,
|
||||
RatioPerBlockPercentiles, RatioPerBlockStdDevBands, RatioSma, RollingWindows,
|
||||
RollingWindowsFrom1w,
|
||||
@@ -119,12 +115,9 @@ impl RealizedFull {
|
||||
|
||||
// Net PnL
|
||||
let net_pnl = RealizedNetPnl {
|
||||
to_rcap: cfg
|
||||
.import("net_realized_pnl_to_rcap", Version::new(2))?,
|
||||
change_1m_to_rcap: cfg
|
||||
.import("net_pnl_change_1m_to_rcap", Version::new(4))?,
|
||||
change_1m_to_mcap: cfg
|
||||
.import("net_pnl_change_1m_to_mcap", Version::new(4))?,
|
||||
to_rcap: cfg.import("net_realized_pnl_to_rcap", Version::new(2))?,
|
||||
change_1m_to_rcap: cfg.import("net_pnl_change_1m_to_rcap", Version::new(4))?,
|
||||
change_1m_to_mcap: cfg.import("net_pnl_change_1m_to_mcap", Version::new(4))?,
|
||||
};
|
||||
|
||||
// SOPR
|
||||
@@ -135,8 +128,7 @@ impl RealizedFull {
|
||||
// Peak regret
|
||||
let peak_regret = RealizedPeakRegret {
|
||||
value: cfg.import("realized_peak_regret", Version::new(2))?,
|
||||
to_rcap: cfg
|
||||
.import("realized_peak_regret_to_rcap", Version::new(2))?,
|
||||
to_rcap: cfg.import("realized_peak_regret_to_rcap", Version::new(2))?,
|
||||
};
|
||||
|
||||
// Investor
|
||||
@@ -184,7 +176,11 @@ impl RealizedFull {
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
self.investor.price.cents.height.len()
|
||||
self.investor
|
||||
.price
|
||||
.cents
|
||||
.height
|
||||
.len()
|
||||
.min(self.cap_raw.len())
|
||||
.min(self.investor.cap_raw.len())
|
||||
.min(self.peak_regret.value.base.cents.height.len())
|
||||
@@ -201,8 +197,7 @@ impl RealizedFull {
|
||||
.cents
|
||||
.height
|
||||
.push(state.realized.investor_price());
|
||||
self.cap_raw
|
||||
.push(state.realized.cap_raw());
|
||||
self.cap_raw.push(state.realized.cap_raw());
|
||||
self.investor
|
||||
.cap_raw
|
||||
.push(state.realized.investor_cap_raw());
|
||||
@@ -236,15 +231,9 @@ impl RealizedFull {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_accum(
|
||||
&mut self,
|
||||
accum: &RealizedFullAccum,
|
||||
) {
|
||||
self.cap_raw
|
||||
.push(accum.cap_raw);
|
||||
self.investor
|
||||
.cap_raw
|
||||
.push(accum.investor_cap_raw);
|
||||
pub(crate) fn push_accum(&mut self, accum: &RealizedFullAccum) {
|
||||
self.cap_raw.push(accum.cap_raw);
|
||||
self.investor.cap_raw.push(accum.investor_cap_raw);
|
||||
|
||||
let investor_price = {
|
||||
let cap = accum.cap_raw.as_u128();
|
||||
@@ -254,11 +243,7 @@ impl RealizedFull {
|
||||
Cents::new((accum.investor_cap_raw / cap) as u64)
|
||||
}
|
||||
};
|
||||
self.investor
|
||||
.price
|
||||
.cents
|
||||
.height
|
||||
.push(investor_price);
|
||||
self.investor.price.cents.height.push(investor_price);
|
||||
|
||||
self.peak_regret
|
||||
.value
|
||||
@@ -270,12 +255,10 @@ impl RealizedFull {
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.core.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.peak_regret
|
||||
.value
|
||||
@@ -283,6 +266,7 @@ impl RealizedFull {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
@@ -290,22 +274,24 @@ impl RealizedFull {
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
activity_transfer_volume: &AmountPerBlockCumulativeWithSums,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core.compute_rest_part2(
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_supply,
|
||||
&activity_transfer_volume.sum._24h.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// SOPR ratios from lazy rolling sums
|
||||
// SOPR ratios from lazy rolling sums (1w, 1m, 1y)
|
||||
for ((sopr, vc), vd) in self
|
||||
.sopr
|
||||
.ratio_extended
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.core.minimal.transfer_volume.sum.0.as_array()[1..].iter())
|
||||
.zip(activity_transfer_volume.sum.0.as_array()[1..].iter())
|
||||
.zip(self.core.sopr.value_destroyed.sum.as_array()[1..].iter())
|
||||
{
|
||||
sopr.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
@@ -349,8 +335,7 @@ impl RealizedFull {
|
||||
&self.core.minimal.loss.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.gross_pnl
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.gross_pnl.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
// Net PnL 1m change relative to rcap and mcap
|
||||
self.net_pnl
|
||||
@@ -381,11 +366,9 @@ impl RealizedFull {
|
||||
)?;
|
||||
|
||||
// Investor price ratio, percentiles and bands
|
||||
self.investor.price.compute_rest(
|
||||
prices,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
self.investor
|
||||
.price
|
||||
.compute_rest(prices, starting_indexes, exit)?;
|
||||
|
||||
// Sell-side risk ratios
|
||||
for (ssrr, rv) in self
|
||||
|
||||
@@ -11,7 +11,7 @@ use vecdb::{
|
||||
use crate::{
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
internal::{
|
||||
AmountPerBlockCumulativeWithSums, FiatPerBlockCumulativeWithSums,
|
||||
FiatPerBlockCumulativeWithSums,
|
||||
FiatPerBlockWithDeltas, Identity, LazyPerBlock, PriceWithRatioPerBlock,
|
||||
},
|
||||
prices,
|
||||
@@ -26,8 +26,6 @@ pub struct RealizedMinimal<M: StorageMode = Rw> {
|
||||
pub loss: FiatPerBlockCumulativeWithSums<Cents, M>,
|
||||
pub price: PriceWithRatioPerBlock<M>,
|
||||
pub mvrv: LazyPerBlock<StoredF32>,
|
||||
|
||||
pub transfer_volume: AmountPerBlockCumulativeWithSums<M>,
|
||||
}
|
||||
|
||||
impl RealizedMinimal {
|
||||
@@ -50,21 +48,12 @@ impl RealizedMinimal {
|
||||
&price.ratio,
|
||||
);
|
||||
|
||||
let transfer_volume = AmountPerBlockCumulativeWithSums::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("transfer_volume"),
|
||||
cfg.version,
|
||||
cfg.indexes,
|
||||
cfg.cached_starts,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
cap,
|
||||
profit: cfg.import("realized_profit", v1)?,
|
||||
loss: cfg.import("realized_loss", v1)?,
|
||||
price,
|
||||
mvrv,
|
||||
transfer_volume,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -75,7 +64,6 @@ impl RealizedMinimal {
|
||||
.len()
|
||||
.min(self.profit.base.cents.height.len())
|
||||
.min(self.loss.base.cents.height.len())
|
||||
.min(self.transfer_volume.base.sats.height.len())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -83,7 +71,6 @@ impl RealizedMinimal {
|
||||
self.cap.cents.height.push(state.realized.cap());
|
||||
self.profit.base.cents.height.push(state.realized.profit());
|
||||
self.loss.base.cents.height.push(state.realized.loss());
|
||||
self.transfer_volume.base.sats.height.push(state.sent);
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
@@ -91,7 +78,6 @@ impl RealizedMinimal {
|
||||
&mut self.cap.cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.profit.base.cents.height,
|
||||
&mut self.loss.base.cents.height,
|
||||
&mut self.transfer_volume.base.sats.height,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -104,20 +90,16 @@ impl RealizedMinimal {
|
||||
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; loss.base.cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; transfer_volume.base.sats.height);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.profit.compute_rest(starting_indexes.height, exit)?;
|
||||
self.loss.compute_rest(starting_indexes.height, exit)?;
|
||||
self.transfer_volume
|
||||
.compute_rest(starting_indexes.height, prices, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ use brk_error::Result;
|
||||
use brk_types::Indexes;
|
||||
use vecdb::Exit;
|
||||
|
||||
use crate::{distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState}, prices};
|
||||
use crate::distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState};
|
||||
|
||||
pub trait RealizedLike: Send + Sync {
|
||||
fn as_core(&self) -> &RealizedCore;
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore;
|
||||
fn min_stateful_len(&self) -> usize;
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>);
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
@@ -36,8 +36,8 @@ impl RealizedLike for RealizedCore {
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.push_state(state)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(prices, starting_indexes, exit)
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(starting_indexes, exit)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&RealizedCore], exit: &Exit) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
@@ -52,8 +52,8 @@ impl RealizedLike for RealizedFull {
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.push_state(state)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(prices, starting_indexes, exit)
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(starting_indexes, exit)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&RealizedCore], exit: &Exit) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
|
||||
@@ -71,7 +71,6 @@ impl RealizedOps for MinimalRealizedState {
|
||||
Cents::new((self.loss_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[inline]
|
||||
fn value_destroyed(&self) -> Cents {
|
||||
if self.value_destroyed_raw == 0 {
|
||||
|
||||
@@ -128,7 +128,7 @@ impl Vecs {
|
||||
.height
|
||||
.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&all_activity.dormancy.height,
|
||||
&all_activity.dormancy._24h.height,
|
||||
supply_total_sats,
|
||||
|(i, dormancy, supply_sats, ..)| {
|
||||
let supply = f64::from(Bitcoin::from(supply_sats));
|
||||
@@ -164,7 +164,7 @@ impl Vecs {
|
||||
self.dormancy.flow.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
supply_total_sats,
|
||||
&all_activity.dormancy.height,
|
||||
&all_activity.dormancy._24h.height,
|
||||
|(i, supply_sats, dormancy, ..)| {
|
||||
let d = f64::from(dormancy);
|
||||
if d == 0.0 {
|
||||
|
||||
Reference in New Issue
Block a user