diff --git a/crates/brk_bindgen/src/generate/constants.rs b/crates/brk_bindgen/src/generate/constants.rs new file mode 100644 index 000000000..2baf83713 --- /dev/null +++ b/crates/brk_bindgen/src/generate/constants.rs @@ -0,0 +1,87 @@ +//! Shared constant generation for static client data. +//! +//! Extracts common logic for generating INDEXES, POOL_ID_TO_POOL_NAME, +//! and cohort name constants across JavaScript and Python clients. + +use std::collections::BTreeMap; + +use brk_cohort::{ + AGE_RANGE_NAMES, AMOUNT_RANGE_NAMES, EPOCH_NAMES, GE_AMOUNT_NAMES, LT_AMOUNT_NAMES, + MAX_AGE_NAMES, MIN_AGE_NAMES, SPENDABLE_TYPE_NAMES, TERM_NAMES, YEAR_NAMES, +}; +use brk_types::{pools, Index, PoolSlug}; +use serde::Serialize; +use serde_json::Value; + +use crate::{to_camel_case, VERSION}; + +/// Collected constant data for client generation. +pub struct ClientConstants { + pub version: String, + pub indexes: Vec<&'static str>, + pub pool_map: BTreeMap, +} + +impl ClientConstants { + /// Collect all constant data. + pub fn collect() -> Self { + let indexes = Index::all(); + let indexes: Vec<&'static str> = indexes.iter().map(|i| i.serialize_long()).collect(); + + let pools = pools(); + let mut sorted_pools: Vec<_> = pools.iter().collect(); + sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); + let pool_map: BTreeMap = + sorted_pools.iter().map(|p| (p.slug(), p.name)).collect(); + + Self { + version: format!("v{}", VERSION), + indexes, + pool_map, + } + } +} + +/// Cohort name constants - shared data definitions. +pub struct CohortConstants; + +impl CohortConstants { + /// Get all cohort constants as name-value pairs for iteration. + pub fn all() -> Vec<(&'static str, Value)> { + fn to_value(v: &T) -> Value { + serde_json::to_value(v).unwrap() + } + + vec![ + ("TERM_NAMES", to_value(&TERM_NAMES)), + ("EPOCH_NAMES", to_value(&EPOCH_NAMES)), + ("YEAR_NAMES", to_value(&YEAR_NAMES)), + ("SPENDABLE_TYPE_NAMES", to_value(&SPENDABLE_TYPE_NAMES)), + ("AGE_RANGE_NAMES", to_value(&AGE_RANGE_NAMES)), + ("MAX_AGE_NAMES", to_value(&MAX_AGE_NAMES)), + ("MIN_AGE_NAMES", to_value(&MIN_AGE_NAMES)), + ("AMOUNT_RANGE_NAMES", to_value(&AMOUNT_RANGE_NAMES)), + ("GE_AMOUNT_NAMES", to_value(&GE_AMOUNT_NAMES)), + ("LT_AMOUNT_NAMES", to_value(<_AMOUNT_NAMES)), + ] + } +} + +/// Convert top-level keys of a JSON object to camelCase. +pub fn camel_case_keys(value: Value) -> Value { + match value { + Value::Object(map) => { + let new_map: serde_json::Map = map + .into_iter() + .map(|(k, v)| (to_camel_case(&k), v)) + .collect(); + Value::Object(new_map) + } + other => other, + } +} + +/// Format a JSON value as a pretty-printed string. +pub fn format_json(value: &T) -> String { + serde_json::to_string_pretty(value).unwrap() +} diff --git a/crates/brk_bindgen/src/generate/mod.rs b/crates/brk_bindgen/src/generate/mod.rs index e94ea76e4..0b068aa89 100644 --- a/crates/brk_bindgen/src/generate/mod.rs +++ b/crates/brk_bindgen/src/generate/mod.rs @@ -4,8 +4,10 @@ //! the `LanguageSyntax` trait, allowing them to work across all supported //! language backends. +mod constants; mod fields; mod tree; +pub use constants::*; pub use fields::*; pub use tree::*; diff --git a/crates/brk_bindgen/src/generators/javascript/client.rs b/crates/brk_bindgen/src/generators/javascript/client.rs index d69e3bac6..0b6e2cb12 100644 --- a/crates/brk_bindgen/src/generators/javascript/client.rs +++ b/crates/brk_bindgen/src/generators/javascript/client.rs @@ -2,16 +2,9 @@ use std::fmt::Write; -use brk_cohort::{ - AGE_RANGE_NAMES, AMOUNT_RANGE_NAMES, EPOCH_NAMES, GE_AMOUNT_NAMES, LT_AMOUNT_NAMES, - MAX_AGE_NAMES, MIN_AGE_NAMES, SPENDABLE_TYPE_NAMES, TERM_NAMES, YEAR_NAMES, -}; -use brk_types::{Index, PoolSlug, pools}; -use serde::Serialize; -use serde_json::Value; - use crate::{ - ClientMetadata, GenericSyntax, IndexSetPattern, JavaScriptSyntax, StructuralPattern, VERSION, + ClientConstants, ClientMetadata, CohortConstants, GenericSyntax, IndexSetPattern, + JavaScriptSyntax, StructuralPattern, camel_case_keys, format_json, generate_parameterized_field, to_camel_case, }; @@ -293,59 +286,16 @@ const _p = (prefix, acc) => acc ? `${{prefix}}_${{acc}}` : prefix; /// Generate static constants for the BrkClient class. pub fn generate_static_constants(output: &mut String) { - fn instance_const(output: &mut String, name: &str, value: &T) { - write_static_const(output, name, &serde_json::to_string_pretty(value).unwrap()); - } + let constants = ClientConstants::collect(); - fn instance_const_raw(output: &mut String, name: &str, value: &str) { - writeln!(output, " {} = {};\n", name, value).unwrap(); - } + // VERSION, INDEXES, POOL_ID_TO_POOL_NAME + writeln!(output, " VERSION = \"{}\";\n", constants.version).unwrap(); + write_static_const(output, "INDEXES", &format_json(&constants.indexes)); + write_static_const(output, "POOL_ID_TO_POOL_NAME", &format_json(&constants.pool_map)); - instance_const_raw(output, "VERSION", &format!("\"v{}\"", VERSION)); - - let indexes = Index::all(); - let indexes_json: Vec<&'static str> = indexes.iter().map(|i| i.serialize_long()).collect(); - instance_const(output, "INDEXES", &indexes_json); - - let pools = pools(); - let mut sorted_pools: Vec<_> = pools.iter().collect(); - sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); - let pool_map: std::collections::BTreeMap = - sorted_pools.iter().map(|p| (p.slug(), p.name)).collect(); - instance_const(output, "POOL_ID_TO_POOL_NAME", &pool_map); - - fn instance_const_camel(output: &mut String, name: &str, value: &T) { - let json_value: Value = serde_json::to_value(value).unwrap(); - let camel_value = camel_case_top_level_keys(json_value); - write_static_const( - output, - name, - &serde_json::to_string_pretty(&camel_value).unwrap(), - ); - } - - instance_const_camel(output, "TERM_NAMES", &TERM_NAMES); - instance_const_camel(output, "EPOCH_NAMES", &EPOCH_NAMES); - instance_const_camel(output, "YEAR_NAMES", &YEAR_NAMES); - instance_const_camel(output, "SPENDABLE_TYPE_NAMES", &SPENDABLE_TYPE_NAMES); - instance_const_camel(output, "AGE_RANGE_NAMES", &AGE_RANGE_NAMES); - instance_const_camel(output, "MAX_AGE_NAMES", &MAX_AGE_NAMES); - instance_const_camel(output, "MIN_AGE_NAMES", &MIN_AGE_NAMES); - instance_const_camel(output, "AMOUNT_RANGE_NAMES", &AMOUNT_RANGE_NAMES); - instance_const_camel(output, "GE_AMOUNT_NAMES", &GE_AMOUNT_NAMES); - instance_const_camel(output, "LT_AMOUNT_NAMES", <_AMOUNT_NAMES); -} - -fn camel_case_top_level_keys(value: Value) -> Value { - match value { - Value::Object(map) => { - let new_map: serde_json::Map = map - .into_iter() - .map(|(k, v)| (to_camel_case(&k), v)) - .collect(); - Value::Object(new_map) - } - other => other, + // Cohort constants with camelCase keys + for (name, value) in CohortConstants::all() { + write_static_const(output, name, &format_json(&camel_case_keys(value))); } } diff --git a/crates/brk_bindgen/src/generators/python/client.rs b/crates/brk_bindgen/src/generators/python/client.rs index 88b08c023..81b658370 100644 --- a/crates/brk_bindgen/src/generators/python/client.rs +++ b/crates/brk_bindgen/src/generators/python/client.rs @@ -2,67 +2,48 @@ use std::fmt::Write; -use brk_cohort::{ - AGE_RANGE_NAMES, AMOUNT_RANGE_NAMES, EPOCH_NAMES, GE_AMOUNT_NAMES, LT_AMOUNT_NAMES, - MAX_AGE_NAMES, MIN_AGE_NAMES, SPENDABLE_TYPE_NAMES, TERM_NAMES, YEAR_NAMES, -}; -use brk_types::{pools, Index}; -use serde::Serialize; - use crate::{ - ClientMetadata, IndexSetPattern, PythonSyntax, StructuralPattern, VERSION, - generate_parameterized_field, index_to_field_name, + ClientConstants, ClientMetadata, CohortConstants, IndexSetPattern, PythonSyntax, + StructuralPattern, format_json, generate_parameterized_field, index_to_field_name, }; /// Generate class-level constants for the BrkClient class. pub fn generate_class_constants(output: &mut String) { - fn class_const(output: &mut String, name: &str, value: &T) { - let json = serde_json::to_string_pretty(value).unwrap(); - // Indent all lines for class body - let indented = json - .lines() - .enumerate() - .map(|(i, line)| { - if i == 0 { - format!(" {} = {}", name, line) - } else { - format!(" {}", line) - } - }) - .collect::>() - .join("\n"); - writeln!(output, "{}\n", indented).unwrap(); - } + let constants = ClientConstants::collect(); // VERSION - writeln!(output, " VERSION = \"v{}\"\n", VERSION).unwrap(); + writeln!(output, " VERSION = \"{}\"\n", constants.version).unwrap(); - // INDEXES - let indexes = Index::all(); - let indexes_list: Vec<&str> = indexes.iter().map(|i| i.serialize_long()).collect(); - class_const(output, "INDEXES", &indexes_list); - - // POOL_ID_TO_POOL_NAME - let pools = pools(); - let mut sorted_pools: Vec<_> = pools.iter().collect(); - sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase())); - let pool_map: std::collections::BTreeMap = sorted_pools + // INDEXES, POOL_ID_TO_POOL_NAME + write_class_const(output, "INDEXES", &format_json(&constants.indexes)); + // Python needs string keys for pool map + let pool_map: std::collections::BTreeMap = constants + .pool_map .iter() - .map(|p| (p.slug().to_string(), p.name)) + .map(|(k, v)| (k.to_string(), *v)) .collect(); - class_const(output, "POOL_ID_TO_POOL_NAME", &pool_map); + write_class_const(output, "POOL_ID_TO_POOL_NAME", &format_json(&pool_map)); - // Cohort names - class_const(output, "TERM_NAMES", &TERM_NAMES); - class_const(output, "EPOCH_NAMES", &EPOCH_NAMES); - class_const(output, "YEAR_NAMES", &YEAR_NAMES); - class_const(output, "SPENDABLE_TYPE_NAMES", &SPENDABLE_TYPE_NAMES); - class_const(output, "AGE_RANGE_NAMES", &AGE_RANGE_NAMES); - class_const(output, "MAX_AGE_NAMES", &MAX_AGE_NAMES); - class_const(output, "MIN_AGE_NAMES", &MIN_AGE_NAMES); - class_const(output, "AMOUNT_RANGE_NAMES", &AMOUNT_RANGE_NAMES); - class_const(output, "GE_AMOUNT_NAMES", &GE_AMOUNT_NAMES); - class_const(output, "LT_AMOUNT_NAMES", <_AMOUNT_NAMES); + // Cohort constants (no camelCase conversion for Python) + for (name, value) in CohortConstants::all() { + write_class_const(output, name, &format_json(&value)); + } +} + +fn write_class_const(output: &mut String, name: &str, json: &str) { + let indented = json + .lines() + .enumerate() + .map(|(i, line)| { + if i == 0 { + format!(" {} = {}", name, line) + } else { + format!(" {}", line) + } + }) + .collect::>() + .join("\n"); + writeln!(output, "{}\n", indented).unwrap(); } /// Generate the base BrkClient class with HTTP functionality diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index f981a6903..66d2b63bb 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -1253,56 +1253,6 @@ impl Price111dSmaPattern { } } -/// Pattern struct for repeated tree structure. -pub struct ActivePriceRatioPattern { - pub ratio: MetricPattern4, - pub ratio_1m_sma: MetricPattern4, - pub ratio_1w_sma: MetricPattern4, - pub ratio_1y_sd: Ratio1ySdPattern, - pub ratio_2y_sd: Ratio1ySdPattern, - pub ratio_4y_sd: Ratio1ySdPattern, - pub ratio_pct1: MetricPattern4, - pub ratio_pct1_usd: MetricPattern4, - pub ratio_pct2: MetricPattern4, - pub ratio_pct2_usd: MetricPattern4, - pub ratio_pct5: MetricPattern4, - pub ratio_pct5_usd: MetricPattern4, - pub ratio_pct95: MetricPattern4, - pub ratio_pct95_usd: MetricPattern4, - pub ratio_pct98: MetricPattern4, - pub ratio_pct98_usd: MetricPattern4, - pub ratio_pct99: MetricPattern4, - pub ratio_pct99_usd: MetricPattern4, - pub ratio_sd: Ratio1ySdPattern, -} - -impl ActivePriceRatioPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - ratio: MetricPattern4::new(client.clone(), acc.clone()), - ratio_1m_sma: MetricPattern4::new(client.clone(), _m(&acc, "1m_sma")), - ratio_1w_sma: MetricPattern4::new(client.clone(), _m(&acc, "1w_sma")), - ratio_1y_sd: Ratio1ySdPattern::new(client.clone(), _m(&acc, "1y")), - ratio_2y_sd: Ratio1ySdPattern::new(client.clone(), _m(&acc, "2y")), - ratio_4y_sd: Ratio1ySdPattern::new(client.clone(), _m(&acc, "4y")), - ratio_pct1: MetricPattern4::new(client.clone(), _m(&acc, "pct1")), - ratio_pct1_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct1_usd")), - ratio_pct2: MetricPattern4::new(client.clone(), _m(&acc, "pct2")), - ratio_pct2_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct2_usd")), - ratio_pct5: MetricPattern4::new(client.clone(), _m(&acc, "pct5")), - ratio_pct5_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct5_usd")), - ratio_pct95: MetricPattern4::new(client.clone(), _m(&acc, "pct95")), - ratio_pct95_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct95_usd")), - ratio_pct98: MetricPattern4::new(client.clone(), _m(&acc, "pct98")), - ratio_pct98_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct98_usd")), - ratio_pct99: MetricPattern4::new(client.clone(), _m(&acc, "pct99")), - ratio_pct99_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct99_usd")), - ratio_sd: Ratio1ySdPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct PercentilesPattern { pub pct05: MetricPattern4, @@ -1353,6 +1303,56 @@ impl PercentilesPattern { } } +/// Pattern struct for repeated tree structure. +pub struct ActivePriceRatioPattern { + pub ratio: MetricPattern4, + pub ratio_1m_sma: MetricPattern4, + pub ratio_1w_sma: MetricPattern4, + pub ratio_1y_sd: Ratio1ySdPattern, + pub ratio_2y_sd: Ratio1ySdPattern, + pub ratio_4y_sd: Ratio1ySdPattern, + pub ratio_pct1: MetricPattern4, + pub ratio_pct1_usd: MetricPattern4, + pub ratio_pct2: MetricPattern4, + pub ratio_pct2_usd: MetricPattern4, + pub ratio_pct5: MetricPattern4, + pub ratio_pct5_usd: MetricPattern4, + pub ratio_pct95: MetricPattern4, + pub ratio_pct95_usd: MetricPattern4, + pub ratio_pct98: MetricPattern4, + pub ratio_pct98_usd: MetricPattern4, + pub ratio_pct99: MetricPattern4, + pub ratio_pct99_usd: MetricPattern4, + pub ratio_sd: Ratio1ySdPattern, +} + +impl ActivePriceRatioPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + ratio: MetricPattern4::new(client.clone(), acc.clone()), + ratio_1m_sma: MetricPattern4::new(client.clone(), _m(&acc, "1m_sma")), + ratio_1w_sma: MetricPattern4::new(client.clone(), _m(&acc, "1w_sma")), + ratio_1y_sd: Ratio1ySdPattern::new(client.clone(), _m(&acc, "1y")), + ratio_2y_sd: Ratio1ySdPattern::new(client.clone(), _m(&acc, "2y")), + ratio_4y_sd: Ratio1ySdPattern::new(client.clone(), _m(&acc, "4y")), + ratio_pct1: MetricPattern4::new(client.clone(), _m(&acc, "pct1")), + ratio_pct1_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct1_usd")), + ratio_pct2: MetricPattern4::new(client.clone(), _m(&acc, "pct2")), + ratio_pct2_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct2_usd")), + ratio_pct5: MetricPattern4::new(client.clone(), _m(&acc, "pct5")), + ratio_pct5_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct5_usd")), + ratio_pct95: MetricPattern4::new(client.clone(), _m(&acc, "pct95")), + ratio_pct95_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct95_usd")), + ratio_pct98: MetricPattern4::new(client.clone(), _m(&acc, "pct98")), + ratio_pct98_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct98_usd")), + ratio_pct99: MetricPattern4::new(client.clone(), _m(&acc, "pct99")), + ratio_pct99_usd: MetricPattern4::new(client.clone(), _m(&acc, "pct99_usd")), + ratio_sd: Ratio1ySdPattern::new(client.clone(), acc.clone()), + } + } +} + /// Pattern struct for repeated tree structure. pub struct RelativePattern5 { pub neg_unrealized_loss_rel_to_market_cap: MetricPattern1, @@ -1638,49 +1638,17 @@ impl ClassAveragePricePattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - _2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_average_price")), - _2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_average_price")), - _2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_average_price")), - _2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_average_price")), - _2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_average_price")), - _2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_average_price")), - _2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_average_price")), - _2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_average_price")), - _2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_average_price")), - _2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_average_price")), - _2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_average_price")), - } - } -} - -/// Pattern struct for repeated tree structure. -pub struct RelativePattern2 { - pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1, - pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1, - pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub supply_in_loss_rel_to_own_supply: MetricPattern1, - pub supply_in_profit_rel_to_own_supply: MetricPattern1, - pub unrealized_loss_rel_to_own_market_cap: MetricPattern1, - pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, - pub unrealized_profit_rel_to_own_market_cap: MetricPattern1, - pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1, -} - -impl RelativePattern2 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")), - neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")), - net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")), - net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")), - supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")), - supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")), - unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")), - unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")), - unrealized_profit_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")), - unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")), + _2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_returns")), + _2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_returns")), + _2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_returns")), + _2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_returns")), + _2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_returns")), + _2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_returns")), + _2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_returns")), + _2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_returns")), + _2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_returns")), + _2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_returns")), + _2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_returns")), } } } @@ -1717,6 +1685,38 @@ impl RelativePattern { } } +/// Pattern struct for repeated tree structure. +pub struct RelativePattern2 { + pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1, + pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1, + pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub supply_in_loss_rel_to_own_supply: MetricPattern1, + pub supply_in_profit_rel_to_own_supply: MetricPattern1, + pub unrealized_loss_rel_to_own_market_cap: MetricPattern1, + pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1, + pub unrealized_profit_rel_to_own_market_cap: MetricPattern1, + pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1, +} + +impl RelativePattern2 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")), + neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")), + net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")), + net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")), + supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")), + supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")), + unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")), + unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")), + unrealized_profit_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")), + unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct CountPattern2 { pub average: MetricPattern1, @@ -1868,27 +1868,27 @@ impl _0satsPattern { } /// Pattern struct for repeated tree structure. -pub struct UnrealizedPattern { - pub neg_unrealized_loss: MetricPattern1, - pub net_unrealized_pnl: MetricPattern1, - pub supply_in_loss: ActiveSupplyPattern, - pub supply_in_profit: ActiveSupplyPattern, - pub total_unrealized_pnl: MetricPattern1, - pub unrealized_loss: MetricPattern1, - pub unrealized_profit: MetricPattern1, +pub struct _100btcPattern { + pub activity: ActivityPattern2, + pub cost_basis: CostBasisPattern, + pub outputs: OutputsPattern, + pub realized: RealizedPattern, + pub relative: RelativePattern, + pub supply: SupplyPattern2, + pub unrealized: UnrealizedPattern, } -impl UnrealizedPattern { +impl _100btcPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { - neg_unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")), - net_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl")), - supply_in_loss: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_loss")), - supply_in_profit: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_profit")), - total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "total_unrealized_pnl")), - unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss")), - unrealized_profit: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit")), + activity: ActivityPattern2::new(client.clone(), acc.clone()), + cost_basis: CostBasisPattern::new(client.clone(), acc.clone()), + outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), + realized: RealizedPattern::new(client.clone(), acc.clone()), + relative: RelativePattern::new(client.clone(), acc.clone()), + supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), + unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), } } } @@ -1946,17 +1946,43 @@ impl _10yPattern { } /// Pattern struct for repeated tree structure. -pub struct _100btcPattern { +pub struct UnrealizedPattern { + pub neg_unrealized_loss: MetricPattern1, + pub net_unrealized_pnl: MetricPattern1, + pub supply_in_loss: ActiveSupplyPattern, + pub supply_in_profit: ActiveSupplyPattern, + pub total_unrealized_pnl: MetricPattern1, + pub unrealized_loss: MetricPattern1, + pub unrealized_profit: MetricPattern1, +} + +impl UnrealizedPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + neg_unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")), + net_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl")), + supply_in_loss: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_loss")), + supply_in_profit: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_profit")), + total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "total_unrealized_pnl")), + unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss")), + unrealized_profit: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit")), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct _0satsPattern2 { pub activity: ActivityPattern2, pub cost_basis: CostBasisPattern, pub outputs: OutputsPattern, pub realized: RealizedPattern, - pub relative: RelativePattern, + pub relative: RelativePattern4, pub supply: SupplyPattern2, pub unrealized: UnrealizedPattern, } -impl _100btcPattern { +impl _0satsPattern2 { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { @@ -1964,7 +1990,7 @@ impl _100btcPattern { cost_basis: CostBasisPattern::new(client.clone(), acc.clone()), outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), realized: RealizedPattern::new(client.clone(), acc.clone()), - relative: RelativePattern::new(client.clone(), acc.clone()), + relative: RelativePattern4::new(client.clone(), _m(&acc, "supply_in")), supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), } @@ -1997,32 +2023,6 @@ impl PeriodCagrPattern { } } -/// Pattern struct for repeated tree structure. -pub struct _0satsPattern2 { - pub activity: ActivityPattern2, - pub cost_basis: CostBasisPattern, - pub outputs: OutputsPattern, - pub realized: RealizedPattern, - pub relative: RelativePattern4, - pub supply: SupplyPattern2, - 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()), - outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")), - realized: RealizedPattern::new(client.clone(), acc.clone()), - relative: RelativePattern4::new(client.clone(), _m(&acc, "supply_in")), - supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")), - unrealized: UnrealizedPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct ActivityPattern2 { pub coinblocks_destroyed: BlockCountPattern, @@ -2065,6 +2065,24 @@ impl SplitPattern2 { } } +/// Pattern struct for repeated tree structure. +pub struct CostBasisPattern2 { + pub max: MetricPattern1, + pub min: MetricPattern1, + pub percentiles: PercentilesPattern, +} + +impl CostBasisPattern2 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + max: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")), + min: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")), + percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")), + } + } +} + /// Pattern struct for repeated tree structure. pub struct SegwitAdoptionPattern { pub base: MetricPattern11, @@ -2101,6 +2119,24 @@ impl UnclaimedRewardsPattern { } } +/// Pattern struct for repeated tree structure. +pub struct CoinbasePattern { + pub bitcoin: BitcoinPattern, + pub dollars: DollarsPattern, + pub sats: DollarsPattern, +} + +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: DollarsPattern::new(client.clone(), _m(&acc, "usd")), + sats: DollarsPattern::new(client.clone(), acc.clone()), + } + } +} + /// Pattern struct for repeated tree structure. pub struct _2015Pattern { pub bitcoin: MetricPattern4, @@ -2119,24 +2155,6 @@ impl _2015Pattern { } } -/// Pattern struct for repeated tree structure. -pub struct CostBasisPattern2 { - pub max: MetricPattern1, - pub min: MetricPattern1, - pub percentiles: PercentilesPattern, -} - -impl CostBasisPattern2 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - max: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")), - min: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")), - percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct CoinbasePattern2 { pub bitcoin: BlockCountPattern, @@ -2174,19 +2192,33 @@ impl ActiveSupplyPattern { } /// Pattern struct for repeated tree structure. -pub struct CoinbasePattern { - pub bitcoin: BitcoinPattern, - pub dollars: DollarsPattern, - pub sats: DollarsPattern, +pub struct _1dReturns1mSdPattern { + pub sd: MetricPattern4, + pub sma: MetricPattern4, } -impl CoinbasePattern { +impl _1dReturns1mSdPattern { /// 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: DollarsPattern::new(client.clone(), _m(&acc, "usd")), - sats: DollarsPattern::new(client.clone(), acc.clone()), + sd: MetricPattern4::new(client.clone(), _m(&acc, "sd")), + sma: MetricPattern4::new(client.clone(), _m(&acc, "sma")), + } + } +} + +/// Pattern struct for repeated tree structure. +pub struct SupplyPattern2 { + pub halved: ActiveSupplyPattern, + pub total: ActiveSupplyPattern, +} + +impl SupplyPattern2 { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + halved: ActiveSupplyPattern::new(client.clone(), _m(&acc, "halved")), + total: ActiveSupplyPattern::new(client.clone(), acc.clone()), } } } @@ -2207,22 +2239,6 @@ impl RelativePattern4 { } } -/// 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")), - } - } -} - /// Pattern struct for repeated tree structure. pub struct CostBasisPattern { pub max: MetricPattern1, @@ -2239,22 +2255,6 @@ impl CostBasisPattern { } } -/// Pattern struct for repeated tree structure. -pub struct SupplyPattern2 { - pub halved: ActiveSupplyPattern, - pub total: ActiveSupplyPattern, -} - -impl SupplyPattern2 { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - halved: ActiveSupplyPattern::new(client.clone(), _m(&acc, "halved")), - total: ActiveSupplyPattern::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct SatsPattern { pub ohlc: MetricPattern1, @@ -2303,20 +2303,6 @@ impl BlockCountPattern { } } -/// Pattern struct for repeated tree structure. -pub struct RealizedPriceExtraPattern { - pub ratio: MetricPattern4, -} - -impl RealizedPriceExtraPattern { - /// Create a new pattern node with accumulated metric name. - pub fn new(client: Arc, acc: String) -> Self { - Self { - ratio: MetricPattern4::new(client.clone(), acc.clone()), - } - } -} - /// Pattern struct for repeated tree structure. pub struct OutputsPattern { pub utxo_count: MetricPattern1, @@ -2331,6 +2317,20 @@ impl OutputsPattern { } } +/// Pattern struct for repeated tree structure. +pub struct RealizedPriceExtraPattern { + pub ratio: MetricPattern4, +} + +impl RealizedPriceExtraPattern { + /// Create a new pattern node with accumulated metric name. + pub fn new(client: Arc, acc: String) -> Self { + Self { + ratio: MetricPattern4::new(client.clone(), acc.clone()), + } + } +} + // Metrics tree /// Metrics tree node. @@ -9300,8 +9300,8 @@ impl MetricsTree_Market_Ath { /// Metrics tree node. pub struct MetricsTree_Market_Dca { - pub class_average_price: ClassAveragePricePattern, - pub class_returns: MetricsTree_Market_Dca_ClassReturns, + pub class_average_price: MetricsTree_Market_Dca_ClassAveragePrice, + pub class_returns: ClassAveragePricePattern, pub class_stack: MetricsTree_Market_Dca_ClassStack, pub period_average_price: PeriodAveragePricePattern, pub period_cagr: PeriodCagrPattern, @@ -9313,8 +9313,8 @@ pub struct MetricsTree_Market_Dca { impl MetricsTree_Market_Dca { pub fn new(client: Arc, base_path: String) -> Self { Self { - class_average_price: ClassAveragePricePattern::new(client.clone(), "dca_class".to_string()), - class_returns: MetricsTree_Market_Dca_ClassReturns::new(client.clone(), format!("{base_path}_class_returns")), + class_average_price: MetricsTree_Market_Dca_ClassAveragePrice::new(client.clone(), format!("{base_path}_class_average_price")), + class_returns: ClassAveragePricePattern::new(client.clone(), "dca_class".to_string()), class_stack: MetricsTree_Market_Dca_ClassStack::new(client.clone(), format!("{base_path}_class_stack")), period_average_price: PeriodAveragePricePattern::new(client.clone(), "dca_average_price".to_string()), period_cagr: PeriodCagrPattern::new(client.clone(), "dca_cagr".to_string()), @@ -9326,34 +9326,34 @@ impl MetricsTree_Market_Dca { } /// Metrics tree node. -pub struct MetricsTree_Market_Dca_ClassReturns { - pub _2015: MetricPattern4, - pub _2016: MetricPattern4, - pub _2017: MetricPattern4, - pub _2018: MetricPattern4, - pub _2019: MetricPattern4, - pub _2020: MetricPattern4, - pub _2021: MetricPattern4, - pub _2022: MetricPattern4, - pub _2023: MetricPattern4, - pub _2024: MetricPattern4, - pub _2025: MetricPattern4, +pub struct MetricsTree_Market_Dca_ClassAveragePrice { + 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 MetricsTree_Market_Dca_ClassReturns { +impl MetricsTree_Market_Dca_ClassAveragePrice { pub fn new(client: Arc, base_path: String) -> Self { Self { - _2015: MetricPattern4::new(client.clone(), "dca_class_2015_returns".to_string()), - _2016: MetricPattern4::new(client.clone(), "dca_class_2016_returns".to_string()), - _2017: MetricPattern4::new(client.clone(), "dca_class_2017_returns".to_string()), - _2018: MetricPattern4::new(client.clone(), "dca_class_2018_returns".to_string()), - _2019: MetricPattern4::new(client.clone(), "dca_class_2019_returns".to_string()), - _2020: MetricPattern4::new(client.clone(), "dca_class_2020_returns".to_string()), - _2021: MetricPattern4::new(client.clone(), "dca_class_2021_returns".to_string()), - _2022: MetricPattern4::new(client.clone(), "dca_class_2022_returns".to_string()), - _2023: MetricPattern4::new(client.clone(), "dca_class_2023_returns".to_string()), - _2024: MetricPattern4::new(client.clone(), "dca_class_2024_returns".to_string()), - _2025: MetricPattern4::new(client.clone(), "dca_class_2025_returns".to_string()), + _2015: MetricPattern4::new(client.clone(), "dca_class_2015_average_price".to_string()), + _2016: MetricPattern4::new(client.clone(), "dca_class_2016_average_price".to_string()), + _2017: MetricPattern4::new(client.clone(), "dca_class_2017_average_price".to_string()), + _2018: MetricPattern4::new(client.clone(), "dca_class_2018_average_price".to_string()), + _2019: MetricPattern4::new(client.clone(), "dca_class_2019_average_price".to_string()), + _2020: MetricPattern4::new(client.clone(), "dca_class_2020_average_price".to_string()), + _2021: MetricPattern4::new(client.clone(), "dca_class_2021_average_price".to_string()), + _2022: MetricPattern4::new(client.clone(), "dca_class_2022_average_price".to_string()), + _2023: MetricPattern4::new(client.clone(), "dca_class_2023_average_price".to_string()), + _2024: MetricPattern4::new(client.clone(), "dca_class_2024_average_price".to_string()), + _2025: MetricPattern4::new(client.clone(), "dca_class_2025_average_price".to_string()), } } } diff --git a/crates/brk_computer/src/price/oracle/stencil.rs b/crates/brk_computer/src/price/oracle/stencil.rs index cebb14389..e8fb63d41 100644 --- a/crates/brk_computer/src/price/oracle/stencil.rs +++ b/crates/brk_computer/src/price/oracle/stencil.rs @@ -135,7 +135,8 @@ pub fn find_best_price(histogram: &Histogram, min_slide: i32, max_slide: i32) -> let range_size = max_slide - min_slide + 1; let chunk_size = (range_size + PARALLEL_CHUNKS - 1) / PARALLEL_CHUNKS; - let (best_position, _best_score) = (0..PARALLEL_CHUNKS) + // Track total score for weighted average computation + let (best_position, best_score, total_score) = (0..PARALLEL_CHUNKS) .into_par_iter() .map(|chunk_idx| { let chunk_start = min_slide + chunk_idx * chunk_size; @@ -143,26 +144,60 @@ pub fn find_best_price(histogram: &Histogram, min_slide: i32, max_slide: i32) -> let mut local_best_score = f64::NEG_INFINITY; let mut local_best_pos = chunk_start; + let mut local_total = 0.0; for slide in chunk_start..=chunk_end { let score = compute_score_fast(&non_zero_bins, &bin_map, linear_sum, slide); + local_total += score; if score > local_best_score { local_best_score = score; local_best_pos = slide; } } - (local_best_pos, local_best_score) + (local_best_pos, local_best_score, local_total) }) .reduce( - || (0, f64::NEG_INFINITY), - |a, b| if a.1 > b.1 { a } else { b }, + || (0, f64::NEG_INFINITY, 0.0), + |a, b| { + let total = a.2 + b.2; + if a.1 > b.1 { + (a.0, a.1, total) + } else { + (b.0, b.1, total) + } + }, ); - // Convert position to price in cents - // Position 0 corresponds to $100 center - // Each bin is 1/200 of a decade (log scale) - position_to_cents(best_position) + // Compute neighbor scores for sub-bin interpolation (matches Python behavior) + let neighbor_up_score = compute_score_fast(&non_zero_bins, &bin_map, linear_sum, best_position + 1); + let neighbor_down_score = compute_score_fast(&non_zero_bins, &bin_map, linear_sum, best_position - 1); + + // Find best neighbor + let (best_neighbor_offset, neighbor_score) = if neighbor_up_score > neighbor_down_score { + (1, neighbor_up_score) + } else { + (-1, neighbor_down_score) + }; + + // Weighted average between best position and best neighbor (Python lines 1144-1149) + // This provides sub-bin precision for the rough estimate + let avg_score = total_score / range_size as f64; + let a1 = best_score - avg_score; + let a2 = (neighbor_score - avg_score).abs(); + + if a1 + a2 > 0.0 { + let w1 = a1 / (a1 + a2); + let w2 = a2 / (a1 + a2); + + let price_best = i64::from(position_to_cents(best_position)?); + let price_neighbor = i64::from(position_to_cents(best_position + best_neighbor_offset)?); + + let weighted_price = Cents::from((w1 * price_best as f64 + w2 * price_neighbor as f64) as i64); + Some(weighted_price) + } else { + position_to_cents(best_position) + } } /// Fast score computation using sparse bin representation diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index 12bc63919..b87b9e347 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -1986,59 +1986,6 @@ function createPrice111dSmaPattern(client, acc) { }; } -/** - * @typedef {Object} ActivePriceRatioPattern - * @property {MetricPattern4} ratio - * @property {MetricPattern4} ratio1mSma - * @property {MetricPattern4} ratio1wSma - * @property {Ratio1ySdPattern} ratio1ySd - * @property {Ratio1ySdPattern} ratio2ySd - * @property {Ratio1ySdPattern} ratio4ySd - * @property {MetricPattern4} ratioPct1 - * @property {MetricPattern4} ratioPct1Usd - * @property {MetricPattern4} ratioPct2 - * @property {MetricPattern4} ratioPct2Usd - * @property {MetricPattern4} ratioPct5 - * @property {MetricPattern4} ratioPct5Usd - * @property {MetricPattern4} ratioPct95 - * @property {MetricPattern4} ratioPct95Usd - * @property {MetricPattern4} ratioPct98 - * @property {MetricPattern4} ratioPct98Usd - * @property {MetricPattern4} ratioPct99 - * @property {MetricPattern4} ratioPct99Usd - * @property {Ratio1ySdPattern} ratioSd - */ - -/** - * Create a ActivePriceRatioPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {ActivePriceRatioPattern} - */ -function createActivePriceRatioPattern(client, acc) { - return { - ratio: createMetricPattern4(client, acc), - ratio1mSma: createMetricPattern4(client, _m(acc, "1m_sma")), - ratio1wSma: createMetricPattern4(client, _m(acc, "1w_sma")), - ratio1ySd: createRatio1ySdPattern(client, _m(acc, "1y")), - ratio2ySd: createRatio1ySdPattern(client, _m(acc, "2y")), - ratio4ySd: createRatio1ySdPattern(client, _m(acc, "4y")), - ratioPct1: createMetricPattern4(client, _m(acc, "pct1")), - ratioPct1Usd: createMetricPattern4(client, _m(acc, "pct1_usd")), - ratioPct2: createMetricPattern4(client, _m(acc, "pct2")), - ratioPct2Usd: createMetricPattern4(client, _m(acc, "pct2_usd")), - ratioPct5: createMetricPattern4(client, _m(acc, "pct5")), - ratioPct5Usd: createMetricPattern4(client, _m(acc, "pct5_usd")), - ratioPct95: createMetricPattern4(client, _m(acc, "pct95")), - ratioPct95Usd: createMetricPattern4(client, _m(acc, "pct95_usd")), - ratioPct98: createMetricPattern4(client, _m(acc, "pct98")), - ratioPct98Usd: createMetricPattern4(client, _m(acc, "pct98_usd")), - ratioPct99: createMetricPattern4(client, _m(acc, "pct99")), - ratioPct99Usd: createMetricPattern4(client, _m(acc, "pct99_usd")), - ratioSd: createRatio1ySdPattern(client, acc), - }; -} - /** * @typedef {Object} PercentilesPattern * @property {MetricPattern4} pct05 @@ -2092,6 +2039,59 @@ function createPercentilesPattern(client, acc) { }; } +/** + * @typedef {Object} ActivePriceRatioPattern + * @property {MetricPattern4} ratio + * @property {MetricPattern4} ratio1mSma + * @property {MetricPattern4} ratio1wSma + * @property {Ratio1ySdPattern} ratio1ySd + * @property {Ratio1ySdPattern} ratio2ySd + * @property {Ratio1ySdPattern} ratio4ySd + * @property {MetricPattern4} ratioPct1 + * @property {MetricPattern4} ratioPct1Usd + * @property {MetricPattern4} ratioPct2 + * @property {MetricPattern4} ratioPct2Usd + * @property {MetricPattern4} ratioPct5 + * @property {MetricPattern4} ratioPct5Usd + * @property {MetricPattern4} ratioPct95 + * @property {MetricPattern4} ratioPct95Usd + * @property {MetricPattern4} ratioPct98 + * @property {MetricPattern4} ratioPct98Usd + * @property {MetricPattern4} ratioPct99 + * @property {MetricPattern4} ratioPct99Usd + * @property {Ratio1ySdPattern} ratioSd + */ + +/** + * Create a ActivePriceRatioPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {ActivePriceRatioPattern} + */ +function createActivePriceRatioPattern(client, acc) { + return { + ratio: createMetricPattern4(client, acc), + ratio1mSma: createMetricPattern4(client, _m(acc, "1m_sma")), + ratio1wSma: createMetricPattern4(client, _m(acc, "1w_sma")), + ratio1ySd: createRatio1ySdPattern(client, _m(acc, "1y")), + ratio2ySd: createRatio1ySdPattern(client, _m(acc, "2y")), + ratio4ySd: createRatio1ySdPattern(client, _m(acc, "4y")), + ratioPct1: createMetricPattern4(client, _m(acc, "pct1")), + ratioPct1Usd: createMetricPattern4(client, _m(acc, "pct1_usd")), + ratioPct2: createMetricPattern4(client, _m(acc, "pct2")), + ratioPct2Usd: createMetricPattern4(client, _m(acc, "pct2_usd")), + ratioPct5: createMetricPattern4(client, _m(acc, "pct5")), + ratioPct5Usd: createMetricPattern4(client, _m(acc, "pct5_usd")), + ratioPct95: createMetricPattern4(client, _m(acc, "pct95")), + ratioPct95Usd: createMetricPattern4(client, _m(acc, "pct95_usd")), + ratioPct98: createMetricPattern4(client, _m(acc, "pct98")), + ratioPct98Usd: createMetricPattern4(client, _m(acc, "pct98_usd")), + ratioPct99: createMetricPattern4(client, _m(acc, "pct99")), + ratioPct99Usd: createMetricPattern4(client, _m(acc, "pct99_usd")), + ratioSd: createRatio1ySdPattern(client, acc), + }; +} + /** * @typedef {Object} RelativePattern5 * @property {MetricPattern1} negUnrealizedLossRelToMarketCap @@ -2461,17 +2461,79 @@ function createDollarsPattern(client, acc) { */ function createClassAveragePricePattern(client, acc) { return { - _2015: createMetricPattern4(client, _m(acc, "2015_average_price")), - _2016: createMetricPattern4(client, _m(acc, "2016_average_price")), - _2017: createMetricPattern4(client, _m(acc, "2017_average_price")), - _2018: createMetricPattern4(client, _m(acc, "2018_average_price")), - _2019: createMetricPattern4(client, _m(acc, "2019_average_price")), - _2020: createMetricPattern4(client, _m(acc, "2020_average_price")), - _2021: createMetricPattern4(client, _m(acc, "2021_average_price")), - _2022: createMetricPattern4(client, _m(acc, "2022_average_price")), - _2023: createMetricPattern4(client, _m(acc, "2023_average_price")), - _2024: createMetricPattern4(client, _m(acc, "2024_average_price")), - _2025: createMetricPattern4(client, _m(acc, "2025_average_price")), + _2015: createMetricPattern4(client, _m(acc, "2015_returns")), + _2016: createMetricPattern4(client, _m(acc, "2016_returns")), + _2017: createMetricPattern4(client, _m(acc, "2017_returns")), + _2018: createMetricPattern4(client, _m(acc, "2018_returns")), + _2019: createMetricPattern4(client, _m(acc, "2019_returns")), + _2020: createMetricPattern4(client, _m(acc, "2020_returns")), + _2021: createMetricPattern4(client, _m(acc, "2021_returns")), + _2022: createMetricPattern4(client, _m(acc, "2022_returns")), + _2023: createMetricPattern4(client, _m(acc, "2023_returns")), + _2024: createMetricPattern4(client, _m(acc, "2024_returns")), + _2025: createMetricPattern4(client, _m(acc, "2025_returns")), + }; +} + +/** + * @typedef {Object} RelativePattern + * @property {MetricPattern1} negUnrealizedLossRelToMarketCap + * @property {MetricPattern1} netUnrealizedPnlRelToMarketCap + * @property {MetricPattern1} nupl + * @property {MetricPattern1} supplyInLossRelToCirculatingSupply + * @property {MetricPattern1} supplyInLossRelToOwnSupply + * @property {MetricPattern1} supplyInProfitRelToCirculatingSupply + * @property {MetricPattern1} supplyInProfitRelToOwnSupply + * @property {MetricPattern4} supplyRelToCirculatingSupply + * @property {MetricPattern1} unrealizedLossRelToMarketCap + * @property {MetricPattern1} unrealizedProfitRelToMarketCap + */ + +/** + * Create a RelativePattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {RelativePattern} + */ +function createRelativePattern(client, acc) { + return { + negUnrealizedLossRelToMarketCap: createMetricPattern1( + client, + _m(acc, "neg_unrealized_loss_rel_to_market_cap"), + ), + netUnrealizedPnlRelToMarketCap: createMetricPattern1( + client, + _m(acc, "net_unrealized_pnl_rel_to_market_cap"), + ), + nupl: createMetricPattern1(client, _m(acc, "nupl")), + supplyInLossRelToCirculatingSupply: createMetricPattern1( + client, + _m(acc, "supply_in_loss_rel_to_circulating_supply"), + ), + supplyInLossRelToOwnSupply: createMetricPattern1( + client, + _m(acc, "supply_in_loss_rel_to_own_supply"), + ), + supplyInProfitRelToCirculatingSupply: createMetricPattern1( + client, + _m(acc, "supply_in_profit_rel_to_circulating_supply"), + ), + supplyInProfitRelToOwnSupply: createMetricPattern1( + client, + _m(acc, "supply_in_profit_rel_to_own_supply"), + ), + supplyRelToCirculatingSupply: createMetricPattern4( + client, + _m(acc, "supply_rel_to_circulating_supply"), + ), + unrealizedLossRelToMarketCap: createMetricPattern1( + client, + _m(acc, "unrealized_loss_rel_to_market_cap"), + ), + unrealizedProfitRelToMarketCap: createMetricPattern1( + client, + _m(acc, "unrealized_profit_rel_to_market_cap"), + ), }; } @@ -2540,68 +2602,6 @@ function createRelativePattern2(client, acc) { }; } -/** - * @typedef {Object} RelativePattern - * @property {MetricPattern1} negUnrealizedLossRelToMarketCap - * @property {MetricPattern1} netUnrealizedPnlRelToMarketCap - * @property {MetricPattern1} nupl - * @property {MetricPattern1} supplyInLossRelToCirculatingSupply - * @property {MetricPattern1} supplyInLossRelToOwnSupply - * @property {MetricPattern1} supplyInProfitRelToCirculatingSupply - * @property {MetricPattern1} supplyInProfitRelToOwnSupply - * @property {MetricPattern4} supplyRelToCirculatingSupply - * @property {MetricPattern1} unrealizedLossRelToMarketCap - * @property {MetricPattern1} unrealizedProfitRelToMarketCap - */ - -/** - * Create a RelativePattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {RelativePattern} - */ -function createRelativePattern(client, acc) { - return { - negUnrealizedLossRelToMarketCap: createMetricPattern1( - client, - _m(acc, "neg_unrealized_loss_rel_to_market_cap"), - ), - netUnrealizedPnlRelToMarketCap: createMetricPattern1( - client, - _m(acc, "net_unrealized_pnl_rel_to_market_cap"), - ), - nupl: createMetricPattern1(client, _m(acc, "nupl")), - supplyInLossRelToCirculatingSupply: createMetricPattern1( - client, - _m(acc, "supply_in_loss_rel_to_circulating_supply"), - ), - supplyInLossRelToOwnSupply: createMetricPattern1( - client, - _m(acc, "supply_in_loss_rel_to_own_supply"), - ), - supplyInProfitRelToCirculatingSupply: createMetricPattern1( - client, - _m(acc, "supply_in_profit_rel_to_circulating_supply"), - ), - supplyInProfitRelToOwnSupply: createMetricPattern1( - client, - _m(acc, "supply_in_profit_rel_to_own_supply"), - ), - supplyRelToCirculatingSupply: createMetricPattern4( - client, - _m(acc, "supply_rel_to_circulating_supply"), - ), - unrealizedLossRelToMarketCap: createMetricPattern1( - client, - _m(acc, "unrealized_loss_rel_to_market_cap"), - ), - unrealizedProfitRelToMarketCap: createMetricPattern1( - client, - _m(acc, "unrealized_profit_rel_to_market_cap"), - ), - }; -} - /** * @template T * @typedef {Object} CountPattern2 @@ -2774,46 +2774,31 @@ function create_0satsPattern(client, acc) { } /** - * @typedef {Object} UnrealizedPattern - * @property {MetricPattern1} negUnrealizedLoss - * @property {MetricPattern1} netUnrealizedPnl - * @property {ActiveSupplyPattern} supplyInLoss - * @property {ActiveSupplyPattern} supplyInProfit - * @property {MetricPattern1} totalUnrealizedPnl - * @property {MetricPattern1} unrealizedLoss - * @property {MetricPattern1} unrealizedProfit + * @typedef {Object} _100btcPattern + * @property {ActivityPattern2} activity + * @property {CostBasisPattern} costBasis + * @property {OutputsPattern} outputs + * @property {RealizedPattern} realized + * @property {RelativePattern} relative + * @property {SupplyPattern2} supply + * @property {UnrealizedPattern} unrealized */ /** - * Create a UnrealizedPattern pattern node + * Create a _100btcPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {UnrealizedPattern} + * @returns {_100btcPattern} */ -function createUnrealizedPattern(client, acc) { +function create_100btcPattern(client, acc) { return { - negUnrealizedLoss: createMetricPattern1( - client, - _m(acc, "neg_unrealized_loss"), - ), - netUnrealizedPnl: createMetricPattern1( - client, - _m(acc, "net_unrealized_pnl"), - ), - supplyInLoss: createActiveSupplyPattern(client, _m(acc, "supply_in_loss")), - supplyInProfit: createActiveSupplyPattern( - client, - _m(acc, "supply_in_profit"), - ), - totalUnrealizedPnl: createMetricPattern1( - client, - _m(acc, "total_unrealized_pnl"), - ), - unrealizedLoss: createMetricPattern1(client, _m(acc, "unrealized_loss")), - unrealizedProfit: createMetricPattern1( - client, - _m(acc, "unrealized_profit"), - ), + activity: createActivityPattern2(client, acc), + costBasis: createCostBasisPattern(client, acc), + outputs: createOutputsPattern(client, _m(acc, "utxo_count")), + realized: createRealizedPattern(client, acc), + relative: createRelativePattern(client, acc), + supply: createSupplyPattern2(client, _m(acc, "supply")), + unrealized: createUnrealizedPattern(client, acc), }; } @@ -2876,29 +2861,73 @@ function create_10yPattern(client, acc) { } /** - * @typedef {Object} _100btcPattern + * @typedef {Object} UnrealizedPattern + * @property {MetricPattern1} negUnrealizedLoss + * @property {MetricPattern1} netUnrealizedPnl + * @property {ActiveSupplyPattern} supplyInLoss + * @property {ActiveSupplyPattern} supplyInProfit + * @property {MetricPattern1} totalUnrealizedPnl + * @property {MetricPattern1} unrealizedLoss + * @property {MetricPattern1} unrealizedProfit + */ + +/** + * Create a UnrealizedPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {UnrealizedPattern} + */ +function createUnrealizedPattern(client, acc) { + return { + negUnrealizedLoss: createMetricPattern1( + client, + _m(acc, "neg_unrealized_loss"), + ), + netUnrealizedPnl: createMetricPattern1( + client, + _m(acc, "net_unrealized_pnl"), + ), + supplyInLoss: createActiveSupplyPattern(client, _m(acc, "supply_in_loss")), + supplyInProfit: createActiveSupplyPattern( + client, + _m(acc, "supply_in_profit"), + ), + totalUnrealizedPnl: createMetricPattern1( + client, + _m(acc, "total_unrealized_pnl"), + ), + unrealizedLoss: createMetricPattern1(client, _m(acc, "unrealized_loss")), + unrealizedProfit: createMetricPattern1( + client, + _m(acc, "unrealized_profit"), + ), + }; +} + +/** + * @typedef {Object} _0satsPattern2 * @property {ActivityPattern2} activity * @property {CostBasisPattern} costBasis * @property {OutputsPattern} outputs * @property {RealizedPattern} realized - * @property {RelativePattern} relative + * @property {RelativePattern4} relative * @property {SupplyPattern2} supply * @property {UnrealizedPattern} unrealized */ /** - * Create a _100btcPattern pattern node + * Create a _0satsPattern2 pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {_100btcPattern} + * @returns {_0satsPattern2} */ -function create_100btcPattern(client, acc) { +function create_0satsPattern2(client, acc) { return { activity: createActivityPattern2(client, acc), costBasis: createCostBasisPattern(client, acc), outputs: createOutputsPattern(client, _m(acc, "utxo_count")), realized: createRealizedPattern(client, acc), - relative: createRelativePattern(client, acc), + relative: createRelativePattern4(client, _m(acc, "supply_in")), supply: createSupplyPattern2(client, _m(acc, "supply")), unrealized: createUnrealizedPattern(client, acc), }; @@ -2933,35 +2962,6 @@ function createPeriodCagrPattern(client, acc) { }; } -/** - * @typedef {Object} _0satsPattern2 - * @property {ActivityPattern2} activity - * @property {CostBasisPattern} costBasis - * @property {OutputsPattern} outputs - * @property {RealizedPattern} realized - * @property {RelativePattern4} relative - * @property {SupplyPattern2} 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), - outputs: createOutputsPattern(client, _m(acc, "utxo_count")), - realized: createRealizedPattern(client, acc), - relative: createRelativePattern4(client, _m(acc, "supply_in")), - supply: createSupplyPattern2(client, _m(acc, "supply")), - unrealized: createUnrealizedPattern(client, acc), - }; -} - /** * @typedef {Object} ActivityPattern2 * @property {BlockCountPattern} coinblocksDestroyed @@ -3024,6 +3024,27 @@ function createSplitPattern2(client, acc) { }; } +/** + * @typedef {Object} CostBasisPattern2 + * @property {MetricPattern1} max + * @property {MetricPattern1} min + * @property {PercentilesPattern} percentiles + */ + +/** + * Create a CostBasisPattern2 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {CostBasisPattern2} + */ +function createCostBasisPattern2(client, acc) { + return { + max: createMetricPattern1(client, _m(acc, "max_cost_basis")), + min: createMetricPattern1(client, _m(acc, "min_cost_basis")), + percentiles: createPercentilesPattern(client, _m(acc, "cost_basis")), + }; +} + /** * @typedef {Object} SegwitAdoptionPattern * @property {MetricPattern11} base @@ -3066,6 +3087,27 @@ function createUnclaimedRewardsPattern(client, acc) { }; } +/** + * @typedef {Object} CoinbasePattern + * @property {BitcoinPattern} bitcoin + * @property {DollarsPattern} dollars + * @property {DollarsPattern} 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: createDollarsPattern(client, _m(acc, "usd")), + sats: createDollarsPattern(client, acc), + }; +} + /** * @typedef {Object} _2015Pattern * @property {MetricPattern4} bitcoin @@ -3087,27 +3129,6 @@ function create_2015Pattern(client, acc) { }; } -/** - * @typedef {Object} CostBasisPattern2 - * @property {MetricPattern1} max - * @property {MetricPattern1} min - * @property {PercentilesPattern} percentiles - */ - -/** - * Create a CostBasisPattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {CostBasisPattern2} - */ -function createCostBasisPattern2(client, acc) { - return { - max: createMetricPattern1(client, _m(acc, "max_cost_basis")), - min: createMetricPattern1(client, _m(acc, "min_cost_basis")), - percentiles: createPercentilesPattern(client, _m(acc, "cost_basis")), - }; -} - /** * @typedef {Object} CoinbasePattern2 * @property {BlockCountPattern} bitcoin @@ -3151,23 +3172,40 @@ function createActiveSupplyPattern(client, acc) { } /** - * @typedef {Object} CoinbasePattern - * @property {BitcoinPattern} bitcoin - * @property {DollarsPattern} dollars - * @property {DollarsPattern} sats + * @typedef {Object} _1dReturns1mSdPattern + * @property {MetricPattern4} sd + * @property {MetricPattern4} sma */ /** - * Create a CoinbasePattern pattern node + * Create a _1dReturns1mSdPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {CoinbasePattern} + * @returns {_1dReturns1mSdPattern} */ -function createCoinbasePattern(client, acc) { +function create_1dReturns1mSdPattern(client, acc) { return { - bitcoin: createBitcoinPattern(client, _m(acc, "btc")), - dollars: createDollarsPattern(client, _m(acc, "usd")), - sats: createDollarsPattern(client, acc), + sd: createMetricPattern4(client, _m(acc, "sd")), + sma: createMetricPattern4(client, _m(acc, "sma")), + }; +} + +/** + * @typedef {Object} SupplyPattern2 + * @property {ActiveSupplyPattern} halved + * @property {ActiveSupplyPattern} total + */ + +/** + * Create a SupplyPattern2 pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {SupplyPattern2} + */ +function createSupplyPattern2(client, acc) { + return { + halved: createActiveSupplyPattern(client, _m(acc, "halved")), + total: createActiveSupplyPattern(client, acc), }; } @@ -3196,25 +3234,6 @@ function createRelativePattern4(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")), - }; -} - /** * @typedef {Object} CostBasisPattern * @property {MetricPattern1} max @@ -3234,25 +3253,6 @@ function createCostBasisPattern(client, acc) { }; } -/** - * @typedef {Object} SupplyPattern2 - * @property {ActiveSupplyPattern} halved - * @property {ActiveSupplyPattern} total - */ - -/** - * Create a SupplyPattern2 pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {SupplyPattern2} - */ -function createSupplyPattern2(client, acc) { - return { - halved: createActiveSupplyPattern(client, _m(acc, "halved")), - total: createActiveSupplyPattern(client, acc), - }; -} - /** * @template T * @typedef {Object} SatsPattern @@ -3316,23 +3316,6 @@ function createBlockCountPattern(client, acc) { }; } -/** - * @typedef {Object} RealizedPriceExtraPattern - * @property {MetricPattern4} ratio - */ - -/** - * Create a RealizedPriceExtraPattern pattern node - * @param {BrkClientBase} client - * @param {string} acc - Accumulated metric name - * @returns {RealizedPriceExtraPattern} - */ -function createRealizedPriceExtraPattern(client, acc) { - return { - ratio: createMetricPattern4(client, acc), - }; -} - /** * @typedef {Object} OutputsPattern * @property {MetricPattern1} utxoCount @@ -3350,6 +3333,23 @@ function createOutputsPattern(client, acc) { }; } +/** + * @typedef {Object} RealizedPriceExtraPattern + * @property {MetricPattern4} ratio + */ + +/** + * Create a RealizedPriceExtraPattern pattern node + * @param {BrkClientBase} client + * @param {string} acc - Accumulated metric name + * @returns {RealizedPriceExtraPattern} + */ +function createRealizedPriceExtraPattern(client, acc) { + return { + ratio: createMetricPattern4(client, acc), + }; +} + // Catalog tree typedefs /** @@ -6421,8 +6421,8 @@ function createOutputsPattern(client, acc) { /** * @typedef {Object} MetricsTree_Market_Dca - * @property {ClassAveragePricePattern} classAveragePrice - * @property {MetricsTree_Market_Dca_ClassReturns} classReturns + * @property {MetricsTree_Market_Dca_ClassAveragePrice} classAveragePrice + * @property {ClassAveragePricePattern} classReturns * @property {MetricsTree_Market_Dca_ClassStack} classStack * @property {PeriodAveragePricePattern} periodAveragePrice * @property {PeriodCagrPattern} periodCagr @@ -6432,18 +6432,18 @@ function createOutputsPattern(client, acc) { */ /** - * @typedef {Object} MetricsTree_Market_Dca_ClassReturns - * @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 + * @typedef {Object} MetricsTree_Market_Dca_ClassAveragePrice + * @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 */ /** @@ -12842,20 +12842,20 @@ class BrkClient extends BrkClientBase { ), }, dca: { - classAveragePrice: createClassAveragePricePattern(this, "dca_class"), - classReturns: { - _2015: createMetricPattern4(this, "dca_class_2015_returns"), - _2016: createMetricPattern4(this, "dca_class_2016_returns"), - _2017: createMetricPattern4(this, "dca_class_2017_returns"), - _2018: createMetricPattern4(this, "dca_class_2018_returns"), - _2019: createMetricPattern4(this, "dca_class_2019_returns"), - _2020: createMetricPattern4(this, "dca_class_2020_returns"), - _2021: createMetricPattern4(this, "dca_class_2021_returns"), - _2022: createMetricPattern4(this, "dca_class_2022_returns"), - _2023: createMetricPattern4(this, "dca_class_2023_returns"), - _2024: createMetricPattern4(this, "dca_class_2024_returns"), - _2025: createMetricPattern4(this, "dca_class_2025_returns"), + classAveragePrice: { + _2015: createMetricPattern4(this, "dca_class_2015_average_price"), + _2016: createMetricPattern4(this, "dca_class_2016_average_price"), + _2017: createMetricPattern4(this, "dca_class_2017_average_price"), + _2018: createMetricPattern4(this, "dca_class_2018_average_price"), + _2019: createMetricPattern4(this, "dca_class_2019_average_price"), + _2020: createMetricPattern4(this, "dca_class_2020_average_price"), + _2021: createMetricPattern4(this, "dca_class_2021_average_price"), + _2022: createMetricPattern4(this, "dca_class_2022_average_price"), + _2023: createMetricPattern4(this, "dca_class_2023_average_price"), + _2024: createMetricPattern4(this, "dca_class_2024_average_price"), + _2025: createMetricPattern4(this, "dca_class_2025_average_price"), }, + classReturns: createClassAveragePricePattern(this, "dca_class"), classStack: { _2015: create_2015Pattern(this, "dca_class_2015_stack"), _2016: create_2015Pattern(this, "dca_class_2016_stack"), diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index 4c3f544c5..a8bb4662c 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -3020,6 +3020,32 @@ class Price111dSmaPattern: self.ratio_sd: Ratio1ySdPattern = Ratio1ySdPattern(client, _m(acc, "ratio")) +class PercentilesPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.pct05: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct05")) + self.pct10: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct10")) + self.pct15: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct15")) + self.pct20: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct20")) + self.pct25: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct25")) + self.pct30: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct30")) + self.pct35: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct35")) + self.pct40: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct40")) + self.pct45: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct45")) + self.pct50: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct50")) + self.pct55: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct55")) + self.pct60: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct60")) + self.pct65: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct65")) + self.pct70: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct70")) + self.pct75: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct75")) + self.pct80: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct80")) + self.pct85: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct85")) + self.pct90: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct90")) + self.pct95: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct95")) + + class ActivePriceRatioPattern: """Pattern struct for repeated tree structure.""" @@ -3074,32 +3100,6 @@ class ActivePriceRatioPattern: self.ratio_sd: Ratio1ySdPattern = Ratio1ySdPattern(client, acc) -class PercentilesPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.pct05: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct05")) - self.pct10: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct10")) - self.pct15: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct15")) - self.pct20: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct20")) - self.pct25: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct25")) - self.pct30: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct30")) - self.pct35: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct35")) - self.pct40: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct40")) - self.pct45: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct45")) - self.pct50: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct50")) - self.pct55: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct55")) - self.pct60: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct60")) - self.pct65: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct65")) - self.pct70: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct70")) - self.pct75: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct75")) - self.pct80: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct80")) - self.pct85: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct85")) - self.pct90: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct90")) - self.pct95: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, "pct95")) - - class RelativePattern5: """Pattern struct for repeated tree structure.""" @@ -3321,38 +3321,53 @@ class ClassAveragePricePattern(Generic[T]): def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self._2015: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2015_average_price") + self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2015_returns")) + self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2016_returns")) + self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2017_returns")) + self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2018_returns")) + self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2019_returns")) + self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2020_returns")) + self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2021_returns")) + self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2022_returns")) + self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2023_returns")) + self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2024_returns")) + self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, "2025_returns")) + + +class RelativePattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.neg_unrealized_loss_rel_to_market_cap: MetricPattern1[StoredF32] = ( + MetricPattern1(client, _m(acc, "neg_unrealized_loss_rel_to_market_cap")) ) - self._2016: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2016_average_price") + self.net_unrealized_pnl_rel_to_market_cap: MetricPattern1[StoredF32] = ( + MetricPattern1(client, _m(acc, "net_unrealized_pnl_rel_to_market_cap")) ) - self._2017: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2017_average_price") + self.nupl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, "nupl")) + self.supply_in_loss_rel_to_circulating_supply: MetricPattern1[StoredF64] = ( + MetricPattern1(client, _m(acc, "supply_in_loss_rel_to_circulating_supply")) ) - self._2018: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2018_average_price") + self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = ( + MetricPattern1(client, _m(acc, "supply_in_loss_rel_to_own_supply")) ) - self._2019: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2019_average_price") + self.supply_in_profit_rel_to_circulating_supply: MetricPattern1[StoredF64] = ( + MetricPattern1( + client, _m(acc, "supply_in_profit_rel_to_circulating_supply") + ) ) - self._2020: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2020_average_price") + self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = ( + MetricPattern1(client, _m(acc, "supply_in_profit_rel_to_own_supply")) ) - self._2021: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2021_average_price") + self.supply_rel_to_circulating_supply: MetricPattern4[StoredF64] = ( + MetricPattern4(client, _m(acc, "supply_rel_to_circulating_supply")) ) - self._2022: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2022_average_price") + self.unrealized_loss_rel_to_market_cap: MetricPattern1[StoredF32] = ( + MetricPattern1(client, _m(acc, "unrealized_loss_rel_to_market_cap")) ) - self._2023: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2023_average_price") - ) - self._2024: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2024_average_price") - ) - self._2025: MetricPattern4[T] = MetricPattern4( - client, _m(acc, "2025_average_price") + self.unrealized_profit_rel_to_market_cap: MetricPattern1[StoredF32] = ( + MetricPattern1(client, _m(acc, "unrealized_profit_rel_to_market_cap")) ) @@ -3401,43 +3416,6 @@ class RelativePattern2: ) -class RelativePattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.neg_unrealized_loss_rel_to_market_cap: MetricPattern1[StoredF32] = ( - MetricPattern1(client, _m(acc, "neg_unrealized_loss_rel_to_market_cap")) - ) - self.net_unrealized_pnl_rel_to_market_cap: MetricPattern1[StoredF32] = ( - MetricPattern1(client, _m(acc, "net_unrealized_pnl_rel_to_market_cap")) - ) - self.nupl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, "nupl")) - self.supply_in_loss_rel_to_circulating_supply: MetricPattern1[StoredF64] = ( - MetricPattern1(client, _m(acc, "supply_in_loss_rel_to_circulating_supply")) - ) - self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = ( - MetricPattern1(client, _m(acc, "supply_in_loss_rel_to_own_supply")) - ) - self.supply_in_profit_rel_to_circulating_supply: MetricPattern1[StoredF64] = ( - MetricPattern1( - client, _m(acc, "supply_in_profit_rel_to_circulating_supply") - ) - ) - self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = ( - MetricPattern1(client, _m(acc, "supply_in_profit_rel_to_own_supply")) - ) - self.supply_rel_to_circulating_supply: MetricPattern4[StoredF64] = ( - MetricPattern4(client, _m(acc, "supply_rel_to_circulating_supply")) - ) - self.unrealized_loss_rel_to_market_cap: MetricPattern1[StoredF32] = ( - MetricPattern1(client, _m(acc, "unrealized_loss_rel_to_market_cap")) - ) - self.unrealized_profit_rel_to_market_cap: MetricPattern1[StoredF32] = ( - MetricPattern1(client, _m(acc, "unrealized_profit_rel_to_market_cap")) - ) - - class CountPattern2(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -3528,32 +3506,18 @@ class _0satsPattern: self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class UnrealizedPattern: +class _100btcPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.neg_unrealized_loss: MetricPattern1[Dollars] = MetricPattern1( - client, _m(acc, "neg_unrealized_loss") - ) - self.net_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1( - client, _m(acc, "net_unrealized_pnl") - ) - self.supply_in_loss: ActiveSupplyPattern = ActiveSupplyPattern( - client, _m(acc, "supply_in_loss") - ) - self.supply_in_profit: ActiveSupplyPattern = ActiveSupplyPattern( - client, _m(acc, "supply_in_profit") - ) - self.total_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1( - client, _m(acc, "total_unrealized_pnl") - ) - self.unrealized_loss: MetricPattern1[Dollars] = MetricPattern1( - client, _m(acc, "unrealized_loss") - ) - self.unrealized_profit: MetricPattern1[Dollars] = MetricPattern1( - client, _m(acc, "unrealized_profit") - ) + self.activity: ActivityPattern2 = ActivityPattern2(client, acc) + self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) + self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, "utxo_count")) + self.realized: RealizedPattern = RealizedPattern(client, acc) + self.relative: RelativePattern = RelativePattern(client, acc) + self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, "supply")) + self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) class _10yTo12yPattern: @@ -3584,7 +3548,35 @@ class _10yPattern: self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) -class _100btcPattern: +class UnrealizedPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.neg_unrealized_loss: MetricPattern1[Dollars] = MetricPattern1( + client, _m(acc, "neg_unrealized_loss") + ) + self.net_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1( + client, _m(acc, "net_unrealized_pnl") + ) + self.supply_in_loss: ActiveSupplyPattern = ActiveSupplyPattern( + client, _m(acc, "supply_in_loss") + ) + self.supply_in_profit: ActiveSupplyPattern = ActiveSupplyPattern( + client, _m(acc, "supply_in_profit") + ) + self.total_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1( + client, _m(acc, "total_unrealized_pnl") + ) + self.unrealized_loss: MetricPattern1[Dollars] = MetricPattern1( + client, _m(acc, "unrealized_loss") + ) + self.unrealized_profit: MetricPattern1[Dollars] = MetricPattern1( + client, _m(acc, "unrealized_profit") + ) + + +class _0satsPattern2: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): @@ -3593,7 +3585,7 @@ class _100btcPattern: self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc) self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, "utxo_count")) self.realized: RealizedPattern = RealizedPattern(client, acc) - self.relative: RelativePattern = RelativePattern(client, acc) + self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, "supply_in")) self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, "supply")) self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) @@ -3612,20 +3604,6 @@ class PeriodCagrPattern: self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p("8y", 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.outputs: OutputsPattern = OutputsPattern(client, _m(acc, "utxo_count")) - self.realized: RealizedPattern = RealizedPattern(client, acc) - self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, "supply_in")) - self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, "supply")) - self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc) - - class ActivityPattern2: """Pattern struct for repeated tree structure.""" @@ -3659,6 +3637,22 @@ class SplitPattern2(Generic[T]): self.open: MetricPattern1[T] = MetricPattern1(client, _m(acc, "open")) +class CostBasisPattern2: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.max: MetricPattern1[Dollars] = MetricPattern1( + client, _m(acc, "max_cost_basis") + ) + self.min: MetricPattern1[Dollars] = MetricPattern1( + client, _m(acc, "min_cost_basis") + ) + self.percentiles: PercentilesPattern = PercentilesPattern( + client, _m(acc, "cost_basis") + ) + + class SegwitAdoptionPattern: """Pattern struct for repeated tree structure.""" @@ -3683,6 +3677,16 @@ class UnclaimedRewardsPattern: self.sats: BlockCountPattern[Sats] = BlockCountPattern(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 = BitcoinPattern(client, _m(acc, "btc")) + self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, "usd")) + self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc) + + class _2015Pattern: """Pattern struct for repeated tree structure.""" @@ -3693,22 +3697,6 @@ class _2015Pattern: self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc) -class CostBasisPattern2: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.max: MetricPattern1[Dollars] = MetricPattern1( - client, _m(acc, "max_cost_basis") - ) - self.min: MetricPattern1[Dollars] = MetricPattern1( - client, _m(acc, "min_cost_basis") - ) - self.percentiles: PercentilesPattern = PercentilesPattern( - client, _m(acc, "cost_basis") - ) - - class CoinbasePattern2: """Pattern struct for repeated tree structure.""" @@ -3733,14 +3721,24 @@ class ActiveSupplyPattern: self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc) -class CoinbasePattern: +class _1dReturns1mSdPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): """Create pattern node with accumulated metric name.""" - self.bitcoin: BitcoinPattern = BitcoinPattern(client, _m(acc, "btc")) - self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, "usd")) - self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc) + self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, "sd")) + self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, "sma")) + + +class SupplyPattern2: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.halved: ActiveSupplyPattern = ActiveSupplyPattern( + client, _m(acc, "halved") + ) + self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc) class RelativePattern4: @@ -3756,15 +3754,6 @@ class RelativePattern4: ) -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 CostBasisPattern: """Pattern struct for repeated tree structure.""" @@ -3778,17 +3767,6 @@ class CostBasisPattern: ) -class SupplyPattern2: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.halved: ActiveSupplyPattern = ActiveSupplyPattern( - client, _m(acc, "halved") - ) - self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc) - - class SatsPattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -3820,14 +3798,6 @@ class BlockCountPattern(Generic[T]): self.sum: MetricPattern1[T] = MetricPattern1(client, acc) -class RealizedPriceExtraPattern: - """Pattern struct for repeated tree structure.""" - - def __init__(self, client: BrkClientBase, acc: str): - """Create pattern node with accumulated metric name.""" - self.ratio: MetricPattern4[StoredF32] = MetricPattern4(client, acc) - - class OutputsPattern: """Pattern struct for repeated tree structure.""" @@ -3836,6 +3806,14 @@ class OutputsPattern: self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, acc) +class RealizedPriceExtraPattern: + """Pattern struct for repeated tree structure.""" + + def __init__(self, client: BrkClientBase, acc: str): + """Create pattern node with accumulated metric name.""" + self.ratio: MetricPattern4[StoredF32] = MetricPattern4(client, acc) + + # Metrics tree classes @@ -10325,42 +10303,42 @@ class MetricsTree_Market_Ath: ) -class MetricsTree_Market_Dca_ClassReturns: +class MetricsTree_Market_Dca_ClassAveragePrice: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ""): - self._2015: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2015_returns" + self._2015: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2015_average_price" ) - self._2016: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2016_returns" + self._2016: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2016_average_price" ) - self._2017: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2017_returns" + self._2017: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2017_average_price" ) - self._2018: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2018_returns" + self._2018: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2018_average_price" ) - self._2019: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2019_returns" + self._2019: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2019_average_price" ) - self._2020: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2020_returns" + self._2020: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2020_average_price" ) - self._2021: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2021_returns" + self._2021: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2021_average_price" ) - self._2022: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2022_returns" + self._2022: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2022_average_price" ) - self._2023: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2023_returns" + self._2023: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2023_average_price" ) - self._2024: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2024_returns" + self._2024: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2024_average_price" ) - self._2025: MetricPattern4[StoredF32] = MetricPattern4( - client, "dca_class_2025_returns" + self._2025: MetricPattern4[Dollars] = MetricPattern4( + client, "dca_class_2025_average_price" ) @@ -10385,11 +10363,11 @@ class MetricsTree_Market_Dca: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ""): - self.class_average_price: ClassAveragePricePattern[Dollars] = ( - ClassAveragePricePattern(client, "dca_class") + self.class_average_price: MetricsTree_Market_Dca_ClassAveragePrice = ( + MetricsTree_Market_Dca_ClassAveragePrice(client) ) - self.class_returns: MetricsTree_Market_Dca_ClassReturns = ( - MetricsTree_Market_Dca_ClassReturns(client) + self.class_returns: ClassAveragePricePattern[StoredF32] = ( + ClassAveragePricePattern(client, "dca_class") ) self.class_stack: MetricsTree_Market_Dca_ClassStack = ( MetricsTree_Market_Dca_ClassStack(client) diff --git a/websites/bitview/scripts/chart/index.js b/websites/bitview/scripts/chart/index.js index 33f059984..8207f1f50 100644 --- a/websites/bitview/scripts/chart/index.js +++ b/websites/bitview/scripts/chart/index.js @@ -569,6 +569,7 @@ export function createChartElement({ * @param {AnyMetricPattern} [args.metric] * @param {Accessor} [args.data] * @param {number} [args.paneIndex] + * @param {[Color, Color]} [args.colors] - [upColor, downColor] for legend * @param {boolean} [args.defaultActive] * @param {boolean} [args.inverse] * @param {SetDataCallback} [args.setDataCallback] @@ -580,24 +581,27 @@ export function createChartElement({ unit, order, paneIndex = 0, + colors: customColors, defaultActive, setDataCallback, data, inverse, options, }) { - const green = inverse ? colors.red : colors.green; - const red = inverse ? colors.green : colors.red; + const defaultGreen = inverse ? colors.red : colors.green; + const defaultRed = inverse ? colors.green : colors.red; + const upColor = customColors?.[0] ?? defaultGreen; + const downColor = customColors?.[1] ?? defaultRed; /** @type {CandlestickISeries} */ const iseries = /** @type {any} */ ( ichart.addSeries( /** @type {SeriesDefinition<'Candlestick'>} */ (CandlestickSeries), { - upColor: green(), - downColor: red(), - wickUpColor: green(), - wickDownColor: red(), + upColor: upColor(), + downColor: downColor(), + wickUpColor: upColor(), + wickDownColor: downColor(), borderVisible: false, visible: defaultActive !== false, ...options, @@ -607,7 +611,7 @@ export function createChartElement({ ); return addSeries({ - colors: [green, red], + colors: [upColor, downColor], iseries, name, order, diff --git a/websites/bitview/scripts/options/context.js b/websites/bitview/scripts/options/context.js index 4882c5a22..794fdf032 100644 --- a/websites/bitview/scripts/options/context.js +++ b/websites/bitview/scripts/options/context.js @@ -1,5 +1,6 @@ import { line, + candlestick, baseline, histogram, fromBlockCount, @@ -37,6 +38,7 @@ export function createContext({ colors, brk }) { // Series helpers line, + candlestick, baseline, histogram, fromBlockCount: (pattern, title, color) => diff --git a/websites/bitview/scripts/options/market/index.js b/websites/bitview/scripts/options/market/index.js index 90456420f..d540c8d88 100644 --- a/websites/bitview/scripts/options/market/index.js +++ b/websites/bitview/scripts/options/market/index.js @@ -1,5 +1,6 @@ /** Market section - Main entry point */ +import { localhost } from "../../utils/env.js"; import { Unit } from "../../utils/units.js"; import { buildAverages, createAveragesSection } from "./averages.js"; import { createPerformanceSection } from "./performance.js"; @@ -12,8 +13,8 @@ import { createInvestingSection } from "./investing.js"; * @returns {PartialOptionsGroup} */ export function createMarketSection(ctx) { - const { colors, brk, line } = ctx; - const { market, supply } = brk.metrics; + const { colors, brk, line, candlestick } = ctx; + const { market, supply, price } = brk.metrics; const { movingAverage, ath, @@ -34,6 +35,16 @@ export function createMarketSection(ctx) { { name: "Price", title: "Bitcoin Price", + ...(localhost && { + top: [ + candlestick({ + metric: price.oracle.ohlcDollars, + name: "Oracle", + unit: Unit.usd, + colors: [colors.cyan, colors.purple], + }), + ], + }), }, // Capitalization diff --git a/websites/bitview/scripts/options/series.js b/websites/bitview/scripts/options/series.js index b206179d2..3cf4194be 100644 --- a/websites/bitview/scripts/options/series.js +++ b/websites/bitview/scripts/options/series.js @@ -24,6 +24,29 @@ export function line({ metric, name, color, defaultActive, unit, options }) { }; } +/** + * Create a Candlestick series + * @param {Object} args + * @param {AnyMetricPattern} args.metric + * @param {string} args.name + * @param {Unit} args.unit + * @param {[Color, Color]} [args.colors] - [upColor, downColor] for legend + * @param {boolean} [args.defaultActive] + * @param {CandlestickSeriesPartialOptions} [args.options] + * @returns {FetchedCandlestickSeriesBlueprint} + */ +export function candlestick({ metric, name, colors, defaultActive, unit, options }) { + return { + type: /** @type {const} */ ("Candlestick"), + metric, + title: name, + colors, + unit, + defaultActive, + options, + }; +} + /** * Create a Baseline series * @param {Object} args diff --git a/websites/bitview/scripts/panes/chart/index.js b/websites/bitview/scripts/panes/chart/index.js index 8c775d3b0..8196f97b4 100644 --- a/websites/bitview/scripts/panes/chart/index.js +++ b/websites/bitview/scripts/panes/chart/index.js @@ -293,6 +293,11 @@ export function init({ return field; }, }); + } else { + // Clean up bottom pane when new option has no bottom series + seriesListBottom.forEach((series) => series.remove()); + seriesListBottom.length = 0; + chart.legendBottom.removeFrom(0); } chart.addFieldsetIfNeeded({ @@ -468,7 +473,19 @@ export function init({ break; } case "Candlestick": { - throw Error("TODO"); + seriesList.push( + chart.addCandlestickSeries({ + metric: blueprint.metric, + name: blueprint.title, + unit, + colors: blueprint.colors, + defaultActive: blueprint.defaultActive, + paneIndex, + options, + order, + }), + ); + break; } case "Line": case undefined: