mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-23 22:29:59 -07:00
global: snapshot
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,68 +1,37 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Height, Indexes, Sats, StoredF64, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use brk_types::{Height, Indexes, Sats, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::internal::ComputedFromHeightCumulativeSum;
|
||||
use crate::internal::{RollingEmas2w, ValueFromHeightCumulative};
|
||||
|
||||
use crate::{blocks, distribution::metrics::ImportConfig, prices};
|
||||
|
||||
use super::ActivityCore;
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct ActivityMetrics<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub core: ActivityCore<M>,
|
||||
|
||||
pub coinblocks_destroyed: ComputedFromHeightCumulativeSum<StoredF64, M>,
|
||||
pub coindays_destroyed: ComputedFromHeightCumulativeSum<StoredF64, M>,
|
||||
#[derive(Traversable)]
|
||||
pub struct ActivityBase<M: StorageMode = Rw> {
|
||||
pub sent: ValueFromHeightCumulative<M>,
|
||||
pub sent_ema: RollingEmas2w<M>,
|
||||
}
|
||||
|
||||
impl ActivityMetrics {
|
||||
impl ActivityBase {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
core: ActivityCore::forced_import(cfg)?,
|
||||
coinblocks_destroyed: cfg
|
||||
.import_cumulative_sum("coinblocks_destroyed", Version::ONE)?,
|
||||
coindays_destroyed: cfg.import_cumulative_sum("coindays_destroyed", Version::ONE)?,
|
||||
sent: cfg.import_value_cumulative("sent", Version::ZERO)?,
|
||||
sent_ema: cfg.import_emas_2w("sent", Version::ZERO)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_len(&self) -> usize {
|
||||
self.core
|
||||
.min_len()
|
||||
.min(self.coinblocks_destroyed.height.len())
|
||||
.min(self.coindays_destroyed.height.len())
|
||||
self.sent.base.sats.height.len()
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(
|
||||
&mut self,
|
||||
height: Height,
|
||||
sent: Sats,
|
||||
satblocks_destroyed: Sats,
|
||||
satdays_destroyed: Sats,
|
||||
) -> Result<()> {
|
||||
self.core.truncate_push(height, sent)?;
|
||||
self.coinblocks_destroyed.height.truncate_push(
|
||||
height,
|
||||
StoredF64::from(Bitcoin::from(satblocks_destroyed)),
|
||||
)?;
|
||||
self.coindays_destroyed.height.truncate_push(
|
||||
height,
|
||||
StoredF64::from(Bitcoin::from(satdays_destroyed)),
|
||||
)?;
|
||||
pub(crate) fn truncate_push(&mut self, height: Height, sent: Sats) -> Result<()> {
|
||||
self.sent.base.sats.height.truncate_push(height, sent)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.core.sent.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.coinblocks_destroyed.height as &mut dyn AnyStoredVec,
|
||||
&mut self.coindays_destroyed.height as &mut dyn AnyStoredVec,
|
||||
]
|
||||
vec![&mut self.sent.base.sats.height as &mut dyn AnyStoredVec]
|
||||
}
|
||||
|
||||
pub(crate) fn validate_computed_versions(&mut self, _base_version: Version) -> Result<()> {
|
||||
@@ -75,12 +44,14 @@ impl ActivityMetrics {
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let core_refs: Vec<&ActivityCore> = others.iter().map(|o| &o.core).collect();
|
||||
self.core
|
||||
.compute_from_stateful(starting_indexes, &core_refs, exit)?;
|
||||
|
||||
sum_others!(self, starting_indexes, others, exit; coinblocks_destroyed.height);
|
||||
sum_others!(self, starting_indexes, others, exit; coindays_destroyed.height);
|
||||
self.sent.base.sats.height.compute_sum_of_others(
|
||||
starting_indexes.height,
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| &v.sent.base.sats.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -91,16 +62,16 @@ impl ActivityMetrics {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core
|
||||
.compute_rest_part1(blocks, prices, starting_indexes, exit)?;
|
||||
self.sent
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
|
||||
let window_starts = blocks.count.window_starts();
|
||||
|
||||
self.coinblocks_destroyed
|
||||
.compute_rest(starting_indexes.height, &window_starts, exit)?;
|
||||
|
||||
self.coindays_destroyed
|
||||
.compute_rest(starting_indexes.height, &window_starts, exit)?;
|
||||
self.sent_ema.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent.base.sats.height,
|
||||
&self.sent.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Indexes, Sats, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::internal::{RollingEmas2w, ValueFromHeightCumulative};
|
||||
|
||||
use crate::{blocks, distribution::metrics::ImportConfig, prices};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct ActivityCore<M: StorageMode = Rw> {
|
||||
pub sent: ValueFromHeightCumulative<M>,
|
||||
pub sent_ema: RollingEmas2w<M>,
|
||||
}
|
||||
|
||||
impl ActivityCore {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
sent: cfg.import_value_cumulative("sent", Version::ZERO)?,
|
||||
sent_ema: cfg.import_emas_2w("sent", Version::ZERO)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_len(&self) -> usize {
|
||||
self.sent.base.sats.height.len()
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(&mut self, height: Height, sent: Sats) -> Result<()> {
|
||||
self.sent.base.sats.height.truncate_push(height, sent)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![&mut self.sent.base.sats.height as &mut dyn AnyStoredVec]
|
||||
}
|
||||
|
||||
pub(crate) fn validate_computed_versions(&mut self, _base_version: Version) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.sent.base.sats.height.compute_sum_of_others(
|
||||
starting_indexes.height,
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| &v.sent.base.sats.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.sent
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
|
||||
self.sent_ema.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent.base.sats.height,
|
||||
&self.sent.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
107
crates/brk_computer/src/distribution/metrics/activity/full.rs
Normal file
107
crates/brk_computer/src/distribution/metrics/activity/full.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Height, Indexes, Sats, StoredF64, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::internal::ComputedFromHeightCumulativeSum;
|
||||
|
||||
use crate::{blocks, distribution::metrics::ImportConfig, prices};
|
||||
|
||||
use super::ActivityBase;
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct ActivityFull<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: ActivityBase<M>,
|
||||
|
||||
pub coinblocks_destroyed: ComputedFromHeightCumulativeSum<StoredF64, M>,
|
||||
pub coindays_destroyed: ComputedFromHeightCumulativeSum<StoredF64, M>,
|
||||
}
|
||||
|
||||
impl ActivityFull {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
base: ActivityBase::forced_import(cfg)?,
|
||||
coinblocks_destroyed: cfg
|
||||
.import_cumulative_sum("coinblocks_destroyed", Version::ONE)?,
|
||||
coindays_destroyed: cfg.import_cumulative_sum("coindays_destroyed", Version::ONE)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_len(&self) -> usize {
|
||||
self.base
|
||||
.min_len()
|
||||
.min(self.coinblocks_destroyed.height.len())
|
||||
.min(self.coindays_destroyed.height.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(
|
||||
&mut self,
|
||||
height: Height,
|
||||
sent: Sats,
|
||||
satblocks_destroyed: Sats,
|
||||
satdays_destroyed: Sats,
|
||||
) -> Result<()> {
|
||||
self.base.truncate_push(height, sent)?;
|
||||
self.coinblocks_destroyed.height.truncate_push(
|
||||
height,
|
||||
StoredF64::from(Bitcoin::from(satblocks_destroyed)),
|
||||
)?;
|
||||
self.coindays_destroyed.height.truncate_push(
|
||||
height,
|
||||
StoredF64::from(Bitcoin::from(satdays_destroyed)),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.base.sent.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.coinblocks_destroyed.height as &mut dyn AnyStoredVec,
|
||||
&mut self.coindays_destroyed.height as &mut dyn AnyStoredVec,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn validate_computed_versions(&mut self, _base_version: Version) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let core_refs: Vec<&ActivityBase> = others.iter().map(|o| &o.base).collect();
|
||||
self.base
|
||||
.compute_from_stateful(starting_indexes, &core_refs, exit)?;
|
||||
|
||||
sum_others!(self, starting_indexes, others, exit; coinblocks_destroyed.height);
|
||||
sum_others!(self, starting_indexes, others, exit; coindays_destroyed.height);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.base
|
||||
.compute_rest_part1(blocks, prices, starting_indexes, exit)?;
|
||||
|
||||
let window_starts = blocks.count.window_starts();
|
||||
|
||||
self.coinblocks_destroyed
|
||||
.compute_rest(starting_indexes.height, &window_starts, exit)?;
|
||||
|
||||
self.coindays_destroyed
|
||||
.compute_rest(starting_indexes.height, &window_starts, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
mod base;
|
||||
mod core;
|
||||
mod full;
|
||||
|
||||
pub use base::*;
|
||||
pub use core::*;
|
||||
pub use full::*;
|
||||
|
||||
@@ -9,8 +9,8 @@ use crate::{blocks, prices};
|
||||
use crate::internal::ComputedFromHeight;
|
||||
|
||||
use crate::distribution::metrics::{
|
||||
ActivityMetrics, CostBasisWithExtended, ImportConfig, OutputsMetrics, RealizedAdjusted,
|
||||
RealizedWithExtended, RelativeForAll, SupplyMetrics, UnrealizedFull,
|
||||
ActivityFull, CostBasisWithExtended, ImportConfig, OutputsMetrics, RealizedAdjusted,
|
||||
RealizedFull, RelativeForAll, SupplyMetrics, UnrealizedFull,
|
||||
};
|
||||
|
||||
/// All-cohort metrics: extended realized + adjusted (as composable add-on),
|
||||
@@ -22,8 +22,8 @@ pub struct AllCohortMetrics<M: StorageMode = Rw> {
|
||||
pub filter: Filter,
|
||||
pub supply: Box<SupplyMetrics<M>>,
|
||||
pub outputs: Box<OutputsMetrics<M>>,
|
||||
pub activity: Box<ActivityMetrics<M>>,
|
||||
pub realized: Box<RealizedWithExtended<M>>,
|
||||
pub activity: Box<ActivityFull<M>>,
|
||||
pub realized: Box<RealizedFull<M>>,
|
||||
pub cost_basis: Box<CostBasisWithExtended<M>>,
|
||||
pub unrealized: Box<UnrealizedFull<M>>,
|
||||
pub adjusted: Box<RealizedAdjusted<M>>,
|
||||
@@ -44,7 +44,7 @@ impl AllCohortMetrics {
|
||||
supply: SupplyMetrics,
|
||||
) -> Result<Self> {
|
||||
let unrealized = UnrealizedFull::forced_import(cfg)?;
|
||||
let realized = RealizedWithExtended::forced_import(cfg)?;
|
||||
let realized = RealizedFull::forced_import(cfg)?;
|
||||
let adjusted = RealizedAdjusted::forced_import(cfg)?;
|
||||
|
||||
let relative = RelativeForAll::forced_import(cfg)?;
|
||||
@@ -53,7 +53,7 @@ impl AllCohortMetrics {
|
||||
filter: cfg.filter.clone(),
|
||||
supply: Box::new(supply),
|
||||
outputs: Box::new(OutputsMetrics::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityMetrics::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityFull::forced_import(cfg)?),
|
||||
realized: Box::new(realized),
|
||||
cost_basis: Box::new(CostBasisWithExtended::forced_import(cfg)?),
|
||||
unrealized: Box::new(unrealized),
|
||||
@@ -97,7 +97,7 @@ impl AllCohortMetrics {
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
&self.unrealized,
|
||||
&self.realized.base,
|
||||
&self.realized,
|
||||
&self.supply.total.sats.height,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
|
||||
@@ -7,20 +7,20 @@ use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
use crate::{blocks, prices};
|
||||
|
||||
use crate::distribution::metrics::{
|
||||
ActivityMetrics, CostBasisBase, ImportConfig, OutputsMetrics, RealizedFull,
|
||||
ActivityFull, CostBasisBase, ImportConfig, OutputsMetrics, RealizedBase,
|
||||
RelativeWithRelToAll, SupplyMetrics, UnrealizedFull,
|
||||
};
|
||||
|
||||
/// Basic cohort metrics: no extensions, with relative (rel_to_all).
|
||||
/// Used by: epoch, year, type (spendable), amount, address cohorts.
|
||||
/// Used by: age_range cohorts.
|
||||
#[derive(Traversable)]
|
||||
pub struct BasicCohortMetrics<M: StorageMode = Rw> {
|
||||
#[traversable(skip)]
|
||||
pub filter: Filter,
|
||||
pub supply: Box<SupplyMetrics<M>>,
|
||||
pub outputs: Box<OutputsMetrics<M>>,
|
||||
pub activity: Box<ActivityMetrics<M>>,
|
||||
pub realized: Box<RealizedFull<M>>,
|
||||
pub activity: Box<ActivityFull<M>>,
|
||||
pub realized: Box<RealizedBase<M>>,
|
||||
pub cost_basis: Box<CostBasisBase<M>>,
|
||||
pub unrealized: Box<UnrealizedFull<M>>,
|
||||
pub relative: Box<RelativeWithRelToAll<M>>,
|
||||
@@ -32,7 +32,7 @@ impl BasicCohortMetrics {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let supply = SupplyMetrics::forced_import(cfg)?;
|
||||
let unrealized = UnrealizedFull::forced_import(cfg)?;
|
||||
let realized = RealizedFull::forced_import(cfg)?;
|
||||
let realized = RealizedBase::forced_import(cfg)?;
|
||||
|
||||
let relative = RelativeWithRelToAll::forced_import(cfg)?;
|
||||
|
||||
@@ -40,7 +40,7 @@ impl BasicCohortMetrics {
|
||||
filter: cfg.filter.clone(),
|
||||
supply: Box::new(supply),
|
||||
outputs: Box::new(OutputsMetrics::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityMetrics::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityFull::forced_import(cfg)?),
|
||||
realized: Box::new(realized),
|
||||
cost_basis: Box::new(CostBasisBase::forced_import(cfg)?),
|
||||
unrealized: Box::new(unrealized),
|
||||
@@ -62,7 +62,6 @@ impl BasicCohortMetrics {
|
||||
prices,
|
||||
starting_indexes,
|
||||
&self.supply.total.btc.height,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ use vecdb::{AnyStoredVec, Exit, ReadableVec, Rw, StorageMode};
|
||||
use crate::{blocks, prices};
|
||||
|
||||
use crate::distribution::metrics::{
|
||||
ActivityCore, CohortMetricsBase, RealizedCore, ImportConfig, OutputsMetrics,
|
||||
RelativeCompleteWithRelToAll, SupplyMetrics, UnrealizedComplete,
|
||||
ActivityBase, CohortMetricsBase, RealizedBase, ImportConfig, OutputsMetrics,
|
||||
RelativeBaseWithRelToAll, SupplyMetrics, UnrealizedBase,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
@@ -17,10 +17,10 @@ pub struct CoreCohortMetrics<M: StorageMode = Rw> {
|
||||
pub filter: Filter,
|
||||
pub supply: Box<SupplyMetrics<M>>,
|
||||
pub outputs: Box<OutputsMetrics<M>>,
|
||||
pub activity: Box<ActivityCore<M>>,
|
||||
pub realized: Box<RealizedCore<M>>,
|
||||
pub unrealized: Box<UnrealizedComplete<M>>,
|
||||
pub relative: Box<RelativeCompleteWithRelToAll<M>>,
|
||||
pub activity: Box<ActivityBase<M>>,
|
||||
pub realized: Box<RealizedBase<M>>,
|
||||
pub unrealized: Box<UnrealizedBase<M>>,
|
||||
pub relative: Box<RelativeBaseWithRelToAll<M>>,
|
||||
}
|
||||
|
||||
impl CoreCohortMetrics {
|
||||
@@ -29,10 +29,10 @@ impl CoreCohortMetrics {
|
||||
filter: cfg.filter.clone(),
|
||||
supply: Box::new(SupplyMetrics::forced_import(cfg)?),
|
||||
outputs: Box::new(OutputsMetrics::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityCore::forced_import(cfg)?),
|
||||
realized: Box::new(RealizedCore::forced_import(cfg)?),
|
||||
unrealized: Box::new(UnrealizedComplete::forced_import(cfg)?),
|
||||
relative: Box::new(RelativeCompleteWithRelToAll::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityBase::forced_import(cfg)?),
|
||||
realized: Box::new(RealizedBase::forced_import(cfg)?),
|
||||
unrealized: Box::new(UnrealizedBase::forced_import(cfg)?),
|
||||
relative: Box::new(RelativeBaseWithRelToAll::forced_import(cfg)?),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -80,17 +80,17 @@ impl CoreCohortMetrics {
|
||||
)?;
|
||||
self.activity.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| &v.activity().core).collect::<Vec<_>>(),
|
||||
&others.iter().map(|v| &v.activity().base).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.realized.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| &v.realized_full().core).collect::<Vec<_>>(),
|
||||
&others.iter().map(|v| v.realized_base()).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| &v.unrealized_full().complete).collect::<Vec<_>>(),
|
||||
&others.iter().map(|v| &v.unrealized_full().base).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -114,6 +114,12 @@ impl CoreCohortMetrics {
|
||||
self.activity
|
||||
.compute_rest_part1(blocks, prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized
|
||||
.sent_in_profit
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized
|
||||
.sent_in_loss
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ use crate::{blocks, prices};
|
||||
use crate::internal::ComputedFromHeight;
|
||||
|
||||
use crate::distribution::metrics::{
|
||||
ActivityMetrics, CostBasisWithExtended, ImportConfig, OutputsMetrics,
|
||||
RealizedWithExtended, RelativeWithExtended, SupplyMetrics, UnrealizedFull,
|
||||
ActivityFull, CostBasisWithExtended, ImportConfig, OutputsMetrics,
|
||||
RealizedFull, RelativeWithExtended, SupplyMetrics, UnrealizedFull,
|
||||
};
|
||||
|
||||
/// Cohort metrics with extended realized + extended cost basis (no adjusted).
|
||||
@@ -21,8 +21,8 @@ pub struct ExtendedCohortMetrics<M: StorageMode = Rw> {
|
||||
pub filter: Filter,
|
||||
pub supply: Box<SupplyMetrics<M>>,
|
||||
pub outputs: Box<OutputsMetrics<M>>,
|
||||
pub activity: Box<ActivityMetrics<M>>,
|
||||
pub realized: Box<RealizedWithExtended<M>>,
|
||||
pub activity: Box<ActivityFull<M>>,
|
||||
pub realized: Box<RealizedFull<M>>,
|
||||
pub cost_basis: Box<CostBasisWithExtended<M>>,
|
||||
pub unrealized: Box<UnrealizedFull<M>>,
|
||||
pub relative: Box<RelativeWithExtended<M>>,
|
||||
@@ -36,7 +36,7 @@ impl ExtendedCohortMetrics {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let supply = SupplyMetrics::forced_import(cfg)?;
|
||||
let unrealized = UnrealizedFull::forced_import(cfg)?;
|
||||
let realized = RealizedWithExtended::forced_import(cfg)?;
|
||||
let realized = RealizedFull::forced_import(cfg)?;
|
||||
|
||||
let relative = RelativeWithExtended::forced_import(cfg)?;
|
||||
|
||||
@@ -44,7 +44,7 @@ impl ExtendedCohortMetrics {
|
||||
filter: cfg.filter.clone(),
|
||||
supply: Box::new(supply),
|
||||
outputs: Box::new(OutputsMetrics::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityMetrics::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityFull::forced_import(cfg)?),
|
||||
realized: Box::new(realized),
|
||||
cost_basis: Box::new(CostBasisWithExtended::forced_import(cfg)?),
|
||||
unrealized: Box::new(unrealized),
|
||||
@@ -75,7 +75,7 @@ impl ExtendedCohortMetrics {
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
&self.unrealized,
|
||||
&self.realized.base,
|
||||
&self.realized,
|
||||
&self.supply.total.sats.height,
|
||||
height_to_market_cap,
|
||||
all_supply_sats,
|
||||
|
||||
@@ -2,36 +2,22 @@ use brk_cohort::Filter;
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints16, BasisPoints32, Bitcoin, Cents, Dollars, Height, Indexes, Sats, StoredF32,
|
||||
Version,
|
||||
BasisPoints16, Height, Indexes, Sats, Version,
|
||||
};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{blocks, prices};
|
||||
|
||||
use crate::internal::{
|
||||
CentsUnsignedToDollars, ComputedFromHeight, ComputedFromHeightCumulative,
|
||||
ComputedFromHeightRatio, Identity, LazyFromHeight, PercentFromHeight, Price, RatioSatsBp16,
|
||||
PercentFromHeight, RatioSatsBp16,
|
||||
ValueFromHeight,
|
||||
};
|
||||
|
||||
use crate::distribution::{
|
||||
metrics::{ActivityCore, ImportConfig, OutputsMetrics, SupplyMetrics},
|
||||
state::{RealizedOps, UnrealizedState},
|
||||
metrics::{ActivityBase, ImportConfig, OutputsMetrics, RealizedMinimal, SupplyMetrics},
|
||||
state::UnrealizedState,
|
||||
};
|
||||
|
||||
/// Minimal realized metrics: realized cap, realized price, MVRV, and realized P/L.
|
||||
#[derive(Traversable)]
|
||||
pub struct MinimalRealized<M: StorageMode = Rw> {
|
||||
pub realized_cap_cents: ComputedFromHeight<Cents, M>,
|
||||
pub realized_profit: ComputedFromHeightCumulative<Cents, M>,
|
||||
pub realized_loss: ComputedFromHeightCumulative<Cents, M>,
|
||||
pub realized_cap: LazyFromHeight<Dollars, Cents>,
|
||||
pub realized_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub realized_price_ratio: ComputedFromHeightRatio<M>,
|
||||
pub mvrv: LazyFromHeight<StoredF32>,
|
||||
}
|
||||
|
||||
/// Minimal unrealized metrics: supply in profit/loss only.
|
||||
#[derive(Traversable)]
|
||||
pub struct MinimalUnrealized<M: StorageMode = Rw> {
|
||||
@@ -57,135 +43,12 @@ pub struct MinimalCohortMetrics<M: StorageMode = Rw> {
|
||||
pub filter: Filter,
|
||||
pub supply: Box<SupplyMetrics<M>>,
|
||||
pub outputs: Box<OutputsMetrics<M>>,
|
||||
pub activity: Box<ActivityCore<M>>,
|
||||
pub realized: Box<MinimalRealized<M>>,
|
||||
pub activity: Box<ActivityBase<M>>,
|
||||
pub realized: Box<RealizedMinimal<M>>,
|
||||
pub unrealized: Box<MinimalUnrealized<M>>,
|
||||
pub relative: Box<MinimalRelative<M>>,
|
||||
}
|
||||
|
||||
impl MinimalRealized {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let realized_cap_cents = cfg.import_computed("realized_cap_cents", Version::ZERO)?;
|
||||
let realized_cap = LazyFromHeight::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("realized_cap"),
|
||||
cfg.version,
|
||||
realized_cap_cents.height.read_only_boxed_clone(),
|
||||
&realized_cap_cents,
|
||||
);
|
||||
|
||||
let realized_profit = cfg.import_cumulative("realized_profit", Version::ZERO)?;
|
||||
let realized_loss = cfg.import_cumulative("realized_loss", Version::ZERO)?;
|
||||
|
||||
let realized_price = cfg.import_price("realized_price", Version::ONE)?;
|
||||
let realized_price_ratio = cfg.import_ratio("realized_price", Version::ONE)?;
|
||||
let mvrv = LazyFromHeight::from_lazy::<Identity<StoredF32>, BasisPoints32>(
|
||||
&cfg.name("mvrv"),
|
||||
cfg.version,
|
||||
&realized_price_ratio.ratio,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
realized_cap_cents,
|
||||
realized_profit,
|
||||
realized_loss,
|
||||
realized_cap,
|
||||
realized_price,
|
||||
realized_price_ratio,
|
||||
mvrv,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.realized_cap_cents
|
||||
.height
|
||||
.len()
|
||||
.min(self.realized_profit.height.len())
|
||||
.min(self.realized_loss.height.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(
|
||||
&mut self,
|
||||
height: Height,
|
||||
state: &impl RealizedOps,
|
||||
) -> Result<()> {
|
||||
self.realized_cap_cents
|
||||
.height
|
||||
.truncate_push(height, state.cap())?;
|
||||
self.realized_profit
|
||||
.height
|
||||
.truncate_push(height, state.profit())?;
|
||||
self.realized_loss
|
||||
.height
|
||||
.truncate_push(height, state.loss())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.realized_cap_cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.realized_profit.height,
|
||||
&mut self.realized_loss.height,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_sources(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
sum_others!(self, starting_indexes, others, exit; realized_cap_cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; realized_profit.height);
|
||||
sum_others!(self, starting_indexes, others, exit; realized_loss.height);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.realized_profit
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.realized_loss
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.realized_price.cents.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.realized_cap_cents.height,
|
||||
height_to_supply,
|
||||
|(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))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.realized_price_ratio.compute_ratio(
|
||||
starting_indexes,
|
||||
&prices.price.cents.height,
|
||||
&self.realized_price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MinimalUnrealized {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
@@ -292,8 +155,8 @@ impl MinimalCohortMetrics {
|
||||
filter: cfg.filter.clone(),
|
||||
supply: Box::new(SupplyMetrics::forced_import(cfg)?),
|
||||
outputs: Box::new(OutputsMetrics::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityCore::forced_import(cfg)?),
|
||||
realized: Box::new(MinimalRealized::forced_import(cfg)?),
|
||||
activity: Box::new(ActivityBase::forced_import(cfg)?),
|
||||
realized: Box::new(RealizedMinimal::forced_import(cfg)?),
|
||||
unrealized: Box::new(MinimalUnrealized::forced_import(cfg)?),
|
||||
relative: Box::new(MinimalRelative::forced_import(cfg)?),
|
||||
})
|
||||
@@ -345,7 +208,7 @@ impl MinimalCohortMetrics {
|
||||
&others.iter().map(|v| v.activity.as_ref()).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.realized.compute_from_sources(
|
||||
self.realized.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others
|
||||
.iter()
|
||||
|
||||
@@ -68,6 +68,104 @@ macro_rules! impl_cohort_metrics_base {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn min_stateful_height_len(&self) -> usize {
|
||||
self.supply.min_len()
|
||||
.min(self.outputs.min_len())
|
||||
.min(self.activity.min_len())
|
||||
.min(self.realized.min_stateful_height_len())
|
||||
.min(self.unrealized_full().min_stateful_height_len())
|
||||
.min(self.cost_basis_base().min_stateful_height_len())
|
||||
}
|
||||
|
||||
fn truncate_push(
|
||||
&mut self,
|
||||
height: brk_types::Height,
|
||||
state: &$crate::distribution::state::CohortState<$crate::distribution::state::RealizedState>,
|
||||
) -> brk_error::Result<()> {
|
||||
self.supply_mut()
|
||||
.truncate_push(height, state.supply.value)?;
|
||||
self.outputs_mut()
|
||||
.truncate_push(height, state.supply.utxo_count)?;
|
||||
self.activity_mut().truncate_push(
|
||||
height,
|
||||
state.sent,
|
||||
state.satblocks_destroyed,
|
||||
state.satdays_destroyed,
|
||||
)?;
|
||||
self.realized.truncate_push(height, &state.realized)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_base_from_others<T: $crate::distribution::metrics::CohortMetricsBase>(
|
||||
&mut self,
|
||||
starting_indexes: &brk_types::Indexes,
|
||||
others: &[&T],
|
||||
exit: &vecdb::Exit,
|
||||
) -> brk_error::Result<()> {
|
||||
self.supply_mut().compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| v.supply()).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.outputs_mut().compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| v.outputs()).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.activity_mut().compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| v.activity()).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.realized.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| v.realized_base()).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized_full_mut().compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| v.unrealized_full()).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.cost_basis_base_mut().compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| v.cost_basis_base()).collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_rest_part1(
|
||||
&mut self,
|
||||
blocks: &$crate::blocks::Vecs,
|
||||
prices: &$crate::prices::Vecs,
|
||||
starting_indexes: &brk_types::Indexes,
|
||||
exit: &vecdb::Exit,
|
||||
) -> brk_error::Result<()> {
|
||||
self.supply_mut()
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.supply_mut()
|
||||
.compute_rest_part1(blocks, starting_indexes, exit)?;
|
||||
self.outputs_mut()
|
||||
.compute_rest(blocks, starting_indexes, exit)?;
|
||||
self.activity_mut()
|
||||
.sent
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.activity_mut()
|
||||
.compute_rest_part1(blocks, prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized.sent_in_profit
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized.sent_in_loss
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.unrealized_full_mut()
|
||||
.compute_rest(prices, starting_indexes, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn collect_all_vecs_mut(&mut self) -> Vec<&mut dyn vecdb::AnyStoredVec> {
|
||||
let mut vecs: Vec<&mut dyn vecdb::AnyStoredVec> = Vec::new();
|
||||
vecs.extend(self.supply.collect_vecs_mut());
|
||||
@@ -103,6 +201,37 @@ macro_rules! impl_cohort_metrics_base {
|
||||
)
|
||||
}
|
||||
|
||||
fn min_stateful_height_len(&self) -> usize {
|
||||
self.inner.min_stateful_height_len()
|
||||
}
|
||||
|
||||
fn truncate_push(
|
||||
&mut self,
|
||||
height: brk_types::Height,
|
||||
state: &$crate::distribution::state::CohortState<$crate::distribution::state::RealizedState>,
|
||||
) -> brk_error::Result<()> {
|
||||
self.inner.truncate_push(height, state)
|
||||
}
|
||||
|
||||
fn compute_rest_part1(
|
||||
&mut self,
|
||||
blocks: &$crate::blocks::Vecs,
|
||||
prices: &$crate::prices::Vecs,
|
||||
starting_indexes: &brk_types::Indexes,
|
||||
exit: &vecdb::Exit,
|
||||
) -> brk_error::Result<()> {
|
||||
self.inner.compute_rest_part1(blocks, prices, starting_indexes, exit)
|
||||
}
|
||||
|
||||
fn compute_base_from_others<T: $crate::distribution::metrics::CohortMetricsBase>(
|
||||
&mut self,
|
||||
starting_indexes: &brk_types::Indexes,
|
||||
others: &[&T],
|
||||
exit: &vecdb::Exit,
|
||||
) -> brk_error::Result<()> {
|
||||
self.inner.compute_base_from_others(starting_indexes, others, exit)
|
||||
}
|
||||
|
||||
fn collect_all_vecs_mut(&mut self) -> Vec<&mut dyn vecdb::AnyStoredVec> {
|
||||
self.inner.collect_all_vecs_mut()
|
||||
}
|
||||
@@ -115,10 +244,10 @@ macro_rules! impl_cohort_metrics_base {
|
||||
fn supply_mut(&mut self) -> &mut $crate::distribution::metrics::SupplyMetrics { &mut self.supply }
|
||||
fn outputs(&self) -> &$crate::distribution::metrics::OutputsMetrics { &self.outputs }
|
||||
fn outputs_mut(&mut self) -> &mut $crate::distribution::metrics::OutputsMetrics { &mut self.outputs }
|
||||
fn activity(&self) -> &$crate::distribution::metrics::ActivityMetrics { &self.activity }
|
||||
fn activity_mut(&mut self) -> &mut $crate::distribution::metrics::ActivityMetrics { &mut self.activity }
|
||||
fn realized_full(&self) -> &$crate::distribution::metrics::RealizedFull { &self.realized }
|
||||
fn realized_full_mut(&mut self) -> &mut $crate::distribution::metrics::RealizedFull { &mut self.realized }
|
||||
fn activity(&self) -> &$crate::distribution::metrics::ActivityFull { &self.activity }
|
||||
fn activity_mut(&mut self) -> &mut $crate::distribution::metrics::ActivityFull { &mut self.activity }
|
||||
fn realized_base(&self) -> &$crate::distribution::metrics::RealizedBase { &self.realized }
|
||||
fn realized_base_mut(&mut self) -> &mut $crate::distribution::metrics::RealizedBase { &mut self.realized }
|
||||
fn unrealized_full(&self) -> &$crate::distribution::metrics::UnrealizedFull { &self.unrealized }
|
||||
fn unrealized_full_mut(&mut self) -> &mut $crate::distribution::metrics::UnrealizedFull { &mut self.unrealized }
|
||||
fn cost_basis_base(&self) -> &$crate::distribution::metrics::CostBasisBase { &self.cost_basis }
|
||||
@@ -131,10 +260,10 @@ macro_rules! impl_cohort_metrics_base {
|
||||
fn supply_mut(&mut self) -> &mut $crate::distribution::metrics::SupplyMetrics { self.inner.supply_mut() }
|
||||
fn outputs(&self) -> &$crate::distribution::metrics::OutputsMetrics { self.inner.outputs() }
|
||||
fn outputs_mut(&mut self) -> &mut $crate::distribution::metrics::OutputsMetrics { self.inner.outputs_mut() }
|
||||
fn activity(&self) -> &$crate::distribution::metrics::ActivityMetrics { self.inner.activity() }
|
||||
fn activity_mut(&mut self) -> &mut $crate::distribution::metrics::ActivityMetrics { self.inner.activity_mut() }
|
||||
fn realized_full(&self) -> &$crate::distribution::metrics::RealizedFull { self.inner.realized_full() }
|
||||
fn realized_full_mut(&mut self) -> &mut $crate::distribution::metrics::RealizedFull { self.inner.realized_full_mut() }
|
||||
fn activity(&self) -> &$crate::distribution::metrics::ActivityFull { self.inner.activity() }
|
||||
fn activity_mut(&mut self) -> &mut $crate::distribution::metrics::ActivityFull { self.inner.activity_mut() }
|
||||
fn realized_base(&self) -> &$crate::distribution::metrics::RealizedBase { self.inner.realized_base() }
|
||||
fn realized_base_mut(&mut self) -> &mut $crate::distribution::metrics::RealizedBase { self.inner.realized_base_mut() }
|
||||
fn unrealized_full(&self) -> &$crate::distribution::metrics::UnrealizedFull { self.inner.unrealized_full() }
|
||||
fn unrealized_full_mut(&mut self) -> &mut $crate::distribution::metrics::UnrealizedFull { self.inner.unrealized_full_mut() }
|
||||
fn cost_basis_base(&self) -> &$crate::distribution::metrics::CostBasisBase { self.inner.cost_basis_base() }
|
||||
@@ -197,10 +326,10 @@ pub trait CohortMetricsBase: CohortMetricsState<Realized = RealizedState> + Send
|
||||
fn supply_mut(&mut self) -> &mut SupplyMetrics;
|
||||
fn outputs(&self) -> &OutputsMetrics;
|
||||
fn outputs_mut(&mut self) -> &mut OutputsMetrics;
|
||||
fn activity(&self) -> &ActivityMetrics;
|
||||
fn activity_mut(&mut self) -> &mut ActivityMetrics;
|
||||
fn realized_full(&self) -> &RealizedFull;
|
||||
fn realized_full_mut(&mut self) -> &mut RealizedFull;
|
||||
fn activity(&self) -> &ActivityFull;
|
||||
fn activity_mut(&mut self) -> &mut ActivityFull;
|
||||
fn realized_base(&self) -> &RealizedBase;
|
||||
fn realized_base_mut(&mut self) -> &mut RealizedBase;
|
||||
fn unrealized_full(&self) -> &UnrealizedFull;
|
||||
fn unrealized_full_mut(&mut self) -> &mut UnrealizedFull;
|
||||
fn cost_basis_base(&self) -> &CostBasisBase;
|
||||
@@ -242,7 +371,7 @@ pub trait CohortMetricsBase: CohortMetricsState<Realized = RealizedState> + Send
|
||||
.min_len()
|
||||
.min(self.outputs().min_len())
|
||||
.min(self.activity().min_len())
|
||||
.min(self.realized_full().min_stateful_height_len())
|
||||
.min(self.realized_base().min_stateful_height_len())
|
||||
.min(self.unrealized_full().min_stateful_height_len())
|
||||
.min(self.cost_basis_base().min_stateful_height_len())
|
||||
}
|
||||
@@ -258,7 +387,7 @@ pub trait CohortMetricsBase: CohortMetricsState<Realized = RealizedState> + Send
|
||||
state.satblocks_destroyed,
|
||||
state.satdays_destroyed,
|
||||
)?;
|
||||
self.realized_full_mut()
|
||||
self.realized_base_mut()
|
||||
.truncate_push(height, &state.realized)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -272,7 +401,7 @@ pub trait CohortMetricsBase: CohortMetricsState<Realized = RealizedState> + Send
|
||||
) -> Result<()> {
|
||||
let weights: Vec<_> = others
|
||||
.iter()
|
||||
.map(|o| &o.realized_full().realized_cap.height)
|
||||
.map(|o| &o.realized_base().realized_cap.height)
|
||||
.collect();
|
||||
let values: Vec<_> = others
|
||||
.iter()
|
||||
@@ -308,13 +437,13 @@ pub trait CohortMetricsBase: CohortMetricsState<Realized = RealizedState> + Send
|
||||
self.activity_mut()
|
||||
.compute_rest_part1(blocks, prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized_full_mut()
|
||||
self.realized_base_mut()
|
||||
.sent_in_profit
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized_full_mut()
|
||||
self.realized_base_mut()
|
||||
.sent_in_loss
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized_full_mut()
|
||||
self.realized_base_mut()
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.unrealized_full_mut()
|
||||
@@ -354,7 +483,7 @@ pub trait CohortMetricsBase: CohortMetricsState<Realized = RealizedState> + Send
|
||||
aggregate!(supply_mut, supply);
|
||||
aggregate!(outputs_mut, outputs);
|
||||
aggregate!(activity_mut, activity);
|
||||
aggregate!(realized_full_mut, realized_full);
|
||||
aggregate!(realized_base_mut, realized_base);
|
||||
aggregate!(unrealized_full_mut, unrealized_full);
|
||||
aggregate!(cost_basis_base_mut, cost_basis_base);
|
||||
Ok(())
|
||||
|
||||
@@ -1,124 +1,172 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints32, Bitcoin, Cents, CentsSats, CentsSquaredSats, Dollars, Height, Indexes, Version,
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes,
|
||||
StoredF64, Version,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, AnyVec, BytesVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
blocks,
|
||||
distribution::state::RealizedState,
|
||||
distribution::state::RealizedOps,
|
||||
internal::{
|
||||
ComputedFromHeight, ComputedFromHeightCumulative, ComputedFromHeightRatio,
|
||||
PercentFromHeight, PercentRollingEmas1w1m, PercentRollingWindows, Price, RatioCentsBp32,
|
||||
ComputedFromHeight, ComputedFromHeightCumulative,
|
||||
ComputedFromHeightRatioPercentiles, FiatFromHeight,
|
||||
LazyFromHeight, NegCentsUnsignedToDollars, PercentFromHeight, RatioCents64,
|
||||
RatioCentsBp32, RatioCentsSignedCentsBps32, RollingEmas1w1m, RollingEmas2w,
|
||||
RollingWindows, ValueFromHeightCumulative,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
use super::RealizedComplete;
|
||||
use super::RealizedMinimal;
|
||||
|
||||
/// Full realized metrics (Source/Extended tier).
|
||||
///
|
||||
/// Contains all Complete-tier fields (via Deref to RealizedComplete) plus:
|
||||
/// - Source-only: peak_regret, peak_regret_rel_to_realized_cap
|
||||
/// - Extended-only: investor_price, price bands, cap_raw, sell_side_risk_ratio
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct RealizedFull<M: StorageMode = Rw> {
|
||||
pub struct RealizedBase<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub complete: RealizedComplete<M>,
|
||||
pub minimal: RealizedMinimal<M>,
|
||||
|
||||
// --- Extended-only fields ---
|
||||
pub investor_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub investor_price_ratio: ComputedFromHeightRatio<M>,
|
||||
pub realized_cap_change_1m: ComputedFromHeight<CentsSigned, M>,
|
||||
|
||||
pub lower_price_band: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub upper_price_band: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub neg_realized_loss: LazyFromHeight<Dollars, Cents>,
|
||||
pub net_realized_pnl: ComputedFromHeightCumulative<CentsSigned, M>,
|
||||
pub net_realized_pnl_ema_1w: ComputedFromHeight<CentsSigned, M>,
|
||||
pub gross_pnl: FiatFromHeight<Cents, M>,
|
||||
|
||||
pub cap_raw: M::Stored<BytesVec<Height, CentsSats>>,
|
||||
pub investor_cap_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
pub realized_profit_ema_1w: ComputedFromHeight<Cents, M>,
|
||||
pub realized_loss_ema_1w: ComputedFromHeight<Cents, M>,
|
||||
|
||||
pub sell_side_risk_ratio: PercentRollingWindows<BasisPoints32, M>,
|
||||
pub sell_side_risk_ratio_24h_ema: PercentRollingEmas1w1m<BasisPoints32, M>,
|
||||
pub realized_profit_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub realized_loss_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub net_realized_pnl_rel_to_realized_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
|
||||
// --- Source-only fields ---
|
||||
pub peak_regret: ComputedFromHeightCumulative<Cents, M>,
|
||||
pub peak_regret_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub value_created: ComputedFromHeight<Cents, M>,
|
||||
pub value_destroyed: ComputedFromHeight<Cents, M>,
|
||||
pub value_created_sum: RollingWindows<Cents, M>,
|
||||
pub value_destroyed_sum: RollingWindows<Cents, M>,
|
||||
pub sopr: RollingWindows<StoredF64, M>,
|
||||
pub sopr_24h_ema: RollingEmas1w1m<StoredF64, M>,
|
||||
|
||||
pub realized_price_ratio_percentiles: ComputedFromHeightRatioPercentiles<M>,
|
||||
|
||||
pub sent_in_profit: ValueFromHeightCumulative<M>,
|
||||
pub sent_in_loss: ValueFromHeightCumulative<M>,
|
||||
pub sent_in_profit_ema: RollingEmas2w<M>,
|
||||
pub sent_in_loss_ema: RollingEmas2w<M>,
|
||||
}
|
||||
|
||||
impl RealizedFull {
|
||||
impl RealizedBase {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
let v1 = Version::ONE;
|
||||
|
||||
let complete = RealizedComplete::forced_import(cfg)?;
|
||||
let minimal = RealizedMinimal::forced_import(cfg)?;
|
||||
|
||||
let investor_price = cfg.import_price("investor_price", v0)?;
|
||||
let investor_price_ratio = cfg.import_ratio("investor_price", v0)?;
|
||||
let lower_price_band = cfg.import_price("lower_price_band", v0)?;
|
||||
let upper_price_band = cfg.import_price("upper_price_band", v0)?;
|
||||
let neg_realized_loss = LazyFromHeight::from_height_source::<NegCentsUnsignedToDollars>(
|
||||
&cfg.name("neg_realized_loss"),
|
||||
cfg.version + Version::ONE,
|
||||
minimal.realized_loss.height.read_only_boxed_clone(),
|
||||
cfg.indexes,
|
||||
);
|
||||
|
||||
let cap_raw = cfg.import_bytes("cap_raw", v0)?;
|
||||
let investor_cap_raw = cfg.import_bytes("investor_cap_raw", v0)?;
|
||||
let realized_profit_ema_1w = cfg.import_computed("realized_profit_ema_1w", v0)?;
|
||||
let realized_loss_ema_1w = cfg.import_computed("realized_loss_ema_1w", v0)?;
|
||||
|
||||
let sell_side_risk_ratio =
|
||||
cfg.import_percent_rolling_bp32("sell_side_risk_ratio", Version::new(2))?;
|
||||
let sell_side_risk_ratio_24h_ema =
|
||||
cfg.import_percent_emas_1w_1m_bp32("sell_side_risk_ratio_24h", Version::new(2))?;
|
||||
let net_realized_pnl = cfg.import_cumulative("net_realized_pnl", v0)?;
|
||||
let net_realized_pnl_ema_1w = cfg.import_computed("net_realized_pnl_ema_1w", v0)?;
|
||||
let gross_pnl = cfg.import_fiat("realized_gross_pnl", v0)?;
|
||||
|
||||
let peak_regret = cfg.import_cumulative("realized_peak_regret", Version::new(2))?;
|
||||
let peak_regret_rel_to_realized_cap =
|
||||
cfg.import_percent_bp32("realized_peak_regret_rel_to_realized_cap", Version::new(2))?;
|
||||
let realized_profit_rel_to_realized_cap =
|
||||
cfg.import_percent_bp32("realized_profit_rel_to_realized_cap", Version::new(2))?;
|
||||
let realized_loss_rel_to_realized_cap =
|
||||
cfg.import_percent_bp32("realized_loss_rel_to_realized_cap", Version::new(2))?;
|
||||
let net_realized_pnl_rel_to_realized_cap =
|
||||
cfg.import_percent_bps32("net_realized_pnl_rel_to_realized_cap", Version::new(2))?;
|
||||
|
||||
let value_created = cfg.import_computed("value_created", v0)?;
|
||||
let value_destroyed = cfg.import_computed("value_destroyed", v0)?;
|
||||
let value_created_sum = cfg.import_rolling("value_created", v1)?;
|
||||
let value_destroyed_sum = cfg.import_rolling("value_destroyed", v1)?;
|
||||
let sopr = cfg.import_rolling("sopr", v1)?;
|
||||
let sopr_24h_ema = cfg.import_emas_1w_1m("sopr_24h", v1)?;
|
||||
|
||||
let realized_price_ratio_percentiles =
|
||||
ComputedFromHeightRatioPercentiles::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("realized_price"),
|
||||
cfg.version + v1,
|
||||
cfg.indexes,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
complete,
|
||||
investor_price,
|
||||
investor_price_ratio,
|
||||
lower_price_band,
|
||||
upper_price_band,
|
||||
cap_raw,
|
||||
investor_cap_raw,
|
||||
sell_side_risk_ratio,
|
||||
sell_side_risk_ratio_24h_ema,
|
||||
peak_regret,
|
||||
peak_regret_rel_to_realized_cap,
|
||||
minimal,
|
||||
realized_cap_change_1m: cfg.import_computed("realized_cap_change_1m", v0)?,
|
||||
neg_realized_loss,
|
||||
net_realized_pnl,
|
||||
net_realized_pnl_ema_1w,
|
||||
gross_pnl,
|
||||
realized_profit_ema_1w,
|
||||
realized_loss_ema_1w,
|
||||
realized_profit_rel_to_realized_cap,
|
||||
realized_loss_rel_to_realized_cap,
|
||||
net_realized_pnl_rel_to_realized_cap,
|
||||
value_created,
|
||||
value_destroyed,
|
||||
value_created_sum,
|
||||
value_destroyed_sum,
|
||||
sopr,
|
||||
sopr_24h_ema,
|
||||
realized_price_ratio_percentiles,
|
||||
sent_in_profit: cfg.import_value_cumulative("sent_in_profit", v0)?,
|
||||
sent_in_loss: cfg.import_value_cumulative("sent_in_loss", v0)?,
|
||||
sent_in_profit_ema: cfg.import_emas_2w("sent_in_profit", v0)?,
|
||||
sent_in_loss_ema: cfg.import_emas_2w("sent_in_loss", v0)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.complete
|
||||
self.minimal
|
||||
.min_stateful_height_len()
|
||||
.min(self.investor_price.cents.height.len())
|
||||
.min(self.cap_raw.len())
|
||||
.min(self.investor_cap_raw.len())
|
||||
.min(self.peak_regret.height.len())
|
||||
.min(self.value_created.height.len())
|
||||
.min(self.value_destroyed.height.len())
|
||||
.min(self.sent_in_profit.base.sats.height.len())
|
||||
.min(self.sent_in_loss.base.sats.height.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(&mut self, height: Height, state: &RealizedState) -> Result<()> {
|
||||
self.complete.truncate_push(height, state)?;
|
||||
self.investor_price
|
||||
.cents
|
||||
pub(crate) fn truncate_push(&mut self, height: Height, state: &impl RealizedOps) -> Result<()> {
|
||||
self.minimal.truncate_push(height, state)?;
|
||||
self.value_created
|
||||
.height
|
||||
.truncate_push(height, state.investor_price())?;
|
||||
self.cap_raw.truncate_push(height, state.cap_raw())?;
|
||||
self.investor_cap_raw
|
||||
.truncate_push(height, state.investor_cap_raw())?;
|
||||
self.peak_regret
|
||||
.truncate_push(height, state.value_created())?;
|
||||
self.value_destroyed
|
||||
.height
|
||||
.truncate_push(height, state.peak_regret())?;
|
||||
|
||||
.truncate_push(height, state.value_destroyed())?;
|
||||
self.sent_in_profit
|
||||
.base
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, state.sent_in_profit())?;
|
||||
self.sent_in_loss
|
||||
.base
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, state.sent_in_loss())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.complete.collect_vecs_mut();
|
||||
vecs.push(&mut self.investor_price.cents.height 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.peak_regret.height as &mut dyn AnyStoredVec);
|
||||
let mut vecs = self.minimal.collect_vecs_mut();
|
||||
vecs.push(&mut self.value_created.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.value_destroyed.height);
|
||||
vecs.push(&mut self.sent_in_profit.base.sats.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.sent_in_loss.base.sats.height);
|
||||
vecs
|
||||
}
|
||||
|
||||
@@ -128,80 +176,14 @@ impl RealizedFull {
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Delegate Complete-tier aggregation
|
||||
let complete_refs: Vec<&RealizedComplete> =
|
||||
others.iter().map(|o| &o.complete).collect();
|
||||
self.complete
|
||||
.compute_from_stateful(starting_indexes, &complete_refs, exit)?;
|
||||
let minimal_refs: Vec<&RealizedMinimal> = others.iter().map(|o| &o.minimal).collect();
|
||||
self.minimal
|
||||
.compute_from_stateful(starting_indexes, &minimal_refs, exit)?;
|
||||
|
||||
// Aggregate raw values for investor_price computation
|
||||
let investor_price_dep_version = others
|
||||
.iter()
|
||||
.map(|o| o.investor_price.cents.height.version())
|
||||
.fold(vecdb::Version::ZERO, |acc, v| acc + v);
|
||||
self.investor_price
|
||||
.cents
|
||||
.height
|
||||
.validate_computed_version_or_reset(investor_price_dep_version)?;
|
||||
|
||||
let start = self
|
||||
.cap_raw
|
||||
.len()
|
||||
.min(self.investor_cap_raw.len())
|
||||
.min(self.investor_price.cents.height.len());
|
||||
let end = others.iter().map(|o| o.cap_raw.len()).min().unwrap_or(0);
|
||||
|
||||
// Pre-collect all cohort data to avoid per-element BytesVec reads in nested loop
|
||||
let cap_ranges: Vec<Vec<CentsSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.cap_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
let investor_cap_ranges: Vec<Vec<CentsSquaredSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.investor_cap_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
|
||||
for i in start..end {
|
||||
let height = Height::from(i);
|
||||
let local_i = i - start;
|
||||
|
||||
let mut sum_cap = CentsSats::ZERO;
|
||||
let mut sum_investor_cap = CentsSquaredSats::ZERO;
|
||||
|
||||
for idx in 0..others.len() {
|
||||
sum_cap += cap_ranges[idx][local_i];
|
||||
sum_investor_cap += investor_cap_ranges[idx][local_i];
|
||||
}
|
||||
|
||||
self.cap_raw.truncate_push(height, sum_cap)?;
|
||||
self.investor_cap_raw
|
||||
.truncate_push(height, sum_investor_cap)?;
|
||||
|
||||
let investor_price = if sum_cap.inner() == 0 {
|
||||
Cents::ZERO
|
||||
} else {
|
||||
Cents::new((sum_investor_cap / sum_cap.inner()) as u64)
|
||||
};
|
||||
self.investor_price
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, investor_price)?;
|
||||
}
|
||||
|
||||
{
|
||||
let _lock = exit.lock();
|
||||
self.investor_price.cents.height.write()?;
|
||||
}
|
||||
|
||||
// Source-only: peak_regret
|
||||
self.peak_regret.height.compute_sum_of_others(
|
||||
starting_indexes.height,
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| &v.peak_regret.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
sum_others!(self, starting_indexes, others, exit; value_created.height);
|
||||
sum_others!(self, starting_indexes, others, exit; value_destroyed.height);
|
||||
sum_others!(self, starting_indexes, others, exit; sent_in_profit.base.sats.height);
|
||||
sum_others!(self, starting_indexes, others, exit; sent_in_loss.base.sats.height);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -211,10 +193,31 @@ impl RealizedFull {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.complete.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.minimal.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.peak_regret
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.net_realized_pnl
|
||||
.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.minimal.realized_profit.height,
|
||||
&self.minimal.realized_loss.height,
|
||||
|(i, profit, loss, ..)| {
|
||||
(
|
||||
i,
|
||||
CentsSigned::new(profit.inner() as i64 - loss.inner() as i64),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.gross_pnl.cents.height.compute_add(
|
||||
starting_indexes.height,
|
||||
&self.minimal.realized_profit.height,
|
||||
&self.minimal.realized_loss.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -225,91 +228,121 @@ impl RealizedFull {
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute all Complete-tier fields
|
||||
self.complete.compute_rest_part2(
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_supply,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.minimal
|
||||
.compute_rest_part2(prices, starting_indexes, height_to_supply, exit)?;
|
||||
|
||||
// Extended-only: investor_price ratio and price bands
|
||||
self.investor_price_ratio.compute_ratio(
|
||||
starting_indexes,
|
||||
&prices.price.cents.height,
|
||||
&self.investor_price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.lower_price_band.cents.height.compute_transform2(
|
||||
self.realized_cap_change_1m.height.compute_rolling_change(
|
||||
starting_indexes.height,
|
||||
&self.complete.realized_price.cents.height,
|
||||
&self.investor_price.cents.height,
|
||||
|(i, rp, ip, ..)| {
|
||||
let rp = rp.as_u128();
|
||||
let ip = ip.as_u128();
|
||||
if ip == 0 {
|
||||
(i, Cents::ZERO)
|
||||
} else {
|
||||
(i, Cents::from(rp * rp / ip))
|
||||
}
|
||||
},
|
||||
&blocks.count.height_1m_ago,
|
||||
&self.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.upper_price_band.cents.height.compute_transform2(
|
||||
self.realized_profit_ema_1w.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&self.investor_price.cents.height,
|
||||
&self.complete.realized_price.cents.height,
|
||||
|(i, ip, rp, ..)| {
|
||||
let ip = ip.as_u128();
|
||||
let rp = rp.as_u128();
|
||||
if rp == 0 {
|
||||
(i, Cents::ZERO)
|
||||
} else {
|
||||
(i, Cents::from(ip * ip / rp))
|
||||
}
|
||||
},
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.minimal.realized_profit.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_ema_1w.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.minimal.realized_loss.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_realized_pnl_ema_1w.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.net_realized_pnl.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Extended-only: sell-side risk ratios
|
||||
for (ssrr, rv) in self
|
||||
.sell_side_risk_ratio
|
||||
self.realized_profit_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.minimal.realized_profit.height,
|
||||
&self.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.minimal.realized_loss.height,
|
||||
&self.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_realized_pnl_rel_to_realized_cap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_realized_pnl.height,
|
||||
&self.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// SOPR: rolling sums of stateful value_created/destroyed, then ratio, then EMAs
|
||||
let window_starts = blocks.count.window_starts();
|
||||
self.value_created_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.value_created.height,
|
||||
exit,
|
||||
)?;
|
||||
self.value_destroyed_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.value_destroyed.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
for ((sopr, vc), vd) in self
|
||||
.sopr
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.complete.gross_pnl_sum.as_array())
|
||||
.zip(self.value_created_sum.as_array())
|
||||
.zip(self.value_destroyed_sum.as_array())
|
||||
{
|
||||
ssrr.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
sopr.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&rv.height,
|
||||
&self.complete.realized_cap_cents.height,
|
||||
&vc.height,
|
||||
&vd.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Extended-only: sell side risk EMAs
|
||||
self.sell_side_risk_ratio_24h_ema.compute_from_24h(
|
||||
self.sopr_24h_ema.compute_from_24h(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&blocks.count.height_1m_ago,
|
||||
&self.sell_side_risk_ratio._24h.bps.height,
|
||||
&self.sopr._24h.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Source-only: peak_regret relative to realized cap
|
||||
self.peak_regret_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.peak_regret.height,
|
||||
&self.complete.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
// Realized price ratio percentiles
|
||||
self.realized_price_ratio_percentiles.compute(
|
||||
blocks,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&self.minimal.realized_price_ratio.ratio.height,
|
||||
&self.minimal.realized_price.cents.height,
|
||||
)?;
|
||||
|
||||
// Sent in profit/loss EMAs
|
||||
self.sent_in_profit_ema.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent_in_profit.base.sats.height,
|
||||
&self.sent_in_profit.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.sent_in_loss_ema.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent_in_loss.base.sats.height,
|
||||
&self.sent_in_loss.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,245 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, Version,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
blocks,
|
||||
distribution::state::RealizedState,
|
||||
internal::{
|
||||
CentsUnsignedToDollars, ComputedFromHeight, LazyFromHeight, PercentFromHeight,
|
||||
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RollingEmas2w, RollingWindows,
|
||||
ValueFromHeightCumulative,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
use super::RealizedCore;
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct RealizedComplete<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub core: RealizedCore<M>,
|
||||
|
||||
pub profit_value_created: ComputedFromHeight<Cents, M>,
|
||||
pub profit_value_destroyed: ComputedFromHeight<Cents, M>,
|
||||
pub loss_value_created: ComputedFromHeight<Cents, M>,
|
||||
pub loss_value_destroyed: ComputedFromHeight<Cents, M>,
|
||||
|
||||
pub capitulation_flow: LazyFromHeight<Dollars, Cents>,
|
||||
pub profit_flow: LazyFromHeight<Dollars, Cents>,
|
||||
|
||||
pub gross_pnl_sum: RollingWindows<Cents, M>,
|
||||
|
||||
pub net_pnl_change_1m: ComputedFromHeight<CentsSigned, M>,
|
||||
pub net_pnl_change_1m_rel_to_realized_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub net_pnl_change_1m_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
|
||||
pub sent_in_profit: ValueFromHeightCumulative<M>,
|
||||
pub sent_in_profit_ema: RollingEmas2w<M>,
|
||||
pub sent_in_loss: ValueFromHeightCumulative<M>,
|
||||
pub sent_in_loss_ema: RollingEmas2w<M>,
|
||||
}
|
||||
|
||||
impl RealizedComplete {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
|
||||
let core = RealizedCore::forced_import(cfg)?;
|
||||
|
||||
let profit_value_created = cfg.import_computed("profit_value_created", v0)?;
|
||||
let profit_value_destroyed = cfg.import_computed("profit_value_destroyed", v0)?;
|
||||
let loss_value_created = cfg.import_computed("loss_value_created", v0)?;
|
||||
let loss_value_destroyed = cfg.import_computed("loss_value_destroyed", v0)?;
|
||||
|
||||
let capitulation_flow = LazyFromHeight::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("capitulation_flow"),
|
||||
cfg.version,
|
||||
loss_value_destroyed.height.read_only_boxed_clone(),
|
||||
&loss_value_destroyed,
|
||||
);
|
||||
let profit_flow = LazyFromHeight::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("profit_flow"),
|
||||
cfg.version,
|
||||
profit_value_destroyed.height.read_only_boxed_clone(),
|
||||
&profit_value_destroyed,
|
||||
);
|
||||
|
||||
let gross_pnl_sum = cfg.import_rolling("gross_pnl_sum", Version::ONE)?;
|
||||
|
||||
Ok(Self {
|
||||
core,
|
||||
profit_value_created,
|
||||
profit_value_destroyed,
|
||||
loss_value_created,
|
||||
loss_value_destroyed,
|
||||
capitulation_flow,
|
||||
profit_flow,
|
||||
gross_pnl_sum,
|
||||
net_pnl_change_1m: cfg.import_computed("net_pnl_change_1m", Version::new(3))?,
|
||||
net_pnl_change_1m_rel_to_realized_cap: cfg
|
||||
.import_percent_bps32("net_pnl_change_1m_rel_to_realized_cap", Version::new(4))?,
|
||||
net_pnl_change_1m_rel_to_market_cap: cfg
|
||||
.import_percent_bps32("net_pnl_change_1m_rel_to_market_cap", Version::new(4))?,
|
||||
sent_in_profit: cfg.import_value_cumulative("sent_in_profit", v0)?,
|
||||
sent_in_profit_ema: cfg.import_emas_2w("sent_in_profit", v0)?,
|
||||
sent_in_loss: cfg.import_value_cumulative("sent_in_loss", v0)?,
|
||||
sent_in_loss_ema: cfg.import_emas_2w("sent_in_loss", v0)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.core
|
||||
.min_stateful_height_len()
|
||||
.min(self.profit_value_created.height.len())
|
||||
.min(self.profit_value_destroyed.height.len())
|
||||
.min(self.loss_value_created.height.len())
|
||||
.min(self.loss_value_destroyed.height.len())
|
||||
.min(self.sent_in_profit.base.sats.height.len())
|
||||
.min(self.sent_in_loss.base.sats.height.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(&mut self, height: Height, state: &RealizedState) -> Result<()> {
|
||||
self.core.truncate_push(height, state)?;
|
||||
self.profit_value_created
|
||||
.height
|
||||
.truncate_push(height, state.profit_value_created())?;
|
||||
self.profit_value_destroyed
|
||||
.height
|
||||
.truncate_push(height, state.profit_value_destroyed())?;
|
||||
self.loss_value_created
|
||||
.height
|
||||
.truncate_push(height, state.loss_value_created())?;
|
||||
self.loss_value_destroyed
|
||||
.height
|
||||
.truncate_push(height, state.loss_value_destroyed())?;
|
||||
self.sent_in_profit
|
||||
.base
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, state.sent_in_profit())?;
|
||||
self.sent_in_loss
|
||||
.base
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, state.sent_in_loss())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.core.collect_vecs_mut();
|
||||
vecs.push(&mut self.profit_value_created.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.profit_value_destroyed.height);
|
||||
vecs.push(&mut self.loss_value_created.height);
|
||||
vecs.push(&mut self.loss_value_destroyed.height);
|
||||
vecs.push(&mut self.sent_in_profit.base.sats.height);
|
||||
vecs.push(&mut self.sent_in_loss.base.sats.height);
|
||||
vecs
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let core_refs: Vec<&RealizedCore> = others.iter().map(|o| &o.core).collect();
|
||||
self.core
|
||||
.compute_from_stateful(starting_indexes, &core_refs, exit)?;
|
||||
|
||||
sum_others!(self, starting_indexes, others, exit; profit_value_created.height);
|
||||
sum_others!(self, starting_indexes, others, exit; profit_value_destroyed.height);
|
||||
sum_others!(self, starting_indexes, others, exit; loss_value_created.height);
|
||||
sum_others!(self, starting_indexes, others, exit; loss_value_destroyed.height);
|
||||
sum_others!(self, starting_indexes, others, exit; sent_in_profit.base.sats.height);
|
||||
sum_others!(self, starting_indexes, others, exit; sent_in_loss.base.sats.height);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core.compute_rest_part2(
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_supply,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let window_starts = blocks.count.window_starts();
|
||||
self.gross_pnl_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.gross_pnl.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.sent_in_profit_ema.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent_in_profit.base.sats.height,
|
||||
&self.sent_in_profit.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.sent_in_loss_ema.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent_in_loss.base.sats.height,
|
||||
&self.sent_in_loss.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.net_pnl_change_1m.height.compute_rolling_change(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1m_ago,
|
||||
&self.core.net_realized_pnl.cumulative.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.net_pnl_change_1m_rel_to_realized_cap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_pnl_change_1m.height,
|
||||
&self.core.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.net_pnl_change_1m_rel_to_market_cap
|
||||
.compute_binary::<CentsSigned, Dollars, RatioCentsSignedDollarsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_pnl_change_1m.height,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,347 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes,
|
||||
Sats, StoredF32, StoredF64, Version,
|
||||
};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
blocks,
|
||||
distribution::state::RealizedOps,
|
||||
internal::{
|
||||
CentsUnsignedToDollars, ComputedFromHeight, ComputedFromHeightCumulative,
|
||||
ComputedFromHeightRatio, FiatFromHeight, Identity, LazyFromHeight,
|
||||
NegCentsUnsignedToDollars, PercentFromHeight, Price, RatioCents64, RatioCentsBp32,
|
||||
RatioCentsSignedCentsBps32, RollingEmas1w1m, RollingWindows,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedCore<M: StorageMode = Rw> {
|
||||
pub realized_cap_cents: ComputedFromHeight<Cents, M>,
|
||||
pub realized_profit: ComputedFromHeightCumulative<Cents, M>,
|
||||
pub realized_loss: ComputedFromHeightCumulative<Cents, M>,
|
||||
|
||||
pub realized_cap: LazyFromHeight<Dollars, Cents>,
|
||||
pub realized_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub realized_price_ratio: ComputedFromHeightRatio<M>,
|
||||
pub realized_cap_change_1m: ComputedFromHeight<CentsSigned, M>,
|
||||
|
||||
pub mvrv: LazyFromHeight<StoredF32>,
|
||||
|
||||
pub neg_realized_loss: LazyFromHeight<Dollars, Cents>,
|
||||
pub net_realized_pnl: ComputedFromHeightCumulative<CentsSigned, M>,
|
||||
pub net_realized_pnl_ema_1w: ComputedFromHeight<CentsSigned, M>,
|
||||
pub gross_pnl: FiatFromHeight<Cents, M>,
|
||||
|
||||
pub realized_profit_ema_1w: ComputedFromHeight<Cents, M>,
|
||||
pub realized_loss_ema_1w: ComputedFromHeight<Cents, M>,
|
||||
|
||||
pub realized_profit_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub realized_loss_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub net_realized_pnl_rel_to_realized_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
|
||||
pub value_created: ComputedFromHeight<Cents, M>,
|
||||
pub value_destroyed: ComputedFromHeight<Cents, M>,
|
||||
pub value_created_sum: RollingWindows<Cents, M>,
|
||||
pub value_destroyed_sum: RollingWindows<Cents, M>,
|
||||
pub sopr: RollingWindows<StoredF64, M>,
|
||||
pub sopr_24h_ema: RollingEmas1w1m<StoredF64, M>,
|
||||
}
|
||||
|
||||
impl RealizedCore {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
let v1 = Version::ONE;
|
||||
|
||||
let realized_cap_cents = cfg.import_computed("realized_cap_cents", v0)?;
|
||||
let realized_cap = LazyFromHeight::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("realized_cap"),
|
||||
cfg.version,
|
||||
realized_cap_cents.height.read_only_boxed_clone(),
|
||||
&realized_cap_cents,
|
||||
);
|
||||
|
||||
let realized_profit = cfg.import_cumulative("realized_profit", v0)?;
|
||||
let realized_profit_ema_1w = cfg.import_computed("realized_profit_ema_1w", v0)?;
|
||||
let realized_loss = cfg.import_cumulative("realized_loss", v0)?;
|
||||
let realized_loss_ema_1w = cfg.import_computed("realized_loss_ema_1w", v0)?;
|
||||
|
||||
let neg_realized_loss = LazyFromHeight::from_height_source::<NegCentsUnsignedToDollars>(
|
||||
&cfg.name("neg_realized_loss"),
|
||||
cfg.version + Version::ONE,
|
||||
realized_loss.height.read_only_boxed_clone(),
|
||||
cfg.indexes,
|
||||
);
|
||||
|
||||
let net_realized_pnl = cfg.import_cumulative("net_realized_pnl", v0)?;
|
||||
let net_realized_pnl_ema_1w = cfg.import_computed("net_realized_pnl_ema_1w", v0)?;
|
||||
let gross_pnl = cfg.import_fiat("realized_gross_pnl", v0)?;
|
||||
|
||||
let realized_profit_rel_to_realized_cap =
|
||||
cfg.import_percent_bp32("realized_profit_rel_to_realized_cap", Version::new(2))?;
|
||||
let realized_loss_rel_to_realized_cap =
|
||||
cfg.import_percent_bp32("realized_loss_rel_to_realized_cap", Version::new(2))?;
|
||||
let net_realized_pnl_rel_to_realized_cap =
|
||||
cfg.import_percent_bps32("net_realized_pnl_rel_to_realized_cap", Version::new(2))?;
|
||||
|
||||
let realized_price = cfg.import_price("realized_price", v1)?;
|
||||
|
||||
let realized_price_ratio = cfg.import_ratio("realized_price", v1)?;
|
||||
let mvrv = LazyFromHeight::from_lazy::<Identity<StoredF32>, BasisPoints32>(
|
||||
&cfg.name("mvrv"),
|
||||
cfg.version,
|
||||
&realized_price_ratio.ratio,
|
||||
);
|
||||
|
||||
let value_created = cfg.import_computed("value_created", v0)?;
|
||||
let value_destroyed = cfg.import_computed("value_destroyed", v0)?;
|
||||
let value_created_sum = cfg.import_rolling("value_created", v1)?;
|
||||
let value_destroyed_sum = cfg.import_rolling("value_destroyed", v1)?;
|
||||
let sopr = cfg.import_rolling("sopr", v1)?;
|
||||
let sopr_24h_ema = cfg.import_emas_1w_1m("sopr_24h", v1)?;
|
||||
|
||||
Ok(Self {
|
||||
realized_cap_cents,
|
||||
realized_cap,
|
||||
realized_price,
|
||||
realized_price_ratio,
|
||||
realized_cap_change_1m: cfg.import_computed("realized_cap_change_1m", v0)?,
|
||||
mvrv,
|
||||
realized_profit,
|
||||
realized_profit_ema_1w,
|
||||
realized_loss,
|
||||
realized_loss_ema_1w,
|
||||
neg_realized_loss,
|
||||
net_realized_pnl,
|
||||
net_realized_pnl_ema_1w,
|
||||
gross_pnl,
|
||||
realized_profit_rel_to_realized_cap,
|
||||
realized_loss_rel_to_realized_cap,
|
||||
net_realized_pnl_rel_to_realized_cap,
|
||||
value_created,
|
||||
value_destroyed,
|
||||
value_created_sum,
|
||||
value_destroyed_sum,
|
||||
sopr,
|
||||
sopr_24h_ema,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.realized_cap_cents
|
||||
.height
|
||||
.len()
|
||||
.min(self.realized_profit.height.len())
|
||||
.min(self.realized_loss.height.len())
|
||||
.min(self.value_created.height.len())
|
||||
.min(self.value_destroyed.height.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(&mut self, height: Height, state: &impl RealizedOps) -> Result<()> {
|
||||
self.realized_cap_cents
|
||||
.height
|
||||
.truncate_push(height, state.cap())?;
|
||||
self.realized_profit
|
||||
.height
|
||||
.truncate_push(height, state.profit())?;
|
||||
self.realized_loss
|
||||
.height
|
||||
.truncate_push(height, state.loss())?;
|
||||
self.value_created
|
||||
.height
|
||||
.truncate_push(height, state.value_created())?;
|
||||
self.value_destroyed
|
||||
.height
|
||||
.truncate_push(height, state.value_destroyed())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.realized_cap_cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.realized_profit.height,
|
||||
&mut self.realized_loss.height,
|
||||
&mut self.value_created.height,
|
||||
&mut self.value_destroyed.height,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
sum_others!(self, starting_indexes, others, exit; realized_cap_cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; realized_profit.height);
|
||||
sum_others!(self, starting_indexes, others, exit; realized_loss.height);
|
||||
sum_others!(self, starting_indexes, others, exit; value_created.height);
|
||||
sum_others!(self, starting_indexes, others, exit; value_destroyed.height);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.realized_profit
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.realized_loss
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
self.net_realized_pnl
|
||||
.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.realized_profit.height,
|
||||
&self.realized_loss.height,
|
||||
|(i, profit, loss, ..)| {
|
||||
(
|
||||
i,
|
||||
CentsSigned::new(profit.inner() as i64 - loss.inner() as i64),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.gross_pnl.cents.height.compute_add(
|
||||
starting_indexes.height,
|
||||
&self.realized_profit.height,
|
||||
&self.realized_loss.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.realized_price.cents.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.realized_cap_cents.height,
|
||||
height_to_supply,
|
||||
|(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))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.realized_price_ratio.compute_ratio(
|
||||
starting_indexes,
|
||||
&prices.price.cents.height,
|
||||
&self.realized_price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.realized_cap_change_1m.height.compute_rolling_change(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1m_ago,
|
||||
&self.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.realized_profit_ema_1w.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.realized_profit.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_ema_1w.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.realized_loss.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_realized_pnl_ema_1w.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.net_realized_pnl.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.realized_profit_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.realized_profit.height,
|
||||
&self.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.realized_loss.height,
|
||||
&self.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_realized_pnl_rel_to_realized_cap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_realized_pnl.height,
|
||||
&self.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// SOPR: rolling sums of stateful value_created/destroyed, then ratio, then EMAs
|
||||
let window_starts = blocks.count.window_starts();
|
||||
self.value_created_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.value_created.height,
|
||||
exit,
|
||||
)?;
|
||||
self.value_destroyed_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.value_destroyed.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
for ((sopr, vc), vd) in self
|
||||
.sopr
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.value_created_sum.as_array())
|
||||
.zip(self.value_destroyed_sum.as_array())
|
||||
{
|
||||
sopr.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&vc.height,
|
||||
&vd.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
self.sopr_24h_ema.compute_from_24h(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&blocks.count.height_1m_ago,
|
||||
&self.sopr._24h.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints32, Cents, Dollars, Height, Indexes, StoredF64, Version};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
blocks,
|
||||
internal::{
|
||||
ComputedFromHeightRatioPercentiles, ComputedFromHeightRatioStdDevBands,
|
||||
PercentFromHeight, RatioCents64, RatioDollarsBp32, RollingWindows,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
use super::RealizedFull;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedExtended<M: StorageMode = Rw> {
|
||||
pub realized_cap_rel_to_own_market_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
|
||||
pub realized_profit_sum: RollingWindows<Cents, M>,
|
||||
pub realized_loss_sum: RollingWindows<Cents, M>,
|
||||
|
||||
pub realized_profit_to_loss_ratio: RollingWindows<StoredF64, M>,
|
||||
|
||||
pub realized_price_ratio_percentiles: ComputedFromHeightRatioPercentiles<M>,
|
||||
pub realized_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands<M>,
|
||||
pub investor_price_ratio_percentiles: ComputedFromHeightRatioPercentiles<M>,
|
||||
pub investor_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands<M>,
|
||||
}
|
||||
|
||||
impl RealizedExtended {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let realized_price_name = cfg.name("realized_price");
|
||||
let realized_price_version = cfg.version + Version::ONE;
|
||||
let investor_price_name = cfg.name("investor_price");
|
||||
let investor_price_version = cfg.version;
|
||||
|
||||
Ok(RealizedExtended {
|
||||
realized_cap_rel_to_own_market_cap: cfg
|
||||
.import_percent_bp32("realized_cap_rel_to_own_market_cap", Version::ONE)?,
|
||||
realized_profit_sum: cfg.import_rolling("realized_profit", Version::ONE)?,
|
||||
realized_loss_sum: cfg.import_rolling("realized_loss", Version::ONE)?,
|
||||
realized_profit_to_loss_ratio: cfg
|
||||
.import_rolling("realized_profit_to_loss_ratio", Version::ONE)?,
|
||||
realized_price_ratio_percentiles: ComputedFromHeightRatioPercentiles::forced_import(
|
||||
cfg.db,
|
||||
&realized_price_name,
|
||||
realized_price_version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
realized_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands::forced_import(
|
||||
cfg.db,
|
||||
&realized_price_name,
|
||||
realized_price_version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
investor_price_ratio_percentiles: ComputedFromHeightRatioPercentiles::forced_import(
|
||||
cfg.db,
|
||||
&investor_price_name,
|
||||
investor_price_version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
investor_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands::forced_import(
|
||||
cfg.db,
|
||||
&investor_price_name,
|
||||
investor_price_version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
base: &RealizedFull,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Realized profit/loss rolling sums
|
||||
let window_starts = blocks.count.window_starts();
|
||||
self.realized_profit_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&base.realized_profit.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&base.realized_loss.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Realized cap relative to own market cap
|
||||
self.realized_cap_rel_to_own_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
|
||||
starting_indexes.height,
|
||||
&base.realized_cap.height,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Realized profit to loss ratios
|
||||
for ((ratio, profit), loss) in self
|
||||
.realized_profit_to_loss_ratio
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.realized_profit_sum.as_array())
|
||||
.zip(self.realized_loss_sum.as_array())
|
||||
{
|
||||
ratio.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&profit.height,
|
||||
&loss.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Realized price: percentiles + stddev bands
|
||||
let realized_price = &base.realized_price.cents.height;
|
||||
self.realized_price_ratio_percentiles.compute(
|
||||
blocks,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&base.realized_price_ratio.ratio.height,
|
||||
realized_price,
|
||||
)?;
|
||||
self.realized_price_ratio_std_dev.compute(
|
||||
blocks,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&base.realized_price_ratio.ratio.height,
|
||||
realized_price,
|
||||
)?;
|
||||
|
||||
// Investor price: percentiles + stddev bands
|
||||
let investor_price = &base.investor_price.cents.height;
|
||||
self.investor_price_ratio_percentiles.compute(
|
||||
blocks,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&base.investor_price_ratio.ratio.height,
|
||||
investor_price,
|
||||
)?;
|
||||
self.investor_price_ratio_std_dev.compute(
|
||||
blocks,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&base.investor_price_ratio.ratio.height,
|
||||
investor_price,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSats, CentsSigned, CentsSquaredSats,
|
||||
Dollars, Height, Indexes, Version,
|
||||
Dollars, Height, Indexes, StoredF64, Version,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
@@ -15,26 +15,26 @@ use crate::{
|
||||
distribution::state::RealizedState,
|
||||
internal::{
|
||||
CentsUnsignedToDollars, ComputedFromHeight, ComputedFromHeightCumulative,
|
||||
ComputedFromHeightRatio, ComputedFromHeightRatioPercentiles, LazyFromHeight,
|
||||
PercentFromHeight, PercentRollingEmas1w1m, PercentRollingWindows, Price, RatioCentsBp32,
|
||||
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RollingEmas2w, RollingWindows,
|
||||
ValueFromHeightCumulative,
|
||||
ComputedFromHeightRatio, ComputedFromHeightRatioPercentiles,
|
||||
ComputedFromHeightRatioStdDevBands, LazyFromHeight, PercentFromHeight,
|
||||
PercentRollingEmas1w1m, PercentRollingWindows, Price, RatioCents64, RatioCentsBp32,
|
||||
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDollarsBp32,
|
||||
RollingWindows,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
use super::RealizedCore;
|
||||
use super::RealizedBase;
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct RealizedBasic<M: StorageMode = Rw> {
|
||||
pub struct RealizedFull<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub core: RealizedCore<M>,
|
||||
pub core: RealizedBase<M>,
|
||||
|
||||
// --- Stateful fields ---
|
||||
pub profit_value_created: ComputedFromHeight<Cents, M>,
|
||||
pub profit_value_destroyed: ComputedFromHeight<Cents, M>,
|
||||
pub loss_value_created: ComputedFromHeight<Cents, M>,
|
||||
@@ -49,12 +49,6 @@ pub struct RealizedBasic<M: StorageMode = Rw> {
|
||||
pub net_pnl_change_1m_rel_to_realized_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub net_pnl_change_1m_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
|
||||
pub sent_in_profit: ValueFromHeightCumulative<M>,
|
||||
pub sent_in_profit_ema: RollingEmas2w<M>,
|
||||
pub sent_in_loss: ValueFromHeightCumulative<M>,
|
||||
pub sent_in_loss_ema: RollingEmas2w<M>,
|
||||
|
||||
// --- Investor price & price bands ---
|
||||
pub investor_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub investor_price_ratio: ComputedFromHeightRatio<M>,
|
||||
|
||||
@@ -67,22 +61,27 @@ pub struct RealizedBasic<M: StorageMode = Rw> {
|
||||
pub sell_side_risk_ratio: PercentRollingWindows<BasisPoints32, M>,
|
||||
pub sell_side_risk_ratio_24h_ema: PercentRollingEmas1w1m<BasisPoints32, M>,
|
||||
|
||||
// --- Peak regret ---
|
||||
pub peak_regret: ComputedFromHeightCumulative<Cents, M>,
|
||||
pub peak_regret_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
|
||||
// --- Realized price ratio percentiles ---
|
||||
pub realized_price_ratio_percentiles: ComputedFromHeightRatioPercentiles<M>,
|
||||
pub realized_cap_rel_to_own_market_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
|
||||
pub realized_profit_sum: RollingWindows<Cents, M>,
|
||||
pub realized_loss_sum: RollingWindows<Cents, M>,
|
||||
pub realized_profit_to_loss_ratio: RollingWindows<StoredF64, M>,
|
||||
|
||||
pub realized_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands<M>,
|
||||
pub investor_price_ratio_percentiles: ComputedFromHeightRatioPercentiles<M>,
|
||||
pub investor_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands<M>,
|
||||
}
|
||||
|
||||
impl RealizedBasic {
|
||||
impl RealizedFull {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
let v1 = Version::ONE;
|
||||
|
||||
let core = RealizedCore::forced_import(cfg)?;
|
||||
let core = RealizedBase::forced_import(cfg)?;
|
||||
|
||||
// Stateful fields
|
||||
let profit_value_created = cfg.import_computed("profit_value_created", v0)?;
|
||||
let profit_value_destroyed = cfg.import_computed("profit_value_destroyed", v0)?;
|
||||
let loss_value_created = cfg.import_computed("loss_value_created", v0)?;
|
||||
@@ -101,9 +100,8 @@ impl RealizedBasic {
|
||||
&profit_value_destroyed,
|
||||
);
|
||||
|
||||
let gross_pnl_sum = cfg.import_rolling("gross_pnl_sum", v1)?;
|
||||
let gross_pnl_sum = cfg.import_rolling("gross_pnl_sum", Version::ONE)?;
|
||||
|
||||
// Investor price & price bands
|
||||
let investor_price = cfg.import_price("investor_price", v0)?;
|
||||
let investor_price_ratio = cfg.import_ratio("investor_price", v0)?;
|
||||
let lower_price_band = cfg.import_price("lower_price_band", v0)?;
|
||||
@@ -117,19 +115,14 @@ impl RealizedBasic {
|
||||
let sell_side_risk_ratio_24h_ema =
|
||||
cfg.import_percent_emas_1w_1m_bp32("sell_side_risk_ratio_24h", Version::new(2))?;
|
||||
|
||||
// Peak regret
|
||||
let peak_regret = cfg.import_cumulative("realized_peak_regret", Version::new(2))?;
|
||||
let peak_regret_rel_to_realized_cap =
|
||||
cfg.import_percent_bp32("realized_peak_regret_rel_to_realized_cap", Version::new(2))?;
|
||||
|
||||
// Realized price ratio percentiles
|
||||
let realized_price_ratio_percentiles =
|
||||
ComputedFromHeightRatioPercentiles::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("realized_price"),
|
||||
cfg.version + v1,
|
||||
cfg.indexes,
|
||||
)?;
|
||||
let realized_price_name = cfg.name("realized_price");
|
||||
let realized_price_version = cfg.version + v1;
|
||||
let investor_price_name = cfg.name("investor_price");
|
||||
let investor_price_version = cfg.version;
|
||||
|
||||
Ok(Self {
|
||||
core,
|
||||
@@ -145,10 +138,6 @@ impl RealizedBasic {
|
||||
.import_percent_bps32("net_pnl_change_1m_rel_to_realized_cap", Version::new(4))?,
|
||||
net_pnl_change_1m_rel_to_market_cap: cfg
|
||||
.import_percent_bps32("net_pnl_change_1m_rel_to_market_cap", Version::new(4))?,
|
||||
sent_in_profit: cfg.import_value_cumulative("sent_in_profit", v0)?,
|
||||
sent_in_profit_ema: cfg.import_emas_2w("sent_in_profit", v0)?,
|
||||
sent_in_loss: cfg.import_value_cumulative("sent_in_loss", v0)?,
|
||||
sent_in_loss_ema: cfg.import_emas_2w("sent_in_loss", v0)?,
|
||||
investor_price,
|
||||
investor_price_ratio,
|
||||
lower_price_band,
|
||||
@@ -159,7 +148,30 @@ impl RealizedBasic {
|
||||
sell_side_risk_ratio_24h_ema,
|
||||
peak_regret,
|
||||
peak_regret_rel_to_realized_cap,
|
||||
realized_price_ratio_percentiles,
|
||||
realized_cap_rel_to_own_market_cap: cfg
|
||||
.import_percent_bp32("realized_cap_rel_to_own_market_cap", v1)?,
|
||||
realized_profit_sum: cfg.import_rolling("realized_profit", v1)?,
|
||||
realized_loss_sum: cfg.import_rolling("realized_loss", v1)?,
|
||||
realized_profit_to_loss_ratio: cfg
|
||||
.import_rolling("realized_profit_to_loss_ratio", v1)?,
|
||||
realized_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands::forced_import(
|
||||
cfg.db,
|
||||
&realized_price_name,
|
||||
realized_price_version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
investor_price_ratio_percentiles: ComputedFromHeightRatioPercentiles::forced_import(
|
||||
cfg.db,
|
||||
&investor_price_name,
|
||||
investor_price_version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
investor_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands::forced_import(
|
||||
cfg.db,
|
||||
&investor_price_name,
|
||||
investor_price_version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -170,8 +182,6 @@ impl RealizedBasic {
|
||||
.min(self.profit_value_destroyed.height.len())
|
||||
.min(self.loss_value_created.height.len())
|
||||
.min(self.loss_value_destroyed.height.len())
|
||||
.min(self.sent_in_profit.base.sats.height.len())
|
||||
.min(self.sent_in_loss.base.sats.height.len())
|
||||
.min(self.investor_price.cents.height.len())
|
||||
.min(self.cap_raw.len())
|
||||
.min(self.investor_cap_raw.len())
|
||||
@@ -192,16 +202,6 @@ impl RealizedBasic {
|
||||
self.loss_value_destroyed
|
||||
.height
|
||||
.truncate_push(height, state.loss_value_destroyed())?;
|
||||
self.sent_in_profit
|
||||
.base
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, state.sent_in_profit())?;
|
||||
self.sent_in_loss
|
||||
.base
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, state.sent_in_loss())?;
|
||||
self.investor_price
|
||||
.cents
|
||||
.height
|
||||
@@ -222,8 +222,6 @@ impl RealizedBasic {
|
||||
vecs.push(&mut self.profit_value_destroyed.height);
|
||||
vecs.push(&mut self.loss_value_created.height);
|
||||
vecs.push(&mut self.loss_value_destroyed.height);
|
||||
vecs.push(&mut self.sent_in_profit.base.sats.height);
|
||||
vecs.push(&mut self.sent_in_loss.base.sats.height);
|
||||
vecs.push(&mut self.investor_price.cents.height);
|
||||
vecs.push(&mut self.cap_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.investor_cap_raw as &mut dyn AnyStoredVec);
|
||||
@@ -231,92 +229,16 @@ impl RealizedBasic {
|
||||
vecs
|
||||
}
|
||||
|
||||
/// Aggregate Core-level fields from source cohorts.
|
||||
/// investor_price, cap_raw, investor_cap_raw come from the stateful scan, not aggregated.
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
others: &[&RealizedBase],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Core aggregation
|
||||
let core_refs: Vec<&RealizedCore> = others.iter().map(|o| &o.core).collect();
|
||||
self.core
|
||||
.compute_from_stateful(starting_indexes, &core_refs, exit)?;
|
||||
|
||||
// Stateful field aggregation
|
||||
sum_others!(self, starting_indexes, others, exit; profit_value_created.height);
|
||||
sum_others!(self, starting_indexes, others, exit; profit_value_destroyed.height);
|
||||
sum_others!(self, starting_indexes, others, exit; loss_value_created.height);
|
||||
sum_others!(self, starting_indexes, others, exit; loss_value_destroyed.height);
|
||||
sum_others!(self, starting_indexes, others, exit; sent_in_profit.base.sats.height);
|
||||
sum_others!(self, starting_indexes, others, exit; sent_in_loss.base.sats.height);
|
||||
|
||||
// Investor price aggregation from raw values
|
||||
let investor_price_dep_version = others
|
||||
.iter()
|
||||
.map(|o| o.investor_price.cents.height.version())
|
||||
.fold(vecdb::Version::ZERO, |acc, v| acc + v);
|
||||
self.investor_price
|
||||
.cents
|
||||
.height
|
||||
.validate_computed_version_or_reset(investor_price_dep_version)?;
|
||||
|
||||
let start = self
|
||||
.cap_raw
|
||||
.len()
|
||||
.min(self.investor_cap_raw.len())
|
||||
.min(self.investor_price.cents.height.len());
|
||||
let end = others.iter().map(|o| o.cap_raw.len()).min().unwrap_or(0);
|
||||
|
||||
let cap_ranges: Vec<Vec<CentsSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.cap_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
let investor_cap_ranges: Vec<Vec<CentsSquaredSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.investor_cap_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
|
||||
for i in start..end {
|
||||
let height = Height::from(i);
|
||||
let local_i = i - start;
|
||||
|
||||
let mut sum_cap = CentsSats::ZERO;
|
||||
let mut sum_investor_cap = CentsSquaredSats::ZERO;
|
||||
|
||||
for idx in 0..others.len() {
|
||||
sum_cap += cap_ranges[idx][local_i];
|
||||
sum_investor_cap += investor_cap_ranges[idx][local_i];
|
||||
}
|
||||
|
||||
self.cap_raw.truncate_push(height, sum_cap)?;
|
||||
self.investor_cap_raw
|
||||
.truncate_push(height, sum_investor_cap)?;
|
||||
|
||||
let investor_price = if sum_cap.inner() == 0 {
|
||||
Cents::ZERO
|
||||
} else {
|
||||
Cents::new((sum_investor_cap / sum_cap.inner()) as u64)
|
||||
};
|
||||
self.investor_price
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, investor_price)?;
|
||||
}
|
||||
|
||||
{
|
||||
let _lock = exit.lock();
|
||||
self.investor_price.cents.height.write()?;
|
||||
}
|
||||
|
||||
// Peak regret aggregation
|
||||
self.peak_regret.height.compute_sum_of_others(
|
||||
starting_indexes.height,
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| &v.peak_regret.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
.compute_from_stateful(starting_indexes, others, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -329,7 +251,6 @@ impl RealizedBasic {
|
||||
self.core.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.peak_regret
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -342,7 +263,6 @@ impl RealizedBasic {
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Core computation
|
||||
self.core.compute_rest_part2(
|
||||
blocks,
|
||||
prices,
|
||||
@@ -351,7 +271,7 @@ impl RealizedBasic {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Gross PnL rolling sums
|
||||
// Gross PnL rolling sum
|
||||
let window_starts = blocks.count.window_starts();
|
||||
self.gross_pnl_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
@@ -360,22 +280,6 @@ impl RealizedBasic {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Sent in profit/loss EMAs
|
||||
self.sent_in_profit_ema.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent_in_profit.base.sats.height,
|
||||
&self.sent_in_profit.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.sent_in_loss_ema.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent_in_loss.base.sats.height,
|
||||
&self.sent_in_loss.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Net PnL change 1m
|
||||
self.net_pnl_change_1m.height.compute_rolling_change(
|
||||
starting_indexes.height,
|
||||
@@ -383,15 +287,13 @@ impl RealizedBasic {
|
||||
&self.core.net_realized_pnl.cumulative.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.net_pnl_change_1m_rel_to_realized_cap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_pnl_change_1m.height,
|
||||
&self.core.realized_cap_cents.height,
|
||||
&self.core.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.net_pnl_change_1m_rel_to_market_cap
|
||||
.compute_binary::<CentsSigned, Dollars, RatioCentsSignedDollarsBps32>(
|
||||
starting_indexes.height,
|
||||
@@ -400,6 +302,15 @@ impl RealizedBasic {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Peak regret
|
||||
self.peak_regret_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.peak_regret.height,
|
||||
&self.core.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Investor price ratio and price bands
|
||||
self.investor_price_ratio.compute_ratio(
|
||||
starting_indexes,
|
||||
@@ -408,9 +319,10 @@ impl RealizedBasic {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Use explicit field paths for split borrows
|
||||
self.lower_price_band.cents.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.core.realized_price.cents.height,
|
||||
&self.core.minimal.realized_price.cents.height,
|
||||
&self.investor_price.cents.height,
|
||||
|(i, rp, ip, ..)| {
|
||||
let rp = rp.as_u128();
|
||||
@@ -427,7 +339,7 @@ impl RealizedBasic {
|
||||
self.upper_price_band.cents.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.investor_price.cents.height,
|
||||
&self.core.realized_price.cents.height,
|
||||
&self.core.minimal.realized_price.cents.height,
|
||||
|(i, ip, rp, ..)| {
|
||||
let ip = ip.as_u128();
|
||||
let rp = rp.as_u128();
|
||||
@@ -450,7 +362,7 @@ impl RealizedBasic {
|
||||
ssrr.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&rv.height,
|
||||
&self.core.realized_cap_cents.height,
|
||||
&self.core.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
@@ -463,22 +375,70 @@ impl RealizedBasic {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Peak regret relative to realized cap
|
||||
self.peak_regret_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
// Extended: realized profit/loss rolling sums
|
||||
let window_starts = blocks.count.window_starts();
|
||||
self.realized_profit_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.minimal.realized_profit.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.minimal.realized_loss.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Realized cap relative to own market cap
|
||||
self.realized_cap_rel_to_own_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.peak_regret.height,
|
||||
&self.core.realized_cap_cents.height,
|
||||
&self.core.minimal.realized_cap.height,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Realized price ratio percentiles
|
||||
self.realized_price_ratio_percentiles.compute(
|
||||
// Realized profit to loss ratios
|
||||
for ((ratio, profit), loss) in self
|
||||
.realized_profit_to_loss_ratio
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.realized_profit_sum.as_array())
|
||||
.zip(self.realized_loss_sum.as_array())
|
||||
{
|
||||
ratio.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&profit.height,
|
||||
&loss.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Realized price stddev bands
|
||||
self.realized_price_ratio_std_dev.compute(
|
||||
blocks,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&self.core.realized_price_ratio.ratio.height,
|
||||
&self.core.realized_price.cents.height,
|
||||
&self.core.minimal.realized_price_ratio.ratio.height,
|
||||
&self.core.minimal.realized_price.cents.height,
|
||||
)?;
|
||||
|
||||
// Investor price: percentiles + stddev bands
|
||||
let investor_price = &self.investor_price.cents.height;
|
||||
self.investor_price_ratio_percentiles.compute(
|
||||
blocks,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&self.investor_price_ratio.ratio.height,
|
||||
investor_price,
|
||||
)?;
|
||||
self.investor_price_ratio_std_dev.compute(
|
||||
blocks,
|
||||
starting_indexes,
|
||||
exit,
|
||||
&self.investor_price_ratio.ratio.height,
|
||||
investor_price,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
151
crates/brk_computer/src/distribution/metrics/realized/minimal.rs
Normal file
151
crates/brk_computer/src/distribution/metrics/realized/minimal.rs
Normal file
@@ -0,0 +1,151 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints32, Bitcoin, Cents, Dollars, Height, Indexes, Sats, StoredF32, Version,
|
||||
};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::state::RealizedOps,
|
||||
internal::{
|
||||
CentsUnsignedToDollars, ComputedFromHeight, ComputedFromHeightCumulative,
|
||||
ComputedFromHeightRatio, Identity, LazyFromHeight, Price,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedMinimal<M: StorageMode = Rw> {
|
||||
pub realized_cap_cents: ComputedFromHeight<Cents, M>,
|
||||
pub realized_profit: ComputedFromHeightCumulative<Cents, M>,
|
||||
pub realized_loss: ComputedFromHeightCumulative<Cents, M>,
|
||||
pub realized_cap: LazyFromHeight<Dollars, Cents>,
|
||||
pub realized_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub realized_price_ratio: ComputedFromHeightRatio<M>,
|
||||
pub mvrv: LazyFromHeight<StoredF32>,
|
||||
}
|
||||
|
||||
impl RealizedMinimal {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let realized_cap_cents = cfg.import_computed("realized_cap_cents", Version::ZERO)?;
|
||||
let realized_cap = LazyFromHeight::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("realized_cap"),
|
||||
cfg.version,
|
||||
realized_cap_cents.height.read_only_boxed_clone(),
|
||||
&realized_cap_cents,
|
||||
);
|
||||
|
||||
let realized_profit = cfg.import_cumulative("realized_profit", Version::ZERO)?;
|
||||
let realized_loss = cfg.import_cumulative("realized_loss", Version::ZERO)?;
|
||||
|
||||
let realized_price = cfg.import_price("realized_price", Version::ONE)?;
|
||||
let realized_price_ratio = cfg.import_ratio("realized_price", Version::ONE)?;
|
||||
let mvrv = LazyFromHeight::from_lazy::<Identity<StoredF32>, BasisPoints32>(
|
||||
&cfg.name("mvrv"),
|
||||
cfg.version,
|
||||
&realized_price_ratio.ratio,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
realized_cap_cents,
|
||||
realized_profit,
|
||||
realized_loss,
|
||||
realized_cap,
|
||||
realized_price,
|
||||
realized_price_ratio,
|
||||
mvrv,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.realized_cap_cents
|
||||
.height
|
||||
.len()
|
||||
.min(self.realized_profit.height.len())
|
||||
.min(self.realized_loss.height.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(
|
||||
&mut self,
|
||||
height: Height,
|
||||
state: &impl RealizedOps,
|
||||
) -> Result<()> {
|
||||
self.realized_cap_cents
|
||||
.height
|
||||
.truncate_push(height, state.cap())?;
|
||||
self.realized_profit
|
||||
.height
|
||||
.truncate_push(height, state.profit())?;
|
||||
self.realized_loss
|
||||
.height
|
||||
.truncate_push(height, state.loss())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.realized_cap_cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.realized_profit.height,
|
||||
&mut self.realized_loss.height,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
sum_others!(self, starting_indexes, others, exit; realized_cap_cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; realized_profit.height);
|
||||
sum_others!(self, starting_indexes, others, exit; realized_loss.height);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.realized_profit
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.realized_loss
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.realized_price.cents.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.realized_cap_cents.height,
|
||||
height_to_supply,
|
||||
|(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))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.realized_price_ratio.compute_ratio(
|
||||
starting_indexes,
|
||||
&prices.price.cents.height,
|
||||
&self.realized_price.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,9 @@
|
||||
mod adjusted;
|
||||
mod base;
|
||||
mod complete;
|
||||
mod core;
|
||||
mod extended;
|
||||
|
||||
mod with_extended;
|
||||
mod full;
|
||||
mod minimal;
|
||||
|
||||
pub use adjusted::*;
|
||||
pub use base::*;
|
||||
pub use complete::*;
|
||||
pub use core::*;
|
||||
pub use extended::*;
|
||||
|
||||
pub use with_extended::*;
|
||||
pub use full::*;
|
||||
pub use minimal::*;
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Height, Indexes};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{blocks, prices};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
use super::{RealizedFull, RealizedExtended};
|
||||
|
||||
/// Realized metrics with guaranteed extended (no Option).
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct RealizedWithExtended<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: RealizedFull<M>,
|
||||
#[traversable(flatten)]
|
||||
pub extended: RealizedExtended<M>,
|
||||
}
|
||||
|
||||
impl RealizedWithExtended {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let base = RealizedFull::forced_import(cfg)?;
|
||||
let extended = RealizedExtended::forced_import(cfg)?;
|
||||
Ok(Self { base, extended })
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.base.compute_rest_part2(
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_supply,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.extended.compute_rest_part2(
|
||||
&self.base,
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,71 +1,107 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, BasisPointsSigned32, Dollars, Height, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
use brk_types::{BasisPoints16, BasisPointsSigned32, Dollars, Height, Sats, StoredF32, Version};
|
||||
use vecdb::{Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::internal::{NegRatioDollarsBps32, PercentFromHeight, RatioDollarsBp16};
|
||||
use crate::internal::{
|
||||
Bps32ToFloat, LazyFromHeight, NegRatioDollarsBps32, PercentFromHeight, RatioDollarsBp16,
|
||||
RatioDollarsBps32, RatioSatsBp16,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedFull, UnrealizedFull};
|
||||
use crate::distribution::metrics::{ImportConfig, UnrealizedBase};
|
||||
|
||||
use super::RelativeComplete;
|
||||
|
||||
/// Full relative metrics (Source/Extended tier).
|
||||
/// Relative metrics for the Complete tier (~6 fields).
|
||||
///
|
||||
/// Contains all Complete-tier fields (via Deref to RelativeComplete) plus:
|
||||
/// - Source-only: neg_unrealized_loss_rel_to_market_cap, invested_capital_in_profit/loss_rel_to_realized_cap
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
/// Excludes source-only fields (invested_capital_in_profit/loss_rel_to_realized_cap).
|
||||
#[derive(Traversable)]
|
||||
pub struct RelativeBase<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub complete: RelativeComplete<M>,
|
||||
pub supply_in_profit_rel_to_own_supply: PercentFromHeight<BasisPoints16, M>,
|
||||
pub supply_in_loss_rel_to_own_supply: PercentFromHeight<BasisPoints16, M>,
|
||||
|
||||
// --- Source-only fields ---
|
||||
pub unrealized_profit_rel_to_market_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub unrealized_loss_rel_to_market_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub net_unrealized_pnl_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub neg_unrealized_loss_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
|
||||
pub invested_capital_in_profit_rel_to_realized_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub invested_capital_in_loss_rel_to_realized_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub nupl: LazyFromHeight<StoredF32, BasisPointsSigned32>,
|
||||
}
|
||||
|
||||
impl RelativeBase {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let complete = RelativeComplete::forced_import(cfg)?;
|
||||
let v1 = Version::ONE;
|
||||
let v2 = Version::new(2);
|
||||
|
||||
let net_unrealized_pnl_rel_to_market_cap =
|
||||
cfg.import_percent_bps32("net_unrealized_pnl_rel_to_market_cap", Version::new(3))?;
|
||||
|
||||
let nupl = LazyFromHeight::from_computed::<Bps32ToFloat>(
|
||||
&cfg.name("nupl"),
|
||||
cfg.version + Version::new(3),
|
||||
net_unrealized_pnl_rel_to_market_cap
|
||||
.bps
|
||||
.height
|
||||
.read_only_boxed_clone(),
|
||||
&net_unrealized_pnl_rel_to_market_cap.bps,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
complete,
|
||||
supply_in_profit_rel_to_own_supply: cfg
|
||||
.import_percent_bp16("supply_in_profit_rel_to_own_supply", v1)?,
|
||||
supply_in_loss_rel_to_own_supply: cfg
|
||||
.import_percent_bp16("supply_in_loss_rel_to_own_supply", v1)?,
|
||||
unrealized_profit_rel_to_market_cap: cfg
|
||||
.import_percent_bp16("unrealized_profit_rel_to_market_cap", v2)?,
|
||||
unrealized_loss_rel_to_market_cap: cfg
|
||||
.import_percent_bp16("unrealized_loss_rel_to_market_cap", v2)?,
|
||||
net_unrealized_pnl_rel_to_market_cap,
|
||||
neg_unrealized_loss_rel_to_market_cap: cfg
|
||||
.import_percent_bps32("neg_unrealized_loss_rel_to_market_cap", Version::new(3))?,
|
||||
invested_capital_in_profit_rel_to_realized_cap: cfg.import_percent_bp16(
|
||||
"invested_capital_in_profit_rel_to_realized_cap",
|
||||
Version::ZERO,
|
||||
)?,
|
||||
invested_capital_in_loss_rel_to_realized_cap: cfg.import_percent_bp16(
|
||||
"invested_capital_in_loss_rel_to_realized_cap",
|
||||
Version::ZERO,
|
||||
)?,
|
||||
nupl,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedFull,
|
||||
realized: &RealizedFull,
|
||||
unrealized: &UnrealizedBase,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute Complete-tier fields
|
||||
self.complete.compute(
|
||||
max_from,
|
||||
&unrealized.complete,
|
||||
supply_total_sats,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Source-only
|
||||
self.supply_in_profit_rel_to_own_supply
|
||||
.compute_binary::<Sats, Sats, RatioSatsBp16>(
|
||||
max_from,
|
||||
&unrealized.supply_in_profit.sats.height,
|
||||
supply_total_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.supply_in_loss_rel_to_own_supply
|
||||
.compute_binary::<Sats, Sats, RatioSatsBp16>(
|
||||
max_from,
|
||||
&unrealized.supply_in_loss.sats.height,
|
||||
supply_total_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized_profit_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.unrealized_profit.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized_loss_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.unrealized_loss.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.net_unrealized_pnl_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBps32>(
|
||||
max_from,
|
||||
&unrealized.net_unrealized_pnl.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.neg_unrealized_loss_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, NegRatioDollarsBps32>(
|
||||
max_from,
|
||||
@@ -73,20 +109,6 @@ impl RelativeBase {
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.invested_capital_in_profit_rel_to_realized_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.invested_capital_in_profit.usd.height,
|
||||
&realized.realized_cap.height,
|
||||
exit,
|
||||
)?;
|
||||
self.invested_capital_in_loss_rel_to_realized_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.invested_capital_in_loss.usd.height,
|
||||
&realized.realized_cap.height,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, BasisPointsSigned32, Dollars, Height, Sats, StoredF32, Version};
|
||||
use vecdb::{Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::internal::{
|
||||
Bps32ToFloat, LazyFromHeight, PercentFromHeight, RatioDollarsBp16, RatioDollarsBps32,
|
||||
RatioSatsBp16,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, UnrealizedComplete};
|
||||
|
||||
/// Relative metrics for the Complete tier (~6 fields).
|
||||
///
|
||||
/// Excludes source-only fields (invested_capital_in_profit/loss_rel_to_realized_cap,
|
||||
/// neg_unrealized_loss_rel_to_market_cap).
|
||||
#[derive(Traversable)]
|
||||
pub struct RelativeComplete<M: StorageMode = Rw> {
|
||||
pub supply_in_profit_rel_to_own_supply: PercentFromHeight<BasisPoints16, M>,
|
||||
pub supply_in_loss_rel_to_own_supply: PercentFromHeight<BasisPoints16, M>,
|
||||
|
||||
pub unrealized_profit_rel_to_market_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub unrealized_loss_rel_to_market_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub net_unrealized_pnl_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub nupl: LazyFromHeight<StoredF32, BasisPointsSigned32>,
|
||||
}
|
||||
|
||||
impl RelativeComplete {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v1 = Version::ONE;
|
||||
let v2 = Version::new(2);
|
||||
|
||||
let net_unrealized_pnl_rel_to_market_cap =
|
||||
cfg.import_percent_bps32("net_unrealized_pnl_rel_to_market_cap", Version::new(3))?;
|
||||
|
||||
let nupl = LazyFromHeight::from_computed::<Bps32ToFloat>(
|
||||
&cfg.name("nupl"),
|
||||
cfg.version + Version::new(3),
|
||||
net_unrealized_pnl_rel_to_market_cap
|
||||
.bps
|
||||
.height
|
||||
.read_only_boxed_clone(),
|
||||
&net_unrealized_pnl_rel_to_market_cap.bps,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
supply_in_profit_rel_to_own_supply: cfg
|
||||
.import_percent_bp16("supply_in_profit_rel_to_own_supply", v1)?,
|
||||
supply_in_loss_rel_to_own_supply: cfg
|
||||
.import_percent_bp16("supply_in_loss_rel_to_own_supply", v1)?,
|
||||
unrealized_profit_rel_to_market_cap: cfg
|
||||
.import_percent_bp16("unrealized_profit_rel_to_market_cap", v2)?,
|
||||
unrealized_loss_rel_to_market_cap: cfg
|
||||
.import_percent_bp16("unrealized_loss_rel_to_market_cap", v2)?,
|
||||
net_unrealized_pnl_rel_to_market_cap,
|
||||
nupl,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedComplete,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.supply_in_profit_rel_to_own_supply
|
||||
.compute_binary::<Sats, Sats, RatioSatsBp16>(
|
||||
max_from,
|
||||
&unrealized.supply_in_profit.sats.height,
|
||||
supply_total_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.supply_in_loss_rel_to_own_supply
|
||||
.compute_binary::<Sats, Sats, RatioSatsBp16>(
|
||||
max_from,
|
||||
&unrealized.supply_in_loss.sats.height,
|
||||
supply_total_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized_profit_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.unrealized_profit.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized_loss_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.unrealized_loss.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.net_unrealized_pnl_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBps32>(
|
||||
max_from,
|
||||
&unrealized.net_unrealized_pnl.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@ use brk_types::{Dollars, Height, Sats};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedFull, UnrealizedFull};
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedBase, UnrealizedFull};
|
||||
|
||||
use super::{RelativeBase, RelativeExtendedOwnPnl};
|
||||
use super::{RelativeFull, RelativeExtendedOwnPnl};
|
||||
|
||||
/// Relative metrics for the "all" cohort (base + own_pnl, NO rel_to_all).
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
@@ -14,7 +14,7 @@ pub struct RelativeForAll<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: RelativeBase<M>,
|
||||
pub base: RelativeFull<M>,
|
||||
#[traversable(flatten)]
|
||||
pub extended_own_pnl: RelativeExtendedOwnPnl<M>,
|
||||
}
|
||||
@@ -22,7 +22,7 @@ pub struct RelativeForAll<M: StorageMode = Rw> {
|
||||
impl RelativeForAll {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
base: RelativeBase::forced_import(cfg)?,
|
||||
base: RelativeFull::forced_import(cfg)?,
|
||||
extended_own_pnl: RelativeExtendedOwnPnl::forced_import(cfg)?,
|
||||
})
|
||||
}
|
||||
@@ -31,7 +31,7 @@ impl RelativeForAll {
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedFull,
|
||||
realized: &RealizedFull,
|
||||
realized: &RealizedBase,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, Dollars, Height, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::internal::{PercentFromHeight, RatioDollarsBp16};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedBase, UnrealizedFull};
|
||||
|
||||
use super::RelativeBase;
|
||||
|
||||
/// Full relative metrics (Source/Extended tier).
|
||||
///
|
||||
/// Contains all Complete-tier fields (via Deref to RelativeBase) plus:
|
||||
/// - Source-only: invested_capital_in_profit/loss_rel_to_realized_cap
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct RelativeFull<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: RelativeBase<M>,
|
||||
|
||||
// --- Source-only fields ---
|
||||
pub invested_capital_in_profit_rel_to_realized_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub invested_capital_in_loss_rel_to_realized_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
}
|
||||
|
||||
impl RelativeFull {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let base = RelativeBase::forced_import(cfg)?;
|
||||
|
||||
Ok(Self {
|
||||
base,
|
||||
invested_capital_in_profit_rel_to_realized_cap: cfg.import_percent_bp16(
|
||||
"invested_capital_in_profit_rel_to_realized_cap",
|
||||
Version::ZERO,
|
||||
)?,
|
||||
invested_capital_in_loss_rel_to_realized_cap: cfg.import_percent_bp16(
|
||||
"invested_capital_in_loss_rel_to_realized_cap",
|
||||
Version::ZERO,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedFull,
|
||||
realized: &RealizedBase,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute Complete-tier fields
|
||||
self.base.compute(
|
||||
max_from,
|
||||
&unrealized.base,
|
||||
supply_total_sats,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Source-only
|
||||
self.invested_capital_in_profit_rel_to_realized_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.invested_capital_in_profit.usd.height,
|
||||
&realized.realized_cap.height,
|
||||
exit,
|
||||
)?;
|
||||
self.invested_capital_in_loss_rel_to_realized_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.invested_capital_in_loss.usd.height,
|
||||
&realized.realized_cap.height,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
mod base;
|
||||
mod complete;
|
||||
mod extended_own_market_cap;
|
||||
mod extended_own_pnl;
|
||||
mod for_all;
|
||||
mod full;
|
||||
|
||||
mod to_all;
|
||||
mod with_extended;
|
||||
mod with_rel_to_all;
|
||||
mod with_rel_to_all_complete;
|
||||
mod with_rel_to_all_base;
|
||||
|
||||
pub use base::*;
|
||||
pub use complete::*;
|
||||
pub use extended_own_market_cap::*;
|
||||
pub use extended_own_pnl::*;
|
||||
pub use for_all::*;
|
||||
pub use full::*;
|
||||
|
||||
pub use to_all::*;
|
||||
pub use with_extended::*;
|
||||
pub use with_rel_to_all::*;
|
||||
pub use with_rel_to_all_complete::*;
|
||||
pub use with_rel_to_all_base::*;
|
||||
|
||||
@@ -4,9 +4,9 @@ use brk_types::{Dollars, Height, Sats};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedFull, UnrealizedFull};
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedBase, UnrealizedFull};
|
||||
|
||||
use super::{RelativeBase, RelativeExtendedOwnMarketCap, RelativeExtendedOwnPnl, RelativeToAll};
|
||||
use super::{RelativeFull, RelativeExtendedOwnMarketCap, RelativeExtendedOwnPnl, RelativeToAll};
|
||||
|
||||
/// Full extended relative metrics (base + rel_to_all + own_market_cap + own_pnl).
|
||||
/// Used by: sth, lth, age_range cohorts.
|
||||
@@ -15,7 +15,7 @@ pub struct RelativeWithExtended<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: RelativeBase<M>,
|
||||
pub base: RelativeFull<M>,
|
||||
#[traversable(flatten)]
|
||||
pub rel_to_all: RelativeToAll<M>,
|
||||
#[traversable(flatten)]
|
||||
@@ -27,7 +27,7 @@ pub struct RelativeWithExtended<M: StorageMode = Rw> {
|
||||
impl RelativeWithExtended {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
base: RelativeBase::forced_import(cfg)?,
|
||||
base: RelativeFull::forced_import(cfg)?,
|
||||
rel_to_all: RelativeToAll::forced_import(cfg)?,
|
||||
extended_own_market_cap: RelativeExtendedOwnMarketCap::forced_import(cfg)?,
|
||||
extended_own_pnl: RelativeExtendedOwnPnl::forced_import(cfg)?,
|
||||
@@ -39,7 +39,7 @@ impl RelativeWithExtended {
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedFull,
|
||||
realized: &RealizedFull,
|
||||
realized: &RealizedBase,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
all_supply_sats: &impl ReadableVec<Height, Sats>,
|
||||
|
||||
@@ -4,9 +4,9 @@ use brk_types::{Dollars, Height, Sats};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedFull, UnrealizedFull};
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedBase, UnrealizedFull};
|
||||
|
||||
use super::{RelativeBase, RelativeToAll};
|
||||
use super::{RelativeFull, RelativeToAll};
|
||||
|
||||
/// Relative metrics with rel_to_all (no extended, no peak_regret).
|
||||
/// Used by: epoch, year, type, amount, address cohorts.
|
||||
@@ -15,7 +15,7 @@ pub struct RelativeWithRelToAll<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: RelativeBase<M>,
|
||||
pub base: RelativeFull<M>,
|
||||
#[traversable(flatten)]
|
||||
pub rel_to_all: RelativeToAll<M>,
|
||||
}
|
||||
@@ -23,7 +23,7 @@ pub struct RelativeWithRelToAll<M: StorageMode = Rw> {
|
||||
impl RelativeWithRelToAll {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
base: RelativeBase::forced_import(cfg)?,
|
||||
base: RelativeFull::forced_import(cfg)?,
|
||||
rel_to_all: RelativeToAll::forced_import(cfg)?,
|
||||
})
|
||||
}
|
||||
@@ -33,7 +33,7 @@ impl RelativeWithRelToAll {
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedFull,
|
||||
realized: &RealizedFull,
|
||||
realized: &RealizedBase,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
all_supply_sats: &impl ReadableVec<Height, Sats>,
|
||||
|
||||
@@ -4,26 +4,26 @@ use brk_types::{Dollars, Height, Sats};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, UnrealizedComplete};
|
||||
use crate::distribution::metrics::{ImportConfig, UnrealizedBase};
|
||||
|
||||
use super::{RelativeComplete, RelativeToAll};
|
||||
use super::{RelativeBase, RelativeToAll};
|
||||
|
||||
/// Complete relative metrics with rel_to_all.
|
||||
/// Used by CompleteCohortMetrics (epoch, class, min_age, max_age).
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct RelativeCompleteWithRelToAll<M: StorageMode = Rw> {
|
||||
pub struct RelativeBaseWithRelToAll<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: RelativeComplete<M>,
|
||||
pub base: RelativeBase<M>,
|
||||
#[traversable(flatten)]
|
||||
pub rel_to_all: RelativeToAll<M>,
|
||||
}
|
||||
|
||||
impl RelativeCompleteWithRelToAll {
|
||||
impl RelativeBaseWithRelToAll {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
base: RelativeComplete::forced_import(cfg)?,
|
||||
base: RelativeBase::forced_import(cfg)?,
|
||||
rel_to_all: RelativeToAll::forced_import(cfg)?,
|
||||
})
|
||||
}
|
||||
@@ -31,7 +31,7 @@ impl RelativeCompleteWithRelToAll {
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedComplete,
|
||||
unrealized: &UnrealizedBase,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
all_supply_sats: &impl ReadableVec<Height, Sats>,
|
||||
@@ -1,93 +1,78 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, CentsSats, CentsSigned, CentsSquaredSats, Height, Indexes, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, AnyVec, BytesVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
use brk_types::{Cents, CentsSigned, Height, Indexes, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::state::UnrealizedState,
|
||||
internal::{CentsSubtractToCentsSigned, FiatFromHeight},
|
||||
prices,
|
||||
internal::{
|
||||
CentsSubtractToCentsSigned, FiatFromHeight, LazyFromHeight, NegCentsUnsignedToDollars,
|
||||
ValueFromHeight,
|
||||
},
|
||||
};
|
||||
|
||||
use brk_types::Dollars;
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
use super::UnrealizedComplete;
|
||||
|
||||
/// Full unrealized metrics (Source/Extended tier).
|
||||
/// Unrealized metrics for the Complete tier (~6 fields).
|
||||
///
|
||||
/// Contains all Complete-tier fields (via Deref to UnrealizedComplete) plus:
|
||||
/// - Source-only: invested_capital, raw BytesVecs, unrealized_gross_pnl
|
||||
/// - Extended-only: pain_index, greed_index, net_sentiment
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct UnrealizedFull<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub complete: UnrealizedComplete<M>,
|
||||
/// Excludes source-only fields (invested_capital, raw BytesVecs)
|
||||
/// and extended-only fields (pain_index, greed_index, net_sentiment).
|
||||
#[derive(Traversable)]
|
||||
pub struct UnrealizedBase<M: StorageMode = Rw> {
|
||||
pub supply_in_profit: ValueFromHeight<M>,
|
||||
pub supply_in_loss: ValueFromHeight<M>,
|
||||
|
||||
// --- Source-only fields ---
|
||||
pub invested_capital_in_profit: FiatFromHeight<Cents, M>,
|
||||
pub invested_capital_in_loss: FiatFromHeight<Cents, M>,
|
||||
pub unrealized_profit: FiatFromHeight<Cents, M>,
|
||||
pub unrealized_loss: FiatFromHeight<Cents, M>,
|
||||
|
||||
pub invested_capital_in_profit_raw: M::Stored<BytesVec<Height, CentsSats>>,
|
||||
pub invested_capital_in_loss_raw: M::Stored<BytesVec<Height, CentsSats>>,
|
||||
pub investor_cap_in_profit_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
pub investor_cap_in_loss_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
pub neg_unrealized_loss: LazyFromHeight<Dollars, Cents>,
|
||||
|
||||
pub gross_pnl: FiatFromHeight<Cents, M>,
|
||||
|
||||
// --- Extended-only fields ---
|
||||
pub pain_index: FiatFromHeight<Cents, M>,
|
||||
pub greed_index: FiatFromHeight<Cents, M>,
|
||||
pub net_sentiment: FiatFromHeight<CentsSigned, M>,
|
||||
pub net_unrealized_pnl: FiatFromHeight<CentsSigned, M>,
|
||||
}
|
||||
|
||||
impl UnrealizedFull {
|
||||
impl UnrealizedBase {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
let supply_in_profit = cfg.import_value("supply_in_profit", v0)?;
|
||||
let supply_in_loss = cfg.import_value("supply_in_loss", v0)?;
|
||||
|
||||
let complete = UnrealizedComplete::forced_import(cfg)?;
|
||||
let unrealized_profit = cfg.import_fiat("unrealized_profit", v0)?;
|
||||
let unrealized_loss = cfg.import_fiat("unrealized_loss", v0)?;
|
||||
|
||||
let invested_capital_in_profit = cfg.import_fiat("invested_capital_in_profit", v0)?;
|
||||
let invested_capital_in_loss = cfg.import_fiat("invested_capital_in_loss", v0)?;
|
||||
|
||||
let invested_capital_in_profit_raw =
|
||||
cfg.import_bytes("invested_capital_in_profit_raw", v0)?;
|
||||
let invested_capital_in_loss_raw = cfg.import_bytes("invested_capital_in_loss_raw", v0)?;
|
||||
let investor_cap_in_profit_raw = cfg.import_bytes("investor_cap_in_profit_raw", v0)?;
|
||||
let investor_cap_in_loss_raw = cfg.import_bytes("investor_cap_in_loss_raw", v0)?;
|
||||
|
||||
let pain_index = cfg.import_fiat("pain_index", v0)?;
|
||||
let greed_index = cfg.import_fiat("greed_index", v0)?;
|
||||
let net_sentiment = cfg.import_fiat("net_sentiment", Version::ONE)?;
|
||||
let neg_unrealized_loss = LazyFromHeight::from_computed::<NegCentsUnsignedToDollars>(
|
||||
&cfg.name("neg_unrealized_loss"),
|
||||
cfg.version,
|
||||
unrealized_loss.cents.height.read_only_boxed_clone(),
|
||||
&unrealized_loss.cents,
|
||||
);
|
||||
|
||||
let gross_pnl = cfg.import_fiat("unrealized_gross_pnl", v0)?;
|
||||
|
||||
let net_unrealized_pnl = cfg.import_fiat("net_unrealized_pnl", v0)?;
|
||||
|
||||
Ok(Self {
|
||||
complete,
|
||||
invested_capital_in_profit,
|
||||
invested_capital_in_loss,
|
||||
invested_capital_in_profit_raw,
|
||||
invested_capital_in_loss_raw,
|
||||
investor_cap_in_profit_raw,
|
||||
investor_cap_in_loss_raw,
|
||||
pain_index,
|
||||
greed_index,
|
||||
net_sentiment,
|
||||
supply_in_profit,
|
||||
supply_in_loss,
|
||||
unrealized_profit,
|
||||
unrealized_loss,
|
||||
neg_unrealized_loss,
|
||||
gross_pnl,
|
||||
net_unrealized_pnl,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.complete
|
||||
.min_stateful_height_len()
|
||||
.min(self.invested_capital_in_profit.cents.height.len())
|
||||
.min(self.invested_capital_in_loss.cents.height.len())
|
||||
.min(self.invested_capital_in_profit_raw.len())
|
||||
.min(self.invested_capital_in_loss_raw.len())
|
||||
.min(self.investor_cap_in_profit_raw.len())
|
||||
.min(self.investor_cap_in_loss_raw.len())
|
||||
self.supply_in_profit
|
||||
.sats
|
||||
.height
|
||||
.len()
|
||||
.min(self.supply_in_loss.sats.height.len())
|
||||
.min(self.unrealized_profit.cents.height.len())
|
||||
.min(self.unrealized_loss.cents.height.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(
|
||||
@@ -95,46 +80,35 @@ impl UnrealizedFull {
|
||||
height: Height,
|
||||
height_state: &UnrealizedState,
|
||||
) -> Result<()> {
|
||||
self.complete.truncate_push(height, height_state)?;
|
||||
|
||||
self.invested_capital_in_profit
|
||||
self.supply_in_profit
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, height_state.supply_in_profit)?;
|
||||
self.supply_in_loss
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, height_state.supply_in_loss)?;
|
||||
self.unrealized_profit
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, height_state.invested_capital_in_profit)?;
|
||||
self.invested_capital_in_loss
|
||||
.truncate_push(height, height_state.unrealized_profit)?;
|
||||
self.unrealized_loss
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, height_state.invested_capital_in_loss)?;
|
||||
|
||||
self.invested_capital_in_profit_raw.truncate_push(
|
||||
height,
|
||||
CentsSats::new(height_state.invested_capital_in_profit_raw),
|
||||
)?;
|
||||
self.invested_capital_in_loss_raw.truncate_push(
|
||||
height,
|
||||
CentsSats::new(height_state.invested_capital_in_loss_raw),
|
||||
)?;
|
||||
self.investor_cap_in_profit_raw.truncate_push(
|
||||
height,
|
||||
CentsSquaredSats::new(height_state.investor_cap_in_profit_raw),
|
||||
)?;
|
||||
self.investor_cap_in_loss_raw.truncate_push(
|
||||
height,
|
||||
CentsSquaredSats::new(height_state.investor_cap_in_loss_raw),
|
||||
)?;
|
||||
.truncate_push(height, height_state.unrealized_loss)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.complete.collect_vecs_mut();
|
||||
vecs.push(&mut self.invested_capital_in_profit.cents.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.invested_capital_in_loss.cents.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.invested_capital_in_profit_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.invested_capital_in_loss_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.investor_cap_in_profit_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.investor_cap_in_loss_raw as &mut dyn AnyStoredVec);
|
||||
vecs
|
||||
vec![
|
||||
&mut self.supply_in_profit.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.supply_in_profit.base.cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.supply_in_loss.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.supply_in_loss.base.cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.unrealized_profit.cents.height,
|
||||
&mut self.unrealized_loss.cents.height,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
@@ -143,149 +117,37 @@ impl UnrealizedFull {
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Delegate Complete-tier aggregation
|
||||
let complete_refs: Vec<&UnrealizedComplete> =
|
||||
others.iter().map(|o| &o.complete).collect();
|
||||
self.complete
|
||||
.compute_from_stateful(starting_indexes, &complete_refs, exit)?;
|
||||
|
||||
// Source-only: invested_capital
|
||||
sum_others!(self, starting_indexes, others, exit; invested_capital_in_profit.cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; invested_capital_in_loss.cents.height);
|
||||
|
||||
// Source-only: raw BytesVec aggregation
|
||||
let start = self
|
||||
.invested_capital_in_profit_raw
|
||||
.len()
|
||||
.min(self.invested_capital_in_loss_raw.len())
|
||||
.min(self.investor_cap_in_profit_raw.len())
|
||||
.min(self.investor_cap_in_loss_raw.len());
|
||||
let end = others
|
||||
.iter()
|
||||
.map(|o| o.invested_capital_in_profit_raw.len())
|
||||
.min()
|
||||
.unwrap_or(0);
|
||||
|
||||
// Pre-collect all cohort data to avoid per-element BytesVec reads in nested loop
|
||||
let invested_profit_ranges: Vec<Vec<CentsSats>> = others
|
||||
.iter()
|
||||
.map(|o| {
|
||||
o.invested_capital_in_profit_raw
|
||||
.collect_range_at(start, end)
|
||||
})
|
||||
.collect();
|
||||
let invested_loss_ranges: Vec<Vec<CentsSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.invested_capital_in_loss_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
let investor_profit_ranges: Vec<Vec<CentsSquaredSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.investor_cap_in_profit_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
let investor_loss_ranges: Vec<Vec<CentsSquaredSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.investor_cap_in_loss_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
|
||||
for i in start..end {
|
||||
let height = Height::from(i);
|
||||
let local_i = i - start;
|
||||
|
||||
let mut sum_invested_profit = CentsSats::ZERO;
|
||||
let mut sum_invested_loss = CentsSats::ZERO;
|
||||
let mut sum_investor_profit = CentsSquaredSats::ZERO;
|
||||
let mut sum_investor_loss = CentsSquaredSats::ZERO;
|
||||
|
||||
for idx in 0..others.len() {
|
||||
sum_invested_profit += invested_profit_ranges[idx][local_i];
|
||||
sum_invested_loss += invested_loss_ranges[idx][local_i];
|
||||
sum_investor_profit += investor_profit_ranges[idx][local_i];
|
||||
sum_investor_loss += investor_loss_ranges[idx][local_i];
|
||||
}
|
||||
|
||||
self.invested_capital_in_profit_raw
|
||||
.truncate_push(height, sum_invested_profit)?;
|
||||
self.invested_capital_in_loss_raw
|
||||
.truncate_push(height, sum_invested_loss)?;
|
||||
self.investor_cap_in_profit_raw
|
||||
.truncate_push(height, sum_investor_profit)?;
|
||||
self.investor_cap_in_loss_raw
|
||||
.truncate_push(height, sum_investor_loss)?;
|
||||
}
|
||||
sum_others!(self, starting_indexes, others, exit; supply_in_profit.sats.height);
|
||||
sum_others!(self, starting_indexes, others, exit; supply_in_loss.sats.height);
|
||||
sum_others!(self, starting_indexes, others, exit; unrealized_profit.cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; unrealized_loss.cents.height);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute derived metrics from stored values + price.
|
||||
/// Compute derived metrics from stored values.
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Complete-tier: net_unrealized_pnl
|
||||
self.complete.compute_rest(starting_indexes, exit)?;
|
||||
|
||||
// Extended-only: Pain index (investor_price_of_losers - spot)
|
||||
self.pain_index.cents.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&self.investor_cap_in_loss_raw,
|
||||
&self.invested_capital_in_loss_raw,
|
||||
&prices.price.cents.height,
|
||||
|(h, investor_cap, invested_cap, spot, ..)| {
|
||||
if invested_cap.inner() == 0 {
|
||||
return (h, Cents::ZERO);
|
||||
}
|
||||
let investor_price_losers = investor_cap.inner() / invested_cap.inner();
|
||||
let spot_u128 = spot.as_u128();
|
||||
(h, Cents::new((investor_price_losers - spot_u128) as u64))
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Extended-only: Greed index (spot - investor_price_of_winners)
|
||||
self.greed_index.cents.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&self.investor_cap_in_profit_raw,
|
||||
&self.invested_capital_in_profit_raw,
|
||||
&prices.price.cents.height,
|
||||
|(h, investor_cap, invested_cap, spot, ..)| {
|
||||
if invested_cap.inner() == 0 {
|
||||
return (h, Cents::ZERO);
|
||||
}
|
||||
let investor_price_winners = investor_cap.inner() / invested_cap.inner();
|
||||
let spot_u128 = spot.as_u128();
|
||||
(h, Cents::new((spot_u128 - investor_price_winners) as u64))
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Source-only: unrealized gross pnl
|
||||
self.gross_pnl.cents.height.compute_add(
|
||||
starting_indexes.height,
|
||||
&self.complete.unrealized_profit.cents.height,
|
||||
&self.complete.unrealized_loss.cents.height,
|
||||
&self.unrealized_profit.cents.height,
|
||||
&self.unrealized_loss.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute net_sentiment.height for separate cohorts (greed - pain).
|
||||
pub(crate) fn compute_net_sentiment_height(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.net_sentiment
|
||||
self.net_unrealized_pnl
|
||||
.cents
|
||||
.height
|
||||
.compute_binary::<Cents, Cents, CentsSubtractToCentsSigned>(
|
||||
starting_indexes.height,
|
||||
&self.greed_index.cents.height,
|
||||
&self.pain_index.cents.height,
|
||||
&self.unrealized_profit.cents.height,
|
||||
&self.unrealized_loss.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, CentsSigned, Height, Indexes, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::state::UnrealizedState,
|
||||
internal::{
|
||||
CentsSubtractToCentsSigned, FiatFromHeight, LazyFromHeight, NegCentsUnsignedToDollars,
|
||||
ValueFromHeight,
|
||||
},
|
||||
};
|
||||
|
||||
use brk_types::Dollars;
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
/// Unrealized metrics for the Complete tier (~6 fields).
|
||||
///
|
||||
/// Excludes source-only fields (invested_capital, raw BytesVecs, unrealized_gross_pnl)
|
||||
/// and extended-only fields (pain_index, greed_index, net_sentiment).
|
||||
#[derive(Traversable)]
|
||||
pub struct UnrealizedComplete<M: StorageMode = Rw> {
|
||||
pub supply_in_profit: ValueFromHeight<M>,
|
||||
pub supply_in_loss: ValueFromHeight<M>,
|
||||
|
||||
pub unrealized_profit: FiatFromHeight<Cents, M>,
|
||||
pub unrealized_loss: FiatFromHeight<Cents, M>,
|
||||
|
||||
pub neg_unrealized_loss: LazyFromHeight<Dollars, Cents>,
|
||||
|
||||
pub net_unrealized_pnl: FiatFromHeight<CentsSigned, M>,
|
||||
}
|
||||
|
||||
impl UnrealizedComplete {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
let supply_in_profit = cfg.import_value("supply_in_profit", v0)?;
|
||||
let supply_in_loss = cfg.import_value("supply_in_loss", v0)?;
|
||||
|
||||
let unrealized_profit = cfg.import_fiat("unrealized_profit", v0)?;
|
||||
let unrealized_loss = cfg.import_fiat("unrealized_loss", v0)?;
|
||||
|
||||
let neg_unrealized_loss = LazyFromHeight::from_computed::<NegCentsUnsignedToDollars>(
|
||||
&cfg.name("neg_unrealized_loss"),
|
||||
cfg.version,
|
||||
unrealized_loss.cents.height.read_only_boxed_clone(),
|
||||
&unrealized_loss.cents,
|
||||
);
|
||||
|
||||
let net_unrealized_pnl = cfg.import_fiat("net_unrealized_pnl", v0)?;
|
||||
|
||||
Ok(Self {
|
||||
supply_in_profit,
|
||||
supply_in_loss,
|
||||
unrealized_profit,
|
||||
unrealized_loss,
|
||||
neg_unrealized_loss,
|
||||
net_unrealized_pnl,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.supply_in_profit
|
||||
.sats
|
||||
.height
|
||||
.len()
|
||||
.min(self.supply_in_loss.sats.height.len())
|
||||
.min(self.unrealized_profit.cents.height.len())
|
||||
.min(self.unrealized_loss.cents.height.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(
|
||||
&mut self,
|
||||
height: Height,
|
||||
height_state: &UnrealizedState,
|
||||
) -> Result<()> {
|
||||
self.supply_in_profit
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, height_state.supply_in_profit)?;
|
||||
self.supply_in_loss
|
||||
.sats
|
||||
.height
|
||||
.truncate_push(height, height_state.supply_in_loss)?;
|
||||
self.unrealized_profit
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, height_state.unrealized_profit)?;
|
||||
self.unrealized_loss
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, height_state.unrealized_loss)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.supply_in_profit.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.supply_in_profit.base.cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.supply_in_loss.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.supply_in_loss.base.cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.unrealized_profit.cents.height,
|
||||
&mut self.unrealized_loss.cents.height,
|
||||
]
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
sum_others!(self, starting_indexes, others, exit; supply_in_profit.sats.height);
|
||||
sum_others!(self, starting_indexes, others, exit; supply_in_loss.sats.height);
|
||||
sum_others!(self, starting_indexes, others, exit; unrealized_profit.cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; unrealized_loss.cents.height);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute derived metrics from stored values.
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.net_unrealized_pnl
|
||||
.cents
|
||||
.height
|
||||
.compute_binary::<Cents, Cents, CentsSubtractToCentsSigned>(
|
||||
starting_indexes.height,
|
||||
&self.unrealized_profit.cents.height,
|
||||
&self.unrealized_loss.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
278
crates/brk_computer/src/distribution/metrics/unrealized/full.rs
Normal file
278
crates/brk_computer/src/distribution/metrics/unrealized/full.rs
Normal file
@@ -0,0 +1,278 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, CentsSats, CentsSigned, CentsSquaredSats, Height, Indexes, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, AnyVec, BytesVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::state::UnrealizedState,
|
||||
internal::{CentsSubtractToCentsSigned, FiatFromHeight},
|
||||
prices,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
use super::UnrealizedBase;
|
||||
|
||||
/// Full unrealized metrics (Source/Extended tier).
|
||||
///
|
||||
/// Contains all Complete-tier fields (via Deref to UnrealizedBase) plus:
|
||||
/// - Source-only: invested_capital, raw BytesVecs
|
||||
/// - Extended-only: pain_index, greed_index, net_sentiment
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct UnrealizedFull<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: UnrealizedBase<M>,
|
||||
|
||||
// --- Source-only fields ---
|
||||
pub invested_capital_in_profit: FiatFromHeight<Cents, M>,
|
||||
pub invested_capital_in_loss: FiatFromHeight<Cents, M>,
|
||||
|
||||
pub invested_capital_in_profit_raw: M::Stored<BytesVec<Height, CentsSats>>,
|
||||
pub invested_capital_in_loss_raw: M::Stored<BytesVec<Height, CentsSats>>,
|
||||
pub investor_cap_in_profit_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
pub investor_cap_in_loss_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
|
||||
// --- Extended-only fields ---
|
||||
pub pain_index: FiatFromHeight<Cents, M>,
|
||||
pub greed_index: FiatFromHeight<Cents, M>,
|
||||
pub net_sentiment: FiatFromHeight<CentsSigned, M>,
|
||||
}
|
||||
|
||||
impl UnrealizedFull {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
|
||||
let base = UnrealizedBase::forced_import(cfg)?;
|
||||
|
||||
let invested_capital_in_profit = cfg.import_fiat("invested_capital_in_profit", v0)?;
|
||||
let invested_capital_in_loss = cfg.import_fiat("invested_capital_in_loss", v0)?;
|
||||
|
||||
let invested_capital_in_profit_raw =
|
||||
cfg.import_bytes("invested_capital_in_profit_raw", v0)?;
|
||||
let invested_capital_in_loss_raw = cfg.import_bytes("invested_capital_in_loss_raw", v0)?;
|
||||
let investor_cap_in_profit_raw = cfg.import_bytes("investor_cap_in_profit_raw", v0)?;
|
||||
let investor_cap_in_loss_raw = cfg.import_bytes("investor_cap_in_loss_raw", v0)?;
|
||||
|
||||
let pain_index = cfg.import_fiat("pain_index", v0)?;
|
||||
let greed_index = cfg.import_fiat("greed_index", v0)?;
|
||||
let net_sentiment = cfg.import_fiat("net_sentiment", Version::ONE)?;
|
||||
|
||||
Ok(Self {
|
||||
base,
|
||||
invested_capital_in_profit,
|
||||
invested_capital_in_loss,
|
||||
invested_capital_in_profit_raw,
|
||||
invested_capital_in_loss_raw,
|
||||
investor_cap_in_profit_raw,
|
||||
investor_cap_in_loss_raw,
|
||||
pain_index,
|
||||
greed_index,
|
||||
net_sentiment,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.base
|
||||
.min_stateful_height_len()
|
||||
.min(self.invested_capital_in_profit.cents.height.len())
|
||||
.min(self.invested_capital_in_loss.cents.height.len())
|
||||
.min(self.invested_capital_in_profit_raw.len())
|
||||
.min(self.invested_capital_in_loss_raw.len())
|
||||
.min(self.investor_cap_in_profit_raw.len())
|
||||
.min(self.investor_cap_in_loss_raw.len())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(
|
||||
&mut self,
|
||||
height: Height,
|
||||
height_state: &UnrealizedState,
|
||||
) -> Result<()> {
|
||||
self.base.truncate_push(height, height_state)?;
|
||||
|
||||
self.invested_capital_in_profit
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, height_state.invested_capital_in_profit)?;
|
||||
self.invested_capital_in_loss
|
||||
.cents
|
||||
.height
|
||||
.truncate_push(height, height_state.invested_capital_in_loss)?;
|
||||
|
||||
self.invested_capital_in_profit_raw.truncate_push(
|
||||
height,
|
||||
CentsSats::new(height_state.invested_capital_in_profit_raw),
|
||||
)?;
|
||||
self.invested_capital_in_loss_raw.truncate_push(
|
||||
height,
|
||||
CentsSats::new(height_state.invested_capital_in_loss_raw),
|
||||
)?;
|
||||
self.investor_cap_in_profit_raw.truncate_push(
|
||||
height,
|
||||
CentsSquaredSats::new(height_state.investor_cap_in_profit_raw),
|
||||
)?;
|
||||
self.investor_cap_in_loss_raw.truncate_push(
|
||||
height,
|
||||
CentsSquaredSats::new(height_state.investor_cap_in_loss_raw),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.base.collect_vecs_mut();
|
||||
vecs.push(&mut self.invested_capital_in_profit.cents.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.invested_capital_in_loss.cents.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.invested_capital_in_profit_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.invested_capital_in_loss_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.investor_cap_in_profit_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.investor_cap_in_loss_raw as &mut dyn AnyStoredVec);
|
||||
vecs
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&Self],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Delegate Complete-tier aggregation
|
||||
let base_refs: Vec<&UnrealizedBase> =
|
||||
others.iter().map(|o| &o.base).collect();
|
||||
self.base
|
||||
.compute_from_stateful(starting_indexes, &base_refs, exit)?;
|
||||
|
||||
// Source-only: invested_capital
|
||||
sum_others!(self, starting_indexes, others, exit; invested_capital_in_profit.cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; invested_capital_in_loss.cents.height);
|
||||
|
||||
// Source-only: raw BytesVec aggregation
|
||||
let start = self
|
||||
.invested_capital_in_profit_raw
|
||||
.len()
|
||||
.min(self.invested_capital_in_loss_raw.len())
|
||||
.min(self.investor_cap_in_profit_raw.len())
|
||||
.min(self.investor_cap_in_loss_raw.len());
|
||||
let end = others
|
||||
.iter()
|
||||
.map(|o| o.invested_capital_in_profit_raw.len())
|
||||
.min()
|
||||
.unwrap_or(0);
|
||||
|
||||
// Pre-collect all cohort data to avoid per-element BytesVec reads in nested loop
|
||||
let invested_profit_ranges: Vec<Vec<CentsSats>> = others
|
||||
.iter()
|
||||
.map(|o| {
|
||||
o.invested_capital_in_profit_raw
|
||||
.collect_range_at(start, end)
|
||||
})
|
||||
.collect();
|
||||
let invested_loss_ranges: Vec<Vec<CentsSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.invested_capital_in_loss_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
let investor_profit_ranges: Vec<Vec<CentsSquaredSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.investor_cap_in_profit_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
let investor_loss_ranges: Vec<Vec<CentsSquaredSats>> = others
|
||||
.iter()
|
||||
.map(|o| o.investor_cap_in_loss_raw.collect_range_at(start, end))
|
||||
.collect();
|
||||
|
||||
for i in start..end {
|
||||
let height = Height::from(i);
|
||||
let local_i = i - start;
|
||||
|
||||
let mut sum_invested_profit = CentsSats::ZERO;
|
||||
let mut sum_invested_loss = CentsSats::ZERO;
|
||||
let mut sum_investor_profit = CentsSquaredSats::ZERO;
|
||||
let mut sum_investor_loss = CentsSquaredSats::ZERO;
|
||||
|
||||
for idx in 0..others.len() {
|
||||
sum_invested_profit += invested_profit_ranges[idx][local_i];
|
||||
sum_invested_loss += invested_loss_ranges[idx][local_i];
|
||||
sum_investor_profit += investor_profit_ranges[idx][local_i];
|
||||
sum_investor_loss += investor_loss_ranges[idx][local_i];
|
||||
}
|
||||
|
||||
self.invested_capital_in_profit_raw
|
||||
.truncate_push(height, sum_invested_profit)?;
|
||||
self.invested_capital_in_loss_raw
|
||||
.truncate_push(height, sum_invested_loss)?;
|
||||
self.investor_cap_in_profit_raw
|
||||
.truncate_push(height, sum_investor_profit)?;
|
||||
self.investor_cap_in_loss_raw
|
||||
.truncate_push(height, sum_investor_loss)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute derived metrics from stored values + price.
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Complete-tier: net_unrealized_pnl
|
||||
self.base.compute_rest(starting_indexes, exit)?;
|
||||
|
||||
// Extended-only: Pain index (investor_price_of_losers - spot)
|
||||
self.pain_index.cents.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&self.investor_cap_in_loss_raw,
|
||||
&self.invested_capital_in_loss_raw,
|
||||
&prices.price.cents.height,
|
||||
|(h, investor_cap, invested_cap, spot, ..)| {
|
||||
if invested_cap.inner() == 0 {
|
||||
return (h, Cents::ZERO);
|
||||
}
|
||||
let investor_price_losers = investor_cap.inner() / invested_cap.inner();
|
||||
let spot_u128 = spot.as_u128();
|
||||
(h, Cents::new((investor_price_losers - spot_u128) as u64))
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Extended-only: Greed index (spot - investor_price_of_winners)
|
||||
self.greed_index.cents.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&self.investor_cap_in_profit_raw,
|
||||
&self.invested_capital_in_profit_raw,
|
||||
&prices.price.cents.height,
|
||||
|(h, investor_cap, invested_cap, spot, ..)| {
|
||||
if invested_cap.inner() == 0 {
|
||||
return (h, Cents::ZERO);
|
||||
}
|
||||
let investor_price_winners = investor_cap.inner() / invested_cap.inner();
|
||||
let spot_u128 = spot.as_u128();
|
||||
(h, Cents::new((spot_u128 - investor_price_winners) as u64))
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute net_sentiment.height for separate cohorts (greed - pain).
|
||||
pub(crate) fn compute_net_sentiment_height(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.net_sentiment
|
||||
.cents
|
||||
.height
|
||||
.compute_binary::<Cents, Cents, CentsSubtractToCentsSigned>(
|
||||
starting_indexes.height,
|
||||
&self.greed_index.cents.height,
|
||||
&self.pain_index.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
mod base;
|
||||
mod complete;
|
||||
mod full;
|
||||
|
||||
pub use base::*;
|
||||
pub use complete::*;
|
||||
pub use full::*;
|
||||
|
||||
@@ -13,6 +13,12 @@ pub trait RealizedOps: Default + Clone + Send + Sync + 'static {
|
||||
fn value_destroyed(&self) -> Cents {
|
||||
Cents::ZERO
|
||||
}
|
||||
fn sent_in_profit(&self) -> Sats {
|
||||
Sats::ZERO
|
||||
}
|
||||
fn sent_in_loss(&self) -> Sats {
|
||||
Sats::ZERO
|
||||
}
|
||||
fn set_cap_raw(&mut self, cap_raw: CentsSats);
|
||||
fn set_investor_cap_raw(&mut self, investor_cap_raw: CentsSquaredSats);
|
||||
fn reset_single_iteration_values(&mut self);
|
||||
@@ -121,13 +127,15 @@ impl RealizedOps for MinimalRealizedState {
|
||||
}
|
||||
}
|
||||
|
||||
/// Core realized state: cap, profit, loss + value_created/destroyed for SOPR.
|
||||
/// Core realized state: cap, profit, loss + value_created/destroyed for SOPR + sent tracking.
|
||||
/// Used by CoreCohortMetrics cohorts (epoch, class, max_age, min_age — ~59 separate cohorts).
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct CoreRealizedState {
|
||||
minimal: MinimalRealizedState,
|
||||
value_created_raw: u128,
|
||||
value_destroyed_raw: u128,
|
||||
sent_in_profit: Sats,
|
||||
sent_in_loss: Sats,
|
||||
}
|
||||
|
||||
impl RealizedOps for CoreRealizedState {
|
||||
@@ -162,6 +170,16 @@ impl RealizedOps for CoreRealizedState {
|
||||
Cents::new((self.value_destroyed_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sent_in_profit(&self) -> Sats {
|
||||
self.sent_in_profit
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sent_in_loss(&self) -> Sats {
|
||||
self.sent_in_loss
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_cap_raw(&mut self, cap_raw: CentsSats) {
|
||||
self.minimal.set_cap_raw(cap_raw);
|
||||
@@ -175,6 +193,8 @@ impl RealizedOps for CoreRealizedState {
|
||||
self.minimal.reset_single_iteration_values();
|
||||
self.value_created_raw = 0;
|
||||
self.value_destroyed_raw = 0;
|
||||
self.sent_in_profit = Sats::ZERO;
|
||||
self.sent_in_loss = Sats::ZERO;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -205,6 +225,14 @@ impl RealizedOps for CoreRealizedState {
|
||||
.send(sats, current_ps, prev_ps, ath_ps, prev_investor_cap);
|
||||
self.value_created_raw += current_ps.as_u128();
|
||||
self.value_destroyed_raw += prev_ps.as_u128();
|
||||
match current_ps.cmp(&prev_ps) {
|
||||
Ordering::Greater | Ordering::Equal => {
|
||||
self.sent_in_profit += sats;
|
||||
}
|
||||
Ordering::Less => {
|
||||
self.sent_in_loss += sats;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,10 +260,6 @@ pub struct RealizedState {
|
||||
loss_value_destroyed_raw: u128,
|
||||
/// Raw realized peak regret: Σ((peak - sell_price) × sats)
|
||||
peak_regret_raw: u128,
|
||||
/// Sats sent in profit
|
||||
sent_in_profit: Sats,
|
||||
/// Sats sent in loss
|
||||
sent_in_loss: Sats,
|
||||
}
|
||||
|
||||
impl RealizedOps for RealizedState {
|
||||
@@ -272,6 +296,16 @@ impl RealizedOps for RealizedState {
|
||||
Cents::new((raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sent_in_profit(&self) -> Sats {
|
||||
self.core.sent_in_profit()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sent_in_loss(&self) -> Sats {
|
||||
self.core.sent_in_loss()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_cap_raw(&mut self, cap_raw: CentsSats) {
|
||||
self.core.set_cap_raw(cap_raw);
|
||||
@@ -290,8 +324,6 @@ impl RealizedOps for RealizedState {
|
||||
self.loss_value_created_raw = 0;
|
||||
self.loss_value_destroyed_raw = 0;
|
||||
self.peak_regret_raw = 0;
|
||||
self.sent_in_profit = Sats::ZERO;
|
||||
self.sent_in_loss = Sats::ZERO;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -323,7 +355,7 @@ impl RealizedOps for RealizedState {
|
||||
ath_ps: CentsSats,
|
||||
prev_investor_cap: CentsSquaredSats,
|
||||
) {
|
||||
// Delegate cap/profit/loss + value_created/destroyed to core
|
||||
// Delegate cap/profit/loss + value_created/destroyed + sent tracking to core
|
||||
self.core
|
||||
.send(sats, current_ps, prev_ps, ath_ps, prev_investor_cap);
|
||||
|
||||
@@ -331,20 +363,13 @@ impl RealizedOps for RealizedState {
|
||||
let current = current_ps.as_u128();
|
||||
let prev = prev_ps.as_u128();
|
||||
match current_ps.cmp(&prev_ps) {
|
||||
Ordering::Greater => {
|
||||
Ordering::Greater | Ordering::Equal => {
|
||||
self.profit_value_created_raw += current;
|
||||
self.profit_value_destroyed_raw += prev;
|
||||
self.sent_in_profit += sats;
|
||||
}
|
||||
Ordering::Less => {
|
||||
self.loss_value_created_raw += current;
|
||||
self.loss_value_destroyed_raw += prev;
|
||||
self.sent_in_loss += sats;
|
||||
}
|
||||
Ordering::Equal => {
|
||||
self.profit_value_created_raw += current;
|
||||
self.profit_value_destroyed_raw += prev;
|
||||
self.sent_in_profit += sats;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,16 +446,4 @@ impl RealizedState {
|
||||
}
|
||||
Cents::new((self.peak_regret_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
/// Get sats sent in profit.
|
||||
#[inline]
|
||||
pub(crate) fn sent_in_profit(&self) -> Sats {
|
||||
self.sent_in_profit
|
||||
}
|
||||
|
||||
/// Get sats sent in loss.
|
||||
#[inline]
|
||||
pub(crate) fn sent_in_loss(&self) -> Sats {
|
||||
self.sent_in_loss
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, Height, Indexes, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{blocks, indexes, prices};
|
||||
|
||||
use super::{ComputedFromHeightRatioExtended, ComputedFromHeightRatioStdDevBands};
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct ComputedFromHeightRatioFull<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: ComputedFromHeightRatioExtended<M>,
|
||||
#[traversable(flatten)]
|
||||
pub std_dev: ComputedFromHeightRatioStdDevBands<M>,
|
||||
}
|
||||
|
||||
impl ComputedFromHeightRatioFull {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
base: ComputedFromHeightRatioExtended::forced_import(db, name, version, indexes)?,
|
||||
std_dev: ComputedFromHeightRatioStdDevBands::forced_import(
|
||||
db, name, version, indexes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute ratio, percentiles, and all stddev bands from an externally-provided metric price (in cents).
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
metric_price: &impl ReadableVec<Height, Cents>,
|
||||
) -> Result<()> {
|
||||
self.base
|
||||
.compute_rest(blocks, prices, starting_indexes, exit, metric_price)?;
|
||||
self.std_dev
|
||||
.compute(blocks, starting_indexes, exit, &self.base.base.ratio.height, metric_price)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
mod extended;
|
||||
mod full;
|
||||
mod percentiles;
|
||||
mod price_extended;
|
||||
mod std_dev_bands;
|
||||
|
||||
pub use extended::*;
|
||||
pub use full::*;
|
||||
pub use percentiles::*;
|
||||
pub use price_extended::*;
|
||||
pub use std_dev_bands::*;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2064,17 +2064,11 @@ class MetricPattern35(Generic[T]):
|
||||
|
||||
# Reusable structural pattern classes
|
||||
|
||||
class AdjustedCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern:
|
||||
class CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.adjusted_sopr: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'adjusted_sopr'))
|
||||
self.adjusted_sopr_ema: _1m1wPattern = _1m1wPattern(client, _m(acc, 'adjusted_sopr_24h_ema'))
|
||||
self.adjusted_value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'adjusted_value_created'))
|
||||
self.adjusted_value_created_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'adjusted_value_created'))
|
||||
self.adjusted_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'adjusted_value_destroyed'))
|
||||
self.adjusted_value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'adjusted_value_destroyed'))
|
||||
self.cap_raw: MetricPattern18[CentsSats] = MetricPattern18(client, _m(acc, 'cap_raw'))
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'capitulation_flow'))
|
||||
self.gross_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'realized_gross_pnl'))
|
||||
@@ -2131,102 +2125,6 @@ class AdjustedCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedS
|
||||
self.value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_destroyed'))
|
||||
self.value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'value_destroyed'))
|
||||
|
||||
class CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.cap_raw: MetricPattern18[CentsSats] = MetricPattern18(client, _m(acc, 'cap_raw'))
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'capitulation_flow'))
|
||||
self.gross_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'realized_gross_pnl'))
|
||||
self.gross_pnl_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'gross_pnl_sum'))
|
||||
self.investor_cap_raw: MetricPattern18[CentsSquaredSats] = MetricPattern18(client, _m(acc, 'investor_cap_raw'))
|
||||
self.investor_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'investor_price'))
|
||||
self.investor_price_ratio: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'investor_price_ratio'))
|
||||
self.loss_value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'loss_value_created'))
|
||||
self.loss_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'loss_value_destroyed'))
|
||||
self.lower_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'lower_price_band'))
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
|
||||
self.neg_realized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_realized_loss'))
|
||||
self.net_pnl_change_1m: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'net_pnl_change_1m'))
|
||||
self.net_pnl_change_1m_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_pnl_change_1m_rel_to_market_cap'))
|
||||
self.net_pnl_change_1m_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_pnl_change_1m_rel_to_realized_cap'))
|
||||
self.net_realized_pnl: CumulativeHeightPattern[CentsSigned] = CumulativeHeightPattern(client, _m(acc, 'net_realized_pnl'))
|
||||
self.net_realized_pnl_ema_1w: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'net_realized_pnl_ema_1w'))
|
||||
self.net_realized_pnl_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_realized_pnl_rel_to_realized_cap'))
|
||||
self.peak_regret: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_peak_regret'))
|
||||
self.peak_regret_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_peak_regret_rel_to_realized_cap'))
|
||||
self.profit_flow: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'profit_flow'))
|
||||
self.profit_value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'profit_value_created'))
|
||||
self.profit_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'profit_value_destroyed'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_cap_change_1m: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'realized_cap_change_1m'))
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_loss'))
|
||||
self.realized_loss_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_loss_ema_1w'))
|
||||
self.realized_loss_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_loss_rel_to_realized_cap'))
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
self.realized_price_ratio: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'realized_price_ratio'))
|
||||
self.realized_profit: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_profit'))
|
||||
self.realized_profit_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_profit_ema_1w'))
|
||||
self.realized_profit_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_profit_rel_to_realized_cap'))
|
||||
self.sell_side_risk_ratio: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, _m(acc, 'sell_side_risk_ratio'))
|
||||
self.sell_side_risk_ratio_24h_ema: _1m1wPattern2 = _1m1wPattern2(client, _m(acc, 'sell_side_risk_ratio_24h_ema'))
|
||||
self.sent_in_loss: BaseCumulativePattern = BaseCumulativePattern(client, _m(acc, 'sent_in_loss'))
|
||||
self.sent_in_loss_ema: _2wPattern = _2wPattern(client, _m(acc, 'sent_in_loss_ema_2w'))
|
||||
self.sent_in_profit: BaseCumulativePattern = BaseCumulativePattern(client, _m(acc, 'sent_in_profit'))
|
||||
self.sent_in_profit_ema: _2wPattern = _2wPattern(client, _m(acc, 'sent_in_profit_ema_2w'))
|
||||
self.sopr: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'sopr'))
|
||||
self.sopr_24h_ema: _1m1wPattern = _1m1wPattern(client, _m(acc, 'sopr_24h_ema'))
|
||||
self.upper_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'upper_price_band'))
|
||||
self.value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_created'))
|
||||
self.value_created_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'value_created'))
|
||||
self.value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_destroyed'))
|
||||
self.value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'value_destroyed'))
|
||||
|
||||
class CapitulationGrossLossMvrvNegNetProfitRealizedSentSoprValuePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'capitulation_flow'))
|
||||
self.gross_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'realized_gross_pnl'))
|
||||
self.gross_pnl_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'gross_pnl_sum'))
|
||||
self.loss_value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'loss_value_created'))
|
||||
self.loss_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'loss_value_destroyed'))
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
|
||||
self.neg_realized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_realized_loss'))
|
||||
self.net_pnl_change_1m: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'net_pnl_change_1m'))
|
||||
self.net_pnl_change_1m_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_pnl_change_1m_rel_to_market_cap'))
|
||||
self.net_pnl_change_1m_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_pnl_change_1m_rel_to_realized_cap'))
|
||||
self.net_realized_pnl: CumulativeHeightPattern[CentsSigned] = CumulativeHeightPattern(client, _m(acc, 'net_realized_pnl'))
|
||||
self.net_realized_pnl_ema_1w: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'net_realized_pnl_ema_1w'))
|
||||
self.net_realized_pnl_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_realized_pnl_rel_to_realized_cap'))
|
||||
self.profit_flow: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'profit_flow'))
|
||||
self.profit_value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'profit_value_created'))
|
||||
self.profit_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'profit_value_destroyed'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_cap_change_1m: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'realized_cap_change_1m'))
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_loss'))
|
||||
self.realized_loss_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_loss_ema_1w'))
|
||||
self.realized_loss_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_loss_rel_to_realized_cap'))
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
self.realized_price_ratio: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'realized_price_ratio'))
|
||||
self.realized_profit: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_profit'))
|
||||
self.realized_profit_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_profit_ema_1w'))
|
||||
self.realized_profit_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_profit_rel_to_realized_cap'))
|
||||
self.sent_in_loss: BaseCumulativePattern = BaseCumulativePattern(client, _m(acc, 'sent_in_loss'))
|
||||
self.sent_in_loss_ema: _2wPattern = _2wPattern(client, _m(acc, 'sent_in_loss_ema_2w'))
|
||||
self.sent_in_profit: BaseCumulativePattern = BaseCumulativePattern(client, _m(acc, 'sent_in_profit'))
|
||||
self.sent_in_profit_ema: _2wPattern = _2wPattern(client, _m(acc, 'sent_in_profit_ema_2w'))
|
||||
self.sopr: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'sopr'))
|
||||
self.sopr_24h_ema: _1m1wPattern = _1m1wPattern(client, _m(acc, 'sopr_24h_ema'))
|
||||
self.value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_created'))
|
||||
self.value_created_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'value_created'))
|
||||
self.value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_destroyed'))
|
||||
self.value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'value_destroyed'))
|
||||
|
||||
class _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdSmaZscorePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2261,6 +2159,40 @@ class _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdSmaZscorePattern:
|
||||
self.sma: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'sma_4y'))
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'zscore_4y'))
|
||||
|
||||
class GrossMvrvNegNetRealizedSentSoprValuePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.gross_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'realized_gross_pnl'))
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
|
||||
self.neg_realized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_realized_loss'))
|
||||
self.net_realized_pnl: CumulativeHeightPattern[CentsSigned] = CumulativeHeightPattern(client, _m(acc, 'net_realized_pnl'))
|
||||
self.net_realized_pnl_ema_1w: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'net_realized_pnl_ema_1w'))
|
||||
self.net_realized_pnl_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_realized_pnl_rel_to_realized_cap'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_cap_change_1m: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'realized_cap_change_1m'))
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_loss'))
|
||||
self.realized_loss_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_loss_ema_1w'))
|
||||
self.realized_loss_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_loss_rel_to_realized_cap'))
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
self.realized_price_ratio: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'realized_price_ratio'))
|
||||
self.realized_price_ratio_percentiles: RatioPattern = RatioPattern(client, _m(acc, 'realized_price_ratio'))
|
||||
self.realized_profit: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_profit'))
|
||||
self.realized_profit_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_profit_ema_1w'))
|
||||
self.realized_profit_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_profit_rel_to_realized_cap'))
|
||||
self.sent_in_loss: BaseCumulativePattern = BaseCumulativePattern(client, _m(acc, 'sent_in_loss'))
|
||||
self.sent_in_loss_ema: _2wPattern = _2wPattern(client, _m(acc, 'sent_in_loss_ema_2w'))
|
||||
self.sent_in_profit: BaseCumulativePattern = BaseCumulativePattern(client, _m(acc, 'sent_in_profit'))
|
||||
self.sent_in_profit_ema: _2wPattern = _2wPattern(client, _m(acc, 'sent_in_profit_ema_2w'))
|
||||
self.sopr: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'sopr'))
|
||||
self.sopr_24h_ema: _1m1wPattern = _1m1wPattern(client, _m(acc, 'sopr_24h_ema'))
|
||||
self.value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_created'))
|
||||
self.value_created_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'value_created'))
|
||||
self.value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_destroyed'))
|
||||
self.value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'value_destroyed'))
|
||||
|
||||
class InvestedNegNetNuplSupplyUnrealizedPattern3:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2287,31 +2219,6 @@ class InvestedNegNetNuplSupplyUnrealizedPattern3:
|
||||
self.unrealized_profit_rel_to_own_gross_pnl: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'unrealized_profit_rel_to_own_gross_pnl'))
|
||||
self.unrealized_profit_rel_to_own_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap'))
|
||||
|
||||
class GrossMvrvNegNetRealizedSoprPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.gross_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'realized_gross_pnl'))
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
|
||||
self.neg_realized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_realized_loss'))
|
||||
self.net_realized_pnl: CumulativeHeightPattern[CentsSigned] = CumulativeHeightPattern(client, _m(acc, 'net_realized_pnl'))
|
||||
self.net_realized_pnl_ema_1w: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'net_realized_pnl_ema_1w'))
|
||||
self.net_realized_pnl_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_realized_pnl_rel_to_realized_cap'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_cap_change_1m: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'realized_cap_change_1m'))
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_loss'))
|
||||
self.realized_loss_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_loss_ema_1w'))
|
||||
self.realized_loss_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_loss_rel_to_realized_cap'))
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
self.realized_price_ratio: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'realized_price_ratio'))
|
||||
self.realized_profit: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_profit'))
|
||||
self.realized_profit_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_profit_ema_1w'))
|
||||
self.realized_profit_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_profit_rel_to_realized_cap'))
|
||||
self.sopr: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'sopr'))
|
||||
self.sopr_24h_ema: _1m1wPattern = _1m1wPattern(client, _m(acc, 'sopr_24h_ema'))
|
||||
|
||||
class Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2505,6 +2412,22 @@ class AverageGainsLossesRsiStochPattern:
|
||||
self.stoch_rsi_d: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'stoch_d_24h'))
|
||||
self.stoch_rsi_k: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'stoch_k_24h'))
|
||||
|
||||
class NegNetNuplSupplyUnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.neg_unrealized_loss_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'neg_unrealized_loss_rel_to_market_cap'))
|
||||
self.net_unrealized_pnl_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_unrealized_pnl_rel_to_market_cap'))
|
||||
self.nupl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'nupl'))
|
||||
self.supply_in_loss_rel_to_circulating_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_in_loss_rel_to_circulating_supply'))
|
||||
self.supply_in_loss_rel_to_own_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_in_loss_rel_to_own_supply'))
|
||||
self.supply_in_profit_rel_to_circulating_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_in_profit_rel_to_circulating_supply'))
|
||||
self.supply_in_profit_rel_to_own_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_in_profit_rel_to_own_supply'))
|
||||
self.supply_rel_to_circulating_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_rel_to_circulating_supply'))
|
||||
self.unrealized_loss_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'unrealized_loss_rel_to_market_cap'))
|
||||
self.unrealized_profit_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'unrealized_profit_rel_to_market_cap'))
|
||||
|
||||
class AllP2aP2pk33P2pk65P2pkhP2shP2trP2wpkhP2wshPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2550,21 +2473,6 @@ class AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern:
|
||||
self.pct90: _1m1w1y24hPattern[StoredU64] = _1m1w1y24hPattern(client, _m(acc, 'p90'))
|
||||
self.sum: _1m1w1y24hPattern[StoredU64] = _1m1w1y24hPattern(client, _m(acc, 'sum'))
|
||||
|
||||
class NetNuplSupplyUnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.net_unrealized_pnl_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_unrealized_pnl_rel_to_market_cap'))
|
||||
self.nupl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'nupl'))
|
||||
self.supply_in_loss_rel_to_circulating_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_in_loss_rel_to_circulating_supply'))
|
||||
self.supply_in_loss_rel_to_own_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_in_loss_rel_to_own_supply'))
|
||||
self.supply_in_profit_rel_to_circulating_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_in_profit_rel_to_circulating_supply'))
|
||||
self.supply_in_profit_rel_to_own_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_in_profit_rel_to_own_supply'))
|
||||
self.supply_rel_to_circulating_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'supply_rel_to_circulating_supply'))
|
||||
self.unrealized_loss_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'unrealized_loss_rel_to_market_cap'))
|
||||
self.unrealized_profit_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'unrealized_profit_rel_to_market_cap'))
|
||||
|
||||
class AverageHeightMaxMedianMinPct10Pct25Pct75Pct90Pattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2603,10 +2511,10 @@ class ActivityAddrOutputsRealizedRelativeSupplyUnrealizedPattern:
|
||||
self.addr_count: MetricPattern1[StoredU64] = MetricPattern1(client, _m(acc, 'addr_count'))
|
||||
self.addr_count_change_1m: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'addr_count_change_1m'))
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: GrossMvrvNegNetRealizedSoprPattern = GrossMvrvNegNetRealizedSoprPattern(client, acc)
|
||||
self.relative: NetNuplSupplyUnrealizedPattern = NetNuplSupplyUnrealizedPattern(client, acc)
|
||||
self.realized: MvrvRealizedPattern = MvrvRealizedPattern(client, acc)
|
||||
self.relative: SupplyPattern = SupplyPattern(client, _m(acc, 'supply_in'))
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, _m(acc, 'supply'))
|
||||
self.unrealized: NegNetSupplyUnrealizedPattern = NegNetSupplyUnrealizedPattern(client, acc)
|
||||
self.unrealized: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply_in'))
|
||||
|
||||
class AverageMaxMedianMinPct10Pct25Pct75Pct90Pattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2643,23 +2551,36 @@ class ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern:
|
||||
self.activity: CoinblocksCoindaysSentPattern = CoinblocksCoindaysSentPattern(client, acc)
|
||||
self.cost_basis: MaxMinPattern = MaxMinPattern(client, _m(acc, 'cost_basis'))
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern = CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern(client, acc)
|
||||
self.realized: GrossMvrvNegNetRealizedSentSoprValuePattern = GrossMvrvNegNetRealizedSentSoprValuePattern(client, acc)
|
||||
self.relative: InvestedNegNetNuplSupplyUnrealizedPattern = InvestedNegNetNuplSupplyUnrealizedPattern(client, acc)
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, _m(acc, 'supply'))
|
||||
self.unrealized: GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern = GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern(client, acc)
|
||||
|
||||
class ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4:
|
||||
class GrossNegNetSupplyUnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: CoinblocksCoindaysSentPattern = CoinblocksCoindaysSentPattern(client, acc)
|
||||
self.cost_basis: MaxMinPattern = MaxMinPattern(client, _m(acc, 'cost_basis'))
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: CapitulationGrossLossMvrvNegNetProfitRealizedSentSoprValuePattern = CapitulationGrossLossMvrvNegNetProfitRealizedSentSoprValuePattern(client, acc)
|
||||
self.relative: NetNuplSupplyUnrealizedPattern = NetNuplSupplyUnrealizedPattern(client, acc)
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, _m(acc, 'supply'))
|
||||
self.unrealized: NegNetSupplyUnrealizedPattern = NegNetSupplyUnrealizedPattern(client, acc)
|
||||
self.gross_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_gross_pnl'))
|
||||
self.neg_unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss'))
|
||||
self.net_unrealized_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'net_unrealized_pnl'))
|
||||
self.supply_in_loss: BtcCentsSatsUsdPattern = BtcCentsSatsUsdPattern(client, _m(acc, 'supply_in_loss'))
|
||||
self.supply_in_profit: BtcCentsSatsUsdPattern = BtcCentsSatsUsdPattern(client, _m(acc, 'supply_in_profit'))
|
||||
self.unrealized_loss: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_loss'))
|
||||
self.unrealized_profit: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_profit'))
|
||||
|
||||
class MvrvRealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_loss'))
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
self.realized_price_ratio: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'realized_price_ratio'))
|
||||
self.realized_profit: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_profit'))
|
||||
|
||||
class _1m1w1y24hBaseCumulativePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2673,6 +2594,18 @@ class _1m1w1y24hBaseCumulativePattern:
|
||||
self.base: BtcCentsSatsUsdPattern = BtcCentsSatsUsdPattern(client, acc)
|
||||
self.cumulative: BtcCentsSatsUsdPattern = BtcCentsSatsUsdPattern(client, _m(acc, 'cumulative'))
|
||||
|
||||
class ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: SentPattern = SentPattern(client, _m(acc, 'sent'))
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: GrossMvrvNegNetRealizedSentSoprValuePattern = GrossMvrvNegNetRealizedSentSoprValuePattern(client, acc)
|
||||
self.relative: NegNetNuplSupplyUnrealizedPattern = NegNetNuplSupplyUnrealizedPattern(client, acc)
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, _m(acc, 'supply'))
|
||||
self.unrealized: GrossNegNetSupplyUnrealizedPattern = GrossNegNetSupplyUnrealizedPattern(client, acc)
|
||||
|
||||
class ActivityOutputsRealizedRelativeSupplyUnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2680,10 +2613,10 @@ class ActivityOutputsRealizedRelativeSupplyUnrealizedPattern:
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: SentPattern = SentPattern(client, _m(acc, 'sent'))
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: GrossMvrvNegNetRealizedSoprPattern = GrossMvrvNegNetRealizedSoprPattern(client, acc)
|
||||
self.relative: NetNuplSupplyUnrealizedPattern = NetNuplSupplyUnrealizedPattern(client, acc)
|
||||
self.realized: MvrvRealizedPattern = MvrvRealizedPattern(client, acc)
|
||||
self.relative: SupplyPattern = SupplyPattern(client, _m(acc, 'supply_in'))
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, _m(acc, 'supply'))
|
||||
self.unrealized: NegNetSupplyUnrealizedPattern = NegNetSupplyUnrealizedPattern(client, acc)
|
||||
self.unrealized: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply_in'))
|
||||
|
||||
class BalanceBothReactivatedReceivingSendingPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2697,18 +2630,6 @@ class BalanceBothReactivatedReceivingSendingPattern:
|
||||
self.receiving: AverageHeightMaxMedianMinPct10Pct25Pct75Pct90Pattern[StoredU32] = AverageHeightMaxMedianMinPct10Pct25Pct75Pct90Pattern(client, _m(acc, 'receiving'))
|
||||
self.sending: AverageHeightMaxMedianMinPct10Pct25Pct75Pct90Pattern[StoredU32] = AverageHeightMaxMedianMinPct10Pct25Pct75Pct90Pattern(client, _m(acc, 'sending'))
|
||||
|
||||
class NegNetSupplyUnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.neg_unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss'))
|
||||
self.net_unrealized_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'net_unrealized_pnl'))
|
||||
self.supply_in_loss: BtcCentsSatsUsdPattern = BtcCentsSatsUsdPattern(client, _m(acc, 'supply_in_loss'))
|
||||
self.supply_in_profit: BtcCentsSatsUsdPattern = BtcCentsSatsUsdPattern(client, _m(acc, 'supply_in_profit'))
|
||||
self.unrealized_loss: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_loss'))
|
||||
self.unrealized_profit: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_profit'))
|
||||
|
||||
class EmaHistogramLineSignalPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2720,28 +2641,6 @@ class EmaHistogramLineSignalPattern:
|
||||
self.line: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'line_24h'))
|
||||
self.signal: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'signal_24h'))
|
||||
|
||||
class MvrvRealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
self.realized_price_ratio: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'realized_price_ratio'))
|
||||
|
||||
class OutputsRealizedRelativeSupplyUnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: MvrvRealizedPattern = MvrvRealizedPattern(client, acc)
|
||||
self.relative: SupplyPattern = SupplyPattern(client, _m(acc, 'supply_in'))
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, _m(acc, 'supply'))
|
||||
self.unrealized: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply_in'))
|
||||
|
||||
class _1m1w1y24hPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -4307,11 +4206,21 @@ class MetricsTree_Distribution_AddressesData:
|
||||
self.funded: MetricPattern34[FundedAddressData] = MetricPattern34(client, 'fundedaddressdata')
|
||||
self.empty: MetricPattern35[EmptyAddressData] = MetricPattern35(client, 'emptyaddressdata')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_All_Adjusted:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.adjusted_value_created: MetricPattern1[Cents] = MetricPattern1(client, 'adjusted_value_created')
|
||||
self.adjusted_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, 'adjusted_value_destroyed')
|
||||
self.adjusted_value_created_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'adjusted_value_created')
|
||||
self.adjusted_value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'adjusted_value_destroyed')
|
||||
self.adjusted_sopr: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'adjusted_sopr')
|
||||
self.adjusted_sopr_ema: _1m1wPattern = _1m1wPattern(client, 'adjusted_sopr_24h_ema')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_All_Relative:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.neg_unrealized_loss_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'neg_unrealized_loss_rel_to_market_cap')
|
||||
self.invested_capital_in_profit_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'invested_capital_in_profit_rel_to_realized_cap')
|
||||
self.invested_capital_in_loss_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'invested_capital_in_loss_rel_to_realized_cap')
|
||||
self.supply_in_profit_rel_to_own_supply: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'supply_in_profit_rel_to_own_supply')
|
||||
@@ -4319,6 +4228,7 @@ class MetricsTree_Distribution_UtxoCohorts_All_Relative:
|
||||
self.unrealized_profit_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'unrealized_profit_rel_to_market_cap')
|
||||
self.unrealized_loss_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'unrealized_loss_rel_to_market_cap')
|
||||
self.net_unrealized_pnl_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'net_unrealized_pnl_rel_to_market_cap')
|
||||
self.neg_unrealized_loss_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'neg_unrealized_loss_rel_to_market_cap')
|
||||
self.nupl: MetricPattern1[StoredF32] = MetricPattern1(client, 'nupl')
|
||||
self.unrealized_profit_rel_to_own_gross_pnl: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'unrealized_profit_rel_to_own_gross_pnl')
|
||||
self.unrealized_loss_rel_to_own_gross_pnl: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'unrealized_loss_rel_to_own_gross_pnl')
|
||||
@@ -4332,10 +4242,13 @@ class MetricsTree_Distribution_UtxoCohorts_All:
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, 'supply')
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, 'utxo_count')
|
||||
self.activity: CoinblocksCoindaysSentPattern = CoinblocksCoindaysSentPattern(client, '')
|
||||
self.realized: AdjustedCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern = AdjustedCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern(client, '')
|
||||
self.realized: CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern = CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern(client, '')
|
||||
self.cost_basis: InvestedMaxMinPercentilesPattern = InvestedMaxMinPercentilesPattern(client, '')
|
||||
self.unrealized: GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern = GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern(client, '')
|
||||
self.adjusted: MetricsTree_Distribution_UtxoCohorts_All_Adjusted = MetricsTree_Distribution_UtxoCohorts_All_Adjusted(client)
|
||||
self.relative: MetricsTree_Distribution_UtxoCohorts_All_Relative = MetricsTree_Distribution_UtxoCohorts_All_Relative(client)
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'dormancy')
|
||||
self.velocity: MetricPattern1[StoredF32] = MetricPattern1(client, 'velocity')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Sth:
|
||||
"""Metrics tree node."""
|
||||
@@ -4344,70 +4257,18 @@ class MetricsTree_Distribution_UtxoCohorts_Sth:
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, 'sth_supply')
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, 'sth_utxo_count')
|
||||
self.activity: CoinblocksCoindaysSentPattern = CoinblocksCoindaysSentPattern(client, 'sth')
|
||||
self.realized: AdjustedCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern = AdjustedCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern(client, 'sth')
|
||||
self.realized: CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern = CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern(client, 'sth')
|
||||
self.cost_basis: InvestedMaxMinPercentilesPattern = InvestedMaxMinPercentilesPattern(client, 'sth')
|
||||
self.unrealized: GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern = GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern(client, 'sth')
|
||||
self.relative: InvestedNegNetNuplSupplyUnrealizedPattern3 = InvestedNegNetNuplSupplyUnrealizedPattern3(client, 'sth')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Lth_Realized:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.investor_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_investor_price')
|
||||
self.investor_price_ratio: BpsRatioPattern = BpsRatioPattern(client, 'lth_investor_price_ratio')
|
||||
self.lower_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_lower_price_band')
|
||||
self.upper_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_upper_price_band')
|
||||
self.cap_raw: MetricPattern18[CentsSats] = MetricPattern18(client, 'lth_cap_raw')
|
||||
self.investor_cap_raw: MetricPattern18[CentsSquaredSats] = MetricPattern18(client, 'lth_investor_cap_raw')
|
||||
self.sell_side_risk_ratio: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, 'lth_sell_side_risk_ratio')
|
||||
self.sell_side_risk_ratio_24h_ema: _1m1wPattern2 = _1m1wPattern2(client, 'lth_sell_side_risk_ratio_24h_ema')
|
||||
self.peak_regret: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, 'lth_realized_peak_regret')
|
||||
self.peak_regret_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'lth_realized_peak_regret_rel_to_realized_cap')
|
||||
self.profit_value_created: MetricPattern1[Cents] = MetricPattern1(client, 'lth_profit_value_created')
|
||||
self.profit_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, 'lth_profit_value_destroyed')
|
||||
self.loss_value_created: MetricPattern1[Cents] = MetricPattern1(client, 'lth_loss_value_created')
|
||||
self.loss_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, 'lth_loss_value_destroyed')
|
||||
self.value_created: MetricPattern1[Cents] = MetricPattern1(client, 'lth_value_created')
|
||||
self.value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, 'lth_value_destroyed')
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, 'lth_capitulation_flow')
|
||||
self.profit_flow: MetricPattern1[Dollars] = MetricPattern1(client, 'lth_profit_flow')
|
||||
self.value_created_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'lth_value_created')
|
||||
self.value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'lth_value_destroyed')
|
||||
self.gross_pnl_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'lth_gross_pnl_sum')
|
||||
self.net_pnl_change_1m: MetricPattern1[CentsSigned] = MetricPattern1(client, 'lth_net_pnl_change_1m')
|
||||
self.net_pnl_change_1m_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'lth_net_pnl_change_1m_rel_to_realized_cap')
|
||||
self.net_pnl_change_1m_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'lth_net_pnl_change_1m_rel_to_market_cap')
|
||||
self.sent_in_profit: BaseCumulativePattern = BaseCumulativePattern(client, 'lth_sent_in_profit')
|
||||
self.sent_in_profit_ema: _2wPattern = _2wPattern(client, 'lth_sent_in_profit_ema_2w')
|
||||
self.sent_in_loss: BaseCumulativePattern = BaseCumulativePattern(client, 'lth_sent_in_loss')
|
||||
self.sent_in_loss_ema: _2wPattern = _2wPattern(client, 'lth_sent_in_loss_ema_2w')
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, 'lth_realized_cap_cents')
|
||||
self.realized_profit: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, 'lth_realized_profit')
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, 'lth_realized_loss')
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, 'lth_realized_cap')
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_realized_price')
|
||||
self.realized_price_ratio: BpsRatioPattern = BpsRatioPattern(client, 'lth_realized_price_ratio')
|
||||
self.realized_cap_change_1m: MetricPattern1[CentsSigned] = MetricPattern1(client, 'lth_realized_cap_change_1m')
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_mvrv')
|
||||
self.neg_realized_loss: MetricPattern1[Dollars] = MetricPattern1(client, 'lth_neg_realized_loss')
|
||||
self.net_realized_pnl: CumulativeHeightPattern[CentsSigned] = CumulativeHeightPattern(client, 'lth_net_realized_pnl')
|
||||
self.net_realized_pnl_ema_1w: MetricPattern1[CentsSigned] = MetricPattern1(client, 'lth_net_realized_pnl_ema_1w')
|
||||
self.gross_pnl: CentsUsdPattern = CentsUsdPattern(client, 'lth_realized_gross_pnl')
|
||||
self.realized_profit_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, 'lth_realized_profit_ema_1w')
|
||||
self.realized_loss_ema_1w: MetricPattern1[Cents] = MetricPattern1(client, 'lth_realized_loss_ema_1w')
|
||||
self.sopr: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'lth_sopr')
|
||||
self.sopr_24h_ema: _1m1wPattern = _1m1wPattern(client, 'lth_sopr_24h_ema')
|
||||
self.realized_profit_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'lth_realized_profit_rel_to_realized_cap')
|
||||
self.realized_loss_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'lth_realized_loss_rel_to_realized_cap')
|
||||
self.net_realized_pnl_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'lth_net_realized_pnl_rel_to_realized_cap')
|
||||
self.realized_cap_rel_to_own_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'lth_realized_cap_rel_to_own_market_cap')
|
||||
self.realized_profit_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'lth_realized_profit')
|
||||
self.realized_loss_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'lth_realized_loss')
|
||||
self.realized_profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'lth_realized_profit_to_loss_ratio')
|
||||
self.realized_price_ratio_percentiles: RatioPattern = RatioPattern(client, 'lth_realized_price_ratio')
|
||||
self.realized_price_ratio_std_dev: RatioPattern2 = RatioPattern2(client, 'lth_realized_price_ratio')
|
||||
self.investor_price_ratio_percentiles: RatioPattern = RatioPattern(client, 'lth_investor_price_ratio')
|
||||
self.investor_price_ratio_std_dev: RatioPattern2 = RatioPattern2(client, 'lth_investor_price_ratio')
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_dormancy')
|
||||
self.velocity: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_velocity')
|
||||
self.adjusted_value_created: MetricPattern1[Cents] = MetricPattern1(client, 'sth_adjusted_value_created')
|
||||
self.adjusted_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, 'sth_adjusted_value_destroyed')
|
||||
self.adjusted_value_created_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'sth_adjusted_value_created')
|
||||
self.adjusted_value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'sth_adjusted_value_destroyed')
|
||||
self.adjusted_sopr: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'sth_adjusted_sopr')
|
||||
self.adjusted_sopr_ema: _1m1wPattern = _1m1wPattern(client, 'sth_adjusted_sopr_24h_ema')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Lth:
|
||||
"""Metrics tree node."""
|
||||
@@ -4416,10 +4277,12 @@ class MetricsTree_Distribution_UtxoCohorts_Lth:
|
||||
self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, 'lth_supply')
|
||||
self.outputs: UtxoPattern = UtxoPattern(client, 'lth_utxo_count')
|
||||
self.activity: CoinblocksCoindaysSentPattern = CoinblocksCoindaysSentPattern(client, 'lth')
|
||||
self.realized: MetricsTree_Distribution_UtxoCohorts_Lth_Realized = MetricsTree_Distribution_UtxoCohorts_Lth_Realized(client)
|
||||
self.realized: CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern = CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSoprUpperValuePattern(client, 'lth')
|
||||
self.cost_basis: InvestedMaxMinPercentilesPattern = InvestedMaxMinPercentilesPattern(client, 'lth')
|
||||
self.unrealized: GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern = GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern(client, 'lth')
|
||||
self.relative: InvestedNegNetNuplSupplyUnrealizedPattern3 = InvestedNegNetNuplSupplyUnrealizedPattern3(client, 'lth')
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_dormancy')
|
||||
self.velocity: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_velocity')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_AgeRange:
|
||||
"""Metrics tree node."""
|
||||
@@ -4451,47 +4314,80 @@ class MetricsTree_Distribution_UtxoCohorts_MaxAge:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._1w: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_1w_old')
|
||||
self._1m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_1m_old')
|
||||
self._2m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_2m_old')
|
||||
self._3m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_3m_old')
|
||||
self._4m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_4m_old')
|
||||
self._5m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_5m_old')
|
||||
self._6m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_6m_old')
|
||||
self._1y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_1y_old')
|
||||
self._2y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_2y_old')
|
||||
self._3y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_3y_old')
|
||||
self._4y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_4y_old')
|
||||
self._5y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_5y_old')
|
||||
self._6y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_6y_old')
|
||||
self._7y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_7y_old')
|
||||
self._8y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_8y_old')
|
||||
self._10y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_10y_old')
|
||||
self._12y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_12y_old')
|
||||
self._15y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_under_15y_old')
|
||||
self._1w: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_1w_old')
|
||||
self._1m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_1m_old')
|
||||
self._2m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_2m_old')
|
||||
self._3m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_3m_old')
|
||||
self._4m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_4m_old')
|
||||
self._5m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_5m_old')
|
||||
self._6m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_6m_old')
|
||||
self._1y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_1y_old')
|
||||
self._2y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_2y_old')
|
||||
self._3y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_3y_old')
|
||||
self._4y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_4y_old')
|
||||
self._5y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_5y_old')
|
||||
self._6y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_6y_old')
|
||||
self._7y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_7y_old')
|
||||
self._8y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_8y_old')
|
||||
self._10y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_10y_old')
|
||||
self._12y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_12y_old')
|
||||
self._15y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_under_15y_old')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_MinAge:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._1d: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_1d_old')
|
||||
self._1w: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_1w_old')
|
||||
self._1m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_1m_old')
|
||||
self._2m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_2m_old')
|
||||
self._3m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_3m_old')
|
||||
self._4m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_4m_old')
|
||||
self._5m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_5m_old')
|
||||
self._6m: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_6m_old')
|
||||
self._1y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_1y_old')
|
||||
self._2y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_2y_old')
|
||||
self._3y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_3y_old')
|
||||
self._4y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_4y_old')
|
||||
self._5y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_5y_old')
|
||||
self._6y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_6y_old')
|
||||
self._7y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_7y_old')
|
||||
self._8y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_8y_old')
|
||||
self._10y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_10y_old')
|
||||
self._12y: ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4 = ActivityCostOutputsRealizedRelativeSupplyUnrealizedPattern4(client, 'utxos_over_12y_old')
|
||||
self._1d: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_1d_old')
|
||||
self._1w: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_1w_old')
|
||||
self._1m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_1m_old')
|
||||
self._2m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_2m_old')
|
||||
self._3m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_3m_old')
|
||||
self._4m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_4m_old')
|
||||
self._5m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_5m_old')
|
||||
self._6m: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_6m_old')
|
||||
self._1y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_1y_old')
|
||||
self._2y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_2y_old')
|
||||
self._3y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_3y_old')
|
||||
self._4y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_4y_old')
|
||||
self._5y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_5y_old')
|
||||
self._6y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_6y_old')
|
||||
self._7y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_7y_old')
|
||||
self._8y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_8y_old')
|
||||
self._10y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_10y_old')
|
||||
self._12y: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'utxos_over_12y_old')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Epoch:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._0: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'epoch_0')
|
||||
self._1: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'epoch_1')
|
||||
self._2: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'epoch_2')
|
||||
self._3: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'epoch_3')
|
||||
self._4: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'epoch_4')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Class:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._2009: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2009')
|
||||
self._2010: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2010')
|
||||
self._2011: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2011')
|
||||
self._2012: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2012')
|
||||
self._2013: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2013')
|
||||
self._2014: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2014')
|
||||
self._2015: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2015')
|
||||
self._2016: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2016')
|
||||
self._2017: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2017')
|
||||
self._2018: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2018')
|
||||
self._2019: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2019')
|
||||
self._2020: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2020')
|
||||
self._2021: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2021')
|
||||
self._2022: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2022')
|
||||
self._2023: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2023')
|
||||
self._2024: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2024')
|
||||
self._2025: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2025')
|
||||
self._2026: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2 = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern2(client, 'class_2026')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_GeAmount:
|
||||
"""Metrics tree node."""
|
||||
@@ -4549,54 +4445,21 @@ class MetricsTree_Distribution_UtxoCohorts_LtAmount:
|
||||
self._10k_btc: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'utxos_under_10k_btc')
|
||||
self._100k_btc: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'utxos_under_100k_btc')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Epoch:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._0: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'epoch_0')
|
||||
self._1: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'epoch_1')
|
||||
self._2: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'epoch_2')
|
||||
self._3: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'epoch_3')
|
||||
self._4: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'epoch_4')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Class:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._2009: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2009')
|
||||
self._2010: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2010')
|
||||
self._2011: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2011')
|
||||
self._2012: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2012')
|
||||
self._2013: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2013')
|
||||
self._2014: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2014')
|
||||
self._2015: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2015')
|
||||
self._2016: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2016')
|
||||
self._2017: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2017')
|
||||
self._2018: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2018')
|
||||
self._2019: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2019')
|
||||
self._2020: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2020')
|
||||
self._2021: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2021')
|
||||
self._2022: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2022')
|
||||
self._2023: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2023')
|
||||
self._2024: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2024')
|
||||
self._2025: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2025')
|
||||
self._2026: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'class_2026')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Type:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.p2pk65: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2pk65')
|
||||
self.p2pk33: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2pk33')
|
||||
self.p2pkh: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2pkh')
|
||||
self.p2ms: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2ms')
|
||||
self.p2sh: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2sh')
|
||||
self.p2wpkh: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2wpkh')
|
||||
self.p2wsh: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2wsh')
|
||||
self.p2tr: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2tr')
|
||||
self.p2a: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2a')
|
||||
self.unknown: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'unknown_outputs')
|
||||
self.empty: OutputsRealizedRelativeSupplyUnrealizedPattern = OutputsRealizedRelativeSupplyUnrealizedPattern(client, 'empty_outputs')
|
||||
self.p2pk65: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2pk65')
|
||||
self.p2pk33: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2pk33')
|
||||
self.p2pkh: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2pkh')
|
||||
self.p2ms: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2ms')
|
||||
self.p2sh: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2sh')
|
||||
self.p2wpkh: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2wpkh')
|
||||
self.p2wsh: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2wsh')
|
||||
self.p2tr: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2tr')
|
||||
self.p2a: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'p2a')
|
||||
self.unknown: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'unknown_outputs')
|
||||
self.empty: ActivityOutputsRealizedRelativeSupplyUnrealizedPattern = ActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, 'empty_outputs')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts:
|
||||
"""Metrics tree node."""
|
||||
@@ -4608,11 +4471,11 @@ class MetricsTree_Distribution_UtxoCohorts:
|
||||
self.age_range: MetricsTree_Distribution_UtxoCohorts_AgeRange = MetricsTree_Distribution_UtxoCohorts_AgeRange(client)
|
||||
self.max_age: MetricsTree_Distribution_UtxoCohorts_MaxAge = MetricsTree_Distribution_UtxoCohorts_MaxAge(client)
|
||||
self.min_age: MetricsTree_Distribution_UtxoCohorts_MinAge = MetricsTree_Distribution_UtxoCohorts_MinAge(client)
|
||||
self.epoch: MetricsTree_Distribution_UtxoCohorts_Epoch = MetricsTree_Distribution_UtxoCohorts_Epoch(client)
|
||||
self.class: MetricsTree_Distribution_UtxoCohorts_Class = MetricsTree_Distribution_UtxoCohorts_Class(client)
|
||||
self.ge_amount: MetricsTree_Distribution_UtxoCohorts_GeAmount = MetricsTree_Distribution_UtxoCohorts_GeAmount(client)
|
||||
self.amount_range: MetricsTree_Distribution_UtxoCohorts_AmountRange = MetricsTree_Distribution_UtxoCohorts_AmountRange(client)
|
||||
self.lt_amount: MetricsTree_Distribution_UtxoCohorts_LtAmount = MetricsTree_Distribution_UtxoCohorts_LtAmount(client)
|
||||
self.epoch: MetricsTree_Distribution_UtxoCohorts_Epoch = MetricsTree_Distribution_UtxoCohorts_Epoch(client)
|
||||
self.class: MetricsTree_Distribution_UtxoCohorts_Class = MetricsTree_Distribution_UtxoCohorts_Class(client)
|
||||
self.type_: MetricsTree_Distribution_UtxoCohorts_Type = MetricsTree_Distribution_UtxoCohorts_Type(client)
|
||||
|
||||
class MetricsTree_Distribution_AddressCohorts_GeAmount:
|
||||
|
||||
Reference in New Issue
Block a user