From efefd39439dc2b4e50a31d3d7a8d47f7f7e74689 Mon Sep 17 00:00:00 2001 From: nym21 Date: Sat, 7 Mar 2026 18:36:53 +0100 Subject: [PATCH] global: snapshot --- crates/brk_client/src/lib.rs | 70 +++++-- .../src/distribution/metrics/cohort/core.rs | 14 +- .../src/distribution/metrics/mod.rs | 8 +- .../src/distribution/metrics/realized/base.rs | 167 +++------------- .../src/distribution/metrics/realized/core.rs | 185 ++++++++++++++++++ .../src/distribution/metrics/realized/full.rs | 106 +++++----- .../src/distribution/metrics/realized/mod.rs | 6 +- modules/brk-client/index.js | 73 +++++-- packages/brk_client/brk_client/__init__.py | 35 +++- 9 files changed, 411 insertions(+), 253 deletions(-) create mode 100644 crates/brk_computer/src/distribution/metrics/realized/core.rs diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index 5090a626c..ccf6481bd 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -984,10 +984,10 @@ pub struct CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSell pub realized_profit_to_loss_ratio: _1m1w1y24hPattern, pub sell_side_risk_ratio: _1m1w1y24hPattern2, pub sell_side_risk_ratio_24h_ema: _1m1wPattern2, - pub sent_in_loss: BaseCumulativePattern, - pub sent_in_loss_ema: _2wPattern, - pub sent_in_profit: BaseCumulativePattern, - pub sent_in_profit_ema: _2wPattern, + pub sent_in_loss: MetricPattern1, + pub sent_in_loss_sum: _1m1w1y24hPattern, + pub sent_in_profit: MetricPattern1, + pub sent_in_profit_sum: _1m1w1y24hPattern, pub sopr: _24hPattern, pub sopr_24h_ema: _1m1wPattern, pub sopr_extended: _1m1w1yPattern, @@ -1047,10 +1047,10 @@ impl CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSo realized_profit_to_loss_ratio: _1m1w1y24hPattern::new(client.clone(), _m(&acc, "realized_profit_to_loss_ratio")), sell_side_risk_ratio: _1m1w1y24hPattern2::new(client.clone(), _m(&acc, "sell_side_risk_ratio")), sell_side_risk_ratio_24h_ema: _1m1wPattern2::new(client.clone(), _m(&acc, "sell_side_risk_ratio_24h_ema")), - sent_in_loss: BaseCumulativePattern::new(client.clone(), _m(&acc, "sent_in_loss")), - sent_in_loss_ema: _2wPattern::new(client.clone(), _m(&acc, "sent_in_loss_ema_2w")), - sent_in_profit: BaseCumulativePattern::new(client.clone(), _m(&acc, "sent_in_profit")), - sent_in_profit_ema: _2wPattern::new(client.clone(), _m(&acc, "sent_in_profit_ema_2w")), + sent_in_loss: MetricPattern1::new(client.clone(), _m(&acc, "sent_in_loss")), + sent_in_loss_sum: _1m1w1y24hPattern::new(client.clone(), _m(&acc, "sent_in_loss")), + sent_in_profit: MetricPattern1::new(client.clone(), _m(&acc, "sent_in_profit")), + sent_in_profit_sum: _1m1w1y24hPattern::new(client.clone(), _m(&acc, "sent_in_profit")), sopr: _24hPattern::new(client.clone(), _m(&acc, "sopr_24h")), sopr_24h_ema: _1m1wPattern::new(client.clone(), _m(&acc, "sopr_24h_ema")), sopr_extended: _1m1w1yPattern::new(client.clone(), _m(&acc, "sopr")), @@ -1195,8 +1195,8 @@ pub struct MvrvNegNetRealizedSentSoprValuePattern { pub realized_price: CentsSatsUsdPattern, pub realized_price_ratio: BpsRatioPattern, pub realized_profit: CumulativeHeightPattern, - pub sent_in_loss: BaseCumulativePattern, - pub sent_in_profit: BaseCumulativePattern, + pub sent_in_loss: MetricPattern1, + pub sent_in_profit: MetricPattern1, pub sopr: _24hPattern, pub value_created: MetricPattern1, pub value_created_sum: _24hPattern, @@ -1218,8 +1218,8 @@ impl MvrvNegNetRealizedSentSoprValuePattern { realized_price: CentsSatsUsdPattern::new(client.clone(), _m(&acc, "realized_price")), realized_price_ratio: BpsRatioPattern::new(client.clone(), _m(&acc, "realized_price_ratio")), realized_profit: CumulativeHeightPattern::new(client.clone(), _m(&acc, "realized_profit")), - sent_in_loss: BaseCumulativePattern::new(client.clone(), _m(&acc, "sent_in_loss")), - sent_in_profit: BaseCumulativePattern::new(client.clone(), _m(&acc, "sent_in_profit")), + sent_in_loss: MetricPattern1::new(client.clone(), _m(&acc, "sent_in_loss")), + sent_in_profit: MetricPattern1::new(client.clone(), _m(&acc, "sent_in_profit")), sopr: _24hPattern::new(client.clone(), _m(&acc, "sopr_24h")), value_created: MetricPattern1::new(client.clone(), _m(&acc, "value_created")), value_created_sum: _24hPattern::new(client.clone(), _m(&acc, "value_created_24h")), @@ -1317,6 +1317,48 @@ impl GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern { } } +/// Pattern struct for repeated tree structure. +pub struct MvrvNegNetRealizedSoprValuePattern { + pub mvrv: MetricPattern1, + pub neg_realized_loss: MetricPattern1, + pub net_realized_pnl: CumulativeHeightPattern, + pub realized_cap: MetricPattern1, + pub realized_cap_cents: MetricPattern1, + pub realized_cap_change_1m: MetricPattern1, + pub realized_loss: CumulativeHeightPattern, + pub realized_price: CentsSatsUsdPattern, + pub realized_price_ratio: BpsRatioPattern, + pub realized_profit: CumulativeHeightPattern, + pub sopr: _24hPattern, + pub value_created: MetricPattern1, + pub value_created_sum: _24hPattern, + pub value_destroyed: MetricPattern1, + pub value_destroyed_sum: _24hPattern, +} + +impl MvrvNegNetRealizedSoprValuePattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + mvrv: MetricPattern1::new(client.clone(), _m(&acc, "mvrv")), + neg_realized_loss: MetricPattern1::new(client.clone(), _m(&acc, "neg_realized_loss")), + net_realized_pnl: CumulativeHeightPattern::new(client.clone(), _m(&acc, "net_realized_pnl")), + realized_cap: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap")), + realized_cap_cents: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap_cents")), + realized_cap_change_1m: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap_change_1m")), + realized_loss: CumulativeHeightPattern::new(client.clone(), _m(&acc, "realized_loss")), + realized_price: CentsSatsUsdPattern::new(client.clone(), _m(&acc, "realized_price")), + realized_price_ratio: BpsRatioPattern::new(client.clone(), _m(&acc, "realized_price_ratio")), + realized_profit: CumulativeHeightPattern::new(client.clone(), _m(&acc, "realized_profit")), + sopr: _24hPattern::new(client.clone(), _m(&acc, "sopr_24h")), + value_created: MetricPattern1::new(client.clone(), _m(&acc, "value_created")), + value_created_sum: _24hPattern::new(client.clone(), _m(&acc, "value_created_24h")), + value_destroyed: MetricPattern1::new(client.clone(), _m(&acc, "value_destroyed")), + value_destroyed_sum: _24hPattern::new(client.clone(), _m(&acc, "value_destroyed_24h")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct NetNuplSupplyUnrealizedPattern2 { pub net_unrealized_pnl_rel_to_market_cap: BpsPercentRatioPattern, @@ -1891,7 +1933,7 @@ impl MvrvRealizedPattern { pub struct ActivityOutputsRealizedRelativeSupplyUnrealizedPattern { pub activity: SentPattern, pub outputs: UtxoPattern, - pub realized: MvrvNegNetRealizedSentSoprValuePattern, + pub realized: MvrvNegNetRealizedSoprValuePattern, pub relative: SupplyPattern2, pub supply: ChangeHalvedTotalPattern, pub unrealized: NegNetSupplyUnrealizedPattern, @@ -1903,7 +1945,7 @@ impl ActivityOutputsRealizedRelativeSupplyUnrealizedPattern { Self { activity: SentPattern::new(client.clone(), _m(&acc, "sent")), outputs: UtxoPattern::new(client.clone(), _m(&acc, "utxo_count")), - realized: MvrvNegNetRealizedSentSoprValuePattern::new(client.clone(), acc.clone()), + realized: MvrvNegNetRealizedSoprValuePattern::new(client.clone(), acc.clone()), relative: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), supply: ChangeHalvedTotalPattern::new(client.clone(), _m(&acc, "supply")), unrealized: NegNetSupplyUnrealizedPattern::new(client.clone(), acc.clone()), diff --git a/crates/brk_computer/src/distribution/metrics/cohort/core.rs b/crates/brk_computer/src/distribution/metrics/cohort/core.rs index 2b7cc3be9..47d815af3 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/core.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/core.rs @@ -7,7 +7,7 @@ use vecdb::{AnyStoredVec, Exit, ReadableVec, Rw, StorageMode}; use crate::{blocks, prices}; use crate::distribution::metrics::{ - ActivityBase, CohortMetricsBase, RealizedBase, ImportConfig, OutputsMetrics, + ActivityBase, CohortMetricsBase, RealizedCore, ImportConfig, OutputsMetrics, RelativeBaseWithRelToAll, SupplyMetrics, UnrealizedCore, }; @@ -18,7 +18,7 @@ pub struct CoreCohortMetrics { pub supply: Box>, pub outputs: Box>, pub activity: Box>, - pub realized: Box>, + pub realized: Box>, pub unrealized: Box>, pub relative: Box>, } @@ -30,7 +30,7 @@ impl CoreCohortMetrics { supply: Box::new(SupplyMetrics::forced_import(cfg)?), outputs: Box::new(OutputsMetrics::forced_import(cfg)?), activity: Box::new(ActivityBase::forced_import(cfg)?), - realized: Box::new(RealizedBase::forced_import(cfg)?), + realized: Box::new(RealizedCore::forced_import(cfg)?), unrealized: Box::new(UnrealizedCore::forced_import(cfg)?), relative: Box::new(RelativeBaseWithRelToAll::forced_import(cfg)?), }) @@ -85,7 +85,7 @@ impl CoreCohortMetrics { )?; self.realized.compute_from_stateful( starting_indexes, - &others.iter().map(|v| v.realized_base()).collect::>(), + &others.iter().map(|v| &v.realized_base().core).collect::>(), exit, )?; self.unrealized.compute_from_stateful( @@ -114,12 +114,6 @@ 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)?; diff --git a/crates/brk_computer/src/distribution/metrics/mod.rs b/crates/brk_computer/src/distribution/metrics/mod.rs index c8d80c7a7..2c0830e47 100644 --- a/crates/brk_computer/src/distribution/metrics/mod.rs +++ b/crates/brk_computer/src/distribution/metrics/mod.rs @@ -52,7 +52,7 @@ pub use config::ImportConfig; pub use cost_basis::{CostBasisBase, CostBasisExtended, CostBasisLike, CostBasisWithExtended}; pub use outputs::OutputsMetrics; pub use realized::{ - RealizedAdjusted, RealizedBase, RealizedFull, RealizedLike, RealizedMinimal, + RealizedAdjusted, RealizedBase, RealizedCore, RealizedFull, RealizedLike, RealizedMinimal, }; pub use relative::{ RelativeBaseWithRelToAll, RelativeForAll, RelativeWithExtended, @@ -205,12 +205,6 @@ pub trait CohortMetricsBase: CohortMetricsState + Send self.activity_mut() .compute_rest_part1(blocks, prices, starting_indexes, exit)?; - self.realized_base_mut() - .sent_in_profit - .compute(prices, starting_indexes.height, exit)?; - self.realized_base_mut() - .sent_in_loss - .compute(prices, starting_indexes.height, exit)?; self.realized_mut() .compute_rest_part1(starting_indexes, exit)?; diff --git a/crates/brk_computer/src/distribution/metrics/realized/base.rs b/crates/brk_computer/src/distribution/metrics/realized/base.rs index df5a68d8b..b3f7aa526 100644 --- a/crates/brk_computer/src/distribution/metrics/realized/base.rs +++ b/crates/brk_computer/src/distribution/metrics/realized/base.rs @@ -1,120 +1,62 @@ use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, StoredF64, Version}; +use brk_types::{Height, Indexes, Sats, Version}; use derive_more::{Deref, DerefMut}; -use vecdb::{ - AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec, -}; +use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec}; use crate::{ - blocks, distribution::state::RealizedOps, - internal::{ - ComputedFromHeight, ComputedFromHeightCumulative, LazyFromHeight, - NegCentsUnsignedToDollars, RatioCents64, RollingWindow24h, ValueFromHeightCumulative, - }, - prices, + internal::ComputedFromHeight, }; use crate::distribution::metrics::ImportConfig; -use super::RealizedMinimal; +use super::RealizedCore; #[derive(Deref, DerefMut, Traversable)] pub struct RealizedBase { #[deref] #[deref_mut] #[traversable(flatten)] - pub minimal: RealizedMinimal, + pub core: RealizedCore, - pub realized_cap_change_1m: ComputedFromHeight, - - pub neg_realized_loss: LazyFromHeight, - pub net_realized_pnl: ComputedFromHeightCumulative, - - pub value_created: ComputedFromHeight, - pub value_destroyed: ComputedFromHeight, - pub value_created_sum: RollingWindow24h, - pub value_destroyed_sum: RollingWindow24h, - pub sopr: RollingWindow24h, - - pub sent_in_profit: ValueFromHeightCumulative, - pub sent_in_loss: ValueFromHeightCumulative, + pub sent_in_profit: ComputedFromHeight, + pub sent_in_loss: ComputedFromHeight, } impl RealizedBase { pub(crate) fn forced_import(cfg: &ImportConfig) -> Result { - let v0 = Version::ZERO; let v1 = Version::ONE; - let minimal = RealizedMinimal::forced_import(cfg)?; - - let neg_realized_loss = LazyFromHeight::from_height_source::( - &cfg.name("neg_realized_loss"), - cfg.version + Version::ONE, - minimal.realized_loss.height.read_only_boxed_clone(), - cfg.indexes, - ); - - let net_realized_pnl = cfg.import("net_realized_pnl", v0)?; - - let value_created = cfg.import("value_created", v0)?; - let value_destroyed = cfg.import("value_destroyed", v0)?; - let value_created_sum = cfg.import("value_created", v1)?; - let value_destroyed_sum = cfg.import("value_destroyed", v1)?; - let sopr = cfg.import("sopr", v1)?; - Ok(Self { - minimal, - realized_cap_change_1m: cfg.import("realized_cap_change_1m", v0)?, - neg_realized_loss, - net_realized_pnl, - value_created, - value_destroyed, - value_created_sum, - value_destroyed_sum, - sopr, - sent_in_profit: cfg.import("sent_in_profit", v0)?, - sent_in_loss: cfg.import("sent_in_loss", v0)?, + core: RealizedCore::forced_import(cfg)?, + sent_in_profit: cfg.import("sent_in_profit", v1)?, + sent_in_loss: cfg.import("sent_in_loss", v1)?, }) } pub(crate) fn min_stateful_height_len(&self) -> usize { - self.minimal + self.core .min_stateful_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()) + .min(self.sent_in_profit.height.len()) + .min(self.sent_in_loss.height.len()) } 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.value_created())?; - self.value_destroyed - .height - .truncate_push(height, state.value_destroyed())?; + self.core.truncate_push(height, state)?; 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.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); + let mut vecs = self.core.collect_vecs_mut(); + vecs.push(&mut self.sent_in_profit.height as &mut dyn AnyStoredVec); + vecs.push(&mut self.sent_in_loss.height); vecs } @@ -124,14 +66,12 @@ impl RealizedBase { others: &[&Self], exit: &Exit, ) -> Result<()> { - let minimal_refs: Vec<&RealizedMinimal> = others.iter().map(|o| &o.minimal).collect(); - self.minimal - .compute_from_stateful(starting_indexes, &minimal_refs, exit)?; + 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; 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); + sum_others!(self, starting_indexes, others, exit; sent_in_profit.height); + sum_others!(self, starting_indexes, others, exit; sent_in_loss.height); Ok(()) } @@ -141,67 +81,6 @@ impl RealizedBase { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - self.minimal.compute_rest_part1(starting_indexes, 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(()) - })?; - - Ok(()) - } - - pub(crate) fn compute_rest_part2( - &mut self, - blocks: &blocks::Vecs, - prices: &prices::Vecs, - starting_indexes: &Indexes, - height_to_supply: &impl ReadableVec, - exit: &Exit, - ) -> Result<()> { - self.minimal - .compute_rest_part2(prices, starting_indexes, height_to_supply, exit)?; - - self.realized_cap_change_1m.height.compute_rolling_change( - starting_indexes.height, - &blocks.count.height_1m_ago, - &self.minimal.realized_cap_cents.height, - exit, - )?; - - // SOPR 24h: rolling sum of stateful value_created/destroyed, then ratio - self.value_created_sum.compute_rolling_sum( - starting_indexes.height, - &blocks.count.height_24h_ago, - &self.value_created.height, - exit, - )?; - self.value_destroyed_sum.compute_rolling_sum( - starting_indexes.height, - &blocks.count.height_24h_ago, - &self.value_destroyed.height, - exit, - )?; - - self.sopr._24h.compute_binary::( - starting_indexes.height, - &self.value_created_sum._24h.height, - &self.value_destroyed_sum._24h.height, - exit, - )?; - - Ok(()) + self.core.compute_rest_part1(starting_indexes, exit) } } diff --git a/crates/brk_computer/src/distribution/metrics/realized/core.rs b/crates/brk_computer/src/distribution/metrics/realized/core.rs new file mode 100644 index 000000000..ab7eaf3b3 --- /dev/null +++ b/crates/brk_computer/src/distribution/metrics/realized/core.rs @@ -0,0 +1,185 @@ +use brk_error::Result; +use brk_traversable::Traversable; +use brk_types::{Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, StoredF64, Version}; +use derive_more::{Deref, DerefMut}; +use vecdb::{ + AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec, +}; + +use crate::{ + blocks, + distribution::state::RealizedOps, + internal::{ + ComputedFromHeight, ComputedFromHeightCumulative, LazyFromHeight, + NegCentsUnsignedToDollars, RatioCents64, RollingWindow24h, + }, + prices, +}; + +use crate::distribution::metrics::ImportConfig; + +use super::RealizedMinimal; + +#[derive(Deref, DerefMut, Traversable)] +pub struct RealizedCore { + #[deref] + #[deref_mut] + #[traversable(flatten)] + pub minimal: RealizedMinimal, + + pub realized_cap_change_1m: ComputedFromHeight, + + pub neg_realized_loss: LazyFromHeight, + pub net_realized_pnl: ComputedFromHeightCumulative, + + pub value_created: ComputedFromHeight, + pub value_destroyed: ComputedFromHeight, + pub value_created_sum: RollingWindow24h, + pub value_destroyed_sum: RollingWindow24h, + pub sopr: RollingWindow24h, +} + +impl RealizedCore { + pub(crate) fn forced_import(cfg: &ImportConfig) -> Result { + let v0 = Version::ZERO; + let v1 = Version::ONE; + + let minimal = RealizedMinimal::forced_import(cfg)?; + + let neg_realized_loss = LazyFromHeight::from_height_source::( + &cfg.name("neg_realized_loss"), + cfg.version + Version::ONE, + minimal.realized_loss.height.read_only_boxed_clone(), + cfg.indexes, + ); + + let net_realized_pnl = cfg.import("net_realized_pnl", v0)?; + + let value_created = cfg.import("value_created", v0)?; + let value_destroyed = cfg.import("value_destroyed", v0)?; + let value_created_sum = cfg.import("value_created", v1)?; + let value_destroyed_sum = cfg.import("value_destroyed", v1)?; + let sopr = cfg.import("sopr", v1)?; + + Ok(Self { + minimal, + realized_cap_change_1m: cfg.import("realized_cap_change_1m", v0)?, + neg_realized_loss, + net_realized_pnl, + value_created, + value_destroyed, + value_created_sum, + value_destroyed_sum, + sopr, + }) + } + + pub(crate) fn min_stateful_height_len(&self) -> usize { + self.minimal + .min_stateful_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.minimal.truncate_push(height, state)?; + 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> { + 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 + } + + pub(crate) fn compute_from_stateful( + &mut self, + starting_indexes: &Indexes, + others: &[&Self], + exit: &Exit, + ) -> Result<()> { + let minimal_refs: Vec<&RealizedMinimal> = others.iter().map(|o| &o.minimal).collect(); + self.minimal + .compute_from_stateful(starting_indexes, &minimal_refs, exit)?; + + 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.minimal.compute_rest_part1(starting_indexes, 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(()) + })?; + + Ok(()) + } + + pub(crate) fn compute_rest_part2( + &mut self, + blocks: &blocks::Vecs, + prices: &prices::Vecs, + starting_indexes: &Indexes, + height_to_supply: &impl ReadableVec, + exit: &Exit, + ) -> Result<()> { + self.minimal + .compute_rest_part2(prices, starting_indexes, height_to_supply, exit)?; + + self.realized_cap_change_1m.height.compute_rolling_change( + starting_indexes.height, + &blocks.count.height_1m_ago, + &self.minimal.realized_cap_cents.height, + exit, + )?; + + self.value_created_sum.compute_rolling_sum( + starting_indexes.height, + &blocks.count.height_24h_ago, + &self.value_created.height, + exit, + )?; + self.value_destroyed_sum.compute_rolling_sum( + starting_indexes.height, + &blocks.count.height_24h_ago, + &self.value_destroyed.height, + exit, + )?; + + self.sopr._24h.compute_binary::( + starting_indexes.height, + &self.value_created_sum._24h.height, + &self.value_destroyed_sum._24h.height, + exit, + )?; + + Ok(()) + } +} diff --git a/crates/brk_computer/src/distribution/metrics/realized/full.rs b/crates/brk_computer/src/distribution/metrics/realized/full.rs index bd6fcb094..7f2df1f7d 100644 --- a/crates/brk_computer/src/distribution/metrics/realized/full.rs +++ b/crates/brk_computer/src/distribution/metrics/realized/full.rs @@ -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, StoredF64, Version, + Dollars, Height, Indexes, Sats, StoredF64, Version, }; use derive_more::{Deref, DerefMut}; use vecdb::{ @@ -19,7 +19,7 @@ use crate::{ ComputedFromHeightRatioStdDevBands, LazyFromHeight, PercentFromHeight, PercentRollingEmas1w1m, PercentRollingWindows, Price, RatioCents64, RatioCentsBp32, RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDollarsBp32, - RollingEmas1w1m, RollingEmas2w, RollingWindows, RollingWindowsFrom1w, + RollingEmas1w1m, RollingWindows, RollingWindowsFrom1w, }, prices, }; @@ -33,7 +33,7 @@ pub struct RealizedFull { #[deref] #[deref_mut] #[traversable(flatten)] - pub core: RealizedBase, + pub base: RealizedBase, pub gross_pnl: FiatFromHeight, @@ -86,8 +86,8 @@ pub struct RealizedFull { pub value_destroyed_sum_extended: RollingWindowsFrom1w, pub sopr_extended: RollingWindowsFrom1w, - pub sent_in_profit_ema: RollingEmas2w, - pub sent_in_loss_ema: RollingEmas2w, + pub sent_in_profit_sum: RollingWindows, + pub sent_in_loss_sum: RollingWindows, pub realized_price_ratio_percentiles: ComputedFromHeightRatioPercentiles, pub realized_price_ratio_std_dev: ComputedFromHeightRatioStdDevBands, @@ -99,7 +99,7 @@ impl RealizedFull { let v0 = Version::ZERO; let v1 = Version::ONE; - let core = RealizedBase::forced_import(cfg)?; + let base = RealizedBase::forced_import(cfg)?; let gross_pnl = cfg.import("realized_gross_pnl", v0)?; @@ -161,11 +161,9 @@ impl RealizedFull { let value_created_sum_extended = cfg.import("value_created", v1)?; let value_destroyed_sum_extended = cfg.import("value_destroyed", v1)?; let sopr_extended = cfg.import("sopr", v1)?; - let sent_in_profit_ema = cfg.import("sent_in_profit", v0)?; - let sent_in_loss_ema = cfg.import("sent_in_loss", v0)?; Ok(Self { - core, + base, gross_pnl, realized_profit_rel_to_realized_cap, realized_loss_rel_to_realized_cap, @@ -205,8 +203,8 @@ impl RealizedFull { value_created_sum_extended, value_destroyed_sum_extended, sopr_extended, - sent_in_profit_ema, - sent_in_loss_ema, + sent_in_profit_sum: cfg.import("sent_in_profit", v1)?, + sent_in_loss_sum: cfg.import("sent_in_loss", v1)?, realized_price_ratio_percentiles: ComputedFromHeightRatioPercentiles::forced_import( cfg.db, &realized_price_name, @@ -229,7 +227,7 @@ impl RealizedFull { } pub(crate) fn min_stateful_height_len(&self) -> usize { - self.core + self.base .min_stateful_height_len() .min(self.profit_value_created.height.len()) .min(self.profit_value_destroyed.height.len()) @@ -242,7 +240,7 @@ impl RealizedFull { } pub(crate) fn truncate_push(&mut self, height: Height, state: &RealizedState) -> Result<()> { - self.core.truncate_push(height, state)?; + self.base.truncate_push(height, state)?; self.profit_value_created .height .truncate_push(height, state.profit_value_created())?; @@ -270,7 +268,7 @@ impl RealizedFull { } pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { - let mut vecs = self.core.collect_vecs_mut(); + let mut vecs = self.base.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); @@ -282,15 +280,13 @@ impl RealizedFull { 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: &[&RealizedBase], exit: &Exit, ) -> Result<()> { - self.core + self.base .compute_from_stateful(starting_indexes, others, exit)?; Ok(()) @@ -301,7 +297,7 @@ impl RealizedFull { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - self.core.compute_rest_part1(starting_indexes, exit)?; + self.base.compute_rest_part1(starting_indexes, exit)?; self.peak_regret .compute_rest(starting_indexes.height, exit)?; Ok(()) @@ -316,7 +312,7 @@ impl RealizedFull { height_to_market_cap: &impl ReadableVec, exit: &Exit, ) -> Result<()> { - self.core.compute_rest_part2( + self.base.core.compute_rest_part2( blocks, prices, starting_indexes, @@ -329,13 +325,13 @@ impl RealizedFull { self.value_created_sum_extended.compute_rolling_sum( starting_indexes.height, &window_starts, - &self.core.value_created.height, + &self.base.core.value_created.height, exit, )?; self.value_destroyed_sum_extended.compute_rolling_sum( starting_indexes.height, &window_starts, - &self.core.value_destroyed.height, + &self.base.core.value_destroyed.height, exit, )?; for ((sopr, vc), vd) in self @@ -357,22 +353,22 @@ impl RealizedFull { self.realized_profit_rel_to_realized_cap .compute_binary::( starting_indexes.height, - &self.core.minimal.realized_profit.height, - &self.core.minimal.realized_cap_cents.height, + &self.base.core.minimal.realized_profit.height, + &self.base.core.minimal.realized_cap_cents.height, exit, )?; self.realized_loss_rel_to_realized_cap .compute_binary::( starting_indexes.height, - &self.core.minimal.realized_loss.height, - &self.core.minimal.realized_cap_cents.height, + &self.base.core.minimal.realized_loss.height, + &self.base.core.minimal.realized_cap_cents.height, exit, )?; self.net_realized_pnl_rel_to_realized_cap .compute_binary::( starting_indexes.height, - &self.core.net_realized_pnl.height, - &self.core.minimal.realized_cap_cents.height, + &self.base.core.net_realized_pnl.height, + &self.base.core.minimal.realized_cap_cents.height, exit, )?; @@ -380,48 +376,49 @@ impl RealizedFull { self.realized_profit_ema_1w.height.compute_rolling_ema( starting_indexes.height, &blocks.count.height_1w_ago, - &self.core.minimal.realized_profit.height, + &self.base.core.minimal.realized_profit.height, exit, )?; self.realized_loss_ema_1w.height.compute_rolling_ema( starting_indexes.height, &blocks.count.height_1w_ago, - &self.core.minimal.realized_loss.height, + &self.base.core.minimal.realized_loss.height, exit, )?; self.net_realized_pnl_ema_1w.height.compute_rolling_ema( starting_indexes.height, &blocks.count.height_1w_ago, - &self.core.net_realized_pnl.height, + &self.base.core.net_realized_pnl.height, exit, )?; self.sopr_24h_ema.compute_from_24h( starting_indexes.height, &blocks.count.height_1w_ago, &blocks.count.height_1m_ago, - &self.core.sopr._24h.height, + &self.base.core.sopr._24h.height, exit, )?; - self.sent_in_profit_ema.compute( + + // Sent in profit/loss rolling sums + let window_starts = blocks.count.window_starts(); + self.sent_in_profit_sum.compute_rolling_sum( starting_indexes.height, - &blocks.count.height_2w_ago, - &self.core.sent_in_profit.base.sats.height, - &self.core.sent_in_profit.base.cents.height, + &window_starts, + &self.base.sent_in_profit.height, exit, )?; - self.sent_in_loss_ema.compute( + self.sent_in_loss_sum.compute_rolling_sum( starting_indexes.height, - &blocks.count.height_2w_ago, - &self.core.sent_in_loss.base.sats.height, - &self.core.sent_in_loss.base.cents.height, + &window_starts, + &self.base.sent_in_loss.height, exit, )?; // Gross PnL self.gross_pnl.cents.height.compute_add( starting_indexes.height, - &self.core.minimal.realized_profit.height, - &self.core.minimal.realized_loss.height, + &self.base.core.minimal.realized_profit.height, + &self.base.core.minimal.realized_loss.height, exit, )?; @@ -437,14 +434,14 @@ impl RealizedFull { self.net_pnl_change_1m.height.compute_rolling_change( starting_indexes.height, &blocks.count.height_1m_ago, - &self.core.net_realized_pnl.cumulative.height, + &self.base.core.net_realized_pnl.cumulative.height, exit, )?; self.net_pnl_change_1m_rel_to_realized_cap .compute_binary::( starting_indexes.height, &self.net_pnl_change_1m.height, - &self.core.minimal.realized_cap_cents.height, + &self.base.core.minimal.realized_cap_cents.height, exit, )?; self.net_pnl_change_1m_rel_to_market_cap @@ -460,7 +457,7 @@ impl RealizedFull { .compute_binary::( starting_indexes.height, &self.peak_regret.height, - &self.core.minimal.realized_cap_cents.height, + &self.base.core.minimal.realized_cap_cents.height, exit, )?; @@ -472,10 +469,9 @@ impl RealizedFull { exit, )?; - // Use explicit field paths for split borrows self.lower_price_band.cents.height.compute_transform2( starting_indexes.height, - &self.core.minimal.realized_price.cents.height, + &self.base.core.minimal.realized_price.cents.height, &self.investor_price.cents.height, |(i, rp, ip, ..)| { let rp = rp.as_u128(); @@ -492,7 +488,7 @@ impl RealizedFull { self.upper_price_band.cents.height.compute_transform2( starting_indexes.height, &self.investor_price.cents.height, - &self.core.minimal.realized_price.cents.height, + &self.base.core.minimal.realized_price.cents.height, |(i, ip, rp, ..)| { let ip = ip.as_u128(); let rp = rp.as_u128(); @@ -515,7 +511,7 @@ impl RealizedFull { ssrr.compute_binary::( starting_indexes.height, &rv.height, - &self.core.minimal.realized_cap_cents.height, + &self.base.core.minimal.realized_cap_cents.height, exit, )?; } @@ -533,13 +529,13 @@ impl RealizedFull { self.realized_profit_sum.compute_rolling_sum( starting_indexes.height, &window_starts, - &self.core.minimal.realized_profit.height, + &self.base.core.minimal.realized_profit.height, exit, )?; self.realized_loss_sum.compute_rolling_sum( starting_indexes.height, &window_starts, - &self.core.minimal.realized_loss.height, + &self.base.core.minimal.realized_loss.height, exit, )?; @@ -547,7 +543,7 @@ impl RealizedFull { self.realized_cap_rel_to_own_market_cap .compute_binary::( starting_indexes.height, - &self.core.minimal.realized_cap.height, + &self.base.core.minimal.realized_cap.height, height_to_market_cap, exit, )?; @@ -572,16 +568,16 @@ impl RealizedFull { blocks, starting_indexes, exit, - &self.core.minimal.realized_price_ratio.ratio.height, - &self.core.minimal.realized_price.cents.height, + &self.base.core.minimal.realized_price_ratio.ratio.height, + &self.base.core.minimal.realized_price.cents.height, )?; self.realized_price_ratio_std_dev.compute( blocks, starting_indexes, exit, - &self.core.minimal.realized_price_ratio.ratio.height, - &self.core.minimal.realized_price.cents.height, + &self.base.core.minimal.realized_price_ratio.ratio.height, + &self.base.core.minimal.realized_price.cents.height, )?; // Investor price: percentiles diff --git a/crates/brk_computer/src/distribution/metrics/realized/mod.rs b/crates/brk_computer/src/distribution/metrics/realized/mod.rs index 23917e32b..0e654a4f3 100644 --- a/crates/brk_computer/src/distribution/metrics/realized/mod.rs +++ b/crates/brk_computer/src/distribution/metrics/realized/mod.rs @@ -1,10 +1,12 @@ mod adjusted; mod base; +mod core; mod full; mod minimal; pub use adjusted::RealizedAdjusted; pub use base::RealizedBase; +pub use self::core::RealizedCore; pub use full::RealizedFull; pub use minimal::RealizedMinimal; @@ -49,8 +51,8 @@ impl RealizedLike for RealizedBase { } impl RealizedLike for RealizedFull { - fn as_base(&self) -> &RealizedBase { &self.core } - fn as_base_mut(&mut self) -> &mut RealizedBase { &mut self.core } + fn as_base(&self) -> &RealizedBase { &self.base } + fn as_base_mut(&mut self) -> &mut RealizedBase { &mut self.base } fn min_stateful_height_len(&self) -> usize { self.min_stateful_height_len() } fn truncate_push(&mut self, height: Height, state: &RealizedState) -> Result<()> { self.truncate_push(height, state) diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index f6f4ec22b..7bf79ce83 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -1619,10 +1619,10 @@ function createMetricPattern35(client, name) { return /** @type {MetricPattern35 * @property {_1m1w1y24hPattern} realizedProfitToLossRatio * @property {_1m1w1y24hPattern2} sellSideRiskRatio * @property {_1m1wPattern2} sellSideRiskRatio24hEma - * @property {BaseCumulativePattern} sentInLoss - * @property {_2wPattern} sentInLossEma - * @property {BaseCumulativePattern} sentInProfit - * @property {_2wPattern} sentInProfitEma + * @property {MetricPattern1} sentInLoss + * @property {_1m1w1y24hPattern} sentInLossSum + * @property {MetricPattern1} sentInProfit + * @property {_1m1w1y24hPattern} sentInProfitSum * @property {_24hPattern} sopr * @property {_1m1wPattern} sopr24hEma * @property {_1m1w1yPattern} soprExtended @@ -1686,10 +1686,10 @@ function createCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealized realizedProfitToLossRatio: create_1m1w1y24hPattern(client, _m(acc, 'realized_profit_to_loss_ratio')), sellSideRiskRatio: create_1m1w1y24hPattern2(client, _m(acc, 'sell_side_risk_ratio')), sellSideRiskRatio24hEma: create_1m1wPattern2(client, _m(acc, 'sell_side_risk_ratio_24h_ema')), - sentInLoss: createBaseCumulativePattern(client, _m(acc, 'sent_in_loss')), - sentInLossEma: create_2wPattern(client, _m(acc, 'sent_in_loss_ema_2w')), - sentInProfit: createBaseCumulativePattern(client, _m(acc, 'sent_in_profit')), - sentInProfitEma: create_2wPattern(client, _m(acc, 'sent_in_profit_ema_2w')), + sentInLoss: createMetricPattern1(client, _m(acc, 'sent_in_loss')), + sentInLossSum: create_1m1w1y24hPattern(client, _m(acc, 'sent_in_loss')), + sentInProfit: createMetricPattern1(client, _m(acc, 'sent_in_profit')), + sentInProfitSum: create_1m1w1y24hPattern(client, _m(acc, 'sent_in_profit')), sopr: create_24hPattern(client, _m(acc, 'sopr_24h')), sopr24hEma: create_1m1wPattern(client, _m(acc, 'sopr_24h_ema')), soprExtended: create_1m1w1yPattern(client, _m(acc, 'sopr')), @@ -1839,8 +1839,8 @@ function createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65 * @property {CentsSatsUsdPattern} realizedPrice * @property {BpsRatioPattern} realizedPriceRatio * @property {CumulativeHeightPattern} realizedProfit - * @property {BaseCumulativePattern} sentInLoss - * @property {BaseCumulativePattern} sentInProfit + * @property {MetricPattern1} sentInLoss + * @property {MetricPattern1} sentInProfit * @property {_24hPattern} sopr * @property {MetricPattern1} valueCreated * @property {_24hPattern} valueCreatedSum @@ -1866,8 +1866,8 @@ function createMvrvNegNetRealizedSentSoprValuePattern(client, acc) { realizedPrice: createCentsSatsUsdPattern(client, _m(acc, 'realized_price')), realizedPriceRatio: createBpsRatioPattern(client, _m(acc, 'realized_price_ratio')), realizedProfit: createCumulativeHeightPattern(client, _m(acc, 'realized_profit')), - sentInLoss: createBaseCumulativePattern(client, _m(acc, 'sent_in_loss')), - sentInProfit: createBaseCumulativePattern(client, _m(acc, 'sent_in_profit')), + sentInLoss: createMetricPattern1(client, _m(acc, 'sent_in_loss')), + sentInProfit: createMetricPattern1(client, _m(acc, 'sent_in_profit')), sopr: create_24hPattern(client, _m(acc, 'sopr_24h')), valueCreated: createMetricPattern1(client, _m(acc, 'value_created')), valueCreatedSum: create_24hPattern(client, _m(acc, 'value_created_24h')), @@ -1970,6 +1970,51 @@ function createGreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern(clien }; } +/** + * @typedef {Object} MvrvNegNetRealizedSoprValuePattern + * @property {MetricPattern1} mvrv + * @property {MetricPattern1} negRealizedLoss + * @property {CumulativeHeightPattern} netRealizedPnl + * @property {MetricPattern1} realizedCap + * @property {MetricPattern1} realizedCapCents + * @property {MetricPattern1} realizedCapChange1m + * @property {CumulativeHeightPattern} realizedLoss + * @property {CentsSatsUsdPattern} realizedPrice + * @property {BpsRatioPattern} realizedPriceRatio + * @property {CumulativeHeightPattern} realizedProfit + * @property {_24hPattern} sopr + * @property {MetricPattern1} valueCreated + * @property {_24hPattern} valueCreatedSum + * @property {MetricPattern1} valueDestroyed + * @property {_24hPattern} valueDestroyedSum + */ + +/** + * Create a MvrvNegNetRealizedSoprValuePattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {MvrvNegNetRealizedSoprValuePattern} + */ +function createMvrvNegNetRealizedSoprValuePattern(client, acc) { + return { + mvrv: createMetricPattern1(client, _m(acc, 'mvrv')), + negRealizedLoss: createMetricPattern1(client, _m(acc, 'neg_realized_loss')), + netRealizedPnl: createCumulativeHeightPattern(client, _m(acc, 'net_realized_pnl')), + realizedCap: createMetricPattern1(client, _m(acc, 'realized_cap')), + realizedCapCents: createMetricPattern1(client, _m(acc, 'realized_cap_cents')), + realizedCapChange1m: createMetricPattern1(client, _m(acc, 'realized_cap_change_1m')), + realizedLoss: createCumulativeHeightPattern(client, _m(acc, 'realized_loss')), + realizedPrice: createCentsSatsUsdPattern(client, _m(acc, 'realized_price')), + realizedPriceRatio: createBpsRatioPattern(client, _m(acc, 'realized_price_ratio')), + realizedProfit: createCumulativeHeightPattern(client, _m(acc, 'realized_profit')), + sopr: create_24hPattern(client, _m(acc, 'sopr_24h')), + valueCreated: createMetricPattern1(client, _m(acc, 'value_created')), + valueCreatedSum: create_24hPattern(client, _m(acc, 'value_created_24h')), + valueDestroyed: createMetricPattern1(client, _m(acc, 'value_destroyed')), + valueDestroyedSum: create_24hPattern(client, _m(acc, 'value_destroyed_24h')), + }; +} + /** * @typedef {Object} NetNuplSupplyUnrealizedPattern2 * @property {BpsPercentRatioPattern} netUnrealizedPnlRelToMarketCap @@ -2600,7 +2645,7 @@ function createMvrvRealizedPattern(client, acc) { * @typedef {Object} ActivityOutputsRealizedRelativeSupplyUnrealizedPattern * @property {SentPattern} activity * @property {UtxoPattern} outputs - * @property {MvrvNegNetRealizedSentSoprValuePattern} realized + * @property {MvrvNegNetRealizedSoprValuePattern} realized * @property {SupplyPattern2} relative * @property {ChangeHalvedTotalPattern} supply * @property {NegNetSupplyUnrealizedPattern} unrealized @@ -2616,7 +2661,7 @@ function createActivityOutputsRealizedRelativeSupplyUnrealizedPattern(client, ac return { activity: createSentPattern(client, _m(acc, 'sent')), outputs: createUtxoPattern(client, _m(acc, 'utxo_count')), - realized: createMvrvNegNetRealizedSentSoprValuePattern(client, acc), + realized: createMvrvNegNetRealizedSoprValuePattern(client, acc), relative: createSupplyPattern2(client, _m(acc, 'supply')), supply: createChangeHalvedTotalPattern(client, _m(acc, 'supply')), unrealized: createNegNetSupplyUnrealizedPattern(client, acc), diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 099663950..0311dead5 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -2114,10 +2114,10 @@ class CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentS self.realized_profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'realized_profit_to_loss_ratio')) 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.sent_in_loss: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'sent_in_loss')) + self.sent_in_loss_sum: _1m1w1y24hPattern[Sats] = _1m1w1y24hPattern(client, _m(acc, 'sent_in_loss')) + self.sent_in_profit: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'sent_in_profit')) + self.sent_in_profit_sum: _1m1w1y24hPattern[Sats] = _1m1w1y24hPattern(client, _m(acc, 'sent_in_profit')) self.sopr: _24hPattern[StoredF64] = _24hPattern(client, _m(acc, 'sopr_24h')) self.sopr_24h_ema: _1m1wPattern = _1m1wPattern(client, _m(acc, 'sopr_24h_ema')) self.sopr_extended: _1m1w1yPattern[StoredF64] = _1m1w1yPattern(client, _m(acc, 'sopr')) @@ -2203,8 +2203,8 @@ class MvrvNegNetRealizedSentSoprValuePattern: 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.sent_in_loss: BaseCumulativePattern = BaseCumulativePattern(client, _m(acc, 'sent_in_loss')) - self.sent_in_profit: BaseCumulativePattern = BaseCumulativePattern(client, _m(acc, 'sent_in_profit')) + self.sent_in_loss: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'sent_in_loss')) + self.sent_in_profit: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'sent_in_profit')) self.sopr: _24hPattern[StoredF64] = _24hPattern(client, _m(acc, 'sopr_24h')) self.value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_created')) self.value_created_sum: _24hPattern[Cents] = _24hPattern(client, _m(acc, 'value_created_24h')) @@ -2255,6 +2255,27 @@ class GreedGrossInvestedInvestorNegNetPainSupplyUnrealizedPattern: self.unrealized_loss: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_loss')) self.unrealized_profit: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_profit')) +class MvrvNegNetRealizedSoprValuePattern: + """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.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.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_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.sopr: _24hPattern[StoredF64] = _24hPattern(client, _m(acc, 'sopr_24h')) + self.value_created: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_created')) + self.value_created_sum: _24hPattern[Cents] = _24hPattern(client, _m(acc, 'value_created_24h')) + self.value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'value_destroyed')) + self.value_destroyed_sum: _24hPattern[Cents] = _24hPattern(client, _m(acc, 'value_destroyed_24h')) + class NetNuplSupplyUnrealizedPattern2: """Pattern struct for repeated tree structure.""" @@ -2547,7 +2568,7 @@ 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: MvrvNegNetRealizedSentSoprValuePattern = MvrvNegNetRealizedSentSoprValuePattern(client, acc) + self.realized: MvrvNegNetRealizedSoprValuePattern = MvrvNegNetRealizedSoprValuePattern(client, acc) self.relative: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) self.supply: ChangeHalvedTotalPattern = ChangeHalvedTotalPattern(client, _m(acc, 'supply')) self.unrealized: NegNetSupplyUnrealizedPattern = NegNetSupplyUnrealizedPattern(client, acc)