From 13ab7d39d75067a2ff80846090510e3d287b587c Mon Sep 17 00:00:00 2001 From: nym21 Date: Sun, 4 Jan 2026 11:51:22 +0100 Subject: [PATCH] global: snapshot --- Cargo.lock | 86 +- Cargo.toml | 4 +- crates/brk_client/src/lib.rs | 812 +++++++++------- crates/brk_cohort/src/by_age_range.rs | 192 ++-- crates/brk_cohort/src/by_max_age.rs | 84 +- crates/brk_cohort/src/by_min_age.rs | 84 +- crates/brk_cohort/src/filter.rs | 32 +- crates/brk_cohort/src/lib.rs | 6 +- .../src/distribution/block/cohort/sent.rs | 23 +- .../src/distribution/cohorts/address/vecs.rs | 1 + .../src/distribution/cohorts/utxo/groups.rs | 53 +- .../src/distribution/cohorts/utxo/receive.rs | 6 +- .../src/distribution/cohorts/utxo/send.rs | 70 +- .../distribution/cohorts/utxo/tick_tock.rs | 42 +- .../src/distribution/cohorts/utxo/vecs.rs | 7 +- .../src/distribution/metrics/config.rs | 5 + .../src/distribution/metrics/realized.rs | 227 ++--- .../src/distribution/state/cohort/address.rs | 16 +- .../src/distribution/state/cohort/base.rs | 21 +- .../distribution/state/cost_basis/realized.rs | 14 - crates/brk_types/src/age.rs | 65 ++ crates/brk_types/src/lib.rs | 4 + crates/{brk_cohort => brk_types}/src/term.rs | 7 +- crates/brk_types/src/timestamp.rs | 5 + modules/brk-client/index.js | 879 ++++++++++-------- packages/brk_client/brk_client/__init__.py | 418 +++++---- 26 files changed, 1696 insertions(+), 1467 deletions(-) create mode 100644 crates/brk_types/src/age.rs rename crates/{brk_cohort => brk_types}/src/term.rs (54%) diff --git a/Cargo.lock b/Cargo.lock index b4e21fd81..e7d67693a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -211,7 +211,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -378,7 +378,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -872,7 +872,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1325,7 +1325,7 @@ version = "0.1.0-alpha.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1518,7 +1518,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1845,7 +1845,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1856,7 +1856,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1890,7 +1890,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -1923,7 +1923,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.112", + "syn 2.0.113", "unicode-xid", ] @@ -1978,7 +1978,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2041,7 +2041,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2265,7 +2265,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2359,7 +2359,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -2851,7 +2851,7 @@ checksum = "b787bebb543f8969132630c51fd0afab173a86c6abae56ff3b9e5e3e3f9f6e58" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3285,7 +3285,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3441,7 +3441,7 @@ checksum = "003b4612827f6501183873fb0735da92157e3c7daa71c40921c7d2758fec2229" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3485,7 +3485,7 @@ dependencies = [ "phf", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -3995,7 +3995,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4024,7 +4024,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4306,6 +4306,8 @@ dependencies = [ [[package]] name = "rawdb" version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63786b0b37f520a26c26787dc0de01a3c2a704706964455d556155a4deed2c6f" dependencies = [ "libc", "log", @@ -4382,7 +4384,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4593,7 +4595,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4698,7 +4700,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4709,7 +4711,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4930,7 +4932,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -4955,9 +4957,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.112" +version = "2.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" +checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" dependencies = [ "proc-macro2", "quote", @@ -4978,7 +4980,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5040,7 +5042,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5051,7 +5053,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5115,7 +5117,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5261,7 +5263,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5351,7 +5353,7 @@ checksum = "ee6ff59666c9cbaec3533964505d39154dc4e0a56151fdea30a09ed0301f62e2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "termcolor", ] @@ -5498,6 +5500,8 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23" [[package]] name = "vecdb" version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c6a6a5e26cf1c7f13e9ea470c94153514ea750e491fb3c5b2846c69db5d17f" dependencies = [ "ctrlc", "log", @@ -5517,9 +5521,11 @@ dependencies = [ [[package]] name = "vecdb_derive" version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374b601ba9563eaba6f46b452a905dee8e7cda6b3321f40be99e50cbccb36cd4" dependencies = [ "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5606,7 +5612,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "wasm-bindgen-shared", ] @@ -5725,7 +5731,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -5736,7 +5742,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6010,7 +6016,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "synstructure", ] @@ -6031,7 +6037,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] @@ -6051,7 +6057,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", "synstructure", ] @@ -6085,7 +6091,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.112", + "syn 2.0.113", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index fa08a227d..6f8976bf3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,8 +81,8 @@ serde_derive = "1.0.228" serde_json = { version = "1.0.148", features = ["float_roundtrip"] } smallvec = "1.15.1" tokio = { version = "1.49.0", features = ["rt-multi-thread"] } -# vecdb = { version = "0.5.2", features = ["derive", "serde_json", "pco", "schemars"] } -vecdb = { path = "../anydb/crates/vecdb", features = ["derive", "serde_json", "pco", "schemars"] } +vecdb = { version = "0.5.4", features = ["derive", "serde_json", "pco", "schemars"] } +# vecdb = { path = "../anydb/crates/vecdb", features = ["derive", "serde_json", "pco", "schemars"] } # vecdb = { git = "https://github.com/anydb-rs/anydb", features = ["derive", "serde_json", "pco"] } [workspace.metadata.release] diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index ac280e952..f62c7fec0 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -2948,8 +2948,8 @@ pub struct RealizedPattern3 { pub adjusted_sopr: MetricPattern21, pub adjusted_sopr_30d_ema: MetricPattern21, pub adjusted_sopr_7d_ema: MetricPattern21, - pub adjusted_value_created: MetricPattern1, - pub adjusted_value_destroyed: MetricPattern1, + pub adjusted_value_created: TotalRealizedPnlPattern, + pub adjusted_value_destroyed: TotalRealizedPnlPattern, pub mvrv: MetricPattern4, pub neg_realized_loss: BlockCountPattern, pub net_realized_pnl: BlockCountPattern, @@ -2986,8 +2986,8 @@ impl RealizedPattern3 { adjusted_sopr: MetricPattern21::new(client.clone(), _m(&acc, "adjusted_sopr")), adjusted_sopr_30d_ema: MetricPattern21::new(client.clone(), _m(&acc, "adjusted_sopr_30d_ema")), adjusted_sopr_7d_ema: MetricPattern21::new(client.clone(), _m(&acc, "adjusted_sopr_7d_ema")), - adjusted_value_created: MetricPattern1::new(client.clone(), _m(&acc, "adjusted_value_created")), - adjusted_value_destroyed: MetricPattern1::new(client.clone(), _m(&acc, "adjusted_value_destroyed")), + adjusted_value_created: TotalRealizedPnlPattern::new(client.clone(), _m(&acc, "adjusted_value_created")), + adjusted_value_destroyed: TotalRealizedPnlPattern::new(client.clone(), _m(&acc, "adjusted_value_destroyed")), mvrv: MetricPattern4::new(client.clone(), _m(&acc, "mvrv")), neg_realized_loss: BlockCountPattern::new(client.clone(), _m(&acc, "neg_realized_loss")), net_realized_pnl: BlockCountPattern::new(client.clone(), _m(&acc, "net_realized_pnl")), @@ -3024,8 +3024,8 @@ pub struct RealizedPattern4 { pub adjusted_sopr: MetricPattern21, pub adjusted_sopr_30d_ema: MetricPattern21, pub adjusted_sopr_7d_ema: MetricPattern21, - pub adjusted_value_created: MetricPattern1, - pub adjusted_value_destroyed: MetricPattern1, + pub adjusted_value_created: TotalRealizedPnlPattern, + pub adjusted_value_destroyed: TotalRealizedPnlPattern, pub mvrv: MetricPattern4, pub neg_realized_loss: BlockCountPattern, pub net_realized_pnl: BlockCountPattern, @@ -3060,8 +3060,8 @@ impl RealizedPattern4 { adjusted_sopr: MetricPattern21::new(client.clone(), _m(&acc, "adjusted_sopr")), adjusted_sopr_30d_ema: MetricPattern21::new(client.clone(), _m(&acc, "adjusted_sopr_30d_ema")), adjusted_sopr_7d_ema: MetricPattern21::new(client.clone(), _m(&acc, "adjusted_sopr_7d_ema")), - adjusted_value_created: MetricPattern1::new(client.clone(), _m(&acc, "adjusted_value_created")), - adjusted_value_destroyed: MetricPattern1::new(client.clone(), _m(&acc, "adjusted_value_destroyed")), + adjusted_value_created: TotalRealizedPnlPattern::new(client.clone(), _m(&acc, "adjusted_value_created")), + adjusted_value_destroyed: TotalRealizedPnlPattern::new(client.clone(), _m(&acc, "adjusted_value_destroyed")), mvrv: MetricPattern4::new(client.clone(), _m(&acc, "mvrv")), neg_realized_loss: BlockCountPattern::new(client.clone(), _m(&acc, "neg_realized_loss")), net_realized_pnl: BlockCountPattern::new(client.clone(), _m(&acc, "net_realized_pnl")), @@ -3339,56 +3339,6 @@ impl Price111dSmaPattern { } } -/// Pattern struct for repeated tree structure. -pub struct PercentilesPattern { - pub cost_basis_pct05: MetricPattern4, - pub cost_basis_pct10: MetricPattern4, - pub cost_basis_pct15: MetricPattern4, - pub cost_basis_pct20: MetricPattern4, - pub cost_basis_pct25: MetricPattern4, - pub cost_basis_pct30: MetricPattern4, - pub cost_basis_pct35: MetricPattern4, - pub cost_basis_pct40: MetricPattern4, - pub cost_basis_pct45: MetricPattern4, - pub cost_basis_pct50: MetricPattern4, - pub cost_basis_pct55: MetricPattern4, - pub cost_basis_pct60: MetricPattern4, - pub cost_basis_pct65: MetricPattern4, - pub cost_basis_pct70: MetricPattern4, - pub cost_basis_pct75: MetricPattern4, - pub cost_basis_pct80: MetricPattern4, - pub cost_basis_pct85: MetricPattern4, - pub cost_basis_pct90: MetricPattern4, - pub cost_basis_pct95: MetricPattern4, -} - -impl PercentilesPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - cost_basis_pct05: MetricPattern4::new(client.clone(), _m(&acc, "pct05")), - cost_basis_pct10: MetricPattern4::new(client.clone(), _m(&acc, "pct10")), - cost_basis_pct15: MetricPattern4::new(client.clone(), _m(&acc, "pct15")), - cost_basis_pct20: MetricPattern4::new(client.clone(), _m(&acc, "pct20")), - cost_basis_pct25: MetricPattern4::new(client.clone(), _m(&acc, "pct25")), - cost_basis_pct30: MetricPattern4::new(client.clone(), _m(&acc, "pct30")), - cost_basis_pct35: MetricPattern4::new(client.clone(), _m(&acc, "pct35")), - cost_basis_pct40: MetricPattern4::new(client.clone(), _m(&acc, "pct40")), - cost_basis_pct45: MetricPattern4::new(client.clone(), _m(&acc, "pct45")), - cost_basis_pct50: MetricPattern4::new(client.clone(), _m(&acc, "pct50")), - cost_basis_pct55: MetricPattern4::new(client.clone(), _m(&acc, "pct55")), - cost_basis_pct60: MetricPattern4::new(client.clone(), _m(&acc, "pct60")), - cost_basis_pct65: MetricPattern4::new(client.clone(), _m(&acc, "pct65")), - cost_basis_pct70: MetricPattern4::new(client.clone(), _m(&acc, "pct70")), - cost_basis_pct75: MetricPattern4::new(client.clone(), _m(&acc, "pct75")), - cost_basis_pct80: MetricPattern4::new(client.clone(), _m(&acc, "pct80")), - cost_basis_pct85: MetricPattern4::new(client.clone(), _m(&acc, "pct85")), - cost_basis_pct90: MetricPattern4::new(client.clone(), _m(&acc, "pct90")), - cost_basis_pct95: MetricPattern4::new(client.clone(), _m(&acc, "pct95")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct ActivePriceRatioPattern { pub ratio: MetricPattern4, @@ -3440,7 +3390,57 @@ impl ActivePriceRatioPattern { } /// Pattern struct for repeated tree structure. -pub struct RelativePattern2 { +pub struct PercentilesPattern { + pub cost_basis_pct05: MetricPattern4, + pub cost_basis_pct10: MetricPattern4, + pub cost_basis_pct15: MetricPattern4, + pub cost_basis_pct20: MetricPattern4, + pub cost_basis_pct25: MetricPattern4, + pub cost_basis_pct30: MetricPattern4, + pub cost_basis_pct35: MetricPattern4, + pub cost_basis_pct40: MetricPattern4, + pub cost_basis_pct45: MetricPattern4, + pub cost_basis_pct50: MetricPattern4, + pub cost_basis_pct55: MetricPattern4, + pub cost_basis_pct60: MetricPattern4, + pub cost_basis_pct65: MetricPattern4, + pub cost_basis_pct70: MetricPattern4, + pub cost_basis_pct75: MetricPattern4, + pub cost_basis_pct80: MetricPattern4, + pub cost_basis_pct85: MetricPattern4, + pub cost_basis_pct90: MetricPattern4, + pub cost_basis_pct95: MetricPattern4, +} + +impl PercentilesPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + cost_basis_pct05: MetricPattern4::new(client.clone(), _m(&acc, "pct05")), + cost_basis_pct10: MetricPattern4::new(client.clone(), _m(&acc, "pct10")), + cost_basis_pct15: MetricPattern4::new(client.clone(), _m(&acc, "pct15")), + cost_basis_pct20: MetricPattern4::new(client.clone(), _m(&acc, "pct20")), + cost_basis_pct25: MetricPattern4::new(client.clone(), _m(&acc, "pct25")), + cost_basis_pct30: MetricPattern4::new(client.clone(), _m(&acc, "pct30")), + cost_basis_pct35: MetricPattern4::new(client.clone(), _m(&acc, "pct35")), + cost_basis_pct40: MetricPattern4::new(client.clone(), _m(&acc, "pct40")), + cost_basis_pct45: MetricPattern4::new(client.clone(), _m(&acc, "pct45")), + cost_basis_pct50: MetricPattern4::new(client.clone(), _m(&acc, "pct50")), + cost_basis_pct55: MetricPattern4::new(client.clone(), _m(&acc, "pct55")), + cost_basis_pct60: MetricPattern4::new(client.clone(), _m(&acc, "pct60")), + cost_basis_pct65: MetricPattern4::new(client.clone(), _m(&acc, "pct65")), + cost_basis_pct70: MetricPattern4::new(client.clone(), _m(&acc, "pct70")), + cost_basis_pct75: MetricPattern4::new(client.clone(), _m(&acc, "pct75")), + cost_basis_pct80: MetricPattern4::new(client.clone(), _m(&acc, "pct80")), + cost_basis_pct85: MetricPattern4::new(client.clone(), _m(&acc, "pct85")), + cost_basis_pct90: MetricPattern4::new(client.clone(), _m(&acc, "pct90")), + cost_basis_pct95: MetricPattern4::new(client.clone(), _m(&acc, "pct95")), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct RelativePattern5 { pub neg_unrealized_loss_rel_to_market_cap: MetricPattern5, pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern5, pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern5, @@ -3461,7 +3461,7 @@ pub struct RelativePattern2 { pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern5, } -impl RelativePattern2 { +impl RelativePattern5 { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { @@ -3635,6 +3635,40 @@ impl PeriodAvgPricePattern { } } +/// Pattern struct for repeated tree structure. +pub struct BitcoinPattern { + pub average: MetricPattern2, + pub base: MetricPattern25, + pub cumulative: MetricPattern1, + pub max: MetricPattern2, + pub median: MetricPattern21, + pub min: MetricPattern2, + pub pct10: MetricPattern21, + pub pct25: MetricPattern21, + pub pct75: MetricPattern21, + pub pct90: MetricPattern21, + pub sum: MetricPattern2, +} + +impl BitcoinPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + average: MetricPattern2::new(client.clone(), _m(&acc, "avg")), + base: MetricPattern25::new(client.clone(), acc.clone()), + cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), + max: MetricPattern2::new(client.clone(), _m(&acc, "max")), + median: MetricPattern21::new(client.clone(), _m(&acc, "median")), + min: MetricPattern2::new(client.clone(), _m(&acc, "min")), + pct10: MetricPattern21::new(client.clone(), _m(&acc, "pct10")), + pct25: MetricPattern21::new(client.clone(), _m(&acc, "pct25")), + pct75: MetricPattern21::new(client.clone(), _m(&acc, "pct75")), + pct90: MetricPattern21::new(client.clone(), _m(&acc, "pct90")), + sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct ClassAvgPricePattern { pub _2015: MetricPattern4, @@ -3670,35 +3704,33 @@ impl ClassAvgPricePattern { } /// Pattern struct for repeated tree structure. -pub struct BitcoinPattern { - pub average: MetricPattern2, - pub base: MetricPattern25, - pub cumulative: MetricPattern1, - pub max: MetricPattern2, - pub median: MetricPattern21, - pub min: MetricPattern2, - pub pct10: MetricPattern21, - pub pct25: MetricPattern21, - pub pct75: MetricPattern21, - pub pct90: MetricPattern21, - pub sum: MetricPattern2, +pub struct RelativePattern2 { + pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern5, + pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern5, + pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern3, + pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern3, + pub supply_in_loss_rel_to_own_supply: MetricPattern5, + pub supply_in_profit_rel_to_own_supply: MetricPattern5, + pub unrealized_loss_rel_to_own_market_cap: MetricPattern5, + pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern5, + pub unrealized_profit_rel_to_own_market_cap: MetricPattern5, + pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern5, } -impl BitcoinPattern { +impl RelativePattern2 { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - average: MetricPattern2::new(client.clone(), _m(&acc, "avg")), - base: MetricPattern25::new(client.clone(), acc.clone()), - cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), - max: MetricPattern2::new(client.clone(), _m(&acc, "max")), - median: MetricPattern21::new(client.clone(), _m(&acc, "median")), - min: MetricPattern2::new(client.clone(), _m(&acc, "min")), - pct10: MetricPattern21::new(client.clone(), _m(&acc, "pct10")), - pct25: MetricPattern21::new(client.clone(), _m(&acc, "pct25")), - pct75: MetricPattern21::new(client.clone(), _m(&acc, "pct75")), - pct90: MetricPattern21::new(client.clone(), _m(&acc, "pct90")), - sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")), + neg_unrealized_loss_rel_to_own_market_cap: MetricPattern5::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")), + neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern5::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")), + net_unrealized_pnl_rel_to_own_market_cap: MetricPattern3::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")), + net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern3::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")), + supply_in_loss_rel_to_own_supply: MetricPattern5::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")), + supply_in_profit_rel_to_own_supply: MetricPattern5::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")), + unrealized_loss_rel_to_own_market_cap: MetricPattern5::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")), + unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern5::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")), + unrealized_profit_rel_to_own_market_cap: MetricPattern5::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")), + unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern5::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")), } } } @@ -3737,32 +3769,32 @@ impl RelativePattern { /// Pattern struct for repeated tree structure. pub struct BlockSizePattern { - pub average: MetricPattern1, + pub average: MetricPattern2, pub cumulative: MetricPattern1, - pub max: MetricPattern1, - pub median: MetricPattern25, - pub min: MetricPattern1, - pub pct10: MetricPattern25, - pub pct25: MetricPattern25, - pub pct75: MetricPattern25, - pub pct90: MetricPattern25, - pub sum: MetricPattern1, + pub max: MetricPattern2, + pub median: MetricPattern21, + pub min: MetricPattern2, + pub pct10: MetricPattern21, + pub pct25: MetricPattern21, + pub pct75: MetricPattern21, + pub pct90: MetricPattern21, + pub sum: MetricPattern2, } impl BlockSizePattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - average: MetricPattern1::new(client.clone(), _m(&acc, "avg")), + average: MetricPattern2::new(client.clone(), _m(&acc, "avg")), cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), - max: MetricPattern1::new(client.clone(), _m(&acc, "max")), - median: MetricPattern25::new(client.clone(), _m(&acc, "median")), - min: MetricPattern1::new(client.clone(), _m(&acc, "min")), - pct10: MetricPattern25::new(client.clone(), _m(&acc, "pct10")), - pct25: MetricPattern25::new(client.clone(), _m(&acc, "pct25")), - pct75: MetricPattern25::new(client.clone(), _m(&acc, "pct75")), - pct90: MetricPattern25::new(client.clone(), _m(&acc, "pct90")), - sum: MetricPattern1::new(client.clone(), _m(&acc, "sum")), + max: MetricPattern2::new(client.clone(), _m(&acc, "max")), + median: MetricPattern21::new(client.clone(), _m(&acc, "median")), + min: MetricPattern2::new(client.clone(), _m(&acc, "min")), + pct10: MetricPattern21::new(client.clone(), _m(&acc, "pct10")), + pct25: MetricPattern21::new(client.clone(), _m(&acc, "pct25")), + pct75: MetricPattern21::new(client.clone(), _m(&acc, "pct75")), + pct90: MetricPattern21::new(client.clone(), _m(&acc, "pct90")), + sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")), } } } @@ -3799,82 +3831,56 @@ impl UnrealizedPattern { /// Pattern struct for repeated tree structure. pub struct AddresstypeToHeightToAddrCountPattern { - pub p2a: MetricPattern25, - pub p2pk33: MetricPattern25, - pub p2pk65: MetricPattern25, - pub p2pkh: MetricPattern25, - pub p2sh: MetricPattern25, - pub p2tr: MetricPattern25, - pub p2wpkh: MetricPattern25, - pub p2wsh: MetricPattern25, + pub p2a: MetricPattern29, + pub p2pk33: MetricPattern31, + pub p2pk65: MetricPattern32, + pub p2pkh: MetricPattern33, + pub p2sh: MetricPattern34, + pub p2tr: MetricPattern35, + pub p2wpkh: MetricPattern36, + pub p2wsh: MetricPattern37, } impl AddresstypeToHeightToAddrCountPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - p2a: MetricPattern25::new(client.clone(), if acc.is_empty() { "p2a".to_string() } else { format!("p2a_{acc}") }), - p2pk33: MetricPattern25::new(client.clone(), if acc.is_empty() { "p2pk33".to_string() } else { format!("p2pk33_{acc}") }), - p2pk65: MetricPattern25::new(client.clone(), if acc.is_empty() { "p2pk65".to_string() } else { format!("p2pk65_{acc}") }), - p2pkh: MetricPattern25::new(client.clone(), if acc.is_empty() { "p2pkh".to_string() } else { format!("p2pkh_{acc}") }), - p2sh: MetricPattern25::new(client.clone(), if acc.is_empty() { "p2sh".to_string() } else { format!("p2sh_{acc}") }), - p2tr: MetricPattern25::new(client.clone(), if acc.is_empty() { "p2tr".to_string() } else { format!("p2tr_{acc}") }), - p2wpkh: MetricPattern25::new(client.clone(), if acc.is_empty() { "p2wpkh".to_string() } else { format!("p2wpkh_{acc}") }), - p2wsh: MetricPattern25::new(client.clone(), if acc.is_empty() { "p2wsh".to_string() } else { format!("p2wsh_{acc}") }), + p2a: MetricPattern29::new(client.clone(), if acc.is_empty() { "p2a".to_string() } else { format!("p2a_{acc}") }), + p2pk33: MetricPattern31::new(client.clone(), if acc.is_empty() { "p2pk33".to_string() } else { format!("p2pk33_{acc}") }), + p2pk65: MetricPattern32::new(client.clone(), if acc.is_empty() { "p2pk65".to_string() } else { format!("p2pk65_{acc}") }), + p2pkh: MetricPattern33::new(client.clone(), if acc.is_empty() { "p2pkh".to_string() } else { format!("p2pkh_{acc}") }), + p2sh: MetricPattern34::new(client.clone(), if acc.is_empty() { "p2sh".to_string() } else { format!("p2sh_{acc}") }), + p2tr: MetricPattern35::new(client.clone(), if acc.is_empty() { "p2tr".to_string() } else { format!("p2tr_{acc}") }), + p2wpkh: MetricPattern36::new(client.clone(), if acc.is_empty() { "p2wpkh".to_string() } else { format!("p2wpkh_{acc}") }), + p2wsh: MetricPattern37::new(client.clone(), if acc.is_empty() { "p2wsh".to_string() } else { format!("p2wsh_{acc}") }), } } } /// Pattern struct for repeated tree structure. pub struct BlockIntervalPattern { - pub average: MetricPattern2, - pub max: MetricPattern2, - pub median: MetricPattern21, - pub min: MetricPattern2, - pub pct10: MetricPattern21, - pub pct25: MetricPattern21, - pub pct75: MetricPattern21, - pub pct90: MetricPattern21, + pub average: MetricPattern1, + pub max: MetricPattern1, + pub median: MetricPattern25, + pub min: MetricPattern1, + pub pct10: MetricPattern25, + pub pct25: MetricPattern25, + pub pct75: MetricPattern25, + pub pct90: MetricPattern25, } impl BlockIntervalPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - average: MetricPattern2::new(client.clone(), _m(&acc, "avg")), - max: MetricPattern2::new(client.clone(), _m(&acc, "max")), - median: MetricPattern21::new(client.clone(), _m(&acc, "median")), - min: MetricPattern2::new(client.clone(), _m(&acc, "min")), - pct10: MetricPattern21::new(client.clone(), _m(&acc, "pct10")), - pct25: MetricPattern21::new(client.clone(), _m(&acc, "pct25")), - pct75: MetricPattern21::new(client.clone(), _m(&acc, "pct75")), - pct90: MetricPattern21::new(client.clone(), _m(&acc, "pct90")), - } - } -} - -/// 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, -} - -impl PeriodCagrPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - _10y: MetricPattern4::new(client.clone(), if acc.is_empty() { "10y".to_string() } else { format!("10y_{acc}") }), - _2y: MetricPattern4::new(client.clone(), if acc.is_empty() { "2y".to_string() } else { format!("2y_{acc}") }), - _3y: MetricPattern4::new(client.clone(), if acc.is_empty() { "3y".to_string() } else { format!("3y_{acc}") }), - _4y: MetricPattern4::new(client.clone(), if acc.is_empty() { "4y".to_string() } else { format!("4y_{acc}") }), - _5y: MetricPattern4::new(client.clone(), if acc.is_empty() { "5y".to_string() } else { format!("5y_{acc}") }), - _6y: MetricPattern4::new(client.clone(), if acc.is_empty() { "6y".to_string() } else { format!("6y_{acc}") }), - _8y: MetricPattern4::new(client.clone(), if acc.is_empty() { "8y".to_string() } else { format!("8y_{acc}") }), + average: MetricPattern1::new(client.clone(), _m(&acc, "avg")), + max: MetricPattern1::new(client.clone(), _m(&acc, "max")), + median: MetricPattern25::new(client.clone(), _m(&acc, "median")), + min: MetricPattern1::new(client.clone(), _m(&acc, "min")), + pct10: MetricPattern25::new(client.clone(), _m(&acc, "pct10")), + pct25: MetricPattern25::new(client.clone(), _m(&acc, "pct25")), + pct75: MetricPattern25::new(client.clone(), _m(&acc, "pct75")), + pct90: MetricPattern25::new(client.clone(), _m(&acc, "pct90")), } } } @@ -3906,23 +3912,49 @@ impl _0satsPattern { } /// Pattern struct for repeated tree structure. -pub struct UpTo1dPattern { +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 PeriodCagrPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + _10y: MetricPattern4::new(client.clone(), if acc.is_empty() { "10y".to_string() } else { format!("10y_{acc}") }), + _2y: MetricPattern4::new(client.clone(), if acc.is_empty() { "2y".to_string() } else { format!("2y_{acc}") }), + _3y: MetricPattern4::new(client.clone(), if acc.is_empty() { "3y".to_string() } else { format!("3y_{acc}") }), + _4y: MetricPattern4::new(client.clone(), if acc.is_empty() { "4y".to_string() } else { format!("4y_{acc}") }), + _5y: MetricPattern4::new(client.clone(), if acc.is_empty() { "5y".to_string() } else { format!("5y_{acc}") }), + _6y: MetricPattern4::new(client.clone(), if acc.is_empty() { "6y".to_string() } else { format!("6y_{acc}") }), + _8y: MetricPattern4::new(client.clone(), if acc.is_empty() { "8y".to_string() } else { format!("8y_{acc}") }), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct _0satsPattern2 { pub activity: ActivityPattern2, - pub cost_basis: CostBasisPattern2, - pub realized: RealizedPattern3, - pub relative: RelativePattern2, + pub cost_basis: CostBasisPattern, + pub realized: RealizedPattern, + pub relative: RelativePattern4, pub supply: SupplyPattern3, pub unrealized: UnrealizedPattern, } -impl UpTo1dPattern { +impl _0satsPattern2 { /// 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()), - realized: RealizedPattern3::new(client.clone(), acc.clone()), - relative: RelativePattern2::new(client.clone(), acc.clone()), + cost_basis: CostBasisPattern::new(client.clone(), acc.clone()), + realized: RealizedPattern::new(client.clone(), acc.clone()), + relative: RelativePattern4::new(client.clone(), _m(&acc, "supply_in")), supply: SupplyPattern3::new(client.clone(), acc.clone()), unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), } @@ -3953,6 +3985,30 @@ impl _10yPattern { } } +/// Pattern struct for repeated tree structure. +pub struct _100btcPattern { + pub activity: ActivityPattern2, + pub cost_basis: CostBasisPattern, + pub realized: RealizedPattern, + pub relative: RelativePattern, + pub supply: SupplyPattern3, + pub unrealized: UnrealizedPattern, +} + +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: CostBasisPattern::new(client.clone(), acc.clone()), + realized: RealizedPattern::new(client.clone(), acc.clone()), + relative: RelativePattern::new(client.clone(), acc.clone()), + supply: SupplyPattern3::new(client.clone(), acc.clone()), + unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), + } + } +} + /// Pattern struct for repeated tree structure. pub struct _10yTo12yPattern { pub activity: ActivityPattern2, @@ -3977,30 +4033,6 @@ impl _10yTo12yPattern { } } -/// Pattern struct for repeated tree structure. -pub struct _0satsPattern2 { - pub activity: ActivityPattern2, - pub cost_basis: CostBasisPattern, - pub realized: RealizedPattern, - pub relative: RelativePattern, - pub supply: SupplyPattern3, - pub unrealized: UnrealizedPattern, -} - -impl _0satsPattern2 { - /// 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()), - realized: RealizedPattern::new(client.clone(), acc.clone()), - relative: RelativePattern::new(client.clone(), acc.clone()), - supply: SupplyPattern3::new(client.clone(), acc.clone()), - unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct SegwitAdoptionPattern { pub average: MetricPattern2, @@ -4025,28 +4057,6 @@ impl SegwitAdoptionPattern { } } -/// Pattern struct for repeated tree structure. -pub struct SupplyPattern3 { - pub supply: SupplyPattern2, - pub supply_half: ActiveSupplyPattern, - pub supply_half_value: ActiveSupplyPattern, - pub supply_value: SupplyValuePattern, - pub utxo_count: MetricPattern1, -} - -impl SupplyPattern3 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), - supply_half: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_half")), - supply_half_value: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_half")), - supply_value: SupplyValuePattern::new(client.clone(), _m(&acc, "supply")), - utxo_count: MetricPattern1::new(client.clone(), _m(&acc, "utxo_count")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct ActivityPattern2 { pub coinblocks_destroyed: BlockCountPattern, @@ -4069,6 +4079,28 @@ impl ActivityPattern2 { } } +/// Pattern struct for repeated tree structure. +pub struct SupplyPattern3 { + pub supply: SupplyPattern2, + pub supply_half: ActiveSupplyPattern, + pub supply_half_value: ActiveSupplyPattern, + pub supply_value: SupplyValuePattern, + pub utxo_count: MetricPattern1, +} + +impl SupplyPattern3 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), + supply_half: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_half")), + supply_half_value: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_half")), + supply_value: SupplyValuePattern::new(client.clone(), _m(&acc, "supply")), + utxo_count: MetricPattern1::new(client.clone(), _m(&acc, "utxo_count")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct SupplyPattern2 { pub base: MetricPattern25, @@ -4089,26 +4121,6 @@ impl SupplyPattern2 { } } -/// Pattern struct for repeated tree structure. -pub struct SentPattern { - pub base: MetricPattern25, - pub bitcoin: BlockCountPattern, - pub dollars: BlockCountPattern, - pub sats: SatsPattern, -} - -impl SentPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - base: MetricPattern25::new(client.clone(), acc.clone()), - bitcoin: BlockCountPattern::new(client.clone(), _m(&acc, "btc")), - dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")), - sats: SatsPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct OpreturnPattern { pub base: MetricPattern25, @@ -4130,19 +4142,21 @@ impl OpreturnPattern { } /// Pattern struct for repeated tree structure. -pub struct CostBasisPattern2 { - pub max_cost_basis: MetricPattern1, - pub min_cost_basis: MetricPattern1, - pub percentiles: PercentilesPattern, +pub struct SentPattern { + pub base: MetricPattern25, + pub bitcoin: BlockCountPattern, + pub dollars: BlockCountPattern, + pub sats: SatsPattern, } -impl CostBasisPattern2 { +impl SentPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - max_cost_basis: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")), - min_cost_basis: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")), - percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")), + base: MetricPattern25::new(client.clone(), acc.clone()), + bitcoin: BlockCountPattern::new(client.clone(), _m(&acc, "btc")), + dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")), + sats: SatsPattern::new(client.clone(), acc.clone()), } } } @@ -4201,6 +4215,24 @@ impl ActiveSupplyPattern { } } +/// Pattern struct for repeated tree structure. +pub struct CostBasisPattern2 { + pub max_cost_basis: MetricPattern1, + pub min_cost_basis: MetricPattern1, + pub percentiles: PercentilesPattern, +} + +impl CostBasisPattern2 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + max_cost_basis: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")), + min_cost_basis: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")), + percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct BlockCountPattern { pub base: MetricPattern25, @@ -4237,22 +4269,6 @@ impl BitcoinPattern2 { } } -/// Pattern struct for repeated tree structure. -pub struct CostBasisPattern { - pub max_cost_basis: MetricPattern1, - pub min_cost_basis: MetricPattern1, -} - -impl CostBasisPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - max_cost_basis: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")), - min_cost_basis: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct SatsPattern4 { pub cumulative: MetricPattern1, @@ -4270,17 +4286,17 @@ impl SatsPattern4 { } /// Pattern struct for repeated tree structure. -pub struct SupplyValuePattern { - pub bitcoin: MetricPattern25, - pub dollars: MetricPattern25, +pub struct RelativePattern4 { + pub supply_in_loss_rel_to_own_supply: MetricPattern5, + pub supply_in_profit_rel_to_own_supply: MetricPattern5, } -impl SupplyValuePattern { +impl RelativePattern4 { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - bitcoin: MetricPattern25::new(client.clone(), _m(&acc, "btc")), - dollars: MetricPattern25::new(client.clone(), _m(&acc, "usd")), + supply_in_loss_rel_to_own_supply: MetricPattern5::new(client.clone(), _m(&acc, "loss_rel_to_own_supply")), + supply_in_profit_rel_to_own_supply: MetricPattern5::new(client.clone(), _m(&acc, "profit_rel_to_own_supply")), } } } @@ -4301,6 +4317,38 @@ impl SatsPattern { } } +/// Pattern struct for repeated tree structure. +pub struct CostBasisPattern { + pub max_cost_basis: MetricPattern1, + pub min_cost_basis: MetricPattern1, +} + +impl CostBasisPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + max_cost_basis: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")), + min_cost_basis: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct SupplyValuePattern { + pub bitcoin: MetricPattern25, + pub dollars: MetricPattern25, +} + +impl SupplyValuePattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + bitcoin: MetricPattern25::new(client.clone(), _m(&acc, "btc")), + dollars: MetricPattern25::new(client.clone(), _m(&acc, "usd")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct _1dReturns1mSdPattern { pub sd: MetricPattern4, @@ -5039,6 +5087,7 @@ pub struct CatalogTree_Computed_Distribution_UtxoCohorts_AgeRange { pub _10y_to_12y: _10yTo12yPattern, pub _12y_to_15y: _10yTo12yPattern, pub _1d_to_1w: _10yTo12yPattern, + pub _1h_to_1d: _10yTo12yPattern, pub _1m_to_2m: _10yTo12yPattern, pub _1w_to_1m: _10yTo12yPattern, pub _1y_to_2y: _10yTo12yPattern, @@ -5055,7 +5104,7 @@ pub struct CatalogTree_Computed_Distribution_UtxoCohorts_AgeRange { pub _7y_to_8y: _10yTo12yPattern, pub _8y_to_10y: _10yTo12yPattern, pub from_15y: _10yTo12yPattern, - pub up_to_1d: UpTo1dPattern, + pub up_to_1h: _10yTo12yPattern, } impl CatalogTree_Computed_Distribution_UtxoCohorts_AgeRange { @@ -5064,6 +5113,7 @@ impl CatalogTree_Computed_Distribution_UtxoCohorts_AgeRange { _10y_to_12y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_10y_up_to_12y_old".to_string()), _12y_to_15y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_12y_up_to_15y_old".to_string()), _1d_to_1w: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1d_up_to_1w_old".to_string()), + _1h_to_1d: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1h_up_to_1d_old".to_string()), _1m_to_2m: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1m_up_to_2m_old".to_string()), _1w_to_1m: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1w_up_to_1m_old".to_string()), _1y_to_2y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1y_up_to_2y_old".to_string()), @@ -5080,7 +5130,7 @@ impl CatalogTree_Computed_Distribution_UtxoCohorts_AgeRange { _7y_to_8y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_7y_up_to_8y_old".to_string()), _8y_to_10y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_8y_up_to_10y_old".to_string()), from_15y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_15y_old".to_string()), - up_to_1d: UpTo1dPattern::new(client.clone(), "utxos_up_to_1d_old".to_string()), + up_to_1h: _10yTo12yPattern::new(client.clone(), "utxos_up_to_1h_old".to_string()), } } } @@ -5195,74 +5245,74 @@ impl CatalogTree_Computed_Distribution_UtxoCohorts_Epoch { /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_UtxoCohorts_GeAmount { - pub _100btc: _0satsPattern2, - pub _100k_sats: _0satsPattern2, - pub _100sats: _0satsPattern2, - pub _10btc: _0satsPattern2, - pub _10k_btc: _0satsPattern2, - pub _10k_sats: _0satsPattern2, - pub _10m_sats: _0satsPattern2, - pub _10sats: _0satsPattern2, - pub _1btc: _0satsPattern2, - pub _1k_btc: _0satsPattern2, - pub _1k_sats: _0satsPattern2, - pub _1m_sats: _0satsPattern2, - pub _1sat: _0satsPattern2, + 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 CatalogTree_Computed_Distribution_UtxoCohorts_GeAmount { pub fn new(client: Arc, base_path: String) -> Self { Self { - _100btc: _0satsPattern2::new(client.clone(), "utxos_above_100btc".to_string()), - _100k_sats: _0satsPattern2::new(client.clone(), "utxos_above_100k_sats".to_string()), - _100sats: _0satsPattern2::new(client.clone(), "utxos_above_100sats".to_string()), - _10btc: _0satsPattern2::new(client.clone(), "utxos_above_10btc".to_string()), - _10k_btc: _0satsPattern2::new(client.clone(), "utxos_above_10k_btc".to_string()), - _10k_sats: _0satsPattern2::new(client.clone(), "utxos_above_10k_sats".to_string()), - _10m_sats: _0satsPattern2::new(client.clone(), "utxos_above_10m_sats".to_string()), - _10sats: _0satsPattern2::new(client.clone(), "utxos_above_10sats".to_string()), - _1btc: _0satsPattern2::new(client.clone(), "utxos_above_1btc".to_string()), - _1k_btc: _0satsPattern2::new(client.clone(), "utxos_above_1k_btc".to_string()), - _1k_sats: _0satsPattern2::new(client.clone(), "utxos_above_1k_sats".to_string()), - _1m_sats: _0satsPattern2::new(client.clone(), "utxos_above_1m_sats".to_string()), - _1sat: _0satsPattern2::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()), } } } /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_UtxoCohorts_LtAmount { - pub _100btc: _0satsPattern2, - pub _100k_btc: _0satsPattern2, - pub _100k_sats: _0satsPattern2, - pub _100sats: _0satsPattern2, - pub _10btc: _0satsPattern2, - pub _10k_btc: _0satsPattern2, - pub _10k_sats: _0satsPattern2, - pub _10m_sats: _0satsPattern2, - pub _10sats: _0satsPattern2, - pub _1btc: _0satsPattern2, - pub _1k_btc: _0satsPattern2, - pub _1k_sats: _0satsPattern2, - pub _1m_sats: _0satsPattern2, + 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 CatalogTree_Computed_Distribution_UtxoCohorts_LtAmount { pub fn new(client: Arc, base_path: String) -> Self { Self { - _100btc: _0satsPattern2::new(client.clone(), "utxos_under_100btc".to_string()), - _100k_btc: _0satsPattern2::new(client.clone(), "utxos_under_100k_btc".to_string()), - _100k_sats: _0satsPattern2::new(client.clone(), "utxos_under_100k_sats".to_string()), - _100sats: _0satsPattern2::new(client.clone(), "utxos_under_100sats".to_string()), - _10btc: _0satsPattern2::new(client.clone(), "utxos_under_10btc".to_string()), - _10k_btc: _0satsPattern2::new(client.clone(), "utxos_under_10k_btc".to_string()), - _10k_sats: _0satsPattern2::new(client.clone(), "utxos_under_10k_sats".to_string()), - _10m_sats: _0satsPattern2::new(client.clone(), "utxos_under_10m_sats".to_string()), - _10sats: _0satsPattern2::new(client.clone(), "utxos_under_10sats".to_string()), - _1btc: _0satsPattern2::new(client.clone(), "utxos_under_1btc".to_string()), - _1k_btc: _0satsPattern2::new(client.clone(), "utxos_under_1k_btc".to_string()), - _1k_sats: _0satsPattern2::new(client.clone(), "utxos_under_1k_sats".to_string()), - _1m_sats: _0satsPattern2::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()), } } } @@ -5316,62 +5366,108 @@ impl CatalogTree_Computed_Distribution_UtxoCohorts_MaxAge { /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_UtxoCohorts_MinAge { - pub _10y: _0satsPattern2, - pub _12y: _0satsPattern2, - pub _1d: _0satsPattern2, - pub _1m: _0satsPattern2, - pub _1w: _0satsPattern2, - pub _1y: _0satsPattern2, - pub _2m: _0satsPattern2, - pub _2y: _0satsPattern2, - pub _3m: _0satsPattern2, - pub _3y: _0satsPattern2, - pub _4m: _0satsPattern2, - pub _4y: _0satsPattern2, - pub _5m: _0satsPattern2, - pub _5y: _0satsPattern2, - pub _6m: _0satsPattern2, - pub _6y: _0satsPattern2, - pub _7y: _0satsPattern2, - pub _8y: _0satsPattern2, + 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 CatalogTree_Computed_Distribution_UtxoCohorts_MinAge { pub fn new(client: Arc, base_path: String) -> Self { Self { - _10y: _0satsPattern2::new(client.clone(), "utxos_at_least_10y_old".to_string()), - _12y: _0satsPattern2::new(client.clone(), "utxos_at_least_12y_old".to_string()), - _1d: _0satsPattern2::new(client.clone(), "utxos_at_least_1d_old".to_string()), - _1m: _0satsPattern2::new(client.clone(), "utxos_at_least_1m_old".to_string()), - _1w: _0satsPattern2::new(client.clone(), "utxos_at_least_1w_old".to_string()), - _1y: _0satsPattern2::new(client.clone(), "utxos_at_least_1y_old".to_string()), - _2m: _0satsPattern2::new(client.clone(), "utxos_at_least_2m_old".to_string()), - _2y: _0satsPattern2::new(client.clone(), "utxos_at_least_2y_old".to_string()), - _3m: _0satsPattern2::new(client.clone(), "utxos_at_least_3m_old".to_string()), - _3y: _0satsPattern2::new(client.clone(), "utxos_at_least_3y_old".to_string()), - _4m: _0satsPattern2::new(client.clone(), "utxos_at_least_4m_old".to_string()), - _4y: _0satsPattern2::new(client.clone(), "utxos_at_least_4y_old".to_string()), - _5m: _0satsPattern2::new(client.clone(), "utxos_at_least_5m_old".to_string()), - _5y: _0satsPattern2::new(client.clone(), "utxos_at_least_5y_old".to_string()), - _6m: _0satsPattern2::new(client.clone(), "utxos_at_least_6m_old".to_string()), - _6y: _0satsPattern2::new(client.clone(), "utxos_at_least_6y_old".to_string()), - _7y: _0satsPattern2::new(client.clone(), "utxos_at_least_7y_old".to_string()), - _8y: _0satsPattern2::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()), } } } /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_UtxoCohorts_Term { - pub long: UpTo1dPattern, - pub short: UpTo1dPattern, + pub long: CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long, + pub short: CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short, } impl CatalogTree_Computed_Distribution_UtxoCohorts_Term { pub fn new(client: Arc, base_path: String) -> Self { Self { - long: UpTo1dPattern::new(client.clone(), "lth".to_string()), - short: UpTo1dPattern::new(client.clone(), "sth".to_string()), + long: CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long::new(client.clone(), format!("{base_path}_long")), + short: CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short::new(client.clone(), format!("{base_path}_short")), + } + } +} + +/// Catalog tree node. +pub struct CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long { + pub activity: ActivityPattern2, + pub cost_basis: CostBasisPattern2, + pub realized: RealizedPattern2, + pub relative: RelativePattern5, + pub supply: SupplyPattern3, + pub unrealized: UnrealizedPattern, +} + +impl CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + activity: ActivityPattern2::new(client.clone(), "lth".to_string()), + cost_basis: CostBasisPattern2::new(client.clone(), "lth".to_string()), + realized: RealizedPattern2::new(client.clone(), "lth".to_string()), + relative: RelativePattern5::new(client.clone(), "lth".to_string()), + supply: SupplyPattern3::new(client.clone(), "lth".to_string()), + unrealized: UnrealizedPattern::new(client.clone(), "lth".to_string()), + } + } +} + +/// Catalog tree node. +pub struct CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short { + pub activity: ActivityPattern2, + pub cost_basis: CostBasisPattern2, + pub realized: RealizedPattern3, + pub relative: RelativePattern5, + pub supply: SupplyPattern3, + pub unrealized: UnrealizedPattern, +} + +impl CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + activity: ActivityPattern2::new(client.clone(), "sth".to_string()), + cost_basis: CostBasisPattern2::new(client.clone(), "sth".to_string()), + realized: RealizedPattern3::new(client.clone(), "sth".to_string()), + relative: RelativePattern5::new(client.clone(), "sth".to_string()), + supply: SupplyPattern3::new(client.clone(), "sth".to_string()), + unrealized: UnrealizedPattern::new(client.clone(), "sth".to_string()), } } } diff --git a/crates/brk_cohort/src/by_age_range.rs b/crates/brk_cohort/src/by_age_range.rs index 0f4548900..2a4fdf3e0 100644 --- a/crates/brk_cohort/src/by_age_range.rs +++ b/crates/brk_cohort/src/by_age_range.rs @@ -1,66 +1,71 @@ use std::ops::Range; +use brk_types::Age; use brk_traversable::Traversable; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use serde::Serialize; use super::{CohortName, Filter, TimeFilter}; -// Age boundary constants in days -pub const DAYS_1D: usize = 1; -pub const DAYS_1W: usize = 7; -pub const DAYS_1M: usize = 30; -pub const DAYS_2M: usize = 2 * 30; -pub const DAYS_3M: usize = 3 * 30; -pub const DAYS_4M: usize = 4 * 30; -pub const DAYS_5M: usize = 5 * 30; -pub const DAYS_6M: usize = 6 * 30; -pub const DAYS_1Y: usize = 365; -pub const DAYS_2Y: usize = 2 * 365; -pub const DAYS_3Y: usize = 3 * 365; -pub const DAYS_4Y: usize = 4 * 365; -pub const DAYS_5Y: usize = 5 * 365; -pub const DAYS_6Y: usize = 6 * 365; -pub const DAYS_7Y: usize = 7 * 365; -pub const DAYS_8Y: usize = 8 * 365; -pub const DAYS_10Y: usize = 10 * 365; -pub const DAYS_12Y: usize = 12 * 365; -pub const DAYS_15Y: usize = 15 * 365; +// Age boundary constants in hours +pub const HOURS_1H: usize = 1; +pub const HOURS_1D: usize = 24; +pub const HOURS_1W: usize = 24 * 7; +pub const HOURS_1M: usize = 24 * 30; +pub const HOURS_2M: usize = 24 * 2 * 30; +pub const HOURS_3M: usize = 24 * 3 * 30; +pub const HOURS_4M: usize = 24 * 4 * 30; +pub const HOURS_5M: usize = 24 * 5 * 30; // STH/LTH threshold +pub const HOURS_6M: usize = 24 * 6 * 30; +pub const HOURS_1Y: usize = 24 * 365; +pub const HOURS_2Y: usize = 24 * 2 * 365; +pub const HOURS_3Y: usize = 24 * 3 * 365; +pub const HOURS_4Y: usize = 24 * 4 * 365; +pub const HOURS_5Y: usize = 24 * 5 * 365; +pub const HOURS_6Y: usize = 24 * 6 * 365; +pub const HOURS_7Y: usize = 24 * 7 * 365; +pub const HOURS_8Y: usize = 24 * 8 * 365; +pub const HOURS_10Y: usize = 24 * 10 * 365; +pub const HOURS_12Y: usize = 24 * 12 * 365; +pub const HOURS_15Y: usize = 24 * 15 * 365; -/// Age boundaries in days. Defines the cohort ranges: -/// [0, B[0]), [B[0], B[1]), [B[1], B[2]), ..., [B[n-1], ∞) -pub const AGE_BOUNDARIES: [usize; 19] = [ - DAYS_1D, DAYS_1W, DAYS_1M, DAYS_2M, DAYS_3M, DAYS_4M, DAYS_5M, DAYS_6M, DAYS_1Y, DAYS_2Y, - DAYS_3Y, DAYS_4Y, DAYS_5Y, DAYS_6Y, DAYS_7Y, DAYS_8Y, DAYS_10Y, DAYS_12Y, DAYS_15Y, +/// Age boundaries in hours. Defines the cohort ranges: +/// [0, 1h), [1h, 1d), [1d, 1w), [1w, 1m), ..., [15y, ∞) +pub const AGE_BOUNDARIES: [usize; 20] = [ + HOURS_1H, HOURS_1D, HOURS_1W, HOURS_1M, HOURS_2M, HOURS_3M, HOURS_4M, + HOURS_5M, HOURS_6M, HOURS_1Y, HOURS_2Y, HOURS_3Y, HOURS_4Y, HOURS_5Y, + HOURS_6Y, HOURS_7Y, HOURS_8Y, HOURS_10Y, HOURS_12Y, HOURS_15Y, ]; /// Age range bounds (end = usize::MAX means unbounded) pub const AGE_RANGE_BOUNDS: ByAgeRange> = ByAgeRange { - up_to_1d: 0..DAYS_1D, - _1d_to_1w: DAYS_1D..DAYS_1W, - _1w_to_1m: DAYS_1W..DAYS_1M, - _1m_to_2m: DAYS_1M..DAYS_2M, - _2m_to_3m: DAYS_2M..DAYS_3M, - _3m_to_4m: DAYS_3M..DAYS_4M, - _4m_to_5m: DAYS_4M..DAYS_5M, - _5m_to_6m: DAYS_5M..DAYS_6M, - _6m_to_1y: DAYS_6M..DAYS_1Y, - _1y_to_2y: DAYS_1Y..DAYS_2Y, - _2y_to_3y: DAYS_2Y..DAYS_3Y, - _3y_to_4y: DAYS_3Y..DAYS_4Y, - _4y_to_5y: DAYS_4Y..DAYS_5Y, - _5y_to_6y: DAYS_5Y..DAYS_6Y, - _6y_to_7y: DAYS_6Y..DAYS_7Y, - _7y_to_8y: DAYS_7Y..DAYS_8Y, - _8y_to_10y: DAYS_8Y..DAYS_10Y, - _10y_to_12y: DAYS_10Y..DAYS_12Y, - _12y_to_15y: DAYS_12Y..DAYS_15Y, - from_15y: DAYS_15Y..usize::MAX, + up_to_1h: 0..HOURS_1H, + _1h_to_1d: HOURS_1H..HOURS_1D, + _1d_to_1w: HOURS_1D..HOURS_1W, + _1w_to_1m: HOURS_1W..HOURS_1M, + _1m_to_2m: HOURS_1M..HOURS_2M, + _2m_to_3m: HOURS_2M..HOURS_3M, + _3m_to_4m: HOURS_3M..HOURS_4M, + _4m_to_5m: HOURS_4M..HOURS_5M, + _5m_to_6m: HOURS_5M..HOURS_6M, + _6m_to_1y: HOURS_6M..HOURS_1Y, + _1y_to_2y: HOURS_1Y..HOURS_2Y, + _2y_to_3y: HOURS_2Y..HOURS_3Y, + _3y_to_4y: HOURS_3Y..HOURS_4Y, + _4y_to_5y: HOURS_4Y..HOURS_5Y, + _5y_to_6y: HOURS_5Y..HOURS_6Y, + _6y_to_7y: HOURS_6Y..HOURS_7Y, + _7y_to_8y: HOURS_7Y..HOURS_8Y, + _8y_to_10y: HOURS_8Y..HOURS_10Y, + _10y_to_12y: HOURS_10Y..HOURS_12Y, + _12y_to_15y: HOURS_12Y..HOURS_15Y, + from_15y: HOURS_15Y..usize::MAX, }; /// Age range filters pub const AGE_RANGE_FILTERS: ByAgeRange = ByAgeRange { - up_to_1d: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS.up_to_1d)), + up_to_1h: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS.up_to_1h)), + _1h_to_1d: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS._1h_to_1d)), _1d_to_1w: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS._1d_to_1w)), _1w_to_1m: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS._1w_to_1m)), _1m_to_2m: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS._1m_to_2m)), @@ -84,7 +89,8 @@ pub const AGE_RANGE_FILTERS: ByAgeRange = ByAgeRange { /// Age range names pub const AGE_RANGE_NAMES: ByAgeRange = ByAgeRange { - up_to_1d: CohortName::new("up_to_1d_old", "<1d", "Up to 1 Day Old"), + up_to_1h: CohortName::new("up_to_1h_old", "<1h", "Up to 1 Hour Old"), + _1h_to_1d: CohortName::new("at_least_1h_up_to_1d_old", "1h-1d", "1 Hour to 1 Day Old"), _1d_to_1w: CohortName::new("at_least_1d_up_to_1w_old", "1d-1w", "1 Day to 1 Week Old"), _1w_to_1m: CohortName::new("at_least_1w_up_to_1m_old", "1w-1m", "1 Week to 1 Month Old"), _1m_to_2m: CohortName::new("at_least_1m_up_to_2m_old", "1m-2m", "1 to 2 Months Old"), @@ -114,7 +120,8 @@ impl ByAgeRange { #[derive(Default, Clone, Traversable, Serialize)] pub struct ByAgeRange { - pub up_to_1d: T, + pub up_to_1h: T, + pub _1h_to_1d: T, pub _1d_to_1w: T, pub _1w_to_1m: T, pub _1m_to_2m: T, @@ -137,33 +144,62 @@ pub struct ByAgeRange { } impl ByAgeRange { - /// Get mutable reference by days old. O(1). + /// Get mutable reference by Age. O(1). #[inline] - pub fn get_mut_by_days_old(&mut self, days_old: usize) -> &mut T { - match days_old { - 0..DAYS_1D => &mut self.up_to_1d, - DAYS_1D..DAYS_1W => &mut self._1d_to_1w, - DAYS_1W..DAYS_1M => &mut self._1w_to_1m, - DAYS_1M..DAYS_2M => &mut self._1m_to_2m, - DAYS_2M..DAYS_3M => &mut self._2m_to_3m, - DAYS_3M..DAYS_4M => &mut self._3m_to_4m, - DAYS_4M..DAYS_5M => &mut self._4m_to_5m, - DAYS_5M..DAYS_6M => &mut self._5m_to_6m, - DAYS_6M..DAYS_1Y => &mut self._6m_to_1y, - DAYS_1Y..DAYS_2Y => &mut self._1y_to_2y, - DAYS_2Y..DAYS_3Y => &mut self._2y_to_3y, - DAYS_3Y..DAYS_4Y => &mut self._3y_to_4y, - DAYS_4Y..DAYS_5Y => &mut self._4y_to_5y, - DAYS_5Y..DAYS_6Y => &mut self._5y_to_6y, - DAYS_6Y..DAYS_7Y => &mut self._6y_to_7y, - DAYS_7Y..DAYS_8Y => &mut self._7y_to_8y, - DAYS_8Y..DAYS_10Y => &mut self._8y_to_10y, - DAYS_10Y..DAYS_12Y => &mut self._10y_to_12y, - DAYS_12Y..DAYS_15Y => &mut self._12y_to_15y, + pub fn get_mut(&mut self, age: Age) -> &mut T { + match age.hours() { + 0..HOURS_1H => &mut self.up_to_1h, + HOURS_1H..HOURS_1D => &mut self._1h_to_1d, + HOURS_1D..HOURS_1W => &mut self._1d_to_1w, + HOURS_1W..HOURS_1M => &mut self._1w_to_1m, + HOURS_1M..HOURS_2M => &mut self._1m_to_2m, + HOURS_2M..HOURS_3M => &mut self._2m_to_3m, + HOURS_3M..HOURS_4M => &mut self._3m_to_4m, + HOURS_4M..HOURS_5M => &mut self._4m_to_5m, + HOURS_5M..HOURS_6M => &mut self._5m_to_6m, + HOURS_6M..HOURS_1Y => &mut self._6m_to_1y, + HOURS_1Y..HOURS_2Y => &mut self._1y_to_2y, + HOURS_2Y..HOURS_3Y => &mut self._2y_to_3y, + HOURS_3Y..HOURS_4Y => &mut self._3y_to_4y, + HOURS_4Y..HOURS_5Y => &mut self._4y_to_5y, + HOURS_5Y..HOURS_6Y => &mut self._5y_to_6y, + HOURS_6Y..HOURS_7Y => &mut self._6y_to_7y, + HOURS_7Y..HOURS_8Y => &mut self._7y_to_8y, + HOURS_8Y..HOURS_10Y => &mut self._8y_to_10y, + HOURS_10Y..HOURS_12Y => &mut self._10y_to_12y, + HOURS_12Y..HOURS_15Y => &mut self._12y_to_15y, _ => &mut self.from_15y, } } + /// Get reference by Age. O(1). + #[inline] + pub fn get(&self, age: Age) -> &T { + match age.hours() { + 0..HOURS_1H => &self.up_to_1h, + HOURS_1H..HOURS_1D => &self._1h_to_1d, + HOURS_1D..HOURS_1W => &self._1d_to_1w, + HOURS_1W..HOURS_1M => &self._1w_to_1m, + HOURS_1M..HOURS_2M => &self._1m_to_2m, + HOURS_2M..HOURS_3M => &self._2m_to_3m, + HOURS_3M..HOURS_4M => &self._3m_to_4m, + HOURS_4M..HOURS_5M => &self._4m_to_5m, + HOURS_5M..HOURS_6M => &self._5m_to_6m, + HOURS_6M..HOURS_1Y => &self._6m_to_1y, + HOURS_1Y..HOURS_2Y => &self._1y_to_2y, + HOURS_2Y..HOURS_3Y => &self._2y_to_3y, + HOURS_3Y..HOURS_4Y => &self._3y_to_4y, + HOURS_4Y..HOURS_5Y => &self._4y_to_5y, + HOURS_5Y..HOURS_6Y => &self._5y_to_6y, + HOURS_6Y..HOURS_7Y => &self._6y_to_7y, + HOURS_7Y..HOURS_8Y => &self._7y_to_8y, + HOURS_8Y..HOURS_10Y => &self._8y_to_10y, + HOURS_10Y..HOURS_12Y => &self._10y_to_12y, + HOURS_12Y..HOURS_15Y => &self._12y_to_15y, + _ => &self.from_15y, + } + } + pub fn new(mut create: F) -> Self where F: FnMut(Filter, &'static str) -> T, @@ -171,7 +207,8 @@ impl ByAgeRange { let f = AGE_RANGE_FILTERS; let n = AGE_RANGE_NAMES; Self { - up_to_1d: create(f.up_to_1d.clone(), n.up_to_1d.id), + up_to_1h: create(f.up_to_1h.clone(), n.up_to_1h.id), + _1h_to_1d: create(f._1h_to_1d.clone(), n._1h_to_1d.id), _1d_to_1w: create(f._1d_to_1w.clone(), n._1d_to_1w.id), _1w_to_1m: create(f._1w_to_1m.clone(), n._1w_to_1m.id), _1m_to_2m: create(f._1m_to_2m.clone(), n._1m_to_2m.id), @@ -201,7 +238,8 @@ impl ByAgeRange { let f = AGE_RANGE_FILTERS; let n = AGE_RANGE_NAMES; Ok(Self { - up_to_1d: create(f.up_to_1d.clone(), n.up_to_1d.id)?, + up_to_1h: create(f.up_to_1h.clone(), n.up_to_1h.id)?, + _1h_to_1d: create(f._1h_to_1d.clone(), n._1h_to_1d.id)?, _1d_to_1w: create(f._1d_to_1w.clone(), n._1d_to_1w.id)?, _1w_to_1m: create(f._1w_to_1m.clone(), n._1w_to_1m.id)?, _1m_to_2m: create(f._1m_to_2m.clone(), n._1m_to_2m.id)?, @@ -226,7 +264,8 @@ impl ByAgeRange { pub fn iter(&self) -> impl Iterator { [ - &self.up_to_1d, + &self.up_to_1h, + &self._1h_to_1d, &self._1d_to_1w, &self._1w_to_1m, &self._1m_to_2m, @@ -252,7 +291,8 @@ impl ByAgeRange { pub fn iter_mut(&mut self) -> impl Iterator { [ - &mut self.up_to_1d, + &mut self.up_to_1h, + &mut self._1h_to_1d, &mut self._1d_to_1w, &mut self._1w_to_1m, &mut self._1m_to_2m, @@ -281,7 +321,8 @@ impl ByAgeRange { T: Send + Sync, { [ - &mut self.up_to_1d, + &mut self.up_to_1h, + &mut self._1h_to_1d, &mut self._1d_to_1w, &mut self._1w_to_1m, &mut self._1m_to_2m, @@ -305,4 +346,3 @@ impl ByAgeRange { .into_par_iter() } } - diff --git a/crates/brk_cohort/src/by_max_age.rs b/crates/brk_cohort/src/by_max_age.rs index 31385e128..abbc62008 100644 --- a/crates/brk_cohort/src/by_max_age.rs +++ b/crates/brk_cohort/src/by_max_age.rs @@ -3,53 +3,53 @@ use rayon::prelude::*; use serde::Serialize; use super::{ - CohortName, Filter, TimeFilter, DAYS_10Y, DAYS_12Y, DAYS_15Y, DAYS_1M, DAYS_1W, DAYS_1Y, - DAYS_2M, DAYS_2Y, DAYS_3M, DAYS_3Y, DAYS_4M, DAYS_4Y, DAYS_5M, DAYS_5Y, DAYS_6M, DAYS_6Y, - DAYS_7Y, DAYS_8Y, + CohortName, Filter, TimeFilter, HOURS_10Y, HOURS_12Y, HOURS_15Y, HOURS_1M, HOURS_1W, HOURS_1Y, + HOURS_2M, HOURS_2Y, HOURS_3M, HOURS_3Y, HOURS_4M, HOURS_4Y, HOURS_5M, HOURS_5Y, HOURS_6M, + HOURS_6Y, HOURS_7Y, HOURS_8Y, }; -/// Max age thresholds in days -pub const MAX_AGE_DAYS: ByMaxAge = ByMaxAge { - _1w: DAYS_1W, - _1m: DAYS_1M, - _2m: DAYS_2M, - _3m: DAYS_3M, - _4m: DAYS_4M, - _5m: DAYS_5M, - _6m: DAYS_6M, - _1y: DAYS_1Y, - _2y: DAYS_2Y, - _3y: DAYS_3Y, - _4y: DAYS_4Y, - _5y: DAYS_5Y, - _6y: DAYS_6Y, - _7y: DAYS_7Y, - _8y: DAYS_8Y, - _10y: DAYS_10Y, - _12y: DAYS_12Y, - _15y: DAYS_15Y, +/// Max age thresholds in hours +pub const MAX_AGE_HOURS: ByMaxAge = ByMaxAge { + _1w: HOURS_1W, + _1m: HOURS_1M, + _2m: HOURS_2M, + _3m: HOURS_3M, + _4m: HOURS_4M, + _5m: HOURS_5M, + _6m: HOURS_6M, + _1y: HOURS_1Y, + _2y: HOURS_2Y, + _3y: HOURS_3Y, + _4y: HOURS_4Y, + _5y: HOURS_5Y, + _6y: HOURS_6Y, + _7y: HOURS_7Y, + _8y: HOURS_8Y, + _10y: HOURS_10Y, + _12y: HOURS_12Y, + _15y: HOURS_15Y, }; -/// Max age filters (LowerThan threshold) +/// Max age filters (LowerThan threshold in hours) pub const MAX_AGE_FILTERS: ByMaxAge = ByMaxAge { - _1w: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._1w)), - _1m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._1m)), - _2m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._2m)), - _3m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._3m)), - _4m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._4m)), - _5m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._5m)), - _6m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._6m)), - _1y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._1y)), - _2y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._2y)), - _3y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._3y)), - _4y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._4y)), - _5y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._5y)), - _6y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._6y)), - _7y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._7y)), - _8y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._8y)), - _10y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._10y)), - _12y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._12y)), - _15y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_DAYS._15y)), + _1w: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1w)), + _1m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1m)), + _2m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._2m)), + _3m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._3m)), + _4m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._4m)), + _5m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._5m)), + _6m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._6m)), + _1y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1y)), + _2y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._2y)), + _3y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._3y)), + _4y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._4y)), + _5y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._5y)), + _6y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._6y)), + _7y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._7y)), + _8y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._8y)), + _10y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._10y)), + _12y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._12y)), + _15y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._15y)), }; /// Max age names diff --git a/crates/brk_cohort/src/by_min_age.rs b/crates/brk_cohort/src/by_min_age.rs index fe92946a6..676e0fe03 100644 --- a/crates/brk_cohort/src/by_min_age.rs +++ b/crates/brk_cohort/src/by_min_age.rs @@ -3,53 +3,53 @@ use rayon::prelude::*; use serde::Serialize; use super::{ - CohortName, Filter, TimeFilter, DAYS_10Y, DAYS_12Y, DAYS_1D, DAYS_1M, DAYS_1W, DAYS_1Y, - DAYS_2M, DAYS_2Y, DAYS_3M, DAYS_3Y, DAYS_4M, DAYS_4Y, DAYS_5M, DAYS_5Y, DAYS_6M, DAYS_6Y, - DAYS_7Y, DAYS_8Y, + CohortName, Filter, TimeFilter, HOURS_10Y, HOURS_12Y, HOURS_1D, HOURS_1M, HOURS_1W, HOURS_1Y, + HOURS_2M, HOURS_2Y, HOURS_3M, HOURS_3Y, HOURS_4M, HOURS_4Y, HOURS_5M, HOURS_5Y, HOURS_6M, + HOURS_6Y, HOURS_7Y, HOURS_8Y, }; -/// Min age thresholds in days -pub const MIN_AGE_DAYS: ByMinAge = ByMinAge { - _1d: DAYS_1D, - _1w: DAYS_1W, - _1m: DAYS_1M, - _2m: DAYS_2M, - _3m: DAYS_3M, - _4m: DAYS_4M, - _5m: DAYS_5M, - _6m: DAYS_6M, - _1y: DAYS_1Y, - _2y: DAYS_2Y, - _3y: DAYS_3Y, - _4y: DAYS_4Y, - _5y: DAYS_5Y, - _6y: DAYS_6Y, - _7y: DAYS_7Y, - _8y: DAYS_8Y, - _10y: DAYS_10Y, - _12y: DAYS_12Y, +/// Min age thresholds in hours +pub const MIN_AGE_HOURS: ByMinAge = ByMinAge { + _1d: HOURS_1D, + _1w: HOURS_1W, + _1m: HOURS_1M, + _2m: HOURS_2M, + _3m: HOURS_3M, + _4m: HOURS_4M, + _5m: HOURS_5M, + _6m: HOURS_6M, + _1y: HOURS_1Y, + _2y: HOURS_2Y, + _3y: HOURS_3Y, + _4y: HOURS_4Y, + _5y: HOURS_5Y, + _6y: HOURS_6Y, + _7y: HOURS_7Y, + _8y: HOURS_8Y, + _10y: HOURS_10Y, + _12y: HOURS_12Y, }; -/// Min age filters (GreaterOrEqual threshold) +/// Min age filters (GreaterOrEqual threshold in hours) pub const MIN_AGE_FILTERS: ByMinAge = ByMinAge { - _1d: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._1d)), - _1w: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._1w)), - _1m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._1m)), - _2m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._2m)), - _3m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._3m)), - _4m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._4m)), - _5m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._5m)), - _6m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._6m)), - _1y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._1y)), - _2y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._2y)), - _3y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._3y)), - _4y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._4y)), - _5y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._5y)), - _6y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._6y)), - _7y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._7y)), - _8y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._8y)), - _10y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._10y)), - _12y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_DAYS._12y)), + _1d: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1d)), + _1w: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1w)), + _1m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1m)), + _2m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._2m)), + _3m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._3m)), + _4m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._4m)), + _5m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._5m)), + _6m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._6m)), + _1y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1y)), + _2y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._2y)), + _3y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._3y)), + _4y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._4y)), + _5y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._5y)), + _6y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._6y)), + _7y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._7y)), + _8y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._8y)), + _10y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._10y)), + _12y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._12y)), }; /// Min age names diff --git a/crates/brk_cohort/src/filter.rs b/crates/brk_cohort/src/filter.rs index 58011ada2..626327399 100644 --- a/crates/brk_cohort/src/filter.rs +++ b/crates/brk_cohort/src/filter.rs @@ -29,13 +29,13 @@ impl Filter { } } - /// Check if a time value (days) is contained by this filter - pub fn contains_time(&self, days: usize) -> bool { + /// Check if a time value (hours) is contained by this filter + pub fn contains_time(&self, hours: usize) -> bool { match self { Filter::All => true, - Filter::Term(Term::Sth) => days < Term::THRESHOLD_DAYS, - Filter::Term(Term::Lth) => days >= Term::THRESHOLD_DAYS, - Filter::Time(t) => t.contains(days), + Filter::Term(Term::Sth) => hours < Term::THRESHOLD_HOURS, + Filter::Term(Term::Lth) => hours >= Term::THRESHOLD_HOURS, + Filter::Time(t) => t.contains(hours), _ => false, } } @@ -54,12 +54,12 @@ impl Filter { match (self, other) { (Filter::All, _) => true, (Filter::Term(Term::Sth), Filter::Time(t)) => { - matches!(t, TimeFilter::LowerThan(d) if *d <= Term::THRESHOLD_DAYS) - || matches!(t, TimeFilter::Range(r) if r.end <= Term::THRESHOLD_DAYS) + matches!(t, TimeFilter::LowerThan(h) if *h <= Term::THRESHOLD_HOURS) + || matches!(t, TimeFilter::Range(r) if r.end <= Term::THRESHOLD_HOURS) } (Filter::Term(Term::Lth), Filter::Time(t)) => { - matches!(t, TimeFilter::GreaterOrEqual(d) if *d >= Term::THRESHOLD_DAYS) - || matches!(t, TimeFilter::Range(r) if r.start >= Term::THRESHOLD_DAYS) + matches!(t, TimeFilter::GreaterOrEqual(h) if *h >= Term::THRESHOLD_HOURS) + || matches!(t, TimeFilter::Range(r) if r.start >= Term::THRESHOLD_HOURS) } (Filter::Time(t1), Filter::Time(t2)) => t1.includes(t2), (Filter::Amount(a1), Filter::Amount(a2)) => a1.includes(a2), @@ -89,17 +89,17 @@ impl Filter { } /// Whether to compute adjusted metrics (adjusted SOPR, adjusted value created/destroyed) - /// For UTXO context: true for All, Term, max_age (LowerThan), and up_to_1d age range + /// For UTXO context: true for All, STH, and max_age (LowerThan) /// For Address context: always false + /// Note: LTH doesn't need adjusted (everything >= 5 months is already > 1 hour) + /// Note: age ranges don't need adjusted (0-1h data lives in its own cohort) pub fn compute_adjusted(&self, context: CohortContext) -> bool { match context { CohortContext::Address => false, - CohortContext::Utxo => match self { - Filter::All | Filter::Term(_) => true, - Filter::Time(TimeFilter::LowerThan(_)) => true, - Filter::Time(TimeFilter::Range(r)) if r.start == 0 => true, - _ => false, - }, + CohortContext::Utxo => matches!( + self, + Filter::All | Filter::Term(Term::Sth) | Filter::Time(TimeFilter::LowerThan(_)) + ), } } } diff --git a/crates/brk_cohort/src/lib.rs b/crates/brk_cohort/src/lib.rs index 11c08bcd4..48448625d 100644 --- a/crates/brk_cohort/src/lib.rs +++ b/crates/brk_cohort/src/lib.rs @@ -21,10 +21,11 @@ mod cohort_name; mod filter; mod filtered; mod state_level; -mod term; mod time_filter; mod utxo; +pub use brk_types::{Age, Term}; + pub use address::*; pub use amount_filter::*; pub use by_address_type::*; @@ -33,7 +34,6 @@ pub use by_amount_range::*; pub use by_any_address::*; pub use by_epoch::*; pub use by_ge_amount::*; -pub use by_year::*; pub use by_lt_amount::*; pub use by_max_age::*; pub use by_min_age::*; @@ -41,11 +41,11 @@ pub use by_spendable_type::*; pub use by_term::*; pub use by_type::*; pub use by_unspendable_type::*; +pub use by_year::*; pub use cohort_context::*; pub use cohort_name::*; pub use filter::*; pub use filtered::*; pub use state_level::*; -pub use term::*; pub use time_filter::*; pub use utxo::*; diff --git a/crates/brk_computer/src/distribution/block/cohort/sent.rs b/crates/brk_computer/src/distribution/block/cohort/sent.rs index d305f132a..e1e1f8252 100644 --- a/crates/brk_computer/src/distribution/block/cohort/sent.rs +++ b/crates/brk_computer/src/distribution/block/cohort/sent.rs @@ -1,7 +1,7 @@ use brk_cohort::{AmountBucket, ByAddressType}; use brk_error::Result; -use brk_types::{CheckedSub, Dollars, Height, Sats, Timestamp, TypeIndex}; -use vecdb::{VecIndex, unlikely}; +use brk_types::{Age, CheckedSub, Dollars, Height, Sats, Timestamp, TypeIndex}; +use vecdb::{unlikely, VecIndex}; use crate::distribution::{address::HeightToAddressTypeToVec, cohorts::AddressCohorts}; @@ -11,7 +11,7 @@ use super::super::cache::AddressLookup; /// /// For each spent UTXO: /// 1. Look up address data -/// 2. Calculate age metrics (blocks_old, days_old) +/// 2. Calculate age metrics /// 3. Update address balance and cohort membership /// 4. Handle addresses becoming empty /// @@ -33,13 +33,8 @@ pub fn process_sent( for (prev_height, by_type) in sent_data.into_iter() { let prev_price = height_to_price.map(|v| v[prev_height.to_usize()]); let prev_timestamp = height_to_timestamp[prev_height.to_usize()]; - let blocks_old = current_height.to_usize() - prev_height.to_usize(); - let days_old = current_timestamp.difference_in_days_between_float(prev_timestamp); - let older_than_hour = current_timestamp - .checked_sub(prev_timestamp) - .unwrap() - .is_more_than_hour(); + let age = Age::new(current_timestamp, prev_timestamp, blocks_old); for (output_type, vec) in by_type.unwrap().into_iter() { // Cache mutable refs for this address type @@ -123,15 +118,7 @@ pub fn process_sent( .state .as_mut() .unwrap() - .send( - addr_data, - value, - current_price, - prev_price, - blocks_old, - days_old, - older_than_hour, - )?; + .send(addr_data, value, current_price, prev_price, age)?; } } } diff --git a/crates/brk_computer/src/distribution/cohorts/address/vecs.rs b/crates/brk_computer/src/distribution/cohorts/address/vecs.rs index f8befcb89..f3ff7dbc1 100644 --- a/crates/brk_computer/src/distribution/cohorts/address/vecs.rs +++ b/crates/brk_computer/src/distribution/cohorts/address/vecs.rs @@ -72,6 +72,7 @@ impl AddressCohortVecs { version, indexes, price, + up_to_1h_realized: None, }; let height_to_addr_count = diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs index 70e8f9543..63e42ae0c 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs @@ -38,7 +38,33 @@ impl UTXOCohorts { ) -> Result { let v = version + VERSION; - // Create "all" cohort first - it doesn't need global sources (it IS the global source) + // 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, + f, + name, + v, + indexes, + price, + states_path, + StateLevel::Full, + None, + None, + ) + }; + + 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(); + + // Phase 2: Import "all" cohort (needs up_to_1h for adjusted, is global supply source) let all = UTXOCohortVecs::forced_import( db, Filter::All, @@ -49,13 +75,13 @@ impl UTXOCohorts { states_path, StateLevel::PriceOnly, None, + up_to_1h_realized, )?; - // Get reference to all's supply for other cohorts to use as global source let all_supply = Some(&all.metrics.supply); - // Create all cohorts first (while borrowing all_supply), then assemble struct - let price_only = |f: Filter, name: &'static str| { + // Phase 3: Import cohorts that need adjusted and/or all_supply + let price_only_adjusted = |f: Filter, name: &'static str| { UTXOCohortVecs::forced_import( db, f, @@ -66,12 +92,13 @@ impl UTXOCohorts { states_path, StateLevel::PriceOnly, all_supply, + up_to_1h_realized, ) }; - let term = ByTerm::try_new(&price_only)?; + let term = ByTerm::try_new(&price_only_adjusted)?; - let full = |f: Filter, name: &'static str| { + let none_adjusted = |f: Filter, name: &'static str| { UTXOCohortVecs::forced_import( db, f, @@ -80,10 +107,15 @@ impl UTXOCohorts { indexes, price, states_path, - StateLevel::Full, + StateLevel::None, all_supply, + up_to_1h_realized, ) }; + + let max_age = ByMaxAge::try_new(&none_adjusted)?; + + // Phase 4: Import remaining cohorts (no adjusted needed) let none = |f: Filter, name: &'static str| { UTXOCohortVecs::forced_import( db, @@ -95,16 +127,11 @@ impl UTXOCohorts { states_path, StateLevel::None, all_supply, + None, ) }; - let epoch = ByEpoch::try_new(&full)?; - let year = ByYear::try_new(&full)?; - let type_ = BySpendableType::try_new(&full)?; - let max_age = ByMaxAge::try_new(&none)?; let min_age = ByMinAge::try_new(&none)?; - let age_range = ByAgeRange::try_new(&full)?; - let amount_range = ByAmountRange::try_new(&full)?; let lt_amount = ByLowerThanAmount::try_new(&none)?; let ge_amount = ByGreatEqualAmount::try_new(&none)?; diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/receive.rs b/crates/brk_computer/src/distribution/cohorts/utxo/receive.rs index c9540f30d..9bef77d01 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/receive.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/receive.rs @@ -8,7 +8,7 @@ impl UTXOCohorts { /// Process received outputs for this block. /// /// New UTXOs are added to: - /// - The "up_to_1d" age cohort (all new UTXOs start at 0 days old) + /// - The "up_to_1h" age cohort (all new UTXOs start at 0 hours old) /// - The appropriate epoch cohort based on block height /// - The appropriate year cohort based on block timestamp /// - The appropriate output type cohort (P2PKH, P2SH, etc.) @@ -22,9 +22,9 @@ impl UTXOCohorts { ) { let supply_state = received.spendable_supply; - // New UTXOs go into up_to_1d, current epoch, and current year + // New UTXOs go into up_to_1h, current epoch, and current year [ - &mut self.0.age_range.up_to_1d, + &mut self.0.age_range.up_to_1h, self.0.epoch.mut_vec_from_height(height), self.0.year.mut_vec_from_timestamp(timestamp), ] diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/send.rs b/crates/brk_computer/src/distribution/cohorts/utxo/send.rs index b18de5b4e..14bb99705 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/send.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/send.rs @@ -1,4 +1,4 @@ -use brk_types::{CheckedSub, Height}; +use brk_types::{Age, Height}; use rustc_hash::FxHashMap; use vecdb::VecIndex; @@ -35,37 +35,22 @@ impl UTXOCohorts { let block_state = &chain_state[height.to_usize()]; let prev_price = block_state.price; let blocks_old = chain_len - 1 - height.to_usize(); - let days_old = last_timestamp.difference_in_days_between(block_state.timestamp); - let days_old_float = - last_timestamp.difference_in_days_between_float(block_state.timestamp); - let older_than_hour = last_timestamp - .checked_sub(block_state.timestamp) - .unwrap() - .is_more_than_hour(); + let age = Age::new(last_timestamp, block_state.timestamp, blocks_old); // Update age range cohort (direct index lookup) - self.0 - .age_range - .get_mut_by_days_old(days_old) - .state - .um() - .send( - &sent.spendable_supply, - current_price, - prev_price, - blocks_old, - days_old_float, - older_than_hour, - ); + self.0.age_range.get_mut(age).state.um().send( + &sent.spendable_supply, + current_price, + prev_price, + age, + ); // Update epoch cohort (direct lookup by height) self.0.epoch.mut_vec_from_height(height).state.um().send( &sent.spendable_supply, current_price, prev_price, - blocks_old, - days_old_float, - older_than_hour, + age, ); // Update year cohort (direct lookup by timestamp) @@ -74,42 +59,31 @@ impl UTXOCohorts { .mut_vec_from_timestamp(block_state.timestamp) .state .um() - .send( - &sent.spendable_supply, - current_price, - prev_price, - blocks_old, - days_old_float, - older_than_hour, - ); + .send(&sent.spendable_supply, current_price, prev_price, age); // Update output type cohorts sent.by_type .spendable .iter_typed() .for_each(|(output_type, supply_state)| { - self.0.type_.get_mut(output_type).state.um().send( - supply_state, - current_price, - prev_price, - blocks_old, - days_old_float, - older_than_hour, - ) + self.0 + .type_ + .get_mut(output_type) + .state + .um() + .send(supply_state, current_price, prev_price, age) }); // Update amount range cohorts sent.by_size_group .iter_typed() .for_each(|(group, supply_state)| { - self.0.amount_range.get_mut(group).state.um().send( - supply_state, - current_price, - prev_price, - blocks_old, - days_old_float, - older_than_hour, - ); + self.0 + .amount_range + .get_mut(group) + .state + .um() + .send(supply_state, current_price, prev_price, age); }); } } diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs b/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs index 61ab8c6ad..278a45c73 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs @@ -1,5 +1,5 @@ use brk_cohort::AGE_BOUNDARIES; -use brk_types::{ONE_DAY_IN_SEC, Timestamp}; +use brk_types::{ONE_HOUR_IN_SEC, Timestamp}; use crate::distribution::state::BlockState; @@ -8,11 +8,11 @@ use super::groups::UTXOCohorts; impl UTXOCohorts { /// Handle age transitions when processing a new block. /// - /// UTXOs age with each block. When they cross day boundaries, - /// they move between age-based cohorts (e.g., from "0-1d" to "1-7d"). + /// UTXOs age with each block. When they cross hour boundaries, + /// they move between age-based cohorts (e.g., from "0-1h" to "1h-1d"). /// /// Complexity: O(k * (log n + m)) where: - /// - k = 19 boundaries to check + /// - k = 20 boundaries to check /// - n = total blocks in chain_state /// - m = blocks crossing each boundary (typically 0-2 per boundary per block) pub fn tick_tock_next_block(&mut self, chain_state: &[BlockState], timestamp: Timestamp) { @@ -28,19 +28,19 @@ impl UTXOCohorts { return; } - // Get age_range cohort states (indexed 0..20) - // Cohort i covers days [BOUNDARIES[i-1], BOUNDARIES[i]) - // Cohort 0 covers [0, 1) days - // Cohort 19 covers [15*365, infinity) days + // Get age_range cohort states (indexed 0..21) + // Cohort i covers hours [BOUNDARIES[i-1], BOUNDARIES[i]) + // Cohort 0 covers [0, 1) hours + // Cohort 20 covers [15*365*24, infinity) hours let mut age_cohorts: Vec<_> = self.0.age_range.iter_mut().map(|v| &mut v.state).collect(); - // For each boundary, find blocks that just crossed it - for (boundary_idx, &boundary_days) in AGE_BOUNDARIES.iter().enumerate() { - let boundary_seconds = (boundary_days as u32) * ONE_DAY_IN_SEC; + // For each boundary (in hours), find blocks that just crossed it + for (boundary_idx, &boundary_hours) in AGE_BOUNDARIES.iter().enumerate() { + let boundary_seconds = (boundary_hours as u32) * ONE_HOUR_IN_SEC; - // Blocks crossing boundary B have timestamps in (prev - B*DAY, curr - B*DAY] - // prev_days < B and curr_days >= B - // means: block was younger than B days, now is B days or older + // Blocks crossing boundary B have timestamps in (prev - B*HOUR, curr - B*HOUR] + // prev_hours < B and curr_hours >= B + // means: block was younger than B hours, now is B hours or older let upper_timestamp = (*timestamp).saturating_sub(boundary_seconds); let lower_timestamp = (*prev_timestamp).saturating_sub(boundary_seconds); @@ -53,23 +53,11 @@ impl UTXOCohorts { let start_idx = chain_state.partition_point(|b| *b.timestamp <= lower_timestamp); let end_idx = chain_state.partition_point(|b| *b.timestamp <= upper_timestamp); - // Process blocks that crossed this boundary + // Move supply from younger cohort to older cohort for block_state in &chain_state[start_idx..end_idx] { - // Double-check the day boundary was actually crossed - // (handles edge cases with day boundaries) - let prev_days = prev_timestamp.difference_in_days_between(block_state.timestamp); - let curr_days = timestamp.difference_in_days_between(block_state.timestamp); - - if prev_days >= boundary_days || curr_days < boundary_days { - continue; - } - - // Block crossed from cohort[boundary_idx] to cohort[boundary_idx + 1] - // Decrement from the "younger" cohort if let Some(state) = age_cohorts[boundary_idx].as_mut() { state.decrement(&block_state.supply, block_state.price); } - // Increment in the "older" cohort if let Some(state) = age_cohorts[boundary_idx + 1].as_mut() { state.increment(&block_state.supply, block_state.price); } diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs b/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs index f827f6773..3961be19e 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs @@ -9,7 +9,7 @@ use vecdb::{AnyStoredVec, Database, Exit, IterableVec}; use crate::{ComputeIndexes, indexes, price, distribution::state::UTXOCohortState}; -use crate::distribution::metrics::{CohortMetrics, ImportConfig, SupplyMetrics}; +use crate::distribution::metrics::{CohortMetrics, ImportConfig, RealizedMetrics, SupplyMetrics}; use super::super::traits::{CohortVecs, DynCohortVecs}; @@ -33,6 +33,9 @@ impl UTXOCohortVecs { /// /// `all_supply` is the supply metrics from the "all" cohort, used as global /// sources for `*_rel_to_market_cap` ratios. Pass `None` for the "all" cohort itself. + /// + /// `up_to_1h_realized` is used for cohorts where `compute_adjusted()` is true, + /// to create lazy adjusted vecs: adjusted = cohort - up_to_1h. #[allow(clippy::too_many_arguments)] pub fn forced_import( db: &Database, @@ -44,6 +47,7 @@ impl UTXOCohortVecs { states_path: &Path, state_level: StateLevel, all_supply: Option<&SupplyMetrics>, + up_to_1h_realized: Option<&RealizedMetrics>, ) -> Result { let compute_dollars = price.is_some(); let full_name = CohortContext::Utxo.full_name(&filter, name); @@ -56,6 +60,7 @@ impl UTXOCohortVecs { version, indexes, price, + up_to_1h_realized, }; Ok(Self { diff --git a/crates/brk_computer/src/distribution/metrics/config.rs b/crates/brk_computer/src/distribution/metrics/config.rs index c74933339..dd2d7d5a2 100644 --- a/crates/brk_computer/src/distribution/metrics/config.rs +++ b/crates/brk_computer/src/distribution/metrics/config.rs @@ -4,6 +4,8 @@ use vecdb::Database; use crate::{indexes, price}; +use super::RealizedMetrics; + /// Configuration for importing metrics. pub struct ImportConfig<'a> { pub db: &'a Database, @@ -13,6 +15,9 @@ pub struct ImportConfig<'a> { pub version: Version, pub indexes: &'a indexes::Vecs, pub price: Option<&'a price::Vecs>, + /// Source for lazy adjusted computation: adjusted = cohort - up_to_1h. + /// Required for cohorts where `compute_adjusted()` is true. + pub up_to_1h_realized: Option<&'a RealizedMetrics>, } impl<'a> ImportConfig<'a> { diff --git a/crates/brk_computer/src/distribution/metrics/realized.rs b/crates/brk_computer/src/distribution/metrics/realized.rs index b5efc7d0f..82a6f9e5c 100644 --- a/crates/brk_computer/src/distribution/metrics/realized.rs +++ b/crates/brk_computer/src/distribution/metrics/realized.rs @@ -13,8 +13,8 @@ use crate::{ indexes, internal::{ ComputedRatioVecsFromDateIndex, ComputedVecsFromDateIndex, ComputedVecsFromHeight, - LazyVecsFrom2FromHeight, LazyVecsFromDateIndex, LazyVecsFromHeight, PercentageDollarsF32, - Source, StoredF32Identity, VecBuilderOptions, + DollarsMinus, LazyVecsFrom2FromHeight, LazyVecsFromDateIndex, LazyVecsFromHeight, + PercentageDollarsF32, Source, StoredF32Identity, VecBuilderOptions, }, price, utils::OptionExt, @@ -64,11 +64,11 @@ pub struct RealizedMetrics { pub height_to_value_destroyed: EagerVec>, pub indexes_to_value_destroyed: ComputedVecsFromHeight, - // === Adjusted Value (optional) === - pub height_to_adjusted_value_created: Option>>, - pub indexes_to_adjusted_value_created: Option>, - pub height_to_adjusted_value_destroyed: Option>>, - pub indexes_to_adjusted_value_destroyed: Option>, + // === Adjusted Value (lazy: cohort - up_to_1h) === + pub indexes_to_adjusted_value_created: + Option>, + pub indexes_to_adjusted_value_destroyed: + Option>, // === SOPR (Spent Output Profit Ratio) === pub dateindex_to_sopr: EagerVec>, @@ -226,16 +226,48 @@ impl RealizedMetrics { let height_to_value_destroyed = EagerVec::forced_import(cfg.db, &cfg.name("value_destroyed"), cfg.version)?; - let height_to_adjusted_value_created = compute_adjusted + let indexes_to_value_created = ComputedVecsFromHeight::forced_import( + cfg.db, + &cfg.name("value_created"), + Source::Vec(height_to_value_created.boxed_clone()), + cfg.version, + cfg.indexes, + sum, + )?; + let indexes_to_value_destroyed = ComputedVecsFromHeight::forced_import( + cfg.db, + &cfg.name("value_destroyed"), + Source::Vec(height_to_value_destroyed.boxed_clone()), + cfg.version, + cfg.indexes, + sum, + )?; + + // Create lazy adjusted vecs if compute_adjusted and up_to_1h is available + let indexes_to_adjusted_value_created = (compute_adjusted && cfg.up_to_1h_realized.is_some()) .then(|| { - EagerVec::forced_import(cfg.db, &cfg.name("adjusted_value_created"), cfg.version) - }) - .transpose()?; - let height_to_adjusted_value_destroyed = compute_adjusted - .then(|| { - EagerVec::forced_import(cfg.db, &cfg.name("adjusted_value_destroyed"), cfg.version) - }) - .transpose()?; + let up_to_1h = cfg.up_to_1h_realized.unwrap(); + LazyVecsFrom2FromHeight::from_computed::( + &cfg.name("adjusted_value_created"), + cfg.version, + height_to_value_created.boxed_clone(), + up_to_1h.height_to_value_created.boxed_clone(), + &indexes_to_value_created, + &up_to_1h.indexes_to_value_created, + ) + }); + let indexes_to_adjusted_value_destroyed = + (compute_adjusted && cfg.up_to_1h_realized.is_some()).then(|| { + let up_to_1h = cfg.up_to_1h_realized.unwrap(); + LazyVecsFrom2FromHeight::from_computed::( + &cfg.name("adjusted_value_destroyed"), + cfg.version, + height_to_value_destroyed.boxed_clone(), + up_to_1h.height_to_value_destroyed.boxed_clone(), + &indexes_to_value_destroyed, + &up_to_1h.indexes_to_value_destroyed, + ) + }); // Create realized_price_extra first so we can reference its ratio for MVRV proxy let indexes_to_realized_price_extra = ComputedRatioVecsFromDateIndex::forced_import( @@ -317,62 +349,14 @@ impl RealizedMetrics { .transpose()?, // === Value Created/Destroyed === - indexes_to_value_created: ComputedVecsFromHeight::forced_import( - cfg.db, - &cfg.name("value_created"), - Source::Vec(height_to_value_created.boxed_clone()), - cfg.version, - cfg.indexes, - sum, - )?, - indexes_to_value_destroyed: ComputedVecsFromHeight::forced_import( - cfg.db, - &cfg.name("value_destroyed"), - Source::Vec(height_to_value_destroyed.boxed_clone()), - cfg.version, - cfg.indexes, - sum, - )?, height_to_value_created, + indexes_to_value_created, height_to_value_destroyed, + indexes_to_value_destroyed, - // === Adjusted Value (optional) === - indexes_to_adjusted_value_created: compute_adjusted - .then(|| { - ComputedVecsFromHeight::forced_import( - cfg.db, - &cfg.name("adjusted_value_created"), - Source::Vec( - height_to_adjusted_value_created - .as_ref() - .unwrap() - .boxed_clone(), - ), - cfg.version, - cfg.indexes, - sum, - ) - }) - .transpose()?, - indexes_to_adjusted_value_destroyed: compute_adjusted - .then(|| { - ComputedVecsFromHeight::forced_import( - cfg.db, - &cfg.name("adjusted_value_destroyed"), - Source::Vec( - height_to_adjusted_value_destroyed - .as_ref() - .unwrap() - .boxed_clone(), - ), - cfg.version, - cfg.indexes, - sum, - ) - }) - .transpose()?, - height_to_adjusted_value_created, - height_to_adjusted_value_destroyed, + // === Adjusted Value (lazy: cohort - up_to_1h) === + indexes_to_adjusted_value_created, + indexes_to_adjusted_value_destroyed, // === SOPR === dateindex_to_sopr: EagerVec::forced_import( @@ -464,22 +448,12 @@ impl RealizedMetrics { /// Get minimum length across height-indexed vectors written in block loop. pub fn min_stateful_height_len(&self) -> usize { - let mut min = self - .height_to_realized_cap + self.height_to_realized_cap .len() .min(self.height_to_realized_profit.len()) .min(self.height_to_realized_loss.len()) .min(self.height_to_value_created.len()) - .min(self.height_to_value_destroyed.len()); - - if let Some(v) = &self.height_to_adjusted_value_created { - min = min.min(v.len()); - } - if let Some(v) = &self.height_to_adjusted_value_destroyed { - min = min.min(v.len()); - } - - min + .min(self.height_to_value_destroyed.len()) } /// Push realized state values to height-indexed vectors. @@ -495,13 +469,6 @@ impl RealizedMetrics { self.height_to_value_destroyed .truncate_push(height, state.value_destroyed)?; - if let Some(v) = self.height_to_adjusted_value_created.as_mut() { - v.truncate_push(height, state.adj_value_created)?; - } - if let Some(v) = self.height_to_adjusted_value_destroyed.as_mut() { - v.truncate_push(height, state.adj_value_destroyed)?; - } - Ok(()) } @@ -512,31 +479,19 @@ impl RealizedMetrics { self.height_to_realized_loss.write()?; self.height_to_value_created.write()?; self.height_to_value_destroyed.write()?; - if let Some(v) = self.height_to_adjusted_value_created.as_mut() { - v.write()?; - } - if let Some(v) = self.height_to_adjusted_value_destroyed.as_mut() { - v.write()?; - } Ok(()) } /// Returns a parallel iterator over all vecs for parallel writing. pub fn par_iter_mut(&mut self) -> impl ParallelIterator { - let mut vecs: Vec<&mut dyn AnyStoredVec> = vec![ - &mut self.height_to_realized_cap, + [ + &mut self.height_to_realized_cap as &mut dyn AnyStoredVec, &mut self.height_to_realized_profit, &mut self.height_to_realized_loss, &mut self.height_to_value_created, &mut self.height_to_value_destroyed, - ]; - if let Some(v) = self.height_to_adjusted_value_created.as_mut() { - vecs.push(v); - } - if let Some(v) = self.height_to_adjusted_value_destroyed.as_mut() { - vecs.push(v); - } - vecs.into_par_iter() + ] + .into_par_iter() } /// Validate computed versions against base version. @@ -593,37 +548,6 @@ impl RealizedMetrics { exit, )?; - if self.height_to_adjusted_value_created.is_some() { - self.height_to_adjusted_value_created - .um() - .compute_sum_of_others( - starting_indexes.height, - &others - .iter() - .map(|v| { - v.height_to_adjusted_value_created - .as_ref() - .unwrap_or(&v.height_to_value_created) - }) - .collect::>(), - exit, - )?; - self.height_to_adjusted_value_destroyed - .um() - .compute_sum_of_others( - starting_indexes.height, - &others - .iter() - .map(|v| { - v.height_to_adjusted_value_destroyed - .as_ref() - .unwrap_or(&v.height_to_value_destroyed) - }) - .collect::>(), - exit, - )?; - } - Ok(()) } @@ -695,25 +619,6 @@ impl RealizedMetrics { Some(&self.height_to_value_destroyed), )?; - // Optional: adjusted value - if let Some(adjusted_value_created) = self.indexes_to_adjusted_value_created.as_mut() { - adjusted_value_created.compute_rest( - indexes, - starting_indexes, - exit, - self.height_to_adjusted_value_created.as_ref(), - )?; - } - - if let Some(adjusted_value_destroyed) = self.indexes_to_adjusted_value_destroyed.as_mut() { - adjusted_value_destroyed.compute_rest( - indexes, - starting_indexes, - exit, - self.height_to_adjusted_value_destroyed.as_ref(), - )?; - } - Ok(()) } @@ -784,16 +689,20 @@ impl RealizedMetrics { exit, )?; - // Optional: adjusted SOPR + // Optional: adjusted SOPR (lazy: cohort - up_to_1h) if let (Some(adjusted_sopr), Some(adj_created), Some(adj_destroyed)) = ( self.dateindex_to_adjusted_sopr.as_mut(), - self.indexes_to_adjusted_value_created.as_ref(), - self.indexes_to_adjusted_value_destroyed.as_ref(), + self.indexes_to_adjusted_value_created + .as_ref() + .and_then(|v| v.dateindex.sum.as_ref()), + self.indexes_to_adjusted_value_destroyed + .as_ref() + .and_then(|v| v.dateindex.sum.as_ref()), ) { adjusted_sopr.compute_divide( starting_indexes.dateindex, - adj_created.dateindex.unwrap_sum(), - adj_destroyed.dateindex.unwrap_sum(), + adj_created.as_ref(), + adj_destroyed.as_ref(), exit, )?; diff --git a/crates/brk_computer/src/distribution/state/cohort/address.rs b/crates/brk_computer/src/distribution/state/cohort/address.rs index c191e7da3..c443286a5 100644 --- a/crates/brk_computer/src/distribution/state/cohort/address.rs +++ b/crates/brk_computer/src/distribution/state/cohort/address.rs @@ -1,13 +1,10 @@ use std::path::Path; use brk_error::Result; -use brk_types::{Dollars, Height, LoadedAddressData, Sats, SupplyState}; +use brk_types::{Age, Dollars, Height, LoadedAddressData, Sats, SupplyState}; use vecdb::unlikely; -use super::{ - super::cost_basis::RealizedState, - base::CohortState, -}; +use super::{super::cost_basis::RealizedState, base::CohortState}; #[derive(Clone)] pub struct AddressCohortState { @@ -43,16 +40,13 @@ impl AddressCohortState { self.inner.reset_single_iteration_values(); } - #[allow(clippy::too_many_arguments)] pub fn send( &mut self, addressdata: &mut LoadedAddressData, value: Sats, current_price: Option, prev_price: Option, - blocks_old: usize, - days_old: f64, - older_than_hour: bool, + age: Age, ) -> Result<()> { let compute_price = current_price.is_some(); @@ -76,9 +70,7 @@ impl AddressCohortState { }, current_price, prev_price, - blocks_old, - days_old, - older_than_hour, + age, compute_price.then(|| (addressdata.realized_price(), &supply_state)), prev_realized_price.map(|prev_price| (prev_price, &prev_supply_state)), ); diff --git a/crates/brk_computer/src/distribution/state/cohort/base.rs b/crates/brk_computer/src/distribution/state/cohort/base.rs index ee613cf63..cda01f11e 100644 --- a/crates/brk_computer/src/distribution/state/cohort/base.rs +++ b/crates/brk_computer/src/distribution/state/cohort/base.rs @@ -1,7 +1,7 @@ use std::path::Path; use brk_error::Result; -use brk_types::{Dollars, Height, Sats, SupplyState}; +use brk_types::{Age, Dollars, Height, Sats, SupplyState}; use crate::internal::PERCENTILES_LEN; @@ -246,17 +246,13 @@ impl CohortState { supply: &SupplyState, current_price: Option, prev_price: Option, - blocks_old: usize, - days_old: f64, - older_than_hour: bool, + age: Age, ) { self.send_( supply, current_price, prev_price, - blocks_old, - days_old, - older_than_hour, + age, None, prev_price.map(|prev_price| (prev_price, supply)), ); @@ -269,9 +265,7 @@ impl CohortState { supply: &SupplyState, current_price: Option, prev_price: Option, - blocks_old: usize, - days_old: f64, - older_than_hour: bool, + age: Age, price_to_amount_increment: Option<(Dollars, &SupplyState)>, price_to_amount_decrement: Option<(Dollars, &SupplyState)>, ) { @@ -283,14 +277,13 @@ impl CohortState { if supply.value > Sats::ZERO { self.sent += supply.value; - self.satblocks_destroyed += supply.value * blocks_old; - self.satdays_destroyed += - Sats::from((u64::from(supply.value) as f64 * days_old).floor() as u64); + self.satblocks_destroyed += age.satblocks_destroyed(supply.value); + self.satdays_destroyed += age.satdays_destroyed(supply.value); if let Some(realized) = self.realized.as_mut() { let current_price = current_price.unwrap(); let prev_price = prev_price.unwrap(); - realized.send(supply, current_price, prev_price, older_than_hour); + realized.send(supply, current_price, prev_price); if let Some((price, supply)) = price_to_amount_increment && supply.value.is_not_zero() diff --git a/crates/brk_computer/src/distribution/state/cost_basis/realized.rs b/crates/brk_computer/src/distribution/state/cost_basis/realized.rs index 264d1a35e..d7f95aa9a 100644 --- a/crates/brk_computer/src/distribution/state/cost_basis/realized.rs +++ b/crates/brk_computer/src/distribution/state/cost_basis/realized.rs @@ -8,9 +8,7 @@ pub struct RealizedState { pub profit: Dollars, pub loss: Dollars, pub value_created: Dollars, - pub adj_value_created: Dollars, pub value_destroyed: Dollars, - pub adj_value_destroyed: Dollars, } impl RealizedState { @@ -19,9 +17,7 @@ impl RealizedState { profit: Dollars::NAN, loss: Dollars::NAN, value_created: Dollars::NAN, - adj_value_created: Dollars::NAN, value_destroyed: Dollars::NAN, - adj_value_destroyed: Dollars::NAN, }; pub fn reset_single_iteration_values(&mut self) { @@ -29,9 +25,7 @@ impl RealizedState { self.profit = Dollars::ZERO; self.loss = Dollars::ZERO; self.value_created = Dollars::ZERO; - self.adj_value_created = Dollars::ZERO; self.value_destroyed = Dollars::ZERO; - self.adj_value_destroyed = Dollars::ZERO; } } @@ -49,9 +43,7 @@ impl RealizedState { self.profit = Dollars::ZERO; self.loss = Dollars::ZERO; self.value_created = Dollars::ZERO; - self.adj_value_created = Dollars::ZERO; self.value_destroyed = Dollars::ZERO; - self.adj_value_destroyed = Dollars::ZERO; } self.cap += realized_cap; @@ -74,7 +66,6 @@ impl RealizedState { supply_state: &SupplyState, current_price: Dollars, prev_price: Dollars, - older_than_hour: bool, ) { let current_value = current_price * supply_state.value; let prev_value = prev_price * supply_state.value; @@ -82,11 +73,6 @@ impl RealizedState { self.value_created += current_value; self.value_destroyed += prev_value; - if older_than_hour { - self.adj_value_created += current_value; - self.adj_value_destroyed += prev_value; - } - match current_price.cmp(&prev_price) { Ordering::Greater => { self.profit += current_value.checked_sub(prev_value).unwrap(); diff --git a/crates/brk_types/src/age.rs b/crates/brk_types/src/age.rs new file mode 100644 index 000000000..f2a40274c --- /dev/null +++ b/crates/brk_types/src/age.rs @@ -0,0 +1,65 @@ +use crate::{Sats, Term, Timestamp}; + +/// Represents the age of a UTXO or address balance. +/// Encapsulates all age-related calculations in one type-safe struct. +#[derive(Debug, Clone, Copy)] +pub struct Age { + /// Age in hours (primary internal unit for cohort boundaries) + hours: usize, + /// Age in blocks (for satblocks_destroyed calculation) + blocks: usize, + /// Age in days as float (for satdays_destroyed - established terminology) + days: f64, +} + +impl Age { + /// Create from timestamps and block count + #[inline] + pub fn new(current_timestamp: Timestamp, prev_timestamp: Timestamp, blocks: usize) -> Self { + Self { + hours: current_timestamp.difference_in_hours_between(prev_timestamp), + blocks, + days: current_timestamp.difference_in_days_between_float(prev_timestamp), + } + } + + /// Hours old (for cohort bucket lookup via HOURS_* boundaries) + #[inline] + pub fn hours(&self) -> usize { + self.hours + } + + /// Blocks old (for satblocks_destroyed calculation) + #[inline] + pub fn blocks(&self) -> usize { + self.blocks + } + + /// Days old as float (for satdays_destroyed - established terminology) + #[inline] + pub fn days(&self) -> f64 { + self.days + } + + /// STH or LTH based on age (5 months = 3600 hours threshold) + #[inline] + pub fn term(&self) -> Term { + if self.hours >= Term::THRESHOLD_HOURS { + Term::Lth + } else { + Term::Sth + } + } + + /// Calculate satblocks destroyed for given supply + #[inline] + pub fn satblocks_destroyed(&self, supply: Sats) -> Sats { + Sats::from(u64::from(supply) * self.blocks as u64) + } + + /// Calculate satdays destroyed for given supply + #[inline] + pub fn satdays_destroyed(&self, supply: Sats) -> Sats { + Sats::from((u64::from(supply) as f64 * self.days).floor() as u64) + } +} diff --git a/crates/brk_types/src/lib.rs b/crates/brk_types/src/lib.rs index 0a657f0b5..7e5e342f6 100644 --- a/crates/brk_types/src/lib.rs +++ b/crates/brk_types/src/lib.rs @@ -4,6 +4,7 @@ pub use vecdb::{CheckedSub, Exit, PrintableIndex, Version}; mod address; mod addressbytes; +mod age; mod addresschainstats; mod addresshash; mod addressindexoutpoint; @@ -131,6 +132,7 @@ mod stored_u8; mod supply_state; mod timeperiod; mod timeperiodparam; +mod term; mod timestamp; mod timestampparam; mod treenode; @@ -163,6 +165,7 @@ mod yearindex; pub use address::*; pub use addressbytes::*; +pub use age::*; pub use addresschainstats::*; pub use addresshash::*; pub use addressindexoutpoint::*; @@ -288,6 +291,7 @@ pub use stored_u16::*; pub use stored_u32::*; pub use stored_u64::*; pub use supply_state::*; +pub use term::*; pub use timeperiod::*; pub use timeperiodparam::*; pub use timestamp::*; diff --git a/crates/brk_cohort/src/term.rs b/crates/brk_types/src/term.rs similarity index 54% rename from crates/brk_cohort/src/term.rs rename to crates/brk_types/src/term.rs index 372faa9c5..dc20e430c 100644 --- a/crates/brk_cohort/src/term.rs +++ b/crates/brk_types/src/term.rs @@ -1,7 +1,5 @@ -use crate::DAYS_5M; - /// Classification for short-term vs long-term holders. -/// The threshold is 150 days (approximately 5 months). +/// The threshold is 150 days (approximately 5 months) = 3600 hours. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Term { /// Short-Term Holder: < 150 days @@ -11,5 +9,6 @@ pub enum Term { } impl Term { - pub const THRESHOLD_DAYS: usize = DAYS_5M; + /// Threshold in hours (150 days * 24 hours = 3600 hours) + pub const THRESHOLD_HOURS: usize = 24 * 150; // 3600 } diff --git a/crates/brk_types/src/timestamp.rs b/crates/brk_types/src/timestamp.rs index c302155a4..a8d19b8e4 100644 --- a/crates/brk_types/src/timestamp.rs +++ b/crates/brk_types/src/timestamp.rs @@ -66,6 +66,11 @@ impl Timestamp { (self.0 - older.0) as f64 / ONE_DAY_IN_SEC_F64 } + #[inline] + pub fn difference_in_hours_between(&self, older: Self) -> usize { + ((self.0 - older.0) / ONE_HOUR_IN_SEC) as usize + } + #[inline] pub fn is_more_than_hour(&self) -> bool { self.0 >= ONE_HOUR_IN_SEC diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index e5784bea5..2aa0db3f3 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -1901,8 +1901,8 @@ function createMetricPattern41(client, name) { * @property {MetricPattern21} adjustedSopr * @property {MetricPattern21} adjustedSopr30dEma * @property {MetricPattern21} adjustedSopr7dEma - * @property {MetricPattern1} adjustedValueCreated - * @property {MetricPattern1} adjustedValueDestroyed + * @property {TotalRealizedPnlPattern} adjustedValueCreated + * @property {TotalRealizedPnlPattern} adjustedValueDestroyed * @property {MetricPattern4} mvrv * @property {BlockCountPattern} negRealizedLoss * @property {BlockCountPattern} netRealizedPnl @@ -1943,8 +1943,8 @@ function createRealizedPattern3(client, acc) { adjustedSopr: createMetricPattern21(client, _m(acc, 'adjusted_sopr')), adjustedSopr30dEma: createMetricPattern21(client, _m(acc, 'adjusted_sopr_30d_ema')), adjustedSopr7dEma: createMetricPattern21(client, _m(acc, 'adjusted_sopr_7d_ema')), - adjustedValueCreated: createMetricPattern1(client, _m(acc, 'adjusted_value_created')), - adjustedValueDestroyed: createMetricPattern1(client, _m(acc, 'adjusted_value_destroyed')), + adjustedValueCreated: createTotalRealizedPnlPattern(client, _m(acc, 'adjusted_value_created')), + adjustedValueDestroyed: createTotalRealizedPnlPattern(client, _m(acc, 'adjusted_value_destroyed')), mvrv: createMetricPattern4(client, _m(acc, 'mvrv')), negRealizedLoss: createBlockCountPattern(client, _m(acc, 'neg_realized_loss')), netRealizedPnl: createBlockCountPattern(client, _m(acc, 'net_realized_pnl')), @@ -1980,8 +1980,8 @@ function createRealizedPattern3(client, acc) { * @property {MetricPattern21} adjustedSopr * @property {MetricPattern21} adjustedSopr30dEma * @property {MetricPattern21} adjustedSopr7dEma - * @property {MetricPattern1} adjustedValueCreated - * @property {MetricPattern1} adjustedValueDestroyed + * @property {TotalRealizedPnlPattern} adjustedValueCreated + * @property {TotalRealizedPnlPattern} adjustedValueDestroyed * @property {MetricPattern4} mvrv * @property {BlockCountPattern} negRealizedLoss * @property {BlockCountPattern} netRealizedPnl @@ -2020,8 +2020,8 @@ function createRealizedPattern4(client, acc) { adjustedSopr: createMetricPattern21(client, _m(acc, 'adjusted_sopr')), adjustedSopr30dEma: createMetricPattern21(client, _m(acc, 'adjusted_sopr_30d_ema')), adjustedSopr7dEma: createMetricPattern21(client, _m(acc, 'adjusted_sopr_7d_ema')), - adjustedValueCreated: createMetricPattern1(client, _m(acc, 'adjusted_value_created')), - adjustedValueDestroyed: createMetricPattern1(client, _m(acc, 'adjusted_value_destroyed')), + adjustedValueCreated: createTotalRealizedPnlPattern(client, _m(acc, 'adjusted_value_created')), + adjustedValueDestroyed: createTotalRealizedPnlPattern(client, _m(acc, 'adjusted_value_destroyed')), mvrv: createMetricPattern4(client, _m(acc, 'mvrv')), negRealizedLoss: createBlockCountPattern(client, _m(acc, 'neg_realized_loss')), netRealizedPnl: createBlockCountPattern(client, _m(acc, 'net_realized_pnl')), @@ -2310,59 +2310,6 @@ function createPrice111dSmaPattern(client, acc) { }; } -/** - * @typedef {Object} PercentilesPattern - * @property {MetricPattern4} costBasisPct05 - * @property {MetricPattern4} costBasisPct10 - * @property {MetricPattern4} costBasisPct15 - * @property {MetricPattern4} costBasisPct20 - * @property {MetricPattern4} costBasisPct25 - * @property {MetricPattern4} costBasisPct30 - * @property {MetricPattern4} costBasisPct35 - * @property {MetricPattern4} costBasisPct40 - * @property {MetricPattern4} costBasisPct45 - * @property {MetricPattern4} costBasisPct50 - * @property {MetricPattern4} costBasisPct55 - * @property {MetricPattern4} costBasisPct60 - * @property {MetricPattern4} costBasisPct65 - * @property {MetricPattern4} costBasisPct70 - * @property {MetricPattern4} costBasisPct75 - * @property {MetricPattern4} costBasisPct80 - * @property {MetricPattern4} costBasisPct85 - * @property {MetricPattern4} costBasisPct90 - * @property {MetricPattern4} costBasisPct95 - */ - -/** - * Create a PercentilesPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {PercentilesPattern} - */ -function createPercentilesPattern(client, acc) { - return { - costBasisPct05: createMetricPattern4(client, _m(acc, 'pct05')), - costBasisPct10: createMetricPattern4(client, _m(acc, 'pct10')), - costBasisPct15: createMetricPattern4(client, _m(acc, 'pct15')), - costBasisPct20: createMetricPattern4(client, _m(acc, 'pct20')), - costBasisPct25: createMetricPattern4(client, _m(acc, 'pct25')), - costBasisPct30: createMetricPattern4(client, _m(acc, 'pct30')), - costBasisPct35: createMetricPattern4(client, _m(acc, 'pct35')), - costBasisPct40: createMetricPattern4(client, _m(acc, 'pct40')), - costBasisPct45: createMetricPattern4(client, _m(acc, 'pct45')), - costBasisPct50: createMetricPattern4(client, _m(acc, 'pct50')), - costBasisPct55: createMetricPattern4(client, _m(acc, 'pct55')), - costBasisPct60: createMetricPattern4(client, _m(acc, 'pct60')), - costBasisPct65: createMetricPattern4(client, _m(acc, 'pct65')), - costBasisPct70: createMetricPattern4(client, _m(acc, 'pct70')), - costBasisPct75: createMetricPattern4(client, _m(acc, 'pct75')), - costBasisPct80: createMetricPattern4(client, _m(acc, 'pct80')), - costBasisPct85: createMetricPattern4(client, _m(acc, 'pct85')), - costBasisPct90: createMetricPattern4(client, _m(acc, 'pct90')), - costBasisPct95: createMetricPattern4(client, _m(acc, 'pct95')), - }; -} - /** * @typedef {Object} ActivePriceRatioPattern * @property {MetricPattern4} ratio @@ -2417,7 +2364,60 @@ function createActivePriceRatioPattern(client, acc) { } /** - * @typedef {Object} RelativePattern2 + * @typedef {Object} PercentilesPattern + * @property {MetricPattern4} costBasisPct05 + * @property {MetricPattern4} costBasisPct10 + * @property {MetricPattern4} costBasisPct15 + * @property {MetricPattern4} costBasisPct20 + * @property {MetricPattern4} costBasisPct25 + * @property {MetricPattern4} costBasisPct30 + * @property {MetricPattern4} costBasisPct35 + * @property {MetricPattern4} costBasisPct40 + * @property {MetricPattern4} costBasisPct45 + * @property {MetricPattern4} costBasisPct50 + * @property {MetricPattern4} costBasisPct55 + * @property {MetricPattern4} costBasisPct60 + * @property {MetricPattern4} costBasisPct65 + * @property {MetricPattern4} costBasisPct70 + * @property {MetricPattern4} costBasisPct75 + * @property {MetricPattern4} costBasisPct80 + * @property {MetricPattern4} costBasisPct85 + * @property {MetricPattern4} costBasisPct90 + * @property {MetricPattern4} costBasisPct95 + */ + +/** + * Create a PercentilesPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {PercentilesPattern} + */ +function createPercentilesPattern(client, acc) { + return { + costBasisPct05: createMetricPattern4(client, _m(acc, 'pct05')), + costBasisPct10: createMetricPattern4(client, _m(acc, 'pct10')), + costBasisPct15: createMetricPattern4(client, _m(acc, 'pct15')), + costBasisPct20: createMetricPattern4(client, _m(acc, 'pct20')), + costBasisPct25: createMetricPattern4(client, _m(acc, 'pct25')), + costBasisPct30: createMetricPattern4(client, _m(acc, 'pct30')), + costBasisPct35: createMetricPattern4(client, _m(acc, 'pct35')), + costBasisPct40: createMetricPattern4(client, _m(acc, 'pct40')), + costBasisPct45: createMetricPattern4(client, _m(acc, 'pct45')), + costBasisPct50: createMetricPattern4(client, _m(acc, 'pct50')), + costBasisPct55: createMetricPattern4(client, _m(acc, 'pct55')), + costBasisPct60: createMetricPattern4(client, _m(acc, 'pct60')), + costBasisPct65: createMetricPattern4(client, _m(acc, 'pct65')), + costBasisPct70: createMetricPattern4(client, _m(acc, 'pct70')), + costBasisPct75: createMetricPattern4(client, _m(acc, 'pct75')), + costBasisPct80: createMetricPattern4(client, _m(acc, 'pct80')), + costBasisPct85: createMetricPattern4(client, _m(acc, 'pct85')), + costBasisPct90: createMetricPattern4(client, _m(acc, 'pct90')), + costBasisPct95: createMetricPattern4(client, _m(acc, 'pct95')), + }; +} + +/** + * @typedef {Object} RelativePattern5 * @property {MetricPattern5} negUnrealizedLossRelToMarketCap * @property {MetricPattern5} negUnrealizedLossRelToOwnMarketCap * @property {MetricPattern5} negUnrealizedLossRelToOwnTotalUnrealizedPnl @@ -2439,12 +2439,12 @@ function createActivePriceRatioPattern(client, acc) { */ /** - * Create a RelativePattern2 pattern node + * Create a RelativePattern5 pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {RelativePattern2} + * @returns {RelativePattern5} */ -function createRelativePattern2(client, acc) { +function createRelativePattern5(client, acc) { return { negUnrealizedLossRelToMarketCap: createMetricPattern5(client, _m(acc, 'neg_unrealized_loss_rel_to_market_cap')), negUnrealizedLossRelToOwnMarketCap: createMetricPattern5(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')), @@ -2631,6 +2631,45 @@ function createPeriodAvgPricePattern(client, acc) { }; } +/** + * @template T + * @typedef {Object} BitcoinPattern + * @property {MetricPattern2} average + * @property {MetricPattern25} base + * @property {MetricPattern1} cumulative + * @property {MetricPattern2} max + * @property {MetricPattern21} median + * @property {MetricPattern2} min + * @property {MetricPattern21} pct10 + * @property {MetricPattern21} pct25 + * @property {MetricPattern21} pct75 + * @property {MetricPattern21} pct90 + * @property {MetricPattern2} sum + */ + +/** + * Create a BitcoinPattern pattern node + * @template T + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {BitcoinPattern} + */ +function createBitcoinPattern(client, acc) { + return { + average: createMetricPattern2(client, _m(acc, 'avg')), + base: createMetricPattern25(client, acc), + cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), + max: createMetricPattern2(client, _m(acc, 'max')), + median: createMetricPattern21(client, _m(acc, 'median')), + min: createMetricPattern2(client, _m(acc, 'min')), + pct10: createMetricPattern21(client, _m(acc, 'pct10')), + pct25: createMetricPattern21(client, _m(acc, 'pct25')), + pct75: createMetricPattern21(client, _m(acc, 'pct75')), + pct90: createMetricPattern21(client, _m(acc, 'pct90')), + sum: createMetricPattern2(client, _m(acc, 'sum')), + }; +} + /** * @template T * @typedef {Object} ClassAvgPricePattern @@ -2671,41 +2710,37 @@ function createClassAvgPricePattern(client, acc) { } /** - * @template T - * @typedef {Object} BitcoinPattern - * @property {MetricPattern2} average - * @property {MetricPattern25} base - * @property {MetricPattern1} cumulative - * @property {MetricPattern2} max - * @property {MetricPattern21} median - * @property {MetricPattern2} min - * @property {MetricPattern21} pct10 - * @property {MetricPattern21} pct25 - * @property {MetricPattern21} pct75 - * @property {MetricPattern21} pct90 - * @property {MetricPattern2} sum + * @typedef {Object} RelativePattern2 + * @property {MetricPattern5} negUnrealizedLossRelToOwnMarketCap + * @property {MetricPattern5} negUnrealizedLossRelToOwnTotalUnrealizedPnl + * @property {MetricPattern3} netUnrealizedPnlRelToOwnMarketCap + * @property {MetricPattern3} netUnrealizedPnlRelToOwnTotalUnrealizedPnl + * @property {MetricPattern5} supplyInLossRelToOwnSupply + * @property {MetricPattern5} supplyInProfitRelToOwnSupply + * @property {MetricPattern5} unrealizedLossRelToOwnMarketCap + * @property {MetricPattern5} unrealizedLossRelToOwnTotalUnrealizedPnl + * @property {MetricPattern5} unrealizedProfitRelToOwnMarketCap + * @property {MetricPattern5} unrealizedProfitRelToOwnTotalUnrealizedPnl */ /** - * Create a BitcoinPattern pattern node - * @template T + * Create a RelativePattern2 pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {BitcoinPattern} + * @returns {RelativePattern2} */ -function createBitcoinPattern(client, acc) { +function createRelativePattern2(client, acc) { return { - average: createMetricPattern2(client, _m(acc, 'avg')), - base: createMetricPattern25(client, acc), - cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), - max: createMetricPattern2(client, _m(acc, 'max')), - median: createMetricPattern21(client, _m(acc, 'median')), - min: createMetricPattern2(client, _m(acc, 'min')), - pct10: createMetricPattern21(client, _m(acc, 'pct10')), - pct25: createMetricPattern21(client, _m(acc, 'pct25')), - pct75: createMetricPattern21(client, _m(acc, 'pct75')), - pct90: createMetricPattern21(client, _m(acc, 'pct90')), - sum: createMetricPattern2(client, _m(acc, 'sum')), + negUnrealizedLossRelToOwnMarketCap: createMetricPattern5(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')), + negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern5(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')), + netUnrealizedPnlRelToOwnMarketCap: createMetricPattern3(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')), + netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern3(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')), + supplyInLossRelToOwnSupply: createMetricPattern5(client, _m(acc, 'supply_in_loss_rel_to_own_supply')), + supplyInProfitRelToOwnSupply: createMetricPattern5(client, _m(acc, 'supply_in_profit_rel_to_own_supply')), + unrealizedLossRelToOwnMarketCap: createMetricPattern5(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')), + unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern5(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')), + unrealizedProfitRelToOwnMarketCap: createMetricPattern5(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')), + unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern5(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')), }; } @@ -2747,16 +2782,16 @@ function createRelativePattern(client, acc) { /** * @template T * @typedef {Object} BlockSizePattern - * @property {MetricPattern1} average + * @property {MetricPattern2} average * @property {MetricPattern1} cumulative - * @property {MetricPattern1} max - * @property {MetricPattern25} median - * @property {MetricPattern1} min - * @property {MetricPattern25} pct10 - * @property {MetricPattern25} pct25 - * @property {MetricPattern25} pct75 - * @property {MetricPattern25} pct90 - * @property {MetricPattern1} sum + * @property {MetricPattern2} max + * @property {MetricPattern21} median + * @property {MetricPattern2} min + * @property {MetricPattern21} pct10 + * @property {MetricPattern21} pct25 + * @property {MetricPattern21} pct75 + * @property {MetricPattern21} pct90 + * @property {MetricPattern2} sum */ /** @@ -2768,16 +2803,16 @@ function createRelativePattern(client, acc) { */ function createBlockSizePattern(client, acc) { return { - average: createMetricPattern1(client, _m(acc, 'avg')), + average: createMetricPattern2(client, _m(acc, 'avg')), cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), - max: createMetricPattern1(client, _m(acc, 'max')), - median: createMetricPattern25(client, _m(acc, 'median')), - min: createMetricPattern1(client, _m(acc, 'min')), - pct10: createMetricPattern25(client, _m(acc, 'pct10')), - pct25: createMetricPattern25(client, _m(acc, 'pct25')), - pct75: createMetricPattern25(client, _m(acc, 'pct75')), - pct90: createMetricPattern25(client, _m(acc, 'pct90')), - sum: createMetricPattern1(client, _m(acc, 'sum')), + max: createMetricPattern2(client, _m(acc, 'max')), + median: createMetricPattern21(client, _m(acc, 'median')), + min: createMetricPattern2(client, _m(acc, 'min')), + pct10: createMetricPattern21(client, _m(acc, 'pct10')), + pct25: createMetricPattern21(client, _m(acc, 'pct25')), + pct75: createMetricPattern21(client, _m(acc, 'pct75')), + pct90: createMetricPattern21(client, _m(acc, 'pct90')), + sum: createMetricPattern2(client, _m(acc, 'sum')), }; } @@ -2817,14 +2852,14 @@ function createUnrealizedPattern(client, acc) { /** * @template T * @typedef {Object} AddresstypeToHeightToAddrCountPattern - * @property {MetricPattern25} p2a - * @property {MetricPattern25} p2pk33 - * @property {MetricPattern25} p2pk65 - * @property {MetricPattern25} p2pkh - * @property {MetricPattern25} p2sh - * @property {MetricPattern25} p2tr - * @property {MetricPattern25} p2wpkh - * @property {MetricPattern25} p2wsh + * @property {MetricPattern29} p2a + * @property {MetricPattern31} p2pk33 + * @property {MetricPattern32} p2pk65 + * @property {MetricPattern33} p2pkh + * @property {MetricPattern34} p2sh + * @property {MetricPattern35} p2tr + * @property {MetricPattern36} p2wpkh + * @property {MetricPattern37} p2wsh */ /** @@ -2836,28 +2871,28 @@ function createUnrealizedPattern(client, acc) { */ function createAddresstypeToHeightToAddrCountPattern(client, acc) { return { - p2a: createMetricPattern25(client, (acc ? `p2a_${acc}` : 'p2a')), - p2pk33: createMetricPattern25(client, (acc ? `p2pk33_${acc}` : 'p2pk33')), - p2pk65: createMetricPattern25(client, (acc ? `p2pk65_${acc}` : 'p2pk65')), - p2pkh: createMetricPattern25(client, (acc ? `p2pkh_${acc}` : 'p2pkh')), - p2sh: createMetricPattern25(client, (acc ? `p2sh_${acc}` : 'p2sh')), - p2tr: createMetricPattern25(client, (acc ? `p2tr_${acc}` : 'p2tr')), - p2wpkh: createMetricPattern25(client, (acc ? `p2wpkh_${acc}` : 'p2wpkh')), - p2wsh: createMetricPattern25(client, (acc ? `p2wsh_${acc}` : 'p2wsh')), + p2a: createMetricPattern29(client, (acc ? `p2a_${acc}` : 'p2a')), + p2pk33: createMetricPattern31(client, (acc ? `p2pk33_${acc}` : 'p2pk33')), + p2pk65: createMetricPattern32(client, (acc ? `p2pk65_${acc}` : 'p2pk65')), + p2pkh: createMetricPattern33(client, (acc ? `p2pkh_${acc}` : 'p2pkh')), + p2sh: createMetricPattern34(client, (acc ? `p2sh_${acc}` : 'p2sh')), + p2tr: createMetricPattern35(client, (acc ? `p2tr_${acc}` : 'p2tr')), + p2wpkh: createMetricPattern36(client, (acc ? `p2wpkh_${acc}` : 'p2wpkh')), + p2wsh: createMetricPattern37(client, (acc ? `p2wsh_${acc}` : 'p2wsh')), }; } /** * @template T * @typedef {Object} BlockIntervalPattern - * @property {MetricPattern2} average - * @property {MetricPattern2} max - * @property {MetricPattern21} median - * @property {MetricPattern2} min - * @property {MetricPattern21} pct10 - * @property {MetricPattern21} pct25 - * @property {MetricPattern21} pct75 - * @property {MetricPattern21} pct90 + * @property {MetricPattern1} average + * @property {MetricPattern1} max + * @property {MetricPattern25} median + * @property {MetricPattern1} min + * @property {MetricPattern25} pct10 + * @property {MetricPattern25} pct25 + * @property {MetricPattern25} pct75 + * @property {MetricPattern25} pct90 */ /** @@ -2869,43 +2904,14 @@ function createAddresstypeToHeightToAddrCountPattern(client, acc) { */ function createBlockIntervalPattern(client, acc) { return { - average: createMetricPattern2(client, _m(acc, 'avg')), - max: createMetricPattern2(client, _m(acc, 'max')), - median: createMetricPattern21(client, _m(acc, 'median')), - min: createMetricPattern2(client, _m(acc, 'min')), - pct10: createMetricPattern21(client, _m(acc, 'pct10')), - pct25: createMetricPattern21(client, _m(acc, 'pct25')), - pct75: createMetricPattern21(client, _m(acc, 'pct75')), - pct90: createMetricPattern21(client, _m(acc, 'pct90')), - }; -} - -/** - * @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 PeriodCagrPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {PeriodCagrPattern} - */ -function createPeriodCagrPattern(client, acc) { - return { - _10y: createMetricPattern4(client, (acc ? `10y_${acc}` : '10y')), - _2y: createMetricPattern4(client, (acc ? `2y_${acc}` : '2y')), - _3y: createMetricPattern4(client, (acc ? `3y_${acc}` : '3y')), - _4y: createMetricPattern4(client, (acc ? `4y_${acc}` : '4y')), - _5y: createMetricPattern4(client, (acc ? `5y_${acc}` : '5y')), - _6y: createMetricPattern4(client, (acc ? `6y_${acc}` : '6y')), - _8y: createMetricPattern4(client, (acc ? `8y_${acc}` : '8y')), + average: createMetricPattern1(client, _m(acc, 'avg')), + max: createMetricPattern1(client, _m(acc, 'max')), + median: createMetricPattern25(client, _m(acc, 'median')), + min: createMetricPattern1(client, _m(acc, 'min')), + pct10: createMetricPattern25(client, _m(acc, 'pct10')), + pct25: createMetricPattern25(client, _m(acc, 'pct25')), + pct75: createMetricPattern25(client, _m(acc, 'pct75')), + pct90: createMetricPattern25(client, _m(acc, 'pct90')), }; } @@ -2939,27 +2945,56 @@ function create_0satsPattern(client, acc) { } /** - * @typedef {Object} UpTo1dPattern + * @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 PeriodCagrPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {PeriodCagrPattern} + */ +function createPeriodCagrPattern(client, acc) { + return { + _10y: createMetricPattern4(client, (acc ? `10y_${acc}` : '10y')), + _2y: createMetricPattern4(client, (acc ? `2y_${acc}` : '2y')), + _3y: createMetricPattern4(client, (acc ? `3y_${acc}` : '3y')), + _4y: createMetricPattern4(client, (acc ? `4y_${acc}` : '4y')), + _5y: createMetricPattern4(client, (acc ? `5y_${acc}` : '5y')), + _6y: createMetricPattern4(client, (acc ? `6y_${acc}` : '6y')), + _8y: createMetricPattern4(client, (acc ? `8y_${acc}` : '8y')), + }; +} + +/** + * @typedef {Object} _0satsPattern2 * @property {ActivityPattern2} activity - * @property {CostBasisPattern2} costBasis - * @property {RealizedPattern3} realized - * @property {RelativePattern2} relative + * @property {CostBasisPattern} costBasis + * @property {RealizedPattern} realized + * @property {RelativePattern4} relative * @property {SupplyPattern3} supply * @property {UnrealizedPattern} unrealized */ /** - * Create a UpTo1dPattern pattern node + * Create a _0satsPattern2 pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {UpTo1dPattern} + * @returns {_0satsPattern2} */ -function createUpTo1dPattern(client, acc) { +function create_0satsPattern2(client, acc) { return { activity: createActivityPattern2(client, acc), - costBasis: createCostBasisPattern2(client, acc), - realized: createRealizedPattern3(client, acc), - relative: createRelativePattern2(client, acc), + costBasis: createCostBasisPattern(client, acc), + realized: createRealizedPattern(client, acc), + relative: createRelativePattern4(client, _m(acc, 'supply_in')), supply: createSupplyPattern3(client, acc), unrealized: createUnrealizedPattern(client, acc), }; @@ -2992,6 +3027,33 @@ function create_10yPattern(client, acc) { }; } +/** + * @typedef {Object} _100btcPattern + * @property {ActivityPattern2} activity + * @property {CostBasisPattern} costBasis + * @property {RealizedPattern} realized + * @property {RelativePattern} relative + * @property {SupplyPattern3} supply + * @property {UnrealizedPattern} unrealized + */ + +/** + * Create a _100btcPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {_100btcPattern} + */ +function create_100btcPattern(client, acc) { + return { + activity: createActivityPattern2(client, acc), + costBasis: createCostBasisPattern(client, acc), + realized: createRealizedPattern(client, acc), + relative: createRelativePattern(client, acc), + supply: createSupplyPattern3(client, acc), + unrealized: createUnrealizedPattern(client, acc), + }; +} + /** * @typedef {Object} _10yTo12yPattern * @property {ActivityPattern2} activity @@ -3019,33 +3081,6 @@ function create_10yTo12yPattern(client, acc) { }; } -/** - * @typedef {Object} _0satsPattern2 - * @property {ActivityPattern2} activity - * @property {CostBasisPattern} costBasis - * @property {RealizedPattern} realized - * @property {RelativePattern} relative - * @property {SupplyPattern3} supply - * @property {UnrealizedPattern} unrealized - */ - -/** - * Create a _0satsPattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {_0satsPattern2} - */ -function create_0satsPattern2(client, acc) { - return { - activity: createActivityPattern2(client, acc), - costBasis: createCostBasisPattern(client, acc), - realized: createRealizedPattern(client, acc), - relative: createRelativePattern(client, acc), - supply: createSupplyPattern3(client, acc), - unrealized: createUnrealizedPattern(client, acc), - }; -} - /** * @template T * @typedef {Object} SegwitAdoptionPattern @@ -3075,31 +3110,6 @@ function createSegwitAdoptionPattern(client, acc) { }; } -/** - * @typedef {Object} SupplyPattern3 - * @property {SupplyPattern2} supply - * @property {ActiveSupplyPattern} supplyHalf - * @property {ActiveSupplyPattern} supplyHalfValue - * @property {SupplyValuePattern} supplyValue - * @property {MetricPattern1} utxoCount - */ - -/** - * Create a SupplyPattern3 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {SupplyPattern3} - */ -function createSupplyPattern3(client, acc) { - return { - supply: createSupplyPattern2(client, _m(acc, 'supply')), - supplyHalf: createActiveSupplyPattern(client, _m(acc, 'supply_half')), - supplyHalfValue: createActiveSupplyPattern(client, _m(acc, 'supply_half')), - supplyValue: createSupplyValuePattern(client, _m(acc, 'supply')), - utxoCount: createMetricPattern1(client, _m(acc, 'utxo_count')), - }; -} - /** * @typedef {Object} ActivityPattern2 * @property {BlockCountPattern} coinblocksDestroyed @@ -3125,6 +3135,31 @@ function createActivityPattern2(client, acc) { }; } +/** + * @typedef {Object} SupplyPattern3 + * @property {SupplyPattern2} supply + * @property {ActiveSupplyPattern} supplyHalf + * @property {ActiveSupplyPattern} supplyHalfValue + * @property {SupplyValuePattern} supplyValue + * @property {MetricPattern1} utxoCount + */ + +/** + * Create a SupplyPattern3 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {SupplyPattern3} + */ +function createSupplyPattern3(client, acc) { + return { + supply: createSupplyPattern2(client, _m(acc, 'supply')), + supplyHalf: createActiveSupplyPattern(client, _m(acc, 'supply_half')), + supplyHalfValue: createActiveSupplyPattern(client, _m(acc, 'supply_half')), + supplyValue: createSupplyValuePattern(client, _m(acc, 'supply')), + utxoCount: createMetricPattern1(client, _m(acc, 'utxo_count')), + }; +} + /** * @typedef {Object} SupplyPattern2 * @property {MetricPattern25} base @@ -3148,29 +3183,6 @@ function createSupplyPattern2(client, acc) { }; } -/** - * @typedef {Object} SentPattern - * @property {MetricPattern25} base - * @property {BlockCountPattern} bitcoin - * @property {BlockCountPattern} dollars - * @property {SatsPattern} sats - */ - -/** - * Create a SentPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {SentPattern} - */ -function createSentPattern(client, acc) { - return { - base: createMetricPattern25(client, acc), - bitcoin: createBlockCountPattern(client, _m(acc, 'btc')), - dollars: createBlockCountPattern(client, _m(acc, 'usd')), - sats: createSatsPattern(client, acc), - }; -} - /** * @typedef {Object} OpreturnPattern * @property {MetricPattern25} base @@ -3195,23 +3207,25 @@ function createOpreturnPattern(client, acc) { } /** - * @typedef {Object} CostBasisPattern2 - * @property {MetricPattern1} maxCostBasis - * @property {MetricPattern1} minCostBasis - * @property {PercentilesPattern} percentiles + * @typedef {Object} SentPattern + * @property {MetricPattern25} base + * @property {BlockCountPattern} bitcoin + * @property {BlockCountPattern} dollars + * @property {SatsPattern} sats */ /** - * Create a CostBasisPattern2 pattern node + * Create a SentPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {CostBasisPattern2} + * @returns {SentPattern} */ -function createCostBasisPattern2(client, acc) { +function createSentPattern(client, acc) { return { - maxCostBasis: createMetricPattern1(client, _m(acc, 'max_cost_basis')), - minCostBasis: createMetricPattern1(client, _m(acc, 'min_cost_basis')), - percentiles: createPercentilesPattern(client, _m(acc, 'cost_basis')), + base: createMetricPattern25(client, acc), + bitcoin: createBlockCountPattern(client, _m(acc, 'btc')), + dollars: createBlockCountPattern(client, _m(acc, 'usd')), + sats: createSatsPattern(client, acc), }; } @@ -3278,6 +3292,27 @@ function createActiveSupplyPattern(client, acc) { }; } +/** + * @typedef {Object} CostBasisPattern2 + * @property {MetricPattern1} maxCostBasis + * @property {MetricPattern1} minCostBasis + * @property {PercentilesPattern} percentiles + */ + +/** + * Create a CostBasisPattern2 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {CostBasisPattern2} + */ +function createCostBasisPattern2(client, acc) { + return { + maxCostBasis: createMetricPattern1(client, _m(acc, 'max_cost_basis')), + minCostBasis: createMetricPattern1(client, _m(acc, 'min_cost_basis')), + percentiles: createPercentilesPattern(client, _m(acc, 'cost_basis')), + }; +} + /** * @template T * @typedef {Object} BlockCountPattern @@ -3324,25 +3359,6 @@ function createBitcoinPattern2(client, acc) { }; } -/** - * @typedef {Object} CostBasisPattern - * @property {MetricPattern1} maxCostBasis - * @property {MetricPattern1} minCostBasis - */ - -/** - * Create a CostBasisPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {CostBasisPattern} - */ -function createCostBasisPattern(client, acc) { - return { - maxCostBasis: createMetricPattern1(client, _m(acc, 'max_cost_basis')), - minCostBasis: createMetricPattern1(client, _m(acc, 'min_cost_basis')), - }; -} - /** * @typedef {Object} SatsPattern4 * @property {MetricPattern1} cumulative @@ -3363,21 +3379,21 @@ function createSatsPattern4(client, acc) { } /** - * @typedef {Object} SupplyValuePattern - * @property {MetricPattern25} bitcoin - * @property {MetricPattern25} dollars + * @typedef {Object} RelativePattern4 + * @property {MetricPattern5} supplyInLossRelToOwnSupply + * @property {MetricPattern5} supplyInProfitRelToOwnSupply */ /** - * Create a SupplyValuePattern pattern node + * Create a RelativePattern4 pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {SupplyValuePattern} + * @returns {RelativePattern4} */ -function createSupplyValuePattern(client, acc) { +function createRelativePattern4(client, acc) { return { - bitcoin: createMetricPattern25(client, _m(acc, 'btc')), - dollars: createMetricPattern25(client, _m(acc, 'usd')), + supplyInLossRelToOwnSupply: createMetricPattern5(client, _m(acc, 'loss_rel_to_own_supply')), + supplyInProfitRelToOwnSupply: createMetricPattern5(client, _m(acc, 'profit_rel_to_own_supply')), }; } @@ -3400,6 +3416,44 @@ function createSatsPattern(client, acc) { }; } +/** + * @typedef {Object} CostBasisPattern + * @property {MetricPattern1} maxCostBasis + * @property {MetricPattern1} minCostBasis + */ + +/** + * Create a CostBasisPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {CostBasisPattern} + */ +function createCostBasisPattern(client, acc) { + return { + maxCostBasis: createMetricPattern1(client, _m(acc, 'max_cost_basis')), + minCostBasis: createMetricPattern1(client, _m(acc, 'min_cost_basis')), + }; +} + +/** + * @typedef {Object} SupplyValuePattern + * @property {MetricPattern25} bitcoin + * @property {MetricPattern25} dollars + */ + +/** + * Create a SupplyValuePattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {SupplyValuePattern} + */ +function createSupplyValuePattern(client, acc) { + return { + bitcoin: createMetricPattern25(client, _m(acc, 'btc')), + dollars: createMetricPattern25(client, _m(acc, 'usd')), + }; +} + /** * @typedef {Object} _1dReturns1mSdPattern * @property {MetricPattern4} sd @@ -3766,6 +3820,7 @@ function createRealizedPriceExtraPattern(client, acc) { * @property {_10yTo12yPattern} _10yTo12y * @property {_10yTo12yPattern} _12yTo15y * @property {_10yTo12yPattern} _1dTo1w + * @property {_10yTo12yPattern} _1hTo1d * @property {_10yTo12yPattern} _1mTo2m * @property {_10yTo12yPattern} _1wTo1m * @property {_10yTo12yPattern} _1yTo2y @@ -3782,7 +3837,7 @@ function createRealizedPriceExtraPattern(client, acc) { * @property {_10yTo12yPattern} _7yTo8y * @property {_10yTo12yPattern} _8yTo10y * @property {_10yTo12yPattern} from15y - * @property {UpTo1dPattern} upTo1d + * @property {_10yTo12yPattern} upTo1h */ /** @@ -3835,36 +3890,36 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_GeAmount - * @property {_0satsPattern2} _100btc - * @property {_0satsPattern2} _100kSats - * @property {_0satsPattern2} _100sats - * @property {_0satsPattern2} _10btc - * @property {_0satsPattern2} _10kBtc - * @property {_0satsPattern2} _10kSats - * @property {_0satsPattern2} _10mSats - * @property {_0satsPattern2} _10sats - * @property {_0satsPattern2} _1btc - * @property {_0satsPattern2} _1kBtc - * @property {_0satsPattern2} _1kSats - * @property {_0satsPattern2} _1mSats - * @property {_0satsPattern2} _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} CatalogTree_Computed_Distribution_UtxoCohorts_LtAmount - * @property {_0satsPattern2} _100btc - * @property {_0satsPattern2} _100kBtc - * @property {_0satsPattern2} _100kSats - * @property {_0satsPattern2} _100sats - * @property {_0satsPattern2} _10btc - * @property {_0satsPattern2} _10kBtc - * @property {_0satsPattern2} _10kSats - * @property {_0satsPattern2} _10mSats - * @property {_0satsPattern2} _10sats - * @property {_0satsPattern2} _1btc - * @property {_0satsPattern2} _1kBtc - * @property {_0satsPattern2} _1kSats - * @property {_0satsPattern2} _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 */ /** @@ -3891,30 +3946,50 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_MinAge - * @property {_0satsPattern2} _10y - * @property {_0satsPattern2} _12y - * @property {_0satsPattern2} _1d - * @property {_0satsPattern2} _1m - * @property {_0satsPattern2} _1w - * @property {_0satsPattern2} _1y - * @property {_0satsPattern2} _2m - * @property {_0satsPattern2} _2y - * @property {_0satsPattern2} _3m - * @property {_0satsPattern2} _3y - * @property {_0satsPattern2} _4m - * @property {_0satsPattern2} _4y - * @property {_0satsPattern2} _5m - * @property {_0satsPattern2} _5y - * @property {_0satsPattern2} _6m - * @property {_0satsPattern2} _6y - * @property {_0satsPattern2} _7y - * @property {_0satsPattern2} _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 */ /** * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_Term - * @property {UpTo1dPattern} long - * @property {UpTo1dPattern} short + * @property {CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long} long + * @property {CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short} short + */ + +/** + * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long + * @property {ActivityPattern2} activity + * @property {CostBasisPattern2} costBasis + * @property {RealizedPattern2} realized + * @property {RelativePattern5} relative + * @property {SupplyPattern3} supply + * @property {UnrealizedPattern} unrealized + */ + +/** + * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short + * @property {ActivityPattern2} activity + * @property {CostBasisPattern2} costBasis + * @property {RealizedPattern3} realized + * @property {RelativePattern5} relative + * @property {SupplyPattern3} supply + * @property {UnrealizedPattern} unrealized */ /** @@ -5052,10 +5127,15 @@ class BrkClient extends BrkClientBase { }); AGE_RANGE_NAMES = /** @type {const} */ ({ - "upTo1d": { - "id": "up_to_1d_old", - "short": "<1d", - "long": "Up to 1 Day Old" + "upTo1h": { + "id": "up_to_1h_old", + "short": "<1h", + "long": "Up to 1 Hour Old" + }, + "_1hTo1d": { + "id": "at_least_1h_up_to_1d_old", + "short": "1h-1d", + "long": "1 Hour to 1 Day Old" }, "_1dTo1w": { "id": "at_least_1d_up_to_1w_old", @@ -5769,6 +5849,7 @@ class BrkClient extends BrkClientBase { _10yTo12y: create_10yTo12yPattern(this, 'utxos_at_least_10y_up_to_12y_old'), _12yTo15y: create_10yTo12yPattern(this, 'utxos_at_least_12y_up_to_15y_old'), _1dTo1w: create_10yTo12yPattern(this, 'utxos_at_least_1d_up_to_1w_old'), + _1hTo1d: create_10yTo12yPattern(this, 'utxos_at_least_1h_up_to_1d_old'), _1mTo2m: create_10yTo12yPattern(this, 'utxos_at_least_1m_up_to_2m_old'), _1wTo1m: create_10yTo12yPattern(this, 'utxos_at_least_1w_up_to_1m_old'), _1yTo2y: create_10yTo12yPattern(this, 'utxos_at_least_1y_up_to_2y_old'), @@ -5785,7 +5866,7 @@ class BrkClient extends BrkClientBase { _7yTo8y: create_10yTo12yPattern(this, 'utxos_at_least_7y_up_to_8y_old'), _8yTo10y: create_10yTo12yPattern(this, 'utxos_at_least_8y_up_to_10y_old'), from15y: create_10yTo12yPattern(this, 'utxos_at_least_15y_old'), - upTo1d: createUpTo1dPattern(this, 'utxos_up_to_1d_old') + upTo1h: create_10yTo12yPattern(this, 'utxos_up_to_1h_old') }, all: { activity: createActivityPattern2(this, ''), @@ -5827,34 +5908,34 @@ class BrkClient extends BrkClientBase { _4: create_0satsPattern2(this, 'epoch_4') }, geAmount: { - _100btc: create_0satsPattern2(this, 'utxos_above_100btc'), - _100kSats: create_0satsPattern2(this, 'utxos_above_100k_sats'), - _100sats: create_0satsPattern2(this, 'utxos_above_100sats'), - _10btc: create_0satsPattern2(this, 'utxos_above_10btc'), - _10kBtc: create_0satsPattern2(this, 'utxos_above_10k_btc'), - _10kSats: create_0satsPattern2(this, 'utxos_above_10k_sats'), - _10mSats: create_0satsPattern2(this, 'utxos_above_10m_sats'), - _10sats: create_0satsPattern2(this, 'utxos_above_10sats'), - _1btc: create_0satsPattern2(this, 'utxos_above_1btc'), - _1kBtc: create_0satsPattern2(this, 'utxos_above_1k_btc'), - _1kSats: create_0satsPattern2(this, 'utxos_above_1k_sats'), - _1mSats: create_0satsPattern2(this, 'utxos_above_1m_sats'), - _1sat: create_0satsPattern2(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_0satsPattern2(this, 'utxos_under_100btc'), - _100kBtc: create_0satsPattern2(this, 'utxos_under_100k_btc'), - _100kSats: create_0satsPattern2(this, 'utxos_under_100k_sats'), - _100sats: create_0satsPattern2(this, 'utxos_under_100sats'), - _10btc: create_0satsPattern2(this, 'utxos_under_10btc'), - _10kBtc: create_0satsPattern2(this, 'utxos_under_10k_btc'), - _10kSats: create_0satsPattern2(this, 'utxos_under_10k_sats'), - _10mSats: create_0satsPattern2(this, 'utxos_under_10m_sats'), - _10sats: create_0satsPattern2(this, 'utxos_under_10sats'), - _1btc: create_0satsPattern2(this, 'utxos_under_1btc'), - _1kBtc: create_0satsPattern2(this, 'utxos_under_1k_btc'), - _1kSats: create_0satsPattern2(this, 'utxos_under_1k_sats'), - _1mSats: create_0satsPattern2(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'), @@ -5877,28 +5958,42 @@ class BrkClient extends BrkClientBase { _8y: create_10yPattern(this, 'utxos_up_to_8y_old') }, minAge: { - _10y: create_0satsPattern2(this, 'utxos_at_least_10y_old'), - _12y: create_0satsPattern2(this, 'utxos_at_least_12y_old'), - _1d: create_0satsPattern2(this, 'utxos_at_least_1d_old'), - _1m: create_0satsPattern2(this, 'utxos_at_least_1m_old'), - _1w: create_0satsPattern2(this, 'utxos_at_least_1w_old'), - _1y: create_0satsPattern2(this, 'utxos_at_least_1y_old'), - _2m: create_0satsPattern2(this, 'utxos_at_least_2m_old'), - _2y: create_0satsPattern2(this, 'utxos_at_least_2y_old'), - _3m: create_0satsPattern2(this, 'utxos_at_least_3m_old'), - _3y: create_0satsPattern2(this, 'utxos_at_least_3y_old'), - _4m: create_0satsPattern2(this, 'utxos_at_least_4m_old'), - _4y: create_0satsPattern2(this, 'utxos_at_least_4y_old'), - _5m: create_0satsPattern2(this, 'utxos_at_least_5m_old'), - _5y: create_0satsPattern2(this, 'utxos_at_least_5y_old'), - _6m: create_0satsPattern2(this, 'utxos_at_least_6m_old'), - _6y: create_0satsPattern2(this, 'utxos_at_least_6y_old'), - _7y: create_0satsPattern2(this, 'utxos_at_least_7y_old'), - _8y: create_0satsPattern2(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: createUpTo1dPattern(this, 'lth'), - short: createUpTo1dPattern(this, 'sth') + long: { + activity: createActivityPattern2(this, 'lth'), + costBasis: createCostBasisPattern2(this, 'lth'), + realized: createRealizedPattern2(this, 'lth'), + relative: createRelativePattern5(this, 'lth'), + supply: createSupplyPattern3(this, 'lth'), + unrealized: createUnrealizedPattern(this, 'lth') + }, + short: { + activity: createActivityPattern2(this, 'sth'), + costBasis: createCostBasisPattern2(this, 'sth'), + realized: createRealizedPattern3(this, 'sth'), + relative: createRelativePattern5(this, 'sth'), + supply: createSupplyPattern3(this, 'sth'), + unrealized: createUnrealizedPattern(this, 'sth') + } }, type: { empty: create_0satsPattern2(this, 'empty_outputs'), diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 93ade6c66..af9fa3a0a 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -2094,8 +2094,8 @@ class RealizedPattern3: self.adjusted_sopr: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'adjusted_sopr')) self.adjusted_sopr_30d_ema: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'adjusted_sopr_30d_ema')) self.adjusted_sopr_7d_ema: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'adjusted_sopr_7d_ema')) - self.adjusted_value_created: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'adjusted_value_created')) - self.adjusted_value_destroyed: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'adjusted_value_destroyed')) + self.adjusted_value_created: TotalRealizedPnlPattern[Dollars] = TotalRealizedPnlPattern(client, _m(acc, 'adjusted_value_created')) + self.adjusted_value_destroyed: TotalRealizedPnlPattern[Dollars] = TotalRealizedPnlPattern(client, _m(acc, 'adjusted_value_destroyed')) self.mvrv: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'mvrv')) self.neg_realized_loss: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'neg_realized_loss')) self.net_realized_pnl: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'net_realized_pnl')) @@ -2132,8 +2132,8 @@ class RealizedPattern4: self.adjusted_sopr: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'adjusted_sopr')) self.adjusted_sopr_30d_ema: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'adjusted_sopr_30d_ema')) self.adjusted_sopr_7d_ema: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'adjusted_sopr_7d_ema')) - self.adjusted_value_created: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'adjusted_value_created')) - self.adjusted_value_destroyed: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'adjusted_value_destroyed')) + self.adjusted_value_created: TotalRealizedPnlPattern[Dollars] = TotalRealizedPnlPattern(client, _m(acc, 'adjusted_value_created')) + self.adjusted_value_destroyed: TotalRealizedPnlPattern[Dollars] = TotalRealizedPnlPattern(client, _m(acc, 'adjusted_value_destroyed')) self.mvrv: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'mvrv')) self.neg_realized_loss: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'neg_realized_loss')) self.net_realized_pnl: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'net_realized_pnl')) @@ -2284,31 +2284,6 @@ class Price111dSmaPattern: self.ratio_pct99_usd: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'ratio_pct99_usd')) self.ratio_sd: Ratio1ySdPattern = Ratio1ySdPattern(client, _m(acc, 'ratio')) -class PercentilesPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.cost_basis_pct05: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct05')) - self.cost_basis_pct10: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct10')) - self.cost_basis_pct15: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct15')) - self.cost_basis_pct20: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct20')) - self.cost_basis_pct25: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct25')) - self.cost_basis_pct30: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct30')) - self.cost_basis_pct35: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct35')) - self.cost_basis_pct40: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct40')) - self.cost_basis_pct45: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct45')) - self.cost_basis_pct50: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct50')) - self.cost_basis_pct55: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct55')) - self.cost_basis_pct60: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct60')) - self.cost_basis_pct65: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct65')) - self.cost_basis_pct70: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct70')) - self.cost_basis_pct75: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct75')) - self.cost_basis_pct80: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct80')) - self.cost_basis_pct85: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct85')) - self.cost_basis_pct90: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct90')) - self.cost_basis_pct95: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct95')) - class ActivePriceRatioPattern: """Pattern struct for repeated tree structure.""" @@ -2334,7 +2309,32 @@ class ActivePriceRatioPattern: self.ratio_pct99_usd: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct99_usd')) self.ratio_sd: Ratio1ySdPattern = Ratio1ySdPattern(client, acc) -class RelativePattern2: +class PercentilesPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.cost_basis_pct05: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct05')) + self.cost_basis_pct10: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct10')) + self.cost_basis_pct15: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct15')) + self.cost_basis_pct20: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct20')) + self.cost_basis_pct25: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct25')) + self.cost_basis_pct30: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct30')) + self.cost_basis_pct35: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct35')) + self.cost_basis_pct40: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct40')) + self.cost_basis_pct45: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct45')) + self.cost_basis_pct50: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct50')) + self.cost_basis_pct55: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct55')) + self.cost_basis_pct60: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct60')) + self.cost_basis_pct65: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct65')) + self.cost_basis_pct70: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct70')) + self.cost_basis_pct75: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct75')) + self.cost_basis_pct80: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct80')) + self.cost_basis_pct85: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct85')) + self.cost_basis_pct90: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct90')) + self.cost_basis_pct95: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct95')) + +class RelativePattern5: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): @@ -2432,6 +2432,23 @@ class PeriodAvgPricePattern(Generic[T]): self._6y: MetricPattern4[T] = MetricPattern4(client, (f'6y_{{acc}}' if acc else '6y')) self._8y: MetricPattern4[T] = MetricPattern4(client, (f'8y_{{acc}}' if acc else '8y')) +class BitcoinPattern(Generic[T]): + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'avg')) + self.base: MetricPattern25[T] = MetricPattern25(client, acc) + self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) + self.max: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'max')) + self.median: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'median')) + self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min')) + self.pct10: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct10')) + self.pct25: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct25')) + self.pct75: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct75')) + self.pct90: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct90')) + self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum')) + class ClassAvgPricePattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2449,22 +2466,21 @@ class ClassAvgPricePattern(Generic[T]): self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_avg_price')) self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_avg_price')) -class BitcoinPattern(Generic[T]): +class RelativePattern2: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'avg')) - self.base: MetricPattern25[T] = MetricPattern25(client, acc) - self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) - self.max: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'max')) - self.median: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'median')) - self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min')) - self.pct10: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct10')) - self.pct25: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct25')) - self.pct75: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct75')) - self.pct90: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct90')) - self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum')) + self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern5[StoredF32] = MetricPattern5(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')) + self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern5[StoredF32] = MetricPattern5(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')) + self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern3[StoredF32] = MetricPattern3(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')) + self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern3[StoredF32] = MetricPattern3(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')) + self.supply_in_loss_rel_to_own_supply: MetricPattern5[StoredF64] = MetricPattern5(client, _m(acc, 'supply_in_loss_rel_to_own_supply')) + self.supply_in_profit_rel_to_own_supply: MetricPattern5[StoredF64] = MetricPattern5(client, _m(acc, 'supply_in_profit_rel_to_own_supply')) + self.unrealized_loss_rel_to_own_market_cap: MetricPattern5[StoredF32] = MetricPattern5(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')) + self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern5[StoredF32] = MetricPattern5(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')) + self.unrealized_profit_rel_to_own_market_cap: MetricPattern5[StoredF32] = MetricPattern5(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')) + self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern5[StoredF32] = MetricPattern5(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')) class RelativePattern: """Pattern struct for repeated tree structure.""" @@ -2487,16 +2503,16 @@ class BlockSizePattern(Generic[T]): def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.average: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'avg')) + self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'avg')) self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) - self.max: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'max')) - self.median: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'median')) - self.min: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'min')) - self.pct10: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'pct10')) - self.pct25: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'pct25')) - self.pct75: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'pct75')) - self.pct90: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'pct90')) - self.sum: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'sum')) + self.max: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'max')) + self.median: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'median')) + self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min')) + self.pct10: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct10')) + self.pct25: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct25')) + self.pct75: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct75')) + self.pct90: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct90')) + self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum')) class UnrealizedPattern: """Pattern struct for repeated tree structure.""" @@ -2518,41 +2534,28 @@ class AddresstypeToHeightToAddrCountPattern(Generic[T]): def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.p2a: MetricPattern25[T] = MetricPattern25(client, (f'p2a_{{acc}}' if acc else 'p2a')) - self.p2pk33: MetricPattern25[T] = MetricPattern25(client, (f'p2pk33_{{acc}}' if acc else 'p2pk33')) - self.p2pk65: MetricPattern25[T] = MetricPattern25(client, (f'p2pk65_{{acc}}' if acc else 'p2pk65')) - self.p2pkh: MetricPattern25[T] = MetricPattern25(client, (f'p2pkh_{{acc}}' if acc else 'p2pkh')) - self.p2sh: MetricPattern25[T] = MetricPattern25(client, (f'p2sh_{{acc}}' if acc else 'p2sh')) - self.p2tr: MetricPattern25[T] = MetricPattern25(client, (f'p2tr_{{acc}}' if acc else 'p2tr')) - self.p2wpkh: MetricPattern25[T] = MetricPattern25(client, (f'p2wpkh_{{acc}}' if acc else 'p2wpkh')) - self.p2wsh: MetricPattern25[T] = MetricPattern25(client, (f'p2wsh_{{acc}}' if acc else 'p2wsh')) + self.p2a: MetricPattern29[T] = MetricPattern29(client, (f'p2a_{{acc}}' if acc else 'p2a')) + self.p2pk33: MetricPattern31[T] = MetricPattern31(client, (f'p2pk33_{{acc}}' if acc else 'p2pk33')) + self.p2pk65: MetricPattern32[T] = MetricPattern32(client, (f'p2pk65_{{acc}}' if acc else 'p2pk65')) + self.p2pkh: MetricPattern33[T] = MetricPattern33(client, (f'p2pkh_{{acc}}' if acc else 'p2pkh')) + self.p2sh: MetricPattern34[T] = MetricPattern34(client, (f'p2sh_{{acc}}' if acc else 'p2sh')) + self.p2tr: MetricPattern35[T] = MetricPattern35(client, (f'p2tr_{{acc}}' if acc else 'p2tr')) + self.p2wpkh: MetricPattern36[T] = MetricPattern36(client, (f'p2wpkh_{{acc}}' if acc else 'p2wpkh')) + self.p2wsh: MetricPattern37[T] = MetricPattern37(client, (f'p2wsh_{{acc}}' if acc else 'p2wsh')) class BlockIntervalPattern(Generic[T]): """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'avg')) - self.max: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'max')) - self.median: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'median')) - self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min')) - self.pct10: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct10')) - self.pct25: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct25')) - self.pct75: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct75')) - self.pct90: MetricPattern21[T] = MetricPattern21(client, _m(acc, 'pct90')) - -class PeriodCagrPattern: - """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, (f'10y_{{acc}}' if acc else '10y')) - self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'2y_{{acc}}' if acc else '2y')) - self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'3y_{{acc}}' if acc else '3y')) - self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'4y_{{acc}}' if acc else '4y')) - self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'5y_{{acc}}' if acc else '5y')) - self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'6y_{{acc}}' if acc else '6y')) - self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'8y_{{acc}}' if acc else '8y')) + self.average: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'avg')) + self.max: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'max')) + self.median: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'median')) + self.min: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'min')) + self.pct10: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'pct10')) + self.pct25: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'pct25')) + self.pct75: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'pct75')) + self.pct90: MetricPattern25[T] = MetricPattern25(client, _m(acc, 'pct90')) class _0satsPattern: """Pattern struct for repeated tree structure.""" @@ -2567,15 +2570,28 @@ class _0satsPattern: self.supply: SupplyPattern3 = SupplyPattern3(client, acc) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class UpTo1dPattern: +class PeriodCagrPattern: + """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, (f'10y_{{acc}}' if acc else '10y')) + self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'2y_{{acc}}' if acc else '2y')) + self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'3y_{{acc}}' if acc else '3y')) + self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'4y_{{acc}}' if acc else '4y')) + self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'5y_{{acc}}' if acc else '5y')) + self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'6y_{{acc}}' if acc else '6y')) + self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, (f'8y_{{acc}}' if acc else '8y')) + +class _0satsPattern2: """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.realized: RealizedPattern3 = RealizedPattern3(client, acc) - self.relative: RelativePattern2 = RelativePattern2(client, acc) + self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) + self.realized: RealizedPattern = RealizedPattern(client, acc) + self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply_in')) self.supply: SupplyPattern3 = SupplyPattern3(client, acc) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) @@ -2591,6 +2607,18 @@ class _10yPattern: self.supply: SupplyPattern3 = SupplyPattern3(client, acc) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) +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: CostBasisPattern = CostBasisPattern(client, acc) + self.realized: RealizedPattern = RealizedPattern(client, acc) + self.relative: RelativePattern = RelativePattern(client, acc) + self.supply: SupplyPattern3 = SupplyPattern3(client, acc) + self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) + class _10yTo12yPattern: """Pattern struct for repeated tree structure.""" @@ -2603,18 +2631,6 @@ class _10yTo12yPattern: self.supply: SupplyPattern3 = SupplyPattern3(client, acc) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class _0satsPattern2: - """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.realized: RealizedPattern = RealizedPattern(client, acc) - self.relative: RelativePattern = RelativePattern(client, acc) - self.supply: SupplyPattern3 = SupplyPattern3(client, acc) - self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) - class SegwitAdoptionPattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2627,17 +2643,6 @@ class SegwitAdoptionPattern(Generic[T]): self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min')) self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum')) -class SupplyPattern3: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) - self.supply_half: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_half')) - self.supply_half_value: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_half')) - self.supply_value: SupplyValuePattern = SupplyValuePattern(client, _m(acc, 'supply')) - self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, _m(acc, 'utxo_count')) - class ActivityPattern2: """Pattern struct for repeated tree structure.""" @@ -2649,6 +2654,17 @@ class ActivityPattern2: self.satdays_destroyed: MetricPattern25[Sats] = MetricPattern25(client, _m(acc, 'satdays_destroyed')) self.sent: SentPattern = SentPattern(client, _m(acc, 'sent')) +class SupplyPattern3: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply')) + self.supply_half: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_half')) + self.supply_half_value: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_half')) + self.supply_value: SupplyValuePattern = SupplyValuePattern(client, _m(acc, 'supply')) + self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, _m(acc, 'utxo_count')) + class SupplyPattern2: """Pattern struct for repeated tree structure.""" @@ -2659,16 +2675,6 @@ class SupplyPattern2: self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd')) self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc) -class SentPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.base: MetricPattern25[Sats] = MetricPattern25(client, acc) - self.bitcoin: BlockCountPattern[Bitcoin] = BlockCountPattern(client, _m(acc, 'btc')) - self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd')) - self.sats: SatsPattern = SatsPattern(client, acc) - class OpreturnPattern: """Pattern struct for repeated tree structure.""" @@ -2679,14 +2685,15 @@ class OpreturnPattern: self.dollars: BitcoinPattern2[Dollars] = BitcoinPattern2(client, _m(acc, 'usd')) self.sats: SatsPattern4 = SatsPattern4(client, acc) -class CostBasisPattern2: +class SentPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.max_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis')) - self.min_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis')) - self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis')) + self.base: MetricPattern25[Sats] = MetricPattern25(client, acc) + self.bitcoin: BlockCountPattern[Bitcoin] = BlockCountPattern(client, _m(acc, 'btc')) + self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd')) + self.sats: SatsPattern = SatsPattern(client, acc) class CoinbasePattern: """Pattern struct for repeated tree structure.""" @@ -2715,6 +2722,15 @@ class ActiveSupplyPattern: self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'usd')) self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc) +class CostBasisPattern2: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.max_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis')) + self.min_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis')) + self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis')) + class BlockCountPattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2733,14 +2749,6 @@ class BitcoinPattern2(Generic[T]): self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) self.last: MetricPattern2[T] = MetricPattern2(client, acc) -class CostBasisPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.max_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis')) - self.min_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis')) - class SatsPattern4: """Pattern struct for repeated tree structure.""" @@ -2749,13 +2757,13 @@ class SatsPattern4: self.cumulative: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'cumulative')) self.last: MetricPattern2[Sats] = MetricPattern2(client, acc) -class SupplyValuePattern: +class RelativePattern4: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.bitcoin: MetricPattern25[Bitcoin] = MetricPattern25(client, _m(acc, 'btc')) - self.dollars: MetricPattern25[Dollars] = MetricPattern25(client, _m(acc, 'usd')) + self.supply_in_loss_rel_to_own_supply: MetricPattern5[StoredF64] = MetricPattern5(client, _m(acc, 'loss_rel_to_own_supply')) + self.supply_in_profit_rel_to_own_supply: MetricPattern5[StoredF64] = MetricPattern5(client, _m(acc, 'profit_rel_to_own_supply')) class SatsPattern: """Pattern struct for repeated tree structure.""" @@ -2765,6 +2773,22 @@ class SatsPattern: self.cumulative: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'cumulative')) self.sum: MetricPattern2[Sats] = MetricPattern2(client, acc) +class CostBasisPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.max_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis')) + self.min_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis')) + +class SupplyValuePattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.bitcoin: MetricPattern25[Bitcoin] = MetricPattern25(client, _m(acc, 'btc')) + self.dollars: MetricPattern25[Dollars] = MetricPattern25(client, _m(acc, 'usd')) + class _1dReturns1mSdPattern: """Pattern struct for repeated tree structure.""" @@ -3126,6 +3150,7 @@ class CatalogTree_Computed_Distribution_UtxoCohorts_AgeRange: self._10y_to_12y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_10y_up_to_12y_old') self._12y_to_15y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_12y_up_to_15y_old') self._1d_to_1w: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1d_up_to_1w_old') + self._1h_to_1d: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1h_up_to_1d_old') self._1m_to_2m: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1m_up_to_2m_old') self._1w_to_1m: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1w_up_to_1m_old') self._1y_to_2y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1y_up_to_2y_old') @@ -3142,7 +3167,7 @@ class CatalogTree_Computed_Distribution_UtxoCohorts_AgeRange: self._7y_to_8y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_7y_up_to_8y_old') self._8y_to_10y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_8y_up_to_10y_old') self.from_15y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_15y_old') - self.up_to_1d: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_1d_old') + self.up_to_1h: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_up_to_1h_old') class CatalogTree_Computed_Distribution_UtxoCohorts_All: """Catalog tree node.""" @@ -3200,37 +3225,37 @@ class CatalogTree_Computed_Distribution_UtxoCohorts_GeAmount: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._100btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_100btc') - self._100k_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_100k_sats') - self._100sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_100sats') - self._10btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_10btc') - self._10k_btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_10k_btc') - self._10k_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_10k_sats') - self._10m_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_10m_sats') - self._10sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_10sats') - self._1btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_1btc') - self._1k_btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_1k_btc') - self._1k_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_1k_sats') - self._1m_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_above_1m_sats') - self._1sat: _0satsPattern2 = _0satsPattern2(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 CatalogTree_Computed_Distribution_UtxoCohorts_LtAmount: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._100btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_100btc') - self._100k_btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_100k_btc') - self._100k_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_100k_sats') - self._100sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_100sats') - self._10btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_10btc') - self._10k_btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_10k_btc') - self._10k_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_10k_sats') - self._10m_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_10m_sats') - self._10sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_10sats') - self._1btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_1btc') - self._1k_btc: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_1k_btc') - self._1k_sats: _0satsPattern2 = _0satsPattern2(client, 'utxos_under_1k_sats') - self._1m_sats: _0satsPattern2 = _0satsPattern2(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 CatalogTree_Computed_Distribution_UtxoCohorts_MaxAge: """Catalog tree node.""" @@ -3259,31 +3284,53 @@ class CatalogTree_Computed_Distribution_UtxoCohorts_MinAge: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._10y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_10y_old') - self._12y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_12y_old') - self._1d: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_1d_old') - self._1m: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_1m_old') - self._1w: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_1w_old') - self._1y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_1y_old') - self._2m: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_2m_old') - self._2y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_2y_old') - self._3m: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_3m_old') - self._3y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_3y_old') - self._4m: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_4m_old') - self._4y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_4y_old') - self._5m: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_5m_old') - self._5y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_5y_old') - self._6m: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_6m_old') - self._6y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_6y_old') - self._7y: _0satsPattern2 = _0satsPattern2(client, 'utxos_at_least_7y_old') - self._8y: _0satsPattern2 = _0satsPattern2(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 CatalogTree_Computed_Distribution_UtxoCohorts_Term: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.long: UpTo1dPattern = UpTo1dPattern(client, 'lth') - self.short: UpTo1dPattern = UpTo1dPattern(client, 'sth') + self.long: CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long = CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long(client, f'{base_path}_long') + self.short: CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short = CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short(client, f'{base_path}_short') + +class CatalogTree_Computed_Distribution_UtxoCohorts_Term_Long: + """Catalog tree node.""" + + def __init__(self, client: BrkClientBase, base_path: str = ''): + self.activity: ActivityPattern2 = ActivityPattern2(client, 'lth') + self.cost_basis: CostBasisPattern2 = CostBasisPattern2(client, 'lth') + self.realized: RealizedPattern2 = RealizedPattern2(client, 'lth') + self.relative: RelativePattern5 = RelativePattern5(client, 'lth') + self.supply: SupplyPattern3 = SupplyPattern3(client, 'lth') + self.unrealized: UnrealizedPattern = UnrealizedPattern(client, 'lth') + +class CatalogTree_Computed_Distribution_UtxoCohorts_Term_Short: + """Catalog tree node.""" + + def __init__(self, client: BrkClientBase, base_path: str = ''): + self.activity: ActivityPattern2 = ActivityPattern2(client, 'sth') + self.cost_basis: CostBasisPattern2 = CostBasisPattern2(client, 'sth') + self.realized: RealizedPattern3 = RealizedPattern3(client, 'sth') + self.relative: RelativePattern5 = RelativePattern5(client, 'sth') + self.supply: SupplyPattern3 = SupplyPattern3(client, 'sth') + self.unrealized: UnrealizedPattern = UnrealizedPattern(client, 'sth') class CatalogTree_Computed_Distribution_UtxoCohorts_Type: """Catalog tree node.""" @@ -4475,10 +4522,15 @@ class BrkClient(BrkClientBase): } AGE_RANGE_NAMES = { - "up_to_1d": { - "id": "up_to_1d_old", - "short": "<1d", - "long": "Up to 1 Day Old" + "up_to_1h": { + "id": "up_to_1h_old", + "short": "<1h", + "long": "Up to 1 Hour Old" + }, + "_1h_to_1d": { + "id": "at_least_1h_up_to_1d_old", + "short": "1h-1d", + "long": "1 Hour to 1 Day Old" }, "_1d_to_1w": { "id": "at_least_1d_up_to_1w_old",