From b18cca92ab46cf1b450a62b2e59141271f0e7656 Mon Sep 17 00:00:00 2001 From: nym21 Date: Thu, 19 Mar 2026 12:15:03 +0100 Subject: [PATCH] global: snapshot --- crates/brk_client/src/lib.rs | 196 ++++++++-------- .../src/distribution/metrics/cohort/type.rs | 2 - .../relative/extended_own_market_cap.rs | 4 +- .../metrics/relative/extended_own_pnl.rs | 4 +- .../src/distribution/metrics/relative/full.rs | 4 +- .../distribution/metrics/unrealized/basic.rs | 37 +-- .../distribution/metrics/unrealized/core.rs | 7 +- .../distribution/metrics/unrealized/full.rs | 4 +- crates/brk_server/src/api/series/mod.rs | 4 +- crates/brk_types/src/basis_points_32.rs | 74 +++++- .../brk_types/src/basis_points_signed_32.rs | 81 +++++-- modules/brk-client/index.js | 218 ++++++++++-------- packages/brk_client/brk_client/__init__.py | 103 +++++---- website/scripts/chart/index.js | 2 +- website/scripts/options/cointime.js | 87 +++---- .../scripts/options/distribution/activity.js | 34 +-- .../scripts/options/distribution/holdings.js | 4 +- website/scripts/options/distribution/index.js | 4 +- .../options/distribution/profitability.js | 149 ++++-------- .../scripts/options/distribution/valuation.js | 18 +- website/scripts/options/investing.js | 26 +-- website/scripts/options/market.js | 10 +- website/scripts/options/partial.js | 49 +--- website/scripts/options/series.js | 25 +- 24 files changed, 571 insertions(+), 575 deletions(-) diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index b28ba5e63..51eccdf33 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -1369,32 +1369,6 @@ pub struct BaseCumulativeDistributionSumToValuePattern { pub value_destroyed: BaseCumulativeSumPattern, } -/// Pattern struct for repeated tree structure. -pub struct BaseCumulativeNegativeSumToPattern2 { - pub base: CentsUsdPattern2, - pub cumulative: CentsUsdPattern2, - pub negative: SeriesPattern1, - pub sum: _1m1w1y24hPattern4, - pub to_mcap: BpsPercentRatioPattern3, - pub to_own_gross_pnl: BpsPercentRatioPattern3, - pub to_own_mcap: BpsPercentRatioPattern4, -} - -impl BaseCumulativeNegativeSumToPattern2 { - /// Create a new pattern node with accumulated series name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - base: CentsUsdPattern2::new(client.clone(), _m(&acc, "unrealized_loss")), - cumulative: CentsUsdPattern2::new(client.clone(), _m(&acc, "unrealized_loss_cumulative")), - negative: SeriesPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")), - sum: _1m1w1y24hPattern4::new(client.clone(), _m(&acc, "unrealized_loss_sum")), - to_mcap: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "unrealized_loss_to_mcap")), - to_own_gross_pnl: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "unrealized_loss_to_own_gross_pnl")), - to_own_mcap: BpsPercentRatioPattern4::new(client.clone(), _m(&acc, "unrealized_loss_to_own_mcap")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct CapLossMvrvNetPriceProfitSoprPattern { pub cap: CentsDeltaUsdPattern, @@ -1411,7 +1385,7 @@ impl CapLossMvrvNetPriceProfitSoprPattern { pub fn new(client: Arc, acc: String) -> Self { Self { cap: CentsDeltaUsdPattern::new(client.clone(), _m(&acc, "realized_cap")), - loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone(), "realized_loss".to_string()), + loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone()), mvrv: SeriesPattern1::new(client.clone(), _m(&acc, "mvrv")), net_pnl: BaseCumulativeDeltaSumPattern::new(client.clone(), _m(&acc, "net_realized_pnl")), price: BpsCentsRatioSatsUsdPattern::new(client.clone(), _m(&acc, "realized_price")), @@ -1425,10 +1399,10 @@ impl CapLossMvrvNetPriceProfitSoprPattern { pub struct GrossInvestedLossNetNuplProfitSentimentPattern2 { pub gross_pnl: CentsUsdPattern2, pub invested_capital: InPattern, - pub loss: BaseCumulativeNegativeSumToPattern2, - pub net_pnl: CentsToUsdPattern2, + pub loss: CentsNegativeToUsdPattern2, + pub net_pnl: CentsToUsdPattern3, pub nupl: BpsRatioPattern, - pub profit: BaseCumulativeSumToPattern2, + pub profit: CentsToUsdPattern4, pub sentiment: GreedNetPainPattern, } @@ -1480,30 +1454,6 @@ impl BaseChangeCumulativeDeltaSumToPattern { } } -/// Pattern struct for repeated tree structure. -pub struct BaseCumulativeSumToPattern2 { - pub base: CentsUsdPattern2, - pub cumulative: CentsUsdPattern2, - pub sum: _1m1w1y24hPattern4, - pub to_mcap: BpsPercentRatioPattern3, - pub to_own_gross_pnl: BpsPercentRatioPattern3, - pub to_own_mcap: BpsPercentRatioPattern3, -} - -impl BaseCumulativeSumToPattern2 { - /// Create a new pattern node with accumulated series name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - base: CentsUsdPattern2::new(client.clone(), acc.clone()), - cumulative: CentsUsdPattern2::new(client.clone(), _m(&acc, "cumulative")), - sum: _1m1w1y24hPattern4::new(client.clone(), _m(&acc, "sum")), - to_mcap: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "to_mcap")), - to_own_gross_pnl: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "to_own_gross_pnl")), - to_own_mcap: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "to_own_mcap")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct BpsCentsPercentilesRatioSatsUsdPattern { pub bps: SeriesPattern1, @@ -1576,6 +1526,30 @@ impl CapLossMvrvPriceProfitSoprPattern { } } +/// Pattern struct for repeated tree structure. +pub struct CentsNegativeToUsdPattern2 { + pub cents: SeriesPattern1, + pub negative: SeriesPattern1, + pub to_mcap: BpsPercentRatioPattern3, + pub to_own_gross_pnl: BpsPercentRatioPattern3, + pub to_own_mcap: BpsPercentRatioPattern4, + pub usd: SeriesPattern1, +} + +impl CentsNegativeToUsdPattern2 { + /// Create a new pattern node with accumulated series name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + cents: SeriesPattern1::new(client.clone(), _m(&acc, "unrealized_loss_cents")), + negative: SeriesPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")), + to_mcap: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "unrealized_loss_to_mcap")), + to_own_gross_pnl: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "unrealized_loss_to_own_gross_pnl")), + to_own_mcap: BpsPercentRatioPattern4::new(client.clone(), _m(&acc, "unrealized_loss_to_own_mcap")), + usd: SeriesPattern1::new(client.clone(), _m(&acc, "unrealized_loss")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct DeltaHalfInToTotalPattern { pub delta: AbsoluteRatePattern, @@ -1802,6 +1776,28 @@ impl BtcCentsSatsToUsdPattern2 { } } +/// Pattern struct for repeated tree structure. +pub struct CentsToUsdPattern4 { + pub cents: SeriesPattern1, + pub to_mcap: BpsPercentRatioPattern3, + pub to_own_gross_pnl: BpsPercentRatioPattern3, + pub to_own_mcap: BpsPercentRatioPattern3, + pub usd: SeriesPattern1, +} + +impl CentsToUsdPattern4 { + /// Create a new pattern node with accumulated series name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + cents: SeriesPattern1::new(client.clone(), _m(&acc, "cents")), + to_mcap: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "to_mcap")), + to_own_gross_pnl: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "to_own_gross_pnl")), + to_own_mcap: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "to_own_mcap")), + usd: SeriesPattern1::new(client.clone(), acc.clone()), + } + } +} + /// Pattern struct for repeated tree structure. pub struct DeltaHalfInTotalPattern2 { pub delta: AbsoluteRatePattern, @@ -2052,12 +2048,12 @@ pub struct BaseCumulativeNegativeSumPattern { impl BaseCumulativeNegativeSumPattern { /// Create a new pattern node with accumulated series name. - pub fn new(client: Arc, acc: String, disc: String) -> Self { + pub fn new(client: Arc, acc: String) -> Self { Self { - base: CentsUsdPattern2::new(client.clone(), _m(&acc, &disc)), - cumulative: CentsUsdPattern2::new(client.clone(), _m(&acc, &format!("{disc}_cumulative", disc=disc))), - negative: SeriesPattern1::new(client.clone(), _m(&acc, &format!("neg_{disc}", disc=disc))), - sum: _1m1w1y24hPattern4::new(client.clone(), _m(&acc, &format!("{disc}_sum", disc=disc))), + base: CentsUsdPattern2::new(client.clone(), _m(&acc, "realized_loss")), + cumulative: CentsUsdPattern2::new(client.clone(), _m(&acc, "realized_loss_cumulative")), + negative: SeriesPattern1::new(client.clone(), _m(&acc, "neg_realized_loss")), + sum: _1m1w1y24hPattern4::new(client.clone(), _m(&acc, "realized_loss_sum")), } } } @@ -2123,14 +2119,14 @@ impl CentsDeltaToUsdPattern { } /// Pattern struct for repeated tree structure. -pub struct CentsToUsdPattern2 { +pub struct CentsToUsdPattern3 { pub cents: SeriesPattern1, pub to_own_gross_pnl: BpsPercentRatioPattern, pub to_own_mcap: BpsPercentRatioPattern, pub usd: SeriesPattern1, } -impl CentsToUsdPattern2 { +impl CentsToUsdPattern3 { /// Create a new pattern node with accumulated series name. pub fn new(client: Arc, acc: String) -> Self { Self { @@ -2152,20 +2148,20 @@ pub struct CoindaysCoinyearsDormancyTransferPattern { /// Pattern struct for repeated tree structure. pub struct LossNetNuplProfitPattern { - pub loss: BaseCumulativeNegativeSumPattern, + pub loss: CentsNegativeUsdPattern, pub net_pnl: CentsUsdPattern, pub nupl: BpsRatioPattern, - pub profit: BaseCumulativeSumPattern3, + pub profit: CentsUsdPattern2, } impl LossNetNuplProfitPattern { /// Create a new pattern node with accumulated series name. pub fn new(client: Arc, acc: String) -> Self { Self { - loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone(), "unrealized_loss".to_string()), + loss: CentsNegativeUsdPattern::new(client.clone(), acc.clone()), net_pnl: CentsUsdPattern::new(client.clone(), _m(&acc, "net_unrealized_pnl")), nupl: BpsRatioPattern::new(client.clone(), _m(&acc, "nupl")), - profit: BaseCumulativeSumPattern3::new(client.clone(), _m(&acc, "unrealized_profit")), + profit: CentsUsdPattern2::new(client.clone(), _m(&acc, "unrealized_profit")), } } } @@ -2446,6 +2442,24 @@ impl CentsDeltaUsdPattern { } } +/// Pattern struct for repeated tree structure. +pub struct CentsNegativeUsdPattern { + pub cents: SeriesPattern1, + pub negative: SeriesPattern1, + pub usd: SeriesPattern1, +} + +impl CentsNegativeUsdPattern { + /// Create a new pattern node with accumulated series name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + cents: SeriesPattern1::new(client.clone(), _m(&acc, "unrealized_loss_cents")), + negative: SeriesPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")), + usd: SeriesPattern1::new(client.clone(), _m(&acc, "unrealized_loss")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct CentsSatsUsdPattern { pub cents: SeriesPattern1, @@ -2509,18 +2523,18 @@ pub struct GreedNetPainPattern { /// Pattern struct for repeated tree structure. pub struct LossNuplProfitPattern { - pub loss: BaseCumulativeNegativeSumPattern, + pub loss: CentsNegativeUsdPattern, pub nupl: BpsRatioPattern, - pub profit: BaseCumulativeSumPattern3, + pub profit: CentsUsdPattern2, } impl LossNuplProfitPattern { /// Create a new pattern node with accumulated series name. pub fn new(client: Arc, acc: String) -> Self { Self { - loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone(), "unrealized_loss".to_string()), + loss: CentsNegativeUsdPattern::new(client.clone(), acc.clone()), nupl: BpsRatioPattern::new(client.clone(), _m(&acc, "nupl")), - profit: BaseCumulativeSumPattern3::new(client.clone(), _m(&acc, "unrealized_profit")), + profit: CentsUsdPattern2::new(client.clone(), _m(&acc, "unrealized_profit")), } } } @@ -6678,9 +6692,8 @@ impl SeriesTree_Cohorts_Utxo_All_Unrealized { /// Series tree node. pub struct SeriesTree_Cohorts_Utxo_All_Unrealized_Profit { - pub base: CentsUsdPattern2, - pub cumulative: CentsUsdPattern2, - pub sum: _1m1w1y24hPattern4, + pub usd: SeriesPattern1, + pub cents: SeriesPattern1, pub to_mcap: BpsPercentRatioPattern3, pub to_own_gross_pnl: BpsPercentRatioPattern3, } @@ -6688,9 +6701,8 @@ pub struct SeriesTree_Cohorts_Utxo_All_Unrealized_Profit { impl SeriesTree_Cohorts_Utxo_All_Unrealized_Profit { pub fn new(client: Arc, base_path: String) -> Self { Self { - base: CentsUsdPattern2::new(client.clone(), "unrealized_profit".to_string()), - cumulative: CentsUsdPattern2::new(client.clone(), "unrealized_profit_cumulative".to_string()), - sum: _1m1w1y24hPattern4::new(client.clone(), "unrealized_profit_sum".to_string()), + usd: SeriesPattern1::new(client.clone(), "unrealized_profit".to_string()), + cents: SeriesPattern1::new(client.clone(), "unrealized_profit_cents".to_string()), to_mcap: BpsPercentRatioPattern3::new(client.clone(), "unrealized_profit_to_mcap".to_string()), to_own_gross_pnl: BpsPercentRatioPattern3::new(client.clone(), "unrealized_profit_to_own_gross_pnl".to_string()), } @@ -6699,9 +6711,8 @@ impl SeriesTree_Cohorts_Utxo_All_Unrealized_Profit { /// Series tree node. pub struct SeriesTree_Cohorts_Utxo_All_Unrealized_Loss { - pub base: CentsUsdPattern2, - pub cumulative: CentsUsdPattern2, - pub sum: _1m1w1y24hPattern4, + pub usd: SeriesPattern1, + pub cents: SeriesPattern1, pub negative: SeriesPattern1, pub to_mcap: BpsPercentRatioPattern3, pub to_own_gross_pnl: BpsPercentRatioPattern3, @@ -6710,9 +6721,8 @@ pub struct SeriesTree_Cohorts_Utxo_All_Unrealized_Loss { impl SeriesTree_Cohorts_Utxo_All_Unrealized_Loss { pub fn new(client: Arc, base_path: String) -> Self { Self { - base: CentsUsdPattern2::new(client.clone(), "unrealized_loss".to_string()), - cumulative: CentsUsdPattern2::new(client.clone(), "unrealized_loss_cumulative".to_string()), - sum: _1m1w1y24hPattern4::new(client.clone(), "unrealized_loss_sum".to_string()), + usd: SeriesPattern1::new(client.clone(), "unrealized_loss".to_string()), + cents: SeriesPattern1::new(client.clone(), "unrealized_loss_cents".to_string()), negative: SeriesPattern1::new(client.clone(), "neg_unrealized_loss".to_string()), to_mcap: BpsPercentRatioPattern3::new(client.clone(), "unrealized_loss_to_mcap".to_string()), to_own_gross_pnl: BpsPercentRatioPattern3::new(client.clone(), "unrealized_loss_to_own_gross_pnl".to_string()), @@ -7153,9 +7163,9 @@ impl SeriesTree_Cohorts_Utxo_Sth_CostBasis { /// Series tree node. pub struct SeriesTree_Cohorts_Utxo_Sth_Unrealized { pub nupl: BpsRatioPattern, - pub profit: BaseCumulativeSumToPattern2, - pub loss: BaseCumulativeNegativeSumToPattern2, - pub net_pnl: CentsToUsdPattern2, + pub profit: CentsToUsdPattern4, + pub loss: CentsNegativeToUsdPattern2, + pub net_pnl: CentsToUsdPattern3, pub gross_pnl: CentsUsdPattern2, pub invested_capital: InPattern, pub sentiment: SeriesTree_Cohorts_Utxo_Sth_Unrealized_Sentiment, @@ -7165,9 +7175,9 @@ impl SeriesTree_Cohorts_Utxo_Sth_Unrealized { pub fn new(client: Arc, base_path: String) -> Self { Self { nupl: BpsRatioPattern::new(client.clone(), "sth_nupl".to_string()), - profit: BaseCumulativeSumToPattern2::new(client.clone(), "sth_unrealized_profit".to_string()), - loss: BaseCumulativeNegativeSumToPattern2::new(client.clone(), "sth".to_string()), - net_pnl: CentsToUsdPattern2::new(client.clone(), "sth_net_unrealized_pnl".to_string()), + profit: CentsToUsdPattern4::new(client.clone(), "sth_unrealized_profit".to_string()), + loss: CentsNegativeToUsdPattern2::new(client.clone(), "sth".to_string()), + net_pnl: CentsToUsdPattern3::new(client.clone(), "sth_net_unrealized_pnl".to_string()), gross_pnl: CentsUsdPattern2::new(client.clone(), "sth_unrealized_gross_pnl".to_string()), invested_capital: InPattern::new(client.clone(), "sth_invested_capital_in".to_string()), sentiment: SeriesTree_Cohorts_Utxo_Sth_Unrealized_Sentiment::new(client.clone(), format!("{base_path}_sentiment")), @@ -7572,9 +7582,9 @@ impl SeriesTree_Cohorts_Utxo_Lth_CostBasis { /// Series tree node. pub struct SeriesTree_Cohorts_Utxo_Lth_Unrealized { pub nupl: BpsRatioPattern, - pub profit: BaseCumulativeSumToPattern2, - pub loss: BaseCumulativeNegativeSumToPattern2, - pub net_pnl: CentsToUsdPattern2, + pub profit: CentsToUsdPattern4, + pub loss: CentsNegativeToUsdPattern2, + pub net_pnl: CentsToUsdPattern3, pub gross_pnl: CentsUsdPattern2, pub invested_capital: InPattern, pub sentiment: SeriesTree_Cohorts_Utxo_Lth_Unrealized_Sentiment, @@ -7584,9 +7594,9 @@ impl SeriesTree_Cohorts_Utxo_Lth_Unrealized { pub fn new(client: Arc, base_path: String) -> Self { Self { nupl: BpsRatioPattern::new(client.clone(), "lth_nupl".to_string()), - profit: BaseCumulativeSumToPattern2::new(client.clone(), "lth_unrealized_profit".to_string()), - loss: BaseCumulativeNegativeSumToPattern2::new(client.clone(), "lth".to_string()), - net_pnl: CentsToUsdPattern2::new(client.clone(), "lth_net_unrealized_pnl".to_string()), + profit: CentsToUsdPattern4::new(client.clone(), "lth_unrealized_profit".to_string()), + loss: CentsNegativeToUsdPattern2::new(client.clone(), "lth".to_string()), + net_pnl: CentsToUsdPattern3::new(client.clone(), "lth_net_unrealized_pnl".to_string()), gross_pnl: CentsUsdPattern2::new(client.clone(), "lth_unrealized_gross_pnl".to_string()), invested_capital: InPattern::new(client.clone(), "lth_invested_capital_in".to_string()), sentiment: SeriesTree_Cohorts_Utxo_Lth_Unrealized_Sentiment::new(client.clone(), format!("{base_path}_sentiment")), diff --git a/crates/brk_computer/src/distribution/metrics/cohort/type.rs b/crates/brk_computer/src/distribution/metrics/cohort/type.rs index c0a546290..309a8516b 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/type.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/type.rs @@ -61,8 +61,6 @@ impl TypeCohortMetrics { self.supply.compute(prices, starting_indexes.height, exit)?; self.realized .compute_rest_part1(starting_indexes, exit)?; - self.unrealized - .compute_rest(starting_indexes.height, exit)?; Ok(()) } diff --git a/crates/brk_computer/src/distribution/metrics/relative/extended_own_market_cap.rs b/crates/brk_computer/src/distribution/metrics/relative/extended_own_market_cap.rs index 06e9920a9..ab515b3b8 100644 --- a/crates/brk_computer/src/distribution/metrics/relative/extended_own_market_cap.rs +++ b/crates/brk_computer/src/distribution/metrics/relative/extended_own_market_cap.rs @@ -42,14 +42,14 @@ impl RelativeExtendedOwnMarketCap { self.unrealized_profit_to_own_mcap .compute_binary::( max_from, - &unrealized.profit.base.usd.height, + &unrealized.profit.usd.height, own_market_cap, exit, )?; self.unrealized_loss_to_own_mcap .compute_binary::( max_from, - &unrealized.loss.base.usd.height, + &unrealized.loss.usd.height, own_market_cap, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/relative/extended_own_pnl.rs b/crates/brk_computer/src/distribution/metrics/relative/extended_own_pnl.rs index e4a4d175e..a90eaf2fe 100644 --- a/crates/brk_computer/src/distribution/metrics/relative/extended_own_pnl.rs +++ b/crates/brk_computer/src/distribution/metrics/relative/extended_own_pnl.rs @@ -43,14 +43,14 @@ impl RelativeExtendedOwnPnl { self.unrealized_profit_to_own_gross_pnl .compute_binary::( max_from, - &unrealized.profit.base.usd.height, + &unrealized.profit.usd.height, gross_pnl_usd, exit, )?; self.unrealized_loss_to_own_gross_pnl .compute_binary::( max_from, - &unrealized.loss.base.usd.height, + &unrealized.loss.usd.height, gross_pnl_usd, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/relative/full.rs b/crates/brk_computer/src/distribution/metrics/relative/full.rs index 3dd8dfc32..bd7fe0118 100644 --- a/crates/brk_computer/src/distribution/metrics/relative/full.rs +++ b/crates/brk_computer/src/distribution/metrics/relative/full.rs @@ -64,14 +64,14 @@ impl RelativeFull { self.unrealized_profit_to_mcap .compute_binary::( max_from, - &unrealized.profit.base.usd.height, + &unrealized.profit.usd.height, market_cap, exit, )?; self.unrealized_loss_to_mcap .compute_binary::( max_from, - &unrealized.loss.base.usd.height, + &unrealized.loss.usd.height, market_cap, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/unrealized/basic.rs b/crates/brk_computer/src/distribution/metrics/unrealized/basic.rs index 1059433be..769b627af 100644 --- a/crates/brk_computer/src/distribution/metrics/unrealized/basic.rs +++ b/crates/brk_computer/src/distribution/metrics/unrealized/basic.rs @@ -1,12 +1,12 @@ use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{Cents, Dollars, Height, Indexes, Version}; +use brk_types::{Cents, Dollars, Indexes, Version}; use derive_more::{Deref, DerefMut}; use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, Rw, StorageMode, WritableVec}; use crate::{ distribution::{metrics::ImportConfig, state::UnrealizedState}, - internal::{FiatPerBlockCumulativeWithSums, LazyPerBlock, NegCentsUnsignedToDollars}, + internal::{FiatPerBlock, LazyPerBlock, NegCentsUnsignedToDollars}, }; use super::UnrealizedMinimal; @@ -17,8 +17,8 @@ pub struct UnrealizedBasic { #[deref_mut] #[traversable(flatten)] pub minimal: UnrealizedMinimal, - pub profit: FiatPerBlockCumulativeWithSums, - pub loss: FiatPerBlockCumulativeWithSums, + pub profit: FiatPerBlock, + pub loss: FiatPerBlock, #[traversable(wrap = "loss", rename = "negative")] pub neg_loss: LazyPerBlock, } @@ -27,13 +27,13 @@ impl UnrealizedBasic { pub(crate) fn forced_import(cfg: &ImportConfig) -> Result { let v1 = Version::ONE; - let loss: FiatPerBlockCumulativeWithSums = cfg.import("unrealized_loss", v1)?; + let loss: FiatPerBlock = cfg.import("unrealized_loss", v1)?; let neg_loss = LazyPerBlock::from_computed::( &cfg.name("neg_unrealized_loss"), cfg.version, - loss.base.cents.height.read_only_boxed_clone(), - &loss.base.cents, + loss.cents.height.read_only_boxed_clone(), + &loss.cents, ); Ok(Self { @@ -46,22 +46,19 @@ impl UnrealizedBasic { pub(crate) fn min_stateful_len(&self) -> usize { self.profit - .base .cents .height .len() - .min(self.loss.base.cents.height.len()) + .min(self.loss.cents.height.len()) } #[inline(always)] pub(crate) fn push_state(&mut self, state: &UnrealizedState) { self.profit - .base .cents .height .push(state.unrealized_profit); self.loss - .base .cents .height .push(state.unrealized_loss); @@ -69,8 +66,8 @@ impl UnrealizedBasic { pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> { vec![ - &mut self.profit.base.cents.height as &mut dyn AnyStoredVec, - &mut self.loss.base.cents.height, + &mut self.profit.cents.height as &mut dyn AnyStoredVec, + &mut self.loss.cents.height, ] } @@ -80,18 +77,8 @@ impl UnrealizedBasic { others: &[&Self], exit: &Exit, ) -> Result<()> { - sum_others!(self, starting_indexes, others, exit; profit.base.cents.height); - sum_others!(self, starting_indexes, others, exit; loss.base.cents.height); - Ok(()) - } - - pub(crate) fn compute_rest( - &mut self, - max_from: Height, - exit: &Exit, - ) -> Result<()> { - self.profit.compute_rest(max_from, exit)?; - self.loss.compute_rest(max_from, exit)?; + sum_others!(self, starting_indexes, others, exit; profit.cents.height); + sum_others!(self, starting_indexes, others, exit; loss.cents.height); Ok(()) } } diff --git a/crates/brk_computer/src/distribution/metrics/unrealized/core.rs b/crates/brk_computer/src/distribution/metrics/unrealized/core.rs index 9d230a672..455a0044e 100644 --- a/crates/brk_computer/src/distribution/metrics/unrealized/core.rs +++ b/crates/brk_computer/src/distribution/metrics/unrealized/core.rs @@ -65,16 +65,13 @@ impl UnrealizedCore { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - self.basic - .compute_rest(starting_indexes.height, exit)?; - self.net_pnl .cents .height .compute_binary::( starting_indexes.height, - &self.basic.profit.base.cents.height, - &self.basic.loss.base.cents.height, + &self.basic.profit.cents.height, + &self.basic.loss.cents.height, exit, )?; diff --git a/crates/brk_computer/src/distribution/metrics/unrealized/full.rs b/crates/brk_computer/src/distribution/metrics/unrealized/full.rs index 88d4c56f3..5b1d692f1 100644 --- a/crates/brk_computer/src/distribution/metrics/unrealized/full.rs +++ b/crates/brk_computer/src/distribution/metrics/unrealized/full.rs @@ -92,8 +92,8 @@ impl UnrealizedFull { self.gross_pnl.cents.height.compute_add( starting_indexes.height, - &self.inner.core.basic.profit.base.cents.height, - &self.inner.core.basic.loss.base.cents.height, + &self.inner.core.basic.profit.cents.height, + &self.inner.core.basic.loss.cents.height, exit, )?; diff --git a/crates/brk_server/src/api/series/mod.rs b/crates/brk_server/src/api/series/mod.rs index 7971f7a03..6eadf12a5 100644 --- a/crates/brk_server/src/api/series/mod.rs +++ b/crates/brk_server/src/api/series/mod.rs @@ -22,8 +22,8 @@ mod bulk; mod data; pub mod legacy; -/// Maximum allowed request weight in bytes (650KB) -const MAX_WEIGHT: usize = 65 * 10_000; +/// Maximum allowed request weight in bytes (320KB) +const MAX_WEIGHT: usize = 4 * 8 * 10_000; /// Maximum allowed request weight for localhost (50MB) const MAX_WEIGHT_LOCALHOST: usize = 50 * 1_000_000; /// Cache control header for series data responses diff --git a/crates/brk_types/src/basis_points_32.rs b/crates/brk_types/src/basis_points_32.rs index 05ea906c6..032b8acf1 100644 --- a/crates/brk_types/src/basis_points_32.rs +++ b/crates/brk_types/src/basis_points_32.rs @@ -3,13 +3,14 @@ use std::ops::{Add, AddAssign, Div}; use derive_more::Deref; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use vecdb::{CheckedSub, Formattable, Pco}; +use vecdb::{unlikely, CheckedSub, Formattable, Pco}; use super::StoredF32; /// Unsigned basis points stored as u32. /// 1 bp = 0.0001. Range: 0–429,496.7295. /// Use for unbounded unsigned ratios (MVRV, NVT, SOPR, etc.). +/// `u32::MAX` is reserved as a NaN sentinel. #[derive( Debug, Deref, @@ -30,9 +31,12 @@ pub struct BasisPoints32(u32); impl BasisPoints32 { pub const ZERO: Self = Self(0); + /// NaN sentinel — uses u32::MAX which is outside the practical range. + pub const NAN: Self = Self(u32::MAX); #[inline] pub const fn new(value: u32) -> Self { + debug_assert!(value != u32::MAX, "u32::MAX is reserved as NaN sentinel"); Self(value) } @@ -41,10 +45,19 @@ impl BasisPoints32 { self.0 } - /// Convert to f32: divide by 10000. + #[inline] + pub fn is_nan(self) -> bool { + self.0 == u32::MAX + } + + /// Convert to f32: divide by 10000. Returns NaN for sentinel value. #[inline] pub fn to_f32(self) -> f32 { - self.0 as f32 / 10000.0 + if unlikely(self.0 == u32::MAX) { + f32::NAN + } else { + self.0 as f32 / 10000.0 + } } } @@ -52,7 +65,7 @@ impl From for BasisPoints32 { #[inline] fn from(value: usize) -> Self { debug_assert!( - value <= u32::MAX as usize, + value < u32::MAX as usize, "usize out of BasisPoints32 range: {value}" ); Self(value as u32) @@ -62,6 +75,7 @@ impl From for BasisPoints32 { impl From for BasisPoints32 { #[inline] fn from(value: u32) -> Self { + debug_assert!(value != u32::MAX, "u32::MAX is reserved as NaN sentinel"); Self(value) } } @@ -75,10 +89,14 @@ impl From for u32 { /// Convert from float: multiply by 10000 and round. /// Input is in ratio form (e.g., 2.5 for MVRV of 2.5). +/// NaN/Inf → NaN sentinel. impl From for BasisPoints32 { #[inline] fn from(value: f64) -> Self { - let scaled = (value * 10000.0).round().clamp(0.0, u32::MAX as f64); + if unlikely(!value.is_finite()) { + return Self::NAN; + } + let scaled = (value * 10000.0).round().clamp(0.0, u32::MAX as f64 - 1.0); Self(scaled as u32) } } @@ -86,13 +104,20 @@ impl From for BasisPoints32 { impl From for f64 { #[inline] fn from(value: BasisPoints32) -> Self { - value.0 as f64 / 10000.0 + if unlikely(value.0 == u32::MAX) { + f64::NAN + } else { + value.0 as f64 / 10000.0 + } } } impl From for BasisPoints32 { #[inline] fn from(value: f32) -> Self { + if unlikely(!value.is_finite()) { + return Self::NAN; + } Self::from(value as f64) } } @@ -107,7 +132,11 @@ impl From for BasisPoints32 { impl From for f32 { #[inline] fn from(value: BasisPoints32) -> Self { - value.0 as f32 / 10000.0 + if unlikely(value.0 == u32::MAX) { + f32::NAN + } else { + value.0 as f32 / 10000.0 + } } } @@ -122,14 +151,18 @@ impl Add for BasisPoints32 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { - Self(self.0 + rhs.0) + if unlikely(self.0 == u32::MAX || rhs.0 == u32::MAX) { + Self::NAN + } else { + Self(self.0 + rhs.0) + } } } impl AddAssign for BasisPoints32 { #[inline] fn add_assign(&mut self, rhs: Self) { - self.0 += rhs.0; + *self = *self + rhs; } } @@ -137,14 +170,22 @@ impl Div for BasisPoints32 { type Output = Self; #[inline] fn div(self, rhs: usize) -> Self::Output { - debug_assert!(rhs <= u32::MAX as usize, "divisor out of u32 range: {rhs}"); - Self(self.0 / rhs as u32) + if unlikely(self.0 == u32::MAX) { + Self::NAN + } else { + debug_assert!(rhs <= u32::MAX as usize, "divisor out of u32 range: {rhs}"); + Self(self.0 / rhs as u32) + } } } impl CheckedSub for BasisPoints32 { fn checked_sub(self, rhs: Self) -> Option { - self.0.checked_sub(rhs.0).map(Self) + if unlikely(self.0 == u32::MAX || rhs.0 == u32::MAX) { + Some(Self::NAN) + } else { + self.0.checked_sub(rhs.0).map(Self) + } } } @@ -162,4 +203,13 @@ impl Formattable for BasisPoints32 { let mut b = itoa::Buffer::new(); buf.extend_from_slice(b.format(self.0).as_bytes()); } + + #[inline(always)] + fn fmt_json(&self, buf: &mut Vec) { + if unlikely(self.0 == u32::MAX) { + buf.extend_from_slice(b"null"); + } else { + self.write_to(buf); + } + } } diff --git a/crates/brk_types/src/basis_points_signed_32.rs b/crates/brk_types/src/basis_points_signed_32.rs index 7a6919d60..4c80e8edf 100644 --- a/crates/brk_types/src/basis_points_signed_32.rs +++ b/crates/brk_types/src/basis_points_signed_32.rs @@ -3,13 +3,14 @@ use std::ops::{Add, AddAssign, Div, Sub, SubAssign}; use derive_more::Deref; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use vecdb::{CheckedSub, Formattable, Pco}; +use vecdb::{unlikely, CheckedSub, Formattable, Pco}; use super::StoredF32; /// Signed basis points stored as i32. /// 1 bp = 0.0001. Range: -214,748.3647 to +214,748.3647. /// Use for unbounded signed values (returns, growth rates, volatility, z-scores, etc.). +/// `i32::MIN` is reserved as a NaN sentinel. #[derive( Debug, Deref, @@ -30,9 +31,12 @@ pub struct BasisPointsSigned32(i32); impl BasisPointsSigned32 { pub const ZERO: Self = Self(0); + /// NaN sentinel — uses i32::MIN which is outside the documented range. + pub const NAN: Self = Self(i32::MIN); #[inline] pub const fn new(value: i32) -> Self { + debug_assert!(value != i32::MIN, "i32::MIN is reserved as NaN sentinel"); Self(value) } @@ -42,14 +46,23 @@ impl BasisPointsSigned32 { } #[inline] - pub fn is_negative(self) -> bool { - self.0 < 0 + pub fn is_nan(self) -> bool { + self.0 == i32::MIN } - /// Convert to f32: divide by 10000. + #[inline] + pub fn is_negative(self) -> bool { + self.0 < 0 && self.0 != i32::MIN + } + + /// Convert to f32: divide by 10000. Returns NaN for sentinel value. #[inline] pub fn to_f32(self) -> f32 { - self.0 as f32 / 10000.0 + if unlikely(self.0 == i32::MIN) { + f32::NAN + } else { + self.0 as f32 / 10000.0 + } } } @@ -67,6 +80,7 @@ impl From for BasisPointsSigned32 { impl From for BasisPointsSigned32 { #[inline] fn from(value: i32) -> Self { + debug_assert!(value != i32::MIN, "i32::MIN is reserved as NaN sentinel"); Self(value) } } @@ -80,24 +94,32 @@ impl From for i32 { /// Convert from float: multiply by 10000 and round. /// Input is in ratio form (e.g., 50.0 for +5000%). +/// NaN/Inf → NaN sentinel. impl From for BasisPointsSigned32 { #[inline] fn from(value: f64) -> Self { + if unlikely(!value.is_finite()) { + return Self::NAN; + } let scaled = (value * 10000.0) .round() - .clamp(i32::MIN as f64, i32::MAX as f64); + .clamp(i32::MIN as f64 + 1.0, i32::MAX as f64); Self(scaled as i32) } } /// Convert from f32 ratio form: multiply by 10000 and round. /// Input is in ratio form (e.g., 0.5 for +50% → 5000 bps). +/// NaN/Inf → NaN sentinel. impl From for BasisPointsSigned32 { #[inline] fn from(value: f32) -> Self { + if unlikely(!value.is_finite()) { + return Self::NAN; + } let scaled = (value * 10000.0) .round() - .clamp(i32::MIN as f32, i32::MAX as f32); + .clamp(i32::MIN as f32 + 1.0, i32::MAX as f32); Self(scaled as i32) } } @@ -105,7 +127,11 @@ impl From for BasisPointsSigned32 { impl From for f64 { #[inline] fn from(value: BasisPointsSigned32) -> Self { - value.0 as f64 / 10000.0 + if unlikely(value.0 == i32::MIN) { + f64::NAN + } else { + value.0 as f64 / 10000.0 + } } } @@ -120,14 +146,18 @@ impl Add for BasisPointsSigned32 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { - Self(self.0 + rhs.0) + if unlikely(self.0 == i32::MIN || rhs.0 == i32::MIN) { + Self::NAN + } else { + Self(self.0 + rhs.0) + } } } impl AddAssign for BasisPointsSigned32 { #[inline] fn add_assign(&mut self, rhs: Self) { - self.0 += rhs.0; + *self = *self + rhs; } } @@ -135,14 +165,18 @@ impl Sub for BasisPointsSigned32 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) + if unlikely(self.0 == i32::MIN || rhs.0 == i32::MIN) { + Self::NAN + } else { + Self(self.0 - rhs.0) + } } } impl SubAssign for BasisPointsSigned32 { #[inline] fn sub_assign(&mut self, rhs: Self) { - self.0 -= rhs.0; + *self = *self - rhs; } } @@ -150,14 +184,22 @@ impl Div for BasisPointsSigned32 { type Output = Self; #[inline] fn div(self, rhs: usize) -> Self::Output { - debug_assert!(rhs <= i32::MAX as usize, "divisor out of i32 range: {rhs}"); - Self(self.0 / rhs as i32) + if unlikely(self.0 == i32::MIN) { + Self::NAN + } else { + debug_assert!(rhs <= i32::MAX as usize, "divisor out of i32 range: {rhs}"); + Self(self.0 / rhs as i32) + } } } impl CheckedSub for BasisPointsSigned32 { fn checked_sub(self, rhs: Self) -> Option { - self.0.checked_sub(rhs.0).map(Self) + if unlikely(self.0 == i32::MIN || rhs.0 == i32::MIN) { + Some(Self::NAN) + } else { + self.0.checked_sub(rhs.0).map(Self) + } } } @@ -175,4 +217,13 @@ impl Formattable for BasisPointsSigned32 { let mut b = itoa::Buffer::new(); buf.extend_from_slice(b.format(self.0).as_bytes()); } + + #[inline(always)] + fn fmt_json(&self, buf: &mut Vec) { + if unlikely(self.0 == i32::MIN) { + buf.extend_from_slice(b"null"); + } else { + self.write_to(buf); + } + } } diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index f7ec69bde..5923a43c6 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -77,6 +77,7 @@ * Unsigned basis points stored as u32. * 1 bp = 0.0001. Range: 0–429,496.7295. * Use for unbounded unsigned ratios (MVRV, NVT, SOPR, etc.). + * `u32::MAX` is reserved as a NaN sentinel. * * @typedef {number} BasisPoints32 */ @@ -91,6 +92,7 @@ * Signed basis points stored as i32. * 1 bp = 0.0001. Range: -214,748.3647 to +214,748.3647. * Use for unbounded signed values (returns, growth rates, volatility, z-scores, etc.). + * `i32::MIN` is reserved as a NaN sentinel. * * @typedef {number} BasisPointsSigned32 */ @@ -2107,35 +2109,6 @@ function create_1m1w1y24hBpsPercentRatioPattern(client, acc) { * @property {BaseCumulativeSumPattern} valueDestroyed */ -/** - * @typedef {Object} BaseCumulativeNegativeSumToPattern2 - * @property {CentsUsdPattern2} base - * @property {CentsUsdPattern2} cumulative - * @property {SeriesPattern1} negative - * @property {_1m1w1y24hPattern4} sum - * @property {BpsPercentRatioPattern3} toMcap - * @property {BpsPercentRatioPattern3} toOwnGrossPnl - * @property {BpsPercentRatioPattern4} toOwnMcap - */ - -/** - * Create a BaseCumulativeNegativeSumToPattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated series name - * @returns {BaseCumulativeNegativeSumToPattern2} - */ -function createBaseCumulativeNegativeSumToPattern2(client, acc) { - return { - base: createCentsUsdPattern2(client, _m(acc, 'unrealized_loss')), - cumulative: createCentsUsdPattern2(client, _m(acc, 'unrealized_loss_cumulative')), - negative: createSeriesPattern1(client, _m(acc, 'neg_unrealized_loss')), - sum: create_1m1w1y24hPattern4(client, _m(acc, 'unrealized_loss_sum')), - toMcap: createBpsPercentRatioPattern3(client, _m(acc, 'unrealized_loss_to_mcap')), - toOwnGrossPnl: createBpsPercentRatioPattern3(client, _m(acc, 'unrealized_loss_to_own_gross_pnl')), - toOwnMcap: createBpsPercentRatioPattern4(client, _m(acc, 'unrealized_loss_to_own_mcap')), - }; -} - /** * @typedef {Object} CapLossMvrvNetPriceProfitSoprPattern * @property {CentsDeltaUsdPattern} cap @@ -2156,7 +2129,7 @@ function createBaseCumulativeNegativeSumToPattern2(client, acc) { function createCapLossMvrvNetPriceProfitSoprPattern(client, acc) { return { cap: createCentsDeltaUsdPattern(client, _m(acc, 'realized_cap')), - loss: createBaseCumulativeNegativeSumPattern(client, acc, 'realized_loss'), + loss: createBaseCumulativeNegativeSumPattern(client, acc), mvrv: createSeriesPattern1(client, _m(acc, 'mvrv')), netPnl: createBaseCumulativeDeltaSumPattern(client, _m(acc, 'net_realized_pnl')), price: createBpsCentsRatioSatsUsdPattern(client, _m(acc, 'realized_price')), @@ -2169,10 +2142,10 @@ function createCapLossMvrvNetPriceProfitSoprPattern(client, acc) { * @typedef {Object} GrossInvestedLossNetNuplProfitSentimentPattern2 * @property {CentsUsdPattern2} grossPnl * @property {InPattern} investedCapital - * @property {BaseCumulativeNegativeSumToPattern2} loss - * @property {CentsToUsdPattern2} netPnl + * @property {CentsNegativeToUsdPattern2} loss + * @property {CentsToUsdPattern3} netPnl * @property {BpsRatioPattern} nupl - * @property {BaseCumulativeSumToPattern2} profit + * @property {CentsToUsdPattern4} profit * @property {GreedNetPainPattern} sentiment */ @@ -2230,33 +2203,6 @@ function createBaseChangeCumulativeDeltaSumToPattern(client, acc) { }; } -/** - * @typedef {Object} BaseCumulativeSumToPattern2 - * @property {CentsUsdPattern2} base - * @property {CentsUsdPattern2} cumulative - * @property {_1m1w1y24hPattern4} sum - * @property {BpsPercentRatioPattern3} toMcap - * @property {BpsPercentRatioPattern3} toOwnGrossPnl - * @property {BpsPercentRatioPattern3} toOwnMcap - */ - -/** - * Create a BaseCumulativeSumToPattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated series name - * @returns {BaseCumulativeSumToPattern2} - */ -function createBaseCumulativeSumToPattern2(client, acc) { - return { - base: createCentsUsdPattern2(client, acc), - cumulative: createCentsUsdPattern2(client, _m(acc, 'cumulative')), - sum: create_1m1w1y24hPattern4(client, _m(acc, 'sum')), - toMcap: createBpsPercentRatioPattern3(client, _m(acc, 'to_mcap')), - toOwnGrossPnl: createBpsPercentRatioPattern3(client, _m(acc, 'to_own_gross_pnl')), - toOwnMcap: createBpsPercentRatioPattern3(client, _m(acc, 'to_own_mcap')), - }; -} - /** * @typedef {Object} BpsCentsPercentilesRatioSatsUsdPattern * @property {SeriesPattern1} bps @@ -2338,6 +2284,33 @@ function createCapLossMvrvPriceProfitSoprPattern(client, acc) { }; } +/** + * @typedef {Object} CentsNegativeToUsdPattern2 + * @property {SeriesPattern1} cents + * @property {SeriesPattern1} negative + * @property {BpsPercentRatioPattern3} toMcap + * @property {BpsPercentRatioPattern3} toOwnGrossPnl + * @property {BpsPercentRatioPattern4} toOwnMcap + * @property {SeriesPattern1} usd + */ + +/** + * Create a CentsNegativeToUsdPattern2 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated series name + * @returns {CentsNegativeToUsdPattern2} + */ +function createCentsNegativeToUsdPattern2(client, acc) { + return { + cents: createSeriesPattern1(client, _m(acc, 'unrealized_loss_cents')), + negative: createSeriesPattern1(client, _m(acc, 'neg_unrealized_loss')), + toMcap: createBpsPercentRatioPattern3(client, _m(acc, 'unrealized_loss_to_mcap')), + toOwnGrossPnl: createBpsPercentRatioPattern3(client, _m(acc, 'unrealized_loss_to_own_gross_pnl')), + toOwnMcap: createBpsPercentRatioPattern4(client, _m(acc, 'unrealized_loss_to_own_mcap')), + usd: createSeriesPattern1(client, _m(acc, 'unrealized_loss')), + }; +} + /** * @typedef {Object} DeltaHalfInToTotalPattern * @property {AbsoluteRatePattern} delta @@ -2594,6 +2567,31 @@ function createBtcCentsSatsToUsdPattern2(client, acc) { }; } +/** + * @typedef {Object} CentsToUsdPattern4 + * @property {SeriesPattern1} cents + * @property {BpsPercentRatioPattern3} toMcap + * @property {BpsPercentRatioPattern3} toOwnGrossPnl + * @property {BpsPercentRatioPattern3} toOwnMcap + * @property {SeriesPattern1} usd + */ + +/** + * Create a CentsToUsdPattern4 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated series name + * @returns {CentsToUsdPattern4} + */ +function createCentsToUsdPattern4(client, acc) { + return { + cents: createSeriesPattern1(client, _m(acc, 'cents')), + toMcap: createBpsPercentRatioPattern3(client, _m(acc, 'to_mcap')), + toOwnGrossPnl: createBpsPercentRatioPattern3(client, _m(acc, 'to_own_gross_pnl')), + toOwnMcap: createBpsPercentRatioPattern3(client, _m(acc, 'to_own_mcap')), + usd: createSeriesPattern1(client, acc), + }; +} + /** * @typedef {Object} DeltaHalfInTotalPattern2 * @property {AbsoluteRatePattern} delta @@ -2878,15 +2876,14 @@ function createBaseCumulativeDeltaSumPattern(client, acc) { * Create a BaseCumulativeNegativeSumPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated series name - * @param {string} disc - Discriminator suffix * @returns {BaseCumulativeNegativeSumPattern} */ -function createBaseCumulativeNegativeSumPattern(client, acc, disc) { +function createBaseCumulativeNegativeSumPattern(client, acc) { return { - base: createCentsUsdPattern2(client, _m(acc, disc)), - cumulative: createCentsUsdPattern2(client, _m(acc, `${disc}_cumulative`)), - negative: createSeriesPattern1(client, _m(_m(acc, 'neg'), disc)), - sum: create_1m1w1y24hPattern4(client, _m(acc, `${disc}_sum`)), + base: createCentsUsdPattern2(client, _m(acc, 'realized_loss')), + cumulative: createCentsUsdPattern2(client, _m(acc, 'realized_loss_cumulative')), + negative: createSeriesPattern1(client, _m(acc, 'neg_realized_loss')), + sum: create_1m1w1y24hPattern4(client, _m(acc, 'realized_loss_sum')), }; } @@ -2960,7 +2957,7 @@ function createCentsDeltaToUsdPattern(client, acc) { } /** - * @typedef {Object} CentsToUsdPattern2 + * @typedef {Object} CentsToUsdPattern3 * @property {SeriesPattern1} cents * @property {BpsPercentRatioPattern} toOwnGrossPnl * @property {BpsPercentRatioPattern} toOwnMcap @@ -2968,12 +2965,12 @@ function createCentsDeltaToUsdPattern(client, acc) { */ /** - * Create a CentsToUsdPattern2 pattern node + * Create a CentsToUsdPattern3 pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated series name - * @returns {CentsToUsdPattern2} + * @returns {CentsToUsdPattern3} */ -function createCentsToUsdPattern2(client, acc) { +function createCentsToUsdPattern3(client, acc) { return { cents: createSeriesPattern1(client, _m(acc, 'cents')), toOwnGrossPnl: createBpsPercentRatioPattern(client, _m(acc, 'to_own_gross_pnl')), @@ -2992,10 +2989,10 @@ function createCentsToUsdPattern2(client, acc) { /** * @typedef {Object} LossNetNuplProfitPattern - * @property {BaseCumulativeNegativeSumPattern} loss + * @property {CentsNegativeUsdPattern} loss * @property {CentsUsdPattern} netPnl * @property {BpsRatioPattern} nupl - * @property {BaseCumulativeSumPattern3} profit + * @property {CentsUsdPattern2} profit */ /** @@ -3006,10 +3003,10 @@ function createCentsToUsdPattern2(client, acc) { */ function createLossNetNuplProfitPattern(client, acc) { return { - loss: createBaseCumulativeNegativeSumPattern(client, acc, 'unrealized_loss'), + loss: createCentsNegativeUsdPattern(client, acc), netPnl: createCentsUsdPattern(client, _m(acc, 'net_unrealized_pnl')), nupl: createBpsRatioPattern(client, _m(acc, 'nupl')), - profit: createBaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit')), + profit: createCentsUsdPattern2(client, _m(acc, 'unrealized_profit')), }; } @@ -3337,6 +3334,27 @@ function createCentsDeltaUsdPattern(client, acc) { }; } +/** + * @typedef {Object} CentsNegativeUsdPattern + * @property {SeriesPattern1} cents + * @property {SeriesPattern1} negative + * @property {SeriesPattern1} usd + */ + +/** + * Create a CentsNegativeUsdPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated series name + * @returns {CentsNegativeUsdPattern} + */ +function createCentsNegativeUsdPattern(client, acc) { + return { + cents: createSeriesPattern1(client, _m(acc, 'unrealized_loss_cents')), + negative: createSeriesPattern1(client, _m(acc, 'neg_unrealized_loss')), + usd: createSeriesPattern1(client, _m(acc, 'unrealized_loss')), + }; +} + /** * @typedef {Object} CentsSatsUsdPattern * @property {SeriesPattern1} cents @@ -3409,9 +3427,9 @@ function createDeltaHalfTotalPattern(client, acc) { /** * @typedef {Object} LossNuplProfitPattern - * @property {BaseCumulativeNegativeSumPattern} loss + * @property {CentsNegativeUsdPattern} loss * @property {BpsRatioPattern} nupl - * @property {BaseCumulativeSumPattern3} profit + * @property {CentsUsdPattern2} profit */ /** @@ -3422,9 +3440,9 @@ function createDeltaHalfTotalPattern(client, acc) { */ function createLossNuplProfitPattern(client, acc) { return { - loss: createBaseCumulativeNegativeSumPattern(client, acc, 'unrealized_loss'), + loss: createCentsNegativeUsdPattern(client, acc), nupl: createBpsRatioPattern(client, _m(acc, 'nupl')), - profit: createBaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit')), + profit: createCentsUsdPattern2(client, _m(acc, 'unrealized_profit')), }; } @@ -5534,18 +5552,16 @@ function createUnspentPattern(client, acc) { /** * @typedef {Object} SeriesTree_Cohorts_Utxo_All_Unrealized_Profit - * @property {CentsUsdPattern2} base - * @property {CentsUsdPattern2} cumulative - * @property {_1m1w1y24hPattern4} sum + * @property {SeriesPattern1} usd + * @property {SeriesPattern1} cents * @property {BpsPercentRatioPattern3} toMcap * @property {BpsPercentRatioPattern3} toOwnGrossPnl */ /** * @typedef {Object} SeriesTree_Cohorts_Utxo_All_Unrealized_Loss - * @property {CentsUsdPattern2} base - * @property {CentsUsdPattern2} cumulative - * @property {_1m1w1y24hPattern4} sum + * @property {SeriesPattern1} usd + * @property {SeriesPattern1} cents * @property {SeriesPattern1} negative * @property {BpsPercentRatioPattern3} toMcap * @property {BpsPercentRatioPattern3} toOwnGrossPnl @@ -5745,9 +5761,9 @@ function createUnspentPattern(client, acc) { /** * @typedef {Object} SeriesTree_Cohorts_Utxo_Sth_Unrealized * @property {BpsRatioPattern} nupl - * @property {BaseCumulativeSumToPattern2} profit - * @property {BaseCumulativeNegativeSumToPattern2} loss - * @property {CentsToUsdPattern2} netPnl + * @property {CentsToUsdPattern4} profit + * @property {CentsNegativeToUsdPattern2} loss + * @property {CentsToUsdPattern3} netPnl * @property {CentsUsdPattern2} grossPnl * @property {InPattern} investedCapital * @property {SeriesTree_Cohorts_Utxo_Sth_Unrealized_Sentiment} sentiment @@ -5932,9 +5948,9 @@ function createUnspentPattern(client, acc) { /** * @typedef {Object} SeriesTree_Cohorts_Utxo_Lth_Unrealized * @property {BpsRatioPattern} nupl - * @property {BaseCumulativeSumToPattern2} profit - * @property {BaseCumulativeNegativeSumToPattern2} loss - * @property {CentsToUsdPattern2} netPnl + * @property {CentsToUsdPattern4} profit + * @property {CentsNegativeToUsdPattern2} loss + * @property {CentsToUsdPattern3} netPnl * @property {CentsUsdPattern2} grossPnl * @property {InPattern} investedCapital * @property {SeriesTree_Cohorts_Utxo_Lth_Unrealized_Sentiment} sentiment @@ -8610,16 +8626,14 @@ class BrkClient extends BrkClientBase { unrealized: { nupl: createBpsRatioPattern(this, 'nupl'), profit: { - base: createCentsUsdPattern2(this, 'unrealized_profit'), - cumulative: createCentsUsdPattern2(this, 'unrealized_profit_cumulative'), - sum: create_1m1w1y24hPattern4(this, 'unrealized_profit_sum'), + usd: createSeriesPattern1(this, 'unrealized_profit'), + cents: createSeriesPattern1(this, 'unrealized_profit_cents'), toMcap: createBpsPercentRatioPattern3(this, 'unrealized_profit_to_mcap'), toOwnGrossPnl: createBpsPercentRatioPattern3(this, 'unrealized_profit_to_own_gross_pnl'), }, loss: { - base: createCentsUsdPattern2(this, 'unrealized_loss'), - cumulative: createCentsUsdPattern2(this, 'unrealized_loss_cumulative'), - sum: create_1m1w1y24hPattern4(this, 'unrealized_loss_sum'), + usd: createSeriesPattern1(this, 'unrealized_loss'), + cents: createSeriesPattern1(this, 'unrealized_loss_cents'), negative: createSeriesPattern1(this, 'neg_unrealized_loss'), toMcap: createBpsPercentRatioPattern3(this, 'unrealized_loss_to_mcap'), toOwnGrossPnl: createBpsPercentRatioPattern3(this, 'unrealized_loss_to_own_gross_pnl'), @@ -8774,9 +8788,9 @@ class BrkClient extends BrkClientBase { }, unrealized: { nupl: createBpsRatioPattern(this, 'sth_nupl'), - profit: createBaseCumulativeSumToPattern2(this, 'sth_unrealized_profit'), - loss: createBaseCumulativeNegativeSumToPattern2(this, 'sth'), - netPnl: createCentsToUsdPattern2(this, 'sth_net_unrealized_pnl'), + profit: createCentsToUsdPattern4(this, 'sth_unrealized_profit'), + loss: createCentsNegativeToUsdPattern2(this, 'sth'), + netPnl: createCentsToUsdPattern3(this, 'sth_net_unrealized_pnl'), grossPnl: createCentsUsdPattern2(this, 'sth_unrealized_gross_pnl'), investedCapital: createInPattern(this, 'sth_invested_capital_in'), sentiment: { @@ -8917,9 +8931,9 @@ class BrkClient extends BrkClientBase { }, unrealized: { nupl: createBpsRatioPattern(this, 'lth_nupl'), - profit: createBaseCumulativeSumToPattern2(this, 'lth_unrealized_profit'), - loss: createBaseCumulativeNegativeSumToPattern2(this, 'lth'), - netPnl: createCentsToUsdPattern2(this, 'lth_net_unrealized_pnl'), + profit: createCentsToUsdPattern4(this, 'lth_unrealized_profit'), + loss: createCentsNegativeToUsdPattern2(this, 'lth'), + netPnl: createCentsToUsdPattern3(this, 'lth_net_unrealized_pnl'), grossPnl: createCentsUsdPattern2(this, 'lth_unrealized_gross_pnl'), investedCapital: createInPattern(this, 'lth_invested_capital_in'), sentiment: { diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 3a437ae50..96a305055 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -34,6 +34,7 @@ BasisPoints16 = int # Unsigned basis points stored as u32. # 1 bp = 0.0001. Range: 0–429,496.7295. # Use for unbounded unsigned ratios (MVRV, NVT, SOPR, etc.). +# `u32::MAX` is reserved as a NaN sentinel. BasisPoints32 = int # Signed basis points stored as i16. # 1 bp = 0.0001. Range: -3.2767 to +3.2767. @@ -42,6 +43,7 @@ BasisPointsSigned16 = int # Signed basis points stored as i32. # 1 bp = 0.0001. Range: -214,748.3647 to +214,748.3647. # Use for unbounded signed values (returns, growth rates, volatility, z-scores, etc.). +# `i32::MIN` is reserved as a NaN sentinel. BasisPointsSigned32 = int # Bitcoin amount as floating point (1 BTC = 100,000,000 satoshis) Bitcoin = float @@ -2354,26 +2356,13 @@ class BaseCumulativeDistributionSumToValuePattern: """Pattern struct for repeated tree structure.""" pass -class BaseCumulativeNegativeSumToPattern2: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated series name.""" - self.base: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'unrealized_loss')) - self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'unrealized_loss_cumulative')) - self.negative: SeriesPattern1[Dollars] = SeriesPattern1(client, _m(acc, 'neg_unrealized_loss')) - self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, _m(acc, 'unrealized_loss_sum')) - self.to_mcap: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'unrealized_loss_to_mcap')) - self.to_own_gross_pnl: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'unrealized_loss_to_own_gross_pnl')) - self.to_own_mcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, _m(acc, 'unrealized_loss_to_own_mcap')) - class CapLossMvrvNetPriceProfitSoprPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated series name.""" self.cap: CentsDeltaUsdPattern = CentsDeltaUsdPattern(client, _m(acc, 'realized_cap')) - self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc, 'realized_loss') + self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc) self.mvrv: SeriesPattern1[StoredF32] = SeriesPattern1(client, _m(acc, 'mvrv')) self.net_pnl: BaseCumulativeDeltaSumPattern = BaseCumulativeDeltaSumPattern(client, _m(acc, 'net_realized_pnl')) self.price: BpsCentsRatioSatsUsdPattern = BpsCentsRatioSatsUsdPattern(client, _m(acc, 'realized_price')) @@ -2408,18 +2397,6 @@ class BaseChangeCumulativeDeltaSumToPattern: self.sum: _1m1w1y24hPattern3 = _1m1w1y24hPattern3(client, _m(acc, 'realized_pnl_sum')) self.to_rcap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_pnl_to_rcap')) -class BaseCumulativeSumToPattern2: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated series name.""" - self.base: CentsUsdPattern2 = CentsUsdPattern2(client, acc) - self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'cumulative')) - self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, _m(acc, 'sum')) - self.to_mcap: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'to_mcap')) - self.to_own_gross_pnl: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'to_own_gross_pnl')) - self.to_own_mcap: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'to_own_mcap')) - class BpsCentsPercentilesRatioSatsUsdPattern: """Pattern struct for repeated tree structure.""" @@ -2456,6 +2433,18 @@ class CapLossMvrvPriceProfitSoprPattern: self.profit: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, _m(acc, 'realized_profit')) self.sopr: ValuePattern = ValuePattern(client, _m(acc, 'value')) +class CentsNegativeToUsdPattern2: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated series name.""" + self.cents: SeriesPattern1[Cents] = SeriesPattern1(client, _m(acc, 'unrealized_loss_cents')) + self.negative: SeriesPattern1[Dollars] = SeriesPattern1(client, _m(acc, 'neg_unrealized_loss')) + self.to_mcap: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'unrealized_loss_to_mcap')) + self.to_own_gross_pnl: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'unrealized_loss_to_own_gross_pnl')) + self.to_own_mcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, _m(acc, 'unrealized_loss_to_own_mcap')) + self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, _m(acc, 'unrealized_loss')) + class DeltaHalfInToTotalPattern: """Pattern struct for repeated tree structure.""" @@ -2569,6 +2558,17 @@ class BtcCentsSatsToUsdPattern2: self.to_own: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'to_own')) self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, _m(acc, 'usd')) +class CentsToUsdPattern4: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated series name.""" + self.cents: SeriesPattern1[Cents] = SeriesPattern1(client, _m(acc, 'cents')) + self.to_mcap: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'to_mcap')) + self.to_own_gross_pnl: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'to_own_gross_pnl')) + self.to_own_mcap: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'to_own_mcap')) + self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, acc) + class DeltaHalfInTotalPattern2: """Pattern struct for repeated tree structure.""" @@ -2691,12 +2691,12 @@ class BaseCumulativeDeltaSumPattern: class BaseCumulativeNegativeSumPattern: """Pattern struct for repeated tree structure.""" - def __init__(self, client: BrkClientBase, acc: str, disc: str): + def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated series name.""" - self.base: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, disc)) - self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, f'{disc}_cumulative')) - self.negative: SeriesPattern1[Dollars] = SeriesPattern1(client, _m(acc, f'neg_{disc}')) - self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, _m(acc, f'{disc}_sum')) + self.base: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'realized_loss')) + self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'realized_loss_cumulative')) + self.negative: SeriesPattern1[Dollars] = SeriesPattern1(client, _m(acc, 'neg_realized_loss')) + self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, _m(acc, 'realized_loss_sum')) class BothReactivatedReceivingSendingPattern: """Pattern struct for repeated tree structure.""" @@ -2728,7 +2728,7 @@ class CentsDeltaToUsdPattern: self.to_own_mcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, _m(acc, 'to_own_mcap')) self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, acc) -class CentsToUsdPattern2: +class CentsToUsdPattern3: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): @@ -2747,10 +2747,10 @@ class LossNetNuplProfitPattern: def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated series name.""" - self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc, 'unrealized_loss') + self.loss: CentsNegativeUsdPattern = CentsNegativeUsdPattern(client, acc) self.net_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'net_unrealized_pnl')) self.nupl: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'nupl')) - self.profit: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit')) + self.profit: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'unrealized_profit')) class OutputsRealizedSupplyUnrealizedPattern2: """Pattern struct for repeated tree structure.""" @@ -2890,6 +2890,15 @@ class CentsDeltaUsdPattern: self.delta: AbsoluteRatePattern2 = AbsoluteRatePattern2(client, _m(acc, 'delta')) self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, acc) +class CentsNegativeUsdPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated series name.""" + self.cents: SeriesPattern1[Cents] = SeriesPattern1(client, _m(acc, 'unrealized_loss_cents')) + self.negative: SeriesPattern1[Dollars] = SeriesPattern1(client, _m(acc, 'neg_unrealized_loss')) + self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, _m(acc, 'unrealized_loss')) + class CentsSatsUsdPattern: """Pattern struct for repeated tree structure.""" @@ -2926,9 +2935,9 @@ class LossNuplProfitPattern: def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated series name.""" - self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc, 'unrealized_loss') + self.loss: CentsNegativeUsdPattern = CentsNegativeUsdPattern(client, acc) self.nupl: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'nupl')) - self.profit: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit')) + self.profit: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'unrealized_profit')) class NuplRealizedSupplyPattern: """Pattern struct for repeated tree structure.""" @@ -4862,9 +4871,8 @@ class SeriesTree_Cohorts_Utxo_All_Unrealized_Profit: """Series tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.base: CentsUsdPattern2 = CentsUsdPattern2(client, 'unrealized_profit') - self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, 'unrealized_profit_cumulative') - self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'unrealized_profit_sum') + self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, 'unrealized_profit') + self.cents: SeriesPattern1[Cents] = SeriesPattern1(client, 'unrealized_profit_cents') self.to_mcap: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'unrealized_profit_to_mcap') self.to_own_gross_pnl: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'unrealized_profit_to_own_gross_pnl') @@ -4872,9 +4880,8 @@ class SeriesTree_Cohorts_Utxo_All_Unrealized_Loss: """Series tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.base: CentsUsdPattern2 = CentsUsdPattern2(client, 'unrealized_loss') - self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, 'unrealized_loss_cumulative') - self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'unrealized_loss_sum') + self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, 'unrealized_loss') + self.cents: SeriesPattern1[Cents] = SeriesPattern1(client, 'unrealized_loss_cents') self.negative: SeriesPattern1[Dollars] = SeriesPattern1(client, 'neg_unrealized_loss') self.to_mcap: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'unrealized_loss_to_mcap') self.to_own_gross_pnl: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'unrealized_loss_to_own_gross_pnl') @@ -5111,9 +5118,9 @@ class SeriesTree_Cohorts_Utxo_Sth_Unrealized: def __init__(self, client: BrkClientBase, base_path: str = ''): self.nupl: BpsRatioPattern = BpsRatioPattern(client, 'sth_nupl') - self.profit: BaseCumulativeSumToPattern2 = BaseCumulativeSumToPattern2(client, 'sth_unrealized_profit') - self.loss: BaseCumulativeNegativeSumToPattern2 = BaseCumulativeNegativeSumToPattern2(client, 'sth') - self.net_pnl: CentsToUsdPattern2 = CentsToUsdPattern2(client, 'sth_net_unrealized_pnl') + self.profit: CentsToUsdPattern4 = CentsToUsdPattern4(client, 'sth_unrealized_profit') + self.loss: CentsNegativeToUsdPattern2 = CentsNegativeToUsdPattern2(client, 'sth') + self.net_pnl: CentsToUsdPattern3 = CentsToUsdPattern3(client, 'sth_net_unrealized_pnl') self.gross_pnl: CentsUsdPattern2 = CentsUsdPattern2(client, 'sth_unrealized_gross_pnl') self.invested_capital: InPattern = InPattern(client, 'sth_invested_capital_in') self.sentiment: SeriesTree_Cohorts_Utxo_Sth_Unrealized_Sentiment = SeriesTree_Cohorts_Utxo_Sth_Unrealized_Sentiment(client) @@ -5313,9 +5320,9 @@ class SeriesTree_Cohorts_Utxo_Lth_Unrealized: def __init__(self, client: BrkClientBase, base_path: str = ''): self.nupl: BpsRatioPattern = BpsRatioPattern(client, 'lth_nupl') - self.profit: BaseCumulativeSumToPattern2 = BaseCumulativeSumToPattern2(client, 'lth_unrealized_profit') - self.loss: BaseCumulativeNegativeSumToPattern2 = BaseCumulativeNegativeSumToPattern2(client, 'lth') - self.net_pnl: CentsToUsdPattern2 = CentsToUsdPattern2(client, 'lth_net_unrealized_pnl') + self.profit: CentsToUsdPattern4 = CentsToUsdPattern4(client, 'lth_unrealized_profit') + self.loss: CentsNegativeToUsdPattern2 = CentsNegativeToUsdPattern2(client, 'lth') + self.net_pnl: CentsToUsdPattern3 = CentsToUsdPattern3(client, 'lth_net_unrealized_pnl') self.gross_pnl: CentsUsdPattern2 = CentsUsdPattern2(client, 'lth_unrealized_gross_pnl') self.invested_capital: InPattern = InPattern(client, 'lth_invested_capital_in') self.sentiment: SeriesTree_Cohorts_Utxo_Lth_Unrealized_Sentiment = SeriesTree_Cohorts_Utxo_Lth_Unrealized_Sentiment(client) diff --git a/website/scripts/chart/index.js b/website/scripts/chart/index.js index e7e8045c5..74c340f4a 100644 --- a/website/scripts/chart/index.js +++ b/website/scripts/chart/index.js @@ -71,7 +71,7 @@ import { Unit } from "../utils/units.js"; const lineWidth = /** @type {any} */ (1.5); -const MAX_SIZE = 100_000; +const MAX_SIZE = 10_000; /** * @param {Object} args diff --git a/website/scripts/options/cointime.js b/website/scripts/options/cointime.js index c29c8aa92..e97ece715 100644 --- a/website/scripts/options/cointime.js +++ b/website/scripts/options/cointime.js @@ -165,7 +165,6 @@ export function createCointimeSection() { return { name: "Cointime", tree: [ - // Prices - the core pricing models { name: "Prices", tree: [ @@ -208,7 +207,6 @@ export function createCointimeSection() { ], }, - // Caps - market capitalizations from different models { name: "Caps", tree: [ @@ -242,7 +240,6 @@ export function createCointimeSection() { ], }, - // Supply - active vs vaulted breakdown { name: "Supply", title: "Active vs Vaulted Supply", @@ -251,7 +248,6 @@ export function createCointimeSection() { ), }, - // Liveliness - the foundational cointime ratios { name: "Activity", title: "Liveliness & Vaultedness", @@ -278,7 +274,6 @@ export function createCointimeSection() { ], }, - // Coinblocks - created, destroyed, stored { name: "Coinblocks", tree: [ @@ -300,7 +295,7 @@ export function createCointimeSection() { name, tree: [ { - name: "Base", + name: "Per Block", title, bottom: [ line({ @@ -329,7 +324,6 @@ export function createCointimeSection() { ], }, - // Value - cointime value flows { name: "Value", tree: [ @@ -360,7 +354,7 @@ export function createCointimeSection() { name, tree: [ { - name: "Base", + name: "Per Block", title, bottom: [ line({ series: pattern.base, name, color, unit: Unit.usd }), @@ -385,7 +379,7 @@ export function createCointimeSection() { name: vocdd.name, tree: [ { - name: "Base", + name: "Per Block", title: vocdd.title, bottom: [ line({ @@ -424,7 +418,6 @@ export function createCointimeSection() { ], }, - // Indicators - derived decision series { name: "Indicators", tree: [ @@ -446,7 +439,7 @@ export function createCointimeSection() { bottom: [ line({ series: cap.aviv.ratio, - name: "aviv", + name: "AVIV", unit: Unit.ratio, }), ], @@ -454,7 +447,6 @@ export function createCointimeSection() { ], }, - // Cointime-Adjusted - comparing base vs adjusted series { name: "Cointime-Adjusted", tree: [ @@ -476,44 +468,39 @@ export function createCointimeSection() { ], }, { - name: "Velocity", - tree: [ - { - name: "BTC", - title: "Cointime-Adjusted BTC Velocity", - bottom: [ - line({ - series: supply.velocity.native, - name: "Base", - color: colors.base, - unit: Unit.ratio, - }), - line({ - series: adjusted.txVelocityNative, - name: "Cointime-Adjusted", - color: colors.adjusted, - unit: Unit.ratio, - }), - ], - }, - { - name: "USD", - title: "Cointime-Adjusted USD Velocity", - bottom: [ - line({ - series: supply.velocity.fiat, - name: "Base", - color: colors.thermo, - unit: Unit.ratio, - }), - line({ - series: adjusted.txVelocityFiat, - name: "Cointime-Adjusted", - color: colors.vaulted, - unit: Unit.ratio, - }), - ], - }, + name: "BTC Velocity", + title: "Cointime-Adjusted BTC Velocity", + bottom: [ + line({ + series: supply.velocity.native, + name: "Base", + color: colors.base, + unit: Unit.ratio, + }), + line({ + series: adjusted.txVelocityNative, + name: "Cointime-Adjusted", + color: colors.adjusted, + unit: Unit.ratio, + }), + ], + }, + { + name: "USD Velocity", + title: "Cointime-Adjusted USD Velocity", + bottom: [ + line({ + series: supply.velocity.fiat, + name: "Base", + color: colors.thermo, + unit: Unit.ratio, + }), + line({ + series: adjusted.txVelocityFiat, + name: "Cointime-Adjusted", + color: colors.vaulted, + unit: Unit.ratio, + }), ], }, ], diff --git a/website/scripts/options/distribution/activity.js b/website/scripts/options/distribution/activity.js index 8701014a7..23812ea38 100644 --- a/website/scripts/options/distribution/activity.js +++ b/website/scripts/options/distribution/activity.js @@ -32,7 +32,7 @@ function volumeAndCoinsTree(activity, color, title) { name: "Volume", tree: [ { - name: "Sum", + name: "Per Block", title: title("Sent Volume"), bottom: [ line({ series: activity.transferVolume.base.sats, name: "Sum", color, unit: Unit.sats }), @@ -52,10 +52,10 @@ function volumeAndCoinsTree(activity, color, title) { ], }, { - name: "Coins Destroyed", + name: "Coindays Destroyed", tree: [ { - name: "Base", + name: "Per Block", title: title("Coindays Destroyed"), bottom: [ line({ series: activity.coindaysDestroyed.base, name: "Base", color, unit: Unit.coindays }), @@ -675,7 +675,7 @@ function groupedRollingSoprCharts(list, all, get24h, get7d, get30d, get1y, title * @template {{ color: Color, name: string }} A * @param {readonly T[]} list * @param {A} all - * @param {readonly { name: string, getCreated: (item: T | A) => AnySeriesPattern, getDestroyed: (item: T | A) => AnySeriesPattern }[]} windows + * @param {readonly { name: string, title: string, getCreated: (item: T | A) => AnySeriesPattern, getDestroyed: (item: T | A) => AnySeriesPattern }[]} windows * @param {(name: string) => string} title * @param {string} [prefix] * @returns {PartialOptionsTree} @@ -686,7 +686,7 @@ function groupedRollingValueCharts(list, all, windows, title, prefix = "") { name: "Created", tree: windows.map((w) => ({ name: w.name, - title: title(`${prefix}Value Created (${w.name})`), + title: title(`${prefix}Value Created (${w.title})`), bottom: mapCohortsWithAll(list, all, (item) => line({ series: w.getCreated(item), name: item.name, color: item.color, unit: Unit.usd }), ), @@ -696,7 +696,7 @@ function groupedRollingValueCharts(list, all, windows, title, prefix = "") { name: "Destroyed", tree: windows.map((w) => ({ name: w.name, - title: title(`${prefix}Value Destroyed (${w.name})`), + title: title(`${prefix}Value Destroyed (${w.title})`), bottom: mapCohortsWithAll(list, all, (item) => line({ series: w.getDestroyed(item), name: item.name, color: item.color, unit: Unit.usd }), ), @@ -711,10 +711,10 @@ function groupedRollingValueCharts(list, all, windows, title, prefix = "") { */ function valueWindows(list, all) { return [ - { name: "24h", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._24h, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._24h }, - { name: "7d", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1w, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1w }, - { name: "30d", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1m, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1m }, - { name: "1y", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1y, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1y }, + { name: "24h", title: "Daily", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._24h, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._24h }, + { name: "7d", title: "Weekly", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1w, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1w }, + { name: "30d", title: "Monthly", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1m, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1m }, + { name: "1y", title: "Yearly", getCreated: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueCreated.sum._1y, getDestroyed: (/** @type {typeof list[number] | typeof all} */ c) => c.tree.realized.sopr.valueDestroyed.sum._1y }, ]; } @@ -823,10 +823,10 @@ export function createGroupedActivitySectionWithAdjusted({ list, all, title }) { tree: groupedRollingValueCharts( list, all, [ - { name: "24h", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._24h, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._24h }, - { name: "7d", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1w, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1w }, - { name: "30d", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1m, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1m }, - { name: "1y", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1y, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1y }, + { name: "24h", title: "Daily", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._24h, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._24h }, + { name: "7d", title: "Weekly", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1w, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1w }, + { name: "30d", title: "Monthly", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1m, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1m }, + { name: "1y", title: "Yearly", getCreated: (c) => c.tree.realized.sopr.adjusted.valueCreated.sum._1y, getDestroyed: (c) => c.tree.realized.sopr.adjusted.valueDestroyed.sum._1y }, ], title, "Adjusted ", @@ -837,7 +837,7 @@ export function createGroupedActivitySectionWithAdjusted({ list, all, title }) { ], }, { - name: "Coins Destroyed", + name: "Coindays Destroyed", title: title("Coindays Destroyed"), bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [ line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }), @@ -914,7 +914,7 @@ export function createGroupedActivitySection({ list, all, title }) { ], }, { - name: "Coins Destroyed", + name: "Coindays Destroyed", title: title("Coindays Destroyed"), bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [ line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }), @@ -955,7 +955,7 @@ export function createGroupedActivitySectionWithActivity({ list, all, title }) { ], }, { - name: "Coins Destroyed", + name: "Coindays Destroyed", title: title("Coindays Destroyed"), bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [ line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }), diff --git a/website/scripts/options/distribution/holdings.js b/website/scripts/options/distribution/holdings.js index bba54b58c..51b3f75b1 100644 --- a/website/scripts/options/distribution/holdings.js +++ b/website/scripts/options/distribution/holdings.js @@ -199,7 +199,7 @@ function groupedDeltaTree(list, all, getDelta, unit, title, name) { name: "Absolute", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`${name} Change (${w.name})`), + title: title(`${name} Change (${w.title})`), bottom: mapCohortsWithAll(list, all, (c) => baseline({ series: getDelta(c).absolute[w.key], name: c.name, color: c.color, unit }), ), @@ -209,7 +209,7 @@ function groupedDeltaTree(list, all, getDelta, unit, title, name) { name: "Rate", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`${name} Rate (${w.name})`), + title: title(`${name} Rate (${w.title})`), bottom: flatMapCohortsWithAll(list, all, (c) => percentRatio({ pattern: getDelta(c).rate[w.key], name: c.name, color: c.color }), ), diff --git a/website/scripts/options/distribution/index.js b/website/scripts/options/distribution/index.js index 7bf04b36d..f98942df9 100644 --- a/website/scripts/options/distribution/index.js +++ b/website/scripts/options/distribution/index.js @@ -677,7 +677,7 @@ function groupedBucketCharts(list, titlePrefix) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: `${titlePrefix}: Supply Change ${w.name}`, + title: `${titlePrefix}: Supply Change (${w.title})`, bottom: list.map(({ name, color, pattern }) => baseline({ series: pattern.supply.all.delta.absolute[w.key], name, color, unit: Unit.sats }), ), @@ -698,7 +698,7 @@ function groupedBucketCharts(list, titlePrefix) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: `${titlePrefix}: Supply Rate ${w.name}`, + title: `${titlePrefix}: Supply Rate (${w.title})`, bottom: list.flatMap(({ name, color, pattern }) => percentRatio({ pattern: pattern.supply.all.delta.rate[w.key], name, color }), ), diff --git a/website/scripts/options/distribution/profitability.js b/website/scripts/options/distribution/profitability.js index a0185d767..7f69194ec 100644 --- a/website/scripts/options/distribution/profitability.js +++ b/website/scripts/options/distribution/profitability.js @@ -45,7 +45,7 @@ function pnlLines(m, unit) { if (m.gross) { series.push(line({ series: m.gross, name: "Total", color: colors.default, unit })); } - series.push(line({ series: m.negLoss, name: "Negative Loss", color: colors.loss, unit, defaultActive: false })); + series.push(line({ series: m.negLoss, name: "Loss (Inverted)", color: colors.loss, unit, defaultActive: false })); return series; } @@ -63,13 +63,13 @@ function netBaseline(s, unit) { // ============================================================================ /** - * @param {{ profit: { base: { usd: AnySeriesPattern } }, loss: { base: { usd: AnySeriesPattern }, negative: AnySeriesPattern }, grossPnl: { usd: AnySeriesPattern } }} u + * @param {{ profit: { usd: AnySeriesPattern }, loss: { usd: AnySeriesPattern, negative: AnySeriesPattern }, grossPnl: { usd: AnySeriesPattern } }} u * @returns {AnyFetchedSeriesBlueprint[]} */ function unrealizedUsdSeries(u) { return [ ...pnlLines( - { profit: u.profit.base.usd, loss: u.loss.base.usd, negLoss: u.loss.negative, gross: u.grossPnl.usd }, + { profit: u.profit.usd, loss: u.loss.usd, negLoss: u.loss.negative, gross: u.grossPnl.usd }, Unit.usd, ), priceLine({ unit: Unit.usd, defaultActive: false }), @@ -105,7 +105,6 @@ function unrealizedPnlTreeAll(u, title) { { name: "USD", title: title("Unrealized P&L"), bottom: unrealizedUsdSeries(u) }, relPnlChart(u.profit.toMcap, u.loss.toMcap, "% of Mcap", title), relPnlChart(u.profit.toOwnGrossPnl, u.loss.toOwnGrossPnl, "% of Own P&L", title), - ...unrealizedCumulativeRollingTree(u.profit, u.loss, title), ]; } @@ -121,7 +120,6 @@ function unrealizedPnlTreeFull(u, title) { relPnlChart(u.profit.toMcap, u.loss.toMcap, "% of Mcap", title), relPnlChart(u.profit.toOwnMcap, u.loss.toOwnMcap, "% of Own Mcap", title), relPnlChart(u.profit.toOwnGrossPnl, u.loss.toOwnGrossPnl, "% of Own P&L", title), - ...unrealizedCumulativeRollingTree(u.profit, u.loss, title), ]; } @@ -141,7 +139,6 @@ function unrealizedPnlTreeLongTerm(u, title) { }, relPnlChart(u.profit.toOwnMcap, u.loss.toOwnMcap, "% of Own Mcap", title), relPnlChart(u.profit.toOwnGrossPnl, u.loss.toOwnGrossPnl, "% of Own P&L", title), - ...unrealizedCumulativeRollingTree(u.profit, u.loss, title), ]; } @@ -158,72 +155,12 @@ function unrealizedPnlTreeMid(u, title) { title: title("Unrealized P&L"), bottom: [ ...pnlLines( - { profit: u.profit.base.usd, loss: u.loss.base.usd, negLoss: u.loss.negative }, + { profit: u.profit.usd, loss: u.loss.usd, negLoss: u.loss.negative }, Unit.usd, ), priceLine({ unit: Unit.usd, defaultActive: false }), ], }, - ...unrealizedCumulativeRollingTree(u.profit, u.loss, title), - ]; -} - -/** - * Unrealized cumulative + rolling P&L tree (profit and loss have cumulative.usd + sum[w].usd) - * @param {{ cumulative: { usd: AnySeriesPattern }, sum: { _24h: { usd: AnySeriesPattern }, _1w: { usd: AnySeriesPattern }, _1m: { usd: AnySeriesPattern }, _1y: { usd: AnySeriesPattern } } }} profit - * @param {{ cumulative: { usd: AnySeriesPattern }, sum: { _24h: { usd: AnySeriesPattern }, _1w: { usd: AnySeriesPattern }, _1m: { usd: AnySeriesPattern }, _1y: { usd: AnySeriesPattern } } }} loss - * @param {(name: string) => string} title - * @returns {PartialOptionsTree} - */ -function unrealizedCumulativeRollingTree(profit, loss, title) { - return [ - { - name: "Cumulative", - title: title("Cumulative Unrealized P&L"), - bottom: [ - line({ series: profit.cumulative.usd, name: "Profit", color: colors.profit, unit: Unit.usd }), - line({ series: loss.cumulative.usd, name: "Loss", color: colors.loss, unit: Unit.usd }), - ], - }, - { - name: "Rolling", - tree: [ - { - name: "Profit", - tree: [ - { - name: "Compare", - title: title("Rolling Unrealized Profit"), - bottom: ROLLING_WINDOWS.map((w) => - line({ series: profit.sum[w.key].usd, name: w.name, color: w.color, unit: Unit.usd }), - ), - }, - ...ROLLING_WINDOWS.map((w) => ({ - name: w.name, - title: title(`Unrealized Profit (${w.name})`), - bottom: [line({ series: profit.sum[w.key].usd, name: "Profit", color: colors.profit, unit: Unit.usd })], - })), - ], - }, - { - name: "Loss", - tree: [ - { - name: "Compare", - title: title("Rolling Unrealized Loss"), - bottom: ROLLING_WINDOWS.map((w) => - line({ series: loss.sum[w.key].usd, name: w.name, color: w.color, unit: Unit.usd }), - ), - }, - ...ROLLING_WINDOWS.map((w) => ({ - name: w.name, - title: title(`Unrealized Loss (${w.name})`), - bottom: [line({ series: loss.sum[w.key].usd, name: "Loss", color: colors.loss, unit: Unit.usd })], - })), - ], - }, - ], - }, ]; } @@ -331,12 +268,12 @@ function realizedPnlSumTreeFull(r, title) { title: title("Realized P&L"), bottom: [ dots({ series: r.profit.base.usd, name: "Profit", color: colors.profit, unit: Unit.usd }), - dots({ series: r.loss.negative, name: "Negative Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }), + dots({ series: r.loss.negative, name: "Loss (Inverted)", color: colors.loss, unit: Unit.usd, defaultActive: false }), dots({ series: r.loss.base.usd, name: "Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }), ], }, { - name: "% of Rcap", + name: "% of Realized Cap", title: title("Realized P&L (% of Realized Cap)"), bottom: [ ...percentRatioBaseline({ pattern: r.profit.toRcap, name: "Profit", color: colors.profit }), @@ -355,7 +292,7 @@ function realizedNetPnlSumTreeFull(r, title) { return [ { name: "USD", title: title("Net Realized P&L"), bottom: [dotsBaseline({ series: r.netPnl.base.usd, name: "Net", unit: Unit.usd })] }, { - name: "% of Rcap", + name: "% of Realized Cap", title: title("Net Realized P&L (% of Realized Cap)"), bottom: percentRatioBaseline({ pattern: r.netPnl.toRcap, name: "Net" }), }, @@ -375,11 +312,11 @@ function realizedPnlCumulativeTreeFull(r, title) { bottom: [ line({ series: r.profit.cumulative.usd, name: "Profit", color: colors.profit, unit: Unit.usd }), line({ series: r.loss.cumulative.usd, name: "Loss", color: colors.loss, unit: Unit.usd }), - line({ series: r.loss.negative, name: "Negative Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }), + line({ series: r.loss.negative, name: "Loss (Inverted)", color: colors.loss, unit: Unit.usd, defaultActive: false }), ], }, { - name: "% of Rcap", + name: "% of Realized Cap", title: title("Cumulative Realized P&L (% of Realized Cap)"), bottom: [ ...percentRatioBaseline({ pattern: r.profit.toRcap, name: "Profit", color: colors.profit }), @@ -411,7 +348,7 @@ function realizedNetPnlDeltaTree(netPnl, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Net Realized P&L Change (${w.name})`), + title: title(`Net Realized P&L Change (${w.title})`), bottom: [baseline({ series: netPnl.delta.absolute[w.key].usd, name: "Change", unit: Unit.usd })], })), ], @@ -428,7 +365,7 @@ function realizedNetPnlDeltaTree(netPnl, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Net Realized P&L Rate (${w.name})`), + title: title(`Net Realized P&L Rate (${w.title})`), bottom: percentRatioBaseline({ pattern: netPnl.delta.rate[w.key], name: "Rate" }), })), ], @@ -455,8 +392,8 @@ function realizedNetPnlDeltaTreeFull(r, title) { bottom: percentRatioBaseline({ pattern: r.netPnl.change1m.toMcap, name: "30d Change" }), }, { - name: "% of Rcap", - title: title("Net Realized P&L Change (% of Rcap)"), + name: "% of Realized Cap", + title: title("Net Realized P&L Change (% of Realized Cap)"), bottom: percentRatioBaseline({ pattern: r.netPnl.change1m.toRcap, name: "30d Change" }), }, ], @@ -482,7 +419,7 @@ function rollingNetRealizedTree(netPnl, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Net Realized P&L (${w.name})`), + title: title(`Net Realized P&L (${w.title})`), bottom: [baseline({ series: netPnl.sum[w.key].usd, name: "Net", unit: Unit.usd })], })), ], @@ -509,7 +446,7 @@ function singleRollingRealizedTreeFull(r, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Profit (${w.name})`), + title: title(`Realized Profit (${w.title})`), bottom: [line({ series: r.profit.sum[w.key].usd, name: "Profit", color: colors.profit, unit: Unit.usd })], })), ], @@ -526,7 +463,7 @@ function singleRollingRealizedTreeFull(r, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Loss (${w.name})`), + title: title(`Realized Loss (${w.title})`), bottom: [line({ series: r.loss.sum[w.key].usd, name: "Loss", color: colors.loss, unit: Unit.usd })], })), ], @@ -544,7 +481,7 @@ function singleRollingRealizedTreeFull(r, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized P/L Ratio (${w.name})`), + title: title(`Realized P/L Ratio (${w.title})`), bottom: [baseline({ series: r.profitToLossRatio[w.key], name: "P/L Ratio", unit: Unit.ratio, base: 1 })], })), ], @@ -565,7 +502,7 @@ function singleRollingRealizedTreeBasic(profit, loss, title) { name: "Profit", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Profit (${w.name})`), + title: title(`Realized Profit (${w.title})`), bottom: [line({ series: profit.sum[w.key].usd, name: "Profit", color: colors.profit, unit: Unit.usd })], })), }, @@ -573,7 +510,7 @@ function singleRollingRealizedTreeBasic(profit, loss, title) { name: "Loss", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Loss (${w.name})`), + title: title(`Realized Loss (${w.title})`), bottom: [line({ series: loss.sum[w.key].usd, name: "Loss", color: colors.loss, unit: Unit.usd })], })), }, @@ -609,7 +546,7 @@ function realizedValueTree(valueCreated, valueDestroyed, label, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`${label} Value (${w.name})`), + title: title(`${label} Value (${w.title})`), bottom: [ line({ series: valueCreated.sum[w.key], name: "Created", color: colors.profit, unit: Unit.usd }), line({ series: valueDestroyed.sum[w.key], name: "Destroyed", color: colors.loss, unit: Unit.usd }), @@ -690,7 +627,7 @@ function realizedSubfolderFull(r, title) { { name: "Gross P&L", tree: [ - { name: "Base", title: title("Gross Realized P&L"), bottom: [dots({ series: r.grossPnl.base.usd, name: "Gross P&L", color: colors.bitcoin, unit: Unit.usd })] }, + { name: "Per Block", title: title("Gross Realized P&L"), bottom: [dots({ series: r.grossPnl.base.usd, name: "Gross P&L", color: colors.bitcoin, unit: Unit.usd })] }, { name: "Rolling", tree: [ @@ -703,7 +640,7 @@ function realizedSubfolderFull(r, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Gross Realized P&L (${w.name})`), + title: title(`Gross Realized P&L (${w.title})`), bottom: [line({ series: r.grossPnl.sum[w.key].usd, name: "Gross P&L", color: colors.bitcoin, unit: Unit.usd })], })), ], @@ -744,7 +681,7 @@ function realizedSubfolderFull(r, title) { tree: [ { name: "USD", title: title("Cumulative Net Realized P&L"), bottom: [baseline({ series: r.netPnl.cumulative.usd, name: "Net", unit: Unit.usd })] }, { - name: "% of Rcap", + name: "% of Realized Cap", title: title("Cumulative Net P&L (% of Realized Cap)"), bottom: percentRatioBaseline({ pattern: r.netPnl.toRcap, name: "Net" }), }, @@ -755,7 +692,7 @@ function realizedSubfolderFull(r, title) { tree: [ { name: "USD", title: title("Cumulative Peak Regret"), bottom: [line({ series: r.peakRegret.cumulative, name: "Peak Regret", unit: Unit.usd })] }, { - name: "% of Rcap", + name: "% of Realized Cap", title: title("Cumulative Peak Regret (% of Realized Cap)"), bottom: percentRatioBaseline({ pattern: r.peakRegret.toRcap, name: "Peak Regret" }), }, @@ -782,7 +719,7 @@ function realizedSubfolderMid(r, title) { title: title("Realized P&L"), bottom: [ dots({ series: r.profit.base.usd, name: "Profit", color: colors.profit, unit: Unit.usd }), - dots({ series: r.loss.negative, name: "Negative Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }), + dots({ series: r.loss.negative, name: "Loss (Inverted)", color: colors.loss, unit: Unit.usd, defaultActive: false }), dots({ series: r.loss.base.usd, name: "Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }), ], }, @@ -898,12 +835,11 @@ export function createProfitabilitySectionWithProfitLoss({ cohort, title }) { name: "USD", title: title("Unrealized P&L"), bottom: [ - ...pnlLines({ profit: u.profit.base.usd, loss: u.loss.base.usd, negLoss: u.loss.negative }, Unit.usd), + ...pnlLines({ profit: u.profit.usd, loss: u.loss.usd, negLoss: u.loss.negative }, Unit.usd), priceLine({ unit: Unit.usd, defaultActive: false }), ], }, - ...unrealizedCumulativeRollingTree(u.profit, u.loss, title), - ], + ], }, { name: "NUPL", title: title("NUPL"), bottom: nuplSeries(u.nupl) }, ], @@ -1089,12 +1025,11 @@ export function createProfitabilitySectionAddress({ cohort, title }) { name: "USD", title: title("Unrealized P&L"), bottom: [ - ...pnlLines({ profit: u.profit.base.usd, loss: u.loss.base.usd, negLoss: u.loss.negative }, Unit.usd), + ...pnlLines({ profit: u.profit.usd, loss: u.loss.usd, negLoss: u.loss.negative }, Unit.usd), priceLine({ unit: Unit.usd, defaultActive: false }), ], }, - ...unrealizedCumulativeRollingTree(u.profit, u.loss, title), - ], + ], }, { name: "NUPL", title: title("NUPL"), bottom: nuplSeries(u.nupl) }, ], @@ -1178,7 +1113,7 @@ function groupedRollingRealizedCharts(list, all, title) { name: "Profit", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Profit (${w.name})`), + title: title(`Realized Profit (${w.title})`), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => line({ series: tree.realized.profit.sum[w.key].usd, name, color, unit: Unit.usd })), })), }, @@ -1186,7 +1121,7 @@ function groupedRollingRealizedCharts(list, all, title) { name: "Loss", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Loss (${w.name})`), + title: title(`Realized Loss (${w.title})`), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => line({ series: tree.realized.loss.sum[w.key].usd, name, color, unit: Unit.usd })), })), }, @@ -1207,7 +1142,7 @@ function groupedRollingRealizedChartsFull(list, all, title) { name: "P/L Ratio", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized P/L Ratio (${w.name})`), + title: title(`Realized P/L Ratio (${w.title})`), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => baseline({ series: tree.realized.profitToLossRatio[w.key], name, color, unit: Unit.ratio, base: 1 }), ), @@ -1279,7 +1214,7 @@ function groupedRealizedNetPnlDeltaTree(list, all, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Net Realized P&L Change (${w.name})`), + title: title(`Net Realized P&L Change (${w.title})`), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => baseline({ series: tree.realized.netPnl.delta.absolute[w.key].usd, name, color, unit: Unit.usd }), ), @@ -1300,7 +1235,7 @@ function groupedRealizedNetPnlDeltaTree(list, all, title) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Net Realized P&L Rate (${w.name})`), + title: title(`Net Realized P&L Rate (${w.title})`), bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => percentRatio({ pattern: tree.realized.netPnl.delta.rate[w.key], name, color }), ), @@ -1399,7 +1334,7 @@ function groupedPnlChartsWithMarketCap(list, all, title) { name: "USD", title: title("Unrealized Profit"), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => - line({ series: tree.unrealized.profit.base.usd, name, color, unit: Unit.usd }), + line({ series: tree.unrealized.profit.usd, name, color, unit: Unit.usd }), ), }, { @@ -1418,7 +1353,7 @@ function groupedPnlChartsWithMarketCap(list, all, title) { name: "USD", title: title("Unrealized Loss"), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => - line({ series: tree.unrealized.loss.base.usd, name, color, unit: Unit.usd }), + line({ series: tree.unrealized.loss.usd, name, color, unit: Unit.usd }), ), }, { @@ -1453,14 +1388,14 @@ function groupedPnlChartsWithOwnMarketCap(list, all, title) { name: "Profit", title: title("Unrealized Profit"), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => - line({ series: tree.unrealized.profit.base.usd, name, color, unit: Unit.usd }), + line({ series: tree.unrealized.profit.usd, name, color, unit: Unit.usd }), ), }, { name: "Loss", title: title("Unrealized Loss"), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => - line({ series: tree.unrealized.loss.base.usd, name, color, unit: Unit.usd }), + line({ series: tree.unrealized.loss.usd, name, color, unit: Unit.usd }), ), }, { @@ -1489,7 +1424,7 @@ function groupedPnlChartsLongTerm(list, all, title) { name: "USD", title: title("Unrealized Profit"), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => - line({ series: tree.unrealized.profit.base.usd, name, color, unit: Unit.usd }), + line({ series: tree.unrealized.profit.usd, name, color, unit: Unit.usd }), ), }, { @@ -1515,7 +1450,7 @@ function groupedPnlChartsLongTerm(list, all, title) { name: "USD", title: title("Unrealized Loss"), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => - line({ series: tree.unrealized.loss.base.usd, name, color, unit: Unit.usd }), + line({ series: tree.unrealized.loss.usd, name, color, unit: Unit.usd }), ), }, { @@ -1642,14 +1577,14 @@ export function createGroupedProfitabilitySectionWithProfitLoss({ list, all, tit name: "Profit", title: title("Unrealized Profit"), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => - line({ series: tree.unrealized.profit.base.usd, name, color, unit: Unit.usd }), + line({ series: tree.unrealized.profit.usd, name, color, unit: Unit.usd }), ), }, { name: "Loss", title: title("Unrealized Loss"), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => - line({ series: tree.unrealized.loss.base.usd, name, color, unit: Unit.usd }), + line({ series: tree.unrealized.loss.usd, name, color, unit: Unit.usd }), ), }, ...groupedNuplCharts(list, all, title), diff --git a/website/scripts/options/distribution/valuation.js b/website/scripts/options/distribution/valuation.js index b5be81d71..328ea6dab 100644 --- a/website/scripts/options/distribution/valuation.js +++ b/website/scripts/options/distribution/valuation.js @@ -50,9 +50,9 @@ export function createValuationSectionFull({ cohort, title }) { bottom: createSingleRealizedCapSeries(cohort), }, { - name: "% of Own Mcap", - title: title("Realized Cap (% of Own Mcap)"), - bottom: percentRatioBaseline({ pattern: tree.realized.cap.toOwnMcap, name: "Rel. to Own M.Cap", color }), + name: "% of Own Market Cap", + title: title("Realized Cap (% of Own Market Cap)"), + bottom: percentRatioBaseline({ pattern: tree.realized.cap.toOwnMcap, name: "Rel. to Own Market Cap", color }), }, ], }, @@ -140,7 +140,7 @@ export function createGroupedValuationSection({ list, all, title }) { name: "Absolute", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Cap Change (${w.name})`), + title: title(`Realized Cap Change (${w.title})`), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => baseline({ series: tree.realized.cap.delta.absolute[w.key].usd, name, color, unit: Unit.usd }), ), @@ -150,7 +150,7 @@ export function createGroupedValuationSection({ list, all, title }) { name: "Rate", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Cap Rate (${w.name})`), + title: title(`Realized Cap Rate (${w.title})`), bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => percentRatio({ pattern: tree.realized.cap.delta.rate[w.key], name, color }), ), @@ -198,8 +198,8 @@ export function createGroupedValuationSectionWithOwnMarketCap({ ), }, { - name: "% of Own Mcap", - title: title("Realized Cap (% of Own Mcap)"), + name: "% of Own Market Cap", + title: title("Realized Cap (% of Own Market Cap)"), bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => percentRatio({ pattern: tree.realized.cap.toOwnMcap, name, color }), ), @@ -213,7 +213,7 @@ export function createGroupedValuationSectionWithOwnMarketCap({ name: "Absolute", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Cap Change (${w.name})`), + title: title(`Realized Cap Change (${w.title})`), bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) => baseline({ series: tree.realized.cap.delta.absolute[w.key].usd, name, color, unit: Unit.usd }), ), @@ -223,7 +223,7 @@ export function createGroupedValuationSectionWithOwnMarketCap({ name: "Rate", tree: ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: title(`Realized Cap Rate (${w.name})`), + title: title(`Realized Cap Rate (${w.title})`), bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => percentRatio({ pattern: tree.realized.cap.delta.rate[w.key], name, color }), ), diff --git a/website/scripts/options/investing.js b/website/scripts/options/investing.js index 776c73af1..cfedcf084 100644 --- a/website/scripts/options/investing.js +++ b/website/scripts/options/investing.js @@ -292,26 +292,8 @@ export function createDcaVsLumpSumSection({ dca, lookback, returns }) { top: topPane(key), }); - /** @param {string} name @param {ShortPeriodKey} key */ - const shortReturnsChart = (name, key) => ({ - name: "Returns", - title: `Returns: ${name} DCA vs Lump Sum`, - top: topPane(key), - bottom: [ - ...percentRatioBaseline({ - pattern: dca.period.return[key], - name: "DCA", - }), - ...percentRatioBaseline({ - pattern: dca.period.lumpSumReturn[key], - name: "Lump Sum", - color: colors.bi.p2, - }), - ], - }); - - /** @param {string} name @param {LongPeriodKey} key */ - const longReturnsChart = (name, key) => ({ + /** @param {string} name @param {AllPeriodKey} key */ + const returnsChart = (name, key) => ({ name: "Returns", title: `Returns: ${name} DCA vs Lump Sum`, top: topPane(key), @@ -372,7 +354,7 @@ export function createDcaVsLumpSumSection({ dca, lookback, returns }) { name, tree: [ costBasisChart(name, key), - shortReturnsChart(name, key), + returnsChart(name, key), stackChart(name, key), ], }; @@ -385,7 +367,7 @@ export function createDcaVsLumpSumSection({ dca, lookback, returns }) { name, tree: [ costBasisChart(name, key), - longReturnsChart(name, key), + returnsChart(name, key), longCagrChart(name, key), stackChart(name, key), ], diff --git a/website/scripts/options/market.js b/website/scripts/options/market.js index 7072734e1..59eafd2f4 100644 --- a/website/scripts/options/market.js +++ b/website/scripts/options/market.js @@ -576,7 +576,7 @@ export function createMarketSection() { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: `Capitalization Growth Rate Spread ${w.name}`, + title: `Capitalization Growth Rate Spread (${w.title})`, bottom: [ baseline({ series: supply.marketMinusRealizedCapGrowthRate[w.key], @@ -660,7 +660,7 @@ export function createMarketSection() { const rsi = technical.rsi[w.key]; return { name: w.name, - title: `RSI (${w.name})`, + title: `RSI (${w.title})`, bottom: [ ...indexRatio({ pattern: rsi.rsi, name: "RSI", color: colors.indicator.main }), priceLine({ unit: Unit.index, number: 70 }), @@ -675,7 +675,7 @@ export function createMarketSection() { const rsi = technical.rsi[w.key]; return { name: w.name, - title: `Stochastic RSI (${w.name})`, + title: `Stochastic RSI (${w.title})`, bottom: [ ...indexRatio({ pattern: rsi.stochRsiK, name: "K", color: colors.indicator.fast }), ...indexRatio({ pattern: rsi.stochRsiD, name: "D", color: colors.indicator.slow }), @@ -698,7 +698,7 @@ export function createMarketSection() { }, ...ROLLING_WINDOWS_TO_1M.map((w) => ({ name: w.name, - title: `MACD (${w.name})`, + title: `MACD (${w.title})`, bottom: [ line({ series: technical.macd[w.key].line, name: "MACD", color: colors.indicator.fast, unit: Unit.usd }), line({ series: technical.macd[w.key].signal, name: "Signal", color: colors.indicator.slow, unit: Unit.usd }), @@ -726,7 +726,7 @@ export function createMarketSection() { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: `Volatility Index (${w.name})`, + title: `Volatility Index (${w.title})`, bottom: [line({ series: volatility[w.key], name: w.name, color: w.color, unit: Unit.percentage })], })), ], diff --git a/website/scripts/options/partial.js b/website/scripts/options/partial.js index 7f56e5f13..dbddc3e6a 100644 --- a/website/scripts/options/partial.js +++ b/website/scripts/options/partial.js @@ -59,27 +59,20 @@ export function createPartialOptions() { } = buildCohortData(); return [ - // Charts section { name: "Charts", tree: [ - // Market section createMarketSection(), - // Network section (on-chain activity) createNetworkSection(), - // Mining section (security & economics) createMiningSection(), - // Cohorts section { name: "Distribution", tree: [ - // Overview - All UTXOs createCohortFolderAll({ ...cohortAll, name: "Overview" }), - // STH vs LTH - Direct comparison createGroupedCohortFolderWithNupl({ name: "STH vs LTH", title: "STH vs LTH", @@ -87,17 +80,13 @@ export function createPartialOptions() { all: cohortAll, }), - // STH - Short term holder cohort createCohortFolderFull(termShort), - // LTH - Long term holder cohort createCohortFolderLongTerm(termLong), - // Ages cohorts { name: "UTXO Age", tree: [ - // Younger Than (< X old) { name: "Younger Than", tree: [ @@ -110,7 +99,6 @@ export function createPartialOptions() { ...underAge.map(createCohortFolderWithAdjusted), ], }, - // Older Than (≥ X old) { name: "Older Than", tree: [ @@ -123,7 +111,6 @@ export function createPartialOptions() { ...overAge.map(createCohortFolderWithAdjusted), ], }, - // Range { name: "Range", tree: [ @@ -139,17 +126,15 @@ export function createPartialOptions() { ], }, - // Sizes cohorts (UTXO size) { name: "UTXO Size", tree: [ - // Less Than (< X sats) { name: "Less Than", tree: [ createGroupedCohortFolderBasicWithMarketCap({ name: "Compare", - title: "Over Amount", + title: "Under Amount", list: utxosUnderAmount, all: cohortAll, }), @@ -158,13 +143,12 @@ export function createPartialOptions() { ), ], }, - // More Than (≥ X sats) { name: "More Than", tree: [ createGroupedCohortFolderBasicWithMarketCap({ name: "Compare", - title: "Under Amount", + title: "Over Amount", list: utxosOverAmount, all: cohortAll, }), @@ -173,7 +157,6 @@ export function createPartialOptions() { ), ], }, - // Range { name: "Range", tree: [ @@ -191,37 +174,39 @@ export function createPartialOptions() { ], }, - // Balances cohorts (Address balance) + createUtxoProfitabilitySection({ + range: profitabilityRange, + profit: profitabilityProfit, + loss: profitabilityLoss, + }), + { name: "Address Balance", tree: [ - // Less Than (< X sats) { name: "Less Than", tree: [ createGroupedAddressCohortFolder({ name: "Compare", - title: "Over Balance", + title: "Under Balance", list: addressesUnderAmount, all: cohortAll, }), ...addressesUnderAmount.map(createAddressCohortFolder), ], }, - // More Than (≥ X sats) { name: "More Than", tree: [ createGroupedAddressCohortFolder({ name: "Compare", - title: "Under Balance", + title: "Over Balance", list: addressesOverAmount, all: cohortAll, }), ...addressesOverAmount.map(createAddressCohortFolder), ], }, - // Range { name: "Range", tree: [ @@ -237,7 +222,6 @@ export function createPartialOptions() { ], }, - // Script Types - addressable types have addrCount, others don't { name: "Script Type", tree: [ @@ -252,7 +236,6 @@ export function createPartialOptions() { ], }, - // Epochs { name: "Epoch", tree: [ @@ -266,7 +249,6 @@ export function createPartialOptions() { ], }, - // Classes { name: "Class", tree: [ @@ -279,20 +261,11 @@ export function createPartialOptions() { ...class_.map(createCohortFolderWithAdjusted), ], }, - - // UTXO Profitability bands - createUtxoProfitabilitySection({ - range: profitabilityRange, - profit: profitabilityProfit, - loss: profitabilityLoss, - }), ], }, - // Investing section createInvestingSection(), - // Frameworks section { name: "Frameworks", tree: [createCointimeSection()], @@ -300,14 +273,12 @@ export function createPartialOptions() { ], }, - // API documentation { name: "API", url: () => "/api", title: "API documentation", }, - // Project link { name: "Source", url: () => "https://bitcoinresearchkit.org", diff --git a/website/scripts/options/series.js b/website/scripts/options/series.js index 665cacd2e..029f6849f 100644 --- a/website/scripts/options/series.js +++ b/website/scripts/options/series.js @@ -17,11 +17,11 @@ export const ROLLING_WINDOWS = [ { key: "_1y", name: "1y", title: "Yearly", color: colors.time._1y }, ]; -/** @type {ReadonlyArray<{key: '_24h' | '_1w' | '_1m', name: string, color: Color}>} */ +/** @type {ReadonlyArray<{key: '_24h' | '_1w' | '_1m', name: string, title: string, color: Color}>} */ export const ROLLING_WINDOWS_TO_1M = [ - { key: "_24h", name: "24h", color: colors.time._24h }, - { key: "_1w", name: "1w", color: colors.time._1w }, - { key: "_1m", name: "1m", color: colors.time._1m }, + { key: "_24h", name: "24h", title: "Daily", color: colors.time._24h }, + { key: "_1w", name: "1w", title: "Weekly", color: colors.time._1w }, + { key: "_1m", name: "1m", title: "Monthly", color: colors.time._1m }, ]; /** @@ -604,7 +604,7 @@ export function distributionWindowsTree({ pattern, base, title, unit }) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: `${title} Distribution (${w.name})`, + title: `${title} Distribution (${w.title})`, bottom: [ ...(base ? [line({ series: base, name: "base", unit })] : []), ...fromStatsPattern({ @@ -755,15 +755,22 @@ export function percentRatioDots({ pattern, name, color, defaultActive }) { * @param {boolean} [args.defaultActive] * @returns {AnyFetchedSeriesBlueprint[]} */ -export function percentRatioBaseline({ pattern, name, defaultActive }) { +export function percentRatioBaseline({ pattern, name, color, defaultActive }) { return [ baseline({ series: pattern.percent, name, + color, defaultActive, unit: Unit.percentage, }), - baseline({ series: pattern.ratio, name, defaultActive, unit: Unit.ratio }), + baseline({ + series: pattern.ratio, + name, + color, + defaultActive, + unit: Unit.ratio, + }), ]; } @@ -798,7 +805,7 @@ export function rollingPercentRatioTree({ }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: `${title} ${w.name}`, + title: `${title} (${w.title})`, bottom: series({ pattern: windows[w.key], name: w.name }), })), ], @@ -834,7 +841,7 @@ export function deltaTree({ delta, title, unit, extract }) { }, ...ROLLING_WINDOWS.map((w) => ({ name: w.name, - title: `${title} Change ${w.name}`, + title: `${title} Change (${w.title})`, bottom: [ baseline({ series: extract(delta.absolute[w.key]),