mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snapshot
This commit is contained in:
@@ -958,8 +958,8 @@ pub struct CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSell
|
||||
pub neg_realized_loss: MetricPattern1<Dollars>,
|
||||
pub net_pnl_change_1m_rel_to_market_cap: BpsPercentRatioPattern,
|
||||
pub net_pnl_change_1m_rel_to_realized_cap: BpsPercentRatioPattern,
|
||||
pub net_pnl_delta: ChangeRatePattern<CentsSigned>,
|
||||
pub net_pnl_delta_extended: _24hChangeRatePattern<CentsSigned>,
|
||||
pub net_pnl_delta: ChangeRatePattern3,
|
||||
pub net_pnl_delta_extended: _24hChangeRatePattern,
|
||||
pub net_realized_pnl: MetricPattern1<CentsSigned>,
|
||||
pub net_realized_pnl_cumulative: MetricPattern1<CentsSigned>,
|
||||
pub net_realized_pnl_rel_to_realized_cap: BpsPercentRatioPattern,
|
||||
@@ -974,8 +974,8 @@ pub struct CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSell
|
||||
pub profit_value_destroyed_sum: _1m1w1y24hPattern<Cents>,
|
||||
pub realized_cap: MetricPattern1<Dollars>,
|
||||
pub realized_cap_cents: MetricPattern1<Cents>,
|
||||
pub realized_cap_delta: ChangeRatePattern<CentsSigned>,
|
||||
pub realized_cap_delta_extended: _24hChangeRatePattern<CentsSigned>,
|
||||
pub realized_cap_delta: ChangeRatePattern3,
|
||||
pub realized_cap_delta_extended: _24hChangeRatePattern,
|
||||
pub realized_cap_rel_to_own_market_cap: BpsPercentRatioPattern,
|
||||
pub realized_loss: CumulativeHeightPattern<Cents>,
|
||||
pub realized_loss_rel_to_realized_cap: BpsPercentRatioPattern,
|
||||
@@ -1029,7 +1029,7 @@ impl CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSo
|
||||
neg_realized_loss: MetricPattern1::new(client.clone(), _m(&acc, "neg_realized_loss")),
|
||||
net_pnl_change_1m_rel_to_market_cap: BpsPercentRatioPattern::new(client.clone(), _m(&acc, "net_pnl_change_1m_rel_to_market_cap")),
|
||||
net_pnl_change_1m_rel_to_realized_cap: BpsPercentRatioPattern::new(client.clone(), _m(&acc, "net_pnl_change_1m_rel_to_realized_cap")),
|
||||
net_pnl_delta: ChangeRatePattern::new(client.clone(), _m(&acc, "net_pnl_delta")),
|
||||
net_pnl_delta: ChangeRatePattern3::new(client.clone(), _m(&acc, "net_pnl_delta")),
|
||||
net_pnl_delta_extended: _24hChangeRatePattern::new(client.clone(), _m(&acc, "net_pnl_delta")),
|
||||
net_realized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_realized_pnl")),
|
||||
net_realized_pnl_cumulative: MetricPattern1::new(client.clone(), _m(&acc, "net_realized_pnl_cumulative")),
|
||||
@@ -1045,7 +1045,7 @@ impl CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentSo
|
||||
profit_value_destroyed_sum: _1m1w1y24hPattern::new(client.clone(), _m(&acc, "profit_value_destroyed")),
|
||||
realized_cap: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap")),
|
||||
realized_cap_cents: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap_cents")),
|
||||
realized_cap_delta: ChangeRatePattern::new(client.clone(), _m(&acc, "realized_cap_delta")),
|
||||
realized_cap_delta: ChangeRatePattern3::new(client.clone(), _m(&acc, "realized_cap_delta")),
|
||||
realized_cap_delta_extended: _24hChangeRatePattern::new(client.clone(), _m(&acc, "realized_cap_delta")),
|
||||
realized_cap_rel_to_own_market_cap: BpsPercentRatioPattern::new(client.clone(), _m(&acc, "realized_cap_rel_to_own_market_cap")),
|
||||
realized_loss: CumulativeHeightPattern::new(client.clone(), _m(&acc, "realized_loss")),
|
||||
@@ -1157,7 +1157,7 @@ pub struct MvrvNegNetRealizedSentSoprValuePattern {
|
||||
pub net_realized_pnl_sum: _24hPattern<CentsSigned>,
|
||||
pub realized_cap: MetricPattern1<Dollars>,
|
||||
pub realized_cap_cents: MetricPattern1<Cents>,
|
||||
pub realized_cap_delta: ChangeRatePattern<CentsSigned>,
|
||||
pub realized_cap_delta: ChangeRatePattern3,
|
||||
pub realized_loss: CumulativeHeightPattern<Cents>,
|
||||
pub realized_loss_sum: _24hPattern<Cents>,
|
||||
pub realized_price: CentsSatsUsdPattern,
|
||||
@@ -1185,7 +1185,7 @@ impl MvrvNegNetRealizedSentSoprValuePattern {
|
||||
net_realized_pnl_sum: _24hPattern::new(client.clone(), _m(&acc, "net_realized_pnl_24h")),
|
||||
realized_cap: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap")),
|
||||
realized_cap_cents: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap_cents")),
|
||||
realized_cap_delta: ChangeRatePattern::new(client.clone(), _m(&acc, "realized_cap_delta")),
|
||||
realized_cap_delta: ChangeRatePattern3::new(client.clone(), _m(&acc, "realized_cap_delta")),
|
||||
realized_loss: CumulativeHeightPattern::new(client.clone(), _m(&acc, "realized_loss")),
|
||||
realized_loss_sum: _24hPattern::new(client.clone(), _m(&acc, "realized_loss_24h")),
|
||||
realized_price: CentsSatsUsdPattern::new(client.clone(), _m(&acc, "realized_price")),
|
||||
@@ -1263,7 +1263,7 @@ pub struct MvrvNegNetRealizedSoprValuePattern {
|
||||
pub net_realized_pnl_sum: _24hPattern<CentsSigned>,
|
||||
pub realized_cap: MetricPattern1<Dollars>,
|
||||
pub realized_cap_cents: MetricPattern1<Cents>,
|
||||
pub realized_cap_delta: ChangeRatePattern<CentsSigned>,
|
||||
pub realized_cap_delta: ChangeRatePattern3,
|
||||
pub realized_loss: CumulativeHeightPattern<Cents>,
|
||||
pub realized_loss_sum: _24hPattern<Cents>,
|
||||
pub realized_price: CentsSatsUsdPattern,
|
||||
@@ -1287,7 +1287,7 @@ impl MvrvNegNetRealizedSoprValuePattern {
|
||||
net_realized_pnl_sum: _24hPattern::new(client.clone(), _m(&acc, "net_realized_pnl_24h")),
|
||||
realized_cap: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap")),
|
||||
realized_cap_cents: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap_cents")),
|
||||
realized_cap_delta: ChangeRatePattern::new(client.clone(), _m(&acc, "realized_cap_delta")),
|
||||
realized_cap_delta: ChangeRatePattern3::new(client.clone(), _m(&acc, "realized_cap_delta")),
|
||||
realized_loss: CumulativeHeightPattern::new(client.clone(), _m(&acc, "realized_loss")),
|
||||
realized_loss_sum: _24hPattern::new(client.clone(), _m(&acc, "realized_loss_24h")),
|
||||
realized_price: CentsSatsUsdPattern::new(client.clone(), _m(&acc, "realized_price")),
|
||||
@@ -2039,6 +2039,28 @@ impl NegNetSupplyUnrealizedPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _24hChangeRatePattern {
|
||||
pub _24h: BpsCentsPercentRatioUsdPattern,
|
||||
pub change_1w: CentsUsdPattern,
|
||||
pub change_1y: CentsUsdPattern,
|
||||
pub rate_1w: BpsPercentRatioPattern,
|
||||
pub rate_1y: BpsPercentRatioPattern,
|
||||
}
|
||||
|
||||
impl _24hChangeRatePattern {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
_24h: BpsCentsPercentRatioUsdPattern::new(client.clone(), acc.clone()),
|
||||
change_1w: CentsUsdPattern::new(client.clone(), _m(&acc, "change_1w")),
|
||||
change_1y: CentsUsdPattern::new(client.clone(), _m(&acc, "change_1y")),
|
||||
rate_1w: BpsPercentRatioPattern::new(client.clone(), _m(&acc, "rate_1w")),
|
||||
rate_1y: BpsPercentRatioPattern::new(client.clone(), _m(&acc, "rate_1y")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct ActivityOutputsRealizedSupplyUnrealizedPattern {
|
||||
pub activity: SentPattern,
|
||||
@@ -2083,6 +2105,28 @@ impl BaseBtcCentsSatsUsdPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct BpsCentsPercentRatioUsdPattern {
|
||||
pub bps: MetricPattern1<BasisPointsSigned32>,
|
||||
pub cents: MetricPattern1<CentsSigned>,
|
||||
pub percent: MetricPattern1<StoredF32>,
|
||||
pub ratio: MetricPattern1<StoredF32>,
|
||||
pub usd: MetricPattern1<Dollars>,
|
||||
}
|
||||
|
||||
impl BpsCentsPercentRatioUsdPattern {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
bps: MetricPattern1::new(client.clone(), _m(&acc, "rate_24h_bps")),
|
||||
cents: MetricPattern1::new(client.clone(), _m(&acc, "change_24h_cents")),
|
||||
percent: MetricPattern1::new(client.clone(), _m(&acc, "rate_24h")),
|
||||
ratio: MetricPattern1::new(client.clone(), _m(&acc, "rate_24h_ratio")),
|
||||
usd: MetricPattern1::new(client.clone(), _m(&acc, "change_24h_usd")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct EmaHistogramLineSignalPattern {
|
||||
pub ema_fast: MetricPattern1<StoredF32>,
|
||||
@@ -2128,7 +2172,7 @@ impl<T: DeserializeOwned> _1m1w1y24hHeightPattern<T> {
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct _24hChangeRatePattern<T> {
|
||||
pub struct _24hChangeRatePattern2<T> {
|
||||
pub _24h: BaseBpsPercentRatioPattern,
|
||||
pub change_1w: MetricPattern1<T>,
|
||||
pub change_1y: MetricPattern1<T>,
|
||||
@@ -2136,7 +2180,7 @@ pub struct _24hChangeRatePattern<T> {
|
||||
pub rate_1y: BpsPercentRatioPattern,
|
||||
}
|
||||
|
||||
impl<T: DeserializeOwned> _24hChangeRatePattern<T> {
|
||||
impl<T: DeserializeOwned> _24hChangeRatePattern2<T> {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
@@ -2211,7 +2255,7 @@ impl _1m1w1y24hPattern5 {
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct BaseBpsPercentRatioPattern {
|
||||
pub base: MetricPattern1<CentsSigned>,
|
||||
pub base: MetricPattern1<SatsSigned>,
|
||||
pub bps: MetricPattern1<BasisPointsSigned32>,
|
||||
pub percent: MetricPattern1<StoredF32>,
|
||||
pub ratio: MetricPattern1<StoredF32>,
|
||||
@@ -2609,6 +2653,22 @@ impl ChangeRatePattern2 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct ChangeRatePattern3 {
|
||||
pub change_1m: CentsUsdPattern,
|
||||
pub rate_1m: BpsPercentRatioPattern,
|
||||
}
|
||||
|
||||
impl ChangeRatePattern3 {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
change_1m: CentsUsdPattern::new(client.clone(), _m(&acc, "change_1m")),
|
||||
rate_1m: BpsPercentRatioPattern::new(client.clone(), _m(&acc, "rate_1m")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct HeightSumPattern {
|
||||
pub height: MetricPattern18<StoredU64>,
|
||||
@@ -2625,6 +2685,22 @@ impl HeightSumPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct RealizedSupplyPattern {
|
||||
pub realized_cap: MetricPattern1<Dollars>,
|
||||
pub supply: MetricPattern1<Sats>,
|
||||
}
|
||||
|
||||
impl RealizedSupplyPattern {
|
||||
/// Create a new pattern node with accumulated metric name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
realized_cap: MetricPattern1::new(client.clone(), _m(&acc, "realized_cap")),
|
||||
supply: MetricPattern1::new(client.clone(), _m(&acc, "supply")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct SdSmaPattern {
|
||||
pub sd: MetricPattern1<StoredF32>,
|
||||
@@ -5568,6 +5644,7 @@ pub struct MetricsTree_Distribution_UtxoCohorts {
|
||||
pub amount_range: MetricsTree_Distribution_UtxoCohorts_AmountRange,
|
||||
pub lt_amount: MetricsTree_Distribution_UtxoCohorts_LtAmount,
|
||||
pub type_: MetricsTree_Distribution_UtxoCohorts_Type,
|
||||
pub profitability: MetricsTree_Distribution_UtxoCohorts_Profitability,
|
||||
}
|
||||
|
||||
impl MetricsTree_Distribution_UtxoCohorts {
|
||||
@@ -5585,6 +5662,7 @@ impl MetricsTree_Distribution_UtxoCohorts {
|
||||
amount_range: MetricsTree_Distribution_UtxoCohorts_AmountRange::new(client.clone(), format!("{base_path}_amount_range")),
|
||||
lt_amount: MetricsTree_Distribution_UtxoCohorts_LtAmount::new(client.clone(), format!("{base_path}_lt_amount")),
|
||||
type_: MetricsTree_Distribution_UtxoCohorts_Type::new(client.clone(), format!("{base_path}_type_")),
|
||||
profitability: MetricsTree_Distribution_UtxoCohorts_Profitability::new(client.clone(), format!("{base_path}_profitability")),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5601,8 +5679,8 @@ pub struct MetricsTree_Distribution_UtxoCohorts_All {
|
||||
pub relative: MetricsTree_Distribution_UtxoCohorts_All_Relative,
|
||||
pub dormancy: MetricPattern1<StoredF32>,
|
||||
pub velocity: MetricPattern1<StoredF32>,
|
||||
pub supply_delta_extended: _24hChangeRatePattern<SatsSigned>,
|
||||
pub utxo_count_delta_extended: _24hChangeRatePattern<StoredI64>,
|
||||
pub supply_delta_extended: _24hChangeRatePattern2<SatsSigned>,
|
||||
pub utxo_count_delta_extended: _24hChangeRatePattern2<StoredI64>,
|
||||
}
|
||||
|
||||
impl MetricsTree_Distribution_UtxoCohorts_All {
|
||||
@@ -5618,8 +5696,8 @@ impl MetricsTree_Distribution_UtxoCohorts_All {
|
||||
relative: MetricsTree_Distribution_UtxoCohorts_All_Relative::new(client.clone(), format!("{base_path}_relative")),
|
||||
dormancy: MetricPattern1::new(client.clone(), "dormancy".to_string()),
|
||||
velocity: MetricPattern1::new(client.clone(), "velocity".to_string()),
|
||||
supply_delta_extended: _24hChangeRatePattern::new(client.clone(), "supply_delta".to_string()),
|
||||
utxo_count_delta_extended: _24hChangeRatePattern::new(client.clone(), "utxo_count_delta".to_string()),
|
||||
supply_delta_extended: _24hChangeRatePattern2::new(client.clone(), "supply_delta".to_string()),
|
||||
utxo_count_delta_extended: _24hChangeRatePattern2::new(client.clone(), "utxo_count_delta".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5685,8 +5763,8 @@ pub struct MetricsTree_Distribution_UtxoCohorts_Sth {
|
||||
pub relative: NetNuplSupplyUnrealizedPattern2,
|
||||
pub dormancy: MetricPattern1<StoredF32>,
|
||||
pub velocity: MetricPattern1<StoredF32>,
|
||||
pub supply_delta_extended: _24hChangeRatePattern<SatsSigned>,
|
||||
pub utxo_count_delta_extended: _24hChangeRatePattern<StoredI64>,
|
||||
pub supply_delta_extended: _24hChangeRatePattern2<SatsSigned>,
|
||||
pub utxo_count_delta_extended: _24hChangeRatePattern2<StoredI64>,
|
||||
pub adjusted_value_created: MetricPattern1<Cents>,
|
||||
pub adjusted_value_destroyed: MetricPattern1<Cents>,
|
||||
pub adjusted_value_created_sum: _1m1w1y24hPattern<Cents>,
|
||||
@@ -5706,8 +5784,8 @@ impl MetricsTree_Distribution_UtxoCohorts_Sth {
|
||||
relative: NetNuplSupplyUnrealizedPattern2::new(client.clone(), "sth".to_string()),
|
||||
dormancy: MetricPattern1::new(client.clone(), "sth_dormancy".to_string()),
|
||||
velocity: MetricPattern1::new(client.clone(), "sth_velocity".to_string()),
|
||||
supply_delta_extended: _24hChangeRatePattern::new(client.clone(), "sth_supply_delta".to_string()),
|
||||
utxo_count_delta_extended: _24hChangeRatePattern::new(client.clone(), "sth_utxo_count_delta".to_string()),
|
||||
supply_delta_extended: _24hChangeRatePattern2::new(client.clone(), "sth_supply_delta".to_string()),
|
||||
utxo_count_delta_extended: _24hChangeRatePattern2::new(client.clone(), "sth_utxo_count_delta".to_string()),
|
||||
adjusted_value_created: MetricPattern1::new(client.clone(), "sth_adjusted_value_created".to_string()),
|
||||
adjusted_value_destroyed: MetricPattern1::new(client.clone(), "sth_adjusted_value_destroyed".to_string()),
|
||||
adjusted_value_created_sum: _1m1w1y24hPattern::new(client.clone(), "sth_adjusted_value_created".to_string()),
|
||||
@@ -5728,8 +5806,8 @@ pub struct MetricsTree_Distribution_UtxoCohorts_Lth {
|
||||
pub relative: NetNuplSupplyUnrealizedPattern2,
|
||||
pub dormancy: MetricPattern1<StoredF32>,
|
||||
pub velocity: MetricPattern1<StoredF32>,
|
||||
pub supply_delta_extended: _24hChangeRatePattern<SatsSigned>,
|
||||
pub utxo_count_delta_extended: _24hChangeRatePattern<StoredI64>,
|
||||
pub supply_delta_extended: _24hChangeRatePattern2<SatsSigned>,
|
||||
pub utxo_count_delta_extended: _24hChangeRatePattern2<StoredI64>,
|
||||
}
|
||||
|
||||
impl MetricsTree_Distribution_UtxoCohorts_Lth {
|
||||
@@ -5744,8 +5822,8 @@ impl MetricsTree_Distribution_UtxoCohorts_Lth {
|
||||
relative: NetNuplSupplyUnrealizedPattern2::new(client.clone(), "lth".to_string()),
|
||||
dormancy: MetricPattern1::new(client.clone(), "lth_dormancy".to_string()),
|
||||
velocity: MetricPattern1::new(client.clone(), "lth_velocity".to_string()),
|
||||
supply_delta_extended: _24hChangeRatePattern::new(client.clone(), "lth_supply_delta".to_string()),
|
||||
utxo_count_delta_extended: _24hChangeRatePattern::new(client.clone(), "lth_utxo_count_delta".to_string()),
|
||||
supply_delta_extended: _24hChangeRatePattern2::new(client.clone(), "lth_supply_delta".to_string()),
|
||||
utxo_count_delta_extended: _24hChangeRatePattern2::new(client.clone(), "lth_utxo_count_delta".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6113,6 +6191,156 @@ impl MetricsTree_Distribution_UtxoCohorts_Type {
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Distribution_UtxoCohorts_Profitability {
|
||||
pub range: MetricsTree_Distribution_UtxoCohorts_Profitability_Range,
|
||||
pub profit: MetricsTree_Distribution_UtxoCohorts_Profitability_Profit,
|
||||
pub loss: MetricsTree_Distribution_UtxoCohorts_Profitability_Loss,
|
||||
}
|
||||
|
||||
impl MetricsTree_Distribution_UtxoCohorts_Profitability {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
range: MetricsTree_Distribution_UtxoCohorts_Profitability_Range::new(client.clone(), format!("{base_path}_range")),
|
||||
profit: MetricsTree_Distribution_UtxoCohorts_Profitability_Profit::new(client.clone(), format!("{base_path}_profit")),
|
||||
loss: MetricsTree_Distribution_UtxoCohorts_Profitability_Loss::new(client.clone(), format!("{base_path}_loss")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Distribution_UtxoCohorts_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,
|
||||
}
|
||||
|
||||
impl MetricsTree_Distribution_UtxoCohorts_Profitability_Range {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
profit_over_1000: RealizedSupplyPattern::new(client.clone(), "profit_over_1000pct".to_string()),
|
||||
profit_500_to_1000: RealizedSupplyPattern::new(client.clone(), "profit_500_to_1000pct".to_string()),
|
||||
profit_300_to_500: RealizedSupplyPattern::new(client.clone(), "profit_300_to_500pct".to_string()),
|
||||
profit_200_to_300: RealizedSupplyPattern::new(client.clone(), "profit_200_to_300pct".to_string()),
|
||||
profit_100_to_200: RealizedSupplyPattern::new(client.clone(), "profit_100_to_200pct".to_string()),
|
||||
profit_90_to_100: RealizedSupplyPattern::new(client.clone(), "profit_90_to_100pct".to_string()),
|
||||
profit_80_to_90: RealizedSupplyPattern::new(client.clone(), "profit_80_to_90pct".to_string()),
|
||||
profit_70_to_80: RealizedSupplyPattern::new(client.clone(), "profit_70_to_80pct".to_string()),
|
||||
profit_60_to_70: RealizedSupplyPattern::new(client.clone(), "profit_60_to_70pct".to_string()),
|
||||
profit_50_to_60: RealizedSupplyPattern::new(client.clone(), "profit_50_to_60pct".to_string()),
|
||||
profit_40_to_50: RealizedSupplyPattern::new(client.clone(), "profit_40_to_50pct".to_string()),
|
||||
profit_30_to_40: RealizedSupplyPattern::new(client.clone(), "profit_30_to_40pct".to_string()),
|
||||
profit_20_to_30: RealizedSupplyPattern::new(client.clone(), "profit_20_to_30pct".to_string()),
|
||||
profit_10_to_20: RealizedSupplyPattern::new(client.clone(), "profit_10_to_20pct".to_string()),
|
||||
profit_0_to_10: RealizedSupplyPattern::new(client.clone(), "profit_0_to_10pct".to_string()),
|
||||
loss_0_to_10: RealizedSupplyPattern::new(client.clone(), "loss_0_to_10pct".to_string()),
|
||||
loss_10_to_20: RealizedSupplyPattern::new(client.clone(), "loss_10_to_20pct".to_string()),
|
||||
loss_20_to_30: RealizedSupplyPattern::new(client.clone(), "loss_20_to_30pct".to_string()),
|
||||
loss_30_to_40: RealizedSupplyPattern::new(client.clone(), "loss_30_to_40pct".to_string()),
|
||||
loss_40_to_50: RealizedSupplyPattern::new(client.clone(), "loss_40_to_50pct".to_string()),
|
||||
loss_50_to_60: RealizedSupplyPattern::new(client.clone(), "loss_50_to_60pct".to_string()),
|
||||
loss_60_to_70: RealizedSupplyPattern::new(client.clone(), "loss_60_to_70pct".to_string()),
|
||||
loss_70_to_80: RealizedSupplyPattern::new(client.clone(), "loss_70_to_80pct".to_string()),
|
||||
loss_80_to_90: RealizedSupplyPattern::new(client.clone(), "loss_80_to_90pct".to_string()),
|
||||
loss_90_to_100: RealizedSupplyPattern::new(client.clone(), "loss_90_to_100pct".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Distribution_UtxoCohorts_Profitability_Profit {
|
||||
pub breakeven: RealizedSupplyPattern,
|
||||
pub _10pct: RealizedSupplyPattern,
|
||||
pub _20pct: RealizedSupplyPattern,
|
||||
pub _30pct: RealizedSupplyPattern,
|
||||
pub _40pct: RealizedSupplyPattern,
|
||||
pub _50pct: RealizedSupplyPattern,
|
||||
pub _60pct: RealizedSupplyPattern,
|
||||
pub _70pct: RealizedSupplyPattern,
|
||||
pub _80pct: RealizedSupplyPattern,
|
||||
pub _90pct: RealizedSupplyPattern,
|
||||
pub _100pct: RealizedSupplyPattern,
|
||||
pub _200pct: RealizedSupplyPattern,
|
||||
pub _300pct: RealizedSupplyPattern,
|
||||
pub _500pct: RealizedSupplyPattern,
|
||||
pub _1000pct: RealizedSupplyPattern,
|
||||
}
|
||||
|
||||
impl MetricsTree_Distribution_UtxoCohorts_Profitability_Profit {
|
||||
pub fn new(client: Arc<BrkClientBase>, 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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Distribution_UtxoCohorts_Profitability_Loss {
|
||||
pub breakeven: RealizedSupplyPattern,
|
||||
pub _10pct: RealizedSupplyPattern,
|
||||
pub _20pct: RealizedSupplyPattern,
|
||||
pub _30pct: RealizedSupplyPattern,
|
||||
pub _40pct: RealizedSupplyPattern,
|
||||
pub _50pct: RealizedSupplyPattern,
|
||||
pub _60pct: RealizedSupplyPattern,
|
||||
pub _70pct: RealizedSupplyPattern,
|
||||
pub _80pct: RealizedSupplyPattern,
|
||||
pub _90pct: RealizedSupplyPattern,
|
||||
}
|
||||
|
||||
impl MetricsTree_Distribution_UtxoCohorts_Profitability_Loss {
|
||||
pub fn new(client: Arc<BrkClientBase>, 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()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Distribution_AddressCohorts {
|
||||
pub ge_amount: MetricsTree_Distribution_AddressCohorts_GeAmount,
|
||||
@@ -6338,9 +6566,8 @@ pub struct MetricsTree_Supply {
|
||||
pub burned: MetricsTree_Supply_Burned,
|
||||
pub inflation_rate: BpsPercentRatioPattern,
|
||||
pub velocity: MetricsTree_Supply_Velocity,
|
||||
pub market_cap: MetricPattern1<Dollars>,
|
||||
pub market_cap_growth_rate: _1m1w1y24hPattern2,
|
||||
pub realized_cap_growth_rate: _1m1w1y24hPattern2,
|
||||
pub market_cap: CentsUsdPattern,
|
||||
pub market_cap_delta: MetricsTree_Supply_MarketCapDelta,
|
||||
pub market_minus_realized_cap_growth_rate: _1m1w1y24hPattern<BasisPointsSigned32>,
|
||||
}
|
||||
|
||||
@@ -6351,9 +6578,8 @@ impl MetricsTree_Supply {
|
||||
burned: MetricsTree_Supply_Burned::new(client.clone(), format!("{base_path}_burned")),
|
||||
inflation_rate: BpsPercentRatioPattern::new(client.clone(), "inflation_rate".to_string()),
|
||||
velocity: MetricsTree_Supply_Velocity::new(client.clone(), format!("{base_path}_velocity")),
|
||||
market_cap: MetricPattern1::new(client.clone(), "market_cap".to_string()),
|
||||
market_cap_growth_rate: _1m1w1y24hPattern2::new(client.clone(), "market_cap_growth_rate".to_string()),
|
||||
realized_cap_growth_rate: _1m1w1y24hPattern2::new(client.clone(), "realized_cap_growth_rate".to_string()),
|
||||
market_cap: CentsUsdPattern::new(client.clone(), "market_cap".to_string()),
|
||||
market_cap_delta: MetricsTree_Supply_MarketCapDelta::new(client.clone(), format!("{base_path}_market_cap_delta")),
|
||||
market_minus_realized_cap_growth_rate: _1m1w1y24hPattern::new(client.clone(), "market_minus_realized_cap_growth_rate".to_string()),
|
||||
}
|
||||
}
|
||||
@@ -6389,6 +6615,27 @@ impl MetricsTree_Supply_Velocity {
|
||||
}
|
||||
}
|
||||
|
||||
/// Metrics tree node.
|
||||
pub struct MetricsTree_Supply_MarketCapDelta {
|
||||
pub change_24h: CentsUsdPattern,
|
||||
pub change_1w: CentsUsdPattern,
|
||||
pub change_1m: CentsUsdPattern,
|
||||
pub change_1y: CentsUsdPattern,
|
||||
pub rate: _1m1w1y24hPattern2,
|
||||
}
|
||||
|
||||
impl MetricsTree_Supply_MarketCapDelta {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
change_24h: CentsUsdPattern::new(client.clone(), "market_cap_delta_change_24h".to_string()),
|
||||
change_1w: CentsUsdPattern::new(client.clone(), "market_cap_delta_change_1w".to_string()),
|
||||
change_1m: CentsUsdPattern::new(client.clone(), "market_cap_delta_change_1m".to_string()),
|
||||
change_1y: CentsUsdPattern::new(client.clone(), "market_cap_delta_change_1y".to_string()),
|
||||
rate: _1m1w1y24hPattern2::new(client.clone(), "market_cap_delta_rate".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Main BRK client with metrics tree and API methods.
|
||||
pub struct BrkClient {
|
||||
base: Arc<BrkClientBase>,
|
||||
|
||||
152
crates/brk_cohort/src/by_loss.rs
Normal file
152
crates/brk_cohort/src/by_loss.rs
Normal file
@@ -0,0 +1,152 @@
|
||||
use brk_traversable::Traversable;
|
||||
use rayon::prelude::*;
|
||||
use serde::Serialize;
|
||||
|
||||
use super::CohortName;
|
||||
|
||||
/// "At least X% loss" threshold names (10 thresholds).
|
||||
pub const LOSS_NAMES: ByLoss<CohortName> = ByLoss {
|
||||
breakeven: CohortName::new("loss_ge_breakeven", "<0%", "In Loss (Below Breakeven)"),
|
||||
_10pct: CohortName::new("loss_ge_10pct", "≥10%L", "10%+ Loss"),
|
||||
_20pct: CohortName::new("loss_ge_20pct", "≥20%L", "20%+ Loss"),
|
||||
_30pct: CohortName::new("loss_ge_30pct", "≥30%L", "30%+ Loss"),
|
||||
_40pct: CohortName::new("loss_ge_40pct", "≥40%L", "40%+ Loss"),
|
||||
_50pct: CohortName::new("loss_ge_50pct", "≥50%L", "50%+ Loss"),
|
||||
_60pct: CohortName::new("loss_ge_60pct", "≥60%L", "60%+ Loss"),
|
||||
_70pct: CohortName::new("loss_ge_70pct", "≥70%L", "70%+ Loss"),
|
||||
_80pct: CohortName::new("loss_ge_80pct", "≥80%L", "80%+ Loss"),
|
||||
_90pct: CohortName::new("loss_ge_90pct", "≥90%L", "90%+ Loss"),
|
||||
};
|
||||
|
||||
/// Number of loss thresholds.
|
||||
pub const LOSS_COUNT: usize = 10;
|
||||
|
||||
impl ByLoss<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&LOSS_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
/// 10 "at least X% loss" aggregate thresholds.
|
||||
///
|
||||
/// Each is a suffix sum over the profitability ranges, from most loss-making up.
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByLoss<T> {
|
||||
pub breakeven: T,
|
||||
pub _10pct: T,
|
||||
pub _20pct: T,
|
||||
pub _30pct: T,
|
||||
pub _40pct: T,
|
||||
pub _50pct: T,
|
||||
pub _60pct: T,
|
||||
pub _70pct: T,
|
||||
pub _80pct: T,
|
||||
pub _90pct: T,
|
||||
}
|
||||
|
||||
impl<T> ByLoss<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(&'static str) -> T,
|
||||
{
|
||||
let n = &LOSS_NAMES;
|
||||
Self {
|
||||
breakeven: create(n.breakeven.id),
|
||||
_10pct: create(n._10pct.id),
|
||||
_20pct: create(n._20pct.id),
|
||||
_30pct: create(n._30pct.id),
|
||||
_40pct: create(n._40pct.id),
|
||||
_50pct: create(n._50pct.id),
|
||||
_60pct: create(n._60pct.id),
|
||||
_70pct: create(n._70pct.id),
|
||||
_80pct: create(n._80pct.id),
|
||||
_90pct: create(n._90pct.id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_new<F, E>(mut create: F) -> Result<Self, E>
|
||||
where
|
||||
F: FnMut(&'static str) -> Result<T, E>,
|
||||
{
|
||||
let n = &LOSS_NAMES;
|
||||
Ok(Self {
|
||||
breakeven: create(n.breakeven.id)?,
|
||||
_10pct: create(n._10pct.id)?,
|
||||
_20pct: create(n._20pct.id)?,
|
||||
_30pct: create(n._30pct.id)?,
|
||||
_40pct: create(n._40pct.id)?,
|
||||
_50pct: create(n._50pct.id)?,
|
||||
_60pct: create(n._60pct.id)?,
|
||||
_70pct: create(n._70pct.id)?,
|
||||
_80pct: create(n._80pct.id)?,
|
||||
_90pct: create(n._90pct.id)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self.breakeven,
|
||||
&self._10pct,
|
||||
&self._20pct,
|
||||
&self._30pct,
|
||||
&self._40pct,
|
||||
&self._50pct,
|
||||
&self._60pct,
|
||||
&self._70pct,
|
||||
&self._80pct,
|
||||
&self._90pct,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
|
||||
[
|
||||
&mut self.breakeven,
|
||||
&mut self._10pct,
|
||||
&mut self._20pct,
|
||||
&mut self._30pct,
|
||||
&mut self._40pct,
|
||||
&mut self._50pct,
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
[
|
||||
&mut self.breakeven,
|
||||
&mut self._10pct,
|
||||
&mut self._20pct,
|
||||
&mut self._30pct,
|
||||
&mut self._40pct,
|
||||
&mut self._50pct,
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
]
|
||||
.into_par_iter()
|
||||
}
|
||||
|
||||
/// Access as array for indexed accumulation.
|
||||
pub fn as_array_mut(&mut self) -> [&mut T; LOSS_COUNT] {
|
||||
[
|
||||
&mut self.breakeven,
|
||||
&mut self._10pct,
|
||||
&mut self._20pct,
|
||||
&mut self._30pct,
|
||||
&mut self._40pct,
|
||||
&mut self._50pct,
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
]
|
||||
}
|
||||
}
|
||||
192
crates/brk_cohort/src/by_profit.rs
Normal file
192
crates/brk_cohort/src/by_profit.rs
Normal file
@@ -0,0 +1,192 @@
|
||||
use brk_traversable::Traversable;
|
||||
use rayon::prelude::*;
|
||||
use serde::Serialize;
|
||||
|
||||
use super::CohortName;
|
||||
|
||||
/// "At least X% profit" threshold names (15 thresholds).
|
||||
pub const PROFIT_NAMES: ByProfit<CohortName> = ByProfit {
|
||||
breakeven: CohortName::new("profit_ge_breakeven", "≥0%", "In Profit (Breakeven+)"),
|
||||
_10pct: CohortName::new("profit_ge_10pct", "≥10%", "10%+ Profit"),
|
||||
_20pct: CohortName::new("profit_ge_20pct", "≥20%", "20%+ Profit"),
|
||||
_30pct: CohortName::new("profit_ge_30pct", "≥30%", "30%+ Profit"),
|
||||
_40pct: CohortName::new("profit_ge_40pct", "≥40%", "40%+ Profit"),
|
||||
_50pct: CohortName::new("profit_ge_50pct", "≥50%", "50%+ Profit"),
|
||||
_60pct: CohortName::new("profit_ge_60pct", "≥60%", "60%+ Profit"),
|
||||
_70pct: CohortName::new("profit_ge_70pct", "≥70%", "70%+ Profit"),
|
||||
_80pct: CohortName::new("profit_ge_80pct", "≥80%", "80%+ Profit"),
|
||||
_90pct: CohortName::new("profit_ge_90pct", "≥90%", "90%+ Profit"),
|
||||
_100pct: CohortName::new("profit_ge_100pct", "≥100%", "100%+ Profit"),
|
||||
_200pct: CohortName::new("profit_ge_200pct", "≥200%", "200%+ Profit"),
|
||||
_300pct: CohortName::new("profit_ge_300pct", "≥300%", "300%+ Profit"),
|
||||
_500pct: CohortName::new("profit_ge_500pct", "≥500%", "500%+ Profit"),
|
||||
_1000pct: CohortName::new("profit_ge_1000pct", "≥1000%", "1000%+ Profit"),
|
||||
};
|
||||
|
||||
/// Number of profit thresholds.
|
||||
pub const PROFIT_COUNT: usize = 15;
|
||||
|
||||
impl ByProfit<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&PROFIT_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
/// 15 "at least X% profit" aggregate thresholds.
|
||||
///
|
||||
/// Each is a prefix sum over the profitability ranges, from most profitable down.
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByProfit<T> {
|
||||
pub breakeven: T,
|
||||
pub _10pct: T,
|
||||
pub _20pct: T,
|
||||
pub _30pct: T,
|
||||
pub _40pct: T,
|
||||
pub _50pct: T,
|
||||
pub _60pct: T,
|
||||
pub _70pct: T,
|
||||
pub _80pct: T,
|
||||
pub _90pct: T,
|
||||
pub _100pct: T,
|
||||
pub _200pct: T,
|
||||
pub _300pct: T,
|
||||
pub _500pct: T,
|
||||
pub _1000pct: T,
|
||||
}
|
||||
|
||||
impl<T> ByProfit<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(&'static str) -> T,
|
||||
{
|
||||
let n = &PROFIT_NAMES;
|
||||
Self {
|
||||
breakeven: create(n.breakeven.id),
|
||||
_10pct: create(n._10pct.id),
|
||||
_20pct: create(n._20pct.id),
|
||||
_30pct: create(n._30pct.id),
|
||||
_40pct: create(n._40pct.id),
|
||||
_50pct: create(n._50pct.id),
|
||||
_60pct: create(n._60pct.id),
|
||||
_70pct: create(n._70pct.id),
|
||||
_80pct: create(n._80pct.id),
|
||||
_90pct: create(n._90pct.id),
|
||||
_100pct: create(n._100pct.id),
|
||||
_200pct: create(n._200pct.id),
|
||||
_300pct: create(n._300pct.id),
|
||||
_500pct: create(n._500pct.id),
|
||||
_1000pct: create(n._1000pct.id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_new<F, E>(mut create: F) -> Result<Self, E>
|
||||
where
|
||||
F: FnMut(&'static str) -> Result<T, E>,
|
||||
{
|
||||
let n = &PROFIT_NAMES;
|
||||
Ok(Self {
|
||||
breakeven: create(n.breakeven.id)?,
|
||||
_10pct: create(n._10pct.id)?,
|
||||
_20pct: create(n._20pct.id)?,
|
||||
_30pct: create(n._30pct.id)?,
|
||||
_40pct: create(n._40pct.id)?,
|
||||
_50pct: create(n._50pct.id)?,
|
||||
_60pct: create(n._60pct.id)?,
|
||||
_70pct: create(n._70pct.id)?,
|
||||
_80pct: create(n._80pct.id)?,
|
||||
_90pct: create(n._90pct.id)?,
|
||||
_100pct: create(n._100pct.id)?,
|
||||
_200pct: create(n._200pct.id)?,
|
||||
_300pct: create(n._300pct.id)?,
|
||||
_500pct: create(n._500pct.id)?,
|
||||
_1000pct: create(n._1000pct.id)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self.breakeven,
|
||||
&self._10pct,
|
||||
&self._20pct,
|
||||
&self._30pct,
|
||||
&self._40pct,
|
||||
&self._50pct,
|
||||
&self._60pct,
|
||||
&self._70pct,
|
||||
&self._80pct,
|
||||
&self._90pct,
|
||||
&self._100pct,
|
||||
&self._200pct,
|
||||
&self._300pct,
|
||||
&self._500pct,
|
||||
&self._1000pct,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
|
||||
[
|
||||
&mut self.breakeven,
|
||||
&mut self._10pct,
|
||||
&mut self._20pct,
|
||||
&mut self._30pct,
|
||||
&mut self._40pct,
|
||||
&mut self._50pct,
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
&mut self._100pct,
|
||||
&mut self._200pct,
|
||||
&mut self._300pct,
|
||||
&mut self._500pct,
|
||||
&mut self._1000pct,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
[
|
||||
&mut self.breakeven,
|
||||
&mut self._10pct,
|
||||
&mut self._20pct,
|
||||
&mut self._30pct,
|
||||
&mut self._40pct,
|
||||
&mut self._50pct,
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
&mut self._100pct,
|
||||
&mut self._200pct,
|
||||
&mut self._300pct,
|
||||
&mut self._500pct,
|
||||
&mut self._1000pct,
|
||||
]
|
||||
.into_par_iter()
|
||||
}
|
||||
|
||||
/// Access as array for indexed accumulation.
|
||||
pub fn as_array_mut(&mut self) -> [&mut T; PROFIT_COUNT] {
|
||||
[
|
||||
&mut self.breakeven,
|
||||
&mut self._10pct,
|
||||
&mut self._20pct,
|
||||
&mut self._30pct,
|
||||
&mut self._40pct,
|
||||
&mut self._50pct,
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
&mut self._100pct,
|
||||
&mut self._200pct,
|
||||
&mut self._300pct,
|
||||
&mut self._500pct,
|
||||
&mut self._1000pct,
|
||||
]
|
||||
}
|
||||
}
|
||||
381
crates/brk_cohort/src/by_profitability_range.rs
Normal file
381
crates/brk_cohort/src/by_profitability_range.rs
Normal file
@@ -0,0 +1,381 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::Cents;
|
||||
use rayon::prelude::*;
|
||||
use serde::Serialize;
|
||||
|
||||
use super::CohortName;
|
||||
|
||||
/// Number of profitability range boundaries (24 boundaries → 25 buckets).
|
||||
pub const PROFITABILITY_BOUNDARY_COUNT: usize = 24;
|
||||
|
||||
/// Compute 24 boundary prices from spot price for profitability bucketing.
|
||||
///
|
||||
/// Boundaries are returned in ascending price order (most profitable first → least profitable last).
|
||||
/// Bucket assignment: prices ascending in k-way merge means we start at the most-profitable bucket
|
||||
/// (lowest cost basis = highest profit) and advance the cursor as price crosses each boundary.
|
||||
///
|
||||
/// For P% profit: boundary = spot × 100 / (100 + P)
|
||||
/// For L% loss: boundary = spot × 100 / (100 - L)
|
||||
///
|
||||
/// Returns boundaries in ascending order:
|
||||
/// [spot/11, spot/6, spot/4, spot/3, spot/2, spot×100/190, spot×100/180, ..., spot×100/10]
|
||||
pub fn compute_profitability_boundaries(spot: Cents) -> [Cents; PROFITABILITY_BOUNDARY_COUNT] {
|
||||
let s = spot.as_u128();
|
||||
// Divisors in ascending boundary order (ascending price):
|
||||
// profit_over_1000: price < spot/11 → boundary at spot*100/1100 = spot/11
|
||||
// profit_500_to_1000: spot/11 ≤ p < spot/6 → boundary at spot*100/600 = spot/6
|
||||
// profit_300_to_500: spot/6 ≤ p < spot/4 → boundary at spot*100/400 = spot/4
|
||||
// profit_200_to_300: spot/4 ≤ p < spot/3 → boundary at spot*100/300 = spot/3
|
||||
// profit_100_to_200: spot/3 ≤ p < spot/2 → boundary at spot*100/200 = spot/2
|
||||
// profit_90_to_100: spot/2 ≤ p < spot*100/190 → boundary at spot*100/190
|
||||
// profit_80_to_90: → boundary at spot*100/180
|
||||
// profit_70_to_80: → boundary at spot*100/170
|
||||
// profit_60_to_70: → boundary at spot*100/160
|
||||
// profit_50_to_60: → boundary at spot*100/150
|
||||
// profit_40_to_50: → boundary at spot*100/140
|
||||
// profit_30_to_40: → boundary at spot*100/130
|
||||
// profit_20_to_30: → boundary at spot*100/120
|
||||
// profit_10_to_20: → boundary at spot*100/110
|
||||
// profit_0_to_10: → boundary at spot (= spot*100/100)
|
||||
// loss_0_to_10: spot ≤ p < spot*100/90 → boundary at spot*100/90
|
||||
// loss_10_to_20: → boundary at spot*100/80
|
||||
// loss_20_to_30: → boundary at spot*100/70
|
||||
// loss_30_to_40: → boundary at spot*100/60
|
||||
// loss_40_to_50: → boundary at spot*100/50 = spot*2
|
||||
// loss_50_to_60: → boundary at spot*100/40 = spot*5/2
|
||||
// loss_60_to_70: → boundary at spot*100/30 = spot*10/3
|
||||
// loss_70_to_80: → boundary at spot*100/20 = spot*5
|
||||
// loss_80_to_90: → boundary at spot*100/10 = spot*10
|
||||
// loss_90_to_100: spot*10 ≤ p (no upper boundary)
|
||||
let divisors: [u128; PROFITABILITY_BOUNDARY_COUNT] = [
|
||||
1100, // >1000% profit upper bound (spot/11)
|
||||
600, // 500-1000% profit upper bound (spot/6)
|
||||
400, // 300-500% profit upper bound (spot/4)
|
||||
300, // 200-300% profit upper bound (spot/3)
|
||||
200, // 100-200% profit upper bound (spot/2)
|
||||
190, // 90-100% profit upper bound
|
||||
180, // 80-90% profit upper bound
|
||||
170, // 70-80% profit upper bound
|
||||
160, // 60-70% profit upper bound
|
||||
150, // 50-60% profit upper bound
|
||||
140, // 40-50% profit upper bound
|
||||
130, // 30-40% profit upper bound
|
||||
120, // 20-30% profit upper bound
|
||||
110, // 10-20% profit upper bound
|
||||
100, // 0-10% profit upper bound (= spot)
|
||||
90, // 0-10% loss upper bound
|
||||
80, // 10-20% loss upper bound
|
||||
70, // 20-30% loss upper bound
|
||||
60, // 30-40% loss upper bound
|
||||
50, // 40-50% loss upper bound
|
||||
40, // 50-60% loss upper bound
|
||||
30, // 60-70% loss upper bound
|
||||
20, // 70-80% loss upper bound
|
||||
10, // 80-90% loss upper bound
|
||||
];
|
||||
|
||||
let mut boundaries = [Cents::ZERO; PROFITABILITY_BOUNDARY_COUNT];
|
||||
for (i, &d) in divisors.iter().enumerate() {
|
||||
boundaries[i] = Cents::from(s * 100 / d);
|
||||
}
|
||||
boundaries
|
||||
}
|
||||
|
||||
/// Profitability range names (25 ranges, from most profitable to most in loss)
|
||||
pub const PROFITABILITY_RANGE_NAMES: ByProfitabilityRange<CohortName> = ByProfitabilityRange {
|
||||
profit_over_1000: CohortName::new("profit_over_1000pct", ">1000%", "Over 1000% Profit"),
|
||||
profit_500_to_1000: CohortName::new("profit_500_to_1000pct", "500-1000%", "500-1000% Profit"),
|
||||
profit_300_to_500: CohortName::new("profit_300_to_500pct", "300-500%", "300-500% Profit"),
|
||||
profit_200_to_300: CohortName::new("profit_200_to_300pct", "200-300%", "200-300% Profit"),
|
||||
profit_100_to_200: CohortName::new("profit_100_to_200pct", "100-200%", "100-200% Profit"),
|
||||
profit_90_to_100: CohortName::new("profit_90_to_100pct", "90-100%", "90-100% Profit"),
|
||||
profit_80_to_90: CohortName::new("profit_80_to_90pct", "80-90%", "80-90% Profit"),
|
||||
profit_70_to_80: CohortName::new("profit_70_to_80pct", "70-80%", "70-80% Profit"),
|
||||
profit_60_to_70: CohortName::new("profit_60_to_70pct", "60-70%", "60-70% Profit"),
|
||||
profit_50_to_60: CohortName::new("profit_50_to_60pct", "50-60%", "50-60% Profit"),
|
||||
profit_40_to_50: CohortName::new("profit_40_to_50pct", "40-50%", "40-50% Profit"),
|
||||
profit_30_to_40: CohortName::new("profit_30_to_40pct", "30-40%", "30-40% Profit"),
|
||||
profit_20_to_30: CohortName::new("profit_20_to_30pct", "20-30%", "20-30% Profit"),
|
||||
profit_10_to_20: CohortName::new("profit_10_to_20pct", "10-20%", "10-20% Profit"),
|
||||
profit_0_to_10: CohortName::new("profit_0_to_10pct", "0-10%", "0-10% Profit"),
|
||||
loss_0_to_10: CohortName::new("loss_0_to_10pct", "0-10%L", "0-10% Loss"),
|
||||
loss_10_to_20: CohortName::new("loss_10_to_20pct", "10-20%L", "10-20% Loss"),
|
||||
loss_20_to_30: CohortName::new("loss_20_to_30pct", "20-30%L", "20-30% Loss"),
|
||||
loss_30_to_40: CohortName::new("loss_30_to_40pct", "30-40%L", "30-40% Loss"),
|
||||
loss_40_to_50: CohortName::new("loss_40_to_50pct", "40-50%L", "40-50% Loss"),
|
||||
loss_50_to_60: CohortName::new("loss_50_to_60pct", "50-60%L", "50-60% Loss"),
|
||||
loss_60_to_70: CohortName::new("loss_60_to_70pct", "60-70%L", "60-70% Loss"),
|
||||
loss_70_to_80: CohortName::new("loss_70_to_80pct", "70-80%L", "70-80% Loss"),
|
||||
loss_80_to_90: CohortName::new("loss_80_to_90pct", "80-90%L", "80-90% Loss"),
|
||||
loss_90_to_100: CohortName::new("loss_90_to_100pct", "90-100%L", "90-100% Loss"),
|
||||
};
|
||||
|
||||
impl ByProfitabilityRange<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&PROFITABILITY_RANGE_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
/// 25 profitability range buckets ordered from most profitable to most in loss.
|
||||
///
|
||||
/// During the k-way merge (ascending price order), the cursor starts at bucket 0
|
||||
/// (profit_over_1000, lowest cost basis) and advances as price crosses each boundary.
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByProfitabilityRange<T> {
|
||||
pub profit_over_1000: T,
|
||||
pub profit_500_to_1000: T,
|
||||
pub profit_300_to_500: T,
|
||||
pub profit_200_to_300: T,
|
||||
pub profit_100_to_200: T,
|
||||
pub profit_90_to_100: T,
|
||||
pub profit_80_to_90: T,
|
||||
pub profit_70_to_80: T,
|
||||
pub profit_60_to_70: T,
|
||||
pub profit_50_to_60: T,
|
||||
pub profit_40_to_50: T,
|
||||
pub profit_30_to_40: T,
|
||||
pub profit_20_to_30: T,
|
||||
pub profit_10_to_20: T,
|
||||
pub profit_0_to_10: T,
|
||||
pub loss_0_to_10: T,
|
||||
pub loss_10_to_20: T,
|
||||
pub loss_20_to_30: T,
|
||||
pub loss_30_to_40: T,
|
||||
pub loss_40_to_50: T,
|
||||
pub loss_50_to_60: T,
|
||||
pub loss_60_to_70: T,
|
||||
pub loss_70_to_80: T,
|
||||
pub loss_80_to_90: T,
|
||||
pub loss_90_to_100: T,
|
||||
}
|
||||
|
||||
/// Number of profitability range buckets.
|
||||
pub const PROFITABILITY_RANGE_COUNT: usize = 25;
|
||||
|
||||
impl<T> ByProfitabilityRange<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(&'static str) -> T,
|
||||
{
|
||||
let n = &PROFITABILITY_RANGE_NAMES;
|
||||
Self {
|
||||
profit_over_1000: create(n.profit_over_1000.id),
|
||||
profit_500_to_1000: create(n.profit_500_to_1000.id),
|
||||
profit_300_to_500: create(n.profit_300_to_500.id),
|
||||
profit_200_to_300: create(n.profit_200_to_300.id),
|
||||
profit_100_to_200: create(n.profit_100_to_200.id),
|
||||
profit_90_to_100: create(n.profit_90_to_100.id),
|
||||
profit_80_to_90: create(n.profit_80_to_90.id),
|
||||
profit_70_to_80: create(n.profit_70_to_80.id),
|
||||
profit_60_to_70: create(n.profit_60_to_70.id),
|
||||
profit_50_to_60: create(n.profit_50_to_60.id),
|
||||
profit_40_to_50: create(n.profit_40_to_50.id),
|
||||
profit_30_to_40: create(n.profit_30_to_40.id),
|
||||
profit_20_to_30: create(n.profit_20_to_30.id),
|
||||
profit_10_to_20: create(n.profit_10_to_20.id),
|
||||
profit_0_to_10: create(n.profit_0_to_10.id),
|
||||
loss_0_to_10: create(n.loss_0_to_10.id),
|
||||
loss_10_to_20: create(n.loss_10_to_20.id),
|
||||
loss_20_to_30: create(n.loss_20_to_30.id),
|
||||
loss_30_to_40: create(n.loss_30_to_40.id),
|
||||
loss_40_to_50: create(n.loss_40_to_50.id),
|
||||
loss_50_to_60: create(n.loss_50_to_60.id),
|
||||
loss_60_to_70: create(n.loss_60_to_70.id),
|
||||
loss_70_to_80: create(n.loss_70_to_80.id),
|
||||
loss_80_to_90: create(n.loss_80_to_90.id),
|
||||
loss_90_to_100: create(n.loss_90_to_100.id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_new<F, E>(mut create: F) -> Result<Self, E>
|
||||
where
|
||||
F: FnMut(&'static str) -> Result<T, E>,
|
||||
{
|
||||
let n = &PROFITABILITY_RANGE_NAMES;
|
||||
Ok(Self {
|
||||
profit_over_1000: create(n.profit_over_1000.id)?,
|
||||
profit_500_to_1000: create(n.profit_500_to_1000.id)?,
|
||||
profit_300_to_500: create(n.profit_300_to_500.id)?,
|
||||
profit_200_to_300: create(n.profit_200_to_300.id)?,
|
||||
profit_100_to_200: create(n.profit_100_to_200.id)?,
|
||||
profit_90_to_100: create(n.profit_90_to_100.id)?,
|
||||
profit_80_to_90: create(n.profit_80_to_90.id)?,
|
||||
profit_70_to_80: create(n.profit_70_to_80.id)?,
|
||||
profit_60_to_70: create(n.profit_60_to_70.id)?,
|
||||
profit_50_to_60: create(n.profit_50_to_60.id)?,
|
||||
profit_40_to_50: create(n.profit_40_to_50.id)?,
|
||||
profit_30_to_40: create(n.profit_30_to_40.id)?,
|
||||
profit_20_to_30: create(n.profit_20_to_30.id)?,
|
||||
profit_10_to_20: create(n.profit_10_to_20.id)?,
|
||||
profit_0_to_10: create(n.profit_0_to_10.id)?,
|
||||
loss_0_to_10: create(n.loss_0_to_10.id)?,
|
||||
loss_10_to_20: create(n.loss_10_to_20.id)?,
|
||||
loss_20_to_30: create(n.loss_20_to_30.id)?,
|
||||
loss_30_to_40: create(n.loss_30_to_40.id)?,
|
||||
loss_40_to_50: create(n.loss_40_to_50.id)?,
|
||||
loss_50_to_60: create(n.loss_50_to_60.id)?,
|
||||
loss_60_to_70: create(n.loss_60_to_70.id)?,
|
||||
loss_70_to_80: create(n.loss_70_to_80.id)?,
|
||||
loss_80_to_90: create(n.loss_80_to_90.id)?,
|
||||
loss_90_to_100: create(n.loss_90_to_100.id)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||
[
|
||||
&self.profit_over_1000,
|
||||
&self.profit_500_to_1000,
|
||||
&self.profit_300_to_500,
|
||||
&self.profit_200_to_300,
|
||||
&self.profit_100_to_200,
|
||||
&self.profit_90_to_100,
|
||||
&self.profit_80_to_90,
|
||||
&self.profit_70_to_80,
|
||||
&self.profit_60_to_70,
|
||||
&self.profit_50_to_60,
|
||||
&self.profit_40_to_50,
|
||||
&self.profit_30_to_40,
|
||||
&self.profit_20_to_30,
|
||||
&self.profit_10_to_20,
|
||||
&self.profit_0_to_10,
|
||||
&self.loss_0_to_10,
|
||||
&self.loss_10_to_20,
|
||||
&self.loss_20_to_30,
|
||||
&self.loss_30_to_40,
|
||||
&self.loss_40_to_50,
|
||||
&self.loss_50_to_60,
|
||||
&self.loss_60_to_70,
|
||||
&self.loss_70_to_80,
|
||||
&self.loss_80_to_90,
|
||||
&self.loss_90_to_100,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
|
||||
[
|
||||
&mut self.profit_over_1000,
|
||||
&mut self.profit_500_to_1000,
|
||||
&mut self.profit_300_to_500,
|
||||
&mut self.profit_200_to_300,
|
||||
&mut self.profit_100_to_200,
|
||||
&mut self.profit_90_to_100,
|
||||
&mut self.profit_80_to_90,
|
||||
&mut self.profit_70_to_80,
|
||||
&mut self.profit_60_to_70,
|
||||
&mut self.profit_50_to_60,
|
||||
&mut self.profit_40_to_50,
|
||||
&mut self.profit_30_to_40,
|
||||
&mut self.profit_20_to_30,
|
||||
&mut self.profit_10_to_20,
|
||||
&mut self.profit_0_to_10,
|
||||
&mut self.loss_0_to_10,
|
||||
&mut self.loss_10_to_20,
|
||||
&mut self.loss_20_to_30,
|
||||
&mut self.loss_30_to_40,
|
||||
&mut self.loss_40_to_50,
|
||||
&mut self.loss_50_to_60,
|
||||
&mut self.loss_60_to_70,
|
||||
&mut self.loss_70_to_80,
|
||||
&mut self.loss_80_to_90,
|
||||
&mut self.loss_90_to_100,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
[
|
||||
&mut self.profit_over_1000,
|
||||
&mut self.profit_500_to_1000,
|
||||
&mut self.profit_300_to_500,
|
||||
&mut self.profit_200_to_300,
|
||||
&mut self.profit_100_to_200,
|
||||
&mut self.profit_90_to_100,
|
||||
&mut self.profit_80_to_90,
|
||||
&mut self.profit_70_to_80,
|
||||
&mut self.profit_60_to_70,
|
||||
&mut self.profit_50_to_60,
|
||||
&mut self.profit_40_to_50,
|
||||
&mut self.profit_30_to_40,
|
||||
&mut self.profit_20_to_30,
|
||||
&mut self.profit_10_to_20,
|
||||
&mut self.profit_0_to_10,
|
||||
&mut self.loss_0_to_10,
|
||||
&mut self.loss_10_to_20,
|
||||
&mut self.loss_20_to_30,
|
||||
&mut self.loss_30_to_40,
|
||||
&mut self.loss_40_to_50,
|
||||
&mut self.loss_50_to_60,
|
||||
&mut self.loss_60_to_70,
|
||||
&mut self.loss_70_to_80,
|
||||
&mut self.loss_80_to_90,
|
||||
&mut self.loss_90_to_100,
|
||||
]
|
||||
.into_par_iter()
|
||||
}
|
||||
|
||||
/// Access as a fixed-size array of references (for indexed access during merge).
|
||||
pub fn as_array(&self) -> [&T; PROFITABILITY_RANGE_COUNT] {
|
||||
[
|
||||
&self.profit_over_1000,
|
||||
&self.profit_500_to_1000,
|
||||
&self.profit_300_to_500,
|
||||
&self.profit_200_to_300,
|
||||
&self.profit_100_to_200,
|
||||
&self.profit_90_to_100,
|
||||
&self.profit_80_to_90,
|
||||
&self.profit_70_to_80,
|
||||
&self.profit_60_to_70,
|
||||
&self.profit_50_to_60,
|
||||
&self.profit_40_to_50,
|
||||
&self.profit_30_to_40,
|
||||
&self.profit_20_to_30,
|
||||
&self.profit_10_to_20,
|
||||
&self.profit_0_to_10,
|
||||
&self.loss_0_to_10,
|
||||
&self.loss_10_to_20,
|
||||
&self.loss_20_to_30,
|
||||
&self.loss_30_to_40,
|
||||
&self.loss_40_to_50,
|
||||
&self.loss_50_to_60,
|
||||
&self.loss_60_to_70,
|
||||
&self.loss_70_to_80,
|
||||
&self.loss_80_to_90,
|
||||
&self.loss_90_to_100,
|
||||
]
|
||||
}
|
||||
|
||||
/// Access as a fixed-size array of mutable references (for indexed access during merge).
|
||||
pub fn as_array_mut(&mut self) -> [&mut T; PROFITABILITY_RANGE_COUNT] {
|
||||
[
|
||||
&mut self.profit_over_1000,
|
||||
&mut self.profit_500_to_1000,
|
||||
&mut self.profit_300_to_500,
|
||||
&mut self.profit_200_to_300,
|
||||
&mut self.profit_100_to_200,
|
||||
&mut self.profit_90_to_100,
|
||||
&mut self.profit_80_to_90,
|
||||
&mut self.profit_70_to_80,
|
||||
&mut self.profit_60_to_70,
|
||||
&mut self.profit_50_to_60,
|
||||
&mut self.profit_40_to_50,
|
||||
&mut self.profit_30_to_40,
|
||||
&mut self.profit_20_to_30,
|
||||
&mut self.profit_10_to_20,
|
||||
&mut self.profit_0_to_10,
|
||||
&mut self.loss_0_to_10,
|
||||
&mut self.loss_10_to_20,
|
||||
&mut self.loss_20_to_30,
|
||||
&mut self.loss_30_to_40,
|
||||
&mut self.loss_40_to_50,
|
||||
&mut self.loss_50_to_60,
|
||||
&mut self.loss_60_to_70,
|
||||
&mut self.loss_70_to_80,
|
||||
&mut self.loss_80_to_90,
|
||||
&mut self.loss_90_to_100,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,12 @@ 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;
|
||||
@@ -34,9 +37,12 @@ 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::*;
|
||||
|
||||
@@ -15,7 +15,7 @@ use crate::{blocks, distribution::DynCohortVecs, indexes, prices};
|
||||
use crate::distribution::metrics::{
|
||||
AllCohortMetrics, BasicCohortMetrics, CohortMetricsBase, CoreCohortMetrics,
|
||||
ExtendedAdjustedCohortMetrics, ExtendedCohortMetrics, ImportConfig, MinimalCohortMetrics,
|
||||
SupplyMetrics,
|
||||
ProfitabilityMetrics, SupplyMetrics,
|
||||
};
|
||||
|
||||
use super::{percentiles::PercentileCache, vecs::UTXOCohortVecs};
|
||||
@@ -39,6 +39,7 @@ pub struct UTXOCohorts<M: StorageMode = Rw> {
|
||||
pub amount_range: ByAmountRange<UTXOCohortVecs<MinimalCohortMetrics<M>>>,
|
||||
pub lt_amount: ByLowerThanAmount<UTXOCohortVecs<MinimalCohortMetrics<M>>>,
|
||||
pub type_: BySpendableType<UTXOCohortVecs<MinimalCohortMetrics<M>>>,
|
||||
pub profitability: ProfitabilityMetrics<M>,
|
||||
#[traversable(skip)]
|
||||
pub(super) percentile_cache: PercentileCache,
|
||||
/// Cached partition_point positions for tick_tock boundary searches.
|
||||
@@ -141,6 +142,9 @@ impl UTXOCohorts<Rw> {
|
||||
AllCohortMetrics::forced_import_with_supply(&all_cfg, all_supply)?,
|
||||
);
|
||||
|
||||
// Phase 3b: Import profitability metrics (derived from "all" during k-way merge).
|
||||
let profitability = ProfitabilityMetrics::forced_import(db, v, indexes)?;
|
||||
|
||||
// Phase 4: Import aggregate cohorts.
|
||||
|
||||
// sth: ExtendedAdjustedCohortMetrics
|
||||
@@ -227,6 +231,7 @@ impl UTXOCohorts<Rw> {
|
||||
amount_range,
|
||||
lt_amount,
|
||||
ge_amount,
|
||||
profitability,
|
||||
percentile_cache: PercentileCache::default(),
|
||||
tick_tock_cached_positions: [0; 20],
|
||||
})
|
||||
@@ -590,6 +595,7 @@ impl UTXOCohorts<Rw> {
|
||||
for v in self.type_.iter_mut() {
|
||||
vecs.extend(v.metrics.collect_all_vecs_mut());
|
||||
}
|
||||
vecs.extend(self.profitability.collect_all_vecs_mut());
|
||||
vecs.into_par_iter()
|
||||
}
|
||||
|
||||
@@ -599,12 +605,13 @@ impl UTXOCohorts<Rw> {
|
||||
.try_for_each(|v| v.write_state(height, cleanup))
|
||||
}
|
||||
|
||||
/// Get minimum height from all separate cohorts' height-indexed vectors.
|
||||
/// Get minimum height from all separate cohorts' + profitability height-indexed vectors.
|
||||
pub(crate) fn min_separate_stateful_height_len(&self) -> Height {
|
||||
self.iter_separate()
|
||||
.map(|v| Height::from(v.min_stateful_height_len()))
|
||||
.min()
|
||||
.unwrap_or_default()
|
||||
.min(Height::from(self.profitability.min_stateful_height_len()))
|
||||
}
|
||||
|
||||
/// Import state for all separate cohorts at or before given height.
|
||||
@@ -650,7 +657,6 @@ impl UTXOCohorts<Rw> {
|
||||
for v in self.lt_amount.iter_mut() {
|
||||
v.metrics.validate_computed_versions(base_version)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use std::{cmp::Reverse, collections::BinaryHeap, fs, path::Path};
|
||||
|
||||
use brk_cohort::{Filtered, TERM_NAMES};
|
||||
use brk_cohort::{
|
||||
compute_profitability_boundaries, Filtered, PROFITABILITY_BOUNDARY_COUNT,
|
||||
PROFITABILITY_RANGE_COUNT, PROFIT_COUNT, TERM_NAMES,
|
||||
};
|
||||
use brk_error::Result;
|
||||
use brk_types::{Cents, CentsCompact, CostBasisDistribution, Date, Height, Sats};
|
||||
use brk_types::{Cents, CentsCompact, CostBasisDistribution, Date, Dollars, Height, Sats};
|
||||
|
||||
use crate::internal::{PERCENTILES, PERCENTILES_LEN};
|
||||
|
||||
use crate::distribution::metrics::{CohortMetricsBase, CostBasis};
|
||||
use crate::distribution::metrics::{CostBasis, ProfitabilityMetrics};
|
||||
|
||||
use super::groups::UTXOCohorts;
|
||||
|
||||
@@ -27,45 +30,47 @@ impl CachedPercentiles {
|
||||
}
|
||||
}
|
||||
|
||||
/// Cached percentile results for all/sth/lth.
|
||||
/// Cached percentile + profitability results for all/sth/lth.
|
||||
/// Avoids re-merging 21 BTreeMaps on every block.
|
||||
#[derive(Clone, Default)]
|
||||
pub(super) struct PercentileCache {
|
||||
all: CachedPercentiles,
|
||||
sth: CachedPercentiles,
|
||||
lth: CachedPercentiles,
|
||||
profitability: [(u64, u128); PROFITABILITY_RANGE_COUNT],
|
||||
initialized: bool,
|
||||
}
|
||||
|
||||
impl UTXOCohorts {
|
||||
/// Compute and push percentiles for aggregate cohorts (all, sth, lth).
|
||||
/// Compute and push percentiles + profitability for aggregate cohorts.
|
||||
///
|
||||
/// Full K-way merge only runs at day boundaries or when the cache is empty.
|
||||
/// For intermediate blocks, pushes cached percentile arrays.
|
||||
/// For intermediate blocks, pushes cached values.
|
||||
pub(crate) fn truncate_push_aggregate_percentiles(
|
||||
&mut self,
|
||||
height: Height,
|
||||
spot_price: Cents,
|
||||
date_opt: Option<Date>,
|
||||
states_path: &Path,
|
||||
) -> Result<()> {
|
||||
if date_opt.is_some() || !self.percentile_cache.initialized {
|
||||
self.merge_and_push_percentiles(height, date_opt, states_path)
|
||||
} else {
|
||||
self.push_cached_percentiles(height)
|
||||
self.recompute_cache(spot_price, date_opt, states_path)?;
|
||||
}
|
||||
self.push_cached(height)
|
||||
}
|
||||
|
||||
/// Full K-way merge: compute percentiles from scratch, update cache, push.
|
||||
fn merge_and_push_percentiles(
|
||||
/// Full K-way merge: recompute percentiles + profitability from scratch, update cache.
|
||||
fn recompute_cache(
|
||||
&mut self,
|
||||
height: Height,
|
||||
spot_price: Cents,
|
||||
date_opt: Option<Date>,
|
||||
states_path: &Path,
|
||||
) -> Result<()> {
|
||||
let collect_merged = date_opt.is_some();
|
||||
let boundaries = compute_profitability_boundaries(spot_price);
|
||||
|
||||
let targets = {
|
||||
let sth_filter = self.sth.metrics.filter().clone();
|
||||
let sth_filter = self.sth.metrics.filter.clone();
|
||||
let mut totals = AllSthLth::<(u64, u128)>::default();
|
||||
|
||||
let maps: Vec<_> = self
|
||||
@@ -101,31 +106,26 @@ impl UTXOCohorts {
|
||||
};
|
||||
let all_has_data = totals.all.0 > 0;
|
||||
let mut targets = totals.map(|(sats, usd)| PercTarget::new(sats, usd, cap));
|
||||
self.percentile_cache.profitability = Default::default();
|
||||
|
||||
if all_has_data {
|
||||
merge_k_way(&maps, &mut targets, collect_merged);
|
||||
merge_k_way(
|
||||
&maps,
|
||||
&mut targets,
|
||||
&boundaries,
|
||||
&mut self.percentile_cache.profitability,
|
||||
collect_merged,
|
||||
);
|
||||
}
|
||||
|
||||
targets
|
||||
};
|
||||
|
||||
// Update cache + push
|
||||
self.percentile_cache.all = targets.all.to_cached();
|
||||
self.percentile_cache.sth = targets.sth.to_cached();
|
||||
self.percentile_cache.lth = targets.lth.to_cached();
|
||||
self.percentile_cache.initialized = true;
|
||||
|
||||
self.percentile_cache
|
||||
.all
|
||||
.push(height, &mut self.all.metrics.cost_basis)?;
|
||||
self.percentile_cache
|
||||
.sth
|
||||
.push(height, &mut self.sth.metrics.cost_basis)?;
|
||||
self.percentile_cache
|
||||
.lth
|
||||
.push(height, &mut self.lth.metrics.cost_basis)?;
|
||||
|
||||
// Serialize full distribution at day boundaries
|
||||
if let Some(date) = date_opt {
|
||||
write_distribution(states_path, "all", date, targets.all.merged)?;
|
||||
write_distribution(states_path, TERM_NAMES.short.id, date, targets.sth.merged)?;
|
||||
@@ -135,8 +135,8 @@ impl UTXOCohorts {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fast path: push cached percentile arrays.
|
||||
fn push_cached_percentiles(&mut self, height: Height) -> Result<()> {
|
||||
/// Push cached percentile + profitability values.
|
||||
fn push_cached(&mut self, height: Height) -> Result<()> {
|
||||
self.percentile_cache
|
||||
.all
|
||||
.push(height, &mut self.all.metrics.cost_basis)?;
|
||||
@@ -146,10 +146,60 @@ impl UTXOCohorts {
|
||||
self.percentile_cache
|
||||
.lth
|
||||
.push(height, &mut self.lth.metrics.cost_basis)?;
|
||||
Ok(())
|
||||
push_profitability(
|
||||
height,
|
||||
&self.percentile_cache.profitability,
|
||||
&mut self.profitability,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert raw (cents × sats) accumulator to Dollars (÷ 100 for cents→dollars, ÷ 1e8 for sats).
|
||||
#[inline]
|
||||
fn raw_usd_to_dollars(raw: u128) -> Dollars {
|
||||
Dollars::from(raw as f64 / 1e10)
|
||||
}
|
||||
|
||||
/// Push profitability range + profit/loss aggregate values to vecs.
|
||||
fn push_profitability(
|
||||
height: Height,
|
||||
buckets: &[(u64, u128); PROFITABILITY_RANGE_COUNT],
|
||||
metrics: &mut ProfitabilityMetrics,
|
||||
) -> Result<()> {
|
||||
// Push 25 range buckets
|
||||
for (i, bucket) in metrics.range.as_array_mut().into_iter().enumerate() {
|
||||
let (sats, usd_raw) = buckets[i];
|
||||
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]
|
||||
let profit_arr = metrics.profit.as_array_mut();
|
||||
let mut cum_sats = 0u64;
|
||||
let mut cum_usd = 0u128;
|
||||
for i in 0..PROFIT_COUNT {
|
||||
cum_sats += buckets[i].0;
|
||||
cum_usd += buckets[i].1;
|
||||
profit_arr[PROFIT_COUNT - 1 - i]
|
||||
.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]
|
||||
let loss_arr = metrics.loss.as_array_mut();
|
||||
let loss_count = loss_arr.len();
|
||||
cum_sats = 0;
|
||||
cum_usd = 0;
|
||||
for i in 0..loss_count {
|
||||
cum_sats += buckets[PROFITABILITY_RANGE_COUNT - 1 - i].0;
|
||||
cum_usd += buckets[PROFITABILITY_RANGE_COUNT - 1 - i].1;
|
||||
loss_arr[loss_count - 1 - i]
|
||||
.truncate_push(height, Sats::from(cum_sats), raw_usd_to_dollars(cum_usd))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_distribution(
|
||||
states_path: &Path,
|
||||
name: &str,
|
||||
@@ -166,9 +216,12 @@ fn write_distribution(
|
||||
}
|
||||
|
||||
/// K-way merge via BinaryHeap over BTreeMap iterators.
|
||||
/// Also accumulates profitability buckets for the "all" target using cursor approach.
|
||||
fn merge_k_way(
|
||||
maps: &[(&std::collections::BTreeMap<CentsCompact, Sats>, bool)],
|
||||
targets: &mut AllSthLth<PercTarget>,
|
||||
boundaries: &[Cents; PROFITABILITY_BOUNDARY_COUNT],
|
||||
prof: &mut [(u64, u128); PROFITABILITY_RANGE_COUNT],
|
||||
collect_merged: bool,
|
||||
) {
|
||||
let mut iters: Vec<_> = maps
|
||||
@@ -185,36 +238,40 @@ fn merge_k_way(
|
||||
}
|
||||
|
||||
let mut current_price: Option<CentsCompact> = None;
|
||||
let mut early_exit = false;
|
||||
let mut boundary_idx = 0usize;
|
||||
|
||||
while let Some(Reverse((price, ci))) = heap.pop() {
|
||||
let (ref mut iter, is_sth) = iters[ci];
|
||||
let (_, &sats) = iter.next().unwrap();
|
||||
let amount = u64::from(sats);
|
||||
let usd = Cents::from(price).as_u128() * amount as u128;
|
||||
let price_cents = Cents::from(price);
|
||||
let usd = price_cents.as_u128() * amount as u128;
|
||||
|
||||
if let Some(prev) = current_price
|
||||
&& prev != price
|
||||
{
|
||||
targets.for_each_mut(|t| t.finalize_price(prev.into(), collect_merged));
|
||||
if !collect_merged && targets.all_match(|t| t.done()) {
|
||||
early_exit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
current_price = Some(price);
|
||||
targets.all.accumulate(amount, usd);
|
||||
targets.term_mut(is_sth).accumulate(amount, usd);
|
||||
|
||||
// Profitability: advance cursor past boundaries (prices are ascending)
|
||||
while boundary_idx < PROFITABILITY_BOUNDARY_COUNT
|
||||
&& price_cents >= boundaries[boundary_idx]
|
||||
{
|
||||
boundary_idx += 1;
|
||||
}
|
||||
prof[boundary_idx].0 += amount;
|
||||
prof[boundary_idx].1 += usd;
|
||||
|
||||
if let Some(&(&next_price, _)) = iter.peek() {
|
||||
heap.push(Reverse((next_price, ci)));
|
||||
}
|
||||
}
|
||||
|
||||
if !early_exit
|
||||
&& let Some(price) = current_price
|
||||
{
|
||||
if let Some(price) = current_price {
|
||||
targets.for_each_mut(|t| t.finalize_price(price.into(), collect_merged));
|
||||
}
|
||||
}
|
||||
@@ -254,9 +311,6 @@ impl<T> AllSthLth<T> {
|
||||
f(&mut self.lth);
|
||||
}
|
||||
|
||||
fn all_match(&self, mut f: impl FnMut(&T) -> bool) -> bool {
|
||||
f(&self.all) && f(&self.sth) && f(&self.lth)
|
||||
}
|
||||
}
|
||||
|
||||
struct PercTarget {
|
||||
@@ -362,8 +416,4 @@ impl PercTarget {
|
||||
self.price_usd = 0;
|
||||
}
|
||||
|
||||
fn done(&self) -> bool {
|
||||
(self.total_sats == 0 || self.sat_idx >= PERCENTILES_LEN)
|
||||
&& (self.total_usd == 0 || self.usd_idx >= PERCENTILES_LEN)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,6 +438,7 @@ pub(crate) fn process_blocks(
|
||||
|
||||
vecs.utxo_cohorts.truncate_push_aggregate_percentiles(
|
||||
height,
|
||||
block_price,
|
||||
date_opt,
|
||||
&vecs.states_path,
|
||||
)?;
|
||||
|
||||
@@ -10,10 +10,10 @@ use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
CentsType, ComputedFromHeight, ComputedFromHeightCumulative,
|
||||
ComputedFromHeightCumulativeSum, ComputedFromHeightRatio, FiatFromHeight, NumericValue,
|
||||
PercentFromHeight, PercentRollingWindows, Price, RollingDelta1m, RollingDeltaExcept1m,
|
||||
RollingWindow24h, RollingWindows, RollingWindowsFrom1w,
|
||||
ValueFromHeight, ValueFromHeightCumulative,
|
||||
ComputedFromHeightCumulativeSum, ComputedFromHeightRatio, FiatFromHeight,
|
||||
FiatRollingDelta1m, FiatRollingDeltaExcept1m, NumericValue, PercentFromHeight,
|
||||
PercentRollingWindows, Price, RollingDelta1m, RollingDeltaExcept1m, RollingWindow24h,
|
||||
RollingWindows, RollingWindowsFrom1w, ValueFromHeight, ValueFromHeightCumulative,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -96,6 +96,16 @@ impl<S: NumericValue + JsonSchema, C: NumericValue + JsonSchema> ConfigImport
|
||||
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
|
||||
}
|
||||
}
|
||||
impl<S: NumericValue + JsonSchema, C: CentsType> ConfigImport for FiatRollingDelta1m<S, C> {
|
||||
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
|
||||
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
|
||||
}
|
||||
}
|
||||
impl<S: NumericValue + JsonSchema, C: CentsType> ConfigImport for FiatRollingDeltaExcept1m<S, C> {
|
||||
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
|
||||
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
|
||||
}
|
||||
}
|
||||
impl<T: BytesVecValue> ConfigImport for BytesVec<Height, T> {
|
||||
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
|
||||
Ok(Self::forced_import(
|
||||
|
||||
@@ -36,6 +36,7 @@ mod cohort;
|
||||
mod config;
|
||||
mod cost_basis;
|
||||
mod outputs;
|
||||
mod profitability;
|
||||
mod realized;
|
||||
mod relative;
|
||||
mod supply;
|
||||
@@ -48,6 +49,7 @@ pub use cohort::{
|
||||
};
|
||||
pub use config::ImportConfig;
|
||||
pub use cost_basis::CostBasis;
|
||||
pub use profitability::ProfitabilityMetrics;
|
||||
pub use outputs::OutputsMetrics;
|
||||
pub use realized::{
|
||||
RealizedAdjusted, RealizedBase, RealizedCore, RealizedFull, RealizedLike, RealizedMinimal,
|
||||
|
||||
124
crates/brk_computer/src/distribution/metrics/profitability.rs
Normal file
124
crates/brk_computer/src/distribution/metrics/profitability.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
use brk_cohort::{ByLoss, ByProfit, ByProfitabilityRange};
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Dollars, Height, Sats, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Database, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{indexes, internal::ComputedFromHeight};
|
||||
|
||||
/// Supply + realized cap for a single profitability bucket.
|
||||
#[derive(Traversable)]
|
||||
pub struct ProfitabilityBucket<M: StorageMode = Rw> {
|
||||
pub supply: ComputedFromHeight<Sats, M>,
|
||||
pub realized_cap: ComputedFromHeight<Dollars, M>,
|
||||
}
|
||||
|
||||
impl<M: StorageMode> ProfitabilityBucket<M> {
|
||||
fn min_len(&self) -> usize {
|
||||
self.supply.height.len().min(self.realized_cap.height.len())
|
||||
}
|
||||
}
|
||||
|
||||
impl ProfitabilityBucket {
|
||||
fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
supply: ComputedFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_supply"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
realized_cap: ComputedFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_realized_cap"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push(
|
||||
&mut self,
|
||||
height: Height,
|
||||
supply: Sats,
|
||||
realized_cap: Dollars,
|
||||
) -> Result<()> {
|
||||
self.supply.height.truncate_push(height, supply)?;
|
||||
self.realized_cap
|
||||
.height
|
||||
.truncate_push(height, realized_cap)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_all_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
vec![
|
||||
&mut self.supply.height as &mut dyn AnyStoredVec,
|
||||
&mut self.realized_cap.height as &mut dyn AnyStoredVec,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// All profitability metrics: 25 ranges + 15 profit thresholds + 10 loss thresholds.
|
||||
#[derive(Traversable)]
|
||||
pub struct ProfitabilityMetrics<M: StorageMode = Rw> {
|
||||
pub range: ByProfitabilityRange<ProfitabilityBucket<M>>,
|
||||
pub profit: ByProfit<ProfitabilityBucket<M>>,
|
||||
pub loss: ByLoss<ProfitabilityBucket<M>>,
|
||||
}
|
||||
|
||||
impl<M: StorageMode> ProfitabilityMetrics<M> {
|
||||
pub(crate) fn min_stateful_height_len(&self) -> usize {
|
||||
self.range.iter()
|
||||
.chain(self.profit.iter())
|
||||
.chain(self.loss.iter())
|
||||
.map(|b| b.min_len())
|
||||
.min()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ProfitabilityMetrics {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let range = ByProfitabilityRange::try_new(|name| {
|
||||
ProfitabilityBucket::forced_import(db, name, version, indexes)
|
||||
})?;
|
||||
|
||||
let profit = ByProfit::try_new(|name| {
|
||||
ProfitabilityBucket::forced_import(db, name, version, indexes)
|
||||
})?;
|
||||
|
||||
let loss = ByLoss::try_new(|name| {
|
||||
ProfitabilityBucket::forced_import(db, name, version, indexes)
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
range,
|
||||
profit,
|
||||
loss,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn collect_all_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = Vec::new();
|
||||
for bucket in self.range.iter_mut() {
|
||||
vecs.extend(bucket.collect_all_vecs_mut());
|
||||
}
|
||||
for bucket in self.profit.iter_mut() {
|
||||
vecs.extend(bucket.collect_all_vecs_mut());
|
||||
}
|
||||
for bucket in self.loss.iter_mut() {
|
||||
vecs.extend(bucket.collect_all_vecs_mut());
|
||||
}
|
||||
vecs
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,8 +10,8 @@ use crate::{
|
||||
blocks,
|
||||
distribution::state::RealizedOps,
|
||||
internal::{
|
||||
ComputedFromHeight, LazyFromHeight, NegCentsUnsignedToDollars, RatioCents64,
|
||||
RollingDelta1m, RollingWindow24h,
|
||||
ComputedFromHeight, FiatRollingDelta1m, LazyFromHeight, NegCentsUnsignedToDollars,
|
||||
RatioCents64, RollingWindow24h,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -27,7 +27,7 @@ pub struct RealizedCore<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub minimal: RealizedMinimal<M>,
|
||||
|
||||
pub realized_cap_delta: RollingDelta1m<Cents, CentsSigned, M>,
|
||||
pub realized_cap_delta: FiatRollingDelta1m<Cents, CentsSigned, M>,
|
||||
|
||||
pub neg_realized_loss: LazyFromHeight<Dollars, Cents>,
|
||||
pub net_realized_pnl: ComputedFromHeight<CentsSigned, M>,
|
||||
|
||||
@@ -14,12 +14,12 @@ use crate::{
|
||||
blocks,
|
||||
distribution::state::RealizedState,
|
||||
internal::{
|
||||
CentsUnsignedToDollars, ComputedFromHeight, ComputedFromHeightCumulative, FiatFromHeight,
|
||||
CentsUnsignedToDollars, ComputedFromHeight, ComputedFromHeightCumulative,
|
||||
ComputedFromHeightRatio, ComputedFromHeightRatioPercentiles,
|
||||
ComputedFromHeightRatioStdDevBands, LazyFromHeight, PercentFromHeight,
|
||||
PercentRollingWindows, Price, RatioCents64, RatioCentsBp32,
|
||||
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDollarsBp32,
|
||||
RollingDelta1m, RollingDeltaExcept1m, RollingWindows, RollingWindowsFrom1w,
|
||||
ComputedFromHeightRatioStdDevBands, FiatFromHeight, FiatRollingDelta1m,
|
||||
FiatRollingDeltaExcept1m, LazyFromHeight, PercentFromHeight, PercentRollingWindows, Price,
|
||||
RatioCents64, RatioCentsBp32, RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32,
|
||||
RatioDollarsBp32, RollingWindows, RollingWindowsFrom1w,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -59,12 +59,12 @@ pub struct RealizedFull<M: StorageMode = Rw> {
|
||||
pub net_realized_pnl_cumulative: ComputedFromHeight<CentsSigned, M>,
|
||||
pub net_realized_pnl_sum_extended: RollingWindowsFrom1w<CentsSigned, M>,
|
||||
|
||||
pub net_pnl_delta: RollingDelta1m<CentsSigned, CentsSigned, M>,
|
||||
pub net_pnl_delta_extended: RollingDeltaExcept1m<CentsSigned, CentsSigned, M>,
|
||||
pub net_pnl_delta: FiatRollingDelta1m<CentsSigned, CentsSigned, M>,
|
||||
pub net_pnl_delta_extended: FiatRollingDeltaExcept1m<CentsSigned, CentsSigned, M>,
|
||||
pub net_pnl_change_1m_rel_to_realized_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub net_pnl_change_1m_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
|
||||
pub realized_cap_delta_extended: RollingDeltaExcept1m<Cents, CentsSigned, M>,
|
||||
pub realized_cap_delta_extended: FiatRollingDeltaExcept1m<Cents, CentsSigned, M>,
|
||||
|
||||
pub investor_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub investor_price_ratio: ComputedFromHeightRatio<M>,
|
||||
@@ -468,14 +468,14 @@ impl RealizedFull {
|
||||
self.net_pnl_change_1m_rel_to_realized_cap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_pnl_delta.change_1m.height,
|
||||
&self.net_pnl_delta.change_1m.cents.height,
|
||||
&self.base.core.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_pnl_change_1m_rel_to_market_cap
|
||||
.compute_binary::<CentsSigned, Dollars, RatioCentsSignedDollarsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_pnl_delta.change_1m.height,
|
||||
&self.net_pnl_delta.change_1m.cents.height,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
|
||||
/// Pre-collect source data from the earliest needed offset.
|
||||
/// Returns (source_data, offset) for use in compute_delta_window.
|
||||
fn collect_source<S: NumericValue>(
|
||||
pub(super) fn collect_source<S: NumericValue>(
|
||||
source: &impl ReadableVec<Height, S>,
|
||||
skip: usize,
|
||||
earliest_starts: &impl ReadableVec<Height, Height>,
|
||||
@@ -40,7 +40,7 @@ fn collect_source<S: NumericValue>(
|
||||
}
|
||||
|
||||
/// Shared computation: change = current - ago, rate = change / ago.
|
||||
fn compute_delta_window<S, C, B>(
|
||||
pub(super) fn compute_delta_window<S, C, B>(
|
||||
change_h: &mut EagerVec<PcoVec<Height, C>>,
|
||||
rate_bps_h: &mut EagerVec<PcoVec<Height, B>>,
|
||||
max_from: Height,
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
//! Fiat delta variants — same as RollingDelta* but change is FiatFromHeight<C>
|
||||
//! (stored cents + lazy USD) instead of ComputedFromHeight<C> (stored cents only).
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPointsSigned32, Height, Version};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{AnyVec, Database, Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
CentsType, FiatFromHeight, NumericValue, PercentFromHeight, PercentRollingWindows,
|
||||
WindowStarts,
|
||||
},
|
||||
};
|
||||
|
||||
use super::delta::{collect_source, compute_delta_window};
|
||||
|
||||
/// Fiat 1m-only delta: fiat change (cents + usd) + rate for the 1-month window.
|
||||
#[derive(Traversable)]
|
||||
pub struct FiatRollingDelta1m<S, C, M: StorageMode = Rw>
|
||||
where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
pub change_1m: FiatFromHeight<C, M>,
|
||||
pub rate_1m: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S, C> FiatRollingDelta1m<S, C>
|
||||
where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
change_1m: FiatFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1m"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_1m: PercentFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_1m"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
_phantom: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
height_1m_ago: &impl ReadableVec<Height, Height>,
|
||||
source: &impl ReadableVec<Height, S>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let skip = self.change_1m.cents.height.len();
|
||||
let (source_data, offset) = collect_source(source, skip, height_1m_ago);
|
||||
|
||||
compute_delta_window(
|
||||
&mut self.change_1m.cents.height,
|
||||
&mut self.rate_1m.bps.height,
|
||||
max_from,
|
||||
height_1m_ago,
|
||||
&source_data,
|
||||
offset,
|
||||
exit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Fiat extended delta: 24h + 1w + 1y windows, fiat change (cents + usd) + rate.
|
||||
#[derive(Traversable)]
|
||||
pub struct FiatRollingDeltaExcept1m<S, C, M: StorageMode = Rw>
|
||||
where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
#[traversable(rename = "24h")]
|
||||
pub change_24h: FiatFromHeight<C, M>,
|
||||
pub change_1w: FiatFromHeight<C, M>,
|
||||
pub change_1y: FiatFromHeight<C, M>,
|
||||
#[traversable(rename = "24h")]
|
||||
pub rate_24h: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub rate_1w: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub rate_1y: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S, C> FiatRollingDeltaExcept1m<S, C>
|
||||
where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
change_24h: FiatFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1w: FiatFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1y: FiatFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_24h: PercentFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_1w: PercentFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_1y: PercentFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
_phantom: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
windows: &WindowStarts<'_>,
|
||||
source: &impl ReadableVec<Height, S>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let skip = self.change_24h.cents.height.len();
|
||||
let (source_data, offset) = collect_source(source, skip, windows._1y);
|
||||
|
||||
let changes: [&mut FiatFromHeight<C>; 3] =
|
||||
[&mut self.change_24h, &mut self.change_1w, &mut self.change_1y];
|
||||
let rates = [&mut self.rate_24h, &mut self.rate_1w, &mut self.rate_1y];
|
||||
let starts = [windows._24h, windows._1w, windows._1y];
|
||||
|
||||
for ((change_w, rate_w), starts) in changes.into_iter().zip(rates).zip(starts) {
|
||||
compute_delta_window(
|
||||
&mut change_w.cents.height,
|
||||
&mut rate_w.bps.height,
|
||||
max_from,
|
||||
starts,
|
||||
&source_data,
|
||||
offset,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Fiat rolling delta: all 4 windows, fiat change (cents + usd) + rate.
|
||||
#[derive(Traversable)]
|
||||
pub struct FiatRollingDelta<S, C, M: StorageMode = Rw>
|
||||
where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
pub change_24h: FiatFromHeight<C, M>,
|
||||
pub change_1w: FiatFromHeight<C, M>,
|
||||
pub change_1m: FiatFromHeight<C, M>,
|
||||
pub change_1y: FiatFromHeight<C, M>,
|
||||
pub rate: PercentRollingWindows<BasisPointsSigned32, M>,
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
|
||||
impl<S, C> FiatRollingDelta<S, C>
|
||||
where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
change_24h: FiatFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1w: FiatFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1m: FiatFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1m"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1y: FiatFromHeight::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate: PercentRollingWindows::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
_phantom: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
windows: &WindowStarts<'_>,
|
||||
source: &impl ReadableVec<Height, S>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let skip = self.change_24h.cents.height.len();
|
||||
let (source_data, offset) = collect_source(source, skip, windows._1y);
|
||||
|
||||
let changes: [&mut FiatFromHeight<C>; 4] = [
|
||||
&mut self.change_24h,
|
||||
&mut self.change_1w,
|
||||
&mut self.change_1m,
|
||||
&mut self.change_1y,
|
||||
];
|
||||
let rates = self.rate.0.as_mut_array();
|
||||
let starts = windows.as_array();
|
||||
|
||||
for ((change_w, rate_w), starts) in changes.into_iter().zip(rates).zip(starts) {
|
||||
compute_delta_window(
|
||||
&mut change_w.cents.height,
|
||||
&mut rate_w.bps.height,
|
||||
max_from,
|
||||
*starts,
|
||||
&source_data,
|
||||
offset,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ mod aggregated;
|
||||
mod cumulative;
|
||||
mod cumulative_sum;
|
||||
mod delta;
|
||||
mod fiat_delta;
|
||||
mod full;
|
||||
mod rolling_average;
|
||||
mod sum;
|
||||
@@ -10,6 +11,7 @@ pub use aggregated::*;
|
||||
pub use cumulative::*;
|
||||
pub use cumulative_sum::*;
|
||||
pub use delta::*;
|
||||
pub use fiat_delta::*;
|
||||
pub use full::*;
|
||||
pub use rolling_average::*;
|
||||
pub use sum::*;
|
||||
|
||||
41
crates/brk_computer/src/internal/from_height/lazy_fiat.rs
Normal file
41
crates/brk_computer/src/internal/from_height/lazy_fiat.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Dollars, Version};
|
||||
use vecdb::ReadableCloneableVec;
|
||||
|
||||
use super::{ComputedFromHeight, LazyFromHeight};
|
||||
use crate::internal::{Identity, NumericValue};
|
||||
|
||||
use super::fiat::CentsType;
|
||||
|
||||
/// Lazy fiat: both cents and usd are lazy views of a stored source.
|
||||
/// Zero extra stored vecs.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyFiatFromHeight<C: CentsType> {
|
||||
pub cents: LazyFromHeight<C, C>,
|
||||
pub usd: LazyFromHeight<Dollars, C>,
|
||||
}
|
||||
|
||||
impl<C: CentsType> LazyFiatFromHeight<C> {
|
||||
pub(crate) fn from_computed(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &ComputedFromHeight<C>,
|
||||
) -> Self
|
||||
where
|
||||
C: NumericValue,
|
||||
{
|
||||
let cents = LazyFromHeight::from_computed::<Identity<C>>(
|
||||
&format!("{name}_cents"),
|
||||
version,
|
||||
source.height.read_only_boxed_clone(),
|
||||
source,
|
||||
);
|
||||
let usd = LazyFromHeight::from_computed::<C::ToDollars>(
|
||||
&format!("{name}_usd"),
|
||||
version,
|
||||
source.height.read_only_boxed_clone(),
|
||||
source,
|
||||
);
|
||||
Self { cents, usd }
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ mod computed;
|
||||
mod constant;
|
||||
mod fiat;
|
||||
mod lazy;
|
||||
mod lazy_fiat;
|
||||
mod percent;
|
||||
mod percentiles;
|
||||
mod price;
|
||||
@@ -17,6 +18,7 @@ pub use computed::*;
|
||||
pub use constant::*;
|
||||
pub use fiat::*;
|
||||
pub use lazy::*;
|
||||
pub use lazy_fiat::*;
|
||||
pub use percent::*;
|
||||
pub use percentiles::*;
|
||||
pub use price::*;
|
||||
|
||||
@@ -44,39 +44,34 @@ impl Vecs {
|
||||
self.velocity
|
||||
.compute(blocks, transactions, distribution, starting_indexes, exit)?;
|
||||
|
||||
// 4. Compute cap growth rates across 4 windows
|
||||
// 4. Compute market cap delta (change + rate across 4 windows)
|
||||
let window_starts = blocks.count.window_starts();
|
||||
|
||||
let realized_cap = &distribution
|
||||
.utxo_cohorts
|
||||
.all
|
||||
.metrics
|
||||
.realized
|
||||
.realized_cap
|
||||
.height;
|
||||
self.market_cap_delta.compute(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.market_cap.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let mcgr_arr = self.market_cap_growth_rate.0.as_mut_array();
|
||||
let rcgr_arr = self.realized_cap_growth_rate.0.as_mut_array();
|
||||
// 5. market_cap_rate - realized_cap_rate per window
|
||||
let all_realized = &distribution.utxo_cohorts.all.metrics.realized;
|
||||
let mcr_arr = self.market_cap_delta.rate.0.as_array();
|
||||
let diff_arr = self.market_minus_realized_cap_growth_rate.0.as_mut_array();
|
||||
let starts_arr = window_starts.as_array();
|
||||
|
||||
// 24h, 1w, 1y from extended; 1m from core delta
|
||||
let rcr_rates = [
|
||||
&all_realized.realized_cap_delta_extended.rate_24h.bps.height,
|
||||
&all_realized.realized_cap_delta_extended.rate_1w.bps.height,
|
||||
&all_realized.realized_cap_delta.rate_1m.bps.height,
|
||||
&all_realized.realized_cap_delta_extended.rate_1y.bps.height,
|
||||
];
|
||||
|
||||
for i in 0..4 {
|
||||
mcgr_arr[i].bps.height.compute_rolling_ratio_change(
|
||||
starting_indexes.height,
|
||||
*starts_arr[i],
|
||||
&self.market_cap.height,
|
||||
exit,
|
||||
)?;
|
||||
rcgr_arr[i].bps.height.compute_rolling_ratio_change(
|
||||
starting_indexes.height,
|
||||
*starts_arr[i],
|
||||
realized_cap,
|
||||
exit,
|
||||
)?;
|
||||
diff_arr[i].height.compute_subtract(
|
||||
starting_indexes.height,
|
||||
&mcgr_arr[i].bps.height,
|
||||
&rcgr_arr[i].bps.height,
|
||||
&mcr_arr[i].bps.height,
|
||||
rcr_rates[i],
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use brk_types::{Cents, Dollars, Sats, Version};
|
||||
use crate::{
|
||||
distribution, indexes,
|
||||
internal::{
|
||||
Identity, LazyFromHeight, LazyValueFromHeight, PercentFromHeight, PercentRollingWindows,
|
||||
FiatRollingDelta, Identity, LazyFiatFromHeight, LazyValueFromHeight, PercentFromHeight,
|
||||
RollingWindows, SatsToBitcoin, finalize_db, open_db,
|
||||
},
|
||||
};
|
||||
@@ -45,30 +45,22 @@ impl Vecs {
|
||||
// Velocity
|
||||
let velocity = super::velocity::Vecs::forced_import(&db, version, indexes)?;
|
||||
|
||||
// Market cap - lazy identity from distribution supply in USD
|
||||
let market_cap = LazyFromHeight::from_lazy::<Identity<Dollars>, Cents>(
|
||||
"market_cap",
|
||||
version,
|
||||
&supply_metrics.total.usd,
|
||||
);
|
||||
// Market cap - lazy fiat (cents + usd) from distribution supply
|
||||
let market_cap =
|
||||
LazyFiatFromHeight::from_computed("market_cap", version, &supply_metrics.total.cents);
|
||||
|
||||
// Growth rates (4 windows: 24h, 1w, 1m, 1y)
|
||||
let market_cap_growth_rate = PercentRollingWindows::forced_import(
|
||||
// Market cap delta (change + rate across 4 windows)
|
||||
let market_cap_delta = FiatRollingDelta::forced_import(
|
||||
&db,
|
||||
"market_cap_growth_rate",
|
||||
version + Version::TWO,
|
||||
indexes,
|
||||
)?;
|
||||
let realized_cap_growth_rate = PercentRollingWindows::forced_import(
|
||||
&db,
|
||||
"realized_cap_growth_rate",
|
||||
version + Version::TWO,
|
||||
"market_cap_delta",
|
||||
version + Version::new(3),
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
let market_minus_realized_cap_growth_rate = RollingWindows::forced_import(
|
||||
&db,
|
||||
"market_minus_realized_cap_growth_rate",
|
||||
version + Version::ONE,
|
||||
version + Version::TWO,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
@@ -79,8 +71,7 @@ impl Vecs {
|
||||
inflation_rate,
|
||||
velocity,
|
||||
market_cap,
|
||||
market_cap_growth_rate,
|
||||
realized_cap_growth_rate,
|
||||
market_cap_delta,
|
||||
market_minus_realized_cap_growth_rate,
|
||||
};
|
||||
finalize_db(&this.db, &this)?;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPointsSigned32, Dollars};
|
||||
use brk_types::{BasisPointsSigned32, Cents, CentsSigned};
|
||||
use vecdb::{Database, Rw, StorageMode};
|
||||
|
||||
use super::{burned, velocity};
|
||||
use crate::internal::{
|
||||
LazyFromHeight, LazyValueFromHeight, PercentFromHeight, PercentRollingWindows, RollingWindows,
|
||||
FiatRollingDelta, LazyFiatFromHeight, LazyValueFromHeight, PercentFromHeight, RollingWindows,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
@@ -16,8 +16,7 @@ pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub burned: burned::Vecs<M>,
|
||||
pub inflation_rate: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub velocity: velocity::Vecs<M>,
|
||||
pub market_cap: LazyFromHeight<Dollars>,
|
||||
pub market_cap_growth_rate: PercentRollingWindows<BasisPointsSigned32, M>,
|
||||
pub realized_cap_growth_rate: PercentRollingWindows<BasisPointsSigned32, M>,
|
||||
pub market_cap: LazyFiatFromHeight<Cents>,
|
||||
pub market_cap_delta: FiatRollingDelta<Cents, CentsSigned, M>,
|
||||
pub market_minus_realized_cap_growth_rate: RollingWindows<BasisPointsSigned32, M>,
|
||||
}
|
||||
|
||||
@@ -1593,8 +1593,8 @@ function createMetricPattern35(client, name) { return /** @type {MetricPattern35
|
||||
* @property {MetricPattern1<Dollars>} negRealizedLoss
|
||||
* @property {BpsPercentRatioPattern} netPnlChange1mRelToMarketCap
|
||||
* @property {BpsPercentRatioPattern} netPnlChange1mRelToRealizedCap
|
||||
* @property {ChangeRatePattern<CentsSigned>} netPnlDelta
|
||||
* @property {_24hChangeRatePattern<CentsSigned>} netPnlDeltaExtended
|
||||
* @property {ChangeRatePattern3} netPnlDelta
|
||||
* @property {_24hChangeRatePattern} netPnlDeltaExtended
|
||||
* @property {MetricPattern1<CentsSigned>} netRealizedPnl
|
||||
* @property {MetricPattern1<CentsSigned>} netRealizedPnlCumulative
|
||||
* @property {BpsPercentRatioPattern} netRealizedPnlRelToRealizedCap
|
||||
@@ -1609,8 +1609,8 @@ function createMetricPattern35(client, name) { return /** @type {MetricPattern35
|
||||
* @property {_1m1w1y24hPattern<Cents>} profitValueDestroyedSum
|
||||
* @property {MetricPattern1<Dollars>} realizedCap
|
||||
* @property {MetricPattern1<Cents>} realizedCapCents
|
||||
* @property {ChangeRatePattern<CentsSigned>} realizedCapDelta
|
||||
* @property {_24hChangeRatePattern<CentsSigned>} realizedCapDeltaExtended
|
||||
* @property {ChangeRatePattern3} realizedCapDelta
|
||||
* @property {_24hChangeRatePattern} realizedCapDeltaExtended
|
||||
* @property {BpsPercentRatioPattern} realizedCapRelToOwnMarketCap
|
||||
* @property {CumulativeHeightPattern<Cents>} realizedLoss
|
||||
* @property {BpsPercentRatioPattern} realizedLossRelToRealizedCap
|
||||
@@ -1668,7 +1668,7 @@ function createCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealized
|
||||
negRealizedLoss: createMetricPattern1(client, _m(acc, 'neg_realized_loss')),
|
||||
netPnlChange1mRelToMarketCap: createBpsPercentRatioPattern(client, _m(acc, 'net_pnl_change_1m_rel_to_market_cap')),
|
||||
netPnlChange1mRelToRealizedCap: createBpsPercentRatioPattern(client, _m(acc, 'net_pnl_change_1m_rel_to_realized_cap')),
|
||||
netPnlDelta: createChangeRatePattern(client, _m(acc, 'net_pnl_delta')),
|
||||
netPnlDelta: createChangeRatePattern3(client, _m(acc, 'net_pnl_delta')),
|
||||
netPnlDeltaExtended: create_24hChangeRatePattern(client, _m(acc, 'net_pnl_delta')),
|
||||
netRealizedPnl: createMetricPattern1(client, _m(acc, 'net_realized_pnl')),
|
||||
netRealizedPnlCumulative: createMetricPattern1(client, _m(acc, 'net_realized_pnl_cumulative')),
|
||||
@@ -1684,7 +1684,7 @@ function createCapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealized
|
||||
profitValueDestroyedSum: create_1m1w1y24hPattern(client, _m(acc, 'profit_value_destroyed')),
|
||||
realizedCap: createMetricPattern1(client, _m(acc, 'realized_cap')),
|
||||
realizedCapCents: createMetricPattern1(client, _m(acc, 'realized_cap_cents')),
|
||||
realizedCapDelta: createChangeRatePattern(client, _m(acc, 'realized_cap_delta')),
|
||||
realizedCapDelta: createChangeRatePattern3(client, _m(acc, 'realized_cap_delta')),
|
||||
realizedCapDeltaExtended: create_24hChangeRatePattern(client, _m(acc, 'realized_cap_delta')),
|
||||
realizedCapRelToOwnMarketCap: createBpsPercentRatioPattern(client, _m(acc, 'realized_cap_rel_to_own_market_cap')),
|
||||
realizedLoss: createCumulativeHeightPattern(client, _m(acc, 'realized_loss')),
|
||||
@@ -1798,7 +1798,7 @@ function create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdSmaZscorePattern(client
|
||||
* @property {_24hPattern<CentsSigned>} netRealizedPnlSum
|
||||
* @property {MetricPattern1<Dollars>} realizedCap
|
||||
* @property {MetricPattern1<Cents>} realizedCapCents
|
||||
* @property {ChangeRatePattern<CentsSigned>} realizedCapDelta
|
||||
* @property {ChangeRatePattern3} realizedCapDelta
|
||||
* @property {CumulativeHeightPattern<Cents>} realizedLoss
|
||||
* @property {_24hPattern<Cents>} realizedLossSum
|
||||
* @property {CentsSatsUsdPattern} realizedPrice
|
||||
@@ -1830,7 +1830,7 @@ function createMvrvNegNetRealizedSentSoprValuePattern(client, acc) {
|
||||
netRealizedPnlSum: create_24hPattern(client, _m(acc, 'net_realized_pnl_24h')),
|
||||
realizedCap: createMetricPattern1(client, _m(acc, 'realized_cap')),
|
||||
realizedCapCents: createMetricPattern1(client, _m(acc, 'realized_cap_cents')),
|
||||
realizedCapDelta: createChangeRatePattern(client, _m(acc, 'realized_cap_delta')),
|
||||
realizedCapDelta: createChangeRatePattern3(client, _m(acc, 'realized_cap_delta')),
|
||||
realizedLoss: createCumulativeHeightPattern(client, _m(acc, 'realized_loss')),
|
||||
realizedLossSum: create_24hPattern(client, _m(acc, 'realized_loss_24h')),
|
||||
realizedPrice: createCentsSatsUsdPattern(client, _m(acc, 'realized_price')),
|
||||
@@ -1910,7 +1910,7 @@ function createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65
|
||||
* @property {_24hPattern<CentsSigned>} netRealizedPnlSum
|
||||
* @property {MetricPattern1<Dollars>} realizedCap
|
||||
* @property {MetricPattern1<Cents>} realizedCapCents
|
||||
* @property {ChangeRatePattern<CentsSigned>} realizedCapDelta
|
||||
* @property {ChangeRatePattern3} realizedCapDelta
|
||||
* @property {CumulativeHeightPattern<Cents>} realizedLoss
|
||||
* @property {_24hPattern<Cents>} realizedLossSum
|
||||
* @property {CentsSatsUsdPattern} realizedPrice
|
||||
@@ -1938,7 +1938,7 @@ function createMvrvNegNetRealizedSoprValuePattern(client, acc) {
|
||||
netRealizedPnlSum: create_24hPattern(client, _m(acc, 'net_realized_pnl_24h')),
|
||||
realizedCap: createMetricPattern1(client, _m(acc, 'realized_cap')),
|
||||
realizedCapCents: createMetricPattern1(client, _m(acc, 'realized_cap_cents')),
|
||||
realizedCapDelta: createChangeRatePattern(client, _m(acc, 'realized_cap_delta')),
|
||||
realizedCapDelta: createChangeRatePattern3(client, _m(acc, 'realized_cap_delta')),
|
||||
realizedLoss: createCumulativeHeightPattern(client, _m(acc, 'realized_loss')),
|
||||
realizedLossSum: create_24hPattern(client, _m(acc, 'realized_loss_24h')),
|
||||
realizedPrice: createCentsSatsUsdPattern(client, _m(acc, 'realized_price')),
|
||||
@@ -2760,6 +2760,31 @@ function createNegNetSupplyUnrealizedPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} _24hChangeRatePattern
|
||||
* @property {BpsCentsPercentRatioUsdPattern} _24h
|
||||
* @property {CentsUsdPattern} change1w
|
||||
* @property {CentsUsdPattern} change1y
|
||||
* @property {BpsPercentRatioPattern} rate1w
|
||||
* @property {BpsPercentRatioPattern} rate1y
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a _24hChangeRatePattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {_24hChangeRatePattern}
|
||||
*/
|
||||
function create_24hChangeRatePattern(client, acc) {
|
||||
return {
|
||||
_24h: createBpsCentsPercentRatioUsdPattern(client, acc),
|
||||
change1w: createCentsUsdPattern(client, _m(acc, 'change_1w')),
|
||||
change1y: createCentsUsdPattern(client, _m(acc, 'change_1y')),
|
||||
rate1w: createBpsPercentRatioPattern(client, _m(acc, 'rate_1w')),
|
||||
rate1y: createBpsPercentRatioPattern(client, _m(acc, 'rate_1y')),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ActivityOutputsRealizedSupplyUnrealizedPattern
|
||||
* @property {SentPattern} activity
|
||||
@@ -2810,6 +2835,31 @@ function createBaseBtcCentsSatsUsdPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} BpsCentsPercentRatioUsdPattern
|
||||
* @property {MetricPattern1<BasisPointsSigned32>} bps
|
||||
* @property {MetricPattern1<CentsSigned>} cents
|
||||
* @property {MetricPattern1<StoredF32>} percent
|
||||
* @property {MetricPattern1<StoredF32>} ratio
|
||||
* @property {MetricPattern1<Dollars>} usd
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a BpsCentsPercentRatioUsdPattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {BpsCentsPercentRatioUsdPattern}
|
||||
*/
|
||||
function createBpsCentsPercentRatioUsdPattern(client, acc) {
|
||||
return {
|
||||
bps: createMetricPattern1(client, _m(acc, 'rate_24h_bps')),
|
||||
cents: createMetricPattern1(client, _m(acc, 'change_24h_cents')),
|
||||
percent: createMetricPattern1(client, _m(acc, 'rate_24h')),
|
||||
ratio: createMetricPattern1(client, _m(acc, 'rate_24h_ratio')),
|
||||
usd: createMetricPattern1(client, _m(acc, 'change_24h_usd')),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmaHistogramLineSignalPattern
|
||||
* @property {MetricPattern1<StoredF32>} emaFast
|
||||
@@ -2864,7 +2914,7 @@ function create_1m1w1y24hHeightPattern(client, acc) {
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @typedef {Object} _24hChangeRatePattern
|
||||
* @typedef {Object} _24hChangeRatePattern2
|
||||
* @property {BaseBpsPercentRatioPattern} _24h
|
||||
* @property {MetricPattern1<T>} change1w
|
||||
* @property {MetricPattern1<T>} change1y
|
||||
@@ -2873,13 +2923,13 @@ function create_1m1w1y24hHeightPattern(client, acc) {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a _24hChangeRatePattern pattern node
|
||||
* Create a _24hChangeRatePattern2 pattern node
|
||||
* @template T
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {_24hChangeRatePattern<T>}
|
||||
* @returns {_24hChangeRatePattern2<T>}
|
||||
*/
|
||||
function create_24hChangeRatePattern(client, acc) {
|
||||
function create_24hChangeRatePattern2(client, acc) {
|
||||
return {
|
||||
_24h: createBaseBpsPercentRatioPattern(client, acc),
|
||||
change1w: createMetricPattern1(client, _m(acc, 'change_1w')),
|
||||
@@ -2960,7 +3010,7 @@ function create_1m1w1y24hPattern5(client, acc) {
|
||||
|
||||
/**
|
||||
* @typedef {Object} BaseBpsPercentRatioPattern
|
||||
* @property {MetricPattern1<CentsSigned>} base
|
||||
* @property {MetricPattern1<SatsSigned>} base
|
||||
* @property {MetricPattern1<BasisPointsSigned32>} bps
|
||||
* @property {MetricPattern1<StoredF32>} percent
|
||||
* @property {MetricPattern1<StoredF32>} ratio
|
||||
@@ -3432,6 +3482,25 @@ function createChangeRatePattern2(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ChangeRatePattern3
|
||||
* @property {CentsUsdPattern} change1m
|
||||
* @property {BpsPercentRatioPattern} rate1m
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a ChangeRatePattern3 pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {ChangeRatePattern3}
|
||||
*/
|
||||
function createChangeRatePattern3(client, acc) {
|
||||
return {
|
||||
change1m: createCentsUsdPattern(client, _m(acc, 'change_1m')),
|
||||
rate1m: createBpsPercentRatioPattern(client, _m(acc, 'rate_1m')),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} HeightSumPattern
|
||||
* @property {MetricPattern18<StoredU64>} height
|
||||
@@ -3451,6 +3520,25 @@ function createHeightSumPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} RealizedSupplyPattern
|
||||
* @property {MetricPattern1<Dollars>} realizedCap
|
||||
* @property {MetricPattern1<Sats>} supply
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a RealizedSupplyPattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated metric name
|
||||
* @returns {RealizedSupplyPattern}
|
||||
*/
|
||||
function createRealizedSupplyPattern(client, acc) {
|
||||
return {
|
||||
realizedCap: createMetricPattern1(client, _m(acc, 'realized_cap')),
|
||||
supply: createMetricPattern1(client, _m(acc, 'supply')),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} SdSmaPattern
|
||||
* @property {MetricPattern1<StoredF32>} sd
|
||||
@@ -4852,6 +4940,7 @@ function create_24hPattern(client, acc) {
|
||||
* @property {MetricsTree_Distribution_UtxoCohorts_AmountRange} amountRange
|
||||
* @property {MetricsTree_Distribution_UtxoCohorts_LtAmount} ltAmount
|
||||
* @property {MetricsTree_Distribution_UtxoCohorts_Type} type
|
||||
* @property {MetricsTree_Distribution_UtxoCohorts_Profitability} profitability
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -4866,8 +4955,8 @@ function create_24hPattern(client, acc) {
|
||||
* @property {MetricsTree_Distribution_UtxoCohorts_All_Relative} relative
|
||||
* @property {MetricPattern1<StoredF32>} dormancy
|
||||
* @property {MetricPattern1<StoredF32>} velocity
|
||||
* @property {_24hChangeRatePattern<SatsSigned>} supplyDeltaExtended
|
||||
* @property {_24hChangeRatePattern<StoredI64>} utxoCountDeltaExtended
|
||||
* @property {_24hChangeRatePattern2<SatsSigned>} supplyDeltaExtended
|
||||
* @property {_24hChangeRatePattern2<StoredI64>} utxoCountDeltaExtended
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -4903,8 +4992,8 @@ function create_24hPattern(client, acc) {
|
||||
* @property {NetNuplSupplyUnrealizedPattern2} relative
|
||||
* @property {MetricPattern1<StoredF32>} dormancy
|
||||
* @property {MetricPattern1<StoredF32>} velocity
|
||||
* @property {_24hChangeRatePattern<SatsSigned>} supplyDeltaExtended
|
||||
* @property {_24hChangeRatePattern<StoredI64>} utxoCountDeltaExtended
|
||||
* @property {_24hChangeRatePattern2<SatsSigned>} supplyDeltaExtended
|
||||
* @property {_24hChangeRatePattern2<StoredI64>} utxoCountDeltaExtended
|
||||
* @property {MetricPattern1<Cents>} adjustedValueCreated
|
||||
* @property {MetricPattern1<Cents>} adjustedValueDestroyed
|
||||
* @property {_1m1w1y24hPattern<Cents>} adjustedValueCreatedSum
|
||||
@@ -4923,8 +5012,8 @@ function create_24hPattern(client, acc) {
|
||||
* @property {NetNuplSupplyUnrealizedPattern2} relative
|
||||
* @property {MetricPattern1<StoredF32>} dormancy
|
||||
* @property {MetricPattern1<StoredF32>} velocity
|
||||
* @property {_24hChangeRatePattern<SatsSigned>} supplyDeltaExtended
|
||||
* @property {_24hChangeRatePattern<StoredI64>} utxoCountDeltaExtended
|
||||
* @property {_24hChangeRatePattern2<SatsSigned>} supplyDeltaExtended
|
||||
* @property {_24hChangeRatePattern2<StoredI64>} utxoCountDeltaExtended
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -5095,6 +5184,75 @@ function create_24hPattern(client, acc) {
|
||||
* @property {ActivityOutputsRealizedSupplyUnrealizedPattern} empty
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Distribution_UtxoCohorts_Profitability
|
||||
* @property {MetricsTree_Distribution_UtxoCohorts_Profitability_Range} range
|
||||
* @property {MetricsTree_Distribution_UtxoCohorts_Profitability_Profit} profit
|
||||
* @property {MetricsTree_Distribution_UtxoCohorts_Profitability_Loss} loss
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Distribution_UtxoCohorts_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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Distribution_UtxoCohorts_Profitability_Profit
|
||||
* @property {RealizedSupplyPattern} breakeven
|
||||
* @property {RealizedSupplyPattern} _10pct
|
||||
* @property {RealizedSupplyPattern} _20pct
|
||||
* @property {RealizedSupplyPattern} _30pct
|
||||
* @property {RealizedSupplyPattern} _40pct
|
||||
* @property {RealizedSupplyPattern} _50pct
|
||||
* @property {RealizedSupplyPattern} _60pct
|
||||
* @property {RealizedSupplyPattern} _70pct
|
||||
* @property {RealizedSupplyPattern} _80pct
|
||||
* @property {RealizedSupplyPattern} _90pct
|
||||
* @property {RealizedSupplyPattern} _100pct
|
||||
* @property {RealizedSupplyPattern} _200pct
|
||||
* @property {RealizedSupplyPattern} _300pct
|
||||
* @property {RealizedSupplyPattern} _500pct
|
||||
* @property {RealizedSupplyPattern} _1000pct
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Distribution_UtxoCohorts_Profitability_Loss
|
||||
* @property {RealizedSupplyPattern} breakeven
|
||||
* @property {RealizedSupplyPattern} _10pct
|
||||
* @property {RealizedSupplyPattern} _20pct
|
||||
* @property {RealizedSupplyPattern} _30pct
|
||||
* @property {RealizedSupplyPattern} _40pct
|
||||
* @property {RealizedSupplyPattern} _50pct
|
||||
* @property {RealizedSupplyPattern} _60pct
|
||||
* @property {RealizedSupplyPattern} _70pct
|
||||
* @property {RealizedSupplyPattern} _80pct
|
||||
* @property {RealizedSupplyPattern} _90pct
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Distribution_AddressCohorts
|
||||
* @property {MetricsTree_Distribution_AddressCohorts_GeAmount} geAmount
|
||||
@@ -5200,9 +5358,8 @@ function create_24hPattern(client, acc) {
|
||||
* @property {MetricsTree_Supply_Burned} burned
|
||||
* @property {BpsPercentRatioPattern} inflationRate
|
||||
* @property {MetricsTree_Supply_Velocity} velocity
|
||||
* @property {MetricPattern1<Dollars>} marketCap
|
||||
* @property {_1m1w1y24hPattern2} marketCapGrowthRate
|
||||
* @property {_1m1w1y24hPattern2} realizedCapGrowthRate
|
||||
* @property {CentsUsdPattern} marketCap
|
||||
* @property {MetricsTree_Supply_MarketCapDelta} marketCapDelta
|
||||
* @property {_1m1w1y24hPattern<BasisPointsSigned32>} marketMinusRealizedCapGrowthRate
|
||||
*/
|
||||
|
||||
@@ -5218,6 +5375,15 @@ function create_24hPattern(client, acc) {
|
||||
* @property {MetricPattern1<StoredF64>} usd
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MetricsTree_Supply_MarketCapDelta
|
||||
* @property {CentsUsdPattern} change24h
|
||||
* @property {CentsUsdPattern} change1w
|
||||
* @property {CentsUsdPattern} change1m
|
||||
* @property {CentsUsdPattern} change1y
|
||||
* @property {_1m1w1y24hPattern2} rate
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main BRK client with metrics tree and API methods
|
||||
* @extends BrkClientBase
|
||||
@@ -7106,8 +7272,8 @@ class BrkClient extends BrkClientBase {
|
||||
},
|
||||
dormancy: createMetricPattern1(this, 'dormancy'),
|
||||
velocity: createMetricPattern1(this, 'velocity'),
|
||||
supplyDeltaExtended: create_24hChangeRatePattern(this, 'supply_delta'),
|
||||
utxoCountDeltaExtended: create_24hChangeRatePattern(this, 'utxo_count_delta'),
|
||||
supplyDeltaExtended: create_24hChangeRatePattern2(this, 'supply_delta'),
|
||||
utxoCountDeltaExtended: create_24hChangeRatePattern2(this, 'utxo_count_delta'),
|
||||
},
|
||||
sth: {
|
||||
supply: createDeltaHalvedTotalPattern(this, 'sth_supply'),
|
||||
@@ -7119,8 +7285,8 @@ class BrkClient extends BrkClientBase {
|
||||
relative: createNetNuplSupplyUnrealizedPattern2(this, 'sth'),
|
||||
dormancy: createMetricPattern1(this, 'sth_dormancy'),
|
||||
velocity: createMetricPattern1(this, 'sth_velocity'),
|
||||
supplyDeltaExtended: create_24hChangeRatePattern(this, 'sth_supply_delta'),
|
||||
utxoCountDeltaExtended: create_24hChangeRatePattern(this, 'sth_utxo_count_delta'),
|
||||
supplyDeltaExtended: create_24hChangeRatePattern2(this, 'sth_supply_delta'),
|
||||
utxoCountDeltaExtended: create_24hChangeRatePattern2(this, 'sth_utxo_count_delta'),
|
||||
adjustedValueCreated: createMetricPattern1(this, 'sth_adjusted_value_created'),
|
||||
adjustedValueDestroyed: createMetricPattern1(this, 'sth_adjusted_value_destroyed'),
|
||||
adjustedValueCreatedSum: create_1m1w1y24hPattern(this, 'sth_adjusted_value_created'),
|
||||
@@ -7137,8 +7303,8 @@ class BrkClient extends BrkClientBase {
|
||||
relative: createNetNuplSupplyUnrealizedPattern2(this, 'lth'),
|
||||
dormancy: createMetricPattern1(this, 'lth_dormancy'),
|
||||
velocity: createMetricPattern1(this, 'lth_velocity'),
|
||||
supplyDeltaExtended: create_24hChangeRatePattern(this, 'lth_supply_delta'),
|
||||
utxoCountDeltaExtended: create_24hChangeRatePattern(this, 'lth_utxo_count_delta'),
|
||||
supplyDeltaExtended: create_24hChangeRatePattern2(this, 'lth_supply_delta'),
|
||||
utxoCountDeltaExtended: create_24hChangeRatePattern2(this, 'lth_utxo_count_delta'),
|
||||
},
|
||||
ageRange: {
|
||||
upTo1h: createActivityOutputsRealizedRelativeSupplyUnrealizedPattern(this, 'utxos_under_1h_old'),
|
||||
@@ -7290,6 +7456,64 @@ class BrkClient extends BrkClientBase {
|
||||
unknown: createActivityOutputsRealizedSupplyUnrealizedPattern(this, 'unknown_outputs'),
|
||||
empty: createActivityOutputsRealizedSupplyUnrealizedPattern(this, 'empty_outputs'),
|
||||
},
|
||||
profitability: {
|
||||
range: {
|
||||
profitOver1000: createRealizedSupplyPattern(this, 'profit_over_1000pct'),
|
||||
profit500To1000: createRealizedSupplyPattern(this, 'profit_500_to_1000pct'),
|
||||
profit300To500: createRealizedSupplyPattern(this, 'profit_300_to_500pct'),
|
||||
profit200To300: createRealizedSupplyPattern(this, 'profit_200_to_300pct'),
|
||||
profit100To200: createRealizedSupplyPattern(this, 'profit_100_to_200pct'),
|
||||
profit90To100: createRealizedSupplyPattern(this, 'profit_90_to_100pct'),
|
||||
profit80To90: createRealizedSupplyPattern(this, 'profit_80_to_90pct'),
|
||||
profit70To80: createRealizedSupplyPattern(this, 'profit_70_to_80pct'),
|
||||
profit60To70: createRealizedSupplyPattern(this, 'profit_60_to_70pct'),
|
||||
profit50To60: createRealizedSupplyPattern(this, 'profit_50_to_60pct'),
|
||||
profit40To50: createRealizedSupplyPattern(this, 'profit_40_to_50pct'),
|
||||
profit30To40: createRealizedSupplyPattern(this, 'profit_30_to_40pct'),
|
||||
profit20To30: createRealizedSupplyPattern(this, 'profit_20_to_30pct'),
|
||||
profit10To20: createRealizedSupplyPattern(this, 'profit_10_to_20pct'),
|
||||
profit0To10: createRealizedSupplyPattern(this, 'profit_0_to_10pct'),
|
||||
loss0To10: createRealizedSupplyPattern(this, 'loss_0_to_10pct'),
|
||||
loss10To20: createRealizedSupplyPattern(this, 'loss_10_to_20pct'),
|
||||
loss20To30: createRealizedSupplyPattern(this, 'loss_20_to_30pct'),
|
||||
loss30To40: createRealizedSupplyPattern(this, 'loss_30_to_40pct'),
|
||||
loss40To50: createRealizedSupplyPattern(this, 'loss_40_to_50pct'),
|
||||
loss50To60: createRealizedSupplyPattern(this, 'loss_50_to_60pct'),
|
||||
loss60To70: createRealizedSupplyPattern(this, 'loss_60_to_70pct'),
|
||||
loss70To80: createRealizedSupplyPattern(this, 'loss_70_to_80pct'),
|
||||
loss80To90: createRealizedSupplyPattern(this, 'loss_80_to_90pct'),
|
||||
loss90To100: createRealizedSupplyPattern(this, 'loss_90_to_100pct'),
|
||||
},
|
||||
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'),
|
||||
},
|
||||
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'),
|
||||
},
|
||||
},
|
||||
},
|
||||
addressCohorts: {
|
||||
geAmount: {
|
||||
@@ -7390,9 +7614,14 @@ class BrkClient extends BrkClientBase {
|
||||
btc: createMetricPattern1(this, 'velocity_btc'),
|
||||
usd: createMetricPattern1(this, 'velocity_usd'),
|
||||
},
|
||||
marketCap: createMetricPattern1(this, 'market_cap'),
|
||||
marketCapGrowthRate: create_1m1w1y24hPattern2(this, 'market_cap_growth_rate'),
|
||||
realizedCapGrowthRate: create_1m1w1y24hPattern2(this, 'realized_cap_growth_rate'),
|
||||
marketCap: createCentsUsdPattern(this, 'market_cap'),
|
||||
marketCapDelta: {
|
||||
change24h: createCentsUsdPattern(this, 'market_cap_delta_change_24h'),
|
||||
change1w: createCentsUsdPattern(this, 'market_cap_delta_change_1w'),
|
||||
change1m: createCentsUsdPattern(this, 'market_cap_delta_change_1m'),
|
||||
change1y: createCentsUsdPattern(this, 'market_cap_delta_change_1y'),
|
||||
rate: create_1m1w1y24hPattern2(this, 'market_cap_delta_rate'),
|
||||
},
|
||||
marketMinusRealizedCapGrowthRate: create_1m1w1y24hPattern(this, 'market_minus_realized_cap_growth_rate'),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2088,8 +2088,8 @@ class CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentS
|
||||
self.neg_realized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_realized_loss'))
|
||||
self.net_pnl_change_1m_rel_to_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_pnl_change_1m_rel_to_market_cap'))
|
||||
self.net_pnl_change_1m_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_pnl_change_1m_rel_to_realized_cap'))
|
||||
self.net_pnl_delta: ChangeRatePattern[CentsSigned] = ChangeRatePattern(client, _m(acc, 'net_pnl_delta'))
|
||||
self.net_pnl_delta_extended: _24hChangeRatePattern[CentsSigned] = _24hChangeRatePattern(client, _m(acc, 'net_pnl_delta'))
|
||||
self.net_pnl_delta: ChangeRatePattern3 = ChangeRatePattern3(client, _m(acc, 'net_pnl_delta'))
|
||||
self.net_pnl_delta_extended: _24hChangeRatePattern = _24hChangeRatePattern(client, _m(acc, 'net_pnl_delta'))
|
||||
self.net_realized_pnl: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'net_realized_pnl'))
|
||||
self.net_realized_pnl_cumulative: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'net_realized_pnl_cumulative'))
|
||||
self.net_realized_pnl_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'net_realized_pnl_rel_to_realized_cap'))
|
||||
@@ -2104,8 +2104,8 @@ class CapCapitulationGrossInvestorLossLowerMvrvNegNetPeakProfitRealizedSellSentS
|
||||
self.profit_value_destroyed_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, _m(acc, 'profit_value_destroyed'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_cap_delta: ChangeRatePattern[CentsSigned] = ChangeRatePattern(client, _m(acc, 'realized_cap_delta'))
|
||||
self.realized_cap_delta_extended: _24hChangeRatePattern[CentsSigned] = _24hChangeRatePattern(client, _m(acc, 'realized_cap_delta'))
|
||||
self.realized_cap_delta: ChangeRatePattern3 = ChangeRatePattern3(client, _m(acc, 'realized_cap_delta'))
|
||||
self.realized_cap_delta_extended: _24hChangeRatePattern = _24hChangeRatePattern(client, _m(acc, 'realized_cap_delta'))
|
||||
self.realized_cap_rel_to_own_market_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_cap_rel_to_own_market_cap'))
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_loss'))
|
||||
self.realized_loss_rel_to_realized_cap: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'realized_loss_rel_to_realized_cap'))
|
||||
@@ -2182,7 +2182,7 @@ class MvrvNegNetRealizedSentSoprValuePattern:
|
||||
self.net_realized_pnl_sum: _24hPattern[CentsSigned] = _24hPattern(client, _m(acc, 'net_realized_pnl_24h'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_cap_delta: ChangeRatePattern[CentsSigned] = ChangeRatePattern(client, _m(acc, 'realized_cap_delta'))
|
||||
self.realized_cap_delta: ChangeRatePattern3 = ChangeRatePattern3(client, _m(acc, 'realized_cap_delta'))
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_loss'))
|
||||
self.realized_loss_sum: _24hPattern[Cents] = _24hPattern(client, _m(acc, 'realized_loss_24h'))
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
@@ -2235,7 +2235,7 @@ class MvrvNegNetRealizedSoprValuePattern:
|
||||
self.net_realized_pnl_sum: _24hPattern[CentsSigned] = _24hPattern(client, _m(acc, 'net_realized_pnl_24h'))
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.realized_cap_cents: MetricPattern1[Cents] = MetricPattern1(client, _m(acc, 'realized_cap_cents'))
|
||||
self.realized_cap_delta: ChangeRatePattern[CentsSigned] = ChangeRatePattern(client, _m(acc, 'realized_cap_delta'))
|
||||
self.realized_cap_delta: ChangeRatePattern3 = ChangeRatePattern3(client, _m(acc, 'realized_cap_delta'))
|
||||
self.realized_loss: CumulativeHeightPattern[Cents] = CumulativeHeightPattern(client, _m(acc, 'realized_loss'))
|
||||
self.realized_loss_sum: _24hPattern[Cents] = _24hPattern(client, _m(acc, 'realized_loss_24h'))
|
||||
self.realized_price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
@@ -2616,6 +2616,17 @@ class NegNetSupplyUnrealizedPattern:
|
||||
self.unrealized_loss: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_loss'))
|
||||
self.unrealized_profit: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'unrealized_profit'))
|
||||
|
||||
class _24hChangeRatePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self._24h: BpsCentsPercentRatioUsdPattern = BpsCentsPercentRatioUsdPattern(client, acc)
|
||||
self.change_1w: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'change_1w'))
|
||||
self.change_1y: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'change_1y'))
|
||||
self.rate_1w: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'rate_1w'))
|
||||
self.rate_1y: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'rate_1y'))
|
||||
|
||||
class ActivityOutputsRealizedSupplyUnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2638,6 +2649,17 @@ class BaseBtcCentsSatsUsdPattern:
|
||||
self.sats: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'rewards_cumulative'))
|
||||
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'rewards_cumulative_usd'))
|
||||
|
||||
class BpsCentsPercentRatioUsdPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bps: MetricPattern1[BasisPointsSigned32] = MetricPattern1(client, _m(acc, 'rate_24h_bps'))
|
||||
self.cents: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'change_24h_cents'))
|
||||
self.percent: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'rate_24h'))
|
||||
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'rate_24h_ratio'))
|
||||
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'change_24h_usd'))
|
||||
|
||||
class EmaHistogramLineSignalPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2660,7 +2682,7 @@ class _1m1w1y24hHeightPattern(Generic[T]):
|
||||
self._24h: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'average_24h'))
|
||||
self.height: MetricPattern18[T] = MetricPattern18(client, acc)
|
||||
|
||||
class _24hChangeRatePattern(Generic[T]):
|
||||
class _24hChangeRatePattern2(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
@@ -2706,7 +2728,7 @@ class BaseBpsPercentRatioPattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.base: MetricPattern1[CentsSigned] = MetricPattern1(client, _m(acc, 'change_24h'))
|
||||
self.base: MetricPattern1[SatsSigned] = MetricPattern1(client, _m(acc, 'change_24h'))
|
||||
self.bps: MetricPattern1[BasisPointsSigned32] = MetricPattern1(client, _m(acc, 'rate_24h_bps'))
|
||||
self.percent: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'rate_24h'))
|
||||
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'rate_24h_ratio'))
|
||||
@@ -2901,6 +2923,14 @@ class ChangeRatePattern2:
|
||||
self.change: _1m1w1y24hPattern[StoredI64] = _1m1w1y24hPattern(client, _m(acc, 'change'))
|
||||
self.rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, _m(acc, 'rate'))
|
||||
|
||||
class ChangeRatePattern3:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.change_1m: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'change_1m'))
|
||||
self.rate_1m: BpsPercentRatioPattern = BpsPercentRatioPattern(client, _m(acc, 'rate_1m'))
|
||||
|
||||
class HeightSumPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2909,6 +2939,14 @@ class HeightSumPattern:
|
||||
self.height: MetricPattern18[StoredU64] = MetricPattern18(client, acc)
|
||||
self.sum: _1m1w1y24hPattern[StoredU64] = _1m1w1y24hPattern(client, _m(acc, 'sum'))
|
||||
|
||||
class RealizedSupplyPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.realized_cap: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'realized_cap'))
|
||||
self.supply: MetricPattern1[Sats] = MetricPattern1(client, _m(acc, 'supply'))
|
||||
|
||||
class SdSmaPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -4320,8 +4358,8 @@ class MetricsTree_Distribution_UtxoCohorts_All:
|
||||
self.relative: MetricsTree_Distribution_UtxoCohorts_All_Relative = MetricsTree_Distribution_UtxoCohorts_All_Relative(client)
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'dormancy')
|
||||
self.velocity: MetricPattern1[StoredF32] = MetricPattern1(client, 'velocity')
|
||||
self.supply_delta_extended: _24hChangeRatePattern[SatsSigned] = _24hChangeRatePattern(client, 'supply_delta')
|
||||
self.utxo_count_delta_extended: _24hChangeRatePattern[StoredI64] = _24hChangeRatePattern(client, 'utxo_count_delta')
|
||||
self.supply_delta_extended: _24hChangeRatePattern2[SatsSigned] = _24hChangeRatePattern2(client, 'supply_delta')
|
||||
self.utxo_count_delta_extended: _24hChangeRatePattern2[StoredI64] = _24hChangeRatePattern2(client, 'utxo_count_delta')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Sth:
|
||||
"""Metrics tree node."""
|
||||
@@ -4336,8 +4374,8 @@ class MetricsTree_Distribution_UtxoCohorts_Sth:
|
||||
self.relative: NetNuplSupplyUnrealizedPattern2 = NetNuplSupplyUnrealizedPattern2(client, 'sth')
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_dormancy')
|
||||
self.velocity: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_velocity')
|
||||
self.supply_delta_extended: _24hChangeRatePattern[SatsSigned] = _24hChangeRatePattern(client, 'sth_supply_delta')
|
||||
self.utxo_count_delta_extended: _24hChangeRatePattern[StoredI64] = _24hChangeRatePattern(client, 'sth_utxo_count_delta')
|
||||
self.supply_delta_extended: _24hChangeRatePattern2[SatsSigned] = _24hChangeRatePattern2(client, 'sth_supply_delta')
|
||||
self.utxo_count_delta_extended: _24hChangeRatePattern2[StoredI64] = _24hChangeRatePattern2(client, 'sth_utxo_count_delta')
|
||||
self.adjusted_value_created: MetricPattern1[Cents] = MetricPattern1(client, 'sth_adjusted_value_created')
|
||||
self.adjusted_value_destroyed: MetricPattern1[Cents] = MetricPattern1(client, 'sth_adjusted_value_destroyed')
|
||||
self.adjusted_value_created_sum: _1m1w1y24hPattern[Cents] = _1m1w1y24hPattern(client, 'sth_adjusted_value_created')
|
||||
@@ -4357,8 +4395,8 @@ class MetricsTree_Distribution_UtxoCohorts_Lth:
|
||||
self.relative: NetNuplSupplyUnrealizedPattern2 = NetNuplSupplyUnrealizedPattern2(client, 'lth')
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_dormancy')
|
||||
self.velocity: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_velocity')
|
||||
self.supply_delta_extended: _24hChangeRatePattern[SatsSigned] = _24hChangeRatePattern(client, 'lth_supply_delta')
|
||||
self.utxo_count_delta_extended: _24hChangeRatePattern[StoredI64] = _24hChangeRatePattern(client, 'lth_utxo_count_delta')
|
||||
self.supply_delta_extended: _24hChangeRatePattern2[SatsSigned] = _24hChangeRatePattern2(client, 'lth_supply_delta')
|
||||
self.utxo_count_delta_extended: _24hChangeRatePattern2[StoredI64] = _24hChangeRatePattern2(client, 'lth_utxo_count_delta')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_AgeRange:
|
||||
"""Metrics tree node."""
|
||||
@@ -4537,6 +4575,79 @@ class MetricsTree_Distribution_UtxoCohorts_Type:
|
||||
self.unknown: ActivityOutputsRealizedSupplyUnrealizedPattern = ActivityOutputsRealizedSupplyUnrealizedPattern(client, 'unknown_outputs')
|
||||
self.empty: ActivityOutputsRealizedSupplyUnrealizedPattern = ActivityOutputsRealizedSupplyUnrealizedPattern(client, 'empty_outputs')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Profitability_Range:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.profit_over_1000: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_over_1000pct')
|
||||
self.profit_500_to_1000: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_500_to_1000pct')
|
||||
self.profit_300_to_500: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_300_to_500pct')
|
||||
self.profit_200_to_300: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_200_to_300pct')
|
||||
self.profit_100_to_200: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_100_to_200pct')
|
||||
self.profit_90_to_100: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_90_to_100pct')
|
||||
self.profit_80_to_90: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_80_to_90pct')
|
||||
self.profit_70_to_80: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_70_to_80pct')
|
||||
self.profit_60_to_70: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_60_to_70pct')
|
||||
self.profit_50_to_60: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_50_to_60pct')
|
||||
self.profit_40_to_50: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_40_to_50pct')
|
||||
self.profit_30_to_40: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_30_to_40pct')
|
||||
self.profit_20_to_30: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_20_to_30pct')
|
||||
self.profit_10_to_20: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_10_to_20pct')
|
||||
self.profit_0_to_10: RealizedSupplyPattern = RealizedSupplyPattern(client, 'profit_0_to_10pct')
|
||||
self.loss_0_to_10: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_0_to_10pct')
|
||||
self.loss_10_to_20: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_10_to_20pct')
|
||||
self.loss_20_to_30: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_20_to_30pct')
|
||||
self.loss_30_to_40: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_30_to_40pct')
|
||||
self.loss_40_to_50: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_40_to_50pct')
|
||||
self.loss_50_to_60: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_50_to_60pct')
|
||||
self.loss_60_to_70: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_60_to_70pct')
|
||||
self.loss_70_to_80: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_70_to_80pct')
|
||||
self.loss_80_to_90: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_80_to_90pct')
|
||||
self.loss_90_to_100: RealizedSupplyPattern = RealizedSupplyPattern(client, 'loss_90_to_100pct')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_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')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_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')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Profitability:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.range: MetricsTree_Distribution_UtxoCohorts_Profitability_Range = MetricsTree_Distribution_UtxoCohorts_Profitability_Range(client)
|
||||
self.profit: MetricsTree_Distribution_UtxoCohorts_Profitability_Profit = MetricsTree_Distribution_UtxoCohorts_Profitability_Profit(client)
|
||||
self.loss: MetricsTree_Distribution_UtxoCohorts_Profitability_Loss = MetricsTree_Distribution_UtxoCohorts_Profitability_Loss(client)
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts:
|
||||
"""Metrics tree node."""
|
||||
|
||||
@@ -4553,6 +4664,7 @@ class MetricsTree_Distribution_UtxoCohorts:
|
||||
self.amount_range: MetricsTree_Distribution_UtxoCohorts_AmountRange = MetricsTree_Distribution_UtxoCohorts_AmountRange(client)
|
||||
self.lt_amount: MetricsTree_Distribution_UtxoCohorts_LtAmount = MetricsTree_Distribution_UtxoCohorts_LtAmount(client)
|
||||
self.type_: MetricsTree_Distribution_UtxoCohorts_Type = MetricsTree_Distribution_UtxoCohorts_Type(client)
|
||||
self.profitability: MetricsTree_Distribution_UtxoCohorts_Profitability = MetricsTree_Distribution_UtxoCohorts_Profitability(client)
|
||||
|
||||
class MetricsTree_Distribution_AddressCohorts_GeAmount:
|
||||
"""Metrics tree node."""
|
||||
@@ -4692,6 +4804,16 @@ class MetricsTree_Supply_Velocity:
|
||||
self.btc: MetricPattern1[StoredF64] = MetricPattern1(client, 'velocity_btc')
|
||||
self.usd: MetricPattern1[StoredF64] = MetricPattern1(client, 'velocity_usd')
|
||||
|
||||
class MetricsTree_Supply_MarketCapDelta:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.change_24h: CentsUsdPattern = CentsUsdPattern(client, 'market_cap_delta_change_24h')
|
||||
self.change_1w: CentsUsdPattern = CentsUsdPattern(client, 'market_cap_delta_change_1w')
|
||||
self.change_1m: CentsUsdPattern = CentsUsdPattern(client, 'market_cap_delta_change_1m')
|
||||
self.change_1y: CentsUsdPattern = CentsUsdPattern(client, 'market_cap_delta_change_1y')
|
||||
self.rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, 'market_cap_delta_rate')
|
||||
|
||||
class MetricsTree_Supply:
|
||||
"""Metrics tree node."""
|
||||
|
||||
@@ -4700,9 +4822,8 @@ class MetricsTree_Supply:
|
||||
self.burned: MetricsTree_Supply_Burned = MetricsTree_Supply_Burned(client)
|
||||
self.inflation_rate: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'inflation_rate')
|
||||
self.velocity: MetricsTree_Supply_Velocity = MetricsTree_Supply_Velocity(client)
|
||||
self.market_cap: MetricPattern1[Dollars] = MetricPattern1(client, 'market_cap')
|
||||
self.market_cap_growth_rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, 'market_cap_growth_rate')
|
||||
self.realized_cap_growth_rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, 'realized_cap_growth_rate')
|
||||
self.market_cap: CentsUsdPattern = CentsUsdPattern(client, 'market_cap')
|
||||
self.market_cap_delta: MetricsTree_Supply_MarketCapDelta = MetricsTree_Supply_MarketCapDelta(client)
|
||||
self.market_minus_realized_cap_growth_rate: _1m1w1y24hPattern[BasisPointsSigned32] = _1m1w1y24hPattern(client, 'market_minus_realized_cap_growth_rate')
|
||||
|
||||
class MetricsTree:
|
||||
|
||||
Reference in New Issue
Block a user