diff --git a/crates/brk_bindgen/src/generate/constants.rs b/crates/brk_bindgen/src/generate/constants.rs index 1bd1edfe5..44b38b229 100644 --- a/crates/brk_bindgen/src/generate/constants.rs +++ b/crates/brk_bindgen/src/generate/constants.rs @@ -6,8 +6,8 @@ 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, CLASS_NAMES, + AGE_RANGE_NAMES, AMOUNT_RANGE_NAMES, EPOCH_NAMES, OVER_AMOUNT_NAMES, UNDER_AMOUNT_NAMES, + UNDER_AGE_NAMES, OVER_AGE_NAMES, SPENDABLE_TYPE_NAMES, TERM_NAMES, CLASS_NAMES, }; use brk_types::{Index, PoolSlug, pools}; use serde::Serialize; @@ -58,11 +58,11 @@ impl CohortConstants { ("CLASS_NAMES", to_value(&CLASS_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)), + ("UNDER_AGE_NAMES", to_value(&UNDER_AGE_NAMES)), + ("OVER_AGE_NAMES", to_value(&OVER_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)), + ("OVER_AMOUNT_NAMES", to_value(&OVER_AMOUNT_NAMES)), + ("UNDER_AMOUNT_NAMES", to_value(&UNDER_AMOUNT_NAMES)), ] } } diff --git a/crates/brk_client/examples/basic.rs b/crates/brk_client/examples/basic.rs index e4d070d93..9a7691da3 100644 --- a/crates/brk_client/examples/basic.rs +++ b/crates/brk_client/examples/basic.rs @@ -40,7 +40,7 @@ fn main() -> brk_client::Result<()> { .metrics() .blocks .count - .block_count + .total .sum ._24h .by diff --git a/crates/brk_client/src/lib.rs b/crates/brk_client/src/lib.rs index c18191f30..c65962ad9 100644 --- a/crates/brk_client/src/lib.rs +++ b/crates/brk_client/src/lib.rs @@ -2422,7 +2422,7 @@ pub struct OutputsRealizedSupplyUnrealizedPattern { pub outputs: UnspentPattern, pub realized: CapLossMvrvNuplPriceProfitSoprPattern, pub supply: HalvedInTotalPattern, - pub unrealized: LossProfitPattern2, + pub unrealized: LossProfitPattern, } impl OutputsRealizedSupplyUnrealizedPattern { @@ -2432,7 +2432,7 @@ impl OutputsRealizedSupplyUnrealizedPattern { outputs: UnspentPattern::new(client.clone(), _m(&acc, "utxo_count")), realized: CapLossMvrvNuplPriceProfitSoprPattern::new(client.clone(), acc.clone()), supply: HalvedInTotalPattern::new(client.clone(), _m(&acc, "supply")), - unrealized: LossProfitPattern2::new(client.clone(), _m(&acc, "unrealized")), + unrealized: LossProfitPattern::new(client.clone(), _m(&acc, "unrealized")), } } } @@ -3024,12 +3024,12 @@ impl InPattern { } /// Pattern struct for repeated tree structure. -pub struct LossProfitPattern2 { +pub struct LossProfitPattern { pub loss: RawSumPattern2, pub profit: RawSumPattern2, } -impl LossProfitPattern2 { +impl LossProfitPattern { /// Create a new pattern node with accumulated metric name. pub fn new(client: Arc, acc: String) -> Self { Self { @@ -5742,7 +5742,7 @@ impl MetricsTree_Market_Dca_Period_CostBasis { pub struct MetricsTree_Market_Dca_Class { pub stack: MetricsTree_Market_Dca_Class_Stack, pub cost_basis: MetricsTree_Market_Dca_Class_CostBasis, - pub r#return: MetricsTree_Market_Dca_Class_R#return, + pub r#return: MetricsTree_Market_Dca_Class_Return, } impl MetricsTree_Market_Dca_Class { @@ -5750,7 +5750,7 @@ impl MetricsTree_Market_Dca_Class { Self { stack: MetricsTree_Market_Dca_Class_Stack::new(client.clone(), format!("{base_path}_stack")), cost_basis: MetricsTree_Market_Dca_Class_CostBasis::new(client.clone(), format!("{base_path}_cost_basis")), - r#return: MetricsTree_Market_Dca_Class_R#return::new(client.clone(), format!("{base_path}_r#return")), + r#return: MetricsTree_Market_Dca_Class_Return::new(client.clone(), format!("{base_path}_return")), } } } @@ -5826,7 +5826,7 @@ impl MetricsTree_Market_Dca_Class_CostBasis { } /// Metrics tree node. -pub struct MetricsTree_Market_Dca_Class_R#return { +pub struct MetricsTree_Market_Dca_Class_Return { pub from_2015: BpsPercentRatioPattern, pub from_2016: BpsPercentRatioPattern, pub from_2017: BpsPercentRatioPattern, @@ -5841,7 +5841,7 @@ pub struct MetricsTree_Market_Dca_Class_R#return { pub from_2026: BpsPercentRatioPattern, } -impl MetricsTree_Market_Dca_Class_R#return { +impl MetricsTree_Market_Dca_Class_Return { pub fn new(client: Arc, base_path: String) -> Self { Self { from_2015: BpsPercentRatioPattern::new(client.clone(), "dca_return_from_2015".to_string()), @@ -6725,13 +6725,13 @@ pub struct MetricsTree_Distribution_Cohorts_Utxo { pub sth: MetricsTree_Distribution_Cohorts_Utxo_Sth, pub lth: MetricsTree_Distribution_Cohorts_Utxo_Lth, pub age_range: MetricsTree_Distribution_Cohorts_Utxo_AgeRange, - pub max_age: MetricsTree_Distribution_Cohorts_Utxo_MaxAge, - pub min_age: MetricsTree_Distribution_Cohorts_Utxo_MinAge, + pub under_age: MetricsTree_Distribution_Cohorts_Utxo_UnderAge, + pub over_age: MetricsTree_Distribution_Cohorts_Utxo_OverAge, pub epoch: MetricsTree_Distribution_Cohorts_Utxo_Epoch, pub class: MetricsTree_Distribution_Cohorts_Utxo_Class, - pub ge_amount: MetricsTree_Distribution_Cohorts_Utxo_GeAmount, + pub over_amount: MetricsTree_Distribution_Cohorts_Utxo_OverAmount, pub amount_range: MetricsTree_Distribution_Cohorts_Utxo_AmountRange, - pub lt_amount: MetricsTree_Distribution_Cohorts_Utxo_LtAmount, + pub under_amount: MetricsTree_Distribution_Cohorts_Utxo_UnderAmount, pub r#type: MetricsTree_Distribution_Cohorts_Utxo_Type, pub profitability: MetricsTree_Distribution_Cohorts_Utxo_Profitability, pub matured: MetricsTree_Distribution_Cohorts_Utxo_Matured, @@ -6744,13 +6744,13 @@ impl MetricsTree_Distribution_Cohorts_Utxo { sth: MetricsTree_Distribution_Cohorts_Utxo_Sth::new(client.clone(), format!("{base_path}_sth")), lth: MetricsTree_Distribution_Cohorts_Utxo_Lth::new(client.clone(), format!("{base_path}_lth")), age_range: MetricsTree_Distribution_Cohorts_Utxo_AgeRange::new(client.clone(), format!("{base_path}_age_range")), - max_age: MetricsTree_Distribution_Cohorts_Utxo_MaxAge::new(client.clone(), format!("{base_path}_max_age")), - min_age: MetricsTree_Distribution_Cohorts_Utxo_MinAge::new(client.clone(), format!("{base_path}_min_age")), + under_age: MetricsTree_Distribution_Cohorts_Utxo_UnderAge::new(client.clone(), format!("{base_path}_under_age")), + over_age: MetricsTree_Distribution_Cohorts_Utxo_OverAge::new(client.clone(), format!("{base_path}_over_age")), epoch: MetricsTree_Distribution_Cohorts_Utxo_Epoch::new(client.clone(), format!("{base_path}_epoch")), class: MetricsTree_Distribution_Cohorts_Utxo_Class::new(client.clone(), format!("{base_path}_class")), - ge_amount: MetricsTree_Distribution_Cohorts_Utxo_GeAmount::new(client.clone(), format!("{base_path}_ge_amount")), + over_amount: MetricsTree_Distribution_Cohorts_Utxo_OverAmount::new(client.clone(), format!("{base_path}_over_amount")), amount_range: MetricsTree_Distribution_Cohorts_Utxo_AmountRange::new(client.clone(), format!("{base_path}_amount_range")), - lt_amount: MetricsTree_Distribution_Cohorts_Utxo_LtAmount::new(client.clone(), format!("{base_path}_lt_amount")), + under_amount: MetricsTree_Distribution_Cohorts_Utxo_UnderAmount::new(client.clone(), format!("{base_path}_under_amount")), r#type: MetricsTree_Distribution_Cohorts_Utxo_Type::new(client.clone(), format!("{base_path}_type")), profitability: MetricsTree_Distribution_Cohorts_Utxo_Profitability::new(client.clone(), format!("{base_path}_profitability")), matured: MetricsTree_Distribution_Cohorts_Utxo_Matured::new(client.clone(), format!("{base_path}_matured")), @@ -7066,7 +7066,7 @@ impl MetricsTree_Distribution_Cohorts_Utxo_AgeRange { } /// Metrics tree node. -pub struct MetricsTree_Distribution_Cohorts_Utxo_MaxAge { +pub struct MetricsTree_Distribution_Cohorts_Utxo_UnderAge { pub _1w: ActivityOutputsRealizedSupplyUnrealizedPattern2, pub _1m: ActivityOutputsRealizedSupplyUnrealizedPattern2, pub _2m: ActivityOutputsRealizedSupplyUnrealizedPattern2, @@ -7087,7 +7087,7 @@ pub struct MetricsTree_Distribution_Cohorts_Utxo_MaxAge { pub _15y: ActivityOutputsRealizedSupplyUnrealizedPattern2, } -impl MetricsTree_Distribution_Cohorts_Utxo_MaxAge { +impl MetricsTree_Distribution_Cohorts_Utxo_UnderAge { pub fn new(client: Arc, base_path: String) -> Self { Self { _1w: ActivityOutputsRealizedSupplyUnrealizedPattern2::new(client.clone(), "utxos_under_1w_old".to_string()), @@ -7113,7 +7113,7 @@ impl MetricsTree_Distribution_Cohorts_Utxo_MaxAge { } /// Metrics tree node. -pub struct MetricsTree_Distribution_Cohorts_Utxo_MinAge { +pub struct MetricsTree_Distribution_Cohorts_Utxo_OverAge { pub _1d: ActivityOutputsRealizedSupplyUnrealizedPattern2, pub _1w: ActivityOutputsRealizedSupplyUnrealizedPattern2, pub _1m: ActivityOutputsRealizedSupplyUnrealizedPattern2, @@ -7134,7 +7134,7 @@ pub struct MetricsTree_Distribution_Cohorts_Utxo_MinAge { pub _12y: ActivityOutputsRealizedSupplyUnrealizedPattern2, } -impl MetricsTree_Distribution_Cohorts_Utxo_MinAge { +impl MetricsTree_Distribution_Cohorts_Utxo_OverAge { pub fn new(client: Arc, base_path: String) -> Self { Self { _1d: ActivityOutputsRealizedSupplyUnrealizedPattern2::new(client.clone(), "utxos_over_1d_old".to_string()), @@ -7228,7 +7228,7 @@ impl MetricsTree_Distribution_Cohorts_Utxo_Class { } /// Metrics tree node. -pub struct MetricsTree_Distribution_Cohorts_Utxo_GeAmount { +pub struct MetricsTree_Distribution_Cohorts_Utxo_OverAmount { pub _1sat: OutputsRealizedSupplyPattern, pub _10sats: OutputsRealizedSupplyPattern, pub _100sats: OutputsRealizedSupplyPattern, @@ -7244,7 +7244,7 @@ pub struct MetricsTree_Distribution_Cohorts_Utxo_GeAmount { pub _10k_btc: OutputsRealizedSupplyPattern, } -impl MetricsTree_Distribution_Cohorts_Utxo_GeAmount { +impl MetricsTree_Distribution_Cohorts_Utxo_OverAmount { pub fn new(client: Arc, base_path: String) -> Self { Self { _1sat: OutputsRealizedSupplyPattern::new(client.clone(), "utxos_over_1sat".to_string()), @@ -7306,7 +7306,7 @@ impl MetricsTree_Distribution_Cohorts_Utxo_AmountRange { } /// Metrics tree node. -pub struct MetricsTree_Distribution_Cohorts_Utxo_LtAmount { +pub struct MetricsTree_Distribution_Cohorts_Utxo_UnderAmount { pub _10sats: OutputsRealizedSupplyPattern, pub _100sats: OutputsRealizedSupplyPattern, pub _1k_sats: OutputsRealizedSupplyPattern, @@ -7322,7 +7322,7 @@ pub struct MetricsTree_Distribution_Cohorts_Utxo_LtAmount { pub _100k_btc: OutputsRealizedSupplyPattern, } -impl MetricsTree_Distribution_Cohorts_Utxo_LtAmount { +impl MetricsTree_Distribution_Cohorts_Utxo_UnderAmount { pub fn new(client: Arc, base_path: String) -> Self { Self { _10sats: OutputsRealizedSupplyPattern::new(client.clone(), "utxos_under_10sats".to_string()), @@ -7394,61 +7394,61 @@ impl MetricsTree_Distribution_Cohorts_Utxo_Profitability { /// Metrics tree node. pub struct MetricsTree_Distribution_Cohorts_Utxo_Profitability_Range { - pub profit_over_1000: RealizedSupplyPattern, - pub profit_500_to_1000: RealizedSupplyPattern, - pub profit_300_to_500: RealizedSupplyPattern, - pub profit_200_to_300: RealizedSupplyPattern, - pub profit_100_to_200: RealizedSupplyPattern, - pub profit_90_to_100: RealizedSupplyPattern, - pub profit_80_to_90: RealizedSupplyPattern, - pub profit_70_to_80: RealizedSupplyPattern, - pub profit_60_to_70: RealizedSupplyPattern, - pub profit_50_to_60: RealizedSupplyPattern, - pub profit_40_to_50: RealizedSupplyPattern, - pub profit_30_to_40: RealizedSupplyPattern, - pub profit_20_to_30: RealizedSupplyPattern, - pub profit_10_to_20: RealizedSupplyPattern, - pub profit_0_to_10: RealizedSupplyPattern, - pub loss_0_to_10: RealizedSupplyPattern, - pub loss_10_to_20: RealizedSupplyPattern, - pub loss_20_to_30: RealizedSupplyPattern, - pub loss_30_to_40: RealizedSupplyPattern, - pub loss_40_to_50: RealizedSupplyPattern, - pub loss_50_to_60: RealizedSupplyPattern, - pub loss_60_to_70: RealizedSupplyPattern, - pub loss_70_to_80: RealizedSupplyPattern, - pub loss_80_to_90: RealizedSupplyPattern, - pub loss_90_to_100: RealizedSupplyPattern, + pub over_1000pct_in_profit: RealizedSupplyPattern, + pub _500pct_to_1000pct_in_profit: RealizedSupplyPattern, + pub _300pct_to_500pct_in_profit: RealizedSupplyPattern, + pub _200pct_to_300pct_in_profit: RealizedSupplyPattern, + pub _100pct_to_200pct_in_profit: RealizedSupplyPattern, + pub _90pct_to_100pct_in_profit: RealizedSupplyPattern, + pub _80pct_to_90pct_in_profit: RealizedSupplyPattern, + pub _70pct_to_80pct_in_profit: RealizedSupplyPattern, + pub _60pct_to_70pct_in_profit: RealizedSupplyPattern, + pub _50pct_to_60pct_in_profit: RealizedSupplyPattern, + pub _40pct_to_50pct_in_profit: RealizedSupplyPattern, + pub _30pct_to_40pct_in_profit: RealizedSupplyPattern, + pub _20pct_to_30pct_in_profit: RealizedSupplyPattern, + pub _10pct_to_20pct_in_profit: RealizedSupplyPattern, + pub _0pct_to_10pct_in_profit: RealizedSupplyPattern, + pub _0pct_to_10pct_in_loss: RealizedSupplyPattern, + pub _10pct_to_20pct_in_loss: RealizedSupplyPattern, + pub _20pct_to_30pct_in_loss: RealizedSupplyPattern, + pub _30pct_to_40pct_in_loss: RealizedSupplyPattern, + pub _40pct_to_50pct_in_loss: RealizedSupplyPattern, + pub _50pct_to_60pct_in_loss: RealizedSupplyPattern, + pub _60pct_to_70pct_in_loss: RealizedSupplyPattern, + pub _70pct_to_80pct_in_loss: RealizedSupplyPattern, + pub _80pct_to_90pct_in_loss: RealizedSupplyPattern, + pub _90pct_to_100pct_in_loss: RealizedSupplyPattern, } impl MetricsTree_Distribution_Cohorts_Utxo_Profitability_Range { pub fn new(client: Arc, base_path: String) -> Self { Self { - profit_over_1000: RealizedSupplyPattern::new(client.clone(), "utxos_over_1000pct_up".to_string()), - profit_500_to_1000: RealizedSupplyPattern::new(client.clone(), "utxos_500pct_to_1000pct_up".to_string()), - profit_300_to_500: RealizedSupplyPattern::new(client.clone(), "utxos_300pct_to_500pct_up".to_string()), - profit_200_to_300: RealizedSupplyPattern::new(client.clone(), "utxos_200pct_to_300pct_up".to_string()), - profit_100_to_200: RealizedSupplyPattern::new(client.clone(), "utxos_100pct_to_200pct_up".to_string()), - profit_90_to_100: RealizedSupplyPattern::new(client.clone(), "utxos_90pct_to_100pct_up".to_string()), - profit_80_to_90: RealizedSupplyPattern::new(client.clone(), "utxos_80pct_to_90pct_up".to_string()), - profit_70_to_80: RealizedSupplyPattern::new(client.clone(), "utxos_70pct_to_80pct_up".to_string()), - profit_60_to_70: RealizedSupplyPattern::new(client.clone(), "utxos_60pct_to_70pct_up".to_string()), - profit_50_to_60: RealizedSupplyPattern::new(client.clone(), "utxos_50pct_to_60pct_up".to_string()), - profit_40_to_50: RealizedSupplyPattern::new(client.clone(), "utxos_40pct_to_50pct_up".to_string()), - profit_30_to_40: RealizedSupplyPattern::new(client.clone(), "utxos_30pct_to_40pct_up".to_string()), - profit_20_to_30: RealizedSupplyPattern::new(client.clone(), "utxos_20pct_to_30pct_up".to_string()), - profit_10_to_20: RealizedSupplyPattern::new(client.clone(), "utxos_10pct_to_20pct_up".to_string()), - profit_0_to_10: RealizedSupplyPattern::new(client.clone(), "utxos_0pct_to_10pct_up".to_string()), - loss_0_to_10: RealizedSupplyPattern::new(client.clone(), "utxos_0pct_to_10pct_down".to_string()), - loss_10_to_20: RealizedSupplyPattern::new(client.clone(), "utxos_10pct_to_20pct_down".to_string()), - loss_20_to_30: RealizedSupplyPattern::new(client.clone(), "utxos_20pct_to_30pct_down".to_string()), - loss_30_to_40: RealizedSupplyPattern::new(client.clone(), "utxos_30pct_to_40pct_down".to_string()), - loss_40_to_50: RealizedSupplyPattern::new(client.clone(), "utxos_40pct_to_50pct_down".to_string()), - loss_50_to_60: RealizedSupplyPattern::new(client.clone(), "utxos_50pct_to_60pct_down".to_string()), - loss_60_to_70: RealizedSupplyPattern::new(client.clone(), "utxos_60pct_to_70pct_down".to_string()), - loss_70_to_80: RealizedSupplyPattern::new(client.clone(), "utxos_70pct_to_80pct_down".to_string()), - loss_80_to_90: RealizedSupplyPattern::new(client.clone(), "utxos_80pct_to_90pct_down".to_string()), - loss_90_to_100: RealizedSupplyPattern::new(client.clone(), "utxos_90pct_to_100pct_down".to_string()), + over_1000pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_over_1000pct_in_profit".to_string()), + _500pct_to_1000pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_500pct_to_1000pct_in_profit".to_string()), + _300pct_to_500pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_300pct_to_500pct_in_profit".to_string()), + _200pct_to_300pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_200pct_to_300pct_in_profit".to_string()), + _100pct_to_200pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_100pct_to_200pct_in_profit".to_string()), + _90pct_to_100pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_90pct_to_100pct_in_profit".to_string()), + _80pct_to_90pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_80pct_to_90pct_in_profit".to_string()), + _70pct_to_80pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_70pct_to_80pct_in_profit".to_string()), + _60pct_to_70pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_60pct_to_70pct_in_profit".to_string()), + _50pct_to_60pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_50pct_to_60pct_in_profit".to_string()), + _40pct_to_50pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_40pct_to_50pct_in_profit".to_string()), + _30pct_to_40pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_30pct_to_40pct_in_profit".to_string()), + _20pct_to_30pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_20pct_to_30pct_in_profit".to_string()), + _10pct_to_20pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_10pct_to_20pct_in_profit".to_string()), + _0pct_to_10pct_in_profit: RealizedSupplyPattern::new(client.clone(), "utxos_0pct_to_10pct_in_profit".to_string()), + _0pct_to_10pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_0pct_to_10pct_in_loss".to_string()), + _10pct_to_20pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_10pct_to_20pct_in_loss".to_string()), + _20pct_to_30pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_20pct_to_30pct_in_loss".to_string()), + _30pct_to_40pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_30pct_to_40pct_in_loss".to_string()), + _40pct_to_50pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_40pct_to_50pct_in_loss".to_string()), + _50pct_to_60pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_50pct_to_60pct_in_loss".to_string()), + _60pct_to_70pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_60pct_to_70pct_in_loss".to_string()), + _70pct_to_80pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_70pct_to_80pct_in_loss".to_string()), + _80pct_to_90pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_80pct_to_90pct_in_loss".to_string()), + _90pct_to_100pct_in_loss: RealizedSupplyPattern::new(client.clone(), "utxos_90pct_to_100pct_in_loss".to_string()), } } } @@ -7469,27 +7469,25 @@ pub struct MetricsTree_Distribution_Cohorts_Utxo_Profitability_Profit { pub _200pct: RealizedSupplyPattern, pub _300pct: RealizedSupplyPattern, pub _500pct: RealizedSupplyPattern, - pub _1000pct: RealizedSupplyPattern, } impl MetricsTree_Distribution_Cohorts_Utxo_Profitability_Profit { pub fn new(client: Arc, base_path: String) -> Self { Self { - breakeven: RealizedSupplyPattern::new(client.clone(), "profit_ge_breakeven".to_string()), - _10pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_10pct".to_string()), - _20pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_20pct".to_string()), - _30pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_30pct".to_string()), - _40pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_40pct".to_string()), - _50pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_50pct".to_string()), - _60pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_60pct".to_string()), - _70pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_70pct".to_string()), - _80pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_80pct".to_string()), - _90pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_90pct".to_string()), - _100pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_100pct".to_string()), - _200pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_200pct".to_string()), - _300pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_300pct".to_string()), - _500pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_500pct".to_string()), - _1000pct: RealizedSupplyPattern::new(client.clone(), "profit_ge_1000pct".to_string()), + breakeven: RealizedSupplyPattern::new(client.clone(), "utxos_in_profit".to_string()), + _10pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_10pct_in_profit".to_string()), + _20pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_20pct_in_profit".to_string()), + _30pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_30pct_in_profit".to_string()), + _40pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_40pct_in_profit".to_string()), + _50pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_50pct_in_profit".to_string()), + _60pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_60pct_in_profit".to_string()), + _70pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_70pct_in_profit".to_string()), + _80pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_80pct_in_profit".to_string()), + _90pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_90pct_in_profit".to_string()), + _100pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_100pct_in_profit".to_string()), + _200pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_200pct_in_profit".to_string()), + _300pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_300pct_in_profit".to_string()), + _500pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_500pct_in_profit".to_string()), } } } @@ -7505,22 +7503,20 @@ pub struct MetricsTree_Distribution_Cohorts_Utxo_Profitability_Loss { pub _60pct: RealizedSupplyPattern, pub _70pct: RealizedSupplyPattern, pub _80pct: RealizedSupplyPattern, - pub _90pct: RealizedSupplyPattern, } impl MetricsTree_Distribution_Cohorts_Utxo_Profitability_Loss { pub fn new(client: Arc, base_path: String) -> Self { Self { - breakeven: RealizedSupplyPattern::new(client.clone(), "loss_ge_breakeven".to_string()), - _10pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_10pct".to_string()), - _20pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_20pct".to_string()), - _30pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_30pct".to_string()), - _40pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_40pct".to_string()), - _50pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_50pct".to_string()), - _60pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_60pct".to_string()), - _70pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_70pct".to_string()), - _80pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_80pct".to_string()), - _90pct: RealizedSupplyPattern::new(client.clone(), "loss_ge_90pct".to_string()), + breakeven: RealizedSupplyPattern::new(client.clone(), "utxos_in_loss".to_string()), + _10pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_10pct_in_loss".to_string()), + _20pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_20pct_in_loss".to_string()), + _30pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_30pct_in_loss".to_string()), + _40pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_40pct_in_loss".to_string()), + _50pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_50pct_in_loss".to_string()), + _60pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_60pct_in_loss".to_string()), + _70pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_70pct_in_loss".to_string()), + _80pct: RealizedSupplyPattern::new(client.clone(), "utxos_over_80pct_in_loss".to_string()), } } } @@ -7580,23 +7576,23 @@ impl MetricsTree_Distribution_Cohorts_Utxo_Matured { /// Metrics tree node. pub struct MetricsTree_Distribution_Cohorts_Address { - pub ge_amount: MetricsTree_Distribution_Cohorts_Address_GeAmount, + pub over_amount: MetricsTree_Distribution_Cohorts_Address_OverAmount, pub amount_range: MetricsTree_Distribution_Cohorts_Address_AmountRange, - pub lt_amount: MetricsTree_Distribution_Cohorts_Address_LtAmount, + pub under_amount: MetricsTree_Distribution_Cohorts_Address_UnderAmount, } impl MetricsTree_Distribution_Cohorts_Address { pub fn new(client: Arc, base_path: String) -> Self { Self { - ge_amount: MetricsTree_Distribution_Cohorts_Address_GeAmount::new(client.clone(), format!("{base_path}_ge_amount")), + over_amount: MetricsTree_Distribution_Cohorts_Address_OverAmount::new(client.clone(), format!("{base_path}_over_amount")), amount_range: MetricsTree_Distribution_Cohorts_Address_AmountRange::new(client.clone(), format!("{base_path}_amount_range")), - lt_amount: MetricsTree_Distribution_Cohorts_Address_LtAmount::new(client.clone(), format!("{base_path}_lt_amount")), + under_amount: MetricsTree_Distribution_Cohorts_Address_UnderAmount::new(client.clone(), format!("{base_path}_under_amount")), } } } /// Metrics tree node. -pub struct MetricsTree_Distribution_Cohorts_Address_GeAmount { +pub struct MetricsTree_Distribution_Cohorts_Address_OverAmount { pub _1sat: AddrOutputsRealizedSupplyPattern, pub _10sats: AddrOutputsRealizedSupplyPattern, pub _100sats: AddrOutputsRealizedSupplyPattern, @@ -7612,7 +7608,7 @@ pub struct MetricsTree_Distribution_Cohorts_Address_GeAmount { pub _10k_btc: AddrOutputsRealizedSupplyPattern, } -impl MetricsTree_Distribution_Cohorts_Address_GeAmount { +impl MetricsTree_Distribution_Cohorts_Address_OverAmount { pub fn new(client: Arc, base_path: String) -> Self { Self { _1sat: AddrOutputsRealizedSupplyPattern::new(client.clone(), "addrs_over_1sat".to_string()), @@ -7674,7 +7670,7 @@ impl MetricsTree_Distribution_Cohorts_Address_AmountRange { } /// Metrics tree node. -pub struct MetricsTree_Distribution_Cohorts_Address_LtAmount { +pub struct MetricsTree_Distribution_Cohorts_Address_UnderAmount { pub _10sats: AddrOutputsRealizedSupplyPattern, pub _100sats: AddrOutputsRealizedSupplyPattern, pub _1k_sats: AddrOutputsRealizedSupplyPattern, @@ -7690,7 +7686,7 @@ pub struct MetricsTree_Distribution_Cohorts_Address_LtAmount { pub _100k_btc: AddrOutputsRealizedSupplyPattern, } -impl MetricsTree_Distribution_Cohorts_Address_LtAmount { +impl MetricsTree_Distribution_Cohorts_Address_UnderAmount { pub fn new(client: Arc, base_path: String) -> Self { Self { _10sats: AddrOutputsRealizedSupplyPattern::new(client.clone(), "addrs_under_10sats".to_string()), @@ -8106,6 +8102,24 @@ impl BrkClient { self.base.get_json(&format!("/api/metric/{metric}/{}/latest", index.name())) } + /// Get metric data length + /// + /// Returns the total number of data points for a metric at the given index. + /// + /// Endpoint: `GET /api/metric/{metric}/{index}/len` + pub fn get_metric_len(&self, metric: Metric, index: Index) -> Result { + self.base.get_json(&format!("/api/metric/{metric}/{}/len", index.name())) + } + + /// Get metric version + /// + /// Returns the current version of a metric. Changes when the metric data is updated. + /// + /// Endpoint: `GET /api/metric/{metric}/{index}/version` + pub fn get_metric_version(&self, metric: Metric, index: Index) -> Result { + self.base.get_json(&format!("/api/metric/{metric}/{}/version", index.name())) + } + /// Metrics catalog /// /// Returns the complete hierarchical catalog of available metrics organized as a tree structure. Metrics are grouped by categories and subcategories. diff --git a/crates/brk_cohort/src/address.rs b/crates/brk_cohort/src/address.rs index 96fccd1cc..3e3f4d6b3 100644 --- a/crates/brk_cohort/src/address.rs +++ b/crates/brk_cohort/src/address.rs @@ -3,13 +3,13 @@ use rayon::prelude::*; use crate::Filter; -use super::{ByAmountRange, ByGreatEqualAmount, ByLowerThanAmount}; +use super::{AmountRange, OverAmount, UnderAmount}; #[derive(Default, Clone, Traversable)] pub struct AddressGroups { - pub ge_amount: ByGreatEqualAmount, - pub amount_range: ByAmountRange, - pub lt_amount: ByLowerThanAmount, + pub over_amount: OverAmount, + pub amount_range: AmountRange, + pub under_amount: UnderAmount, } impl AddressGroups { @@ -18,9 +18,9 @@ impl AddressGroups { F: FnMut(Filter, &'static str) -> T, { Self { - ge_amount: ByGreatEqualAmount::new(&mut create), - amount_range: ByAmountRange::new(&mut create), - lt_amount: ByLowerThanAmount::new(&mut create), + over_amount: OverAmount::new(&mut create), + amount_range: AmountRange::new(&mut create), + under_amount: UnderAmount::new(&mut create), } } @@ -29,34 +29,34 @@ impl AddressGroups { F: Fn(Filter, &'static str) -> Result, { Ok(Self { - ge_amount: ByGreatEqualAmount::try_new(create)?, - amount_range: ByAmountRange::try_new(create)?, - lt_amount: ByLowerThanAmount::try_new(create)?, + over_amount: OverAmount::try_new(create)?, + amount_range: AmountRange::try_new(create)?, + under_amount: UnderAmount::try_new(create)?, }) } pub fn iter(&self) -> impl Iterator { - self.ge_amount + self.over_amount .iter() .chain(self.amount_range.iter()) - .chain(self.lt_amount.iter()) + .chain(self.under_amount.iter()) } pub fn iter_mut(&mut self) -> impl Iterator { - self.ge_amount + self.over_amount .iter_mut() .chain(self.amount_range.iter_mut()) - .chain(self.lt_amount.iter_mut()) + .chain(self.under_amount.iter_mut()) } pub fn par_iter_mut(&mut self) -> impl ParallelIterator where T: Send + Sync, { - self.ge_amount + self.over_amount .par_iter_mut() .chain(self.amount_range.par_iter_mut()) - .chain(self.lt_amount.par_iter_mut()) + .chain(self.under_amount.par_iter_mut()) } pub fn iter_separate(&self) -> impl Iterator { @@ -75,7 +75,7 @@ impl AddressGroups { } pub fn iter_overlapping_mut(&mut self) -> impl Iterator { - self.lt_amount.iter_mut().chain(self.ge_amount.iter_mut()) + self.under_amount.iter_mut().chain(self.over_amount.iter_mut()) } } diff --git a/crates/brk_cohort/src/by_age_range.rs b/crates/brk_cohort/src/age_range.rs similarity index 98% rename from crates/brk_cohort/src/by_age_range.rs rename to crates/brk_cohort/src/age_range.rs index c467b4503..cf51d08ec 100644 --- a/crates/brk_cohort/src/by_age_range.rs +++ b/crates/brk_cohort/src/age_range.rs @@ -38,7 +38,7 @@ pub const AGE_BOUNDARIES: [usize; 20] = [ ]; /// Age range bounds (end = usize::MAX means unbounded) -pub const AGE_RANGE_BOUNDS: ByAgeRange> = ByAgeRange { +pub const AGE_RANGE_BOUNDS: AgeRange> = AgeRange { up_to_1h: 0..HOURS_1H, _1h_to_1d: HOURS_1H..HOURS_1D, _1d_to_1w: HOURS_1D..HOURS_1W, @@ -63,7 +63,7 @@ pub const AGE_RANGE_BOUNDS: ByAgeRange> = ByAgeRange { }; /// Age range filters -pub const AGE_RANGE_FILTERS: ByAgeRange = ByAgeRange { +pub const AGE_RANGE_FILTERS: AgeRange = AgeRange { up_to_1h: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS.up_to_1h)), _1h_to_1d: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS._1h_to_1d)), _1d_to_1w: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS._1d_to_1w)), @@ -88,7 +88,7 @@ pub const AGE_RANGE_FILTERS: ByAgeRange = ByAgeRange { }; /// Age range names -pub const AGE_RANGE_NAMES: ByAgeRange = ByAgeRange { +pub const AGE_RANGE_NAMES: AgeRange = AgeRange { up_to_1h: CohortName::new("under_1h_old", "<1h", "Under 1 Hour Old"), _1h_to_1d: CohortName::new("1h_to_1d_old", "1h-1d", "1 Hour to 1 Day Old"), _1d_to_1w: CohortName::new("1d_to_1w_old", "1d-1w", "1 Day to 1 Week Old"), @@ -112,14 +112,14 @@ pub const AGE_RANGE_NAMES: ByAgeRange = ByAgeRange { from_15y: CohortName::new("over_15y_old", "15y+", "15+ Years Old"), }; -impl ByAgeRange { +impl AgeRange { pub const fn names() -> &'static Self { &AGE_RANGE_NAMES } } #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByAgeRange { +pub struct AgeRange { pub up_to_1h: T, pub _1h_to_1d: T, pub _1d_to_1w: T, @@ -143,7 +143,7 @@ pub struct ByAgeRange { pub from_15y: T, } -impl ByAgeRange { +impl AgeRange { /// Get mutable reference by Age. O(1). #[inline] pub fn get_mut(&mut self, age: Age) -> &mut T { diff --git a/crates/brk_cohort/src/by_amount_range.rs b/crates/brk_cohort/src/amount_range.rs similarity index 97% rename from crates/brk_cohort/src/by_amount_range.rs rename to crates/brk_cohort/src/amount_range.rs index 73f0e416f..ed54c7dc3 100644 --- a/crates/brk_cohort/src/by_amount_range.rs +++ b/crates/brk_cohort/src/amount_range.rs @@ -13,7 +13,7 @@ pub struct AmountBucket(u8); impl AmountBucket { /// Returns (self, other) if buckets differ, None if same. - /// Use with `ByAmountRange::get_mut_by_bucket` to avoid recomputing. + /// Use with `AmountRange::get_mut_by_bucket` to avoid recomputing. #[inline(always)] pub fn transition_to(self, other: Self) -> Option<(Self, Self)> { if self != other { @@ -59,7 +59,7 @@ pub fn amounts_in_different_buckets(a: Sats, b: Sats) -> bool { } /// Amount range bounds -pub const AMOUNT_RANGE_BOUNDS: ByAmountRange> = ByAmountRange { +pub const AMOUNT_RANGE_BOUNDS: AmountRange> = AmountRange { _0sats: Sats::ZERO..Sats::_1, _1sat_to_10sats: Sats::_1..Sats::_10, _10sats_to_100sats: Sats::_10..Sats::_100, @@ -78,7 +78,7 @@ pub const AMOUNT_RANGE_BOUNDS: ByAmountRange> = ByAmountRange { }; /// Amount range names -pub const AMOUNT_RANGE_NAMES: ByAmountRange = ByAmountRange { +pub const AMOUNT_RANGE_NAMES: AmountRange = AmountRange { _0sats: CohortName::new("with_0sats", "0 sats", "0 Sats"), _1sat_to_10sats: CohortName::new("above_1sat_under_10sats", "1-10 sats", "1-10 Sats"), _10sats_to_100sats: CohortName::new("above_10sats_under_100sats", "10-100 sats", "10-100 Sats"), @@ -121,7 +121,7 @@ pub const AMOUNT_RANGE_NAMES: ByAmountRange = ByAmountRange { }; /// Amount range filters -pub const AMOUNT_RANGE_FILTERS: ByAmountRange = ByAmountRange { +pub const AMOUNT_RANGE_FILTERS: AmountRange = AmountRange { _0sats: Filter::Amount(AmountFilter::Range(AMOUNT_RANGE_BOUNDS._0sats)), _1sat_to_10sats: Filter::Amount(AmountFilter::Range(AMOUNT_RANGE_BOUNDS._1sat_to_10sats)), _10sats_to_100sats: Filter::Amount(AmountFilter::Range(AMOUNT_RANGE_BOUNDS._10sats_to_100sats)), @@ -152,7 +152,7 @@ pub const AMOUNT_RANGE_FILTERS: ByAmountRange = ByAmountRange { }; #[derive(Debug, Default, Clone, Traversable, Serialize)] -pub struct ByAmountRange { +pub struct AmountRange { pub _0sats: T, pub _1sat_to_10sats: T, pub _10sats_to_100sats: T, @@ -170,13 +170,13 @@ pub struct ByAmountRange { pub _100k_btc_or_more: T, } -impl ByAmountRange { +impl AmountRange { pub const fn names() -> &'static Self { &AMOUNT_RANGE_NAMES } } -impl ByAmountRange { +impl AmountRange { pub fn new(mut create: F) -> Self where F: FnMut(Filter, &'static str) -> T, @@ -385,7 +385,7 @@ impl ByAmountRange { } } -impl Add for ByAmountRange +impl Add for AmountRange where T: Add, { @@ -411,7 +411,7 @@ where } } -impl AddAssign for ByAmountRange +impl AddAssign for AmountRange where T: AddAssign, { diff --git a/crates/brk_cohort/src/by_type.rs b/crates/brk_cohort/src/by_type.rs index 9b8743dc3..881373f8a 100644 --- a/crates/brk_cohort/src/by_type.rs +++ b/crates/brk_cohort/src/by_type.rs @@ -2,15 +2,15 @@ use std::ops::{Add, AddAssign}; use brk_types::OutputType; -use super::{BySpendableType, ByUnspendableType}; +use super::{SpendableType, UnspendableType}; #[derive(Default, Clone, Debug)] -pub struct GroupedByType { - pub spendable: BySpendableType, - pub unspendable: ByUnspendableType, +pub struct ByType { + pub spendable: SpendableType, + pub unspendable: UnspendableType, } -impl GroupedByType { +impl ByType { pub fn get(&self, output_type: OutputType) -> &T { match output_type { OutputType::P2PK65 => &self.spendable.p2pk65, @@ -46,7 +46,7 @@ impl GroupedByType { } } -impl Add for GroupedByType +impl Add for ByType where T: Add, { @@ -59,7 +59,7 @@ where } } -impl AddAssign for GroupedByType +impl AddAssign for ByType where T: AddAssign, { diff --git a/crates/brk_cohort/src/by_value.rs b/crates/brk_cohort/src/by_value.rs deleted file mode 100644 index f58d311b3..000000000 --- a/crates/brk_cohort/src/by_value.rs +++ /dev/null @@ -1,37 +0,0 @@ -#[derive(Default, Clone)] -pub struct GroupedByValue { - pub up_to_1cent: T, - pub from_1c_to_10c: T, - pub from_10c_to_1d: T, - pub from_1d_to_10d: T, - pub from_10usd_to_100usd: T, - pub from_100usd_to_1_000usd: T, - pub from_1_000usd_to_10_000usd: T, - pub from_10_000usd_to_100_000usd: T, - pub from_100_000usd_to_1_000_000usd: T, - pub from_1_000_000usd_to_10_000_000usd: T, - pub from_10_000_000usd_to_100_000_000usd: T, - pub from_100_000_000usd_to_1_000_000_000usd: T, - pub from_1_000_000_000usd: T, - // ... -} - -impl GroupedByValue { - pub fn as_mut_vec(&mut self) -> Vec<&mut T> { - vec![ - &mut self.up_to_1cent, - &mut self.from_1c_to_10c, - &mut self.from_10c_to_1d, - &mut self.from_1d_to_10d, - &mut self.from_10usd_to_100usd, - &mut self.from_100usd_to_1_000usd, - &mut self.from_1_000usd_to_10_000usd, - &mut self.from_10_000usd_to_100_000usd, - &mut self.from_100_000usd_to_1_000_000usd, - &mut self.from_1_000_000usd_to_10_000_000usd, - &mut self.from_10_000_000usd_to_100_000_000usd, - &mut self.from_100_000_000usd_to_1_000_000_000usd, - &mut self.from_1_000_000_000usd, - ] - } -} diff --git a/crates/brk_cohort/src/by_class.rs b/crates/brk_cohort/src/class.rs similarity index 97% rename from crates/brk_cohort/src/by_class.rs rename to crates/brk_cohort/src/class.rs index 7b4972915..62173d19d 100644 --- a/crates/brk_cohort/src/by_class.rs +++ b/crates/brk_cohort/src/class.rs @@ -6,7 +6,7 @@ use serde::Serialize; use super::{CohortName, Filter}; /// Class values -pub const CLASS_VALUES: ByClass = ByClass { +pub const CLASS_VALUES: Class = Class { _2009: Year::new(2009), _2010: Year::new(2010), _2011: Year::new(2011), @@ -28,7 +28,7 @@ pub const CLASS_VALUES: ByClass = ByClass { }; /// Class filters -pub const CLASS_FILTERS: ByClass = ByClass { +pub const CLASS_FILTERS: Class = Class { _2009: Filter::Class(CLASS_VALUES._2009), _2010: Filter::Class(CLASS_VALUES._2010), _2011: Filter::Class(CLASS_VALUES._2011), @@ -50,7 +50,7 @@ pub const CLASS_FILTERS: ByClass = ByClass { }; /// Class names -pub const CLASS_NAMES: ByClass = ByClass { +pub const CLASS_NAMES: Class = Class { _2009: CohortName::new("class_2009", "2009", "Class 2009"), _2010: CohortName::new("class_2010", "2010", "Class 2010"), _2011: CohortName::new("class_2011", "2011", "Class 2011"), @@ -72,7 +72,7 @@ pub const CLASS_NAMES: ByClass = ByClass { }; #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByClass { +pub struct Class { pub _2009: T, pub _2010: T, pub _2011: T, @@ -93,13 +93,13 @@ pub struct ByClass { pub _2026: T, } -impl ByClass { +impl Class { pub const fn names() -> &'static Self { &CLASS_NAMES } } -impl ByClass { +impl Class { pub fn new(mut create: F) -> Self where F: FnMut(Filter, &'static str) -> T, diff --git a/crates/brk_cohort/src/filter.rs b/crates/brk_cohort/src/filter.rs index 91f7aaf62..a158e2ec0 100644 --- a/crates/brk_cohort/src/filter.rs +++ b/crates/brk_cohort/src/filter.rs @@ -89,7 +89,7 @@ impl Filter { } /// Whether to compute adjusted metrics (adjusted SOPR, adjusted value created/destroyed) - /// For UTXO context: true for All, STH, and max_age (LowerThan) + /// For UTXO context: true for All, STH, and under_age (LowerThan) /// For Address context: always false /// Note: LTH doesn't need adjusted (everything >= 5 months is already > 1 hour) /// Note: age ranges don't need adjusted (0-1h data lives in its own cohort) diff --git a/crates/brk_cohort/src/lib.rs b/crates/brk_cohort/src/lib.rs index 2d9fa1ef2..b0dfd95a8 100644 --- a/crates/brk_cohort/src/lib.rs +++ b/crates/brk_cohort/src/lib.rs @@ -2,56 +2,56 @@ mod address; mod amount_filter; +mod age_range; +mod amount_range; mod by_address_type; -mod by_age_range; -mod by_amount_range; mod by_any_address; mod by_epoch; -mod by_ge_amount; -mod by_loss; -mod by_lt_amount; -mod by_max_age; -mod by_min_age; -mod by_profitability_range; -mod by_profit; -mod by_spendable_type; mod by_term; mod by_type; -mod by_unspendable_type; -mod by_class; +mod class; mod cohort_context; mod cohort_name; mod filter; mod filtered; +mod loss; +mod over_age; +mod over_amount; +mod profit; +mod profitability_range; +mod spendable_type; mod state_level; mod time_filter; +mod under_age; +mod under_amount; +mod unspendable_type; mod utxo; pub use brk_types::{Age, Term}; pub use address::*; pub use amount_filter::*; +pub use age_range::*; +pub use amount_range::*; pub use by_address_type::*; -pub use by_age_range::*; -pub use by_amount_range::*; pub use by_any_address::*; pub use by_epoch::*; -pub use by_ge_amount::*; -pub use by_loss::*; -pub use by_lt_amount::*; -pub use by_max_age::*; -pub use by_min_age::*; -pub use by_profitability_range::*; -pub use by_profit::*; -pub use by_spendable_type::*; pub use by_term::*; pub use by_type::*; -pub use by_unspendable_type::*; -pub use by_class::*; +pub use class::*; pub use cohort_context::*; pub use cohort_name::*; pub use filter::*; pub use filtered::*; +pub use loss::*; +pub use over_age::*; +pub use over_amount::*; +pub use profit::*; +pub use profitability_range::*; +pub use spendable_type::*; pub use state_level::*; pub use time_filter::*; +pub use under_age::*; +pub use under_amount::*; +pub use unspendable_type::*; pub use utxo::*; diff --git a/crates/brk_cohort/src/by_loss.rs b/crates/brk_cohort/src/loss.rs similarity index 89% rename from crates/brk_cohort/src/by_loss.rs rename to crates/brk_cohort/src/loss.rs index 132c71730..daef084e0 100644 --- a/crates/brk_cohort/src/by_loss.rs +++ b/crates/brk_cohort/src/loss.rs @@ -5,7 +5,7 @@ use serde::Serialize; use super::CohortName; /// "At least X% loss" threshold names (10 thresholds). -pub const LOSS_NAMES: ByLoss = ByLoss { +pub const LOSS_NAMES: Loss = Loss { breakeven: CohortName::new("utxos_in_loss", "<0%", "In Loss (Below Breakeven)"), _10pct: CohortName::new("utxos_over_10pct_in_loss", "≥10%L", "10%+ Loss"), _20pct: CohortName::new("utxos_over_20pct_in_loss", "≥20%L", "20%+ Loss"), @@ -15,13 +15,12 @@ pub const LOSS_NAMES: ByLoss = ByLoss { _60pct: CohortName::new("utxos_over_60pct_in_loss", "≥60%L", "60%+ Loss"), _70pct: CohortName::new("utxos_over_70pct_in_loss", "≥70%L", "70%+ Loss"), _80pct: CohortName::new("utxos_over_80pct_in_loss", "≥80%L", "80%+ Loss"), - _90pct: CohortName::new("utxos_over_90pct_in_loss", "≥90%L", "90%+ Loss"), }; /// Number of loss thresholds. -pub const LOSS_COUNT: usize = 10; +pub const LOSS_COUNT: usize = 9; -impl ByLoss { +impl Loss { pub const fn names() -> &'static Self { &LOSS_NAMES } @@ -31,7 +30,7 @@ impl ByLoss { /// /// Each is a suffix sum over the profitability ranges, from most loss-making up. #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByLoss { +pub struct Loss { pub breakeven: T, pub _10pct: T, pub _20pct: T, @@ -41,10 +40,9 @@ pub struct ByLoss { pub _60pct: T, pub _70pct: T, pub _80pct: T, - pub _90pct: T, } -impl ByLoss { +impl Loss { pub fn new(mut create: F) -> Self where F: FnMut(&'static str) -> T, @@ -60,7 +58,6 @@ impl ByLoss { _60pct: create(n._60pct.id), _70pct: create(n._70pct.id), _80pct: create(n._80pct.id), - _90pct: create(n._90pct.id), } } @@ -79,7 +76,6 @@ impl ByLoss { _60pct: create(n._60pct.id)?, _70pct: create(n._70pct.id)?, _80pct: create(n._80pct.id)?, - _90pct: create(n._90pct.id)?, }) } @@ -94,7 +90,6 @@ impl ByLoss { &self._60pct, &self._70pct, &self._80pct, - &self._90pct, ] .into_iter() } @@ -110,7 +105,6 @@ impl ByLoss { &mut self._60pct, &mut self._70pct, &mut self._80pct, - &mut self._90pct, ] .into_iter() } @@ -129,7 +123,6 @@ impl ByLoss { &mut self._60pct, &mut self._70pct, &mut self._80pct, - &mut self._90pct, ] .into_par_iter() } @@ -146,7 +139,6 @@ impl ByLoss { &mut self._60pct, &mut self._70pct, &mut self._80pct, - &mut self._90pct, ] } } diff --git a/crates/brk_cohort/src/by_min_age.rs b/crates/brk_cohort/src/over_age.rs similarity index 77% rename from crates/brk_cohort/src/by_min_age.rs rename to crates/brk_cohort/src/over_age.rs index 5939f6ea7..199d5a0c6 100644 --- a/crates/brk_cohort/src/by_min_age.rs +++ b/crates/brk_cohort/src/over_age.rs @@ -8,8 +8,8 @@ use super::{ HOURS_10Y, HOURS_12Y, TimeFilter, }; -/// Min age thresholds in hours -pub const MIN_AGE_HOURS: ByMinAge = ByMinAge { +/// Over-age thresholds in hours +pub const OVER_AGE_HOURS: OverAge = OverAge { _1d: HOURS_1D, _1w: HOURS_1W, _1m: HOURS_1M, @@ -30,30 +30,30 @@ pub const MIN_AGE_HOURS: ByMinAge = ByMinAge { _12y: HOURS_12Y, }; -/// Min age filters (GreaterOrEqual threshold in hours) -pub const MIN_AGE_FILTERS: ByMinAge = ByMinAge { - _1d: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1d)), - _1w: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1w)), - _1m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1m)), - _2m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._2m)), - _3m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._3m)), - _4m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._4m)), - _5m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._5m)), - _6m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._6m)), - _1y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1y)), - _2y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._2y)), - _3y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._3y)), - _4y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._4y)), - _5y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._5y)), - _6y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._6y)), - _7y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._7y)), - _8y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._8y)), - _10y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._10y)), - _12y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._12y)), +/// Over-age filters (GreaterOrEqual threshold in hours) +pub const OVER_AGE_FILTERS: OverAge = OverAge { + _1d: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._1d)), + _1w: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._1w)), + _1m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._1m)), + _2m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._2m)), + _3m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._3m)), + _4m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._4m)), + _5m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._5m)), + _6m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._6m)), + _1y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._1y)), + _2y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._2y)), + _3y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._3y)), + _4y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._4y)), + _5y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._5y)), + _6y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._6y)), + _7y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._7y)), + _8y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._8y)), + _10y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._10y)), + _12y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._12y)), }; -/// Min age names -pub const MIN_AGE_NAMES: ByMinAge = ByMinAge { +/// Over-age names +pub const OVER_AGE_NAMES: OverAge = OverAge { _1d: CohortName::new("over_1d_old", "1d+", "Over 1 Day Old"), _1w: CohortName::new("over_1w_old", "1w+", "Over 1 Week Old"), _1m: CohortName::new("over_1m_old", "1m+", "Over 1 Month Old"), @@ -75,7 +75,7 @@ pub const MIN_AGE_NAMES: ByMinAge = ByMinAge { }; #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByMinAge { +pub struct OverAge { pub _1d: T, pub _1w: T, pub _1m: T, @@ -96,19 +96,19 @@ pub struct ByMinAge { pub _12y: T, } -impl ByMinAge { +impl OverAge { pub const fn names() -> &'static Self { - &MIN_AGE_NAMES + &OVER_AGE_NAMES } } -impl ByMinAge { +impl OverAge { pub fn new(mut create: F) -> Self where F: FnMut(Filter, &'static str) -> T, { - let f = MIN_AGE_FILTERS; - let n = MIN_AGE_NAMES; + let f = OVER_AGE_FILTERS; + let n = OVER_AGE_NAMES; Self { _1d: create(f._1d.clone(), n._1d.id), _1w: create(f._1w.clone(), n._1w.id), @@ -135,8 +135,8 @@ impl ByMinAge { where F: FnMut(Filter, &'static str) -> Result, { - let f = MIN_AGE_FILTERS; - let n = MIN_AGE_NAMES; + let f = OVER_AGE_FILTERS; + let n = OVER_AGE_NAMES; Ok(Self { _1d: create(f._1d.clone(), n._1d.id)?, _1w: create(f._1w.clone(), n._1w.id)?, diff --git a/crates/brk_cohort/src/by_ge_amount.rs b/crates/brk_cohort/src/over_amount.rs similarity index 75% rename from crates/brk_cohort/src/by_ge_amount.rs rename to crates/brk_cohort/src/over_amount.rs index b135222bb..5c14bf4b5 100644 --- a/crates/brk_cohort/src/by_ge_amount.rs +++ b/crates/brk_cohort/src/over_amount.rs @@ -5,8 +5,8 @@ use serde::Serialize; use super::{AmountFilter, CohortName, Filter}; -/// Greater-or-equal amount thresholds -pub const GE_AMOUNT_THRESHOLDS: ByGreatEqualAmount = ByGreatEqualAmount { +/// Over-amount thresholds +pub const OVER_AMOUNT_THRESHOLDS: OverAmount = OverAmount { _1sat: Sats::_1, _10sats: Sats::_10, _100sats: Sats::_100, @@ -22,8 +22,8 @@ pub const GE_AMOUNT_THRESHOLDS: ByGreatEqualAmount = ByGreatEqualAmount { _10k_btc: Sats::_10K_BTC, }; -/// Greater-or-equal amount names -pub const GE_AMOUNT_NAMES: ByGreatEqualAmount = ByGreatEqualAmount { +/// Over-amount names +pub const OVER_AMOUNT_NAMES: OverAmount = OverAmount { _1sat: CohortName::new("over_1sat", "1+ sats", "Over 1 Sat"), _10sats: CohortName::new("over_10sats", "10+ sats", "Over 10 Sats"), _100sats: CohortName::new("over_100sats", "100+ sats", "Over 100 Sats"), @@ -39,27 +39,27 @@ pub const GE_AMOUNT_NAMES: ByGreatEqualAmount = ByGreatEqualAmount { _10k_btc: CohortName::new("over_10k_btc", "10k+ BTC", "Over 10K BTC"), }; -/// Greater-or-equal amount filters -pub const GE_AMOUNT_FILTERS: ByGreatEqualAmount = ByGreatEqualAmount { - _1sat: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1sat)), - _10sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10sats)), - _100sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._100sats)), - _1k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1k_sats)), - _10k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10k_sats)), +/// Over-amount filters +pub const OVER_AMOUNT_FILTERS: OverAmount = OverAmount { + _1sat: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1sat)), + _10sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10sats)), + _100sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._100sats)), + _1k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1k_sats)), + _10k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10k_sats)), _100k_sats: Filter::Amount(AmountFilter::GreaterOrEqual( - GE_AMOUNT_THRESHOLDS._100k_sats, + OVER_AMOUNT_THRESHOLDS._100k_sats, )), - _1m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1m_sats)), - _10m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10m_sats)), - _1btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1btc)), - _10btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10btc)), - _100btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._100btc)), - _1k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1k_btc)), - _10k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10k_btc)), + _1m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1m_sats)), + _10m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10m_sats)), + _1btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1btc)), + _10btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10btc)), + _100btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._100btc)), + _1k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1k_btc)), + _10k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10k_btc)), }; #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByGreatEqualAmount { +pub struct OverAmount { pub _1sat: T, pub _10sats: T, pub _100sats: T, @@ -75,19 +75,19 @@ pub struct ByGreatEqualAmount { pub _10k_btc: T, } -impl ByGreatEqualAmount { +impl OverAmount { pub const fn names() -> &'static Self { - &GE_AMOUNT_NAMES + &OVER_AMOUNT_NAMES } } -impl ByGreatEqualAmount { +impl OverAmount { pub fn new(mut create: F) -> Self where F: FnMut(Filter, &'static str) -> T, { - let f = GE_AMOUNT_FILTERS; - let n = GE_AMOUNT_NAMES; + let f = OVER_AMOUNT_FILTERS; + let n = OVER_AMOUNT_NAMES; Self { _1sat: create(f._1sat.clone(), n._1sat.id), _10sats: create(f._10sats.clone(), n._10sats.id), @@ -109,8 +109,8 @@ impl ByGreatEqualAmount { where F: FnMut(Filter, &'static str) -> Result, { - let f = GE_AMOUNT_FILTERS; - let n = GE_AMOUNT_NAMES; + let f = OVER_AMOUNT_FILTERS; + let n = OVER_AMOUNT_NAMES; Ok(Self { _1sat: create(f._1sat.clone(), n._1sat.id)?, _10sats: create(f._10sats.clone(), n._10sats.id)?, diff --git a/crates/brk_cohort/src/by_profit.rs b/crates/brk_cohort/src/profit.rs similarity index 91% rename from crates/brk_cohort/src/by_profit.rs rename to crates/brk_cohort/src/profit.rs index 9c281163a..85a003704 100644 --- a/crates/brk_cohort/src/by_profit.rs +++ b/crates/brk_cohort/src/profit.rs @@ -5,7 +5,7 @@ use serde::Serialize; use super::CohortName; /// "At least X% profit" threshold names (15 thresholds). -pub const PROFIT_NAMES: ByProfit = ByProfit { +pub const PROFIT_NAMES: Profit = Profit { breakeven: CohortName::new("utxos_in_profit", "≥0%", "In Profit (Breakeven+)"), _10pct: CohortName::new("utxos_over_10pct_in_profit", "≥10%", "10%+ Profit"), _20pct: CohortName::new("utxos_over_20pct_in_profit", "≥20%", "20%+ Profit"), @@ -20,13 +20,12 @@ pub const PROFIT_NAMES: ByProfit = ByProfit { _200pct: CohortName::new("utxos_over_200pct_in_profit", "≥200%", "200%+ Profit"), _300pct: CohortName::new("utxos_over_300pct_in_profit", "≥300%", "300%+ Profit"), _500pct: CohortName::new("utxos_over_500pct_in_profit", "≥500%", "500%+ Profit"), - _1000pct: CohortName::new("utxos_over_1000pct_in_profit", "≥1000%", "1000%+ Profit"), }; /// Number of profit thresholds. -pub const PROFIT_COUNT: usize = 15; +pub const PROFIT_COUNT: usize = 14; -impl ByProfit { +impl Profit { pub const fn names() -> &'static Self { &PROFIT_NAMES } @@ -36,7 +35,7 @@ impl ByProfit { /// /// Each is a prefix sum over the profitability ranges, from most profitable down. #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByProfit { +pub struct Profit { pub breakeven: T, pub _10pct: T, pub _20pct: T, @@ -51,10 +50,9 @@ pub struct ByProfit { pub _200pct: T, pub _300pct: T, pub _500pct: T, - pub _1000pct: T, } -impl ByProfit { +impl Profit { pub fn new(mut create: F) -> Self where F: FnMut(&'static str) -> T, @@ -75,7 +73,6 @@ impl ByProfit { _200pct: create(n._200pct.id), _300pct: create(n._300pct.id), _500pct: create(n._500pct.id), - _1000pct: create(n._1000pct.id), } } @@ -99,7 +96,6 @@ impl ByProfit { _200pct: create(n._200pct.id)?, _300pct: create(n._300pct.id)?, _500pct: create(n._500pct.id)?, - _1000pct: create(n._1000pct.id)?, }) } @@ -119,7 +115,6 @@ impl ByProfit { &self._200pct, &self._300pct, &self._500pct, - &self._1000pct, ] .into_iter() } @@ -140,7 +135,6 @@ impl ByProfit { &mut self._200pct, &mut self._300pct, &mut self._500pct, - &mut self._1000pct, ] .into_iter() } @@ -164,7 +158,6 @@ impl ByProfit { &mut self._200pct, &mut self._300pct, &mut self._500pct, - &mut self._1000pct, ] .into_par_iter() } @@ -186,7 +179,6 @@ impl ByProfit { &mut self._200pct, &mut self._300pct, &mut self._500pct, - &mut self._1000pct, ] } } diff --git a/crates/brk_cohort/src/by_profitability_range.rs b/crates/brk_cohort/src/profitability_range.rs similarity index 98% rename from crates/brk_cohort/src/by_profitability_range.rs rename to crates/brk_cohort/src/profitability_range.rs index d345ce842..c04e53f56 100644 --- a/crates/brk_cohort/src/by_profitability_range.rs +++ b/crates/brk_cohort/src/profitability_range.rs @@ -82,7 +82,7 @@ pub fn compute_profitability_boundaries(spot: Cents) -> [Cents; PROFITABILITY_BO } /// Profitability range names (25 ranges, from most profitable to most in loss) -pub const PROFITABILITY_RANGE_NAMES: ByProfitabilityRange = ByProfitabilityRange { +pub const PROFITABILITY_RANGE_NAMES: ProfitabilityRange = ProfitabilityRange { over_1000pct_in_profit: CohortName::new("utxos_over_1000pct_in_profit", ">1000%", "Over 1000% Profit"), _500pct_to_1000pct_in_profit: CohortName::new("utxos_500pct_to_1000pct_in_profit", "500-1000%", "500-1000% Profit"), _300pct_to_500pct_in_profit: CohortName::new("utxos_300pct_to_500pct_in_profit", "300-500%", "300-500% Profit"), @@ -110,7 +110,7 @@ pub const PROFITABILITY_RANGE_NAMES: ByProfitabilityRange = ByProfit _90pct_to_100pct_in_loss: CohortName::new("utxos_90pct_to_100pct_in_loss", "90-100%L", "90-100% Loss"), }; -impl ByProfitabilityRange { +impl ProfitabilityRange { pub const fn names() -> &'static Self { &PROFITABILITY_RANGE_NAMES } @@ -121,7 +121,7 @@ impl ByProfitabilityRange { /// During the k-way merge (ascending price order), the cursor starts at bucket 0 /// (over_1000pct_in_profit, lowest cost basis) and advances as price crosses each boundary. #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByProfitabilityRange { +pub struct ProfitabilityRange { pub over_1000pct_in_profit: T, pub _500pct_to_1000pct_in_profit: T, pub _300pct_to_500pct_in_profit: T, @@ -152,7 +152,7 @@ pub struct ByProfitabilityRange { /// Number of profitability range buckets. pub const PROFITABILITY_RANGE_COUNT: usize = 25; -impl ByProfitabilityRange { +impl ProfitabilityRange { pub fn new(mut create: F) -> Self where F: FnMut(&'static str) -> T, diff --git a/crates/brk_cohort/src/by_spendable_type.rs b/crates/brk_cohort/src/spendable_type.rs similarity index 95% rename from crates/brk_cohort/src/by_spendable_type.rs rename to crates/brk_cohort/src/spendable_type.rs index f4bbc301a..c16ba77dc 100644 --- a/crates/brk_cohort/src/by_spendable_type.rs +++ b/crates/brk_cohort/src/spendable_type.rs @@ -8,7 +8,7 @@ use serde::Serialize; use super::{CohortName, Filter}; /// Spendable type values -pub const SPENDABLE_TYPE_VALUES: BySpendableType = BySpendableType { +pub const SPENDABLE_TYPE_VALUES: SpendableType = SpendableType { p2pk65: OutputType::P2PK65, p2pk33: OutputType::P2PK33, p2pkh: OutputType::P2PKH, @@ -23,7 +23,7 @@ pub const SPENDABLE_TYPE_VALUES: BySpendableType = BySpendableType { }; /// Spendable type filters -pub const SPENDABLE_TYPE_FILTERS: BySpendableType = BySpendableType { +pub const SPENDABLE_TYPE_FILTERS: SpendableType = SpendableType { p2pk65: Filter::Type(SPENDABLE_TYPE_VALUES.p2pk65), p2pk33: Filter::Type(SPENDABLE_TYPE_VALUES.p2pk33), p2pkh: Filter::Type(SPENDABLE_TYPE_VALUES.p2pkh), @@ -38,7 +38,7 @@ pub const SPENDABLE_TYPE_FILTERS: BySpendableType = BySpendableType { }; /// Spendable type names -pub const SPENDABLE_TYPE_NAMES: BySpendableType = BySpendableType { +pub const SPENDABLE_TYPE_NAMES: SpendableType = SpendableType { p2pk65: CohortName::new("p2pk65", "P2PK65", "Pay to Public Key (65 bytes)"), p2pk33: CohortName::new("p2pk33", "P2PK33", "Pay to Public Key (33 bytes)"), p2pkh: CohortName::new("p2pkh", "P2PKH", "Pay to Public Key Hash"), @@ -53,7 +53,7 @@ pub const SPENDABLE_TYPE_NAMES: BySpendableType = BySpendableType { }; #[derive(Default, Clone, Debug, Traversable, Serialize)] -pub struct BySpendableType { +pub struct SpendableType { pub p2pk65: T, pub p2pk33: T, pub p2pkh: T, @@ -67,13 +67,13 @@ pub struct BySpendableType { pub empty: T, } -impl BySpendableType { +impl SpendableType { pub const fn names() -> &'static Self { &SPENDABLE_TYPE_NAMES } } -impl BySpendableType { +impl SpendableType { pub fn new(mut create: F) -> Self where F: FnMut(Filter, &'static str) -> T, @@ -222,7 +222,7 @@ impl BySpendableType { } } -impl Add for BySpendableType +impl Add for SpendableType where T: Add, { @@ -244,7 +244,7 @@ where } } -impl AddAssign for BySpendableType +impl AddAssign for SpendableType where T: AddAssign, { diff --git a/crates/brk_cohort/src/by_max_age.rs b/crates/brk_cohort/src/under_age.rs similarity index 77% rename from crates/brk_cohort/src/by_max_age.rs rename to crates/brk_cohort/src/under_age.rs index e37501d5f..bbe3d0beb 100644 --- a/crates/brk_cohort/src/by_max_age.rs +++ b/crates/brk_cohort/src/under_age.rs @@ -8,8 +8,8 @@ use super::{ HOURS_12Y, HOURS_15Y, TimeFilter, }; -/// Max age thresholds in hours -pub const MAX_AGE_HOURS: ByMaxAge = ByMaxAge { +/// Under-age thresholds in hours +pub const UNDER_AGE_HOURS: UnderAge = UnderAge { _1w: HOURS_1W, _1m: HOURS_1M, _2m: HOURS_2M, @@ -30,30 +30,30 @@ pub const MAX_AGE_HOURS: ByMaxAge = ByMaxAge { _15y: HOURS_15Y, }; -/// Max age filters (LowerThan threshold in hours) -pub const MAX_AGE_FILTERS: ByMaxAge = ByMaxAge { - _1w: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1w)), - _1m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1m)), - _2m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._2m)), - _3m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._3m)), - _4m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._4m)), - _5m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._5m)), - _6m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._6m)), - _1y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1y)), - _2y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._2y)), - _3y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._3y)), - _4y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._4y)), - _5y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._5y)), - _6y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._6y)), - _7y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._7y)), - _8y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._8y)), - _10y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._10y)), - _12y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._12y)), - _15y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._15y)), +/// Under-age filters (LowerThan threshold in hours) +pub const UNDER_AGE_FILTERS: UnderAge = UnderAge { + _1w: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._1w)), + _1m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._1m)), + _2m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._2m)), + _3m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._3m)), + _4m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._4m)), + _5m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._5m)), + _6m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._6m)), + _1y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._1y)), + _2y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._2y)), + _3y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._3y)), + _4y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._4y)), + _5y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._5y)), + _6y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._6y)), + _7y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._7y)), + _8y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._8y)), + _10y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._10y)), + _12y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._12y)), + _15y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._15y)), }; -/// Max age names -pub const MAX_AGE_NAMES: ByMaxAge = ByMaxAge { +/// Under-age names +pub const UNDER_AGE_NAMES: UnderAge = UnderAge { _1w: CohortName::new("under_1w_old", "<1w", "Under 1 Week Old"), _1m: CohortName::new("under_1m_old", "<1m", "Under 1 Month Old"), _2m: CohortName::new("under_2m_old", "<2m", "Under 2 Months Old"), @@ -75,7 +75,7 @@ pub const MAX_AGE_NAMES: ByMaxAge = ByMaxAge { }; #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByMaxAge { +pub struct UnderAge { pub _1w: T, pub _1m: T, pub _2m: T, @@ -96,19 +96,19 @@ pub struct ByMaxAge { pub _15y: T, } -impl ByMaxAge { +impl UnderAge { pub const fn names() -> &'static Self { - &MAX_AGE_NAMES + &UNDER_AGE_NAMES } } -impl ByMaxAge { +impl UnderAge { pub fn new(mut create: F) -> Self where F: FnMut(Filter, &'static str) -> T, { - let f = MAX_AGE_FILTERS; - let n = MAX_AGE_NAMES; + let f = UNDER_AGE_FILTERS; + let n = UNDER_AGE_NAMES; Self { _1w: create(f._1w.clone(), n._1w.id), _1m: create(f._1m.clone(), n._1m.id), @@ -135,8 +135,8 @@ impl ByMaxAge { where F: FnMut(Filter, &'static str) -> Result, { - let f = MAX_AGE_FILTERS; - let n = MAX_AGE_NAMES; + let f = UNDER_AGE_FILTERS; + let n = UNDER_AGE_NAMES; Ok(Self { _1w: create(f._1w.clone(), n._1w.id)?, _1m: create(f._1m.clone(), n._1m.id)?, diff --git a/crates/brk_cohort/src/by_lt_amount.rs b/crates/brk_cohort/src/under_amount.rs similarity index 76% rename from crates/brk_cohort/src/by_lt_amount.rs rename to crates/brk_cohort/src/under_amount.rs index ec93a71da..dd487ab8d 100644 --- a/crates/brk_cohort/src/by_lt_amount.rs +++ b/crates/brk_cohort/src/under_amount.rs @@ -5,8 +5,8 @@ use serde::Serialize; use super::{AmountFilter, CohortName, Filter}; -/// Lower-than amount thresholds -pub const LT_AMOUNT_THRESHOLDS: ByLowerThanAmount = ByLowerThanAmount { +/// Under-amount thresholds +pub const UNDER_AMOUNT_THRESHOLDS: UnderAmount = UnderAmount { _10sats: Sats::_10, _100sats: Sats::_100, _1k_sats: Sats::_1K, @@ -22,8 +22,8 @@ pub const LT_AMOUNT_THRESHOLDS: ByLowerThanAmount = ByLowerThanAmount { _100k_btc: Sats::_100K_BTC, }; -/// Lower-than amount names -pub const LT_AMOUNT_NAMES: ByLowerThanAmount = ByLowerThanAmount { +/// Under-amount names +pub const UNDER_AMOUNT_NAMES: UnderAmount = UnderAmount { _10sats: CohortName::new("under_10sats", "<10 sats", "Under 10 Sats"), _100sats: CohortName::new("under_100sats", "<100 sats", "Under 100 Sats"), _1k_sats: CohortName::new("under_1k_sats", "<1k sats", "Under 1K Sats"), @@ -39,25 +39,25 @@ pub const LT_AMOUNT_NAMES: ByLowerThanAmount = ByLowerThanAmount { _100k_btc: CohortName::new("under_100k_btc", "<100k BTC", "Under 100K BTC"), }; -/// Lower-than amount filters -pub const LT_AMOUNT_FILTERS: ByLowerThanAmount = ByLowerThanAmount { - _10sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10sats)), - _100sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._100sats)), - _1k_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._1k_sats)), - _10k_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10k_sats)), - _100k_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._100k_sats)), - _1m_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._1m_sats)), - _10m_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10m_sats)), - _1btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._1btc)), - _10btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10btc)), - _100btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._100btc)), - _1k_btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._1k_btc)), - _10k_btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10k_btc)), - _100k_btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._100k_btc)), +/// Under-amount filters +pub const UNDER_AMOUNT_FILTERS: UnderAmount = UnderAmount { + _10sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10sats)), + _100sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._100sats)), + _1k_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._1k_sats)), + _10k_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10k_sats)), + _100k_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._100k_sats)), + _1m_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._1m_sats)), + _10m_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10m_sats)), + _1btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._1btc)), + _10btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10btc)), + _100btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._100btc)), + _1k_btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._1k_btc)), + _10k_btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10k_btc)), + _100k_btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._100k_btc)), }; #[derive(Default, Clone, Traversable, Serialize)] -pub struct ByLowerThanAmount { +pub struct UnderAmount { pub _10sats: T, pub _100sats: T, pub _1k_sats: T, @@ -73,19 +73,19 @@ pub struct ByLowerThanAmount { pub _100k_btc: T, } -impl ByLowerThanAmount { +impl UnderAmount { pub const fn names() -> &'static Self { - <_AMOUNT_NAMES + &UNDER_AMOUNT_NAMES } } -impl ByLowerThanAmount { +impl UnderAmount { pub fn new(mut create: F) -> Self where F: FnMut(Filter, &'static str) -> T, { - let f = LT_AMOUNT_FILTERS; - let n = LT_AMOUNT_NAMES; + let f = UNDER_AMOUNT_FILTERS; + let n = UNDER_AMOUNT_NAMES; Self { _10sats: create(f._10sats.clone(), n._10sats.id), _100sats: create(f._100sats.clone(), n._100sats.id), @@ -107,8 +107,8 @@ impl ByLowerThanAmount { where F: FnMut(Filter, &'static str) -> Result, { - let f = LT_AMOUNT_FILTERS; - let n = LT_AMOUNT_NAMES; + let f = UNDER_AMOUNT_FILTERS; + let n = UNDER_AMOUNT_NAMES; Ok(Self { _10sats: create(f._10sats.clone(), n._10sats.id)?, _100sats: create(f._100sats.clone(), n._100sats.id)?, diff --git a/crates/brk_cohort/src/by_unspendable_type.rs b/crates/brk_cohort/src/unspendable_type.rs similarity index 77% rename from crates/brk_cohort/src/by_unspendable_type.rs rename to crates/brk_cohort/src/unspendable_type.rs index 6e288f820..f1772f1cc 100644 --- a/crates/brk_cohort/src/by_unspendable_type.rs +++ b/crates/brk_cohort/src/unspendable_type.rs @@ -3,17 +3,17 @@ use std::ops::{Add, AddAssign}; use brk_traversable::Traversable; #[derive(Default, Clone, Debug, Traversable)] -pub struct ByUnspendableType { +pub struct UnspendableType { pub opreturn: T, } -impl ByUnspendableType { +impl UnspendableType { pub fn as_vec(&self) -> [&T; 1] { [&self.opreturn] } } -impl Add for ByUnspendableType +impl Add for UnspendableType where T: Add, { @@ -25,7 +25,7 @@ where } } -impl AddAssign for ByUnspendableType +impl AddAssign for UnspendableType where T: AddAssign, { diff --git a/crates/brk_cohort/src/utxo.rs b/crates/brk_cohort/src/utxo.rs index bf0da73c9..c76a5355c 100644 --- a/crates/brk_cohort/src/utxo.rs +++ b/crates/brk_cohort/src/utxo.rs @@ -2,23 +2,23 @@ use brk_traversable::Traversable; use rayon::prelude::*; use crate::{ - ByAgeRange, ByAmountRange, ByEpoch, ByGreatEqualAmount, ByLowerThanAmount, ByMaxAge, ByMinAge, - ByClass, BySpendableType, ByTerm, Filter, + AgeRange, AmountRange, ByEpoch, OverAmount, UnderAmount, UnderAge, OverAge, + Class, SpendableType, ByTerm, Filter, }; #[derive(Default, Clone, Traversable)] pub struct UTXOGroups { pub all: T, - pub age_range: ByAgeRange, + pub age_range: AgeRange, pub epoch: ByEpoch, - pub class: ByClass, - pub min_age: ByMinAge, - pub ge_amount: ByGreatEqualAmount, - pub amount_range: ByAmountRange, + pub class: Class, + pub over_age: OverAge, + pub over_amount: OverAmount, + pub amount_range: AmountRange, pub term: ByTerm, - pub type_: BySpendableType, - pub max_age: ByMaxAge, - pub lt_amount: ByLowerThanAmount, + pub type_: SpendableType, + pub under_age: UnderAge, + pub under_amount: UnderAmount, } impl UTXOGroups { @@ -28,16 +28,16 @@ impl UTXOGroups { { Self { all: create(Filter::All, ""), - age_range: ByAgeRange::new(&mut create), + age_range: AgeRange::new(&mut create), epoch: ByEpoch::new(&mut create), - class: ByClass::new(&mut create), - min_age: ByMinAge::new(&mut create), - ge_amount: ByGreatEqualAmount::new(&mut create), - amount_range: ByAmountRange::new(&mut create), + class: Class::new(&mut create), + over_age: OverAge::new(&mut create), + over_amount: OverAmount::new(&mut create), + amount_range: AmountRange::new(&mut create), term: ByTerm::new(&mut create), - type_: BySpendableType::new(&mut create), - max_age: ByMaxAge::new(&mut create), - lt_amount: ByLowerThanAmount::new(&mut create), + type_: SpendableType::new(&mut create), + under_age: UnderAge::new(&mut create), + under_amount: UnderAmount::new(&mut create), } } @@ -45,14 +45,14 @@ impl UTXOGroups { [&self.all] .into_iter() .chain(self.term.iter()) - .chain(self.max_age.iter()) - .chain(self.min_age.iter()) - .chain(self.ge_amount.iter()) + .chain(self.under_age.iter()) + .chain(self.over_age.iter()) + .chain(self.over_amount.iter()) .chain(self.age_range.iter()) .chain(self.epoch.iter()) .chain(self.class.iter()) .chain(self.amount_range.iter()) - .chain(self.lt_amount.iter()) + .chain(self.under_amount.iter()) .chain(self.type_.iter()) } @@ -60,14 +60,14 @@ impl UTXOGroups { [&mut self.all] .into_iter() .chain(self.term.iter_mut()) - .chain(self.max_age.iter_mut()) - .chain(self.min_age.iter_mut()) - .chain(self.ge_amount.iter_mut()) + .chain(self.under_age.iter_mut()) + .chain(self.over_age.iter_mut()) + .chain(self.over_amount.iter_mut()) .chain(self.age_range.iter_mut()) .chain(self.epoch.iter_mut()) .chain(self.class.iter_mut()) .chain(self.amount_range.iter_mut()) - .chain(self.lt_amount.iter_mut()) + .chain(self.under_amount.iter_mut()) .chain(self.type_.iter_mut()) } @@ -78,14 +78,14 @@ impl UTXOGroups { [&mut self.all] .into_par_iter() .chain(self.term.par_iter_mut()) - .chain(self.max_age.par_iter_mut()) - .chain(self.min_age.par_iter_mut()) - .chain(self.ge_amount.par_iter_mut()) + .chain(self.under_age.par_iter_mut()) + .chain(self.over_age.par_iter_mut()) + .chain(self.over_amount.par_iter_mut()) .chain(self.age_range.par_iter_mut()) .chain(self.epoch.par_iter_mut()) .chain(self.class.par_iter_mut()) .chain(self.amount_range.par_iter_mut()) - .chain(self.lt_amount.par_iter_mut()) + .chain(self.under_amount.par_iter_mut()) .chain(self.type_.par_iter_mut()) } @@ -123,10 +123,10 @@ impl UTXOGroups { [&mut self.all] .into_iter() .chain(self.term.iter_mut()) - .chain(self.max_age.iter_mut()) - .chain(self.min_age.iter_mut()) - .chain(self.lt_amount.iter_mut()) - .chain(self.ge_amount.iter_mut()) + .chain(self.under_age.iter_mut()) + .chain(self.over_age.iter_mut()) + .chain(self.under_amount.iter_mut()) + .chain(self.over_amount.iter_mut()) } /// Iterator over aggregate cohorts (all, sth, lth) that compute values from sub-cohorts. diff --git a/crates/brk_computer/src/distribution/cohorts/address/groups.rs b/crates/brk_computer/src/distribution/cohorts/address/groups.rs index 1f3f41358..f1cf4abd3 100644 --- a/crates/brk_computer/src/distribution/cohorts/address/groups.rs +++ b/crates/brk_computer/src/distribution/cohorts/address/groups.rs @@ -1,7 +1,7 @@ use std::path::Path; use brk_cohort::{ - AddressGroups, ByAmountRange, ByGreatEqualAmount, ByLowerThanAmount, Filter, Filtered, + AddressGroups, AmountRange, OverAmount, UnderAmount, Filter, Filtered, }; use brk_error::Result; use brk_traversable::Traversable; @@ -41,9 +41,9 @@ impl AddressCohorts { let none = |f: Filter, name: &'static str| create(f, name, false); Ok(Self(AddressGroups { - amount_range: ByAmountRange::try_new(&full)?, - lt_amount: ByLowerThanAmount::try_new(&none)?, - ge_amount: ByGreatEqualAmount::try_new(&none)?, + amount_range: AmountRange::try_new(&full)?, + under_amount: UnderAmount::try_new(&none)?, + over_amount: OverAmount::try_new(&none)?, })) } @@ -56,9 +56,9 @@ impl AddressCohorts { let pairs: Vec<_> = self .0 - .ge_amount + .over_amount .iter_mut() - .chain(self.0.lt_amount.iter_mut()) + .chain(self.0.under_amount.iter_mut()) .map(|vecs| { let filter = vecs.filter().clone(); ( diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs index b3a565411..96858280e 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/groups.rs @@ -1,8 +1,8 @@ use std::path::Path; use brk_cohort::{ - ByAgeRange, ByAmountRange, ByClass, ByEpoch, ByGreatEqualAmount, ByLowerThanAmount, ByMaxAge, - ByMinAge, BySpendableType, CohortContext, Filter, Filtered, Term, + AgeRange, AmountRange, Class, ByEpoch, OverAmount, UnderAmount, UnderAge, + OverAge, SpendableType, CohortContext, Filter, Filtered, Term, }; use brk_error::Result; use brk_traversable::Traversable; @@ -39,18 +39,18 @@ pub struct UTXOCohorts { pub all: UTXOCohortVecs>, pub sth: UTXOCohortVecs>, pub lth: UTXOCohortVecs>, - pub age_range: ByAgeRange>>, - pub max_age: ByMaxAge>>, - pub min_age: ByMinAge>>, + pub age_range: AgeRange>>, + pub under_age: UnderAge>>, + pub over_age: OverAge>>, pub epoch: ByEpoch>>, - pub class: ByClass>>, - pub ge_amount: ByGreatEqualAmount>>, - pub amount_range: ByAmountRange>>, - pub lt_amount: ByLowerThanAmount>>, + pub class: Class>>, + pub over_amount: OverAmount>>, + pub amount_range: AmountRange>>, + pub under_amount: UnderAmount>>, #[traversable(rename = "type")] - pub type_: BySpendableType>>, + pub type_: SpendableType>>, pub profitability: ProfitabilityMetrics, - pub matured: ByAgeRange>, + pub matured: AgeRange>, #[traversable(skip)] pub(super) fenwick: CostBasisFenwick, /// Cached partition_point positions for tick_tock boundary searches. @@ -104,7 +104,7 @@ impl UTXOCohorts { )) }; - let age_range = ByAgeRange::try_new(&basic_separate)?; + let age_range = AgeRange::try_new(&basic_separate)?; let core_separate = |f: Filter, name: &'static str| -> Result> { @@ -124,7 +124,7 @@ impl UTXOCohorts { }; let epoch = ByEpoch::try_new(&core_separate)?; - let class = ByClass::try_new(&core_separate)?; + let class = Class::try_new(&core_separate)?; // Helper for separate cohorts with MinimalCohortMetrics + MinimalRealizedState let minimal_separate = @@ -144,7 +144,7 @@ impl UTXOCohorts { )) }; - let amount_range = ByAmountRange::try_new(&minimal_separate)?; + let amount_range = AmountRange::try_new(&minimal_separate)?; let type_separate = |f: Filter, name: &'static str| -> Result> { @@ -163,7 +163,7 @@ impl UTXOCohorts { )) }; - let type_ = BySpendableType::try_new(&type_separate)?; + let type_ = SpendableType::try_new(&type_separate)?; // Phase 3: Import "all" cohort with pre-imported supply. let all = UTXOCohortVecs::new( @@ -221,11 +221,11 @@ impl UTXOCohorts { )) }; - // max_age: CoreCohortMetrics (no state, aggregates from age_range) - let max_age = ByMaxAge::try_new(&core_no_state)?; + // under_age: CoreCohortMetrics (no state, aggregates from age_range) + let under_age = UnderAge::try_new(&core_no_state)?; - // min_age: CoreCohortMetrics (no state, aggregates from age_range) - let min_age = ByMinAge::try_new(&core_no_state)?; + // over_age: CoreCohortMetrics (no state, aggregates from age_range) + let over_age = OverAge::try_new(&core_no_state)?; let minimal_no_state = |f: Filter, name: &'static str| -> Result> { @@ -243,10 +243,10 @@ impl UTXOCohorts { )) }; - let lt_amount = ByLowerThanAmount::try_new(&minimal_no_state)?; - let ge_amount = ByGreatEqualAmount::try_new(&minimal_no_state)?; + let under_amount = UnderAmount::try_new(&minimal_no_state)?; + let over_amount = OverAmount::try_new(&minimal_no_state)?; - let matured = ByAgeRange::try_new(&|_f: Filter, + let matured = AgeRange::try_new(&|_f: Filter, name: &'static str| -> Result { AmountPerBlock::forced_import(db, &format!("utxo_{name}_matured"), v, indexes) @@ -259,12 +259,12 @@ impl UTXOCohorts { epoch, class, type_, - max_age, - min_age, + under_age, + over_age, age_range, amount_range, - lt_amount, - ge_amount, + under_amount, + over_amount, profitability, matured, fenwick: CostBasisFenwick::new(), @@ -325,7 +325,7 @@ impl UTXOCohorts { pub(crate) fn push_maturation( &mut self, height: Height, - matured: &ByAgeRange, + matured: &AgeRange, ) -> Result<()> { for (v, &sats) in self.matured.iter_mut().zip(matured.iter()) { v.sats.height.truncate_push(height, sats)?; @@ -398,11 +398,11 @@ impl UTXOCohorts { sth, lth, age_range, - max_age, - min_age, - ge_amount, + under_age, + over_age, + over_amount, amount_range, - lt_amount, + under_amount, .. } = self; @@ -424,21 +424,21 @@ impl UTXOCohorts { lth.metrics.compute_base_from_others(si, &sources, exit) }), Box::new(|| { - min_age.par_iter_mut().try_for_each(|vecs| { + over_age.par_iter_mut().try_for_each(|vecs| { let sources = filter_sources_from(ar.iter(), Some(&vecs.metrics.filter)); vecs.metrics.compute_from_base_sources(si, &sources, exit) }) }), Box::new(|| { - max_age.par_iter_mut().try_for_each(|vecs| { + under_age.par_iter_mut().try_for_each(|vecs| { let sources = filter_sources_from(ar.iter(), Some(&vecs.metrics.filter)); vecs.metrics.compute_from_base_sources(si, &sources, exit) }) }), Box::new(|| { - ge_amount + over_amount .par_iter_mut() - .chain(lt_amount.par_iter_mut()) + .chain(under_amount.par_iter_mut()) .try_for_each(|vecs| { let sources = filter_minimal_sources_from(amr.iter(), Some(&vecs.metrics.filter)); @@ -471,10 +471,10 @@ impl UTXOCohorts { all.push(&mut self.all); all.push(&mut self.sth); all.push(&mut self.lth); - all.extend(self.max_age.iter_mut().map(|x| x as &mut dyn DynCohortVecs)); - all.extend(self.min_age.iter_mut().map(|x| x as &mut dyn DynCohortVecs)); + all.extend(self.under_age.iter_mut().map(|x| x as &mut dyn DynCohortVecs)); + all.extend(self.over_age.iter_mut().map(|x| x as &mut dyn DynCohortVecs)); all.extend( - self.ge_amount + self.over_amount .iter_mut() .map(|x| x as &mut dyn DynCohortVecs), ); @@ -491,7 +491,7 @@ impl UTXOCohorts { .map(|x| x as &mut dyn DynCohortVecs), ); all.extend( - self.lt_amount + self.under_amount .iter_mut() .map(|x| x as &mut dyn DynCohortVecs), ); @@ -563,11 +563,11 @@ impl UTXOCohorts { sth, lth, age_range, - max_age, - min_age, - ge_amount, + under_age, + over_age, + over_amount, amount_range, - lt_amount, + under_amount, epoch, class, type_, @@ -610,19 +610,19 @@ impl UTXOCohorts { }) }), Box::new(|| { - max_age.par_iter_mut().try_for_each(|v| { + under_age.par_iter_mut().try_for_each(|v| { v.metrics .compute_rest_part2(blocks, prices, starting_indexes, ss, exit) }) }), Box::new(|| { - min_age.par_iter_mut().try_for_each(|v| { + over_age.par_iter_mut().try_for_each(|v| { v.metrics .compute_rest_part2(blocks, prices, starting_indexes, ss, exit) }) }), Box::new(|| { - ge_amount + over_amount .par_iter_mut() .try_for_each(|v| v.metrics.compute_rest_part2(prices, starting_indexes, exit)) }), @@ -644,7 +644,7 @@ impl UTXOCohorts { .try_for_each(|v| v.metrics.compute_rest_part2(prices, starting_indexes, exit)) }), Box::new(|| { - lt_amount + under_amount .par_iter_mut() .try_for_each(|v| v.metrics.compute_rest_part2(prices, starting_indexes, exit)) }), @@ -674,13 +674,13 @@ impl UTXOCohorts { for v in self.age_range.iter_mut() { vecs.extend(v.metrics.collect_all_vecs_mut()); } - for v in self.max_age.iter_mut() { + for v in self.under_age.iter_mut() { vecs.extend(v.metrics.collect_all_vecs_mut()); } - for v in self.min_age.iter_mut() { + for v in self.over_age.iter_mut() { vecs.extend(v.metrics.collect_all_vecs_mut()); } - for v in self.ge_amount.iter_mut() { + for v in self.over_amount.iter_mut() { vecs.extend(v.metrics.collect_all_vecs_mut()); } for v in self.epoch.iter_mut() { @@ -692,7 +692,7 @@ impl UTXOCohorts { for v in self.amount_range.iter_mut() { vecs.extend(v.metrics.collect_all_vecs_mut()); } - for v in self.lt_amount.iter_mut() { + for v in self.under_amount.iter_mut() { vecs.extend(v.metrics.collect_all_vecs_mut()); } for v in self.type_.iter_mut() { @@ -764,10 +764,10 @@ impl UTXOCohorts { self.all.metrics.validate_computed_versions(base_version)?; self.sth.metrics.validate_computed_versions(base_version)?; self.lth.metrics.validate_computed_versions(base_version)?; - for v in self.min_age.iter_mut() { + for v in self.over_age.iter_mut() { v.metrics.validate_computed_versions(base_version)?; } - for v in self.max_age.iter_mut() { + for v in self.under_age.iter_mut() { v.metrics.validate_computed_versions(base_version)?; } Ok(()) diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/percentiles.rs b/crates/brk_computer/src/distribution/cohorts/utxo/percentiles.rs index e853b1e8f..d48918759 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/percentiles.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/percentiles.rs @@ -121,8 +121,8 @@ fn push_profitability( bucket.truncate_push(height, Sats::from(sats), raw_usd_to_dollars(usd_raw))?; } - // ByProfit: forward cumulative sum over ranges[0..15], pushed in reverse. - // profit[0] (breakeven) = sum(0..=14), ..., profit[14] (_1000pct) = ranges[0] + // Profit: forward cumulative sum over ranges[0..15], pushed in reverse. + // profit[0] (breakeven) = sum(0..=13), ..., profit[13] (_500pct) = ranges[0] let profit_arr = metrics.profit.as_array_mut(); let mut cum_sats = 0u64; let mut cum_usd = 0u128; @@ -133,8 +133,8 @@ fn push_profitability( .truncate_push(height, Sats::from(cum_sats), raw_usd_to_dollars(cum_usd))?; } - // ByLoss: backward cumulative sum over ranges[15..25], pushed in reverse. - // loss[0] (breakeven) = sum(15..=24), ..., loss[9] (_90pct) = ranges[24] + // Loss: backward cumulative sum over ranges[15..25], pushed in reverse. + // loss[0] (breakeven) = sum(15..=24), ..., loss[8] (_80pct) = ranges[24] let loss_arr = metrics.loss.as_array_mut(); let loss_count = loss_arr.len(); cum_sats = 0; diff --git a/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs b/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs index 6c805773e..f37737bc6 100644 --- a/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs +++ b/crates/brk_computer/src/distribution/cohorts/utxo/tick_tock.rs @@ -1,4 +1,4 @@ -use brk_cohort::{AGE_BOUNDARIES, ByAgeRange}; +use brk_cohort::{AGE_BOUNDARIES, AgeRange}; use brk_types::{CostBasisSnapshot, ONE_HOUR_IN_SEC, Sats, Timestamp}; use vecdb::{Rw, unlikely}; @@ -22,9 +22,9 @@ impl UTXOCohorts { &mut self, chain_state: &[BlockState], timestamp: Timestamp, - ) -> ByAgeRange { + ) -> AgeRange { if chain_state.is_empty() { - return ByAgeRange::default(); + return AgeRange::default(); } let prev_timestamp = chain_state.last().unwrap().timestamp; @@ -32,7 +32,7 @@ impl UTXOCohorts { // Skip if no time has passed if elapsed == 0 { - return ByAgeRange::default(); + return AgeRange::default(); } let mut matured = [Sats::ZERO; 21]; @@ -96,6 +96,6 @@ impl UTXOCohorts { } } - ByAgeRange::from_array(matured) + AgeRange::from_array(matured) } } diff --git a/crates/brk_computer/src/distribution/metrics/cohort/core.rs b/crates/brk_computer/src/distribution/metrics/cohort/core.rs index 8d1ffc34b..44916bc3b 100644 --- a/crates/brk_computer/src/distribution/metrics/cohort/core.rs +++ b/crates/brk_computer/src/distribution/metrics/cohort/core.rs @@ -62,7 +62,7 @@ impl CoreCohortMetrics { vecs } - /// Aggregate Core-tier fields from CohortMetricsBase sources (e.g. age_range → max_age/min_age). + /// Aggregate Core-tier fields from CohortMetricsBase sources (e.g. age_range → under_age/over_age). pub(crate) fn compute_from_base_sources( &mut self, starting_indexes: &Indexes, diff --git a/crates/brk_computer/src/distribution/metrics/profitability.rs b/crates/brk_computer/src/distribution/metrics/profitability.rs index 3ac1389de..f1a237a26 100644 --- a/crates/brk_computer/src/distribution/metrics/profitability.rs +++ b/crates/brk_computer/src/distribution/metrics/profitability.rs @@ -1,4 +1,4 @@ -use brk_cohort::{ByLoss, ByProfit, ByProfitabilityRange}; +use brk_cohort::{Loss, Profit, ProfitabilityRange}; use brk_error::Result; use brk_traversable::Traversable; use brk_types::{Dollars, Height, Sats, Version}; @@ -66,9 +66,9 @@ impl ProfitabilityBucket { /// All profitability metrics: 25 ranges + 15 profit thresholds + 10 loss thresholds. #[derive(Traversable)] pub struct ProfitabilityMetrics { - pub range: ByProfitabilityRange>, - pub profit: ByProfit>, - pub loss: ByLoss>, + pub range: ProfitabilityRange>, + pub profit: Profit>, + pub loss: Loss>, } impl ProfitabilityMetrics { @@ -88,15 +88,15 @@ impl ProfitabilityMetrics { version: Version, indexes: &indexes::Vecs, ) -> Result { - let range = ByProfitabilityRange::try_new(|name| { + let range = ProfitabilityRange::try_new(|name| { ProfitabilityBucket::forced_import(db, name, version, indexes) })?; - let profit = ByProfit::try_new(|name| { + let profit = Profit::try_new(|name| { ProfitabilityBucket::forced_import(db, name, version, indexes) })?; - let loss = ByLoss::try_new(|name| { + let loss = Loss::try_new(|name| { ProfitabilityBucket::forced_import(db, name, version, indexes) })?; diff --git a/crates/brk_computer/src/distribution/state/cost_basis/realized.rs b/crates/brk_computer/src/distribution/state/cost_basis/realized.rs index 0ba846f31..ac1df0018 100644 --- a/crates/brk_computer/src/distribution/state/cost_basis/realized.rs +++ b/crates/brk_computer/src/distribution/state/cost_basis/realized.rs @@ -151,7 +151,7 @@ impl RealizedOps for MinimalRealizedState { } /// Core realized state: extends Minimal with sent_in_profit/loss tracking. -/// Used by CoreCohortMetrics cohorts (epoch, class, max_age, min_age — ~59 separate cohorts). +/// Used by CoreCohortMetrics cohorts (epoch, class, under_age, over_age — ~59 separate cohorts). #[derive(Debug, Default, Clone)] pub struct CoreRealizedState { minimal: MinimalRealizedState, diff --git a/crates/brk_computer/src/distribution/state/transacted.rs b/crates/brk_computer/src/distribution/state/transacted.rs index 8dd8cddc9..d9f1e6048 100644 --- a/crates/brk_computer/src/distribution/state/transacted.rs +++ b/crates/brk_computer/src/distribution/state/transacted.rs @@ -1,14 +1,14 @@ use std::ops::{Add, AddAssign}; -use brk_cohort::{ByAmountRange, GroupedByType}; +use brk_cohort::{AmountRange, ByType}; use brk_types::{OutputType, Sats, SupplyState}; use vecdb::unlikely; #[derive(Default, Debug)] pub struct Transacted { pub spendable_supply: SupplyState, - pub by_type: GroupedByType, - pub by_size_group: ByAmountRange, + pub by_type: ByType, + pub by_size_group: AmountRange, } impl Transacted { diff --git a/crates/brk_query/src/impl/metrics.rs b/crates/brk_query/src/impl/metrics.rs index 2a43cfc68..26c5634f1 100644 --- a/crates/brk_query/src/impl/metrics.rs +++ b/crates/brk_query/src/impl/metrics.rs @@ -116,6 +116,24 @@ impl Query { vec.last_json_value().ok_or(Error::NoData) } + /// Returns the length (total data points) for a single metric. + pub fn len(&self, metric: &Metric, index: Index) -> Result { + let vec = self + .vecs() + .get(metric, index) + .ok_or_else(|| self.metric_not_found_error(metric))?; + Ok(vec.len()) + } + + /// Returns the version for a single metric. + pub fn version(&self, metric: &Metric, index: Index) -> Result { + let vec = self + .vecs() + .get(metric, index) + .ok_or_else(|| self.metric_not_found_error(metric))?; + Ok(vec.version()) + } + /// Search for vecs matching the given metrics and index. /// Returns error if no metrics requested or any requested metric is not found. pub fn search(&self, params: &MetricSelection) -> Result> { @@ -290,7 +308,7 @@ impl Query { let indexes = index_to_vec.keys().copied().collect(); Some(MetricInfo { indexes, - value_type, + value_type: value_type.into(), }) } diff --git a/crates/brk_server/src/api/metrics/mod.rs b/crates/brk_server/src/api/metrics/mod.rs index 07b49c2fe..bff5b8bf6 100644 --- a/crates/brk_server/src/api/metrics/mod.rs +++ b/crates/brk_server/src/api/metrics/mod.rs @@ -195,6 +195,50 @@ impl ApiMetricsRoutes for ApiRouter { .not_found(), ), ) + .api_route( + "/api/metric/{metric}/{index}/len", + get_with( + async |uri: Uri, + headers: HeaderMap, + State(state): State, + Path(path): Path| { + state + .cached_json(&headers, CacheStrategy::Height, &uri, move |q| { + q.len(&path.metric, path.index) + }) + .await + }, + |op| op + .id("get_metric_len") + .metrics_tag() + .summary("Get metric data length") + .description("Returns the total number of data points for a metric at the given index.") + .ok_response::() + .not_found(), + ), + ) + .api_route( + "/api/metric/{metric}/{index}/version", + get_with( + async |uri: Uri, + headers: HeaderMap, + State(state): State, + Path(path): Path| { + state + .cached_json(&headers, CacheStrategy::Height, &uri, move |q| { + q.version(&path.metric, path.index) + }) + .await + }, + |op| op + .id("get_metric_version") + .metrics_tag() + .summary("Get metric version") + .description("Returns the current version of a metric. Changes when the metric data is updated.") + .ok_response::() + .not_found(), + ), + ) .api_route( "/api/metric/{metric}/{index}/data", get_with( diff --git a/crates/brk_traversable_derive/src/lib.rs b/crates/brk_traversable_derive/src/lib.rs index 5f59ef4ff..cd4efdc7c 100644 --- a/crates/brk_traversable_derive/src/lib.rs +++ b/crates/brk_traversable_derive/src/lib.rs @@ -395,6 +395,7 @@ fn generate_field_traversals(infos: &[FieldInfo], merge: bool) -> proc_macro2::T let field_name = info.name; let field_name_str = { let s = field_name.to_string(); + let s = s.strip_prefix("r#").unwrap_or(&s).to_string(); s.strip_prefix('_').map(String::from).unwrap_or(s) }; diff --git a/crates/brk_types/src/metricinfo.rs b/crates/brk_types/src/metricinfo.rs index 4f4aa8a3c..670f1af38 100644 --- a/crates/brk_types/src/metricinfo.rs +++ b/crates/brk_types/src/metricinfo.rs @@ -1,14 +1,16 @@ +use std::borrow::Cow; + use schemars::JsonSchema; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use crate::Index; /// Metadata about a metric -#[derive(Debug, Serialize, JsonSchema)] +#[derive(Debug, Serialize, Deserialize, JsonSchema)] pub struct MetricInfo { /// Available indexes pub indexes: Vec, /// Value type (e.g. "f32", "u64", "Sats") #[serde(rename = "type")] - pub value_type: &'static str, + pub value_type: Cow<'static, str>, } diff --git a/modules/brk-client/index.js b/modules/brk-client/index.js index 3981510d5..87fb457ed 100644 --- a/modules/brk-client/index.js +++ b/modules/brk-client/index.js @@ -3270,7 +3270,7 @@ function createInRawSumPattern2(client, acc) { * @property {UnspentPattern} outputs * @property {CapLossMvrvNuplPriceProfitSoprPattern} realized * @property {HalvedInTotalPattern} supply - * @property {LossProfitPattern2} unrealized + * @property {LossProfitPattern} unrealized */ /** @@ -3284,7 +3284,7 @@ function createOutputsRealizedSupplyUnrealizedPattern(client, acc) { outputs: createUnspentPattern(client, _m(acc, 'utxo_count')), realized: createCapLossMvrvNuplPriceProfitSoprPattern(client, acc), supply: createHalvedInTotalPattern(client, _m(acc, 'supply')), - unrealized: createLossProfitPattern2(client, _m(acc, 'unrealized')), + unrealized: createLossProfitPattern(client, _m(acc, 'unrealized')), }; } @@ -3983,18 +3983,18 @@ function createInPattern(client, acc) { } /** - * @typedef {Object} LossProfitPattern2 + * @typedef {Object} LossProfitPattern * @property {RawSumPattern2} loss * @property {RawSumPattern2} profit */ /** - * Create a LossProfitPattern2 pattern node + * Create a LossProfitPattern pattern node * @param {BrkClientBase} client * @param {string} acc - Accumulated metric name - * @returns {LossProfitPattern2} + * @returns {LossProfitPattern} */ -function createLossProfitPattern2(client, acc) { +function createLossProfitPattern(client, acc) { return { loss: createRawSumPattern2(client, _m(acc, 'loss')), profit: createRawSumPattern2(client, _m(acc, 'profit')), @@ -5390,7 +5390,7 @@ function createRawPattern2(client, acc) { * @typedef {Object} MetricsTree_Market_Dca_Period * @property {_10y1m1w1y2y3m3y4y5y6m6y8yPattern3} stack * @property {MetricsTree_Market_Dca_Period_CostBasis} costBasis - * @property {_10y1m1w1y2y3m3y4y5y6m6y8yPattern2} r#return + * @property {_10y1m1w1y2y3m3y4y5y6m6y8yPattern2} return * @property {_10y2y3y4y5y6y8yPattern} cagr * @property {_10y1m1w1y2y3m3y4y5y6m6y8yPattern3} lumpSumStack * @property {_10y1m1w1y2y3m3y4y5y6m6y8yPattern2} lumpSumReturn @@ -5416,7 +5416,7 @@ function createRawPattern2(client, acc) { * @typedef {Object} MetricsTree_Market_Dca_Class * @property {MetricsTree_Market_Dca_Class_Stack} stack * @property {MetricsTree_Market_Dca_Class_CostBasis} costBasis - * @property {MetricsTree_Market_Dca_Class_R#return} r#return + * @property {MetricsTree_Market_Dca_Class_Return} return */ /** @@ -5452,7 +5452,7 @@ function createRawPattern2(client, acc) { */ /** - * @typedef {Object} MetricsTree_Market_Dca_Class_R#return + * @typedef {Object} MetricsTree_Market_Dca_Class_Return * @property {BpsPercentRatioPattern} from2015 * @property {BpsPercentRatioPattern} from2016 * @property {BpsPercentRatioPattern} from2017 @@ -5865,13 +5865,13 @@ function createRawPattern2(client, acc) { * @property {MetricsTree_Distribution_Cohorts_Utxo_Sth} sth * @property {MetricsTree_Distribution_Cohorts_Utxo_Lth} lth * @property {MetricsTree_Distribution_Cohorts_Utxo_AgeRange} ageRange - * @property {MetricsTree_Distribution_Cohorts_Utxo_MaxAge} maxAge - * @property {MetricsTree_Distribution_Cohorts_Utxo_MinAge} minAge + * @property {MetricsTree_Distribution_Cohorts_Utxo_UnderAge} underAge + * @property {MetricsTree_Distribution_Cohorts_Utxo_OverAge} overAge * @property {MetricsTree_Distribution_Cohorts_Utxo_Epoch} epoch * @property {MetricsTree_Distribution_Cohorts_Utxo_Class} class - * @property {MetricsTree_Distribution_Cohorts_Utxo_GeAmount} geAmount + * @property {MetricsTree_Distribution_Cohorts_Utxo_OverAmount} overAmount * @property {MetricsTree_Distribution_Cohorts_Utxo_AmountRange} amountRange - * @property {MetricsTree_Distribution_Cohorts_Utxo_LtAmount} ltAmount + * @property {MetricsTree_Distribution_Cohorts_Utxo_UnderAmount} underAmount * @property {MetricsTree_Distribution_Cohorts_Utxo_Type} type * @property {MetricsTree_Distribution_Cohorts_Utxo_Profitability} profitability * @property {MetricsTree_Distribution_Cohorts_Utxo_Matured} matured @@ -6012,7 +6012,7 @@ function createRawPattern2(client, acc) { */ /** - * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_MaxAge + * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_UnderAge * @property {ActivityOutputsRealizedSupplyUnrealizedPattern2} _1w * @property {ActivityOutputsRealizedSupplyUnrealizedPattern2} _1m * @property {ActivityOutputsRealizedSupplyUnrealizedPattern2} _2m @@ -6034,7 +6034,7 @@ function createRawPattern2(client, acc) { */ /** - * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_MinAge + * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_OverAge * @property {ActivityOutputsRealizedSupplyUnrealizedPattern2} _1d * @property {ActivityOutputsRealizedSupplyUnrealizedPattern2} _1w * @property {ActivityOutputsRealizedSupplyUnrealizedPattern2} _1m @@ -6087,7 +6087,7 @@ function createRawPattern2(client, acc) { */ /** - * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_GeAmount + * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_OverAmount * @property {OutputsRealizedSupplyPattern} _1sat * @property {OutputsRealizedSupplyPattern} _10sats * @property {OutputsRealizedSupplyPattern} _100sats @@ -6123,7 +6123,7 @@ function createRawPattern2(client, acc) { */ /** - * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_LtAmount + * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_UnderAmount * @property {OutputsRealizedSupplyPattern} _10sats * @property {OutputsRealizedSupplyPattern} _100sats * @property {OutputsRealizedSupplyPattern} _1kSats @@ -6163,31 +6163,31 @@ function createRawPattern2(client, acc) { /** * @typedef {Object} MetricsTree_Distribution_Cohorts_Utxo_Profitability_Range - * @property {RealizedSupplyPattern} profitOver1000 - * @property {RealizedSupplyPattern} profit500To1000 - * @property {RealizedSupplyPattern} profit300To500 - * @property {RealizedSupplyPattern} profit200To300 - * @property {RealizedSupplyPattern} profit100To200 - * @property {RealizedSupplyPattern} profit90To100 - * @property {RealizedSupplyPattern} profit80To90 - * @property {RealizedSupplyPattern} profit70To80 - * @property {RealizedSupplyPattern} profit60To70 - * @property {RealizedSupplyPattern} profit50To60 - * @property {RealizedSupplyPattern} profit40To50 - * @property {RealizedSupplyPattern} profit30To40 - * @property {RealizedSupplyPattern} profit20To30 - * @property {RealizedSupplyPattern} profit10To20 - * @property {RealizedSupplyPattern} profit0To10 - * @property {RealizedSupplyPattern} loss0To10 - * @property {RealizedSupplyPattern} loss10To20 - * @property {RealizedSupplyPattern} loss20To30 - * @property {RealizedSupplyPattern} loss30To40 - * @property {RealizedSupplyPattern} loss40To50 - * @property {RealizedSupplyPattern} loss50To60 - * @property {RealizedSupplyPattern} loss60To70 - * @property {RealizedSupplyPattern} loss70To80 - * @property {RealizedSupplyPattern} loss80To90 - * @property {RealizedSupplyPattern} loss90To100 + * @property {RealizedSupplyPattern} over1000pctInProfit + * @property {RealizedSupplyPattern} _500pctTo1000pctInProfit + * @property {RealizedSupplyPattern} _300pctTo500pctInProfit + * @property {RealizedSupplyPattern} _200pctTo300pctInProfit + * @property {RealizedSupplyPattern} _100pctTo200pctInProfit + * @property {RealizedSupplyPattern} _90pctTo100pctInProfit + * @property {RealizedSupplyPattern} _80pctTo90pctInProfit + * @property {RealizedSupplyPattern} _70pctTo80pctInProfit + * @property {RealizedSupplyPattern} _60pctTo70pctInProfit + * @property {RealizedSupplyPattern} _50pctTo60pctInProfit + * @property {RealizedSupplyPattern} _40pctTo50pctInProfit + * @property {RealizedSupplyPattern} _30pctTo40pctInProfit + * @property {RealizedSupplyPattern} _20pctTo30pctInProfit + * @property {RealizedSupplyPattern} _10pctTo20pctInProfit + * @property {RealizedSupplyPattern} _0pctTo10pctInProfit + * @property {RealizedSupplyPattern} _0pctTo10pctInLoss + * @property {RealizedSupplyPattern} _10pctTo20pctInLoss + * @property {RealizedSupplyPattern} _20pctTo30pctInLoss + * @property {RealizedSupplyPattern} _30pctTo40pctInLoss + * @property {RealizedSupplyPattern} _40pctTo50pctInLoss + * @property {RealizedSupplyPattern} _50pctTo60pctInLoss + * @property {RealizedSupplyPattern} _60pctTo70pctInLoss + * @property {RealizedSupplyPattern} _70pctTo80pctInLoss + * @property {RealizedSupplyPattern} _80pctTo90pctInLoss + * @property {RealizedSupplyPattern} _90pctTo100pctInLoss */ /** @@ -6206,7 +6206,6 @@ function createRawPattern2(client, acc) { * @property {RealizedSupplyPattern} _200pct * @property {RealizedSupplyPattern} _300pct * @property {RealizedSupplyPattern} _500pct - * @property {RealizedSupplyPattern} _1000pct */ /** @@ -6220,7 +6219,6 @@ function createRawPattern2(client, acc) { * @property {RealizedSupplyPattern} _60pct * @property {RealizedSupplyPattern} _70pct * @property {RealizedSupplyPattern} _80pct - * @property {RealizedSupplyPattern} _90pct */ /** @@ -6250,13 +6248,13 @@ function createRawPattern2(client, acc) { /** * @typedef {Object} MetricsTree_Distribution_Cohorts_Address - * @property {MetricsTree_Distribution_Cohorts_Address_GeAmount} geAmount + * @property {MetricsTree_Distribution_Cohorts_Address_OverAmount} overAmount * @property {MetricsTree_Distribution_Cohorts_Address_AmountRange} amountRange - * @property {MetricsTree_Distribution_Cohorts_Address_LtAmount} ltAmount + * @property {MetricsTree_Distribution_Cohorts_Address_UnderAmount} underAmount */ /** - * @typedef {Object} MetricsTree_Distribution_Cohorts_Address_GeAmount + * @typedef {Object} MetricsTree_Distribution_Cohorts_Address_OverAmount * @property {AddrOutputsRealizedSupplyPattern} _1sat * @property {AddrOutputsRealizedSupplyPattern} _10sats * @property {AddrOutputsRealizedSupplyPattern} _100sats @@ -6292,7 +6290,7 @@ function createRawPattern2(client, acc) { */ /** - * @typedef {Object} MetricsTree_Distribution_Cohorts_Address_LtAmount + * @typedef {Object} MetricsTree_Distribution_Cohorts_Address_UnderAmount * @property {AddrOutputsRealizedSupplyPattern} _10sats * @property {AddrOutputsRealizedSupplyPattern} _100sats * @property {AddrOutputsRealizedSupplyPattern} _1kSats @@ -6847,7 +6845,7 @@ class BrkClient extends BrkClientBase { } }); - MAX_AGE_NAMES = /** @type {const} */ ({ + UNDER_AGE_NAMES = /** @type {const} */ ({ "_1w": { "id": "under_1w_old", "short": "<1w", @@ -6940,7 +6938,7 @@ class BrkClient extends BrkClientBase { } }); - MIN_AGE_NAMES = /** @type {const} */ ({ + OVER_AGE_NAMES = /** @type {const} */ ({ "_1d": { "id": "over_1d_old", "short": "1d+", @@ -7111,7 +7109,7 @@ class BrkClient extends BrkClientBase { } }); - GE_AMOUNT_NAMES = /** @type {const} */ ({ + OVER_AMOUNT_NAMES = /** @type {const} */ ({ "_1sat": { "id": "over_1sat", "short": "1+ sats", @@ -7179,7 +7177,7 @@ class BrkClient extends BrkClientBase { } }); - LT_AMOUNT_NAMES = /** @type {const} */ ({ + UNDER_AMOUNT_NAMES = /** @type {const} */ ({ "_10sats": { "id": "under_10sats", "short": "<10 sats", @@ -7943,7 +7941,7 @@ class BrkClient extends BrkClientBase { _8y: createCentsSatsUsdPattern(this, 'dca_cost_basis_8y'), _10y: createCentsSatsUsdPattern(this, 'dca_cost_basis_10y'), }, - r#return: create_10y1m1w1y2y3m3y4y5y6m6y8yPattern2(this, 'dca_return'), + return: create_10y1m1w1y2y3m3y4y5y6m6y8yPattern2(this, 'dca_return'), cagr: create_10y2y3y4y5y6y8yPattern(this, 'dca_cagr'), lumpSumStack: create_10y1m1w1y2y3m3y4y5y6m6y8yPattern3(this, 'lump_sum_stack'), lumpSumReturn: create_10y1m1w1y2y3m3y4y5y6m6y8yPattern2(this, 'lump_sum_return'), @@ -7977,7 +7975,7 @@ class BrkClient extends BrkClientBase { from2025: createCentsSatsUsdPattern(this, 'dca_cost_basis_from_2025'), from2026: createCentsSatsUsdPattern(this, 'dca_cost_basis_from_2026'), }, - r#return: { + return: { from2015: createBpsPercentRatioPattern(this, 'dca_return_from_2015'), from2016: createBpsPercentRatioPattern(this, 'dca_return_from_2016'), from2017: createBpsPercentRatioPattern(this, 'dca_return_from_2017'), @@ -8410,7 +8408,7 @@ class BrkClient extends BrkClientBase { _12yTo15y: createActivityOutputsRealizedSupplyUnrealizedPattern(this, 'utxos_12y_to_15y_old'), from15y: createActivityOutputsRealizedSupplyUnrealizedPattern(this, 'utxos_over_15y_old'), }, - maxAge: { + underAge: { _1w: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'utxos_under_1w_old'), _1m: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'utxos_under_1m_old'), _2m: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'utxos_under_2m_old'), @@ -8430,7 +8428,7 @@ class BrkClient extends BrkClientBase { _12y: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'utxos_under_12y_old'), _15y: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'utxos_under_15y_old'), }, - minAge: { + overAge: { _1d: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'utxos_over_1d_old'), _1w: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'utxos_over_1w_old'), _1m: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'utxos_over_1m_old'), @@ -8477,7 +8475,7 @@ class BrkClient extends BrkClientBase { _2025: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'class_2025'), _2026: createActivityOutputsRealizedSupplyUnrealizedPattern2(this, 'class_2026'), }, - geAmount: { + overAmount: { _1sat: createOutputsRealizedSupplyPattern(this, 'utxos_over_1sat'), _10sats: createOutputsRealizedSupplyPattern(this, 'utxos_over_10sats'), _100sats: createOutputsRealizedSupplyPattern(this, 'utxos_over_100sats'), @@ -8509,7 +8507,7 @@ class BrkClient extends BrkClientBase { _10kBtcTo100kBtc: createOutputsRealizedSupplyPattern(this, 'utxos_above_10k_btc_under_100k_btc'), _100kBtcOrMore: createOutputsRealizedSupplyPattern(this, 'utxos_above_100k_btc'), }, - ltAmount: { + underAmount: { _10sats: createOutputsRealizedSupplyPattern(this, 'utxos_under_10sats'), _100sats: createOutputsRealizedSupplyPattern(this, 'utxos_under_100sats'), _1kSats: createOutputsRealizedSupplyPattern(this, 'utxos_under_1k_sats'), @@ -8539,60 +8537,58 @@ class BrkClient extends BrkClientBase { }, profitability: { range: { - profitOver1000: createRealizedSupplyPattern(this, 'utxos_over_1000pct_up'), - profit500To1000: createRealizedSupplyPattern(this, 'utxos_500pct_to_1000pct_up'), - profit300To500: createRealizedSupplyPattern(this, 'utxos_300pct_to_500pct_up'), - profit200To300: createRealizedSupplyPattern(this, 'utxos_200pct_to_300pct_up'), - profit100To200: createRealizedSupplyPattern(this, 'utxos_100pct_to_200pct_up'), - profit90To100: createRealizedSupplyPattern(this, 'utxos_90pct_to_100pct_up'), - profit80To90: createRealizedSupplyPattern(this, 'utxos_80pct_to_90pct_up'), - profit70To80: createRealizedSupplyPattern(this, 'utxos_70pct_to_80pct_up'), - profit60To70: createRealizedSupplyPattern(this, 'utxos_60pct_to_70pct_up'), - profit50To60: createRealizedSupplyPattern(this, 'utxos_50pct_to_60pct_up'), - profit40To50: createRealizedSupplyPattern(this, 'utxos_40pct_to_50pct_up'), - profit30To40: createRealizedSupplyPattern(this, 'utxos_30pct_to_40pct_up'), - profit20To30: createRealizedSupplyPattern(this, 'utxos_20pct_to_30pct_up'), - profit10To20: createRealizedSupplyPattern(this, 'utxos_10pct_to_20pct_up'), - profit0To10: createRealizedSupplyPattern(this, 'utxos_0pct_to_10pct_up'), - loss0To10: createRealizedSupplyPattern(this, 'utxos_0pct_to_10pct_down'), - loss10To20: createRealizedSupplyPattern(this, 'utxos_10pct_to_20pct_down'), - loss20To30: createRealizedSupplyPattern(this, 'utxos_20pct_to_30pct_down'), - loss30To40: createRealizedSupplyPattern(this, 'utxos_30pct_to_40pct_down'), - loss40To50: createRealizedSupplyPattern(this, 'utxos_40pct_to_50pct_down'), - loss50To60: createRealizedSupplyPattern(this, 'utxos_50pct_to_60pct_down'), - loss60To70: createRealizedSupplyPattern(this, 'utxos_60pct_to_70pct_down'), - loss70To80: createRealizedSupplyPattern(this, 'utxos_70pct_to_80pct_down'), - loss80To90: createRealizedSupplyPattern(this, 'utxos_80pct_to_90pct_down'), - loss90To100: createRealizedSupplyPattern(this, 'utxos_90pct_to_100pct_down'), + over1000pctInProfit: createRealizedSupplyPattern(this, 'utxos_over_1000pct_in_profit'), + _500pctTo1000pctInProfit: createRealizedSupplyPattern(this, 'utxos_500pct_to_1000pct_in_profit'), + _300pctTo500pctInProfit: createRealizedSupplyPattern(this, 'utxos_300pct_to_500pct_in_profit'), + _200pctTo300pctInProfit: createRealizedSupplyPattern(this, 'utxos_200pct_to_300pct_in_profit'), + _100pctTo200pctInProfit: createRealizedSupplyPattern(this, 'utxos_100pct_to_200pct_in_profit'), + _90pctTo100pctInProfit: createRealizedSupplyPattern(this, 'utxos_90pct_to_100pct_in_profit'), + _80pctTo90pctInProfit: createRealizedSupplyPattern(this, 'utxos_80pct_to_90pct_in_profit'), + _70pctTo80pctInProfit: createRealizedSupplyPattern(this, 'utxos_70pct_to_80pct_in_profit'), + _60pctTo70pctInProfit: createRealizedSupplyPattern(this, 'utxos_60pct_to_70pct_in_profit'), + _50pctTo60pctInProfit: createRealizedSupplyPattern(this, 'utxos_50pct_to_60pct_in_profit'), + _40pctTo50pctInProfit: createRealizedSupplyPattern(this, 'utxos_40pct_to_50pct_in_profit'), + _30pctTo40pctInProfit: createRealizedSupplyPattern(this, 'utxos_30pct_to_40pct_in_profit'), + _20pctTo30pctInProfit: createRealizedSupplyPattern(this, 'utxos_20pct_to_30pct_in_profit'), + _10pctTo20pctInProfit: createRealizedSupplyPattern(this, 'utxos_10pct_to_20pct_in_profit'), + _0pctTo10pctInProfit: createRealizedSupplyPattern(this, 'utxos_0pct_to_10pct_in_profit'), + _0pctTo10pctInLoss: createRealizedSupplyPattern(this, 'utxos_0pct_to_10pct_in_loss'), + _10pctTo20pctInLoss: createRealizedSupplyPattern(this, 'utxos_10pct_to_20pct_in_loss'), + _20pctTo30pctInLoss: createRealizedSupplyPattern(this, 'utxos_20pct_to_30pct_in_loss'), + _30pctTo40pctInLoss: createRealizedSupplyPattern(this, 'utxos_30pct_to_40pct_in_loss'), + _40pctTo50pctInLoss: createRealizedSupplyPattern(this, 'utxos_40pct_to_50pct_in_loss'), + _50pctTo60pctInLoss: createRealizedSupplyPattern(this, 'utxos_50pct_to_60pct_in_loss'), + _60pctTo70pctInLoss: createRealizedSupplyPattern(this, 'utxos_60pct_to_70pct_in_loss'), + _70pctTo80pctInLoss: createRealizedSupplyPattern(this, 'utxos_70pct_to_80pct_in_loss'), + _80pctTo90pctInLoss: createRealizedSupplyPattern(this, 'utxos_80pct_to_90pct_in_loss'), + _90pctTo100pctInLoss: createRealizedSupplyPattern(this, 'utxos_90pct_to_100pct_in_loss'), }, profit: { - breakeven: createRealizedSupplyPattern(this, 'profit_ge_breakeven'), - _10pct: createRealizedSupplyPattern(this, 'profit_ge_10pct'), - _20pct: createRealizedSupplyPattern(this, 'profit_ge_20pct'), - _30pct: createRealizedSupplyPattern(this, 'profit_ge_30pct'), - _40pct: createRealizedSupplyPattern(this, 'profit_ge_40pct'), - _50pct: createRealizedSupplyPattern(this, 'profit_ge_50pct'), - _60pct: createRealizedSupplyPattern(this, 'profit_ge_60pct'), - _70pct: createRealizedSupplyPattern(this, 'profit_ge_70pct'), - _80pct: createRealizedSupplyPattern(this, 'profit_ge_80pct'), - _90pct: createRealizedSupplyPattern(this, 'profit_ge_90pct'), - _100pct: createRealizedSupplyPattern(this, 'profit_ge_100pct'), - _200pct: createRealizedSupplyPattern(this, 'profit_ge_200pct'), - _300pct: createRealizedSupplyPattern(this, 'profit_ge_300pct'), - _500pct: createRealizedSupplyPattern(this, 'profit_ge_500pct'), - _1000pct: createRealizedSupplyPattern(this, 'profit_ge_1000pct'), + breakeven: createRealizedSupplyPattern(this, 'utxos_in_profit'), + _10pct: createRealizedSupplyPattern(this, 'utxos_over_10pct_in_profit'), + _20pct: createRealizedSupplyPattern(this, 'utxos_over_20pct_in_profit'), + _30pct: createRealizedSupplyPattern(this, 'utxos_over_30pct_in_profit'), + _40pct: createRealizedSupplyPattern(this, 'utxos_over_40pct_in_profit'), + _50pct: createRealizedSupplyPattern(this, 'utxos_over_50pct_in_profit'), + _60pct: createRealizedSupplyPattern(this, 'utxos_over_60pct_in_profit'), + _70pct: createRealizedSupplyPattern(this, 'utxos_over_70pct_in_profit'), + _80pct: createRealizedSupplyPattern(this, 'utxos_over_80pct_in_profit'), + _90pct: createRealizedSupplyPattern(this, 'utxos_over_90pct_in_profit'), + _100pct: createRealizedSupplyPattern(this, 'utxos_over_100pct_in_profit'), + _200pct: createRealizedSupplyPattern(this, 'utxos_over_200pct_in_profit'), + _300pct: createRealizedSupplyPattern(this, 'utxos_over_300pct_in_profit'), + _500pct: createRealizedSupplyPattern(this, 'utxos_over_500pct_in_profit'), }, loss: { - breakeven: createRealizedSupplyPattern(this, 'loss_ge_breakeven'), - _10pct: createRealizedSupplyPattern(this, 'loss_ge_10pct'), - _20pct: createRealizedSupplyPattern(this, 'loss_ge_20pct'), - _30pct: createRealizedSupplyPattern(this, 'loss_ge_30pct'), - _40pct: createRealizedSupplyPattern(this, 'loss_ge_40pct'), - _50pct: createRealizedSupplyPattern(this, 'loss_ge_50pct'), - _60pct: createRealizedSupplyPattern(this, 'loss_ge_60pct'), - _70pct: createRealizedSupplyPattern(this, 'loss_ge_70pct'), - _80pct: createRealizedSupplyPattern(this, 'loss_ge_80pct'), - _90pct: createRealizedSupplyPattern(this, 'loss_ge_90pct'), + breakeven: createRealizedSupplyPattern(this, 'utxos_in_loss'), + _10pct: createRealizedSupplyPattern(this, 'utxos_over_10pct_in_loss'), + _20pct: createRealizedSupplyPattern(this, 'utxos_over_20pct_in_loss'), + _30pct: createRealizedSupplyPattern(this, 'utxos_over_30pct_in_loss'), + _40pct: createRealizedSupplyPattern(this, 'utxos_over_40pct_in_loss'), + _50pct: createRealizedSupplyPattern(this, 'utxos_over_50pct_in_loss'), + _60pct: createRealizedSupplyPattern(this, 'utxos_over_60pct_in_loss'), + _70pct: createRealizedSupplyPattern(this, 'utxos_over_70pct_in_loss'), + _80pct: createRealizedSupplyPattern(this, 'utxos_over_80pct_in_loss'), }, }, matured: { @@ -8620,7 +8616,7 @@ class BrkClient extends BrkClientBase { }, }, address: { - geAmount: { + overAmount: { _1sat: createAddrOutputsRealizedSupplyPattern(this, 'addrs_over_1sat'), _10sats: createAddrOutputsRealizedSupplyPattern(this, 'addrs_over_10sats'), _100sats: createAddrOutputsRealizedSupplyPattern(this, 'addrs_over_100sats'), @@ -8652,7 +8648,7 @@ class BrkClient extends BrkClientBase { _10kBtcTo100kBtc: createAddrOutputsRealizedSupplyPattern(this, 'addrs_above_10k_btc_under_100k_btc'), _100kBtcOrMore: createAddrOutputsRealizedSupplyPattern(this, 'addrs_above_100k_btc'), }, - ltAmount: { + underAmount: { _10sats: createAddrOutputsRealizedSupplyPattern(this, 'addrs_under_10sats'), _100sats: createAddrOutputsRealizedSupplyPattern(this, 'addrs_under_100sats'), _1kSats: createAddrOutputsRealizedSupplyPattern(this, 'addrs_under_1k_sats'), @@ -9084,6 +9080,36 @@ class BrkClient extends BrkClientBase { return this.getJson(`/api/metric/${metric}/${index}/latest`); } + /** + * Get metric data length + * + * Returns the total number of data points for a metric at the given index. + * + * Endpoint: `GET /api/metric/{metric}/{index}/len` + * + * @param {Metric} metric - Metric name + * @param {Index} index - Aggregation index + * @returns {Promise} + */ + async getMetricLen(metric, index) { + return this.getJson(`/api/metric/${metric}/${index}/len`); + } + + /** + * Get metric version + * + * Returns the current version of a metric. Changes when the metric data is updated. + * + * Endpoint: `GET /api/metric/{metric}/{index}/version` + * + * @param {Metric} metric - Metric name + * @param {Index} index - Aggregation index + * @returns {Promise} + */ + async getMetricVersion(metric, index) { + return this.getJson(`/api/metric/${metric}/${index}/version`); + } + /** * Metrics catalog * diff --git a/packages/brk_client/brk_client/__init__.py b/packages/brk_client/brk_client/__init__.py index be95d18e9..7ecbca56d 100644 --- a/packages/brk_client/brk_client/__init__.py +++ b/packages/brk_client/brk_client/__init__.py @@ -2863,7 +2863,7 @@ class OutputsRealizedSupplyUnrealizedPattern: self.outputs: UnspentPattern = UnspentPattern(client, _m(acc, 'utxo_count')) self.realized: CapLossMvrvNuplPriceProfitSoprPattern = CapLossMvrvNuplPriceProfitSoprPattern(client, acc) self.supply: HalvedInTotalPattern = HalvedInTotalPattern(client, _m(acc, 'supply')) - self.unrealized: LossProfitPattern2 = LossProfitPattern2(client, _m(acc, 'unrealized')) + self.unrealized: LossProfitPattern = LossProfitPattern(client, _m(acc, 'unrealized')) class _1m1w1y24hPattern(Generic[T]): """Pattern struct for repeated tree structure.""" @@ -3158,7 +3158,7 @@ class InPattern: self.in_loss: RawPattern2[CentsSats] = RawPattern2(client, _m(acc, 'loss_raw')) self.in_profit: RawPattern2[CentsSats] = RawPattern2(client, _m(acc, 'profit_raw')) -class LossProfitPattern2: +class LossProfitPattern: """Pattern struct for repeated tree structure.""" def __init__(self, client: BrkClientBase, acc: str): @@ -4450,7 +4450,7 @@ class MetricsTree_Market_Dca_Class_CostBasis: self.from_2025: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'dca_cost_basis_from_2025') self.from_2026: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'dca_cost_basis_from_2026') -class MetricsTree_Market_Dca_Class_R#return: +class MetricsTree_Market_Dca_Class_Return: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): @@ -4473,7 +4473,7 @@ class MetricsTree_Market_Dca_Class: def __init__(self, client: BrkClientBase, base_path: str = ''): self.stack: MetricsTree_Market_Dca_Class_Stack = MetricsTree_Market_Dca_Class_Stack(client) self.cost_basis: MetricsTree_Market_Dca_Class_CostBasis = MetricsTree_Market_Dca_Class_CostBasis(client) - self.r#return: MetricsTree_Market_Dca_Class_R#return = MetricsTree_Market_Dca_Class_R#return(client) + self.r#return: MetricsTree_Market_Dca_Class_Return = MetricsTree_Market_Dca_Class_Return(client) class MetricsTree_Market_Dca: """Metrics tree node.""" @@ -5044,7 +5044,7 @@ class MetricsTree_Distribution_Cohorts_Utxo_AgeRange: self._12y_to_15y: ActivityOutputsRealizedSupplyUnrealizedPattern = ActivityOutputsRealizedSupplyUnrealizedPattern(client, 'utxos_12y_to_15y_old') self.from_15y: ActivityOutputsRealizedSupplyUnrealizedPattern = ActivityOutputsRealizedSupplyUnrealizedPattern(client, 'utxos_over_15y_old') -class MetricsTree_Distribution_Cohorts_Utxo_MaxAge: +class MetricsTree_Distribution_Cohorts_Utxo_UnderAge: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): @@ -5067,7 +5067,7 @@ class MetricsTree_Distribution_Cohorts_Utxo_MaxAge: self._12y: ActivityOutputsRealizedSupplyUnrealizedPattern2 = ActivityOutputsRealizedSupplyUnrealizedPattern2(client, 'utxos_under_12y_old') self._15y: ActivityOutputsRealizedSupplyUnrealizedPattern2 = ActivityOutputsRealizedSupplyUnrealizedPattern2(client, 'utxos_under_15y_old') -class MetricsTree_Distribution_Cohorts_Utxo_MinAge: +class MetricsTree_Distribution_Cohorts_Utxo_OverAge: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): @@ -5123,7 +5123,7 @@ class MetricsTree_Distribution_Cohorts_Utxo_Class: self._2025: ActivityOutputsRealizedSupplyUnrealizedPattern2 = ActivityOutputsRealizedSupplyUnrealizedPattern2(client, 'class_2025') self._2026: ActivityOutputsRealizedSupplyUnrealizedPattern2 = ActivityOutputsRealizedSupplyUnrealizedPattern2(client, 'class_2026') -class MetricsTree_Distribution_Cohorts_Utxo_GeAmount: +class MetricsTree_Distribution_Cohorts_Utxo_OverAmount: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): @@ -5161,7 +5161,7 @@ class MetricsTree_Distribution_Cohorts_Utxo_AmountRange: self._10k_btc_to_100k_btc: OutputsRealizedSupplyPattern = OutputsRealizedSupplyPattern(client, 'utxos_above_10k_btc_under_100k_btc') self._100k_btc_or_more: OutputsRealizedSupplyPattern = OutputsRealizedSupplyPattern(client, 'utxos_above_100k_btc') -class MetricsTree_Distribution_Cohorts_Utxo_LtAmount: +class MetricsTree_Distribution_Cohorts_Utxo_UnderAmount: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): @@ -5199,66 +5199,64 @@ class MetricsTree_Distribution_Cohorts_Utxo_Profitability_Range: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.profit_over_1000: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_1000pct_up') - self.profit_500_to_1000: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_500pct_to_1000pct_up') - self.profit_300_to_500: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_300pct_to_500pct_up') - self.profit_200_to_300: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_200pct_to_300pct_up') - self.profit_100_to_200: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_100pct_to_200pct_up') - self.profit_90_to_100: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_90pct_to_100pct_up') - self.profit_80_to_90: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_80pct_to_90pct_up') - self.profit_70_to_80: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_70pct_to_80pct_up') - self.profit_60_to_70: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_60pct_to_70pct_up') - self.profit_50_to_60: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_50pct_to_60pct_up') - self.profit_40_to_50: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_40pct_to_50pct_up') - self.profit_30_to_40: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_30pct_to_40pct_up') - self.profit_20_to_30: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_20pct_to_30pct_up') - self.profit_10_to_20: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_10pct_to_20pct_up') - self.profit_0_to_10: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_0pct_to_10pct_up') - self.loss_0_to_10: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_0pct_to_10pct_down') - self.loss_10_to_20: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_10pct_to_20pct_down') - self.loss_20_to_30: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_20pct_to_30pct_down') - self.loss_30_to_40: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_30pct_to_40pct_down') - self.loss_40_to_50: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_40pct_to_50pct_down') - self.loss_50_to_60: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_50pct_to_60pct_down') - self.loss_60_to_70: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_60pct_to_70pct_down') - self.loss_70_to_80: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_70pct_to_80pct_down') - self.loss_80_to_90: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_80pct_to_90pct_down') - self.loss_90_to_100: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_90pct_to_100pct_down') + self.over_1000pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_1000pct_in_profit') + self._500pct_to_1000pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_500pct_to_1000pct_in_profit') + self._300pct_to_500pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_300pct_to_500pct_in_profit') + self._200pct_to_300pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_200pct_to_300pct_in_profit') + self._100pct_to_200pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_100pct_to_200pct_in_profit') + self._90pct_to_100pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_90pct_to_100pct_in_profit') + self._80pct_to_90pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_80pct_to_90pct_in_profit') + self._70pct_to_80pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_70pct_to_80pct_in_profit') + self._60pct_to_70pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_60pct_to_70pct_in_profit') + self._50pct_to_60pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_50pct_to_60pct_in_profit') + self._40pct_to_50pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_40pct_to_50pct_in_profit') + self._30pct_to_40pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_30pct_to_40pct_in_profit') + self._20pct_to_30pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_20pct_to_30pct_in_profit') + self._10pct_to_20pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_10pct_to_20pct_in_profit') + self._0pct_to_10pct_in_profit: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_0pct_to_10pct_in_profit') + self._0pct_to_10pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_0pct_to_10pct_in_loss') + self._10pct_to_20pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_10pct_to_20pct_in_loss') + self._20pct_to_30pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_20pct_to_30pct_in_loss') + self._30pct_to_40pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_30pct_to_40pct_in_loss') + self._40pct_to_50pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_40pct_to_50pct_in_loss') + self._50pct_to_60pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_50pct_to_60pct_in_loss') + self._60pct_to_70pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_60pct_to_70pct_in_loss') + self._70pct_to_80pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_70pct_to_80pct_in_loss') + self._80pct_to_90pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_80pct_to_90pct_in_loss') + self._90pct_to_100pct_in_loss: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_90pct_to_100pct_in_loss') class MetricsTree_Distribution_Cohorts_Utxo_Profitability_Profit: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.breakeven: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_breakeven') - self._10pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_10pct') - self._20pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_20pct') - self._30pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_30pct') - self._40pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_40pct') - self._50pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_50pct') - self._60pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_60pct') - self._70pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_70pct') - self._80pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_80pct') - self._90pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_90pct') - self._100pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_100pct') - self._200pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_200pct') - self._300pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_300pct') - self._500pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_500pct') - self._1000pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_ge_1000pct') + self.breakeven: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_in_profit') + self._10pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_10pct_in_profit') + self._20pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_20pct_in_profit') + self._30pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_30pct_in_profit') + self._40pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_40pct_in_profit') + self._50pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_50pct_in_profit') + self._60pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_60pct_in_profit') + self._70pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_70pct_in_profit') + self._80pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_80pct_in_profit') + self._90pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_90pct_in_profit') + self._100pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_100pct_in_profit') + self._200pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_200pct_in_profit') + self._300pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_300pct_in_profit') + self._500pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_500pct_in_profit') class MetricsTree_Distribution_Cohorts_Utxo_Profitability_Loss: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.breakeven: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_breakeven') - self._10pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_10pct') - self._20pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_20pct') - self._30pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_30pct') - self._40pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_40pct') - self._50pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_50pct') - self._60pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_60pct') - self._70pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_70pct') - self._80pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_80pct') - self._90pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_ge_90pct') + self.breakeven: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_in_loss') + self._10pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_10pct_in_loss') + self._20pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_20pct_in_loss') + self._30pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_30pct_in_loss') + self._40pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_40pct_in_loss') + self._50pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_50pct_in_loss') + self._60pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_60pct_in_loss') + self._70pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_70pct_in_loss') + self._80pct: RealizedSupplyPattern = RealizedSupplyPattern(client, 'utxos_over_80pct_in_loss') class MetricsTree_Distribution_Cohorts_Utxo_Profitability: """Metrics tree node.""" @@ -5302,18 +5300,18 @@ class MetricsTree_Distribution_Cohorts_Utxo: self.sth: MetricsTree_Distribution_Cohorts_Utxo_Sth = MetricsTree_Distribution_Cohorts_Utxo_Sth(client) self.lth: MetricsTree_Distribution_Cohorts_Utxo_Lth = MetricsTree_Distribution_Cohorts_Utxo_Lth(client) self.age_range: MetricsTree_Distribution_Cohorts_Utxo_AgeRange = MetricsTree_Distribution_Cohorts_Utxo_AgeRange(client) - self.max_age: MetricsTree_Distribution_Cohorts_Utxo_MaxAge = MetricsTree_Distribution_Cohorts_Utxo_MaxAge(client) - self.min_age: MetricsTree_Distribution_Cohorts_Utxo_MinAge = MetricsTree_Distribution_Cohorts_Utxo_MinAge(client) + self.under_age: MetricsTree_Distribution_Cohorts_Utxo_UnderAge = MetricsTree_Distribution_Cohorts_Utxo_UnderAge(client) + self.over_age: MetricsTree_Distribution_Cohorts_Utxo_OverAge = MetricsTree_Distribution_Cohorts_Utxo_OverAge(client) self.epoch: MetricsTree_Distribution_Cohorts_Utxo_Epoch = MetricsTree_Distribution_Cohorts_Utxo_Epoch(client) self.class: MetricsTree_Distribution_Cohorts_Utxo_Class = MetricsTree_Distribution_Cohorts_Utxo_Class(client) - self.ge_amount: MetricsTree_Distribution_Cohorts_Utxo_GeAmount = MetricsTree_Distribution_Cohorts_Utxo_GeAmount(client) + self.over_amount: MetricsTree_Distribution_Cohorts_Utxo_OverAmount = MetricsTree_Distribution_Cohorts_Utxo_OverAmount(client) self.amount_range: MetricsTree_Distribution_Cohorts_Utxo_AmountRange = MetricsTree_Distribution_Cohorts_Utxo_AmountRange(client) - self.lt_amount: MetricsTree_Distribution_Cohorts_Utxo_LtAmount = MetricsTree_Distribution_Cohorts_Utxo_LtAmount(client) + self.under_amount: MetricsTree_Distribution_Cohorts_Utxo_UnderAmount = MetricsTree_Distribution_Cohorts_Utxo_UnderAmount(client) self.r#type: MetricsTree_Distribution_Cohorts_Utxo_Type = MetricsTree_Distribution_Cohorts_Utxo_Type(client) self.profitability: MetricsTree_Distribution_Cohorts_Utxo_Profitability = MetricsTree_Distribution_Cohorts_Utxo_Profitability(client) self.matured: MetricsTree_Distribution_Cohorts_Utxo_Matured = MetricsTree_Distribution_Cohorts_Utxo_Matured(client) -class MetricsTree_Distribution_Cohorts_Address_GeAmount: +class MetricsTree_Distribution_Cohorts_Address_OverAmount: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): @@ -5351,7 +5349,7 @@ class MetricsTree_Distribution_Cohorts_Address_AmountRange: self._10k_btc_to_100k_btc: AddrOutputsRealizedSupplyPattern = AddrOutputsRealizedSupplyPattern(client, 'addrs_above_10k_btc_under_100k_btc') self._100k_btc_or_more: AddrOutputsRealizedSupplyPattern = AddrOutputsRealizedSupplyPattern(client, 'addrs_above_100k_btc') -class MetricsTree_Distribution_Cohorts_Address_LtAmount: +class MetricsTree_Distribution_Cohorts_Address_UnderAmount: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): @@ -5373,9 +5371,9 @@ class MetricsTree_Distribution_Cohorts_Address: """Metrics tree node.""" def __init__(self, client: BrkClientBase, base_path: str = ''): - self.ge_amount: MetricsTree_Distribution_Cohorts_Address_GeAmount = MetricsTree_Distribution_Cohorts_Address_GeAmount(client) + self.over_amount: MetricsTree_Distribution_Cohorts_Address_OverAmount = MetricsTree_Distribution_Cohorts_Address_OverAmount(client) self.amount_range: MetricsTree_Distribution_Cohorts_Address_AmountRange = MetricsTree_Distribution_Cohorts_Address_AmountRange(client) - self.lt_amount: MetricsTree_Distribution_Cohorts_Address_LtAmount = MetricsTree_Distribution_Cohorts_Address_LtAmount(client) + self.under_amount: MetricsTree_Distribution_Cohorts_Address_UnderAmount = MetricsTree_Distribution_Cohorts_Address_UnderAmount(client) class MetricsTree_Distribution_Cohorts: """Metrics tree node.""" @@ -5956,7 +5954,7 @@ class BrkClient(BrkClientBase): } } - MAX_AGE_NAMES = { + UNDER_AGE_NAMES = { "_1w": { "id": "under_1w_old", "short": "<1w", @@ -6049,7 +6047,7 @@ class BrkClient(BrkClientBase): } } - MIN_AGE_NAMES = { + OVER_AGE_NAMES = { "_1d": { "id": "over_1d_old", "short": "1d+", @@ -6220,7 +6218,7 @@ class BrkClient(BrkClientBase): } } - GE_AMOUNT_NAMES = { + OVER_AMOUNT_NAMES = { "_1sat": { "id": "over_1sat", "short": "1+ sats", @@ -6288,7 +6286,7 @@ class BrkClient(BrkClientBase): } } - LT_AMOUNT_NAMES = { + UNDER_AMOUNT_NAMES = { "_10sats": { "id": "under_10sats", "short": "<10 sats", @@ -6612,6 +6610,22 @@ class BrkClient(BrkClientBase): Endpoint: `GET /api/metric/{metric}/{index}/latest`""" return self.get_json(f'/api/metric/{metric}/{index}/latest') + def get_metric_len(self, metric: Metric, index: Index) -> float: + """Get metric data length. + + Returns the total number of data points for a metric at the given index. + + Endpoint: `GET /api/metric/{metric}/{index}/len`""" + return self.get_json(f'/api/metric/{metric}/{index}/len') + + def get_metric_version(self, metric: Metric, index: Index) -> Version: + """Get metric version. + + Returns the current version of a metric. Changes when the metric data is updated. + + Endpoint: `GET /api/metric/{metric}/{index}/version`""" + return self.get_json(f'/api/metric/{metric}/{index}/version') + def get_metrics_tree(self) -> TreeNode: """Metrics catalog. diff --git a/website/llms.txt b/website/llms.txt index 2df10e1cd..29c8cfded 100644 --- a/website/llms.txt +++ b/website/llms.txt @@ -50,6 +50,11 @@ Get the latest value: GET /api/metric/{metric}/{index}/latest +Get the data length or version: + + GET /api/metric/{metric}/{index}/len + GET /api/metric/{metric}/{index}/version + Example — last 30 days of Bitcoin closing price: GET /api/metric/price/day?start=-30