diff --git a/Cargo.lock b/Cargo.lock index 515f9efc1..490ba538b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -784,9 +784,9 @@ checksum = "dda4398f387cc6395a3e93b3867cd9abda914c97a0b344d1eefb2e5c51785fca" [[package]] name = "cc" -version = "1.2.53" +version = "1.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932" +checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" dependencies = [ "find-msvc-tools", "jobserver", @@ -2386,9 +2386,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -2882,9 +2882,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index 2261c2f96..88aed410c 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -1458,44 +1458,6 @@ impl AaopoolPattern { } } -/// Pattern struct for repeated tree structure. -pub struct RelativePattern2 { - pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1, - pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1, - pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub supply_in_loss_rel_to_circulating_supply: MetricPattern1, - pub supply_in_loss_rel_to_own_supply: MetricPattern1, - pub supply_in_profit_rel_to_circulating_supply: MetricPattern1, - pub supply_in_profit_rel_to_own_supply: MetricPattern1, - pub supply_rel_to_circulating_supply: MetricPattern4, - pub unrealized_loss_rel_to_own_market_cap: MetricPattern1, - pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub unrealized_profit_rel_to_own_market_cap: MetricPattern1, - pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1, -} - -impl RelativePattern2 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")), - neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")), - net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")), - net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")), - supply_in_loss_rel_to_circulating_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_circulating_supply")), - supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")), - supply_in_profit_rel_to_circulating_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_circulating_supply")), - supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")), - supply_rel_to_circulating_supply: MetricPattern4::new(client.clone(), _m(&acc, "supply_rel_to_circulating_supply")), - unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")), - unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")), - unrealized_profit_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")), - unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct LookbackPattern { pub _10y: MetricPattern4, @@ -1570,42 +1532,6 @@ impl PeriodLumpSumStackPattern { } } -/// Pattern struct for repeated tree structure. -pub struct ClassAveragePricePattern { - pub _2015: MetricPattern4, - pub _2016: MetricPattern4, - pub _2017: MetricPattern4, - pub _2018: MetricPattern4, - pub _2019: MetricPattern4, - pub _2020: MetricPattern4, - pub _2021: MetricPattern4, - pub _2022: MetricPattern4, - pub _2023: MetricPattern4, - pub _2024: MetricPattern4, - pub _2025: MetricPattern4, - pub _2026: MetricPattern4, -} - -impl ClassAveragePricePattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - _2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_average_price")), - _2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_average_price")), - _2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_average_price")), - _2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_average_price")), - _2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_average_price")), - _2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_average_price")), - _2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_average_price")), - _2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_average_price")), - _2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_average_price")), - _2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_average_price")), - _2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_average_price")), - _2026: MetricPattern4::new(client.clone(), _m(&acc, "2026_average_price")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct PeriodAveragePricePattern { pub _10y: MetricPattern4, @@ -1642,6 +1568,42 @@ impl PeriodAveragePricePattern { } } +/// Pattern struct for repeated tree structure. +pub struct ClassAveragePricePattern { + pub _2015: MetricPattern4, + pub _2016: MetricPattern4, + pub _2017: MetricPattern4, + pub _2018: MetricPattern4, + pub _2019: MetricPattern4, + pub _2020: MetricPattern4, + pub _2021: MetricPattern4, + pub _2022: MetricPattern4, + pub _2023: MetricPattern4, + pub _2024: MetricPattern4, + pub _2025: MetricPattern4, + pub _2026: MetricPattern4, +} + +impl ClassAveragePricePattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + _2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_average_price")), + _2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_average_price")), + _2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_average_price")), + _2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_average_price")), + _2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_average_price")), + _2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_average_price")), + _2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_average_price")), + _2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_average_price")), + _2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_average_price")), + _2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_average_price")), + _2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_average_price")), + _2026: MetricPattern4::new(client.clone(), _m(&acc, "2026_average_price")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct BitcoinPattern { pub average: MetricPattern2, @@ -1710,6 +1672,38 @@ impl DollarsPattern { } } +/// Pattern struct for repeated tree structure. +pub struct RelativePattern2 { + pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1, + pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1, + pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub supply_in_loss_rel_to_own_supply: MetricPattern1, + pub supply_in_profit_rel_to_own_supply: MetricPattern1, + pub unrealized_loss_rel_to_own_market_cap: MetricPattern1, + pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub unrealized_profit_rel_to_own_market_cap: MetricPattern1, + pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1, +} + +impl RelativePattern2 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")), + neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")), + net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")), + net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")), + supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")), + supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")), + unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")), + unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")), + unrealized_profit_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")), + unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct RelativePattern { pub neg_unrealized_loss_rel_to_market_cap: MetricPattern1, @@ -1921,27 +1915,27 @@ impl PhaseDailyCentsPattern { } /// Pattern struct for repeated tree structure. -pub struct PeriodCagrPattern { - pub _10y: MetricPattern4, - pub _2y: MetricPattern4, - pub _3y: MetricPattern4, - pub _4y: MetricPattern4, - pub _5y: MetricPattern4, - pub _6y: MetricPattern4, - pub _8y: MetricPattern4, +pub struct _10yTo12yPattern { + pub activity: ActivityPattern2, + pub cost_basis: CostBasisPattern2, + pub outputs: OutputsPattern, + pub realized: RealizedPattern2, + pub relative: RelativePattern2, + pub supply: SupplyPattern2, + pub unrealized: UnrealizedPattern, } -impl PeriodCagrPattern { +impl _10yTo12yPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - _10y: MetricPattern4::new(client.clone(), _p("10y", &acc)), - _2y: MetricPattern4::new(client.clone(), _p("2y", &acc)), - _3y: MetricPattern4::new(client.clone(), _p("3y", &acc)), - _4y: MetricPattern4::new(client.clone(), _p("4y", &acc)), - _5y: MetricPattern4::new(client.clone(), _p("5y", &acc)), - _6y: MetricPattern4::new(client.clone(), _p("6y", &acc)), - _8y: MetricPattern4::new(client.clone(), _p("8y", &acc)), + activity: ActivityPattern2::new(client.clone(), acc.clone()), + cost_basis: CostBasisPattern2::new(client.clone(), acc.clone()), + outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), + realized: RealizedPattern2::new(client.clone(), acc.clone()), + relative: RelativePattern2::new(client.clone(), acc.clone()), + supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), + unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), } } } @@ -1991,7 +1985,7 @@ impl _0satsPattern2 { cost_basis: CostBasisPattern::new(client.clone(), acc.clone()), outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), realized: RealizedPattern::new(client.clone(), acc.clone()), - relative: RelativePattern4::new(client.clone(), _m(&acc, "supply")), + relative: RelativePattern4::new(client.clone(), _m(&acc, "supply_in")), supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), } @@ -1999,27 +1993,27 @@ impl _0satsPattern2 { } /// Pattern struct for repeated tree structure. -pub struct _0Pattern { - pub activity: ActivityPattern2, - pub cost_basis: CostBasisPattern, - pub outputs: OutputsPattern, - pub realized: RealizedPattern, - pub relative: RelativePattern, - pub supply: SupplyPattern2, - pub unrealized: UnrealizedPattern, +pub struct PeriodCagrPattern { + pub _10y: MetricPattern4, + pub _2y: MetricPattern4, + pub _3y: MetricPattern4, + pub _4y: MetricPattern4, + pub _5y: MetricPattern4, + pub _6y: MetricPattern4, + pub _8y: MetricPattern4, } -impl _0Pattern { +impl PeriodCagrPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - activity: ActivityPattern2::new(client.clone(), acc.clone()), - cost_basis: CostBasisPattern::new(client.clone(), acc.clone()), - outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), - realized: RealizedPattern::new(client.clone(), acc.clone()), - relative: RelativePattern::new(client.clone(), acc.clone()), - supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), - unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), + _10y: MetricPattern4::new(client.clone(), _p("10y", &acc)), + _2y: MetricPattern4::new(client.clone(), _p("2y", &acc)), + _3y: MetricPattern4::new(client.clone(), _p("3y", &acc)), + _4y: MetricPattern4::new(client.clone(), _p("4y", &acc)), + _5y: MetricPattern4::new(client.clone(), _p("5y", &acc)), + _6y: MetricPattern4::new(client.clone(), _p("6y", &acc)), + _8y: MetricPattern4::new(client.clone(), _p("8y", &acc)), } } } @@ -2051,53 +2045,31 @@ impl _10yPattern { } /// Pattern struct for repeated tree structure. -pub struct _10yTo12yPattern { +pub struct _100btcPattern { pub activity: ActivityPattern2, - pub cost_basis: CostBasisPattern2, + pub cost_basis: CostBasisPattern, pub outputs: OutputsPattern, - pub realized: RealizedPattern2, - pub relative: RelativePattern2, + pub realized: RealizedPattern, + pub relative: RelativePattern, pub supply: SupplyPattern2, pub unrealized: UnrealizedPattern, } -impl _10yTo12yPattern { +impl _100btcPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { activity: ActivityPattern2::new(client.clone(), acc.clone()), - cost_basis: CostBasisPattern2::new(client.clone(), acc.clone()), + cost_basis: CostBasisPattern::new(client.clone(), acc.clone()), outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), - realized: RealizedPattern2::new(client.clone(), acc.clone()), - relative: RelativePattern2::new(client.clone(), acc.clone()), + realized: RealizedPattern::new(client.clone(), acc.clone()), + relative: RelativePattern::new(client.clone(), acc.clone()), supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), } } } -/// Pattern struct for repeated tree structure. -pub struct RelativePattern4 { - pub supply_in_loss_rel_to_circulating_supply: MetricPattern1, - pub supply_in_loss_rel_to_own_supply: MetricPattern1, - pub supply_in_profit_rel_to_circulating_supply: MetricPattern1, - pub supply_in_profit_rel_to_own_supply: MetricPattern1, - pub supply_rel_to_circulating_supply: MetricPattern4, -} - -impl RelativePattern4 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - supply_in_loss_rel_to_circulating_supply: MetricPattern1::new(client.clone(), _m(&acc, "in_loss_rel_to_circulating_supply")), - supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "in_loss_rel_to_own_supply")), - supply_in_profit_rel_to_circulating_supply: MetricPattern1::new(client.clone(), _m(&acc, "in_profit_rel_to_circulating_supply")), - supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "in_profit_rel_to_own_supply")), - supply_rel_to_circulating_supply: MetricPattern4::new(client.clone(), _m(&acc, "rel_to_circulating_supply")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct ActivityPattern2 { pub coinblocks_destroyed: BlockCountPattern, @@ -2176,6 +2148,24 @@ impl CoinbasePattern { } } +/// Pattern struct for repeated tree structure. +pub struct SegwitAdoptionPattern { + pub base: MetricPattern11, + pub cumulative: MetricPattern2, + pub sum: MetricPattern2, +} + +impl SegwitAdoptionPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + base: MetricPattern11::new(client.clone(), acc.clone()), + cumulative: MetricPattern2::new(client.clone(), _m(&acc, "cumulative")), + sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct CostBasisPattern2 { pub max: MetricPattern1, @@ -2230,24 +2220,6 @@ impl _2015Pattern { } } -/// Pattern struct for repeated tree structure. -pub struct SegwitAdoptionPattern { - pub base: MetricPattern11, - pub cumulative: MetricPattern2, - pub sum: MetricPattern2, -} - -impl SegwitAdoptionPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - base: MetricPattern11::new(client.clone(), acc.clone()), - cumulative: MetricPattern2::new(client.clone(), _m(&acc, "cumulative")), - sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct CoinbasePattern2 { pub bitcoin: BlockCountPattern, @@ -2266,38 +2238,6 @@ impl CoinbasePattern2 { } } -/// Pattern struct for repeated tree structure. -pub struct SupplyPattern2 { - pub halved: ActiveSupplyPattern, - pub total: ActiveSupplyPattern, -} - -impl SupplyPattern2 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - halved: ActiveSupplyPattern::new(client.clone(), _m(&acc, "halved")), - total: ActiveSupplyPattern::new(client.clone(), acc.clone()), - } - } -} - -/// Pattern struct for repeated tree structure. -pub struct CostBasisPattern { - pub max: MetricPattern1, - pub min: MetricPattern1, -} - -impl CostBasisPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - max: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")), - min: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct _1dReturns1mSdPattern { pub sd: MetricPattern4, @@ -2315,33 +2255,49 @@ impl _1dReturns1mSdPattern { } /// Pattern struct for repeated tree structure. -pub struct SatsPattern { - pub ohlc: MetricPattern1, - pub split: SplitPattern2, +pub struct CostBasisPattern { + pub max: MetricPattern1, + pub min: MetricPattern1, } -impl SatsPattern { +impl CostBasisPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - ohlc: MetricPattern1::new(client.clone(), _m(&acc, "ohlc_sats")), - split: SplitPattern2::new(client.clone(), _m(&acc, "sats")), + max: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")), + min: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")), } } } /// Pattern struct for repeated tree structure. -pub struct BlockCountPattern { - pub cumulative: MetricPattern1, - pub sum: MetricPattern1, +pub struct SupplyPattern2 { + pub halved: ActiveSupplyPattern, + pub total: ActiveSupplyPattern, } -impl BlockCountPattern { +impl SupplyPattern2 { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), - sum: MetricPattern1::new(client.clone(), acc.clone()), + halved: ActiveSupplyPattern::new(client.clone(), _m(&acc, "halved")), + total: ActiveSupplyPattern::new(client.clone(), acc.clone()), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct RelativePattern4 { + pub supply_in_loss_rel_to_own_supply: MetricPattern1, + pub supply_in_profit_rel_to_own_supply: MetricPattern1, +} + +impl RelativePattern4 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "loss_rel_to_own_supply")), + supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "profit_rel_to_own_supply")), } } } @@ -2362,6 +2318,38 @@ impl BitcoinPattern2 { } } +/// Pattern struct for repeated tree structure. +pub struct SatsPattern { + pub ohlc: MetricPattern1, + pub split: SplitPattern2, +} + +impl SatsPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + ohlc: MetricPattern1::new(client.clone(), _m(&acc, "ohlc")), + split: SplitPattern2::new(client.clone(), acc.clone()), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct BlockCountPattern { + pub cumulative: MetricPattern1, + pub sum: MetricPattern1, +} + +impl BlockCountPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), + sum: MetricPattern1::new(client.clone(), acc.clone()), + } + } +} + /// Pattern struct for repeated tree structure. pub struct OutputsPattern { pub utxo_count: MetricPattern1, @@ -3321,95 +3309,95 @@ impl MetricsTree_Distribution_UtxoCohorts_AmountRange { /// Metrics tree node. pub struct MetricsTree_Distribution_UtxoCohorts_Epoch { - pub _0: _0Pattern, - pub _1: _0Pattern, - pub _2: _0Pattern, - pub _3: _0Pattern, - pub _4: _0Pattern, + pub _0: _0satsPattern2, + pub _1: _0satsPattern2, + pub _2: _0satsPattern2, + pub _3: _0satsPattern2, + pub _4: _0satsPattern2, } impl MetricsTree_Distribution_UtxoCohorts_Epoch { pub fn new(client: Arc, base_path: String) -> Self { Self { - _0: _0Pattern::new(client.clone(), "epoch_0".to_string()), - _1: _0Pattern::new(client.clone(), "epoch_1".to_string()), - _2: _0Pattern::new(client.clone(), "epoch_2".to_string()), - _3: _0Pattern::new(client.clone(), "epoch_3".to_string()), - _4: _0Pattern::new(client.clone(), "epoch_4".to_string()), + _0: _0satsPattern2::new(client.clone(), "epoch_0".to_string()), + _1: _0satsPattern2::new(client.clone(), "epoch_1".to_string()), + _2: _0satsPattern2::new(client.clone(), "epoch_2".to_string()), + _3: _0satsPattern2::new(client.clone(), "epoch_3".to_string()), + _4: _0satsPattern2::new(client.clone(), "epoch_4".to_string()), } } } /// Metrics tree node. pub struct MetricsTree_Distribution_UtxoCohorts_GeAmount { - pub _100btc: _0Pattern, - pub _100k_sats: _0Pattern, - pub _100sats: _0Pattern, - pub _10btc: _0Pattern, - pub _10k_btc: _0Pattern, - pub _10k_sats: _0Pattern, - pub _10m_sats: _0Pattern, - pub _10sats: _0Pattern, - pub _1btc: _0Pattern, - pub _1k_btc: _0Pattern, - pub _1k_sats: _0Pattern, - pub _1m_sats: _0Pattern, - pub _1sat: _0Pattern, + pub _100btc: _100btcPattern, + pub _100k_sats: _100btcPattern, + pub _100sats: _100btcPattern, + pub _10btc: _100btcPattern, + pub _10k_btc: _100btcPattern, + pub _10k_sats: _100btcPattern, + pub _10m_sats: _100btcPattern, + pub _10sats: _100btcPattern, + pub _1btc: _100btcPattern, + pub _1k_btc: _100btcPattern, + pub _1k_sats: _100btcPattern, + pub _1m_sats: _100btcPattern, + pub _1sat: _100btcPattern, } impl MetricsTree_Distribution_UtxoCohorts_GeAmount { pub fn new(client: Arc, base_path: String) -> Self { Self { - _100btc: _0Pattern::new(client.clone(), "utxos_above_100btc".to_string()), - _100k_sats: _0Pattern::new(client.clone(), "utxos_above_100k_sats".to_string()), - _100sats: _0Pattern::new(client.clone(), "utxos_above_100sats".to_string()), - _10btc: _0Pattern::new(client.clone(), "utxos_above_10btc".to_string()), - _10k_btc: _0Pattern::new(client.clone(), "utxos_above_10k_btc".to_string()), - _10k_sats: _0Pattern::new(client.clone(), "utxos_above_10k_sats".to_string()), - _10m_sats: _0Pattern::new(client.clone(), "utxos_above_10m_sats".to_string()), - _10sats: _0Pattern::new(client.clone(), "utxos_above_10sats".to_string()), - _1btc: _0Pattern::new(client.clone(), "utxos_above_1btc".to_string()), - _1k_btc: _0Pattern::new(client.clone(), "utxos_above_1k_btc".to_string()), - _1k_sats: _0Pattern::new(client.clone(), "utxos_above_1k_sats".to_string()), - _1m_sats: _0Pattern::new(client.clone(), "utxos_above_1m_sats".to_string()), - _1sat: _0Pattern::new(client.clone(), "utxos_above_1sat".to_string()), + _100btc: _100btcPattern::new(client.clone(), "utxos_above_100btc".to_string()), + _100k_sats: _100btcPattern::new(client.clone(), "utxos_above_100k_sats".to_string()), + _100sats: _100btcPattern::new(client.clone(), "utxos_above_100sats".to_string()), + _10btc: _100btcPattern::new(client.clone(), "utxos_above_10btc".to_string()), + _10k_btc: _100btcPattern::new(client.clone(), "utxos_above_10k_btc".to_string()), + _10k_sats: _100btcPattern::new(client.clone(), "utxos_above_10k_sats".to_string()), + _10m_sats: _100btcPattern::new(client.clone(), "utxos_above_10m_sats".to_string()), + _10sats: _100btcPattern::new(client.clone(), "utxos_above_10sats".to_string()), + _1btc: _100btcPattern::new(client.clone(), "utxos_above_1btc".to_string()), + _1k_btc: _100btcPattern::new(client.clone(), "utxos_above_1k_btc".to_string()), + _1k_sats: _100btcPattern::new(client.clone(), "utxos_above_1k_sats".to_string()), + _1m_sats: _100btcPattern::new(client.clone(), "utxos_above_1m_sats".to_string()), + _1sat: _100btcPattern::new(client.clone(), "utxos_above_1sat".to_string()), } } } /// Metrics tree node. pub struct MetricsTree_Distribution_UtxoCohorts_LtAmount { - pub _100btc: _0Pattern, - pub _100k_btc: _0Pattern, - pub _100k_sats: _0Pattern, - pub _100sats: _0Pattern, - pub _10btc: _0Pattern, - pub _10k_btc: _0Pattern, - pub _10k_sats: _0Pattern, - pub _10m_sats: _0Pattern, - pub _10sats: _0Pattern, - pub _1btc: _0Pattern, - pub _1k_btc: _0Pattern, - pub _1k_sats: _0Pattern, - pub _1m_sats: _0Pattern, + pub _100btc: _100btcPattern, + pub _100k_btc: _100btcPattern, + pub _100k_sats: _100btcPattern, + pub _100sats: _100btcPattern, + pub _10btc: _100btcPattern, + pub _10k_btc: _100btcPattern, + pub _10k_sats: _100btcPattern, + pub _10m_sats: _100btcPattern, + pub _10sats: _100btcPattern, + pub _1btc: _100btcPattern, + pub _1k_btc: _100btcPattern, + pub _1k_sats: _100btcPattern, + pub _1m_sats: _100btcPattern, } impl MetricsTree_Distribution_UtxoCohorts_LtAmount { pub fn new(client: Arc, base_path: String) -> Self { Self { - _100btc: _0Pattern::new(client.clone(), "utxos_under_100btc".to_string()), - _100k_btc: _0Pattern::new(client.clone(), "utxos_under_100k_btc".to_string()), - _100k_sats: _0Pattern::new(client.clone(), "utxos_under_100k_sats".to_string()), - _100sats: _0Pattern::new(client.clone(), "utxos_under_100sats".to_string()), - _10btc: _0Pattern::new(client.clone(), "utxos_under_10btc".to_string()), - _10k_btc: _0Pattern::new(client.clone(), "utxos_under_10k_btc".to_string()), - _10k_sats: _0Pattern::new(client.clone(), "utxos_under_10k_sats".to_string()), - _10m_sats: _0Pattern::new(client.clone(), "utxos_under_10m_sats".to_string()), - _10sats: _0Pattern::new(client.clone(), "utxos_under_10sats".to_string()), - _1btc: _0Pattern::new(client.clone(), "utxos_under_1btc".to_string()), - _1k_btc: _0Pattern::new(client.clone(), "utxos_under_1k_btc".to_string()), - _1k_sats: _0Pattern::new(client.clone(), "utxos_under_1k_sats".to_string()), - _1m_sats: _0Pattern::new(client.clone(), "utxos_under_1m_sats".to_string()), + _100btc: _100btcPattern::new(client.clone(), "utxos_under_100btc".to_string()), + _100k_btc: _100btcPattern::new(client.clone(), "utxos_under_100k_btc".to_string()), + _100k_sats: _100btcPattern::new(client.clone(), "utxos_under_100k_sats".to_string()), + _100sats: _100btcPattern::new(client.clone(), "utxos_under_100sats".to_string()), + _10btc: _100btcPattern::new(client.clone(), "utxos_under_10btc".to_string()), + _10k_btc: _100btcPattern::new(client.clone(), "utxos_under_10k_btc".to_string()), + _10k_sats: _100btcPattern::new(client.clone(), "utxos_under_10k_sats".to_string()), + _10m_sats: _100btcPattern::new(client.clone(), "utxos_under_10m_sats".to_string()), + _10sats: _100btcPattern::new(client.clone(), "utxos_under_10sats".to_string()), + _1btc: _100btcPattern::new(client.clone(), "utxos_under_1btc".to_string()), + _1k_btc: _100btcPattern::new(client.clone(), "utxos_under_1k_btc".to_string()), + _1k_sats: _100btcPattern::new(client.clone(), "utxos_under_1k_sats".to_string()), + _1m_sats: _100btcPattern::new(client.clone(), "utxos_under_1m_sats".to_string()), } } } @@ -3463,47 +3451,47 @@ impl MetricsTree_Distribution_UtxoCohorts_MaxAge { /// Metrics tree node. pub struct MetricsTree_Distribution_UtxoCohorts_MinAge { - pub _10y: _0Pattern, - pub _12y: _0Pattern, - pub _1d: _0Pattern, - pub _1m: _0Pattern, - pub _1w: _0Pattern, - pub _1y: _0Pattern, - pub _2m: _0Pattern, - pub _2y: _0Pattern, - pub _3m: _0Pattern, - pub _3y: _0Pattern, - pub _4m: _0Pattern, - pub _4y: _0Pattern, - pub _5m: _0Pattern, - pub _5y: _0Pattern, - pub _6m: _0Pattern, - pub _6y: _0Pattern, - pub _7y: _0Pattern, - pub _8y: _0Pattern, + pub _10y: _100btcPattern, + pub _12y: _100btcPattern, + pub _1d: _100btcPattern, + pub _1m: _100btcPattern, + pub _1w: _100btcPattern, + pub _1y: _100btcPattern, + pub _2m: _100btcPattern, + pub _2y: _100btcPattern, + pub _3m: _100btcPattern, + pub _3y: _100btcPattern, + pub _4m: _100btcPattern, + pub _4y: _100btcPattern, + pub _5m: _100btcPattern, + pub _5y: _100btcPattern, + pub _6m: _100btcPattern, + pub _6y: _100btcPattern, + pub _7y: _100btcPattern, + pub _8y: _100btcPattern, } impl MetricsTree_Distribution_UtxoCohorts_MinAge { pub fn new(client: Arc, base_path: String) -> Self { Self { - _10y: _0Pattern::new(client.clone(), "utxos_at_least_10y_old".to_string()), - _12y: _0Pattern::new(client.clone(), "utxos_at_least_12y_old".to_string()), - _1d: _0Pattern::new(client.clone(), "utxos_at_least_1d_old".to_string()), - _1m: _0Pattern::new(client.clone(), "utxos_at_least_1m_old".to_string()), - _1w: _0Pattern::new(client.clone(), "utxos_at_least_1w_old".to_string()), - _1y: _0Pattern::new(client.clone(), "utxos_at_least_1y_old".to_string()), - _2m: _0Pattern::new(client.clone(), "utxos_at_least_2m_old".to_string()), - _2y: _0Pattern::new(client.clone(), "utxos_at_least_2y_old".to_string()), - _3m: _0Pattern::new(client.clone(), "utxos_at_least_3m_old".to_string()), - _3y: _0Pattern::new(client.clone(), "utxos_at_least_3y_old".to_string()), - _4m: _0Pattern::new(client.clone(), "utxos_at_least_4m_old".to_string()), - _4y: _0Pattern::new(client.clone(), "utxos_at_least_4y_old".to_string()), - _5m: _0Pattern::new(client.clone(), "utxos_at_least_5m_old".to_string()), - _5y: _0Pattern::new(client.clone(), "utxos_at_least_5y_old".to_string()), - _6m: _0Pattern::new(client.clone(), "utxos_at_least_6m_old".to_string()), - _6y: _0Pattern::new(client.clone(), "utxos_at_least_6y_old".to_string()), - _7y: _0Pattern::new(client.clone(), "utxos_at_least_7y_old".to_string()), - _8y: _0Pattern::new(client.clone(), "utxos_at_least_8y_old".to_string()), + _10y: _100btcPattern::new(client.clone(), "utxos_at_least_10y_old".to_string()), + _12y: _100btcPattern::new(client.clone(), "utxos_at_least_12y_old".to_string()), + _1d: _100btcPattern::new(client.clone(), "utxos_at_least_1d_old".to_string()), + _1m: _100btcPattern::new(client.clone(), "utxos_at_least_1m_old".to_string()), + _1w: _100btcPattern::new(client.clone(), "utxos_at_least_1w_old".to_string()), + _1y: _100btcPattern::new(client.clone(), "utxos_at_least_1y_old".to_string()), + _2m: _100btcPattern::new(client.clone(), "utxos_at_least_2m_old".to_string()), + _2y: _100btcPattern::new(client.clone(), "utxos_at_least_2y_old".to_string()), + _3m: _100btcPattern::new(client.clone(), "utxos_at_least_3m_old".to_string()), + _3y: _100btcPattern::new(client.clone(), "utxos_at_least_3y_old".to_string()), + _4m: _100btcPattern::new(client.clone(), "utxos_at_least_4m_old".to_string()), + _4y: _100btcPattern::new(client.clone(), "utxos_at_least_4y_old".to_string()), + _5m: _100btcPattern::new(client.clone(), "utxos_at_least_5m_old".to_string()), + _5y: _100btcPattern::new(client.clone(), "utxos_at_least_5y_old".to_string()), + _6m: _100btcPattern::new(client.clone(), "utxos_at_least_6m_old".to_string()), + _6y: _100btcPattern::new(client.clone(), "utxos_at_least_6y_old".to_string()), + _7y: _100btcPattern::new(client.clone(), "utxos_at_least_7y_old".to_string()), + _8y: _100btcPattern::new(client.clone(), "utxos_at_least_8y_old".to_string()), } } } @@ -3575,80 +3563,80 @@ impl MetricsTree_Distribution_UtxoCohorts_Term_Short { /// Metrics tree node. pub struct MetricsTree_Distribution_UtxoCohorts_Type { - pub empty: _0Pattern, - pub p2a: _0Pattern, - pub p2ms: _0Pattern, - pub p2pk33: _0Pattern, - pub p2pk65: _0Pattern, - pub p2pkh: _0Pattern, - pub p2sh: _0Pattern, - pub p2tr: _0Pattern, - pub p2wpkh: _0Pattern, - pub p2wsh: _0Pattern, - pub unknown: _0Pattern, + pub empty: _0satsPattern2, + pub p2a: _0satsPattern2, + pub p2ms: _0satsPattern2, + pub p2pk33: _0satsPattern2, + pub p2pk65: _0satsPattern2, + pub p2pkh: _0satsPattern2, + pub p2sh: _0satsPattern2, + pub p2tr: _0satsPattern2, + pub p2wpkh: _0satsPattern2, + pub p2wsh: _0satsPattern2, + pub unknown: _0satsPattern2, } impl MetricsTree_Distribution_UtxoCohorts_Type { pub fn new(client: Arc, base_path: String) -> Self { Self { - empty: _0Pattern::new(client.clone(), "empty_outputs".to_string()), - p2a: _0Pattern::new(client.clone(), "p2a".to_string()), - p2ms: _0Pattern::new(client.clone(), "p2ms".to_string()), - p2pk33: _0Pattern::new(client.clone(), "p2pk33".to_string()), - p2pk65: _0Pattern::new(client.clone(), "p2pk65".to_string()), - p2pkh: _0Pattern::new(client.clone(), "p2pkh".to_string()), - p2sh: _0Pattern::new(client.clone(), "p2sh".to_string()), - p2tr: _0Pattern::new(client.clone(), "p2tr".to_string()), - p2wpkh: _0Pattern::new(client.clone(), "p2wpkh".to_string()), - p2wsh: _0Pattern::new(client.clone(), "p2wsh".to_string()), - unknown: _0Pattern::new(client.clone(), "unknown_outputs".to_string()), + empty: _0satsPattern2::new(client.clone(), "empty_outputs".to_string()), + p2a: _0satsPattern2::new(client.clone(), "p2a".to_string()), + p2ms: _0satsPattern2::new(client.clone(), "p2ms".to_string()), + p2pk33: _0satsPattern2::new(client.clone(), "p2pk33".to_string()), + p2pk65: _0satsPattern2::new(client.clone(), "p2pk65".to_string()), + p2pkh: _0satsPattern2::new(client.clone(), "p2pkh".to_string()), + p2sh: _0satsPattern2::new(client.clone(), "p2sh".to_string()), + p2tr: _0satsPattern2::new(client.clone(), "p2tr".to_string()), + p2wpkh: _0satsPattern2::new(client.clone(), "p2wpkh".to_string()), + p2wsh: _0satsPattern2::new(client.clone(), "p2wsh".to_string()), + unknown: _0satsPattern2::new(client.clone(), "unknown_outputs".to_string()), } } } /// Metrics tree node. pub struct MetricsTree_Distribution_UtxoCohorts_Year { - pub _2009: _0Pattern, - pub _2010: _0Pattern, - pub _2011: _0Pattern, - pub _2012: _0Pattern, - pub _2013: _0Pattern, - pub _2014: _0Pattern, - pub _2015: _0Pattern, - pub _2016: _0Pattern, - pub _2017: _0Pattern, - pub _2018: _0Pattern, - pub _2019: _0Pattern, - pub _2020: _0Pattern, - pub _2021: _0Pattern, - pub _2022: _0Pattern, - pub _2023: _0Pattern, - pub _2024: _0Pattern, - pub _2025: _0Pattern, - pub _2026: _0Pattern, + pub _2009: _0satsPattern2, + pub _2010: _0satsPattern2, + pub _2011: _0satsPattern2, + pub _2012: _0satsPattern2, + pub _2013: _0satsPattern2, + pub _2014: _0satsPattern2, + pub _2015: _0satsPattern2, + pub _2016: _0satsPattern2, + pub _2017: _0satsPattern2, + pub _2018: _0satsPattern2, + pub _2019: _0satsPattern2, + pub _2020: _0satsPattern2, + pub _2021: _0satsPattern2, + pub _2022: _0satsPattern2, + pub _2023: _0satsPattern2, + pub _2024: _0satsPattern2, + pub _2025: _0satsPattern2, + pub _2026: _0satsPattern2, } impl MetricsTree_Distribution_UtxoCohorts_Year { pub fn new(client: Arc, base_path: String) -> Self { Self { - _2009: _0Pattern::new(client.clone(), "year_2009".to_string()), - _2010: _0Pattern::new(client.clone(), "year_2010".to_string()), - _2011: _0Pattern::new(client.clone(), "year_2011".to_string()), - _2012: _0Pattern::new(client.clone(), "year_2012".to_string()), - _2013: _0Pattern::new(client.clone(), "year_2013".to_string()), - _2014: _0Pattern::new(client.clone(), "year_2014".to_string()), - _2015: _0Pattern::new(client.clone(), "year_2015".to_string()), - _2016: _0Pattern::new(client.clone(), "year_2016".to_string()), - _2017: _0Pattern::new(client.clone(), "year_2017".to_string()), - _2018: _0Pattern::new(client.clone(), "year_2018".to_string()), - _2019: _0Pattern::new(client.clone(), "year_2019".to_string()), - _2020: _0Pattern::new(client.clone(), "year_2020".to_string()), - _2021: _0Pattern::new(client.clone(), "year_2021".to_string()), - _2022: _0Pattern::new(client.clone(), "year_2022".to_string()), - _2023: _0Pattern::new(client.clone(), "year_2023".to_string()), - _2024: _0Pattern::new(client.clone(), "year_2024".to_string()), - _2025: _0Pattern::new(client.clone(), "year_2025".to_string()), - _2026: _0Pattern::new(client.clone(), "year_2026".to_string()), + _2009: _0satsPattern2::new(client.clone(), "year_2009".to_string()), + _2010: _0satsPattern2::new(client.clone(), "year_2010".to_string()), + _2011: _0satsPattern2::new(client.clone(), "year_2011".to_string()), + _2012: _0satsPattern2::new(client.clone(), "year_2012".to_string()), + _2013: _0satsPattern2::new(client.clone(), "year_2013".to_string()), + _2014: _0satsPattern2::new(client.clone(), "year_2014".to_string()), + _2015: _0satsPattern2::new(client.clone(), "year_2015".to_string()), + _2016: _0satsPattern2::new(client.clone(), "year_2016".to_string()), + _2017: _0satsPattern2::new(client.clone(), "year_2017".to_string()), + _2018: _0satsPattern2::new(client.clone(), "year_2018".to_string()), + _2019: _0satsPattern2::new(client.clone(), "year_2019".to_string()), + _2020: _0satsPattern2::new(client.clone(), "year_2020".to_string()), + _2021: _0satsPattern2::new(client.clone(), "year_2021".to_string()), + _2022: _0satsPattern2::new(client.clone(), "year_2022".to_string()), + _2023: _0satsPattern2::new(client.clone(), "year_2023".to_string()), + _2024: _0satsPattern2::new(client.clone(), "year_2024".to_string()), + _2025: _0satsPattern2::new(client.clone(), "year_2025".to_string()), + _2026: _0satsPattern2::new(client.clone(), "year_2026".to_string()), } } } @@ -4983,8 +4971,8 @@ impl MetricsTree_Positions { pub struct MetricsTree_Price { pub cents: MetricsTree_Price_Cents, pub oracle: MetricsTree_Price_Oracle, - pub sats: SatsPattern, - pub usd: MetricsTree_Price_Usd, + pub sats: MetricsTree_Price_Sats, + pub usd: SatsPattern, } impl MetricsTree_Price { @@ -4992,8 +4980,8 @@ impl MetricsTree_Price { Self { cents: MetricsTree_Price_Cents::new(client.clone(), format!("{base_path}_cents")), oracle: MetricsTree_Price_Oracle::new(client.clone(), format!("{base_path}_oracle")), - sats: SatsPattern::new(client.clone(), "price".to_string()), - usd: MetricsTree_Price_Usd::new(client.clone(), format!("{base_path}_usd")), + sats: MetricsTree_Price_Sats::new(client.clone(), format!("{base_path}_sats")), + usd: SatsPattern::new(client.clone(), "price".to_string()), } } } @@ -5104,16 +5092,16 @@ impl MetricsTree_Price_Oracle { } /// Metrics tree node. -pub struct MetricsTree_Price_Usd { - pub ohlc: MetricPattern1, - pub split: SplitPattern2, +pub struct MetricsTree_Price_Sats { + pub ohlc: MetricPattern1, + pub split: SplitPattern2, } -impl MetricsTree_Price_Usd { +impl MetricsTree_Price_Sats { pub fn new(client: Arc, base_path: String) -> Self { Self { - ohlc: MetricPattern1::new(client.clone(), "price_ohlc".to_string()), - split: SplitPattern2::new(client.clone(), "price".to_string()), + ohlc: MetricPattern1::new(client.clone(), "price_ohlc_sats".to_string()), + split: SplitPattern2::new(client.clone(), "price_sats".to_string()), } } } diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs index d9da8f188..71bcf4e79 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs @@ -38,8 +38,8 @@ impl UTXOCohorts { ) -> Result { let v = version + VERSION; - // Phase 1: Import base cohorts for overlapping computations (age_range, amount_range). - // These are the source cohorts and must be imported before "all" to provide up_to_1h. + // Phase 1: Import base cohorts that don't need adjusted (age_range, amount_range, etc.) + // These are the source cohorts for overlapping computations. let base = |f: Filter, name: &'static str| { UTXOCohortVecs::forced_import( db, @@ -57,6 +57,9 @@ impl UTXOCohorts { let age_range = ByAgeRange::try_new(&base)?; let amount_range = ByAmountRange::try_new(&base)?; + let epoch = ByEpoch::try_new(&base)?; + let year = ByYear::try_new(&base)?; + let type_ = BySpendableType::try_new(&base)?; // Get up_to_1h realized for adjusted computation (cohort - up_to_1h) let up_to_1h_realized = age_range.up_to_1h.metrics.realized.as_ref(); @@ -77,27 +80,7 @@ impl UTXOCohorts { let all_supply = Some(&all.metrics.supply); - // Phase 3: Import cohorts that need all_supply but not adjusted (epoch, year, type) - let base_with_all_supply = |f: Filter, name: &'static str| { - UTXOCohortVecs::forced_import( - db, - f, - name, - v, - indexes, - price, - states_path, - StateLevel::Full, - all_supply, - None, - ) - }; - - let epoch = ByEpoch::try_new(&base_with_all_supply)?; - let year = ByYear::try_new(&base_with_all_supply)?; - let type_ = BySpendableType::try_new(&base_with_all_supply)?; - - // Phase 4: Import cohorts that need all_supply and up_to_1h for adjusted + // Phase 3: Import cohorts that need adjusted and/or all_supply let price_only_adjusted = |f: Filter, name: &'static str| { UTXOCohortVecs::forced_import( db, @@ -132,17 +115,7 @@ impl UTXOCohorts { let max_age = ByMaxAge::try_new(&none_adjusted)?; - // Phase 5: Add rel_to_circulating metrics to base cohorts now that up_to_1h_realized is no longer borrowed - let mut age_range = age_range; - let mut amount_range = amount_range; - for (vecs, name) in age_range.iter_mut().zip(ByAgeRange::names().iter()) { - vecs.add_rel_to_circulating(name.id, v, all_supply.unwrap()); - } - for (vecs, name) in amount_range.iter_mut().zip(ByAmountRange::names().iter()) { - vecs.add_rel_to_circulating(name.id, v, all_supply.unwrap()); - } - - // Phase 6: Import remaining cohorts (no adjusted needed) + // Phase 4: Import remaining cohorts (no adjusted needed) let none = |f: Filter, name: &'static str| { UTXOCohortVecs::forced_import( db, diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs b/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs index 69d3445b7..ee84c6777 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs @@ -80,19 +80,6 @@ impl UTXOCohortVecs { }) } - /// Add relative-to-circulating-supply metrics in a second step. - /// Called after the "all" cohort is available. - pub fn add_rel_to_circulating( - &mut self, - name: &str, - version: Version, - all_supply: &SupplyMetrics, - ) { - let full_name = CohortContext::Utxo.full_name(self.filter(), name); - self.metrics - .add_rel_to_circulating(&full_name, version, all_supply); - } - /// Get the starting height when state was imported. pub fn state_starting_height(&self) -> Option { self.state_starting_height diff --git a/crates/brk_computer/src/distribution/metrics/mod.rs b/crates/brk_computer/src/distribution/metrics/mod.rs index e24cff2e4..0ce788c3f 100644 --- a/crates/brk_computer/src/distribution/metrics/mod.rs +++ b/crates/brk_computer/src/distribution/metrics/mod.rs @@ -333,28 +333,6 @@ impl CohortMetrics { Ok(()) } - /// Add relative-to-circulating-supply metrics in a second step. - /// Called after the "all" cohort is available. - pub fn add_rel_to_circulating( - &mut self, - full_name: &str, - version: Version, - all_supply: &SupplyMetrics, - ) { - if let (Some(relative), Some(unrealized)) = - (self.relative.as_mut(), self.unrealized.as_ref()) - { - relative.add_rel_to_circulating( - &self.filter, - full_name, - version, - unrealized, - &self.supply, - all_supply, - ); - } - } - /// Second phase of computed metrics (ratios, relative values). #[allow(clippy::too_many_arguments)] pub fn compute_rest_part2( diff --git a/crates/brk_computer/src/distribution/metrics/relative.rs b/crates/brk_computer/src/distribution/metrics/relative.rs index ea4974408..b624b614b 100644 --- a/crates/brk_computer/src/distribution/metrics/relative.rs +++ b/crates/brk_computer/src/distribution/metrics/relative.rs @@ -1,4 +1,3 @@ -use brk_cohort::Filter; use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Dollars, Sats, StoredF32, StoredF64, Version}; @@ -353,95 +352,4 @@ impl RelativeMetrics { }), }) } - - /// Add relative-to-circulating-supply metrics in a second step. - /// Called after the "all" cohort is available to provide global supply sources. - pub fn add_rel_to_circulating( - &mut self, - filter: &Filter, - full_name: &str, - version: Version, - unrealized: &UnrealizedMetrics, - supply: &SupplyMetrics, - all_supply: &SupplyMetrics, - ) { - let v1 = Version::ONE; - - // Skip if this is the "all" cohort itself - if !filter.compute_rel_to_all() { - return; - } - - let name = |suffix: &str| { - if full_name.is_empty() { - suffix.to_string() - } else { - format!("{full_name}_{suffix}") - } - }; - - // Global sources from "all" cohort - let global_supply_sats_height = &all_supply.total.sats.height; - let global_supply_sats_difficultyepoch = &all_supply.total.sats.difficultyepoch; - let global_supply_sats_dates = &all_supply.total.sats.rest.dates; - let global_supply_sats_dateindex = &all_supply.total.sats.rest.dateindex; - - // Fill in supply_rel_to_circulating_supply if not already set - if self.supply_rel_to_circulating_supply.is_none() { - self.supply_rel_to_circulating_supply = Some( - LazyBinaryFromDateLast::from_both_derived_last::( - &name("supply_rel_to_circulating_supply"), - version + v1, - supply.total.sats.rest.dateindex.boxed_clone(), - &supply.total.sats.rest.dates, - global_supply_sats_dateindex.boxed_clone(), - global_supply_sats_dates, - ), - ); - } - - // Fill in supply_in_profit_rel_to_circulating_supply if not already set - if self.supply_in_profit_rel_to_circulating_supply.is_none() { - self.supply_in_profit_rel_to_circulating_supply = Some( - LazyBinaryFromHeightLast::from_height_difficultyepoch_dates::( - &name("supply_in_profit_rel_to_circulating_supply"), - version + v1, - unrealized.supply_in_profit.height.boxed_clone(), - global_supply_sats_height.boxed_clone(), - unrealized.supply_in_profit.difficultyepoch.sats.boxed_clone(), - global_supply_sats_difficultyepoch.boxed_clone(), - unrealized - .supply_in_profit - .indexes - .sats_dateindex - .boxed_clone(), - &unrealized.supply_in_profit.indexes.sats, - global_supply_sats_dateindex.boxed_clone(), - global_supply_sats_dates, - ), - ); - } - - // Fill in supply_in_loss_rel_to_circulating_supply if not already set - if self.supply_in_loss_rel_to_circulating_supply.is_none() { - self.supply_in_loss_rel_to_circulating_supply = Some( - LazyBinaryFromHeightLast::from_height_difficultyepoch_dates::( - &name("supply_in_loss_rel_to_circulating_supply"), - version + v1, - unrealized.supply_in_loss.height.boxed_clone(), - global_supply_sats_height.boxed_clone(), - unrealized.supply_in_loss.difficultyepoch.sats.boxed_clone(), - global_supply_sats_difficultyepoch.boxed_clone(), - unrealized - .supply_in_loss - .indexes - .sats_dateindex - .boxed_clone(), - &unrealized.supply_in_loss.indexes.sats, - global_supply_sats_dateindex.boxed_clone(), - global_supply_sats_dates, - ), - ); - } - } } diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index 8303bf481..031b3b2ce 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -1849,47 +1849,6 @@ function createAaopoolPattern(client, acc) { }; } -/** - * @typedef {Object} RelativePattern2 - * @property {MetricPattern1} negUnrealizedLossRelToOwnMarketCap - * @property {MetricPattern1} negUnrealizedLossRelToOwnTotalUnrealizedPnl - * @property {MetricPattern1} netUnrealizedPnlRelToOwnMarketCap - * @property {MetricPattern1} netUnrealizedPnlRelToOwnTotalUnrealizedPnl - * @property {MetricPattern1} supplyInLossRelToCirculatingSupply - * @property {MetricPattern1} supplyInLossRelToOwnSupply - * @property {MetricPattern1} supplyInProfitRelToCirculatingSupply - * @property {MetricPattern1} supplyInProfitRelToOwnSupply - * @property {MetricPattern4} supplyRelToCirculatingSupply - * @property {MetricPattern1} unrealizedLossRelToOwnMarketCap - * @property {MetricPattern1} unrealizedLossRelToOwnTotalUnrealizedPnl - * @property {MetricPattern1} unrealizedProfitRelToOwnMarketCap - * @property {MetricPattern1} unrealizedProfitRelToOwnTotalUnrealizedPnl - */ - -/** - * Create a RelativePattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {RelativePattern2} - */ -function createRelativePattern2(client, acc) { - return { - negUnrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')), - negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')), - netUnrealizedPnlRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')), - netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')), - supplyInLossRelToCirculatingSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_circulating_supply')), - supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')), - supplyInProfitRelToCirculatingSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_circulating_supply')), - supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')), - supplyRelToCirculatingSupply: createMetricPattern4(client, _m(acc, 'supply_rel_to_circulating_supply')), - unrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')), - unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')), - unrealizedProfitRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')), - unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')), - }; -} - /** * @template T * @typedef {Object} LookbackPattern @@ -1972,47 +1931,6 @@ function createPeriodLumpSumStackPattern(client, acc) { }; } -/** - * @template T - * @typedef {Object} ClassAveragePricePattern - * @property {MetricPattern4} _2015 - * @property {MetricPattern4} _2016 - * @property {MetricPattern4} _2017 - * @property {MetricPattern4} _2018 - * @property {MetricPattern4} _2019 - * @property {MetricPattern4} _2020 - * @property {MetricPattern4} _2021 - * @property {MetricPattern4} _2022 - * @property {MetricPattern4} _2023 - * @property {MetricPattern4} _2024 - * @property {MetricPattern4} _2025 - * @property {MetricPattern4} _2026 - */ - -/** - * Create a ClassAveragePricePattern pattern node - * @template T - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {ClassAveragePricePattern} - */ -function createClassAveragePricePattern(client, acc) { - return { - _2015: createMetricPattern4(client, _m(acc, '2015_average_price')), - _2016: createMetricPattern4(client, _m(acc, '2016_average_price')), - _2017: createMetricPattern4(client, _m(acc, '2017_average_price')), - _2018: createMetricPattern4(client, _m(acc, '2018_average_price')), - _2019: createMetricPattern4(client, _m(acc, '2019_average_price')), - _2020: createMetricPattern4(client, _m(acc, '2020_average_price')), - _2021: createMetricPattern4(client, _m(acc, '2021_average_price')), - _2022: createMetricPattern4(client, _m(acc, '2022_average_price')), - _2023: createMetricPattern4(client, _m(acc, '2023_average_price')), - _2024: createMetricPattern4(client, _m(acc, '2024_average_price')), - _2025: createMetricPattern4(client, _m(acc, '2025_average_price')), - _2026: createMetricPattern4(client, _m(acc, '2026_average_price')), - }; -} - /** * @template T * @typedef {Object} PeriodAveragePricePattern @@ -2054,6 +1972,47 @@ function createPeriodAveragePricePattern(client, acc) { }; } +/** + * @template T + * @typedef {Object} ClassAveragePricePattern + * @property {MetricPattern4} _2015 + * @property {MetricPattern4} _2016 + * @property {MetricPattern4} _2017 + * @property {MetricPattern4} _2018 + * @property {MetricPattern4} _2019 + * @property {MetricPattern4} _2020 + * @property {MetricPattern4} _2021 + * @property {MetricPattern4} _2022 + * @property {MetricPattern4} _2023 + * @property {MetricPattern4} _2024 + * @property {MetricPattern4} _2025 + * @property {MetricPattern4} _2026 + */ + +/** + * Create a ClassAveragePricePattern pattern node + * @template T + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {ClassAveragePricePattern} + */ +function createClassAveragePricePattern(client, acc) { + return { + _2015: createMetricPattern4(client, _m(acc, '2015_average_price')), + _2016: createMetricPattern4(client, _m(acc, '2016_average_price')), + _2017: createMetricPattern4(client, _m(acc, '2017_average_price')), + _2018: createMetricPattern4(client, _m(acc, '2018_average_price')), + _2019: createMetricPattern4(client, _m(acc, '2019_average_price')), + _2020: createMetricPattern4(client, _m(acc, '2020_average_price')), + _2021: createMetricPattern4(client, _m(acc, '2021_average_price')), + _2022: createMetricPattern4(client, _m(acc, '2022_average_price')), + _2023: createMetricPattern4(client, _m(acc, '2023_average_price')), + _2024: createMetricPattern4(client, _m(acc, '2024_average_price')), + _2025: createMetricPattern4(client, _m(acc, '2025_average_price')), + _2026: createMetricPattern4(client, _m(acc, '2026_average_price')), + }; +} + /** * @typedef {Object} BitcoinPattern * @property {MetricPattern2} average @@ -2130,6 +2089,41 @@ function createDollarsPattern(client, acc) { }; } +/** + * @typedef {Object} RelativePattern2 + * @property {MetricPattern1} negUnrealizedLossRelToOwnMarketCap + * @property {MetricPattern1} negUnrealizedLossRelToOwnTotalUnrealizedPnl + * @property {MetricPattern1} netUnrealizedPnlRelToOwnMarketCap + * @property {MetricPattern1} netUnrealizedPnlRelToOwnTotalUnrealizedPnl + * @property {MetricPattern1} supplyInLossRelToOwnSupply + * @property {MetricPattern1} supplyInProfitRelToOwnSupply + * @property {MetricPattern1} unrealizedLossRelToOwnMarketCap + * @property {MetricPattern1} unrealizedLossRelToOwnTotalUnrealizedPnl + * @property {MetricPattern1} unrealizedProfitRelToOwnMarketCap + * @property {MetricPattern1} unrealizedProfitRelToOwnTotalUnrealizedPnl + */ + +/** + * Create a RelativePattern2 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {RelativePattern2} + */ +function createRelativePattern2(client, acc) { + return { + negUnrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')), + negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')), + netUnrealizedPnlRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')), + netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')), + supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')), + supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')), + unrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')), + unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')), + unrealizedProfitRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')), + unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')), + }; +} + /** * @typedef {Object} RelativePattern * @property {MetricPattern1} negUnrealizedLossRelToMarketCap @@ -2370,31 +2364,31 @@ function createPhaseDailyCentsPattern(client, acc) { } /** - * @typedef {Object} PeriodCagrPattern - * @property {MetricPattern4} _10y - * @property {MetricPattern4} _2y - * @property {MetricPattern4} _3y - * @property {MetricPattern4} _4y - * @property {MetricPattern4} _5y - * @property {MetricPattern4} _6y - * @property {MetricPattern4} _8y + * @typedef {Object} _10yTo12yPattern + * @property {ActivityPattern2} activity + * @property {CostBasisPattern2} costBasis + * @property {OutputsPattern} outputs + * @property {RealizedPattern2} realized + * @property {RelativePattern2} relative + * @property {SupplyPattern2} supply + * @property {UnrealizedPattern} unrealized */ /** - * Create a PeriodCagrPattern pattern node + * Create a _10yTo12yPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {PeriodCagrPattern} + * @returns {_10yTo12yPattern} */ -function createPeriodCagrPattern(client, acc) { +function create_10yTo12yPattern(client, acc) { return { - _10y: createMetricPattern4(client, _p('10y', acc)), - _2y: createMetricPattern4(client, _p('2y', acc)), - _3y: createMetricPattern4(client, _p('3y', acc)), - _4y: createMetricPattern4(client, _p('4y', acc)), - _5y: createMetricPattern4(client, _p('5y', acc)), - _6y: createMetricPattern4(client, _p('6y', acc)), - _8y: createMetricPattern4(client, _p('8y', acc)), + activity: createActivityPattern2(client, acc), + costBasis: createCostBasisPattern2(client, acc), + outputs: createOutputsPattern(client, _m(acc, 'utxo_count')), + realized: createRealizedPattern2(client, acc), + relative: createRelativePattern2(client, acc), + supply: createSupplyPattern2(client, _m(acc, 'supply')), + unrealized: createUnrealizedPattern(client, acc), }; } @@ -2450,38 +2444,38 @@ function create_0satsPattern2(client, acc) { costBasis: createCostBasisPattern(client, acc), outputs: createOutputsPattern(client, _m(acc, 'utxo_count')), realized: createRealizedPattern(client, acc), - relative: createRelativePattern4(client, _m(acc, 'supply')), + relative: createRelativePattern4(client, _m(acc, 'supply_in')), supply: createSupplyPattern2(client, _m(acc, 'supply')), unrealized: createUnrealizedPattern(client, acc), }; } /** - * @typedef {Object} _0Pattern - * @property {ActivityPattern2} activity - * @property {CostBasisPattern} costBasis - * @property {OutputsPattern} outputs - * @property {RealizedPattern} realized - * @property {RelativePattern} relative - * @property {SupplyPattern2} supply - * @property {UnrealizedPattern} unrealized + * @typedef {Object} PeriodCagrPattern + * @property {MetricPattern4} _10y + * @property {MetricPattern4} _2y + * @property {MetricPattern4} _3y + * @property {MetricPattern4} _4y + * @property {MetricPattern4} _5y + * @property {MetricPattern4} _6y + * @property {MetricPattern4} _8y */ /** - * Create a _0Pattern pattern node + * Create a PeriodCagrPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {_0Pattern} + * @returns {PeriodCagrPattern} */ -function create_0Pattern(client, acc) { +function createPeriodCagrPattern(client, acc) { return { - activity: createActivityPattern2(client, acc), - costBasis: createCostBasisPattern(client, acc), - outputs: createOutputsPattern(client, _m(acc, 'utxo_count')), - realized: createRealizedPattern(client, acc), - relative: createRelativePattern(client, acc), - supply: createSupplyPattern2(client, _m(acc, 'supply')), - unrealized: createUnrealizedPattern(client, acc), + _10y: createMetricPattern4(client, _p('10y', acc)), + _2y: createMetricPattern4(client, _p('2y', acc)), + _3y: createMetricPattern4(client, _p('3y', acc)), + _4y: createMetricPattern4(client, _p('4y', acc)), + _5y: createMetricPattern4(client, _p('5y', acc)), + _6y: createMetricPattern4(client, _p('6y', acc)), + _8y: createMetricPattern4(client, _p('8y', acc)), }; } @@ -2515,59 +2509,34 @@ function create_10yPattern(client, acc) { } /** - * @typedef {Object} _10yTo12yPattern + * @typedef {Object} _100btcPattern * @property {ActivityPattern2} activity - * @property {CostBasisPattern2} costBasis + * @property {CostBasisPattern} costBasis * @property {OutputsPattern} outputs - * @property {RealizedPattern2} realized - * @property {RelativePattern2} relative + * @property {RealizedPattern} realized + * @property {RelativePattern} relative * @property {SupplyPattern2} supply * @property {UnrealizedPattern} unrealized */ /** - * Create a _10yTo12yPattern pattern node + * Create a _100btcPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {_10yTo12yPattern} + * @returns {_100btcPattern} */ -function create_10yTo12yPattern(client, acc) { +function create_100btcPattern(client, acc) { return { activity: createActivityPattern2(client, acc), - costBasis: createCostBasisPattern2(client, acc), + costBasis: createCostBasisPattern(client, acc), outputs: createOutputsPattern(client, _m(acc, 'utxo_count')), - realized: createRealizedPattern2(client, acc), - relative: createRelativePattern2(client, acc), + realized: createRealizedPattern(client, acc), + relative: createRelativePattern(client, acc), supply: createSupplyPattern2(client, _m(acc, 'supply')), unrealized: createUnrealizedPattern(client, acc), }; } -/** - * @typedef {Object} RelativePattern4 - * @property {MetricPattern1} supplyInLossRelToCirculatingSupply - * @property {MetricPattern1} supplyInLossRelToOwnSupply - * @property {MetricPattern1} supplyInProfitRelToCirculatingSupply - * @property {MetricPattern1} supplyInProfitRelToOwnSupply - * @property {MetricPattern4} supplyRelToCirculatingSupply - */ - -/** - * Create a RelativePattern4 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {RelativePattern4} - */ -function createRelativePattern4(client, acc) { - return { - supplyInLossRelToCirculatingSupply: createMetricPattern1(client, _m(acc, 'in_loss_rel_to_circulating_supply')), - supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'in_loss_rel_to_own_supply')), - supplyInProfitRelToCirculatingSupply: createMetricPattern1(client, _m(acc, 'in_profit_rel_to_circulating_supply')), - supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'in_profit_rel_to_own_supply')), - supplyRelToCirculatingSupply: createMetricPattern4(client, _m(acc, 'rel_to_circulating_supply')), - }; -} - /** * @typedef {Object} ActivityPattern2 * @property {BlockCountPattern} coinblocksDestroyed @@ -2660,6 +2629,27 @@ function createCoinbasePattern(client, acc) { }; } +/** + * @typedef {Object} SegwitAdoptionPattern + * @property {MetricPattern11} base + * @property {MetricPattern2} cumulative + * @property {MetricPattern2} sum + */ + +/** + * Create a SegwitAdoptionPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {SegwitAdoptionPattern} + */ +function createSegwitAdoptionPattern(client, acc) { + return { + base: createMetricPattern11(client, acc), + cumulative: createMetricPattern2(client, _m(acc, 'cumulative')), + sum: createMetricPattern2(client, _m(acc, 'sum')), + }; +} + /** * @typedef {Object} CostBasisPattern2 * @property {MetricPattern1} max @@ -2723,27 +2713,6 @@ function create_2015Pattern(client, acc) { }; } -/** - * @typedef {Object} SegwitAdoptionPattern - * @property {MetricPattern11} base - * @property {MetricPattern2} cumulative - * @property {MetricPattern2} sum - */ - -/** - * Create a SegwitAdoptionPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {SegwitAdoptionPattern} - */ -function createSegwitAdoptionPattern(client, acc) { - return { - base: createMetricPattern11(client, acc), - cumulative: createMetricPattern2(client, _m(acc, 'cumulative')), - sum: createMetricPattern2(client, _m(acc, 'sum')), - }; -} - /** * @typedef {Object} CoinbasePattern2 * @property {BlockCountPattern} bitcoin @@ -2765,44 +2734,6 @@ function createCoinbasePattern2(client, acc) { }; } -/** - * @typedef {Object} SupplyPattern2 - * @property {ActiveSupplyPattern} halved - * @property {ActiveSupplyPattern} total - */ - -/** - * Create a SupplyPattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {SupplyPattern2} - */ -function createSupplyPattern2(client, acc) { - return { - halved: createActiveSupplyPattern(client, _m(acc, 'halved')), - total: createActiveSupplyPattern(client, acc), - }; -} - -/** - * @typedef {Object} CostBasisPattern - * @property {MetricPattern1} max - * @property {MetricPattern1} min - */ - -/** - * Create a CostBasisPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {CostBasisPattern} - */ -function createCostBasisPattern(client, acc) { - return { - max: createMetricPattern1(client, _m(acc, 'max_cost_basis')), - min: createMetricPattern1(client, _m(acc, 'min_cost_basis')), - }; -} - /** * @typedef {Object} _1dReturns1mSdPattern * @property {MetricPattern4} sd @@ -2823,44 +2754,59 @@ function create_1dReturns1mSdPattern(client, acc) { } /** - * @template T - * @typedef {Object} SatsPattern - * @property {MetricPattern1} ohlc - * @property {SplitPattern2} split + * @typedef {Object} CostBasisPattern + * @property {MetricPattern1} max + * @property {MetricPattern1} min */ /** - * Create a SatsPattern pattern node - * @template T + * Create a CostBasisPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {SatsPattern} + * @returns {CostBasisPattern} */ -function createSatsPattern(client, acc) { +function createCostBasisPattern(client, acc) { return { - ohlc: createMetricPattern1(client, _m(acc, 'ohlc_sats')), - split: createSplitPattern2(client, _m(acc, 'sats')), + max: createMetricPattern1(client, _m(acc, 'max_cost_basis')), + min: createMetricPattern1(client, _m(acc, 'min_cost_basis')), }; } /** - * @template T - * @typedef {Object} BlockCountPattern - * @property {MetricPattern1} cumulative - * @property {MetricPattern1} sum + * @typedef {Object} SupplyPattern2 + * @property {ActiveSupplyPattern} halved + * @property {ActiveSupplyPattern} total */ /** - * Create a BlockCountPattern pattern node - * @template T + * Create a SupplyPattern2 pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {BlockCountPattern} + * @returns {SupplyPattern2} */ -function createBlockCountPattern(client, acc) { +function createSupplyPattern2(client, acc) { return { - cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), - sum: createMetricPattern1(client, acc), + halved: createActiveSupplyPattern(client, _m(acc, 'halved')), + total: createActiveSupplyPattern(client, acc), + }; +} + +/** + * @typedef {Object} RelativePattern4 + * @property {MetricPattern1} supplyInLossRelToOwnSupply + * @property {MetricPattern1} supplyInProfitRelToOwnSupply + */ + +/** + * Create a RelativePattern4 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {RelativePattern4} + */ +function createRelativePattern4(client, acc) { + return { + supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'loss_rel_to_own_supply')), + supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'profit_rel_to_own_supply')), }; } @@ -2885,6 +2831,48 @@ function createBitcoinPattern2(client, acc) { }; } +/** + * @template T + * @typedef {Object} SatsPattern + * @property {MetricPattern1} ohlc + * @property {SplitPattern2} split + */ + +/** + * Create a SatsPattern pattern node + * @template T + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {SatsPattern} + */ +function createSatsPattern(client, acc) { + return { + ohlc: createMetricPattern1(client, _m(acc, 'ohlc')), + split: createSplitPattern2(client, acc), + }; +} + +/** + * @template T + * @typedef {Object} BlockCountPattern + * @property {MetricPattern1} cumulative + * @property {MetricPattern1} sum + */ + +/** + * Create a BlockCountPattern pattern node + * @template T + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {BlockCountPattern} + */ +function createBlockCountPattern(client, acc) { + return { + cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), + sum: createMetricPattern1(client, acc), + }; +} + /** * @typedef {Object} OutputsPattern * @property {MetricPattern1} utxoCount @@ -3337,45 +3325,45 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} MetricsTree_Distribution_UtxoCohorts_Epoch - * @property {_0Pattern} _0 - * @property {_0Pattern} _1 - * @property {_0Pattern} _2 - * @property {_0Pattern} _3 - * @property {_0Pattern} _4 + * @property {_0satsPattern2} _0 + * @property {_0satsPattern2} _1 + * @property {_0satsPattern2} _2 + * @property {_0satsPattern2} _3 + * @property {_0satsPattern2} _4 */ /** * @typedef {Object} MetricsTree_Distribution_UtxoCohorts_GeAmount - * @property {_0Pattern} _100btc - * @property {_0Pattern} _100kSats - * @property {_0Pattern} _100sats - * @property {_0Pattern} _10btc - * @property {_0Pattern} _10kBtc - * @property {_0Pattern} _10kSats - * @property {_0Pattern} _10mSats - * @property {_0Pattern} _10sats - * @property {_0Pattern} _1btc - * @property {_0Pattern} _1kBtc - * @property {_0Pattern} _1kSats - * @property {_0Pattern} _1mSats - * @property {_0Pattern} _1sat + * @property {_100btcPattern} _100btc + * @property {_100btcPattern} _100kSats + * @property {_100btcPattern} _100sats + * @property {_100btcPattern} _10btc + * @property {_100btcPattern} _10kBtc + * @property {_100btcPattern} _10kSats + * @property {_100btcPattern} _10mSats + * @property {_100btcPattern} _10sats + * @property {_100btcPattern} _1btc + * @property {_100btcPattern} _1kBtc + * @property {_100btcPattern} _1kSats + * @property {_100btcPattern} _1mSats + * @property {_100btcPattern} _1sat */ /** * @typedef {Object} MetricsTree_Distribution_UtxoCohorts_LtAmount - * @property {_0Pattern} _100btc - * @property {_0Pattern} _100kBtc - * @property {_0Pattern} _100kSats - * @property {_0Pattern} _100sats - * @property {_0Pattern} _10btc - * @property {_0Pattern} _10kBtc - * @property {_0Pattern} _10kSats - * @property {_0Pattern} _10mSats - * @property {_0Pattern} _10sats - * @property {_0Pattern} _1btc - * @property {_0Pattern} _1kBtc - * @property {_0Pattern} _1kSats - * @property {_0Pattern} _1mSats + * @property {_100btcPattern} _100btc + * @property {_100btcPattern} _100kBtc + * @property {_100btcPattern} _100kSats + * @property {_100btcPattern} _100sats + * @property {_100btcPattern} _10btc + * @property {_100btcPattern} _10kBtc + * @property {_100btcPattern} _10kSats + * @property {_100btcPattern} _10mSats + * @property {_100btcPattern} _10sats + * @property {_100btcPattern} _1btc + * @property {_100btcPattern} _1kBtc + * @property {_100btcPattern} _1kSats + * @property {_100btcPattern} _1mSats */ /** @@ -3402,24 +3390,24 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} MetricsTree_Distribution_UtxoCohorts_MinAge - * @property {_0Pattern} _10y - * @property {_0Pattern} _12y - * @property {_0Pattern} _1d - * @property {_0Pattern} _1m - * @property {_0Pattern} _1w - * @property {_0Pattern} _1y - * @property {_0Pattern} _2m - * @property {_0Pattern} _2y - * @property {_0Pattern} _3m - * @property {_0Pattern} _3y - * @property {_0Pattern} _4m - * @property {_0Pattern} _4y - * @property {_0Pattern} _5m - * @property {_0Pattern} _5y - * @property {_0Pattern} _6m - * @property {_0Pattern} _6y - * @property {_0Pattern} _7y - * @property {_0Pattern} _8y + * @property {_100btcPattern} _10y + * @property {_100btcPattern} _12y + * @property {_100btcPattern} _1d + * @property {_100btcPattern} _1m + * @property {_100btcPattern} _1w + * @property {_100btcPattern} _1y + * @property {_100btcPattern} _2m + * @property {_100btcPattern} _2y + * @property {_100btcPattern} _3m + * @property {_100btcPattern} _3y + * @property {_100btcPattern} _4m + * @property {_100btcPattern} _4y + * @property {_100btcPattern} _5m + * @property {_100btcPattern} _5y + * @property {_100btcPattern} _6m + * @property {_100btcPattern} _6y + * @property {_100btcPattern} _7y + * @property {_100btcPattern} _8y */ /** @@ -3452,39 +3440,39 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} MetricsTree_Distribution_UtxoCohorts_Type - * @property {_0Pattern} empty - * @property {_0Pattern} p2a - * @property {_0Pattern} p2ms - * @property {_0Pattern} p2pk33 - * @property {_0Pattern} p2pk65 - * @property {_0Pattern} p2pkh - * @property {_0Pattern} p2sh - * @property {_0Pattern} p2tr - * @property {_0Pattern} p2wpkh - * @property {_0Pattern} p2wsh - * @property {_0Pattern} unknown + * @property {_0satsPattern2} empty + * @property {_0satsPattern2} p2a + * @property {_0satsPattern2} p2ms + * @property {_0satsPattern2} p2pk33 + * @property {_0satsPattern2} p2pk65 + * @property {_0satsPattern2} p2pkh + * @property {_0satsPattern2} p2sh + * @property {_0satsPattern2} p2tr + * @property {_0satsPattern2} p2wpkh + * @property {_0satsPattern2} p2wsh + * @property {_0satsPattern2} unknown */ /** * @typedef {Object} MetricsTree_Distribution_UtxoCohorts_Year - * @property {_0Pattern} _2009 - * @property {_0Pattern} _2010 - * @property {_0Pattern} _2011 - * @property {_0Pattern} _2012 - * @property {_0Pattern} _2013 - * @property {_0Pattern} _2014 - * @property {_0Pattern} _2015 - * @property {_0Pattern} _2016 - * @property {_0Pattern} _2017 - * @property {_0Pattern} _2018 - * @property {_0Pattern} _2019 - * @property {_0Pattern} _2020 - * @property {_0Pattern} _2021 - * @property {_0Pattern} _2022 - * @property {_0Pattern} _2023 - * @property {_0Pattern} _2024 - * @property {_0Pattern} _2025 - * @property {_0Pattern} _2026 + * @property {_0satsPattern2} _2009 + * @property {_0satsPattern2} _2010 + * @property {_0satsPattern2} _2011 + * @property {_0satsPattern2} _2012 + * @property {_0satsPattern2} _2013 + * @property {_0satsPattern2} _2014 + * @property {_0satsPattern2} _2015 + * @property {_0satsPattern2} _2016 + * @property {_0satsPattern2} _2017 + * @property {_0satsPattern2} _2018 + * @property {_0satsPattern2} _2019 + * @property {_0satsPattern2} _2020 + * @property {_0satsPattern2} _2021 + * @property {_0satsPattern2} _2022 + * @property {_0satsPattern2} _2023 + * @property {_0satsPattern2} _2024 + * @property {_0satsPattern2} _2025 + * @property {_0satsPattern2} _2026 */ /** @@ -4085,8 +4073,8 @@ function createRealizedPriceExtraPattern(client, acc) { * @typedef {Object} MetricsTree_Price * @property {MetricsTree_Price_Cents} cents * @property {MetricsTree_Price_Oracle} oracle - * @property {SatsPattern} sats - * @property {MetricsTree_Price_Usd} usd + * @property {MetricsTree_Price_Sats} sats + * @property {SatsPattern} usd */ /** @@ -4138,9 +4126,9 @@ function createRealizedPriceExtraPattern(client, acc) { */ /** - * @typedef {Object} MetricsTree_Price_Usd - * @property {MetricPattern1} ohlc - * @property {SplitPattern2} split + * @typedef {Object} MetricsTree_Price_Sats + * @property {MetricPattern1} ohlc + * @property {SplitPattern2} split */ /** @@ -5498,41 +5486,41 @@ class BrkClient extends BrkClientBase { _1satTo10sats: create_0satsPattern2(this, 'utxos_above_1sat_under_10sats'), }, epoch: { - _0: create_0Pattern(this, 'epoch_0'), - _1: create_0Pattern(this, 'epoch_1'), - _2: create_0Pattern(this, 'epoch_2'), - _3: create_0Pattern(this, 'epoch_3'), - _4: create_0Pattern(this, 'epoch_4'), + _0: create_0satsPattern2(this, 'epoch_0'), + _1: create_0satsPattern2(this, 'epoch_1'), + _2: create_0satsPattern2(this, 'epoch_2'), + _3: create_0satsPattern2(this, 'epoch_3'), + _4: create_0satsPattern2(this, 'epoch_4'), }, geAmount: { - _100btc: create_0Pattern(this, 'utxos_above_100btc'), - _100kSats: create_0Pattern(this, 'utxos_above_100k_sats'), - _100sats: create_0Pattern(this, 'utxos_above_100sats'), - _10btc: create_0Pattern(this, 'utxos_above_10btc'), - _10kBtc: create_0Pattern(this, 'utxos_above_10k_btc'), - _10kSats: create_0Pattern(this, 'utxos_above_10k_sats'), - _10mSats: create_0Pattern(this, 'utxos_above_10m_sats'), - _10sats: create_0Pattern(this, 'utxos_above_10sats'), - _1btc: create_0Pattern(this, 'utxos_above_1btc'), - _1kBtc: create_0Pattern(this, 'utxos_above_1k_btc'), - _1kSats: create_0Pattern(this, 'utxos_above_1k_sats'), - _1mSats: create_0Pattern(this, 'utxos_above_1m_sats'), - _1sat: create_0Pattern(this, 'utxos_above_1sat'), + _100btc: create_100btcPattern(this, 'utxos_above_100btc'), + _100kSats: create_100btcPattern(this, 'utxos_above_100k_sats'), + _100sats: create_100btcPattern(this, 'utxos_above_100sats'), + _10btc: create_100btcPattern(this, 'utxos_above_10btc'), + _10kBtc: create_100btcPattern(this, 'utxos_above_10k_btc'), + _10kSats: create_100btcPattern(this, 'utxos_above_10k_sats'), + _10mSats: create_100btcPattern(this, 'utxos_above_10m_sats'), + _10sats: create_100btcPattern(this, 'utxos_above_10sats'), + _1btc: create_100btcPattern(this, 'utxos_above_1btc'), + _1kBtc: create_100btcPattern(this, 'utxos_above_1k_btc'), + _1kSats: create_100btcPattern(this, 'utxos_above_1k_sats'), + _1mSats: create_100btcPattern(this, 'utxos_above_1m_sats'), + _1sat: create_100btcPattern(this, 'utxos_above_1sat'), }, ltAmount: { - _100btc: create_0Pattern(this, 'utxos_under_100btc'), - _100kBtc: create_0Pattern(this, 'utxos_under_100k_btc'), - _100kSats: create_0Pattern(this, 'utxos_under_100k_sats'), - _100sats: create_0Pattern(this, 'utxos_under_100sats'), - _10btc: create_0Pattern(this, 'utxos_under_10btc'), - _10kBtc: create_0Pattern(this, 'utxos_under_10k_btc'), - _10kSats: create_0Pattern(this, 'utxos_under_10k_sats'), - _10mSats: create_0Pattern(this, 'utxos_under_10m_sats'), - _10sats: create_0Pattern(this, 'utxos_under_10sats'), - _1btc: create_0Pattern(this, 'utxos_under_1btc'), - _1kBtc: create_0Pattern(this, 'utxos_under_1k_btc'), - _1kSats: create_0Pattern(this, 'utxos_under_1k_sats'), - _1mSats: create_0Pattern(this, 'utxos_under_1m_sats'), + _100btc: create_100btcPattern(this, 'utxos_under_100btc'), + _100kBtc: create_100btcPattern(this, 'utxos_under_100k_btc'), + _100kSats: create_100btcPattern(this, 'utxos_under_100k_sats'), + _100sats: create_100btcPattern(this, 'utxos_under_100sats'), + _10btc: create_100btcPattern(this, 'utxos_under_10btc'), + _10kBtc: create_100btcPattern(this, 'utxos_under_10k_btc'), + _10kSats: create_100btcPattern(this, 'utxos_under_10k_sats'), + _10mSats: create_100btcPattern(this, 'utxos_under_10m_sats'), + _10sats: create_100btcPattern(this, 'utxos_under_10sats'), + _1btc: create_100btcPattern(this, 'utxos_under_1btc'), + _1kBtc: create_100btcPattern(this, 'utxos_under_1k_btc'), + _1kSats: create_100btcPattern(this, 'utxos_under_1k_sats'), + _1mSats: create_100btcPattern(this, 'utxos_under_1m_sats'), }, maxAge: { _10y: create_10yPattern(this, 'utxos_up_to_10y_old'), @@ -5555,24 +5543,24 @@ class BrkClient extends BrkClientBase { _8y: create_10yPattern(this, 'utxos_up_to_8y_old'), }, minAge: { - _10y: create_0Pattern(this, 'utxos_at_least_10y_old'), - _12y: create_0Pattern(this, 'utxos_at_least_12y_old'), - _1d: create_0Pattern(this, 'utxos_at_least_1d_old'), - _1m: create_0Pattern(this, 'utxos_at_least_1m_old'), - _1w: create_0Pattern(this, 'utxos_at_least_1w_old'), - _1y: create_0Pattern(this, 'utxos_at_least_1y_old'), - _2m: create_0Pattern(this, 'utxos_at_least_2m_old'), - _2y: create_0Pattern(this, 'utxos_at_least_2y_old'), - _3m: create_0Pattern(this, 'utxos_at_least_3m_old'), - _3y: create_0Pattern(this, 'utxos_at_least_3y_old'), - _4m: create_0Pattern(this, 'utxos_at_least_4m_old'), - _4y: create_0Pattern(this, 'utxos_at_least_4y_old'), - _5m: create_0Pattern(this, 'utxos_at_least_5m_old'), - _5y: create_0Pattern(this, 'utxos_at_least_5y_old'), - _6m: create_0Pattern(this, 'utxos_at_least_6m_old'), - _6y: create_0Pattern(this, 'utxos_at_least_6y_old'), - _7y: create_0Pattern(this, 'utxos_at_least_7y_old'), - _8y: create_0Pattern(this, 'utxos_at_least_8y_old'), + _10y: create_100btcPattern(this, 'utxos_at_least_10y_old'), + _12y: create_100btcPattern(this, 'utxos_at_least_12y_old'), + _1d: create_100btcPattern(this, 'utxos_at_least_1d_old'), + _1m: create_100btcPattern(this, 'utxos_at_least_1m_old'), + _1w: create_100btcPattern(this, 'utxos_at_least_1w_old'), + _1y: create_100btcPattern(this, 'utxos_at_least_1y_old'), + _2m: create_100btcPattern(this, 'utxos_at_least_2m_old'), + _2y: create_100btcPattern(this, 'utxos_at_least_2y_old'), + _3m: create_100btcPattern(this, 'utxos_at_least_3m_old'), + _3y: create_100btcPattern(this, 'utxos_at_least_3y_old'), + _4m: create_100btcPattern(this, 'utxos_at_least_4m_old'), + _4y: create_100btcPattern(this, 'utxos_at_least_4y_old'), + _5m: create_100btcPattern(this, 'utxos_at_least_5m_old'), + _5y: create_100btcPattern(this, 'utxos_at_least_5y_old'), + _6m: create_100btcPattern(this, 'utxos_at_least_6m_old'), + _6y: create_100btcPattern(this, 'utxos_at_least_6y_old'), + _7y: create_100btcPattern(this, 'utxos_at_least_7y_old'), + _8y: create_100btcPattern(this, 'utxos_at_least_8y_old'), }, term: { long: { @@ -5595,37 +5583,37 @@ class BrkClient extends BrkClientBase { }, }, type: { - empty: create_0Pattern(this, 'empty_outputs'), - p2a: create_0Pattern(this, 'p2a'), - p2ms: create_0Pattern(this, 'p2ms'), - p2pk33: create_0Pattern(this, 'p2pk33'), - p2pk65: create_0Pattern(this, 'p2pk65'), - p2pkh: create_0Pattern(this, 'p2pkh'), - p2sh: create_0Pattern(this, 'p2sh'), - p2tr: create_0Pattern(this, 'p2tr'), - p2wpkh: create_0Pattern(this, 'p2wpkh'), - p2wsh: create_0Pattern(this, 'p2wsh'), - unknown: create_0Pattern(this, 'unknown_outputs'), + empty: create_0satsPattern2(this, 'empty_outputs'), + p2a: create_0satsPattern2(this, 'p2a'), + p2ms: create_0satsPattern2(this, 'p2ms'), + p2pk33: create_0satsPattern2(this, 'p2pk33'), + p2pk65: create_0satsPattern2(this, 'p2pk65'), + p2pkh: create_0satsPattern2(this, 'p2pkh'), + p2sh: create_0satsPattern2(this, 'p2sh'), + p2tr: create_0satsPattern2(this, 'p2tr'), + p2wpkh: create_0satsPattern2(this, 'p2wpkh'), + p2wsh: create_0satsPattern2(this, 'p2wsh'), + unknown: create_0satsPattern2(this, 'unknown_outputs'), }, year: { - _2009: create_0Pattern(this, 'year_2009'), - _2010: create_0Pattern(this, 'year_2010'), - _2011: create_0Pattern(this, 'year_2011'), - _2012: create_0Pattern(this, 'year_2012'), - _2013: create_0Pattern(this, 'year_2013'), - _2014: create_0Pattern(this, 'year_2014'), - _2015: create_0Pattern(this, 'year_2015'), - _2016: create_0Pattern(this, 'year_2016'), - _2017: create_0Pattern(this, 'year_2017'), - _2018: create_0Pattern(this, 'year_2018'), - _2019: create_0Pattern(this, 'year_2019'), - _2020: create_0Pattern(this, 'year_2020'), - _2021: create_0Pattern(this, 'year_2021'), - _2022: create_0Pattern(this, 'year_2022'), - _2023: create_0Pattern(this, 'year_2023'), - _2024: create_0Pattern(this, 'year_2024'), - _2025: create_0Pattern(this, 'year_2025'), - _2026: create_0Pattern(this, 'year_2026'), + _2009: create_0satsPattern2(this, 'year_2009'), + _2010: create_0satsPattern2(this, 'year_2010'), + _2011: create_0satsPattern2(this, 'year_2011'), + _2012: create_0satsPattern2(this, 'year_2012'), + _2013: create_0satsPattern2(this, 'year_2013'), + _2014: create_0satsPattern2(this, 'year_2014'), + _2015: create_0satsPattern2(this, 'year_2015'), + _2016: create_0satsPattern2(this, 'year_2016'), + _2017: create_0satsPattern2(this, 'year_2017'), + _2018: create_0satsPattern2(this, 'year_2018'), + _2019: create_0satsPattern2(this, 'year_2019'), + _2020: create_0satsPattern2(this, 'year_2020'), + _2021: create_0satsPattern2(this, 'year_2021'), + _2022: create_0satsPattern2(this, 'year_2022'), + _2023: create_0satsPattern2(this, 'year_2023'), + _2024: create_0satsPattern2(this, 'year_2024'), + _2025: create_0satsPattern2(this, 'year_2025'), + _2026: create_0satsPattern2(this, 'year_2026'), }, }, }, @@ -6133,11 +6121,11 @@ class BrkClient extends BrkClientBase { priceCents: createMetricPattern11(this, 'oracle_price_cents'), txCount: createMetricPattern6(this, 'oracle_tx_count'), }, - sats: createSatsPattern(this, 'price'), - usd: { - ohlc: createMetricPattern1(this, 'price_ohlc'), - split: createSplitPattern2(this, 'price'), + sats: { + ohlc: createMetricPattern1(this, 'price_ohlc_sats'), + split: createSplitPattern2(this, 'price_sats'), }, + usd: createSatsPattern(this, 'price'), }, scripts: { count: { diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index c3fe7220d..884c33813 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -2017,25 +2017,6 @@ class AaopoolPattern: self.fee: UnclaimedRewardsPattern = UnclaimedRewardsPattern(client, _m(acc, 'fee')) self.subsidy: UnclaimedRewardsPattern = UnclaimedRewardsPattern(client, _m(acc, 'subsidy')) -class RelativePattern2: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')) - self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')) - self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')) - self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')) - self.supply_in_loss_rel_to_circulating_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_circulating_supply')) - self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')) - self.supply_in_profit_rel_to_circulating_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_circulating_supply')) - self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')) - self.supply_rel_to_circulating_supply: MetricPattern4[StoredF64] = MetricPattern4(client, _m(acc, 'supply_rel_to_circulating_supply')) - self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')) - self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')) - self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')) - self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')) - class LookbackPattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2073,24 +2054,6 @@ class PeriodLumpSumStackPattern: self._6y: _2015Pattern = _2015Pattern(client, _p('6y', acc)) self._8y: _2015Pattern = _2015Pattern(client, _p('8y', acc)) -class ClassAveragePricePattern(Generic[T]): - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_average_price')) - self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_average_price')) - self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_average_price')) - self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_average_price')) - self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_average_price')) - self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_average_price')) - self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_average_price')) - self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_average_price')) - self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_average_price')) - self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_average_price')) - self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_average_price')) - self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2026_average_price')) - class PeriodAveragePricePattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2109,6 +2072,24 @@ class PeriodAveragePricePattern(Generic[T]): self._6y: MetricPattern4[T] = MetricPattern4(client, _p('6y', acc)) self._8y: MetricPattern4[T] = MetricPattern4(client, _p('8y', acc)) +class ClassAveragePricePattern(Generic[T]): + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_average_price')) + self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_average_price')) + self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_average_price')) + self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_average_price')) + self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_average_price')) + self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_average_price')) + self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_average_price')) + self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_average_price')) + self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_average_price')) + self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_average_price')) + self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_average_price')) + self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2026_average_price')) + class BitcoinPattern: """Pattern struct for repeated tree structure.""" @@ -2143,6 +2124,22 @@ class DollarsPattern(Generic[T]): self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90')) self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum')) +class RelativePattern2: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')) + self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')) + self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')) + self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')) + self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')) + self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')) + self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')) + self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')) + self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')) + self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')) + class RelativePattern: """Pattern struct for repeated tree structure.""" @@ -2248,18 +2245,18 @@ class PhaseDailyCentsPattern(Generic[T]): self.pct75: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct75')) self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90')) -class PeriodCagrPattern: +class _10yTo12yPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self._10y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('10y', acc)) - self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('2y', acc)) - self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('3y', acc)) - self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('4y', acc)) - self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('5y', acc)) - self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc)) - self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc)) + self.activity: ActivityPattern2 = ActivityPattern2(client, acc) + self.cost_basis: CostBasisPattern2 = CostBasisPattern2(client, acc) + self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) + self.realized: RealizedPattern2 = RealizedPattern2(client, acc) + self.relative: RelativePattern2 = RelativePattern2(client, acc) + self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) + self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) class UnrealizedPattern: """Pattern struct for repeated tree structure.""" @@ -2283,22 +2280,22 @@ class _0satsPattern2: self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) self.realized: RealizedPattern = RealizedPattern(client, acc) - self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply')) + self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply_in')) self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class _0Pattern: +class PeriodCagrPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.activity: ActivityPattern2 = ActivityPattern2(client, acc) - self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) - self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) - self.realized: RealizedPattern = RealizedPattern(client, acc) - self.relative: RelativePattern = RelativePattern(client, acc) - self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) - self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) + self._10y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('10y', acc)) + self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('2y', acc)) + self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('3y', acc)) + self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('4y', acc)) + self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('5y', acc)) + self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc)) + self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc)) class _10yPattern: """Pattern struct for repeated tree structure.""" @@ -2313,30 +2310,19 @@ class _10yPattern: self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class _10yTo12yPattern: +class _100btcPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" self.activity: ActivityPattern2 = ActivityPattern2(client, acc) - self.cost_basis: CostBasisPattern2 = CostBasisPattern2(client, acc) + self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count')) - self.realized: RealizedPattern2 = RealizedPattern2(client, acc) - self.relative: RelativePattern2 = RelativePattern2(client, acc) + self.realized: RealizedPattern = RealizedPattern(client, acc) + self.relative: RelativePattern = RelativePattern(client, acc) self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class RelativePattern4: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.supply_in_loss_rel_to_circulating_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'in_loss_rel_to_circulating_supply')) - self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'in_loss_rel_to_own_supply')) - self.supply_in_profit_rel_to_circulating_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'in_profit_rel_to_circulating_supply')) - self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'in_profit_rel_to_own_supply')) - self.supply_rel_to_circulating_supply: MetricPattern4[StoredF64] = MetricPattern4(client, _m(acc, 'rel_to_circulating_supply')) - class ActivityPattern2: """Pattern struct for repeated tree structure.""" @@ -2376,6 +2362,15 @@ class CoinbasePattern: self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, 'usd')) self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc) +class SegwitAdoptionPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc) + self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative')) + self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum')) + class CostBasisPattern2: """Pattern struct for repeated tree structure.""" @@ -2403,15 +2398,6 @@ class _2015Pattern: self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd')) self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc) -class SegwitAdoptionPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc) - self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative')) - self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum')) - class CoinbasePattern2: """Pattern struct for repeated tree structure.""" @@ -2421,13 +2407,13 @@ class CoinbasePattern2: self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd')) self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc) -class SupplyPattern2: +class _1dReturns1mSdPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved')) - self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc) + self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd')) + self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma')) class CostBasisPattern: """Pattern struct for repeated tree structure.""" @@ -2437,29 +2423,21 @@ class CostBasisPattern: self.max: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis')) self.min: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis')) -class _1dReturns1mSdPattern: +class SupplyPattern2: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd')) - self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma')) + self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved')) + self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc) -class SatsPattern(Generic[T]): +class RelativePattern4: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.ohlc: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'ohlc_sats')) - self.split: SplitPattern2[T] = SplitPattern2(client, _m(acc, 'sats')) - -class BlockCountPattern(Generic[T]): - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) - self.sum: MetricPattern1[T] = MetricPattern1(client, acc) + self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'loss_rel_to_own_supply')) + self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'profit_rel_to_own_supply')) class BitcoinPattern2(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2469,6 +2447,22 @@ class BitcoinPattern2(Generic[T]): self.cumulative: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'cumulative')) self.sum: MetricPattern1[T] = MetricPattern1(client, acc) +class SatsPattern(Generic[T]): + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.ohlc: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'ohlc')) + self.split: SplitPattern2[T] = SplitPattern2(client, acc) + +class BlockCountPattern(Generic[T]): + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) + self.sum: MetricPattern1[T] = MetricPattern1(client, acc) + class OutputsPattern: """Pattern struct for repeated tree structure.""" @@ -2886,47 +2880,47 @@ class MetricsTree_Distribution_UtxoCohorts_Epoch: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._0: _0Pattern = _0Pattern(client, 'epoch_0') - self._1: _0Pattern = _0Pattern(client, 'epoch_1') - self._2: _0Pattern = _0Pattern(client, 'epoch_2') - self._3: _0Pattern = _0Pattern(client, 'epoch_3') - self._4: _0Pattern = _0Pattern(client, 'epoch_4') + self._0: _0satsPattern2 = _0satsPattern2(client, 'epoch_0') + self._1: _0satsPattern2 = _0satsPattern2(client, 'epoch_1') + self._2: _0satsPattern2 = _0satsPattern2(client, 'epoch_2') + self._3: _0satsPattern2 = _0satsPattern2(client, 'epoch_3') + self._4: _0satsPattern2 = _0satsPattern2(client, 'epoch_4') class MetricsTree_Distribution_UtxoCohorts_GeAmount: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._100btc: _0Pattern = _0Pattern(client, 'utxos_above_100btc') - self._100k_sats: _0Pattern = _0Pattern(client, 'utxos_above_100k_sats') - self._100sats: _0Pattern = _0Pattern(client, 'utxos_above_100sats') - self._10btc: _0Pattern = _0Pattern(client, 'utxos_above_10btc') - self._10k_btc: _0Pattern = _0Pattern(client, 'utxos_above_10k_btc') - self._10k_sats: _0Pattern = _0Pattern(client, 'utxos_above_10k_sats') - self._10m_sats: _0Pattern = _0Pattern(client, 'utxos_above_10m_sats') - self._10sats: _0Pattern = _0Pattern(client, 'utxos_above_10sats') - self._1btc: _0Pattern = _0Pattern(client, 'utxos_above_1btc') - self._1k_btc: _0Pattern = _0Pattern(client, 'utxos_above_1k_btc') - self._1k_sats: _0Pattern = _0Pattern(client, 'utxos_above_1k_sats') - self._1m_sats: _0Pattern = _0Pattern(client, 'utxos_above_1m_sats') - self._1sat: _0Pattern = _0Pattern(client, 'utxos_above_1sat') + self._100btc: _100btcPattern = _100btcPattern(client, 'utxos_above_100btc') + self._100k_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_100k_sats') + self._100sats: _100btcPattern = _100btcPattern(client, 'utxos_above_100sats') + self._10btc: _100btcPattern = _100btcPattern(client, 'utxos_above_10btc') + self._10k_btc: _100btcPattern = _100btcPattern(client, 'utxos_above_10k_btc') + self._10k_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_10k_sats') + self._10m_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_10m_sats') + self._10sats: _100btcPattern = _100btcPattern(client, 'utxos_above_10sats') + self._1btc: _100btcPattern = _100btcPattern(client, 'utxos_above_1btc') + self._1k_btc: _100btcPattern = _100btcPattern(client, 'utxos_above_1k_btc') + self._1k_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_1k_sats') + self._1m_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_1m_sats') + self._1sat: _100btcPattern = _100btcPattern(client, 'utxos_above_1sat') class MetricsTree_Distribution_UtxoCohorts_LtAmount: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._100btc: _0Pattern = _0Pattern(client, 'utxos_under_100btc') - self._100k_btc: _0Pattern = _0Pattern(client, 'utxos_under_100k_btc') - self._100k_sats: _0Pattern = _0Pattern(client, 'utxos_under_100k_sats') - self._100sats: _0Pattern = _0Pattern(client, 'utxos_under_100sats') - self._10btc: _0Pattern = _0Pattern(client, 'utxos_under_10btc') - self._10k_btc: _0Pattern = _0Pattern(client, 'utxos_under_10k_btc') - self._10k_sats: _0Pattern = _0Pattern(client, 'utxos_under_10k_sats') - self._10m_sats: _0Pattern = _0Pattern(client, 'utxos_under_10m_sats') - self._10sats: _0Pattern = _0Pattern(client, 'utxos_under_10sats') - self._1btc: _0Pattern = _0Pattern(client, 'utxos_under_1btc') - self._1k_btc: _0Pattern = _0Pattern(client, 'utxos_under_1k_btc') - self._1k_sats: _0Pattern = _0Pattern(client, 'utxos_under_1k_sats') - self._1m_sats: _0Pattern = _0Pattern(client, 'utxos_under_1m_sats') + self._100btc: _100btcPattern = _100btcPattern(client, 'utxos_under_100btc') + self._100k_btc: _100btcPattern = _100btcPattern(client, 'utxos_under_100k_btc') + self._100k_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_100k_sats') + self._100sats: _100btcPattern = _100btcPattern(client, 'utxos_under_100sats') + self._10btc: _100btcPattern = _100btcPattern(client, 'utxos_under_10btc') + self._10k_btc: _100btcPattern = _100btcPattern(client, 'utxos_under_10k_btc') + self._10k_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_10k_sats') + self._10m_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_10m_sats') + self._10sats: _100btcPattern = _100btcPattern(client, 'utxos_under_10sats') + self._1btc: _100btcPattern = _100btcPattern(client, 'utxos_under_1btc') + self._1k_btc: _100btcPattern = _100btcPattern(client, 'utxos_under_1k_btc') + self._1k_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_1k_sats') + self._1m_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_1m_sats') class MetricsTree_Distribution_UtxoCohorts_MaxAge: """Metrics tree node.""" @@ -2955,24 +2949,24 @@ class MetricsTree_Distribution_UtxoCohorts_MinAge: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._10y: _0Pattern = _0Pattern(client, 'utxos_at_least_10y_old') - self._12y: _0Pattern = _0Pattern(client, 'utxos_at_least_12y_old') - self._1d: _0Pattern = _0Pattern(client, 'utxos_at_least_1d_old') - self._1m: _0Pattern = _0Pattern(client, 'utxos_at_least_1m_old') - self._1w: _0Pattern = _0Pattern(client, 'utxos_at_least_1w_old') - self._1y: _0Pattern = _0Pattern(client, 'utxos_at_least_1y_old') - self._2m: _0Pattern = _0Pattern(client, 'utxos_at_least_2m_old') - self._2y: _0Pattern = _0Pattern(client, 'utxos_at_least_2y_old') - self._3m: _0Pattern = _0Pattern(client, 'utxos_at_least_3m_old') - self._3y: _0Pattern = _0Pattern(client, 'utxos_at_least_3y_old') - self._4m: _0Pattern = _0Pattern(client, 'utxos_at_least_4m_old') - self._4y: _0Pattern = _0Pattern(client, 'utxos_at_least_4y_old') - self._5m: _0Pattern = _0Pattern(client, 'utxos_at_least_5m_old') - self._5y: _0Pattern = _0Pattern(client, 'utxos_at_least_5y_old') - self._6m: _0Pattern = _0Pattern(client, 'utxos_at_least_6m_old') - self._6y: _0Pattern = _0Pattern(client, 'utxos_at_least_6y_old') - self._7y: _0Pattern = _0Pattern(client, 'utxos_at_least_7y_old') - self._8y: _0Pattern = _0Pattern(client, 'utxos_at_least_8y_old') + self._10y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_10y_old') + self._12y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_12y_old') + self._1d: _100btcPattern = _100btcPattern(client, 'utxos_at_least_1d_old') + self._1m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_1m_old') + self._1w: _100btcPattern = _100btcPattern(client, 'utxos_at_least_1w_old') + self._1y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_1y_old') + self._2m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_2m_old') + self._2y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_2y_old') + self._3m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_3m_old') + self._3y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_3y_old') + self._4m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_4m_old') + self._4y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_4y_old') + self._5m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_5m_old') + self._5y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_5y_old') + self._6m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_6m_old') + self._6y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_6y_old') + self._7y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_7y_old') + self._8y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_8y_old') class MetricsTree_Distribution_UtxoCohorts_Term_Long: """Metrics tree node.""" @@ -3009,40 +3003,40 @@ class MetricsTree_Distribution_UtxoCohorts_Type: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.empty: _0Pattern = _0Pattern(client, 'empty_outputs') - self.p2a: _0Pattern = _0Pattern(client, 'p2a') - self.p2ms: _0Pattern = _0Pattern(client, 'p2ms') - self.p2pk33: _0Pattern = _0Pattern(client, 'p2pk33') - self.p2pk65: _0Pattern = _0Pattern(client, 'p2pk65') - self.p2pkh: _0Pattern = _0Pattern(client, 'p2pkh') - self.p2sh: _0Pattern = _0Pattern(client, 'p2sh') - self.p2tr: _0Pattern = _0Pattern(client, 'p2tr') - self.p2wpkh: _0Pattern = _0Pattern(client, 'p2wpkh') - self.p2wsh: _0Pattern = _0Pattern(client, 'p2wsh') - self.unknown: _0Pattern = _0Pattern(client, 'unknown_outputs') + self.empty: _0satsPattern2 = _0satsPattern2(client, 'empty_outputs') + self.p2a: _0satsPattern2 = _0satsPattern2(client, 'p2a') + self.p2ms: _0satsPattern2 = _0satsPattern2(client, 'p2ms') + self.p2pk33: _0satsPattern2 = _0satsPattern2(client, 'p2pk33') + self.p2pk65: _0satsPattern2 = _0satsPattern2(client, 'p2pk65') + self.p2pkh: _0satsPattern2 = _0satsPattern2(client, 'p2pkh') + self.p2sh: _0satsPattern2 = _0satsPattern2(client, 'p2sh') + self.p2tr: _0satsPattern2 = _0satsPattern2(client, 'p2tr') + self.p2wpkh: _0satsPattern2 = _0satsPattern2(client, 'p2wpkh') + self.p2wsh: _0satsPattern2 = _0satsPattern2(client, 'p2wsh') + self.unknown: _0satsPattern2 = _0satsPattern2(client, 'unknown_outputs') class MetricsTree_Distribution_UtxoCohorts_Year: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._2009: _0Pattern = _0Pattern(client, 'year_2009') - self._2010: _0Pattern = _0Pattern(client, 'year_2010') - self._2011: _0Pattern = _0Pattern(client, 'year_2011') - self._2012: _0Pattern = _0Pattern(client, 'year_2012') - self._2013: _0Pattern = _0Pattern(client, 'year_2013') - self._2014: _0Pattern = _0Pattern(client, 'year_2014') - self._2015: _0Pattern = _0Pattern(client, 'year_2015') - self._2016: _0Pattern = _0Pattern(client, 'year_2016') - self._2017: _0Pattern = _0Pattern(client, 'year_2017') - self._2018: _0Pattern = _0Pattern(client, 'year_2018') - self._2019: _0Pattern = _0Pattern(client, 'year_2019') - self._2020: _0Pattern = _0Pattern(client, 'year_2020') - self._2021: _0Pattern = _0Pattern(client, 'year_2021') - self._2022: _0Pattern = _0Pattern(client, 'year_2022') - self._2023: _0Pattern = _0Pattern(client, 'year_2023') - self._2024: _0Pattern = _0Pattern(client, 'year_2024') - self._2025: _0Pattern = _0Pattern(client, 'year_2025') - self._2026: _0Pattern = _0Pattern(client, 'year_2026') + self._2009: _0satsPattern2 = _0satsPattern2(client, 'year_2009') + self._2010: _0satsPattern2 = _0satsPattern2(client, 'year_2010') + self._2011: _0satsPattern2 = _0satsPattern2(client, 'year_2011') + self._2012: _0satsPattern2 = _0satsPattern2(client, 'year_2012') + self._2013: _0satsPattern2 = _0satsPattern2(client, 'year_2013') + self._2014: _0satsPattern2 = _0satsPattern2(client, 'year_2014') + self._2015: _0satsPattern2 = _0satsPattern2(client, 'year_2015') + self._2016: _0satsPattern2 = _0satsPattern2(client, 'year_2016') + self._2017: _0satsPattern2 = _0satsPattern2(client, 'year_2017') + self._2018: _0satsPattern2 = _0satsPattern2(client, 'year_2018') + self._2019: _0satsPattern2 = _0satsPattern2(client, 'year_2019') + self._2020: _0satsPattern2 = _0satsPattern2(client, 'year_2020') + self._2021: _0satsPattern2 = _0satsPattern2(client, 'year_2021') + self._2022: _0satsPattern2 = _0satsPattern2(client, 'year_2022') + self._2023: _0satsPattern2 = _0satsPattern2(client, 'year_2023') + self._2024: _0satsPattern2 = _0satsPattern2(client, 'year_2024') + self._2025: _0satsPattern2 = _0satsPattern2(client, 'year_2025') + self._2026: _0satsPattern2 = _0satsPattern2(client, 'year_2026') class MetricsTree_Distribution_UtxoCohorts: """Metrics tree node.""" @@ -3765,12 +3759,12 @@ class MetricsTree_Price_Oracle: self.price_cents: MetricPattern11[Cents] = MetricPattern11(client, 'oracle_price_cents') self.tx_count: MetricPattern6[StoredU32] = MetricPattern6(client, 'oracle_tx_count') -class MetricsTree_Price_Usd: +class MetricsTree_Price_Sats: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.ohlc: MetricPattern1[OHLCDollars] = MetricPattern1(client, 'price_ohlc') - self.split: SplitPattern2[Dollars] = SplitPattern2(client, 'price') + self.ohlc: MetricPattern1[OHLCSats] = MetricPattern1(client, 'price_ohlc_sats') + self.split: SplitPattern2[Sats] = SplitPattern2(client, 'price_sats') class MetricsTree_Price: """Metrics tree node.""" @@ -3778,8 +3772,8 @@ class MetricsTree_Price: def __init__(self, client: BrkClientBase, base_path: str = ''): self.cents: MetricsTree_Price_Cents = MetricsTree_Price_Cents(client) self.oracle: MetricsTree_Price_Oracle = MetricsTree_Price_Oracle(client) - self.sats: SatsPattern[OHLCSats] = SatsPattern(client, 'price') - self.usd: MetricsTree_Price_Usd = MetricsTree_Price_Usd(client) + self.sats: MetricsTree_Price_Sats = MetricsTree_Price_Sats(client) + self.usd: SatsPattern[OHLCDollars] = SatsPattern(client, 'price') class MetricsTree_Scripts_Count: """Metrics tree node.""" diff --git a/website/scripts/options/cointime.js b/website/scripts/options/cointime.js index 3e93a4303..2bf9600bd 100644 --- a/website/scripts/options/cointime.js +++ b/website/scripts/options/cointime.js @@ -1,13 +1,9 @@ import { Unit } from "../utils/units.js"; -import { priceLine, priceLines } from "./constants.js"; -import { line, baseline } from "./series.js"; +import { line } from "./series.js"; import { satsBtcUsd, - percentileUsdMap, - percentileMap, - sdPatterns, - sdBandsUsd, - sdBandsRatio, + createRatioChart, + createZScoresFolder, } from "./shared.js"; /** @@ -18,229 +14,21 @@ import { * @param {string} args.legend * @param {AnyMetricPattern} args.price * @param {ActivePriceRatioPattern} args.ratio - * @param {Color} [args.color] + * @param {Color} args.color * @returns {PartialOptionsTree} */ function createCointimePriceWithRatioOptions( ctx, { title, legend, price, ratio, color }, ) { - const { colors } = ctx; - - const pctUsdMap = percentileUsdMap(colors, ratio); - const pctMap = percentileMap(colors, ratio); - const sdPats = sdPatterns(ratio); - return [ { name: "price", title, top: [line({ metric: price, name: legend, color, unit: Unit.usd })], }, - { - name: "Ratio", - title: `${title} Ratio`, - top: [ - line({ metric: price, name: legend, color, unit: Unit.usd }), - ...pctUsdMap.map(({ name: pctName, prop, color: pctColor }) => - line({ - metric: prop, - name: pctName, - color: pctColor, - defaultActive: false, - unit: Unit.usd, - options: { lineStyle: 1 }, - }), - ), - ], - bottom: [ - baseline({ - metric: ratio.ratio, - name: "Ratio", - unit: Unit.ratio, - base: 1, - }), - line({ - metric: ratio.ratio1wSma, - name: "1w SMA", - color: colors.lime, - unit: Unit.ratio, - defaultActive: false, - }), - line({ - metric: ratio.ratio1mSma, - name: "1m SMA", - color: colors.teal, - unit: Unit.ratio, - defaultActive: false, - }), - line({ - metric: ratio.ratio1ySd.sma, - name: "1y SMA", - color: colors.sky, - unit: Unit.ratio, - defaultActive: false, - }), - line({ - metric: ratio.ratio2ySd.sma, - name: "2y SMA", - color: colors.indigo, - unit: Unit.ratio, - defaultActive: false, - }), - line({ - metric: ratio.ratio4ySd.sma, - name: "4y SMA", - color: colors.purple, - unit: Unit.ratio, - defaultActive: false, - }), - line({ - metric: ratio.ratioSd.sma, - name: "All SMA", - color: colors.rose, - unit: Unit.ratio, - defaultActive: false, - }), - ...pctMap.map(({ name: pctName, prop, color: pctColor }) => - line({ - metric: prop, - name: pctName, - color: pctColor, - defaultActive: false, - unit: Unit.ratio, - options: { lineStyle: 1 }, - }), - ), - priceLine({ ctx, unit: Unit.ratio, number: 1 }), - ], - }, - { - name: "ZScores", - tree: [ - // Compare all Z-Scores - { - name: "Compare", - title: `${title} Z-Scores`, - top: [ - line({ metric: price, name: legend, color, unit: Unit.usd }), - line({ - metric: ratio.ratio1ySd._0sdUsd, - name: "1y 0σ", - color: colors.orange, - defaultActive: false, - unit: Unit.usd, - }), - line({ - metric: ratio.ratio2ySd._0sdUsd, - name: "2y 0σ", - color: colors.yellow, - defaultActive: false, - unit: Unit.usd, - }), - line({ - metric: ratio.ratio4ySd._0sdUsd, - name: "4y 0σ", - color: colors.lime, - defaultActive: false, - unit: Unit.usd, - }), - line({ - metric: ratio.ratioSd._0sdUsd, - name: "all 0σ", - color: colors.blue, - defaultActive: false, - unit: Unit.usd, - }), - ], - bottom: [ - line({ - metric: ratio.ratioSd.zscore, - name: "all", - color: colors.blue, - unit: Unit.sd, - }), - line({ - metric: ratio.ratio4ySd.zscore, - name: "4y", - color: colors.lime, - unit: Unit.sd, - }), - line({ - metric: ratio.ratio2ySd.zscore, - name: "2y", - color: colors.yellow, - unit: Unit.sd, - }), - line({ - metric: ratio.ratio1ySd.zscore, - name: "1y", - color: colors.orange, - unit: Unit.sd, - }), - ...priceLines({ - ctx, - unit: Unit.sd, - numbers: [0, 1, -1, 2, -2, 3, -3, 4, -4], - defaultActive: false, - }), - ], - }, - // Individual Z-Score charts - ...sdPats.map(({ nameAddon, titleAddon, sd }) => ({ - name: nameAddon, - title: `${title} ${titleAddon} Z-Score`, - top: [ - line({ metric: price, name: legend, color, unit: Unit.usd }), - ...sdBandsUsd(colors, sd).map( - ({ name: bandName, prop, color: bandColor }) => - line({ - metric: prop, - name: bandName, - color: bandColor, - unit: Unit.usd, - defaultActive: false, - }), - ), - ], - bottom: [ - baseline({ - metric: sd.zscore, - name: "Z-Score", - unit: Unit.sd, - }), - baseline({ - metric: ratio.ratio, - name: "Ratio", - unit: Unit.ratio, - base: 1, - }), - line({ - metric: sd.sd, - name: "Volatility", - color: colors.gray, - unit: Unit.percentage, - }), - ...sdBandsRatio(colors, sd).map( - ({ name: bandName, prop, color: bandColor }) => - line({ - metric: prop, - name: bandName, - color: bandColor, - unit: Unit.ratio, - defaultActive: false, - }), - ), - ...priceLines({ - ctx, - unit: Unit.sd, - numbers: [0, 1, -1, 2, -2, 3, -3], - defaultActive: false, - }), - ], - })), - ], - }, + createRatioChart(ctx, { title, price, ratio, color }), + createZScoresFolder(ctx, { title, legend, price, ratio, color }), ]; } @@ -252,7 +40,7 @@ function createCointimePriceWithRatioOptions( export function createCointimeSection(ctx) { const { colors, brk } = ctx; const { cointime, distribution, supply } = brk.metrics; - const { pricing, cap, activity, supply: cointimeSupply, adjusted } = cointime; + const { pricing, cap, activity, supply: cointimeSupply, adjusted, reserveRisk, value } = cointime; const { all } = distribution.utxoCohorts; // Cointime prices data @@ -481,6 +269,132 @@ export function createCointimeSection(ctx) { ], }, + // Reserve Risk + { + name: "Reserve Risk", + tree: [ + { + name: "reserve risk", + title: "Reserve Risk", + bottom: [ + line({ + metric: reserveRisk.reserveRisk, + name: "Reserve Risk", + color: colors.orange, + unit: Unit.ratio, + }), + ], + }, + { + name: "hodl bank", + title: "HODL Bank", + bottom: [ + line({ + metric: reserveRisk.hodlBank, + name: "HODL Bank", + color: colors.blue, + unit: Unit.ratio, + }), + ], + }, + { + name: "vocdd 365d sma", + title: "VOCDD 365d SMA", + bottom: [ + line({ + metric: reserveRisk.vocdd365dSma, + name: "VOCDD 365d SMA", + color: colors.purple, + unit: Unit.ratio, + }), + ], + }, + ], + }, + + // Cointime Value + { + name: "Value", + tree: [ + { + name: "created", + title: "Cointime Value Created", + bottom: [ + line({ + metric: value.cointimeValueCreated.sum, + name: "Created", + color: colors.green, + unit: Unit.usd, + }), + line({ + metric: value.cointimeValueCreated.cumulative, + name: "Cumulative", + color: colors.green, + unit: Unit.usd, + defaultActive: false, + }), + ], + }, + { + name: "destroyed", + title: "Cointime Value Destroyed", + bottom: [ + line({ + metric: value.cointimeValueDestroyed.sum, + name: "Destroyed", + color: colors.red, + unit: Unit.usd, + }), + line({ + metric: value.cointimeValueDestroyed.cumulative, + name: "Cumulative", + color: colors.red, + unit: Unit.usd, + defaultActive: false, + }), + ], + }, + { + name: "stored", + title: "Cointime Value Stored", + bottom: [ + line({ + metric: value.cointimeValueStored.sum, + name: "Stored", + color: colors.blue, + unit: Unit.usd, + }), + line({ + metric: value.cointimeValueStored.cumulative, + name: "Cumulative", + color: colors.blue, + unit: Unit.usd, + defaultActive: false, + }), + ], + }, + { + name: "vocdd", + title: "VOCDD (Value of Coin Days Destroyed)", + bottom: [ + line({ + metric: value.vocdd.sum, + name: "VOCDD", + color: colors.orange, + unit: Unit.usd, + }), + line({ + metric: value.vocdd.cumulative, + name: "Cumulative", + color: colors.orange, + unit: Unit.usd, + defaultActive: false, + }), + ], + }, + ], + }, + // Adjusted metrics { name: "Adjusted", diff --git a/website/scripts/options/context.js b/website/scripts/options/context.js index 9e11df3fb..2378c9128 100644 --- a/website/scripts/options/context.js +++ b/website/scripts/options/context.js @@ -60,21 +60,8 @@ export function createContext({ brk }) { fromValuePattern: (pattern, title, sumColor, cumulativeColor) => fromValuePattern(colors, pattern, title, sumColor, cumulativeColor), /** @type {OmitFirstArg} */ - fromBitcoinPatternWithUnit: ( - pattern, - title, - unit, - sumColor, - cumulativeColor, - ) => - fromBitcoinPatternWithUnit( - colors, - pattern, - title, - unit, - sumColor, - cumulativeColor, - ), + fromBitcoinPatternWithUnit: (pattern, unit, title, sumColor, cumulativeColor) => + fromBitcoinPatternWithUnit(colors, pattern, unit, title, sumColor, cumulativeColor), /** @type {OmitFirstArg} */ fromBlockCountWithUnit: (pattern, unit, title, sumColor, cumulativeColor) => fromBlockCountWithUnit( diff --git a/website/scripts/options/distribution/address.js b/website/scripts/options/distribution/address.js index 29185e90a..fe266faf5 100644 --- a/website/scripts/options/distribution/address.js +++ b/website/scripts/options/distribution/address.js @@ -16,6 +16,15 @@ import { createAddressCountSeries, createRealizedPriceSeries, createRealizedPriceRatioSeries, + createSingleCoinsDestroyedSeries, + createGroupedCoinblocksDestroyedSeries, + createGroupedCoindaysDestroyedSeries, + createGroupedSatblocksDestroyedSeries, + createGroupedSatdaysDestroyedSeries, + createSingleSentSeries, + createGroupedSentSatsSeries, + createGroupedSentBitcoinSeries, + createGroupedSentDollarsSeries, } from "./shared.js"; /** @@ -123,7 +132,7 @@ export function createAddressCohortFolder(ctx, args) { ...createCostBasisSection(list, useGroupName, title), // Activity section - ...createActivitySection(list, useGroupName, title), + ...createActivitySection(args, title), ], }; } @@ -208,20 +217,25 @@ function createRealizedPnlSection(ctx, args, title) { color: colors.green, unit: Unit.usd, }), + line({ + metric: realized.realizedProfit.cumulative, + name: "Profit Cumulative", + color: colors.green, + unit: Unit.usd, + defaultActive: false, + }), line({ metric: realized.realizedLoss.sum, name: "Loss", color: colors.red, unit: Unit.usd, - defaultActive: false, }), - // RealizedPattern (address cohorts) doesn't have realizedProfitToLossRatio line({ - metric: realized.totalRealizedPnl, - name: "Total", - color: colors.default, - defaultActive: false, + metric: realized.realizedLoss.cumulative, + name: "Loss Cumulative", + color: colors.red, unit: Unit.usd, + defaultActive: false, }), line({ metric: realized.negRealizedLoss.sum, @@ -231,7 +245,176 @@ function createRealizedPnlSection(ctx, args, title) { }), line({ metric: realized.negRealizedLoss.cumulative, - name: "Negative Loss", + name: "Negative Loss Cumulative", + color: colors.red, + unit: Unit.usd, + defaultActive: false, + }), + line({ + metric: realized.totalRealizedPnl, + name: "Total", + color: colors.default, + unit: Unit.usd, + defaultActive: false, + }), + baseline({ + metric: realized.realizedProfitRelToRealizedCap.sum, + name: "Profit", + color: colors.green, + unit: Unit.pctRcap, + }), + baseline({ + metric: realized.realizedProfitRelToRealizedCap.cumulative, + name: "Profit Cumulative", + color: colors.green, + unit: Unit.pctRcap, + defaultActive: false, + }), + baseline({ + metric: realized.realizedLossRelToRealizedCap.sum, + name: "Loss", + color: colors.red, + unit: Unit.pctRcap, + }), + baseline({ + metric: realized.realizedLossRelToRealizedCap.cumulative, + name: "Loss Cumulative", + color: colors.red, + unit: Unit.pctRcap, + defaultActive: false, + }), + ], + }, + { + name: "Net pnl", + title: `Net Realized P&L ${title}`, + bottom: [ + baseline({ + metric: realized.netRealizedPnl.sum, + name: "Net", + unit: Unit.usd, + }), + baseline({ + metric: realized.netRealizedPnl.cumulative, + name: "Net Cumulative", + unit: Unit.usd, + defaultActive: false, + }), + baseline({ + metric: realized.netRealizedPnlCumulative30dDelta, + name: "Cumulative 30d change", + unit: Unit.usd, + defaultActive: false, + }), + baseline({ + metric: realized.netRealizedPnlRelToRealizedCap.sum, + name: "Net", + unit: Unit.pctRcap, + }), + baseline({ + metric: realized.netRealizedPnlRelToRealizedCap.cumulative, + name: "Net Cumulative", + unit: Unit.pctRcap, + defaultActive: false, + }), + baseline({ + metric: realized.netRealizedPnlCumulative30dDeltaRelToRealizedCap, + name: "Cumulative 30d change", + unit: Unit.pctRcap, + defaultActive: false, + }), + baseline({ + metric: realized.netRealizedPnlCumulative30dDeltaRelToMarketCap, + name: "Cumulative 30d change", + unit: Unit.pctMcap, + }), + priceLine({ + ctx, + unit: Unit.usd, + number: 1, + }), + priceLine({ + ctx, + unit: Unit.pctMcap, + }), + priceLine({ + ctx, + unit: Unit.pctRcap, + }), + ], + }, + { + name: "sopr", + title: `SOPR ${title}`, + bottom: [ + baseline({ + metric: realized.sopr, + name: "SOPR", + unit: Unit.ratio, + base: 1, + }), + baseline({ + metric: realized.sopr7dEma, + name: "7d EMA", + color: [colors.lime, colors.rose], + unit: Unit.ratio, + defaultActive: false, + base: 1, + }), + baseline({ + metric: realized.sopr30dEma, + name: "30d EMA", + color: [colors.avocado, colors.pink], + unit: Unit.ratio, + defaultActive: false, + base: 1, + }), + priceLine({ + ctx, + unit: Unit.ratio, + number: 1, + }), + ], + }, + { + name: "Sell Side Risk", + title: `Sell Side Risk Ratio ${title}`, + bottom: [ + line({ + metric: realized.sellSideRiskRatio, + name: "Raw", + color: colors.orange, + unit: Unit.ratio, + }), + line({ + metric: realized.sellSideRiskRatio7dEma, + name: "7d EMA", + color: colors.red, + unit: Unit.ratio, + defaultActive: false, + }), + line({ + metric: realized.sellSideRiskRatio30dEma, + name: "30d EMA", + color: colors.rose, + unit: Unit.ratio, + defaultActive: false, + }), + ], + }, + { + name: "value", + title: `Value Created & Destroyed ${title}`, + bottom: [ + line({ + metric: realized.valueCreated, + name: "Created", + color: colors.emerald, + unit: Unit.usd, + }), + line({ + metric: realized.valueDestroyed, + name: "Destroyed", color: colors.red, unit: Unit.usd, }), @@ -255,19 +438,6 @@ function createUnrealizedSection(ctx, list, useGroupName, title) { { name: "Unrealized", tree: [ - { - name: "nupl", - title: `Net Unrealized P&L ${title}`, - bottom: list.flatMap(({ color, name, tree }) => [ - baseline({ - metric: tree.unrealized.netUnrealizedPnl, - name: useGroupName ? name : "NUPL", - color: useGroupName ? color : [colors.red, colors.green], - unit: Unit.ratio, - options: { baseValue: { price: 0 } }, - }), - ]), - }, { name: "profit", title: `Unrealized Profit ${title}`, @@ -275,7 +445,7 @@ function createUnrealizedSection(ctx, list, useGroupName, title) { line({ metric: tree.unrealized.unrealizedProfit, name: useGroupName ? name : "Profit", - color, + color: useGroupName ? color : colors.green, unit: Unit.usd, }), ]), @@ -287,11 +457,117 @@ function createUnrealizedSection(ctx, list, useGroupName, title) { line({ metric: tree.unrealized.unrealizedLoss, name: useGroupName ? name : "Loss", - color, + color: useGroupName ? color : colors.red, unit: Unit.usd, }), ]), }, + { + name: "total pnl", + title: `Total Unrealized P&L ${title}`, + bottom: list.flatMap(({ color, name, tree }) => [ + baseline({ + metric: tree.unrealized.totalUnrealizedPnl, + name: useGroupName ? name : "Total", + color: useGroupName ? color : undefined, + unit: Unit.usd, + }), + ]), + }, + { + name: "negative loss", + title: `Negative Unrealized Loss ${title}`, + bottom: list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.unrealized.negUnrealizedLoss, + name: useGroupName ? name : "Negative Loss", + color: useGroupName ? color : colors.red, + unit: Unit.usd, + }), + ]), + }, + { + name: "Relative", + tree: [ + { + name: "nupl", + title: `NUPL (Rel to Market Cap) ${title}`, + bottom: list.flatMap(({ color, name, tree }) => [ + baseline({ + metric: tree.relative.nupl, + name: useGroupName ? name : "NUPL", + color: useGroupName ? color : undefined, + unit: Unit.ratio, + options: { baseValue: { price: 0 } }, + }), + ]), + }, + { + name: "profit", + title: `Unrealized Profit (% of Market Cap) ${title}`, + bottom: list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.relative.unrealizedProfitRelToMarketCap, + name: useGroupName ? name : "Profit", + color: useGroupName ? color : colors.green, + unit: Unit.pctMcap, + }), + ]), + }, + { + name: "loss", + title: `Unrealized Loss (% of Market Cap) ${title}`, + bottom: list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.relative.unrealizedLossRelToMarketCap, + name: useGroupName ? name : "Loss", + color: useGroupName ? color : colors.red, + unit: Unit.pctMcap, + }), + ]), + }, + { + name: "net pnl", + title: `Net Unrealized P&L (% of Market Cap) ${title}`, + bottom: list.flatMap(({ color, name, tree }) => [ + baseline({ + metric: tree.relative.netUnrealizedPnlRelToMarketCap, + name: useGroupName ? name : "Net", + color: useGroupName ? color : undefined, + unit: Unit.pctMcap, + }), + ]), + }, + { + name: "negative loss", + title: `Negative Unrealized Loss (% of Market Cap) ${title}`, + bottom: list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.relative.negUnrealizedLossRelToMarketCap, + name: useGroupName ? name : "Negative Loss", + color: useGroupName ? color : colors.red, + unit: Unit.pctMcap, + }), + ]), + }, + ], + }, + { + name: "nupl", + title: `Net Unrealized P&L ${title}`, + bottom: list.flatMap(({ color, name, tree }) => [ + baseline({ + metric: tree.unrealized.netUnrealizedPnl, + name: useGroupName ? name : "NUPL", + color: useGroupName ? color : undefined, + unit: Unit.ratio, + }), + priceLine({ + ctx, + unit: Unit.ratio, + }), + ]), + }, ], }, ]; @@ -340,12 +616,37 @@ function createCostBasisSection(list, useGroupName, title) { /** * Create activity section - * @param {readonly AddressCohortObject[]} list - * @param {boolean} useGroupName + * @param {AddressCohortObject | AddressCohortGroupObject} args * @param {string} title * @returns {PartialOptionsTree} */ -function createActivitySection(list, useGroupName, title) { +function createActivitySection(args, title) { + const list = "list" in args ? args.list : [args]; + const isSingle = !("list" in args); + + // Single cohort: all metrics on one chart + if (isSingle) { + const cohort = /** @type {AddressCohortObject} */ (args); + return [ + { + name: "Activity", + tree: [ + { + name: "Coins Destroyed", + title: `Coins Destroyed ${title}`, + bottom: createSingleCoinsDestroyedSeries(cohort), + }, + { + name: "Sent", + title: `Sent ${title}`, + bottom: createSingleSentSeries(cohort), + }, + ], + }, + ]; + } + + // Grouped cohorts: split charts for comparison return [ { name: "Activity", @@ -353,38 +654,42 @@ function createActivitySection(list, useGroupName, title) { { name: "coinblocks destroyed", title: `Coinblocks Destroyed ${title}`, - bottom: list.flatMap(({ color, name, tree }) => [ - line({ - metric: tree.activity.coinblocksDestroyed.sum, - name: useGroupName ? name : "Coinblocks", - color, - unit: Unit.coinblocks, - }), - line({ - metric: tree.activity.coinblocksDestroyed.cumulative, - name: useGroupName ? name : "Coinblocks", - color, - unit: Unit.coinblocks, - }), - ]), + bottom: createGroupedCoinblocksDestroyedSeries(list), }, { name: "coindays destroyed", title: `Coindays Destroyed ${title}`, - bottom: list.flatMap(({ color, name, tree }) => [ - line({ - metric: tree.activity.coindaysDestroyed.sum, - name: useGroupName ? name : "Coindays", - color, - unit: Unit.coindays, - }), - line({ - metric: tree.activity.coindaysDestroyed.cumulative, - name: useGroupName ? name : "Coindays", - color, - unit: Unit.coindays, - }), - ]), + bottom: createGroupedCoindaysDestroyedSeries(list), + }, + { + name: "satblocks destroyed", + title: `Satblocks Destroyed ${title}`, + bottom: createGroupedSatblocksDestroyedSeries(list), + }, + { + name: "satdays destroyed", + title: `Satdays Destroyed ${title}`, + bottom: createGroupedSatdaysDestroyedSeries(list), + }, + { + name: "Sent", + tree: [ + { + name: "sats", + title: `Sent (Sats) ${title}`, + bottom: createGroupedSentSatsSeries(list), + }, + { + name: "bitcoin", + title: `Sent (BTC) ${title}`, + bottom: createGroupedSentBitcoinSeries(list), + }, + { + name: "dollars", + title: `Sent ($) ${title}`, + bottom: createGroupedSentDollarsSeries(list), + }, + ], }, ], }, diff --git a/website/scripts/options/distribution/data.js b/website/scripts/options/distribution/data.js index cabf30f46..93a7ef68a 100644 --- a/website/scripts/options/distribution/data.js +++ b/website/scripts/options/distribution/data.js @@ -92,8 +92,8 @@ export function buildCohortData(colors, brk) { }; }); - // Min age cohorts (from X time) - CohortBasic (neither adjustedSopr nor percentiles) - /** @type {readonly CohortBasic[]} */ + // Min age cohorts (from X time) - CohortBasicWithMarketCap (has RelToMarketCap) + /** @type {readonly CohortBasicWithMarketCap[]} */ const fromDate = entries(utxoCohorts.minAge).map(([key, tree]) => { const names = MIN_AGE_NAMES[key]; return { @@ -116,8 +116,8 @@ export function buildCohortData(colors, brk) { }; }); - // Epoch cohorts - CohortBasic (neither adjustedSopr nor percentiles) - /** @type {readonly CohortBasic[]} */ + // Epoch cohorts - CohortBasicWithoutMarketCap (no RelToMarketCap) + /** @type {readonly CohortBasicWithoutMarketCap[]} */ const epoch = entries(utxoCohorts.epoch).map(([key, tree]) => { const names = EPOCH_NAMES[key]; return { @@ -128,8 +128,8 @@ export function buildCohortData(colors, brk) { }; }); - // UTXOs above amount - CohortBasic (neither adjustedSopr nor percentiles) - /** @type {readonly CohortBasic[]} */ + // UTXOs above amount - CohortBasicWithMarketCap (has RelToMarketCap) + /** @type {readonly CohortBasicWithMarketCap[]} */ const utxosAboveAmount = entries(utxoCohorts.geAmount).map(([key, tree]) => { const names = GE_AMOUNT_NAMES[key]; return { @@ -154,8 +154,8 @@ export function buildCohortData(colors, brk) { }, ); - // UTXOs under amount - CohortBasic (neither adjustedSopr nor percentiles) - /** @type {readonly CohortBasic[]} */ + // UTXOs under amount - CohortBasicWithMarketCap (has RelToMarketCap) + /** @type {readonly CohortBasicWithMarketCap[]} */ const utxosUnderAmount = entries(utxoCohorts.ltAmount).map(([key, tree]) => { const names = LT_AMOUNT_NAMES[key]; return { @@ -180,8 +180,8 @@ export function buildCohortData(colors, brk) { }, ); - // UTXOs amount ranges - CohortBasic (neither adjustedSopr nor percentiles) - /** @type {readonly CohortBasic[]} */ + // UTXOs amount ranges - CohortBasicWithoutMarketCap (no RelToMarketCap) + /** @type {readonly CohortBasicWithoutMarketCap[]} */ const utxosAmountRanges = entries(utxoCohorts.amountRange).map( ([key, tree]) => { const names = AMOUNT_RANGE_NAMES[key]; @@ -221,7 +221,7 @@ export function buildCohortData(colors, brk) { }; }); - /** @type {readonly CohortBasic[]} */ + /** @type {readonly CohortBasicWithoutMarketCap[]} */ const typeOther = entries(utxoCohorts.type) .filter(([key]) => !isAddressable(key)) .map(([key, tree]) => { @@ -234,8 +234,8 @@ export function buildCohortData(colors, brk) { }; }); - // Year cohorts - CohortBasic (neither adjustedSopr nor percentiles) - /** @type {readonly CohortBasic[]} */ + // Year cohorts - CohortBasicWithoutMarketCap (no RelToMarketCap) + /** @type {readonly CohortBasicWithoutMarketCap[]} */ const year = entries(utxoCohorts.year).map(([key, tree]) => { const names = YEAR_NAMES[key]; return { diff --git a/website/scripts/options/distribution/index.js b/website/scripts/options/distribution/index.js index 5681cce0f..4662911b5 100644 --- a/website/scripts/options/distribution/index.js +++ b/website/scripts/options/distribution/index.js @@ -11,7 +11,8 @@ export { createCohortFolderFull, createCohortFolderWithAdjusted, createCohortFolderWithPercentiles, - createCohortFolderBasic, + createCohortFolderBasicWithMarketCap, + createCohortFolderBasicWithoutMarketCap, createCohortFolderAddress, } from "./utxo.js"; export { createAddressCohortFolder } from "./address.js"; @@ -27,6 +28,5 @@ export { createRealizedPriceSeries, createRealizedPriceRatioSeries, createRealizedCapSeries, - createCostBasisMinMaxSeries, createCostBasisPercentilesSeries, } from "./shared.js"; diff --git a/website/scripts/options/distribution/shared.js b/website/scripts/options/distribution/shared.js index 8d0b53cd7..10f8a1b7a 100644 --- a/website/scripts/options/distribution/shared.js +++ b/website/scripts/options/distribution/shared.js @@ -221,72 +221,256 @@ export function createRealizedCapSeries(list, useGroupName) { } /** - * Create cost basis min/max series (available on all cohorts) - * @param {readonly CohortObject[]} list + * Create cost basis percentile series (only for cohorts with CostBasisPattern2) + * Includes min (p0) and max (p100) with full rainbow coloring + * @param {Colors} colors + * @param {readonly CohortWithCostBasisPercentiles[]} list * @param {boolean} useGroupName * @returns {AnyFetchedSeriesBlueprint[]} */ -export function createCostBasisMinMaxSeries(list, useGroupName) { - return list.flatMap(({ color, name, tree }) => [ +export function createCostBasisPercentilesSeries(colors, list, useGroupName) { + return list.flatMap(({ name, tree }) => { + const cb = tree.costBasis; + const p = cb.percentiles; + const n = (/** @type {number} */ pct) => (useGroupName ? `${name} p${pct}` : `p${pct}`); + return [ + line({ metric: cb.max, name: n(100), color: colors.purple, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct95, name: n(95), color: colors.fuchsia, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct90, name: n(90), color: colors.pink, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct85, name: n(85), color: colors.pink, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct80, name: n(80), color: colors.rose, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct75, name: n(75), color: colors.red, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct70, name: n(70), color: colors.orange, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct65, name: n(65), color: colors.amber, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct60, name: n(60), color: colors.yellow, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct55, name: n(55), color: colors.yellow, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct50, name: n(50), color: colors.avocado, unit: Unit.usd }), + line({ metric: p.pct45, name: n(45), color: colors.lime, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct40, name: n(40), color: colors.green, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct35, name: n(35), color: colors.emerald, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct30, name: n(30), color: colors.teal, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct25, name: n(25), color: colors.teal, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct20, name: n(20), color: colors.cyan, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct15, name: n(15), color: colors.sky, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct10, name: n(10), color: colors.blue, unit: Unit.usd, defaultActive: false }), + line({ metric: p.pct05, name: n(5), color: colors.indigo, unit: Unit.usd, defaultActive: false }), + line({ metric: cb.min, name: n(0), color: colors.violet, unit: Unit.usd, defaultActive: false }), + ]; + }); +} + +// ============================================================================ +// Activity Section Helpers +// ============================================================================ + +/** + * Create coins destroyed series (coinblocks, coindays, satblocks, satdays) for single cohort + * All metrics on one chart + * @param {CohortObject} cohort + * @returns {AnyFetchedSeriesBlueprint[]} + */ +export function createSingleCoinsDestroyedSeries(cohort) { + const { tree, color } = cohort; + return [ line({ - metric: tree.costBasis.min, - name: useGroupName ? `${name} min` : "Min", + metric: tree.activity.coinblocksDestroyed.sum, + name: "Coinblocks", color, - unit: Unit.usd, + unit: Unit.coinblocks, }), line({ - metric: tree.costBasis.max, - name: useGroupName ? `${name} max` : "Max", + metric: tree.activity.coinblocksDestroyed.cumulative, + name: "Coinblocks Cumulative", color, - unit: Unit.usd, + unit: Unit.coinblocks, + defaultActive: false, + }), + line({ + metric: tree.activity.coindaysDestroyed.sum, + name: "Coindays", + color, + unit: Unit.coindays, + }), + line({ + metric: tree.activity.coindaysDestroyed.cumulative, + name: "Coindays Cumulative", + color, + unit: Unit.coindays, + defaultActive: false, + }), + line({ + metric: tree.activity.satblocksDestroyed, + name: "Satblocks", + color, + unit: Unit.satblocks, + }), + line({ + metric: tree.activity.satdaysDestroyed, + name: "Satdays", + color, + unit: Unit.satdays, + }), + ]; +} + +/** + * Create coinblocks destroyed series for grouped cohorts (comparison) + * @param {readonly CohortObject[]} list + * @returns {AnyFetchedSeriesBlueprint[]} + */ +export function createGroupedCoinblocksDestroyedSeries(list) { + return list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.activity.coinblocksDestroyed.sum, + name, + color, + unit: Unit.coinblocks, }), ]); } /** - * Create cost basis percentile series (only for cohorts with CostBasisPattern2) - * @param {readonly CohortWithCostBasisPercentiles[]} list - * @param {boolean} useGroupName + * Create coindays destroyed series for grouped cohorts (comparison) + * @param {readonly CohortObject[]} list * @returns {AnyFetchedSeriesBlueprint[]} */ -export function createCostBasisPercentilesSeries(list, useGroupName) { - return list.flatMap(({ color, name, tree }) => { - const percentiles = tree.costBasis.percentiles; - return [ - line({ - metric: percentiles.pct10, - name: useGroupName ? `${name} p10` : "p10", - color, - unit: Unit.usd, - defaultActive: false, - }), - line({ - metric: percentiles.pct25, - name: useGroupName ? `${name} p25` : "p25", - color, - unit: Unit.usd, - defaultActive: false, - }), - line({ - metric: percentiles.pct50, - name: useGroupName ? `${name} p50` : "p50", - color, - unit: Unit.usd, - }), - line({ - metric: percentiles.pct75, - name: useGroupName ? `${name} p75` : "p75", - color, - unit: Unit.usd, - defaultActive: false, - }), - line({ - metric: percentiles.pct90, - name: useGroupName ? `${name} p90` : "p90", - color, - unit: Unit.usd, - defaultActive: false, - }), - ]; - }); +export function createGroupedCoindaysDestroyedSeries(list) { + return list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.activity.coindaysDestroyed.sum, + name, + color, + unit: Unit.coindays, + }), + ]); +} + +/** + * Create satblocks destroyed series for grouped cohorts (comparison) + * @param {readonly CohortObject[]} list + * @returns {AnyFetchedSeriesBlueprint[]} + */ +export function createGroupedSatblocksDestroyedSeries(list) { + return list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.activity.satblocksDestroyed, + name, + color, + unit: Unit.satblocks, + }), + ]); +} + +/** + * Create satdays destroyed series for grouped cohorts (comparison) + * @param {readonly CohortObject[]} list + * @returns {AnyFetchedSeriesBlueprint[]} + */ +export function createGroupedSatdaysDestroyedSeries(list) { + return list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.activity.satdaysDestroyed, + name, + color, + unit: Unit.satdays, + }), + ]); +} + +/** + * Create sent series (sats, btc, usd) for single cohort - all on one chart + * @param {CohortObject} cohort + * @returns {AnyFetchedSeriesBlueprint[]} + */ +export function createSingleSentSeries(cohort) { + const { tree, color } = cohort; + return [ + line({ + metric: tree.activity.sent.sats.sum, + name: "Sent", + color, + unit: Unit.sats, + }), + line({ + metric: tree.activity.sent.sats.cumulative, + name: "Cumulative", + color, + unit: Unit.sats, + defaultActive: false, + }), + line({ + metric: tree.activity.sent.bitcoin.sum, + name: "Sent", + color, + unit: Unit.btc, + }), + line({ + metric: tree.activity.sent.bitcoin.cumulative, + name: "Cumulative", + color, + unit: Unit.btc, + defaultActive: false, + }), + line({ + metric: tree.activity.sent.dollars.sum, + name: "Sent", + color, + unit: Unit.usd, + }), + line({ + metric: tree.activity.sent.dollars.cumulative, + name: "Cumulative", + color, + unit: Unit.usd, + defaultActive: false, + }), + ]; +} + +/** + * Create sent (sats) series for grouped cohorts (comparison) + * @param {readonly CohortObject[]} list + * @returns {AnyFetchedSeriesBlueprint[]} + */ +export function createGroupedSentSatsSeries(list) { + return list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.activity.sent.sats.sum, + name, + color, + unit: Unit.sats, + }), + ]); +} + +/** + * Create sent (bitcoin) series for grouped cohorts (comparison) + * @param {readonly CohortObject[]} list + * @returns {AnyFetchedSeriesBlueprint[]} + */ +export function createGroupedSentBitcoinSeries(list) { + return list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.activity.sent.bitcoin.sum, + name, + color, + unit: Unit.btc, + }), + ]); +} + +/** + * Create sent (dollars) series for grouped cohorts (comparison) + * @param {readonly CohortObject[]} list + * @returns {AnyFetchedSeriesBlueprint[]} + */ +export function createGroupedSentDollarsSeries(list) { + return list.flatMap(({ color, name, tree }) => [ + line({ + metric: tree.activity.sent.dollars.sum, + name, + color, + unit: Unit.usd, + }), + ]); } diff --git a/website/scripts/options/distribution/utxo.js b/website/scripts/options/distribution/utxo.js index ce2cf9a28..9abf7197a 100644 --- a/website/scripts/options/distribution/utxo.js +++ b/website/scripts/options/distribution/utxo.js @@ -58,7 +58,7 @@ export function createCohortFolderAll(ctx, args) { createSingleAddrCountChart(ctx, args, title), createSingleRealizedSectionFull(ctx, args, title), createSingleUnrealizedSectionAll(ctx, args, title), - createSingleCostBasisSectionWithPercentiles(args, title), + createSingleCostBasisSectionWithPercentiles(ctx, args, title), createSingleActivitySectionWithAdjusted(ctx, args, title), ], }; @@ -81,7 +81,7 @@ export function createCohortFolderFull(ctx, args) { createGroupedUtxoCountChart(list, title), createGroupedRealizedSectionWithAdjusted(ctx, list, title), createGroupedUnrealizedSectionFull(ctx, list, title), - createGroupedCostBasisSectionWithPercentiles(list, title), + createGroupedCostBasisSectionWithPercentiles(ctx, list, title), createGroupedActivitySectionWithAdjusted(list, title), ], }; @@ -94,7 +94,7 @@ export function createCohortFolderFull(ctx, args) { createSingleUtxoCountChart(args, title), createSingleRealizedSectionFull(ctx, args, title), createSingleUnrealizedSectionFull(ctx, args, title), - createSingleCostBasisSectionWithPercentiles(args, title), + createSingleCostBasisSectionWithPercentiles(ctx, args, title), createSingleActivitySectionWithAdjusted(ctx, args, title), ], }; @@ -153,7 +153,7 @@ export function createCohortFolderWithPercentiles(ctx, args) { createGroupedUtxoCountChart(list, title), createGroupedRealizedSectionBasic(ctx, list, title), createGroupedUnrealizedSectionWithOwnCaps(ctx, list, title), - createGroupedCostBasisSectionWithPercentiles(list, title), + createGroupedCostBasisSectionWithPercentiles(ctx, list, title), createGroupedActivitySectionBasic(list, title), ], }; @@ -166,19 +166,55 @@ export function createCohortFolderWithPercentiles(ctx, args) { createSingleUtxoCountChart(args, title), createSingleRealizedSectionWithPercentiles(ctx, args, title), createSingleUnrealizedSectionWithOwnCaps(ctx, args, title), - createSingleCostBasisSectionWithPercentiles(args, title), + createSingleCostBasisSectionWithPercentiles(ctx, args, title), createSingleActivitySectionBasic(ctx, args, title), ], }; } /** - * Basic folder: no adjustedSopr, no percentiles (minAge.*, epoch.*, amount cohorts) + * Basic folder WITH RelToMarketCap (minAge.*, geAmount.*, ltAmount.*, type.*) * @param {PartialContext} ctx - * @param {CohortBasic | CohortGroupBasic} args + * @param {CohortBasicWithMarketCap | CohortGroupBasicWithMarketCap} args * @returns {PartialOptionsGroup} */ -export function createCohortFolderBasic(ctx, args) { +export function createCohortFolderBasicWithMarketCap(ctx, args) { + if ("list" in args) { + const { list } = args; + const title = args.title ? `by ${args.title}` : ""; + return { + name: args.name || "all", + tree: [ + createGroupedSupplySection(list, title), + createGroupedUtxoCountChart(list, title), + createGroupedRealizedSectionBasic(ctx, list, title), + createGroupedUnrealizedSectionWithMarketCapOnly(ctx, list, title), + createGroupedCostBasisSection(list, title), + createGroupedActivitySectionBasic(list, title), + ], + }; + } + const title = args.title ? `of ${args.title}` : ""; + return { + name: args.name || "all", + tree: [ + createSingleSupplyChart(ctx, args, title), + createSingleUtxoCountChart(args, title), + createSingleRealizedSectionBasic(ctx, args, title), + createSingleUnrealizedSectionWithMarketCapOnly(ctx, args, title), + createSingleCostBasisSection(args, title), + createSingleActivitySectionBasic(ctx, args, title), + ], + }; +} + +/** + * Basic folder WITHOUT RelToMarketCap (epoch.*, amountRange.*, year.*) + * @param {PartialContext} ctx + * @param {CohortBasicWithoutMarketCap | CohortGroupBasicWithoutMarketCap} args + * @returns {PartialOptionsGroup} + */ +export function createCohortFolderBasicWithoutMarketCap(ctx, args) { if ("list" in args) { const { list } = args; const title = args.title ? `by ${args.title}` : ""; @@ -217,6 +253,7 @@ export function createCohortFolderBasic(ctx, args) { /** * Address folder: like basic but with address count (addressable type cohorts) + * Uses base unrealized section (no RelToMarketCap since it extends CohortBasicWithoutMarketCap) * @param {PartialContext} ctx * @param {CohortAddress | CohortGroupAddress} args * @returns {PartialOptionsGroup} @@ -468,7 +505,7 @@ function createSingleRealizedSectionWithPercentiles(ctx, cohort, title) { /** * Create realized section for CohortBasic (no adjustedSopr, partial ratio) * @param {PartialContext} ctx - * @param {CohortBasic} cohort + * @param {CohortBasic | CohortAddress} cohort * @param {string} title * @returns {PartialOptionsGroup} */ @@ -491,7 +528,7 @@ function createSingleRealizedSectionBasic(ctx, cohort, title) { /** * Create realized section without adjusted SOPR for grouped cohorts * @param {PartialContext} ctx - * @param {readonly (CohortWithPercentiles | CohortBasic)[]} list + * @param {readonly (CohortWithPercentiles | CohortBasic | CohortAddress)[]} list * @param {string} title * @returns {PartialOptionsGroup} */ @@ -558,10 +595,11 @@ function createSingleRealizedPriceChartsWithRatio(ctx, cohort, title) { return [ createSingleRealizedPriceChart(cohort, title), createRatioChart(ctx, { - title: `Realized Price ${title}`, + title, price: tree.realized.realizedPrice, ratio, color, + name: "MVRV", }), createZScoresFolder(ctx, { title: `Realized Price ${title}`, @@ -577,7 +615,7 @@ function createSingleRealizedPriceChartsWithRatio(ctx, cohort, title) { * Create realized price and basic ratio charts for cohorts with RealizedPriceExtraPattern * (CohortWithAdjusted, CohortBasic have RealizedPattern/4 which has RealizedPriceExtraPattern) * @param {PartialContext} ctx - * @param {CohortWithAdjusted | CohortBasic} cohort + * @param {CohortWithAdjusted | CohortBasic | CohortAddress} cohort * @param {string} title * @returns {PartialChartOption[]} */ @@ -617,6 +655,13 @@ function createSingleRealizedCapSeries(ctx, cohort) { color, unit: Unit.usd, }), + line({ + metric: tree.realized.realizedValue, + name: "Value", + color, + unit: Unit.usd, + defaultActive: false, + }), baseline({ metric: tree.realized.realizedCap30dDelta, name: "30d change", @@ -689,8 +734,8 @@ function createSingleRealizedPnlSection(ctx, cohort, title) { ), ...fromBitcoinPatternWithUnit( tree.realized.negRealizedLoss, - "Negative Loss", Unit.usd, + "Negative Loss", colors.red, ), ...("realizedProfitToLossRatio" in tree.realized @@ -716,12 +761,26 @@ function createSingleRealizedPnlSection(ctx, cohort, title) { color: colors.green, unit: Unit.pctRcap, }), + baseline({ + metric: tree.realized.realizedProfitRelToRealizedCap.cumulative, + name: "Profit Cumulative", + color: colors.green, + unit: Unit.pctRcap, + defaultActive: false, + }), baseline({ metric: tree.realized.realizedLossRelToRealizedCap.sum, name: "Loss", color: colors.red, unit: Unit.pctRcap, }), + baseline({ + metric: tree.realized.realizedLossRelToRealizedCap.cumulative, + name: "Loss Cumulative", + color: colors.red, + unit: Unit.pctRcap, + defaultActive: false, + }), priceLine({ ctx, unit: Unit.pctRcap }), priceLine({ ctx, unit: Unit.usd, defaultActive: false }), ], @@ -746,6 +805,12 @@ function createSingleRealizedPnlSection(ctx, cohort, title) { name: "Net", unit: Unit.pctRcap, }), + baseline({ + metric: tree.realized.netRealizedPnlRelToRealizedCap.cumulative, + name: "Net Cumulative", + unit: Unit.pctRcap, + defaultActive: false, + }), baseline({ metric: tree.realized.netRealizedPnlCumulative30dDeltaRelToRealizedCap, @@ -900,7 +965,6 @@ function createGroupedRealizedPnlSections(ctx, list, title) { name, color, unit: Unit.usd, - defaultActive: false, }), ]), priceLine({ ctx, unit: Unit.usd }), @@ -980,7 +1044,7 @@ function createSingleBaseSoprChart(ctx, cohort, title) { metric: tree.realized.sopr, name: "SOPR", unit: Unit.ratio, - options: { baseValue: { price: 1 } }, + base: 1, }), baseline({ metric: tree.realized.sopr7dEma, @@ -988,7 +1052,7 @@ function createSingleBaseSoprChart(ctx, cohort, title) { color: [colors.lime, colors.rose], unit: Unit.ratio, defaultActive: false, - options: { baseValue: { price: 1 } }, + base: 1, }), baseline({ metric: tree.realized.sopr30dEma, @@ -996,7 +1060,7 @@ function createSingleBaseSoprChart(ctx, cohort, title) { color: [colors.avocado, colors.pink], unit: Unit.ratio, defaultActive: false, - options: { baseValue: { price: 1 } }, + base: 1, }), priceLine({ ctx, number: 1, unit: Unit.ratio }), ], @@ -1064,7 +1128,7 @@ function createGroupedBaseSoprChart(ctx, list, title) { name, color, unit: Unit.ratio, - options: { baseValue: { price: 1 } }, + base: 1, }), baseline({ metric: tree.realized.sopr7dEma, @@ -1072,7 +1136,7 @@ function createGroupedBaseSoprChart(ctx, list, title) { color, unit: Unit.ratio, defaultActive: false, - options: { baseValue: { price: 1 } }, + base: 1, }), baseline({ metric: tree.realized.sopr30dEma, @@ -1080,7 +1144,7 @@ function createGroupedBaseSoprChart(ctx, list, title) { color, unit: Unit.ratio, defaultActive: false, - options: { baseValue: { price: 1 } }, + base: 1, }), ]), priceLine({ ctx, number: 1, unit: Unit.ratio }), @@ -1171,7 +1235,7 @@ function createGroupedSoprSectionWithAdjusted(ctx, list, title) { /** * Create SOPR section without adjusted SOPR (for cohorts with RealizedPattern/2) * @param {PartialContext} ctx - * @param {CohortWithPercentiles | CohortBasic} cohort + * @param {CohortWithPercentiles | CohortBasic | CohortAddress} cohort * @param {string} title * @returns {PartialOptionsGroup} */ @@ -1185,7 +1249,7 @@ function createSingleSoprSectionBasic(ctx, cohort, title) { /** * Create grouped SOPR section without adjusted SOPR * @param {PartialContext} ctx - * @param {readonly (CohortWithPercentiles | CohortBasic)[]} list + * @param {readonly (CohortWithPercentiles | CohortBasic | CohortAddress)[]} list * @param {string} title * @returns {PartialOptionsGroup} */ @@ -1378,8 +1442,7 @@ function createNetUnrealizedPnlBaseMetric(tree) { return baseline({ metric: tree.unrealized.netUnrealizedPnl, name: "Net", - unit: Unit.ratio, - options: { baseValue: { price: 0 } }, + unit: Unit.usd, }); } @@ -1457,6 +1520,18 @@ function createSingleUnrealizedSectionFull(ctx, cohort, title) { priceLine({ ctx, unit: Unit.pctMcap }), ], }, + { + name: "nupl", + title: `NUPL ${title}`, + bottom: [ + baseline({ + metric: tree.relative.nupl, + name: "NUPL", + unit: Unit.ratio, + }), + priceLine({ ctx, unit: Unit.ratio }), + ], + }, ], }; } @@ -1493,6 +1568,22 @@ function createSingleUnrealizedSectionWithMarketCap(ctx, cohort, title) { priceLine({ ctx, unit: Unit.pctMcap }), ], }, + ...("nupl" in tree.relative + ? [ + { + name: "nupl", + title: `NUPL ${title}`, + bottom: [ + baseline({ + metric: tree.relative.nupl, + name: "NUPL", + unit: Unit.ratio, + }), + priceLine({ ctx, unit: Unit.ratio }), + ], + }, + ] + : []), ], }; } @@ -1530,20 +1621,91 @@ function createSingleUnrealizedSectionWithOwnCaps(ctx, cohort, title) { priceLine({ ctx, unit: Unit.usd }), ], }, + ...("nupl" in tree.relative + ? [ + { + name: "nupl", + title: `NUPL ${title}`, + bottom: [ + baseline({ + metric: tree.relative.nupl, + name: "NUPL", + unit: Unit.ratio, + }), + priceLine({ ctx, unit: Unit.ratio }), + ], + }, + ] + : []), ], }; } /** - * Unrealized section with only base metrics (no relative unrealized) - * Used by: Epoch cohorts (RelativePattern4) + * Unrealized section WITH RelToMarketCap metrics (for CohortBasicWithMarketCap) + * Used by: minAge.*, geAmount.*, ltAmount.* * @param {PartialContext} ctx - * @param {{ tree: { unrealized: PatternAll["unrealized"] } }} cohort + * @param {CohortBasicWithMarketCap} cohort + * @param {string} title + * @returns {PartialOptionsGroup} + */ +function createSingleUnrealizedSectionWithMarketCapOnly(ctx, cohort, title) { + const { tree } = cohort; + + return { + name: "Unrealized", + tree: [ + { + name: "pnl", + title: `Unrealized P&L ${title}`, + bottom: [ + ...createUnrealizedPnlBaseMetrics(ctx, tree), + ...createUnrealizedPnlRelToMarketCapMetrics(ctx, tree.relative), + priceLine({ ctx, unit: Unit.usd, defaultActive: false }), + priceLine({ ctx, unit: Unit.pctMcap, defaultActive: false }), + ], + }, + { + name: "Net pnl", + title: `Net Unrealized P&L ${title}`, + bottom: [ + createNetUnrealizedPnlBaseMetric(tree), + ...createNetUnrealizedPnlRelToMarketCapMetrics(tree.relative), + priceLine({ ctx, unit: Unit.usd }), + priceLine({ ctx, unit: Unit.pctMcap }), + ], + }, + ...("nupl" in tree.relative + ? [ + { + name: "nupl", + title: `NUPL ${title}`, + bottom: [ + baseline({ + metric: tree.relative.nupl, + name: "NUPL", + unit: Unit.ratio, + }), + priceLine({ ctx, unit: Unit.ratio }), + ], + }, + ] + : []), + ], + }; +} + +/** + * Unrealized section with only base metrics (no RelToMarketCap) + * Used by: epoch.*, amountRange.*, year.* + * @param {PartialContext} ctx + * @param {CohortBasicWithoutMarketCap} cohort * @param {string} title * @returns {PartialOptionsGroup} */ function createSingleUnrealizedSectionBase(ctx, cohort, title) { const { tree } = cohort; + return { name: "Unrealized", tree: [ @@ -1634,7 +1796,7 @@ function createGroupedUnrealizedSectionFull(ctx, list, title) { metric: tree.unrealized.netUnrealizedPnl, name, color, - unit: Unit.ratio, + unit: Unit.usd, }), baseline({ metric: tree.relative.netUnrealizedPnlRelToMarketCap, @@ -1661,6 +1823,21 @@ function createGroupedUnrealizedSectionFull(ctx, list, title) { priceLine({ ctx, unit: Unit.pctOwnPnl }), ], }, + { + name: "nupl", + title: `NUPL ${title}`, + bottom: [ + ...list.flatMap(({ color, name, tree }) => [ + baseline({ + metric: tree.relative.nupl, + name, + color, + unit: Unit.ratio, + }), + ]), + priceLine({ ctx, unit: Unit.ratio }), + ], + }, ], }; } @@ -1686,7 +1863,7 @@ function createGroupedUnrealizedSectionWithMarketCap(ctx, list, title) { metric: tree.unrealized.netUnrealizedPnl, name, color, - unit: Unit.ratio, + unit: Unit.usd, }), baseline({ metric: tree.relative.netUnrealizedPnlRelToMarketCap, @@ -1699,6 +1876,21 @@ function createGroupedUnrealizedSectionWithMarketCap(ctx, list, title) { priceLine({ ctx, unit: Unit.pctMcap }), ], }, + { + name: "nupl", + title: `NUPL ${title}`, + bottom: [ + ...list.flatMap(({ color, name, tree }) => [ + baseline({ + metric: tree.relative.nupl, + name, + color, + unit: Unit.ratio, + }), + ]), + priceLine({ ctx, unit: Unit.ratio }), + ], + }, ], }; } @@ -1711,6 +1903,7 @@ function createGroupedUnrealizedSectionWithMarketCap(ctx, list, title) { * @returns {PartialOptionsGroup} */ function createGroupedUnrealizedSectionWithOwnCaps(ctx, list, title) { + const cohortsWithNupl = list.filter(({ tree }) => "nupl" in tree.relative); return { name: "Unrealized", tree: [ @@ -1724,7 +1917,7 @@ function createGroupedUnrealizedSectionWithOwnCaps(ctx, list, title) { metric: tree.unrealized.netUnrealizedPnl, name, color, - unit: Unit.ratio, + unit: Unit.usd, }), baseline({ metric: tree.relative.netUnrealizedPnlRelToOwnMarketCap, @@ -1744,14 +1937,89 @@ function createGroupedUnrealizedSectionWithOwnCaps(ctx, list, title) { priceLine({ ctx, unit: Unit.pctOwnPnl }), ], }, + ...(cohortsWithNupl.length > 0 + ? [ + { + name: "nupl", + title: `NUPL ${title}`, + bottom: [ + ...cohortsWithNupl.flatMap(({ color, name, tree }) => [ + baseline({ + metric: /** @type {{ nupl: AnyMetricPattern }} */ ( + tree.relative + ).nupl, + name, + color, + unit: Unit.ratio, + }), + ]), + priceLine({ ctx, unit: Unit.ratio }), + ], + }, + ] + : []), ], }; } /** - * Grouped unrealized section for Basic cohorts (base only) + * Grouped unrealized section WITH RelToMarketCap (for CohortBasicWithMarketCap) + * Used by: minAge.*, geAmount.*, ltAmount.* * @param {PartialContext} ctx - * @param {readonly CohortBasic[]} list + * @param {readonly CohortBasicWithMarketCap[]} list + * @param {string} title + * @returns {PartialOptionsGroup} + */ +function createGroupedUnrealizedSectionWithMarketCapOnly(ctx, list, title) { + return { + name: "Unrealized", + tree: [ + ...createGroupedUnrealizedBaseCharts(list, title), + { + name: "Net pnl", + title: `Net Unrealized P&L ${title}`, + bottom: [ + ...list.flatMap(({ color, name, tree }) => [ + baseline({ + metric: tree.unrealized.netUnrealizedPnl, + name, + color, + unit: Unit.usd, + }), + baseline({ + metric: tree.relative.netUnrealizedPnlRelToMarketCap, + name, + color, + unit: Unit.pctMcap, + }), + ]), + priceLine({ ctx, unit: Unit.usd }), + priceLine({ ctx, unit: Unit.pctMcap }), + ], + }, + { + name: "nupl", + title: `NUPL ${title}`, + bottom: [ + ...list.flatMap(({ color, name, tree }) => [ + baseline({ + metric: tree.relative.nupl, + name, + color, + unit: Unit.ratio, + }), + ]), + priceLine({ ctx, unit: Unit.ratio }), + ], + }, + ], + }; +} + +/** + * Grouped unrealized section without RelToMarketCap (for CohortBasicWithoutMarketCap) + * @param {PartialContext} ctx + * @param {readonly CohortBasicWithoutMarketCap[]} list * @param {string} title * @returns {PartialOptionsGroup} */ @@ -1769,7 +2037,7 @@ function createGroupedUnrealizedSectionBase(ctx, list, title) { metric: tree.unrealized.netUnrealizedPnl, name, color, - unit: Unit.ratio, + unit: Unit.usd, }), ]), priceLine({ ctx, unit: Unit.usd }), @@ -1781,11 +2049,13 @@ function createGroupedUnrealizedSectionBase(ctx, list, title) { /** * Create cost basis section for single cohort WITH percentiles + * @param {PartialContext} ctx * @param {CohortAll | CohortFull | CohortWithPercentiles} cohort * @param {string} title * @returns {PartialOptionsGroup} */ -function createSingleCostBasisSectionWithPercentiles(cohort, title) { +function createSingleCostBasisSectionWithPercentiles(ctx, cohort, title) { + const { colors } = ctx; const { color, tree } = cohort; return { @@ -1819,7 +2089,7 @@ function createSingleCostBasisSectionWithPercentiles(cohort, title) { { name: "percentiles", title: `Cost Basis Percentiles ${title}`, - top: createCostBasisPercentilesSeries([cohort], false), + top: createCostBasisPercentilesSeries(colors, [cohort], false), }, ], }; @@ -1827,11 +2097,13 @@ function createSingleCostBasisSectionWithPercentiles(cohort, title) { /** * Create cost basis section for grouped cohorts WITH percentiles + * @param {PartialContext} ctx * @param {readonly (CohortFull | CohortWithPercentiles)[]} list * @param {string} title * @returns {PartialOptionsGroup} */ -function createGroupedCostBasisSectionWithPercentiles(list, title) { +function createGroupedCostBasisSectionWithPercentiles(ctx, list, title) { + const { colors } = ctx; return { name: "Cost Basis", tree: [ @@ -1861,13 +2133,18 @@ function createGroupedCostBasisSectionWithPercentiles(list, title) { line({ metric: tree.costBasis.max, name, color, unit: Unit.usd }), ), }, + { + name: "percentiles", + title: `Cost Basis Percentiles ${title}`, + top: createCostBasisPercentilesSeries(colors, list, true), + }, ], }; } /** * Create cost basis section for single cohort (no percentiles) - * @param {CohortWithAdjusted | CohortBasic} cohort + * @param {CohortWithAdjusted | CohortBasic | CohortAddress} cohort * @param {string} title * @returns {PartialOptionsGroup} */ @@ -1908,7 +2185,7 @@ function createSingleCostBasisSection(cohort, title) { /** * Create cost basis section for grouped cohorts (no percentiles) - * @param {readonly (CohortWithAdjusted | CohortBasic)[]} list + * @param {readonly (CohortWithAdjusted | CohortBasic | CohortAddress)[]} list * @param {string} title * @returns {PartialOptionsGroup} */ @@ -1954,12 +2231,36 @@ function createGroupedCostBasisSection(list, title) { * @returns {PartialOptionsGroup} */ function createSingleActivitySectionWithAdjusted(ctx, cohort, title) { - const { colors } = ctx; + const { colors, fromBlockCountWithUnit, fromBitcoinPatternWithUnit } = ctx; const { tree, color } = cohort; return { name: "Activity", tree: [ + { + name: "Sent", + title: `Sent ${title}`, + bottom: [ + ...fromBlockCountWithUnit( + tree.activity.sent.sats, + Unit.sats, + undefined, + color, + ), + ...fromBitcoinPatternWithUnit( + tree.activity.sent.bitcoin, + Unit.btc, + undefined, + color, + ), + ...fromBlockCountWithUnit( + tree.activity.sent.dollars, + Unit.usd, + undefined, + color, + ), + ], + }, { name: "Sell Side Risk", title: `Sell Side Risk Ratio ${title}`, @@ -2046,6 +2347,18 @@ function createSingleActivitySectionWithAdjusted(ctx, cohort, title) { unit: Unit.coindays, defaultActive: false, }), + line({ + metric: tree.activity.satblocksDestroyed, + name: "Satblocks", + color, + unit: Unit.satblocks, + }), + line({ + metric: tree.activity.satdaysDestroyed, + name: "Satdays", + color, + unit: Unit.satdays, + }), ], }, ], @@ -2055,17 +2368,41 @@ function createSingleActivitySectionWithAdjusted(ctx, cohort, title) { /** * Create activity section without adjusted values (for cohorts with RealizedPattern/2) * @param {PartialContext} ctx - * @param {CohortWithPercentiles | CohortBasic} cohort + * @param {CohortWithPercentiles | CohortBasic | CohortAddress} cohort * @param {string} title * @returns {PartialOptionsGroup} */ function createSingleActivitySectionBasic(ctx, cohort, title) { - const { colors } = ctx; + const { colors, fromBlockCountWithUnit, fromBitcoinPatternWithUnit } = ctx; const { tree, color } = cohort; return { name: "Activity", tree: [ + { + name: "Sent", + title: `Sent ${title}`, + bottom: [ + ...fromBlockCountWithUnit( + tree.activity.sent.sats, + Unit.sats, + undefined, + color, + ), + ...fromBitcoinPatternWithUnit( + tree.activity.sent.bitcoin, + Unit.btc, + undefined, + color, + ), + ...fromBlockCountWithUnit( + tree.activity.sent.dollars, + Unit.usd, + undefined, + color, + ), + ], + }, { name: "Sell Side Risk", title: `Sell Side Risk Ratio ${title}`, @@ -2140,6 +2477,18 @@ function createSingleActivitySectionBasic(ctx, cohort, title) { unit: Unit.coindays, defaultActive: false, }), + line({ + metric: tree.activity.satblocksDestroyed, + name: "Satblocks", + color, + unit: Unit.satblocks, + }), + line({ + metric: tree.activity.satdaysDestroyed, + name: "Satdays", + color, + unit: Unit.satdays, + }), ], }, ], @@ -2278,7 +2627,7 @@ function createGroupedActivitySectionWithAdjusted(list, title) { /** * Create activity section for grouped cohorts without adjusted values (for cohorts with RealizedPattern/2) - * @param {readonly (CohortWithPercentiles | CohortBasic)[]} list + * @param {readonly (CohortWithPercentiles | CohortBasic | CohortAddress)[]} list * @param {string} title * @returns {PartialOptionsGroup} */ diff --git a/website/scripts/options/market/averages.js b/website/scripts/options/market/averages.js index 4b8eece33..8ed834551 100644 --- a/website/scripts/options/market/averages.js +++ b/website/scripts/options/market/averages.js @@ -1,45 +1,69 @@ /** Moving averages section */ import { Unit } from "../../utils/units.js"; -import { priceLine, priceLines } from "../constants.js"; -import { line, baseline } from "../series.js"; -import { - percentileUsdMap, - percentileMap, - sdPatterns, - sdBandsUsd, - sdBandsRatio, -} from "../shared.js"; +import { line } from "../series.js"; +import { createRatioChart, createZScoresFolder } from "../shared.js"; import { periodIdToName } from "./utils.js"; /** - * Build averages data array from market patterns * @param {Colors} colors * @param {MarketMovingAverage} ma */ -export function buildAverages(colors, ma) { +function buildSmaAverages(colors, ma) { return /** @type {const} */ ([ - ["1w", 7, "red", ma.price1wSma, ma.price1wEma], - ["8d", 8, "orange", ma.price8dSma, ma.price8dEma], - ["13d", 13, "amber", ma.price13dSma, ma.price13dEma], - ["21d", 21, "yellow", ma.price21dSma, ma.price21dEma], - ["1m", 30, "lime", ma.price1mSma, ma.price1mEma], - ["34d", 34, "green", ma.price34dSma, ma.price34dEma], - ["55d", 55, "emerald", ma.price55dSma, ma.price55dEma], - ["89d", 89, "teal", ma.price89dSma, ma.price89dEma], - ["144d", 144, "cyan", ma.price144dSma, ma.price144dEma], - ["200d", 200, "sky", ma.price200dSma, ma.price200dEma], - ["1y", 365, "blue", ma.price1ySma, ma.price1yEma], - ["2y", 730, "indigo", ma.price2ySma, ma.price2yEma], - ["200w", 1400, "violet", ma.price200wSma, ma.price200wEma], - ["4y", 1460, "purple", ma.price4ySma, ma.price4yEma], - ]).map(([id, days, colorKey, sma, ema]) => ({ + ["1w", 7, "red", ma.price1wSma], + ["8d", 8, "orange", ma.price8dSma], + ["13d", 13, "amber", ma.price13dSma], + ["21d", 21, "yellow", ma.price21dSma], + ["1m", 30, "lime", ma.price1mSma], + ["34d", 34, "green", ma.price34dSma], + ["55d", 55, "emerald", ma.price55dSma], + ["89d", 89, "teal", ma.price89dSma], + ["111d", 111, "cyan", ma.price111dSma], + ["144d", 144, "sky", ma.price144dSma], + ["200d", 200, "blue", ma.price200dSma], + ["350d", 350, "indigo", ma.price350dSma], + ["1y", 365, "violet", ma.price1ySma], + ["2y", 730, "purple", ma.price2ySma], + ["200w", 1400, "fuchsia", ma.price200wSma], + ["4y", 1460, "pink", ma.price4ySma], + ]).map(([id, days, colorKey, ratio]) => ({ id, name: periodIdToName(id, true), days, color: colors[colorKey], - sma, - ema, + ratio, + })); +} + +/** + * @param {Colors} colors + * @param {MarketMovingAverage} ma + */ +function buildEmaAverages(colors, ma) { + return /** @type {const} */ ([ + ["1w", 7, "red", ma.price1wEma], + ["8d", 8, "orange", ma.price8dEma], + ["12d", 12, "amber", ma.price12dEma], + ["13d", 13, "yellow", ma.price13dEma], + ["21d", 21, "lime", ma.price21dEma], + ["26d", 26, "green", ma.price26dEma], + ["1m", 30, "emerald", ma.price1mEma], + ["34d", 34, "teal", ma.price34dEma], + ["55d", 55, "cyan", ma.price55dEma], + ["89d", 89, "sky", ma.price89dEma], + ["144d", 144, "blue", ma.price144dEma], + ["200d", 200, "indigo", ma.price200dEma], + ["1y", 365, "violet", ma.price1yEma], + ["2y", 730, "purple", ma.price2yEma], + ["200w", 1400, "fuchsia", ma.price200wEma], + ["4y", 1460, "pink", ma.price4yEma], + ]).map(([id, days, colorKey, ratio]) => ({ + id, + name: periodIdToName(id, true), + days, + color: colors[colorKey], + ratio, })); } @@ -50,271 +74,77 @@ export function buildAverages(colors, ma) { * @param {string} args.title * @param {string} args.legend * @param {EmaRatioPattern} args.ratio - * @param {Color} [args.color] + * @param {Color} args.color * @returns {PartialOptionsTree} */ export function createPriceWithRatioOptions( ctx, { title, legend, ratio, color }, ) { - const { colors } = ctx; const priceMetric = ratio.price; - const pctUsdMap = percentileUsdMap(colors, ratio); - const pctMap = percentileMap(colors, ratio); - const sdPats = sdPatterns(ratio); - return [ { name: "price", title, top: [line({ metric: priceMetric, name: legend, color, unit: Unit.usd })], }, - { - name: "Ratio", - title: `${title} Ratio`, - top: [ - line({ metric: priceMetric, name: legend, color, unit: Unit.usd }), - ...pctUsdMap.map(({ name: pctName, prop, color: pctColor }) => - line({ - metric: prop, - name: pctName, - color: pctColor, - defaultActive: false, - unit: Unit.usd, - options: { lineStyle: 1 }, - }), - ), - ], - bottom: [ - baseline({ - metric: ratio.ratio, - name: "Ratio", - base: 1, - unit: Unit.ratio, - }), - .../** @type {const} */ ([ - { - metric: ratio.ratio1wSma, - name: "1w SMA", - color: colors.lime, - }, - { - metric: ratio.ratio1mSma, - name: "1m SMA", - color: colors.teal, - }, - { - metric: ratio.ratio1ySd.sma, - name: "1y SMA", - color: colors.sky, - }, - { - metric: ratio.ratio2ySd.sma, - name: "2y SMA", - color: colors.indigo, - }, - { - metric: ratio.ratio4ySd.sma, - name: "4y SMA", - color: colors.purple, - }, - { - metric: ratio.ratioSd.sma, - name: "All SMA", - color: colors.rose, - }, - ]).map(({ metric, name, color }) => - line({ - metric, - name, - color, - unit: Unit.ratio, - defaultActive: false, - style: 1, - }), - ), - ...pctMap.map(({ name: pctName, prop, color: pctColor }) => - line({ - metric: prop, - name: pctName, - color: pctColor, - defaultActive: false, - unit: Unit.ratio, - style: 1, - }), - ), - priceLine({ ctx, unit: Unit.ratio, number: 1 }), - ], - }, - { - name: "ZScores", - tree: [ - { - name: "Compare", - title: `${title} Z-Scores`, - top: [ - line({ metric: priceMetric, name: legend, color, unit: Unit.usd }), - line({ - metric: ratio.ratio1ySd._0sdUsd, - name: "1y 0σ", - color: colors.orange, - defaultActive: false, - unit: Unit.usd, - }), - line({ - metric: ratio.ratio2ySd._0sdUsd, - name: "2y 0σ", - color: colors.yellow, - defaultActive: false, - unit: Unit.usd, - }), - line({ - metric: ratio.ratio4ySd._0sdUsd, - name: "4y 0σ", - color: colors.lime, - defaultActive: false, - unit: Unit.usd, - }), - line({ - metric: ratio.ratioSd._0sdUsd, - name: "all 0σ", - color: colors.blue, - defaultActive: false, - unit: Unit.usd, - }), - ], - bottom: [ - line({ - metric: ratio.ratioSd.zscore, - name: "all", - color: colors.blue, - unit: Unit.sd, - }), - line({ - metric: ratio.ratio4ySd.zscore, - name: "4y", - color: colors.lime, - unit: Unit.sd, - }), - line({ - metric: ratio.ratio2ySd.zscore, - name: "2y", - color: colors.yellow, - unit: Unit.sd, - }), - line({ - metric: ratio.ratio1ySd.zscore, - name: "1y", - color: colors.orange, - unit: Unit.sd, - }), - ...priceLines({ - ctx, - unit: Unit.sd, - numbers: [0, 1, -1, 2, -2, 3, -3], - defaultActive: false, - }), - ], - }, - ...sdPats.map(({ nameAddon, titleAddon, sd }) => ({ - name: nameAddon, - title: `${title} ${titleAddon} Z-Score`, - top: [ - line({ metric: priceMetric, name: legend, color, unit: Unit.usd }), - ...sdBandsUsd(colors, sd).map( - ({ name: bandName, prop, color: bandColor }) => - line({ - metric: prop, - name: bandName, - color: bandColor, - unit: Unit.usd, - defaultActive: false, - }), - ), - ], - bottom: [ - baseline({ - metric: sd.zscore, - name: "Z-Score", - unit: Unit.sd, - }), - baseline({ - metric: ratio.ratio, - name: "Ratio", - unit: Unit.ratio, - base: 1, - }), - line({ - metric: sd.sd, - name: "Volatility", - color: colors.gray, - unit: Unit.percentage, - }), - ...sdBandsRatio(colors, sd).map( - ({ name: bandName, prop, color: bandColor }) => - line({ - metric: prop, - name: bandName, - color: bandColor, - unit: Unit.ratio, - defaultActive: false, - }), - ), - priceLine({ ctx, unit: Unit.ratio, number: 1 }), - priceLine({ - ctx, - unit: Unit.sd, - }), - ...priceLines({ - ctx, - unit: Unit.sd, - numbers: [1, -1, 2, -2, 3, -3], - defaultActive: false, - }), - ], - })), - ], - }, + createRatioChart(ctx, { title, price: priceMetric, ratio, color }), + createZScoresFolder(ctx, { + title, + legend, + price: priceMetric, + ratio, + color, + }), ]; } /** - * Create Averages section * @param {PartialContext} ctx - * @param {ReturnType} averages + * @param {MarketMovingAverage} movingAverage */ -export function createAveragesSection(ctx, averages) { +export function createAveragesSection(ctx, movingAverage) { + const { colors } = ctx; + const smaAverages = buildSmaAverages(colors, movingAverage); + const emaAverages = buildEmaAverages(colors, movingAverage); + + /** + * @param {string} label + * @param {ReturnType | ReturnType} averages + */ + const createSubSection = (label, averages) => ({ + name: label, + tree: [ + { + name: "Compare", + title: `Price ${label}s`, + top: averages.map(({ id, color, ratio }) => + line({ + metric: ratio.price, + name: id, + color, + unit: Unit.usd, + }), + ), + }, + ...averages.map(({ name, color, ratio }) => ({ + name, + tree: createPriceWithRatioOptions(ctx, { + ratio, + title: `${name} ${label}`, + legend: "average", + color, + }), + })), + ], + }); + return { name: "Averages", tree: [ - { nameAddon: "Simple", metricAddon: /** @type {const} */ ("sma") }, - { nameAddon: "Exponential", metricAddon: /** @type {const} */ ("ema") }, - ].map(({ nameAddon, metricAddon }) => ({ - name: nameAddon, - tree: [ - { - name: "Compare", - title: `Price ${metricAddon.toUpperCase()}s`, - top: averages.map(({ id, color, sma, ema }) => - line({ - metric: (metricAddon === "sma" ? sma : ema).price, - name: id, - color, - unit: Unit.usd, - }), - ), - }, - ...averages.map(({ name, color, sma, ema }) => ({ - name, - tree: createPriceWithRatioOptions(ctx, { - ratio: metricAddon === "sma" ? sma : ema, - title: `${name} ${metricAddon.toUpperCase()}`, - legend: "average", - color, - }), - })), - ], - })), + createSubSection("SMA", smaAverages), + createSubSection("EMA", emaAverages), + ], }; } diff --git a/website/scripts/options/market/index.js b/website/scripts/options/market/index.js index a56b6b824..e48d7e8a4 100644 --- a/website/scripts/options/market/index.js +++ b/website/scripts/options/market/index.js @@ -3,7 +3,7 @@ import { localhost } from "../../utils/env.js"; import { Unit } from "../../utils/units.js"; import { candlestick, line } from "../series.js"; -import { buildAverages, createAveragesSection } from "./averages.js"; +import { createAveragesSection } from "./averages.js"; import { createPerformanceSection } from "./performance.js"; import { createIndicatorsSection } from "./indicators/index.js"; import { createInvestingSection } from "./investing.js"; @@ -27,7 +27,6 @@ export function createMarketSection(ctx) { indicators, } = market; - const averages = buildAverages(colors, movingAverage); return { name: "Market", @@ -163,7 +162,7 @@ export function createMarketSection(ctx) { }, // Averages - createAveragesSection(ctx, averages), + createAveragesSection(ctx, movingAverage), // Performance createPerformanceSection(ctx, returns), diff --git a/website/scripts/options/partial.js b/website/scripts/options/partial.js index 310598dfa..67a65d3d8 100644 --- a/website/scripts/options/partial.js +++ b/website/scripts/options/partial.js @@ -7,7 +7,8 @@ import { createCohortFolderFull, createCohortFolderWithAdjusted, createCohortFolderWithPercentiles, - createCohortFolderBasic, + createCohortFolderBasicWithMarketCap, + createCohortFolderBasicWithoutMarketCap, createCohortFolderAddress, createAddressCohortFolder, } from "./distribution/index.js"; @@ -57,8 +58,12 @@ export function createPartialOptions({ brk }) { /** @param {CohortWithPercentiles} cohort */ const mapWithPercentiles = (cohort) => createCohortFolderWithPercentiles(ctx, cohort); - /** @param {CohortBasic} cohort */ - const mapBasic = (cohort) => createCohortFolderBasic(ctx, cohort); + /** @param {CohortBasicWithMarketCap} cohort */ + const mapBasicWithMarketCap = (cohort) => + createCohortFolderBasicWithMarketCap(ctx, cohort); + /** @param {CohortBasicWithoutMarketCap} cohort */ + const mapBasicWithoutMarketCap = (cohort) => + createCohortFolderBasicWithoutMarketCap(ctx, cohort); /** @param {CohortAddress} cohort */ const mapAddress = (cohort) => createCohortFolderAddress(ctx, cohort); /** @param {AddressCohortObject} cohort */ @@ -119,7 +124,7 @@ export function createPartialOptions({ brk }) { list: typeAddressable, }), ...typeAddressable.map(mapAddress), - ...typeOther.map(mapBasic), + ...typeOther.map(mapBasicWithoutMarketCap), ], }, @@ -143,12 +148,12 @@ export function createPartialOptions({ brk }) { { name: "At Least", tree: [ - createCohortFolderBasic(ctx, { + createCohortFolderBasicWithMarketCap(ctx, { name: "Compare", title: "Age At Least", list: fromDate, }), - ...fromDate.map(mapBasic), + ...fromDate.map(mapBasicWithMarketCap), ], }, // Range @@ -174,36 +179,36 @@ export function createPartialOptions({ brk }) { { name: "Under", tree: [ - createCohortFolderBasic(ctx, { + createCohortFolderBasicWithMarketCap(ctx, { name: "Compare", title: "Amount Under", list: utxosUnderAmount, }), - ...utxosUnderAmount.map(mapBasic), + ...utxosUnderAmount.map(mapBasicWithMarketCap), ], }, // Above (≥ X sats) { name: "Above", tree: [ - createCohortFolderBasic(ctx, { + createCohortFolderBasicWithMarketCap(ctx, { name: "Compare", title: "Amount Above", list: utxosAboveAmount, }), - ...utxosAboveAmount.map(mapBasic), + ...utxosAboveAmount.map(mapBasicWithMarketCap), ], }, // Range { name: "Range", tree: [ - createCohortFolderBasic(ctx, { + createCohortFolderBasicWithoutMarketCap(ctx, { name: "Compare", title: "Amount Range", list: utxosAmountRanges, }), - ...utxosAmountRanges.map(mapBasic), + ...utxosAmountRanges.map(mapBasicWithoutMarketCap), ], }, ], @@ -252,29 +257,29 @@ export function createPartialOptions({ brk }) { ], }, - // Epochs - CohortBasic + // Epochs - CohortBasicWithoutMarketCap (no RelToMarketCap) { name: "Epochs", tree: [ - createCohortFolderBasic(ctx, { + createCohortFolderBasicWithoutMarketCap(ctx, { name: "Compare", title: "Epoch", list: epoch, }), - ...epoch.map(mapBasic), + ...epoch.map(mapBasicWithoutMarketCap), ], }, - // Years - CohortBasic + // Years - CohortBasicWithoutMarketCap (no RelToMarketCap) { name: "Years", tree: [ - createCohortFolderBasic(ctx, { + createCohortFolderBasicWithoutMarketCap(ctx, { name: "Compare", title: "Year", list: year, }), - ...year.map(mapBasic), + ...year.map(mapBasicWithoutMarketCap), ], }, ], diff --git a/website/scripts/options/series.js b/website/scripts/options/series.js index 2390ffa01..e9b031fb4 100644 --- a/website/scripts/options/series.js +++ b/website/scripts/options/series.js @@ -718,8 +718,8 @@ export function fromValuePattern( * Create sum/cumulative series from a BitcoinPattern ({ sum, cumulative }) with explicit unit and colors * @param {Colors} colors * @param {{ sum: AnyMetricPattern, cumulative: AnyMetricPattern }} pattern - * @param {string} title * @param {Unit} unit + * @param {string} [title] * @param {Color} [sumColor] * @param {Color} [cumulativeColor] * @returns {AnyFetchedSeriesBlueprint[]} @@ -727,21 +727,21 @@ export function fromValuePattern( export function fromBitcoinPatternWithUnit( colors, pattern, - title, unit, + title = "", sumColor, cumulativeColor, ) { return [ { metric: pattern.sum, - title: `${title} sum`, + title: `${title} sum`.trim(), color: sumColor, unit, }, { metric: pattern.cumulative, - title: `${title} cumulative`, + title: `${title} cumulative`.trim(), color: cumulativeColor ?? colors.stat.cumulative, unit, defaultActive: false, @@ -763,7 +763,7 @@ export function fromBlockCountWithUnit( colors, pattern, unit, - title, + title = "", sumColor, cumulativeColor, ) { diff --git a/website/scripts/options/shared.js b/website/scripts/options/shared.js index cb0bfbe98..04fea79ee 100644 --- a/website/scripts/options/shared.js +++ b/website/scripts/options/shared.js @@ -148,14 +148,15 @@ export function ratioSmas(colors, ratio) { * @param {AnyMetricPattern} args.price - The price metric to show in top pane * @param {ActivePriceRatioPattern} args.ratio - The ratio pattern * @param {Color} args.color + * @param {string} [args.name] - Optional name override (default: "ratio") * @returns {PartialChartOption} */ -export function createRatioChart(ctx, { title, price, ratio, color }) { +export function createRatioChart(ctx, { title, price, ratio, color, name }) { const { colors } = ctx; return { - name: "ratio", - title: `${title} Ratio`, + name: name ?? "ratio", + title: name ? (title ? `${name} - ${title}` : name) : `${title} Ratio`, top: [ line({ metric: price, name: "price", color, unit: Unit.usd }), ...percentileUsdMap(colors, ratio).map(({ name, prop, color }) => diff --git a/website/scripts/options/types.js b/website/scripts/options/types.js index 33643a7e5..217387a2a 100644 --- a/website/scripts/options/types.js +++ b/website/scripts/options/types.js @@ -145,10 +145,16 @@ * - AgeRangePattern (ageRange.*) * @typedef {LongTermPattern | AgeRangePattern} PatternWithPercentiles * - * Patterns with neither (RealizedPattern/2, CostBasisPattern): + * Patterns with RelToMarketCap in relative (RelativePattern): * - BasicUtxoPattern (minAge.*, geAmount.*, ltAmount.*) - * - EpochPattern (epoch.*) - * @typedef {BasicUtxoPattern | EpochPattern} PatternBasic + * @typedef {BasicUtxoPattern} PatternBasicWithMarketCap + * + * Patterns without RelToMarketCap in relative (RelativePattern4): + * - EpochPattern (epoch.*, amountRange.*, year.*, type.*) + * @typedef {EpochPattern} PatternBasicWithoutMarketCap + * + * Union of basic patterns (for backwards compat) + * @typedef {PatternBasicWithMarketCap | PatternBasicWithoutMarketCap} PatternBasic * * ============================================================================ * Cohort Object Types (by capability) @@ -183,19 +189,29 @@ * @property {Color} color * @property {PatternWithPercentiles} tree * - * Basic cohort: neither (minAge.*, epoch.*, amount cohorts) - * @typedef {Object} CohortBasic + * Basic cohort WITH RelToMarketCap (minAge.*, geAmount.*, ltAmount.*) + * @typedef {Object} CohortBasicWithMarketCap * @property {string} name * @property {string} title * @property {Color} color - * @property {PatternBasic} tree + * @property {PatternBasicWithMarketCap} tree + * + * Basic cohort WITHOUT RelToMarketCap (epoch.*, amountRange.*, year.*, type.*) + * @typedef {Object} CohortBasicWithoutMarketCap + * @property {string} name + * @property {string} title + * @property {Color} color + * @property {PatternBasicWithoutMarketCap} tree + * + * Union of basic cohort types + * @typedef {CohortBasicWithMarketCap | CohortBasicWithoutMarketCap} CohortBasic * * ============================================================================ * Extended Cohort Types (with address count) * ============================================================================ * - * Basic cohort with address count (for "type" cohorts) - * @typedef {CohortBasic & { addrCount: Brk.MetricPattern1 }} CohortAddress + * Addressable cohort with address count (for "type" cohorts - no RelToMarketCap) + * @typedef {CohortBasicWithoutMarketCap & { addrCount: Brk.MetricPattern1 }} CohortAddress * * ============================================================================ * Cohort Group Types (by capability) @@ -216,10 +232,18 @@ * @property {string} title * @property {readonly CohortWithPercentiles[]} list * - * @typedef {Object} CohortGroupBasic + * @typedef {Object} CohortGroupBasicWithMarketCap * @property {string} name * @property {string} title - * @property {readonly CohortBasic[]} list + * @property {readonly CohortBasicWithMarketCap[]} list + * + * @typedef {Object} CohortGroupBasicWithoutMarketCap + * @property {string} name + * @property {string} title + * @property {readonly CohortBasicWithoutMarketCap[]} list + * + * Union of basic cohort group types + * @typedef {CohortGroupBasicWithMarketCap | CohortGroupBasicWithoutMarketCap} CohortGroupBasic * * @typedef {Object} UtxoCohortGroupObject * @property {string} name diff --git a/website/scripts/options/unused.js b/website/scripts/options/unused.js index 7fd78f6ad..138ec8279 100644 --- a/website/scripts/options/unused.js +++ b/website/scripts/options/unused.js @@ -13,6 +13,34 @@ function walk(node, map, path) { map.set(/** @type {AnyMetricPattern} */ (node), path); } else if (node && typeof node === "object") { for (const [key, value] of Object.entries(node)) { + const kn = key.toLowerCase(); + if ( + kn === "mvrv" || + kn === "time" || + kn === "height" || + kn === "constants" || + kn === "oracle" || + kn === "split" || + kn === "outpoint" || + kn === "positions" || + kn === "outputtype" || + kn === "heighttopool" || + kn.endsWith("index") || + kn.endsWith("indexes") || + kn.endsWith("bytes") || + (kn.startsWith("_") && kn.endsWith("start")) + ) + continue; + // if ( + // kn === "mvrv" || + // kn.endsWith("index") || + // kn.endsWith("indexes") || + // kn.endsWith("start") || + // kn.endsWith("hash") || + // kn.endsWith("data") || + // kn.endsWith("constants") + // ) + // return; walk(/** @type {TreeNode | null | undefined} */ (value), map, [ ...path, key, diff --git a/website/scripts/types.js b/website/scripts/types.js index 768695680..520830402 100644 --- a/website/scripts/types.js +++ b/website/scripts/types.js @@ -14,7 +14,7 @@ * * @import { WebSockets } from "./utils/ws.js" * - * @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, SeriesType, AnyFetchedSeriesBlueprint, TableOption, ExplorerOption, UrlOption, PartialOptionsGroup, OptionsGroup, PartialOptionsTree, UtxoCohortObject, AddressCohortObject, CohortObject, CohortGroupObject, FetchedLineSeriesBlueprint, FetchedBaselineSeriesBlueprint, FetchedHistogramSeriesBlueprint, PartialContext, PatternAll, PatternFull, PatternWithAdjusted, PatternWithPercentiles, PatternBasic, CohortAll, CohortFull, CohortWithAdjusted, CohortWithPercentiles, CohortBasic, CohortAddress, CohortGroupFull, CohortGroupWithAdjusted, CohortGroupWithPercentiles, CohortGroupBasic, UtxoCohortGroupObject, AddressCohortGroupObject, FetchedDotsSeriesBlueprint, FetchedCandlestickSeriesBlueprint } from "./options/partial.js" + * @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, SeriesType, AnyFetchedSeriesBlueprint, TableOption, ExplorerOption, UrlOption, PartialOptionsGroup, OptionsGroup, PartialOptionsTree, UtxoCohortObject, AddressCohortObject, CohortObject, CohortGroupObject, FetchedLineSeriesBlueprint, FetchedBaselineSeriesBlueprint, FetchedHistogramSeriesBlueprint, PartialContext, PatternAll, PatternFull, PatternWithAdjusted, PatternWithPercentiles, PatternBasic, PatternBasicWithMarketCap, PatternBasicWithoutMarketCap, CohortAll, CohortFull, CohortWithAdjusted, CohortWithPercentiles, CohortBasic, CohortBasicWithMarketCap, CohortBasicWithoutMarketCap, CohortAddress, CohortGroupFull, CohortGroupWithAdjusted, CohortGroupWithPercentiles, CohortGroupBasic, CohortGroupBasicWithMarketCap, CohortGroupBasicWithoutMarketCap, UtxoCohortGroupObject, AddressCohortGroupObject, FetchedDotsSeriesBlueprint, FetchedCandlestickSeriesBlueprint } from "./options/partial.js" * * * @import { UnitObject as Unit } from "./utils/units.js" @@ -41,7 +41,7 @@ * @typedef {Brk._10yTo12yPattern} AgeRangePattern * @typedef {Brk._0satsPattern2} UtxoAmountPattern * @typedef {Brk._0satsPattern} AddressAmountPattern - * @typedef {Brk._0Pattern} BasicUtxoPattern + * @typedef {Brk._100btcPattern} BasicUtxoPattern * @typedef {Brk._0satsPattern2} EpochPattern * @typedef {Brk.Ratio1ySdPattern} Ratio1ySdPattern * @typedef {Brk.Dollars} Dollars diff --git a/website/scripts/utils/units.js b/website/scripts/utils/units.js index d41f95e29..4a9718faa 100644 --- a/website/scripts/utils/units.js +++ b/website/scripts/utils/units.js @@ -51,6 +51,8 @@ export const Unit = /** @type {const} */ ({ // Cointime coinblocks: { id: "coinblocks", name: "Coinblocks" }, coindays: { id: "coindays", name: "Coindays" }, + satblocks: { id: "satblocks", name: "Satblocks" }, + satdays: { id: "satdays", name: "Satdays" }, // Hash price/value usdPerThsPerDay: { id: "usd-ths-day", name: "USD/TH/s/Day" },