diff --git a/Cargo.lock b/Cargo.lock index 065753c10..b4e21fd81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1489,9 +1489,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -1499,9 +1499,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -2950,9 +2950,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "libloading" @@ -4305,7 +4305,7 @@ dependencies = [ [[package]] name = "rawdb" -version = "0.5.2" +version = "0.5.4" dependencies = [ "libc", "log", @@ -5094,9 +5094,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", @@ -5497,7 +5497,7 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23" [[package]] name = "vecdb" -version = "0.5.2" +version = "0.5.4" dependencies = [ "ctrlc", "log", @@ -5516,7 +5516,7 @@ dependencies = [ [[package]] name = "vecdb_derive" -version = "0.5.2" +version = "0.5.4" dependencies = [ "quote", "syn 2.0.112", @@ -6110,9 +6110,9 @@ checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" [[package]] name = "zmij" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9211a9f64b825911bdf0240f58b7a8dac217fe260fc61f080a07f61372fbd5" +checksum = "4ee2a72b10d087f75fb2e1c2c7343e308fe6970527c22a41caf8372e165ff5c1" [[package]] name = "zopfli" diff --git a/Cargo.toml b/Cargo.toml index 0330e2e6a..fa08a227d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,7 +80,7 @@ serde_bytes = "0.11.19" serde_derive = "1.0.228" serde_json = { version = "1.0.148", features = ["float_roundtrip"] } smallvec = "1.15.1" -tokio = { version = "1.48.0", features = ["rt-multi-thread"] } +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 = { git = "https://github.com/anydb-rs/anydb", features = ["derive", "serde_json", "pco"] } diff --git a/crates/brk_bindgen/src/analysis/tree.rs b/crates/brk_bindgen/src/analysis/tree.rs index e580177a2..42a87ab98 100644 --- a/crates/brk_bindgen/src/analysis/tree.rs +++ b/crates/brk_bindgen/src/analysis/tree.rs @@ -112,24 +112,27 @@ fn collect_indexes_from_tree( /// Get the metric base for a pattern instance by analyzing all leaf descendants. /// -/// For root-level instances (no common prefix among leaves), returns empty string. -/// For cohort-level instances, returns the common prefix among all leaves. +/// For root-level instances (no common prefix/suffix among leaves), returns empty string. +/// For cohort-level instances, returns the common prefix or suffix among all leaves. pub fn get_pattern_instance_base(node: &TreeNode) -> String { let leaf_names = get_all_leaf_names(node); if leaf_names.is_empty() { return String::new(); } - // Find the longest common prefix among all leaf names + // First try to find a common prefix let common_prefix = find_common_prefix_at_underscore(&leaf_names); - - // If no common prefix, we're at root level - if common_prefix.is_empty() { - return String::new(); + if !common_prefix.is_empty() { + return common_prefix.trim_end_matches('_').to_string(); } - // Return the common prefix (without trailing underscore) - common_prefix.trim_end_matches('_').to_string() + // If no common prefix, try to find a common suffix + let common_suffix = find_common_suffix_at_underscore(&leaf_names); + if !common_suffix.is_empty() { + return common_suffix.trim_start_matches('_').to_string(); + } + + String::new() } /// Find the longest common prefix at an underscore boundary. @@ -184,6 +187,14 @@ fn find_common_prefix_at_underscore(names: &[String]) -> String { String::new() } +/// Find the longest common suffix at an underscore boundary. +fn find_common_suffix_at_underscore(names: &[String]) -> String { + // Reverse strings, find common prefix, reverse result + let reversed: Vec = names.iter().map(|s| s.chars().rev().collect()).collect(); + let prefix = find_common_prefix_at_underscore(&reversed); + prefix.chars().rev().collect() +} + /// Infer the accumulated name for a child node based on a descendant leaf name. pub fn infer_accumulated_name(parent_acc: &str, field_name: &str, descendant_leaf: &str) -> String { if let Some(pos) = descendant_leaf.find(field_name) { diff --git a/crates/brk_bindgen/src/generators/javascript/client.rs b/crates/brk_bindgen/src/generators/javascript/client.rs index efeca8fa7..ab24cbb60 100644 --- a/crates/brk_bindgen/src/generators/javascript/client.rs +++ b/crates/brk_bindgen/src/generators/javascript/client.rs @@ -66,6 +66,8 @@ class BrkError extends Error {{ * @property {{(index: Index) => Endpoint|undefined}} get - Get an endpoint for a specific index */ +/** @typedef {{MetricPattern}} AnyMetricPattern */ + /** * Create an endpoint for a metric index. * @template T diff --git a/crates/brk_bundler/src/lib.rs b/crates/brk_bundler/src/lib.rs index 0cddde9eb..11a76151a 100644 --- a/crates/brk_bundler/src/lib.rs +++ b/crates/brk_bundler/src/lib.rs @@ -199,7 +199,8 @@ pub async fn bundle( .unwrap(); // Poll watcher to catch programmatic edits (e.g., Claude Code's atomic writes) - let poll_config = notify::Config::default().with_poll_interval(Duration::from_secs(1)); + let poll_config = notify::Config::default() + .with_poll_interval(Duration::from_secs(1)); let mut poll_watcher = PollWatcher::new( move |res: Result| match res { Ok(event) => match event.kind { diff --git a/crates/brk_cli/Cargo.toml b/crates/brk_cli/Cargo.toml index 3b83790f5..ed2dab225 100644 --- a/crates/brk_cli/Cargo.toml +++ b/crates/brk_cli/Cargo.toml @@ -22,7 +22,7 @@ brk_query = { workspace = true } brk_reader = { workspace = true } brk_rpc = { workspace = true } brk_server = { workspace = true } -clap = { version = "4.5.53", features = ["derive", "string"] } +clap = { version = "4.5.54", features = ["derive", "string"] } color-eyre = { workspace = true } brk_alloc = { workspace = true } log = { workspace = true } diff --git a/crates/brk_cli/src/main.rs b/crates/brk_cli/src/main.rs index 3a24675e3..c41084ab6 100644 --- a/crates/brk_cli/src/main.rs +++ b/crates/brk_cli/src/main.rs @@ -132,15 +132,7 @@ pub fn run() -> color_eyre::Result<()> { modules_path = downloaded_modules_path; } - Some( - bundle( - &modules_path, - &websites_path, - website.to_folder_name(), - true, - ) - .await?, - ) + Some(websites_path.join(website.to_folder_name())) } else { None }; diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index aba12c569..ac280e952 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -2034,8 +2034,8 @@ pub struct MetricPattern27By { } impl MetricPattern27By { - pub fn by_monthindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::MonthIndex) + pub fn by_opreturnindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::OpReturnIndex) } } @@ -2073,7 +2073,7 @@ impl AnyMetricPattern for MetricPattern27 { fn indexes(&self) -> &'static [Index] { &[ - Index::MonthIndex, + Index::OpReturnIndex, ] } } @@ -2081,7 +2081,7 @@ impl AnyMetricPattern for MetricPattern27 { impl MetricPattern for MetricPattern27 { fn get(&self, index: Index) -> Option> { match index { - Index::MonthIndex => Some(self.by.by_monthindex()), + Index::OpReturnIndex => Some(self.by.by_opreturnindex()), _ => None, } } @@ -2095,8 +2095,8 @@ pub struct MetricPattern28By { } impl MetricPattern28By { - pub fn by_opreturnindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::OpReturnIndex) + pub fn by_txoutindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::TxOutIndex) } } @@ -2134,7 +2134,7 @@ impl AnyMetricPattern for MetricPattern28 { fn indexes(&self) -> &'static [Index] { &[ - Index::OpReturnIndex, + Index::TxOutIndex, ] } } @@ -2142,7 +2142,7 @@ impl AnyMetricPattern for MetricPattern28 { impl MetricPattern for MetricPattern28 { fn get(&self, index: Index) -> Option> { match index { - Index::OpReturnIndex => Some(self.by.by_opreturnindex()), + Index::TxOutIndex => Some(self.by.by_txoutindex()), _ => None, } } @@ -2156,8 +2156,8 @@ pub struct MetricPattern29By { } impl MetricPattern29By { - pub fn by_txoutindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::TxOutIndex) + pub fn by_p2aaddressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2AAddressIndex) } } @@ -2195,7 +2195,7 @@ impl AnyMetricPattern for MetricPattern29 { fn indexes(&self) -> &'static [Index] { &[ - Index::TxOutIndex, + Index::P2AAddressIndex, ] } } @@ -2203,7 +2203,7 @@ impl AnyMetricPattern for MetricPattern29 { impl MetricPattern for MetricPattern29 { fn get(&self, index: Index) -> Option> { match index { - Index::TxOutIndex => Some(self.by.by_txoutindex()), + Index::P2AAddressIndex => Some(self.by.by_p2aaddressindex()), _ => None, } } @@ -2217,8 +2217,8 @@ pub struct MetricPattern30By { } impl MetricPattern30By { - pub fn by_p2aaddressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2AAddressIndex) + pub fn by_p2msoutputindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2MSOutputIndex) } } @@ -2256,7 +2256,7 @@ impl AnyMetricPattern for MetricPattern30 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2AAddressIndex, + Index::P2MSOutputIndex, ] } } @@ -2264,7 +2264,7 @@ impl AnyMetricPattern for MetricPattern30 { impl MetricPattern for MetricPattern30 { fn get(&self, index: Index) -> Option> { match index { - Index::P2AAddressIndex => Some(self.by.by_p2aaddressindex()), + Index::P2MSOutputIndex => Some(self.by.by_p2msoutputindex()), _ => None, } } @@ -2278,8 +2278,8 @@ pub struct MetricPattern31By { } impl MetricPattern31By { - pub fn by_p2msoutputindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2MSOutputIndex) + pub fn by_p2pk33addressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2PK33AddressIndex) } } @@ -2317,7 +2317,7 @@ impl AnyMetricPattern for MetricPattern31 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2MSOutputIndex, + Index::P2PK33AddressIndex, ] } } @@ -2325,7 +2325,7 @@ impl AnyMetricPattern for MetricPattern31 { impl MetricPattern for MetricPattern31 { fn get(&self, index: Index) -> Option> { match index { - Index::P2MSOutputIndex => Some(self.by.by_p2msoutputindex()), + Index::P2PK33AddressIndex => Some(self.by.by_p2pk33addressindex()), _ => None, } } @@ -2339,8 +2339,8 @@ pub struct MetricPattern32By { } impl MetricPattern32By { - pub fn by_p2pk33addressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2PK33AddressIndex) + pub fn by_p2pk65addressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2PK65AddressIndex) } } @@ -2378,7 +2378,7 @@ impl AnyMetricPattern for MetricPattern32 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2PK33AddressIndex, + Index::P2PK65AddressIndex, ] } } @@ -2386,7 +2386,7 @@ impl AnyMetricPattern for MetricPattern32 { impl MetricPattern for MetricPattern32 { fn get(&self, index: Index) -> Option> { match index { - Index::P2PK33AddressIndex => Some(self.by.by_p2pk33addressindex()), + Index::P2PK65AddressIndex => Some(self.by.by_p2pk65addressindex()), _ => None, } } @@ -2400,8 +2400,8 @@ pub struct MetricPattern33By { } impl MetricPattern33By { - pub fn by_p2pk65addressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2PK65AddressIndex) + pub fn by_p2pkhaddressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2PKHAddressIndex) } } @@ -2439,7 +2439,7 @@ impl AnyMetricPattern for MetricPattern33 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2PK65AddressIndex, + Index::P2PKHAddressIndex, ] } } @@ -2447,7 +2447,7 @@ impl AnyMetricPattern for MetricPattern33 { impl MetricPattern for MetricPattern33 { fn get(&self, index: Index) -> Option> { match index { - Index::P2PK65AddressIndex => Some(self.by.by_p2pk65addressindex()), + Index::P2PKHAddressIndex => Some(self.by.by_p2pkhaddressindex()), _ => None, } } @@ -2461,8 +2461,8 @@ pub struct MetricPattern34By { } impl MetricPattern34By { - pub fn by_p2pkhaddressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2PKHAddressIndex) + pub fn by_p2shaddressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2SHAddressIndex) } } @@ -2500,7 +2500,7 @@ impl AnyMetricPattern for MetricPattern34 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2PKHAddressIndex, + Index::P2SHAddressIndex, ] } } @@ -2508,7 +2508,7 @@ impl AnyMetricPattern for MetricPattern34 { impl MetricPattern for MetricPattern34 { fn get(&self, index: Index) -> Option> { match index { - Index::P2PKHAddressIndex => Some(self.by.by_p2pkhaddressindex()), + Index::P2SHAddressIndex => Some(self.by.by_p2shaddressindex()), _ => None, } } @@ -2522,8 +2522,8 @@ pub struct MetricPattern35By { } impl MetricPattern35By { - pub fn by_p2shaddressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2SHAddressIndex) + pub fn by_p2traddressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2TRAddressIndex) } } @@ -2561,7 +2561,7 @@ impl AnyMetricPattern for MetricPattern35 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2SHAddressIndex, + Index::P2TRAddressIndex, ] } } @@ -2569,7 +2569,7 @@ impl AnyMetricPattern for MetricPattern35 { impl MetricPattern for MetricPattern35 { fn get(&self, index: Index) -> Option> { match index { - Index::P2SHAddressIndex => Some(self.by.by_p2shaddressindex()), + Index::P2TRAddressIndex => Some(self.by.by_p2traddressindex()), _ => None, } } @@ -2583,8 +2583,8 @@ pub struct MetricPattern36By { } impl MetricPattern36By { - pub fn by_p2traddressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2TRAddressIndex) + pub fn by_p2wpkhaddressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2WPKHAddressIndex) } } @@ -2622,7 +2622,7 @@ impl AnyMetricPattern for MetricPattern36 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2TRAddressIndex, + Index::P2WPKHAddressIndex, ] } } @@ -2630,7 +2630,7 @@ impl AnyMetricPattern for MetricPattern36 { impl MetricPattern for MetricPattern36 { fn get(&self, index: Index) -> Option> { match index { - Index::P2TRAddressIndex => Some(self.by.by_p2traddressindex()), + Index::P2WPKHAddressIndex => Some(self.by.by_p2wpkhaddressindex()), _ => None, } } @@ -2644,8 +2644,8 @@ pub struct MetricPattern37By { } impl MetricPattern37By { - pub fn by_p2wpkhaddressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2WPKHAddressIndex) + pub fn by_p2wshaddressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::P2WSHAddressIndex) } } @@ -2683,7 +2683,7 @@ impl AnyMetricPattern for MetricPattern37 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2WPKHAddressIndex, + Index::P2WSHAddressIndex, ] } } @@ -2691,7 +2691,7 @@ impl AnyMetricPattern for MetricPattern37 { impl MetricPattern for MetricPattern37 { fn get(&self, index: Index) -> Option> { match index { - Index::P2WPKHAddressIndex => Some(self.by.by_p2wpkhaddressindex()), + Index::P2WSHAddressIndex => Some(self.by.by_p2wshaddressindex()), _ => None, } } @@ -2705,8 +2705,8 @@ pub struct MetricPattern38By { } impl MetricPattern38By { - pub fn by_p2wshaddressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::P2WSHAddressIndex) + pub fn by_txindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::TxIndex) } } @@ -2744,7 +2744,7 @@ impl AnyMetricPattern for MetricPattern38 { fn indexes(&self) -> &'static [Index] { &[ - Index::P2WSHAddressIndex, + Index::TxIndex, ] } } @@ -2752,7 +2752,7 @@ impl AnyMetricPattern for MetricPattern38 { impl MetricPattern for MetricPattern38 { fn get(&self, index: Index) -> Option> { match index { - Index::P2WSHAddressIndex => Some(self.by.by_p2wshaddressindex()), + Index::TxIndex => Some(self.by.by_txindex()), _ => None, } } @@ -2766,8 +2766,8 @@ pub struct MetricPattern39By { } impl MetricPattern39By { - pub fn by_quarterindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::QuarterIndex) + pub fn by_unknownoutputindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::UnknownOutputIndex) } } @@ -2805,7 +2805,7 @@ impl AnyMetricPattern for MetricPattern39 { fn indexes(&self) -> &'static [Index] { &[ - Index::QuarterIndex, + Index::UnknownOutputIndex, ] } } @@ -2813,7 +2813,7 @@ impl AnyMetricPattern for MetricPattern39 { impl MetricPattern for MetricPattern39 { fn get(&self, index: Index) -> Option> { match index { - Index::QuarterIndex => Some(self.by.by_quarterindex()), + Index::UnknownOutputIndex => Some(self.by.by_unknownoutputindex()), _ => None, } } @@ -2827,8 +2827,8 @@ pub struct MetricPattern40By { } impl MetricPattern40By { - pub fn by_semesterindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::SemesterIndex) + pub fn by_loadedaddressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::LoadedAddressIndex) } } @@ -2866,7 +2866,7 @@ impl AnyMetricPattern for MetricPattern40 { fn indexes(&self) -> &'static [Index] { &[ - Index::SemesterIndex, + Index::LoadedAddressIndex, ] } } @@ -2874,7 +2874,7 @@ impl AnyMetricPattern for MetricPattern40 { impl MetricPattern for MetricPattern40 { fn get(&self, index: Index) -> Option> { match index { - Index::SemesterIndex => Some(self.by.by_semesterindex()), + Index::LoadedAddressIndex => Some(self.by.by_loadedaddressindex()), _ => None, } } @@ -2888,8 +2888,8 @@ pub struct MetricPattern41By { } impl MetricPattern41By { - pub fn by_txindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::TxIndex) + pub fn by_emptyaddressindex(&self) -> Endpoint { + Endpoint::new(self.client.clone(), self.name.clone(), Index::EmptyAddressIndex) } } @@ -2925,311 +2925,6 @@ impl AnyMetricPattern for MetricPattern41 { &self.name } - fn indexes(&self) -> &'static [Index] { - &[ - Index::TxIndex, - ] - } -} - -impl MetricPattern for MetricPattern41 { - fn get(&self, index: Index) -> Option> { - match index { - Index::TxIndex => Some(self.by.by_txindex()), - _ => None, - } - } -} - -/// Container for index endpoint methods. -pub struct MetricPattern42By { - client: Arc, - name: Arc, - _marker: std::marker::PhantomData, -} - -impl MetricPattern42By { - pub fn by_unknownoutputindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::UnknownOutputIndex) - } -} - -/// Index accessor for metrics with 1 indexes. -pub struct MetricPattern42 { - client: Arc, - name: Arc, - pub by: MetricPattern42By, -} - -impl MetricPattern42 { - pub fn new(client: Arc, name: String) -> Self { - let name: Arc = name.into(); - Self { - client: client.clone(), - name: name.clone(), - by: MetricPattern42By { - client, - name, - _marker: std::marker::PhantomData, - } - } - } - - /// Get the metric name. - pub fn name(&self) -> &str { - &self.name - } -} - -impl AnyMetricPattern for MetricPattern42 { - fn name(&self) -> &str { - &self.name - } - - fn indexes(&self) -> &'static [Index] { - &[ - Index::UnknownOutputIndex, - ] - } -} - -impl MetricPattern for MetricPattern42 { - fn get(&self, index: Index) -> Option> { - match index { - Index::UnknownOutputIndex => Some(self.by.by_unknownoutputindex()), - _ => None, - } - } -} - -/// Container for index endpoint methods. -pub struct MetricPattern43By { - client: Arc, - name: Arc, - _marker: std::marker::PhantomData, -} - -impl MetricPattern43By { - pub fn by_weekindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::WeekIndex) - } -} - -/// Index accessor for metrics with 1 indexes. -pub struct MetricPattern43 { - client: Arc, - name: Arc, - pub by: MetricPattern43By, -} - -impl MetricPattern43 { - pub fn new(client: Arc, name: String) -> Self { - let name: Arc = name.into(); - Self { - client: client.clone(), - name: name.clone(), - by: MetricPattern43By { - client, - name, - _marker: std::marker::PhantomData, - } - } - } - - /// Get the metric name. - pub fn name(&self) -> &str { - &self.name - } -} - -impl AnyMetricPattern for MetricPattern43 { - fn name(&self) -> &str { - &self.name - } - - fn indexes(&self) -> &'static [Index] { - &[ - Index::WeekIndex, - ] - } -} - -impl MetricPattern for MetricPattern43 { - fn get(&self, index: Index) -> Option> { - match index { - Index::WeekIndex => Some(self.by.by_weekindex()), - _ => None, - } - } -} - -/// Container for index endpoint methods. -pub struct MetricPattern44By { - client: Arc, - name: Arc, - _marker: std::marker::PhantomData, -} - -impl MetricPattern44By { - pub fn by_yearindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::YearIndex) - } -} - -/// Index accessor for metrics with 1 indexes. -pub struct MetricPattern44 { - client: Arc, - name: Arc, - pub by: MetricPattern44By, -} - -impl MetricPattern44 { - pub fn new(client: Arc, name: String) -> Self { - let name: Arc = name.into(); - Self { - client: client.clone(), - name: name.clone(), - by: MetricPattern44By { - client, - name, - _marker: std::marker::PhantomData, - } - } - } - - /// Get the metric name. - pub fn name(&self) -> &str { - &self.name - } -} - -impl AnyMetricPattern for MetricPattern44 { - fn name(&self) -> &str { - &self.name - } - - fn indexes(&self) -> &'static [Index] { - &[ - Index::YearIndex, - ] - } -} - -impl MetricPattern for MetricPattern44 { - fn get(&self, index: Index) -> Option> { - match index { - Index::YearIndex => Some(self.by.by_yearindex()), - _ => None, - } - } -} - -/// Container for index endpoint methods. -pub struct MetricPattern45By { - client: Arc, - name: Arc, - _marker: std::marker::PhantomData, -} - -impl MetricPattern45By { - pub fn by_loadedaddressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::LoadedAddressIndex) - } -} - -/// Index accessor for metrics with 1 indexes. -pub struct MetricPattern45 { - client: Arc, - name: Arc, - pub by: MetricPattern45By, -} - -impl MetricPattern45 { - pub fn new(client: Arc, name: String) -> Self { - let name: Arc = name.into(); - Self { - client: client.clone(), - name: name.clone(), - by: MetricPattern45By { - client, - name, - _marker: std::marker::PhantomData, - } - } - } - - /// Get the metric name. - pub fn name(&self) -> &str { - &self.name - } -} - -impl AnyMetricPattern for MetricPattern45 { - fn name(&self) -> &str { - &self.name - } - - fn indexes(&self) -> &'static [Index] { - &[ - Index::LoadedAddressIndex, - ] - } -} - -impl MetricPattern for MetricPattern45 { - fn get(&self, index: Index) -> Option> { - match index { - Index::LoadedAddressIndex => Some(self.by.by_loadedaddressindex()), - _ => None, - } - } -} - -/// Container for index endpoint methods. -pub struct MetricPattern46By { - client: Arc, - name: Arc, - _marker: std::marker::PhantomData, -} - -impl MetricPattern46By { - pub fn by_emptyaddressindex(&self) -> Endpoint { - Endpoint::new(self.client.clone(), self.name.clone(), Index::EmptyAddressIndex) - } -} - -/// Index accessor for metrics with 1 indexes. -pub struct MetricPattern46 { - client: Arc, - name: Arc, - pub by: MetricPattern46By, -} - -impl MetricPattern46 { - pub fn new(client: Arc, name: String) -> Self { - let name: Arc = name.into(); - Self { - client: client.clone(), - name: name.clone(), - by: MetricPattern46By { - client, - name, - _marker: std::marker::PhantomData, - } - } - } - - /// Get the metric name. - pub fn name(&self) -> &str { - &self.name - } -} - -impl AnyMetricPattern for MetricPattern46 { - fn name(&self) -> &str { - &self.name - } - fn indexes(&self) -> &'static [Index] { &[ Index::EmptyAddressIndex, @@ -3237,7 +2932,7 @@ impl AnyMetricPattern for MetricPattern46 { } } -impl MetricPattern for MetricPattern46 { +impl MetricPattern for MetricPattern41 { fn get(&self, index: Index) -> Option> { match index { Index::EmptyAddressIndex => Some(self.by.by_emptyaddressindex()), @@ -3324,6 +3019,78 @@ impl RealizedPattern3 { } } +/// Pattern struct for repeated tree structure. +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 mvrv: MetricPattern4, + pub neg_realized_loss: BlockCountPattern, + pub net_realized_pnl: BlockCountPattern, + pub net_realized_pnl_cumulative_30d_delta: MetricPattern4, + pub net_realized_pnl_cumulative_30d_delta_rel_to_market_cap: MetricPattern4, + pub net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap: MetricPattern4, + pub net_realized_pnl_rel_to_realized_cap: MetricPattern25, + pub realized_cap: MetricPattern1, + pub realized_cap_30d_delta: MetricPattern4, + pub realized_loss: BlockCountPattern, + pub realized_loss_rel_to_realized_cap: MetricPattern25, + pub realized_price: MetricPattern1, + pub realized_price_extra: RealizedPriceExtraPattern, + pub realized_profit: BlockCountPattern, + pub realized_profit_rel_to_realized_cap: MetricPattern25, + pub realized_value: MetricPattern1, + pub sell_side_risk_ratio: MetricPattern21, + pub sell_side_risk_ratio_30d_ema: MetricPattern21, + pub sell_side_risk_ratio_7d_ema: MetricPattern21, + pub sopr: MetricPattern21, + pub sopr_30d_ema: MetricPattern21, + pub sopr_7d_ema: MetricPattern21, + pub total_realized_pnl: TotalRealizedPnlPattern, + pub value_created: MetricPattern1, + pub value_destroyed: MetricPattern1, +} + +impl RealizedPattern4 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + 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")), + 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")), + net_realized_pnl_cumulative_30d_delta: MetricPattern4::new(client.clone(), _m(&acc, "net_realized_pnl_cumulative_30d_delta")), + net_realized_pnl_cumulative_30d_delta_rel_to_market_cap: MetricPattern4::new(client.clone(), _m(&acc, "net_realized_pnl_cumulative_30d_delta_rel_to_market_cap")), + net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap: MetricPattern4::new(client.clone(), _m(&acc, "net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap")), + net_realized_pnl_rel_to_realized_cap: MetricPattern25::new(client.clone(), _m(&acc, "net_realized_pnl_rel_to_realized_cap")), + realized_cap: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap")), + realized_cap_30d_delta: MetricPattern4::new(client.clone(), _m(&acc, "realized_cap_30d_delta")), + realized_loss: BlockCountPattern::new(client.clone(), _m(&acc, "realized_loss")), + realized_loss_rel_to_realized_cap: MetricPattern25::new(client.clone(), _m(&acc, "realized_loss_rel_to_realized_cap")), + realized_price: MetricPattern1::new(client.clone(), _m(&acc, "realized_price")), + realized_price_extra: RealizedPriceExtraPattern::new(client.clone(), _m(&acc, "realized_price")), + realized_profit: BlockCountPattern::new(client.clone(), _m(&acc, "realized_profit")), + realized_profit_rel_to_realized_cap: MetricPattern25::new(client.clone(), _m(&acc, "realized_profit_rel_to_realized_cap")), + realized_value: MetricPattern1::new(client.clone(), _m(&acc, "realized_value")), + sell_side_risk_ratio: MetricPattern21::new(client.clone(), _m(&acc, "sell_side_risk_ratio")), + sell_side_risk_ratio_30d_ema: MetricPattern21::new(client.clone(), _m(&acc, "sell_side_risk_ratio_30d_ema")), + sell_side_risk_ratio_7d_ema: MetricPattern21::new(client.clone(), _m(&acc, "sell_side_risk_ratio_7d_ema")), + sopr: MetricPattern21::new(client.clone(), _m(&acc, "sopr")), + sopr_30d_ema: MetricPattern21::new(client.clone(), _m(&acc, "sopr_30d_ema")), + sopr_7d_ema: MetricPattern21::new(client.clone(), _m(&acc, "sopr_7d_ema")), + total_realized_pnl: TotalRealizedPnlPattern::new(client.clone(), _m(&acc, "total_realized_pnl")), + value_created: MetricPattern1::new(client.clone(), _m(&acc, "value_created")), + value_destroyed: MetricPattern1::new(client.clone(), _m(&acc, "value_destroyed")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct Ratio1ySdPattern { pub _0sd_usd: MetricPattern4, @@ -3758,6 +3525,150 @@ impl AXbtPattern { } } +/// Pattern struct for repeated tree structure. +pub struct PriceAgoPattern { + pub _10y: MetricPattern4, + pub _1d: MetricPattern4, + pub _1m: MetricPattern4, + pub _1w: MetricPattern4, + pub _1y: MetricPattern4, + pub _2y: MetricPattern4, + pub _3m: MetricPattern4, + pub _3y: MetricPattern4, + pub _4y: MetricPattern4, + pub _5y: MetricPattern4, + pub _6m: MetricPattern4, + pub _6y: MetricPattern4, + pub _8y: MetricPattern4, +} + +impl PriceAgoPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + _10y: MetricPattern4::new(client.clone(), _m(&acc, "10y_ago")), + _1d: MetricPattern4::new(client.clone(), _m(&acc, "1d_ago")), + _1m: MetricPattern4::new(client.clone(), _m(&acc, "1m_ago")), + _1w: MetricPattern4::new(client.clone(), _m(&acc, "1w_ago")), + _1y: MetricPattern4::new(client.clone(), _m(&acc, "1y_ago")), + _2y: MetricPattern4::new(client.clone(), _m(&acc, "2y_ago")), + _3m: MetricPattern4::new(client.clone(), _m(&acc, "3m_ago")), + _3y: MetricPattern4::new(client.clone(), _m(&acc, "3y_ago")), + _4y: MetricPattern4::new(client.clone(), _m(&acc, "4y_ago")), + _5y: MetricPattern4::new(client.clone(), _m(&acc, "5y_ago")), + _6m: MetricPattern4::new(client.clone(), _m(&acc, "6m_ago")), + _6y: MetricPattern4::new(client.clone(), _m(&acc, "6y_ago")), + _8y: MetricPattern4::new(client.clone(), _m(&acc, "8y_ago")), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct PeriodLumpSumStackPattern { + pub _10y: ActiveSupplyPattern, + pub _1m: ActiveSupplyPattern, + pub _1w: ActiveSupplyPattern, + pub _1y: ActiveSupplyPattern, + pub _2y: ActiveSupplyPattern, + pub _3m: ActiveSupplyPattern, + pub _3y: ActiveSupplyPattern, + pub _4y: ActiveSupplyPattern, + pub _5y: ActiveSupplyPattern, + pub _6m: ActiveSupplyPattern, + pub _6y: ActiveSupplyPattern, + pub _8y: ActiveSupplyPattern, +} + +impl PeriodLumpSumStackPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + _10y: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "10y".to_string() } else { format!("10y_{acc}") }), + _1m: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "1m".to_string() } else { format!("1m_{acc}") }), + _1w: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "1w".to_string() } else { format!("1w_{acc}") }), + _1y: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "1y".to_string() } else { format!("1y_{acc}") }), + _2y: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "2y".to_string() } else { format!("2y_{acc}") }), + _3m: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "3m".to_string() } else { format!("3m_{acc}") }), + _3y: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "3y".to_string() } else { format!("3y_{acc}") }), + _4y: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "4y".to_string() } else { format!("4y_{acc}") }), + _5y: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "5y".to_string() } else { format!("5y_{acc}") }), + _6m: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "6m".to_string() } else { format!("6m_{acc}") }), + _6y: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "6y".to_string() } else { format!("6y_{acc}") }), + _8y: ActiveSupplyPattern::new(client.clone(), if acc.is_empty() { "8y".to_string() } else { format!("8y_{acc}") }), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct PeriodAvgPricePattern { + pub _10y: MetricPattern4, + pub _1m: MetricPattern4, + pub _1w: MetricPattern4, + pub _1y: MetricPattern4, + pub _2y: MetricPattern4, + pub _3m: MetricPattern4, + pub _3y: MetricPattern4, + pub _4y: MetricPattern4, + pub _5y: MetricPattern4, + pub _6m: MetricPattern4, + pub _6y: MetricPattern4, + pub _8y: MetricPattern4, +} + +impl PeriodAvgPricePattern { + /// 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}") }), + _1m: MetricPattern4::new(client.clone(), if acc.is_empty() { "1m".to_string() } else { format!("1m_{acc}") }), + _1w: MetricPattern4::new(client.clone(), if acc.is_empty() { "1w".to_string() } else { format!("1w_{acc}") }), + _1y: MetricPattern4::new(client.clone(), if acc.is_empty() { "1y".to_string() } else { format!("1y_{acc}") }), + _2y: MetricPattern4::new(client.clone(), if acc.is_empty() { "2y".to_string() } else { format!("2y_{acc}") }), + _3m: MetricPattern4::new(client.clone(), if acc.is_empty() { "3m".to_string() } else { format!("3m_{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}") }), + _6m: MetricPattern4::new(client.clone(), if acc.is_empty() { "6m".to_string() } else { format!("6m_{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 ClassAvgPricePattern { + pub _2015: MetricPattern4, + pub _2016: MetricPattern4, + pub _2017: MetricPattern4, + pub _2018: MetricPattern4, + pub _2019: MetricPattern4, + pub _2020: MetricPattern4, + pub _2021: MetricPattern4, + pub _2022: MetricPattern4, + pub _2023: MetricPattern4, + pub _2024: MetricPattern4, + pub _2025: MetricPattern4, +} + +impl ClassAvgPricePattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + _2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_avg_price")), + _2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_avg_price")), + _2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_avg_price")), + _2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_avg_price")), + _2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_avg_price")), + _2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_avg_price")), + _2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_avg_price")), + _2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_avg_price")), + _2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_avg_price")), + _2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_avg_price")), + _2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_avg_price")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct BitcoinPattern { pub average: MetricPattern2, @@ -3826,32 +3737,32 @@ impl RelativePattern { /// Pattern struct for repeated tree structure. pub struct BlockSizePattern { - pub average: MetricPattern2, + pub average: MetricPattern1, 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 max: MetricPattern1, + pub median: MetricPattern25, + pub min: MetricPattern1, + pub pct10: MetricPattern25, + pub pct25: MetricPattern25, + pub pct75: MetricPattern25, + pub pct90: MetricPattern25, + pub sum: MetricPattern1, } impl BlockSizePattern { /// 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")), + average: MetricPattern1::new(client.clone(), _m(&acc, "avg")), 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")), + 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")), } } } @@ -3888,84 +3799,82 @@ impl UnrealizedPattern { /// Pattern struct for repeated tree structure. pub struct AddresstypeToHeightToAddrCountPattern { - pub p2a: MetricPattern30, - pub p2pk33: MetricPattern32, - pub p2pk65: MetricPattern33, - pub p2pkh: MetricPattern34, - pub p2sh: MetricPattern35, - pub p2tr: MetricPattern36, - pub p2wpkh: MetricPattern37, - pub p2wsh: MetricPattern38, + pub p2a: MetricPattern25, + pub p2pk33: MetricPattern25, + pub p2pk65: MetricPattern25, + pub p2pkh: MetricPattern25, + pub p2sh: MetricPattern25, + pub p2tr: MetricPattern25, + pub p2wpkh: MetricPattern25, + pub p2wsh: MetricPattern25, } impl AddresstypeToHeightToAddrCountPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - p2a: MetricPattern30::new(client.clone(), if acc.is_empty() { "p2a".to_string() } else { format!("p2a_{acc}") }), - p2pk33: MetricPattern32::new(client.clone(), if acc.is_empty() { "p2pk33".to_string() } else { format!("p2pk33_{acc}") }), - p2pk65: MetricPattern33::new(client.clone(), if acc.is_empty() { "p2pk65".to_string() } else { format!("p2pk65_{acc}") }), - p2pkh: MetricPattern34::new(client.clone(), if acc.is_empty() { "p2pkh".to_string() } else { format!("p2pkh_{acc}") }), - p2sh: MetricPattern35::new(client.clone(), if acc.is_empty() { "p2sh".to_string() } else { format!("p2sh_{acc}") }), - p2tr: MetricPattern36::new(client.clone(), if acc.is_empty() { "p2tr".to_string() } else { format!("p2tr_{acc}") }), - p2wpkh: MetricPattern37::new(client.clone(), if acc.is_empty() { "p2wpkh".to_string() } else { format!("p2wpkh_{acc}") }), - p2wsh: MetricPattern38::new(client.clone(), if acc.is_empty() { "p2wsh".to_string() } else { format!("p2wsh_{acc}") }), + 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}") }), } } } /// Pattern struct for repeated tree structure. pub struct BlockIntervalPattern { - pub average: MetricPattern1, - pub max: MetricPattern1, - pub median: MetricPattern25, - pub min: MetricPattern1, - pub pct10: MetricPattern25, - pub pct25: MetricPattern25, - pub pct75: MetricPattern25, - pub pct90: MetricPattern25, + pub average: MetricPattern2, + pub max: MetricPattern2, + pub median: MetricPattern21, + pub min: MetricPattern2, + pub pct10: MetricPattern21, + pub pct25: MetricPattern21, + pub pct75: MetricPattern21, + pub pct90: MetricPattern21, } impl BlockIntervalPattern { /// 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")), - 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")), + 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 Constant0Pattern { - pub dateindex: MetricPattern21, - pub decadeindex: MetricPattern22, - pub height: MetricPattern25, - pub monthindex: MetricPattern27, - pub quarterindex: MetricPattern39, - pub semesterindex: MetricPattern40, - pub weekindex: MetricPattern43, - pub yearindex: MetricPattern44, +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 Constant0Pattern { +impl PeriodCagrPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - dateindex: MetricPattern21::new(client.clone(), acc.clone()), - decadeindex: MetricPattern22::new(client.clone(), acc.clone()), - height: MetricPattern25::new(client.clone(), acc.clone()), - monthindex: MetricPattern27::new(client.clone(), acc.clone()), - quarterindex: MetricPattern39::new(client.clone(), acc.clone()), - semesterindex: MetricPattern40::new(client.clone(), acc.clone()), - weekindex: MetricPattern43::new(client.clone(), acc.clone()), - yearindex: MetricPattern44::new(client.clone(), acc.clone()), + _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}") }), } } } @@ -4021,22 +3930,22 @@ impl UpTo1dPattern { } /// Pattern struct for repeated tree structure. -pub struct _0satsPattern2 { +pub struct _10yPattern { pub activity: ActivityPattern2, pub cost_basis: CostBasisPattern, - pub realized: RealizedPattern, + pub realized: RealizedPattern4, pub relative: RelativePattern, pub supply: SupplyPattern3, pub unrealized: UnrealizedPattern, } -impl _0satsPattern2 { +impl _10yPattern { /// 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()), + realized: RealizedPattern4::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()), @@ -4068,6 +3977,30 @@ 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, @@ -4092,28 +4025,6 @@ impl SegwitAdoptionPattern { } } -/// Pattern struct for repeated tree structure. -pub struct ActivityPattern2 { - pub coinblocks_destroyed: BlockCountPattern, - pub coindays_destroyed: BlockCountPattern, - pub satblocks_destroyed: MetricPattern25, - pub satdays_destroyed: MetricPattern25, - pub sent: SentPattern, -} - -impl ActivityPattern2 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - coinblocks_destroyed: BlockCountPattern::new(client.clone(), _m(&acc, "coinblocks_destroyed")), - coindays_destroyed: BlockCountPattern::new(client.clone(), _m(&acc, "coindays_destroyed")), - satblocks_destroyed: MetricPattern25::new(client.clone(), _m(&acc, "satblocks_destroyed")), - satdays_destroyed: MetricPattern25::new(client.clone(), _m(&acc, "satdays_destroyed")), - sent: SentPattern::new(client.clone(), _m(&acc, "sent")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct SupplyPattern3 { pub supply: SupplyPattern2, @@ -4137,21 +4048,23 @@ impl SupplyPattern3 { } /// Pattern struct for repeated tree structure. -pub struct SentPattern { - pub base: MetricPattern25, - pub bitcoin: BlockCountPattern, - pub dollars: BlockCountPattern, - pub sats: SatsPattern, +pub struct ActivityPattern2 { + pub coinblocks_destroyed: BlockCountPattern, + pub coindays_destroyed: BlockCountPattern, + pub satblocks_destroyed: MetricPattern25, + pub satdays_destroyed: MetricPattern25, + pub sent: SentPattern, } -impl SentPattern { +impl ActivityPattern2 { /// 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()), + coinblocks_destroyed: BlockCountPattern::new(client.clone(), _m(&acc, "coinblocks_destroyed")), + coindays_destroyed: BlockCountPattern::new(client.clone(), _m(&acc, "coindays_destroyed")), + satblocks_destroyed: MetricPattern25::new(client.clone(), _m(&acc, "satblocks_destroyed")), + satdays_destroyed: MetricPattern25::new(client.clone(), _m(&acc, "satdays_destroyed")), + sent: SentPattern::new(client.clone(), _m(&acc, "sent")), } } } @@ -4176,6 +4089,26 @@ 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, @@ -4196,24 +4129,6 @@ impl OpreturnPattern { } } -/// Pattern struct for repeated tree structure. -pub struct CoinbasePattern { - pub bitcoin: BitcoinPattern, - pub dollars: BitcoinPattern, - pub sats: BitcoinPattern, -} - -impl CoinbasePattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - bitcoin: BitcoinPattern::new(client.clone(), _m(&acc, "btc")), - dollars: BitcoinPattern::new(client.clone(), _m(&acc, "usd")), - sats: BitcoinPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct CostBasisPattern2 { pub max_cost_basis: MetricPattern1, @@ -4232,6 +4147,24 @@ impl CostBasisPattern2 { } } +/// Pattern struct for repeated tree structure. +pub struct CoinbasePattern { + pub bitcoin: BitcoinPattern, + pub dollars: BitcoinPattern, + pub sats: BitcoinPattern, +} + +impl CoinbasePattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + bitcoin: BitcoinPattern::new(client.clone(), _m(&acc, "btc")), + dollars: BitcoinPattern::new(client.clone(), _m(&acc, "usd")), + sats: BitcoinPattern::new(client.clone(), acc.clone()), + } + } +} + /// Pattern struct for repeated tree structure. pub struct UnclaimedRewardsPattern { pub bitcoin: BlockCountPattern, @@ -4268,24 +4201,6 @@ impl ActiveSupplyPattern { } } -/// Pattern struct for repeated tree structure. -pub struct BitcoinPattern2 { - pub base: MetricPattern25, - pub cumulative: MetricPattern1, - pub last: MetricPattern2, -} - -impl BitcoinPattern2 { - /// 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()), - cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), - last: MetricPattern2::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct BlockCountPattern { pub base: MetricPattern25, @@ -4305,33 +4220,19 @@ impl BlockCountPattern { } /// Pattern struct for repeated tree structure. -pub struct _1dReturns1mSdPattern { - pub sd: MetricPattern4, - pub sma: MetricPattern4, +pub struct BitcoinPattern2 { + pub base: MetricPattern25, + pub cumulative: MetricPattern1, + pub last: MetricPattern2, } -impl _1dReturns1mSdPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - sd: MetricPattern4::new(client.clone(), _m(&acc, "sd")), - sma: MetricPattern4::new(client.clone(), _m(&acc, "sma")), - } - } -} - -/// Pattern struct for repeated tree structure. -pub struct SatsPattern { - pub cumulative: MetricPattern1, - pub sum: MetricPattern2, -} - -impl SatsPattern { +impl BitcoinPattern2 { /// 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()), cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), - sum: MetricPattern2::new(client.clone(), acc.clone()), + last: MetricPattern2::new(client.clone(), acc.clone()), } } } @@ -4352,6 +4253,22 @@ impl CostBasisPattern { } } +/// Pattern struct for repeated tree structure. +pub struct SatsPattern4 { + pub cumulative: MetricPattern1, + pub last: MetricPattern2, +} + +impl SatsPattern4 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), + last: MetricPattern2::new(client.clone(), acc.clone()), + } + } +} + /// Pattern struct for repeated tree structure. pub struct SupplyValuePattern { pub bitcoin: MetricPattern25, @@ -4369,17 +4286,33 @@ impl SupplyValuePattern { } /// Pattern struct for repeated tree structure. -pub struct SatsPattern4 { +pub struct SatsPattern { pub cumulative: MetricPattern1, - pub last: MetricPattern2, + pub sum: MetricPattern2, } -impl SatsPattern4 { +impl SatsPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { cumulative: MetricPattern1::new(client.clone(), _m(&acc, "cumulative")), - last: MetricPattern2::new(client.clone(), acc.clone()), + sum: MetricPattern2::new(client.clone(), acc.clone()), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct _1dReturns1mSdPattern { + pub sd: MetricPattern4, + pub sma: MetricPattern4, +} + +impl _1dReturns1mSdPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + sd: MetricPattern4::new(client.clone(), _m(&acc, "sd")), + sma: MetricPattern4::new(client.clone(), _m(&acc, "sma")), } } } @@ -4839,39 +4772,47 @@ impl CatalogTree_Computed_Cointime_Value { /// Catalog tree node. pub struct CatalogTree_Computed_Constants { - pub constant_0: Constant0Pattern, - pub constant_1: Constant0Pattern, - pub constant_100: Constant0Pattern, - pub constant_2: Constant0Pattern, - pub constant_3: Constant0Pattern, - pub constant_38_2: Constant0Pattern, - pub constant_4: Constant0Pattern, - pub constant_50: Constant0Pattern, - pub constant_600: Constant0Pattern, - pub constant_61_8: Constant0Pattern, - pub constant_minus_1: Constant0Pattern, - pub constant_minus_2: Constant0Pattern, - pub constant_minus_3: Constant0Pattern, - pub constant_minus_4: Constant0Pattern, + pub constant_0: MetricPattern3, + pub constant_1: MetricPattern3, + pub constant_100: MetricPattern3, + pub constant_2: MetricPattern3, + pub constant_20: MetricPattern3, + pub constant_3: MetricPattern3, + pub constant_30: MetricPattern3, + pub constant_38_2: MetricPattern3, + pub constant_4: MetricPattern3, + pub constant_50: MetricPattern3, + pub constant_600: MetricPattern3, + pub constant_61_8: MetricPattern3, + pub constant_70: MetricPattern3, + pub constant_80: MetricPattern3, + pub constant_minus_1: MetricPattern3, + pub constant_minus_2: MetricPattern3, + pub constant_minus_3: MetricPattern3, + pub constant_minus_4: MetricPattern3, } impl CatalogTree_Computed_Constants { pub fn new(client: Arc, base_path: String) -> Self { Self { - constant_0: Constant0Pattern::new(client.clone(), "constant_0".to_string()), - constant_1: Constant0Pattern::new(client.clone(), "constant_1".to_string()), - constant_100: Constant0Pattern::new(client.clone(), "constant_100".to_string()), - constant_2: Constant0Pattern::new(client.clone(), "constant_2".to_string()), - constant_3: Constant0Pattern::new(client.clone(), "constant_3".to_string()), - constant_38_2: Constant0Pattern::new(client.clone(), "constant_38_2".to_string()), - constant_4: Constant0Pattern::new(client.clone(), "constant_4".to_string()), - constant_50: Constant0Pattern::new(client.clone(), "constant_50".to_string()), - constant_600: Constant0Pattern::new(client.clone(), "constant_600".to_string()), - constant_61_8: Constant0Pattern::new(client.clone(), "constant_61_8".to_string()), - constant_minus_1: Constant0Pattern::new(client.clone(), "constant_minus_1".to_string()), - constant_minus_2: Constant0Pattern::new(client.clone(), "constant_minus_2".to_string()), - constant_minus_3: Constant0Pattern::new(client.clone(), "constant_minus_3".to_string()), - constant_minus_4: Constant0Pattern::new(client.clone(), "constant_minus_4".to_string()), + constant_0: MetricPattern3::new(client.clone(), format!("{base_path}_constant_0")), + constant_1: MetricPattern3::new(client.clone(), format!("{base_path}_constant_1")), + constant_100: MetricPattern3::new(client.clone(), format!("{base_path}_constant_100")), + constant_2: MetricPattern3::new(client.clone(), format!("{base_path}_constant_2")), + constant_20: MetricPattern3::new(client.clone(), format!("{base_path}_constant_20")), + constant_3: MetricPattern3::new(client.clone(), format!("{base_path}_constant_3")), + constant_30: MetricPattern3::new(client.clone(), format!("{base_path}_constant_30")), + constant_38_2: MetricPattern3::new(client.clone(), format!("{base_path}_constant_38_2")), + constant_4: MetricPattern3::new(client.clone(), format!("{base_path}_constant_4")), + constant_50: MetricPattern3::new(client.clone(), format!("{base_path}_constant_50")), + constant_600: MetricPattern3::new(client.clone(), format!("{base_path}_constant_600")), + constant_61_8: MetricPattern3::new(client.clone(), format!("{base_path}_constant_61_8")), + constant_70: MetricPattern3::new(client.clone(), format!("{base_path}_constant_70")), + constant_80: MetricPattern3::new(client.clone(), format!("{base_path}_constant_80")), + constant_minus_1: MetricPattern3::new(client.clone(), format!("{base_path}_constant_minus_1")), + constant_minus_2: MetricPattern3::new(client.clone(), format!("{base_path}_constant_minus_2")), + constant_minus_3: MetricPattern3::new(client.clone(), format!("{base_path}_constant_minus_3")), + constant_minus_4: MetricPattern3::new(client.clone(), format!("{base_path}_constant_minus_4")), } } } @@ -4888,8 +4829,8 @@ pub struct CatalogTree_Computed_Distribution { pub any_address_indexes: AddresstypeToHeightToAddrCountPattern, pub chain_state: MetricPattern25, pub empty_addr_count: MetricPattern1, - pub emptyaddressindex: MetricPattern46, - pub loadedaddressindex: MetricPattern45, + pub emptyaddressindex: MetricPattern41, + pub loadedaddressindex: MetricPattern40, pub utxo_cohorts: CatalogTree_Computed_Distribution_UtxoCohorts, } @@ -4899,15 +4840,15 @@ impl CatalogTree_Computed_Distribution { addr_count: MetricPattern1::new(client.clone(), format!("{base_path}_addr_count")), address_cohorts: CatalogTree_Computed_Distribution_AddressCohorts::new(client.clone(), format!("{base_path}_address_cohorts")), addresses_data: CatalogTree_Computed_Distribution_AddressesData::new(client.clone(), format!("{base_path}_addresses_data")), - addresstype_to_height_to_addr_count: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "".to_string()), - addresstype_to_height_to_empty_addr_count: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "".to_string()), - addresstype_to_indexes_to_addr_count: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "".to_string()), - addresstype_to_indexes_to_empty_addr_count: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "".to_string()), + addresstype_to_height_to_addr_count: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "addr_count".to_string()), + addresstype_to_height_to_empty_addr_count: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "empty_addr_count".to_string()), + addresstype_to_indexes_to_addr_count: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "addr_count".to_string()), + addresstype_to_indexes_to_empty_addr_count: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "empty_addr_count".to_string()), any_address_indexes: AddresstypeToHeightToAddrCountPattern::new(client.clone(), "anyaddressindex".to_string()), chain_state: MetricPattern25::new(client.clone(), format!("{base_path}_chain_state")), empty_addr_count: MetricPattern1::new(client.clone(), format!("{base_path}_empty_addr_count")), - emptyaddressindex: MetricPattern46::new(client.clone(), format!("{base_path}_emptyaddressindex")), - loadedaddressindex: MetricPattern45::new(client.clone(), format!("{base_path}_loadedaddressindex")), + emptyaddressindex: MetricPattern41::new(client.clone(), format!("{base_path}_emptyaddressindex")), + loadedaddressindex: MetricPattern40::new(client.clone(), format!("{base_path}_loadedaddressindex")), utxo_cohorts: CatalogTree_Computed_Distribution_UtxoCohorts::new(client.clone(), format!("{base_path}_utxo_cohorts")), } } @@ -5047,15 +4988,15 @@ impl CatalogTree_Computed_Distribution_AddressCohorts_LtAmount { /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_AddressesData { - pub empty: MetricPattern46, - pub loaded: MetricPattern45, + pub empty: MetricPattern41, + pub loaded: MetricPattern40, } impl CatalogTree_Computed_Distribution_AddressesData { pub fn new(client: Arc, base_path: String) -> Self { Self { - empty: MetricPattern46::new(client.clone(), format!("{base_path}_empty")), - loaded: MetricPattern45::new(client.clone(), format!("{base_path}_loaded")), + empty: MetricPattern41::new(client.clone(), format!("{base_path}_empty")), + loaded: MetricPattern40::new(client.clone(), format!("{base_path}_loaded")), } } } @@ -5233,21 +5174,21 @@ impl CatalogTree_Computed_Distribution_UtxoCohorts_AmountRange { /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_UtxoCohorts_Epoch { - pub _0: _10yTo12yPattern, - pub _1: _10yTo12yPattern, - pub _2: _10yTo12yPattern, - pub _3: _10yTo12yPattern, - pub _4: _10yTo12yPattern, + pub _0: _0satsPattern2, + pub _1: _0satsPattern2, + pub _2: _0satsPattern2, + pub _3: _0satsPattern2, + pub _4: _0satsPattern2, } impl CatalogTree_Computed_Distribution_UtxoCohorts_Epoch { pub fn new(client: Arc, base_path: String) -> Self { Self { - _0: _10yTo12yPattern::new(client.clone(), "epoch_0".to_string()), - _1: _10yTo12yPattern::new(client.clone(), "epoch_1".to_string()), - _2: _10yTo12yPattern::new(client.clone(), "epoch_2".to_string()), - _3: _10yTo12yPattern::new(client.clone(), "epoch_3".to_string()), - _4: _10yTo12yPattern::new(client.clone(), "epoch_4".to_string()), + _0: _0satsPattern2::new(client.clone(), "epoch_0".to_string()), + _1: _0satsPattern2::new(client.clone(), "epoch_1".to_string()), + _2: _0satsPattern2::new(client.clone(), "epoch_2".to_string()), + _3: _0satsPattern2::new(client.clone(), "epoch_3".to_string()), + _4: _0satsPattern2::new(client.clone(), "epoch_4".to_string()), } } } @@ -5328,94 +5269,94 @@ impl CatalogTree_Computed_Distribution_UtxoCohorts_LtAmount { /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_UtxoCohorts_MaxAge { - pub _10y: UpTo1dPattern, - pub _12y: UpTo1dPattern, - pub _15y: UpTo1dPattern, - pub _1m: UpTo1dPattern, - pub _1w: UpTo1dPattern, - pub _1y: UpTo1dPattern, - pub _2m: UpTo1dPattern, - pub _2y: UpTo1dPattern, - pub _3m: UpTo1dPattern, - pub _3y: UpTo1dPattern, - pub _4m: UpTo1dPattern, - pub _4y: UpTo1dPattern, - pub _5m: UpTo1dPattern, - pub _5y: UpTo1dPattern, - pub _6m: UpTo1dPattern, - pub _6y: UpTo1dPattern, - pub _7y: UpTo1dPattern, - pub _8y: UpTo1dPattern, + pub _10y: _10yPattern, + pub _12y: _10yPattern, + pub _15y: _10yPattern, + pub _1m: _10yPattern, + pub _1w: _10yPattern, + pub _1y: _10yPattern, + pub _2m: _10yPattern, + pub _2y: _10yPattern, + pub _3m: _10yPattern, + pub _3y: _10yPattern, + pub _4m: _10yPattern, + pub _4y: _10yPattern, + pub _5m: _10yPattern, + pub _5y: _10yPattern, + pub _6m: _10yPattern, + pub _6y: _10yPattern, + pub _7y: _10yPattern, + pub _8y: _10yPattern, } impl CatalogTree_Computed_Distribution_UtxoCohorts_MaxAge { pub fn new(client: Arc, base_path: String) -> Self { Self { - _10y: UpTo1dPattern::new(client.clone(), "utxos_up_to_10y_old".to_string()), - _12y: UpTo1dPattern::new(client.clone(), "utxos_up_to_12y_old".to_string()), - _15y: UpTo1dPattern::new(client.clone(), "utxos_up_to_15y_old".to_string()), - _1m: UpTo1dPattern::new(client.clone(), "utxos_up_to_1m_old".to_string()), - _1w: UpTo1dPattern::new(client.clone(), "utxos_up_to_1w_old".to_string()), - _1y: UpTo1dPattern::new(client.clone(), "utxos_up_to_1y_old".to_string()), - _2m: UpTo1dPattern::new(client.clone(), "utxos_up_to_2m_old".to_string()), - _2y: UpTo1dPattern::new(client.clone(), "utxos_up_to_2y_old".to_string()), - _3m: UpTo1dPattern::new(client.clone(), "utxos_up_to_3m_old".to_string()), - _3y: UpTo1dPattern::new(client.clone(), "utxos_up_to_3y_old".to_string()), - _4m: UpTo1dPattern::new(client.clone(), "utxos_up_to_4m_old".to_string()), - _4y: UpTo1dPattern::new(client.clone(), "utxos_up_to_4y_old".to_string()), - _5m: UpTo1dPattern::new(client.clone(), "utxos_up_to_5m_old".to_string()), - _5y: UpTo1dPattern::new(client.clone(), "utxos_up_to_5y_old".to_string()), - _6m: UpTo1dPattern::new(client.clone(), "utxos_up_to_6m_old".to_string()), - _6y: UpTo1dPattern::new(client.clone(), "utxos_up_to_6y_old".to_string()), - _7y: UpTo1dPattern::new(client.clone(), "utxos_up_to_7y_old".to_string()), - _8y: UpTo1dPattern::new(client.clone(), "utxos_up_to_8y_old".to_string()), + _10y: _10yPattern::new(client.clone(), "utxos_up_to_10y_old".to_string()), + _12y: _10yPattern::new(client.clone(), "utxos_up_to_12y_old".to_string()), + _15y: _10yPattern::new(client.clone(), "utxos_up_to_15y_old".to_string()), + _1m: _10yPattern::new(client.clone(), "utxos_up_to_1m_old".to_string()), + _1w: _10yPattern::new(client.clone(), "utxos_up_to_1w_old".to_string()), + _1y: _10yPattern::new(client.clone(), "utxos_up_to_1y_old".to_string()), + _2m: _10yPattern::new(client.clone(), "utxos_up_to_2m_old".to_string()), + _2y: _10yPattern::new(client.clone(), "utxos_up_to_2y_old".to_string()), + _3m: _10yPattern::new(client.clone(), "utxos_up_to_3m_old".to_string()), + _3y: _10yPattern::new(client.clone(), "utxos_up_to_3y_old".to_string()), + _4m: _10yPattern::new(client.clone(), "utxos_up_to_4m_old".to_string()), + _4y: _10yPattern::new(client.clone(), "utxos_up_to_4y_old".to_string()), + _5m: _10yPattern::new(client.clone(), "utxos_up_to_5m_old".to_string()), + _5y: _10yPattern::new(client.clone(), "utxos_up_to_5y_old".to_string()), + _6m: _10yPattern::new(client.clone(), "utxos_up_to_6m_old".to_string()), + _6y: _10yPattern::new(client.clone(), "utxos_up_to_6y_old".to_string()), + _7y: _10yPattern::new(client.clone(), "utxos_up_to_7y_old".to_string()), + _8y: _10yPattern::new(client.clone(), "utxos_up_to_8y_old".to_string()), } } } /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_UtxoCohorts_MinAge { - pub _10y: _10yTo12yPattern, - pub _12y: _10yTo12yPattern, - pub _1d: _10yTo12yPattern, - pub _1m: _10yTo12yPattern, - pub _1w: _10yTo12yPattern, - pub _1y: _10yTo12yPattern, - pub _2m: _10yTo12yPattern, - pub _2y: _10yTo12yPattern, - pub _3m: _10yTo12yPattern, - pub _3y: _10yTo12yPattern, - pub _4m: _10yTo12yPattern, - pub _4y: _10yTo12yPattern, - pub _5m: _10yTo12yPattern, - pub _5y: _10yTo12yPattern, - pub _6m: _10yTo12yPattern, - pub _6y: _10yTo12yPattern, - pub _7y: _10yTo12yPattern, - pub _8y: _10yTo12yPattern, + 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, } impl CatalogTree_Computed_Distribution_UtxoCohorts_MinAge { pub fn new(client: Arc, base_path: String) -> Self { Self { - _10y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_10y_old".to_string()), - _12y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_12y_old".to_string()), - _1d: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1d_old".to_string()), - _1m: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1m_old".to_string()), - _1w: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1w_old".to_string()), - _1y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_1y_old".to_string()), - _2m: _10yTo12yPattern::new(client.clone(), "utxos_at_least_2m_old".to_string()), - _2y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_2y_old".to_string()), - _3m: _10yTo12yPattern::new(client.clone(), "utxos_at_least_3m_old".to_string()), - _3y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_3y_old".to_string()), - _4m: _10yTo12yPattern::new(client.clone(), "utxos_at_least_4m_old".to_string()), - _4y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_4y_old".to_string()), - _5m: _10yTo12yPattern::new(client.clone(), "utxos_at_least_5m_old".to_string()), - _5y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_5y_old".to_string()), - _6m: _10yTo12yPattern::new(client.clone(), "utxos_at_least_6m_old".to_string()), - _6y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_6y_old".to_string()), - _7y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_7y_old".to_string()), - _8y: _10yTo12yPattern::new(client.clone(), "utxos_at_least_8y_old".to_string()), + _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()), } } } @@ -5470,47 +5411,47 @@ impl CatalogTree_Computed_Distribution_UtxoCohorts_Type { /// Catalog tree node. pub struct CatalogTree_Computed_Distribution_UtxoCohorts_Year { - pub _2009: _10yTo12yPattern, - pub _2010: _10yTo12yPattern, - pub _2011: _10yTo12yPattern, - pub _2012: _10yTo12yPattern, - pub _2013: _10yTo12yPattern, - pub _2014: _10yTo12yPattern, - pub _2015: _10yTo12yPattern, - pub _2016: _10yTo12yPattern, - pub _2017: _10yTo12yPattern, - pub _2018: _10yTo12yPattern, - pub _2019: _10yTo12yPattern, - pub _2020: _10yTo12yPattern, - pub _2021: _10yTo12yPattern, - pub _2022: _10yTo12yPattern, - pub _2023: _10yTo12yPattern, - pub _2024: _10yTo12yPattern, - pub _2025: _10yTo12yPattern, - pub _2026: _10yTo12yPattern, + pub _2009: _0satsPattern2, + pub _2010: _0satsPattern2, + pub _2011: _0satsPattern2, + pub _2012: _0satsPattern2, + pub _2013: _0satsPattern2, + pub _2014: _0satsPattern2, + pub _2015: _0satsPattern2, + pub _2016: _0satsPattern2, + pub _2017: _0satsPattern2, + pub _2018: _0satsPattern2, + pub _2019: _0satsPattern2, + pub _2020: _0satsPattern2, + pub _2021: _0satsPattern2, + pub _2022: _0satsPattern2, + pub _2023: _0satsPattern2, + pub _2024: _0satsPattern2, + pub _2025: _0satsPattern2, + pub _2026: _0satsPattern2, } impl CatalogTree_Computed_Distribution_UtxoCohorts_Year { pub fn new(client: Arc, base_path: String) -> Self { Self { - _2009: _10yTo12yPattern::new(client.clone(), "year_2009".to_string()), - _2010: _10yTo12yPattern::new(client.clone(), "year_2010".to_string()), - _2011: _10yTo12yPattern::new(client.clone(), "year_2011".to_string()), - _2012: _10yTo12yPattern::new(client.clone(), "year_2012".to_string()), - _2013: _10yTo12yPattern::new(client.clone(), "year_2013".to_string()), - _2014: _10yTo12yPattern::new(client.clone(), "year_2014".to_string()), - _2015: _10yTo12yPattern::new(client.clone(), "year_2015".to_string()), - _2016: _10yTo12yPattern::new(client.clone(), "year_2016".to_string()), - _2017: _10yTo12yPattern::new(client.clone(), "year_2017".to_string()), - _2018: _10yTo12yPattern::new(client.clone(), "year_2018".to_string()), - _2019: _10yTo12yPattern::new(client.clone(), "year_2019".to_string()), - _2020: _10yTo12yPattern::new(client.clone(), "year_2020".to_string()), - _2021: _10yTo12yPattern::new(client.clone(), "year_2021".to_string()), - _2022: _10yTo12yPattern::new(client.clone(), "year_2022".to_string()), - _2023: _10yTo12yPattern::new(client.clone(), "year_2023".to_string()), - _2024: _10yTo12yPattern::new(client.clone(), "year_2024".to_string()), - _2025: _10yTo12yPattern::new(client.clone(), "year_2025".to_string()), - _2026: _10yTo12yPattern::new(client.clone(), "year_2026".to_string()), + _2009: _0satsPattern2::new(client.clone(), "year_2009".to_string()), + _2010: _0satsPattern2::new(client.clone(), "year_2010".to_string()), + _2011: _0satsPattern2::new(client.clone(), "year_2011".to_string()), + _2012: _0satsPattern2::new(client.clone(), "year_2012".to_string()), + _2013: _0satsPattern2::new(client.clone(), "year_2013".to_string()), + _2014: _0satsPattern2::new(client.clone(), "year_2014".to_string()), + _2015: _0satsPattern2::new(client.clone(), "year_2015".to_string()), + _2016: _0satsPattern2::new(client.clone(), "year_2016".to_string()), + _2017: _0satsPattern2::new(client.clone(), "year_2017".to_string()), + _2018: _0satsPattern2::new(client.clone(), "year_2018".to_string()), + _2019: _0satsPattern2::new(client.clone(), "year_2019".to_string()), + _2020: _0satsPattern2::new(client.clone(), "year_2020".to_string()), + _2021: _0satsPattern2::new(client.clone(), "year_2021".to_string()), + _2022: _0satsPattern2::new(client.clone(), "year_2022".to_string()), + _2023: _0satsPattern2::new(client.clone(), "year_2023".to_string()), + _2024: _0satsPattern2::new(client.clone(), "year_2024".to_string()), + _2025: _0satsPattern2::new(client.clone(), "year_2025".to_string()), + _2026: _0satsPattern2::new(client.clone(), "year_2026".to_string()), } } } @@ -5537,34 +5478,34 @@ impl CatalogTree_Computed_Indexes { /// Catalog tree node. pub struct CatalogTree_Computed_Indexes_Address { pub emptyoutputindex: MetricPattern24, - pub opreturnindex: MetricPattern28, - pub p2aaddressindex: MetricPattern30, - pub p2msoutputindex: MetricPattern31, - pub p2pk33addressindex: MetricPattern32, - pub p2pk65addressindex: MetricPattern33, - pub p2pkhaddressindex: MetricPattern34, - pub p2shaddressindex: MetricPattern35, - pub p2traddressindex: MetricPattern36, - pub p2wpkhaddressindex: MetricPattern37, - pub p2wshaddressindex: MetricPattern38, - pub unknownoutputindex: MetricPattern42, + pub opreturnindex: MetricPattern27, + pub p2aaddressindex: MetricPattern29, + pub p2msoutputindex: MetricPattern30, + pub p2pk33addressindex: MetricPattern31, + pub p2pk65addressindex: MetricPattern32, + pub p2pkhaddressindex: MetricPattern33, + pub p2shaddressindex: MetricPattern34, + pub p2traddressindex: MetricPattern35, + pub p2wpkhaddressindex: MetricPattern36, + pub p2wshaddressindex: MetricPattern37, + pub unknownoutputindex: MetricPattern39, } impl CatalogTree_Computed_Indexes_Address { pub fn new(client: Arc, base_path: String) -> Self { Self { emptyoutputindex: MetricPattern24::new(client.clone(), format!("{base_path}_emptyoutputindex")), - opreturnindex: MetricPattern28::new(client.clone(), format!("{base_path}_opreturnindex")), - p2aaddressindex: MetricPattern30::new(client.clone(), format!("{base_path}_p2aaddressindex")), - p2msoutputindex: MetricPattern31::new(client.clone(), format!("{base_path}_p2msoutputindex")), - p2pk33addressindex: MetricPattern32::new(client.clone(), format!("{base_path}_p2pk33addressindex")), - p2pk65addressindex: MetricPattern33::new(client.clone(), format!("{base_path}_p2pk65addressindex")), - p2pkhaddressindex: MetricPattern34::new(client.clone(), format!("{base_path}_p2pkhaddressindex")), - p2shaddressindex: MetricPattern35::new(client.clone(), format!("{base_path}_p2shaddressindex")), - p2traddressindex: MetricPattern36::new(client.clone(), format!("{base_path}_p2traddressindex")), - p2wpkhaddressindex: MetricPattern37::new(client.clone(), format!("{base_path}_p2wpkhaddressindex")), - p2wshaddressindex: MetricPattern38::new(client.clone(), format!("{base_path}_p2wshaddressindex")), - unknownoutputindex: MetricPattern42::new(client.clone(), format!("{base_path}_unknownoutputindex")), + opreturnindex: MetricPattern27::new(client.clone(), format!("{base_path}_opreturnindex")), + p2aaddressindex: MetricPattern29::new(client.clone(), format!("{base_path}_p2aaddressindex")), + p2msoutputindex: MetricPattern30::new(client.clone(), format!("{base_path}_p2msoutputindex")), + p2pk33addressindex: MetricPattern31::new(client.clone(), format!("{base_path}_p2pk33addressindex")), + p2pk65addressindex: MetricPattern32::new(client.clone(), format!("{base_path}_p2pk65addressindex")), + p2pkhaddressindex: MetricPattern33::new(client.clone(), format!("{base_path}_p2pkhaddressindex")), + p2shaddressindex: MetricPattern34::new(client.clone(), format!("{base_path}_p2shaddressindex")), + p2traddressindex: MetricPattern35::new(client.clone(), format!("{base_path}_p2traddressindex")), + p2wpkhaddressindex: MetricPattern36::new(client.clone(), format!("{base_path}_p2wpkhaddressindex")), + p2wshaddressindex: MetricPattern37::new(client.clone(), format!("{base_path}_p2wshaddressindex")), + unknownoutputindex: MetricPattern39::new(client.clone(), format!("{base_path}_unknownoutputindex")), } } } @@ -5639,21 +5580,21 @@ impl CatalogTree_Computed_Indexes_Time { /// Catalog tree node. pub struct CatalogTree_Computed_Indexes_Transaction { - pub input_count: MetricPattern41, - pub output_count: MetricPattern41, - pub txindex: MetricPattern41, + pub input_count: MetricPattern38, + pub output_count: MetricPattern38, + pub txindex: MetricPattern38, pub txinindex: MetricPattern26, - pub txoutindex: MetricPattern29, + pub txoutindex: MetricPattern28, } impl CatalogTree_Computed_Indexes_Transaction { pub fn new(client: Arc, base_path: String) -> Self { Self { - input_count: MetricPattern41::new(client.clone(), format!("{base_path}_input_count")), - output_count: MetricPattern41::new(client.clone(), format!("{base_path}_output_count")), - txindex: MetricPattern41::new(client.clone(), format!("{base_path}_txindex")), + input_count: MetricPattern38::new(client.clone(), format!("{base_path}_input_count")), + output_count: MetricPattern38::new(client.clone(), format!("{base_path}_output_count")), + txindex: MetricPattern38::new(client.clone(), format!("{base_path}_txindex")), txinindex: MetricPattern26::new(client.clone(), format!("{base_path}_txinindex")), - txoutindex: MetricPattern29::new(client.clone(), format!("{base_path}_txoutindex")), + txoutindex: MetricPattern28::new(client.clone(), format!("{base_path}_txoutindex")), } } } @@ -5751,163 +5692,60 @@ impl CatalogTree_Computed_Market_Ath { /// Catalog tree node. pub struct CatalogTree_Computed_Market_Dca { - pub _10y_dca_avg_price: MetricPattern4, - pub _10y_dca_cagr: MetricPattern4, - pub _10y_dca_returns: MetricPattern4, - pub _10y_dca_stack: MetricPattern4, - pub _1m_dca_avg_price: MetricPattern4, - pub _1m_dca_returns: MetricPattern4, - pub _1m_dca_stack: MetricPattern4, - pub _1w_dca_avg_price: MetricPattern4, - pub _1w_dca_returns: MetricPattern4, - pub _1w_dca_stack: MetricPattern4, - pub _1y_dca_avg_price: MetricPattern4, - pub _1y_dca_returns: MetricPattern4, - pub _1y_dca_stack: MetricPattern4, - pub _2y_dca_avg_price: MetricPattern4, - pub _2y_dca_cagr: MetricPattern4, - pub _2y_dca_returns: MetricPattern4, - pub _2y_dca_stack: MetricPattern4, - pub _3m_dca_avg_price: MetricPattern4, - pub _3m_dca_returns: MetricPattern4, - pub _3m_dca_stack: MetricPattern4, - pub _3y_dca_avg_price: MetricPattern4, - pub _3y_dca_cagr: MetricPattern4, - pub _3y_dca_returns: MetricPattern4, - pub _3y_dca_stack: MetricPattern4, - pub _4y_dca_avg_price: MetricPattern4, - pub _4y_dca_cagr: MetricPattern4, - pub _4y_dca_returns: MetricPattern4, - pub _4y_dca_stack: MetricPattern4, - pub _5y_dca_avg_price: MetricPattern4, - pub _5y_dca_cagr: MetricPattern4, - pub _5y_dca_returns: MetricPattern4, - pub _5y_dca_stack: MetricPattern4, - pub _6m_dca_avg_price: MetricPattern4, - pub _6m_dca_returns: MetricPattern4, - pub _6m_dca_stack: MetricPattern4, - pub _6y_dca_avg_price: MetricPattern4, - pub _6y_dca_cagr: MetricPattern4, - pub _6y_dca_returns: MetricPattern4, - pub _6y_dca_stack: MetricPattern4, - pub _8y_dca_avg_price: MetricPattern4, - pub _8y_dca_cagr: MetricPattern4, - pub _8y_dca_returns: MetricPattern4, - pub _8y_dca_stack: MetricPattern4, - pub dca_class_2015_avg_price: MetricPattern4, - pub dca_class_2015_returns: MetricPattern4, - pub dca_class_2015_stack: MetricPattern4, - pub dca_class_2016_avg_price: MetricPattern4, - pub dca_class_2016_returns: MetricPattern4, - pub dca_class_2016_stack: MetricPattern4, - pub dca_class_2017_avg_price: MetricPattern4, - pub dca_class_2017_returns: MetricPattern4, - pub dca_class_2017_stack: MetricPattern4, - pub dca_class_2018_avg_price: MetricPattern4, - pub dca_class_2018_returns: MetricPattern4, - pub dca_class_2018_stack: MetricPattern4, - pub dca_class_2019_avg_price: MetricPattern4, - pub dca_class_2019_returns: MetricPattern4, - pub dca_class_2019_stack: MetricPattern4, - pub dca_class_2020_avg_price: MetricPattern4, - pub dca_class_2020_returns: MetricPattern4, - pub dca_class_2020_stack: MetricPattern4, - pub dca_class_2021_avg_price: MetricPattern4, - pub dca_class_2021_returns: MetricPattern4, - pub dca_class_2021_stack: MetricPattern4, - pub dca_class_2022_avg_price: MetricPattern4, - pub dca_class_2022_returns: MetricPattern4, - pub dca_class_2022_stack: MetricPattern4, - pub dca_class_2023_avg_price: MetricPattern4, - pub dca_class_2023_returns: MetricPattern4, - pub dca_class_2023_stack: MetricPattern4, - pub dca_class_2024_avg_price: MetricPattern4, - pub dca_class_2024_returns: MetricPattern4, - pub dca_class_2024_stack: MetricPattern4, - pub dca_class_2025_avg_price: MetricPattern4, - pub dca_class_2025_returns: MetricPattern4, - pub dca_class_2025_stack: MetricPattern4, + pub class_avg_price: ClassAvgPricePattern, + pub class_returns: ClassAvgPricePattern, + pub class_stack: CatalogTree_Computed_Market_Dca_ClassStack, + pub period_avg_price: PeriodAvgPricePattern, + pub period_cagr: PeriodCagrPattern, + pub period_lump_sum_stack: PeriodLumpSumStackPattern, + pub period_returns: PeriodAvgPricePattern, + pub period_stack: PeriodLumpSumStackPattern, } impl CatalogTree_Computed_Market_Dca { pub fn new(client: Arc, base_path: String) -> Self { Self { - _10y_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_10y_dca_avg_price")), - _10y_dca_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_10y_dca_cagr")), - _10y_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_10y_dca_returns")), - _10y_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_10y_dca_stack")), - _1m_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_1m_dca_avg_price")), - _1m_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_1m_dca_returns")), - _1m_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_1m_dca_stack")), - _1w_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_1w_dca_avg_price")), - _1w_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_1w_dca_returns")), - _1w_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_1w_dca_stack")), - _1y_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_1y_dca_avg_price")), - _1y_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_1y_dca_returns")), - _1y_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_1y_dca_stack")), - _2y_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_2y_dca_avg_price")), - _2y_dca_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_2y_dca_cagr")), - _2y_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_2y_dca_returns")), - _2y_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_2y_dca_stack")), - _3m_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_3m_dca_avg_price")), - _3m_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_3m_dca_returns")), - _3m_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_3m_dca_stack")), - _3y_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_3y_dca_avg_price")), - _3y_dca_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_3y_dca_cagr")), - _3y_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_3y_dca_returns")), - _3y_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_3y_dca_stack")), - _4y_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_4y_dca_avg_price")), - _4y_dca_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_4y_dca_cagr")), - _4y_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_4y_dca_returns")), - _4y_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_4y_dca_stack")), - _5y_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_5y_dca_avg_price")), - _5y_dca_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_5y_dca_cagr")), - _5y_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_5y_dca_returns")), - _5y_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_5y_dca_stack")), - _6m_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_6m_dca_avg_price")), - _6m_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_6m_dca_returns")), - _6m_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_6m_dca_stack")), - _6y_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_6y_dca_avg_price")), - _6y_dca_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_6y_dca_cagr")), - _6y_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_6y_dca_returns")), - _6y_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_6y_dca_stack")), - _8y_dca_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_8y_dca_avg_price")), - _8y_dca_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_8y_dca_cagr")), - _8y_dca_returns: MetricPattern4::new(client.clone(), format!("{base_path}_8y_dca_returns")), - _8y_dca_stack: MetricPattern4::new(client.clone(), format!("{base_path}_8y_dca_stack")), - dca_class_2015_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2015_avg_price")), - dca_class_2015_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2015_returns")), - dca_class_2015_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2015_stack")), - dca_class_2016_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2016_avg_price")), - dca_class_2016_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2016_returns")), - dca_class_2016_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2016_stack")), - dca_class_2017_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2017_avg_price")), - dca_class_2017_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2017_returns")), - dca_class_2017_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2017_stack")), - dca_class_2018_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2018_avg_price")), - dca_class_2018_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2018_returns")), - dca_class_2018_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2018_stack")), - dca_class_2019_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2019_avg_price")), - dca_class_2019_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2019_returns")), - dca_class_2019_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2019_stack")), - dca_class_2020_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2020_avg_price")), - dca_class_2020_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2020_returns")), - dca_class_2020_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2020_stack")), - dca_class_2021_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2021_avg_price")), - dca_class_2021_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2021_returns")), - dca_class_2021_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2021_stack")), - dca_class_2022_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2022_avg_price")), - dca_class_2022_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2022_returns")), - dca_class_2022_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2022_stack")), - dca_class_2023_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2023_avg_price")), - dca_class_2023_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2023_returns")), - dca_class_2023_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2023_stack")), - dca_class_2024_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2024_avg_price")), - dca_class_2024_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2024_returns")), - dca_class_2024_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2024_stack")), - dca_class_2025_avg_price: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2025_avg_price")), - dca_class_2025_returns: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2025_returns")), - dca_class_2025_stack: MetricPattern4::new(client.clone(), format!("{base_path}_dca_class_2025_stack")), + class_avg_price: ClassAvgPricePattern::new(client.clone(), "dca_class".to_string()), + class_returns: ClassAvgPricePattern::new(client.clone(), "dca_class".to_string()), + class_stack: CatalogTree_Computed_Market_Dca_ClassStack::new(client.clone(), format!("{base_path}_class_stack")), + period_avg_price: PeriodAvgPricePattern::new(client.clone(), "dca_avg_price".to_string()), + period_cagr: PeriodCagrPattern::new(client.clone(), "dca_cagr".to_string()), + period_lump_sum_stack: PeriodLumpSumStackPattern::new(client.clone(), "".to_string()), + period_returns: PeriodAvgPricePattern::new(client.clone(), "dca_returns".to_string()), + period_stack: PeriodLumpSumStackPattern::new(client.clone(), "".to_string()), + } + } +} + +/// Catalog tree node. +pub struct CatalogTree_Computed_Market_Dca_ClassStack { + pub _2015: ActiveSupplyPattern, + pub _2016: ActiveSupplyPattern, + pub _2017: ActiveSupplyPattern, + pub _2018: ActiveSupplyPattern, + pub _2019: ActiveSupplyPattern, + pub _2020: ActiveSupplyPattern, + pub _2021: ActiveSupplyPattern, + pub _2022: ActiveSupplyPattern, + pub _2023: ActiveSupplyPattern, + pub _2024: ActiveSupplyPattern, + pub _2025: ActiveSupplyPattern, +} + +impl CatalogTree_Computed_Market_Dca_ClassStack { + pub fn new(client: Arc, base_path: String) -> Self { + Self { + _2015: ActiveSupplyPattern::new(client.clone(), "dca_class_2015_stack".to_string()), + _2016: ActiveSupplyPattern::new(client.clone(), "dca_class_2016_stack".to_string()), + _2017: ActiveSupplyPattern::new(client.clone(), "dca_class_2017_stack".to_string()), + _2018: ActiveSupplyPattern::new(client.clone(), "dca_class_2018_stack".to_string()), + _2019: ActiveSupplyPattern::new(client.clone(), "dca_class_2019_stack".to_string()), + _2020: ActiveSupplyPattern::new(client.clone(), "dca_class_2020_stack".to_string()), + _2021: ActiveSupplyPattern::new(client.clone(), "dca_class_2021_stack".to_string()), + _2022: ActiveSupplyPattern::new(client.clone(), "dca_class_2022_stack".to_string()), + _2023: ActiveSupplyPattern::new(client.clone(), "dca_class_2023_stack".to_string()), + _2024: ActiveSupplyPattern::new(client.clone(), "dca_class_2024_stack".to_string()), + _2025: ActiveSupplyPattern::new(client.clone(), "dca_class_2025_stack".to_string()), } } } @@ -5963,37 +5801,13 @@ impl CatalogTree_Computed_Market_Indicators { /// Catalog tree node. pub struct CatalogTree_Computed_Market_Lookback { - pub price_10y_ago: MetricPattern4, - pub price_1d_ago: MetricPattern4, - pub price_1m_ago: MetricPattern4, - pub price_1w_ago: MetricPattern4, - pub price_1y_ago: MetricPattern4, - pub price_2y_ago: MetricPattern4, - pub price_3m_ago: MetricPattern4, - pub price_3y_ago: MetricPattern4, - pub price_4y_ago: MetricPattern4, - pub price_5y_ago: MetricPattern4, - pub price_6m_ago: MetricPattern4, - pub price_6y_ago: MetricPattern4, - pub price_8y_ago: MetricPattern4, + pub price_ago: PriceAgoPattern, } impl CatalogTree_Computed_Market_Lookback { pub fn new(client: Arc, base_path: String) -> Self { Self { - price_10y_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_10y_ago")), - price_1d_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_1d_ago")), - price_1m_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_1m_ago")), - price_1w_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_1w_ago")), - price_1y_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_1y_ago")), - price_2y_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_2y_ago")), - price_3m_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_3m_ago")), - price_3y_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_3y_ago")), - price_4y_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_4y_ago")), - price_5y_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_5y_ago")), - price_6m_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_6m_ago")), - price_6y_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_6y_ago")), - price_8y_ago: MetricPattern4::new(client.clone(), format!("{base_path}_price_8y_ago")), + price_ago: PriceAgoPattern::new(client.clone(), "price".to_string()), } } } @@ -6117,30 +5931,12 @@ pub struct CatalogTree_Computed_Market_Returns { pub _1d_returns_1m_sd: _1dReturns1mSdPattern, pub _1d_returns_1w_sd: _1dReturns1mSdPattern, pub _1d_returns_1y_sd: _1dReturns1mSdPattern, - pub _10y_cagr: MetricPattern4, - pub _10y_price_returns: MetricPattern4, - pub _1d_price_returns: MetricPattern4, - pub _1m_price_returns: MetricPattern4, - pub _1w_price_returns: MetricPattern4, - pub _1y_price_returns: MetricPattern4, - pub _2y_cagr: MetricPattern4, - pub _2y_price_returns: MetricPattern4, - pub _3m_price_returns: MetricPattern4, - pub _3y_cagr: MetricPattern4, - pub _3y_price_returns: MetricPattern4, - pub _4y_cagr: MetricPattern4, - pub _4y_price_returns: MetricPattern4, - pub _5y_cagr: MetricPattern4, - pub _5y_price_returns: MetricPattern4, - pub _6m_price_returns: MetricPattern4, - pub _6y_cagr: MetricPattern4, - pub _6y_price_returns: MetricPattern4, - pub _8y_cagr: MetricPattern4, - pub _8y_price_returns: MetricPattern4, + pub cagr: PeriodCagrPattern, pub downside_1m_sd: _1dReturns1mSdPattern, pub downside_1w_sd: _1dReturns1mSdPattern, pub downside_1y_sd: _1dReturns1mSdPattern, pub downside_returns: MetricPattern21, + pub price_returns: PriceAgoPattern, } impl CatalogTree_Computed_Market_Returns { @@ -6149,30 +5945,12 @@ impl CatalogTree_Computed_Market_Returns { _1d_returns_1m_sd: _1dReturns1mSdPattern::new(client.clone(), "1d_returns_1m_sd".to_string()), _1d_returns_1w_sd: _1dReturns1mSdPattern::new(client.clone(), "1d_returns_1w_sd".to_string()), _1d_returns_1y_sd: _1dReturns1mSdPattern::new(client.clone(), "1d_returns_1y_sd".to_string()), - _10y_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_10y_cagr")), - _10y_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_10y_price_returns")), - _1d_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_1d_price_returns")), - _1m_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_1m_price_returns")), - _1w_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_1w_price_returns")), - _1y_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_1y_price_returns")), - _2y_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_2y_cagr")), - _2y_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_2y_price_returns")), - _3m_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_3m_price_returns")), - _3y_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_3y_cagr")), - _3y_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_3y_price_returns")), - _4y_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_4y_cagr")), - _4y_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_4y_price_returns")), - _5y_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_5y_cagr")), - _5y_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_5y_price_returns")), - _6m_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_6m_price_returns")), - _6y_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_6y_cagr")), - _6y_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_6y_price_returns")), - _8y_cagr: MetricPattern4::new(client.clone(), format!("{base_path}_8y_cagr")), - _8y_price_returns: MetricPattern4::new(client.clone(), format!("{base_path}_8y_price_returns")), + cagr: PeriodCagrPattern::new(client.clone(), "cagr".to_string()), downside_1m_sd: _1dReturns1mSdPattern::new(client.clone(), "downside_1m_sd".to_string()), downside_1w_sd: _1dReturns1mSdPattern::new(client.clone(), "downside_1w_sd".to_string()), downside_1y_sd: _1dReturns1mSdPattern::new(client.clone(), "downside_1y_sd".to_string()), downside_returns: MetricPattern21::new(client.clone(), format!("{base_path}_downside_returns")), + price_returns: PriceAgoPattern::new(client.clone(), "price_returns".to_string()), } } } @@ -6238,13 +6016,13 @@ impl CatalogTree_Computed_Outputs_Count { /// Catalog tree node. pub struct CatalogTree_Computed_Outputs_Spent { - pub txinindex: MetricPattern29, + pub txinindex: MetricPattern28, } impl CatalogTree_Computed_Outputs_Spent { pub fn new(client: Arc, base_path: String) -> Self { Self { - txinindex: MetricPattern29::new(client.clone(), format!("{base_path}_txinindex")), + txinindex: MetricPattern28::new(client.clone(), format!("{base_path}_txinindex")), } } } @@ -6914,14 +6692,14 @@ impl CatalogTree_Computed_Transactions { /// Catalog tree node. pub struct CatalogTree_Computed_Transactions_Count { - pub is_coinbase: MetricPattern41, + pub is_coinbase: MetricPattern38, pub tx_count: BitcoinPattern, } impl CatalogTree_Computed_Transactions_Count { pub fn new(client: Arc, base_path: String) -> Self { Self { - is_coinbase: MetricPattern41::new(client.clone(), format!("{base_path}_is_coinbase")), + is_coinbase: MetricPattern38::new(client.clone(), format!("{base_path}_is_coinbase")), tx_count: BitcoinPattern::new(client.clone(), "tx_count".to_string()), } } @@ -6931,8 +6709,8 @@ impl CatalogTree_Computed_Transactions_Count { pub struct CatalogTree_Computed_Transactions_Fees { pub fee: CatalogTree_Computed_Transactions_Fees_Fee, pub fee_rate: CatalogTree_Computed_Transactions_Fees_FeeRate, - pub input_value: MetricPattern41, - pub output_value: MetricPattern41, + pub input_value: MetricPattern38, + pub output_value: MetricPattern38, } impl CatalogTree_Computed_Transactions_Fees { @@ -6940,30 +6718,30 @@ impl CatalogTree_Computed_Transactions_Fees { Self { fee: CatalogTree_Computed_Transactions_Fees_Fee::new(client.clone(), format!("{base_path}_fee")), fee_rate: CatalogTree_Computed_Transactions_Fees_FeeRate::new(client.clone(), format!("{base_path}_fee_rate")), - input_value: MetricPattern41::new(client.clone(), format!("{base_path}_input_value")), - output_value: MetricPattern41::new(client.clone(), format!("{base_path}_output_value")), + input_value: MetricPattern38::new(client.clone(), format!("{base_path}_input_value")), + output_value: MetricPattern38::new(client.clone(), format!("{base_path}_output_value")), } } } /// Catalog tree node. pub struct CatalogTree_Computed_Transactions_Fees_Fee { - pub base: MetricPattern41, + pub base: MetricPattern38, pub bitcoin: BlockSizePattern, - pub bitcoin_txindex: MetricPattern41, + pub bitcoin_txindex: MetricPattern38, pub dollars: BlockSizePattern, - pub dollars_txindex: MetricPattern41, + pub dollars_txindex: MetricPattern38, pub sats: BlockSizePattern, } impl CatalogTree_Computed_Transactions_Fees_Fee { pub fn new(client: Arc, base_path: String) -> Self { Self { - base: MetricPattern41::new(client.clone(), format!("{base_path}_base")), + base: MetricPattern38::new(client.clone(), format!("{base_path}_base")), bitcoin: BlockSizePattern::new(client.clone(), "fee_btc".to_string()), - bitcoin_txindex: MetricPattern41::new(client.clone(), format!("{base_path}_bitcoin_txindex")), + bitcoin_txindex: MetricPattern38::new(client.clone(), format!("{base_path}_bitcoin_txindex")), dollars: BlockSizePattern::new(client.clone(), "fee_usd".to_string()), - dollars_txindex: MetricPattern41::new(client.clone(), format!("{base_path}_dollars_txindex")), + dollars_txindex: MetricPattern38::new(client.clone(), format!("{base_path}_dollars_txindex")), sats: BlockSizePattern::new(client.clone(), "fee".to_string()), } } @@ -6972,7 +6750,7 @@ impl CatalogTree_Computed_Transactions_Fees_Fee { /// Catalog tree node. pub struct CatalogTree_Computed_Transactions_Fees_FeeRate { pub average: MetricPattern1, - pub base: MetricPattern41, + pub base: MetricPattern38, pub max: MetricPattern1, pub median: MetricPattern25, pub min: MetricPattern1, @@ -6986,7 +6764,7 @@ impl CatalogTree_Computed_Transactions_Fees_FeeRate { pub fn new(client: Arc, base_path: String) -> Self { Self { average: MetricPattern1::new(client.clone(), format!("{base_path}_average")), - base: MetricPattern41::new(client.clone(), format!("{base_path}_base")), + base: MetricPattern38::new(client.clone(), format!("{base_path}_base")), max: MetricPattern1::new(client.clone(), format!("{base_path}_max")), median: MetricPattern25::new(client.clone(), format!("{base_path}_median")), min: MetricPattern1::new(client.clone(), format!("{base_path}_min")), @@ -7002,8 +6780,8 @@ impl CatalogTree_Computed_Transactions_Fees_FeeRate { pub struct CatalogTree_Computed_Transactions_Size { pub tx_vsize: BlockIntervalPattern, pub tx_weight: BlockIntervalPattern, - pub vsize: MetricPattern41, - pub weight: MetricPattern41, + pub vsize: MetricPattern38, + pub weight: MetricPattern38, } impl CatalogTree_Computed_Transactions_Size { @@ -7011,8 +6789,8 @@ impl CatalogTree_Computed_Transactions_Size { Self { tx_vsize: BlockIntervalPattern::new(client.clone(), "tx_vsize".to_string()), tx_weight: BlockIntervalPattern::new(client.clone(), "tx_weight".to_string()), - vsize: MetricPattern41::new(client.clone(), format!("{base_path}_vsize")), - weight: MetricPattern41::new(client.clone(), format!("{base_path}_weight")), + vsize: MetricPattern38::new(client.clone(), format!("{base_path}_vsize")), + weight: MetricPattern38::new(client.clone(), format!("{base_path}_weight")), } } } @@ -7109,14 +6887,14 @@ pub struct CatalogTree_Indexed_Address { pub first_p2traddressindex: MetricPattern25, pub first_p2wpkhaddressindex: MetricPattern25, pub first_p2wshaddressindex: MetricPattern25, - pub p2abytes: MetricPattern30, - pub p2pk33bytes: MetricPattern32, - pub p2pk65bytes: MetricPattern33, - pub p2pkhbytes: MetricPattern34, - pub p2shbytes: MetricPattern35, - pub p2trbytes: MetricPattern36, - pub p2wpkhbytes: MetricPattern37, - pub p2wshbytes: MetricPattern38, + pub p2abytes: MetricPattern29, + pub p2pk33bytes: MetricPattern31, + pub p2pk65bytes: MetricPattern32, + pub p2pkhbytes: MetricPattern33, + pub p2shbytes: MetricPattern34, + pub p2trbytes: MetricPattern35, + pub p2wpkhbytes: MetricPattern36, + pub p2wshbytes: MetricPattern37, } impl CatalogTree_Indexed_Address { @@ -7130,14 +6908,14 @@ impl CatalogTree_Indexed_Address { first_p2traddressindex: MetricPattern25::new(client.clone(), format!("{base_path}_first_p2traddressindex")), first_p2wpkhaddressindex: MetricPattern25::new(client.clone(), format!("{base_path}_first_p2wpkhaddressindex")), first_p2wshaddressindex: MetricPattern25::new(client.clone(), format!("{base_path}_first_p2wshaddressindex")), - p2abytes: MetricPattern30::new(client.clone(), format!("{base_path}_p2abytes")), - p2pk33bytes: MetricPattern32::new(client.clone(), format!("{base_path}_p2pk33bytes")), - p2pk65bytes: MetricPattern33::new(client.clone(), format!("{base_path}_p2pk65bytes")), - p2pkhbytes: MetricPattern34::new(client.clone(), format!("{base_path}_p2pkhbytes")), - p2shbytes: MetricPattern35::new(client.clone(), format!("{base_path}_p2shbytes")), - p2trbytes: MetricPattern36::new(client.clone(), format!("{base_path}_p2trbytes")), - p2wpkhbytes: MetricPattern37::new(client.clone(), format!("{base_path}_p2wpkhbytes")), - p2wshbytes: MetricPattern38::new(client.clone(), format!("{base_path}_p2wshbytes")), + p2abytes: MetricPattern29::new(client.clone(), format!("{base_path}_p2abytes")), + p2pk33bytes: MetricPattern31::new(client.clone(), format!("{base_path}_p2pk33bytes")), + p2pk65bytes: MetricPattern32::new(client.clone(), format!("{base_path}_p2pk65bytes")), + p2pkhbytes: MetricPattern33::new(client.clone(), format!("{base_path}_p2pkhbytes")), + p2shbytes: MetricPattern34::new(client.clone(), format!("{base_path}_p2shbytes")), + p2trbytes: MetricPattern35::new(client.clone(), format!("{base_path}_p2trbytes")), + p2wpkhbytes: MetricPattern36::new(client.clone(), format!("{base_path}_p2wpkhbytes")), + p2wshbytes: MetricPattern37::new(client.clone(), format!("{base_path}_p2wshbytes")), } } } @@ -7186,31 +6964,31 @@ impl CatalogTree_Indexed_Output { /// Catalog tree node. pub struct CatalogTree_Indexed_Tx { - pub base_size: MetricPattern41, + pub base_size: MetricPattern38, pub first_txindex: MetricPattern25, - pub first_txinindex: MetricPattern41, - pub first_txoutindex: MetricPattern41, - pub height: MetricPattern41, - pub is_explicitly_rbf: MetricPattern41, - pub rawlocktime: MetricPattern41, - pub total_size: MetricPattern41, - pub txid: MetricPattern41, - pub txversion: MetricPattern41, + pub first_txinindex: MetricPattern38, + pub first_txoutindex: MetricPattern38, + pub height: MetricPattern38, + pub is_explicitly_rbf: MetricPattern38, + pub rawlocktime: MetricPattern38, + pub total_size: MetricPattern38, + pub txid: MetricPattern38, + pub txversion: MetricPattern38, } impl CatalogTree_Indexed_Tx { pub fn new(client: Arc, base_path: String) -> Self { Self { - base_size: MetricPattern41::new(client.clone(), format!("{base_path}_base_size")), + base_size: MetricPattern38::new(client.clone(), format!("{base_path}_base_size")), first_txindex: MetricPattern25::new(client.clone(), format!("{base_path}_first_txindex")), - first_txinindex: MetricPattern41::new(client.clone(), format!("{base_path}_first_txinindex")), - first_txoutindex: MetricPattern41::new(client.clone(), format!("{base_path}_first_txoutindex")), - height: MetricPattern41::new(client.clone(), format!("{base_path}_height")), - is_explicitly_rbf: MetricPattern41::new(client.clone(), format!("{base_path}_is_explicitly_rbf")), - rawlocktime: MetricPattern41::new(client.clone(), format!("{base_path}_rawlocktime")), - total_size: MetricPattern41::new(client.clone(), format!("{base_path}_total_size")), - txid: MetricPattern41::new(client.clone(), format!("{base_path}_txid")), - txversion: MetricPattern41::new(client.clone(), format!("{base_path}_txversion")), + first_txinindex: MetricPattern38::new(client.clone(), format!("{base_path}_first_txinindex")), + first_txoutindex: MetricPattern38::new(client.clone(), format!("{base_path}_first_txoutindex")), + height: MetricPattern38::new(client.clone(), format!("{base_path}_height")), + is_explicitly_rbf: MetricPattern38::new(client.clone(), format!("{base_path}_is_explicitly_rbf")), + rawlocktime: MetricPattern38::new(client.clone(), format!("{base_path}_rawlocktime")), + total_size: MetricPattern38::new(client.clone(), format!("{base_path}_total_size")), + txid: MetricPattern38::new(client.clone(), format!("{base_path}_txid")), + txversion: MetricPattern38::new(client.clone(), format!("{base_path}_txversion")), } } } @@ -7239,20 +7017,20 @@ impl CatalogTree_Indexed_Txin { /// Catalog tree node. pub struct CatalogTree_Indexed_Txout { pub first_txoutindex: MetricPattern25, - pub outputtype: MetricPattern29, - pub txindex: MetricPattern29, - pub typeindex: MetricPattern29, - pub value: MetricPattern29, + pub outputtype: MetricPattern28, + pub txindex: MetricPattern28, + pub typeindex: MetricPattern28, + pub value: MetricPattern28, } impl CatalogTree_Indexed_Txout { pub fn new(client: Arc, base_path: String) -> Self { Self { first_txoutindex: MetricPattern25::new(client.clone(), format!("{base_path}_first_txoutindex")), - outputtype: MetricPattern29::new(client.clone(), format!("{base_path}_outputtype")), - txindex: MetricPattern29::new(client.clone(), format!("{base_path}_txindex")), - typeindex: MetricPattern29::new(client.clone(), format!("{base_path}_typeindex")), - value: MetricPattern29::new(client.clone(), format!("{base_path}_value")), + outputtype: MetricPattern28::new(client.clone(), format!("{base_path}_outputtype")), + txindex: MetricPattern28::new(client.clone(), format!("{base_path}_txindex")), + typeindex: MetricPattern28::new(client.clone(), format!("{base_path}_typeindex")), + value: MetricPattern28::new(client.clone(), format!("{base_path}_value")), } } } diff --git a/crates/brk_cohort/src/filter.rs b/crates/brk_cohort/src/filter.rs index f266fd0b4..58011ada2 100644 --- a/crates/brk_cohort/src/filter.rs +++ b/crates/brk_cohort/src/filter.rs @@ -68,12 +68,17 @@ impl Filter { } /// Whether to compute extended metrics (realized cap ratios, profit/loss ratios, percentiles) - /// For UTXO context: false for Type and Amount filters + /// For UTXO context: true only for age range cohorts (Range) and aggregate cohorts (All, Term) /// For Address context: always false pub fn is_extended(&self, context: CohortContext) -> bool { match context { CohortContext::Address => false, - CohortContext::Utxo => !matches!(self, Filter::Type(_) | Filter::Amount(_)), + CohortContext::Utxo => { + matches!( + self, + Filter::All | Filter::Term(_) | Filter::Time(TimeFilter::Range(_)) + ) + } } } diff --git a/crates/brk_computer/src/blocks/count/import.rs b/crates/brk_computer/src/blocks/count/import.rs index 0eeeff77e..e51b492db 100644 --- a/crates/brk_computer/src/blocks/count/import.rs +++ b/crates/brk_computer/src/blocks/count/import.rs @@ -14,68 +14,59 @@ use crate::{ }; impl Vecs { - pub fn forced_import( - db: &Database, - version: Version, - indexes: &indexes::Vecs, - ) -> Result { - let v0 = Version::ZERO; + pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result { let last = || VecBuilderOptions::default().add_last(); let sum_cum = || VecBuilderOptions::default().add_sum().add_cumulative(); Ok(Self { dateindex_to_block_count_target: LazyVecFrom1::init( "block_count_target", - version + v0, + version, indexes.time.dateindex_to_dateindex.boxed_clone(), |_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)), ), weekindex_to_block_count_target: LazyVecFrom1::init( "block_count_target", - version + v0, + version, indexes.time.weekindex_to_weekindex.boxed_clone(), |_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)), ), monthindex_to_block_count_target: LazyVecFrom1::init( "block_count_target", - version + v0, + version, indexes.time.monthindex_to_monthindex.boxed_clone(), |_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)), ), quarterindex_to_block_count_target: LazyVecFrom1::init( "block_count_target", - version + v0, + version, indexes.time.quarterindex_to_quarterindex.boxed_clone(), |_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)), ), semesterindex_to_block_count_target: LazyVecFrom1::init( "block_count_target", - version + v0, + version, indexes.time.semesterindex_to_semesterindex.boxed_clone(), |_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)), ), yearindex_to_block_count_target: LazyVecFrom1::init( "block_count_target", - version + v0, + version, indexes.time.yearindex_to_yearindex.boxed_clone(), |_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)), ), decadeindex_to_block_count_target: LazyVecFrom1::init( "block_count_target", - version + v0, + version, indexes.time.decadeindex_to_decadeindex.boxed_clone(), |_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)), ), - height_to_24h_block_count: EagerVec::forced_import( - db, - "24h_block_count", - version + v0, - )?, + height_to_24h_block_count: EagerVec::forced_import(db, "24h_block_count", version)?, indexes_to_block_count: ComputedVecsFromHeight::forced_import( db, "block_count", Source::Compute, - version + v0, + version, indexes, sum_cum(), )?, @@ -83,7 +74,7 @@ impl Vecs { db, "1w_block_count", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -91,7 +82,7 @@ impl Vecs { db, "1m_block_count", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -99,7 +90,7 @@ impl Vecs { db, "1y_block_count", Source::Compute, - version + v0, + version, indexes, last(), )?, diff --git a/crates/brk_computer/src/blocks/difficulty/import.rs b/crates/brk_computer/src/blocks/difficulty/import.rs index 848ccd234..07c50694a 100644 --- a/crates/brk_computer/src/blocks/difficulty/import.rs +++ b/crates/brk_computer/src/blocks/difficulty/import.rs @@ -10,7 +10,6 @@ use crate::{ impl Vecs { pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result { - let v0 = Version::ZERO; let v2 = Version::TWO; let last = || VecBuilderOptions::default().add_last(); @@ -19,7 +18,7 @@ impl Vecs { db, "difficultyepoch", Source::Compute, - version + v0, + version, indexes, last(), )?, diff --git a/crates/brk_computer/src/blocks/halving/import.rs b/crates/brk_computer/src/blocks/halving/import.rs index 5e849dcd1..e84ae82ef 100644 --- a/crates/brk_computer/src/blocks/halving/import.rs +++ b/crates/brk_computer/src/blocks/halving/import.rs @@ -10,7 +10,6 @@ use crate::{ impl Vecs { pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result { - let v0 = Version::ZERO; let v2 = Version::TWO; let last = || VecBuilderOptions::default().add_last(); @@ -19,7 +18,7 @@ impl Vecs { db, "halvingepoch", Source::Compute, - version + v0, + version, indexes, last(), )?, diff --git a/crates/brk_computer/src/blocks/import.rs b/crates/brk_computer/src/blocks/import.rs index d33d3dd56..bfa032a4b 100644 --- a/crates/brk_computer/src/blocks/import.rs +++ b/crates/brk_computer/src/blocks/import.rs @@ -9,8 +9,8 @@ use vecdb::{Database, PAGE_SIZE}; use crate::{indexes, price}; use super::{ - CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, MiningVecs, - RewardsVecs, SizeVecs, TimeVecs, Vecs, WeightVecs, + CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, MiningVecs, RewardsVecs, SizeVecs, + TimeVecs, Vecs, WeightVecs, }; impl Vecs { @@ -24,7 +24,7 @@ impl Vecs { let db = Database::open(&parent_path.join(super::DB_NAME))?; db.set_min_len(PAGE_SIZE * 50_000_000)?; - let version = parent_version + Version::ZERO; + let version = parent_version; let compute_dollars = price.is_some(); let count = CountVecs::forced_import(&db, version, indexes)?; diff --git a/crates/brk_computer/src/blocks/interval/import.rs b/crates/brk_computer/src/blocks/interval/import.rs index 583363e1b..d59207cd2 100644 --- a/crates/brk_computer/src/blocks/interval/import.rs +++ b/crates/brk_computer/src/blocks/interval/import.rs @@ -16,7 +16,6 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, ) -> Result { - let v0 = Version::ZERO; let stats = || { VecBuilderOptions::default() .add_average() @@ -26,7 +25,7 @@ impl Vecs { let height_to_interval = LazyVecFrom1::init( "interval", - version + v0, + version, indexer.vecs.block.height_to_timestamp.boxed_clone(), |height: Height, timestamp_iter| { let timestamp = timestamp_iter.get(height)?; @@ -46,7 +45,7 @@ impl Vecs { db, "block_interval", Source::Vec(height_to_interval.boxed_clone()), - version + v0, + version, indexes, stats(), )?, diff --git a/crates/brk_computer/src/blocks/mining/import.rs b/crates/brk_computer/src/blocks/mining/import.rs index 315ebe407..89973be17 100644 --- a/crates/brk_computer/src/blocks/mining/import.rs +++ b/crates/brk_computer/src/blocks/mining/import.rs @@ -5,8 +5,8 @@ use vecdb::{Database, IterableCloneableVec}; use super::Vecs; use crate::{ - internal::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source, VecBuilderOptions}, indexes, + internal::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source, VecBuilderOptions}, }; impl Vecs { @@ -16,7 +16,6 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, ) -> Result { - let v0 = Version::ZERO; let v4 = Version::new(4); let v5 = Version::new(5); @@ -36,7 +35,7 @@ impl Vecs { db, "hash_rate_1w_sma", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -44,7 +43,7 @@ impl Vecs { db, "hash_rate_1m_sma", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -52,7 +51,7 @@ impl Vecs { db, "hash_rate_2m_sma", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -60,7 +59,7 @@ impl Vecs { db, "hash_rate_1y_sma", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -148,7 +147,7 @@ impl Vecs { db, "difficulty", Source::Vec(indexer.vecs.block.height_to_difficulty.boxed_clone()), - version + v0, + version, indexes, last(), )?, @@ -156,7 +155,7 @@ impl Vecs { db, "difficulty_as_hash", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -164,7 +163,7 @@ impl Vecs { db, "difficulty_adjustment", Source::Compute, - version + v0, + version, indexes, sum(), )?, diff --git a/crates/brk_computer/src/blocks/rewards/import.rs b/crates/brk_computer/src/blocks/rewards/import.rs index 3eda32bf2..f1a96c957 100644 --- a/crates/brk_computer/src/blocks/rewards/import.rs +++ b/crates/brk_computer/src/blocks/rewards/import.rs @@ -4,8 +4,8 @@ use vecdb::{Database, EagerVec, ImportableVec}; use super::Vecs; use crate::{ - internal::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions}, indexes, + internal::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions}, }; impl Vecs { @@ -15,25 +15,20 @@ impl Vecs { indexes: &indexes::Vecs, compute_dollars: bool, ) -> Result { - let v0 = Version::ZERO; let last = || VecBuilderOptions::default().add_last(); Ok(Self { - height_to_24h_coinbase_sum: EagerVec::forced_import( - db, - "24h_coinbase_sum", - version + v0, - )?, + height_to_24h_coinbase_sum: EagerVec::forced_import(db, "24h_coinbase_sum", version)?, height_to_24h_coinbase_usd_sum: EagerVec::forced_import( db, "24h_coinbase_usd_sum", - version + v0, + version, )?, indexes_to_coinbase: ComputedValueVecsFromHeight::forced_import( db, "coinbase", Source::Compute, - version + v0, + version, VecBuilderOptions::default() .add_sum() .add_cumulative() @@ -47,7 +42,7 @@ impl Vecs { db, "subsidy", Source::Compute, - version + v0, + version, VecBuilderOptions::default() .add_percentiles() .add_sum() @@ -61,16 +56,16 @@ impl Vecs { db, "unclaimed_rewards", Source::Compute, - version + v0, + version, VecBuilderOptions::default().add_sum().add_cumulative(), compute_dollars, indexes, )?, - dateindex_to_fee_dominance: EagerVec::forced_import(db, "fee_dominance", version + v0)?, + dateindex_to_fee_dominance: EagerVec::forced_import(db, "fee_dominance", version)?, dateindex_to_subsidy_dominance: EagerVec::forced_import( db, "subsidy_dominance", - version + v0, + version, )?, indexes_to_subsidy_usd_1y_sma: compute_dollars .then(|| { @@ -78,7 +73,7 @@ impl Vecs { db, "subsidy_usd_1y_sma", Source::Compute, - version + v0, + version, indexes, last(), ) diff --git a/crates/brk_computer/src/blocks/size/import.rs b/crates/brk_computer/src/blocks/size/import.rs index 499132c08..d8e4031fd 100644 --- a/crates/brk_computer/src/blocks/size/import.rs +++ b/crates/brk_computer/src/blocks/size/import.rs @@ -16,7 +16,6 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, ) -> Result { - let v0 = Version::ZERO; let full_stats = || { VecBuilderOptions::default() .add_average() @@ -28,7 +27,7 @@ impl Vecs { let height_to_vbytes = LazyVecFrom1::init( "vbytes", - version + v0, + version, indexer.vecs.block.height_to_weight.boxed_clone(), |height: Height, weight_iter| { weight_iter @@ -42,7 +41,7 @@ impl Vecs { db, "block_size", Source::Vec(indexer.vecs.block.height_to_total_size.boxed_clone()), - version + v0, + version, indexes, full_stats(), )?, @@ -50,7 +49,7 @@ impl Vecs { db, "block_vbytes", Source::Vec(height_to_vbytes.boxed_clone()), - version + v0, + version, indexes, full_stats(), )?, diff --git a/crates/brk_computer/src/blocks/time/import.rs b/crates/brk_computer/src/blocks/time/import.rs index 107b4722e..956df1347 100644 --- a/crates/brk_computer/src/blocks/time/import.rs +++ b/crates/brk_computer/src/blocks/time/import.rs @@ -18,13 +18,12 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, ) -> Result { - let height_to_timestamp_fixed = - EagerVec::forced_import(db, "timestamp_fixed", version + Version::ZERO)?; + let height_to_timestamp_fixed = EagerVec::forced_import(db, "timestamp_fixed", version)?; Ok(Self { height_to_date: LazyVecFrom1::init( "date", - version + Version::ZERO, + version, indexer.vecs.block.height_to_timestamp.boxed_clone(), |height: Height, timestamp_iter| { timestamp_iter.get_at(height.to_usize()).map(Date::from) @@ -32,14 +31,14 @@ impl Vecs { ), height_to_date_fixed: LazyVecFrom1::init( "date_fixed", - version + Version::ZERO, + version, height_to_timestamp_fixed.boxed_clone(), |height: Height, timestamp_iter| timestamp_iter.get(height).map(Date::from), ), height_to_timestamp_fixed, difficultyepoch_to_timestamp: LazyVecFrom2::init( "timestamp", - version + Version::ZERO, + version, indexes.block.difficultyepoch_to_first_height.boxed_clone(), indexer.vecs.block.height_to_timestamp.boxed_clone(), |di: DifficultyEpoch, first_height_iter, timestamp_iter| { @@ -52,7 +51,7 @@ impl Vecs { db, "timestamp", Source::Compute, - version + Version::ZERO, + version, indexes, VecBuilderOptions::default().add_first(), )?, diff --git a/crates/brk_computer/src/blocks/weight/import.rs b/crates/brk_computer/src/blocks/weight/import.rs index 49a0a5af4..2e61994e4 100644 --- a/crates/brk_computer/src/blocks/weight/import.rs +++ b/crates/brk_computer/src/blocks/weight/import.rs @@ -6,7 +6,9 @@ use vecdb::{Database, IterableCloneableVec}; use super::Vecs; use crate::{ indexes, - internal::{ComputedVecsFromHeight, LazyVecsFromHeight, Source, VecBuilderOptions, WeightToFullness}, + internal::{ + ComputedVecsFromHeight, LazyVecsFromHeight, Source, VecBuilderOptions, WeightToFullness, + }, }; impl Vecs { @@ -16,7 +18,6 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, ) -> Result { - let v0 = Version::ZERO; let full_stats = || { VecBuilderOptions::default() .add_average() @@ -30,14 +31,14 @@ impl Vecs { db, "block_weight", Source::Vec(indexer.vecs.block.height_to_weight.boxed_clone()), - version + v0, + version, indexes, full_stats(), )?; let indexes_to_block_fullness = LazyVecsFromHeight::from_computed::( "block_fullness", - version + v0, + version, indexer.vecs.block.height_to_weight.boxed_clone(), &indexes_to_block_weight, ); diff --git a/crates/brk_computer/src/cointime/import.rs b/crates/brk_computer/src/cointime/import.rs index 9b9214e00..e89ab5e5c 100644 --- a/crates/brk_computer/src/cointime/import.rs +++ b/crates/brk_computer/src/cointime/import.rs @@ -6,7 +6,7 @@ use brk_types::Version; use vecdb::{Database, PAGE_SIZE}; use super::{ - ActivityVecs, AdjustedVecs, CapVecs, PricingVecs, SupplyVecs, ValueVecs, Vecs, DB_NAME, + ActivityVecs, AdjustedVecs, CapVecs, PricingVecs, SupplyVecs, ValueVecs, Vecs, DB_NAME, VERSION, }; use crate::{indexes, price}; @@ -21,15 +21,15 @@ impl Vecs { db.set_min_len(PAGE_SIZE * 1_000_000)?; let compute_dollars = price.is_some(); - let v0 = parent_version; - let v1 = parent_version + Version::ONE; + let version = parent_version + VERSION; + let v1 = version + Version::ONE; - let activity = ActivityVecs::forced_import(&db, v0, indexes)?; + let activity = ActivityVecs::forced_import(&db, version, indexes)?; let supply = SupplyVecs::forced_import(&db, v1, indexes, compute_dollars)?; let value = ValueVecs::forced_import(&db, v1, indexes)?; let cap = CapVecs::forced_import(&db, v1, indexes)?; - let pricing = PricingVecs::forced_import(&db, v0, indexes, price)?; - let adjusted = AdjustedVecs::forced_import(&db, v0, indexes)?; + let pricing = PricingVecs::forced_import(&db, version, indexes, price)?; + let adjusted = AdjustedVecs::forced_import(&db, version, indexes)?; let this = Self { db, diff --git a/crates/brk_computer/src/cointime/mod.rs b/crates/brk_computer/src/cointime/mod.rs index 377ee45f0..686d84930 100644 --- a/crates/brk_computer/src/cointime/mod.rs +++ b/crates/brk_computer/src/cointime/mod.rs @@ -9,6 +9,7 @@ mod compute; mod import; use brk_traversable::Traversable; +use brk_types::Version; use vecdb::Database; pub use activity::Vecs as ActivityVecs; @@ -19,6 +20,7 @@ pub use supply::Vecs as SupplyVecs; pub use value::Vecs as ValueVecs; pub const DB_NAME: &str = "cointime"; +const VERSION: Version = Version::ZERO; #[derive(Clone, Traversable)] pub struct Vecs { diff --git a/crates/brk_computer/src/constants.rs b/crates/brk_computer/src/constants.rs index 5e1b7e628..24277a20f 100644 --- a/crates/brk_computer/src/constants.rs +++ b/crates/brk_computer/src/constants.rs @@ -2,8 +2,8 @@ use brk_traversable::Traversable; use brk_types::{StoredF32, StoredI16, StoredU16, Version}; use super::{ - internal::{ConstantVecs, ReturnF32Tenths, ReturnI16, ReturnU16}, indexes, + internal::{ConstantVecs, ReturnF32Tenths, ReturnI16, ReturnU16}, }; pub const DB_NAME: &str = "constants"; @@ -15,9 +15,13 @@ pub struct Vecs { pub constant_2: ConstantVecs, pub constant_3: ConstantVecs, pub constant_4: ConstantVecs, + pub constant_20: ConstantVecs, + pub constant_30: ConstantVecs, pub constant_38_2: ConstantVecs, pub constant_50: ConstantVecs, pub constant_61_8: ConstantVecs, + pub constant_70: ConstantVecs, + pub constant_80: ConstantVecs, pub constant_100: ConstantVecs, pub constant_600: ConstantVecs, pub constant_minus_1: ConstantVecs, @@ -28,7 +32,7 @@ pub struct Vecs { impl Vecs { pub fn new(version: Version, indexes: &indexes::Vecs) -> Self { - let v = version + Version::ZERO; + let v = version; Self { constant_0: ConstantVecs::new::>("constant_0", v, indexes), @@ -36,9 +40,13 @@ impl Vecs { constant_2: ConstantVecs::new::>("constant_2", v, indexes), constant_3: ConstantVecs::new::>("constant_3", v, indexes), constant_4: ConstantVecs::new::>("constant_4", v, indexes), + constant_20: ConstantVecs::new::>("constant_20", v, indexes), + constant_30: ConstantVecs::new::>("constant_30", v, indexes), constant_38_2: ConstantVecs::new::>("constant_38_2", v, indexes), constant_50: ConstantVecs::new::>("constant_50", v, indexes), constant_61_8: ConstantVecs::new::>("constant_61_8", v, indexes), + constant_70: ConstantVecs::new::>("constant_70", v, indexes), + constant_80: ConstantVecs::new::>("constant_80", v, indexes), constant_100: ConstantVecs::new::>("constant_100", v, indexes), constant_600: ConstantVecs::new::>("constant_600", v, indexes), constant_minus_1: ConstantVecs::new::>("constant_minus_1", v, indexes), diff --git a/crates/brk_computer/src/distribution/cohorts/address/groups.rs b/crates/brk_computer/src/distribution/cohorts/address/groups.rs index 82093727d..9fcbfba64 100644 --- a/crates/brk_computer/src/distribution/cohorts/address/groups.rs +++ b/crates/brk_computer/src/distribution/cohorts/address/groups.rs @@ -5,12 +5,12 @@ use brk_cohort::{ }; use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version}; +use brk_types::{DateIndex, Dollars, Height, Version}; use derive_deref::{Deref, DerefMut}; use rayon::prelude::*; use vecdb::{AnyStoredVec, Database, Exit, IterableVec}; -use crate::{ComputeIndexes, indexes, price, distribution::DynCohortVecs}; +use crate::{ComputeIndexes, distribution::DynCohortVecs, indexes, price}; use crate::distribution::metrics::SupplyMetrics; @@ -35,7 +35,7 @@ impl AddressCohorts { states_path: &Path, all_supply: Option<&SupplyMetrics>, ) -> Result { - let v = version + VERSION + Version::ZERO; + let v = version + VERSION; // Helper to create a cohort - only amount_range cohorts have state let create = |filter: Filter, @@ -119,18 +119,16 @@ impl AddressCohorts { /// Second phase of post-processing: compute relative metrics. #[allow(clippy::too_many_arguments)] - pub fn compute_rest_part2( + pub fn compute_rest_part2( &mut self, indexes: &indexes::Vecs, price: Option<&price::Vecs>, starting_indexes: &ComputeIndexes, - height_to_supply: &S, height_to_market_cap: Option<&HM>, dateindex_to_market_cap: Option<&DM>, exit: &Exit, ) -> Result<()> where - S: IterableVec + Sync, HM: IterableVec + Sync, DM: IterableVec + Sync, { @@ -139,7 +137,6 @@ impl AddressCohorts { indexes, price, starting_indexes, - height_to_supply, height_to_market_cap, dateindex_to_market_cap, exit, diff --git a/crates/brk_computer/src/distribution/cohorts/address/vecs.rs b/crates/brk_computer/src/distribution/cohorts/address/vecs.rs index 8d35f9a58..f8befcb89 100644 --- a/crates/brk_computer/src/distribution/cohorts/address/vecs.rs +++ b/crates/brk_computer/src/distribution/cohorts/address/vecs.rs @@ -3,7 +3,7 @@ use std::path::Path; use brk_cohort::{CohortContext, Filter, Filtered}; use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{Bitcoin, DateIndex, Dollars, Height, StoredU64, Version}; +use brk_types::{DateIndex, Dollars, Height, StoredU64, Version}; use rayon::prelude::*; use vecdb::{ AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, ImportableVec, @@ -12,9 +12,10 @@ use vecdb::{ use crate::{ ComputeIndexes, - internal::{ComputedVecsFromHeight, Source, VecBuilderOptions}, - indexes, price, distribution::state::AddressCohortState, + indexes, + internal::{ComputedVecsFromHeight, Source, VecBuilderOptions}, + price, }; use crate::distribution::metrics::{CohortMetrics, ImportConfig, SupplyMetrics}; @@ -73,11 +74,8 @@ impl AddressCohortVecs { price, }; - let height_to_addr_count = EagerVec::forced_import( - db, - &cfg.name("addr_count"), - version + VERSION + Version::ZERO, - )?; + let height_to_addr_count = + EagerVec::forced_import(db, &cfg.name("addr_count"), version + VERSION)?; Ok(Self { starting_height: None, @@ -91,7 +89,7 @@ impl AddressCohortVecs { db, &cfg.name("addr_count"), Source::Vec(height_to_addr_count.boxed_clone()), - version + VERSION + Version::ZERO, + version + VERSION, indexes, VecBuilderOptions::default().add_last(), )?, @@ -290,7 +288,6 @@ impl CohortVecs for AddressCohortVecs { indexes: &indexes::Vecs, price: Option<&price::Vecs>, starting_indexes: &ComputeIndexes, - height_to_supply: &impl IterableVec, height_to_market_cap: Option<&impl IterableVec>, dateindex_to_market_cap: Option<&impl IterableVec>, exit: &Exit, @@ -299,7 +296,6 @@ impl CohortVecs for AddressCohortVecs { indexes, price, starting_indexes, - height_to_supply, height_to_market_cap, dateindex_to_market_cap, exit, diff --git a/crates/brk_computer/src/distribution/cohorts/traits.rs b/crates/brk_computer/src/distribution/cohorts/traits.rs index a9c210329..926b2e9ee 100644 --- a/crates/brk_computer/src/distribution/cohorts/traits.rs +++ b/crates/brk_computer/src/distribution/cohorts/traits.rs @@ -1,5 +1,5 @@ use brk_error::Result; -use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version}; +use brk_types::{DateIndex, Dollars, Height, Version}; use vecdb::{Exit, IterableVec}; use crate::{ComputeIndexes, indexes, price}; @@ -63,7 +63,6 @@ pub trait CohortVecs: DynCohortVecs { indexes: &indexes::Vecs, price: Option<&price::Vecs>, starting_indexes: &ComputeIndexes, - height_to_supply: &impl IterableVec, height_to_market_cap: Option<&impl IterableVec>, dateindex_to_market_cap: Option<&impl IterableVec>, exit: &Exit, diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs index b83374a9e..70e8f9543 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs @@ -6,16 +6,17 @@ use brk_cohort::{ }; use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{Bitcoin, DateIndex, Dollars, Height, Sats, Version}; +use brk_types::{DateIndex, Dollars, Height, Sats, Version}; use derive_deref::{Deref, DerefMut}; use rayon::prelude::*; use vecdb::{AnyStoredVec, Database, Exit, IterableVec}; use crate::{ ComputeIndexes, - internal::{PERCENTILES, PERCENTILES_LEN}, - indexes, price, distribution::DynCohortVecs, + indexes, + internal::{PERCENTILES, PERCENTILES_LEN}, + price, }; use super::{super::traits::CohortVecs, vecs::UTXOCohortVecs}; @@ -35,7 +36,7 @@ impl UTXOCohorts { price: Option<&price::Vecs>, states_path: &Path, ) -> Result { - let v = version + VERSION + Version::ZERO; + let v = version + VERSION; // Create "all" cohort first - it doesn't need global sources (it IS the global source) let all = UTXOCohortVecs::forced_import( @@ -202,18 +203,16 @@ impl UTXOCohorts { /// Second phase of post-processing: compute relative metrics. #[allow(clippy::too_many_arguments)] - pub fn compute_rest_part2( + pub fn compute_rest_part2( &mut self, indexes: &indexes::Vecs, price: Option<&price::Vecs>, starting_indexes: &ComputeIndexes, - height_to_supply: &S, height_to_market_cap: Option<&HM>, dateindex_to_market_cap: Option<&DM>, exit: &Exit, ) -> Result<()> where - S: IterableVec + Sync, HM: IterableVec + Sync, DM: IterableVec + Sync, { @@ -222,7 +221,6 @@ impl UTXOCohorts { indexes, price, starting_indexes, - height_to_supply, height_to_market_cap, dateindex_to_market_cap, exit, diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs b/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs index 5ee9b2f9f..f827f6773 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/vecs.rs @@ -3,7 +3,7 @@ use std::path::Path; use brk_cohort::{CohortContext, Filter, Filtered, StateLevel}; use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version}; +use brk_types::{DateIndex, Dollars, Height, Version}; use rayon::prelude::*; use vecdb::{AnyStoredVec, Database, Exit, IterableVec}; @@ -242,7 +242,6 @@ impl CohortVecs for UTXOCohortVecs { indexes: &indexes::Vecs, price: Option<&price::Vecs>, starting_indexes: &ComputeIndexes, - height_to_supply: &impl IterableVec, height_to_market_cap: Option<&impl IterableVec>, dateindex_to_market_cap: Option<&impl IterableVec>, exit: &Exit, @@ -251,7 +250,6 @@ impl CohortVecs for UTXOCohortVecs { indexes, price, starting_indexes, - height_to_supply, height_to_market_cap, dateindex_to_market_cap, exit, diff --git a/crates/brk_computer/src/distribution/compute/aggregates.rs b/crates/brk_computer/src/distribution/compute/aggregates.rs index 60a4b9fc8..c50272a85 100644 --- a/crates/brk_computer/src/distribution/compute/aggregates.rs +++ b/crates/brk_computer/src/distribution/compute/aggregates.rs @@ -1,5 +1,5 @@ use brk_error::Result; -use brk_types::{Bitcoin, DateIndex, Dollars, Height}; +use brk_types::{DateIndex, Dollars, Height}; use log::info; use vecdb::{Exit, IterableVec}; @@ -49,19 +49,17 @@ pub fn compute_rest_part1( /// /// Computes supply ratios, market cap ratios, etc. using total references. #[allow(clippy::too_many_arguments)] -pub fn compute_rest_part2( +pub fn compute_rest_part2( utxo_cohorts: &mut UTXOCohorts, address_cohorts: &mut AddressCohorts, indexes: &indexes::Vecs, price: Option<&price::Vecs>, starting_indexes: &ComputeIndexes, - height_to_supply: &S, height_to_market_cap: Option<&HM>, dateindex_to_market_cap: Option<&DM>, exit: &Exit, ) -> Result<()> where - S: IterableVec + Sync, HM: IterableVec + Sync, DM: IterableVec + Sync, { @@ -71,7 +69,6 @@ where indexes, price, starting_indexes, - height_to_supply, height_to_market_cap, dateindex_to_market_cap, exit, @@ -81,7 +78,6 @@ where indexes, price, starting_indexes, - height_to_supply, height_to_market_cap, dateindex_to_market_cap, exit, diff --git a/crates/brk_computer/src/distribution/metrics/activity.rs b/crates/brk_computer/src/distribution/metrics/activity.rs index 737ba040b..9f659e2d4 100644 --- a/crates/brk_computer/src/distribution/metrics/activity.rs +++ b/crates/brk_computer/src/distribution/metrics/activity.rs @@ -8,9 +8,9 @@ use vecdb::{ }; use crate::{ - ComputeIndexes, + ComputeIndexes, indexes, internal::{ComputedValueVecsFromHeight, ComputedVecsFromHeight, Source, VecBuilderOptions}, - indexes, price, + price, }; use super::ImportConfig; @@ -40,17 +40,16 @@ pub struct ActivityMetrics { impl ActivityMetrics { /// Import activity metrics from database. pub fn forced_import(cfg: &ImportConfig) -> Result { - let v0 = Version::ZERO; let compute_dollars = cfg.compute_dollars(); let sum_cum = VecBuilderOptions::default().add_sum().add_cumulative(); let height_to_sent: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("sent"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("sent"), cfg.version)?; let indexes_to_sent = ComputedValueVecsFromHeight::forced_import( cfg.db, &cfg.name("sent"), Source::Vec(height_to_sent.boxed_clone()), - cfg.version + v0, + cfg.version, sum_cum, compute_dollars, cfg.indexes, @@ -63,20 +62,20 @@ impl ActivityMetrics { height_to_satblocks_destroyed: EagerVec::forced_import( cfg.db, &cfg.name("satblocks_destroyed"), - cfg.version + v0, + cfg.version, )?, height_to_satdays_destroyed: EagerVec::forced_import( cfg.db, &cfg.name("satdays_destroyed"), - cfg.version + v0, + cfg.version, )?, indexes_to_coinblocks_destroyed: ComputedVecsFromHeight::forced_import( cfg.db, &cfg.name("coinblocks_destroyed"), Source::Compute, - cfg.version + v0, + cfg.version, cfg.indexes, sum_cum, )?, @@ -85,7 +84,7 @@ impl ActivityMetrics { cfg.db, &cfg.name("coindays_destroyed"), Source::Compute, - cfg.version + v0, + cfg.version, cfg.indexes, sum_cum, )?, diff --git a/crates/brk_computer/src/distribution/metrics/cost_basis.rs b/crates/brk_computer/src/distribution/metrics/cost_basis.rs index bfe293eeb..63f40e11e 100644 --- a/crates/brk_computer/src/distribution/metrics/cost_basis.rs +++ b/crates/brk_computer/src/distribution/metrics/cost_basis.rs @@ -33,22 +33,21 @@ pub struct CostBasisMetrics { impl CostBasisMetrics { /// Import cost basis metrics from database. pub fn forced_import(cfg: &ImportConfig) -> Result { - let v0 = Version::ZERO; let extended = cfg.extended(); let last = VecBuilderOptions::default().add_last(); let height_to_min_cost_basis = - EagerVec::forced_import(cfg.db, &cfg.name("min_cost_basis"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("min_cost_basis"), cfg.version)?; let height_to_max_cost_basis = - EagerVec::forced_import(cfg.db, &cfg.name("max_cost_basis"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("max_cost_basis"), cfg.version)?; Ok(Self { indexes_to_min_cost_basis: ComputedVecsFromHeight::forced_import( cfg.db, &cfg.name("min_cost_basis"), Source::Vec(height_to_min_cost_basis.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, last, )?, @@ -56,7 +55,7 @@ impl CostBasisMetrics { cfg.db, &cfg.name("max_cost_basis"), Source::Vec(height_to_max_cost_basis.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, last, )?, @@ -67,7 +66,7 @@ impl CostBasisMetrics { CostBasisPercentiles::forced_import( cfg.db, &cfg.name(""), - cfg.version + v0, + cfg.version, cfg.indexes, true, ) diff --git a/crates/brk_computer/src/distribution/metrics/mod.rs b/crates/brk_computer/src/distribution/metrics/mod.rs index 99f375f8c..84f13afba 100644 --- a/crates/brk_computer/src/distribution/metrics/mod.rs +++ b/crates/brk_computer/src/distribution/metrics/mod.rs @@ -17,7 +17,7 @@ pub use unrealized::*; use brk_cohort::Filter; use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version}; +use brk_types::{DateIndex, Dollars, Height, Version}; use rayon::prelude::*; use vecdb::{AnyStoredVec, Exit, IterableVec}; @@ -319,7 +319,6 @@ impl CohortMetrics { indexes: &indexes::Vecs, price: Option<&price_vecs::Vecs>, starting_indexes: &ComputeIndexes, - height_to_supply: &impl IterableVec, height_to_market_cap: Option<&impl IterableVec>, dateindex_to_market_cap: Option<&impl IterableVec>, exit: &Exit, @@ -329,7 +328,7 @@ impl CohortMetrics { indexes, price, starting_indexes, - height_to_supply, + &self.supply.height_to_supply_value.bitcoin, height_to_market_cap, dateindex_to_market_cap, exit, diff --git a/crates/brk_computer/src/distribution/metrics/realized.rs b/crates/brk_computer/src/distribution/metrics/realized.rs index 79d879d08..b5efc7d0f 100644 --- a/crates/brk_computer/src/distribution/metrics/realized.rs +++ b/crates/brk_computer/src/distribution/metrics/realized.rs @@ -9,13 +9,14 @@ use vecdb::{ use crate::{ ComputeIndexes, + distribution::state::RealizedState, + indexes, internal::{ ComputedRatioVecsFromDateIndex, ComputedVecsFromDateIndex, ComputedVecsFromHeight, LazyVecsFrom2FromHeight, LazyVecsFromDateIndex, LazyVecsFromHeight, PercentageDollarsF32, Source, StoredF32Identity, VecBuilderOptions, }, - indexes, price, - distribution::state::RealizedState, + price, utils::OptionExt, }; @@ -93,7 +94,6 @@ pub struct RealizedMetrics { impl RealizedMetrics { /// Import realized metrics from database. pub fn forced_import(cfg: &ImportConfig) -> Result { - let v0 = Version::ZERO; let v1 = Version::ONE; let v3 = Version::new(3); let extended = cfg.extended(); @@ -103,13 +103,13 @@ impl RealizedMetrics { let sum_cum = VecBuilderOptions::default().add_sum().add_cumulative(); let height_to_realized_loss: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("realized_loss"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("realized_loss"), cfg.version)?; let indexes_to_realized_loss = ComputedVecsFromHeight::forced_import( cfg.db, &cfg.name("realized_loss"), Source::Vec(height_to_realized_loss.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, sum_cum, )?; @@ -126,7 +126,7 @@ impl RealizedMetrics { cfg.db, &cfg.name("realized_value"), Source::Compute, - cfg.version + v0, + cfg.version, cfg.indexes, sum, )?; @@ -145,25 +145,25 @@ impl RealizedMetrics { // Extract vecs needed for lazy ratio construction let height_to_realized_cap: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("realized_cap"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("realized_cap"), cfg.version)?; let indexes_to_realized_cap = ComputedVecsFromHeight::forced_import( cfg.db, &cfg.name("realized_cap"), Source::Vec(height_to_realized_cap.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, last, )?; let height_to_realized_profit: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("realized_profit"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("realized_profit"), cfg.version)?; let indexes_to_realized_profit = ComputedVecsFromHeight::forced_import( cfg.db, &cfg.name("realized_profit"), Source::Vec(height_to_realized_profit.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, sum_cum, )?; @@ -172,7 +172,7 @@ impl RealizedMetrics { cfg.db, &cfg.name("net_realized_pnl"), Source::Compute, - cfg.version + v0, + cfg.version, cfg.indexes, sum_cum, )?; @@ -216,32 +216,24 @@ impl RealizedMetrics { cfg.db, &cfg.name("realized_price"), Source::Compute, - cfg.version + v0, + cfg.version + v1, cfg.indexes, last, )?; let height_to_value_created = - EagerVec::forced_import(cfg.db, &cfg.name("value_created"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("value_created"), cfg.version)?; let height_to_value_destroyed = - EagerVec::forced_import(cfg.db, &cfg.name("value_destroyed"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("value_destroyed"), cfg.version)?; let height_to_adjusted_value_created = compute_adjusted .then(|| { - EagerVec::forced_import( - cfg.db, - &cfg.name("adjusted_value_created"), - cfg.version + v0, - ) + 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 + v0, - ) + EagerVec::forced_import(cfg.db, &cfg.name("adjusted_value_destroyed"), cfg.version) }) .transpose()?; @@ -250,7 +242,7 @@ impl RealizedMetrics { cfg.db, &cfg.name("realized_price"), Some(&indexes_to_realized_price), - cfg.version + v0, + cfg.version + v1, cfg.indexes, extended, cfg.price, @@ -260,7 +252,7 @@ impl RealizedMetrics { // ratio = close / realized_price = market_cap / realized_cap = MVRV let indexes_to_mvrv = LazyVecsFromDateIndex::from_computed::( &cfg.name("mvrv"), - cfg.version + v0, + cfg.version, indexes_to_realized_price_extra .ratio .dateindex @@ -283,7 +275,7 @@ impl RealizedMetrics { cfg.db, &cfg.name("realized_cap_rel_to_own_market_cap"), Source::Compute, - cfg.version + v0, + cfg.version, cfg.indexes, last, ) @@ -293,7 +285,7 @@ impl RealizedMetrics { cfg.db, &cfg.name("realized_cap_30d_delta"), Source::Compute, - cfg.version + v0, + cfg.version, cfg.indexes, last, )?, @@ -329,7 +321,7 @@ impl RealizedMetrics { cfg.db, &cfg.name("value_created"), Source::Vec(height_to_value_created.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, sum, )?, @@ -337,7 +329,7 @@ impl RealizedMetrics { cfg.db, &cfg.name("value_destroyed"), Source::Vec(height_to_value_destroyed.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, sum, )?, @@ -356,7 +348,7 @@ impl RealizedMetrics { .unwrap() .boxed_clone(), ), - cfg.version + v0, + cfg.version, cfg.indexes, sum, ) @@ -373,7 +365,7 @@ impl RealizedMetrics { .unwrap() .boxed_clone(), ), - cfg.version + v0, + cfg.version, cfg.indexes, sum, ) diff --git a/crates/brk_computer/src/distribution/metrics/relative.rs b/crates/brk_computer/src/distribution/metrics/relative.rs index 62f4d4c19..5cac95da4 100644 --- a/crates/brk_computer/src/distribution/metrics/relative.rs +++ b/crates/brk_computer/src/distribution/metrics/relative.rs @@ -108,7 +108,6 @@ impl RelativeMetrics { supply: &SupplyMetrics, all_supply: Option<&SupplyMetrics>, ) -> Result { - let v0 = Version::ZERO; let v1 = Version::ONE; let v2 = Version::new(2); let extended = cfg.extended(); @@ -227,7 +226,7 @@ impl RelativeMetrics { height_to_unrealized_profit_rel_to_market_cap: global_market_cap_height.map(|mc| { LazyVecFrom2::transformed::( &cfg.name("unrealized_profit_rel_to_market_cap"), - cfg.version + v0, + cfg.version, unrealized.height_to_unrealized_profit.boxed_clone(), mc.boxed_clone(), ) @@ -235,7 +234,7 @@ impl RelativeMetrics { height_to_unrealized_loss_rel_to_market_cap: global_market_cap_height.map(|mc| { LazyVecFrom2::transformed::( &cfg.name("unrealized_loss_rel_to_market_cap"), - cfg.version + v0, + cfg.version, unrealized.height_to_unrealized_loss.boxed_clone(), mc.boxed_clone(), ) @@ -243,7 +242,7 @@ impl RelativeMetrics { height_to_neg_unrealized_loss_rel_to_market_cap: global_market_cap_height.map(|mc| { LazyVecFrom2::transformed::( &cfg.name("neg_unrealized_loss_rel_to_market_cap"), - cfg.version + v0, + cfg.version, unrealized.height_to_unrealized_loss.boxed_clone(), mc.boxed_clone(), ) @@ -401,7 +400,7 @@ impl RelativeMetrics { height_to_unrealized_profit_rel_to_own_total_unrealized_pnl: extended.then(|| { LazyVecFrom2::transformed::( &cfg.name("unrealized_profit_rel_to_own_total_unrealized_pnl"), - cfg.version + v0, + cfg.version, unrealized.height_to_unrealized_profit.boxed_clone(), unrealized.height_to_total_unrealized_pnl.boxed_clone(), ) @@ -409,7 +408,7 @@ impl RelativeMetrics { height_to_unrealized_loss_rel_to_own_total_unrealized_pnl: extended.then(|| { LazyVecFrom2::transformed::( &cfg.name("unrealized_loss_rel_to_own_total_unrealized_pnl"), - cfg.version + v0, + cfg.version, unrealized.height_to_unrealized_loss.boxed_clone(), unrealized.height_to_total_unrealized_pnl.boxed_clone(), ) @@ -417,7 +416,7 @@ impl RelativeMetrics { height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: extended.then(|| { LazyVecFrom2::transformed::( &cfg.name("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"), - cfg.version + v0, + cfg.version, unrealized.height_to_unrealized_loss.boxed_clone(), unrealized.height_to_total_unrealized_pnl.boxed_clone(), ) diff --git a/crates/brk_computer/src/distribution/metrics/supply.rs b/crates/brk_computer/src/distribution/metrics/supply.rs index 87d640067..443de4f67 100644 --- a/crates/brk_computer/src/distribution/metrics/supply.rs +++ b/crates/brk_computer/src/distribution/metrics/supply.rs @@ -8,13 +8,13 @@ use vecdb::{ }; use crate::{ - ComputeIndexes, + ComputeIndexes, indexes, internal::{ ComputedHeightValueVecs, ComputedValueVecsFromDateIndex, ComputedVecsFromHeight, HalfClosePriceTimesSats, HalveDollars, HalveSats, HalveSatsToBitcoin, LazyHeightValueVecs, LazyValueVecsFromDateIndex, Source, VecBuilderOptions, }, - indexes, price, + price, }; use super::ImportConfig; @@ -47,13 +47,12 @@ pub struct SupplyMetrics { impl SupplyMetrics { /// Import supply metrics from database. pub fn forced_import(cfg: &ImportConfig) -> Result { - let v0 = Version::ZERO; let v1 = Version::ONE; let compute_dollars = cfg.compute_dollars(); let last = VecBuilderOptions::default().add_last(); let height_to_supply: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("supply"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("supply"), cfg.version)?; let price_source = cfg .price @@ -63,7 +62,7 @@ impl SupplyMetrics { cfg.db, &cfg.name("supply"), Source::Vec(height_to_supply.boxed_clone()), - cfg.version + v0, + cfg.version, price_source.clone(), )?; @@ -86,25 +85,25 @@ impl SupplyMetrics { &cfg.name("supply_half"), height_to_supply.boxed_clone(), price_source, - cfg.version + v0, + cfg.version, ); let indexes_to_supply_half = LazyValueVecsFromDateIndex::from_source::( &cfg.name("supply_half"), &indexes_to_supply, - cfg.version + v0, + cfg.version, ); let height_to_utxo_count = - EagerVec::forced_import(cfg.db, &cfg.name("utxo_count"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("utxo_count"), cfg.version)?; Ok(Self { indexes_to_utxo_count: ComputedVecsFromHeight::forced_import( cfg.db, &cfg.name("utxo_count"), Source::Vec(height_to_utxo_count.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, last, )?, diff --git a/crates/brk_computer/src/distribution/metrics/unrealized.rs b/crates/brk_computer/src/distribution/metrics/unrealized.rs index 5b26e88df..c078edbda 100644 --- a/crates/brk_computer/src/distribution/metrics/unrealized.rs +++ b/crates/brk_computer/src/distribution/metrics/unrealized.rs @@ -1,6 +1,6 @@ use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{DateIndex, Dollars, Height, Sats, Version}; +use brk_types::{DateIndex, Dollars, Height, Sats}; use rayon::prelude::*; use vecdb::{ AnyStoredVec, AnyVec, EagerVec, Exit, GenericStoredVec, ImportableVec, IterableCloneableVec, @@ -9,11 +9,11 @@ use vecdb::{ use crate::{ ComputeIndexes, + distribution::state::UnrealizedState, internal::{ ComputedHeightValueVecs, ComputedValueVecsFromDateIndex, ComputedVecsFromDateIndex, DollarsMinus, DollarsPlus, LazyVecsFromDateIndex, Source, VecBuilderOptions, }, - distribution::state::UnrealizedState, }; use super::ImportConfig; @@ -57,23 +57,22 @@ pub struct UnrealizedMetrics { impl UnrealizedMetrics { /// Import unrealized metrics from database. pub fn forced_import(cfg: &ImportConfig) -> Result { - let v0 = Version::ZERO; let compute_dollars = cfg.compute_dollars(); let last = VecBuilderOptions::default().add_last(); let dateindex_to_supply_in_profit = - EagerVec::forced_import(cfg.db, &cfg.name("supply_in_profit"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("supply_in_profit"), cfg.version)?; let dateindex_to_supply_in_loss = - EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version)?; let dateindex_to_unrealized_profit = - EagerVec::forced_import(cfg.db, &cfg.name("unrealized_profit"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("unrealized_profit"), cfg.version)?; let dateindex_to_unrealized_loss = - EagerVec::forced_import(cfg.db, &cfg.name("unrealized_loss"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("unrealized_loss"), cfg.version)?; let height_to_unrealized_loss: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("unrealized_loss"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("unrealized_loss"), cfg.version)?; let height_to_neg_unrealized_loss = LazyVecFrom1::transformed::( &cfg.name("neg_unrealized_loss"), - cfg.version + v0, + cfg.version, height_to_unrealized_loss.boxed_clone(), ); @@ -81,26 +80,26 @@ impl UnrealizedMetrics { cfg.db, &cfg.name("unrealized_loss"), Source::Vec(dateindex_to_unrealized_loss.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, last, )?; let indexes_to_neg_unrealized_loss = LazyVecsFromDateIndex::from_computed::( &cfg.name("neg_unrealized_loss"), - cfg.version + v0, + cfg.version, Some(dateindex_to_unrealized_loss.boxed_clone()), &indexes_to_unrealized_loss, ); // Extract profit sources for lazy net/total vecs let height_to_unrealized_profit: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("unrealized_profit"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("unrealized_profit"), cfg.version)?; let indexes_to_unrealized_profit = ComputedVecsFromDateIndex::forced_import( cfg.db, &cfg.name("unrealized_profit"), Source::Vec(dateindex_to_unrealized_profit.boxed_clone()), - cfg.version + v0, + cfg.version, cfg.indexes, last, )?; @@ -108,13 +107,13 @@ impl UnrealizedMetrics { // Create lazy height vecs from profit/loss sources let height_to_net_unrealized_pnl = LazyVecFrom2::transformed::( &cfg.name("net_unrealized_pnl"), - cfg.version + v0, + cfg.version, height_to_unrealized_profit.boxed_clone(), height_to_unrealized_loss.boxed_clone(), ); let height_to_total_unrealized_pnl = LazyVecFrom2::transformed::( &cfg.name("total_unrealized_pnl"), - cfg.version + v0, + cfg.version, height_to_unrealized_profit.boxed_clone(), height_to_unrealized_loss.boxed_clone(), ); @@ -124,7 +123,7 @@ impl UnrealizedMetrics { cfg.db, &cfg.name("net_unrealized_pnl"), Source::Compute, - cfg.version + v0, + cfg.version, cfg.indexes, last, )?; @@ -132,15 +131,15 @@ impl UnrealizedMetrics { cfg.db, &cfg.name("total_unrealized_pnl"), Source::Compute, - cfg.version + v0, + cfg.version, cfg.indexes, last, )?; let height_to_supply_in_profit: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("supply_in_profit"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("supply_in_profit"), cfg.version)?; let height_to_supply_in_loss: EagerVec> = - EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version + v0)?; + EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version)?; let price_source = cfg .price @@ -150,14 +149,14 @@ impl UnrealizedMetrics { cfg.db, &cfg.name("supply_in_profit"), Source::Vec(height_to_supply_in_profit.boxed_clone()), - cfg.version + v0, + cfg.version, price_source.clone(), )?; let height_to_supply_in_loss_value = ComputedHeightValueVecs::forced_import( cfg.db, &cfg.name("supply_in_loss"), Source::Vec(height_to_supply_in_loss.boxed_clone()), - cfg.version + v0, + cfg.version, price_source, )?; @@ -168,7 +167,7 @@ impl UnrealizedMetrics { cfg.db, &cfg.name("supply_in_profit"), Source::Vec(dateindex_to_supply_in_profit.boxed_clone()), - cfg.version + v0, + cfg.version, last, compute_dollars, cfg.indexes, @@ -178,7 +177,7 @@ impl UnrealizedMetrics { cfg.db, &cfg.name("supply_in_loss"), Source::Vec(dateindex_to_supply_in_loss.boxed_clone()), - cfg.version + v0, + cfg.version, last, compute_dollars, cfg.indexes, diff --git a/crates/brk_computer/src/distribution/vecs.rs b/crates/brk_computer/src/distribution/vecs.rs index fbf3ffb60..0c42849fc 100644 --- a/crates/brk_computer/src/distribution/vecs.rs +++ b/crates/brk_computer/src/distribution/vecs.rs @@ -19,8 +19,7 @@ use crate::{ compute::{StartMode, determine_start_mode, process_blocks, recover_state, reset_state}, state::BlockState, }, - indexes, - inputs, + indexes, inputs, internal::{ComputedVecsFromHeight, Source, VecBuilderOptions}, outputs, price, transactions, }; @@ -63,7 +62,7 @@ const SAVED_STAMPED_CHANGES: u16 = 10; impl Vecs { pub fn forced_import( parent: &Path, - version: Version, + parent_version: Version, indexes: &indexes::Vecs, price: Option<&price::Vecs>, ) -> Result { @@ -74,7 +73,7 @@ impl Vecs { db.set_min_len(PAGE_SIZE * 20_000_000)?; db.set_min_regions(50_000)?; - let v0 = version + VERSION + Version::ZERO; + let version = parent_version + VERSION; let utxo_cohorts = UTXOCohorts::forced_import(&db, version, indexes, price, &states_path)?; @@ -90,37 +89,37 @@ impl Vecs { // Create address data BytesVecs first so we can also use them for identity mappings let loadedaddressindex_to_loadedaddressdata = BytesVec::forced_import_with( - vecdb::ImportOptions::new(&db, "loadedaddressdata", v0) + vecdb::ImportOptions::new(&db, "loadedaddressdata", version) .with_saved_stamped_changes(SAVED_STAMPED_CHANGES), )?; let emptyaddressindex_to_emptyaddressdata = BytesVec::forced_import_with( - vecdb::ImportOptions::new(&db, "emptyaddressdata", v0) + vecdb::ImportOptions::new(&db, "emptyaddressdata", version) .with_saved_stamped_changes(SAVED_STAMPED_CHANGES), )?; // Identity mappings for traversable let loadedaddressindex_to_loadedaddressindex = LazyVecFrom1::init( "loadedaddressindex", - v0, + version, loadedaddressindex_to_loadedaddressdata.boxed_clone(), |index, _| Some(index), ); let emptyaddressindex_to_emptyaddressindex = LazyVecFrom1::init( "emptyaddressindex", - v0, + version, emptyaddressindex_to_emptyaddressdata.boxed_clone(), |index, _| Some(index), ); // Extract address type height vecs before struct literal to use as sources let addresstype_to_height_to_addr_count = - AddressTypeToHeightToAddressCount::forced_import(&db, "addr_count", v0)?; + AddressTypeToHeightToAddressCount::forced_import(&db, "addr_count", version)?; let addresstype_to_height_to_empty_addr_count = - AddressTypeToHeightToAddressCount::forced_import(&db, "empty_addr_count", v0)?; + AddressTypeToHeightToAddressCount::forced_import(&db, "empty_addr_count", version)?; let this = Self { chain_state: BytesVec::forced_import_with( - vecdb::ImportOptions::new(&db, "chain", v0) + vecdb::ImportOptions::new(&db, "chain", version) .with_saved_stamped_changes(SAVED_STAMPED_CHANGES), )?, @@ -128,7 +127,7 @@ impl Vecs { &db, "addr_count", Source::Compute, - v0, + version, indexes, VecBuilderOptions::default().add_last(), )?, @@ -136,23 +135,24 @@ impl Vecs { &db, "empty_addr_count", Source::Compute, - v0, + version, indexes, VecBuilderOptions::default().add_last(), )?, - addresstype_to_indexes_to_addr_count: AddressTypeToIndexesToAddressCount::forced_import( - &db, - "addr_count", - v0, - indexes, - &addresstype_to_height_to_addr_count, - )?, + addresstype_to_indexes_to_addr_count: + AddressTypeToIndexesToAddressCount::forced_import( + &db, + "addr_count", + version, + indexes, + &addresstype_to_height_to_addr_count, + )?, addresstype_to_indexes_to_empty_addr_count: AddressTypeToIndexesToAddressCount::forced_import( &db, "empty_addr_count", - v0, + version, indexes, &addresstype_to_height_to_empty_addr_count, )?, @@ -162,7 +162,7 @@ impl Vecs { utxo_cohorts, address_cohorts, - any_address_indexes: AnyAddressIndexesVecs::forced_import(&db, v0)?, + any_address_indexes: AnyAddressIndexesVecs::forced_import(&db, version)?, addresses_data: AddressesDataVecs { loaded: loadedaddressindex_to_loadedaddressdata, empty: emptyaddressindex_to_emptyaddressdata, @@ -328,11 +328,52 @@ impl Vecs { exit, )?; + // 6b. Compute address count dateindex vecs (per-addresstype) + self.addresstype_to_indexes_to_addr_count.compute( + indexes, + starting_indexes, + exit, + &self.addresstype_to_height_to_addr_count, + )?; + self.addresstype_to_indexes_to_empty_addr_count.compute( + indexes, + starting_indexes, + exit, + &self.addresstype_to_height_to_empty_addr_count, + )?; + + // 6c. Compute global address count dateindex vecs (sum of all address types) + let addr_count_sources: Vec<_> = + self.addresstype_to_height_to_addr_count.values().collect(); + self.indexes_to_addr_count + .compute_all(indexes, starting_indexes, exit, |height_vec| { + Ok(height_vec.compute_sum_of_others( + starting_indexes.height, + &addr_count_sources, + exit, + )?) + })?; + + let empty_addr_count_sources: Vec<_> = self + .addresstype_to_height_to_empty_addr_count + .values() + .collect(); + self.indexes_to_empty_addr_count.compute_all( + indexes, + starting_indexes, + exit, + |height_vec| { + Ok(height_vec.compute_sum_of_others( + starting_indexes.height, + &empty_addr_count_sources, + exit, + )?) + }, + )?; + // 7. Compute rest part2 (relative metrics) let supply_metrics = &self.utxo_cohorts.all.metrics.supply; - let height_to_supply = &supply_metrics.height_to_supply_value.bitcoin.clone(); - let height_to_market_cap = supply_metrics .height_to_supply_value .dollars @@ -354,7 +395,6 @@ impl Vecs { indexes, price, starting_indexes, - height_to_supply, height_to_market_cap_ref, dateindex_to_market_cap_ref, exit, diff --git a/crates/brk_computer/src/inputs/count/import.rs b/crates/brk_computer/src/inputs/count/import.rs index 991f9fa53..f2b7d446d 100644 --- a/crates/brk_computer/src/inputs/count/import.rs +++ b/crates/brk_computer/src/inputs/count/import.rs @@ -24,7 +24,7 @@ impl Vecs { db, "input_count", Source::Vec(indexes.transaction.txindex_to_input_count.boxed_clone()), - version + Version::ZERO, + version, indexes, full_stats(), )?, diff --git a/crates/brk_computer/src/inputs/import.rs b/crates/brk_computer/src/inputs/import.rs index 66c27fa48..62c82fe93 100644 --- a/crates/brk_computer/src/inputs/import.rs +++ b/crates/brk_computer/src/inputs/import.rs @@ -17,7 +17,7 @@ impl Vecs { let db = Database::open(&parent_path.join(super::DB_NAME))?; db.set_min_len(PAGE_SIZE * 50_000_000)?; - let version = parent_version + Version::ZERO; + let version = parent_version; let spent = SpentVecs::forced_import(&db, version)?; let count = CountVecs::forced_import(&db, version, indexes)?; diff --git a/crates/brk_computer/src/internal/builder/lazy.rs b/crates/brk_computer/src/internal/builder/lazy.rs index 7abb864b2..11dfe886b 100644 --- a/crates/brk_computer/src/internal/builder/lazy.rs +++ b/crates/brk_computer/src/internal/builder/lazy.rs @@ -60,7 +60,7 @@ where first: options.first.then(|| { Box::new(LazyVecFrom2::init( &maybe_suffix("first"), - version + VERSION + Version::ZERO, + version + VERSION, source_extra .first .as_ref() @@ -77,7 +77,7 @@ where last: options.last.then(|| { Box::new(LazyVecFrom2::init( name, - version + VERSION + Version::ZERO, + version + VERSION, source_extra.last.as_ref().map_or_else( || { source @@ -102,7 +102,7 @@ where min: options.min.then(|| { Box::new(LazyVecFrom2::init( &maybe_suffix("min"), - version + VERSION + Version::ZERO, + version + VERSION, source_extra .min .as_ref() @@ -121,7 +121,7 @@ where max: options.max.then(|| { Box::new(LazyVecFrom2::init( &maybe_suffix("max"), - version + VERSION + Version::ZERO, + version + VERSION, source_extra .max .as_ref() @@ -140,7 +140,7 @@ where average: options.average.then(|| { Box::new(LazyVecFrom2::init( &maybe_suffix("avg"), - version + VERSION + Version::ZERO, + version + VERSION, source_extra .average .as_ref() @@ -172,7 +172,7 @@ where } else { maybe_suffix("sum") }), - version + VERSION + Version::ZERO, + version + VERSION, source_extra .sum .as_ref() @@ -200,7 +200,7 @@ where cumulative: options.cumulative.then(|| { Box::new(LazyVecFrom2::init( &suffix("cumulative"), - version + VERSION + Version::ZERO, + version + VERSION, source_extra.cumulative.u().boxed_clone(), len_source.clone(), |i: I, source, len_source| { diff --git a/crates/brk_computer/src/internal/computed/from_dateindex.rs b/crates/brk_computer/src/internal/computed/from_dateindex.rs index 2a2f20b9f..06f533042 100644 --- a/crates/brk_computer/src/internal/computed/from_dateindex.rs +++ b/crates/brk_computer/src/internal/computed/from_dateindex.rs @@ -1,7 +1,8 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{ - DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex, + DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, TreeNode, Version, WeekIndex, + YearIndex, }; use schemars::JsonSchema; use vecdb::{ @@ -9,7 +10,7 @@ use vecdb::{ PcoVec, }; -use crate::{ComputeIndexes, internal::LazyVecsBuilder, indexes, utils::OptionExt}; +use crate::{ComputeIndexes, indexes, internal::LazyVecsBuilder, utils::OptionExt}; use crate::internal::{ComputedVecValue, EagerVecsBuilder, Source, VecBuilderOptions}; @@ -45,12 +46,12 @@ where ) -> Result { let dateindex = source .is_compute() - .then(|| EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap()); + .then(|| EagerVec::forced_import(db, name, version + VERSION).unwrap()); let dateindex_extra = EagerVecsBuilder::forced_import( db, name, - version + VERSION + Version::ZERO, + version + VERSION, options.copy_self_extra(), )?; @@ -61,7 +62,7 @@ where Ok(Self { weekindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, dateindex_source.clone(), &dateindex_extra, indexes.time.weekindex_to_weekindex.boxed_clone(), @@ -69,7 +70,7 @@ where ), monthindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, dateindex_source.clone(), &dateindex_extra, indexes.time.monthindex_to_monthindex.boxed_clone(), @@ -77,7 +78,7 @@ where ), quarterindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, dateindex_source.clone(), &dateindex_extra, indexes.time.quarterindex_to_quarterindex.boxed_clone(), @@ -85,7 +86,7 @@ where ), semesterindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, dateindex_source.clone(), &dateindex_extra, indexes.time.semesterindex_to_semesterindex.boxed_clone(), @@ -93,7 +94,7 @@ where ), yearindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, dateindex_source.clone(), &dateindex_extra, indexes.time.yearindex_to_yearindex.boxed_clone(), @@ -101,7 +102,7 @@ where ), decadeindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, dateindex_source.clone(), &dateindex_extra, indexes.time.decadeindex_to_decadeindex.boxed_clone(), @@ -151,9 +152,9 @@ impl Traversable for ComputedVecsFromDateIndex where T: ComputedVecValue + JsonSchema, { - fn to_tree_node(&self) -> brk_traversable::TreeNode { + fn to_tree_node(&self) -> TreeNode { let dateindex_extra_node = self.dateindex_extra.to_tree_node(); - brk_traversable::TreeNode::Branch( + TreeNode::Branch( [ self.dateindex .as_ref() diff --git a/crates/brk_computer/src/internal/computed/from_height/standard.rs b/crates/brk_computer/src/internal/computed/from_height/standard.rs index 7397a5593..5c2056afe 100644 --- a/crates/brk_computer/src/internal/computed/from_height/standard.rs +++ b/crates/brk_computer/src/internal/computed/from_height/standard.rs @@ -3,7 +3,7 @@ use brk_error::Result; use brk_traversable::Traversable; use brk_types::{ DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex, - Version, WeekIndex, YearIndex, + TreeNode, Version, WeekIndex, YearIndex, }; use schemars::JsonSchema; use vecdb::{ @@ -12,9 +12,8 @@ use vecdb::{ }; use crate::{ - ComputeIndexes, + ComputeIndexes, indexes, internal::{LazyVecsBuilder, Source}, - indexes, utils::OptionExt, }; @@ -56,17 +55,16 @@ where ) -> Result { let height = source .is_compute() - .then(|| EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap()); + .then(|| EagerVec::forced_import(db, name, version + VERSION).unwrap()); let height_extra = EagerVecsBuilder::forced_import( db, name, - version + VERSION + Version::ZERO, + version + VERSION, options.copy_self_extra(), )?; - let dateindex = - EagerVecsBuilder::forced_import(db, name, version + VERSION + Version::ZERO, options)?; + let dateindex = EagerVecsBuilder::forced_import(db, name, version + VERSION, options)?; let options = options.remove_percentiles(); @@ -75,7 +73,7 @@ where Ok(Self { weekindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.weekindex_to_weekindex.boxed_clone(), @@ -83,7 +81,7 @@ where ), monthindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.monthindex_to_monthindex.boxed_clone(), @@ -91,7 +89,7 @@ where ), quarterindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.quarterindex_to_quarterindex.boxed_clone(), @@ -99,7 +97,7 @@ where ), semesterindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.semesterindex_to_semesterindex.boxed_clone(), @@ -107,7 +105,7 @@ where ), yearindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.yearindex_to_yearindex.boxed_clone(), @@ -115,19 +113,22 @@ where ), decadeindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.decadeindex_to_decadeindex.boxed_clone(), options.into(), ), - // halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION + Version::ZERO, format, options)?, + // halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION , format, options)?, difficultyepoch: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, height_source, &height_extra, - indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(), + indexes + .block + .difficultyepoch_to_difficultyepoch + .boxed_clone(), options.into(), ), height, @@ -193,9 +194,9 @@ impl Traversable for ComputedVecsFromHeight where T: ComputedVecValue + JsonSchema, { - fn to_tree_node(&self) -> brk_traversable::TreeNode { + fn to_tree_node(&self) -> TreeNode { let height_extra_node = self.height_extra.to_tree_node(); - brk_traversable::TreeNode::Branch( + TreeNode::Branch( [ self.height .as_ref() diff --git a/crates/brk_computer/src/internal/computed/from_height/strict.rs b/crates/brk_computer/src/internal/computed/from_height/strict.rs index e6c247298..177169d86 100644 --- a/crates/brk_computer/src/internal/computed/from_height/strict.rs +++ b/crates/brk_computer/src/internal/computed/from_height/strict.rs @@ -1,7 +1,7 @@ use brk_error::Result; use brk_traversable::Traversable; -use brk_types::{DifficultyEpoch, Height, Version}; +use brk_types::{DifficultyEpoch, Height, TreeNode, Version}; use schemars::JsonSchema; use vecdb::{ AnyExportableVec, Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec, @@ -36,12 +36,12 @@ where indexes: &indexes::Vecs, options: VecBuilderOptions, ) -> Result { - let height = EagerVec::forced_import(db, name, version + VERSION + Version::ZERO)?; + let height = EagerVec::forced_import(db, name, version + VERSION)?; let height_extra = EagerVecsBuilder::forced_import( db, name, - version + VERSION + Version::ZERO, + version + VERSION, options.copy_self_extra(), )?; @@ -50,15 +50,18 @@ where Ok(Self { difficultyepoch: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, Some(height.boxed_clone()), &height_extra, - indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(), + indexes + .block + .difficultyepoch_to_difficultyepoch + .boxed_clone(), options.into(), ), height, height_extra, - // halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION + Version::ZERO, format, options)?, + // halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION , format, options)?, }) } @@ -84,9 +87,9 @@ impl Traversable for ComputedVecsFromHeightStrict where T: ComputedVecValue + JsonSchema, { - fn to_tree_node(&self) -> brk_traversable::TreeNode { + fn to_tree_node(&self) -> TreeNode { let height_extra_node = self.height_extra.to_tree_node(); - brk_traversable::TreeNode::Branch( + TreeNode::Branch( [ Some(("height".to_string(), self.height.to_tree_node())), if height_extra_node.is_empty() { diff --git a/crates/brk_computer/src/internal/computed/from_txindex.rs b/crates/brk_computer/src/internal/computed/from_txindex.rs index 890ad090f..c91ff4f26 100644 --- a/crates/brk_computer/src/internal/computed/from_txindex.rs +++ b/crates/brk_computer/src/internal/computed/from_txindex.rs @@ -3,7 +3,7 @@ use brk_indexer::Indexer; use brk_traversable::Traversable; use brk_types::{ Bitcoin, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, Height, MonthIndex, QuarterIndex, - Sats, SemesterIndex, TxIndex, Version, WeekIndex, YearIndex, + Sats, SemesterIndex, TreeNode, TxIndex, Version, WeekIndex, YearIndex, }; use schemars::JsonSchema; use vecdb::{ @@ -12,9 +12,9 @@ use vecdb::{ }; use crate::{ - ComputeIndexes, + ComputeIndexes, indexes, internal::{LazyVecsBuilder, Source}, - indexes, price, + price, utils::OptionExt, }; @@ -54,22 +54,20 @@ where indexes: &indexes::Vecs, options: VecBuilderOptions, ) -> Result { - let txindex = source.is_compute().then(|| { - Box::new(EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap()) - }); + let txindex = source + .is_compute() + .then(|| Box::new(EagerVec::forced_import(db, name, version + VERSION).unwrap())); - let height = - EagerVecsBuilder::forced_import(db, name, version + VERSION + Version::ZERO, options)?; + let height = EagerVecsBuilder::forced_import(db, name, version + VERSION, options)?; let options = options.remove_percentiles(); - let dateindex = - EagerVecsBuilder::forced_import(db, name, version + VERSION + Version::ZERO, options)?; + let dateindex = EagerVecsBuilder::forced_import(db, name, version + VERSION, options)?; Ok(Self { weekindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.weekindex_to_weekindex.boxed_clone(), @@ -77,15 +75,18 @@ where ), difficultyepoch: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &height, - indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(), + indexes + .block + .difficultyepoch_to_difficultyepoch + .boxed_clone(), options.into(), ), monthindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.monthindex_to_monthindex.boxed_clone(), @@ -93,7 +94,7 @@ where ), quarterindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.quarterindex_to_quarterindex.boxed_clone(), @@ -101,7 +102,7 @@ where ), semesterindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.semesterindex_to_semesterindex.boxed_clone(), @@ -109,7 +110,7 @@ where ), yearindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.yearindex_to_yearindex.boxed_clone(), @@ -117,7 +118,7 @@ where ), decadeindex: LazyVecsBuilder::forced_import( name, - version + VERSION + Version::ZERO, + version + VERSION, None, &dateindex, indexes.time.decadeindex_to_decadeindex.boxed_clone(), @@ -127,7 +128,7 @@ where txindex, height, dateindex, - // halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION + Version::ZERO, format, options)?, + // halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION , format, options)?, }) } @@ -402,8 +403,8 @@ impl Traversable for ComputedVecsFromTxindex where T: ComputedVecValue + JsonSchema, { - fn to_tree_node(&self) -> brk_traversable::TreeNode { - brk_traversable::TreeNode::Branch( + fn to_tree_node(&self) -> TreeNode { + TreeNode::Branch( [ self.txindex .as_ref() diff --git a/crates/brk_computer/src/internal/lazy/binary/from_dateindex.rs b/crates/brk_computer/src/internal/lazy/binary/from_dateindex.rs index 0c0f85c11..590bd1d0d 100644 --- a/crates/brk_computer/src/internal/lazy/binary/from_dateindex.rs +++ b/crates/brk_computer/src/internal/lazy/binary/from_dateindex.rs @@ -1,11 +1,14 @@ use brk_traversable::Traversable; use brk_types::{ - DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex, + DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, TreeNode, Version, WeekIndex, + YearIndex, }; use schemars::JsonSchema; use vecdb::{AnyExportableVec, BinaryTransform, IterableCloneableVec, LazyVecFrom2}; -use crate::internal::{ComputedVecValue, ComputedVecsFromDateIndex, ComputedVecsFromHeight, LazyTransform2Builder}; +use crate::internal::{ + ComputedVecValue, ComputedVecsFromDateIndex, ComputedVecsFromHeight, LazyTransform2Builder, +}; const VERSION: Version = Version::ZERO; @@ -215,8 +218,8 @@ where S1T: ComputedVecValue, S2T: ComputedVecValue, { - fn to_tree_node(&self) -> brk_traversable::TreeNode { - brk_traversable::TreeNode::Branch( + fn to_tree_node(&self) -> TreeNode { + TreeNode::Branch( [ self.dateindex .as_ref() diff --git a/crates/brk_computer/src/internal/lazy/binary/from_height.rs b/crates/brk_computer/src/internal/lazy/binary/from_height.rs index 1884221f4..7a65eaa3f 100644 --- a/crates/brk_computer/src/internal/lazy/binary/from_height.rs +++ b/crates/brk_computer/src/internal/lazy/binary/from_height.rs @@ -1,7 +1,7 @@ use brk_traversable::Traversable; use brk_types::{ DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex, - Version, WeekIndex, YearIndex, + TreeNode, Version, WeekIndex, YearIndex, }; use schemars::JsonSchema; use vecdb::{AnyExportableVec, BinaryTransform, IterableBoxedVec, LazyVecFrom2}; @@ -192,9 +192,9 @@ where S1T: ComputedVecValue, S2T: ComputedVecValue, { - fn to_tree_node(&self) -> brk_traversable::TreeNode { + fn to_tree_node(&self) -> TreeNode { let height_extra_node = self.height_extra.to_tree_node(); - brk_traversable::TreeNode::Branch( + TreeNode::Branch( [ Some(("height".to_string(), self.height.to_tree_node())), if height_extra_node.is_empty() { diff --git a/crates/brk_computer/src/internal/lazy/from_dateindex.rs b/crates/brk_computer/src/internal/lazy/from_dateindex.rs index 4cf6a0da4..e493095ce 100644 --- a/crates/brk_computer/src/internal/lazy/from_dateindex.rs +++ b/crates/brk_computer/src/internal/lazy/from_dateindex.rs @@ -1,6 +1,7 @@ use brk_traversable::Traversable; use brk_types::{ - DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex, + DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, TreeNode, Version, WeekIndex, + YearIndex, }; use schemars::JsonSchema; use vecdb::{AnyExportableVec, IterableBoxedVec, LazyVecFrom1, UnaryTransform}; @@ -65,9 +66,9 @@ where T: ComputedVecValue + JsonSchema, S1T: ComputedVecValue, { - fn to_tree_node(&self) -> brk_traversable::TreeNode { + fn to_tree_node(&self) -> TreeNode { let dateindex_extra_node = self.dateindex_extra.to_tree_node(); - brk_traversable::TreeNode::Branch( + TreeNode::Branch( [ self.dateindex .as_ref() diff --git a/crates/brk_computer/src/internal/lazy/from_height.rs b/crates/brk_computer/src/internal/lazy/from_height.rs index dae5ba7c9..0414784bd 100644 --- a/crates/brk_computer/src/internal/lazy/from_height.rs +++ b/crates/brk_computer/src/internal/lazy/from_height.rs @@ -1,7 +1,7 @@ use brk_traversable::Traversable; use brk_types::{ DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex, - Version, WeekIndex, YearIndex, + TreeNode, Version, WeekIndex, YearIndex, }; use schemars::JsonSchema; use vecdb::{AnyExportableVec, IterableBoxedVec, LazyVecFrom1, UnaryTransform}; @@ -72,9 +72,9 @@ where T: ComputedVecValue + JsonSchema, S1T: ComputedVecValue, { - fn to_tree_node(&self) -> brk_traversable::TreeNode { + fn to_tree_node(&self) -> TreeNode { let height_extra_node = self.height_extra.to_tree_node(); - brk_traversable::TreeNode::Branch( + TreeNode::Branch( [ Some(("height".to_string(), self.height.to_tree_node())), if height_extra_node.is_empty() { diff --git a/crates/brk_computer/src/internal/specialized/constant.rs b/crates/brk_computer/src/internal/specialized/constant.rs index e3c9ef7de..27e45d8ef 100644 --- a/crates/brk_computer/src/internal/specialized/constant.rs +++ b/crates/brk_computer/src/internal/specialized/constant.rs @@ -1,17 +1,19 @@ use brk_traversable::Traversable; use brk_types::{ - DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, - YearIndex, + DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, TreeNode, Version, + WeekIndex, YearIndex, }; use schemars::JsonSchema; use serde::Serialize; -use vecdb::{Formattable, IterableCloneableVec, LazyVecFrom1, UnaryTransform, VecValue}; +use vecdb::{ + AnyExportableVec, Formattable, IterableCloneableVec, LazyVecFrom1, UnaryTransform, VecValue, +}; -use crate::indexes; +use crate::{indexes, internal::ComputedVecValue}; /// Lazy constant vecs for all index levels. /// Uses const generic transforms to return the same value for every index. -#[derive(Clone, Traversable)] +#[derive(Clone)] pub struct ConstantVecs where T: VecValue + Formattable + Serialize + JsonSchema, @@ -83,3 +85,44 @@ impl ConstantVecs { } } } + +impl Traversable for ConstantVecs +where + T: ComputedVecValue + JsonSchema, +{ + fn to_tree_node(&self) -> TreeNode { + TreeNode::Branch( + [ + Some(("height".to_string(), self.height.to_tree_node())), + Some(("dateindex".to_string(), self.dateindex.to_tree_node())), + Some(("weekindex".to_string(), self.weekindex.to_tree_node())), + Some(("monthindex".to_string(), self.monthindex.to_tree_node())), + Some(("quarterindex".to_string(), self.quarterindex.to_tree_node())), + Some(( + "semesterindex".to_string(), + self.semesterindex.to_tree_node(), + )), + Some(("yearindex".to_string(), self.yearindex.to_tree_node())), + Some(("decadeindex".to_string(), self.decadeindex.to_tree_node())), + ] + .into_iter() + .flatten() + .collect(), + ) + .merge_branches() + .unwrap() + } + + fn iter_any_exportable(&self) -> impl Iterator { + let mut regular_iter: Box> = + Box::new(self.height.iter_any_exportable()); + regular_iter = Box::new(regular_iter.chain(self.dateindex.iter_any_exportable())); + regular_iter = Box::new(regular_iter.chain(self.weekindex.iter_any_exportable())); + regular_iter = Box::new(regular_iter.chain(self.monthindex.iter_any_exportable())); + regular_iter = Box::new(regular_iter.chain(self.quarterindex.iter_any_exportable())); + regular_iter = Box::new(regular_iter.chain(self.semesterindex.iter_any_exportable())); + regular_iter = Box::new(regular_iter.chain(self.yearindex.iter_any_exportable())); + regular_iter = Box::new(regular_iter.chain(self.decadeindex.iter_any_exportable())); + regular_iter + } +} diff --git a/crates/brk_computer/src/internal/value/lazy/from_dateindex.rs b/crates/brk_computer/src/internal/value/lazy/from_dateindex.rs index 3dd543db0..3bc2d5dd1 100644 --- a/crates/brk_computer/src/internal/value/lazy/from_dateindex.rs +++ b/crates/brk_computer/src/internal/value/lazy/from_dateindex.rs @@ -35,14 +35,14 @@ impl LazyValueVecsFromDateIndex { let sats = LazyVecsFromDateIndex::from_computed::( name, - v + Version::ZERO, + v, source.sats.dateindex.as_ref().map(|v| v.boxed_clone()), &source.sats, ); let bitcoin = LazyVecsFromDateIndex::from_computed::( &format!("{name}_btc"), - v + Version::ZERO, + v, source.sats.dateindex.as_ref().map(|v| v.boxed_clone()), &source.sats, ); @@ -50,7 +50,7 @@ impl LazyValueVecsFromDateIndex { let dollars = source.dollars.as_ref().map(|dollars_source| { LazyVecsFromDateIndex::from_computed::( &format!("{name}_usd"), - v + Version::ZERO, + v, dollars_source.dateindex.as_ref().map(|v| v.boxed_clone()), dollars_source, ) diff --git a/crates/brk_computer/src/internal/value/lazy/height.rs b/crates/brk_computer/src/internal/value/lazy/height.rs index c028b84dd..7663dc58a 100644 --- a/crates/brk_computer/src/internal/value/lazy/height.rs +++ b/crates/brk_computer/src/internal/value/lazy/height.rs @@ -32,15 +32,11 @@ impl LazyHeightValueVecs { { let v = version + VERSION; - let sats = LazyVecFrom1::transformed::( - name, - v + Version::ZERO, - sats_source.clone(), - ); + let sats = LazyVecFrom1::transformed::(name, v, sats_source.clone()); let bitcoin = LazyVecFrom1::transformed::( &format!("{name}_btc"), - v + Version::ZERO, + v, sats_source.clone(), ); @@ -48,7 +44,7 @@ impl LazyHeightValueVecs { let dollars = price_source.map(|price| { LazyVecFrom2::transformed::( &format!("{name}_usd"), - v + Version::ZERO, + v, price, sats_source, ) diff --git a/crates/brk_computer/src/internal/value/lazy/value_height.rs b/crates/brk_computer/src/internal/value/lazy/value_height.rs index 045ef0c82..0f452a971 100644 --- a/crates/brk_computer/src/internal/value/lazy/value_height.rs +++ b/crates/brk_computer/src/internal/value/lazy/value_height.rs @@ -27,7 +27,7 @@ impl ComputedHeightValueVecs { ) -> Result { let sats = source .is_compute() - .then(|| EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap()); + .then(|| EagerVec::forced_import(db, name, version + VERSION).unwrap()); let sats_source: IterableBoxedVec = source .vec() @@ -35,14 +35,14 @@ impl ComputedHeightValueVecs { let bitcoin = LazyVecFrom1::transformed::( &format!("{name}_btc"), - version + VERSION + Version::ZERO, + version + VERSION, sats_source.clone(), ); let dollars = price_source.map(|price| { LazyVecFrom2::transformed::( &format!("{name}_usd"), - version + VERSION + Version::ZERO, + version + VERSION, price, sats_source.clone(), ) diff --git a/crates/brk_computer/src/market/ath/import.rs b/crates/brk_computer/src/market/ath/import.rs index cf48cc264..c2e4b0d09 100644 --- a/crates/brk_computer/src/market/ath/import.rs +++ b/crates/brk_computer/src/market/ath/import.rs @@ -4,11 +4,12 @@ use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec}; use super::Vecs; use crate::{ + indexes, internal::{ ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, LazyVecsFromDateIndex, PercentageDiffCloseDollars, Source, StoredU16ToYears, VecBuilderOptions, }, - indexes, price, + price, }; impl Vecs { @@ -18,14 +19,13 @@ impl Vecs { indexes: &indexes::Vecs, price: &price::Vecs, ) -> Result { - let v0 = Version::ZERO; let last = VecBuilderOptions::default().add_last(); let indexes_to_price_ath = ComputedVecsFromDateIndex::forced_import( db, "price_ath", Source::Compute, - version + v0, + version, indexes, last, )?; @@ -34,7 +34,7 @@ impl Vecs { db, "max_days_between_price_aths", Source::Compute, - version + v0, + version, indexes, last, )?; @@ -42,7 +42,7 @@ impl Vecs { let indexes_to_max_years_between_price_aths = LazyVecsFromDateIndex::from_computed::( "max_years_between_price_aths", - version + v0, + version, indexes_to_max_days_between_price_aths .dateindex .as_ref() @@ -53,21 +53,21 @@ impl Vecs { let indexes_to_price_drawdown = LazyVecsFrom2FromDateIndex::from_computed::( "price_drawdown", - version + v0, + version, &price.usd.timeindexes_to_price_close, &indexes_to_price_ath, ); Ok(Self { - height_to_price_ath: EagerVec::forced_import(db, "price_ath", version + v0)?, - height_to_price_drawdown: EagerVec::forced_import(db, "price_drawdown", version + v0)?, + height_to_price_ath: EagerVec::forced_import(db, "price_ath", version)?, + height_to_price_drawdown: EagerVec::forced_import(db, "price_drawdown", version)?, indexes_to_price_ath, indexes_to_price_drawdown, indexes_to_days_since_price_ath: ComputedVecsFromDateIndex::forced_import( db, "days_since_price_ath", Source::Compute, - version + v0, + version, indexes, last, )?, diff --git a/crates/brk_computer/src/market/compute.rs b/crates/brk_computer/src/market/compute.rs index 6ee870f61..612995d37 100644 --- a/crates/brk_computer/src/market/compute.rs +++ b/crates/brk_computer/src/market/compute.rs @@ -31,8 +31,9 @@ impl Vecs { // Moving average metrics (independent) self.moving_average.compute(price, starting_indexes, exit)?; - // DCA metrics - self.dca.compute(price, starting_indexes, exit)?; + // DCA metrics (depends on lookback for lump sum comparison) + self.dca + .compute(price, &self.lookback, starting_indexes, exit)?; self.indicators.compute( &blocks.rewards, diff --git a/crates/brk_computer/src/market/dca/by_class.rs b/crates/brk_computer/src/market/dca/by_class.rs new file mode 100644 index 000000000..7d7a43066 --- /dev/null +++ b/crates/brk_computer/src/market/dca/by_class.rs @@ -0,0 +1,213 @@ +use brk_traversable::Traversable; +use brk_types::{Date, DateIndex}; + +/// DCA class years +pub const DCA_CLASS_YEARS: ByDcaClass = ByDcaClass { + _2015: 2015, + _2016: 2016, + _2017: 2017, + _2018: 2018, + _2019: 2019, + _2020: 2020, + _2021: 2021, + _2022: 2022, + _2023: 2023, + _2024: 2024, + _2025: 2025, +}; + +/// DCA class names +pub const DCA_CLASS_NAMES: ByDcaClass<&'static str> = ByDcaClass { + _2015: "dca_class_2015", + _2016: "dca_class_2016", + _2017: "dca_class_2017", + _2018: "dca_class_2018", + _2019: "dca_class_2019", + _2020: "dca_class_2020", + _2021: "dca_class_2021", + _2022: "dca_class_2022", + _2023: "dca_class_2023", + _2024: "dca_class_2024", + _2025: "dca_class_2025", +}; + +/// Generic wrapper for DCA year class data +#[derive(Default, Clone, Traversable)] +pub struct ByDcaClass { + pub _2015: T, + pub _2016: T, + pub _2017: T, + pub _2018: T, + pub _2019: T, + pub _2020: T, + pub _2021: T, + pub _2022: T, + pub _2023: T, + pub _2024: T, + pub _2025: T, +} + +impl ByDcaClass { + pub fn new(mut create: F) -> Self + where + F: FnMut(&'static str, u16, DateIndex) -> T, + { + let n = DCA_CLASS_NAMES; + let y = DCA_CLASS_YEARS; + Self { + _2015: create(n._2015, y._2015, Self::dateindex(y._2015)), + _2016: create(n._2016, y._2016, Self::dateindex(y._2016)), + _2017: create(n._2017, y._2017, Self::dateindex(y._2017)), + _2018: create(n._2018, y._2018, Self::dateindex(y._2018)), + _2019: create(n._2019, y._2019, Self::dateindex(y._2019)), + _2020: create(n._2020, y._2020, Self::dateindex(y._2020)), + _2021: create(n._2021, y._2021, Self::dateindex(y._2021)), + _2022: create(n._2022, y._2022, Self::dateindex(y._2022)), + _2023: create(n._2023, y._2023, Self::dateindex(y._2023)), + _2024: create(n._2024, y._2024, Self::dateindex(y._2024)), + _2025: create(n._2025, y._2025, Self::dateindex(y._2025)), + } + } + + pub fn try_new(mut create: F) -> Result + where + F: FnMut(&'static str, u16, DateIndex) -> Result, + { + let n = DCA_CLASS_NAMES; + let y = DCA_CLASS_YEARS; + Ok(Self { + _2015: create(n._2015, y._2015, Self::dateindex(y._2015))?, + _2016: create(n._2016, y._2016, Self::dateindex(y._2016))?, + _2017: create(n._2017, y._2017, Self::dateindex(y._2017))?, + _2018: create(n._2018, y._2018, Self::dateindex(y._2018))?, + _2019: create(n._2019, y._2019, Self::dateindex(y._2019))?, + _2020: create(n._2020, y._2020, Self::dateindex(y._2020))?, + _2021: create(n._2021, y._2021, Self::dateindex(y._2021))?, + _2022: create(n._2022, y._2022, Self::dateindex(y._2022))?, + _2023: create(n._2023, y._2023, Self::dateindex(y._2023))?, + _2024: create(n._2024, y._2024, Self::dateindex(y._2024))?, + _2025: create(n._2025, y._2025, Self::dateindex(y._2025))?, + }) + } + + pub fn dateindex(year: u16) -> DateIndex { + DateIndex::try_from(Date::new(year, 1, 1)).unwrap() + } + + pub fn iter(&self) -> impl Iterator { + [ + &self._2015, + &self._2016, + &self._2017, + &self._2018, + &self._2019, + &self._2020, + &self._2021, + &self._2022, + &self._2023, + &self._2024, + &self._2025, + ] + .into_iter() + } + + pub fn iter_mut(&mut self) -> impl Iterator { + [ + &mut self._2015, + &mut self._2016, + &mut self._2017, + &mut self._2018, + &mut self._2019, + &mut self._2020, + &mut self._2021, + &mut self._2022, + &mut self._2023, + &mut self._2024, + &mut self._2025, + ] + .into_iter() + } + + pub fn iter_mut_with_dateindex(&mut self) -> impl Iterator { + let y = DCA_CLASS_YEARS; + [ + (&mut self._2015, Self::dateindex(y._2015)), + (&mut self._2016, Self::dateindex(y._2016)), + (&mut self._2017, Self::dateindex(y._2017)), + (&mut self._2018, Self::dateindex(y._2018)), + (&mut self._2019, Self::dateindex(y._2019)), + (&mut self._2020, Self::dateindex(y._2020)), + (&mut self._2021, Self::dateindex(y._2021)), + (&mut self._2022, Self::dateindex(y._2022)), + (&mut self._2023, Self::dateindex(y._2023)), + (&mut self._2024, Self::dateindex(y._2024)), + (&mut self._2025, Self::dateindex(y._2025)), + ] + .into_iter() + } + + pub fn dateindexes() -> [DateIndex; 11] { + let y = DCA_CLASS_YEARS; + [ + Self::dateindex(y._2015), + Self::dateindex(y._2016), + Self::dateindex(y._2017), + Self::dateindex(y._2018), + Self::dateindex(y._2019), + Self::dateindex(y._2020), + Self::dateindex(y._2021), + Self::dateindex(y._2022), + Self::dateindex(y._2023), + Self::dateindex(y._2024), + Self::dateindex(y._2025), + ] + } + + pub fn zip(self, other: ByDcaClass) -> ByDcaClass<(T, U)> { + ByDcaClass { + _2015: (self._2015, other._2015), + _2016: (self._2016, other._2016), + _2017: (self._2017, other._2017), + _2018: (self._2018, other._2018), + _2019: (self._2019, other._2019), + _2020: (self._2020, other._2020), + _2021: (self._2021, other._2021), + _2022: (self._2022, other._2022), + _2023: (self._2023, other._2023), + _2024: (self._2024, other._2024), + _2025: (self._2025, other._2025), + } + } + + pub fn zip_ref<'a, U>(&'a self, other: &'a ByDcaClass) -> ByDcaClass<(&'a T, &'a U)> { + ByDcaClass { + _2015: (&self._2015, &other._2015), + _2016: (&self._2016, &other._2016), + _2017: (&self._2017, &other._2017), + _2018: (&self._2018, &other._2018), + _2019: (&self._2019, &other._2019), + _2020: (&self._2020, &other._2020), + _2021: (&self._2021, &other._2021), + _2022: (&self._2022, &other._2022), + _2023: (&self._2023, &other._2023), + _2024: (&self._2024, &other._2024), + _2025: (&self._2025, &other._2025), + } + } + + pub fn map U>(self, mut f: F) -> ByDcaClass { + ByDcaClass { + _2015: f(self._2015), + _2016: f(self._2016), + _2017: f(self._2017), + _2018: f(self._2018), + _2019: f(self._2019), + _2020: f(self._2020), + _2021: f(self._2021), + _2022: f(self._2022), + _2023: f(self._2023), + _2024: f(self._2024), + _2025: f(self._2025), + } + } +} diff --git a/crates/brk_computer/src/market/dca/by_period.rs b/crates/brk_computer/src/market/dca/by_period.rs new file mode 100644 index 000000000..4ccb29b07 --- /dev/null +++ b/crates/brk_computer/src/market/dca/by_period.rs @@ -0,0 +1,395 @@ +use brk_traversable::Traversable; + +/// DCA period identifiers with their day counts +pub const DCA_PERIOD_DAYS: ByDcaPeriod = ByDcaPeriod { + _1w: 7, + _1m: 30, + _3m: 3 * 30, + _6m: 6 * 30, + _1y: 365, + _2y: 2 * 365, + _3y: 3 * 365, + _4y: 4 * 365, + _5y: 5 * 365, + _6y: 6 * 365, + _8y: 8 * 365, + _10y: 10 * 365, +}; + +/// DCA period names +pub const DCA_PERIOD_NAMES: ByDcaPeriod<&'static str> = ByDcaPeriod { + _1w: "1w", + _1m: "1m", + _3m: "3m", + _6m: "6m", + _1y: "1y", + _2y: "2y", + _3y: "3y", + _4y: "4y", + _5y: "5y", + _6y: "6y", + _8y: "8y", + _10y: "10y", +}; + +/// DCA CAGR period days (only periods >= 2y) +pub const DCA_CAGR_DAYS: ByDcaCagr = ByDcaCagr { + _2y: 2 * 365, + _3y: 3 * 365, + _4y: 4 * 365, + _5y: 5 * 365, + _6y: 6 * 365, + _8y: 8 * 365, + _10y: 10 * 365, +}; + +/// DCA CAGR period names +pub const DCA_CAGR_NAMES: ByDcaCagr<&'static str> = ByDcaCagr { + _2y: "2y", + _3y: "3y", + _4y: "4y", + _5y: "5y", + _6y: "6y", + _8y: "8y", + _10y: "10y", +}; + +/// Generic wrapper for DCA period-based data +#[derive(Default, Clone, Traversable)] +pub struct ByDcaPeriod { + pub _1w: T, + pub _1m: T, + pub _3m: T, + pub _6m: T, + pub _1y: T, + pub _2y: T, + pub _3y: T, + pub _4y: T, + pub _5y: T, + pub _6y: T, + pub _8y: T, + pub _10y: T, +} + +impl ByDcaPeriod { + pub fn new(mut create: F) -> Self + where + F: FnMut(&'static str, u32) -> T, + { + let n = DCA_PERIOD_NAMES; + let d = DCA_PERIOD_DAYS; + Self { + _1w: create(n._1w, d._1w), + _1m: create(n._1m, d._1m), + _3m: create(n._3m, d._3m), + _6m: create(n._6m, d._6m), + _1y: create(n._1y, d._1y), + _2y: create(n._2y, d._2y), + _3y: create(n._3y, d._3y), + _4y: create(n._4y, d._4y), + _5y: create(n._5y, d._5y), + _6y: create(n._6y, d._6y), + _8y: create(n._8y, d._8y), + _10y: create(n._10y, d._10y), + } + } + + pub fn try_new(mut create: F) -> Result + where + F: FnMut(&'static str, u32) -> Result, + { + let n = DCA_PERIOD_NAMES; + let d = DCA_PERIOD_DAYS; + Ok(Self { + _1w: create(n._1w, d._1w)?, + _1m: create(n._1m, d._1m)?, + _3m: create(n._3m, d._3m)?, + _6m: create(n._6m, d._6m)?, + _1y: create(n._1y, d._1y)?, + _2y: create(n._2y, d._2y)?, + _3y: create(n._3y, d._3y)?, + _4y: create(n._4y, d._4y)?, + _5y: create(n._5y, d._5y)?, + _6y: create(n._6y, d._6y)?, + _8y: create(n._8y, d._8y)?, + _10y: create(n._10y, d._10y)?, + }) + } + + pub fn iter(&self) -> impl Iterator { + [ + &self._1w, + &self._1m, + &self._3m, + &self._6m, + &self._1y, + &self._2y, + &self._3y, + &self._4y, + &self._5y, + &self._6y, + &self._8y, + &self._10y, + ] + .into_iter() + } + + pub fn iter_mut(&mut self) -> impl Iterator { + [ + &mut self._1w, + &mut self._1m, + &mut self._3m, + &mut self._6m, + &mut self._1y, + &mut self._2y, + &mut self._3y, + &mut self._4y, + &mut self._5y, + &mut self._6y, + &mut self._8y, + &mut self._10y, + ] + .into_iter() + } + + pub fn iter_with_days(&self) -> impl Iterator { + let d = DCA_PERIOD_DAYS; + [ + (&self._1w, d._1w), + (&self._1m, d._1m), + (&self._3m, d._3m), + (&self._6m, d._6m), + (&self._1y, d._1y), + (&self._2y, d._2y), + (&self._3y, d._3y), + (&self._4y, d._4y), + (&self._5y, d._5y), + (&self._6y, d._6y), + (&self._8y, d._8y), + (&self._10y, d._10y), + ] + .into_iter() + } + + pub fn iter_mut_with_days(&mut self) -> impl Iterator { + let d = DCA_PERIOD_DAYS; + [ + (&mut self._1w, d._1w), + (&mut self._1m, d._1m), + (&mut self._3m, d._3m), + (&mut self._6m, d._6m), + (&mut self._1y, d._1y), + (&mut self._2y, d._2y), + (&mut self._3y, d._3y), + (&mut self._4y, d._4y), + (&mut self._5y, d._5y), + (&mut self._6y, d._6y), + (&mut self._8y, d._8y), + (&mut self._10y, d._10y), + ] + .into_iter() + } + + pub fn zip_mut<'a, U>(&'a mut self, other: &'a ByDcaPeriod) -> impl Iterator { + [ + (&mut self._1w, &other._1w), + (&mut self._1m, &other._1m), + (&mut self._3m, &other._3m), + (&mut self._6m, &other._6m), + (&mut self._1y, &other._1y), + (&mut self._2y, &other._2y), + (&mut self._3y, &other._3y), + (&mut self._4y, &other._4y), + (&mut self._5y, &other._5y), + (&mut self._6y, &other._6y), + (&mut self._8y, &other._8y), + (&mut self._10y, &other._10y), + ] + .into_iter() + } + + pub fn zip_mut_with_days<'a, U>( + &'a mut self, + other: &'a ByDcaPeriod, + ) -> impl Iterator { + let d = DCA_PERIOD_DAYS; + [ + (&mut self._1w, &other._1w, d._1w), + (&mut self._1m, &other._1m, d._1m), + (&mut self._3m, &other._3m, d._3m), + (&mut self._6m, &other._6m, d._6m), + (&mut self._1y, &other._1y, d._1y), + (&mut self._2y, &other._2y, d._2y), + (&mut self._3y, &other._3y, d._3y), + (&mut self._4y, &other._4y, d._4y), + (&mut self._5y, &other._5y, d._5y), + (&mut self._6y, &other._6y, d._6y), + (&mut self._8y, &other._8y, d._8y), + (&mut self._10y, &other._10y, d._10y), + ] + .into_iter() + } + + pub fn zip_ref<'a, U>(&'a self, other: &'a ByDcaPeriod) -> ByDcaPeriod<(&'a T, &'a U)> { + ByDcaPeriod { + _1w: (&self._1w, &other._1w), + _1m: (&self._1m, &other._1m), + _3m: (&self._3m, &other._3m), + _6m: (&self._6m, &other._6m), + _1y: (&self._1y, &other._1y), + _2y: (&self._2y, &other._2y), + _3y: (&self._3y, &other._3y), + _4y: (&self._4y, &other._4y), + _5y: (&self._5y, &other._5y), + _6y: (&self._6y, &other._6y), + _8y: (&self._8y, &other._8y), + _10y: (&self._10y, &other._10y), + } + } + + pub fn map U>(self, mut f: F) -> ByDcaPeriod { + ByDcaPeriod { + _1w: f(self._1w), + _1m: f(self._1m), + _3m: f(self._3m), + _6m: f(self._6m), + _1y: f(self._1y), + _2y: f(self._2y), + _3y: f(self._3y), + _4y: f(self._4y), + _5y: f(self._5y), + _6y: f(self._6y), + _8y: f(self._8y), + _10y: f(self._10y), + } + } + + pub fn zip_mut2_with_days<'a, U, V>( + &'a mut self, + other1: &'a ByDcaPeriod, + other2: &'a ByDcaPeriod, + ) -> impl Iterator { + let d = DCA_PERIOD_DAYS; + [ + (&mut self._1w, &other1._1w, &other2._1w, d._1w), + (&mut self._1m, &other1._1m, &other2._1m, d._1m), + (&mut self._3m, &other1._3m, &other2._3m, d._3m), + (&mut self._6m, &other1._6m, &other2._6m, d._6m), + (&mut self._1y, &other1._1y, &other2._1y, d._1y), + (&mut self._2y, &other1._2y, &other2._2y, d._2y), + (&mut self._3y, &other1._3y, &other2._3y, d._3y), + (&mut self._4y, &other1._4y, &other2._4y, d._4y), + (&mut self._5y, &other1._5y, &other2._5y, d._5y), + (&mut self._6y, &other1._6y, &other2._6y, d._6y), + (&mut self._8y, &other1._8y, &other2._8y, d._8y), + (&mut self._10y, &other1._10y, &other2._10y, d._10y), + ] + .into_iter() + } +} + +/// Generic wrapper for DCA CAGR data (periods >= 2 years) +#[derive(Default, Clone, Traversable)] +pub struct ByDcaCagr { + pub _2y: T, + pub _3y: T, + pub _4y: T, + pub _5y: T, + pub _6y: T, + pub _8y: T, + pub _10y: T, +} + +impl ByDcaCagr { + pub fn new(mut create: F) -> Self + where + F: FnMut(&'static str, u32) -> T, + { + let n = DCA_CAGR_NAMES; + let d = DCA_CAGR_DAYS; + Self { + _2y: create(n._2y, d._2y), + _3y: create(n._3y, d._3y), + _4y: create(n._4y, d._4y), + _5y: create(n._5y, d._5y), + _6y: create(n._6y, d._6y), + _8y: create(n._8y, d._8y), + _10y: create(n._10y, d._10y), + } + } + + pub fn try_new(mut create: F) -> Result + where + F: FnMut(&'static str, u32) -> Result, + { + let n = DCA_CAGR_NAMES; + let d = DCA_CAGR_DAYS; + Ok(Self { + _2y: create(n._2y, d._2y)?, + _3y: create(n._3y, d._3y)?, + _4y: create(n._4y, d._4y)?, + _5y: create(n._5y, d._5y)?, + _6y: create(n._6y, d._6y)?, + _8y: create(n._8y, d._8y)?, + _10y: create(n._10y, d._10y)?, + }) + } + + pub fn iter(&self) -> impl Iterator { + [ + &self._2y, + &self._3y, + &self._4y, + &self._5y, + &self._6y, + &self._8y, + &self._10y, + ] + .into_iter() + } + + pub fn iter_mut(&mut self) -> impl Iterator { + [ + &mut self._2y, + &mut self._3y, + &mut self._4y, + &mut self._5y, + &mut self._6y, + &mut self._8y, + &mut self._10y, + ] + .into_iter() + } + + pub fn iter_mut_with_days(&mut self) -> impl Iterator { + let d = DCA_CAGR_DAYS; + [ + (&mut self._2y, d._2y), + (&mut self._3y, d._3y), + (&mut self._4y, d._4y), + (&mut self._5y, d._5y), + (&mut self._6y, d._6y), + (&mut self._8y, d._8y), + (&mut self._10y, d._10y), + ] + .into_iter() + } + + /// Zip with the matching subset of a ByDcaPeriod + pub fn zip_mut_with_period<'a, U>( + &'a mut self, + period: &'a ByDcaPeriod, + ) -> impl Iterator { + let d = DCA_CAGR_DAYS; + [ + (&mut self._2y, &period._2y, d._2y), + (&mut self._3y, &period._3y, d._3y), + (&mut self._4y, &period._4y, d._4y), + (&mut self._5y, &period._5y, d._5y), + (&mut self._6y, &period._6y, d._6y), + (&mut self._8y, &period._8y, d._8y), + (&mut self._10y, &period._10y, d._10y), + ] + .into_iter() + } +} diff --git a/crates/brk_computer/src/market/dca/compute.rs b/crates/brk_computer/src/market/dca/compute.rs index cc2562971..fde31bb01 100644 --- a/crates/brk_computer/src/market/dca/compute.rs +++ b/crates/brk_computer/src/market/dca/compute.rs @@ -1,11 +1,11 @@ use brk_error::Result; -use brk_types::{Date, DateIndex}; use vecdb::Exit; use super::Vecs; use crate::{ + market::lookback, price, - traits::{ComputeDCAAveragePriceViaLen, ComputeDCAStackViaLen}, + traits::{ComputeDCAAveragePriceViaLen, ComputeDCAStackViaLen, ComputeLumpSumStackViaLen}, utils::OptionExt, ComputeIndexes, }; @@ -14,334 +14,79 @@ impl Vecs { pub fn compute( &mut self, price: &price::Vecs, + lookback: &lookback::Vecs, starting_indexes: &ComputeIndexes, exit: &Exit, ) -> Result<()> { let close = price.usd.timeindexes_to_price_close.dateindex.u(); - // DCA by period - stack and avg_price - self._1w_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 7, exit)?; - Ok(()) - })?; - self._1w_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._1w_dca_stack.dateindex.u(), - 7, - exit, - )?; + // DCA by period - stack + for (stack, days) in self.period_stack.iter_mut_with_days() { + stack.compute_all(Some(price), starting_indexes, exit, |v| { + v.compute_dca_stack_via_len(starting_indexes.dateindex, close, days as usize, exit)?; Ok(()) })?; + } - self._1m_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 30, exit)?; - Ok(()) - })?; - self._1m_dca_avg_price - .compute_all(starting_indexes, exit, |v| { + // DCA by period - avg_price (needs stack's dateindex) + for (avg_price, stack, days) in self + .period_avg_price + .zip_mut_with_days(&self.period_stack) + { + avg_price.compute_all(starting_indexes, exit, |v| { v.compute_dca_avg_price_via_len( starting_indexes.dateindex, - self._1m_dca_stack.dateindex.u(), - 30, - exit, - )?; - Ok(()) - })?; - - self._3m_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 3 * 30, exit)?; - Ok(()) - })?; - self._3m_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._3m_dca_stack.dateindex.u(), - 3 * 30, - exit, - )?; - Ok(()) - })?; - - self._6m_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 6 * 30, exit)?; - Ok(()) - })?; - self._6m_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._6m_dca_stack.dateindex.u(), - 6 * 30, - exit, - )?; - Ok(()) - })?; - - self._1y_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 365, exit)?; - Ok(()) - })?; - self._1y_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._1y_dca_stack.dateindex.u(), - 365, - exit, - )?; - Ok(()) - })?; - - self._2y_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 2 * 365, exit)?; - Ok(()) - })?; - self._2y_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._2y_dca_stack.dateindex.u(), - 2 * 365, - exit, - )?; - Ok(()) - })?; - - self._3y_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 3 * 365, exit)?; - Ok(()) - })?; - self._3y_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._3y_dca_stack.dateindex.u(), - 3 * 365, - exit, - )?; - Ok(()) - })?; - - self._4y_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 4 * 365, exit)?; - Ok(()) - })?; - self._4y_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._4y_dca_stack.dateindex.u(), - 4 * 365, - exit, - )?; - Ok(()) - })?; - - self._5y_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 5 * 365, exit)?; - Ok(()) - })?; - self._5y_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._5y_dca_stack.dateindex.u(), - 5 * 365, - exit, - )?; - Ok(()) - })?; - - self._6y_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 6 * 365, exit)?; - Ok(()) - })?; - self._6y_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._6y_dca_stack.dateindex.u(), - 6 * 365, - exit, - )?; - Ok(()) - })?; - - self._8y_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 8 * 365, exit)?; - Ok(()) - })?; - self._8y_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._8y_dca_stack.dateindex.u(), - 8 * 365, - exit, - )?; - Ok(()) - })?; - - self._10y_dca_stack - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 10 * 365, exit)?; - Ok(()) - })?; - self._10y_dca_avg_price - .compute_all(starting_indexes, exit, |v| { - v.compute_dca_avg_price_via_len( - starting_indexes.dateindex, - self._10y_dca_stack.dateindex.u(), - 10 * 365, + stack.sats.dateindex.u(), + days as usize, exit, )?; Ok(()) })?; + } // DCA by period - CAGR (computed from returns) - self._2y_dca_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._2y_dca_returns.dateindex.u(), - 2 * 365, - exit, - )?; - Ok(()) - })?; - self._3y_dca_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._3y_dca_returns.dateindex.u(), - 3 * 365, - exit, - )?; - Ok(()) - })?; - self._4y_dca_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._4y_dca_returns.dateindex.u(), - 4 * 365, - exit, - )?; - Ok(()) - })?; - self._5y_dca_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._5y_dca_returns.dateindex.u(), - 5 * 365, - exit, - )?; - Ok(()) - })?; - self._6y_dca_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._6y_dca_returns.dateindex.u(), - 6 * 365, - exit, - )?; - Ok(()) - })?; - self._8y_dca_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._8y_dca_returns.dateindex.u(), - 8 * 365, - exit, - )?; - Ok(()) - })?; - self._10y_dca_cagr - .compute_all(starting_indexes, exit, |v| { + for (cagr, returns, days) in self + .period_cagr + .zip_mut_with_period(&self.period_returns) + { + cagr.compute_all(starting_indexes, exit, |v| { v.compute_cagr( starting_indexes.dateindex, - self._10y_dca_returns.dateindex.u(), - 10 * 365, + returns.dateindex.u(), + days as usize, exit, )?; Ok(()) })?; + } + + // Lump sum by period - stack (for comparison with DCA) + let lookback_dca = lookback.price_ago.as_dca_period(); + for (stack, lookback_price, days) in self + .period_lump_sum_stack + .zip_mut_with_days(&lookback_dca) + { + stack.compute_all(Some(price), starting_indexes, exit, |v| { + v.compute_lump_sum_stack_via_len( + starting_indexes.dateindex, + close, + lookback_price.dateindex.u(), + days as usize, + exit, + )?; + Ok(()) + })?; + } // DCA by year class - stack and avg_price - // Each year class computes DCA from Jan 1 of that year - [ - ( - 2025, - &mut self.dca_class_2025_stack, - &mut self.dca_class_2025_avg_price, - ), - ( - 2024, - &mut self.dca_class_2024_stack, - &mut self.dca_class_2024_avg_price, - ), - ( - 2023, - &mut self.dca_class_2023_stack, - &mut self.dca_class_2023_avg_price, - ), - ( - 2022, - &mut self.dca_class_2022_stack, - &mut self.dca_class_2022_avg_price, - ), - ( - 2021, - &mut self.dca_class_2021_stack, - &mut self.dca_class_2021_avg_price, - ), - ( - 2020, - &mut self.dca_class_2020_stack, - &mut self.dca_class_2020_avg_price, - ), - ( - 2019, - &mut self.dca_class_2019_stack, - &mut self.dca_class_2019_avg_price, - ), - ( - 2018, - &mut self.dca_class_2018_stack, - &mut self.dca_class_2018_avg_price, - ), - ( - 2017, - &mut self.dca_class_2017_stack, - &mut self.dca_class_2017_avg_price, - ), - ( - 2016, - &mut self.dca_class_2016_stack, - &mut self.dca_class_2016_avg_price, - ), - ( - 2015, - &mut self.dca_class_2015_stack, - &mut self.dca_class_2015_avg_price, - ), - ] - .into_iter() - .try_for_each(|(year, stack, avg_price)| -> Result<()> { - let dateindex = DateIndex::try_from(Date::new(year, 1, 1)).unwrap(); - - stack.compute_all(starting_indexes, exit, |v| { + let dateindexes = super::ByDcaClass::<()>::dateindexes(); + for ((stack, avg_price), dateindex) in self + .class_stack + .iter_mut() + .zip(self.class_avg_price.iter_mut()) + .zip(dateindexes) + { + stack.compute_all(Some(price), starting_indexes, exit, |v| { v.compute_dca_stack_via_from(starting_indexes.dateindex, close, dateindex, exit)?; Ok(()) })?; @@ -349,15 +94,13 @@ impl Vecs { avg_price.compute_all(starting_indexes, exit, |v| { v.compute_dca_avg_price_via_from( starting_indexes.dateindex, - stack.dateindex.u(), + stack.sats.dateindex.u(), dateindex, exit, )?; Ok(()) })?; - - Ok(()) - })?; + } Ok(()) } diff --git a/crates/brk_computer/src/market/dca/import.rs b/crates/brk_computer/src/market/dca/import.rs index 11c2610a5..26c4335ee 100644 --- a/crates/brk_computer/src/market/dca/import.rs +++ b/crates/brk_computer/src/market/dca/import.rs @@ -2,13 +2,14 @@ use brk_error::Result; use brk_types::Version; use vecdb::Database; -use super::Vecs; +use super::{ByDcaCagr, ByDcaClass, ByDcaPeriod, DCA_CLASS_NAMES, DCA_PERIOD_NAMES, Vecs}; use crate::{ + indexes, internal::{ - ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, PercentageDiffCloseDollars, Source, - VecBuilderOptions, + ComputedValueVecsFromDateIndex, ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, + PercentageDiffCloseDollars, Source, VecBuilderOptions, }, - indexes, price, + price, }; impl Vecs { @@ -18,680 +19,117 @@ impl Vecs { indexes: &indexes::Vecs, price: &price::Vecs, ) -> Result { - let v0 = Version::ZERO; let last = VecBuilderOptions::default().add_last(); // DCA by period - stack - let _1w_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "1w_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _1m_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "1m_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _3m_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "3m_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _6m_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "6m_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _1y_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "1y_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _2y_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "2y_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _3y_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "3y_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _4y_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "4y_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _5y_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "5y_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _6y_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "6y_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _8y_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "8y_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _10y_dca_stack = ComputedVecsFromDateIndex::forced_import( - db, - "10y_dca_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; + let period_stack = ByDcaPeriod::try_new(|name, _days| { + ComputedValueVecsFromDateIndex::forced_import( + db, + &format!("{name}_dca_stack"), + Source::Compute, + version, + last, + true, + indexes, + ) + })?; // DCA by period - avg price - let _1w_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "1w_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _1m_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "1m_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _3m_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "3m_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _6m_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "6m_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _1y_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "1y_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _2y_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "2y_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _3y_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "3y_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _4y_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "4y_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _5y_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "5y_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _6y_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "6y_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _8y_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "8y_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _10y_dca_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "10y_dca_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; + let period_avg_price = ByDcaPeriod::try_new(|name, _days| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_dca_avg_price"), + Source::Compute, + version, + indexes, + last, + ) + })?; - // DCA by period - returns (lazy) - let _1w_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "1w_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_1w_dca_avg_price, - ); - let _1m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "1m_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_1m_dca_avg_price, - ); - let _3m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "3m_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_3m_dca_avg_price, - ); - let _6m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "6m_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_6m_dca_avg_price, - ); - let _1y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "1y_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_1y_dca_avg_price, - ); - let _2y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "2y_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_2y_dca_avg_price, - ); - let _3y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "3y_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_3y_dca_avg_price, - ); - let _4y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "4y_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_4y_dca_avg_price, - ); - let _5y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "5y_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_5y_dca_avg_price, - ); - let _6y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "6y_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_6y_dca_avg_price, - ); - let _8y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::( - "8y_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_8y_dca_avg_price, - ); - let _10y_dca_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "10y_dca_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &_10y_dca_avg_price, - ); + // DCA by period - returns (lazy, derived from price and avg_price) + let period_returns = + DCA_PERIOD_NAMES + .zip_ref(&period_avg_price) + .map(|(name, avg_price)| { + LazyVecsFrom2FromDateIndex::from_computed::( + &format!("{name}_dca_returns"), + version, + &price.usd.timeindexes_to_price_close, + avg_price, + ) + }); // DCA by period - CAGR - let _2y_dca_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "2y_dca_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _3y_dca_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "3y_dca_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _4y_dca_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "4y_dca_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _5y_dca_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "5y_dca_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _6y_dca_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "6y_dca_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _8y_dca_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "8y_dca_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _10y_dca_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "10y_dca_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; + let period_cagr = ByDcaCagr::try_new(|name, _days| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_dca_cagr"), + Source::Compute, + version, + indexes, + last, + ) + })?; + + // Lump sum by period - stack + let period_lump_sum_stack = ByDcaPeriod::try_new(|name, _days| { + ComputedValueVecsFromDateIndex::forced_import( + db, + &format!("{name}_lump_sum_stack"), + Source::Compute, + version, + last, + true, + indexes, + ) + })?; // DCA by year class - stack - let dca_class_2025_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2025_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2024_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2024_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2023_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2023_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2022_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2022_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2021_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2021_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2020_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2020_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2019_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2019_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2018_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2018_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2017_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2017_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2016_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2016_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2015_stack = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2015_stack", - Source::Compute, - version + v0, - indexes, - last, - )?; + let class_stack = ByDcaClass::try_new(|name, _year, _dateindex| { + ComputedValueVecsFromDateIndex::forced_import( + db, + &format!("{name}_stack"), + Source::Compute, + version, + last, + true, + indexes, + ) + })?; // DCA by year class - avg price - let dca_class_2025_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2025_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2024_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2024_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2023_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2023_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2022_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2022_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2021_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2021_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2020_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2020_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2019_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2019_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2018_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2018_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2017_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2017_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2016_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2016_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; - let dca_class_2015_avg_price = ComputedVecsFromDateIndex::forced_import( - db, - "dca_class_2015_avg_price", - Source::Compute, - version + v0, - indexes, - last, - )?; + let class_avg_price = ByDcaClass::try_new(|name, _year, _dateindex| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_avg_price"), + Source::Compute, + version, + indexes, + last, + ) + })?; // DCA by year class - returns (lazy) - let dca_class_2025_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2025_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2025_avg_price, - ); - let dca_class_2024_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2024_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2024_avg_price, - ); - let dca_class_2023_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2023_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2023_avg_price, - ); - let dca_class_2022_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2022_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2022_avg_price, - ); - let dca_class_2021_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2021_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2021_avg_price, - ); - let dca_class_2020_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2020_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2020_avg_price, - ); - let dca_class_2019_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2019_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2019_avg_price, - ); - let dca_class_2018_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2018_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2018_avg_price, - ); - let dca_class_2017_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2017_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2017_avg_price, - ); - let dca_class_2016_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2016_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2016_avg_price, - ); - let dca_class_2015_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "dca_class_2015_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &dca_class_2015_avg_price, - ); + let class_returns = DCA_CLASS_NAMES + .zip_ref(&class_avg_price) + .map(|(name, avg_price)| { + LazyVecsFrom2FromDateIndex::from_computed::( + &format!("{name}_returns"), + version, + &price.usd.timeindexes_to_price_close, + avg_price, + ) + }); Ok(Self { - _1w_dca_stack, - _1m_dca_stack, - _3m_dca_stack, - _6m_dca_stack, - _1y_dca_stack, - _2y_dca_stack, - _3y_dca_stack, - _4y_dca_stack, - _5y_dca_stack, - _6y_dca_stack, - _8y_dca_stack, - _10y_dca_stack, - - _1w_dca_avg_price, - _1m_dca_avg_price, - _3m_dca_avg_price, - _6m_dca_avg_price, - _1y_dca_avg_price, - _2y_dca_avg_price, - _3y_dca_avg_price, - _4y_dca_avg_price, - _5y_dca_avg_price, - _6y_dca_avg_price, - _8y_dca_avg_price, - _10y_dca_avg_price, - - _1w_dca_returns, - _1m_dca_returns, - _3m_dca_returns, - _6m_dca_returns, - _1y_dca_returns, - _2y_dca_returns, - _3y_dca_returns, - _4y_dca_returns, - _5y_dca_returns, - _6y_dca_returns, - _8y_dca_returns, - _10y_dca_returns, - - _2y_dca_cagr, - _3y_dca_cagr, - _4y_dca_cagr, - _5y_dca_cagr, - _6y_dca_cagr, - _8y_dca_cagr, - _10y_dca_cagr, - - dca_class_2025_stack, - dca_class_2024_stack, - dca_class_2023_stack, - dca_class_2022_stack, - dca_class_2021_stack, - dca_class_2020_stack, - dca_class_2019_stack, - dca_class_2018_stack, - dca_class_2017_stack, - dca_class_2016_stack, - dca_class_2015_stack, - - dca_class_2025_avg_price, - dca_class_2024_avg_price, - dca_class_2023_avg_price, - dca_class_2022_avg_price, - dca_class_2021_avg_price, - dca_class_2020_avg_price, - dca_class_2019_avg_price, - dca_class_2018_avg_price, - dca_class_2017_avg_price, - dca_class_2016_avg_price, - dca_class_2015_avg_price, - - dca_class_2025_returns, - dca_class_2024_returns, - dca_class_2023_returns, - dca_class_2022_returns, - dca_class_2021_returns, - dca_class_2020_returns, - dca_class_2019_returns, - dca_class_2018_returns, - dca_class_2017_returns, - dca_class_2016_returns, - dca_class_2015_returns, + period_stack, + period_avg_price, + period_returns, + period_cagr, + period_lump_sum_stack, + class_stack, + class_avg_price, + class_returns, }) } } diff --git a/crates/brk_computer/src/market/dca/mod.rs b/crates/brk_computer/src/market/dca/mod.rs index 1136f9ebd..fcb7904d3 100644 --- a/crates/brk_computer/src/market/dca/mod.rs +++ b/crates/brk_computer/src/market/dca/mod.rs @@ -1,5 +1,9 @@ +mod by_class; +mod by_period; mod compute; mod import; mod vecs; +pub use by_class::*; +pub use by_period::*; pub use vecs::Vecs; diff --git a/crates/brk_computer/src/market/dca/vecs.rs b/crates/brk_computer/src/market/dca/vecs.rs index 6bf14b62b..1d5bda444 100644 --- a/crates/brk_computer/src/market/dca/vecs.rs +++ b/crates/brk_computer/src/market/dca/vecs.rs @@ -1,98 +1,25 @@ use brk_traversable::Traversable; -use brk_types::{Close, Dollars, Sats, StoredF32}; +use brk_types::{Close, Dollars, StoredF32}; -use crate::internal::{ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex}; +use super::{ByDcaCagr, ByDcaClass, ByDcaPeriod}; +use crate::internal::{ + ComputedValueVecsFromDateIndex, ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, +}; /// Dollar-cost averaging metrics by time period and year class #[derive(Clone, Traversable)] pub struct Vecs { - // DCA by period - stack - pub _1w_dca_stack: ComputedVecsFromDateIndex, - pub _1m_dca_stack: ComputedVecsFromDateIndex, - pub _3m_dca_stack: ComputedVecsFromDateIndex, - pub _6m_dca_stack: ComputedVecsFromDateIndex, - pub _1y_dca_stack: ComputedVecsFromDateIndex, - pub _2y_dca_stack: ComputedVecsFromDateIndex, - pub _3y_dca_stack: ComputedVecsFromDateIndex, - pub _4y_dca_stack: ComputedVecsFromDateIndex, - pub _5y_dca_stack: ComputedVecsFromDateIndex, - pub _6y_dca_stack: ComputedVecsFromDateIndex, - pub _8y_dca_stack: ComputedVecsFromDateIndex, - pub _10y_dca_stack: ComputedVecsFromDateIndex, + // DCA by period + pub period_stack: ByDcaPeriod, + pub period_avg_price: ByDcaPeriod>, + pub period_returns: ByDcaPeriod, Dollars>>, + pub period_cagr: ByDcaCagr>, - // DCA by period - avg price - pub _1w_dca_avg_price: ComputedVecsFromDateIndex, - pub _1m_dca_avg_price: ComputedVecsFromDateIndex, - pub _3m_dca_avg_price: ComputedVecsFromDateIndex, - pub _6m_dca_avg_price: ComputedVecsFromDateIndex, - pub _1y_dca_avg_price: ComputedVecsFromDateIndex, - pub _2y_dca_avg_price: ComputedVecsFromDateIndex, - pub _3y_dca_avg_price: ComputedVecsFromDateIndex, - pub _4y_dca_avg_price: ComputedVecsFromDateIndex, - pub _5y_dca_avg_price: ComputedVecsFromDateIndex, - pub _6y_dca_avg_price: ComputedVecsFromDateIndex, - pub _8y_dca_avg_price: ComputedVecsFromDateIndex, - pub _10y_dca_avg_price: ComputedVecsFromDateIndex, + // Lump sum by period (for comparison with DCA) + pub period_lump_sum_stack: ByDcaPeriod, - // DCA by period - returns (lazy) - pub _1w_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _1m_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _3m_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _6m_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _1y_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _2y_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _3y_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _4y_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _5y_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _6y_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _8y_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _10y_dca_returns: LazyVecsFrom2FromDateIndex, Dollars>, - - // DCA by period - CAGR - pub _2y_dca_cagr: ComputedVecsFromDateIndex, - pub _3y_dca_cagr: ComputedVecsFromDateIndex, - pub _4y_dca_cagr: ComputedVecsFromDateIndex, - pub _5y_dca_cagr: ComputedVecsFromDateIndex, - pub _6y_dca_cagr: ComputedVecsFromDateIndex, - pub _8y_dca_cagr: ComputedVecsFromDateIndex, - pub _10y_dca_cagr: ComputedVecsFromDateIndex, - - // DCA by year class - stack - pub dca_class_2025_stack: ComputedVecsFromDateIndex, - pub dca_class_2024_stack: ComputedVecsFromDateIndex, - pub dca_class_2023_stack: ComputedVecsFromDateIndex, - pub dca_class_2022_stack: ComputedVecsFromDateIndex, - pub dca_class_2021_stack: ComputedVecsFromDateIndex, - pub dca_class_2020_stack: ComputedVecsFromDateIndex, - pub dca_class_2019_stack: ComputedVecsFromDateIndex, - pub dca_class_2018_stack: ComputedVecsFromDateIndex, - pub dca_class_2017_stack: ComputedVecsFromDateIndex, - pub dca_class_2016_stack: ComputedVecsFromDateIndex, - pub dca_class_2015_stack: ComputedVecsFromDateIndex, - - // DCA by year class - avg price - pub dca_class_2025_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2024_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2023_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2022_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2021_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2020_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2019_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2018_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2017_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2016_avg_price: ComputedVecsFromDateIndex, - pub dca_class_2015_avg_price: ComputedVecsFromDateIndex, - - // DCA by year class - returns (lazy) - pub dca_class_2025_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2024_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2023_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2022_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2021_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2020_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2019_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2018_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2017_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2016_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub dca_class_2015_returns: LazyVecsFrom2FromDateIndex, Dollars>, + // DCA by year class + pub class_stack: ByDcaClass, + pub class_avg_price: ByDcaClass>, + pub class_returns: ByDcaClass, Dollars>>, } diff --git a/crates/brk_computer/src/market/import.rs b/crates/brk_computer/src/market/import.rs index 24b7d3c87..683c96a9c 100644 --- a/crates/brk_computer/src/market/import.rs +++ b/crates/brk_computer/src/market/import.rs @@ -24,7 +24,7 @@ impl Vecs { let db = Database::open(&parent_path.join(super::DB_NAME))?; db.set_min_len(PAGE_SIZE * 1_000_000)?; - let version = parent_version + Version::ZERO; + let version = parent_version; let price = price.expect("price required for market"); @@ -35,7 +35,15 @@ impl Vecs { let range = RangeVecs::forced_import(&db, version, indexes)?; let moving_average = MovingAverageVecs::forced_import(&db, version, indexes, Some(price))?; let dca = DcaVecs::forced_import(&db, version, indexes, price)?; - let indicators = IndicatorsVecs::forced_import(&db, version, indexes, true, distribution, transactions, &moving_average)?; + let indicators = IndicatorsVecs::forced_import( + &db, + version, + indexes, + true, + distribution, + transactions, + &moving_average, + )?; let this = Self { db, diff --git a/crates/brk_computer/src/market/indicators/compute.rs b/crates/brk_computer/src/market/indicators/compute.rs index 17693ba6e..94df09dda 100644 --- a/crates/brk_computer/src/market/indicators/compute.rs +++ b/crates/brk_computer/src/market/indicators/compute.rs @@ -39,7 +39,7 @@ impl Vecs { })?; } - let returns_dateindex = returns._1d_price_returns.dateindex.u(); + let returns_dateindex = returns.price_returns._1d.dateindex.u(); self.dateindex_to_rsi_gains.compute_transform( starting_indexes.dateindex, @@ -55,14 +55,14 @@ impl Vecs { exit, )?; - self.dateindex_to_rsi_avg_gain_14d.compute_sma( + self.dateindex_to_rsi_avg_gain_14d.compute_rma( starting_indexes.dateindex, &self.dateindex_to_rsi_gains, 14, exit, )?; - self.dateindex_to_rsi_avg_loss_14d.compute_sma( + self.dateindex_to_rsi_avg_loss_14d.compute_rma( starting_indexes.dateindex, &self.dateindex_to_rsi_losses, 14, diff --git a/crates/brk_computer/src/market/indicators/import.rs b/crates/brk_computer/src/market/indicators/import.rs index 020c57c95..15c989747 100644 --- a/crates/brk_computer/src/market/indicators/import.rs +++ b/crates/brk_computer/src/market/indicators/import.rs @@ -12,6 +12,8 @@ use crate::{ transactions, }; +const VERSION: Version = Version::ZERO; + impl Vecs { pub fn forced_import( db: &Database, @@ -22,7 +24,7 @@ impl Vecs { transactions: &transactions::Vecs, moving_average: &moving_average::Vecs, ) -> Result { - let v0 = Version::ZERO; + let v = version + VERSION; let last = || VecBuilderOptions::default().add_last(); let indexes_to_nvt = distribution @@ -37,44 +39,45 @@ impl Vecs { .map(|(market_cap, volume)| { LazyVecsFrom2FromDateIndex::from_dateindex_and_height::( "nvt", - version + v0, + v, market_cap, volume, ) }); - let dateindex_to_rsi_gains = EagerVec::forced_import(db, "rsi_gains", version + v0)?; - let dateindex_to_rsi_losses = EagerVec::forced_import(db, "rsi_losses", version + v0)?; + let dateindex_to_rsi_gains = EagerVec::forced_import(db, "rsi_gains", v)?; + let dateindex_to_rsi_losses = EagerVec::forced_import(db, "rsi_losses", v)?; + // v1: Changed from SMA to RMA (Wilder's smoothing) let dateindex_to_rsi_avg_gain_14d = - EagerVec::forced_import(db, "rsi_avg_gain_14d", version + v0)?; + EagerVec::forced_import(db, "rsi_avg_gain_14d", v + Version::ONE)?; let dateindex_to_rsi_avg_loss_14d = - EagerVec::forced_import(db, "rsi_avg_loss_14d", version + v0)?; + EagerVec::forced_import(db, "rsi_avg_loss_14d", v + Version::ONE)?; let dateindex_to_rsi_14d = LazyVecFrom2::transformed::( "rsi_14d", - version + v0, + v, dateindex_to_rsi_avg_gain_14d.boxed_clone(), dateindex_to_rsi_avg_loss_14d.boxed_clone(), ); - let dateindex_to_macd_line = EagerVec::forced_import(db, "macd_line", version + v0)?; - let dateindex_to_macd_signal = EagerVec::forced_import(db, "macd_signal", version + v0)?; + let dateindex_to_macd_line = EagerVec::forced_import(db, "macd_line", v)?; + let dateindex_to_macd_signal = EagerVec::forced_import(db, "macd_signal", v)?; let dateindex_to_macd_histogram = LazyVecFrom2::transformed::( "macd_histogram", - version + v0, + v, dateindex_to_macd_line.boxed_clone(), dateindex_to_macd_signal.boxed_clone(), ); - let dateindex_to_rsi_14d_min = EagerVec::forced_import(db, "rsi_14d_min", version + v0)?; - let dateindex_to_rsi_14d_max = EagerVec::forced_import(db, "rsi_14d_max", version + v0)?; - let dateindex_to_stoch_rsi = EagerVec::forced_import(db, "stoch_rsi", version + v0)?; - let dateindex_to_stoch_rsi_k = EagerVec::forced_import(db, "stoch_rsi_k", version + v0)?; - let dateindex_to_stoch_rsi_d = EagerVec::forced_import(db, "stoch_rsi_d", version + v0)?; + let dateindex_to_rsi_14d_min = EagerVec::forced_import(db, "rsi_14d_min", v)?; + let dateindex_to_rsi_14d_max = EagerVec::forced_import(db, "rsi_14d_max", v)?; + let dateindex_to_stoch_rsi = EagerVec::forced_import(db, "stoch_rsi", v)?; + let dateindex_to_stoch_rsi_k = EagerVec::forced_import(db, "stoch_rsi_k", v)?; + let dateindex_to_stoch_rsi_d = EagerVec::forced_import(db, "stoch_rsi_d", v)?; - let dateindex_to_stoch_k = EagerVec::forced_import(db, "stoch_k", version + v0)?; - let dateindex_to_stoch_d = EagerVec::forced_import(db, "stoch_d", version + v0)?; + let dateindex_to_stoch_k = EagerVec::forced_import(db, "stoch_k", v)?; + let dateindex_to_stoch_d = EagerVec::forced_import(db, "stoch_d", v)?; - let dateindex_to_gini = EagerVec::forced_import(db, "gini", version + v0)?; + let dateindex_to_gini = EagerVec::forced_import(db, "gini", v)?; // Pi Cycle Top: 111d SMA / (2 * 350d SMA) - signals top when > 1 let dateindex_to_pi_cycle = moving_average @@ -86,7 +89,7 @@ impl Vecs { .map(|(sma_111, sma_350_x2)| { LazyVecFrom2::transformed::( "pi_cycle", - version + v0, + v, sma_111.boxed_clone(), sma_350_x2.boxed_clone(), ) @@ -99,7 +102,7 @@ impl Vecs { db, "puell_multiple", Source::Compute, - version + v0, + v, indexes, last(), ) diff --git a/crates/brk_computer/src/market/lookback/by_period.rs b/crates/brk_computer/src/market/lookback/by_period.rs new file mode 100644 index 000000000..ad4733ae9 --- /dev/null +++ b/crates/brk_computer/src/market/lookback/by_period.rs @@ -0,0 +1,215 @@ +use brk_traversable::Traversable; + +use crate::market::dca::ByDcaPeriod; + +/// Lookback period days (includes 1d, unlike DCA) +pub const LOOKBACK_PERIOD_DAYS: ByLookbackPeriod = ByLookbackPeriod { + _1d: 1, + _1w: 7, + _1m: 30, + _3m: 3 * 30, + _6m: 6 * 30, + _1y: 365, + _2y: 2 * 365, + _3y: 3 * 365, + _4y: 4 * 365, + _5y: 5 * 365, + _6y: 6 * 365, + _8y: 8 * 365, + _10y: 10 * 365, +}; + +/// Lookback period names +pub const LOOKBACK_PERIOD_NAMES: ByLookbackPeriod<&'static str> = ByLookbackPeriod { + _1d: "1d", + _1w: "1w", + _1m: "1m", + _3m: "3m", + _6m: "6m", + _1y: "1y", + _2y: "2y", + _3y: "3y", + _4y: "4y", + _5y: "5y", + _6y: "6y", + _8y: "8y", + _10y: "10y", +}; + +/// Generic wrapper for lookback period-based data (includes 1d) +#[derive(Default, Clone, Traversable)] +pub struct ByLookbackPeriod { + pub _1d: T, + pub _1w: T, + pub _1m: T, + pub _3m: T, + pub _6m: T, + pub _1y: T, + pub _2y: T, + pub _3y: T, + pub _4y: T, + pub _5y: T, + pub _6y: T, + pub _8y: T, + pub _10y: T, +} + +impl ByLookbackPeriod { + pub fn new(mut create: F) -> Self + where + F: FnMut(&'static str, u32) -> T, + { + let n = LOOKBACK_PERIOD_NAMES; + let d = LOOKBACK_PERIOD_DAYS; + Self { + _1d: create(n._1d, d._1d), + _1w: create(n._1w, d._1w), + _1m: create(n._1m, d._1m), + _3m: create(n._3m, d._3m), + _6m: create(n._6m, d._6m), + _1y: create(n._1y, d._1y), + _2y: create(n._2y, d._2y), + _3y: create(n._3y, d._3y), + _4y: create(n._4y, d._4y), + _5y: create(n._5y, d._5y), + _6y: create(n._6y, d._6y), + _8y: create(n._8y, d._8y), + _10y: create(n._10y, d._10y), + } + } + + pub fn try_new(mut create: F) -> Result + where + F: FnMut(&'static str, u32) -> Result, + { + let n = LOOKBACK_PERIOD_NAMES; + let d = LOOKBACK_PERIOD_DAYS; + Ok(Self { + _1d: create(n._1d, d._1d)?, + _1w: create(n._1w, d._1w)?, + _1m: create(n._1m, d._1m)?, + _3m: create(n._3m, d._3m)?, + _6m: create(n._6m, d._6m)?, + _1y: create(n._1y, d._1y)?, + _2y: create(n._2y, d._2y)?, + _3y: create(n._3y, d._3y)?, + _4y: create(n._4y, d._4y)?, + _5y: create(n._5y, d._5y)?, + _6y: create(n._6y, d._6y)?, + _8y: create(n._8y, d._8y)?, + _10y: create(n._10y, d._10y)?, + }) + } + + pub fn iter(&self) -> impl Iterator { + [ + &self._1d, + &self._1w, + &self._1m, + &self._3m, + &self._6m, + &self._1y, + &self._2y, + &self._3y, + &self._4y, + &self._5y, + &self._6y, + &self._8y, + &self._10y, + ] + .into_iter() + } + + pub fn iter_mut(&mut self) -> impl Iterator { + [ + &mut self._1d, + &mut self._1w, + &mut self._1m, + &mut self._3m, + &mut self._6m, + &mut self._1y, + &mut self._2y, + &mut self._3y, + &mut self._4y, + &mut self._5y, + &mut self._6y, + &mut self._8y, + &mut self._10y, + ] + .into_iter() + } + + pub fn iter_mut_with_days(&mut self) -> impl Iterator { + let d = LOOKBACK_PERIOD_DAYS; + [ + (&mut self._1d, d._1d), + (&mut self._1w, d._1w), + (&mut self._1m, d._1m), + (&mut self._3m, d._3m), + (&mut self._6m, d._6m), + (&mut self._1y, d._1y), + (&mut self._2y, d._2y), + (&mut self._3y, d._3y), + (&mut self._4y, d._4y), + (&mut self._5y, d._5y), + (&mut self._6y, d._6y), + (&mut self._8y, d._8y), + (&mut self._10y, d._10y), + ] + .into_iter() + } + + /// Get the DCA-matching subset (excludes 1d) + pub fn as_dca_period(&self) -> ByDcaPeriod<&T> { + ByDcaPeriod { + _1w: &self._1w, + _1m: &self._1m, + _3m: &self._3m, + _6m: &self._6m, + _1y: &self._1y, + _2y: &self._2y, + _3y: &self._3y, + _4y: &self._4y, + _5y: &self._5y, + _6y: &self._6y, + _8y: &self._8y, + _10y: &self._10y, + } + } + + pub fn zip_ref<'a, U>(&'a self, other: &'a ByLookbackPeriod) -> ByLookbackPeriod<(&'a T, &'a U)> { + ByLookbackPeriod { + _1d: (&self._1d, &other._1d), + _1w: (&self._1w, &other._1w), + _1m: (&self._1m, &other._1m), + _3m: (&self._3m, &other._3m), + _6m: (&self._6m, &other._6m), + _1y: (&self._1y, &other._1y), + _2y: (&self._2y, &other._2y), + _3y: (&self._3y, &other._3y), + _4y: (&self._4y, &other._4y), + _5y: (&self._5y, &other._5y), + _6y: (&self._6y, &other._6y), + _8y: (&self._8y, &other._8y), + _10y: (&self._10y, &other._10y), + } + } + + pub fn map U>(self, mut f: F) -> ByLookbackPeriod { + ByLookbackPeriod { + _1d: f(self._1d), + _1w: f(self._1w), + _1m: f(self._1m), + _3m: f(self._3m), + _6m: f(self._6m), + _1y: f(self._1y), + _2y: f(self._2y), + _3y: f(self._3y), + _4y: f(self._4y), + _5y: f(self._5y), + _6y: f(self._6y), + _8y: f(self._8y), + _10y: f(self._10y), + } + } +} diff --git a/crates/brk_computer/src/market/lookback/compute.rs b/crates/brk_computer/src/market/lookback/compute.rs index 3d1749c4b..21f9935f1 100644 --- a/crates/brk_computer/src/market/lookback/compute.rs +++ b/crates/brk_computer/src/market/lookback/compute.rs @@ -13,71 +13,12 @@ impl Vecs { ) -> Result<()> { let close = price.usd.timeindexes_to_price_close.dateindex.u(); - self.price_1d_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 1, exit)?; - Ok(()) - })?; - - self.price_1w_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 7, exit)?; - Ok(()) - })?; - - self.price_1m_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 30, exit)?; - Ok(()) - })?; - - self.price_3m_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 3 * 30, exit)?; - Ok(()) - })?; - - self.price_6m_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 6 * 30, exit)?; - Ok(()) - })?; - - self.price_1y_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 365, exit)?; - Ok(()) - })?; - - self.price_2y_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 2 * 365, exit)?; - Ok(()) - })?; - - self.price_3y_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 3 * 365, exit)?; - Ok(()) - })?; - - self.price_4y_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 4 * 365, exit)?; - Ok(()) - })?; - - self.price_5y_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 5 * 365, exit)?; - Ok(()) - })?; - - self.price_6y_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 6 * 365, exit)?; - Ok(()) - })?; - - self.price_8y_ago.compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 8 * 365, exit)?; - Ok(()) - })?; - - self.price_10y_ago - .compute_all(starting_indexes, exit, |v| { - v.compute_previous_value(starting_indexes.dateindex, close, 10 * 365, exit)?; + for (price_ago, days) in self.price_ago.iter_mut_with_days() { + price_ago.compute_all(starting_indexes, exit, |v| { + v.compute_previous_value(starting_indexes.dateindex, close, days as usize, exit)?; Ok(()) })?; + } Ok(()) } diff --git a/crates/brk_computer/src/market/lookback/import.rs b/crates/brk_computer/src/market/lookback/import.rs index f4d926a08..dab87c4b0 100644 --- a/crates/brk_computer/src/market/lookback/import.rs +++ b/crates/brk_computer/src/market/lookback/import.rs @@ -2,140 +2,27 @@ use brk_error::Result; use brk_types::Version; use vecdb::Database; -use super::Vecs; +use super::{ByLookbackPeriod, Vecs}; use crate::{ indexes, internal::{ComputedVecsFromDateIndex, Source, VecBuilderOptions}, }; impl Vecs { - pub fn forced_import( - db: &Database, - version: Version, - indexes: &indexes::Vecs, - ) -> Result { - let v0 = Version::ZERO; + pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result { let last = VecBuilderOptions::default().add_last(); - let price_1d_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_1d_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_1w_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_1w_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_1m_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_1m_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_3m_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_3m_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_6m_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_6m_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_1y_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_1y_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_2y_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_2y_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_3y_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_3y_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_4y_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_4y_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_5y_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_5y_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_6y_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_6y_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_8y_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_8y_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; - let price_10y_ago = ComputedVecsFromDateIndex::forced_import( - db, - "price_10y_ago", - Source::Compute, - version + v0, - indexes, - last, - )?; + let price_ago = ByLookbackPeriod::try_new(|name, _days| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("price_{name}_ago"), + Source::Compute, + version, + indexes, + last, + ) + })?; - Ok(Self { - price_1d_ago, - price_1w_ago, - price_1m_ago, - price_3m_ago, - price_6m_ago, - price_1y_ago, - price_2y_ago, - price_3y_ago, - price_4y_ago, - price_5y_ago, - price_6y_ago, - price_8y_ago, - price_10y_ago, - }) + Ok(Self { price_ago }) } } diff --git a/crates/brk_computer/src/market/lookback/mod.rs b/crates/brk_computer/src/market/lookback/mod.rs index 1136f9ebd..bf7af787f 100644 --- a/crates/brk_computer/src/market/lookback/mod.rs +++ b/crates/brk_computer/src/market/lookback/mod.rs @@ -1,5 +1,7 @@ +mod by_period; mod compute; mod import; mod vecs; +pub use by_period::*; pub use vecs::Vecs; diff --git a/crates/brk_computer/src/market/lookback/vecs.rs b/crates/brk_computer/src/market/lookback/vecs.rs index d873f0d8a..f5dafb3c1 100644 --- a/crates/brk_computer/src/market/lookback/vecs.rs +++ b/crates/brk_computer/src/market/lookback/vecs.rs @@ -1,22 +1,11 @@ use brk_traversable::Traversable; use brk_types::Dollars; +use super::ByLookbackPeriod; use crate::internal::ComputedVecsFromDateIndex; /// Price lookback metrics #[derive(Clone, Traversable)] pub struct Vecs { - pub price_1d_ago: ComputedVecsFromDateIndex, - pub price_1w_ago: ComputedVecsFromDateIndex, - pub price_1m_ago: ComputedVecsFromDateIndex, - pub price_3m_ago: ComputedVecsFromDateIndex, - pub price_6m_ago: ComputedVecsFromDateIndex, - pub price_1y_ago: ComputedVecsFromDateIndex, - pub price_2y_ago: ComputedVecsFromDateIndex, - pub price_3y_ago: ComputedVecsFromDateIndex, - pub price_4y_ago: ComputedVecsFromDateIndex, - pub price_5y_ago: ComputedVecsFromDateIndex, - pub price_6y_ago: ComputedVecsFromDateIndex, - pub price_8y_ago: ComputedVecsFromDateIndex, - pub price_10y_ago: ComputedVecsFromDateIndex, + pub price_ago: ByLookbackPeriod>, } diff --git a/crates/brk_computer/src/market/moving_average/import.rs b/crates/brk_computer/src/market/moving_average/import.rs index 6d5127589..cf19ebb62 100644 --- a/crates/brk_computer/src/market/moving_average/import.rs +++ b/crates/brk_computer/src/market/moving_average/import.rs @@ -4,8 +4,9 @@ use vecdb::{Database, IterableCloneableVec}; use super::Vecs; use crate::{ + indexes, internal::{ComputedRatioVecsFromDateIndex, DollarsTimesTenths, LazyVecsFromDateIndex}, - indexes, price, + price, }; impl Vecs { @@ -15,13 +16,11 @@ impl Vecs { indexes: &indexes::Vecs, price: Option<&price::Vecs>, ) -> Result { - let v0 = Version::ZERO; - let indexes_to_price_1w_sma = ComputedRatioVecsFromDateIndex::forced_import( db, "price_1w_sma", None, - version + v0, + version, indexes, true, price, @@ -30,7 +29,7 @@ impl Vecs { db, "price_8d_sma", None, - version + v0, + version, indexes, true, price, @@ -39,7 +38,7 @@ impl Vecs { db, "price_13d_sma", None, - version + v0, + version, indexes, true, price, @@ -48,7 +47,7 @@ impl Vecs { db, "price_21d_sma", None, - version + v0, + version, indexes, true, price, @@ -57,7 +56,7 @@ impl Vecs { db, "price_1m_sma", None, - version + v0, + version, indexes, true, price, @@ -66,7 +65,7 @@ impl Vecs { db, "price_34d_sma", None, - version + v0, + version, indexes, true, price, @@ -75,7 +74,7 @@ impl Vecs { db, "price_55d_sma", None, - version + v0, + version, indexes, true, price, @@ -84,7 +83,7 @@ impl Vecs { db, "price_89d_sma", None, - version + v0, + version, indexes, true, price, @@ -93,7 +92,7 @@ impl Vecs { db, "price_111d_sma", None, - version + v0, + version, indexes, true, price, @@ -102,7 +101,7 @@ impl Vecs { db, "price_144d_sma", None, - version + v0, + version, indexes, true, price, @@ -111,7 +110,7 @@ impl Vecs { db, "price_200d_sma", None, - version + v0, + version, indexes, true, price, @@ -120,7 +119,7 @@ impl Vecs { db, "price_350d_sma", None, - version + v0, + version, indexes, true, price, @@ -129,7 +128,7 @@ impl Vecs { db, "price_1y_sma", None, - version + v0, + version, indexes, true, price, @@ -138,7 +137,7 @@ impl Vecs { db, "price_2y_sma", None, - version + v0, + version, indexes, true, price, @@ -147,7 +146,7 @@ impl Vecs { db, "price_200w_sma", None, - version + v0, + version, indexes, true, price, @@ -156,7 +155,7 @@ impl Vecs { db, "price_4y_sma", None, - version + v0, + version, indexes, true, price, @@ -166,7 +165,7 @@ impl Vecs { db, "price_1w_ema", None, - version + v0, + version, indexes, true, price, @@ -175,7 +174,7 @@ impl Vecs { db, "price_8d_ema", None, - version + v0, + version, indexes, true, price, @@ -184,7 +183,7 @@ impl Vecs { db, "price_12d_ema", None, - version + v0, + version, indexes, true, price, @@ -193,7 +192,7 @@ impl Vecs { db, "price_13d_ema", None, - version + v0, + version, indexes, true, price, @@ -202,7 +201,7 @@ impl Vecs { db, "price_21d_ema", None, - version + v0, + version, indexes, true, price, @@ -211,7 +210,7 @@ impl Vecs { db, "price_26d_ema", None, - version + v0, + version, indexes, true, price, @@ -220,7 +219,7 @@ impl Vecs { db, "price_1m_ema", None, - version + v0, + version, indexes, true, price, @@ -229,7 +228,7 @@ impl Vecs { db, "price_34d_ema", None, - version + v0, + version, indexes, true, price, @@ -238,7 +237,7 @@ impl Vecs { db, "price_55d_ema", None, - version + v0, + version, indexes, true, price, @@ -247,7 +246,7 @@ impl Vecs { db, "price_89d_ema", None, - version + v0, + version, indexes, true, price, @@ -256,7 +255,7 @@ impl Vecs { db, "price_144d_ema", None, - version + v0, + version, indexes, true, price, @@ -265,7 +264,7 @@ impl Vecs { db, "price_200d_ema", None, - version + v0, + version, indexes, true, price, @@ -274,7 +273,7 @@ impl Vecs { db, "price_1y_ema", None, - version + v0, + version, indexes, true, price, @@ -283,7 +282,7 @@ impl Vecs { db, "price_2y_ema", None, - version + v0, + version, indexes, true, price, @@ -292,7 +291,7 @@ impl Vecs { db, "price_200w_ema", None, - version + v0, + version, indexes, true, price, @@ -301,7 +300,7 @@ impl Vecs { db, "price_4y_ema", None, - version + v0, + version, indexes, true, price, @@ -311,7 +310,7 @@ impl Vecs { let indexes_to_price_200d_sma_x2_4 = LazyVecsFromDateIndex::from_computed::>( "price_200d_sma_x2_4", - version + v0, + version, price_200d_sma_source .dateindex .as_ref() @@ -321,7 +320,7 @@ impl Vecs { let indexes_to_price_200d_sma_x0_8 = LazyVecsFromDateIndex::from_computed::>( "price_200d_sma_x0_8", - version + v0, + version, price_200d_sma_source .dateindex .as_ref() @@ -333,7 +332,7 @@ impl Vecs { let indexes_to_price_350d_sma_x2 = LazyVecsFromDateIndex::from_computed::>( "price_350d_sma_x2", - version + v0, + version, price_350d_sma_source .dateindex .as_ref() diff --git a/crates/brk_computer/src/market/range/import.rs b/crates/brk_computer/src/market/range/import.rs index 854c099a8..d9f4c882e 100644 --- a/crates/brk_computer/src/market/range/import.rs +++ b/crates/brk_computer/src/market/range/import.rs @@ -4,13 +4,12 @@ use vecdb::{Database, EagerVec, ImportableVec}; use super::Vecs; use crate::{ - internal::{ComputedVecsFromDateIndex, Source, VecBuilderOptions}, indexes, + internal::{ComputedVecsFromDateIndex, Source, VecBuilderOptions}, }; impl Vecs { pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result { - let v0 = Version::ZERO; let v1 = Version::ONE; let last = VecBuilderOptions::default().add_last(); @@ -82,12 +81,12 @@ impl Vecs { dateindex_to_price_true_range: EagerVec::forced_import( db, "price_true_range", - version + v0, + version, )?, dateindex_to_price_true_range_2w_sum: EagerVec::forced_import( db, "price_true_range_2w_sum", - version + v0, + version, )?, indexes_to_price_2w_choppiness_index: ComputedVecsFromDateIndex::forced_import( db, diff --git a/crates/brk_computer/src/market/returns/compute.rs b/crates/brk_computer/src/market/returns/compute.rs index f48d5ff11..939b0cc9a 100644 --- a/crates/brk_computer/src/market/returns/compute.rs +++ b/crates/brk_computer/src/market/returns/compute.rs @@ -7,73 +7,22 @@ use crate::{utils::OptionExt, ComputeIndexes}; impl Vecs { pub fn compute(&mut self, starting_indexes: &ComputeIndexes, exit: &Exit) -> Result<()> { - // CAGR computed from returns - self._2y_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._2y_price_returns.dateindex.u(), - 2 * 365, - exit, - )?; - Ok(()) - })?; - self._3y_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._3y_price_returns.dateindex.u(), - 3 * 365, - exit, - )?; - Ok(()) - })?; - self._4y_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._4y_price_returns.dateindex.u(), - 4 * 365, - exit, - )?; - Ok(()) - })?; - self._5y_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._5y_price_returns.dateindex.u(), - 5 * 365, - exit, - )?; - Ok(()) - })?; - self._6y_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._6y_price_returns.dateindex.u(), - 6 * 365, - exit, - )?; - Ok(()) - })?; - self._8y_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._8y_price_returns.dateindex.u(), - 8 * 365, - exit, - )?; - Ok(()) - })?; - self._10y_cagr.compute_all(starting_indexes, exit, |v| { - v.compute_cagr( - starting_indexes.dateindex, - self._10y_price_returns.dateindex.u(), - 10 * 365, - exit, - )?; - Ok(()) - })?; + // CAGR computed from returns (2y+ periods only) + let price_returns_dca = self.price_returns.as_dca_period(); + for (cagr, returns, days) in self.cagr.zip_mut_with_period(&price_returns_dca) { + cagr.compute_all(starting_indexes, exit, |v| { + v.compute_cagr( + starting_indexes.dateindex, + returns.dateindex.u(), + days as usize, + exit, + )?; + Ok(()) + })?; + } // Returns standard deviation (computed from 1d returns) - let _1d_price_returns_dateindex = self._1d_price_returns.dateindex.u(); + let _1d_price_returns_dateindex = self.price_returns._1d.dateindex.u(); self.indexes_to_1d_returns_1w_sd.compute_all( starting_indexes, diff --git a/crates/brk_computer/src/market/returns/import.rs b/crates/brk_computer/src/market/returns/import.rs index 3e1f6b678..dabfa9608 100644 --- a/crates/brk_computer/src/market/returns/import.rs +++ b/crates/brk_computer/src/market/returns/import.rs @@ -2,15 +2,17 @@ use brk_error::Result; use brk_types::Version; use vecdb::{Database, EagerVec, ImportableVec}; -use super::super::lookback; +use super::super::lookback::{self, LOOKBACK_PERIOD_NAMES}; use super::Vecs; use crate::{ + indexes, internal::{ ComputedStandardDeviationVecsFromDateIndex, ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, PercentageDiffCloseDollars, Source, StandardDeviationVecsOptions, VecBuilderOptions, }, - indexes, price, + market::dca::ByDcaCagr, + price, }; impl Vecs { @@ -21,160 +23,33 @@ impl Vecs { price: &price::Vecs, lookback: &lookback::Vecs, ) -> Result { - let v0 = Version::ZERO; let v1 = Version::ONE; let last = VecBuilderOptions::default().add_last(); - // Price returns (lazy, from price.close and lookback.price_*_ago) - let _1d_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "1d_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_1d_ago, - ); - let _1w_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "1w_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_1w_ago, - ); - let _1m_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "1m_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_1m_ago, - ); - let _3m_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "3m_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_3m_ago, - ); - let _6m_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "6m_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_6m_ago, - ); - let _1y_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "1y_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_1y_ago, - ); - let _2y_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "2y_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_2y_ago, - ); - let _3y_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "3y_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_3y_ago, - ); - let _4y_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "4y_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_4y_ago, - ); - let _5y_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "5y_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_5y_ago, - ); - let _6y_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "6y_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_6y_ago, - ); - let _8y_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "8y_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_8y_ago, - ); - let _10y_price_returns = - LazyVecsFrom2FromDateIndex::from_computed::( - "10y_price_returns", - version + v0, - &price.usd.timeindexes_to_price_close, - &lookback.price_10y_ago, - ); + // Price returns (lazy, from price.close and lookback.price_ago) + let price_returns = + LOOKBACK_PERIOD_NAMES + .zip_ref(&lookback.price_ago) + .map(|(name, price_ago)| { + LazyVecsFrom2FromDateIndex::from_computed::( + &format!("{name}_price_returns"), + version, + &price.usd.timeindexes_to_price_close, + price_ago, + ) + }); - // CAGR (computed) - let _2y_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "2y_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _3y_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "3y_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _4y_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "4y_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _5y_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "5y_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _6y_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "6y_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _8y_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "8y_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; - let _10y_cagr = ComputedVecsFromDateIndex::forced_import( - db, - "10y_cagr", - Source::Compute, - version + v0, - indexes, - last, - )?; + // CAGR (computed, 2y+ only) + let cagr = ByDcaCagr::try_new(|name, _days| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_cagr"), + Source::Compute, + version, + indexes, + last, + ) + })?; // Returns standard deviation (computed from 1d returns) let indexes_to_1d_returns_1w_sd = @@ -213,7 +88,7 @@ impl Vecs { // Downside returns and deviation (for Sortino ratio) let dateindex_to_downside_returns = - EagerVec::forced_import(db, "downside_returns", version + v0)?; + EagerVec::forced_import(db, "downside_returns", version)?; let indexes_to_downside_1w_sd = ComputedStandardDeviationVecsFromDateIndex::forced_import( db, "downside_1w_sd", @@ -246,27 +121,8 @@ impl Vecs { )?; Ok(Self { - _1d_price_returns, - _1w_price_returns, - _1m_price_returns, - _3m_price_returns, - _6m_price_returns, - _1y_price_returns, - _2y_price_returns, - _3y_price_returns, - _4y_price_returns, - _5y_price_returns, - _6y_price_returns, - _8y_price_returns, - _10y_price_returns, - - _2y_cagr, - _3y_cagr, - _4y_cagr, - _5y_cagr, - _6y_cagr, - _8y_cagr, - _10y_cagr, + price_returns, + cagr, indexes_to_1d_returns_1w_sd, indexes_to_1d_returns_1m_sd, diff --git a/crates/brk_computer/src/market/returns/vecs.rs b/crates/brk_computer/src/market/returns/vecs.rs index 7626dfd2b..10bf7236f 100644 --- a/crates/brk_computer/src/market/returns/vecs.rs +++ b/crates/brk_computer/src/market/returns/vecs.rs @@ -2,37 +2,22 @@ use brk_traversable::Traversable; use brk_types::{Close, DateIndex, Dollars, StoredF32}; use vecdb::{EagerVec, PcoVec}; -use crate::internal::{ - ComputedStandardDeviationVecsFromDateIndex, ComputedVecsFromDateIndex, - LazyVecsFrom2FromDateIndex, +use crate::{ + internal::{ + ComputedStandardDeviationVecsFromDateIndex, ComputedVecsFromDateIndex, + LazyVecsFrom2FromDateIndex, + }, + market::{dca::ByDcaCagr, lookback::ByLookbackPeriod}, }; /// Price returns, CAGR, and returns standard deviation metrics #[derive(Clone, Traversable)] pub struct Vecs { - // Price returns (lazy, from price.close and history.price_*_ago) - pub _1d_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _1w_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _1m_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _3m_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _6m_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _1y_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _2y_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _3y_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _4y_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _5y_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _6y_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _8y_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, - pub _10y_price_returns: LazyVecsFrom2FromDateIndex, Dollars>, + // Price returns (lazy, from price.close and lookback.price_ago) + pub price_returns: ByLookbackPeriod, Dollars>>, - // CAGR (computed from returns) - pub _2y_cagr: ComputedVecsFromDateIndex, - pub _3y_cagr: ComputedVecsFromDateIndex, - pub _4y_cagr: ComputedVecsFromDateIndex, - pub _5y_cagr: ComputedVecsFromDateIndex, - pub _6y_cagr: ComputedVecsFromDateIndex, - pub _8y_cagr: ComputedVecsFromDateIndex, - pub _10y_cagr: ComputedVecsFromDateIndex, + // CAGR (computed from returns, 2y+ only) + pub cagr: ByDcaCagr>, // Returns standard deviation (computed from 1d returns) pub indexes_to_1d_returns_1w_sd: ComputedStandardDeviationVecsFromDateIndex, diff --git a/crates/brk_computer/src/market/volatility/import.rs b/crates/brk_computer/src/market/volatility/import.rs index 06e3b3ba9..ff54579f7 100644 --- a/crates/brk_computer/src/market/volatility/import.rs +++ b/crates/brk_computer/src/market/volatility/import.rs @@ -51,7 +51,8 @@ impl Vecs { ); let dateindex_to_sharpe_1w = returns - ._1w_price_returns + .price_returns + ._1w .dateindex .as_ref() .zip(indexes_to_price_1w_volatility.dateindex.as_ref()) @@ -65,7 +66,8 @@ impl Vecs { }); let dateindex_to_sharpe_1m = returns - ._1m_price_returns + .price_returns + ._1m .dateindex .as_ref() .zip(indexes_to_price_1m_volatility.dateindex.as_ref()) @@ -79,7 +81,8 @@ impl Vecs { }); let dateindex_to_sharpe_1y = returns - ._1y_price_returns + .price_returns + ._1y .dateindex .as_ref() .zip(indexes_to_price_1y_volatility.dateindex.as_ref()) @@ -94,7 +97,8 @@ impl Vecs { // Sortino ratio = returns / downside volatility let dateindex_to_sortino_1w = returns - ._1w_price_returns + .price_returns + ._1w .dateindex .as_ref() .zip(returns.indexes_to_downside_1w_sd.sd.dateindex.as_ref()) @@ -108,7 +112,8 @@ impl Vecs { }); let dateindex_to_sortino_1m = returns - ._1m_price_returns + .price_returns + ._1m .dateindex .as_ref() .zip(returns.indexes_to_downside_1m_sd.sd.dateindex.as_ref()) @@ -122,7 +127,8 @@ impl Vecs { }); let dateindex_to_sortino_1y = returns - ._1y_price_returns + .price_returns + ._1y .dateindex .as_ref() .zip(returns.indexes_to_downside_1y_sd.sd.dateindex.as_ref()) diff --git a/crates/brk_computer/src/outputs/count/import.rs b/crates/brk_computer/src/outputs/count/import.rs index 6975a1bc2..80f1a5fa8 100644 --- a/crates/brk_computer/src/outputs/count/import.rs +++ b/crates/brk_computer/src/outputs/count/import.rs @@ -24,7 +24,7 @@ impl Vecs { db, "output_count", Source::Vec(indexes.transaction.txindex_to_output_count.boxed_clone()), - version + Version::ZERO, + version, indexes, full_stats(), )?, @@ -32,7 +32,7 @@ impl Vecs { db, "exact_utxo_count", Source::Compute, - version + Version::ZERO, + version, indexes, full_stats(), )?, diff --git a/crates/brk_computer/src/outputs/import.rs b/crates/brk_computer/src/outputs/import.rs index 324c2a9df..3490c5302 100644 --- a/crates/brk_computer/src/outputs/import.rs +++ b/crates/brk_computer/src/outputs/import.rs @@ -17,7 +17,7 @@ impl Vecs { let db = Database::open(&parent_path.join(super::DB_NAME))?; db.set_min_len(PAGE_SIZE * 10_000_000)?; - let version = parent_version + Version::ZERO; + let version = parent_version; let spent = SpentVecs::forced_import(&db, version)?; let count = CountVecs::forced_import(&db, version, indexes)?; diff --git a/crates/brk_computer/src/pools/mod.rs b/crates/brk_computer/src/pools/mod.rs index e4bc57cc5..a13134bfc 100644 --- a/crates/brk_computer/src/pools/mod.rs +++ b/crates/brk_computer/src/pools/mod.rs @@ -14,9 +14,9 @@ use vecdb::{ mod vecs; use crate::{ - blocks, transactions, + blocks, indexes::{self, ComputeIndexes}, - price, + price, transactions, }; pub const DB_NAME: &str = "pools"; @@ -46,14 +46,14 @@ impl Vecs { let version = parent_version + Version::new(3) + Version::new(pools.len() as u64); let this = Self { - height_to_pool: BytesVec::forced_import(&db, "pool", version + Version::ZERO)?, + height_to_pool: BytesVec::forced_import(&db, "pool", version)?, vecs: pools .iter() .map(|pool| { vecs::Vecs::forced_import( &db, pool.slug, - version + Version::ZERO, + version, indexes, price, blocks, diff --git a/crates/brk_computer/src/pools/vecs.rs b/crates/brk_computer/src/pools/vecs.rs index fd8292b53..0b44c1bf1 100644 --- a/crates/brk_computer/src/pools/vecs.rs +++ b/crates/brk_computer/src/pools/vecs.rs @@ -7,15 +7,15 @@ use vecdb::{ }; use crate::{ - blocks, transactions, + blocks, + indexes::{self, ComputeIndexes}, internal::{ ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight, DollarsPlus, LazyValueVecsFrom2FromHeight, LazyVecsFrom2FromDateIndex, LazyVecsFrom2FromHeight, MaskSats, PercentageU32F32, SatsPlus, SatsPlusToBitcoin, Source, VecBuilderOptions, }, - indexes::{self, ComputeIndexes}, - price, + price, transactions, }; #[derive(Clone, Traversable)] @@ -51,7 +51,7 @@ impl Vecs { ) -> Result { let suffix = |s: &str| format!("{}_{s}", slug); let compute_dollars = price.is_some(); - let version = parent_version + Version::ZERO; + let version = parent_version; let last = VecBuilderOptions::default().add_last(); let sum_cum = VecBuilderOptions::default().add_sum().add_cumulative(); @@ -91,7 +91,8 @@ impl Vecs { .unwrap() .boxed_clone(), blocks - .rewards.indexes_to_subsidy + .rewards + .indexes_to_subsidy .sats .height .as_ref() @@ -117,7 +118,13 @@ impl Vecs { .as_ref() .unwrap() .boxed_clone(), - transactions.fees.indexes_to_fee.sats.height.unwrap_sum().boxed_clone(), + transactions + .fees + .indexes_to_fee + .sats + .height + .unwrap_sum() + .boxed_clone(), ); let indexes_to_fee = ComputedValueVecsFromHeight::forced_import( @@ -140,7 +147,8 @@ impl Vecs { .unwrap() .boxed_clone(), blocks - .count.indexes_to_block_count + .count + .indexes_to_block_count .height .as_ref() .unwrap() @@ -157,7 +165,8 @@ impl Vecs { .unwrap() .boxed_clone(), blocks - .count.indexes_to_block_count + .count + .indexes_to_block_count .height .as_ref() .unwrap() diff --git a/crates/brk_computer/src/positions.rs b/crates/brk_computer/src/positions.rs index 4554f0265..d9c6d4dcb 100644 --- a/crates/brk_computer/src/positions.rs +++ b/crates/brk_computer/src/positions.rs @@ -27,7 +27,7 @@ impl Vecs { let db = Database::open(&parent_path.join(DB_NAME))?; db.set_min_len(PAGE_SIZE * 1_000_000)?; - let version = parent_version + Version::ZERO; + let version = parent_version; let this = Self { height_to_position: PcoVec::forced_import(&db, "position", version + Version::TWO)?, diff --git a/crates/brk_computer/src/scripts/count/import.rs b/crates/brk_computer/src/scripts/count/import.rs index 3ee20cda4..9067c2685 100644 --- a/crates/brk_computer/src/scripts/count/import.rs +++ b/crates/brk_computer/src/scripts/count/import.rs @@ -20,7 +20,6 @@ impl Vecs { indexes: &indexes::Vecs, outputs: &outputs::Vecs, ) -> Result { - let v0 = Version::ZERO; let full_stats = || { VecBuilderOptions::default() .add_average() @@ -34,7 +33,7 @@ impl Vecs { db, "p2a_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -42,7 +41,7 @@ impl Vecs { db, "p2ms_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -50,7 +49,7 @@ impl Vecs { db, "p2pk33_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -58,7 +57,7 @@ impl Vecs { db, "p2pk65_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -66,7 +65,7 @@ impl Vecs { db, "p2pkh_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -74,7 +73,7 @@ impl Vecs { db, "p2sh_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -82,7 +81,7 @@ impl Vecs { db, "p2tr_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -90,7 +89,7 @@ impl Vecs { db, "p2wpkh_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -98,7 +97,7 @@ impl Vecs { db, "p2wsh_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -108,7 +107,7 @@ impl Vecs { db, "segwit_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?; @@ -119,7 +118,7 @@ impl Vecs { let indexes_to_taproot_adoption = LazyVecsFrom2FromHeight::from_height_and_txindex::( "taproot_adoption", - version + v0, + version, indexes_to_p2tr_count.height.u().boxed_clone(), outputs.count.indexes_to_count.height.sum.u().boxed_clone(), &indexes_to_p2tr_count, @@ -128,7 +127,7 @@ impl Vecs { let indexes_to_segwit_adoption = LazyVecsFrom2FromHeight::from_height_and_txindex::( "segwit_adoption", - version + v0, + version, indexes_to_segwit_count.height.u().boxed_clone(), outputs.count.indexes_to_count.height.sum.u().boxed_clone(), &indexes_to_segwit_count, @@ -149,7 +148,7 @@ impl Vecs { db, "opreturn_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?, @@ -157,7 +156,7 @@ impl Vecs { db, "emptyoutput_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?, @@ -165,7 +164,7 @@ impl Vecs { db, "unknownoutput_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?, diff --git a/crates/brk_computer/src/scripts/import.rs b/crates/brk_computer/src/scripts/import.rs index c97215216..f3f6c20e4 100644 --- a/crates/brk_computer/src/scripts/import.rs +++ b/crates/brk_computer/src/scripts/import.rs @@ -20,7 +20,7 @@ impl Vecs { let db = Database::open(&parent_path.join(super::DB_NAME))?; db.set_min_len(PAGE_SIZE * 50_000_000)?; - let version = parent_version + Version::ZERO; + let version = parent_version; let compute_dollars = price.is_some(); let count = CountVecs::forced_import(&db, version, indexes, outputs)?; diff --git a/crates/brk_computer/src/scripts/value/import.rs b/crates/brk_computer/src/scripts/value/import.rs index a6c4e02a6..42d653d74 100644 --- a/crates/brk_computer/src/scripts/value/import.rs +++ b/crates/brk_computer/src/scripts/value/import.rs @@ -15,16 +15,13 @@ impl Vecs { indexes: &indexes::Vecs, compute_dollars: bool, ) -> Result { - let v0 = Version::ZERO; - - let height_to_opreturn_value = - EagerVec::forced_import(db, "opreturn_value", version + v0)?; + let height_to_opreturn_value = EagerVec::forced_import(db, "opreturn_value", version)?; let indexes_to_opreturn_value = ComputedValueVecsFromHeight::forced_import( db, "opreturn_value", Source::Vec(height_to_opreturn_value.boxed_clone()), - version + v0, + version, VecBuilderOptions::default() .add_sum() .add_cumulative() diff --git a/crates/brk_computer/src/supply/burned/import.rs b/crates/brk_computer/src/supply/burned/import.rs index 437277c4c..704b106de 100644 --- a/crates/brk_computer/src/supply/burned/import.rs +++ b/crates/brk_computer/src/supply/burned/import.rs @@ -15,28 +15,25 @@ impl Vecs { indexes: &indexes::Vecs, compute_dollars: bool, ) -> Result { - let v0 = Version::ZERO; - - let height_to_opreturn = EagerVec::forced_import(db, "opreturn_supply", version + v0)?; + let height_to_opreturn = EagerVec::forced_import(db, "opreturn_supply", version)?; let indexes_to_opreturn = ComputedValueVecsFromHeight::forced_import( db, "opreturn_supply", Source::Vec(height_to_opreturn.boxed_clone()), - version + v0, + version, VecBuilderOptions::default().add_last().add_cumulative(), compute_dollars, indexes, )?; - let height_to_unspendable = - EagerVec::forced_import(db, "unspendable_supply", version + v0)?; + let height_to_unspendable = EagerVec::forced_import(db, "unspendable_supply", version)?; let indexes_to_unspendable = ComputedValueVecsFromHeight::forced_import( db, "unspendable_supply", Source::Vec(height_to_unspendable.boxed_clone()), - version + v0, + version, VecBuilderOptions::default().add_last().add_cumulative(), compute_dollars, indexes, diff --git a/crates/brk_computer/src/supply/circulating/import.rs b/crates/brk_computer/src/supply/circulating/import.rs index 6d9959a49..f455a7f1e 100644 --- a/crates/brk_computer/src/supply/circulating/import.rs +++ b/crates/brk_computer/src/supply/circulating/import.rs @@ -9,21 +9,19 @@ use crate::{ impl Vecs { pub fn import(version: Version, distribution: &distribution::Vecs) -> Self { - let v0 = Version::ZERO; - // Reference distribution's actual circulating supply lazily let supply_metrics = &distribution.utxo_cohorts.all.metrics.supply; let height_to_sats = LazyVecFrom1::init( "circulating_sats", - version + v0, + version, supply_metrics.height_to_supply.boxed_clone(), |height, iter| iter.get(height), ); let height_to_btc = LazyVecFrom1::transformed::( "circulating_btc", - version + v0, + version, supply_metrics.height_to_supply.boxed_clone(), ); @@ -34,7 +32,7 @@ impl Vecs { .map(|d| { LazyVecFrom1::init( "circulating_usd", - version + v0, + version, d.boxed_clone(), |height, iter| iter.get(height), ) @@ -45,7 +43,7 @@ impl Vecs { SatsIdentity, SatsToBitcoin, DollarsIdentity, - >("circulating", &supply_metrics.indexes_to_supply, version + v0); + >("circulating", &supply_metrics.indexes_to_supply, version); Self { height_to_sats, diff --git a/crates/brk_computer/src/supply/inflation/import.rs b/crates/brk_computer/src/supply/inflation/import.rs index 637f3a61f..b46b076b9 100644 --- a/crates/brk_computer/src/supply/inflation/import.rs +++ b/crates/brk_computer/src/supply/inflation/import.rs @@ -9,18 +9,12 @@ use crate::{ }; impl Vecs { - pub fn forced_import( - db: &Database, - version: Version, - indexes: &indexes::Vecs, - ) -> Result { - let v0 = Version::ZERO; - + pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result { let indexes_to_inflation_rate = ComputedVecsFromDateIndex::forced_import( db, "inflation_rate", Source::Compute, - version + v0, + version, indexes, VecBuilderOptions::default().add_average(), )?; diff --git a/crates/brk_computer/src/supply/market_cap/import.rs b/crates/brk_computer/src/supply/market_cap/import.rs index a25af611e..6744c5d40 100644 --- a/crates/brk_computer/src/supply/market_cap/import.rs +++ b/crates/brk_computer/src/supply/market_cap/import.rs @@ -9,7 +9,6 @@ use crate::{ impl Vecs { pub fn import(version: Version, distribution: &distribution::Vecs) -> Self { - let v0 = Version::ZERO; let supply_metrics = &distribution.utxo_cohorts.all.metrics.supply; // Market cap by height (lazy from distribution's supply in USD) @@ -18,19 +17,16 @@ impl Vecs { .dollars .as_ref() .map(|d| { - LazyVecFrom1::init( - "market_cap", - version + v0, - d.boxed_clone(), - |height, iter| iter.get(height), - ) + LazyVecFrom1::init("market_cap", version, d.boxed_clone(), |height, iter| { + iter.get(height) + }) }); // Market cap by indexes (lazy from distribution's supply in USD) let indexes = supply_metrics.indexes_to_supply.dollars.as_ref().map(|d| { LazyVecsFromDateIndex::from_computed::( "market_cap", - version + v0, + version, d.dateindex.as_ref().map(|v| v.boxed_clone()), d, ) diff --git a/crates/brk_computer/src/supply/velocity/import.rs b/crates/brk_computer/src/supply/velocity/import.rs index 8fda54071..a9dc05aab 100644 --- a/crates/brk_computer/src/supply/velocity/import.rs +++ b/crates/brk_computer/src/supply/velocity/import.rs @@ -15,13 +15,11 @@ impl Vecs { indexes: &indexes::Vecs, compute_dollars: bool, ) -> Result { - let v0 = Version::ZERO; - let indexes_to_btc = ComputedVecsFromDateIndex::forced_import( db, "btc_velocity", Source::Compute, - version + v0, + version, indexes, VecBuilderOptions::default().add_average(), )?; @@ -31,7 +29,7 @@ impl Vecs { db, "usd_velocity", Source::Compute, - version + v0, + version, indexes, VecBuilderOptions::default().add_average(), ) diff --git a/crates/brk_computer/src/traits.rs b/crates/brk_computer/src/traits.rs index dccd4d75a..9cd4bed27 100644 --- a/crates/brk_computer/src/traits.rs +++ b/crates/brk_computer/src/traits.rs @@ -210,6 +210,53 @@ impl ComputeDCAAveragePriceViaLen for EagerVec> { } } +pub trait ComputeLumpSumStackViaLen { + fn compute_lump_sum_stack_via_len( + &mut self, + max_from: DateIndex, + closes: &impl IterableVec>, + lookback_prices: &impl IterableVec, + len: usize, + exit: &Exit, + ) -> Result<()>; +} + +impl ComputeLumpSumStackViaLen for EagerVec> { + /// Compute lump sum stack: sats you would have if you invested (len * DCA_AMOUNT) at the lookback price + fn compute_lump_sum_stack_via_len( + &mut self, + max_from: DateIndex, + closes: &impl IterableVec>, + lookback_prices: &impl IterableVec, + len: usize, + exit: &Exit, + ) -> Result<()> { + self.validate_computed_version_or_reset(closes.version())?; + + let index = max_from.to_usize().min(self.len()); + let total_invested = DCA_AMOUNT * len; + + lookback_prices + .iter() + .enumerate() + .skip(index) + .try_for_each(|(i, lookback_price)| { + let stack = if lookback_price == Dollars::ZERO { + Sats::ZERO + } else { + Sats::from(Bitcoin::from(total_invested / lookback_price)) + }; + + self.truncate_push_at(i, stack) + })?; + + let _lock = exit.lock(); + self.write()?; + + Ok(()) + } +} + pub trait ComputeFromBitcoin { fn compute_from_bitcoin( &mut self, diff --git a/crates/brk_computer/src/transactions/count/import.rs b/crates/brk_computer/src/transactions/count/import.rs index 84dbd0647..8345224ff 100644 --- a/crates/brk_computer/src/transactions/count/import.rs +++ b/crates/brk_computer/src/transactions/count/import.rs @@ -16,8 +16,6 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, ) -> Result { - let v0 = Version::ZERO; - let full_stats = || { VecBuilderOptions::default() .add_average() @@ -29,7 +27,7 @@ impl Vecs { let txindex_to_is_coinbase = LazyVecFrom2::init( "is_coinbase", - version + v0, + version, indexer.vecs.tx.txindex_to_height.boxed_clone(), indexer.vecs.tx.height_to_first_txindex.boxed_clone(), |index: TxIndex, txindex_to_height_iter, height_to_first_txindex_iter| { @@ -45,7 +43,7 @@ impl Vecs { db, "tx_count", Source::Compute, - version + v0, + version, indexes, full_stats(), )?, diff --git a/crates/brk_computer/src/transactions/fees/import.rs b/crates/brk_computer/src/transactions/fees/import.rs index 38ebbbbf6..6cacfda1e 100644 --- a/crates/brk_computer/src/transactions/fees/import.rs +++ b/crates/brk_computer/src/transactions/fees/import.rs @@ -5,8 +5,9 @@ use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec}; use super::Vecs; use crate::{ - indexes, price, + indexes, internal::{ComputedValueVecsFromTxindex, ComputedVecsFromTxindex, Source, VecBuilderOptions}, + price, }; impl Vecs { @@ -17,8 +18,6 @@ impl Vecs { indexes: &indexes::Vecs, price: Option<&price::Vecs>, ) -> Result { - let v0 = Version::ZERO; - let stats = || { VecBuilderOptions::default() .add_average() @@ -26,10 +25,10 @@ impl Vecs { .add_percentiles() }; - let txindex_to_input_value = EagerVec::forced_import(db, "input_value", version + v0)?; - let txindex_to_output_value = EagerVec::forced_import(db, "output_value", version + v0)?; - let txindex_to_fee = EagerVec::forced_import(db, "fee", version + v0)?; - let txindex_to_fee_rate = EagerVec::forced_import(db, "fee_rate", version + v0)?; + let txindex_to_input_value = EagerVec::forced_import(db, "input_value", version)?; + let txindex_to_output_value = EagerVec::forced_import(db, "output_value", version)?; + let txindex_to_fee = EagerVec::forced_import(db, "fee", version)?; + let txindex_to_fee_rate = EagerVec::forced_import(db, "fee_rate", version)?; Ok(Self { txindex_to_input_value, @@ -42,7 +41,7 @@ impl Vecs { indexer, indexes, Source::Vec(txindex_to_fee.boxed_clone()), - version + v0, + version, price, VecBuilderOptions::default() .add_sum() @@ -55,7 +54,7 @@ impl Vecs { db, "fee_rate", Source::Vec(txindex_to_fee_rate.boxed_clone()), - version + v0, + version, indexes, stats(), )?, diff --git a/crates/brk_computer/src/transactions/import.rs b/crates/brk_computer/src/transactions/import.rs index 04b8abcef..37331e421 100644 --- a/crates/brk_computer/src/transactions/import.rs +++ b/crates/brk_computer/src/transactions/import.rs @@ -21,7 +21,7 @@ impl Vecs { let db = Database::open(&parent_path.join(super::DB_NAME))?; db.set_min_len(PAGE_SIZE * 50_000_000)?; - let version = parent_version + Version::ZERO; + let version = parent_version; let compute_dollars = price.is_some(); let count = CountVecs::forced_import(&db, version, indexer, indexes)?; diff --git a/crates/brk_computer/src/transactions/size/import.rs b/crates/brk_computer/src/transactions/size/import.rs index ceef37540..95319b21d 100644 --- a/crates/brk_computer/src/transactions/size/import.rs +++ b/crates/brk_computer/src/transactions/size/import.rs @@ -16,8 +16,6 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, ) -> Result { - let v0 = Version::ZERO; - let stats = || { VecBuilderOptions::default() .add_average() @@ -27,7 +25,7 @@ impl Vecs { let txindex_to_weight = LazyVecFrom2::init( "weight", - version + v0, + version, indexer.vecs.tx.txindex_to_base_size.boxed_clone(), indexer.vecs.tx.txindex_to_total_size.boxed_clone(), |index: TxIndex, txindex_to_base_size_iter, txindex_to_total_size_iter| { @@ -42,7 +40,7 @@ impl Vecs { // Derive directly from eager sources to avoid Lazy <- Lazy let txindex_to_vsize = LazyVecFrom2::init( "vsize", - version + v0, + version, indexer.vecs.tx.txindex_to_base_size.boxed_clone(), indexer.vecs.tx.txindex_to_total_size.boxed_clone(), |index: TxIndex, txindex_to_base_size_iter, txindex_to_total_size_iter| { @@ -59,7 +57,7 @@ impl Vecs { db, "tx_vsize", Source::Vec(txindex_to_vsize.boxed_clone()), - version + v0, + version, indexes, stats(), )?, @@ -67,7 +65,7 @@ impl Vecs { db, "tx_weight", Source::Vec(txindex_to_weight.boxed_clone()), - version + v0, + version, indexes, stats(), )?, diff --git a/crates/brk_computer/src/transactions/versions/import.rs b/crates/brk_computer/src/transactions/versions/import.rs index 5cdfe4122..6857ad1e0 100644 --- a/crates/brk_computer/src/transactions/versions/import.rs +++ b/crates/brk_computer/src/transactions/versions/import.rs @@ -9,12 +9,7 @@ use crate::{ }; impl Vecs { - pub fn forced_import( - db: &Database, - version: Version, - indexes: &indexes::Vecs, - ) -> Result { - let v0 = Version::ZERO; + pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result { let sum_cum = || VecBuilderOptions::default().add_sum().add_cumulative(); Ok(Self { @@ -22,7 +17,7 @@ impl Vecs { db, "tx_v1", Source::Compute, - version + v0, + version, indexes, sum_cum(), )?, @@ -30,7 +25,7 @@ impl Vecs { db, "tx_v2", Source::Compute, - version + v0, + version, indexes, sum_cum(), )?, @@ -38,7 +33,7 @@ impl Vecs { db, "tx_v3", Source::Compute, - version + v0, + version, indexes, sum_cum(), )?, diff --git a/crates/brk_computer/src/transactions/volume/import.rs b/crates/brk_computer/src/transactions/volume/import.rs index f8e7715a7..14ce7a1f5 100644 --- a/crates/brk_computer/src/transactions/volume/import.rs +++ b/crates/brk_computer/src/transactions/volume/import.rs @@ -4,8 +4,8 @@ use vecdb::Database; use super::Vecs; use crate::{ - internal::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions}, indexes, + internal::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions}, }; impl Vecs { @@ -15,7 +15,6 @@ impl Vecs { indexes: &indexes::Vecs, compute_dollars: bool, ) -> Result { - let v0 = Version::ZERO; let v2 = Version::TWO; let last = || VecBuilderOptions::default().add_last(); @@ -24,7 +23,7 @@ impl Vecs { db, "sent_sum", Source::Compute, - version + v0, + version, VecBuilderOptions::default().add_sum(), compute_dollars, indexes, @@ -33,7 +32,7 @@ impl Vecs { db, "annualized_volume", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -41,7 +40,7 @@ impl Vecs { db, "annualized_volume_btc", Source::Compute, - version + v0, + version, indexes, last(), )?, @@ -49,7 +48,7 @@ impl Vecs { db, "annualized_volume_usd", Source::Compute, - version + v0, + version, indexes, last(), )?, diff --git a/crates/brk_server/src/extended/header_map.rs b/crates/brk_server/src/extended/header_map.rs index 8c821da6e..186f972d0 100644 --- a/crates/brk_server/src/extended/header_map.rs +++ b/crates/brk_server/src/extended/header_map.rs @@ -135,7 +135,7 @@ impl HeaderMapExtended for HeaderMap { .map(|s| s.to_str().unwrap_or_default()) .unwrap_or_default() { - "js" => self.insert_content_type_application_javascript(), + "js" | "mjs" => self.insert_content_type_application_javascript(), "json" | "map" => self.insert_content_type_application_json(), "html" => self.insert_content_type_text_html(), "css" => self.insert_content_type_text_css(), diff --git a/crates/brk_server/src/files/file.rs b/crates/brk_server/src/files/file.rs index 4c8bfad47..27db71083 100644 --- a/crates/brk_server/src/files/file.rs +++ b/crates/brk_server/src/files/file.rs @@ -42,15 +42,29 @@ fn any_handler( let mut path = files_path.join(&sanitized); - // Canonicalize and verify the path stays within the allowed directory + // Canonicalize and verify the path stays within the project root + // (allows symlinks to modules/ which is outside the website directory) if let Ok(canonical) = path.canonicalize() && let Ok(canonical_base) = files_path.canonicalize() - && !canonical.starts_with(&canonical_base) { - let mut response: Response = - (StatusCode::FORBIDDEN, "Access denied".to_string()).into_response(); - response.headers_mut().insert_cors(); - return response; + // Allow paths within files_path OR within project root (2 levels up) + let project_root = canonical_base.parent().and_then(|p| p.parent()); + let allowed = canonical.starts_with(&canonical_base) + || project_root.is_some_and(|root| canonical.starts_with(root)); + if !allowed { + let mut response: Response = + (StatusCode::FORBIDDEN, "Access denied".to_string()).into_response(); + response.headers_mut().insert_cors(); + return response; + } + } + + // Auto-resolve .js extension for ES module imports + if !path.exists() && path.extension().is_none() { + let with_js = path.with_extension("js"); + if with_js.exists() { + path = with_js; + } } if !path.exists() || path.is_dir() { @@ -91,9 +105,10 @@ fn path_to_response(headers: &HeaderMap, state: &AppState, path: &Path) -> Respo fn path_to_response_(headers: &HeaderMap, state: &AppState, path: &Path) -> Result { let (modified, date) = headers.check_if_modified_since(path)?; - if modified == ModifiedState::NotModifiedSince { - return Ok(Response::new_not_modified()); - } + // TODO: Re-enable for production + // if modified == ModifiedState::NotModifiedSince { + // return Ok(Response::new_not_modified()); + // } let serialized_path = path.to_str().unwrap(); @@ -102,7 +117,8 @@ fn path_to_response_(headers: &HeaderMap, state: &AppState, path: &Path) -> Resu .is_some_and(|extension| extension == "html") || serialized_path.ends_with("service-worker.js"); - let guard_res = if !must_revalidate { + // TODO: Re-enable caching for production + let guard_res = if false && !must_revalidate { Some(state.cache.get_value_or_guard( &path.to_str().unwrap().to_owned(), Some(Duration::from_millis(50)), @@ -133,17 +149,19 @@ fn path_to_response_(headers: &HeaderMap, state: &AppState, path: &Path) -> Resu headers.insert_cors(); headers.insert_content_type(path); - if must_revalidate { - headers.insert_cache_control_must_revalidate(); - } else if path.extension().is_some_and(|extension| { - extension == "jpg" - || extension == "png" - || extension == "woff2" - || extension == "js" - || extension == "map" - }) { - headers.insert_cache_control_immutable(); - } + // TODO: Re-enable immutable caching for production + // if must_revalidate { + // headers.insert_cache_control_must_revalidate(); + // } else if path.extension().is_some_and(|extension| { + // extension == "jpg" + // || extension == "png" + // || extension == "woff2" + // || extension == "js" + // || extension == "map" + // }) { + // headers.insert_cache_control_immutable(); + // } + headers.insert_cache_control_must_revalidate(); headers.insert_last_modified(date); diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index fa369ff37..e5784bea5 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -563,6 +563,8 @@ class BrkError extends Error { * @property {(index: Index) => Endpoint|undefined} get - Get an endpoint for a specific index */ +/** @typedef {MetricPattern} AnyMetricPattern */ + /** * Create an endpoint for a metric index. * @template T @@ -1459,7 +1461,7 @@ function createMetricPattern26(client, name) { /** * @template T - * @typedef {{ name: string, by: { monthindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern27 + * @typedef {{ name: string, by: { opreturnindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern27 */ /** @@ -1470,35 +1472,6 @@ function createMetricPattern26(client, name) { * @returns {MetricPattern27} */ function createMetricPattern27(client, name) { - return { - name, - by: { - get monthindex() { return _endpoint(client, name, 'monthindex'); } - }, - indexes() { - return ['monthindex']; - }, - get(index) { - if (this.indexes().includes(index)) { - return _endpoint(client, name, index); - } - } - }; -} - -/** - * @template T - * @typedef {{ name: string, by: { opreturnindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern28 - */ - -/** - * Create a MetricPattern28 accessor - * @template T - * @param {BrkClientBase} client - * @param {string} name - The metric vec name - * @returns {MetricPattern28} - */ -function createMetricPattern28(client, name) { return { name, by: { @@ -1517,17 +1490,17 @@ function createMetricPattern28(client, name) { /** * @template T - * @typedef {{ name: string, by: { txoutindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern29 + * @typedef {{ name: string, by: { txoutindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern28 */ /** - * Create a MetricPattern29 accessor + * Create a MetricPattern28 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern29} + * @returns {MetricPattern28} */ -function createMetricPattern29(client, name) { +function createMetricPattern28(client, name) { return { name, by: { @@ -1546,17 +1519,17 @@ function createMetricPattern29(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2aaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern30 + * @typedef {{ name: string, by: { p2aaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern29 */ /** - * Create a MetricPattern30 accessor + * Create a MetricPattern29 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern30} + * @returns {MetricPattern29} */ -function createMetricPattern30(client, name) { +function createMetricPattern29(client, name) { return { name, by: { @@ -1575,17 +1548,17 @@ function createMetricPattern30(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2msoutputindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern31 + * @typedef {{ name: string, by: { p2msoutputindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern30 */ /** - * Create a MetricPattern31 accessor + * Create a MetricPattern30 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern31} + * @returns {MetricPattern30} */ -function createMetricPattern31(client, name) { +function createMetricPattern30(client, name) { return { name, by: { @@ -1604,17 +1577,17 @@ function createMetricPattern31(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2pk33addressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern32 + * @typedef {{ name: string, by: { p2pk33addressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern31 */ /** - * Create a MetricPattern32 accessor + * Create a MetricPattern31 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern32} + * @returns {MetricPattern31} */ -function createMetricPattern32(client, name) { +function createMetricPattern31(client, name) { return { name, by: { @@ -1633,17 +1606,17 @@ function createMetricPattern32(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2pk65addressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern33 + * @typedef {{ name: string, by: { p2pk65addressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern32 */ /** - * Create a MetricPattern33 accessor + * Create a MetricPattern32 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern33} + * @returns {MetricPattern32} */ -function createMetricPattern33(client, name) { +function createMetricPattern32(client, name) { return { name, by: { @@ -1662,17 +1635,17 @@ function createMetricPattern33(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2pkhaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern34 + * @typedef {{ name: string, by: { p2pkhaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern33 */ /** - * Create a MetricPattern34 accessor + * Create a MetricPattern33 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern34} + * @returns {MetricPattern33} */ -function createMetricPattern34(client, name) { +function createMetricPattern33(client, name) { return { name, by: { @@ -1691,17 +1664,17 @@ function createMetricPattern34(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2shaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern35 + * @typedef {{ name: string, by: { p2shaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern34 */ /** - * Create a MetricPattern35 accessor + * Create a MetricPattern34 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern35} + * @returns {MetricPattern34} */ -function createMetricPattern35(client, name) { +function createMetricPattern34(client, name) { return { name, by: { @@ -1720,17 +1693,17 @@ function createMetricPattern35(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2traddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern36 + * @typedef {{ name: string, by: { p2traddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern35 */ /** - * Create a MetricPattern36 accessor + * Create a MetricPattern35 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern36} + * @returns {MetricPattern35} */ -function createMetricPattern36(client, name) { +function createMetricPattern35(client, name) { return { name, by: { @@ -1749,17 +1722,17 @@ function createMetricPattern36(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2wpkhaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern37 + * @typedef {{ name: string, by: { p2wpkhaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern36 */ /** - * Create a MetricPattern37 accessor + * Create a MetricPattern36 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern37} + * @returns {MetricPattern36} */ -function createMetricPattern37(client, name) { +function createMetricPattern36(client, name) { return { name, by: { @@ -1778,17 +1751,17 @@ function createMetricPattern37(client, name) { /** * @template T - * @typedef {{ name: string, by: { p2wshaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern38 + * @typedef {{ name: string, by: { p2wshaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern37 */ /** - * Create a MetricPattern38 accessor + * Create a MetricPattern37 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern38} + * @returns {MetricPattern37} */ -function createMetricPattern38(client, name) { +function createMetricPattern37(client, name) { return { name, by: { @@ -1807,75 +1780,17 @@ function createMetricPattern38(client, name) { /** * @template T - * @typedef {{ name: string, by: { quarterindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern39 + * @typedef {{ name: string, by: { txindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern38 */ /** - * Create a MetricPattern39 accessor + * Create a MetricPattern38 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern39} + * @returns {MetricPattern38} */ -function createMetricPattern39(client, name) { - return { - name, - by: { - get quarterindex() { return _endpoint(client, name, 'quarterindex'); } - }, - indexes() { - return ['quarterindex']; - }, - get(index) { - if (this.indexes().includes(index)) { - return _endpoint(client, name, index); - } - } - }; -} - -/** - * @template T - * @typedef {{ name: string, by: { semesterindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern40 - */ - -/** - * Create a MetricPattern40 accessor - * @template T - * @param {BrkClientBase} client - * @param {string} name - The metric vec name - * @returns {MetricPattern40} - */ -function createMetricPattern40(client, name) { - return { - name, - by: { - get semesterindex() { return _endpoint(client, name, 'semesterindex'); } - }, - indexes() { - return ['semesterindex']; - }, - get(index) { - if (this.indexes().includes(index)) { - return _endpoint(client, name, index); - } - } - }; -} - -/** - * @template T - * @typedef {{ name: string, by: { txindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern41 - */ - -/** - * Create a MetricPattern41 accessor - * @template T - * @param {BrkClientBase} client - * @param {string} name - The metric vec name - * @returns {MetricPattern41} - */ -function createMetricPattern41(client, name) { +function createMetricPattern38(client, name) { return { name, by: { @@ -1894,17 +1809,17 @@ function createMetricPattern41(client, name) { /** * @template T - * @typedef {{ name: string, by: { unknownoutputindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern42 + * @typedef {{ name: string, by: { unknownoutputindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern39 */ /** - * Create a MetricPattern42 accessor + * Create a MetricPattern39 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern42} + * @returns {MetricPattern39} */ -function createMetricPattern42(client, name) { +function createMetricPattern39(client, name) { return { name, by: { @@ -1923,75 +1838,17 @@ function createMetricPattern42(client, name) { /** * @template T - * @typedef {{ name: string, by: { weekindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern43 + * @typedef {{ name: string, by: { loadedaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern40 */ /** - * Create a MetricPattern43 accessor + * Create a MetricPattern40 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern43} + * @returns {MetricPattern40} */ -function createMetricPattern43(client, name) { - return { - name, - by: { - get weekindex() { return _endpoint(client, name, 'weekindex'); } - }, - indexes() { - return ['weekindex']; - }, - get(index) { - if (this.indexes().includes(index)) { - return _endpoint(client, name, index); - } - } - }; -} - -/** - * @template T - * @typedef {{ name: string, by: { yearindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern44 - */ - -/** - * Create a MetricPattern44 accessor - * @template T - * @param {BrkClientBase} client - * @param {string} name - The metric vec name - * @returns {MetricPattern44} - */ -function createMetricPattern44(client, name) { - return { - name, - by: { - get yearindex() { return _endpoint(client, name, 'yearindex'); } - }, - indexes() { - return ['yearindex']; - }, - get(index) { - if (this.indexes().includes(index)) { - return _endpoint(client, name, index); - } - } - }; -} - -/** - * @template T - * @typedef {{ name: string, by: { loadedaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern45 - */ - -/** - * Create a MetricPattern45 accessor - * @template T - * @param {BrkClientBase} client - * @param {string} name - The metric vec name - * @returns {MetricPattern45} - */ -function createMetricPattern45(client, name) { +function createMetricPattern40(client, name) { return { name, by: { @@ -2010,17 +1867,17 @@ function createMetricPattern45(client, name) { /** * @template T - * @typedef {{ name: string, by: { emptyaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern46 + * @typedef {{ name: string, by: { emptyaddressindex: Endpoint }, indexes: () => Index[], get: (index: Index) => Endpoint|undefined }} MetricPattern41 */ /** - * Create a MetricPattern46 accessor + * Create a MetricPattern41 accessor * @template T * @param {BrkClientBase} client * @param {string} name - The metric vec name - * @returns {MetricPattern46} + * @returns {MetricPattern41} */ -function createMetricPattern46(client, name) { +function createMetricPattern41(client, name) { return { name, by: { @@ -2118,6 +1975,81 @@ function createRealizedPattern3(client, acc) { }; } +/** + * @typedef {Object} RealizedPattern4 + * @property {MetricPattern21} adjustedSopr + * @property {MetricPattern21} adjustedSopr30dEma + * @property {MetricPattern21} adjustedSopr7dEma + * @property {MetricPattern1} adjustedValueCreated + * @property {MetricPattern1} adjustedValueDestroyed + * @property {MetricPattern4} mvrv + * @property {BlockCountPattern} negRealizedLoss + * @property {BlockCountPattern} netRealizedPnl + * @property {MetricPattern4} netRealizedPnlCumulative30dDelta + * @property {MetricPattern4} netRealizedPnlCumulative30dDeltaRelToMarketCap + * @property {MetricPattern4} netRealizedPnlCumulative30dDeltaRelToRealizedCap + * @property {MetricPattern25} netRealizedPnlRelToRealizedCap + * @property {MetricPattern1} realizedCap + * @property {MetricPattern4} realizedCap30dDelta + * @property {BlockCountPattern} realizedLoss + * @property {MetricPattern25} realizedLossRelToRealizedCap + * @property {MetricPattern1} realizedPrice + * @property {RealizedPriceExtraPattern} realizedPriceExtra + * @property {BlockCountPattern} realizedProfit + * @property {MetricPattern25} realizedProfitRelToRealizedCap + * @property {MetricPattern1} realizedValue + * @property {MetricPattern21} sellSideRiskRatio + * @property {MetricPattern21} sellSideRiskRatio30dEma + * @property {MetricPattern21} sellSideRiskRatio7dEma + * @property {MetricPattern21} sopr + * @property {MetricPattern21} sopr30dEma + * @property {MetricPattern21} sopr7dEma + * @property {TotalRealizedPnlPattern} totalRealizedPnl + * @property {MetricPattern1} valueCreated + * @property {MetricPattern1} valueDestroyed + */ + +/** + * Create a RealizedPattern4 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {RealizedPattern4} + */ +function createRealizedPattern4(client, acc) { + return { + 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')), + mvrv: createMetricPattern4(client, _m(acc, 'mvrv')), + negRealizedLoss: createBlockCountPattern(client, _m(acc, 'neg_realized_loss')), + netRealizedPnl: createBlockCountPattern(client, _m(acc, 'net_realized_pnl')), + netRealizedPnlCumulative30dDelta: createMetricPattern4(client, _m(acc, 'net_realized_pnl_cumulative_30d_delta')), + netRealizedPnlCumulative30dDeltaRelToMarketCap: createMetricPattern4(client, _m(acc, 'net_realized_pnl_cumulative_30d_delta_rel_to_market_cap')), + netRealizedPnlCumulative30dDeltaRelToRealizedCap: createMetricPattern4(client, _m(acc, 'net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap')), + netRealizedPnlRelToRealizedCap: createMetricPattern25(client, _m(acc, 'net_realized_pnl_rel_to_realized_cap')), + realizedCap: createMetricPattern1(client, _m(acc, 'realized_cap')), + realizedCap30dDelta: createMetricPattern4(client, _m(acc, 'realized_cap_30d_delta')), + realizedLoss: createBlockCountPattern(client, _m(acc, 'realized_loss')), + realizedLossRelToRealizedCap: createMetricPattern25(client, _m(acc, 'realized_loss_rel_to_realized_cap')), + realizedPrice: createMetricPattern1(client, _m(acc, 'realized_price')), + realizedPriceExtra: createRealizedPriceExtraPattern(client, _m(acc, 'realized_price')), + realizedProfit: createBlockCountPattern(client, _m(acc, 'realized_profit')), + realizedProfitRelToRealizedCap: createMetricPattern25(client, _m(acc, 'realized_profit_rel_to_realized_cap')), + realizedValue: createMetricPattern1(client, _m(acc, 'realized_value')), + sellSideRiskRatio: createMetricPattern21(client, _m(acc, 'sell_side_risk_ratio')), + sellSideRiskRatio30dEma: createMetricPattern21(client, _m(acc, 'sell_side_risk_ratio_30d_ema')), + sellSideRiskRatio7dEma: createMetricPattern21(client, _m(acc, 'sell_side_risk_ratio_7d_ema')), + sopr: createMetricPattern21(client, _m(acc, 'sopr')), + sopr30dEma: createMetricPattern21(client, _m(acc, 'sopr_30d_ema')), + sopr7dEma: createMetricPattern21(client, _m(acc, 'sopr_7d_ema')), + totalRealizedPnl: createTotalRealizedPnlPattern(client, _m(acc, 'total_realized_pnl')), + valueCreated: createMetricPattern1(client, _m(acc, 'value_created')), + valueDestroyed: createMetricPattern1(client, _m(acc, 'value_destroyed')), + }; +} + /** * @typedef {Object} Ratio1ySdPattern * @property {MetricPattern4} _0sdUsd @@ -2576,6 +2508,168 @@ function createAXbtPattern(client, acc) { }; } +/** + * @template T + * @typedef {Object} PriceAgoPattern + * @property {MetricPattern4} _10y + * @property {MetricPattern4} _1d + * @property {MetricPattern4} _1m + * @property {MetricPattern4} _1w + * @property {MetricPattern4} _1y + * @property {MetricPattern4} _2y + * @property {MetricPattern4} _3m + * @property {MetricPattern4} _3y + * @property {MetricPattern4} _4y + * @property {MetricPattern4} _5y + * @property {MetricPattern4} _6m + * @property {MetricPattern4} _6y + * @property {MetricPattern4} _8y + */ + +/** + * Create a PriceAgoPattern pattern node + * @template T + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {PriceAgoPattern} + */ +function createPriceAgoPattern(client, acc) { + return { + _10y: createMetricPattern4(client, _m(acc, '10y_ago')), + _1d: createMetricPattern4(client, _m(acc, '1d_ago')), + _1m: createMetricPattern4(client, _m(acc, '1m_ago')), + _1w: createMetricPattern4(client, _m(acc, '1w_ago')), + _1y: createMetricPattern4(client, _m(acc, '1y_ago')), + _2y: createMetricPattern4(client, _m(acc, '2y_ago')), + _3m: createMetricPattern4(client, _m(acc, '3m_ago')), + _3y: createMetricPattern4(client, _m(acc, '3y_ago')), + _4y: createMetricPattern4(client, _m(acc, '4y_ago')), + _5y: createMetricPattern4(client, _m(acc, '5y_ago')), + _6m: createMetricPattern4(client, _m(acc, '6m_ago')), + _6y: createMetricPattern4(client, _m(acc, '6y_ago')), + _8y: createMetricPattern4(client, _m(acc, '8y_ago')), + }; +} + +/** + * @typedef {Object} PeriodLumpSumStackPattern + * @property {ActiveSupplyPattern} _10y + * @property {ActiveSupplyPattern} _1m + * @property {ActiveSupplyPattern} _1w + * @property {ActiveSupplyPattern} _1y + * @property {ActiveSupplyPattern} _2y + * @property {ActiveSupplyPattern} _3m + * @property {ActiveSupplyPattern} _3y + * @property {ActiveSupplyPattern} _4y + * @property {ActiveSupplyPattern} _5y + * @property {ActiveSupplyPattern} _6m + * @property {ActiveSupplyPattern} _6y + * @property {ActiveSupplyPattern} _8y + */ + +/** + * Create a PeriodLumpSumStackPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {PeriodLumpSumStackPattern} + */ +function createPeriodLumpSumStackPattern(client, acc) { + return { + _10y: createActiveSupplyPattern(client, (acc ? `10y_${acc}` : '10y')), + _1m: createActiveSupplyPattern(client, (acc ? `1m_${acc}` : '1m')), + _1w: createActiveSupplyPattern(client, (acc ? `1w_${acc}` : '1w')), + _1y: createActiveSupplyPattern(client, (acc ? `1y_${acc}` : '1y')), + _2y: createActiveSupplyPattern(client, (acc ? `2y_${acc}` : '2y')), + _3m: createActiveSupplyPattern(client, (acc ? `3m_${acc}` : '3m')), + _3y: createActiveSupplyPattern(client, (acc ? `3y_${acc}` : '3y')), + _4y: createActiveSupplyPattern(client, (acc ? `4y_${acc}` : '4y')), + _5y: createActiveSupplyPattern(client, (acc ? `5y_${acc}` : '5y')), + _6m: createActiveSupplyPattern(client, (acc ? `6m_${acc}` : '6m')), + _6y: createActiveSupplyPattern(client, (acc ? `6y_${acc}` : '6y')), + _8y: createActiveSupplyPattern(client, (acc ? `8y_${acc}` : '8y')), + }; +} + +/** + * @template T + * @typedef {Object} PeriodAvgPricePattern + * @property {MetricPattern4} _10y + * @property {MetricPattern4} _1m + * @property {MetricPattern4} _1w + * @property {MetricPattern4} _1y + * @property {MetricPattern4} _2y + * @property {MetricPattern4} _3m + * @property {MetricPattern4} _3y + * @property {MetricPattern4} _4y + * @property {MetricPattern4} _5y + * @property {MetricPattern4} _6m + * @property {MetricPattern4} _6y + * @property {MetricPattern4} _8y + */ + +/** + * Create a PeriodAvgPricePattern pattern node + * @template T + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {PeriodAvgPricePattern} + */ +function createPeriodAvgPricePattern(client, acc) { + return { + _10y: createMetricPattern4(client, (acc ? `10y_${acc}` : '10y')), + _1m: createMetricPattern4(client, (acc ? `1m_${acc}` : '1m')), + _1w: createMetricPattern4(client, (acc ? `1w_${acc}` : '1w')), + _1y: createMetricPattern4(client, (acc ? `1y_${acc}` : '1y')), + _2y: createMetricPattern4(client, (acc ? `2y_${acc}` : '2y')), + _3m: createMetricPattern4(client, (acc ? `3m_${acc}` : '3m')), + _3y: createMetricPattern4(client, (acc ? `3y_${acc}` : '3y')), + _4y: createMetricPattern4(client, (acc ? `4y_${acc}` : '4y')), + _5y: createMetricPattern4(client, (acc ? `5y_${acc}` : '5y')), + _6m: createMetricPattern4(client, (acc ? `6m_${acc}` : '6m')), + _6y: createMetricPattern4(client, (acc ? `6y_${acc}` : '6y')), + _8y: createMetricPattern4(client, (acc ? `8y_${acc}` : '8y')), + }; +} + +/** + * @template T + * @typedef {Object} ClassAvgPricePattern + * @property {MetricPattern4} _2015 + * @property {MetricPattern4} _2016 + * @property {MetricPattern4} _2017 + * @property {MetricPattern4} _2018 + * @property {MetricPattern4} _2019 + * @property {MetricPattern4} _2020 + * @property {MetricPattern4} _2021 + * @property {MetricPattern4} _2022 + * @property {MetricPattern4} _2023 + * @property {MetricPattern4} _2024 + * @property {MetricPattern4} _2025 + */ + +/** + * Create a ClassAvgPricePattern pattern node + * @template T + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {ClassAvgPricePattern} + */ +function createClassAvgPricePattern(client, acc) { + return { + _2015: createMetricPattern4(client, _m(acc, '2015_avg_price')), + _2016: createMetricPattern4(client, _m(acc, '2016_avg_price')), + _2017: createMetricPattern4(client, _m(acc, '2017_avg_price')), + _2018: createMetricPattern4(client, _m(acc, '2018_avg_price')), + _2019: createMetricPattern4(client, _m(acc, '2019_avg_price')), + _2020: createMetricPattern4(client, _m(acc, '2020_avg_price')), + _2021: createMetricPattern4(client, _m(acc, '2021_avg_price')), + _2022: createMetricPattern4(client, _m(acc, '2022_avg_price')), + _2023: createMetricPattern4(client, _m(acc, '2023_avg_price')), + _2024: createMetricPattern4(client, _m(acc, '2024_avg_price')), + _2025: createMetricPattern4(client, _m(acc, '2025_avg_price')), + }; +} + /** * @template T * @typedef {Object} BitcoinPattern @@ -2653,16 +2747,16 @@ function createRelativePattern(client, acc) { /** * @template T * @typedef {Object} BlockSizePattern - * @property {MetricPattern2} average + * @property {MetricPattern1} average * @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 + * @property {MetricPattern1} max + * @property {MetricPattern25} median + * @property {MetricPattern1} min + * @property {MetricPattern25} pct10 + * @property {MetricPattern25} pct25 + * @property {MetricPattern25} pct75 + * @property {MetricPattern25} pct90 + * @property {MetricPattern1} sum */ /** @@ -2674,16 +2768,16 @@ function createRelativePattern(client, acc) { */ function createBlockSizePattern(client, acc) { return { - average: createMetricPattern2(client, _m(acc, 'avg')), + average: createMetricPattern1(client, _m(acc, 'avg')), 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')), + 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')), }; } @@ -2723,14 +2817,14 @@ function createUnrealizedPattern(client, acc) { /** * @template T * @typedef {Object} AddresstypeToHeightToAddrCountPattern - * @property {MetricPattern30} p2a - * @property {MetricPattern32} p2pk33 - * @property {MetricPattern33} p2pk65 - * @property {MetricPattern34} p2pkh - * @property {MetricPattern35} p2sh - * @property {MetricPattern36} p2tr - * @property {MetricPattern37} p2wpkh - * @property {MetricPattern38} p2wsh + * @property {MetricPattern25} p2a + * @property {MetricPattern25} p2pk33 + * @property {MetricPattern25} p2pk65 + * @property {MetricPattern25} p2pkh + * @property {MetricPattern25} p2sh + * @property {MetricPattern25} p2tr + * @property {MetricPattern25} p2wpkh + * @property {MetricPattern25} p2wsh */ /** @@ -2742,28 +2836,28 @@ function createUnrealizedPattern(client, acc) { */ function createAddresstypeToHeightToAddrCountPattern(client, acc) { return { - p2a: createMetricPattern30(client, (acc ? `p2a_${acc}` : 'p2a')), - p2pk33: createMetricPattern32(client, (acc ? `p2pk33_${acc}` : 'p2pk33')), - p2pk65: createMetricPattern33(client, (acc ? `p2pk65_${acc}` : 'p2pk65')), - p2pkh: createMetricPattern34(client, (acc ? `p2pkh_${acc}` : 'p2pkh')), - p2sh: createMetricPattern35(client, (acc ? `p2sh_${acc}` : 'p2sh')), - p2tr: createMetricPattern36(client, (acc ? `p2tr_${acc}` : 'p2tr')), - p2wpkh: createMetricPattern37(client, (acc ? `p2wpkh_${acc}` : 'p2wpkh')), - p2wsh: createMetricPattern38(client, (acc ? `p2wsh_${acc}` : 'p2wsh')), + 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')), }; } /** * @template T * @typedef {Object} BlockIntervalPattern - * @property {MetricPattern1} average - * @property {MetricPattern1} max - * @property {MetricPattern25} median - * @property {MetricPattern1} min - * @property {MetricPattern25} pct10 - * @property {MetricPattern25} pct25 - * @property {MetricPattern25} pct75 - * @property {MetricPattern25} pct90 + * @property {MetricPattern2} average + * @property {MetricPattern2} max + * @property {MetricPattern21} median + * @property {MetricPattern2} min + * @property {MetricPattern21} pct10 + * @property {MetricPattern21} pct25 + * @property {MetricPattern21} pct75 + * @property {MetricPattern21} pct90 */ /** @@ -2775,47 +2869,43 @@ function createAddresstypeToHeightToAddrCountPattern(client, acc) { */ function createBlockIntervalPattern(client, acc) { return { - 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')), + 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')), }; } /** - * @template T - * @typedef {Object} Constant0Pattern - * @property {MetricPattern21} dateindex - * @property {MetricPattern22} decadeindex - * @property {MetricPattern25} height - * @property {MetricPattern27} monthindex - * @property {MetricPattern39} quarterindex - * @property {MetricPattern40} semesterindex - * @property {MetricPattern43} weekindex - * @property {MetricPattern44} yearindex + * @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 Constant0Pattern pattern node - * @template T + * Create a PeriodCagrPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {Constant0Pattern} + * @returns {PeriodCagrPattern} */ -function createConstant0Pattern(client, acc) { +function createPeriodCagrPattern(client, acc) { return { - dateindex: createMetricPattern21(client, acc), - decadeindex: createMetricPattern22(client, acc), - height: createMetricPattern25(client, acc), - monthindex: createMetricPattern27(client, acc), - quarterindex: createMetricPattern39(client, acc), - semesterindex: createMetricPattern40(client, acc), - weekindex: createMetricPattern43(client, acc), - yearindex: createMetricPattern44(client, acc), + _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')), }; } @@ -2876,26 +2966,26 @@ function createUpTo1dPattern(client, acc) { } /** - * @typedef {Object} _0satsPattern2 + * @typedef {Object} _10yPattern * @property {ActivityPattern2} activity * @property {CostBasisPattern} costBasis - * @property {RealizedPattern} realized + * @property {RealizedPattern4} realized * @property {RelativePattern} relative * @property {SupplyPattern3} supply * @property {UnrealizedPattern} unrealized */ /** - * Create a _0satsPattern2 pattern node + * Create a _10yPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {_0satsPattern2} + * @returns {_10yPattern} */ -function create_0satsPattern2(client, acc) { +function create_10yPattern(client, acc) { return { activity: createActivityPattern2(client, acc), costBasis: createCostBasisPattern(client, acc), - realized: createRealizedPattern(client, acc), + realized: createRealizedPattern4(client, acc), relative: createRelativePattern(client, acc), supply: createSupplyPattern3(client, acc), unrealized: createUnrealizedPattern(client, acc), @@ -2929,6 +3019,33 @@ 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 @@ -2958,31 +3075,6 @@ function createSegwitAdoptionPattern(client, acc) { }; } -/** - * @typedef {Object} ActivityPattern2 - * @property {BlockCountPattern} coinblocksDestroyed - * @property {BlockCountPattern} coindaysDestroyed - * @property {MetricPattern25} satblocksDestroyed - * @property {MetricPattern25} satdaysDestroyed - * @property {SentPattern} sent - */ - -/** - * Create a ActivityPattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {ActivityPattern2} - */ -function createActivityPattern2(client, acc) { - return { - coinblocksDestroyed: createBlockCountPattern(client, _m(acc, 'coinblocks_destroyed')), - coindaysDestroyed: createBlockCountPattern(client, _m(acc, 'coindays_destroyed')), - satblocksDestroyed: createMetricPattern25(client, _m(acc, 'satblocks_destroyed')), - satdaysDestroyed: createMetricPattern25(client, _m(acc, 'satdays_destroyed')), - sent: createSentPattern(client, _m(acc, 'sent')), - }; -} - /** * @typedef {Object} SupplyPattern3 * @property {SupplyPattern2} supply @@ -3009,25 +3101,27 @@ function createSupplyPattern3(client, acc) { } /** - * @typedef {Object} SentPattern - * @property {MetricPattern25} base - * @property {BlockCountPattern} bitcoin - * @property {BlockCountPattern} dollars - * @property {SatsPattern} sats + * @typedef {Object} ActivityPattern2 + * @property {BlockCountPattern} coinblocksDestroyed + * @property {BlockCountPattern} coindaysDestroyed + * @property {MetricPattern25} satblocksDestroyed + * @property {MetricPattern25} satdaysDestroyed + * @property {SentPattern} sent */ /** - * Create a SentPattern pattern node + * Create a ActivityPattern2 pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {SentPattern} + * @returns {ActivityPattern2} */ -function createSentPattern(client, acc) { +function createActivityPattern2(client, acc) { return { - base: createMetricPattern25(client, acc), - bitcoin: createBlockCountPattern(client, _m(acc, 'btc')), - dollars: createBlockCountPattern(client, _m(acc, 'usd')), - sats: createSatsPattern(client, acc), + coinblocksDestroyed: createBlockCountPattern(client, _m(acc, 'coinblocks_destroyed')), + coindaysDestroyed: createBlockCountPattern(client, _m(acc, 'coindays_destroyed')), + satblocksDestroyed: createMetricPattern25(client, _m(acc, 'satblocks_destroyed')), + satdaysDestroyed: createMetricPattern25(client, _m(acc, 'satdays_destroyed')), + sent: createSentPattern(client, _m(acc, 'sent')), }; } @@ -3054,6 +3148,29 @@ 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 @@ -3077,27 +3194,6 @@ function createOpreturnPattern(client, acc) { }; } -/** - * @typedef {Object} CoinbasePattern - * @property {BitcoinPattern} bitcoin - * @property {BitcoinPattern} dollars - * @property {BitcoinPattern} sats - */ - -/** - * Create a CoinbasePattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {CoinbasePattern} - */ -function createCoinbasePattern(client, acc) { - return { - bitcoin: createBitcoinPattern(client, _m(acc, 'btc')), - dollars: createBitcoinPattern(client, _m(acc, 'usd')), - sats: createBitcoinPattern(client, acc), - }; -} - /** * @typedef {Object} CostBasisPattern2 * @property {MetricPattern1} maxCostBasis @@ -3119,6 +3215,27 @@ function createCostBasisPattern2(client, acc) { }; } +/** + * @typedef {Object} CoinbasePattern + * @property {BitcoinPattern} bitcoin + * @property {BitcoinPattern} dollars + * @property {BitcoinPattern} sats + */ + +/** + * Create a CoinbasePattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {CoinbasePattern} + */ +function createCoinbasePattern(client, acc) { + return { + bitcoin: createBitcoinPattern(client, _m(acc, 'btc')), + dollars: createBitcoinPattern(client, _m(acc, 'usd')), + sats: createBitcoinPattern(client, acc), + }; +} + /** * @typedef {Object} UnclaimedRewardsPattern * @property {BlockCountPattern} bitcoin @@ -3161,29 +3278,6 @@ function createActiveSupplyPattern(client, acc) { }; } -/** - * @template T - * @typedef {Object} BitcoinPattern2 - * @property {MetricPattern25} base - * @property {MetricPattern1} cumulative - * @property {MetricPattern2} last - */ - -/** - * Create a BitcoinPattern2 pattern node - * @template T - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {BitcoinPattern2} - */ -function createBitcoinPattern2(client, acc) { - return { - base: createMetricPattern25(client, acc), - cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), - last: createMetricPattern2(client, acc), - }; -} - /** * @template T * @typedef {Object} BlockCountPattern @@ -3208,40 +3302,25 @@ function createBlockCountPattern(client, acc) { } /** - * @typedef {Object} _1dReturns1mSdPattern - * @property {MetricPattern4} sd - * @property {MetricPattern4} sma + * @template T + * @typedef {Object} BitcoinPattern2 + * @property {MetricPattern25} base + * @property {MetricPattern1} cumulative + * @property {MetricPattern2} last */ /** - * Create a _1dReturns1mSdPattern pattern node + * Create a BitcoinPattern2 pattern node + * @template T * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {_1dReturns1mSdPattern} + * @returns {BitcoinPattern2} */ -function create_1dReturns1mSdPattern(client, acc) { - return { - sd: createMetricPattern4(client, _m(acc, 'sd')), - sma: createMetricPattern4(client, _m(acc, 'sma')), - }; -} - -/** - * @typedef {Object} SatsPattern - * @property {MetricPattern1} cumulative - * @property {MetricPattern2} sum - */ - -/** - * Create a SatsPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {SatsPattern} - */ -function createSatsPattern(client, acc) { +function createBitcoinPattern2(client, acc) { return { + base: createMetricPattern25(client, acc), cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), - sum: createMetricPattern2(client, acc), + last: createMetricPattern2(client, acc), }; } @@ -3264,6 +3343,25 @@ function createCostBasisPattern(client, acc) { }; } +/** + * @typedef {Object} SatsPattern4 + * @property {MetricPattern1} cumulative + * @property {MetricPattern2} last + */ + +/** + * Create a SatsPattern4 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {SatsPattern4} + */ +function createSatsPattern4(client, acc) { + return { + cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), + last: createMetricPattern2(client, acc), + }; +} + /** * @typedef {Object} SupplyValuePattern * @property {MetricPattern25} bitcoin @@ -3284,21 +3382,40 @@ function createSupplyValuePattern(client, acc) { } /** - * @typedef {Object} SatsPattern4 + * @typedef {Object} SatsPattern * @property {MetricPattern1} cumulative - * @property {MetricPattern2} last + * @property {MetricPattern2} sum */ /** - * Create a SatsPattern4 pattern node + * Create a SatsPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {SatsPattern4} + * @returns {SatsPattern} */ -function createSatsPattern4(client, acc) { +function createSatsPattern(client, acc) { return { cumulative: createMetricPattern1(client, _m(acc, 'cumulative')), - last: createMetricPattern2(client, acc), + sum: createMetricPattern2(client, acc), + }; +} + +/** + * @typedef {Object} _1dReturns1mSdPattern + * @property {MetricPattern4} sd + * @property {MetricPattern4} sma + */ + +/** + * Create a _1dReturns1mSdPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {_1dReturns1mSdPattern} + */ +function create_1dReturns1mSdPattern(client, acc) { + return { + sd: createMetricPattern4(client, _m(acc, 'sd')), + sma: createMetricPattern4(client, _m(acc, 'sma')), }; } @@ -3526,20 +3643,24 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Constants - * @property {Constant0Pattern} constant0 - * @property {Constant0Pattern} constant1 - * @property {Constant0Pattern} constant100 - * @property {Constant0Pattern} constant2 - * @property {Constant0Pattern} constant3 - * @property {Constant0Pattern} constant382 - * @property {Constant0Pattern} constant4 - * @property {Constant0Pattern} constant50 - * @property {Constant0Pattern} constant600 - * @property {Constant0Pattern} constant618 - * @property {Constant0Pattern} constantMinus1 - * @property {Constant0Pattern} constantMinus2 - * @property {Constant0Pattern} constantMinus3 - * @property {Constant0Pattern} constantMinus4 + * @property {MetricPattern3} constant0 + * @property {MetricPattern3} constant1 + * @property {MetricPattern3} constant100 + * @property {MetricPattern3} constant2 + * @property {MetricPattern3} constant20 + * @property {MetricPattern3} constant3 + * @property {MetricPattern3} constant30 + * @property {MetricPattern3} constant382 + * @property {MetricPattern3} constant4 + * @property {MetricPattern3} constant50 + * @property {MetricPattern3} constant600 + * @property {MetricPattern3} constant618 + * @property {MetricPattern3} constant70 + * @property {MetricPattern3} constant80 + * @property {MetricPattern3} constantMinus1 + * @property {MetricPattern3} constantMinus2 + * @property {MetricPattern3} constantMinus3 + * @property {MetricPattern3} constantMinus4 */ /** @@ -3554,8 +3675,8 @@ function createRealizedPriceExtraPattern(client, acc) { * @property {AddresstypeToHeightToAddrCountPattern} anyAddressIndexes * @property {MetricPattern25} chainState * @property {MetricPattern1} emptyAddrCount - * @property {MetricPattern46} emptyaddressindex - * @property {MetricPattern45} loadedaddressindex + * @property {MetricPattern41} emptyaddressindex + * @property {MetricPattern40} loadedaddressindex * @property {CatalogTree_Computed_Distribution_UtxoCohorts} utxoCohorts */ @@ -3621,8 +3742,8 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Distribution_AddressesData - * @property {MetricPattern46} empty - * @property {MetricPattern45} loaded + * @property {MetricPattern41} empty + * @property {MetricPattern40} loaded */ /** @@ -3705,11 +3826,11 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_Epoch - * @property {_10yTo12yPattern} _0 - * @property {_10yTo12yPattern} _1 - * @property {_10yTo12yPattern} _2 - * @property {_10yTo12yPattern} _3 - * @property {_10yTo12yPattern} _4 + * @property {_0satsPattern2} _0 + * @property {_0satsPattern2} _1 + * @property {_0satsPattern2} _2 + * @property {_0satsPattern2} _3 + * @property {_0satsPattern2} _4 */ /** @@ -3748,46 +3869,46 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_MaxAge - * @property {UpTo1dPattern} _10y - * @property {UpTo1dPattern} _12y - * @property {UpTo1dPattern} _15y - * @property {UpTo1dPattern} _1m - * @property {UpTo1dPattern} _1w - * @property {UpTo1dPattern} _1y - * @property {UpTo1dPattern} _2m - * @property {UpTo1dPattern} _2y - * @property {UpTo1dPattern} _3m - * @property {UpTo1dPattern} _3y - * @property {UpTo1dPattern} _4m - * @property {UpTo1dPattern} _4y - * @property {UpTo1dPattern} _5m - * @property {UpTo1dPattern} _5y - * @property {UpTo1dPattern} _6m - * @property {UpTo1dPattern} _6y - * @property {UpTo1dPattern} _7y - * @property {UpTo1dPattern} _8y + * @property {_10yPattern} _10y + * @property {_10yPattern} _12y + * @property {_10yPattern} _15y + * @property {_10yPattern} _1m + * @property {_10yPattern} _1w + * @property {_10yPattern} _1y + * @property {_10yPattern} _2m + * @property {_10yPattern} _2y + * @property {_10yPattern} _3m + * @property {_10yPattern} _3y + * @property {_10yPattern} _4m + * @property {_10yPattern} _4y + * @property {_10yPattern} _5m + * @property {_10yPattern} _5y + * @property {_10yPattern} _6m + * @property {_10yPattern} _6y + * @property {_10yPattern} _7y + * @property {_10yPattern} _8y */ /** * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_MinAge - * @property {_10yTo12yPattern} _10y - * @property {_10yTo12yPattern} _12y - * @property {_10yTo12yPattern} _1d - * @property {_10yTo12yPattern} _1m - * @property {_10yTo12yPattern} _1w - * @property {_10yTo12yPattern} _1y - * @property {_10yTo12yPattern} _2m - * @property {_10yTo12yPattern} _2y - * @property {_10yTo12yPattern} _3m - * @property {_10yTo12yPattern} _3y - * @property {_10yTo12yPattern} _4m - * @property {_10yTo12yPattern} _4y - * @property {_10yTo12yPattern} _5m - * @property {_10yTo12yPattern} _5y - * @property {_10yTo12yPattern} _6m - * @property {_10yTo12yPattern} _6y - * @property {_10yTo12yPattern} _7y - * @property {_10yTo12yPattern} _8y + * @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 */ /** @@ -3813,24 +3934,24 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Distribution_UtxoCohorts_Year - * @property {_10yTo12yPattern} _2009 - * @property {_10yTo12yPattern} _2010 - * @property {_10yTo12yPattern} _2011 - * @property {_10yTo12yPattern} _2012 - * @property {_10yTo12yPattern} _2013 - * @property {_10yTo12yPattern} _2014 - * @property {_10yTo12yPattern} _2015 - * @property {_10yTo12yPattern} _2016 - * @property {_10yTo12yPattern} _2017 - * @property {_10yTo12yPattern} _2018 - * @property {_10yTo12yPattern} _2019 - * @property {_10yTo12yPattern} _2020 - * @property {_10yTo12yPattern} _2021 - * @property {_10yTo12yPattern} _2022 - * @property {_10yTo12yPattern} _2023 - * @property {_10yTo12yPattern} _2024 - * @property {_10yTo12yPattern} _2025 - * @property {_10yTo12yPattern} _2026 + * @property {_0satsPattern2} _2009 + * @property {_0satsPattern2} _2010 + * @property {_0satsPattern2} _2011 + * @property {_0satsPattern2} _2012 + * @property {_0satsPattern2} _2013 + * @property {_0satsPattern2} _2014 + * @property {_0satsPattern2} _2015 + * @property {_0satsPattern2} _2016 + * @property {_0satsPattern2} _2017 + * @property {_0satsPattern2} _2018 + * @property {_0satsPattern2} _2019 + * @property {_0satsPattern2} _2020 + * @property {_0satsPattern2} _2021 + * @property {_0satsPattern2} _2022 + * @property {_0satsPattern2} _2023 + * @property {_0satsPattern2} _2024 + * @property {_0satsPattern2} _2025 + * @property {_0satsPattern2} _2026 */ /** @@ -3844,17 +3965,17 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Indexes_Address * @property {MetricPattern24} emptyoutputindex - * @property {MetricPattern28} opreturnindex - * @property {MetricPattern30} p2aaddressindex - * @property {MetricPattern31} p2msoutputindex - * @property {MetricPattern32} p2pk33addressindex - * @property {MetricPattern33} p2pk65addressindex - * @property {MetricPattern34} p2pkhaddressindex - * @property {MetricPattern35} p2shaddressindex - * @property {MetricPattern36} p2traddressindex - * @property {MetricPattern37} p2wpkhaddressindex - * @property {MetricPattern38} p2wshaddressindex - * @property {MetricPattern42} unknownoutputindex + * @property {MetricPattern27} opreturnindex + * @property {MetricPattern29} p2aaddressindex + * @property {MetricPattern30} p2msoutputindex + * @property {MetricPattern31} p2pk33addressindex + * @property {MetricPattern32} p2pk65addressindex + * @property {MetricPattern33} p2pkhaddressindex + * @property {MetricPattern34} p2shaddressindex + * @property {MetricPattern35} p2traddressindex + * @property {MetricPattern36} p2wpkhaddressindex + * @property {MetricPattern37} p2wshaddressindex + * @property {MetricPattern39} unknownoutputindex */ /** @@ -3890,11 +4011,11 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Indexes_Transaction - * @property {MetricPattern41} inputCount - * @property {MetricPattern41} outputCount - * @property {MetricPattern41} txindex + * @property {MetricPattern38} inputCount + * @property {MetricPattern38} outputCount + * @property {MetricPattern38} txindex * @property {MetricPattern26} txinindex - * @property {MetricPattern29} txoutindex + * @property {MetricPattern28} txoutindex */ /** @@ -3937,82 +4058,29 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Market_Dca - * @property {MetricPattern4} _10yDcaAvgPrice - * @property {MetricPattern4} _10yDcaCagr - * @property {MetricPattern4} _10yDcaReturns - * @property {MetricPattern4} _10yDcaStack - * @property {MetricPattern4} _1mDcaAvgPrice - * @property {MetricPattern4} _1mDcaReturns - * @property {MetricPattern4} _1mDcaStack - * @property {MetricPattern4} _1wDcaAvgPrice - * @property {MetricPattern4} _1wDcaReturns - * @property {MetricPattern4} _1wDcaStack - * @property {MetricPattern4} _1yDcaAvgPrice - * @property {MetricPattern4} _1yDcaReturns - * @property {MetricPattern4} _1yDcaStack - * @property {MetricPattern4} _2yDcaAvgPrice - * @property {MetricPattern4} _2yDcaCagr - * @property {MetricPattern4} _2yDcaReturns - * @property {MetricPattern4} _2yDcaStack - * @property {MetricPattern4} _3mDcaAvgPrice - * @property {MetricPattern4} _3mDcaReturns - * @property {MetricPattern4} _3mDcaStack - * @property {MetricPattern4} _3yDcaAvgPrice - * @property {MetricPattern4} _3yDcaCagr - * @property {MetricPattern4} _3yDcaReturns - * @property {MetricPattern4} _3yDcaStack - * @property {MetricPattern4} _4yDcaAvgPrice - * @property {MetricPattern4} _4yDcaCagr - * @property {MetricPattern4} _4yDcaReturns - * @property {MetricPattern4} _4yDcaStack - * @property {MetricPattern4} _5yDcaAvgPrice - * @property {MetricPattern4} _5yDcaCagr - * @property {MetricPattern4} _5yDcaReturns - * @property {MetricPattern4} _5yDcaStack - * @property {MetricPattern4} _6mDcaAvgPrice - * @property {MetricPattern4} _6mDcaReturns - * @property {MetricPattern4} _6mDcaStack - * @property {MetricPattern4} _6yDcaAvgPrice - * @property {MetricPattern4} _6yDcaCagr - * @property {MetricPattern4} _6yDcaReturns - * @property {MetricPattern4} _6yDcaStack - * @property {MetricPattern4} _8yDcaAvgPrice - * @property {MetricPattern4} _8yDcaCagr - * @property {MetricPattern4} _8yDcaReturns - * @property {MetricPattern4} _8yDcaStack - * @property {MetricPattern4} dcaClass2015AvgPrice - * @property {MetricPattern4} dcaClass2015Returns - * @property {MetricPattern4} dcaClass2015Stack - * @property {MetricPattern4} dcaClass2016AvgPrice - * @property {MetricPattern4} dcaClass2016Returns - * @property {MetricPattern4} dcaClass2016Stack - * @property {MetricPattern4} dcaClass2017AvgPrice - * @property {MetricPattern4} dcaClass2017Returns - * @property {MetricPattern4} dcaClass2017Stack - * @property {MetricPattern4} dcaClass2018AvgPrice - * @property {MetricPattern4} dcaClass2018Returns - * @property {MetricPattern4} dcaClass2018Stack - * @property {MetricPattern4} dcaClass2019AvgPrice - * @property {MetricPattern4} dcaClass2019Returns - * @property {MetricPattern4} dcaClass2019Stack - * @property {MetricPattern4} dcaClass2020AvgPrice - * @property {MetricPattern4} dcaClass2020Returns - * @property {MetricPattern4} dcaClass2020Stack - * @property {MetricPattern4} dcaClass2021AvgPrice - * @property {MetricPattern4} dcaClass2021Returns - * @property {MetricPattern4} dcaClass2021Stack - * @property {MetricPattern4} dcaClass2022AvgPrice - * @property {MetricPattern4} dcaClass2022Returns - * @property {MetricPattern4} dcaClass2022Stack - * @property {MetricPattern4} dcaClass2023AvgPrice - * @property {MetricPattern4} dcaClass2023Returns - * @property {MetricPattern4} dcaClass2023Stack - * @property {MetricPattern4} dcaClass2024AvgPrice - * @property {MetricPattern4} dcaClass2024Returns - * @property {MetricPattern4} dcaClass2024Stack - * @property {MetricPattern4} dcaClass2025AvgPrice - * @property {MetricPattern4} dcaClass2025Returns - * @property {MetricPattern4} dcaClass2025Stack + * @property {ClassAvgPricePattern} classAvgPrice + * @property {ClassAvgPricePattern} classReturns + * @property {CatalogTree_Computed_Market_Dca_ClassStack} classStack + * @property {PeriodAvgPricePattern} periodAvgPrice + * @property {PeriodCagrPattern} periodCagr + * @property {PeriodLumpSumStackPattern} periodLumpSumStack + * @property {PeriodAvgPricePattern} periodReturns + * @property {PeriodLumpSumStackPattern} periodStack + */ + +/** + * @typedef {Object} CatalogTree_Computed_Market_Dca_ClassStack + * @property {ActiveSupplyPattern} _2015 + * @property {ActiveSupplyPattern} _2016 + * @property {ActiveSupplyPattern} _2017 + * @property {ActiveSupplyPattern} _2018 + * @property {ActiveSupplyPattern} _2019 + * @property {ActiveSupplyPattern} _2020 + * @property {ActiveSupplyPattern} _2021 + * @property {ActiveSupplyPattern} _2022 + * @property {ActiveSupplyPattern} _2023 + * @property {ActiveSupplyPattern} _2024 + * @property {ActiveSupplyPattern} _2025 */ /** @@ -4040,19 +4108,7 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Market_Lookback - * @property {MetricPattern4} price10yAgo - * @property {MetricPattern4} price1dAgo - * @property {MetricPattern4} price1mAgo - * @property {MetricPattern4} price1wAgo - * @property {MetricPattern4} price1yAgo - * @property {MetricPattern4} price2yAgo - * @property {MetricPattern4} price3mAgo - * @property {MetricPattern4} price3yAgo - * @property {MetricPattern4} price4yAgo - * @property {MetricPattern4} price5yAgo - * @property {MetricPattern4} price6mAgo - * @property {MetricPattern4} price6yAgo - * @property {MetricPattern4} price8yAgo + * @property {PriceAgoPattern} priceAgo */ /** @@ -4114,30 +4170,12 @@ function createRealizedPriceExtraPattern(client, acc) { * @property {_1dReturns1mSdPattern} _1dReturns1mSd * @property {_1dReturns1mSdPattern} _1dReturns1wSd * @property {_1dReturns1mSdPattern} _1dReturns1ySd - * @property {MetricPattern4} _10yCagr - * @property {MetricPattern4} _10yPriceReturns - * @property {MetricPattern4} _1dPriceReturns - * @property {MetricPattern4} _1mPriceReturns - * @property {MetricPattern4} _1wPriceReturns - * @property {MetricPattern4} _1yPriceReturns - * @property {MetricPattern4} _2yCagr - * @property {MetricPattern4} _2yPriceReturns - * @property {MetricPattern4} _3mPriceReturns - * @property {MetricPattern4} _3yCagr - * @property {MetricPattern4} _3yPriceReturns - * @property {MetricPattern4} _4yCagr - * @property {MetricPattern4} _4yPriceReturns - * @property {MetricPattern4} _5yCagr - * @property {MetricPattern4} _5yPriceReturns - * @property {MetricPattern4} _6mPriceReturns - * @property {MetricPattern4} _6yCagr - * @property {MetricPattern4} _6yPriceReturns - * @property {MetricPattern4} _8yCagr - * @property {MetricPattern4} _8yPriceReturns + * @property {PeriodCagrPattern} cagr * @property {_1dReturns1mSdPattern} downside1mSd * @property {_1dReturns1mSdPattern} downside1wSd * @property {_1dReturns1mSdPattern} downside1ySd * @property {MetricPattern21} downsideReturns + * @property {PriceAgoPattern} priceReturns */ /** @@ -4167,7 +4205,7 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Outputs_Spent - * @property {MetricPattern29} txinindex + * @property {MetricPattern28} txinindex */ /** @@ -4475,7 +4513,7 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Computed_Transactions_Count - * @property {MetricPattern41} isCoinbase + * @property {MetricPattern38} isCoinbase * @property {BitcoinPattern} txCount */ @@ -4483,24 +4521,24 @@ function createRealizedPriceExtraPattern(client, acc) { * @typedef {Object} CatalogTree_Computed_Transactions_Fees * @property {CatalogTree_Computed_Transactions_Fees_Fee} fee * @property {CatalogTree_Computed_Transactions_Fees_FeeRate} feeRate - * @property {MetricPattern41} inputValue - * @property {MetricPattern41} outputValue + * @property {MetricPattern38} inputValue + * @property {MetricPattern38} outputValue */ /** * @typedef {Object} CatalogTree_Computed_Transactions_Fees_Fee - * @property {MetricPattern41} base + * @property {MetricPattern38} base * @property {BlockSizePattern} bitcoin - * @property {MetricPattern41} bitcoinTxindex + * @property {MetricPattern38} bitcoinTxindex * @property {BlockSizePattern} dollars - * @property {MetricPattern41} dollarsTxindex + * @property {MetricPattern38} dollarsTxindex * @property {BlockSizePattern} sats */ /** * @typedef {Object} CatalogTree_Computed_Transactions_Fees_FeeRate * @property {MetricPattern1} average - * @property {MetricPattern41} base + * @property {MetricPattern38} base * @property {MetricPattern1} max * @property {MetricPattern25} median * @property {MetricPattern1} min @@ -4514,8 +4552,8 @@ function createRealizedPriceExtraPattern(client, acc) { * @typedef {Object} CatalogTree_Computed_Transactions_Size * @property {BlockIntervalPattern} txVsize * @property {BlockIntervalPattern} txWeight - * @property {MetricPattern41} vsize - * @property {MetricPattern41} weight + * @property {MetricPattern38} vsize + * @property {MetricPattern38} weight */ /** @@ -4563,14 +4601,14 @@ function createRealizedPriceExtraPattern(client, acc) { * @property {MetricPattern25} firstP2traddressindex * @property {MetricPattern25} firstP2wpkhaddressindex * @property {MetricPattern25} firstP2wshaddressindex - * @property {MetricPattern30} p2abytes - * @property {MetricPattern32} p2pk33bytes - * @property {MetricPattern33} p2pk65bytes - * @property {MetricPattern34} p2pkhbytes - * @property {MetricPattern35} p2shbytes - * @property {MetricPattern36} p2trbytes - * @property {MetricPattern37} p2wpkhbytes - * @property {MetricPattern38} p2wshbytes + * @property {MetricPattern29} p2abytes + * @property {MetricPattern31} p2pk33bytes + * @property {MetricPattern32} p2pk65bytes + * @property {MetricPattern33} p2pkhbytes + * @property {MetricPattern34} p2shbytes + * @property {MetricPattern35} p2trbytes + * @property {MetricPattern36} p2wpkhbytes + * @property {MetricPattern37} p2wshbytes */ /** @@ -4593,16 +4631,16 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Indexed_Tx - * @property {MetricPattern41} baseSize + * @property {MetricPattern38} baseSize * @property {MetricPattern25} firstTxindex - * @property {MetricPattern41} firstTxinindex - * @property {MetricPattern41} firstTxoutindex - * @property {MetricPattern41} height - * @property {MetricPattern41} isExplicitlyRbf - * @property {MetricPattern41} rawlocktime - * @property {MetricPattern41} totalSize - * @property {MetricPattern41} txid - * @property {MetricPattern41} txversion + * @property {MetricPattern38} firstTxinindex + * @property {MetricPattern38} firstTxoutindex + * @property {MetricPattern38} height + * @property {MetricPattern38} isExplicitlyRbf + * @property {MetricPattern38} rawlocktime + * @property {MetricPattern38} totalSize + * @property {MetricPattern38} txid + * @property {MetricPattern38} txversion */ /** @@ -4617,10 +4655,10 @@ function createRealizedPriceExtraPattern(client, acc) { /** * @typedef {Object} CatalogTree_Indexed_Txout * @property {MetricPattern25} firstTxoutindex - * @property {MetricPattern29} outputtype - * @property {MetricPattern29} txindex - * @property {MetricPattern29} typeindex - * @property {MetricPattern29} value + * @property {MetricPattern28} outputtype + * @property {MetricPattern28} txindex + * @property {MetricPattern28} typeindex + * @property {MetricPattern28} value */ /** @@ -5643,20 +5681,24 @@ class BrkClient extends BrkClientBase { } }, constants: { - constant0: createConstant0Pattern(this, 'constant_0'), - constant1: createConstant0Pattern(this, 'constant_1'), - constant100: createConstant0Pattern(this, 'constant_100'), - constant2: createConstant0Pattern(this, 'constant_2'), - constant3: createConstant0Pattern(this, 'constant_3'), - constant382: createConstant0Pattern(this, 'constant_38_2'), - constant4: createConstant0Pattern(this, 'constant_4'), - constant50: createConstant0Pattern(this, 'constant_50'), - constant600: createConstant0Pattern(this, 'constant_600'), - constant618: createConstant0Pattern(this, 'constant_61_8'), - constantMinus1: createConstant0Pattern(this, 'constant_minus_1'), - constantMinus2: createConstant0Pattern(this, 'constant_minus_2'), - constantMinus3: createConstant0Pattern(this, 'constant_minus_3'), - constantMinus4: createConstant0Pattern(this, 'constant_minus_4') + constant0: createMetricPattern3(this, 'constant_0'), + constant1: createMetricPattern3(this, 'constant_1'), + constant100: createMetricPattern3(this, 'constant_100'), + constant2: createMetricPattern3(this, 'constant_2'), + constant20: createMetricPattern3(this, 'constant_20'), + constant3: createMetricPattern3(this, 'constant_3'), + constant30: createMetricPattern3(this, 'constant_30'), + constant382: createMetricPattern3(this, 'constant_38_2'), + constant4: createMetricPattern3(this, 'constant_4'), + constant50: createMetricPattern3(this, 'constant_50'), + constant600: createMetricPattern3(this, 'constant_600'), + constant618: createMetricPattern3(this, 'constant_61_8'), + constant70: createMetricPattern3(this, 'constant_70'), + constant80: createMetricPattern3(this, 'constant_80'), + constantMinus1: createMetricPattern3(this, 'constant_minus_1'), + constantMinus2: createMetricPattern3(this, 'constant_minus_2'), + constantMinus3: createMetricPattern3(this, 'constant_minus_3'), + constantMinus4: createMetricPattern3(this, 'constant_minus_4') }, distribution: { addrCount: createMetricPattern1(this, 'addr_count'), @@ -5710,18 +5752,18 @@ class BrkClient extends BrkClientBase { } }, addressesData: { - empty: createMetricPattern46(this, 'emptyaddressdata'), - loaded: createMetricPattern45(this, 'loadedaddressdata') + empty: createMetricPattern41(this, 'emptyaddressdata'), + loaded: createMetricPattern40(this, 'loadedaddressdata') }, - addresstypeToHeightToAddrCount: createAddresstypeToHeightToAddrCountPattern(this, ''), - addresstypeToHeightToEmptyAddrCount: createAddresstypeToHeightToAddrCountPattern(this, ''), - addresstypeToIndexesToAddrCount: createAddresstypeToHeightToAddrCountPattern(this, ''), - addresstypeToIndexesToEmptyAddrCount: createAddresstypeToHeightToAddrCountPattern(this, ''), + addresstypeToHeightToAddrCount: createAddresstypeToHeightToAddrCountPattern(this, 'addr_count'), + addresstypeToHeightToEmptyAddrCount: createAddresstypeToHeightToAddrCountPattern(this, 'empty_addr_count'), + addresstypeToIndexesToAddrCount: createAddresstypeToHeightToAddrCountPattern(this, 'addr_count'), + addresstypeToIndexesToEmptyAddrCount: createAddresstypeToHeightToAddrCountPattern(this, 'empty_addr_count'), anyAddressIndexes: createAddresstypeToHeightToAddrCountPattern(this, 'anyaddressindex'), chainState: createMetricPattern25(this, 'chain'), emptyAddrCount: createMetricPattern1(this, 'empty_addr_count'), - emptyaddressindex: createMetricPattern46(this, 'emptyaddressindex'), - loadedaddressindex: createMetricPattern45(this, 'loadedaddressindex'), + emptyaddressindex: createMetricPattern41(this, 'emptyaddressindex'), + loadedaddressindex: createMetricPattern40(this, 'loadedaddressindex'), utxoCohorts: { ageRange: { _10yTo12y: create_10yTo12yPattern(this, 'utxos_at_least_10y_up_to_12y_old'), @@ -5778,11 +5820,11 @@ class BrkClient extends BrkClientBase { _1satTo10sats: create_0satsPattern2(this, 'utxos_above_1sat_under_10sats') }, epoch: { - _0: create_10yTo12yPattern(this, 'epoch_0'), - _1: create_10yTo12yPattern(this, 'epoch_1'), - _2: create_10yTo12yPattern(this, 'epoch_2'), - _3: create_10yTo12yPattern(this, 'epoch_3'), - _4: create_10yTo12yPattern(this, 'epoch_4') + _0: create_0satsPattern2(this, 'epoch_0'), + _1: create_0satsPattern2(this, 'epoch_1'), + _2: create_0satsPattern2(this, 'epoch_2'), + _3: create_0satsPattern2(this, 'epoch_3'), + _4: create_0satsPattern2(this, 'epoch_4') }, geAmount: { _100btc: create_0satsPattern2(this, 'utxos_above_100btc'), @@ -5815,44 +5857,44 @@ class BrkClient extends BrkClientBase { _1mSats: create_0satsPattern2(this, 'utxos_under_1m_sats') }, maxAge: { - _10y: createUpTo1dPattern(this, 'utxos_up_to_10y_old'), - _12y: createUpTo1dPattern(this, 'utxos_up_to_12y_old'), - _15y: createUpTo1dPattern(this, 'utxos_up_to_15y_old'), - _1m: createUpTo1dPattern(this, 'utxos_up_to_1m_old'), - _1w: createUpTo1dPattern(this, 'utxos_up_to_1w_old'), - _1y: createUpTo1dPattern(this, 'utxos_up_to_1y_old'), - _2m: createUpTo1dPattern(this, 'utxos_up_to_2m_old'), - _2y: createUpTo1dPattern(this, 'utxos_up_to_2y_old'), - _3m: createUpTo1dPattern(this, 'utxos_up_to_3m_old'), - _3y: createUpTo1dPattern(this, 'utxos_up_to_3y_old'), - _4m: createUpTo1dPattern(this, 'utxos_up_to_4m_old'), - _4y: createUpTo1dPattern(this, 'utxos_up_to_4y_old'), - _5m: createUpTo1dPattern(this, 'utxos_up_to_5m_old'), - _5y: createUpTo1dPattern(this, 'utxos_up_to_5y_old'), - _6m: createUpTo1dPattern(this, 'utxos_up_to_6m_old'), - _6y: createUpTo1dPattern(this, 'utxos_up_to_6y_old'), - _7y: createUpTo1dPattern(this, 'utxos_up_to_7y_old'), - _8y: createUpTo1dPattern(this, 'utxos_up_to_8y_old') + _10y: create_10yPattern(this, 'utxos_up_to_10y_old'), + _12y: create_10yPattern(this, 'utxos_up_to_12y_old'), + _15y: create_10yPattern(this, 'utxos_up_to_15y_old'), + _1m: create_10yPattern(this, 'utxos_up_to_1m_old'), + _1w: create_10yPattern(this, 'utxos_up_to_1w_old'), + _1y: create_10yPattern(this, 'utxos_up_to_1y_old'), + _2m: create_10yPattern(this, 'utxos_up_to_2m_old'), + _2y: create_10yPattern(this, 'utxos_up_to_2y_old'), + _3m: create_10yPattern(this, 'utxos_up_to_3m_old'), + _3y: create_10yPattern(this, 'utxos_up_to_3y_old'), + _4m: create_10yPattern(this, 'utxos_up_to_4m_old'), + _4y: create_10yPattern(this, 'utxos_up_to_4y_old'), + _5m: create_10yPattern(this, 'utxos_up_to_5m_old'), + _5y: create_10yPattern(this, 'utxos_up_to_5y_old'), + _6m: create_10yPattern(this, 'utxos_up_to_6m_old'), + _6y: create_10yPattern(this, 'utxos_up_to_6y_old'), + _7y: create_10yPattern(this, 'utxos_up_to_7y_old'), + _8y: create_10yPattern(this, 'utxos_up_to_8y_old') }, minAge: { - _10y: create_10yTo12yPattern(this, 'utxos_at_least_10y_old'), - _12y: create_10yTo12yPattern(this, 'utxos_at_least_12y_old'), - _1d: create_10yTo12yPattern(this, 'utxos_at_least_1d_old'), - _1m: create_10yTo12yPattern(this, 'utxos_at_least_1m_old'), - _1w: create_10yTo12yPattern(this, 'utxos_at_least_1w_old'), - _1y: create_10yTo12yPattern(this, 'utxos_at_least_1y_old'), - _2m: create_10yTo12yPattern(this, 'utxos_at_least_2m_old'), - _2y: create_10yTo12yPattern(this, 'utxos_at_least_2y_old'), - _3m: create_10yTo12yPattern(this, 'utxos_at_least_3m_old'), - _3y: create_10yTo12yPattern(this, 'utxos_at_least_3y_old'), - _4m: create_10yTo12yPattern(this, 'utxos_at_least_4m_old'), - _4y: create_10yTo12yPattern(this, 'utxos_at_least_4y_old'), - _5m: create_10yTo12yPattern(this, 'utxos_at_least_5m_old'), - _5y: create_10yTo12yPattern(this, 'utxos_at_least_5y_old'), - _6m: create_10yTo12yPattern(this, 'utxos_at_least_6m_old'), - _6y: create_10yTo12yPattern(this, 'utxos_at_least_6y_old'), - _7y: create_10yTo12yPattern(this, 'utxos_at_least_7y_old'), - _8y: create_10yTo12yPattern(this, 'utxos_at_least_8y_old') + _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') }, term: { long: createUpTo1dPattern(this, 'lth'), @@ -5872,41 +5914,41 @@ class BrkClient extends BrkClientBase { unknown: create_0satsPattern2(this, 'unknown_outputs') }, year: { - _2009: create_10yTo12yPattern(this, 'year_2009'), - _2010: create_10yTo12yPattern(this, 'year_2010'), - _2011: create_10yTo12yPattern(this, 'year_2011'), - _2012: create_10yTo12yPattern(this, 'year_2012'), - _2013: create_10yTo12yPattern(this, 'year_2013'), - _2014: create_10yTo12yPattern(this, 'year_2014'), - _2015: create_10yTo12yPattern(this, 'year_2015'), - _2016: create_10yTo12yPattern(this, 'year_2016'), - _2017: create_10yTo12yPattern(this, 'year_2017'), - _2018: create_10yTo12yPattern(this, 'year_2018'), - _2019: create_10yTo12yPattern(this, 'year_2019'), - _2020: create_10yTo12yPattern(this, 'year_2020'), - _2021: create_10yTo12yPattern(this, 'year_2021'), - _2022: create_10yTo12yPattern(this, 'year_2022'), - _2023: create_10yTo12yPattern(this, 'year_2023'), - _2024: create_10yTo12yPattern(this, 'year_2024'), - _2025: create_10yTo12yPattern(this, 'year_2025'), - _2026: create_10yTo12yPattern(this, 'year_2026') + _2009: create_0satsPattern2(this, 'year_2009'), + _2010: create_0satsPattern2(this, 'year_2010'), + _2011: create_0satsPattern2(this, 'year_2011'), + _2012: create_0satsPattern2(this, 'year_2012'), + _2013: create_0satsPattern2(this, 'year_2013'), + _2014: create_0satsPattern2(this, 'year_2014'), + _2015: create_0satsPattern2(this, 'year_2015'), + _2016: create_0satsPattern2(this, 'year_2016'), + _2017: create_0satsPattern2(this, 'year_2017'), + _2018: create_0satsPattern2(this, 'year_2018'), + _2019: create_0satsPattern2(this, 'year_2019'), + _2020: create_0satsPattern2(this, 'year_2020'), + _2021: create_0satsPattern2(this, 'year_2021'), + _2022: create_0satsPattern2(this, 'year_2022'), + _2023: create_0satsPattern2(this, 'year_2023'), + _2024: create_0satsPattern2(this, 'year_2024'), + _2025: create_0satsPattern2(this, 'year_2025'), + _2026: create_0satsPattern2(this, 'year_2026') } } }, indexes: { address: { emptyoutputindex: createMetricPattern24(this, 'emptyoutputindex'), - opreturnindex: createMetricPattern28(this, 'opreturnindex'), - p2aaddressindex: createMetricPattern30(this, 'p2aaddressindex'), - p2msoutputindex: createMetricPattern31(this, 'p2msoutputindex'), - p2pk33addressindex: createMetricPattern32(this, 'p2pk33addressindex'), - p2pk65addressindex: createMetricPattern33(this, 'p2pk65addressindex'), - p2pkhaddressindex: createMetricPattern34(this, 'p2pkhaddressindex'), - p2shaddressindex: createMetricPattern35(this, 'p2shaddressindex'), - p2traddressindex: createMetricPattern36(this, 'p2traddressindex'), - p2wpkhaddressindex: createMetricPattern37(this, 'p2wpkhaddressindex'), - p2wshaddressindex: createMetricPattern38(this, 'p2wshaddressindex'), - unknownoutputindex: createMetricPattern42(this, 'unknownoutputindex') + opreturnindex: createMetricPattern27(this, 'opreturnindex'), + p2aaddressindex: createMetricPattern29(this, 'p2aaddressindex'), + p2msoutputindex: createMetricPattern30(this, 'p2msoutputindex'), + p2pk33addressindex: createMetricPattern31(this, 'p2pk33addressindex'), + p2pk65addressindex: createMetricPattern32(this, 'p2pk65addressindex'), + p2pkhaddressindex: createMetricPattern33(this, 'p2pkhaddressindex'), + p2shaddressindex: createMetricPattern34(this, 'p2shaddressindex'), + p2traddressindex: createMetricPattern35(this, 'p2traddressindex'), + p2wpkhaddressindex: createMetricPattern36(this, 'p2wpkhaddressindex'), + p2wshaddressindex: createMetricPattern37(this, 'p2wshaddressindex'), + unknownoutputindex: createMetricPattern39(this, 'unknownoutputindex') }, block: { dateindex: createMetricPattern25(this, 'dateindex'), @@ -5936,11 +5978,11 @@ class BrkClient extends BrkClientBase { yearindexCount: createMetricPattern22(this, 'yearindex_count') }, transaction: { - inputCount: createMetricPattern41(this, 'input_count'), - outputCount: createMetricPattern41(this, 'output_count'), - txindex: createMetricPattern41(this, 'txindex'), + inputCount: createMetricPattern38(this, 'input_count'), + outputCount: createMetricPattern38(this, 'output_count'), + txindex: createMetricPattern38(this, 'txindex'), txinindex: createMetricPattern26(this, 'txinindex'), - txoutindex: createMetricPattern29(this, 'txoutindex') + txoutindex: createMetricPattern28(this, 'txoutindex') } }, inputs: { @@ -5961,82 +6003,26 @@ class BrkClient extends BrkClientBase { priceDrawdown: createMetricPattern3(this, 'price_drawdown') }, dca: { - _10yDcaAvgPrice: createMetricPattern4(this, '10y_dca_avg_price'), - _10yDcaCagr: createMetricPattern4(this, '10y_dca_cagr'), - _10yDcaReturns: createMetricPattern4(this, '10y_dca_returns'), - _10yDcaStack: createMetricPattern4(this, '10y_dca_stack'), - _1mDcaAvgPrice: createMetricPattern4(this, '1m_dca_avg_price'), - _1mDcaReturns: createMetricPattern4(this, '1m_dca_returns'), - _1mDcaStack: createMetricPattern4(this, '1m_dca_stack'), - _1wDcaAvgPrice: createMetricPattern4(this, '1w_dca_avg_price'), - _1wDcaReturns: createMetricPattern4(this, '1w_dca_returns'), - _1wDcaStack: createMetricPattern4(this, '1w_dca_stack'), - _1yDcaAvgPrice: createMetricPattern4(this, '1y_dca_avg_price'), - _1yDcaReturns: createMetricPattern4(this, '1y_dca_returns'), - _1yDcaStack: createMetricPattern4(this, '1y_dca_stack'), - _2yDcaAvgPrice: createMetricPattern4(this, '2y_dca_avg_price'), - _2yDcaCagr: createMetricPattern4(this, '2y_dca_cagr'), - _2yDcaReturns: createMetricPattern4(this, '2y_dca_returns'), - _2yDcaStack: createMetricPattern4(this, '2y_dca_stack'), - _3mDcaAvgPrice: createMetricPattern4(this, '3m_dca_avg_price'), - _3mDcaReturns: createMetricPattern4(this, '3m_dca_returns'), - _3mDcaStack: createMetricPattern4(this, '3m_dca_stack'), - _3yDcaAvgPrice: createMetricPattern4(this, '3y_dca_avg_price'), - _3yDcaCagr: createMetricPattern4(this, '3y_dca_cagr'), - _3yDcaReturns: createMetricPattern4(this, '3y_dca_returns'), - _3yDcaStack: createMetricPattern4(this, '3y_dca_stack'), - _4yDcaAvgPrice: createMetricPattern4(this, '4y_dca_avg_price'), - _4yDcaCagr: createMetricPattern4(this, '4y_dca_cagr'), - _4yDcaReturns: createMetricPattern4(this, '4y_dca_returns'), - _4yDcaStack: createMetricPattern4(this, '4y_dca_stack'), - _5yDcaAvgPrice: createMetricPattern4(this, '5y_dca_avg_price'), - _5yDcaCagr: createMetricPattern4(this, '5y_dca_cagr'), - _5yDcaReturns: createMetricPattern4(this, '5y_dca_returns'), - _5yDcaStack: createMetricPattern4(this, '5y_dca_stack'), - _6mDcaAvgPrice: createMetricPattern4(this, '6m_dca_avg_price'), - _6mDcaReturns: createMetricPattern4(this, '6m_dca_returns'), - _6mDcaStack: createMetricPattern4(this, '6m_dca_stack'), - _6yDcaAvgPrice: createMetricPattern4(this, '6y_dca_avg_price'), - _6yDcaCagr: createMetricPattern4(this, '6y_dca_cagr'), - _6yDcaReturns: createMetricPattern4(this, '6y_dca_returns'), - _6yDcaStack: createMetricPattern4(this, '6y_dca_stack'), - _8yDcaAvgPrice: createMetricPattern4(this, '8y_dca_avg_price'), - _8yDcaCagr: createMetricPattern4(this, '8y_dca_cagr'), - _8yDcaReturns: createMetricPattern4(this, '8y_dca_returns'), - _8yDcaStack: createMetricPattern4(this, '8y_dca_stack'), - dcaClass2015AvgPrice: createMetricPattern4(this, 'dca_class_2015_avg_price'), - dcaClass2015Returns: createMetricPattern4(this, 'dca_class_2015_returns'), - dcaClass2015Stack: createMetricPattern4(this, 'dca_class_2015_stack'), - dcaClass2016AvgPrice: createMetricPattern4(this, 'dca_class_2016_avg_price'), - dcaClass2016Returns: createMetricPattern4(this, 'dca_class_2016_returns'), - dcaClass2016Stack: createMetricPattern4(this, 'dca_class_2016_stack'), - dcaClass2017AvgPrice: createMetricPattern4(this, 'dca_class_2017_avg_price'), - dcaClass2017Returns: createMetricPattern4(this, 'dca_class_2017_returns'), - dcaClass2017Stack: createMetricPattern4(this, 'dca_class_2017_stack'), - dcaClass2018AvgPrice: createMetricPattern4(this, 'dca_class_2018_avg_price'), - dcaClass2018Returns: createMetricPattern4(this, 'dca_class_2018_returns'), - dcaClass2018Stack: createMetricPattern4(this, 'dca_class_2018_stack'), - dcaClass2019AvgPrice: createMetricPattern4(this, 'dca_class_2019_avg_price'), - dcaClass2019Returns: createMetricPattern4(this, 'dca_class_2019_returns'), - dcaClass2019Stack: createMetricPattern4(this, 'dca_class_2019_stack'), - dcaClass2020AvgPrice: createMetricPattern4(this, 'dca_class_2020_avg_price'), - dcaClass2020Returns: createMetricPattern4(this, 'dca_class_2020_returns'), - dcaClass2020Stack: createMetricPattern4(this, 'dca_class_2020_stack'), - dcaClass2021AvgPrice: createMetricPattern4(this, 'dca_class_2021_avg_price'), - dcaClass2021Returns: createMetricPattern4(this, 'dca_class_2021_returns'), - dcaClass2021Stack: createMetricPattern4(this, 'dca_class_2021_stack'), - dcaClass2022AvgPrice: createMetricPattern4(this, 'dca_class_2022_avg_price'), - dcaClass2022Returns: createMetricPattern4(this, 'dca_class_2022_returns'), - dcaClass2022Stack: createMetricPattern4(this, 'dca_class_2022_stack'), - dcaClass2023AvgPrice: createMetricPattern4(this, 'dca_class_2023_avg_price'), - dcaClass2023Returns: createMetricPattern4(this, 'dca_class_2023_returns'), - dcaClass2023Stack: createMetricPattern4(this, 'dca_class_2023_stack'), - dcaClass2024AvgPrice: createMetricPattern4(this, 'dca_class_2024_avg_price'), - dcaClass2024Returns: createMetricPattern4(this, 'dca_class_2024_returns'), - dcaClass2024Stack: createMetricPattern4(this, 'dca_class_2024_stack'), - dcaClass2025AvgPrice: createMetricPattern4(this, 'dca_class_2025_avg_price'), - dcaClass2025Returns: createMetricPattern4(this, 'dca_class_2025_returns'), - dcaClass2025Stack: createMetricPattern4(this, 'dca_class_2025_stack') + classAvgPrice: createClassAvgPricePattern(this, 'dca_class'), + classReturns: createClassAvgPricePattern(this, 'dca_class'), + classStack: { + _2015: createActiveSupplyPattern(this, 'dca_class_2015_stack'), + _2016: createActiveSupplyPattern(this, 'dca_class_2016_stack'), + _2017: createActiveSupplyPattern(this, 'dca_class_2017_stack'), + _2018: createActiveSupplyPattern(this, 'dca_class_2018_stack'), + _2019: createActiveSupplyPattern(this, 'dca_class_2019_stack'), + _2020: createActiveSupplyPattern(this, 'dca_class_2020_stack'), + _2021: createActiveSupplyPattern(this, 'dca_class_2021_stack'), + _2022: createActiveSupplyPattern(this, 'dca_class_2022_stack'), + _2023: createActiveSupplyPattern(this, 'dca_class_2023_stack'), + _2024: createActiveSupplyPattern(this, 'dca_class_2024_stack'), + _2025: createActiveSupplyPattern(this, 'dca_class_2025_stack') + }, + periodAvgPrice: createPeriodAvgPricePattern(this, 'dca_avg_price'), + periodCagr: createPeriodCagrPattern(this, 'dca_cagr'), + periodLumpSumStack: createPeriodLumpSumStackPattern(this, ''), + periodReturns: createPeriodAvgPricePattern(this, 'dca_returns'), + periodStack: createPeriodLumpSumStackPattern(this, '') }, indicators: { gini: createMetricPattern21(this, 'gini'), @@ -6060,19 +6046,7 @@ class BrkClient extends BrkClientBase { stochRsiK: createMetricPattern21(this, 'stoch_rsi_k') }, lookback: { - price10yAgo: createMetricPattern4(this, 'price_10y_ago'), - price1dAgo: createMetricPattern4(this, 'price_1d_ago'), - price1mAgo: createMetricPattern4(this, 'price_1m_ago'), - price1wAgo: createMetricPattern4(this, 'price_1w_ago'), - price1yAgo: createMetricPattern4(this, 'price_1y_ago'), - price2yAgo: createMetricPattern4(this, 'price_2y_ago'), - price3mAgo: createMetricPattern4(this, 'price_3m_ago'), - price3yAgo: createMetricPattern4(this, 'price_3y_ago'), - price4yAgo: createMetricPattern4(this, 'price_4y_ago'), - price5yAgo: createMetricPattern4(this, 'price_5y_ago'), - price6mAgo: createMetricPattern4(this, 'price_6m_ago'), - price6yAgo: createMetricPattern4(this, 'price_6y_ago'), - price8yAgo: createMetricPattern4(this, 'price_8y_ago') + priceAgo: createPriceAgoPattern(this, 'price') }, movingAverage: { price111dSma: createPrice111dSmaPattern(this, 'price_111d_sma'), @@ -6128,30 +6102,12 @@ class BrkClient extends BrkClientBase { _1dReturns1mSd: create_1dReturns1mSdPattern(this, '1d_returns_1m_sd'), _1dReturns1wSd: create_1dReturns1mSdPattern(this, '1d_returns_1w_sd'), _1dReturns1ySd: create_1dReturns1mSdPattern(this, '1d_returns_1y_sd'), - _10yCagr: createMetricPattern4(this, '10y_cagr'), - _10yPriceReturns: createMetricPattern4(this, '10y_price_returns'), - _1dPriceReturns: createMetricPattern4(this, '1d_price_returns'), - _1mPriceReturns: createMetricPattern4(this, '1m_price_returns'), - _1wPriceReturns: createMetricPattern4(this, '1w_price_returns'), - _1yPriceReturns: createMetricPattern4(this, '1y_price_returns'), - _2yCagr: createMetricPattern4(this, '2y_cagr'), - _2yPriceReturns: createMetricPattern4(this, '2y_price_returns'), - _3mPriceReturns: createMetricPattern4(this, '3m_price_returns'), - _3yCagr: createMetricPattern4(this, '3y_cagr'), - _3yPriceReturns: createMetricPattern4(this, '3y_price_returns'), - _4yCagr: createMetricPattern4(this, '4y_cagr'), - _4yPriceReturns: createMetricPattern4(this, '4y_price_returns'), - _5yCagr: createMetricPattern4(this, '5y_cagr'), - _5yPriceReturns: createMetricPattern4(this, '5y_price_returns'), - _6mPriceReturns: createMetricPattern4(this, '6m_price_returns'), - _6yCagr: createMetricPattern4(this, '6y_cagr'), - _6yPriceReturns: createMetricPattern4(this, '6y_price_returns'), - _8yCagr: createMetricPattern4(this, '8y_cagr'), - _8yPriceReturns: createMetricPattern4(this, '8y_price_returns'), + cagr: createPeriodCagrPattern(this, 'cagr'), downside1mSd: create_1dReturns1mSdPattern(this, 'downside_1m_sd'), downside1wSd: create_1dReturns1mSdPattern(this, 'downside_1w_sd'), downside1ySd: create_1dReturns1mSdPattern(this, 'downside_1y_sd'), - downsideReturns: createMetricPattern21(this, 'downside_returns') + downsideReturns: createMetricPattern21(this, 'downside_returns'), + priceReturns: createPriceAgoPattern(this, 'price_returns') }, volatility: { price1mVolatility: createMetricPattern4(this, 'price_1m_volatility'), @@ -6171,7 +6127,7 @@ class BrkClient extends BrkClientBase { utxoCount: createBitcoinPattern(this, 'exact_utxo_count') }, spent: { - txinindex: createMetricPattern29(this, 'txinindex') + txinindex: createMetricPattern28(this, 'txinindex') } }, pools: { @@ -6421,21 +6377,21 @@ class BrkClient extends BrkClientBase { }, transactions: { count: { - isCoinbase: createMetricPattern41(this, 'is_coinbase'), + isCoinbase: createMetricPattern38(this, 'is_coinbase'), txCount: createBitcoinPattern(this, 'tx_count') }, fees: { fee: { - base: createMetricPattern41(this, 'fee'), + base: createMetricPattern38(this, 'fee'), bitcoin: createBlockSizePattern(this, 'fee_btc'), - bitcoinTxindex: createMetricPattern41(this, 'fee_btc'), + bitcoinTxindex: createMetricPattern38(this, 'fee_btc'), dollars: createBlockSizePattern(this, 'fee_usd'), - dollarsTxindex: createMetricPattern41(this, 'fee_usd'), + dollarsTxindex: createMetricPattern38(this, 'fee_usd'), sats: createBlockSizePattern(this, 'fee') }, feeRate: { average: createMetricPattern1(this, 'fee_rate_avg'), - base: createMetricPattern41(this, 'fee_rate'), + base: createMetricPattern38(this, 'fee_rate'), max: createMetricPattern1(this, 'fee_rate_max'), median: createMetricPattern25(this, 'fee_rate_median'), min: createMetricPattern1(this, 'fee_rate_min'), @@ -6444,14 +6400,14 @@ class BrkClient extends BrkClientBase { pct75: createMetricPattern25(this, 'fee_rate_pct75'), pct90: createMetricPattern25(this, 'fee_rate_pct90') }, - inputValue: createMetricPattern41(this, 'input_value'), - outputValue: createMetricPattern41(this, 'output_value') + inputValue: createMetricPattern38(this, 'input_value'), + outputValue: createMetricPattern38(this, 'output_value') }, size: { txVsize: createBlockIntervalPattern(this, 'tx_vsize'), txWeight: createBlockIntervalPattern(this, 'tx_weight'), - vsize: createMetricPattern41(this, 'vsize'), - weight: createMetricPattern41(this, 'weight') + vsize: createMetricPattern38(this, 'vsize'), + weight: createMetricPattern38(this, 'weight') }, versions: { txV1: createBlockCountPattern(this, 'tx_v1'), @@ -6483,14 +6439,14 @@ class BrkClient extends BrkClientBase { firstP2traddressindex: createMetricPattern25(this, 'first_p2traddressindex'), firstP2wpkhaddressindex: createMetricPattern25(this, 'first_p2wpkhaddressindex'), firstP2wshaddressindex: createMetricPattern25(this, 'first_p2wshaddressindex'), - p2abytes: createMetricPattern30(this, 'p2abytes'), - p2pk33bytes: createMetricPattern32(this, 'p2pk33bytes'), - p2pk65bytes: createMetricPattern33(this, 'p2pk65bytes'), - p2pkhbytes: createMetricPattern34(this, 'p2pkhbytes'), - p2shbytes: createMetricPattern35(this, 'p2shbytes'), - p2trbytes: createMetricPattern36(this, 'p2trbytes'), - p2wpkhbytes: createMetricPattern37(this, 'p2wpkhbytes'), - p2wshbytes: createMetricPattern38(this, 'p2wshbytes') + p2abytes: createMetricPattern29(this, 'p2abytes'), + p2pk33bytes: createMetricPattern31(this, 'p2pk33bytes'), + p2pk65bytes: createMetricPattern32(this, 'p2pk65bytes'), + p2pkhbytes: createMetricPattern33(this, 'p2pkhbytes'), + p2shbytes: createMetricPattern34(this, 'p2shbytes'), + p2trbytes: createMetricPattern35(this, 'p2trbytes'), + p2wpkhbytes: createMetricPattern36(this, 'p2wpkhbytes'), + p2wshbytes: createMetricPattern37(this, 'p2wshbytes') }, block: { blockhash: createMetricPattern25(this, 'blockhash'), @@ -6507,16 +6463,16 @@ class BrkClient extends BrkClientBase { txindex: createMetricPattern7(this, 'txindex') }, tx: { - baseSize: createMetricPattern41(this, 'base_size'), + baseSize: createMetricPattern38(this, 'base_size'), firstTxindex: createMetricPattern25(this, 'first_txindex'), - firstTxinindex: createMetricPattern41(this, 'first_txinindex'), - firstTxoutindex: createMetricPattern41(this, 'first_txoutindex'), - height: createMetricPattern41(this, 'height'), - isExplicitlyRbf: createMetricPattern41(this, 'is_explicitly_rbf'), - rawlocktime: createMetricPattern41(this, 'rawlocktime'), - totalSize: createMetricPattern41(this, 'total_size'), - txid: createMetricPattern41(this, 'txid'), - txversion: createMetricPattern41(this, 'txversion') + firstTxinindex: createMetricPattern38(this, 'first_txinindex'), + firstTxoutindex: createMetricPattern38(this, 'first_txoutindex'), + height: createMetricPattern38(this, 'height'), + isExplicitlyRbf: createMetricPattern38(this, 'is_explicitly_rbf'), + rawlocktime: createMetricPattern38(this, 'rawlocktime'), + totalSize: createMetricPattern38(this, 'total_size'), + txid: createMetricPattern38(this, 'txid'), + txversion: createMetricPattern38(this, 'txversion') }, txin: { firstTxinindex: createMetricPattern25(this, 'first_txinindex'), @@ -6527,10 +6483,10 @@ class BrkClient extends BrkClientBase { }, txout: { firstTxoutindex: createMetricPattern25(this, 'first_txoutindex'), - outputtype: createMetricPattern29(this, 'outputtype'), - txindex: createMetricPattern29(this, 'txindex'), - typeindex: createMetricPattern29(this, 'typeindex'), - value: createMetricPattern29(this, 'value') + outputtype: createMetricPattern28(this, 'outputtype'), + txindex: createMetricPattern28(this, 'txindex'), + typeindex: createMetricPattern28(this, 'typeindex'), + value: createMetricPattern28(this, 'value') } } }; diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 45b114b82..93ade6c66 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -1611,8 +1611,8 @@ class _MetricPattern27By(Generic[T]): self._client = client self._name = name - def by_monthindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'monthindex') + def by_opreturnindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'opreturnindex') class MetricPattern27(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1629,11 +1629,11 @@ class MetricPattern27(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['monthindex'] + return ['opreturnindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'monthindex': return self.by.by_monthindex() + if index == 'opreturnindex': return self.by.by_opreturnindex() return None class _MetricPattern28By(Generic[T]): @@ -1643,8 +1643,8 @@ class _MetricPattern28By(Generic[T]): self._client = client self._name = name - def by_opreturnindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'opreturnindex') + def by_txoutindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'txoutindex') class MetricPattern28(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1661,11 +1661,11 @@ class MetricPattern28(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['opreturnindex'] + return ['txoutindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'opreturnindex': return self.by.by_opreturnindex() + if index == 'txoutindex': return self.by.by_txoutindex() return None class _MetricPattern29By(Generic[T]): @@ -1675,8 +1675,8 @@ class _MetricPattern29By(Generic[T]): self._client = client self._name = name - def by_txoutindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'txoutindex') + def by_p2aaddressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2aaddressindex') class MetricPattern29(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1693,11 +1693,11 @@ class MetricPattern29(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['txoutindex'] + return ['p2aaddressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'txoutindex': return self.by.by_txoutindex() + if index == 'p2aaddressindex': return self.by.by_p2aaddressindex() return None class _MetricPattern30By(Generic[T]): @@ -1707,8 +1707,8 @@ class _MetricPattern30By(Generic[T]): self._client = client self._name = name - def by_p2aaddressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2aaddressindex') + def by_p2msoutputindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2msoutputindex') class MetricPattern30(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1725,11 +1725,11 @@ class MetricPattern30(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2aaddressindex'] + return ['p2msoutputindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2aaddressindex': return self.by.by_p2aaddressindex() + if index == 'p2msoutputindex': return self.by.by_p2msoutputindex() return None class _MetricPattern31By(Generic[T]): @@ -1739,8 +1739,8 @@ class _MetricPattern31By(Generic[T]): self._client = client self._name = name - def by_p2msoutputindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2msoutputindex') + def by_p2pk33addressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2pk33addressindex') class MetricPattern31(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1757,11 +1757,11 @@ class MetricPattern31(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2msoutputindex'] + return ['p2pk33addressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2msoutputindex': return self.by.by_p2msoutputindex() + if index == 'p2pk33addressindex': return self.by.by_p2pk33addressindex() return None class _MetricPattern32By(Generic[T]): @@ -1771,8 +1771,8 @@ class _MetricPattern32By(Generic[T]): self._client = client self._name = name - def by_p2pk33addressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2pk33addressindex') + def by_p2pk65addressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2pk65addressindex') class MetricPattern32(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1789,11 +1789,11 @@ class MetricPattern32(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2pk33addressindex'] + return ['p2pk65addressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2pk33addressindex': return self.by.by_p2pk33addressindex() + if index == 'p2pk65addressindex': return self.by.by_p2pk65addressindex() return None class _MetricPattern33By(Generic[T]): @@ -1803,8 +1803,8 @@ class _MetricPattern33By(Generic[T]): self._client = client self._name = name - def by_p2pk65addressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2pk65addressindex') + def by_p2pkhaddressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2pkhaddressindex') class MetricPattern33(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1821,11 +1821,11 @@ class MetricPattern33(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2pk65addressindex'] + return ['p2pkhaddressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2pk65addressindex': return self.by.by_p2pk65addressindex() + if index == 'p2pkhaddressindex': return self.by.by_p2pkhaddressindex() return None class _MetricPattern34By(Generic[T]): @@ -1835,8 +1835,8 @@ class _MetricPattern34By(Generic[T]): self._client = client self._name = name - def by_p2pkhaddressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2pkhaddressindex') + def by_p2shaddressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2shaddressindex') class MetricPattern34(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1853,11 +1853,11 @@ class MetricPattern34(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2pkhaddressindex'] + return ['p2shaddressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2pkhaddressindex': return self.by.by_p2pkhaddressindex() + if index == 'p2shaddressindex': return self.by.by_p2shaddressindex() return None class _MetricPattern35By(Generic[T]): @@ -1867,8 +1867,8 @@ class _MetricPattern35By(Generic[T]): self._client = client self._name = name - def by_p2shaddressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2shaddressindex') + def by_p2traddressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2traddressindex') class MetricPattern35(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1885,11 +1885,11 @@ class MetricPattern35(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2shaddressindex'] + return ['p2traddressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2shaddressindex': return self.by.by_p2shaddressindex() + if index == 'p2traddressindex': return self.by.by_p2traddressindex() return None class _MetricPattern36By(Generic[T]): @@ -1899,8 +1899,8 @@ class _MetricPattern36By(Generic[T]): self._client = client self._name = name - def by_p2traddressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2traddressindex') + def by_p2wpkhaddressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2wpkhaddressindex') class MetricPattern36(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1917,11 +1917,11 @@ class MetricPattern36(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2traddressindex'] + return ['p2wpkhaddressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2traddressindex': return self.by.by_p2traddressindex() + if index == 'p2wpkhaddressindex': return self.by.by_p2wpkhaddressindex() return None class _MetricPattern37By(Generic[T]): @@ -1931,8 +1931,8 @@ class _MetricPattern37By(Generic[T]): self._client = client self._name = name - def by_p2wpkhaddressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2wpkhaddressindex') + def by_p2wshaddressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'p2wshaddressindex') class MetricPattern37(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1949,11 +1949,11 @@ class MetricPattern37(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2wpkhaddressindex'] + return ['p2wshaddressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2wpkhaddressindex': return self.by.by_p2wpkhaddressindex() + if index == 'p2wshaddressindex': return self.by.by_p2wshaddressindex() return None class _MetricPattern38By(Generic[T]): @@ -1963,8 +1963,8 @@ class _MetricPattern38By(Generic[T]): self._client = client self._name = name - def by_p2wshaddressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'p2wshaddressindex') + def by_txindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'txindex') class MetricPattern38(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -1981,11 +1981,11 @@ class MetricPattern38(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['p2wshaddressindex'] + return ['txindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'p2wshaddressindex': return self.by.by_p2wshaddressindex() + if index == 'txindex': return self.by.by_txindex() return None class _MetricPattern39By(Generic[T]): @@ -1995,8 +1995,8 @@ class _MetricPattern39By(Generic[T]): self._client = client self._name = name - def by_quarterindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'quarterindex') + def by_unknownoutputindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'unknownoutputindex') class MetricPattern39(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -2013,11 +2013,11 @@ class MetricPattern39(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['quarterindex'] + return ['unknownoutputindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'quarterindex': return self.by.by_quarterindex() + if index == 'unknownoutputindex': return self.by.by_unknownoutputindex() return None class _MetricPattern40By(Generic[T]): @@ -2027,8 +2027,8 @@ class _MetricPattern40By(Generic[T]): self._client = client self._name = name - def by_semesterindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'semesterindex') + def by_loadedaddressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'loadedaddressindex') class MetricPattern40(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -2045,11 +2045,11 @@ class MetricPattern40(Generic[T]): def indexes(self) -> List[str]: """Get the list of available indexes.""" - return ['semesterindex'] + return ['loadedaddressindex'] def get(self, index: str) -> Optional[Endpoint[T]]: """Get an endpoint for a specific index, if supported.""" - if index == 'semesterindex': return self.by.by_semesterindex() + if index == 'loadedaddressindex': return self.by.by_loadedaddressindex() return None class _MetricPattern41By(Generic[T]): @@ -2059,8 +2059,8 @@ class _MetricPattern41By(Generic[T]): self._client = client self._name = name - def by_txindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'txindex') + def by_emptyaddressindex(self) -> Endpoint[T]: + return Endpoint(self._client, self._name, 'emptyaddressindex') class MetricPattern41(Generic[T]): """Index accessor for metrics with 1 indexes.""" @@ -2075,166 +2075,6 @@ class MetricPattern41(Generic[T]): """Get the metric name.""" return self._name - def indexes(self) -> List[str]: - """Get the list of available indexes.""" - return ['txindex'] - - def get(self, index: str) -> Optional[Endpoint[T]]: - """Get an endpoint for a specific index, if supported.""" - if index == 'txindex': return self.by.by_txindex() - return None - -class _MetricPattern42By(Generic[T]): - """Index endpoint methods container.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - - def by_unknownoutputindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'unknownoutputindex') - -class MetricPattern42(Generic[T]): - """Index accessor for metrics with 1 indexes.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - self.by: _MetricPattern42By[T] = _MetricPattern42By(client, name) - - @property - def name(self) -> str: - """Get the metric name.""" - return self._name - - def indexes(self) -> List[str]: - """Get the list of available indexes.""" - return ['unknownoutputindex'] - - def get(self, index: str) -> Optional[Endpoint[T]]: - """Get an endpoint for a specific index, if supported.""" - if index == 'unknownoutputindex': return self.by.by_unknownoutputindex() - return None - -class _MetricPattern43By(Generic[T]): - """Index endpoint methods container.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - - def by_weekindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'weekindex') - -class MetricPattern43(Generic[T]): - """Index accessor for metrics with 1 indexes.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - self.by: _MetricPattern43By[T] = _MetricPattern43By(client, name) - - @property - def name(self) -> str: - """Get the metric name.""" - return self._name - - def indexes(self) -> List[str]: - """Get the list of available indexes.""" - return ['weekindex'] - - def get(self, index: str) -> Optional[Endpoint[T]]: - """Get an endpoint for a specific index, if supported.""" - if index == 'weekindex': return self.by.by_weekindex() - return None - -class _MetricPattern44By(Generic[T]): - """Index endpoint methods container.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - - def by_yearindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'yearindex') - -class MetricPattern44(Generic[T]): - """Index accessor for metrics with 1 indexes.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - self.by: _MetricPattern44By[T] = _MetricPattern44By(client, name) - - @property - def name(self) -> str: - """Get the metric name.""" - return self._name - - def indexes(self) -> List[str]: - """Get the list of available indexes.""" - return ['yearindex'] - - def get(self, index: str) -> Optional[Endpoint[T]]: - """Get an endpoint for a specific index, if supported.""" - if index == 'yearindex': return self.by.by_yearindex() - return None - -class _MetricPattern45By(Generic[T]): - """Index endpoint methods container.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - - def by_loadedaddressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'loadedaddressindex') - -class MetricPattern45(Generic[T]): - """Index accessor for metrics with 1 indexes.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - self.by: _MetricPattern45By[T] = _MetricPattern45By(client, name) - - @property - def name(self) -> str: - """Get the metric name.""" - return self._name - - def indexes(self) -> List[str]: - """Get the list of available indexes.""" - return ['loadedaddressindex'] - - def get(self, index: str) -> Optional[Endpoint[T]]: - """Get an endpoint for a specific index, if supported.""" - if index == 'loadedaddressindex': return self.by.by_loadedaddressindex() - return None - -class _MetricPattern46By(Generic[T]): - """Index endpoint methods container.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - - def by_emptyaddressindex(self) -> Endpoint[T]: - return Endpoint(self._client, self._name, 'emptyaddressindex') - -class MetricPattern46(Generic[T]): - """Index accessor for metrics with 1 indexes.""" - - def __init__(self, client: BrkClientBase, name: str): - self._client = client - self._name = name - self.by: _MetricPattern46By[T] = _MetricPattern46By(client, name) - - @property - def name(self) -> str: - """Get the metric name.""" - return self._name - def indexes(self) -> List[str]: """Get the list of available indexes.""" return ['emptyaddressindex'] @@ -2284,6 +2124,42 @@ class RealizedPattern3: self.value_created: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'value_created')) self.value_destroyed: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'value_destroyed')) +class RealizedPattern4: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + 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.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')) + self.net_realized_pnl_cumulative_30d_delta: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'net_realized_pnl_cumulative_30d_delta')) + self.net_realized_pnl_cumulative_30d_delta_rel_to_market_cap: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'net_realized_pnl_cumulative_30d_delta_rel_to_market_cap')) + self.net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap')) + self.net_realized_pnl_rel_to_realized_cap: MetricPattern25[StoredF32] = MetricPattern25(client, _m(acc, 'net_realized_pnl_rel_to_realized_cap')) + self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap')) + self.realized_cap_30d_delta: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'realized_cap_30d_delta')) + self.realized_loss: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'realized_loss')) + self.realized_loss_rel_to_realized_cap: MetricPattern25[StoredF32] = MetricPattern25(client, _m(acc, 'realized_loss_rel_to_realized_cap')) + self.realized_price: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_price')) + self.realized_price_extra: RealizedPriceExtraPattern = RealizedPriceExtraPattern(client, _m(acc, 'realized_price')) + self.realized_profit: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'realized_profit')) + self.realized_profit_rel_to_realized_cap: MetricPattern25[StoredF32] = MetricPattern25(client, _m(acc, 'realized_profit_rel_to_realized_cap')) + self.realized_value: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_value')) + self.sell_side_risk_ratio: MetricPattern21[StoredF32] = MetricPattern21(client, _m(acc, 'sell_side_risk_ratio')) + self.sell_side_risk_ratio_30d_ema: MetricPattern21[StoredF32] = MetricPattern21(client, _m(acc, 'sell_side_risk_ratio_30d_ema')) + self.sell_side_risk_ratio_7d_ema: MetricPattern21[StoredF32] = MetricPattern21(client, _m(acc, 'sell_side_risk_ratio_7d_ema')) + self.sopr: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'sopr')) + self.sopr_30d_ema: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'sopr_30d_ema')) + self.sopr_7d_ema: MetricPattern21[StoredF64] = MetricPattern21(client, _m(acc, 'sopr_7d_ema')) + self.total_realized_pnl: TotalRealizedPnlPattern[Dollars] = TotalRealizedPnlPattern(client, _m(acc, 'total_realized_pnl')) + self.value_created: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'value_created')) + self.value_destroyed: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'value_destroyed')) + class Ratio1ySdPattern: """Pattern struct for repeated tree structure.""" @@ -2501,6 +2377,78 @@ class AXbtPattern: self.fee: SentPattern = SentPattern(client, _m(acc, 'fee')) self.subsidy: SentPattern = SentPattern(client, _m(acc, 'subsidy')) +class PriceAgoPattern(Generic[T]): + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self._10y: MetricPattern4[T] = MetricPattern4(client, _m(acc, '10y_ago')) + self._1d: MetricPattern4[T] = MetricPattern4(client, _m(acc, '1d_ago')) + self._1m: MetricPattern4[T] = MetricPattern4(client, _m(acc, '1m_ago')) + self._1w: MetricPattern4[T] = MetricPattern4(client, _m(acc, '1w_ago')) + self._1y: MetricPattern4[T] = MetricPattern4(client, _m(acc, '1y_ago')) + self._2y: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2y_ago')) + self._3m: MetricPattern4[T] = MetricPattern4(client, _m(acc, '3m_ago')) + self._3y: MetricPattern4[T] = MetricPattern4(client, _m(acc, '3y_ago')) + self._4y: MetricPattern4[T] = MetricPattern4(client, _m(acc, '4y_ago')) + self._5y: MetricPattern4[T] = MetricPattern4(client, _m(acc, '5y_ago')) + self._6m: MetricPattern4[T] = MetricPattern4(client, _m(acc, '6m_ago')) + self._6y: MetricPattern4[T] = MetricPattern4(client, _m(acc, '6y_ago')) + self._8y: MetricPattern4[T] = MetricPattern4(client, _m(acc, '8y_ago')) + +class PeriodLumpSumStackPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self._10y: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'10y_{{acc}}' if acc else '10y')) + self._1m: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'1m_{{acc}}' if acc else '1m')) + self._1w: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'1w_{{acc}}' if acc else '1w')) + self._1y: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'1y_{{acc}}' if acc else '1y')) + self._2y: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'2y_{{acc}}' if acc else '2y')) + self._3m: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'3m_{{acc}}' if acc else '3m')) + self._3y: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'3y_{{acc}}' if acc else '3y')) + self._4y: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'4y_{{acc}}' if acc else '4y')) + self._5y: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'5y_{{acc}}' if acc else '5y')) + self._6m: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'6m_{{acc}}' if acc else '6m')) + self._6y: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'6y_{{acc}}' if acc else '6y')) + self._8y: ActiveSupplyPattern = ActiveSupplyPattern(client, (f'8y_{{acc}}' if acc else '8y')) + +class PeriodAvgPricePattern(Generic[T]): + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self._10y: MetricPattern4[T] = MetricPattern4(client, (f'10y_{{acc}}' if acc else '10y')) + self._1m: MetricPattern4[T] = MetricPattern4(client, (f'1m_{{acc}}' if acc else '1m')) + self._1w: MetricPattern4[T] = MetricPattern4(client, (f'1w_{{acc}}' if acc else '1w')) + self._1y: MetricPattern4[T] = MetricPattern4(client, (f'1y_{{acc}}' if acc else '1y')) + self._2y: MetricPattern4[T] = MetricPattern4(client, (f'2y_{{acc}}' if acc else '2y')) + self._3m: MetricPattern4[T] = MetricPattern4(client, (f'3m_{{acc}}' if acc else '3m')) + self._3y: MetricPattern4[T] = MetricPattern4(client, (f'3y_{{acc}}' if acc else '3y')) + self._4y: MetricPattern4[T] = MetricPattern4(client, (f'4y_{{acc}}' if acc else '4y')) + self._5y: MetricPattern4[T] = MetricPattern4(client, (f'5y_{{acc}}' if acc else '5y')) + self._6m: MetricPattern4[T] = MetricPattern4(client, (f'6m_{{acc}}' if acc else '6m')) + 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 ClassAvgPricePattern(Generic[T]): + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_avg_price')) + self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_avg_price')) + self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_avg_price')) + self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_avg_price')) + self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_avg_price')) + self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_avg_price')) + self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_avg_price')) + self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_avg_price')) + self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_avg_price')) + 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]): """Pattern struct for repeated tree structure.""" @@ -2539,16 +2487,16 @@ class BlockSizePattern(Generic[T]): def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'avg')) + self.average: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'avg')) 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.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')) class UnrealizedPattern: """Pattern struct for repeated tree structure.""" @@ -2570,42 +2518,41 @@ class AddresstypeToHeightToAddrCountPattern(Generic[T]): def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.p2a: MetricPattern30[T] = MetricPattern30(client, (f'p2a_{{acc}}' if acc else 'p2a')) - self.p2pk33: MetricPattern32[T] = MetricPattern32(client, (f'p2pk33_{{acc}}' if acc else 'p2pk33')) - self.p2pk65: MetricPattern33[T] = MetricPattern33(client, (f'p2pk65_{{acc}}' if acc else 'p2pk65')) - self.p2pkh: MetricPattern34[T] = MetricPattern34(client, (f'p2pkh_{{acc}}' if acc else 'p2pkh')) - self.p2sh: MetricPattern35[T] = MetricPattern35(client, (f'p2sh_{{acc}}' if acc else 'p2sh')) - self.p2tr: MetricPattern36[T] = MetricPattern36(client, (f'p2tr_{{acc}}' if acc else 'p2tr')) - self.p2wpkh: MetricPattern37[T] = MetricPattern37(client, (f'p2wpkh_{{acc}}' if acc else 'p2wpkh')) - self.p2wsh: MetricPattern38[T] = MetricPattern38(client, (f'p2wsh_{{acc}}' if acc else 'p2wsh')) + 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')) 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: 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')) + 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 Constant0Pattern(Generic[T]): +class PeriodCagrPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.dateindex: MetricPattern21[T] = MetricPattern21(client, acc) - self.decadeindex: MetricPattern22[T] = MetricPattern22(client, acc) - self.height: MetricPattern25[T] = MetricPattern25(client, acc) - self.monthindex: MetricPattern27[T] = MetricPattern27(client, acc) - self.quarterindex: MetricPattern39[T] = MetricPattern39(client, acc) - self.semesterindex: MetricPattern40[T] = MetricPattern40(client, acc) - self.weekindex: MetricPattern43[T] = MetricPattern43(client, acc) - self.yearindex: MetricPattern44[T] = MetricPattern44(client, acc) + 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 _0satsPattern: """Pattern struct for repeated tree structure.""" @@ -2632,14 +2579,14 @@ class UpTo1dPattern: self.supply: SupplyPattern3 = SupplyPattern3(client, acc) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class _0satsPattern2: +class _10yPattern: """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.realized: RealizedPattern4 = RealizedPattern4(client, acc) self.relative: RelativePattern = RelativePattern(client, acc) self.supply: SupplyPattern3 = SupplyPattern3(client, acc) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) @@ -2656,6 +2603,18 @@ 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.""" @@ -2668,17 +2627,6 @@ class SegwitAdoptionPattern(Generic[T]): self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min')) self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum')) -class ActivityPattern2: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.coinblocks_destroyed: BlockCountPattern[StoredF64] = BlockCountPattern(client, _m(acc, 'coinblocks_destroyed')) - self.coindays_destroyed: BlockCountPattern[StoredF64] = BlockCountPattern(client, _m(acc, 'coindays_destroyed')) - self.satblocks_destroyed: MetricPattern25[Sats] = MetricPattern25(client, _m(acc, 'satblocks_destroyed')) - 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.""" @@ -2690,15 +2638,16 @@ class SupplyPattern3: self.supply_value: SupplyValuePattern = SupplyValuePattern(client, _m(acc, 'supply')) self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, _m(acc, 'utxo_count')) -class SentPattern: +class ActivityPattern2: """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) + self.coinblocks_destroyed: BlockCountPattern[StoredF64] = BlockCountPattern(client, _m(acc, 'coinblocks_destroyed')) + self.coindays_destroyed: BlockCountPattern[StoredF64] = BlockCountPattern(client, _m(acc, 'coindays_destroyed')) + self.satblocks_destroyed: MetricPattern25[Sats] = MetricPattern25(client, _m(acc, 'satblocks_destroyed')) + self.satdays_destroyed: MetricPattern25[Sats] = MetricPattern25(client, _m(acc, 'satdays_destroyed')) + self.sent: SentPattern = SentPattern(client, _m(acc, 'sent')) class SupplyPattern2: """Pattern struct for repeated tree structure.""" @@ -2710,6 +2659,16 @@ 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.""" @@ -2720,15 +2679,6 @@ class OpreturnPattern: self.dollars: BitcoinPattern2[Dollars] = BitcoinPattern2(client, _m(acc, 'usd')) self.sats: SatsPattern4 = SatsPattern4(client, acc) -class CoinbasePattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.bitcoin: BitcoinPattern[Bitcoin] = BitcoinPattern(client, _m(acc, 'btc')) - self.dollars: BitcoinPattern[Dollars] = BitcoinPattern(client, _m(acc, 'usd')) - self.sats: BitcoinPattern[Sats] = BitcoinPattern(client, acc) - class CostBasisPattern2: """Pattern struct for repeated tree structure.""" @@ -2738,6 +2688,15 @@ class CostBasisPattern2: self.min_cost_basis: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis')) self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis')) +class CoinbasePattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.bitcoin: BitcoinPattern[Bitcoin] = BitcoinPattern(client, _m(acc, 'btc')) + self.dollars: BitcoinPattern[Dollars] = BitcoinPattern(client, _m(acc, 'usd')) + self.sats: BitcoinPattern[Sats] = BitcoinPattern(client, acc) + class UnclaimedRewardsPattern: """Pattern struct for repeated tree structure.""" @@ -2756,15 +2715,6 @@ class ActiveSupplyPattern: self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'usd')) self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc) -class BitcoinPattern2(Generic[T]): - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.base: MetricPattern25[T] = MetricPattern25(client, acc) - self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) - self.last: MetricPattern2[T] = MetricPattern2(client, acc) - class BlockCountPattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -2774,21 +2724,14 @@ class BlockCountPattern(Generic[T]): self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum')) -class _1dReturns1mSdPattern: +class BitcoinPattern2(Generic[T]): """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd')) - self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma')) - -class SatsPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.cumulative: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'cumulative')) - self.sum: MetricPattern2[Sats] = MetricPattern2(client, acc) + self.base: MetricPattern25[T] = MetricPattern25(client, acc) + self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative')) + self.last: MetricPattern2[T] = MetricPattern2(client, acc) class CostBasisPattern: """Pattern struct for repeated tree structure.""" @@ -2798,6 +2741,14 @@ class CostBasisPattern: 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.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.cumulative: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'cumulative')) + self.last: MetricPattern2[Sats] = MetricPattern2(client, acc) + class SupplyValuePattern: """Pattern struct for repeated tree structure.""" @@ -2806,13 +2757,21 @@ class SupplyValuePattern: self.bitcoin: MetricPattern25[Bitcoin] = MetricPattern25(client, _m(acc, 'btc')) self.dollars: MetricPattern25[Dollars] = MetricPattern25(client, _m(acc, 'usd')) -class SatsPattern4: +class SatsPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" self.cumulative: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'cumulative')) - self.last: MetricPattern2[Sats] = MetricPattern2(client, acc) + self.sum: MetricPattern2[Sats] = MetricPattern2(client, acc) + +class _1dReturns1mSdPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd')) + self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma')) class TotalRealizedPnlPattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -3036,20 +2995,24 @@ class CatalogTree_Computed_Constants: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.constant_0: Constant0Pattern[StoredU16] = Constant0Pattern(client, 'constant_0') - self.constant_1: Constant0Pattern[StoredU16] = Constant0Pattern(client, 'constant_1') - self.constant_100: Constant0Pattern[StoredU16] = Constant0Pattern(client, 'constant_100') - self.constant_2: Constant0Pattern[StoredU16] = Constant0Pattern(client, 'constant_2') - self.constant_3: Constant0Pattern[StoredU16] = Constant0Pattern(client, 'constant_3') - self.constant_38_2: Constant0Pattern[StoredF32] = Constant0Pattern(client, 'constant_38_2') - self.constant_4: Constant0Pattern[StoredU16] = Constant0Pattern(client, 'constant_4') - self.constant_50: Constant0Pattern[StoredU16] = Constant0Pattern(client, 'constant_50') - self.constant_600: Constant0Pattern[StoredU16] = Constant0Pattern(client, 'constant_600') - self.constant_61_8: Constant0Pattern[StoredF32] = Constant0Pattern(client, 'constant_61_8') - self.constant_minus_1: Constant0Pattern[StoredI16] = Constant0Pattern(client, 'constant_minus_1') - self.constant_minus_2: Constant0Pattern[StoredI16] = Constant0Pattern(client, 'constant_minus_2') - self.constant_minus_3: Constant0Pattern[StoredI16] = Constant0Pattern(client, 'constant_minus_3') - self.constant_minus_4: Constant0Pattern[StoredI16] = Constant0Pattern(client, 'constant_minus_4') + self.constant_0: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_0') + self.constant_1: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_1') + self.constant_100: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_100') + self.constant_2: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_2') + self.constant_20: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_20') + self.constant_3: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_3') + self.constant_30: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_30') + self.constant_38_2: MetricPattern3[StoredF32] = MetricPattern3(client, f'{base_path}_constant_38_2') + self.constant_4: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_4') + self.constant_50: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_50') + self.constant_600: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_600') + self.constant_61_8: MetricPattern3[StoredF32] = MetricPattern3(client, f'{base_path}_constant_61_8') + self.constant_70: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_70') + self.constant_80: MetricPattern3[StoredU16] = MetricPattern3(client, f'{base_path}_constant_80') + self.constant_minus_1: MetricPattern3[StoredI16] = MetricPattern3(client, f'{base_path}_constant_minus_1') + self.constant_minus_2: MetricPattern3[StoredI16] = MetricPattern3(client, f'{base_path}_constant_minus_2') + self.constant_minus_3: MetricPattern3[StoredI16] = MetricPattern3(client, f'{base_path}_constant_minus_3') + self.constant_minus_4: MetricPattern3[StoredI16] = MetricPattern3(client, f'{base_path}_constant_minus_4') class CatalogTree_Computed_Distribution: """Catalog tree node.""" @@ -3058,15 +3021,15 @@ class CatalogTree_Computed_Distribution: self.addr_count: MetricPattern1[StoredU64] = MetricPattern1(client, f'{base_path}_addr_count') self.address_cohorts: CatalogTree_Computed_Distribution_AddressCohorts = CatalogTree_Computed_Distribution_AddressCohorts(client, f'{base_path}_address_cohorts') self.addresses_data: CatalogTree_Computed_Distribution_AddressesData = CatalogTree_Computed_Distribution_AddressesData(client, f'{base_path}_addresses_data') - self.addresstype_to_height_to_addr_count: AddresstypeToHeightToAddrCountPattern[StoredU64] = AddresstypeToHeightToAddrCountPattern(client, '') - self.addresstype_to_height_to_empty_addr_count: AddresstypeToHeightToAddrCountPattern[StoredU64] = AddresstypeToHeightToAddrCountPattern(client, '') - self.addresstype_to_indexes_to_addr_count: AddresstypeToHeightToAddrCountPattern[StoredU64] = AddresstypeToHeightToAddrCountPattern(client, '') - self.addresstype_to_indexes_to_empty_addr_count: AddresstypeToHeightToAddrCountPattern[StoredU64] = AddresstypeToHeightToAddrCountPattern(client, '') + self.addresstype_to_height_to_addr_count: AddresstypeToHeightToAddrCountPattern[StoredU64] = AddresstypeToHeightToAddrCountPattern(client, 'addr_count') + self.addresstype_to_height_to_empty_addr_count: AddresstypeToHeightToAddrCountPattern[StoredU64] = AddresstypeToHeightToAddrCountPattern(client, 'empty_addr_count') + self.addresstype_to_indexes_to_addr_count: AddresstypeToHeightToAddrCountPattern[StoredU64] = AddresstypeToHeightToAddrCountPattern(client, 'addr_count') + self.addresstype_to_indexes_to_empty_addr_count: AddresstypeToHeightToAddrCountPattern[StoredU64] = AddresstypeToHeightToAddrCountPattern(client, 'empty_addr_count') self.any_address_indexes: AddresstypeToHeightToAddrCountPattern[AnyAddressIndex] = AddresstypeToHeightToAddrCountPattern(client, 'anyaddressindex') self.chain_state: MetricPattern25[SupplyState] = MetricPattern25(client, f'{base_path}_chain_state') self.empty_addr_count: MetricPattern1[StoredU64] = MetricPattern1(client, f'{base_path}_empty_addr_count') - self.emptyaddressindex: MetricPattern46[EmptyAddressIndex] = MetricPattern46(client, f'{base_path}_emptyaddressindex') - self.loadedaddressindex: MetricPattern45[LoadedAddressIndex] = MetricPattern45(client, f'{base_path}_loadedaddressindex') + self.emptyaddressindex: MetricPattern41[EmptyAddressIndex] = MetricPattern41(client, f'{base_path}_emptyaddressindex') + self.loadedaddressindex: MetricPattern40[LoadedAddressIndex] = MetricPattern40(client, f'{base_path}_loadedaddressindex') self.utxo_cohorts: CatalogTree_Computed_Distribution_UtxoCohorts = CatalogTree_Computed_Distribution_UtxoCohorts(client, f'{base_path}_utxo_cohorts') class CatalogTree_Computed_Distribution_AddressCohorts: @@ -3137,8 +3100,8 @@ class CatalogTree_Computed_Distribution_AddressesData: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.empty: MetricPattern46[EmptyAddressData] = MetricPattern46(client, f'{base_path}_empty') - self.loaded: MetricPattern45[LoadedAddressData] = MetricPattern45(client, f'{base_path}_loaded') + self.empty: MetricPattern41[EmptyAddressData] = MetricPattern41(client, f'{base_path}_empty') + self.loaded: MetricPattern40[LoadedAddressData] = MetricPattern40(client, f'{base_path}_loaded') class CatalogTree_Computed_Distribution_UtxoCohorts: """Catalog tree node.""" @@ -3227,11 +3190,11 @@ class CatalogTree_Computed_Distribution_UtxoCohorts_Epoch: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._0: _10yTo12yPattern = _10yTo12yPattern(client, 'epoch_0') - self._1: _10yTo12yPattern = _10yTo12yPattern(client, 'epoch_1') - self._2: _10yTo12yPattern = _10yTo12yPattern(client, 'epoch_2') - self._3: _10yTo12yPattern = _10yTo12yPattern(client, 'epoch_3') - self._4: _10yTo12yPattern = _10yTo12yPattern(client, 'epoch_4') + self._0: _0satsPattern2 = _0satsPattern2(client, 'epoch_0') + self._1: _0satsPattern2 = _0satsPattern2(client, 'epoch_1') + self._2: _0satsPattern2 = _0satsPattern2(client, 'epoch_2') + self._3: _0satsPattern2 = _0satsPattern2(client, 'epoch_3') + self._4: _0satsPattern2 = _0satsPattern2(client, 'epoch_4') class CatalogTree_Computed_Distribution_UtxoCohorts_GeAmount: """Catalog tree node.""" @@ -3273,47 +3236,47 @@ class CatalogTree_Computed_Distribution_UtxoCohorts_MaxAge: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._10y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_10y_old') - self._12y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_12y_old') - self._15y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_15y_old') - self._1m: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_1m_old') - self._1w: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_1w_old') - self._1y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_1y_old') - self._2m: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_2m_old') - self._2y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_2y_old') - self._3m: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_3m_old') - self._3y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_3y_old') - self._4m: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_4m_old') - self._4y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_4y_old') - self._5m: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_5m_old') - self._5y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_5y_old') - self._6m: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_6m_old') - self._6y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_6y_old') - self._7y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_7y_old') - self._8y: UpTo1dPattern = UpTo1dPattern(client, 'utxos_up_to_8y_old') + self._10y: _10yPattern = _10yPattern(client, 'utxos_up_to_10y_old') + self._12y: _10yPattern = _10yPattern(client, 'utxos_up_to_12y_old') + self._15y: _10yPattern = _10yPattern(client, 'utxos_up_to_15y_old') + self._1m: _10yPattern = _10yPattern(client, 'utxos_up_to_1m_old') + self._1w: _10yPattern = _10yPattern(client, 'utxos_up_to_1w_old') + self._1y: _10yPattern = _10yPattern(client, 'utxos_up_to_1y_old') + self._2m: _10yPattern = _10yPattern(client, 'utxos_up_to_2m_old') + self._2y: _10yPattern = _10yPattern(client, 'utxos_up_to_2y_old') + self._3m: _10yPattern = _10yPattern(client, 'utxos_up_to_3m_old') + self._3y: _10yPattern = _10yPattern(client, 'utxos_up_to_3y_old') + self._4m: _10yPattern = _10yPattern(client, 'utxos_up_to_4m_old') + self._4y: _10yPattern = _10yPattern(client, 'utxos_up_to_4y_old') + self._5m: _10yPattern = _10yPattern(client, 'utxos_up_to_5m_old') + self._5y: _10yPattern = _10yPattern(client, 'utxos_up_to_5y_old') + self._6m: _10yPattern = _10yPattern(client, 'utxos_up_to_6m_old') + self._6y: _10yPattern = _10yPattern(client, 'utxos_up_to_6y_old') + self._7y: _10yPattern = _10yPattern(client, 'utxos_up_to_7y_old') + self._8y: _10yPattern = _10yPattern(client, 'utxos_up_to_8y_old') class CatalogTree_Computed_Distribution_UtxoCohorts_MinAge: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._10y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_10y_old') - self._12y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_12y_old') - self._1d: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1d_old') - self._1m: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1m_old') - self._1w: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1w_old') - self._1y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_1y_old') - self._2m: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_2m_old') - self._2y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_2y_old') - self._3m: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_3m_old') - self._3y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_3y_old') - self._4m: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_4m_old') - self._4y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_4y_old') - self._5m: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_5m_old') - self._5y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_5y_old') - self._6m: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_6m_old') - self._6y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_6y_old') - self._7y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_7y_old') - self._8y: _10yTo12yPattern = _10yTo12yPattern(client, 'utxos_at_least_8y_old') + 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') class CatalogTree_Computed_Distribution_UtxoCohorts_Term: """Catalog tree node.""" @@ -3342,24 +3305,24 @@ class CatalogTree_Computed_Distribution_UtxoCohorts_Year: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._2009: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2009') - self._2010: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2010') - self._2011: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2011') - self._2012: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2012') - self._2013: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2013') - self._2014: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2014') - self._2015: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2015') - self._2016: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2016') - self._2017: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2017') - self._2018: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2018') - self._2019: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2019') - self._2020: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2020') - self._2021: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2021') - self._2022: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2022') - self._2023: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2023') - self._2024: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2024') - self._2025: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2025') - self._2026: _10yTo12yPattern = _10yTo12yPattern(client, 'year_2026') + self._2009: _0satsPattern2 = _0satsPattern2(client, 'year_2009') + self._2010: _0satsPattern2 = _0satsPattern2(client, 'year_2010') + self._2011: _0satsPattern2 = _0satsPattern2(client, 'year_2011') + self._2012: _0satsPattern2 = _0satsPattern2(client, 'year_2012') + self._2013: _0satsPattern2 = _0satsPattern2(client, 'year_2013') + self._2014: _0satsPattern2 = _0satsPattern2(client, 'year_2014') + self._2015: _0satsPattern2 = _0satsPattern2(client, 'year_2015') + self._2016: _0satsPattern2 = _0satsPattern2(client, 'year_2016') + self._2017: _0satsPattern2 = _0satsPattern2(client, 'year_2017') + self._2018: _0satsPattern2 = _0satsPattern2(client, 'year_2018') + self._2019: _0satsPattern2 = _0satsPattern2(client, 'year_2019') + self._2020: _0satsPattern2 = _0satsPattern2(client, 'year_2020') + self._2021: _0satsPattern2 = _0satsPattern2(client, 'year_2021') + self._2022: _0satsPattern2 = _0satsPattern2(client, 'year_2022') + self._2023: _0satsPattern2 = _0satsPattern2(client, 'year_2023') + self._2024: _0satsPattern2 = _0satsPattern2(client, 'year_2024') + self._2025: _0satsPattern2 = _0satsPattern2(client, 'year_2025') + self._2026: _0satsPattern2 = _0satsPattern2(client, 'year_2026') class CatalogTree_Computed_Indexes: """Catalog tree node.""" @@ -3375,17 +3338,17 @@ class CatalogTree_Computed_Indexes_Address: def __init__(self, client: BrkClientBase, base_path: str = ''): self.emptyoutputindex: MetricPattern24[EmptyOutputIndex] = MetricPattern24(client, f'{base_path}_emptyoutputindex') - self.opreturnindex: MetricPattern28[OpReturnIndex] = MetricPattern28(client, f'{base_path}_opreturnindex') - self.p2aaddressindex: MetricPattern30[P2AAddressIndex] = MetricPattern30(client, f'{base_path}_p2aaddressindex') - self.p2msoutputindex: MetricPattern31[P2MSOutputIndex] = MetricPattern31(client, f'{base_path}_p2msoutputindex') - self.p2pk33addressindex: MetricPattern32[P2PK33AddressIndex] = MetricPattern32(client, f'{base_path}_p2pk33addressindex') - self.p2pk65addressindex: MetricPattern33[P2PK65AddressIndex] = MetricPattern33(client, f'{base_path}_p2pk65addressindex') - self.p2pkhaddressindex: MetricPattern34[P2PKHAddressIndex] = MetricPattern34(client, f'{base_path}_p2pkhaddressindex') - self.p2shaddressindex: MetricPattern35[P2SHAddressIndex] = MetricPattern35(client, f'{base_path}_p2shaddressindex') - self.p2traddressindex: MetricPattern36[P2TRAddressIndex] = MetricPattern36(client, f'{base_path}_p2traddressindex') - self.p2wpkhaddressindex: MetricPattern37[P2WPKHAddressIndex] = MetricPattern37(client, f'{base_path}_p2wpkhaddressindex') - self.p2wshaddressindex: MetricPattern38[P2WSHAddressIndex] = MetricPattern38(client, f'{base_path}_p2wshaddressindex') - self.unknownoutputindex: MetricPattern42[UnknownOutputIndex] = MetricPattern42(client, f'{base_path}_unknownoutputindex') + self.opreturnindex: MetricPattern27[OpReturnIndex] = MetricPattern27(client, f'{base_path}_opreturnindex') + self.p2aaddressindex: MetricPattern29[P2AAddressIndex] = MetricPattern29(client, f'{base_path}_p2aaddressindex') + self.p2msoutputindex: MetricPattern30[P2MSOutputIndex] = MetricPattern30(client, f'{base_path}_p2msoutputindex') + self.p2pk33addressindex: MetricPattern31[P2PK33AddressIndex] = MetricPattern31(client, f'{base_path}_p2pk33addressindex') + self.p2pk65addressindex: MetricPattern32[P2PK65AddressIndex] = MetricPattern32(client, f'{base_path}_p2pk65addressindex') + self.p2pkhaddressindex: MetricPattern33[P2PKHAddressIndex] = MetricPattern33(client, f'{base_path}_p2pkhaddressindex') + self.p2shaddressindex: MetricPattern34[P2SHAddressIndex] = MetricPattern34(client, f'{base_path}_p2shaddressindex') + self.p2traddressindex: MetricPattern35[P2TRAddressIndex] = MetricPattern35(client, f'{base_path}_p2traddressindex') + self.p2wpkhaddressindex: MetricPattern36[P2WPKHAddressIndex] = MetricPattern36(client, f'{base_path}_p2wpkhaddressindex') + self.p2wshaddressindex: MetricPattern37[P2WSHAddressIndex] = MetricPattern37(client, f'{base_path}_p2wshaddressindex') + self.unknownoutputindex: MetricPattern39[UnknownOutputIndex] = MetricPattern39(client, f'{base_path}_unknownoutputindex') class CatalogTree_Computed_Indexes_Block: """Catalog tree node.""" @@ -3424,11 +3387,11 @@ class CatalogTree_Computed_Indexes_Transaction: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.input_count: MetricPattern41[StoredU64] = MetricPattern41(client, f'{base_path}_input_count') - self.output_count: MetricPattern41[StoredU64] = MetricPattern41(client, f'{base_path}_output_count') - self.txindex: MetricPattern41[TxIndex] = MetricPattern41(client, f'{base_path}_txindex') + self.input_count: MetricPattern38[StoredU64] = MetricPattern38(client, f'{base_path}_input_count') + self.output_count: MetricPattern38[StoredU64] = MetricPattern38(client, f'{base_path}_output_count') + self.txindex: MetricPattern38[TxIndex] = MetricPattern38(client, f'{base_path}_txindex') self.txinindex: MetricPattern26[TxInIndex] = MetricPattern26(client, f'{base_path}_txinindex') - self.txoutindex: MetricPattern29[TxOutIndex] = MetricPattern29(client, f'{base_path}_txoutindex') + self.txoutindex: MetricPattern28[TxOutIndex] = MetricPattern28(client, f'{base_path}_txoutindex') class CatalogTree_Computed_Inputs: """Catalog tree node.""" @@ -3477,82 +3440,30 @@ class CatalogTree_Computed_Market_Dca: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self._10y_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__10y_dca_avg_price') - self._10y_dca_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__10y_dca_cagr') - self._10y_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__10y_dca_returns') - self._10y_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__10y_dca_stack') - self._1m_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__1m_dca_avg_price') - self._1m_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__1m_dca_returns') - self._1m_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__1m_dca_stack') - self._1w_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__1w_dca_avg_price') - self._1w_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__1w_dca_returns') - self._1w_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__1w_dca_stack') - self._1y_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__1y_dca_avg_price') - self._1y_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__1y_dca_returns') - self._1y_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__1y_dca_stack') - self._2y_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__2y_dca_avg_price') - self._2y_dca_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__2y_dca_cagr') - self._2y_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__2y_dca_returns') - self._2y_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__2y_dca_stack') - self._3m_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__3m_dca_avg_price') - self._3m_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__3m_dca_returns') - self._3m_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__3m_dca_stack') - self._3y_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__3y_dca_avg_price') - self._3y_dca_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__3y_dca_cagr') - self._3y_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__3y_dca_returns') - self._3y_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__3y_dca_stack') - self._4y_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__4y_dca_avg_price') - self._4y_dca_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__4y_dca_cagr') - self._4y_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__4y_dca_returns') - self._4y_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__4y_dca_stack') - self._5y_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__5y_dca_avg_price') - self._5y_dca_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__5y_dca_cagr') - self._5y_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__5y_dca_returns') - self._5y_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__5y_dca_stack') - self._6m_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__6m_dca_avg_price') - self._6m_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__6m_dca_returns') - self._6m_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__6m_dca_stack') - self._6y_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__6y_dca_avg_price') - self._6y_dca_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__6y_dca_cagr') - self._6y_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__6y_dca_returns') - self._6y_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__6y_dca_stack') - self._8y_dca_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}__8y_dca_avg_price') - self._8y_dca_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__8y_dca_cagr') - self._8y_dca_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__8y_dca_returns') - self._8y_dca_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}__8y_dca_stack') - self.dca_class_2015_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2015_avg_price') - self.dca_class_2015_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2015_returns') - self.dca_class_2015_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2015_stack') - self.dca_class_2016_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2016_avg_price') - self.dca_class_2016_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2016_returns') - self.dca_class_2016_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2016_stack') - self.dca_class_2017_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2017_avg_price') - self.dca_class_2017_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2017_returns') - self.dca_class_2017_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2017_stack') - self.dca_class_2018_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2018_avg_price') - self.dca_class_2018_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2018_returns') - self.dca_class_2018_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2018_stack') - self.dca_class_2019_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2019_avg_price') - self.dca_class_2019_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2019_returns') - self.dca_class_2019_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2019_stack') - self.dca_class_2020_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2020_avg_price') - self.dca_class_2020_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2020_returns') - self.dca_class_2020_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2020_stack') - self.dca_class_2021_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2021_avg_price') - self.dca_class_2021_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2021_returns') - self.dca_class_2021_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2021_stack') - self.dca_class_2022_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2022_avg_price') - self.dca_class_2022_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2022_returns') - self.dca_class_2022_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2022_stack') - self.dca_class_2023_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2023_avg_price') - self.dca_class_2023_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2023_returns') - self.dca_class_2023_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2023_stack') - self.dca_class_2024_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2024_avg_price') - self.dca_class_2024_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2024_returns') - self.dca_class_2024_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2024_stack') - self.dca_class_2025_avg_price: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_dca_class_2025_avg_price') - self.dca_class_2025_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}_dca_class_2025_returns') - self.dca_class_2025_stack: MetricPattern4[Sats] = MetricPattern4(client, f'{base_path}_dca_class_2025_stack') + self.class_avg_price: ClassAvgPricePattern[Dollars] = ClassAvgPricePattern(client, 'dca_class') + self.class_returns: ClassAvgPricePattern[StoredF32] = ClassAvgPricePattern(client, 'dca_class') + self.class_stack: CatalogTree_Computed_Market_Dca_ClassStack = CatalogTree_Computed_Market_Dca_ClassStack(client, f'{base_path}_class_stack') + self.period_avg_price: PeriodAvgPricePattern[Dollars] = PeriodAvgPricePattern(client, 'dca_avg_price') + self.period_cagr: PeriodCagrPattern = PeriodCagrPattern(client, 'dca_cagr') + self.period_lump_sum_stack: PeriodLumpSumStackPattern = PeriodLumpSumStackPattern(client, '') + self.period_returns: PeriodAvgPricePattern[StoredF32] = PeriodAvgPricePattern(client, 'dca_returns') + self.period_stack: PeriodLumpSumStackPattern = PeriodLumpSumStackPattern(client, '') + +class CatalogTree_Computed_Market_Dca_ClassStack: + """Catalog tree node.""" + + def __init__(self, client: BrkClientBase, base_path: str = ''): + self._2015: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2015_stack') + self._2016: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2016_stack') + self._2017: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2017_stack') + self._2018: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2018_stack') + self._2019: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2019_stack') + self._2020: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2020_stack') + self._2021: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2021_stack') + self._2022: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2022_stack') + self._2023: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2023_stack') + self._2024: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2024_stack') + self._2025: ActiveSupplyPattern = ActiveSupplyPattern(client, 'dca_class_2025_stack') class CatalogTree_Computed_Market_Indicators: """Catalog tree node.""" @@ -3582,19 +3493,7 @@ class CatalogTree_Computed_Market_Lookback: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.price_10y_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_10y_ago') - self.price_1d_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_1d_ago') - self.price_1m_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_1m_ago') - self.price_1w_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_1w_ago') - self.price_1y_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_1y_ago') - self.price_2y_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_2y_ago') - self.price_3m_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_3m_ago') - self.price_3y_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_3y_ago') - self.price_4y_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_4y_ago') - self.price_5y_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_5y_ago') - self.price_6m_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_6m_ago') - self.price_6y_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_6y_ago') - self.price_8y_ago: MetricPattern4[Dollars] = MetricPattern4(client, f'{base_path}_price_8y_ago') + self.price_ago: PriceAgoPattern[Dollars] = PriceAgoPattern(client, 'price') class CatalogTree_Computed_Market_MovingAverage: """Catalog tree node.""" @@ -3659,30 +3558,12 @@ class CatalogTree_Computed_Market_Returns: self._1d_returns_1m_sd: _1dReturns1mSdPattern = _1dReturns1mSdPattern(client, '1d_returns_1m_sd') self._1d_returns_1w_sd: _1dReturns1mSdPattern = _1dReturns1mSdPattern(client, '1d_returns_1w_sd') self._1d_returns_1y_sd: _1dReturns1mSdPattern = _1dReturns1mSdPattern(client, '1d_returns_1y_sd') - self._10y_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__10y_cagr') - self._10y_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__10y_price_returns') - self._1d_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__1d_price_returns') - self._1m_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__1m_price_returns') - self._1w_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__1w_price_returns') - self._1y_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__1y_price_returns') - self._2y_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__2y_cagr') - self._2y_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__2y_price_returns') - self._3m_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__3m_price_returns') - self._3y_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__3y_cagr') - self._3y_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__3y_price_returns') - self._4y_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__4y_cagr') - self._4y_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__4y_price_returns') - self._5y_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__5y_cagr') - self._5y_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__5y_price_returns') - self._6m_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__6m_price_returns') - self._6y_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__6y_cagr') - self._6y_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__6y_price_returns') - self._8y_cagr: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__8y_cagr') - self._8y_price_returns: MetricPattern4[StoredF32] = MetricPattern4(client, f'{base_path}__8y_price_returns') + self.cagr: PeriodCagrPattern = PeriodCagrPattern(client, 'cagr') self.downside_1m_sd: _1dReturns1mSdPattern = _1dReturns1mSdPattern(client, 'downside_1m_sd') self.downside_1w_sd: _1dReturns1mSdPattern = _1dReturns1mSdPattern(client, 'downside_1w_sd') self.downside_1y_sd: _1dReturns1mSdPattern = _1dReturns1mSdPattern(client, 'downside_1y_sd') self.downside_returns: MetricPattern21[StoredF32] = MetricPattern21(client, f'{base_path}_downside_returns') + self.price_returns: PriceAgoPattern[StoredF32] = PriceAgoPattern(client, 'price_returns') class CatalogTree_Computed_Market_Volatility: """Catalog tree node.""" @@ -3716,7 +3597,7 @@ class CatalogTree_Computed_Outputs_Spent: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.txinindex: MetricPattern29[TxInIndex] = MetricPattern29(client, f'{base_path}_txinindex') + self.txinindex: MetricPattern28[TxInIndex] = MetricPattern28(client, f'{base_path}_txinindex') class CatalogTree_Computed_Pools: """Catalog tree node.""" @@ -4044,7 +3925,7 @@ class CatalogTree_Computed_Transactions_Count: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.is_coinbase: MetricPattern41[StoredBool] = MetricPattern41(client, f'{base_path}_is_coinbase') + self.is_coinbase: MetricPattern38[StoredBool] = MetricPattern38(client, f'{base_path}_is_coinbase') self.tx_count: BitcoinPattern[StoredU64] = BitcoinPattern(client, 'tx_count') class CatalogTree_Computed_Transactions_Fees: @@ -4053,18 +3934,18 @@ class CatalogTree_Computed_Transactions_Fees: def __init__(self, client: BrkClientBase, base_path: str = ''): self.fee: CatalogTree_Computed_Transactions_Fees_Fee = CatalogTree_Computed_Transactions_Fees_Fee(client, f'{base_path}_fee') self.fee_rate: CatalogTree_Computed_Transactions_Fees_FeeRate = CatalogTree_Computed_Transactions_Fees_FeeRate(client, f'{base_path}_fee_rate') - self.input_value: MetricPattern41[Sats] = MetricPattern41(client, f'{base_path}_input_value') - self.output_value: MetricPattern41[Sats] = MetricPattern41(client, f'{base_path}_output_value') + self.input_value: MetricPattern38[Sats] = MetricPattern38(client, f'{base_path}_input_value') + self.output_value: MetricPattern38[Sats] = MetricPattern38(client, f'{base_path}_output_value') class CatalogTree_Computed_Transactions_Fees_Fee: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.base: MetricPattern41[Sats] = MetricPattern41(client, f'{base_path}_base') + self.base: MetricPattern38[Sats] = MetricPattern38(client, f'{base_path}_base') self.bitcoin: BlockSizePattern[Bitcoin] = BlockSizePattern(client, 'fee_btc') - self.bitcoin_txindex: MetricPattern41[Bitcoin] = MetricPattern41(client, f'{base_path}_bitcoin_txindex') + self.bitcoin_txindex: MetricPattern38[Bitcoin] = MetricPattern38(client, f'{base_path}_bitcoin_txindex') self.dollars: BlockSizePattern[Dollars] = BlockSizePattern(client, 'fee_usd') - self.dollars_txindex: MetricPattern41[Dollars] = MetricPattern41(client, f'{base_path}_dollars_txindex') + self.dollars_txindex: MetricPattern38[Dollars] = MetricPattern38(client, f'{base_path}_dollars_txindex') self.sats: BlockSizePattern[Sats] = BlockSizePattern(client, 'fee') class CatalogTree_Computed_Transactions_Fees_FeeRate: @@ -4072,7 +3953,7 @@ class CatalogTree_Computed_Transactions_Fees_FeeRate: def __init__(self, client: BrkClientBase, base_path: str = ''): self.average: MetricPattern1[FeeRate] = MetricPattern1(client, f'{base_path}_average') - self.base: MetricPattern41[FeeRate] = MetricPattern41(client, f'{base_path}_base') + self.base: MetricPattern38[FeeRate] = MetricPattern38(client, f'{base_path}_base') self.max: MetricPattern1[FeeRate] = MetricPattern1(client, f'{base_path}_max') self.median: MetricPattern25[FeeRate] = MetricPattern25(client, f'{base_path}_median') self.min: MetricPattern1[FeeRate] = MetricPattern1(client, f'{base_path}_min') @@ -4087,8 +3968,8 @@ class CatalogTree_Computed_Transactions_Size: def __init__(self, client: BrkClientBase, base_path: str = ''): self.tx_vsize: BlockIntervalPattern[VSize] = BlockIntervalPattern(client, 'tx_vsize') self.tx_weight: BlockIntervalPattern[Weight] = BlockIntervalPattern(client, 'tx_weight') - self.vsize: MetricPattern41[VSize] = MetricPattern41(client, f'{base_path}_vsize') - self.weight: MetricPattern41[Weight] = MetricPattern41(client, f'{base_path}_weight') + self.vsize: MetricPattern38[VSize] = MetricPattern38(client, f'{base_path}_vsize') + self.weight: MetricPattern38[Weight] = MetricPattern38(client, f'{base_path}_weight') class CatalogTree_Computed_Transactions_Versions: """Catalog tree node.""" @@ -4141,14 +4022,14 @@ class CatalogTree_Indexed_Address: self.first_p2traddressindex: MetricPattern25[P2TRAddressIndex] = MetricPattern25(client, f'{base_path}_first_p2traddressindex') self.first_p2wpkhaddressindex: MetricPattern25[P2WPKHAddressIndex] = MetricPattern25(client, f'{base_path}_first_p2wpkhaddressindex') self.first_p2wshaddressindex: MetricPattern25[P2WSHAddressIndex] = MetricPattern25(client, f'{base_path}_first_p2wshaddressindex') - self.p2abytes: MetricPattern30[P2ABytes] = MetricPattern30(client, f'{base_path}_p2abytes') - self.p2pk33bytes: MetricPattern32[P2PK33Bytes] = MetricPattern32(client, f'{base_path}_p2pk33bytes') - self.p2pk65bytes: MetricPattern33[P2PK65Bytes] = MetricPattern33(client, f'{base_path}_p2pk65bytes') - self.p2pkhbytes: MetricPattern34[P2PKHBytes] = MetricPattern34(client, f'{base_path}_p2pkhbytes') - self.p2shbytes: MetricPattern35[P2SHBytes] = MetricPattern35(client, f'{base_path}_p2shbytes') - self.p2trbytes: MetricPattern36[P2TRBytes] = MetricPattern36(client, f'{base_path}_p2trbytes') - self.p2wpkhbytes: MetricPattern37[P2WPKHBytes] = MetricPattern37(client, f'{base_path}_p2wpkhbytes') - self.p2wshbytes: MetricPattern38[P2WSHBytes] = MetricPattern38(client, f'{base_path}_p2wshbytes') + self.p2abytes: MetricPattern29[P2ABytes] = MetricPattern29(client, f'{base_path}_p2abytes') + self.p2pk33bytes: MetricPattern31[P2PK33Bytes] = MetricPattern31(client, f'{base_path}_p2pk33bytes') + self.p2pk65bytes: MetricPattern32[P2PK65Bytes] = MetricPattern32(client, f'{base_path}_p2pk65bytes') + self.p2pkhbytes: MetricPattern33[P2PKHBytes] = MetricPattern33(client, f'{base_path}_p2pkhbytes') + self.p2shbytes: MetricPattern34[P2SHBytes] = MetricPattern34(client, f'{base_path}_p2shbytes') + self.p2trbytes: MetricPattern35[P2TRBytes] = MetricPattern35(client, f'{base_path}_p2trbytes') + self.p2wpkhbytes: MetricPattern36[P2WPKHBytes] = MetricPattern36(client, f'{base_path}_p2wpkhbytes') + self.p2wshbytes: MetricPattern37[P2WSHBytes] = MetricPattern37(client, f'{base_path}_p2wshbytes') class CatalogTree_Indexed_Block: """Catalog tree node.""" @@ -4174,16 +4055,16 @@ class CatalogTree_Indexed_Tx: """Catalog tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.base_size: MetricPattern41[StoredU32] = MetricPattern41(client, f'{base_path}_base_size') + self.base_size: MetricPattern38[StoredU32] = MetricPattern38(client, f'{base_path}_base_size') self.first_txindex: MetricPattern25[TxIndex] = MetricPattern25(client, f'{base_path}_first_txindex') - self.first_txinindex: MetricPattern41[TxInIndex] = MetricPattern41(client, f'{base_path}_first_txinindex') - self.first_txoutindex: MetricPattern41[TxOutIndex] = MetricPattern41(client, f'{base_path}_first_txoutindex') - self.height: MetricPattern41[Height] = MetricPattern41(client, f'{base_path}_height') - self.is_explicitly_rbf: MetricPattern41[StoredBool] = MetricPattern41(client, f'{base_path}_is_explicitly_rbf') - self.rawlocktime: MetricPattern41[RawLockTime] = MetricPattern41(client, f'{base_path}_rawlocktime') - self.total_size: MetricPattern41[StoredU32] = MetricPattern41(client, f'{base_path}_total_size') - self.txid: MetricPattern41[Txid] = MetricPattern41(client, f'{base_path}_txid') - self.txversion: MetricPattern41[TxVersion] = MetricPattern41(client, f'{base_path}_txversion') + self.first_txinindex: MetricPattern38[TxInIndex] = MetricPattern38(client, f'{base_path}_first_txinindex') + self.first_txoutindex: MetricPattern38[TxOutIndex] = MetricPattern38(client, f'{base_path}_first_txoutindex') + self.height: MetricPattern38[Height] = MetricPattern38(client, f'{base_path}_height') + self.is_explicitly_rbf: MetricPattern38[StoredBool] = MetricPattern38(client, f'{base_path}_is_explicitly_rbf') + self.rawlocktime: MetricPattern38[RawLockTime] = MetricPattern38(client, f'{base_path}_rawlocktime') + self.total_size: MetricPattern38[StoredU32] = MetricPattern38(client, f'{base_path}_total_size') + self.txid: MetricPattern38[Txid] = MetricPattern38(client, f'{base_path}_txid') + self.txversion: MetricPattern38[TxVersion] = MetricPattern38(client, f'{base_path}_txversion') class CatalogTree_Indexed_Txin: """Catalog tree node.""" @@ -4200,10 +4081,10 @@ class CatalogTree_Indexed_Txout: def __init__(self, client: BrkClientBase, base_path: str = ''): self.first_txoutindex: MetricPattern25[TxOutIndex] = MetricPattern25(client, f'{base_path}_first_txoutindex') - self.outputtype: MetricPattern29[OutputType] = MetricPattern29(client, f'{base_path}_outputtype') - self.txindex: MetricPattern29[TxIndex] = MetricPattern29(client, f'{base_path}_txindex') - self.typeindex: MetricPattern29[TypeIndex] = MetricPattern29(client, f'{base_path}_typeindex') - self.value: MetricPattern29[Sats] = MetricPattern29(client, f'{base_path}_value') + self.outputtype: MetricPattern28[OutputType] = MetricPattern28(client, f'{base_path}_outputtype') + self.txindex: MetricPattern28[TxIndex] = MetricPattern28(client, f'{base_path}_txindex') + self.typeindex: MetricPattern28[TypeIndex] = MetricPattern28(client, f'{base_path}_typeindex') + self.value: MetricPattern28[Sats] = MetricPattern28(client, f'{base_path}_value') class BrkClient(BrkClientBase): """Main BRK client with catalog tree and API methods.""" diff --git a/websites/.gitignore b/websites/.gitignore deleted file mode 100644 index 3a599655c..000000000 --- a/websites/.gitignore +++ /dev/null @@ -1 +0,0 @@ -**/scripts/modules diff --git a/websites/bitview/scripts/chart/index.js b/websites/bitview/scripts/chart/index.js index e4244d1c5..168533cfd 100644 --- a/websites/bitview/scripts/chart/index.js +++ b/websites/bitview/scripts/chart/index.js @@ -1,5 +1,3 @@ -/** @import { IChartApi, ISeriesApi as _ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData as _BaselineData, HistogramData as _HistogramData, SeriesType, IPaneApi, LineSeriesPartialOptions as _LineSeriesPartialOptions, HistogramSeriesPartialOptions as _HistogramSeriesPartialOptions, BaselineSeriesPartialOptions as _BaselineSeriesPartialOptions, CandlestickSeriesPartialOptions as _CandlestickSeriesPartialOptions, WhitespaceData, DeepPartial, ChartOptions, Time, LineData as _LineData, createChart as CreateChart } from '../modules/lightweight-charts/5.0.9/dist/typings' */ - import { createChart as _createChart, CandlestickSeries, @@ -29,7 +27,7 @@ import { style } from "../utils/elements"; * @typedef {Object} Indexed * @property {number} index * - * @typedef {_ISeriesApi} ISeries + * @typedef {_ISeriesApi} ISeries * @typedef {_ISeriesApi<'Candlestick', number>} CandlestickISeries * @typedef {_ISeriesApi<'Histogram', number>} HistogramISeries * @typedef {_ISeriesApi<'Line', number>} LineISeries @@ -275,7 +273,7 @@ function createChartElement({ /** * @param {Object} args * @param {Unit} args.unit - * @param {SeriesType} args.seriesType + * @param {LCSeriesType} args.seriesType * @param {number} args.paneIndex */ function addPriceScaleSelectorIfNeeded({ unit, paneIndex, seriesType }) { @@ -315,8 +313,8 @@ function createChartElement({ * @param {Unit} args.unit * @param {number} args.order * @param {Color[]} args.colors - * @param {SeriesType} args.seriesType - * @param {MetricAccessor} [args.metric] + * @param {LCSeriesType} args.seriesType + * @param {AnyMetricPattern} [args.metric] * @param {SetDataCallback} [args.setDataCallback] * @param {Accessor[]>} [args.data] * @param {number} args.paneIndex @@ -559,7 +557,7 @@ function createChartElement({ * @param {string} args.name * @param {Unit} args.unit * @param {number} args.order - * @param {MetricAccessor} [args.metric] + * @param {AnyMetricPattern} [args.metric] * @param {Accessor} [args.data] * @param {number} [args.paneIndex] * @param {boolean} [args.defaultActive] @@ -618,8 +616,8 @@ function createChartElement({ * @param {string} args.name * @param {Unit} args.unit * @param {number} args.order - * @param {Color} args.color - * @param {MetricAccessor} [args.metric] + * @param {Color | [Color, Color]} [args.color] - Single color or [positive, negative] colors + * @param {AnyMetricPattern} [args.metric] * @param {Accessor} [args.data] * @param {number} [args.paneIndex] * @param {boolean} [args.defaultActive] @@ -630,7 +628,7 @@ function createChartElement({ metric, name, unit, - color, + color = [colors.green, colors.red], order, paneIndex = 0, defaultActive, @@ -638,21 +636,26 @@ function createChartElement({ data, options, }) { + const isDualColor = Array.isArray(color); + const positiveColor = isDualColor ? color[0] : color; + const negativeColor = isDualColor ? color[1] : color; + /** @type {HistogramISeries} */ const iseries = /** @type {any} */ ( ichart.addSeries( /** @type {SeriesDefinition<'Histogram'>} */ (HistogramSeries), { - color: color(), + color: positiveColor(), visible: defaultActive !== false, priceLineVisible: false, + ...options, }, paneIndex, ) ); return addSeries({ - colors: [color], + colors: isDualColor ? [positiveColor, negativeColor] : [positiveColor], iseries, name, order, @@ -660,7 +663,20 @@ function createChartElement({ seriesType: "Bar", unit, data, - setDataCallback, + setDataCallback: isDualColor + ? (args) => { + iseries.setData( + iseries.data().map((d) => ({ + ...d, + color: + "value" in d && d.value >= 0 + ? positiveColor() + : negativeColor(), + })), + ); + setDataCallback?.(args); + } + : setDataCallback, defaultActive, metric, }); @@ -671,7 +687,7 @@ function createChartElement({ * @param {Unit} args.unit * @param {number} args.order * @param {Accessor} [args.data] - * @param {MetricAccessor} [args.metric] + * @param {AnyMetricPattern} [args.metric] * @param {Color} [args.color] * @param {SetDataCallback} [args.setDataCallback] * @param {number} [args.paneIndex] @@ -730,7 +746,7 @@ function createChartElement({ * @param {Unit} args.unit * @param {number} args.order * @param {Accessor} [args.data] - * @param {MetricAccessor} [args.metric] + * @param {AnyMetricPattern} [args.metric] * @param {SetDataCallback} [args.setDataCallback] * @param {number} [args.paneIndex] * @param {boolean} [args.defaultActive] diff --git a/websites/bitview/scripts/entry.js b/websites/bitview/scripts/entry.js index ffcb5fe71..4981f4f44 100644 --- a/websites/bitview/scripts/entry.js +++ b/websites/bitview/scripts/entry.js @@ -1,9 +1,11 @@ /** * @import * as _ from "./modules/leeoniya-ufuzzy/1.0.19/dist/uFuzzy.d.ts" * + * @import { IChartApi, ISeriesApi as _ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData as _BaselineData, HistogramData as _HistogramData, SeriesType as LCSeriesType, IPaneApi, LineSeriesPartialOptions as _LineSeriesPartialOptions, HistogramSeriesPartialOptions as _HistogramSeriesPartialOptions, BaselineSeriesPartialOptions as _BaselineSeriesPartialOptions, CandlestickSeriesPartialOptions as _CandlestickSeriesPartialOptions, WhitespaceData, DeepPartial, ChartOptions, Time, LineData as _LineData, createChart as CreateChart, LineStyle } from './modules/lightweight-charts/5.0.9/dist/typings' + * * @import { Signal, Signals, Accessor } from "./signals"; * - * @import { BrkClient, CatalogTree_Computed_Distribution_UtxoCohorts as UtxoCohortTree, CatalogTree_Computed_Distribution_AddressCohorts as AddressCohortTree, CatalogTree_Computed_Distribution_UtxoCohorts_All as AllUtxoPattern, UpTo1dPattern as MaxAgePattern, _10yTo12yPattern as MinAgePattern, _0satsPattern2 as UtxoAmountPattern, _0satsPattern as AddressAmountPattern, Ratio1ySdPattern, Dollars, Price111dSmaPattern as EmaRatioPattern, Index, BlockCountPattern, BitcoinPattern, BlockSizePattern, BlockIntervalPattern, CoinbasePattern, Constant0Pattern, ActivePriceRatioPattern, _0satsPattern, PricePaidPattern2, UnclaimedRewardsPattern as ValuePattern, SentPattern as RewardPattern, Metric } from "./modules/brk-client/index.js" + * @import { BrkClient, CatalogTree_Computed_Distribution_UtxoCohorts as UtxoCohortTree, CatalogTree_Computed_Distribution_AddressCohorts as AddressCohortTree, CatalogTree_Computed_Distribution_UtxoCohorts_All as AllUtxoPattern, UpTo1dPattern as MaxAgePattern, _10yTo12yPattern as MinAgePattern, _0satsPattern2 as UtxoAmountPattern, _0satsPattern as AddressAmountPattern, Ratio1ySdPattern, Dollars, Price111dSmaPattern as EmaRatioPattern, Index, BlockCountPattern, BitcoinPattern, BlockSizePattern, BlockIntervalPattern, CoinbasePattern, ActivePriceRatioPattern, _0satsPattern, UnclaimedRewardsPattern as ValuePattern, SentPattern as RewardPattern, Metric, MetricPattern, AnyMetricPattern } from "./modules/brk-client/index.js" * * @import { Resources, MetricResource } from './resources' * @@ -13,7 +15,7 @@ * * @import { WebSockets } from "./utils/ws" * - * @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, SeriesType, AnyFetchedSeriesBlueprint, TableOption, ExplorerOption, UrlOption, PartialOptionsGroup, OptionsGroup, PartialOptionsTree, UtxoCohortObject, AddressCohortObject, CohortObject, UtxoCohortGroupObject, AddressCohortGroupObject, CohortGroupObject, MetricAccessor, FetchedLineSeriesBlueprint, PartialContext, AgeCohortObject, AmountCohortObject, AgeCohortGroupObject, AmountCohortGroupObject } from "./options/partial/index.js" + * @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, SeriesType, AnyFetchedSeriesBlueprint, TableOption, ExplorerOption, UrlOption, PartialOptionsGroup, OptionsGroup, PartialOptionsTree, UtxoCohortObject, AddressCohortObject, CohortObject, UtxoCohortGroupObject, AddressCohortGroupObject, CohortGroupObject, FetchedLineSeriesBlueprint, FetchedHistogramSeriesBlueprint, PartialContext, AgeCohortObject, AmountCohortObject, AgeCohortGroupObject, AmountCohortGroupObject } from "./options/partial/index.js" * * @import { Unit } from "./utils/serde" * @@ -58,7 +60,7 @@ * @typedef {Market["dca"]} MarketDca * * Generic tree node type for walking - * @typedef {MetricAccessor | Record} TreeNode + * @typedef {AnyMetricPattern | Record} TreeNode */ // DO NOT CHANGE, Exact format is expected in `brk_bundler` diff --git a/websites/bitview/scripts/modules b/websites/bitview/scripts/modules new file mode 120000 index 000000000..5be29a99c --- /dev/null +++ b/websites/bitview/scripts/modules @@ -0,0 +1 @@ +../../../modules \ No newline at end of file diff --git a/websites/bitview/scripts/options/full.js b/websites/bitview/scripts/options/full.js index a731ac4dc..c718c7a62 100644 --- a/websites/bitview/scripts/options/full.js +++ b/websites/bitview/scripts/options/full.js @@ -48,10 +48,16 @@ export function initOptions({ colors, signals, brk, qrcode }) { * @param {AnyFetchedSeriesBlueprint[]} [arr] */ function arrayToRecord(arr = []) { - return (arr || []).reduce((record, blueprint) => { + return [...(arr || [])].reduce((record, blueprint) => { + if (!blueprint.metric) { + throw new Error( + `Blueprint missing metric: ${JSON.stringify(blueprint)}`, + ); + } markUsed(blueprint.metric); // Use any index's path - unit is the same regardless of index (e.g., supply is "sats" for both height and dateindex) - const unit = blueprint.unit ?? serdeUnit.deserialize(blueprint.metric.name); + const unit = + blueprint.unit ?? serdeUnit.deserialize(blueprint.metric.name); record[unit] ??= []; record[unit].push(blueprint); return record; diff --git a/websites/bitview/scripts/options/partial.js b/websites/bitview/scripts/options/partial.js deleted file mode 100644 index b1d68f51a..000000000 --- a/websites/bitview/scripts/options/partial.js +++ /dev/null @@ -1,4376 +0,0 @@ -// @ts-nocheck - -/** - * A tree accessor - an object with a `.by` property containing MetricNodes keyed by index name. - * Example: brk.tree.computed.price.priceClose has { by: { dateindex: MetricNode, height: MetricNode, ... } } - * @template T - * @typedef {{ by: Partial>>, indexes: () => Index[] }} MetricAccessor - */ - -/** - * @typedef {Object} BaseSeriesBlueprint - * @property {string} title - * @property {boolean} [defaultActive] - * - * @typedef {Object} BaselineSeriesBlueprintSpecific - * @property {"Baseline"} type - * @property {Color} [color] - * @property {[Color, Color]} [colors] - * @property {BaselineSeriesPartialOptions} [options] - * @property {Accessor} [data] - * @typedef {BaseSeriesBlueprint & BaselineSeriesBlueprintSpecific} BaselineSeriesBlueprint - * - * @typedef {Object} CandlestickSeriesBlueprintSpecific - * @property {"Candlestick"} type - * @property {Color} [color] - * @property {CandlestickSeriesPartialOptions} [options] - * @property {Accessor} [data] - * @typedef {BaseSeriesBlueprint & CandlestickSeriesBlueprintSpecific} CandlestickSeriesBlueprint - * - * @typedef {Object} LineSeriesBlueprintSpecific - * @property {"Line"} [type] - * @property {Color} [color] - * @property {LineSeriesPartialOptions} [options] - * @property {Accessor} [data] - * @typedef {BaseSeriesBlueprint & LineSeriesBlueprintSpecific} LineSeriesBlueprint - * - * @typedef {Object} HistogramSeriesBlueprintSpecific - * @property {"Histogram"} type - * @property {Color} color - * @property {HistogramSeriesPartialOptions} [options] - * @property {Accessor} [data] - * @typedef {BaseSeriesBlueprint & HistogramSeriesBlueprintSpecific} HistogramSeriesBlueprint - * - * @typedef {BaselineSeriesBlueprint | CandlestickSeriesBlueprint | LineSeriesBlueprint | HistogramSeriesBlueprint} AnySeriesBlueprint - * - * @typedef {AnySeriesBlueprint["type"]} SeriesType - * - * @typedef {{ metric: MetricAccessor, unit?: Unit }} FetchedAnySeriesOptions - * - * @typedef {BaselineSeriesBlueprint & FetchedAnySeriesOptions} FetchedBaselineSeriesBlueprint - * @typedef {CandlestickSeriesBlueprint & FetchedAnySeriesOptions} FetchedCandlestickSeriesBlueprint - * @typedef {LineSeriesBlueprint & FetchedAnySeriesOptions} FetchedLineSeriesBlueprint - * @typedef {HistogramSeriesBlueprint & FetchedAnySeriesOptions} FetchedHistogramSeriesBlueprint - * @typedef {AnySeriesBlueprint & FetchedAnySeriesOptions} AnyFetchedSeriesBlueprint - * - * @typedef {Object} PartialOption - * @property {string} name - * - * @typedef {Object} ProcessedOptionAddons - * @property {string} title - * @property {string[]} path - * - * @typedef {Object} PartialExplorerOptionSpecific - * @property {"explorer"} kind - * @property {string} title - * - * @typedef {PartialOption & PartialExplorerOptionSpecific} PartialExplorerOption - * - * @typedef {Required & ProcessedOptionAddons} ExplorerOption - * - * @typedef {Object} PartialChartOptionSpecific - * @property {"chart"} [kind] - * @property {string} title - * @property {AnyFetchedSeriesBlueprint[]} [top] - * @property {AnyFetchedSeriesBlueprint[]} [bottom] - * - * @typedef {PartialOption & PartialChartOptionSpecific} PartialChartOption - * - * @typedef {Object} ProcessedChartOptionAddons - * @property {Record} top - * @property {Record} bottom - * - * @typedef {Required> & ProcessedChartOptionAddons & ProcessedOptionAddons} ChartOption - * - * @typedef {Object} PartialTableOptionSpecific - * @property {"table"} kind - * @property {string} title - * - * @typedef {PartialOption & PartialTableOptionSpecific} PartialTableOption - * - * @typedef {Required & ProcessedOptionAddons} TableOption - * - * @typedef {Object} PartialSimulationOptionSpecific - * @property {"simulation"} kind - * @property {string} title - * - * @typedef {PartialOption & PartialSimulationOptionSpecific} PartialSimulationOption - * - * @typedef {Required & ProcessedOptionAddons} SimulationOption - * - * @typedef {Object} PartialUrlOptionSpecific - * @property {"url"} [kind] - * @property {() => string} url - * @property {string} title - * @property {boolean} [qrcode] - * - * @typedef {PartialOption & PartialUrlOptionSpecific} PartialUrlOption - * - * @typedef {Required & ProcessedOptionAddons} UrlOption - * - * @typedef {PartialExplorerOption | PartialChartOption | PartialTableOption | PartialSimulationOption | PartialUrlOption} AnyPartialOption - * - * @typedef {ExplorerOption | ChartOption | TableOption | SimulationOption | UrlOption} Option - * - * @typedef {(AnyPartialOption | PartialOptionsGroup)[]} PartialOptionsTree - * - * @typedef {Object} PartialOptionsGroup - * @property {string} name - * @property {PartialOptionsTree} tree - * - * @typedef {Object} OptionsGroup - * @property {string} name - * @property {OptionsTree} tree - * - * @typedef {(Option | OptionsGroup)[]} OptionsTree - * - */ - -import { localhost } from "../utils/env"; - -/** - * @param {Object} args - * @param {Colors} args.colors - * @param {BrkClient} args.brk - * @returns {PartialOptionsTree} - */ -export function createPartialOptions({ colors, brk }) { - /** @type {(obj: T) => [keyof T, T[keyof T]][]} */ - const entries = Object.entries; - - /** - * @param {string} id - * @param {boolean} compoundAdjective - */ - function periodIdToName(id, compoundAdjective) { - const suffix = compoundAdjective || parseInt(id) === 1 ? "" : "s"; - return id - .replace("d", ` day${suffix}`) - .replace("w", ` week${suffix}`) - .replace("m", ` month${suffix}`) - .replace("y", ` year${suffix}`); - } - - const market = brk.tree.computed.market; - const averages = /** @type {const} */ ([ - ["1w", 7, "red", market.price1wSma, market.price1wEma], - ["8d", 8, "orange", market.price8dSma, market.price8dEma], - ["13d", 13, "amber", market.price13dSma, market.price13dEma], - ["21d", 21, "yellow", market.price21dSma, market.price21dEma], - ["1m", 30, "lime", market.price1mSma, market.price1mEma], - ["34d", 34, "green", market.price34dSma, market.price34dEma], - ["55d", 55, "emerald", market.price55dSma, market.price55dEma], - ["89d", 89, "teal", market.price89dSma, market.price89dEma], - ["144d", 144, "cyan", market.price144dSma, market.price144dEma], - ["200d", 200, "sky", market.price200dSma, market.price200dEma], - ["1y", 365, "blue", market.price1ySma, market.price1yEma], - ["2y", 730, "indigo", market.price2ySma, market.price2yEma], - ["200w", 1400, "violet", market.price200wSma, market.price200wEma], - ["4y", 1460, "purple", market.price4ySma, market.price4yEma], - ]).map( - ([id, days, colorKey, sma, ema]) => - /** @type {const} */ ({ - id, - name: periodIdToName(id, true), - days, - color: colors[colorKey], - sma, - ema, - }), - ); - - const dcaClasses = /** @type {const} */ ([ - [2015, "pink", false], - [2016, "red", false], - [2017, "orange", true], - [2018, "yellow", true], - [2019, "green", true], - [2020, "teal", true], - [2021, "sky", true], - [2022, "blue", true], - [2023, "purple", true], - [2024, "fuchsia", true], - [2025, "pink", true], - ]).map( - ([year, colorKey, defaultActive]) => - /** @type {const} */ ({ - year, - color: colors[colorKey], - defaultActive, - }), - ); - - const utxoCohorts = brk.tree.computed.stateful.utxoCohorts; - const addressCohorts = brk.tree.computed.stateful.addressCohorts; - const { - TERM_NAMES, - EPOCH_NAMES, - MAX_AGE_NAMES, - MIN_AGE_NAMES, - AGE_RANGE_NAMES, - GE_AMOUNT_NAMES, - LT_AMOUNT_NAMES, - AMOUNT_RANGE_NAMES, - SPENDABLE_TYPE_NAMES, - } = brk; - - const cohortAll = /** @type {const} */ ({ - name: "", - title: "", - color: colors.orange, - tree: utxoCohorts.all, - }); - const cohortAllForComparaison = /** @type {const} */ ({ - name: "all", - title: "", - color: colors.default, - tree: utxoCohorts.all, - }); - - const constant100 = flattenConstant(brk.tree.computed.constants.constant100); - - const termColors = /** @type {const} */ ({ - short: "yellow", - long: "fuchsia", - }); - const terms = entries(utxoCohorts.term).map(([key, tree]) => { - const names = TERM_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[termColors[key]], - tree, - }); - }); - - const maxAgeColors = /** @type {const} */ ({ - _1w: "red", - _1m: "orange", - _2m: "amber", - _3m: "yellow", - _4m: "lime", - _5m: "green", - _6m: "teal", - _1y: "sky", - _2y: "indigo", - _3y: "violet", - _4y: "purple", - _5y: "fuchsia", - _6y: "pink", - _7y: "red", - _8y: "orange", - _10y: "amber", - _12y: "yellow", - _15y: "lime", - }); - const upToDate = entries(utxoCohorts.maxAge).map(([key, tree]) => { - const names = MAX_AGE_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[maxAgeColors[key]], - tree, - }); - }); - - const minAgeColors = /** @type {const} */ ({ - _1d: "red", - _1w: "orange", - _1m: "yellow", - _2m: "lime", - _3m: "green", - _4m: "teal", - _5m: "cyan", - _6m: "blue", - _1y: "indigo", - _2y: "violet", - _3y: "purple", - _4y: "fuchsia", - _5y: "pink", - _6y: "rose", - _7y: "red", - _8y: "orange", - _10y: "yellow", - _12y: "lime", - }); - const fromDate = entries(utxoCohorts.minAge).map(([key, tree]) => { - const names = MIN_AGE_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[minAgeColors[key]], - tree, - }); - }); - - const ageRangeColors = /** @type {const} */ ({ - upTo1d: "pink", - _1dTo1w: "red", - _1wTo1m: "orange", - _1mTo2m: "yellow", - _2mTo3m: "yellow", - _3mTo4m: "lime", - _4mTo5m: "lime", - _5mTo6m: "lime", - _6mTo1y: "green", - _1yTo2y: "cyan", - _2yTo3y: "blue", - _3yTo4y: "indigo", - _4yTo5y: "violet", - _5yTo6y: "purple", - _6yTo7y: "purple", - _7yTo8y: "fuchsia", - _8yTo10y: "fuchsia", - _10yTo12y: "pink", - _12yTo15y: "red", - from15y: "orange", - }); - const dateRange = entries(utxoCohorts.ageRange).map(([key, tree]) => { - const names = AGE_RANGE_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[ageRangeColors[key]], - tree, - }); - }); - - const epochColors = /** @type {const} */ ({ - _0: "red", - _1: "yellow", - _2: "orange", - _3: "lime", - _4: "green", - }); - const epoch = entries(utxoCohorts.epoch).map(([key, tree]) => { - const names = EPOCH_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[epochColors[key]], - tree, - }); - }); - - const geAmountColors = /** @type {const} */ ({ - _1sat: "orange", - _10sats: "orange", - _100sats: "yellow", - _1kSats: "lime", - _10kSats: "green", - _100kSats: "cyan", - _1mSats: "blue", - _10mSats: "indigo", - _1btc: "purple", - _10btc: "violet", - _100btc: "fuchsia", - _1kBtc: "pink", - _10kBtc: "red", - }); - const utxosAboveAmount = entries(utxoCohorts.geAmount).map(([key, tree]) => { - const names = GE_AMOUNT_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[geAmountColors[key]], - tree, - }); - }); - /** @type {readonly AddressCohortObject[]} */ - const addressesAboveAmount = entries(addressCohorts.geAmount).map( - ([key, tree]) => { - const names = GE_AMOUNT_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[geAmountColors[key]], - tree, - }); - }, - ); - - const ltAmountColors = /** @type {const} */ ({ - _10sats: "orange", - _100sats: "yellow", - _1kSats: "lime", - _10kSats: "green", - _100kSats: "cyan", - _1mSats: "blue", - _10mSats: "indigo", - _1btc: "purple", - _10btc: "violet", - _100btc: "fuchsia", - _1kBtc: "pink", - _10kBtc: "red", - _100kBtc: "orange", - }); - const utxosUnderAmount = entries(utxoCohorts.ltAmount).map(([key, tree]) => { - const names = LT_AMOUNT_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[ltAmountColors[key]], - tree, - }); - }); - /** @type {readonly AddressCohortObject[]} */ - const addressesUnderAmount = entries(addressCohorts.ltAmount).map( - ([key, tree]) => { - const names = LT_AMOUNT_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[ltAmountColors[key]], - tree, - }); - }, - ); - - const amountRangeColors = /** @type {const} */ ({ - _0sats: "red", - _1satTo10sats: "orange", - _10satsTo100sats: "yellow", - _100satsTo1kSats: "lime", - _1kSatsTo10kSats: "green", - _10kSatsTo100kSats: "cyan", - _100kSatsTo1mSats: "blue", - _1mSatsTo10mSats: "indigo", - _10mSatsTo1btc: "purple", - _1btcTo10btc: "violet", - _10btcTo100btc: "fuchsia", - _100btcTo1kBtc: "pink", - _1kBtcTo10kBtc: "red", - _10kBtcTo100kBtc: "orange", - _100kBtcOrMore: "yellow", - }); - const utxosAmountRanges = entries(utxoCohorts.amountRange).map( - ([key, tree]) => { - const names = AMOUNT_RANGE_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[amountRangeColors[key]], - tree, - }); - }, - ); - /** @type {readonly AddressCohortObject[]} */ - const addressesAmountRanges = entries(addressCohorts.amountRange).map( - ([key, tree]) => { - const names = AMOUNT_RANGE_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[amountRangeColors[key]], - tree, - }); - }, - ); - - const spendableTypeColors = /** @type {const} */ ({ - p2pk65: "red", - p2pk33: "orange", - p2pkh: "yellow", - p2ms: "lime", - p2sh: "green", - p2wpkh: "teal", - p2wsh: "blue", - p2tr: "indigo", - p2a: "purple", - unknown: "violet", - empty: "fuchsia", - }); - const type = entries(utxoCohorts.type).map(([key, tree]) => { - const names = SPENDABLE_TYPE_NAMES[key]; - return /** @type {const} */ ({ - name: names.short, - title: names.long, - color: colors[spendableTypeColors[key]], - tree, - }); - }); - - const cointime = brk.tree.computed.cointime; - const cointimePrices = /** @type {const} */ ([ - { - price: cointime.trueMarketMean, - ratio: cointime.trueMarketMeanRatio, - name: "True market mean", - title: "true market mean", - color: colors.blue, - }, - { - price: cointime.vaultedPrice, - ratio: cointime.vaultedPriceRatio, - name: "Vaulted", - title: "vaulted price", - color: colors.lime, - }, - { - price: cointime.activePrice, - ratio: cointime.activePriceRatio, - name: "Active", - title: "active price", - color: colors.rose, - }, - { - price: cointime.cointimePrice, - ratio: cointime.cointimePriceRatio, - name: "cointime", - title: "cointime price", - color: colors.yellow, - }, - ]); - const cointimeCapitalizations = /** @type {const} */ ([ - [cointime.vaultedCap, "vaulted", "lime"], - [cointime.activeCap, "active", "rose"], - [cointime.cointimeCap, "cointime", "yellow"], - [cointime.investorCap, "investor", "fuchsia"], - [cointime.thermoCap, "thermo", "emerald"], - ]).map(([metric, name, colorKey]) => { - return /** @type {const} */ ({ - metric, - name, - title: `${name} Capitalization`, - color: colors[colorKey], - }); - }); - - /** - * Get constant pattern by number dynamically from tree - * Examples: 0 → constant0, 38.2 → constant382, -1 → constantMinus1 - * @param {number} num - * @returns {Constant0Pattern} - */ - function getConstant(num) { - const constants = brk.tree.computed.constants; - const key = - num >= 0 - ? `constant${String(num).replace(".", "")}` - : `constantMinus${Math.abs(num)}`; - const constant = constants[key]; - if (!constant) throw new Error(`Unknown constant: ${num} (key: ${key})`); - return constant; - } - - /** - * @param {Object} args - * @param {number} [args.number] - * @param {string} [args.name] - * @param {boolean} [args.defaultActive] - * @param {number} [args.lineStyle] - * @param {Color} [args.color] - * @param {Unit} args.unit - */ - function createPriceLine({ - number = 0, - unit, - defaultActive, - color, - name, - lineStyle, - }) { - return /** @satisfies {FetchedLineSeriesBlueprint} */ ({ - metric: flattenConstant(getConstant(number)), - title: name ?? `${number}`, - unit, - defaultActive, - color: color ?? colors.gray, - options: { - lineStyle: lineStyle ?? 4, - lastValueVisible: false, - crosshairMarkerVisible: false, - }, - }); - } - - /** - * @param {Object} args - * @param {number[]} args.numbers - * @param {boolean} [args.defaultActive] - * @param {Unit} args.unit - */ - function createPriceLines({ numbers, unit }) { - return numbers.map( - (number) => - /** @satisfies {FetchedLineSeriesBlueprint} */ ({ - metric: flattenConstant(getConstant(number)), - title: `${number}`, - unit, - defaultActive: !number, - color: colors.gray, - options: { - lineStyle: 4, - lastValueVisible: false, - crosshairMarkerVisible: false, - }, - }), - ); - } - - // ============================================================================ - // Tree-first helper functions - // These accept typed pattern objects from brk.tree and return series blueprints - // ============================================================================ - - /** - * Create a single series from a tree accessor - * @param {Object} args - * @param {MetricAccessor} args.metric - Tree accessor with .by property - * @param {string} args.name - Display name for the series - * @param {Color} [args.color] - * @param {Unit} [args.unit] - * @param {boolean} [args.defaultActive] - * @param {LineSeriesPartialOptions} [args.options] - */ - function s({ metric, name, color, defaultActive, unit, options }) { - return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({ - metric, - title: name, - color, - unit, - defaultActive, - options, - }); - } - - /** - * Create series from a BlockCountPattern ({ base, sum, cumulative }) - * @template T - * @param {BlockCountPattern} pattern - * @param {string} title - * @param {Color} [color] - */ - function fromBlockCount(pattern, title, color) { - return /** @satisfies {AnyFetchedSeriesBlueprint[]} */ ([ - { metric: pattern.base, title, color: color ?? colors.default }, - { - metric: pattern.sum, - title: `${title} (sum)`, - color: colors.red, - defaultActive: false, - }, - { - metric: pattern.cumulative, - title: `${title} (cum.)`, - color: colors.cyan, - defaultActive: false, - }, - ]); - } - - /** - * Create series from a BitcoinPattern ({ base, sum, cumulative, average, min, max, median, pct* }) - * @template T - * @param {BitcoinPattern} pattern - * @param {string} title - * @param {Color} [color] - */ - function fromBitcoin(pattern, title, color) { - return /** @satisfies {AnyFetchedSeriesBlueprint[]} */ ([ - { metric: pattern.base, title, color: color ?? colors.default }, - { metric: pattern.average, title: "Average", defaultActive: false }, - { - metric: pattern.sum, - title: `${title} (sum)`, - color: colors.red, - defaultActive: false, - }, - { - metric: pattern.cumulative, - title: `${title} (cum.)`, - color: colors.cyan, - defaultActive: false, - }, - { - metric: pattern.max, - title: "Max", - color: colors.pink, - defaultActive: false, - }, - { - metric: pattern.min, - title: "Min", - color: colors.green, - defaultActive: false, - }, - { - metric: pattern.median, - title: "Median", - color: colors.amber, - defaultActive: false, - }, - { - metric: pattern.pct75, - title: "pct75", - color: colors.red, - defaultActive: false, - }, - { - metric: pattern.pct25, - title: "pct25", - color: colors.yellow, - defaultActive: false, - }, - { - metric: pattern.pct90, - title: "pct90", - color: colors.rose, - defaultActive: false, - }, - { - metric: pattern.pct10, - title: "pct10", - color: colors.lime, - defaultActive: false, - }, - ]); - } - - /** - * Create series from a BlockSizePattern ({ sum, cumulative, average, min, max, median, pct* }) - * @template T - * @param {BlockSizePattern} pattern - * @param {string} title - * @param {Color} [color] - */ - function fromBlockSize(pattern, title, color) { - return /** @satisfies {AnyFetchedSeriesBlueprint[]} */ ([ - { metric: pattern.sum, title, color: color ?? colors.default }, - { metric: pattern.average, title: "Average", defaultActive: false }, - { - metric: pattern.cumulative, - title: `${title} (cum.)`, - color: colors.cyan, - defaultActive: false, - }, - { - metric: pattern.max, - title: "Max", - color: colors.pink, - defaultActive: false, - }, - { - metric: pattern.min, - title: "Min", - color: colors.green, - defaultActive: false, - }, - { - metric: pattern.median, - title: "Median", - color: colors.amber, - defaultActive: false, - }, - { - metric: pattern.pct75, - title: "pct75", - color: colors.red, - defaultActive: false, - }, - { - metric: pattern.pct25, - title: "pct25", - color: colors.yellow, - defaultActive: false, - }, - { - metric: pattern.pct90, - title: "pct90", - color: colors.rose, - defaultActive: false, - }, - { - metric: pattern.pct10, - title: "pct10", - color: colors.lime, - defaultActive: false, - }, - ]); - } - - /** - * Flatten a Constant0Pattern into a simple MetricAccessor - * Constant0Pattern has { dateindex: { by: {...} }, height: { by: {...} }, ... } - * This flattens it to { by: { dateindex: MetricNode, height: MetricNode, ... } } - * @param {Constant0Pattern} pattern - * @returns {MetricAccessor} - */ - function flattenConstant(pattern) { - return { - by: { - dateindex: pattern.dateindex.by.dateindex, - decadeindex: pattern.decadeindex.by.decadeindex, - height: pattern.height.by.height, - monthindex: pattern.monthindex.by.monthindex, - quarterindex: pattern.quarterindex.by.quarterindex, - semesterindex: pattern.semesterindex.by.semesterindex, - weekindex: pattern.weekindex.by.weekindex, - yearindex: pattern.yearindex.by.yearindex, - }, - }; - } - - /** - * Create a constant line series - * @param {Object} args - * @param {Constant0Pattern} args.constant - The constant pattern from tree.constants - * @param {string} args.name - * @param {Unit} args.unit - * @param {Color} [args.color] - * @param {number} [args.lineStyle] - * @param {boolean} [args.defaultActive] - */ - function line({ constant, name, unit, color, lineStyle, defaultActive }) { - return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({ - metric: flattenConstant(constant), - title: name, - unit, - defaultActive, - color: color ?? colors.gray, - options: { - lineStyle: lineStyle ?? 4, - lastValueVisible: false, - crosshairMarkerVisible: false, - }, - }); - } - - // Shorthand for tree access - const tree = brk.tree.computed; - const constants = tree.constants; - - const percentiles = [ - { - name: "pct1", - color: colors.indigo, - }, - { - name: "pct2", - color: colors.violet, - }, - { - name: "pct5", - color: colors.purple, - }, - { - name: "pct95", - color: colors.amber, - }, - { - name: "pct98", - color: colors.orange, - }, - { - name: "pct99", - color: colors.red, - }, - ]; - - const ratioAverages = /** @type {const} */ ([ - { - name: "1w sma", - metric: "1w_sma", - color: colors.lime, - }, - { - name: "1m sma", - metric: "1m_sma", - color: colors.teal, - }, - { - name: "1y sma", - metric: "1y_sma", - color: colors.sky, - }, - { - name: "2y sma", - metric: "2y_sma", - color: colors.indigo, - }, - { - name: "4y sma", - metric: "4y_sma", - color: colors.purple, - }, - { - name: "all sma", - metric: "sma", - color: colors.rose, - }, - ]); - - /** - * @param {Object} args - * @param {string} args.name - * @param {string} args.legend - * @param {string} args.title - * @param {Indexes3} [args.price] - Separate price pattern (for ActivePriceRatioPattern style) - * @param {ActivePriceRatioPattern | EmaRatioPattern} args.ratio - Ratio pattern (tree-first) - * @param {Color} [args.color] - */ - function createPriceWithRatioOptions({ - name, - title, - legend, - price, - ratio, - color, - }) { - // Support both patterns: EmaRatioPattern has .price, ActivePriceRatioPattern needs separate price arg - const priceMetric = price ?? ratio.price; - - // Map percentile names to ratio pattern properties - const percentileUsdMap = /** @type {const} */ ([ - { name: "pct99", prop: ratio.ratioPct99Usd, color: colors.rose }, - { name: "pct98", prop: ratio.ratioPct98Usd, color: colors.pink }, - { name: "pct95", prop: ratio.ratioPct95Usd, color: colors.fuchsia }, - { name: "pct5", prop: ratio.ratioPct5Usd, color: colors.cyan }, - { name: "pct2", prop: ratio.ratioPct2Usd, color: colors.sky }, - { name: "pct1", prop: ratio.ratioPct1Usd, color: colors.blue }, - ]); - - const percentileMap = /** @type {const} */ ([ - { name: "pct99", prop: ratio.ratioPct99, color: colors.rose }, - { name: "pct98", prop: ratio.ratioPct98, color: colors.pink }, - { name: "pct95", prop: ratio.ratioPct95, color: colors.fuchsia }, - { name: "pct5", prop: ratio.ratioPct5, color: colors.cyan }, - { name: "pct2", prop: ratio.ratioPct2, color: colors.sky }, - { name: "pct1", prop: ratio.ratioPct1, color: colors.blue }, - ]); - - // SD patterns by window - const sdPatterns = /** @type {const} */ ([ - { nameAddon: "all", titleAddon: "", sd: ratio.ratioSd }, - { nameAddon: "4y", titleAddon: "4y", sd: ratio.ratio4ySd }, - { nameAddon: "2y", titleAddon: "2y", sd: ratio.ratio2ySd }, - { nameAddon: "1y", titleAddon: "1y", sd: ratio.ratio1ySd }, - ]); - - // SD band definitions with their pattern property accessors - /** @param {Ratio1ySdPattern} sd */ - const getSdBands = (sd) => [ - { name: "0σ", prop: sd._0sdUsd, color: colors.lime }, - { name: "+0.5σ", prop: sd.p05sdUsd, color: colors.yellow }, - { name: "+1σ", prop: sd.p1sdUsd, color: colors.amber }, - { name: "+1.5σ", prop: sd.p15sdUsd, color: colors.orange }, - { name: "+2σ", prop: sd.p2sdUsd, color: colors.red }, - { name: "+2.5σ", prop: sd.p25sdUsd, color: colors.rose }, - { name: "+3σ", prop: sd.p3sd, color: colors.pink }, // No USD variant for ±3σ - { name: "−0.5σ", prop: sd.m05sdUsd, color: colors.teal }, - { name: "−1σ", prop: sd.m1sdUsd, color: colors.cyan }, - { name: "−1.5σ", prop: sd.m15sdUsd, color: colors.sky }, - { name: "−2σ", prop: sd.m2sdUsd, color: colors.blue }, - { name: "−2.5σ", prop: sd.m25sdUsd, color: colors.indigo }, - { name: "−3σ", prop: sd.m3sd, color: colors.violet }, // No USD variant for ±3σ - ]; - - return [ - { - name: "price", - title, - top: [ - s({ - metric: priceMetric, - name: legend, - color, - }), - ], - }, - { - name: "Ratio", - title: `${title} Ratio`, - top: [ - s({ - metric: priceMetric, - name: legend, - color, - }), - ...percentileUsdMap.map(({ name, prop, color }) => - s({ - metric: prop, - name, - color, - defaultActive: false, - options: { - lineStyle: 1, - }, - }), - ), - ], - bottom: [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: ratio.ratio, - title: "Ratio", - type: "Baseline", - options: { - baseValue: { price: 1 }, - }, - }), - ...percentileMap.map(({ name, prop, color }) => - s({ - metric: prop, - name, - color, - defaultActive: false, - options: { - lineStyle: 1, - }, - }), - ), - s({ - metric: ratio.ratio1wSma, - name: "1w SMA", - color: colors.orange, - defaultActive: false, - options: { - lineStyle: 1, - }, - }), - s({ - metric: ratio.ratio1mSma, - name: "1m SMA", - color: colors.red, - defaultActive: false, - options: { - lineStyle: 1, - }, - }), - createPriceLine({ - number: 1, - unit: "ratio", - }), - ], - }, - { - name: "ZScores", - tree: [ - { - name: "compare", - title: `Compare ${title} ZScores`, - top: [ - s({ - metric: priceMetric, - name: legend, - color, - }), - s({ - metric: ratio.ratio1ySd._0sdUsd, - name: "1y 0sd", - color: colors.fuchsia, - defaultActive: false, - }), - s({ - metric: ratio.ratio2ySd._0sdUsd, - name: "2y 0sd", - color: colors.purple, - defaultActive: false, - }), - s({ - metric: ratio.ratio4ySd._0sdUsd, - name: "4y 0sd", - color: colors.violet, - defaultActive: false, - }), - s({ - metric: ratio.ratioSd._0sdUsd, - name: "0sd", - color: colors.indigo, - defaultActive: false, - }), - ], - bottom: [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: ratio.ratioSd.zscore, - title: "All", - type: "Baseline", - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: ratio.ratio4ySd.zscore, - colors: [colors.lime, colors.rose], - title: "4y", - type: "Baseline", - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: ratio.ratio2ySd.zscore, - colors: [colors.avocado, colors.pink], - title: "2y", - type: "Baseline", - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: ratio.ratio1ySd.zscore, - colors: [colors.yellow, colors.fuchsia], - title: "1Y", - type: "Baseline", - }), - ...createPriceLines({ - numbers: [0, 1, 2, 3, 4, -1, -2, -3, -4], - unit: "ratio", - }), - ], - }, - ...sdPatterns.flatMap(({ nameAddon, titleAddon, sd }) => ({ - name: nameAddon, - title: `${title} ${titleAddon} ZScore`, - top: [ - s({ - metric: priceMetric, - name: legend, - color, - }), - ...getSdBands(sd).map(({ name, prop, color }) => - s({ - metric: prop, - name, - color, - defaultActive: false, - options: { - lineStyle: 1, - }, - }), - ), - ], - bottom: [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: sd.zscore, - title: "score", - type: "Baseline", - }), - ...createPriceLines({ - numbers: [0, 1, 2, 3, 4, -1, -2, -3, -4], - unit: "ratio", - }), - ], - })), - ], - }, - ]; - } - - /** - * @typedef {Object} UtxoCohortObject - * @property {string} name - * @property {string} title - * @property {Color} color - * @property {UtxoCohortPattern} tree - */ - - /** - * @typedef {Object} AddressCohortObject - * @property {string} name - * @property {string} title - * @property {Color} color - * @property {AddressCohortPattern} tree - */ - - /** @typedef {UtxoCohortObject | AddressCohortObject} CohortObject */ - - /** - * @typedef {Object} UtxoCohortGroupObject - * @property {string} name - * @property {string} title - * @property {readonly UtxoCohortObject[]} list - */ - - /** - * @typedef {Object} AddressCohortGroupObject - * @property {string} name - * @property {string} title - * @property {readonly AddressCohortObject[]} list - */ - - /** @typedef {UtxoCohortGroupObject | AddressCohortGroupObject} CohortGroupObject */ - - /** - * @param {CohortObject | CohortGroupObject} args - */ - function createCohortGroupFolder(args) { - const list = "list" in args ? args.list : [args]; - const useGroupName = "list" in args; - - const title = args.title - ? `${useGroupName ? "by" : "of"} ${args.title}` - : ""; - - return /** @satisfies {PartialOptionsGroup} */ ({ - name: args.name || "all", - tree: [ - !("list" in args) - ? { - name: "supply", - title: `Supply ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.supply.supply.sats, - name: "Supply", - color: colors.default, - }), - s({ - metric: tree.supply.supply.bitcoin, - name: "Supply", - color: colors.default, - }), - s({ - metric: tree.supply.supply.dollars, - name: "Supply", - color: colors.default, - }), - ...("supplyRelToCirculatingSupply" in tree.relative - ? [ - s({ - metric: tree.relative.supplyRelToCirculatingSupply, - name: "Supply", - color: colors.default, - }), - ] - : []), - s({ - metric: tree.unrealized.supplyInProfit.sats, - name: "In Profit", - color: colors.green, - }), - s({ - metric: tree.unrealized.supplyInProfit.bitcoin, - name: "In Profit", - color: colors.green, - }), - s({ - metric: tree.unrealized.supplyInProfit.dollars, - name: "In Profit", - color: colors.green, - }), - s({ - metric: tree.unrealized.supplyInLoss.sats, - name: "In Loss", - color: colors.red, - }), - s({ - metric: tree.unrealized.supplyInLoss.bitcoin, - name: "In Loss", - color: colors.red, - }), - s({ - metric: tree.unrealized.supplyInLoss.dollars, - name: "In Loss", - color: colors.red, - }), - s({ - metric: tree.supply.supplyHalf.sats, - name: "half", - color: colors.gray, - options: { - lineStyle: 4, - }, - }), - s({ - metric: tree.supply.supplyHalf.bitcoin, - name: useGroupName ? name : "half", - color: "list" in args ? color : colors.gray, - options: { - lineStyle: 4, - }, - }), - s({ - metric: tree.supply.supplyHalf.dollars, - name: useGroupName ? name : "half", - color: "list" in args ? color : colors.gray, - options: { - lineStyle: 4, - }, - }), - ...("supplyInProfitRelToCirculatingSupply" in tree.relative - ? [ - s({ - metric: - tree.relative.supplyInProfitRelToCirculatingSupply, - name: "In Profit", - color: colors.green, - }), - s({ - metric: - tree.relative.supplyInLossRelToCirculatingSupply, - name: "In Loss", - color: colors.red, - }), - ] - : []), - s({ - metric: tree.relative.supplyInProfitRelToOwnSupply, - name: "In Profit", - color: colors.green, - }), - s({ - metric: tree.relative.supplyInLossRelToOwnSupply, - name: "In Loss", - color: colors.red, - }), - createPriceLine({ - unit: "%self", - number: 100, - lineStyle: 0, - color: colors.default, - }), - createPriceLine({ - unit: "%self", - number: 50, - }), - ]); - }), - } - : { - name: "supply", - tree: [ - { - name: "total", - title: `Supply ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.supply.supply.sats, - name, - color, - }), - s({ - metric: tree.supply.supply.bitcoin, - name, - color, - }), - s({ - metric: tree.supply.supply.dollars, - name, - color, - }), - "supplyRelToCirculatingSupply" in tree.relative - ? s({ - metric: tree.relative.supplyRelToCirculatingSupply, - name, - color, - }) - : s({ - unit: "%all", - metric: constant100, - name, - color, - }), - ]); - }), - }, - { - name: "in profit", - title: `Supply In Profit ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.unrealized.supplyInProfit.sats, - name, - color, - }), - s({ - metric: tree.unrealized.supplyInProfit.bitcoin, - name, - color, - }), - s({ - metric: tree.unrealized.supplyInProfit.dollars, - name, - color, - }), - ...("supplyInProfitRelToCirculatingSupply" in - tree.relative - ? [ - s({ - metric: - tree.relative - .supplyInProfitRelToCirculatingSupply, - name, - color, - }), - ] - : []), - ]); - }), - }, - { - name: "in loss", - title: `Supply In loss ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.unrealized.supplyInLoss.sats, - name, - color, - }), - s({ - metric: tree.unrealized.supplyInLoss.bitcoin, - name, - color, - }), - s({ - metric: tree.unrealized.supplyInLoss.dollars, - name, - color, - }), - ...("supplyInLossRelToCirculatingSupply" in tree.relative - ? [ - s({ - metric: - tree.relative - .supplyInLossRelToCirculatingSupply, - name, - color, - }), - ] - : []), - ]); - }), - }, - ], - }, - { - name: "utxo count", - title: `UTXO Count ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.supply.utxoCount, - name: useGroupName ? name : "Count", - color, - }), - ]); - }), - }, - ...(list.filter(({ tree }) => tree.addrCount).length > - ("list" in args ? 1 : 0) - ? !("list" in args) || - list.filter(({ tree }) => tree.emptyAddrCount).length <= 1 - ? [ - { - name: "address count", - title: `Address Count ${title}`, - bottom: list.flatMap(({ name, color, tree }) => { - return [ - ...(tree.addrCount - ? /** @type {const} */ ([ - s({ - metric: tree.addrCount, - name: useGroupName ? name : "Loaded", - color: useGroupName ? color : colors.orange, - }), - ]) - : []), - ...(tree.emptyAddrCount - ? /** @type {const} */ ([ - s({ - metric: tree.emptyAddrCount, - name: "Empty", - color: colors.gray, - defaultActive: false, - }), - ]) - : []), - ]; - }), - }, - ] - : [ - { - name: "address count", - tree: [ - { - name: "loaded", - title: `Loaded Address Count ${title}`, - bottom: list - .filter(({ tree }) => tree.addrCount) - .flatMap(({ name, color, tree }) => { - return [ - s({ - metric: tree.addrCount, - name, - color, - }), - ]; - }), - }, - ...(list.filter(({ tree }) => tree.emptyAddrCount).length - ? [ - { - name: "empty", - title: `Empty Address Count ${title}`, - bottom: list - .filter(({ tree }) => tree.emptyAddrCount) - .flatMap(({ name, color, tree }) => { - return [ - s({ - metric: tree.emptyAddrCount, - name, - color, - }), - ]; - }), - }, - ] - : []), - ], - }, - ] - : []), - { - name: "Realized", - tree: [ - ...("list" in args - ? [ - { - name: "Price", - title: `Realized Price ${title}`, - top: list.map(({ color, name, tree }) => - s({ - metric: tree.realizedPrice, - name, - color, - }), - ), - }, - { - name: "Ratio", - title: `Realized Price Ratio ${title}`, - bottom: [ - ...list.map(({ color, name, tree }) => - s({ - metric: tree.realizedPriceExtra.ratio, - name, - color, - }), - ), - createPriceLine({ - unit: "ratio", - number: 1, - }), - ], - }, - ] - : createPriceWithRatioOptions({ - title: `Realized Price ${title}`, - price: args.tree.realizedPrice, - ratio: args.tree.realizedPriceExtra, - name: "price", - legend: "realized", - color: args.color, - })), - { - name: "capitalization", - title: `Realized Capitalization ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.realized.realizedCap, - name: useGroupName ? name : "Capitalization", - color, - }), - ...(!("list" in args) - ? [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.realizedCap30dDelta, - title: "30d change", - defaultActive: false, - }), - createPriceLine({ - unit: "usd", - defaultActive: false, - }), - ] - : []), - ...(!("list" in args) && - tree.realized?.realizedCapRelToOwnMarketCap - ? [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.realizedCapRelToOwnMarketCap, - title: "ratio", - options: { baseValue: { price: 100 } }, - colors: [colors.red, colors.green], - }), - createPriceLine({ - unit: "%cmcap", - defaultActive: true, - number: 100, - }), - ] - : []), - ]); - }), - }, - ...(!("list" in args) - ? [ - { - name: "pnl", - title: `Realized Profit And Loss ${title}`, - bottom: [ - s({ - metric: args.tree.realized.realizedProfit.base, - name: "Profit", - color: colors.green, - }), - s({ - metric: args.tree.realized.realizedLoss.base, - name: "Loss", - color: colors.red, - defaultActive: false, - }), - ...(args.tree.realized?.realizedProfitToLossRatio - ? [ - s({ - metric: - args.tree.realized.realizedProfitToLossRatio, - name: "proft / loss", - color: colors.yellow, - }), - ] - : []), - s({ - metric: args.tree.realized.totalRealizedPnl.base, - name: "Total", - color: colors.default, - defaultActive: false, - }), - s({ - metric: args.tree.realized.negRealizedLoss.base, - name: "Negative Loss", - color: colors.red, - }), - s({ - metric: args.tree.realized.realizedProfit.cumulative, - name: "Cumulative Profit", - color: colors.green, - defaultActive: false, - }), - s({ - metric: args.tree.realized.realizedLoss.cumulative, - name: "Cumulative Loss", - color: colors.red, - defaultActive: false, - }), - s({ - metric: args.tree.realized.negRealizedLoss.cumulative, - name: "Cumulative Negative Loss", - color: colors.red, - defaultActive: false, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - args.tree.realized.realizedProfitRelToRealizedCap, - title: "Profit", - color: colors.green, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: args.tree.realized.realizedLossRelToRealizedCap, - title: "Loss", - color: colors.red, - }), - createPriceLine({ - unit: "%rcap", - }), - createPriceLine({ - unit: "usd", - defaultActive: false, - }), - ], - }, - { - name: "Net pnl", - title: `Net Realized Profit And Loss ${title}`, - bottom: list.flatMap(({ color, name, tree }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.netRealizedPnl.base, - title: "Raw", - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.netRealizedPnl.cumulative, - title: "Cumulative", - defaultActive: false, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.netRealizedPnlCumulative30dDelta, - title: "cumulative 30d change", - defaultActive: false, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.netRealizedPnlRelToRealizedCap, - title: "Raw", - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - tree.realized - .netRealizedPnlCumulative30dDeltaRelToRealizedCap, - title: "cumulative 30d change", - defaultActive: false, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - tree.realized - .netRealizedPnlCumulative30dDeltaRelToMarketCap, - title: "cumulative 30d change", - }), - createPriceLine({ - unit: "%mcap", - }), - createPriceLine({ - unit: "%rcap", - }), - createPriceLine({ - unit: "usd", - }), - ]), - }, - { - name: "sopr", - title: `Spent Output Profit Ratio ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.sopr, - title: "normal", - options: { - baseValue: { - price: 1, - }, - }, - }), - ...(tree.realized?.adjustedSopr - ? [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.adjustedSopr, - title: "adjusted", - colors: [colors.yellow, colors.fuchsia], - defaultActive: false, - options: { - baseValue: { - price: 1, - }, - }, - }), - ] - : []), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.sopr7dEma, - title: "7d ema", - colors: [colors.lime, colors.rose], - defaultActive: false, - options: { - baseValue: { - price: 1, - }, - }, - }), - ...(tree.realized?.adjustedSopr7dEma - ? [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.adjustedSopr7dEma, - title: "adj. 7d ema", - colors: [colors.amber, colors.purple], - defaultActive: false, - options: { - baseValue: { - price: 1, - }, - }, - }), - ] - : []), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.sopr30dEma, - title: "30d ema", - colors: [colors.avocado, colors.pink], - defaultActive: false, - options: { - baseValue: { - price: 1, - }, - }, - }), - ...(tree.realized?.adjustedSopr30dEma - ? [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.adjustedSopr30dEma, - title: "adj. 30d ema", - colors: [colors.orange, colors.violet], - defaultActive: false, - options: { - baseValue: { - price: 1, - }, - }, - }), - ] - : []), - createPriceLine({ - number: 1, - unit: "ratio", - }), - ]; - }), - }, - ] - : [ - { - name: "profit", - title: `Realized Profit ${title}`, - bottom: [ - ...list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.realized.realizedProfit.base, - name, - color, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - tree.realized.realizedProfitRelToRealizedCap, - title: name, - color, - }), - ]); - }), - createPriceLine({ - unit: "usd", - }), - ], - }, - { - name: "loss", - title: `Realized Loss ${title}`, - bottom: [ - ...list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.realized.realizedLoss.base, - name, - color, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.realizedLossRelToRealizedCap, - title: name, - color, - }), - ]); - }), - createPriceLine({ - unit: "usd", - }), - ], - }, - { - name: "Total pnl", - title: `Total Realized Profit And Loss Loss ${title}`, - bottom: [ - ...list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.realized.totalRealizedPnl.base, - name, - color, - }), - ...(tree.realized?.realizedProfitToLossRatio - ? [ - s({ - metric: - tree.realized.realizedProfitToLossRatio, - name, - color, - }), - ] - : []), - ]); - }), - ], - }, - { - name: "Net pnl", - title: `Net Realized Profit And Loss ${title}`, - bottom: [ - ...list.flatMap(({ color, name, tree }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.netRealizedPnl.base, - title: name, - color, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.netRealizedPnlRelToRealizedCap, - title: name, - color, - }), - ]), - createPriceLine({ - unit: "usd", - }), - createPriceLine({ - unit: "%rcap", - }), - ], - }, - { - name: "cumulative", - tree: [ - { - name: "profit", - title: `Cumulative Realized Profit ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.realized.realizedProfit.cumulative, - name, - color, - }), - ]); - }), - }, - { - name: "loss", - title: `Cumulative Realized Loss ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.realized.realizedLoss.cumulative, - name, - color, - }), - ]); - }), - }, - { - name: "Net pnl", - title: `Cumulative Net Realized Profit And Loss ${title}`, - bottom: [ - ...list.flatMap(({ color, name, tree }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.netRealizedPnl.cumulative, - title: name, - color, - defaultActive: false, - }), - ]), - createPriceLine({ - unit: "usd", - }), - ], - }, - { - name: "Net pnl 30d change", - title: `Cumulative Net Realized Profit And Loss 30 Day Change ${title}`, - bottom: [ - ...list.flatMap(({ color, name, tree }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - tree.realized.netRealizedPnlCumulative30dDelta, - title: name, - color, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - tree.realized - .netRealizedPnlCumulative30dDeltaRelToRealizedCap, - title: name, - color, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - tree.realized - .netRealizedPnlCumulative30dDeltaRelToMarketCap, - title: name, - color, - }), - ]), - createPriceLine({ - unit: "usd", - }), - createPriceLine({ - unit: "%mcap", - }), - createPriceLine({ - unit: "%rcap", - }), - ], - }, - ], - }, - { - name: "sopr", - tree: [ - { - name: "Normal", - title: `Spent Output Profit Ratio ${title}`, - bottom: [ - ...list.flatMap(({ color, name, tree }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.realized.sopr, - title: name, - color, - }), - ]), - createPriceLine({ - number: 1, - unit: "ratio", - }), - ], - }, - ...(() => { - const reducedList = list - .filter(({ tree }) => tree.realized?.adjustedSopr) - .map(({ color, name, tree }) => ({ - color, - name, - metric: tree.realized.adjustedSopr, - })); - - return reducedList.length - ? [ - { - name: "Adjusted", - title: `Adjusted Spent Output Profit Ratio ${title}`, - bottom: [ - ...reducedList.flatMap( - ({ color, name, metric }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric, - title: name, - color, - }), - ], - ), - createPriceLine({ - number: 1, - unit: "ratio", - }), - ], - }, - ] - : []; - })(), - ], - }, - ]), - { - name: "Sell Side Risk", - title: `Sell Side Risk Ratio ${title}`, - bottom: !("list" in args) - ? list.flatMap(({ tree }) => [ - s({ - metric: tree.realized.sellSideRiskRatio, - name: "raw", - color: colors.orange, - }), - s({ - metric: tree.realized.sellSideRiskRatio7dEma, - name: "7d ema", - color: colors.red, - defaultActive: false, - }), - s({ - metric: tree.realized.sellSideRiskRatio30dEma, - name: "30d ema", - color: colors.rose, - defaultActive: false, - }), - ]) - : list.flatMap(({ color, name, tree }) => [ - s({ - metric: tree.realized.sellSideRiskRatio, - name, - color: color, - }), - ]), - }, - { - name: "value", - tree: [ - ...(!("list" in args) - ? [ - { - name: "created", - title: `value created ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return [ - s({ - metric: tree.realized.valueCreated, - name: "normal", - color: colors.emerald, - }), - ...(tree.realized?.adjustedValueCreated - ? [ - s({ - metric: tree.realized.adjustedValueCreated, - name: "adjusted", - color: colors.lime, - }), - ] - : []), - ]; - }), - }, - { - name: "destroyed", - title: `value destroyed ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return [ - s({ - metric: tree.realized.valueDestroyed, - name: "normal", - color: colors.red, - }), - ...(tree.realized?.adjustedValueDestroyed - ? [ - s({ - metric: - tree.realized.adjustedValueDestroyed, - name: "adjusted", - color: colors.pink, - }), - ] - : []), - ]; - }), - }, - ] - : [ - { - name: "created", - tree: [ - { - name: "Normal", - title: `Value Created ${title}`, - bottom: list.flatMap(({ color, name, tree }) => [ - s({ - metric: tree.realized.valueCreated, - name, - color, - }), - ]), - }, - ...(() => { - const reducedList = list - .filter( - ({ tree }) => - tree.realized?.adjustedValueCreated, - ) - .map(({ color, name, tree }) => ({ - color, - name, - metric: tree.realized.adjustedValueCreated, - })); - return reducedList.length - ? [ - { - name: "Adjusted", - title: `Adjusted value created ${title}`, - bottom: reducedList.map( - ({ color, name, metric }) => - s({ - metric, - name, - color, - }), - ), - }, - ] - : []; - })(), - ], - }, - { - name: "destroyed", - tree: [ - { - name: "Normal", - title: `Value destroyed ${title}`, - bottom: list.flatMap(({ color, name, tree }) => [ - s({ - metric: tree.realized.valueDestroyed, - name, - color, - }), - ]), - }, - ...(() => { - const reducedList = list - .filter( - ({ tree }) => - tree.realized?.adjustedValueDestroyed, - ) - .map(({ color, name, tree }) => ({ - color, - name, - metric: tree.realized.adjustedValueDestroyed, - })); - return reducedList.length - ? [ - { - name: "Adjusted", - title: `Adjusted value destroyed ${title}`, - bottom: reducedList.map( - ({ color, name, metric }) => - s({ - metric, - name, - color, - }), - ), - }, - ] - : []; - })(), - ], - }, - ]), - ], - }, - ], - }, - { - name: "Unrealized", - tree: [ - ...(!("list" in args) - ? [ - { - name: "pnl", - title: `Unrealized Profit And Loss ${title}`, - bottom: [ - s({ - metric: args.tree.unrealized.totalUnrealizedPnl, - name: "total", - color: colors.default, - }), - s({ - metric: args.tree.unrealized.unrealizedProfit, - name: "Profit", - color: colors.green, - }), - s({ - metric: args.tree.unrealized.unrealizedLoss, - name: "Loss", - color: colors.red, - defaultActive: false, - }), - s({ - metric: args.tree.unrealized.negUnrealizedLoss, - name: "Negative Loss", - color: colors.red, - }), - s({ - metric: - args.tree.relative.unrealizedProfitRelToMarketCap, - name: "Profit", - color: colors.green, - }), - s({ - metric: args.tree.relative.unrealizedLossRelToMarketCap, - name: "Loss", - color: colors.red, - defaultActive: false, - }), - s({ - metric: - args.tree.relative.negUnrealizedLossRelToMarketCap, - name: "Negative Loss", - color: colors.red, - }), - ...("unrealizedProfitRelToOwnMarketCap" in - args.tree.relative - ? [ - s({ - metric: - args.tree.relative - .unrealizedProfitRelToOwnMarketCap, - name: "Profit", - color: colors.green, - }), - s({ - metric: - args.tree.relative - .unrealizedLossRelToOwnMarketCap, - name: "Loss", - color: colors.red, - defaultActive: false, - }), - s({ - metric: - args.tree.relative - .negUnrealizedLossRelToOwnMarketCap, - name: "Negative Loss", - color: colors.red, - }), - createPriceLine({ - unit: "%cmcap", - number: 100, - }), - createPriceLine({ - unit: "%cmcap", - }), - ] - : []), - ...("unrealizedProfitRelToOwnTotalUnrealizedPnl" in - args.tree.relative - ? [ - s({ - metric: - args.tree.relative - .unrealizedProfitRelToOwnTotalUnrealizedPnl, - name: "Profit", - color: colors.green, - }), - s({ - metric: - args.tree.relative - .unrealizedLossRelToOwnTotalUnrealizedPnl, - name: "Loss", - color: colors.red, - defaultActive: false, - }), - s({ - metric: - args.tree.relative - .negUnrealizedLossRelToOwnTotalUnrealizedPnl, - name: "Negative Loss", - color: colors.red, - }), - createPriceLine({ - unit: "%cp+l", - number: 100, - }), - createPriceLine({ - unit: "%cp+l", - }), - ] - : []), - createPriceLine({ - unit: "usd", - defaultActive: false, - }), - createPriceLine({ - unit: "%mcap", - defaultActive: false, - }), - ], - }, - ] - : [ - { - name: "profit", - title: `Unrealized Profit ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.unrealized.unrealizedProfit, - name, - color, - }), - ]); - }), - }, - { - name: "loss", - title: `Unrealized Loss ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.unrealized.unrealizedLoss, - name, - color, - }), - ]); - }), - }, - { - name: "total pnl", - title: `Unrealized Total Profit And Loss ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.unrealized.totalUnrealizedPnl, - name, - color, - }), - ]); - }), - }, - ]), - { - name: "Net pnl", - title: `Net Unrealized Profit And Loss ${title}`, - bottom: [ - ...list.flatMap(({ color, name, tree }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.unrealized.netUnrealizedPnl, - title: useGroupName ? name : "Net", - color: useGroupName ? color : undefined, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: tree.relative.netUnrealizedPnlRelToMarketCap, - title: useGroupName ? name : "Net", - color: useGroupName ? color : undefined, - }), - ...("netUnrealizedPnlRelToOwnMarketCap" in tree.relative - ? [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - tree.relative.netUnrealizedPnlRelToOwnMarketCap, - title: useGroupName ? name : "Net", - color: useGroupName ? color : undefined, - }), - createPriceLine({ - unit: "%cmcap", - }), - ] - : []), - ...("netUnrealizedPnlRelToOwnTotalUnrealizedPnl" in - tree.relative - ? [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - metric: - tree.relative - .netUnrealizedPnlRelToOwnTotalUnrealizedPnl, - title: useGroupName ? name : "Net", - color: useGroupName ? color : undefined, - }), - createPriceLine({ - unit: "%cp+l", - }), - ] - : []), - ]), - createPriceLine({ - unit: "usd", - }), - createPriceLine({ - unit: "%mcap", - }), - ], - }, - ], - }, - ...("list" in args - ? [ - { - name: "Cost Basis", - tree: [ - { - name: "Average", - title: `Average Cost Basis ${title}`, - top: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.realizedPrice, - name, - color: color, - }), - ]); - }), - }, - { - name: "Min", - title: `Min Cost Basis ${title}`, - top: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.costBasis.minCostBasis, - name, - color: color, - }), - ]); - }), - }, - { - name: "Max", - title: `Max Cost Basis ${title}`, - top: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.costBasis.maxCostBasis, - name, - color: color, - }), - ]); - }), - }, - ], - }, - ] - : [ - { - name: "Cost Basis", - title: `Cost Basis ${title}`, - top: [ - s({ - metric: args.tree.realizedPrice, - name: "Average", - color: args.color, - }), - s({ - metric: args.tree.costBasis.minCostBasis, - name: "Min", - color: colors.green, - defaultActive: false, - }), - s({ - metric: args.tree.costBasis.maxCostBasis, - name: "Max", - color: colors.red, - }), - ], - }, - ]), - ...("list" in args - ? [ - { - name: "Coins Destroyed", - tree: [ - { - name: "Sum", - title: `Sum of Coins Destroyed ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.activity.coinblocksDestroyed.base, - name, - color, - }), - s({ - metric: tree.activity.coindaysDestroyed.base, - name, - color, - }), - ]); - }), - }, - { - name: "Cumulative", - title: `Cumulative Coins Destroyed ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.activity.coinblocksDestroyed.cumulative, - name, - color, - }), - s({ - metric: tree.activity.coindaysDestroyed.cumulative, - name, - color, - }), - ]); - }), - }, - ], - }, - ] - : [ - { - name: "Coins Destroyed", - title: `Coins Destroyed ${title}`, - bottom: list.flatMap(({ color, name, tree }) => { - return /** @type {const} */ ([ - s({ - metric: tree.activity.coinblocksDestroyed.base, - name: "sum", - color, - }), - s({ - metric: tree.activity.coinblocksDestroyed.cumulative, - name: "cumulative", - color, - defaultActive: false, - }), - s({ - metric: tree.activity.coindaysDestroyed.base, - name: "sum", - color, - }), - s({ - metric: tree.activity.coindaysDestroyed.cumulative, - name: "cumulative", - color, - defaultActive: false, - }), - ]); - }), - }, - ]), - ], - }); - } - - return [ - ...(localhost - ? /** @type {const} */ ([ - { - name: "Explorer", - title: "Explorer", - kind: "explorer", - }, - ]) - : []), - { - name: "Charts", - tree: [ - { - name: "Market", - tree: [ - { - name: "Price", - title: "Bitcoin Price", - }, - { - name: "Capitalization", - title: "Market Capitalization", - bottom: [ - s({ - metric: "market_cap", - name: "Capitalization", - }), - ], - }, - { - name: "All Time High", - title: "All Time High", - // tree: [ - // { - // name: "Value", - top: [ - s({ - metric: "price_ath", - name: "ath", - }), - ], - bottom: [ - s({ - metric: "price_drawdown", - name: "Drawdown", - color: colors.red, - }), - s({ - metric: "days_since_price_ath", - name: "since", - }), - s({ - metric: "max_days_between_price_aths", - name: "Max", - color: colors.red, - }), - s({ - metric: "max_years_between_price_aths", - name: "Max", - color: colors.red, - }), - ], - }, - { - name: "Averages", - tree: [ - { - nameAddon: "Simple", - metricAddon: "sma", - }, - { - nameAddon: "Exponential", - metricAddon: "ema", - }, - ].map(({ nameAddon, metricAddon }) => ({ - name: nameAddon, - tree: [ - { - name: "Compare", - title: `Market Price ${nameAddon} Moving Averages`, - top: averages.map(({ id, color, sma, ema }) => - s({ - metric: (metricAddon === "sma" ? sma : ema).price, - name: id, - color, - }), - ), - }, - ...averages.map(({ name, color, sma, ema }) => ({ - name, - tree: createPriceWithRatioOptions({ - ratio: metricAddon === "sma" ? sma : ema, - name, - title: `${name} Market Price ${nameAddon} Moving Average`, - legend: "average", - color, - }), - })), - ], - })), - }, - { - name: "Performance", - tree: /** @type {const} */ ([ - ["1d", market._1dPriceReturns], - ["1w", market._1wPriceReturns], - ["1m", market._1mPriceReturns], - ["3m", market._3mPriceReturns], - ["6m", market._6mPriceReturns], - ["1y", market._1yPriceReturns], - ["2y", market._2yPriceReturns, market._2yCagr], - ["3y", market._3yPriceReturns, market._3yCagr], - ["4y", market._4yPriceReturns, market._4yCagr], - ["5y", market._5yPriceReturns, market._5yCagr], - ["6y", market._6yPriceReturns, market._6yCagr], - ["8y", market._8yPriceReturns, market._8yCagr], - ["10y", market._10yPriceReturns, market._10yCagr], - ]).map(([id, priceReturns, cagr]) => { - const name = periodIdToName(id, true); - return { - name, - title: `${name} Performance`, - bottom: [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: priceReturns, - title: "total", - type: "Baseline", - }), - ...(cagr - ? [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: cagr, - title: "cagr", - type: "Baseline", - colors: [colors.lime, colors.pink], - }), - ] - : []), - createPriceLine({ - unit: "percentage", - }), - ], - }; - }), - }, - { - name: "Indicators", - tree: [ - { - name: "Volatility", - title: "Bitcoin Price Volatility Index", - bottom: [ - s({ - metric: "price_1w_volatility", - name: "1w", - color: colors.red, - }), - s({ - metric: "price_1m_volatility", - name: "1m", - color: colors.orange, - }), - s({ - metric: "price_1y_volatility", - name: "1y", - color: colors.lime, - }), - ], - }, - { - name: "MinMax", - tree: [ - { - metric: "1w", - title: "1 Week", - }, - { - metric: "2w", - title: "2 Week", - }, - { - metric: "1m", - title: "1 Month", - }, - { - metric: "1y", - title: "1 Year", - }, - ].map(({ metric, title }) => ({ - name: metric, - title: `Bitcoin Price ${title} MinMax Bands`, - top: [ - s({ - metric: `price_${metric}_min`, - name: "min", - color: colors.red, - }), - s({ - metric: `price_${metric}_max`, - name: "max", - color: colors.green, - }), - ], - })), - }, - { - name: "True range", - title: "Bitcoin Price True Range", - bottom: [ - s({ - metric: "price_true_range", - name: "value", - color: colors.yellow, - }), - ], - }, - { - name: "Choppiness", - title: "Bitcoin Price Choppiness Index", - bottom: [ - s({ - metric: "price_2w_choppiness_index", - name: "2w", - color: colors.red, - }), - createPriceLine({ - unit: "index", - number: 61.8, - }), - createPriceLine({ - unit: "index", - number: 38.2, - }), - ], - }, - { - name: "Mayer multiple", - title: "Mayer multiple", - top: [ - s({ - metric: `price_200d_sma`, - name: "200d sma", - color: colors.yellow, - }), - s({ - metric: `price_200d_sma_x2_4`, - name: "200d sma x2.4", - color: colors.green, - }), - s({ - metric: `price_200d_sma_x0_8`, - name: "200d sma x0.8", - color: colors.red, - }), - ], - }, - ], - }, - { - name: "Investing", - tree: [ - { - name: "DCA vs Lump sum", - tree: [ - .../** @type {const} */ ([ - [ - "1w", - market._1wDcaAvgPrice, - market.price1wAgo, - market._1wDcaReturns, - market._1wPriceReturns, - ], - [ - "1m", - market._1mDcaAvgPrice, - market.price1mAgo, - market._1mDcaReturns, - market._1mPriceReturns, - ], - [ - "3m", - market._3mDcaAvgPrice, - market.price3mAgo, - market._3mDcaReturns, - market._3mPriceReturns, - ], - [ - "6m", - market._6mDcaAvgPrice, - market.price6mAgo, - market._6mDcaReturns, - market._6mPriceReturns, - ], - [ - "1y", - market._1yDcaAvgPrice, - market.price1yAgo, - market._1yDcaReturns, - market._1yPriceReturns, - ], - ]).map( - ([ - id, - dcaAvgPrice, - priceAgo, - dcaReturns, - priceReturns, - ]) => { - const name = periodIdToName(id, true); - - return /** @satisfies {PartialChartOption} */ ({ - name, - title: `${name} DCA vs Lump Sum Returns`, - top: [ - s({ - metric: dcaAvgPrice, - name: `dca`, - color: colors.orange, - }), - s({ - metric: priceAgo, - name: `lump sum`, - color: colors.cyan, - }), - ], - bottom: [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: dcaReturns, - title: "dca", - type: "Baseline", - colors: [colors.yellow, colors.pink], - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: priceReturns, - title: "lump sum", - type: "Baseline", - }), - createPriceLine({ - unit: "percentage", - }), - ], - }); - }, - ), - .../** @type {const} */ ([ - [ - "2y", - market._2yDcaAvgPrice, - market.price2yAgo, - market._2yDcaReturns, - market._2yPriceReturns, - market._2yDcaCagr, - market._2yCagr, - ], - [ - "3y", - market._3yDcaAvgPrice, - market.price3yAgo, - market._3yDcaReturns, - market._3yPriceReturns, - market._3yDcaCagr, - market._3yCagr, - ], - [ - "4y", - market._4yDcaAvgPrice, - market.price4yAgo, - market._4yDcaReturns, - market._4yPriceReturns, - market._4yDcaCagr, - market._4yCagr, - ], - [ - "5y", - market._5yDcaAvgPrice, - market.price5yAgo, - market._5yDcaReturns, - market._5yPriceReturns, - market._5yDcaCagr, - market._5yCagr, - ], - [ - "6y", - market._6yDcaAvgPrice, - market.price6yAgo, - market._6yDcaReturns, - market._6yPriceReturns, - market._6yDcaCagr, - market._6yCagr, - ], - [ - "8y", - market._8yDcaAvgPrice, - market.price8yAgo, - market._8yDcaReturns, - market._8yPriceReturns, - market._8yDcaCagr, - market._8yCagr, - ], - [ - "10y", - market._10yDcaAvgPrice, - market.price10yAgo, - market._10yDcaReturns, - market._10yPriceReturns, - market._10yDcaCagr, - market._10yCagr, - ], - ]).map( - ([ - id, - dcaAvgPrice, - priceAgo, - dcaReturns, - priceReturns, - dcaCagr, - cagr, - ]) => { - const name = periodIdToName(id, true); - return /** @satisfies {PartialChartOption} */ ({ - name, - title: `${name} DCA vs Lump Sum Returns`, - top: [ - s({ - metric: dcaAvgPrice, - name: `dca`, - color: colors.orange, - }), - s({ - metric: priceAgo, - name: `lump sum`, - color: colors.cyan, - }), - ], - bottom: [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: dcaReturns, - title: "dca", - type: "Baseline", - colors: [colors.yellow, colors.pink], - }), - - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: priceReturns, - title: "lump sum", - type: "Baseline", - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: dcaCagr, - title: "dca cagr", - type: "Baseline", - colors: [colors.yellow, colors.pink], - defaultActive: false, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: cagr, - title: "lump sum cagr", - type: "Baseline", - defaultActive: false, - }), - createPriceLine({ - unit: "percentage", - }), - ], - }); - }, - ), - ], - }, - { - name: "DCA Class", - tree: [ - { - name: "Compare", - title: "DCA Classes", - top: dcaClasses.map(({ year, color, defaultActive }) => - s({ - metric: `dca_class_${year}_avg_price`, - name: `${year}`, - color, - defaultActive, - }), - ), - }, - ...dcaClasses.map( - ({ year, color }) => - /** @satisfies {PartialChartOption} */ ({ - name: `${year}`, - title: `DCA Since ${year}`, - top: [ - s({ - metric: `dca_class_${year}_avg_price`, - name: "cost basis", - color, - }), - ], - bottom: [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - metric: `dca_class_${year}_returns`, - title: "dca", - type: "Baseline", - }), - createPriceLine({ - unit: "percentage", - }), - ], - }), - ), - ], - }, - ], - }, - ], - }, - { - name: "Chain", - tree: [ - { - name: "Block", - tree: [ - { - name: "Count", - title: "Block Count", - bottom: [ - ...createSumCumulativeSeries({ - metric: "block_count", - }), - s({ - metric: "block_count_target", - name: "Target", - color: colors.gray, - options: { - lineStyle: 4, - }, - }), - s({ - metric: "1w_block_count", - name: "1w sum", - color: colors.red, - defaultActive: false, - }), - s({ - metric: "1m_block_count", - name: "1m sum", - color: colors.pink, - defaultActive: false, - }), - s({ - metric: "1y_block_count", - name: "1y sum", - color: colors.purple, - defaultActive: false, - }), - ], - }, - { - name: "Interval", - title: "Block Interval", - bottom: [ - s({ - metric: "interval", - name: "Interval", - }), - createAverageSeries("block_interval"), - ...createMinMaxPercentilesSeries("block_interval"), - createPriceLine({ - unit: "secs", - name: "Target", - number: 600, - }), - ], - }, - { - name: "Size", - title: "Block Size", - bottom: [ - s({ - metric: "total_size", - name: "raw", - }), - s({ - metric: "vbytes", - name: "raw", - }), - s({ - metric: "weight", - name: "raw", - }), - ...createAverageSumCumulativeMinMaxPercentilesSeries( - "block_size", - ), - ...createAverageSumCumulativeMinMaxPercentilesSeries( - "block_weight", - ), - ...createAverageSumCumulativeMinMaxPercentilesSeries( - "block_vbytes", - ), - ], - }, - ], - }, - { - name: "Transaction", - tree: [ - { - name: "Count", - title: "Transaction Count", - bottom: createBaseAverageSumCumulativeMinMaxPercentilesSeries( - { - metric: "tx_count", - name: "Count", - }, - ), - }, - { - name: "Volume", - title: "Transaction Volume", - bottom: [ - s({ - metric: "sent", - name: "Sent", - }), - s({ - metric: "sent_btc", - name: "Sent", - }), - s({ - metric: "sent_usd", - name: "Sent", - }), - s({ - metric: "annualized_volume", - name: "annualized", - color: colors.red, - defaultActive: false, - }), - s({ - metric: "annualized_volume_btc", - name: "annualized", - color: colors.red, - defaultActive: false, - }), - s({ - metric: "annualized_volume_usd", - name: "annualized", - color: colors.lime, - defaultActive: false, - }), - ], - }, - { - name: "Size", - title: "Transaction Size", - bottom: [ - createAverageSeries("tx_weight"), - ...createMinMaxPercentilesSeries("tx_weight"), - createAverageSeries("tx_vsize"), - ...createMinMaxPercentilesSeries("tx_vsize"), - ], - }, - { - name: "Versions", - title: "Transaction Versions", - bottom: [ - [colors.orange, colors.red], - [colors.cyan, colors.blue], - [colors.lime, colors.green], - ].flatMap(([sumColor, cumulativeColor], index) => - createSumCumulativeSeries({ - metric: `tx_v${index + 1}`, - common: `v${index + 1}`, - sumColor, - cumulativeColor, - }), - ), - }, - { - name: "Velocity", - title: "Transactions Velocity", - bottom: [ - s({ - metric: "tx_btc_velocity", - name: "bitcoin", - }), - s({ - metric: "tx_usd_velocity", - name: "dollars", - color: colors.emerald, - }), - ], - }, - { - name: "Speed", - title: "Transactions Per Second", - bottom: [ - s({ - metric: "tx_per_sec", - name: "Transactions", - }), - ], - }, - ], - }, - { - name: "Input", - tree: [ - { - name: "Count", - title: "Transaction Input Count", - bottom: [ - createAverageSeries("input_count"), - createCumulativeSeries({ metric: "input_count" }), - ...createMinMaxPercentilesSeries("input_count"), - ], - }, - { - name: "Speed", - title: "Inputs Per Second", - bottom: [ - s({ - metric: "inputs_per_sec", - name: "Inputs", - }), - ], - }, - // { - // name: "Value", - // title: "Transaction Input Value", - // bottom: [ - // createAverageSeries({ concat: "input_value" }), - // ...createSumCumulativeSeries({ concat: "input_value" }), - // ], - // }, - ], - }, - { - name: "Output", - tree: [ - { - name: "Count", - title: "Transaction Output Count", - bottom: [ - createAverageSeries("output_count"), - createCumulativeSeries({ metric: "output_count" }), - ...createMinMaxPercentilesSeries("output_count"), - ], - }, - { - name: "Speed", - title: "Outputs Per Second", - bottom: [ - s({ - metric: "outputs_per_sec", - name: "Outputs", - }), - ], - }, - // { - // name: "Value", - // title: "Transaction Output Value", - // bottom: [ - // createAverageSeries({ concat: "output_value" }), - // ...createSumCumulativeSeries({ concat: "output_value" }), - // ], - // }, - ], - }, - { - name: "Mining", - tree: [ - { - name: "Supply", - title: "Circulating Supply", - bottom: [ - s({ - metric: "supply", - name: "Mined", - }), - s({ - metric: "supply_btc", - name: "Mined", - }), - s({ - metric: "supply_usd", - name: "Mined", - }), - ], - }, - { - name: "Rewards", - tree: [ - { - name: "Coinbase", - title: "Coinbase", - bottom: [ - ...createBaseAverageSumCumulativeMinMaxPercentilesSeries( - { - metric: "coinbase", - name: "Coinbase", - }, - ), - ...createBaseAverageSumCumulativeMinMaxPercentilesSeries( - { - metric: "coinbase_btc", - name: "Coinbase", - }, - ), - ...createBaseAverageSumCumulativeMinMaxPercentilesSeries( - { - metric: "coinbase_usd", - name: "Coinbase", - }, - ), - ], - }, - { - name: "Subsidy", - title: "Subsidy", - bottom: [ - ...createBaseAverageSumCumulativeMinMaxPercentilesSeries( - { - metric: "subsidy", - name: "Subsidy", - }, - ), - s({ - metric: "subsidy_usd_1y_sma", - name: "1y sma", - }), - ...createBaseAverageSumCumulativeMinMaxPercentilesSeries( - { - metric: "subsidy_btc", - name: "Subsidy", - }, - ), - ...createBaseAverageSumCumulativeMinMaxPercentilesSeries( - { - metric: "subsidy_usd", - name: "Subsidy", - }, - ), - ], - }, - { - name: "Fee", - title: "Transaction Fee", - bottom: [ - ...createAverageSumCumulativeMinMaxPercentilesSeries( - "fee", - ), - ...createAverageSumCumulativeMinMaxPercentilesSeries( - "fee_btc", - ), - ...createAverageSumCumulativeMinMaxPercentilesSeries( - "fee_usd", - ), - ], - }, - { - name: "Dominance", - title: "Reward Dominance", - bottom: [ - s({ - metric: "fee_dominance", - name: "Fee", - color: colors.amber, - }), - s({ - metric: "subsidy_dominance", - name: "Subsidy", - color: colors.red, - }), - ], - }, - { - name: "Unclaimed", - title: "Unclaimed Rewards", - bottom: [ - ...createSumCumulativeSeries({ - metric: "unclaimed_rewards", - }), - ...createSumCumulativeSeries({ - metric: "unclaimed_rewards_btc", - }), - ...createSumCumulativeSeries({ - metric: "unclaimed_rewards_usd", - }), - ], - }, - { - name: "Inflation", - title: "Inflation Rate", - bottom: [ - s({ - metric: "inflation_rate", - name: "Inflation", - }), - ], - }, - { - name: "Puell multiple", - title: "Puell multiple", - bottom: [ - s({ - metric: "puell_multiple", - name: "Multiple", - }), - ], - }, - ], - }, - { - name: "Feerate", - title: "Transaction Fee Rate", - bottom: [ - createAverageSeries("fee_rate"), - ...createMinMaxPercentilesSeries("fee_rate"), - ], - }, - { - name: "Halving", - title: "Halving Epoch", - bottom: [ - s({ - metric: "halvingepoch", - name: "Halving", - }), - s({ - metric: "blocks_before_next_halving", - name: "Before next", - }), - s({ - metric: "days_before_next_halving", - name: "Before next", - }), - ], - }, - { - name: "Difficulty", - title: "Difficulty", - bottom: [ - s({ - metric: "difficulty", - name: "Value", - }), - s({ - metric: "difficultyepoch", - name: "Difficulty", - }), - s({ - metric: "blocks_before_next_difficulty_adjustment", - name: "Before next", - }), - s({ - metric: "days_before_next_difficulty_adjustment", - name: "Before next", - }), - ], - }, - { - name: "adjustment", - title: "Difficulty adjustment", - bottom: [ - { - metric: "difficulty_adjustment", - title: "difficulty change", - type: "Baseline", - }, - ], - }, - { - name: "hash", - tree: [ - { - name: "Rate", - title: "Hash Rate", - bottom: [ - s({ - metric: "hash_rate", - name: "Raw", - }), - s({ - metric: "hash_rate_1w_sma", - name: "1w sma", - color: colors.red, - defaultActive: false, - }), - s({ - metric: "hash_rate_1m_sma", - name: "1m sma", - color: colors.pink, - defaultActive: false, - }), - s({ - metric: "hash_rate_2m_sma", - name: "2m sma", - color: colors.purple, - defaultActive: false, - }), - s({ - metric: "hash_rate_1y_sma", - name: "1y sma", - color: colors.indigo, - defaultActive: false, - }), - s({ - metric: "difficulty_as_hash", - name: "difficulty", - color: colors.default, - options: { - lineStyle: 1, - }, - }), - ], - }, - { - name: "Price", - title: "Hash Price", - bottom: [ - s({ - metric: "hash_price_ths", - name: "Dollars", - color: colors.emerald, - }), - s({ - metric: "hash_price_phs", - name: "Dollars", - color: colors.emerald, - }), - s({ - metric: "hash_price_rebound", - name: "Rebound", - color: colors.yellow, - }), - s({ - metric: "hash_price_ths_min", - name: "Min", - color: colors.red, - options: { - lineStyle: 1, - }, - }), - s({ - metric: "hash_price_phs_min", - name: "Min", - color: colors.red, - options: { - lineStyle: 1, - }, - }), - ], - }, - { - name: "Value", - title: "Hash Value", - bottom: [ - s({ - metric: "hash_value_ths", - name: "Sats", - color: colors.orange, - }), - s({ - metric: "hash_value_phs", - name: "Sats", - color: colors.orange, - }), - s({ - metric: "hash_value_rebound", - name: "Rebound", - color: colors.yellow, - }), - s({ - metric: "hash_value_ths_min", - name: "Min", - color: colors.red, - options: { - lineStyle: 1, - }, - }), - s({ - metric: "hash_value_phs_min", - name: "Min", - color: colors.red, - options: { - lineStyle: 1, - }, - }), - ], - }, - ], - }, - { - name: "Pools", - tree: entries(brk.tree.computed.pools.vecs).map( - ([key, pool]) => { - const name = - brk.POOL_ID_TO_POOL_NAME[key.toLowerCase()] || key; - return { - name, - tree: [ - { - name: "Dominance", - title: `Mining Dominance of ${name}`, - bottom: [ - s({ - metric: pool._1dDominance.base, - name: "1d", - color: colors.rose, - defaultActive: false, - }), - s({ - metric: pool._1wDominance, - name: "1w", - color: colors.red, - defaultActive: false, - }), - s({ - metric: pool._1mDominance, - name: "1m", - }), - s({ - metric: pool._1yDominance, - name: "1y", - color: colors.lime, - defaultActive: false, - }), - s({ - metric: pool.dominance.base, - name: "all time", - color: colors.teal, - defaultActive: false, - }), - ], - }, - { - name: "Blocks mined", - title: `Blocks mined by ${name}`, - bottom: [ - s({ - metric: pool.blocksMined.base, - name: "Sum", - }), - s({ - metric: pool.blocksMined.cumulative, - name: "Cumulative", - color: colors.blue, - }), - s({ - metric: pool._1wBlocksMined, - name: "1w Sum", - color: colors.red, - defaultActive: false, - }), - s({ - metric: pool._1mBlocksMined, - name: "1m Sum", - color: colors.pink, - defaultActive: false, - }), - s({ - metric: pool._1yBlocksMined, - name: "1y Sum", - color: colors.purple, - defaultActive: false, - }), - ], - }, - { - name: "Rewards", - title: `Rewards collected by ${name}`, - bottom: [ - { - pattern: pool.coinbase, - label: "coinbase", - cumulativeColor: colors.red, - sumColor: colors.orange, - }, - { - pattern: pool.subsidy, - label: "subsidy", - cumulativeColor: colors.emerald, - sumColor: colors.lime, - }, - { - pattern: pool.fee, - label: "fee", - cumulativeColor: colors.indigo, - sumColor: colors.cyan, - }, - ].flatMap( - ({ - pattern, - label, - sumColor, - cumulativeColor, - }) => [ - ...createSumCumulativeSeries({ - metric: pattern.sats, - common: label, - sumColor, - cumulativeColor, - }), - ...createSumCumulativeSeries({ - metric: pattern.bitcoin, - common: label, - sumColor, - cumulativeColor, - }), - ...createSumCumulativeSeries({ - metric: pattern.dollars, - common: label, - sumColor, - cumulativeColor, - }), - ], - ), - }, - { - name: "Days since block", - title: `Days since ${name} mined a block`, - bottom: [ - s({ - metric: pool.daysSinceBlock, - name: "Since block", - }), - ], - }, - ], - }; - }, - ), - }, - ], - }, - { - name: "Unspendable", - tree: [ - { - name: "supply", - title: "Unspendable Supply", - bottom: [ - s({ - metric: "unspendable_supply", - name: "Supply", - }), - s({ - metric: "unspendable_supply_btc", - name: "Supply", - }), - s({ - metric: "unspendable_supply_usd", - name: "Supply", - }), - ], - }, - { - name: "op_return", - tree: [ - { - name: "outputs", - title: "op_return outputs", - bottom: [ - s({ - metric: "opreturn_count", - name: "Count", - }), - s({ - metric: "opreturn_count", - name: "sum", - }), - s({ - metric: "opreturn_count_cumulative", - name: "cumulative", - color: colors.red, - }), - ], - }, - { - name: "supply", - title: "OP_return Supply", - bottom: [ - s({ - metric: "opreturn_supply", - name: "Supply", - }), - s({ - metric: "opreturn_supply_btc", - name: "Supply", - }), - s({ - metric: "opreturn_supply_usd", - name: "Supply", - }), - ], - }, - ], - }, - ], - }, - ], - }, - { - name: "Cohorts", - tree: [ - createCohortGroupFolder(cohortAll), - { - name: "terms", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "UTXOs Term", - list: [...terms, cohortAllForComparaison], - }), - ...terms.map(createCohortGroupFolder), - ], - }, - { - name: "Epochs", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "Epoch", - list: [...epoch, cohortAllForComparaison], - }), - ...epoch.map(createCohortGroupFolder), - ], - }, - { - name: "types", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "Type", - list: [...type, cohortAllForComparaison], - }), - ...type.map(createCohortGroupFolder), - ], - }, - { - name: "UTXOs Up to age", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "UTXOs Up To Age", - list: [...upToDate, cohortAllForComparaison], - }), - ...upToDate.map(createCohortGroupFolder), - ], - }, - { - name: "UTXOs from age", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "UTXOs from age", - list: [...fromDate, cohortAllForComparaison], - }), - ...fromDate.map(createCohortGroupFolder), - ], - }, - { - name: "UTXOs age Ranges", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "UTXOs Age Range", - list: [...dateRange, cohortAllForComparaison], - }), - ...dateRange.map(createCohortGroupFolder), - ], - }, - { - name: "UTXOs under amounts", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "UTXOs under amount", - list: [...utxosUnderAmount, cohortAllForComparaison], - }), - ...utxosUnderAmount.map(createCohortGroupFolder), - ], - }, - { - name: "UTXOs Above Amounts", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "UTXOs Above Amount", - list: [...utxosAboveAmount, cohortAllForComparaison], - }), - ...utxosAboveAmount.map(createCohortGroupFolder), - ], - }, - { - name: "UTXOs between amounts", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "UTXOs between amounts", - list: [...utxosAmountRanges, cohortAllForComparaison], - }), - ...utxosAmountRanges.map(createCohortGroupFolder), - ], - }, - { - name: "Addresses under amount", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "Addresses under Amount", - list: [...addressesUnderAmount, cohortAllForComparaison], - }), - ...addressesUnderAmount.map(createCohortGroupFolder), - ], - }, - { - name: "Addresses above amount", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "Addresses above amount", - list: [...addressesAboveAmount, cohortAllForComparaison], - }), - ...addressesAboveAmount.map(createCohortGroupFolder), - ], - }, - { - name: "Addresses between amounts", - tree: [ - createCohortGroupFolder({ - name: "Compare", - title: "Addresses between amounts", - list: [...addressesAmountRanges, cohortAllForComparaison], - }), - ...addressesAmountRanges.map(createCohortGroupFolder), - ], - }, - ], - }, - { - name: "Cointime", - tree: [ - { - name: "Prices", - tree: [ - { - name: "Compare", - title: "Compare Cointime Prices", - top: cointimePrices.map(({ price, name, color }) => - s({ - metric: price, - name, - color, - }), - ), - }, - ...cointimePrices.map( - ({ price, ratio, name, color, title }) => ({ - name, - tree: createPriceWithRatioOptions({ - price, - ratio, - legend: name, - color, - name, - title, - }), - }), - ), - ], - }, - { - name: "Capitalization", - tree: [ - { - name: "Compare", - title: "Compare Cointime Capitalizations", - bottom: [ - s({ - metric: `market_cap`, - name: "Market", - color: colors.default, - }), - s({ - metric: `realized_cap`, - name: "Realized", - color: colors.orange, - }), - ...cointimeCapitalizations.map(({ metric, name, color }) => - s({ - metric, - name, - color, - }), - ), - ], - }, - ...cointimeCapitalizations.map( - ({ metric, name, color, title }) => ({ - name, - title, - bottom: [ - s({ - metric, - name, - color, - }), - s({ - metric: `market_cap`, - name: "Market", - color: colors.default, - }), - s({ - metric: `realized_cap`, - name: "Realized", - color: colors.orange, - }), - ], - }), - ), - ], - }, - { - name: "Supply", - title: "Cointime Supply", - bottom: /** @type {const} */ ([ - [utxoCohorts.all.supply.supply, "all", colors.orange], - [cointime.vaultedSupply, "vaulted", colors.lime], - [cointime.activeSupply, "active", colors.rose], - ]).flatMap(([supply, name, color]) => [ - s({ metric: supply.sats, name, color }), - s({ metric: supply.bitcoin, name, color }), - s({ metric: supply.dollars, name, color }), - ]), - }, - { - name: "Liveliness & Vaultedness", - title: "Liveliness & Vaultedness", - bottom: [ - s({ - metric: "liveliness", - name: "Liveliness", - color: colors.rose, - }), - s({ - metric: "vaultedness", - name: "Vaultedness", - color: colors.lime, - }), - s({ - metric: "activity_to_vaultedness_ratio", - name: "Liveliness / Vaultedness", - color: colors.purple, - }), - ], - }, - { - name: "Coinblocks", - title: "Coinblocks", - bottom: [ - s({ - metric: "coinblocks_destroyed", - name: "Destroyed", - color: colors.red, - }), - s({ - metric: "coinblocks_destroyed_cumulative", - name: "Cumulative Destroyed", - color: colors.red, - defaultActive: false, - }), - s({ - metric: "coinblocks_created", - name: "created", - color: colors.orange, - }), - s({ - metric: "coinblocks_created_cumulative", - name: "Cumulative created", - color: colors.orange, - defaultActive: false, - }), - s({ - metric: "coinblocks_stored", - name: "stored", - color: colors.green, - }), - s({ - metric: "coinblocks_stored_cumulative", - name: "Cumulative stored", - color: colors.green, - defaultActive: false, - }), - ], - }, - { - name: "Adjusted", - tree: [ - { - name: "inflation", - title: "Cointime-Adjusted inflation rate", - bottom: [ - s({ - metric: "inflation_rate", - name: "base", - color: colors.orange, - }), - s({ - metric: "cointime_adj_inflation_rate", - name: "base", - color: colors.purple, - }), - ], - }, - { - name: "Velocity", - title: "Cointime-Adjusted transactions velocity", - bottom: [ - s({ - metric: "tx_btc_velocity", - name: "btc", - color: colors.orange, - }), - s({ - metric: "cointime_adj_tx_btc_velocity", - name: "adj. btc", - color: colors.red, - }), - s({ - metric: "tx_usd_velocity", - name: "usd", - color: colors.emerald, - }), - s({ - metric: "cointime_adj_tx_usd_velocity", - name: "adj. usd", - color: colors.lime, - }), - ], - }, - ], - }, - ], - }, - ], - }, - { - kind: "table", - title: "Table", - name: "Table", - }, - { - name: "Simulations", - tree: [ - { - kind: "simulation", - title: "Save In Bitcoin", - name: "Save In Bitcoin", - }, - ], - }, - { - name: "Tools", - tree: [ - { - name: "API", - url: () => "/api", - title: "API documentation", - }, - { - name: "MCP", - url: () => - "https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_mcp/README.md#brk_mcp", - title: "Model Context Protocol documentation", - }, - { - name: "Crate", - url: () => "/crate", - title: "View on crates.io", - }, - { - name: "Source", - url: () => "/github", - title: "Source code and issues", - }, - { - name: "Changelog", - url: () => "/changelog", - title: "Release notes and changelog", - }, - ], - }, - { - name: "Hosting", - tree: [ - { - name: "Status", - url: () => "/status", - title: "Service status and uptime", - }, - { - name: "Self-host", - url: () => "/install", - title: "Install and run yourself", - }, - { - name: "Service", - url: () => "/service", - title: "Hosted service offering", - }, - ], - }, - { - name: "Community", - tree: [ - { - name: "Discord", - url: () => "/discord", - title: "Join the Discord server", - }, - { - name: "GitHub", - url: () => "/github", - title: "Source code and issues", - }, - { - name: "Nostr", - url: () => "/nostr", - title: "Follow on Nostr", - }, - ], - }, - { - name: "Donate", - qrcode: true, - url: () => "bitcoin:bc1q098zsm89m7kgyze338vfejhpdt92ua9p3peuve", - title: "Bitcoin address for donations", - }, - { - name: "Share", - qrcode: true, - url: () => window.location.href, - title: "Share", - }, - ]; -} diff --git a/websites/bitview/scripts/options/partial/cohorts/shared.js b/websites/bitview/scripts/options/partial/cohorts/shared.js index 4e8c1a525..93ec09a42 100644 --- a/websites/bitview/scripts/options/partial/cohorts/shared.js +++ b/websites/bitview/scripts/options/partial/cohorts/shared.js @@ -47,7 +47,8 @@ export function createSingleSupplySeries(ctx, cohort, title) { * @returns {AnyFetchedSeriesBlueprint[]} */ export function createGroupedSupplyTotalSeries(ctx, list) { - const { s, constant100 } = ctx; + const { s, brk } = ctx; + const constant100 = brk.tree.computed.constants.constant100; return list.flatMap(({ color, name, tree }) => [ s({ metric: tree.supply.supply.sats, name, color }), @@ -206,11 +207,11 @@ export function createCostBasisPercentilesSeries(ctx, list, useGroupName) { return list.flatMap(({ color, name, tree }) => { const percentiles = tree.costBasis.percentiles; return [ - s({ metric: percentiles.pct10, name: useGroupName ? `${name} p10` : "p10", color, defaultActive: false }), - s({ metric: percentiles.pct25, name: useGroupName ? `${name} p25` : "p25", color, defaultActive: false }), - s({ metric: percentiles.pct50, name: useGroupName ? `${name} p50` : "p50", color }), - s({ metric: percentiles.pct75, name: useGroupName ? `${name} p75` : "p75", color, defaultActive: false }), - s({ metric: percentiles.pct90, name: useGroupName ? `${name} p90` : "p90", color, defaultActive: false }), + s({ metric: percentiles.costBasisPct10, name: useGroupName ? `${name} p10` : "p10", color, defaultActive: false }), + s({ metric: percentiles.costBasisPct25, name: useGroupName ? `${name} p25` : "p25", color, defaultActive: false }), + s({ metric: percentiles.costBasisPct50, name: useGroupName ? `${name} p50` : "p50", color }), + s({ metric: percentiles.costBasisPct75, name: useGroupName ? `${name} p75` : "p75", color, defaultActive: false }), + s({ metric: percentiles.costBasisPct90, name: useGroupName ? `${name} p90` : "p90", color, defaultActive: false }), ]; }); } diff --git a/websites/bitview/scripts/options/partial/cohorts/utxo.js b/websites/bitview/scripts/options/partial/cohorts/utxo.js index 1ae8cbfaa..90c790718 100644 --- a/websites/bitview/scripts/options/partial/cohorts/utxo.js +++ b/websites/bitview/scripts/options/partial/cohorts/utxo.js @@ -15,8 +15,6 @@ import { createUtxoCountSeries, createRealizedPriceSeries, createRealizedPriceRatioSeries, - createRealizedCapSeries, - createCostBasisMinMaxSeries, createCostBasisPercentilesSeries, } from "./shared.js"; @@ -97,7 +95,12 @@ export function createUtxoCohortFolder(ctx, args) { createRealizedSection(ctx, list, args, useGroupName, isSingle, title), ...createUnrealizedSection(ctx, list, useGroupName, title), ...(hasPercentiles - ? createCostBasisSectionWithPercentiles(ctx, /** @type {readonly AgeCohortObject[]} */ (list), useGroupName, title) + ? createCostBasisSectionWithPercentiles( + ctx, + /** @type {readonly AgeCohortObject[]} */ (list), + useGroupName, + title, + ) : createCostBasisSectionBasic(ctx, list, useGroupName, title)), ...createActivitySection(ctx, list, useGroupName, title), ], @@ -120,7 +123,11 @@ function createSupplySection(ctx, list, args, useGroupName, isSingle, title) { ? { name: "supply", title: `Supply ${title}`, - bottom: createSingleSupplySeries(ctx, /** @type {UtxoCohortObject} */ (args), title), + bottom: createSingleSupplySeries( + ctx, + /** @type {UtxoCohortObject} */ (args), + title, + ), } : { name: "supply", @@ -188,13 +195,29 @@ function createRealizedSection(ctx, list, args, useGroupName, isSingle, title) { bottom: createRealizedPriceRatioSeries(ctx, list), }, ] - : createRealizedPriceOptions(ctx, /** @type {UtxoCohortObject} */ (args), title)), + : createRealizedPriceOptions( + ctx, + /** @type {UtxoCohortObject} */ (args), + title, + )), { name: "capitalization", title: `Realized Capitalization ${title}`, - bottom: createRealizedCapWithExtras(ctx, list, args, useGroupName, title), + bottom: createRealizedCapWithExtras( + ctx, + list, + args, + useGroupName, + title, + ), }, - ...(!useGroupName ? createRealizedPnlSection(ctx, /** @type {UtxoCohortObject} */ (args), title) : []), + ...(!useGroupName + ? createRealizedPnlSection( + ctx, + /** @type {UtxoCohortObject} */ (args), + title, + ) + : []), ], }; } @@ -214,7 +237,9 @@ function createRealizedPriceOptions(ctx, args, title) { { name: "price", title: `Realized Price ${title}`, - top: [s({ metric: tree.realized.realizedPrice, name: "realized", color })], + top: [ + s({ metric: tree.realized.realizedPrice, name: "realized", color }), + ], }, ]; } @@ -390,14 +415,22 @@ function createCostBasisSectionWithPercentiles(ctx, list, useGroupName, title) { name: "min", title: `Min Cost Basis ${title}`, top: list.map(({ color, name, tree }) => - s({ metric: tree.costBasis.minCostBasis, name: useGroupName ? name : "Min", color }), + s({ + metric: tree.costBasis.minCostBasis, + name: useGroupName ? name : "Min", + color, + }), ), }, { name: "max", title: `Max Cost Basis ${title}`, top: list.map(({ color, name, tree }) => - s({ metric: tree.costBasis.maxCostBasis, name: useGroupName ? name : "Max", color }), + s({ + metric: tree.costBasis.maxCostBasis, + name: useGroupName ? name : "Max", + color, + }), ), }, { @@ -429,14 +462,22 @@ function createCostBasisSectionBasic(ctx, list, useGroupName, title) { name: "min", title: `Min Cost Basis ${title}`, top: list.map(({ color, name, tree }) => - s({ metric: tree.costBasis.minCostBasis, name: useGroupName ? name : "Min", color }), + s({ + metric: tree.costBasis.minCostBasis, + name: useGroupName ? name : "Min", + color, + }), ), }, { name: "max", title: `Max Cost Basis ${title}`, top: list.map(({ color, name, tree }) => - s({ metric: tree.costBasis.maxCostBasis, name: useGroupName ? name : "Max", color }), + s({ + metric: tree.costBasis.maxCostBasis, + name: useGroupName ? name : "Max", + color, + }), ), }, ], diff --git a/websites/bitview/scripts/options/partial/cointime.js b/websites/bitview/scripts/options/partial/cointime.js index 1334368b3..ffaa46a77 100644 --- a/websites/bitview/scripts/options/partial/cointime.js +++ b/websites/bitview/scripts/options/partial/cointime.js @@ -7,7 +7,7 @@ * @param {string} args.name * @param {string} args.title * @param {string} args.legend - * @param {MetricAccessor} args.price + * @param {AnyMetricPattern} args.price * @param {ActivePriceRatioPattern} args.ratio * @param {Color} [args.color] * @returns {PartialOptionsTree} diff --git a/websites/bitview/scripts/options/partial/constants.js b/websites/bitview/scripts/options/partial/constants.js index eba1a2c1e..93d5b5aa9 100644 --- a/websites/bitview/scripts/options/partial/constants.js +++ b/websites/bitview/scripts/options/partial/constants.js @@ -5,45 +5,20 @@ * Examples: 0 → constant0, 38.2 → constant382, -1 → constantMinus1 * @param {BrkClient["tree"]["computed"]["constants"]} constants * @param {number} num - * @returns {Constant0Pattern} + * @returns {AnyMetricPattern} */ export function getConstant(constants, num) { const key = num >= 0 ? `constant${String(num).replace(".", "")}` : `constantMinus${Math.abs(num)}`; - const constant = /** @type {Constant0Pattern | undefined} */ ( - /** @type {Record>} */ (constants)[key] + const constant = /** @type {AnyMetricPattern | undefined} */ ( + /** @type {Record} */ (constants)[key] ); if (!constant) throw new Error(`Unknown constant: ${num} (key: ${key})`); return constant; } -/** - * Flatten a Constant0Pattern into a simple MetricAccessor - * Constant0Pattern has { dateindex: { by: {...} }, height: { by: {...} }, ... } - * This flattens it to { by: { dateindex: MetricNode, height: MetricNode, ... } } - * @param {Constant0Pattern} pattern - * @returns {MetricAccessor} - */ -export function flattenConstant(pattern) { - return { - by: { - dateindex: pattern.dateindex.by.dateindex, - decadeindex: pattern.decadeindex.by.decadeindex, - height: pattern.height.by.height, - monthindex: pattern.monthindex.by.monthindex, - quarterindex: pattern.quarterindex.by.quarterindex, - semesterindex: pattern.semesterindex.by.semesterindex, - weekindex: pattern.weekindex.by.weekindex, - yearindex: pattern.yearindex.by.yearindex, - }, - indexes() { - return /** @type {Index[]} */ (Object.keys(this.by)); - }, - }; -} - /** * Create a price line series (horizontal reference line) * @param {Object} args @@ -68,7 +43,7 @@ export function createPriceLine({ lineStyle, }) { return { - metric: flattenConstant(getConstant(constants, number)), + metric: getConstant(constants, number), title: name ?? `${number}`, unit, defaultActive, @@ -92,7 +67,7 @@ export function createPriceLine({ */ export function createPriceLines({ constants, colors, numbers, unit }) { return numbers.map((number) => ({ - metric: flattenConstant(getConstant(constants, number)), + metric: getConstant(constants, number), title: `${number}`, unit, defaultActive: !number, @@ -109,7 +84,7 @@ export function createPriceLines({ constants, colors, numbers, unit }) { * Create a constant line series * @param {Object} args * @param {Colors} args.colors - * @param {Constant0Pattern} args.constant + * @param {AnyMetricPattern} args.constant * @param {string} args.name * @param {Unit} args.unit * @param {Color} [args.color] @@ -127,7 +102,7 @@ export function line({ defaultActive, }) { return { - metric: flattenConstant(constant), + metric: constant, title: name, unit, defaultActive, diff --git a/websites/bitview/scripts/options/partial/context.js b/websites/bitview/scripts/options/partial/context.js index ab290ab08..1c1449b5e 100644 --- a/websites/bitview/scripts/options/partial/context.js +++ b/websites/bitview/scripts/options/partial/context.js @@ -1,11 +1,5 @@ import { s, fromBlockCount, fromBitcoin, fromBlockSize } from "./series.js"; -import { - getConstant, - flattenConstant, - createPriceLine, - createPriceLines, - line, -} from "./constants.js"; +import { createPriceLine, createPriceLines, line } from "./constants.js"; /** * Create a context object with all dependencies for building partial options @@ -16,13 +10,10 @@ import { */ export function createContext({ colors, brk }) { const constants = brk.tree.computed.constants; - const constant100 = flattenConstant(constants.constant100); return { colors, brk, - constants, - constant100, // Series helpers s, @@ -33,9 +24,6 @@ export function createContext({ colors, brk }) { fromBlockSize: (pattern, title, color) => fromBlockSize(colors, pattern, title, color), - // Constant helpers - getConstant: (num) => getConstant(constants, num), - flattenConstant, createPriceLine: (args) => createPriceLine({ constants, colors, ...args }), createPriceLines: (args) => createPriceLines({ constants, colors, ...args }), diff --git a/websites/bitview/scripts/options/partial/index.js b/websites/bitview/scripts/options/partial/index.js index a59768cd2..fc2e55b06 100644 --- a/websites/bitview/scripts/options/partial/index.js +++ b/websites/bitview/scripts/options/partial/index.js @@ -7,7 +7,7 @@ import { createUtxoCohortFolder, createAddressCohortFolder, } from "./cohorts/index.js"; -import { createMarketSection } from "./market.js"; +import { createMarketSection } from "./market/index.js"; import { createChainSection } from "./chain.js"; import { createCointimeSection } from "./cointime.js"; diff --git a/websites/bitview/scripts/options/partial/market.js b/websites/bitview/scripts/options/partial/market.js deleted file mode 100644 index cbbbaa10d..000000000 --- a/websites/bitview/scripts/options/partial/market.js +++ /dev/null @@ -1,480 +0,0 @@ -/** Market section builder - typed tree-based patterns */ - -/** - * Convert period ID to readable name - * @param {string} id - * @param {boolean} [compoundAdjective] - */ -function periodIdToName(id, compoundAdjective) { - const suffix = compoundAdjective || parseInt(id) === 1 ? "" : "s"; - return id - .replace("d", ` day${suffix}`) - .replace("w", ` week${suffix}`) - .replace("m", ` month${suffix}`) - .replace("y", ` year${suffix}`); -} - -/** - * Create price with ratio options (for moving averages) - * @param {PartialContext} ctx - * @param {Object} args - * @param {string} args.name - * @param {string} args.title - * @param {string} args.legend - * @param {EmaRatioPattern} args.ratio - * @param {Color} [args.color] - * @returns {PartialOptionsTree} - */ -function createPriceWithRatioOptions(ctx, { name, title, legend, ratio, color }) { - const { s, colors, createPriceLine } = ctx; - const priceMetric = ratio.price; - - // Percentile USD mappings - const percentileUsdMap = [ - { name: "pct99", prop: ratio.ratioPct99Usd, color: colors.rose }, - { name: "pct98", prop: ratio.ratioPct98Usd, color: colors.pink }, - { name: "pct95", prop: ratio.ratioPct95Usd, color: colors.fuchsia }, - { name: "pct5", prop: ratio.ratioPct5Usd, color: colors.cyan }, - { name: "pct2", prop: ratio.ratioPct2Usd, color: colors.sky }, - { name: "pct1", prop: ratio.ratioPct1Usd, color: colors.blue }, - ]; - - // Percentile ratio mappings - const percentileMap = [ - { name: "pct99", prop: ratio.ratioPct99, color: colors.rose }, - { name: "pct98", prop: ratio.ratioPct98, color: colors.pink }, - { name: "pct95", prop: ratio.ratioPct95, color: colors.fuchsia }, - { name: "pct5", prop: ratio.ratioPct5, color: colors.cyan }, - { name: "pct2", prop: ratio.ratioPct2, color: colors.sky }, - { name: "pct1", prop: ratio.ratioPct1, color: colors.blue }, - ]; - - // SD patterns by window - const sdPatterns = [ - { nameAddon: "all", titleAddon: "", sd: ratio.ratioSd }, - { nameAddon: "4y", titleAddon: "4y", sd: ratio.ratio4ySd }, - { nameAddon: "2y", titleAddon: "2y", sd: ratio.ratio2ySd }, - { nameAddon: "1y", titleAddon: "1y", sd: ratio.ratio1ySd }, - ]; - - /** @param {Ratio1ySdPattern} sd */ - const getSdBands = (sd) => [ - { name: "0σ", prop: sd._0sdUsd, color: colors.lime }, - { name: "+0.5σ", prop: sd.p05sdUsd, color: colors.yellow }, - { name: "+1σ", prop: sd.p1sdUsd, color: colors.amber }, - { name: "+1.5σ", prop: sd.p15sdUsd, color: colors.orange }, - { name: "+2σ", prop: sd.p2sdUsd, color: colors.red }, - { name: "+2.5σ", prop: sd.p25sdUsd, color: colors.rose }, - { name: "+3σ", prop: sd.p3sd, color: colors.pink }, - { name: "−0.5σ", prop: sd.m05sdUsd, color: colors.teal }, - { name: "−1σ", prop: sd.m1sdUsd, color: colors.cyan }, - { name: "−1.5σ", prop: sd.m15sdUsd, color: colors.sky }, - { name: "−2σ", prop: sd.m2sdUsd, color: colors.blue }, - { name: "−2.5σ", prop: sd.m25sdUsd, color: colors.indigo }, - { name: "−3σ", prop: sd.m3sd, color: colors.violet }, - ]; - - return [ - { - name: "price", - title, - top: [s({ metric: priceMetric, name: legend, color, unit: "usd" })], - }, - { - name: "Ratio", - title: `${title} Ratio`, - top: [ - s({ metric: priceMetric, name: legend, color, unit: "usd" }), - ...percentileUsdMap.map(({ name: pctName, prop, color: pctColor }) => - s({ - metric: prop, - name: pctName, - color: pctColor, - defaultActive: false, - unit: "usd", - options: { lineStyle: 1 }, - }), - ), - ], - bottom: [ - s({ metric: ratio.ratio, name: "ratio", color, unit: "ratio" }), - s({ metric: ratio.ratio1wSma, name: "1w sma", color: colors.lime, unit: "ratio" }), - s({ metric: ratio.ratio1mSma, name: "1m sma", color: colors.teal, unit: "ratio" }), - s({ metric: ratio.ratio1ySd.sma, name: "1y sma", color: colors.sky, unit: "ratio" }), - s({ metric: ratio.ratio2ySd.sma, name: "2y sma", color: colors.indigo, unit: "ratio" }), - s({ metric: ratio.ratio4ySd.sma, name: "4y sma", color: colors.purple, unit: "ratio" }), - s({ metric: ratio.ratioSd.sma, name: "all sma", color: colors.rose, unit: "ratio" }), - ...percentileMap.map(({ name: pctName, prop, color: pctColor }) => - s({ - metric: prop, - name: pctName, - color: pctColor, - defaultActive: false, - unit: "ratio", - options: { lineStyle: 1 }, - }), - ), - createPriceLine({ unit: "ratio", number: 1 }), - ], - }, - { - name: "ZScores", - tree: sdPatterns.map(({ nameAddon, titleAddon, sd }) => ({ - name: nameAddon, - title: `${title} ${titleAddon} Z-Score`, - top: getSdBands(sd).map(({ name: bandName, prop, color: bandColor }) => - s({ metric: prop, name: bandName, color: bandColor, unit: "usd" }), - ), - bottom: [ - s({ metric: sd.zscore, name: "zscore", color, unit: "sd" }), - createPriceLine({ unit: "sd", number: 3 }), - createPriceLine({ unit: "sd", number: 2 }), - createPriceLine({ unit: "sd", number: 1 }), - createPriceLine({ unit: "sd", number: 0 }), - createPriceLine({ unit: "sd", number: -1 }), - createPriceLine({ unit: "sd", number: -2 }), - createPriceLine({ unit: "sd", number: -3 }), - ], - })), - }, - ]; -} - -/** - * Build averages data array from market patterns - * @param {Colors} colors - * @param {MarketMovingAverage} ma - */ -function buildAverages(colors, ma) { - return /** @type {const} */ ([ - ["1w", 7, "red", ma.price1wSma, ma.price1wEma], - ["8d", 8, "orange", ma.price8dSma, ma.price8dEma], - ["13d", 13, "amber", ma.price13dSma, ma.price13dEma], - ["21d", 21, "yellow", ma.price21dSma, ma.price21dEma], - ["1m", 30, "lime", ma.price1mSma, ma.price1mEma], - ["34d", 34, "green", ma.price34dSma, ma.price34dEma], - ["55d", 55, "emerald", ma.price55dSma, ma.price55dEma], - ["89d", 89, "teal", ma.price89dSma, ma.price89dEma], - ["144d", 144, "cyan", ma.price144dSma, ma.price144dEma], - ["200d", 200, "sky", ma.price200dSma, ma.price200dEma], - ["1y", 365, "blue", ma.price1ySma, ma.price1yEma], - ["2y", 730, "indigo", ma.price2ySma, ma.price2yEma], - ["200w", 1400, "violet", ma.price200wSma, ma.price200wEma], - ["4y", 1460, "purple", ma.price4ySma, ma.price4yEma], - ]).map(([id, days, colorKey, sma, ema]) => ({ - id, - name: periodIdToName(id, true), - days, - color: colors[colorKey], - sma, - ema, - })); -} - -/** - * Build DCA classes data array - * @param {Colors} colors - * @param {MarketDca} dca - */ -function buildDcaClasses(colors, dca) { - return /** @type {const} */ ([ - [2015, "pink", false, dca.dcaClass2015AvgPrice, dca.dcaClass2015Returns, dca.dcaClass2015Stack], - [2016, "red", false, dca.dcaClass2016AvgPrice, dca.dcaClass2016Returns, dca.dcaClass2016Stack], - [2017, "orange", true, dca.dcaClass2017AvgPrice, dca.dcaClass2017Returns, dca.dcaClass2017Stack], - [2018, "yellow", true, dca.dcaClass2018AvgPrice, dca.dcaClass2018Returns, dca.dcaClass2018Stack], - [2019, "green", true, dca.dcaClass2019AvgPrice, dca.dcaClass2019Returns, dca.dcaClass2019Stack], - [2020, "teal", true, dca.dcaClass2020AvgPrice, dca.dcaClass2020Returns, dca.dcaClass2020Stack], - [2021, "sky", true, dca.dcaClass2021AvgPrice, dca.dcaClass2021Returns, dca.dcaClass2021Stack], - [2022, "blue", true, dca.dcaClass2022AvgPrice, dca.dcaClass2022Returns, dca.dcaClass2022Stack], - [2023, "purple", true, dca.dcaClass2023AvgPrice, dca.dcaClass2023Returns, dca.dcaClass2023Stack], - [2024, "fuchsia", true, dca.dcaClass2024AvgPrice, dca.dcaClass2024Returns, dca.dcaClass2024Stack], - [2025, "pink", true, dca.dcaClass2025AvgPrice, dca.dcaClass2025Returns, dca.dcaClass2025Stack], - ]).map(([year, colorKey, defaultActive, avgPrice, returns, stack]) => ({ - year, - color: colors[colorKey], - defaultActive, - avgPrice, - returns, - stack, - })); -} - -/** - * Create Market section - * @param {PartialContext} ctx - * @returns {PartialOptionsGroup} - */ -export function createMarketSection(ctx) { - const { colors, brk, s, createPriceLine } = ctx; - const { market, supply } = brk.tree.computed; - const { movingAverage, ath, returns, volatility, range, dca, lookback } = market; - - const averages = buildAverages(colors, movingAverage); - const dcaClasses = buildDcaClasses(colors, dca); - - return { - name: "Market", - tree: [ - // Price (empty chart, shows candlesticks by default) - { - name: "Price", - title: "Bitcoin Price", - }, - - // Capitalization - { - name: "Capitalization", - title: "Market Capitalization", - bottom: [s({ metric: supply.marketCap.indexes, name: "Capitalization", unit: "usd" })], - }, - - // All Time High - { - name: "All Time High", - title: "All Time High", - top: [s({ metric: ath.priceAth, name: "ath", unit: "usd" })], - bottom: [ - s({ metric: ath.priceDrawdown, name: "Drawdown", color: colors.red, unit: "percentage" }), - s({ metric: ath.daysSincePriceAth, name: "since", unit: "days" }), - s({ metric: ath.maxDaysBetweenPriceAths, name: "Max", color: colors.red, unit: "days" }), - s({ metric: ath.maxYearsBetweenPriceAths, name: "Max", color: colors.red, unit: "years" }), - ], - }, - - // Averages - { - name: "Averages", - tree: [ - { nameAddon: "Simple", metricAddon: /** @type {const} */ ("sma") }, - { nameAddon: "Exponential", metricAddon: /** @type {const} */ ("ema") }, - ].map(({ nameAddon, metricAddon }) => ({ - name: nameAddon, - tree: [ - { - name: "Compare", - title: `Market Price ${nameAddon} Moving Averages`, - top: averages.map(({ id, color, sma, ema }) => - s({ - metric: (metricAddon === "sma" ? sma : ema).price, - name: id, - color, - unit: "usd", - }), - ), - }, - ...averages.map(({ name, color, sma, ema }) => ({ - name, - tree: createPriceWithRatioOptions(ctx, { - ratio: metricAddon === "sma" ? sma : ema, - name, - title: `${name} Market Price ${nameAddon} Moving Average`, - legend: "average", - color, - }), - })), - ], - })), - }, - - // Performance - { - name: "Performance", - tree: /** @type {const} */ ([ - ["1d", returns._1dPriceReturns, undefined], - ["1w", returns._1wPriceReturns, undefined], - ["1m", returns._1mPriceReturns, undefined], - ["3m", returns._3mPriceReturns, undefined], - ["6m", returns._6mPriceReturns, undefined], - ["1y", returns._1yPriceReturns, undefined], - ["2y", returns._2yPriceReturns, returns._2yCagr], - ["3y", returns._3yPriceReturns, returns._3yCagr], - ["4y", returns._4yPriceReturns, returns._4yCagr], - ["5y", returns._5yPriceReturns, returns._5yCagr], - ["6y", returns._6yPriceReturns, returns._6yCagr], - ["8y", returns._8yPriceReturns, returns._8yCagr], - ["10y", returns._10yPriceReturns, returns._10yCagr], - ]).map(([id, priceReturns, cagr]) => { - const name = periodIdToName(id, true); - return { - name, - title: `${name} Performance`, - bottom: [ - /** @type {AnyFetchedSeriesBlueprint} */ ({ - metric: priceReturns, - title: "total", - type: "Baseline", - unit: "percentage", - }), - ...(cagr - ? [ - /** @type {AnyFetchedSeriesBlueprint} */ ({ - metric: cagr, - title: "cagr", - type: "Baseline", - colors: [colors.lime, colors.pink], - unit: "percentage", - }), - ] - : []), - createPriceLine({ unit: "percentage" }), - ], - }; - }), - }, - - // Indicators - { - name: "Indicators", - tree: [ - // Volatility - { - name: "Volatility", - title: "Bitcoin Price Volatility Index", - bottom: [ - s({ metric: volatility.price1wVolatility, name: "1w", color: colors.red, unit: "percentage" }), - s({ metric: volatility.price1mVolatility, name: "1m", color: colors.orange, unit: "percentage" }), - s({ metric: volatility.price1yVolatility, name: "1y", color: colors.lime, unit: "percentage" }), - ], - }, - - // MinMax - { - name: "MinMax", - tree: [ - { id: "1w", title: "1 Week", min: range.price1wMin, max: range.price1wMax }, - { id: "2w", title: "2 Week", min: range.price2wMin, max: range.price2wMax }, - { id: "1m", title: "1 Month", min: range.price1mMin, max: range.price1mMax }, - { id: "1y", title: "1 Year", min: range.price1yMin, max: range.price1yMax }, - ].map(({ id, title, min, max }) => ({ - name: id, - title: `Bitcoin Price ${title} MinMax Bands`, - top: [ - s({ metric: min, name: "min", color: colors.red, unit: "usd" }), - s({ metric: max, name: "max", color: colors.green, unit: "usd" }), - ], - })), - }, - - // True range - { - name: "True range", - title: "Bitcoin Price True Range", - bottom: [s({ metric: range.priceTrueRange, name: "value", color: colors.yellow, unit: "usd" })], - }, - - // Choppiness - { - name: "Choppiness", - title: "Bitcoin Price Choppiness Index", - bottom: [ - s({ metric: range.price2wChoppinessIndex, name: "2w", color: colors.red, unit: "index" }), - createPriceLine({ unit: "index", number: 61.8 }), - createPriceLine({ unit: "index", number: 38.2 }), - ], - }, - - // Mayer multiple - { - name: "Mayer multiple", - title: "Mayer multiple", - top: [ - s({ metric: movingAverage.price200dSma.price, name: "200d sma", color: colors.yellow, unit: "usd" }), - s({ metric: movingAverage.price200dSmaX24, name: "200d sma x2.4", color: colors.green, unit: "usd" }), - s({ metric: movingAverage.price200dSmaX08, name: "200d sma x0.8", color: colors.red, unit: "usd" }), - ], - }, - ], - }, - - // Investing - { - name: "Investing", - tree: [ - // DCA vs Lump sum - { - name: "DCA vs Lump sum", - tree: [ - .../** @type {const} */ ([ - ["1w", dca._1wDcaAvgPrice, lookback.price1wAgo, dca._1wDcaReturns, returns._1wPriceReturns], - ["1m", dca._1mDcaAvgPrice, lookback.price1mAgo, dca._1mDcaReturns, returns._1mPriceReturns], - ["3m", dca._3mDcaAvgPrice, lookback.price3mAgo, dca._3mDcaReturns, returns._3mPriceReturns], - ["6m", dca._6mDcaAvgPrice, lookback.price6mAgo, dca._6mDcaReturns, returns._6mPriceReturns], - ["1y", dca._1yDcaAvgPrice, lookback.price1yAgo, dca._1yDcaReturns, returns._1yPriceReturns], - ]).map(([id, dcaAvgPrice, priceAgo, dcaReturns, priceReturns]) => { - const name = periodIdToName(id, true); - return { - name, - tree: [ - { - name: "price", - title: `${name} DCA vs Lump Sum (Price)`, - top: [ - s({ metric: dcaAvgPrice, name: "DCA avg", color: colors.green, unit: "usd" }), - s({ metric: priceAgo, name: "Lump sum", color: colors.orange, unit: "usd" }), - ], - }, - { - name: "returns", - title: `${name} DCA vs Lump Sum (Returns)`, - bottom: [ - /** @type {AnyFetchedSeriesBlueprint} */ ({ - metric: dcaReturns, - title: "DCA", - type: "Baseline", - unit: "percentage", - }), - /** @type {AnyFetchedSeriesBlueprint} */ ({ - metric: priceReturns, - title: "Lump sum", - type: "Baseline", - colors: [colors.lime, colors.red], - unit: "percentage", - }), - createPriceLine({ unit: "percentage" }), - ], - }, - ], - }; - }), - ], - }, - - // DCA classes - { - name: "DCA classes", - tree: [ - { - name: "Average price", - title: "DCA Average Price by Year", - top: dcaClasses.map(({ year, color, defaultActive, avgPrice }) => - s({ metric: avgPrice, name: `${year}`, color, defaultActive, unit: "usd" }), - ), - }, - { - name: "Returns", - title: "DCA Returns by Year", - bottom: dcaClasses.map(({ year, color, defaultActive, returns }) => - /** @type {AnyFetchedSeriesBlueprint} */ ({ - metric: returns, - title: `${year}`, - type: "Baseline", - color, - defaultActive, - unit: "percentage", - }), - ), - }, - { - name: "Stack", - title: "DCA Stack by Year", - bottom: dcaClasses.map(({ year, color, defaultActive, stack }) => - s({ metric: stack, name: `${year}`, color, defaultActive, unit: "sats" }), - ), - }, - ], - }, - ], - }, - ], - }; -} diff --git a/websites/bitview/scripts/options/partial/market/averages.js b/websites/bitview/scripts/options/partial/market/averages.js new file mode 100644 index 000000000..b640f4a80 --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/averages.js @@ -0,0 +1,179 @@ +/** Moving averages section */ + +import { periodIdToName } from "./utils.js"; + +/** + * Build averages data array from market patterns + * @param {Colors} colors + * @param {MarketMovingAverage} ma + */ +export function buildAverages(colors, ma) { + return /** @type {const} */ ([ + ["1w", 7, "red", ma.price1wSma, ma.price1wEma], + ["8d", 8, "orange", ma.price8dSma, ma.price8dEma], + ["13d", 13, "amber", ma.price13dSma, ma.price13dEma], + ["21d", 21, "yellow", ma.price21dSma, ma.price21dEma], + ["1m", 30, "lime", ma.price1mSma, ma.price1mEma], + ["34d", 34, "green", ma.price34dSma, ma.price34dEma], + ["55d", 55, "emerald", ma.price55dSma, ma.price55dEma], + ["89d", 89, "teal", ma.price89dSma, ma.price89dEma], + ["144d", 144, "cyan", ma.price144dSma, ma.price144dEma], + ["200d", 200, "sky", ma.price200dSma, ma.price200dEma], + ["1y", 365, "blue", ma.price1ySma, ma.price1yEma], + ["2y", 730, "indigo", ma.price2ySma, ma.price2yEma], + ["200w", 1400, "violet", ma.price200wSma, ma.price200wEma], + ["4y", 1460, "purple", ma.price4ySma, ma.price4yEma], + ]).map(([id, days, colorKey, sma, ema]) => ({ + id, + name: periodIdToName(id, true), + days, + color: colors[colorKey], + sma, + ema, + })); +} + +/** + * Create price with ratio options (for moving averages) + * @param {PartialContext} ctx + * @param {Object} args + * @param {string} args.title + * @param {string} args.legend + * @param {EmaRatioPattern} args.ratio + * @param {Color} [args.color] + * @returns {PartialOptionsTree} + */ +export function createPriceWithRatioOptions(ctx, { title, legend, ratio, color }) { + const { s, colors, createPriceLine } = ctx; + const priceMetric = ratio.price; + + const percentileUsdMap = [ + { name: "pct99", prop: ratio.ratioPct99Usd, color: colors.rose }, + { name: "pct98", prop: ratio.ratioPct98Usd, color: colors.pink }, + { name: "pct95", prop: ratio.ratioPct95Usd, color: colors.fuchsia }, + { name: "pct5", prop: ratio.ratioPct5Usd, color: colors.cyan }, + { name: "pct2", prop: ratio.ratioPct2Usd, color: colors.sky }, + { name: "pct1", prop: ratio.ratioPct1Usd, color: colors.blue }, + ]; + + const percentileMap = [ + { name: "pct99", prop: ratio.ratioPct99, color: colors.rose }, + { name: "pct98", prop: ratio.ratioPct98, color: colors.pink }, + { name: "pct95", prop: ratio.ratioPct95, color: colors.fuchsia }, + { name: "pct5", prop: ratio.ratioPct5, color: colors.cyan }, + { name: "pct2", prop: ratio.ratioPct2, color: colors.sky }, + { name: "pct1", prop: ratio.ratioPct1, color: colors.blue }, + ]; + + const sdPatterns = [ + { nameAddon: "all", titleAddon: "", sd: ratio.ratioSd }, + { nameAddon: "4y", titleAddon: "4y", sd: ratio.ratio4ySd }, + { nameAddon: "2y", titleAddon: "2y", sd: ratio.ratio2ySd }, + { nameAddon: "1y", titleAddon: "1y", sd: ratio.ratio1ySd }, + ]; + + /** @param {Ratio1ySdPattern} sd */ + const getSdBands = (sd) => [ + { name: "0σ", prop: sd._0sdUsd, color: colors.lime }, + { name: "+0.5σ", prop: sd.p05sdUsd, color: colors.yellow }, + { name: "+1σ", prop: sd.p1sdUsd, color: colors.amber }, + { name: "+1.5σ", prop: sd.p15sdUsd, color: colors.orange }, + { name: "+2σ", prop: sd.p2sdUsd, color: colors.red }, + { name: "+2.5σ", prop: sd.p25sdUsd, color: colors.rose }, + { name: "+3σ", prop: sd.p3sd, color: colors.pink }, + { name: "−0.5σ", prop: sd.m05sdUsd, color: colors.teal }, + { name: "−1σ", prop: sd.m1sdUsd, color: colors.cyan }, + { name: "−1.5σ", prop: sd.m15sdUsd, color: colors.sky }, + { name: "−2σ", prop: sd.m2sdUsd, color: colors.blue }, + { name: "−2.5σ", prop: sd.m25sdUsd, color: colors.indigo }, + { name: "−3σ", prop: sd.m3sd, color: colors.violet }, + ]; + + return [ + { + name: "price", + title, + top: [s({ metric: priceMetric, name: legend, color, unit: "usd" })], + }, + { + name: "Ratio", + title: `${title} Ratio`, + top: [ + s({ metric: priceMetric, name: legend, color, unit: "usd" }), + ...percentileUsdMap.map(({ name: pctName, prop, color: pctColor }) => + s({ metric: prop, name: pctName, color: pctColor, defaultActive: false, unit: "usd", options: { lineStyle: 1 } }), + ), + ], + bottom: [ + s({ metric: ratio.ratio, name: "ratio", color, unit: "ratio" }), + s({ metric: ratio.ratio1wSma, name: "1w sma", color: colors.lime, unit: "ratio" }), + s({ metric: ratio.ratio1mSma, name: "1m sma", color: colors.teal, unit: "ratio" }), + s({ metric: ratio.ratio1ySd.sma, name: "1y sma", color: colors.sky, unit: "ratio" }), + s({ metric: ratio.ratio2ySd.sma, name: "2y sma", color: colors.indigo, unit: "ratio" }), + s({ metric: ratio.ratio4ySd.sma, name: "4y sma", color: colors.purple, unit: "ratio" }), + s({ metric: ratio.ratioSd.sma, name: "all sma", color: colors.rose, unit: "ratio" }), + ...percentileMap.map(({ name: pctName, prop, color: pctColor }) => + s({ metric: prop, name: pctName, color: pctColor, defaultActive: false, unit: "ratio", options: { lineStyle: 1 } }), + ), + createPriceLine({ unit: "ratio", number: 1 }), + ], + }, + { + name: "ZScores", + tree: sdPatterns.map(({ nameAddon, titleAddon, sd }) => ({ + name: nameAddon, + title: `${title} ${titleAddon} Z-Score`, + top: getSdBands(sd).map(({ name: bandName, prop, color: bandColor }) => + s({ metric: prop, name: bandName, color: bandColor, unit: "usd" }), + ), + bottom: [ + s({ metric: sd.zscore, name: "zscore", color, unit: "sd" }), + createPriceLine({ unit: "sd", number: 3 }), + createPriceLine({ unit: "sd", number: 2 }), + createPriceLine({ unit: "sd", number: 1 }), + createPriceLine({ unit: "sd", number: 0 }), + createPriceLine({ unit: "sd", number: -1 }), + createPriceLine({ unit: "sd", number: -2 }), + createPriceLine({ unit: "sd", number: -3 }), + ], + })), + }, + ]; +} + +/** + * Create Averages section + * @param {PartialContext} ctx + * @param {ReturnType} averages + */ +export function createAveragesSection(ctx, averages) { + const { s } = ctx; + + return { + name: "Averages", + tree: [ + { nameAddon: "Simple", metricAddon: /** @type {const} */ ("sma") }, + { nameAddon: "Exponential", metricAddon: /** @type {const} */ ("ema") }, + ].map(({ nameAddon, metricAddon }) => ({ + name: nameAddon, + tree: [ + { + name: "Compare", + title: `Market Price ${nameAddon} Moving Averages`, + top: averages.map(({ id, color, sma, ema }) => + s({ metric: (metricAddon === "sma" ? sma : ema).price, name: id, color, unit: "usd" }), + ), + }, + ...averages.map(({ name, color, sma, ema }) => ({ + name, + tree: createPriceWithRatioOptions(ctx, { + ratio: metricAddon === "sma" ? sma : ema, + title: `${name} Market Price ${nameAddon} Moving Average`, + legend: "average", + color, + }), + })), + ], + })), + }; +} diff --git a/websites/bitview/scripts/options/partial/market/index.js b/websites/bitview/scripts/options/partial/market/index.js new file mode 100644 index 000000000..403ecc84b --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/index.js @@ -0,0 +1,62 @@ +/** Market section - Main entry point */ + +import { buildAverages, createAveragesSection } from "./averages.js"; +import { createPerformanceSection } from "./performance.js"; +import { createIndicatorsSection } from "./indicators/index.js"; +import { createInvestingSection } from "./investing.js"; + +/** + * Create Market section + * @param {PartialContext} ctx + * @returns {PartialOptionsGroup} + */ +export function createMarketSection(ctx) { + const { colors, brk, s } = ctx; + const { market, supply } = brk.tree.computed; + const { movingAverage, ath, returns, volatility, range, dca, lookback, indicators } = market; + + const averages = buildAverages(colors, movingAverage); + + return { + name: "Market", + tree: [ + // Price + { + name: "Price", + title: "Bitcoin Price", + }, + + // Capitalization + { + name: "Capitalization", + title: "Market Capitalization", + bottom: [s({ metric: supply.marketCap.indexes, name: "Capitalization", unit: "usd" })], + }, + + // All Time High + { + name: "All Time High", + title: "All Time High", + top: [s({ metric: ath.priceAth, name: "ath", unit: "usd" })], + bottom: [ + s({ metric: ath.priceDrawdown, name: "Drawdown", color: colors.red, unit: "percentage" }), + s({ metric: ath.daysSincePriceAth, name: "since", unit: "days" }), + s({ metric: ath.maxDaysBetweenPriceAths, name: "Max", color: colors.red, unit: "days" }), + s({ metric: ath.maxYearsBetweenPriceAths, name: "Max", color: colors.red, unit: "years" }), + ], + }, + + // Averages + createAveragesSection(ctx, averages), + + // Performance + createPerformanceSection(ctx, returns), + + // Indicators + createIndicatorsSection(ctx, { volatility, range, movingAverage, indicators }), + + // Investing + createInvestingSection(ctx, { dca, lookback, returns }), + ], + }; +} diff --git a/websites/bitview/scripts/options/partial/market/indicators/bands.js b/websites/bitview/scripts/options/partial/market/indicators/bands.js new file mode 100644 index 000000000..cde5d3331 --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/indicators/bands.js @@ -0,0 +1,43 @@ +/** Bands indicators (MinMax, Mayer Multiple) */ + +/** + * Create Bands section + * @param {PartialContext} ctx + * @param {Object} args + * @param {Market["range"]} args.range + * @param {Market["movingAverage"]} args.movingAverage + */ +export function createBandsSection(ctx, { range, movingAverage }) { + const { s, colors } = ctx; + + return { + name: "Bands", + tree: [ + { + name: "MinMax", + tree: [ + { id: "1w", title: "1 Week", min: range.price1wMin, max: range.price1wMax }, + { id: "2w", title: "2 Week", min: range.price2wMin, max: range.price2wMax }, + { id: "1m", title: "1 Month", min: range.price1mMin, max: range.price1mMax }, + { id: "1y", title: "1 Year", min: range.price1yMin, max: range.price1yMax }, + ].map(({ id, title, min, max }) => ({ + name: id, + title: `Bitcoin Price ${title} MinMax Bands`, + top: [ + s({ metric: min, name: "min", color: colors.red, unit: "usd" }), + s({ metric: max, name: "max", color: colors.green, unit: "usd" }), + ], + })), + }, + { + name: "Mayer Multiple", + title: "Mayer Multiple", + top: [ + s({ metric: movingAverage.price200dSma.price, name: "200d sma", color: colors.yellow, unit: "usd" }), + s({ metric: movingAverage.price200dSmaX24, name: "200d sma x2.4", color: colors.green, unit: "usd" }), + s({ metric: movingAverage.price200dSmaX08, name: "200d sma x0.8", color: colors.red, unit: "usd" }), + ], + }, + ], + }; +} diff --git a/websites/bitview/scripts/options/partial/market/indicators/index.js b/websites/bitview/scripts/options/partial/market/indicators/index.js new file mode 100644 index 000000000..ddf7a06bf --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/indicators/index.js @@ -0,0 +1,27 @@ +/** Indicators section - Main entry point */ + +import { createMomentumSection } from "./momentum.js"; +import { createVolatilitySection } from "./volatility.js"; +import { createBandsSection } from "./bands.js"; +import { createOnchainSection } from "./onchain.js"; + +/** + * Create Indicators section + * @param {PartialContext} ctx + * @param {Object} args + * @param {Market["volatility"]} args.volatility + * @param {Market["range"]} args.range + * @param {Market["movingAverage"]} args.movingAverage + * @param {Market["indicators"]} args.indicators + */ +export function createIndicatorsSection(ctx, { volatility, range, movingAverage, indicators }) { + return { + name: "Indicators", + tree: [ + createMomentumSection(ctx, indicators), + createVolatilitySection(ctx, { volatility, range }), + createBandsSection(ctx, { range, movingAverage }), + createOnchainSection(ctx, { indicators, movingAverage }), + ], + }; +} diff --git a/websites/bitview/scripts/options/partial/market/indicators/momentum.js b/websites/bitview/scripts/options/partial/market/indicators/momentum.js new file mode 100644 index 000000000..c96f03208 --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/indicators/momentum.js @@ -0,0 +1,106 @@ +/** Momentum indicators (RSI, StochRSI, Stochastic, MACD) */ + +/** + * Create Momentum section + * @param {PartialContext} ctx + * @param {Market["indicators"]} indicators + */ +export function createMomentumSection(ctx, indicators) { + const { s, colors, createPriceLine } = ctx; + + return { + name: "Momentum", + tree: [ + { + name: "RSI", + title: "Relative Strength Index (14d)", + bottom: [ + s({ + metric: indicators.rsi14d, + name: "RSI", + color: colors.indigo, + unit: "index", + }), + s({ + metric: indicators.rsi14dMin, + name: "Min", + color: colors.red, + defaultActive: false, + unit: "index", + }), + s({ + metric: indicators.rsi14dMax, + name: "Max", + color: colors.green, + defaultActive: false, + unit: "index", + }), + createPriceLine({ unit: "index", number: 70 }), + createPriceLine({ unit: "index", number: 50, defaultActive: false }), + createPriceLine({ unit: "index", number: 30 }), + ], + }, + { + name: "StochRSI", + title: "Stochastic RSI", + bottom: [ + // s({ + // metric: indicators.stochRsi, + // name: "Stoch RSI", + // color: colors.purple, + // unit: "index", + // }), + s({ + metric: indicators.stochRsiK, + name: "K", + color: colors.blue, + unit: "index", + }), + s({ + metric: indicators.stochRsiD, + name: "D", + color: colors.orange, + unit: "index", + }), + createPriceLine({ unit: "index", number: 80 }), + createPriceLine({ unit: "index", number: 20 }), + ], + }, + // { + // name: "Stochastic", + // title: "Stochastic Oscillator", + // bottom: [ + // s({ metric: indicators.stochK, name: "K", color: colors.blue, unit: "index" }), + // s({ metric: indicators.stochD, name: "D", color: colors.orange, unit: "index" }), + // createPriceLine({ unit: "index", number: 80 }), + // createPriceLine({ unit: "index", number: 20 }), + // ], + // }, + { + name: "MACD", + title: "Moving Average Convergence Divergence", + bottom: [ + s({ + metric: indicators.macdLine, + name: "MACD", + color: colors.blue, + unit: "usd", + }), + s({ + metric: indicators.macdSignal, + name: "Signal", + color: colors.orange, + unit: "usd", + }), + /** @type {FetchedHistogramSeriesBlueprint} */ ({ + metric: indicators.macdHistogram, + title: "Histogram", + type: "Histogram", + unit: "usd", + }), + createPriceLine({ unit: "usd" }), + ], + }, + ], + }; +} diff --git a/websites/bitview/scripts/options/partial/market/indicators/onchain.js b/websites/bitview/scripts/options/partial/market/indicators/onchain.js new file mode 100644 index 000000000..eda97cae4 --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/indicators/onchain.js @@ -0,0 +1,81 @@ +/** On-chain indicators (Pi Cycle, Puell, NVT, Gini) */ + +/** + * Create On-chain section + * @param {PartialContext} ctx + * @param {Object} args + * @param {Market["indicators"]} args.indicators + * @param {Market["movingAverage"]} args.movingAverage + */ +export function createOnchainSection(ctx, { indicators, movingAverage }) { + const { s, colors, createPriceLine } = ctx; + + return { + name: "On-chain", + tree: [ + { + name: "Pi Cycle", + title: "Pi Cycle Top Indicator", + top: [ + s({ + metric: movingAverage.price111dSma.price, + name: "111d SMA", + color: colors.green, + unit: "usd", + }), + s({ + metric: movingAverage.price350dSmaX2, + name: "350d SMA x2", + color: colors.red, + unit: "usd", + }), + ], + bottom: [ + s({ + metric: indicators.piCycle, + name: "Pi Cycle", + color: colors.purple, + unit: "ratio", + }), + createPriceLine({ unit: "ratio", number: 1 }), + ], + }, + { + name: "Puell Multiple", + title: "Puell Multiple", + bottom: [ + s({ + metric: indicators.puellMultiple, + name: "Puell", + color: colors.green, + unit: "ratio", + }), + ], + }, + { + name: "NVT", + title: "Network Value to Transactions Ratio", + bottom: [ + s({ + metric: indicators.nvt, + name: "NVT", + color: colors.orange, + unit: "ratio", + }), + ], + }, + { + name: "Gini", + title: "Gini Coefficient", + bottom: [ + s({ + metric: indicators.gini, + name: "Gini", + color: colors.red, + unit: "ratio", + }), + ], + }, + ], + }; +} diff --git a/websites/bitview/scripts/options/partial/market/indicators/volatility.js b/websites/bitview/scripts/options/partial/market/indicators/volatility.js new file mode 100644 index 000000000..89574c83e --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/indicators/volatility.js @@ -0,0 +1,61 @@ +/** Volatility indicators (Index, True Range, Choppiness, Sharpe, Sortino) */ + +/** + * Create Volatility section + * @param {PartialContext} ctx + * @param {Object} args + * @param {Market["volatility"]} args.volatility + * @param {Market["range"]} args.range + */ +export function createVolatilitySection(ctx, { volatility, range }) { + const { s, colors, createPriceLine } = ctx; + + return { + name: "Volatility", + tree: [ + { + name: "Index", + title: "Bitcoin Price Volatility Index", + bottom: [ + s({ metric: volatility.price1wVolatility, name: "1w", color: colors.red, unit: "percentage" }), + s({ metric: volatility.price1mVolatility, name: "1m", color: colors.orange, unit: "percentage" }), + s({ metric: volatility.price1yVolatility, name: "1y", color: colors.lime, unit: "percentage" }), + ], + }, + { + name: "True Range", + title: "Bitcoin Price True Range", + bottom: [s({ metric: range.priceTrueRange, name: "value", color: colors.yellow, unit: "usd" })], + }, + { + name: "Choppiness", + title: "Bitcoin Price Choppiness Index", + bottom: [ + s({ metric: range.price2wChoppinessIndex, name: "2w", color: colors.red, unit: "index" }), + createPriceLine({ unit: "index", number: 61.8 }), + createPriceLine({ unit: "index", number: 38.2 }), + ], + }, + { + name: "Sharpe Ratio", + title: "Sharpe Ratio", + bottom: [ + s({ metric: volatility.sharpe1w, name: "1w", color: colors.red, unit: "ratio" }), + s({ metric: volatility.sharpe1m, name: "1m", color: colors.orange, unit: "ratio" }), + s({ metric: volatility.sharpe1y, name: "1y", color: colors.lime, unit: "ratio" }), + createPriceLine({ unit: "ratio" }), + ], + }, + { + name: "Sortino Ratio", + title: "Sortino Ratio", + bottom: [ + s({ metric: volatility.sortino1w, name: "1w", color: colors.red, unit: "ratio" }), + s({ metric: volatility.sortino1m, name: "1m", color: colors.orange, unit: "ratio" }), + s({ metric: volatility.sortino1y, name: "1y", color: colors.lime, unit: "ratio" }), + createPriceLine({ unit: "ratio" }), + ], + }, + ], + }; +} diff --git a/websites/bitview/scripts/options/partial/market/investing.js b/websites/bitview/scripts/options/partial/market/investing.js new file mode 100644 index 000000000..ef64b551d --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/investing.js @@ -0,0 +1,197 @@ +/** Investing section (DCA) */ + +import { periodIdToName } from "./utils.js"; + +/** + * Build DCA classes data array + * @param {Colors} colors + * @param {MarketDca} dca + */ +export function buildDcaClasses(colors, dca) { + return /** @type {const} */ ([ + [2025, "pink", true], + [2024, "fuchsia", true], + [2023, "purple", true], + [2022, "blue", true], + [2021, "sky", true], + [2020, "teal", true], + [2019, "green", true], + [2018, "yellow", true], + [2017, "orange", true], + [2016, "red", false], + [2015, "pink", false], + ]).map(([year, colorKey, defaultActive]) => ({ + year, + color: colors[colorKey], + defaultActive, + costBasis: dca.classAvgPrice[`_${year}`], + returns: dca.classReturns[`_${year}`], + stack: dca.classStack[`_${year}`], + })); +} + +/** + * Create Investing section + * @param {PartialContext} ctx + * @param {Object} args + * @param {Market["dca"]} args.dca + * @param {Market["lookback"]} args.lookback + * @param {Market["returns"]} args.returns + */ +export function createInvestingSection(ctx, { dca, lookback, returns }) { + const { s, colors, createPriceLine } = ctx; + const dcaClasses = buildDcaClasses(colors, dca); + + return { + name: "Investing", + tree: [ + // DCA vs Lump sum + { + name: "DCA vs Lump sum", + tree: /** @type {const} */ ([ + ["1w", "_1w"], + ["1m", "_1m"], + ["3m", "_3m"], + ["6m", "_6m"], + ["1y", "_1y"], + ["2y", "_2y"], + ["3y", "_3y"], + ["4y", "_4y"], + ["5y", "_5y"], + ["6y", "_6y"], + ["8y", "_8y"], + ["10y", "_10y"], + ]).map(([id, key]) => { + const name = periodIdToName(id, true); + const priceAgo = lookback.priceAgo[key]; + const priceReturns = returns.priceReturns[key]; + const dcaCostBasis = dca.periodAvgPrice[key]; + const dcaReturns = dca.periodReturns[key]; + const dcaStack = dca.periodStack[key]; + const lumpSumStack = dca.periodLumpSumStack[key]; + return { + name, + tree: [ + { + name: "Cost basis", + title: `${name} DCA vs Lump Sum (Cost Basis)`, + top: [ + s({ metric: dcaCostBasis, name: "DCA", color: colors.green, unit: "usd" }), + s({ metric: priceAgo, name: "Lump sum", color: colors.orange, unit: "usd" }), + ], + }, + { + name: "Returns", + title: `${name} DCA vs Lump Sum (Returns)`, + bottom: [ + /** @type {AnyFetchedSeriesBlueprint} */ ({ + metric: dcaReturns, + title: "DCA", + type: "Baseline", + unit: "percentage", + }), + /** @type {AnyFetchedSeriesBlueprint} */ ({ + metric: priceReturns, + title: "Lump sum", + type: "Baseline", + colors: [colors.lime, colors.red], + unit: "percentage", + }), + createPriceLine({ unit: "percentage" }), + ], + }, + { + name: "Stack", + title: `${name} DCA vs Lump Sum Stack ($100/day)`, + bottom: [ + s({ metric: dcaStack.sats, name: "DCA", color: colors.green, unit: "sats" }), + s({ metric: dcaStack.bitcoin, name: "DCA", color: colors.green, unit: "btc" }), + s({ metric: dcaStack.dollars, name: "DCA", color: colors.green, unit: "usd" }), + s({ metric: lumpSumStack.sats, name: "Lump sum", color: colors.orange, unit: "sats" }), + s({ metric: lumpSumStack.bitcoin, name: "Lump sum", color: colors.orange, unit: "btc" }), + s({ metric: lumpSumStack.dollars, name: "Lump sum", color: colors.orange, unit: "usd" }), + ], + }, + ], + }; + }), + }, + + // DCA classes + { + name: "DCA classes", + tree: [ + // Comparison charts (all years overlaid) + { + name: "Compare", + tree: [ + { + name: "Cost basis", + title: "DCA Cost Basis by Year", + top: dcaClasses.map(({ year, color, defaultActive, costBasis }) => + s({ metric: costBasis, name: `${year}`, color, defaultActive, unit: "usd" }), + ), + }, + { + name: "Returns", + title: "DCA Returns by Year", + bottom: dcaClasses.map(({ year, color, defaultActive, returns }) => + /** @type {AnyFetchedSeriesBlueprint} */ ({ + metric: returns, + title: `${year}`, + type: "Baseline", + color, + defaultActive, + unit: "percentage", + }), + ), + }, + { + name: "Stack", + title: "DCA Stack by Year ($100/day)", + bottom: dcaClasses.flatMap(({ year, color, defaultActive, stack }) => [ + s({ metric: stack.sats, name: `${year}`, color, defaultActive, unit: "sats" }), + s({ metric: stack.bitcoin, name: `${year}`, color, defaultActive, unit: "btc" }), + s({ metric: stack.dollars, name: `${year}`, color, defaultActive, unit: "usd" }), + ]), + }, + ], + }, + // Individual year charts + ...dcaClasses.map(({ year, color, costBasis, returns, stack }) => ({ + name: `${year}`, + tree: [ + { + name: "Cost basis", + title: `DCA Class ${year} Cost Basis`, + top: [s({ metric: costBasis, name: "Cost basis", color, unit: "usd" })], + }, + { + name: "Returns", + title: `DCA Class ${year} Returns`, + bottom: [ + /** @type {AnyFetchedSeriesBlueprint} */ ({ + metric: returns, + title: "Returns", + type: "Baseline", + color, + unit: "percentage", + }), + ], + }, + { + name: "Stack", + title: `DCA Class ${year} Stack ($100/day)`, + bottom: [ + s({ metric: stack.sats, name: "Stack", color, unit: "sats" }), + s({ metric: stack.bitcoin, name: "Stack", color, unit: "btc" }), + s({ metric: stack.dollars, name: "Stack", color, unit: "usd" }), + ], + }, + ], + })), + ], + }, + ], + }; +} diff --git a/websites/bitview/scripts/options/partial/market/performance.js b/websites/bitview/scripts/options/partial/market/performance.js new file mode 100644 index 000000000..8713da05b --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/performance.js @@ -0,0 +1,59 @@ +/** Performance section */ + +import { periodIdToName } from "./utils.js"; + +/** + * Create Performance section + * @param {PartialContext} ctx + * @param {Market["returns"]} returns + */ +export function createPerformanceSection(ctx, returns) { + const { colors, createPriceLine } = ctx; + + return { + name: "Performance", + tree: /** @type {const} */ ([ + ["1d", "_1d", undefined], + ["1w", "_1w", undefined], + ["1m", "_1m", undefined], + ["3m", "_3m", undefined], + ["6m", "_6m", undefined], + ["1y", "_1y", undefined], + ["2y", "_2y", "_2y"], + ["3y", "_3y", "_3y"], + ["4y", "_4y", "_4y"], + ["5y", "_5y", "_5y"], + ["6y", "_6y", "_6y"], + ["8y", "_8y", "_8y"], + ["10y", "_10y", "_10y"], + ]).map(([id, returnKey, cagrKey]) => { + const priceReturns = returns.priceReturns[returnKey]; + const cagr = cagrKey ? returns.cagr[cagrKey] : undefined; + const name = periodIdToName(id, true); + return { + name, + title: `${name} Performance`, + bottom: [ + /** @type {AnyFetchedSeriesBlueprint} */ ({ + metric: priceReturns, + title: "total", + type: "Baseline", + unit: "percentage", + }), + ...(cagr + ? [ + /** @type {AnyFetchedSeriesBlueprint} */ ({ + metric: cagr, + title: "cagr", + type: "Baseline", + colors: [colors.lime, colors.pink], + unit: "percentage", + }), + ] + : []), + createPriceLine({ unit: "percentage" }), + ], + }; + }), + }; +} diff --git a/websites/bitview/scripts/options/partial/market/utils.js b/websites/bitview/scripts/options/partial/market/utils.js new file mode 100644 index 000000000..936173d85 --- /dev/null +++ b/websites/bitview/scripts/options/partial/market/utils.js @@ -0,0 +1,23 @@ +/** Market utilities */ + +/** + * Convert period ID to readable name + * @param {string} id + * @param {boolean} [compoundAdjective] + */ +export function periodIdToName(id, compoundAdjective) { + const num = parseInt(id); + const s = compoundAdjective || num === 1 ? "" : "s"; + switch (id.slice(-1)) { + case "d": + return `${num} day${s}`; + case "w": + return `${num} week${s}`; + case "m": + return `${num} month${s}`; + case "y": + return `${num} year${s}`; + default: + return id; + } +} diff --git a/websites/bitview/scripts/options/partial/series.js b/websites/bitview/scripts/options/partial/series.js index 93e1e8cc4..8ea73f51d 100644 --- a/websites/bitview/scripts/options/partial/series.js +++ b/websites/bitview/scripts/options/partial/series.js @@ -3,7 +3,7 @@ /** * Create a single series from a tree accessor * @param {Object} args - * @param {MetricAccessor} args.metric - Tree accessor with .by property + * @param {AnyMetricPattern} args.metric - Tree accessor with .by property * @param {string} args.name - Display name for the series * @param {Color} [args.color] * @param {Unit} [args.unit] diff --git a/websites/bitview/scripts/options/partial/types.js b/websites/bitview/scripts/options/partial/types.js index 53abb8c59..9a3dd1e68 100644 --- a/websites/bitview/scripts/options/partial/types.js +++ b/websites/bitview/scripts/options/partial/types.js @@ -27,7 +27,7 @@ * * @typedef {Object} HistogramSeriesBlueprintSpecific * @property {"Histogram"} type - * @property {Color} color + * @property {Color | [Color, Color]} [color] - Single color or [positive, negative] colors (defaults to green/red) * @property {HistogramSeriesPartialOptions} [options] * @property {Accessor} [data] * @typedef {BaseSeriesBlueprint & HistogramSeriesBlueprintSpecific} HistogramSeriesBlueprint @@ -36,7 +36,7 @@ * * @typedef {AnySeriesBlueprint["type"]} SeriesType * - * @typedef {{ metric: MetricAccessor, unit?: Unit }} FetchedAnySeriesOptions + * @typedef {{ metric: AnyMetricPattern, unit?: Unit }} FetchedAnySeriesOptions * * @typedef {BaselineSeriesBlueprint & FetchedAnySeriesOptions} FetchedBaselineSeriesBlueprint * @typedef {CandlestickSeriesBlueprint & FetchedAnySeriesOptions} FetchedCandlestickSeriesBlueprint @@ -168,17 +168,13 @@ * @typedef {Object} PartialContext * @property {Colors} colors * @property {BrkClient} brk - * @property {BrkClient["tree"]["computed"]["constants"]} constants - * @property {(args: { metric: MetricAccessor, name: string, color?: Color, defaultActive?: boolean, unit?: Unit, options?: LineSeriesPartialOptions }) => AnyFetchedSeriesBlueprint} s + * @property {(args: { metric: AnyMetricPattern, name: string, color?: Color, defaultActive?: boolean, unit?: Unit, options?: LineSeriesPartialOptions }) => AnyFetchedSeriesBlueprint} s * @property {(pattern: BlockCountPattern, title: string, color?: Color) => AnyFetchedSeriesBlueprint[]} fromBlockCount * @property {(pattern: BitcoinPattern, title: string, color?: Color) => AnyFetchedSeriesBlueprint[]} fromBitcoin * @property {(pattern: BlockSizePattern, title: string, color?: Color) => AnyFetchedSeriesBlueprint[]} fromBlockSize - * @property {(num: number) => Constant0Pattern} getConstant - * @property {(pattern: Constant0Pattern) => MetricAccessor} flattenConstant - * @property {(args: { number?: number, name?: string, defaultActive?: boolean, lineStyle?: number, color?: Color, unit: Unit }) => FetchedLineSeriesBlueprint} createPriceLine + * @property {(args: { number?: number, name?: string, defaultActive?: boolean, lineStyle?: LineStyle, color?: Color, unit: Unit }) => FetchedLineSeriesBlueprint} createPriceLine * @property {(args: { numbers: number[], unit: Unit }) => FetchedLineSeriesBlueprint[]} createPriceLines - * @property {(args: { constant: Constant0Pattern, name: string, unit: Unit, color?: Color, lineStyle?: number, defaultActive?: boolean }) => FetchedLineSeriesBlueprint} line - * @property {MetricAccessor} constant100 + * @property {(args: { constant: AnyMetricPattern, name: string, unit: Unit, color?: Color, lineStyle?: number, defaultActive?: boolean }) => FetchedLineSeriesBlueprint} line */ // Re-export for type consumers diff --git a/websites/bitview/scripts/options/unused.js b/websites/bitview/scripts/options/unused.js index a883b83b0..6c1829cab 100644 --- a/websites/bitview/scripts/options/unused.js +++ b/websites/bitview/scripts/options/unused.js @@ -2,17 +2,17 @@ import { localhost } from "../utils/env.js"; -/** @type {Set> | null} */ +/** @type {Set | null} */ export const unused = localhost ? new Set() : null; /** - * Walk and collect MetricAccessors + * Walk and collect AnyMetricPatterns * @param {TreeNode | null | undefined} node - * @param {Set>} set + * @param {Set} set */ function walk(node, set) { if (node && "by" in node) { - set.add(/** @type {MetricAccessor} */ (node)); + set.add(/** @type {AnyMetricPattern} */ (node)); } else if (node && typeof node === "object") { for (const value of Object.values(node)) { walk(/** @type {TreeNode | null | undefined} */ (value), set); @@ -21,7 +21,7 @@ function walk(node, set) { } /** - * Collect all MetricAccessors from tree + * Collect all AnyMetricPatterns from tree * @param {TreeNode} tree */ export function collect(tree) { @@ -30,7 +30,7 @@ export function collect(tree) { /** * Mark a metric as used - * @param {MetricAccessor} metric + * @param {AnyMetricPattern} metric */ export function markUsed(metric) { unused?.delete(metric); diff --git a/websites/bitview/scripts/panes/chart/index.js b/websites/bitview/scripts/panes/chart/index.js index e1cdc1c9d..20ea01f5a 100644 --- a/websites/bitview/scripts/panes/chart/index.js +++ b/websites/bitview/scripts/panes/chart/index.js @@ -15,7 +15,7 @@ const LINE = "line"; const CANDLE = "candle"; /** - * @typedef {"timestamp" | "date" | "week" | "epoch" | "month" | "quarter" | "semester" | "year" | "decade" } ChartableIndexName + * @typedef {"timestamp" | "date" | "week" | "month" | "quarter" | "semester" | "year" | "decade" } ChartableIndexName */ /** @@ -433,6 +433,8 @@ export function init({ blueprints[unit]?.forEach((blueprint, order) => { order += orderStart; + const options = blueprint.options; + // Tree-first: metric is now an accessor with .by property const indexes = Object.keys(blueprint.metric.by); @@ -447,7 +449,7 @@ export function init({ defaultActive: blueprint.defaultActive, paneIndex, options: { - ...blueprint.options, + ...options, topLineColor: blueprint.color?.() ?? blueprint.colors?.[0](), bottomLineColor: @@ -467,7 +469,7 @@ export function init({ color: blueprint.color, defaultActive: blueprint.defaultActive, paneIndex, - options: blueprint.options, + options, order, }), ); @@ -486,7 +488,7 @@ export function init({ unit, defaultActive: blueprint.defaultActive, paneIndex, - options: blueprint.options, + options, order, }), ); @@ -513,12 +515,10 @@ function createIndexSelector({ option, brk, signals }) { "timestamp", "date", "week", - "epoch", "month", "quarter", "semester", "year", - // "h.epoch", "decade", ]); diff --git a/websites/bitview/scripts/resources.js b/websites/bitview/scripts/resources.js index 7c90d4f3f..d35d98f1d 100644 --- a/websites/bitview/scripts/resources.js +++ b/websites/bitview/scripts/resources.js @@ -1,8 +1,3 @@ -/** - * @import { Signal, Signals } from "./signals"; - * @import { MetricNode } from "./modules/brk-client/index"; - */ - /** * @template T * @typedef {Object} Resource diff --git a/websites/bitview/scripts/utils/serde.js b/websites/bitview/scripts/utils/serde.js index 7ea4e907d..697f1e29f 100644 --- a/websites/bitview/scripts/utils/serde.js +++ b/websites/bitview/scripts/utils/serde.js @@ -123,8 +123,6 @@ export const serdeChartableIndex = { return "date"; case "decadeindex": return "decade"; - case "difficultyepoch": - return "epoch"; case "height": return "timestamp"; case "monthindex": @@ -153,8 +151,6 @@ export const serdeChartableIndex = { return "dateindex"; case "week": return "weekindex"; - case "epoch": - return "difficultyepoch"; case "month": return "monthindex"; case "quarter": @@ -308,7 +304,7 @@ export const serdeUnit = { (v.includes("_usd") && !v.endsWith("velocity")) || v.includes("cointime_value") || v.endsWith("_ago") || - v.endsWith("cost_basis") || + v.includes("cost_basis") || v.endsWith("_price") || (v.startsWith("price") && (v.endsWith("min") || v.endsWith("max"))) || (v.endsWith("_cap") && !v.includes("rel_to")) || diff --git a/websites/bitview/tsconfig.json b/websites/bitview/tsconfig.json index 38ee578c4..630890d02 100644 --- a/websites/bitview/tsconfig.json +++ b/websites/bitview/tsconfig.json @@ -9,7 +9,7 @@ "module": "ESNext", "outDir": "/tmp/brk", "lib": ["DOM", "DOM.Iterable", "ESNext", "WebWorker"], - "skipLibCheck": true + "skipLibCheck": true, }, - "exclude": ["assets", "scripts/modules"] + "exclude": ["assets", "./scripts/modules", "../../modules"], }