mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snapshot part 4
This commit is contained in:
@@ -1330,13 +1330,13 @@ impl CapLossMvrvNetPriceProfitSoprPattern {
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct InInvestedMaxMinPercentilesSupplyPattern {
|
||||
pub struct InMaxMinPerSupplyPattern {
|
||||
pub in_loss: PerPattern,
|
||||
pub in_profit: PerPattern,
|
||||
pub invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub max: CentsSatsUsdPattern,
|
||||
pub min: CentsSatsUsdPattern,
|
||||
pub percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub supply_density: BpsPercentRatioPattern3,
|
||||
}
|
||||
|
||||
@@ -4045,6 +4045,8 @@ impl SeriesTree_Mining_Rewards {
|
||||
pub struct SeriesTree_Mining_Rewards_Subsidy {
|
||||
pub base: BtcCentsSatsUsdPattern,
|
||||
pub cumulative: BtcCentsSatsUsdPattern,
|
||||
pub sum: _1m1w1y24hPattern3,
|
||||
pub average: _1m1w1y24hPattern3,
|
||||
pub dominance: _1m1w1y24hBpsPercentRatioPattern,
|
||||
pub sma_1y: CentsUsdPattern2,
|
||||
}
|
||||
@@ -4054,6 +4056,8 @@ impl SeriesTree_Mining_Rewards_Subsidy {
|
||||
Self {
|
||||
base: BtcCentsSatsUsdPattern::new(client.clone(), "subsidy".to_string()),
|
||||
cumulative: BtcCentsSatsUsdPattern::new(client.clone(), "subsidy_cumulative".to_string()),
|
||||
sum: _1m1w1y24hPattern3::new(client.clone(), "subsidy_sum".to_string()),
|
||||
average: _1m1w1y24hPattern3::new(client.clone(), "subsidy_average".to_string()),
|
||||
dominance: _1m1w1y24hBpsPercentRatioPattern::new(client.clone(), "subsidy_dominance".to_string()),
|
||||
sma_1y: CentsUsdPattern2::new(client.clone(), "subsidy_sma_1y".to_string()),
|
||||
}
|
||||
@@ -6644,8 +6648,8 @@ pub struct SeriesTree_Cohorts_Utxo_All_CostBasis {
|
||||
pub in_loss: PerPattern,
|
||||
pub min: CentsSatsUsdPattern,
|
||||
pub max: CentsSatsUsdPattern,
|
||||
pub percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub supply_density: BpsPercentRatioPattern3,
|
||||
}
|
||||
|
||||
@@ -6656,8 +6660,8 @@ impl SeriesTree_Cohorts_Utxo_All_CostBasis {
|
||||
in_loss: PerPattern::new(client.clone(), "cost_basis_in_loss_per".to_string()),
|
||||
min: CentsSatsUsdPattern::new(client.clone(), "cost_basis_min".to_string()),
|
||||
max: CentsSatsUsdPattern::new(client.clone(), "cost_basis_max".to_string()),
|
||||
percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "cost_basis".to_string()),
|
||||
invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "invested_capital".to_string()),
|
||||
per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "cost_basis_per_coin".to_string()),
|
||||
per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "cost_basis_per_dollar".to_string()),
|
||||
supply_density: BpsPercentRatioPattern3::new(client.clone(), "supply_density".to_string()),
|
||||
}
|
||||
}
|
||||
@@ -7114,8 +7118,8 @@ pub struct SeriesTree_Cohorts_Utxo_Sth_CostBasis {
|
||||
pub in_loss: PerPattern,
|
||||
pub min: CentsSatsUsdPattern,
|
||||
pub max: CentsSatsUsdPattern,
|
||||
pub percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub supply_density: BpsPercentRatioPattern3,
|
||||
}
|
||||
|
||||
@@ -7126,8 +7130,8 @@ impl SeriesTree_Cohorts_Utxo_Sth_CostBasis {
|
||||
in_loss: PerPattern::new(client.clone(), "sth_cost_basis_in_loss_per".to_string()),
|
||||
min: CentsSatsUsdPattern::new(client.clone(), "sth_cost_basis_min".to_string()),
|
||||
max: CentsSatsUsdPattern::new(client.clone(), "sth_cost_basis_max".to_string()),
|
||||
percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "sth_cost_basis".to_string()),
|
||||
invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "sth_invested_capital".to_string()),
|
||||
per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "sth_cost_basis_per_coin".to_string()),
|
||||
per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "sth_cost_basis_per_dollar".to_string()),
|
||||
supply_density: BpsPercentRatioPattern3::new(client.clone(), "sth_supply_density".to_string()),
|
||||
}
|
||||
}
|
||||
@@ -7508,8 +7512,8 @@ pub struct SeriesTree_Cohorts_Utxo_Lth_CostBasis {
|
||||
pub in_loss: PerPattern,
|
||||
pub min: CentsSatsUsdPattern,
|
||||
pub max: CentsSatsUsdPattern,
|
||||
pub percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern,
|
||||
pub supply_density: BpsPercentRatioPattern3,
|
||||
}
|
||||
|
||||
@@ -7520,8 +7524,8 @@ impl SeriesTree_Cohorts_Utxo_Lth_CostBasis {
|
||||
in_loss: PerPattern::new(client.clone(), "lth_cost_basis_in_loss_per".to_string()),
|
||||
min: CentsSatsUsdPattern::new(client.clone(), "lth_cost_basis_min".to_string()),
|
||||
max: CentsSatsUsdPattern::new(client.clone(), "lth_cost_basis_max".to_string()),
|
||||
percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "lth_cost_basis".to_string()),
|
||||
invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "lth_invested_capital".to_string()),
|
||||
per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "lth_cost_basis_per_coin".to_string()),
|
||||
per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern::new(client.clone(), "lth_cost_basis_per_dollar".to_string()),
|
||||
supply_density: BpsPercentRatioPattern3::new(client.clone(), "lth_supply_density".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
BlockCountTarget24h, BlockCountTarget1w, BlockCountTarget1m, BlockCountTarget1y,
|
||||
CachedWindowStarts, PerBlockCumulativeWithSums, ConstantVecs, Windows,
|
||||
CachedWindowStarts, PerBlockCumulativeRolling, ConstantVecs, Windows,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ impl Vecs {
|
||||
_1m: ConstantVecs::new::<BlockCountTarget1m>("block_count_target_1m", version, indexes),
|
||||
_1y: ConstantVecs::new::<BlockCountTarget1y>("block_count_target_1y", version, indexes),
|
||||
},
|
||||
total: PerBlockCumulativeWithSums::forced_import(
|
||||
total: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"block_count",
|
||||
version + Version::ONE,
|
||||
|
||||
@@ -2,10 +2,10 @@ use brk_traversable::Traversable;
|
||||
use brk_types::{StoredU32, StoredU64};
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{PerBlockCumulativeWithSums, ConstantVecs, Windows};
|
||||
use crate::internal::{PerBlockCumulativeRolling, ConstantVecs, Windows};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub target: Windows<ConstantVecs<StoredU64>>,
|
||||
pub total: PerBlockCumulativeWithSums<StoredU32, StoredU64, M>,
|
||||
pub total: PerBlockCumulativeRolling<StoredU32, StoredU64, M>,
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
CachedWindowStarts, LazyPerBlock, OneMinusF64, PerBlock, PerBlockCumulativeWithSums,
|
||||
CachedWindowStarts, LazyPerBlock, OneMinusF64, PerBlock, PerBlockCumulativeRolling,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -27,10 +27,10 @@ impl Vecs {
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
coinblocks_created: PerBlockCumulativeWithSums::forced_import(
|
||||
coinblocks_created: PerBlockCumulativeRolling::forced_import(
|
||||
db, "coinblocks_created", version, indexes, cached_starts,
|
||||
)?,
|
||||
coinblocks_stored: PerBlockCumulativeWithSums::forced_import(
|
||||
coinblocks_stored: PerBlockCumulativeRolling::forced_import(
|
||||
db, "coinblocks_stored", version, indexes, cached_starts,
|
||||
)?,
|
||||
liveliness,
|
||||
|
||||
@@ -2,12 +2,12 @@ use brk_traversable::Traversable;
|
||||
use brk_types::StoredF64;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{LazyPerBlock, PerBlock, PerBlockCumulativeWithSums};
|
||||
use crate::internal::{LazyPerBlock, PerBlock, PerBlockCumulativeRolling};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub coinblocks_created: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
pub coinblocks_stored: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
pub coinblocks_created: PerBlockCumulativeRolling<StoredF64, StoredF64, M>,
|
||||
pub coinblocks_stored: PerBlockCumulativeRolling<StoredF64, StoredF64, M>,
|
||||
pub liveliness: PerBlock<StoredF64, M>,
|
||||
pub vaultedness: LazyPerBlock<StoredF64>,
|
||||
pub ratio: PerBlock<StoredF64, M>,
|
||||
|
||||
@@ -5,7 +5,7 @@ use vecdb::Database;
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeWithSums},
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeRolling},
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
@@ -16,28 +16,28 @@ impl Vecs {
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
destroyed: PerBlockCumulativeWithSums::forced_import(
|
||||
destroyed: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"cointime_value_destroyed",
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
created: PerBlockCumulativeWithSums::forced_import(
|
||||
created: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"cointime_value_created",
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
stored: PerBlockCumulativeWithSums::forced_import(
|
||||
stored: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"cointime_value_stored",
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
vocdd: PerBlockCumulativeWithSums::forced_import(
|
||||
vocdd: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"vocdd",
|
||||
version + Version::ONE,
|
||||
|
||||
@@ -2,12 +2,12 @@ use brk_traversable::Traversable;
|
||||
use brk_types::StoredF64;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::PerBlockCumulativeWithSums;
|
||||
use crate::internal::PerBlockCumulativeRolling;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub destroyed: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
pub created: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
pub stored: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
pub vocdd: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
pub destroyed: PerBlockCumulativeRolling<StoredF64, StoredF64, M>,
|
||||
pub created: PerBlockCumulativeRolling<StoredF64, StoredF64, M>,
|
||||
pub stored: PerBlockCumulativeRolling<StoredF64, StoredF64, M>,
|
||||
pub vocdd: PerBlockCumulativeRolling<StoredF64, StoredF64, M>,
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use vecdb::{Database, Exit, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeWithSums},
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeRolling},
|
||||
};
|
||||
|
||||
use super::TotalAddrCountVecs;
|
||||
@@ -14,9 +14,9 @@ use super::TotalAddrCountVecs;
|
||||
/// New address count per block (global + per-type)
|
||||
#[derive(Traversable)]
|
||||
pub struct NewAddrCountVecs<M: StorageMode = Rw> {
|
||||
pub all: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub all: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
#[traversable(flatten)]
|
||||
pub by_addr_type: ByAddrType<PerBlockCumulativeWithSums<StoredU64, StoredU64, M>>,
|
||||
pub by_addr_type: ByAddrType<PerBlockCumulativeRolling<StoredU64, StoredU64, M>>,
|
||||
}
|
||||
|
||||
impl NewAddrCountVecs {
|
||||
@@ -26,7 +26,7 @@ impl NewAddrCountVecs {
|
||||
indexes: &indexes::Vecs,
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
let all = PerBlockCumulativeWithSums::forced_import(
|
||||
let all = PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"new_addr_count",
|
||||
version,
|
||||
@@ -35,7 +35,7 @@ impl NewAddrCountVecs {
|
||||
)?;
|
||||
|
||||
let by_addr_type = ByAddrType::new_with_name(|name| {
|
||||
PerBlockCumulativeWithSums::forced_import(
|
||||
PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
&format!("{name}_new_addr_count"),
|
||||
version,
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::{
|
||||
state::UTXOCohortState,
|
||||
},
|
||||
indexes,
|
||||
internal::{AmountPerBlockCumulativeWithSums, CachedWindowStarts},
|
||||
internal::{AmountPerBlockCumulativeRolling, CachedWindowStarts},
|
||||
prices,
|
||||
};
|
||||
|
||||
@@ -50,7 +50,7 @@ pub struct UTXOCohorts<M: StorageMode = Rw> {
|
||||
#[traversable(rename = "type")]
|
||||
pub type_: SpendableType<UTXOCohortVecs<TypeCohortMetrics<M>>>,
|
||||
pub profitability: ProfitabilityMetrics<M>,
|
||||
pub matured: AgeRange<AmountPerBlockCumulativeWithSums<M>>,
|
||||
pub matured: AgeRange<AmountPerBlockCumulativeRolling<M>>,
|
||||
#[traversable(skip)]
|
||||
pub(super) fenwick: CostBasisFenwick,
|
||||
/// Cached partition_point positions for tick_tock boundary searches.
|
||||
@@ -259,8 +259,8 @@ impl UTXOCohorts<Rw> {
|
||||
let prefix = CohortContext::Utxo.prefix();
|
||||
let matured = AgeRange::try_new(&|_f: Filter,
|
||||
name: &'static str|
|
||||
-> Result<AmountPerBlockCumulativeWithSums> {
|
||||
AmountPerBlockCumulativeWithSums::forced_import(
|
||||
-> Result<AmountPerBlockCumulativeRolling> {
|
||||
AmountPerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
&format!("{prefix}_{name}_matured_supply"),
|
||||
v,
|
||||
@@ -713,10 +713,11 @@ impl UTXOCohorts<Rw> {
|
||||
}
|
||||
vecs.extend(self.profitability.collect_all_vecs_mut());
|
||||
for v in self.matured.iter_mut() {
|
||||
vecs.push(&mut v.base.sats.height);
|
||||
vecs.push(&mut v.base.cents.height);
|
||||
vecs.push(&mut v.cumulative.sats.height);
|
||||
vecs.push(&mut v.cumulative.cents.height);
|
||||
let inner = &mut v.inner;
|
||||
vecs.push(&mut inner.base.sats.height);
|
||||
vecs.push(&mut inner.base.cents.height);
|
||||
vecs.push(&mut inner.cumulative.sats.height);
|
||||
vecs.push(&mut inner.cumulative.cents.height);
|
||||
}
|
||||
vecs.into_par_iter()
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
internal::{AmountPerBlockCumulativeWithSums, PerBlockCumulativeWithSums},
|
||||
internal::{AmountPerBlockCumulativeRolling, PerBlockCumulativeRolling},
|
||||
prices,
|
||||
};
|
||||
|
||||
@@ -19,11 +19,11 @@ pub struct ActivityCore<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub minimal: ActivityMinimal<M>,
|
||||
|
||||
pub coindays_destroyed: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
pub coindays_destroyed: PerBlockCumulativeRolling<StoredF64, StoredF64, M>,
|
||||
#[traversable(wrap = "transfer_volume", rename = "in_profit")]
|
||||
pub transfer_volume_in_profit: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub transfer_volume_in_profit: AmountPerBlockCumulativeRolling<M>,
|
||||
#[traversable(wrap = "transfer_volume", rename = "in_loss")]
|
||||
pub transfer_volume_in_loss: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub transfer_volume_in_loss: AmountPerBlockCumulativeRolling<M>,
|
||||
}
|
||||
|
||||
impl ActivityCore {
|
||||
@@ -69,10 +69,10 @@ impl ActivityCore {
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.minimal.collect_vecs_mut();
|
||||
vecs.push(&mut self.coindays_destroyed.base.height);
|
||||
vecs.push(&mut self.transfer_volume_in_profit.base.sats.height);
|
||||
vecs.push(&mut self.transfer_volume_in_profit.base.cents.height);
|
||||
vecs.push(&mut self.transfer_volume_in_loss.base.sats.height);
|
||||
vecs.push(&mut self.transfer_volume_in_loss.base.cents.height);
|
||||
vecs.push(&mut self.transfer_volume_in_profit.inner.base.sats.height);
|
||||
vecs.push(&mut self.transfer_volume_in_profit.inner.base.cents.height);
|
||||
vecs.push(&mut self.transfer_volume_in_loss.inner.base.sats.height);
|
||||
vecs.push(&mut self.transfer_volume_in_loss.inner.base.cents.height);
|
||||
vecs
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@ use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
internal::AmountPerBlockCumulativeWithSums,
|
||||
internal::AmountPerBlockCumulativeRolling,
|
||||
prices,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct ActivityMinimal<M: StorageMode = Rw> {
|
||||
pub transfer_volume: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub transfer_volume: AmountPerBlockCumulativeRolling<M>,
|
||||
}
|
||||
|
||||
impl ActivityMinimal {
|
||||
@@ -39,9 +39,10 @@ impl ActivityMinimal {
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let inner = &mut self.transfer_volume.inner;
|
||||
vec![
|
||||
&mut self.transfer_volume.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut self.transfer_volume.base.cents.height,
|
||||
&mut inner.base.sats.height as &mut dyn AnyStoredVec,
|
||||
&mut inner.base.cents.height,
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ use vecdb::{BytesVec, BytesVecValue, Database, ImportableVec};
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
AmountPerBlock, AmountPerBlockCumulative, AmountPerBlockCumulativeWithSums,
|
||||
AmountPerBlock, AmountPerBlockCumulative, AmountPerBlockCumulativeRolling,
|
||||
CachedWindowStarts, CentsType, FiatPerBlock, FiatPerBlockCumulativeWithSums, NumericValue,
|
||||
PerBlock, PerBlockCumulativeWithSums, PercentPerBlock, PercentRollingWindows, Price,
|
||||
PerBlock, PerBlockCumulativeRolling, PercentPerBlock, PercentRollingWindows, Price,
|
||||
PriceWithRatioExtendedPerBlock, PriceWithRatioPerBlock, RatioPerBlock,
|
||||
RollingWindow24hPerBlock, RollingWindows, RollingWindowsFrom1w,
|
||||
},
|
||||
@@ -54,7 +54,7 @@ impl<T: NumericValue + JsonSchema> ConfigImport for PerBlock<T> {
|
||||
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
|
||||
}
|
||||
}
|
||||
impl<T, C> ConfigImport for PerBlockCumulativeWithSums<T, C>
|
||||
impl<T, C> ConfigImport for PerBlockCumulativeRolling<T, C>
|
||||
where
|
||||
T: NumericValue + JsonSchema + Into<C>,
|
||||
C: NumericValue + JsonSchema,
|
||||
@@ -79,7 +79,7 @@ impl<T: NumericValue + JsonSchema> ConfigImport for RollingWindow24hPerBlock<T>
|
||||
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
|
||||
}
|
||||
}
|
||||
impl ConfigImport for AmountPerBlockCumulativeWithSums {
|
||||
impl ConfigImport for AmountPerBlockCumulativeRolling {
|
||||
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
|
||||
Self::forced_import(
|
||||
cfg.db,
|
||||
|
||||
@@ -24,8 +24,8 @@ pub struct CostBasis<M: StorageMode = Rw> {
|
||||
pub in_loss: CostBasisSide<M>,
|
||||
pub min: Price<PerBlock<Cents, M>>,
|
||||
pub max: Price<PerBlock<Cents, M>>,
|
||||
pub percentiles: PercentilesVecs<M>,
|
||||
pub invested_capital: PercentilesVecs<M>,
|
||||
pub per_coin: PercentilesVecs<M>,
|
||||
pub per_dollar: PercentilesVecs<M>,
|
||||
pub supply_density: PercentPerBlock<BasisPoints16, M>,
|
||||
}
|
||||
|
||||
@@ -42,15 +42,15 @@ impl CostBasis {
|
||||
},
|
||||
min: cfg.import("cost_basis_min", Version::ZERO)?,
|
||||
max: cfg.import("cost_basis_max", Version::ZERO)?,
|
||||
percentiles: PercentilesVecs::forced_import(
|
||||
per_coin: PercentilesVecs::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis"),
|
||||
&cfg.name("cost_basis_per_coin"),
|
||||
cfg.version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
invested_capital: PercentilesVecs::forced_import(
|
||||
per_dollar: PercentilesVecs::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("invested_capital"),
|
||||
&cfg.name("cost_basis_per_dollar"),
|
||||
cfg.version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
@@ -84,8 +84,8 @@ impl CostBasis {
|
||||
sat_prices: &[Cents; PERCENTILES_LEN],
|
||||
usd_prices: &[Cents; PERCENTILES_LEN],
|
||||
) {
|
||||
self.percentiles.push(sat_prices);
|
||||
self.invested_capital.push(usd_prices);
|
||||
self.per_coin.push(sat_prices);
|
||||
self.per_dollar.push(usd_prices);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -94,9 +94,9 @@ impl CostBasis {
|
||||
}
|
||||
|
||||
pub(crate) fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
|
||||
self.percentiles
|
||||
self.per_coin
|
||||
.validate_computed_version_or_reset(base_version)?;
|
||||
self.invested_capital
|
||||
self.per_dollar
|
||||
.validate_computed_version_or_reset(base_version)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -112,13 +112,13 @@ impl CostBasis {
|
||||
&mut self.supply_density.bps.height,
|
||||
];
|
||||
vecs.extend(
|
||||
self.percentiles
|
||||
self.per_coin
|
||||
.vecs
|
||||
.iter_mut()
|
||||
.map(|v| &mut v.cents.height as &mut dyn AnyStoredVec),
|
||||
);
|
||||
vecs.extend(
|
||||
self.invested_capital
|
||||
self.per_dollar
|
||||
.vecs
|
||||
.iter_mut()
|
||||
.map(|v| &mut v.cents.height as &mut dyn AnyStoredVec),
|
||||
|
||||
@@ -5,14 +5,14 @@ use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
distribution::metrics::ImportConfig,
|
||||
internal::{PerBlockCumulativeWithSums, RatioCents64, RollingWindows},
|
||||
internal::{PerBlockCumulativeRolling, RatioCents64, RollingWindows},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct AdjustedSopr<M: StorageMode = Rw> {
|
||||
pub ratio: RollingWindows<StoredF64, M>,
|
||||
pub transfer_volume: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub value_destroyed: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub transfer_volume: PerBlockCumulativeRolling<Cents, Cents, M>,
|
||||
pub value_destroyed: PerBlockCumulativeRolling<Cents, Cents, M>,
|
||||
}
|
||||
|
||||
impl AdjustedSopr {
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
internal::{
|
||||
FiatPerBlockCumulativeWithSumsAndDeltas, LazyPerBlock, NegCentsUnsignedToDollars,
|
||||
PerBlockCumulativeWithSums, RatioCents64, RollingWindow24hPerBlock, Windows,
|
||||
PerBlockCumulativeRolling, RatioCents64, RollingWindow24hPerBlock, Windows,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -28,7 +28,7 @@ pub struct NegRealizedLoss {
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedSoprCore<M: StorageMode = Rw> {
|
||||
pub value_destroyed: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub value_destroyed: PerBlockCumulativeRolling<Cents, Cents, M>,
|
||||
pub ratio: RollingWindow24hPerBlock<StoredF64, M>,
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ impl RealizedCore {
|
||||
cfg.cached_starts,
|
||||
)?;
|
||||
|
||||
let value_destroyed = PerBlockCumulativeWithSums::forced_import(
|
||||
let value_destroyed = PerBlockCumulativeRolling::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("value_destroyed"),
|
||||
cfg.version + v1,
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
blocks,
|
||||
distribution::state::{CohortState, CostBasisData, RealizedState, WithCapital},
|
||||
internal::{
|
||||
AmountPerBlockCumulativeWithSums, FiatPerBlockCumulativeWithSums, PercentPerBlock,
|
||||
AmountPerBlockCumulativeRolling, FiatPerBlockCumulativeWithSums, PercentPerBlock,
|
||||
PercentRollingWindows, PriceWithRatioExtendedPerBlock, RatioCents64, RatioCentsBp32,
|
||||
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDollarsBp32,
|
||||
RatioPerBlockPercentiles, RatioPerBlockStdDevBands, RatioSma, RollingWindows,
|
||||
@@ -274,7 +274,7 @@ impl RealizedFull {
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
activity_transfer_volume: &AmountPerBlockCumulativeWithSums,
|
||||
activity_transfer_volume: &AmountPerBlockCumulativeRolling,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core.compute_rest_part2(
|
||||
|
||||
@@ -23,7 +23,7 @@ use crate::{
|
||||
state::BlockState,
|
||||
},
|
||||
indexes, inputs,
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeWithSums, db_utils::{finalize_db, open_db}},
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeRolling, db_utils::{finalize_db, open_db}},
|
||||
outputs, prices, transactions,
|
||||
};
|
||||
|
||||
@@ -70,7 +70,7 @@ pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[traversable(wrap = "cohorts", rename = "addr")]
|
||||
pub addr_cohorts: AddrCohorts<M>,
|
||||
#[traversable(wrap = "cointime/activity")]
|
||||
pub coinblocks_destroyed: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
|
||||
pub coinblocks_destroyed: PerBlockCumulativeRolling<StoredF64, StoredF64, M>,
|
||||
pub addrs: AddrMetricsVecs<M>,
|
||||
|
||||
/// In-memory block state for UTXO processing. Persisted via supply_state.
|
||||
@@ -173,7 +173,7 @@ impl Vecs {
|
||||
utxo_cohorts,
|
||||
addr_cohorts,
|
||||
|
||||
coinblocks_destroyed: PerBlockCumulativeWithSums::forced_import(
|
||||
coinblocks_destroyed: PerBlockCumulativeRolling::forced_import(
|
||||
&db,
|
||||
"coinblocks_destroyed",
|
||||
version + Version::TWO,
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, Height, Sats, Version};
|
||||
use brk_types::{Height, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
AmountPerBlock, CachedWindowStarts, LazyRollingAvgsAmountFromHeight,
|
||||
LazyRollingSumsAmountFromHeight, SatsToCents,
|
||||
AmountPerBlockCumulative, CachedWindowStarts, LazyRollingAvgsAmountFromHeight,
|
||||
LazyRollingSumsAmountFromHeight,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct AmountPerBlockCumulativeWithSums<M: StorageMode = Rw> {
|
||||
pub base: AmountPerBlock<M>,
|
||||
pub cumulative: AmountPerBlock<M>,
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct AmountPerBlockCumulativeRolling<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub inner: AmountPerBlockCumulative<M>,
|
||||
pub sum: LazyRollingSumsAmountFromHeight,
|
||||
pub average: LazyRollingAvgsAmountFromHeight,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::TWO;
|
||||
|
||||
impl AmountPerBlockCumulativeWithSums {
|
||||
impl AmountPerBlockCumulativeRolling {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
@@ -32,29 +35,26 @@ impl AmountPerBlockCumulativeWithSums {
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let base = AmountPerBlock::forced_import(db, name, v, indexes)?;
|
||||
let cumulative =
|
||||
AmountPerBlock::forced_import(db, &format!("{name}_cumulative"), v, indexes)?;
|
||||
let inner = AmountPerBlockCumulative::forced_import(db, name, v, indexes)?;
|
||||
let sum = LazyRollingSumsAmountFromHeight::new(
|
||||
&format!("{name}_sum"),
|
||||
v,
|
||||
&cumulative.sats.height,
|
||||
&cumulative.cents.height,
|
||||
&inner.cumulative.sats.height,
|
||||
&inner.cumulative.cents.height,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let average = LazyRollingAvgsAmountFromHeight::new(
|
||||
&format!("{name}_average"),
|
||||
v,
|
||||
&cumulative.sats.height,
|
||||
&cumulative.cents.height,
|
||||
&inner.cumulative.sats.height,
|
||||
&inner.cumulative.cents.height,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
base,
|
||||
cumulative,
|
||||
inner,
|
||||
sum,
|
||||
average,
|
||||
})
|
||||
@@ -77,26 +77,6 @@ impl AmountPerBlockCumulativeWithSums {
|
||||
prices: &prices::Vecs,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.cumulative
|
||||
.sats
|
||||
.height
|
||||
.compute_cumulative(max_from, &self.base.sats.height, exit)?;
|
||||
|
||||
self.base
|
||||
.cents
|
||||
.height
|
||||
.compute_binary::<Sats, Cents, SatsToCents>(
|
||||
max_from,
|
||||
&self.base.sats.height,
|
||||
&prices.spot.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.cumulative
|
||||
.cents
|
||||
.height
|
||||
.compute_cumulative(max_from, &self.base.cents.height, exit)?;
|
||||
|
||||
Ok(())
|
||||
self.inner.compute(prices, max_from, exit)
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,24 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, Height, Sats, Version};
|
||||
use brk_types::{Height, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
AmountPerBlock, CachedWindowStarts, LazyRollingAvgsAmountFromHeight,
|
||||
LazyRollingSumsAmountFromHeight, RollingDistributionAmountPerBlock, SatsToCents,
|
||||
AmountPerBlockCumulativeRolling, CachedWindowStarts, RollingDistributionAmountPerBlock,
|
||||
WindowStarts,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct AmountPerBlockFull<M: StorageMode = Rw> {
|
||||
pub base: AmountPerBlock<M>,
|
||||
pub cumulative: AmountPerBlock<M>,
|
||||
pub sum: LazyRollingSumsAmountFromHeight,
|
||||
pub average: LazyRollingAvgsAmountFromHeight,
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub inner: AmountPerBlockCumulativeRolling<M>,
|
||||
#[traversable(flatten)]
|
||||
pub distribution: RollingDistributionAmountPerBlock<M>,
|
||||
}
|
||||
@@ -35,33 +35,14 @@ impl AmountPerBlockFull {
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
let base = AmountPerBlock::forced_import(db, name, v, indexes)?;
|
||||
let cumulative =
|
||||
AmountPerBlock::forced_import(db, &format!("{name}_cumulative"), v, indexes)?;
|
||||
let sum = LazyRollingSumsAmountFromHeight::new(
|
||||
&format!("{name}_sum"),
|
||||
v,
|
||||
&cumulative.sats.height,
|
||||
&cumulative.cents.height,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let average = LazyRollingAvgsAmountFromHeight::new(
|
||||
&format!("{name}_average"),
|
||||
v,
|
||||
&cumulative.sats.height,
|
||||
&cumulative.cents.height,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let rolling = RollingDistributionAmountPerBlock::forced_import(db, name, v, indexes)?;
|
||||
let inner =
|
||||
AmountPerBlockCumulativeRolling::forced_import(db, name, v, indexes, cached_starts)?;
|
||||
let distribution =
|
||||
RollingDistributionAmountPerBlock::forced_import(db, name, v, indexes)?;
|
||||
|
||||
Ok(Self {
|
||||
base,
|
||||
cumulative,
|
||||
sum,
|
||||
average,
|
||||
distribution: rolling,
|
||||
inner,
|
||||
distribution,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -73,33 +54,15 @@ impl AmountPerBlockFull {
|
||||
exit: &Exit,
|
||||
compute_sats: impl FnOnce(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
|
||||
) -> Result<()> {
|
||||
compute_sats(&mut self.base.sats.height)?;
|
||||
compute_sats(&mut self.inner.base.sats.height)?;
|
||||
|
||||
self.cumulative
|
||||
.sats
|
||||
.height
|
||||
.compute_cumulative(max_from, &self.base.sats.height, exit)?;
|
||||
|
||||
self.base
|
||||
.cents
|
||||
.height
|
||||
.compute_binary::<Sats, Cents, SatsToCents>(
|
||||
max_from,
|
||||
&self.base.sats.height,
|
||||
&prices.spot.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.cumulative
|
||||
.cents
|
||||
.height
|
||||
.compute_cumulative(max_from, &self.base.cents.height, exit)?;
|
||||
self.inner.compute_rest(max_from, prices, exit)?;
|
||||
|
||||
self.distribution.compute(
|
||||
max_from,
|
||||
windows,
|
||||
&self.base.sats.height,
|
||||
&self.base.cents.height,
|
||||
&self.inner.base.sats.height,
|
||||
&self.inner.base.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
mod base;
|
||||
mod cumulative;
|
||||
mod cumulative_sum;
|
||||
mod cumulative_rolling;
|
||||
mod full;
|
||||
mod lazy;
|
||||
mod lazy_derived_resolutions;
|
||||
@@ -11,7 +11,7 @@ mod with_deltas;
|
||||
|
||||
pub use base::*;
|
||||
pub use cumulative::*;
|
||||
pub use cumulative_sum::*;
|
||||
pub use cumulative_rolling::*;
|
||||
pub use full::*;
|
||||
pub use lazy::*;
|
||||
pub use lazy_derived_resolutions::*;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! PerBlockCumulativeWithSums - base PerBlock + cumulative PerBlock + lazy rolling sums.
|
||||
//! PerBlockCumulativeRolling - base PerBlock + cumulative PerBlock + lazy rolling sums.
|
||||
//!
|
||||
//! Rolling sums are derived lazily from the cumulative vec via LazyDeltaVec.
|
||||
//! No rolling sum vecs are stored on disk.
|
||||
@@ -24,7 +24,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct PerBlockCumulativeWithSums<T, C, M: StorageMode = Rw>
|
||||
pub struct PerBlockCumulativeRolling<T, C, M: StorageMode = Rw>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
C: NumericValue + JsonSchema,
|
||||
@@ -35,7 +35,7 @@ where
|
||||
pub average: LazyRollingAvgsFromHeight<C>,
|
||||
}
|
||||
|
||||
impl<T, C> PerBlockCumulativeWithSums<T, C>
|
||||
impl<T, C> PerBlockCumulativeRolling<T, C>
|
||||
where
|
||||
T: NumericValue + JsonSchema + Into<C>,
|
||||
C: NumericValue + JsonSchema,
|
||||
@@ -1,6 +1,6 @@
|
||||
mod aggregated;
|
||||
mod base;
|
||||
mod cumulative_sum;
|
||||
mod cumulative_rolling;
|
||||
mod distribution;
|
||||
mod full;
|
||||
mod lazy_distribution;
|
||||
@@ -12,7 +12,7 @@ mod with_deltas;
|
||||
|
||||
pub use aggregated::*;
|
||||
pub use base::*;
|
||||
pub use cumulative_sum::*;
|
||||
pub use cumulative_rolling::*;
|
||||
pub use distribution::*;
|
||||
pub use full::*;
|
||||
pub use lazy_distribution::*;
|
||||
|
||||
@@ -6,7 +6,7 @@ use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
AmountPerBlockCumulative, AmountPerBlockCumulativeWithSums, AmountPerBlockFull,
|
||||
AmountPerBlockCumulative, AmountPerBlockCumulativeRolling, AmountPerBlockFull,
|
||||
CachedWindowStarts, FiatPerBlock, LazyPercentRollingWindows, OneMinusBp16,
|
||||
PercentPerBlock, PercentRollingWindows, RatioRollingWindows,
|
||||
},
|
||||
@@ -33,10 +33,10 @@ impl Vecs {
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
coinbase: AmountPerBlockCumulativeWithSums::forced_import(
|
||||
coinbase: AmountPerBlockCumulativeRolling::forced_import(
|
||||
db, "coinbase", version, indexes, cached_starts,
|
||||
)?,
|
||||
subsidy: AmountPerBlockCumulativeWithSums::forced_import(
|
||||
subsidy: AmountPerBlockCumulativeRolling::forced_import(
|
||||
db, "subsidy", version, indexes, cached_starts,
|
||||
)?,
|
||||
fees: AmountPerBlockFull::forced_import(db, "fees", version, indexes, cached_starts)?,
|
||||
|
||||
@@ -3,15 +3,15 @@ use brk_types::{BasisPoints16, BasisPoints32, Cents};
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{
|
||||
AmountPerBlockCumulative, AmountPerBlockCumulativeWithSums, AmountPerBlockFull,
|
||||
AmountPerBlockCumulative, AmountPerBlockCumulativeRolling, AmountPerBlockFull,
|
||||
FiatPerBlock, LazyPercentRollingWindows, PercentPerBlock, PercentRollingWindows,
|
||||
RatioRollingWindows,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub coinbase: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub subsidy: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub coinbase: AmountPerBlockCumulativeRolling<M>,
|
||||
pub subsidy: AmountPerBlockCumulativeRolling<M>,
|
||||
pub fees: AmountPerBlockFull<M>,
|
||||
pub unclaimed: AmountPerBlockCumulative<M>,
|
||||
#[traversable(wrap = "fees", rename = "dominance")]
|
||||
|
||||
@@ -7,7 +7,7 @@ use vecdb::{BinaryTransform, Database, Exit, ReadableVec, Rw, StorageMode, Versi
|
||||
use crate::{
|
||||
blocks, indexes,
|
||||
internal::{
|
||||
AmountPerBlockCumulativeWithSums, CachedWindowStarts, MaskSats, PercentRollingWindows,
|
||||
AmountPerBlockCumulativeRolling, CachedWindowStarts, MaskSats, PercentRollingWindows,
|
||||
RatioU64Bp16,
|
||||
},
|
||||
mining, prices,
|
||||
@@ -22,7 +22,7 @@ pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub base: minor::Vecs<M>,
|
||||
|
||||
pub rewards: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub rewards: AmountPerBlockCumulativeRolling<M>,
|
||||
#[traversable(rename = "dominance")]
|
||||
pub dominance_rolling: PercentRollingWindows<BasisPoints16, M>,
|
||||
}
|
||||
@@ -39,7 +39,7 @@ impl Vecs {
|
||||
|
||||
let base = minor::Vecs::forced_import(db, slug, version, indexes, cached_starts)?;
|
||||
|
||||
let rewards = AmountPerBlockCumulativeWithSums::forced_import(
|
||||
let rewards = AmountPerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
&suffix("rewards"),
|
||||
version,
|
||||
|
||||
@@ -8,7 +8,7 @@ use vecdb::{
|
||||
use crate::{
|
||||
blocks, indexes,
|
||||
internal::{
|
||||
CachedWindowStarts, PerBlockCumulativeWithSums, PercentPerBlock, RatioU64Bp16,
|
||||
CachedWindowStarts, PerBlockCumulativeRolling, PercentPerBlock, RatioU64Bp16,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[traversable(skip)]
|
||||
slug: PoolSlug,
|
||||
|
||||
pub blocks_mined: PerBlockCumulativeWithSums<StoredU32, StoredU64, M>,
|
||||
pub blocks_mined: PerBlockCumulativeRolling<StoredU32, StoredU64, M>,
|
||||
pub dominance: PercentPerBlock<BasisPoints16, M>,
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ impl Vecs {
|
||||
) -> Result<Self> {
|
||||
let suffix = |s: &str| format!("{}_{s}", slug);
|
||||
|
||||
let blocks_mined = PerBlockCumulativeWithSums::forced_import(
|
||||
let blocks_mined = PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
&suffix("blocks_mined"),
|
||||
version + Version::ONE,
|
||||
|
||||
@@ -5,7 +5,7 @@ use vecdb::Database;
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeWithSums},
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeRolling},
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
@@ -16,23 +16,23 @@ impl Vecs {
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
let p2a =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2a_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2a_count", version, indexes, cached_starts)?;
|
||||
let p2ms =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2ms_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2ms_count", version, indexes, cached_starts)?;
|
||||
let p2pk33 =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2pk33_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2pk33_count", version, indexes, cached_starts)?;
|
||||
let p2pk65 =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2pk65_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2pk65_count", version, indexes, cached_starts)?;
|
||||
let p2pkh =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2pkh_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2pkh_count", version, indexes, cached_starts)?;
|
||||
let p2sh =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2sh_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2sh_count", version, indexes, cached_starts)?;
|
||||
let p2tr =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2tr_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2tr_count", version, indexes, cached_starts)?;
|
||||
let p2wpkh =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2wpkh_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2wpkh_count", version, indexes, cached_starts)?;
|
||||
let p2wsh =
|
||||
PerBlockCumulativeWithSums::forced_import(db, "p2wsh_count", version, indexes, cached_starts)?;
|
||||
PerBlockCumulativeRolling::forced_import(db, "p2wsh_count", version, indexes, cached_starts)?;
|
||||
Ok(Self {
|
||||
p2a,
|
||||
p2ms,
|
||||
@@ -43,21 +43,21 @@ impl Vecs {
|
||||
p2tr,
|
||||
p2wpkh,
|
||||
p2wsh,
|
||||
op_return: PerBlockCumulativeWithSums::forced_import(
|
||||
op_return: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"op_return_count",
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
empty_output: PerBlockCumulativeWithSums::forced_import(
|
||||
empty_output: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"empty_output_count",
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
unknown_output: PerBlockCumulativeWithSums::forced_import(
|
||||
unknown_output: PerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"unknown_output_count",
|
||||
version,
|
||||
|
||||
@@ -2,20 +2,20 @@ use brk_traversable::Traversable;
|
||||
use brk_types::StoredU64;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::PerBlockCumulativeWithSums;
|
||||
use crate::internal::PerBlockCumulativeRolling;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub p2a: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2ms: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2pk33: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2pk65: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2pkh: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2sh: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2tr: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2wpkh: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2wsh: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub op_return: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub empty_output: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub unknown_output: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub p2a: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub p2ms: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub p2pk33: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub p2pk65: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub p2pkh: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub p2sh: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub p2tr: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub p2wpkh: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub p2wsh: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub op_return: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub empty_output: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub unknown_output: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use brk_types::Version;
|
||||
use vecdb::Database;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{indexes, internal::{AmountPerBlockCumulativeWithSums, CachedWindowStarts}};
|
||||
use crate::{indexes, internal::{AmountPerBlockCumulativeRolling, CachedWindowStarts}};
|
||||
|
||||
impl Vecs {
|
||||
pub(crate) fn forced_import(
|
||||
@@ -13,7 +13,7 @@ impl Vecs {
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
op_return: AmountPerBlockCumulativeWithSums::forced_import(
|
||||
op_return: AmountPerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"op_return_value",
|
||||
version,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use brk_traversable::Traversable;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::AmountPerBlockCumulativeWithSums;
|
||||
use crate::internal::AmountPerBlockCumulativeRolling;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub op_return: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub op_return: AmountPerBlockCumulativeRolling<M>,
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use brk_types::Version;
|
||||
use vecdb::Database;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{indexes, internal::{AmountPerBlockCumulativeWithSums, CachedWindowStarts}};
|
||||
use crate::{indexes, internal::{AmountPerBlockCumulativeRolling, CachedWindowStarts}};
|
||||
|
||||
impl Vecs {
|
||||
pub(crate) fn forced_import(
|
||||
@@ -13,7 +13,7 @@ impl Vecs {
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
total: AmountPerBlockCumulativeWithSums::forced_import(
|
||||
total: AmountPerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"unspendable_supply",
|
||||
version,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use brk_traversable::Traversable;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::AmountPerBlockCumulativeWithSums;
|
||||
use crate::internal::AmountPerBlockCumulativeRolling;
|
||||
|
||||
#[derive(Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub total: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub total: AmountPerBlockCumulativeRolling<M>,
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use vecdb::Database;
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeWithSums},
|
||||
internal::{CachedWindowStarts, PerBlockCumulativeRolling},
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
@@ -16,9 +16,9 @@ impl Vecs {
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
v1: PerBlockCumulativeWithSums::forced_import(db, "tx_v1", version, indexes, cached_starts)?,
|
||||
v2: PerBlockCumulativeWithSums::forced_import(db, "tx_v2", version, indexes, cached_starts)?,
|
||||
v3: PerBlockCumulativeWithSums::forced_import(db, "tx_v3", version, indexes, cached_starts)?,
|
||||
v1: PerBlockCumulativeRolling::forced_import(db, "tx_v1", version, indexes, cached_starts)?,
|
||||
v2: PerBlockCumulativeRolling::forced_import(db, "tx_v2", version, indexes, cached_starts)?,
|
||||
v3: PerBlockCumulativeRolling::forced_import(db, "tx_v3", version, indexes, cached_starts)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ use brk_traversable::Traversable;
|
||||
use brk_types::StoredU64;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::PerBlockCumulativeWithSums;
|
||||
use crate::internal::PerBlockCumulativeRolling;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub v1: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub v2: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub v3: PerBlockCumulativeWithSums<StoredU64, StoredU64, M>,
|
||||
pub v1: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub v2: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
pub v3: PerBlockCumulativeRolling<StoredU64, StoredU64, M>,
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ use vecdb::Database;
|
||||
use super::Vecs;
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{AmountPerBlockCumulativeWithSums, CachedWindowStarts, PerBlock, Windows},
|
||||
internal::{AmountPerBlockCumulativeRolling, CachedWindowStarts, PerBlock, Windows},
|
||||
};
|
||||
|
||||
impl Vecs {
|
||||
@@ -17,7 +17,7 @@ impl Vecs {
|
||||
) -> Result<Self> {
|
||||
let v = version + Version::TWO;
|
||||
Ok(Self {
|
||||
transfer_volume: AmountPerBlockCumulativeWithSums::forced_import(
|
||||
transfer_volume: AmountPerBlockCumulativeRolling::forced_import(
|
||||
db,
|
||||
"transfer_volume_bis",
|
||||
version,
|
||||
|
||||
@@ -2,11 +2,11 @@ use brk_traversable::Traversable;
|
||||
use brk_types::StoredF32;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{AmountPerBlockCumulativeWithSums, PerBlock, Windows};
|
||||
use crate::internal::{AmountPerBlockCumulativeRolling, PerBlock, Windows};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
pub transfer_volume: AmountPerBlockCumulativeWithSums<M>,
|
||||
pub transfer_volume: AmountPerBlockCumulativeRolling<M>,
|
||||
pub tx_per_sec: Windows<PerBlock<StoredF32, M>>,
|
||||
pub outputs_per_sec: Windows<PerBlock<StoredF32, M>>,
|
||||
pub inputs_per_sec: Windows<PerBlock<StoredF32, M>>,
|
||||
|
||||
@@ -2067,13 +2067,13 @@ function createCapLossMvrvNetPriceProfitSoprPattern(client, acc) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} InInvestedMaxMinPercentilesSupplyPattern
|
||||
* @typedef {Object} InMaxMinPerSupplyPattern
|
||||
* @property {PerPattern} inLoss
|
||||
* @property {PerPattern} inProfit
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} investedCapital
|
||||
* @property {CentsSatsUsdPattern} max
|
||||
* @property {CentsSatsUsdPattern} min
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} percentiles
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} perCoin
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} perDollar
|
||||
* @property {BpsPercentRatioPattern3} supplyDensity
|
||||
*/
|
||||
|
||||
@@ -4413,6 +4413,8 @@ function createUnspentPattern(client, acc) {
|
||||
* @typedef {Object} SeriesTree_Mining_Rewards_Subsidy
|
||||
* @property {BtcCentsSatsUsdPattern} base
|
||||
* @property {BtcCentsSatsUsdPattern} cumulative
|
||||
* @property {_1m1w1y24hPattern3} sum
|
||||
* @property {_1m1w1y24hPattern3} average
|
||||
* @property {_1m1w1y24hBpsPercentRatioPattern} dominance
|
||||
* @property {CentsUsdPattern2} sma1y
|
||||
*/
|
||||
@@ -5556,8 +5558,8 @@ function createUnspentPattern(client, acc) {
|
||||
* @property {PerPattern} inLoss
|
||||
* @property {CentsSatsUsdPattern} min
|
||||
* @property {CentsSatsUsdPattern} max
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} percentiles
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} investedCapital
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} perCoin
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} perDollar
|
||||
* @property {BpsPercentRatioPattern3} supplyDensity
|
||||
*/
|
||||
|
||||
@@ -5764,8 +5766,8 @@ function createUnspentPattern(client, acc) {
|
||||
* @property {PerPattern} inLoss
|
||||
* @property {CentsSatsUsdPattern} min
|
||||
* @property {CentsSatsUsdPattern} max
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} percentiles
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} investedCapital
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} perCoin
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} perDollar
|
||||
* @property {BpsPercentRatioPattern3} supplyDensity
|
||||
*/
|
||||
|
||||
@@ -5940,8 +5942,8 @@ function createUnspentPattern(client, acc) {
|
||||
* @property {PerPattern} inLoss
|
||||
* @property {CentsSatsUsdPattern} min
|
||||
* @property {CentsSatsUsdPattern} max
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} percentiles
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} investedCapital
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} perCoin
|
||||
* @property {Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern} perDollar
|
||||
* @property {BpsPercentRatioPattern3} supplyDensity
|
||||
*/
|
||||
|
||||
@@ -7786,6 +7788,8 @@ class BrkClient extends BrkClientBase {
|
||||
subsidy: {
|
||||
base: createBtcCentsSatsUsdPattern(this, 'subsidy'),
|
||||
cumulative: createBtcCentsSatsUsdPattern(this, 'subsidy_cumulative'),
|
||||
sum: create_1m1w1y24hPattern3(this, 'subsidy_sum'),
|
||||
average: create_1m1w1y24hPattern3(this, 'subsidy_average'),
|
||||
dominance: create_1m1w1y24hBpsPercentRatioPattern(this, 'subsidy_dominance'),
|
||||
sma1y: createCentsUsdPattern2(this, 'subsidy_sma_1y'),
|
||||
},
|
||||
@@ -8611,8 +8615,8 @@ class BrkClient extends BrkClientBase {
|
||||
inLoss: createPerPattern(this, 'cost_basis_in_loss_per'),
|
||||
min: createCentsSatsUsdPattern(this, 'cost_basis_min'),
|
||||
max: createCentsSatsUsdPattern(this, 'cost_basis_max'),
|
||||
percentiles: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'cost_basis'),
|
||||
investedCapital: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'invested_capital'),
|
||||
perCoin: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'cost_basis_per_coin'),
|
||||
perDollar: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'cost_basis_per_dollar'),
|
||||
supplyDensity: createBpsPercentRatioPattern3(this, 'supply_density'),
|
||||
},
|
||||
unrealized: {
|
||||
@@ -8766,8 +8770,8 @@ class BrkClient extends BrkClientBase {
|
||||
inLoss: createPerPattern(this, 'sth_cost_basis_in_loss_per'),
|
||||
min: createCentsSatsUsdPattern(this, 'sth_cost_basis_min'),
|
||||
max: createCentsSatsUsdPattern(this, 'sth_cost_basis_max'),
|
||||
percentiles: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'sth_cost_basis'),
|
||||
investedCapital: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'sth_invested_capital'),
|
||||
perCoin: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'sth_cost_basis_per_coin'),
|
||||
perDollar: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'sth_cost_basis_per_dollar'),
|
||||
supplyDensity: createBpsPercentRatioPattern3(this, 'sth_supply_density'),
|
||||
},
|
||||
unrealized: {
|
||||
@@ -8901,8 +8905,8 @@ class BrkClient extends BrkClientBase {
|
||||
inLoss: createPerPattern(this, 'lth_cost_basis_in_loss_per'),
|
||||
min: createCentsSatsUsdPattern(this, 'lth_cost_basis_min'),
|
||||
max: createCentsSatsUsdPattern(this, 'lth_cost_basis_max'),
|
||||
percentiles: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'lth_cost_basis'),
|
||||
investedCapital: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'lth_invested_capital'),
|
||||
perCoin: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'lth_cost_basis_per_coin'),
|
||||
perDollar: createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(this, 'lth_cost_basis_per_dollar'),
|
||||
supplyDensity: createBpsPercentRatioPattern3(this, 'lth_supply_density'),
|
||||
},
|
||||
unrealized: {
|
||||
|
||||
@@ -2339,7 +2339,7 @@ class CapLossMvrvNetPriceProfitSoprPattern:
|
||||
self.profit: BaseCumulativeSumPattern = BaseCumulativeSumPattern(client, _m(acc, 'realized_profit'))
|
||||
self.sopr: RatioValuePattern = RatioValuePattern(client, acc)
|
||||
|
||||
class InInvestedMaxMinPercentilesSupplyPattern:
|
||||
class InMaxMinPerSupplyPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
pass
|
||||
|
||||
@@ -3639,6 +3639,8 @@ class SeriesTree_Mining_Rewards_Subsidy:
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.base: BtcCentsSatsUsdPattern = BtcCentsSatsUsdPattern(client, 'subsidy')
|
||||
self.cumulative: BtcCentsSatsUsdPattern = BtcCentsSatsUsdPattern(client, 'subsidy_cumulative')
|
||||
self.sum: _1m1w1y24hPattern3 = _1m1w1y24hPattern3(client, 'subsidy_sum')
|
||||
self.average: _1m1w1y24hPattern3 = _1m1w1y24hPattern3(client, 'subsidy_average')
|
||||
self.dominance: _1m1w1y24hBpsPercentRatioPattern = _1m1w1y24hBpsPercentRatioPattern(client, 'subsidy_dominance')
|
||||
self.sma_1y: CentsUsdPattern2 = CentsUsdPattern2(client, 'subsidy_sma_1y')
|
||||
|
||||
@@ -4866,8 +4868,8 @@ class SeriesTree_Cohorts_Utxo_All_CostBasis:
|
||||
self.in_loss: PerPattern = PerPattern(client, 'cost_basis_in_loss_per')
|
||||
self.min: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'cost_basis_min')
|
||||
self.max: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'cost_basis_max')
|
||||
self.percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'cost_basis')
|
||||
self.invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'invested_capital')
|
||||
self.per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'cost_basis_per_coin')
|
||||
self.per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'cost_basis_per_dollar')
|
||||
self.supply_density: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'supply_density')
|
||||
|
||||
class SeriesTree_Cohorts_Utxo_All_Unrealized_Profit:
|
||||
@@ -5092,8 +5094,8 @@ class SeriesTree_Cohorts_Utxo_Sth_CostBasis:
|
||||
self.in_loss: PerPattern = PerPattern(client, 'sth_cost_basis_in_loss_per')
|
||||
self.min: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_cost_basis_min')
|
||||
self.max: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_cost_basis_max')
|
||||
self.percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'sth_cost_basis')
|
||||
self.invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'sth_invested_capital')
|
||||
self.per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'sth_cost_basis_per_coin')
|
||||
self.per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'sth_cost_basis_per_dollar')
|
||||
self.supply_density: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'sth_supply_density')
|
||||
|
||||
class SeriesTree_Cohorts_Utxo_Sth_Unrealized_Sentiment:
|
||||
@@ -5282,8 +5284,8 @@ class SeriesTree_Cohorts_Utxo_Lth_CostBasis:
|
||||
self.in_loss: PerPattern = PerPattern(client, 'lth_cost_basis_in_loss_per')
|
||||
self.min: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_cost_basis_min')
|
||||
self.max: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_cost_basis_max')
|
||||
self.percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'lth_cost_basis')
|
||||
self.invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'lth_invested_capital')
|
||||
self.per_coin: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'lth_cost_basis_per_coin')
|
||||
self.per_dollar: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'lth_cost_basis_per_dollar')
|
||||
self.supply_density: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'lth_supply_density')
|
||||
|
||||
class SeriesTree_Cohorts_Utxo_Lth_Unrealized_Sentiment:
|
||||
|
||||
@@ -5,9 +5,9 @@ import {
|
||||
dots,
|
||||
line,
|
||||
price,
|
||||
sumsArray,
|
||||
multiSeriesTree,
|
||||
percentRatioDots,
|
||||
sumsAndAveragesCumulative,
|
||||
} from "./series.js";
|
||||
import { satsBtcUsd, priceRatioPercentilesTree } from "./shared.js";
|
||||
|
||||
@@ -277,50 +277,27 @@ export function createCointimeSection() {
|
||||
{
|
||||
name: "Coinblocks",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
tree: multiSeriesTree({
|
||||
entries: coinblocks.map(({ pattern, name, color }) => ({
|
||||
name,
|
||||
color,
|
||||
base: pattern.base,
|
||||
average: pattern.average,
|
||||
rolling: pattern.sum,
|
||||
cumulative: pattern.cumulative,
|
||||
})),
|
||||
title: "Coinblocks",
|
||||
unit: Unit.coinblocks,
|
||||
}),
|
||||
},
|
||||
...multiSeriesTree({
|
||||
entries: coinblocks.map(({ pattern, name, color }) => ({
|
||||
name,
|
||||
color,
|
||||
average: pattern.average,
|
||||
sum: pattern.sum,
|
||||
cumulative: pattern.cumulative,
|
||||
})),
|
||||
title: "Coinblocks",
|
||||
unit: Unit.coinblocks,
|
||||
}),
|
||||
...coinblocks.map(({ pattern, name, title, color }) => ({
|
||||
name,
|
||||
tree: [
|
||||
{
|
||||
name: "Per Block",
|
||||
title,
|
||||
bottom: [
|
||||
line({
|
||||
series: pattern.base,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coinblocks,
|
||||
}),
|
||||
],
|
||||
},
|
||||
...sumsArray({ windows: pattern.sum, title, unit: Unit.coinblocks }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: [
|
||||
line({
|
||||
series: pattern.cumulative,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coinblocks,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
tree: sumsAndAveragesCumulative({
|
||||
sum: pattern.sum,
|
||||
average: pattern.average,
|
||||
cumulative: pattern.cumulative,
|
||||
title,
|
||||
unit: Unit.coinblocks,
|
||||
color,
|
||||
}),
|
||||
})),
|
||||
],
|
||||
},
|
||||
@@ -328,95 +305,47 @@ export function createCointimeSection() {
|
||||
{
|
||||
name: "Value",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
tree: multiSeriesTree({
|
||||
entries: [
|
||||
...cointimeValues.map(({ pattern, name, color }) => ({
|
||||
name,
|
||||
color,
|
||||
base: pattern.base,
|
||||
average: pattern.average,
|
||||
rolling: pattern.sum,
|
||||
cumulative: pattern.cumulative,
|
||||
})),
|
||||
{
|
||||
name: vocdd.name,
|
||||
color: vocdd.color,
|
||||
base: vocdd.pattern.base,
|
||||
average: vocdd.pattern.average,
|
||||
rolling: vocdd.pattern.sum,
|
||||
cumulative: vocdd.pattern.cumulative,
|
||||
},
|
||||
],
|
||||
title: "Cointime Value",
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
},
|
||||
...cointimeValues.map(({ pattern, name, title, color }) => ({
|
||||
name,
|
||||
tree: [
|
||||
...multiSeriesTree({
|
||||
entries: [
|
||||
...cointimeValues.map(({ pattern, name, color }) => ({
|
||||
name,
|
||||
color,
|
||||
average: pattern.average,
|
||||
sum: pattern.sum,
|
||||
cumulative: pattern.cumulative,
|
||||
})),
|
||||
{
|
||||
name: "Per Block",
|
||||
title,
|
||||
bottom: [
|
||||
line({ series: pattern.base, name, color, unit: Unit.usd }),
|
||||
],
|
||||
},
|
||||
...sumsArray({ windows: pattern.sum, title, unit: Unit.usd }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: [
|
||||
line({
|
||||
series: pattern.cumulative,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
name: vocdd.name,
|
||||
color: vocdd.color,
|
||||
average: vocdd.pattern.average,
|
||||
sum: vocdd.pattern.sum,
|
||||
cumulative: vocdd.pattern.cumulative,
|
||||
},
|
||||
],
|
||||
title: "Cointime Value",
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
...cointimeValues.map(({ pattern, name, title, color }) => ({
|
||||
name,
|
||||
tree: sumsAndAveragesCumulative({
|
||||
sum: pattern.sum,
|
||||
average: pattern.average,
|
||||
cumulative: pattern.cumulative,
|
||||
title,
|
||||
unit: Unit.usd,
|
||||
color,
|
||||
}),
|
||||
})),
|
||||
{
|
||||
name: vocdd.name,
|
||||
tree: [
|
||||
{
|
||||
name: "Per Block",
|
||||
title: vocdd.title,
|
||||
bottom: [
|
||||
line({
|
||||
series: vocdd.pattern.base,
|
||||
name: vocdd.name,
|
||||
color: vocdd.color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
series: reserveRisk.vocddMedian1y,
|
||||
name: "365d Median",
|
||||
color: colors.time._1y,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
...sumsArray({
|
||||
windows: vocdd.pattern.sum,
|
||||
title: vocdd.title,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${vocdd.title} (Total)`,
|
||||
bottom: [
|
||||
line({
|
||||
series: vocdd.pattern.cumulative,
|
||||
name: vocdd.name,
|
||||
color: vocdd.color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
tree: sumsAndAveragesCumulative({
|
||||
sum: vocdd.pattern.sum,
|
||||
average: vocdd.pattern.average,
|
||||
cumulative: vocdd.pattern.cumulative,
|
||||
title: vocdd.title,
|
||||
unit: Unit.usd,
|
||||
color: vocdd.color,
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -9,7 +9,15 @@
|
||||
*/
|
||||
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { line, baseline, dotsBaseline, percentRatio, chartsFromCount, averagesTree, ROLLING_WINDOWS } from "../series.js";
|
||||
import {
|
||||
line,
|
||||
baseline,
|
||||
dotsBaseline,
|
||||
percentRatio,
|
||||
chartsFromCount,
|
||||
averagesArray,
|
||||
ROLLING_WINDOWS,
|
||||
} from "../series.js";
|
||||
import {
|
||||
satsBtcUsdFullTree,
|
||||
mapCohortsWithAll,
|
||||
@@ -33,7 +41,6 @@ function volumeAndCoinsTree(activity, color, title) {
|
||||
name: "Volume",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: activity.transferVolume,
|
||||
name: "Volume",
|
||||
title: title("Sent Volume"),
|
||||
color,
|
||||
}),
|
||||
@@ -62,7 +69,6 @@ function sentProfitLossTree(sent, title) {
|
||||
name: "Sent In Profit",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: sent.inProfit,
|
||||
name: "In Profit",
|
||||
title: title("Sent Volume In Profit"),
|
||||
color: colors.profit,
|
||||
}),
|
||||
@@ -71,7 +77,6 @@ function sentProfitLossTree(sent, title) {
|
||||
name: "Sent In Loss",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: sent.inLoss,
|
||||
name: "In Loss",
|
||||
title: title("Sent Volume In Loss"),
|
||||
color: colors.loss,
|
||||
}),
|
||||
@@ -90,7 +95,14 @@ function fullVolumeTree(activity, color, title) {
|
||||
return [
|
||||
...volumeAndCoinsTree(activity, color, title),
|
||||
...sentProfitLossTree(activity.transferVolume, title),
|
||||
averagesTree({ windows: activity.dormancy, title: title("Dormancy"), unit: Unit.days, name: "Dormancy" }),
|
||||
{
|
||||
name: "Dormancy",
|
||||
tree: averagesArray({
|
||||
windows: activity.dormancy,
|
||||
title: title("Dormancy"),
|
||||
unit: Unit.days,
|
||||
}),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -110,13 +122,26 @@ function singleRollingSoprTree(ratio, title, prefix = "") {
|
||||
name: "Compare",
|
||||
title: title(`${prefix}SOPR`),
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
baseline({ series: ratio[w.key], name: w.name, color: w.color, unit: Unit.ratio, base: 1 }),
|
||||
baseline({
|
||||
series: ratio[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: title(`${prefix}SOPR (${w.title})`),
|
||||
bottom: [baseline({ series: ratio[w.key], name: "SOPR", unit: Unit.ratio, base: 1 })],
|
||||
bottom: [
|
||||
baseline({
|
||||
series: ratio[w.key],
|
||||
name: "SOPR",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
],
|
||||
})),
|
||||
];
|
||||
}
|
||||
@@ -136,7 +161,11 @@ function singleSellSideRiskTree(sellSideRisk, title) {
|
||||
name: "Compare",
|
||||
title: title("Sell Side Risk"),
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
percentRatio({ pattern: sellSideRisk[w.key], name: w.name, color: w.color }),
|
||||
percentRatio({
|
||||
pattern: sellSideRisk[w.key],
|
||||
name: w.name,
|
||||
color: w.color,
|
||||
}),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
@@ -171,11 +200,18 @@ export function createActivitySectionWithAdjusted({ cohort, title }) {
|
||||
...singleRollingSoprTree(sopr.ratio, title),
|
||||
{
|
||||
name: "Adjusted",
|
||||
tree: singleRollingSoprTree(sopr.adjusted.ratio, title, "Adjusted "),
|
||||
tree: singleRollingSoprTree(
|
||||
sopr.adjusted.ratio,
|
||||
title,
|
||||
"Adjusted ",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{ name: "Sell Side Risk", tree: singleSellSideRiskTree(r.sellSideRiskRatio, title) },
|
||||
{
|
||||
name: "Sell Side Risk",
|
||||
tree: singleSellSideRiskTree(r.sellSideRiskRatio, title),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -198,7 +234,10 @@ export function createActivitySection({ cohort, title }) {
|
||||
name: "SOPR",
|
||||
tree: singleRollingSoprTree(sopr.ratio, title),
|
||||
},
|
||||
{ name: "Sell Side Risk", tree: singleSellSideRiskTree(r.sellSideRiskRatio, title) },
|
||||
{
|
||||
name: "Sell Side Risk",
|
||||
tree: singleSellSideRiskTree(r.sellSideRiskRatio, title),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -220,13 +259,19 @@ export function createActivitySectionWithActivity({ cohort, title }) {
|
||||
{
|
||||
name: "SOPR",
|
||||
title: title("SOPR (24h)"),
|
||||
bottom: [dotsBaseline({ series: sopr.ratio._24h, name: "SOPR", unit: Unit.ratio, base: 1 })],
|
||||
bottom: [
|
||||
dotsBaseline({
|
||||
series: sopr.ratio._24h,
|
||||
name: "SOPR",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Minimal activity section: volume only
|
||||
* @param {{ cohort: CohortBasicWithMarketCap | CohortBasicWithoutMarketCap | CohortWithoutRelative | CohortAddr | AddrCohortObject, title: (name: string) => string }} args
|
||||
@@ -237,7 +282,6 @@ export function createActivitySectionMinimal({ cohort, title }) {
|
||||
name: "Activity",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: cohort.tree.activity.transferVolume,
|
||||
name: "Volume",
|
||||
title: title("Volume"),
|
||||
}),
|
||||
};
|
||||
@@ -255,7 +299,12 @@ export function createGroupedActivitySectionMinimal({ list, all, title }) {
|
||||
name: w.name,
|
||||
title: title(`Volume (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.activity.transferVolume.sum[w.key].sats, name, color, unit: Unit.sats }),
|
||||
line({
|
||||
series: tree.activity.transferVolume.sum[w.key].sats,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
};
|
||||
@@ -280,7 +329,13 @@ function groupedSoprCharts(list, all, getRatio, title, prefix = "") {
|
||||
name: w.name,
|
||||
title: title(`${prefix}SOPR (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, (c) =>
|
||||
baseline({ series: getRatio(c)[w.key], name: c.name, color: c.color, unit: Unit.ratio, base: 1 }),
|
||||
baseline({
|
||||
series: getRatio(c)[w.key],
|
||||
name: c.name,
|
||||
color: c.color,
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
),
|
||||
}));
|
||||
}
|
||||
@@ -300,7 +355,6 @@ function groupedSoprCharts(list, all, getRatio, title, prefix = "") {
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Grouped Activity Sections
|
||||
// ============================================================================
|
||||
@@ -317,16 +371,32 @@ export function createGroupedActivitySectionWithAdjusted({ list, all, title }) {
|
||||
name: "Volume",
|
||||
title: title("Sent Volume"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.transferVolume.sum._24h.sats, name, color, unit: Unit.sats }),
|
||||
line({
|
||||
series: tree.activity.transferVolume.sum._24h.sats,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "SOPR",
|
||||
tree: [
|
||||
...groupedSoprCharts(list, all, (c) => c.tree.realized.sopr.ratio, title),
|
||||
...groupedSoprCharts(
|
||||
list,
|
||||
all,
|
||||
(c) => c.tree.realized.sopr.ratio,
|
||||
title,
|
||||
),
|
||||
{
|
||||
name: "Adjusted",
|
||||
tree: groupedSoprCharts(list, all, (c) => c.tree.realized.sopr.adjusted.ratio, title, "Adjusted "),
|
||||
tree: groupedSoprCharts(
|
||||
list,
|
||||
all,
|
||||
(c) => c.tree.realized.sopr.adjusted.ratio,
|
||||
title,
|
||||
"Adjusted ",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -336,7 +406,12 @@ export function createGroupedActivitySectionWithAdjusted({ list, all, title }) {
|
||||
name: w.name,
|
||||
title: title(`Sell Side Risk (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.realized.sellSideRiskRatio[w.key].ratio, name, color, unit: Unit.ratio }),
|
||||
line({
|
||||
series: tree.realized.sellSideRiskRatio[w.key].ratio,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
},
|
||||
@@ -344,7 +419,12 @@ export function createGroupedActivitySectionWithAdjusted({ list, all, title }) {
|
||||
name: "Coindays Destroyed",
|
||||
title: title("Coindays Destroyed"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }),
|
||||
line({
|
||||
series: tree.activity.coindaysDestroyed.sum._24h,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coindays,
|
||||
}),
|
||||
]),
|
||||
},
|
||||
],
|
||||
@@ -364,13 +444,23 @@ export function createGroupedActivitySection({ list, all, title }) {
|
||||
name: "Volume",
|
||||
title: title("Sent Volume"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.transferVolume.sum._24h.sats, name, color, unit: Unit.sats }),
|
||||
line({
|
||||
series: tree.activity.transferVolume.sum._24h.sats,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "SOPR",
|
||||
tree: [
|
||||
...groupedSoprCharts(list, all, (c) => c.tree.realized.sopr.ratio, title),
|
||||
...groupedSoprCharts(
|
||||
list,
|
||||
all,
|
||||
(c) => c.tree.realized.sopr.ratio,
|
||||
title,
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -379,7 +469,12 @@ export function createGroupedActivitySection({ list, all, title }) {
|
||||
name: w.name,
|
||||
title: title(`Sell Side Risk (${w.title})`),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
line({ series: tree.realized.sellSideRiskRatio[w.key].ratio, name, color, unit: Unit.ratio }),
|
||||
line({
|
||||
series: tree.realized.sellSideRiskRatio[w.key].ratio,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
},
|
||||
@@ -387,7 +482,12 @@ export function createGroupedActivitySection({ list, all, title }) {
|
||||
name: "Coindays Destroyed",
|
||||
title: title("Coindays Destroyed"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }),
|
||||
line({
|
||||
series: tree.activity.coindaysDestroyed.sum._24h,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coindays,
|
||||
}),
|
||||
]),
|
||||
},
|
||||
],
|
||||
@@ -407,24 +507,39 @@ export function createGroupedActivitySectionWithActivity({ list, all, title }) {
|
||||
name: "Volume",
|
||||
title: title("Sent Volume"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.transferVolume.sum._24h.sats, name, color, unit: Unit.sats }),
|
||||
line({
|
||||
series: tree.activity.transferVolume.sum._24h.sats,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "SOPR",
|
||||
title: title("SOPR (24h)"),
|
||||
bottom: mapCohortsWithAll(list, all, ({ name, color, tree }) =>
|
||||
baseline({ series: tree.realized.sopr.ratio._24h, name, color, unit: Unit.ratio, base: 1 }),
|
||||
baseline({
|
||||
series: tree.realized.sopr.ratio._24h,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Coindays Destroyed",
|
||||
title: title("Coindays Destroyed"),
|
||||
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) => [
|
||||
line({ series: tree.activity.coindaysDestroyed.sum._24h, name, color, unit: Unit.coindays }),
|
||||
line({
|
||||
series: tree.activity.coindaysDestroyed.sum._24h,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.coindays,
|
||||
}),
|
||||
]),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ export function createCostBasisSectionWithPercentiles({ cohort, title }) {
|
||||
tree: singleWeightFolder({
|
||||
avgPrice: tree.realized.price, avgName: "Average",
|
||||
inProfit: cb.inProfit.perCoin, inLoss: cb.inLoss.perCoin,
|
||||
percentiles: cb.percentiles, color, weightLabel: "BTC-weighted", title,
|
||||
percentiles: cb.perCoin, color, weightLabel: "BTC-weighted", title,
|
||||
min: cb.min, max: cb.max,
|
||||
}),
|
||||
},
|
||||
@@ -102,7 +102,7 @@ export function createCostBasisSectionWithPercentiles({ cohort, title }) {
|
||||
tree: singleWeightFolder({
|
||||
avgPrice: tree.realized.investor.price, avgName: "Average",
|
||||
inProfit: cb.inProfit.perDollar, inLoss: cb.inLoss.perDollar,
|
||||
percentiles: cb.investedCapital, color, weightLabel: "USD-weighted", title,
|
||||
percentiles: cb.perDollar, color, weightLabel: "USD-weighted", title,
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -215,7 +215,7 @@ export function createGroupedCostBasisSectionWithPercentiles({ list, all, title
|
||||
getAvgPrice: (c) => c.tree.realized.price,
|
||||
getInProfit: (c) => c.tree.costBasis.inProfit.perCoin,
|
||||
getInLoss: (c) => c.tree.costBasis.inLoss.perCoin,
|
||||
getPercentiles: (c) => c.tree.costBasis.percentiles,
|
||||
getPercentiles: (c) => c.tree.costBasis.perCoin,
|
||||
avgTitle: "Average", weightLabel: "BTC-weighted",
|
||||
}),
|
||||
},
|
||||
@@ -226,7 +226,7 @@ export function createGroupedCostBasisSectionWithPercentiles({ list, all, title
|
||||
getAvgPrice: (c) => c.tree.realized.investor.price,
|
||||
getInProfit: (c) => c.tree.costBasis.inProfit.perDollar,
|
||||
getInLoss: (c) => c.tree.costBasis.inLoss.perDollar,
|
||||
getPercentiles: (c) => c.tree.costBasis.investedCapital,
|
||||
getPercentiles: (c) => c.tree.costBasis.perDollar,
|
||||
avgTitle: "Average", weightLabel: "USD-weighted",
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -10,8 +10,19 @@
|
||||
* - activity.js: SOPR, Volume, Lifespan
|
||||
*/
|
||||
|
||||
import { formatCohortTitle, satsBtcUsd, satsBtcUsdFullTree } from "../shared.js";
|
||||
import { ROLLING_WINDOWS, line, baseline, percentRatio, sumsTree, rollingPercentRatioTree } from "../series.js";
|
||||
import {
|
||||
formatCohortTitle,
|
||||
satsBtcUsd,
|
||||
satsBtcUsdFullTree,
|
||||
} from "../shared.js";
|
||||
import {
|
||||
ROLLING_WINDOWS,
|
||||
line,
|
||||
baseline,
|
||||
percentRatio,
|
||||
sumsTree,
|
||||
rollingPercentRatioTree,
|
||||
} from "../series.js";
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { colors } from "../../utils/colors.js";
|
||||
|
||||
@@ -210,7 +221,6 @@ export function createCohortFolderAgeRangeWithMatured(cohort) {
|
||||
name: "Matured",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: cohort.matured,
|
||||
name: cohort.name,
|
||||
title: title("Matured Supply"),
|
||||
}),
|
||||
});
|
||||
@@ -452,13 +462,22 @@ export function createGroupedCohortFolderAgeRangeWithMatured({
|
||||
list,
|
||||
all,
|
||||
}) {
|
||||
const folder = createGroupedCohortFolderAgeRange({ name, title: groupTitle, list, all });
|
||||
const folder = createGroupedCohortFolderAgeRange({
|
||||
name,
|
||||
title: groupTitle,
|
||||
list,
|
||||
all,
|
||||
});
|
||||
const title = formatCohortTitle(groupTitle);
|
||||
folder.tree.push({
|
||||
name: "Matured",
|
||||
title: title("Matured Supply"),
|
||||
bottom: list.flatMap((cohort) =>
|
||||
satsBtcUsd({ pattern: cohort.matured.base, name: cohort.name, color: cohort.color }),
|
||||
satsBtcUsd({
|
||||
pattern: cohort.matured.base,
|
||||
name: cohort.name,
|
||||
color: cohort.color,
|
||||
}),
|
||||
),
|
||||
});
|
||||
return folder;
|
||||
@@ -607,14 +626,32 @@ function singleBucketFolder({ name, color, pattern }) {
|
||||
title: `${name}: Supply`,
|
||||
bottom: [
|
||||
...satsBtcUsd({ pattern: pattern.supply.all, name: "Total" }),
|
||||
...satsBtcUsd({ pattern: pattern.supply.sth, name: "STH", color: colors.term.short }),
|
||||
...satsBtcUsd({
|
||||
pattern: pattern.supply.sth,
|
||||
name: "STH",
|
||||
color: colors.term.short,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Change",
|
||||
tree: [
|
||||
{ ...sumsTree({ windows: pattern.supply.all.delta.absolute, title: `${name}: Supply Change`, unit: Unit.sats, series: baseline }), name: "Absolute" },
|
||||
{ ...rollingPercentRatioTree({ windows: pattern.supply.all.delta.rate, title: `${name}: Supply Rate` }), name: "Rate" },
|
||||
{
|
||||
...sumsTree({
|
||||
windows: pattern.supply.all.delta.absolute,
|
||||
title: `${name}: Supply Change`,
|
||||
unit: Unit.sats,
|
||||
series: baseline,
|
||||
}),
|
||||
name: "Absolute",
|
||||
},
|
||||
{
|
||||
...rollingPercentRatioTree({
|
||||
windows: pattern.supply.all.delta.rate,
|
||||
title: `${name}: Supply Rate`,
|
||||
}),
|
||||
name: "Rate",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -623,14 +660,25 @@ function singleBucketFolder({ name, color, pattern }) {
|
||||
name: "Realized Cap",
|
||||
title: `${name}: Realized Cap`,
|
||||
bottom: [
|
||||
line({ series: pattern.realizedCap.all, name: "Total", unit: Unit.usd }),
|
||||
line({ series: pattern.realizedCap.sth, name: "STH", color: colors.term.short, unit: Unit.usd }),
|
||||
line({
|
||||
series: pattern.realizedCap.all,
|
||||
name: "Total",
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
series: pattern.realizedCap.sth,
|
||||
name: "STH",
|
||||
color: colors.term.short,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "NUPL",
|
||||
title: `${name}: NUPL`,
|
||||
bottom: [line({ series: pattern.nupl.ratio, name, color, unit: Unit.ratio })],
|
||||
bottom: [
|
||||
line({ series: pattern.nupl.ratio, name, color, unit: Unit.ratio }),
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -671,7 +719,12 @@ function groupedBucketCharts(list, titlePrefix) {
|
||||
title: `${titlePrefix}: Supply Change`,
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
list.map(({ name, color, pattern }) =>
|
||||
baseline({ series: pattern.supply.all.delta.absolute[w.key], name: `${name} ${w.name}`, color, unit: Unit.sats }),
|
||||
baseline({
|
||||
series: pattern.supply.all.delta.absolute[w.key],
|
||||
name: `${name} ${w.name}`,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
@@ -679,7 +732,12 @@ function groupedBucketCharts(list, titlePrefix) {
|
||||
name: w.name,
|
||||
title: `${titlePrefix}: Supply Change (${w.title})`,
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
baseline({ series: pattern.supply.all.delta.absolute[w.key], name, color, unit: Unit.sats }),
|
||||
baseline({
|
||||
series: pattern.supply.all.delta.absolute[w.key],
|
||||
name,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
],
|
||||
@@ -692,7 +750,11 @@ function groupedBucketCharts(list, titlePrefix) {
|
||||
title: `${titlePrefix}: Supply Rate`,
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
list.flatMap(({ name, color, pattern }) =>
|
||||
percentRatio({ pattern: pattern.supply.all.delta.rate[w.key], name: `${name} ${w.name}`, color }),
|
||||
percentRatio({
|
||||
pattern: pattern.supply.all.delta.rate[w.key],
|
||||
name: `${name} ${w.name}`,
|
||||
color,
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
@@ -700,7 +762,11 @@ function groupedBucketCharts(list, titlePrefix) {
|
||||
name: w.name,
|
||||
title: `${titlePrefix}: Supply Rate (${w.title})`,
|
||||
bottom: list.flatMap(({ name, color, pattern }) =>
|
||||
percentRatio({ pattern: pattern.supply.all.delta.rate[w.key], name, color }),
|
||||
percentRatio({
|
||||
pattern: pattern.supply.all.delta.rate[w.key],
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
],
|
||||
@@ -716,14 +782,24 @@ function groupedBucketCharts(list, titlePrefix) {
|
||||
name: "All",
|
||||
title: `${titlePrefix}: Realized Cap`,
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
line({ series: pattern.realizedCap.all, name, color, unit: Unit.usd }),
|
||||
line({
|
||||
series: pattern.realizedCap.all,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "STH",
|
||||
title: `${titlePrefix}: STH Realized Cap`,
|
||||
bottom: list.map(({ name, color, pattern }) =>
|
||||
line({ series: pattern.realizedCap.sth, name, color, unit: Unit.usd }),
|
||||
line({
|
||||
series: pattern.realizedCap.sth,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
@@ -749,7 +825,10 @@ export function createUtxoProfitabilitySection({ range, profit, loss }) {
|
||||
{
|
||||
name: "Range",
|
||||
tree: [
|
||||
{ name: "Compare", tree: groupedBucketCharts(range, "Profitability Range") },
|
||||
{
|
||||
name: "Compare",
|
||||
tree: groupedBucketCharts(range, "Profitability Range"),
|
||||
},
|
||||
...range.map(singleBucketFolder),
|
||||
],
|
||||
},
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { ROLLING_WINDOWS, line, dotted, baseline, dots, dotsBaseline, percentRatio, percentRatioBaseline } from "../series.js";
|
||||
import { ROLLING_WINDOWS, line, dotted, baseline, percentRatio, percentRatioBaseline } from "../series.js";
|
||||
import { colors } from "../../utils/colors.js";
|
||||
import { priceLine } from "../constants.js";
|
||||
import {
|
||||
@@ -236,7 +236,7 @@ function nuplSeries(nupl) {
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Flat metric folder: Compare + windows + Cumulative + Per Block + optional % of Realized Cap
|
||||
* Flat metric folder: Compare + windows + Cumulative + optional % of Realized Cap
|
||||
* @param {Object} args
|
||||
* @param {{ sum: Record<string, { usd: AnySeriesPattern }>, cumulative: { usd: AnySeriesPattern }, base: { usd: AnySeriesPattern } }} args.pattern
|
||||
* @param {string} args.metricTitle
|
||||
@@ -264,11 +264,6 @@ function realizedMetricFolder({ pattern, metricTitle, color, title, toRcap }) {
|
||||
title: title(`Realized ${metricTitle} (Total)`),
|
||||
bottom: [line({ series: pattern.cumulative.usd, name: metricTitle, color, unit: Unit.usd })],
|
||||
},
|
||||
{
|
||||
name: "Per Block",
|
||||
title: title(`Realized ${metricTitle} per Block`),
|
||||
bottom: [dots({ series: pattern.base.usd, name: metricTitle, color, unit: Unit.usd })],
|
||||
},
|
||||
...(toRcap ? [{
|
||||
name: "% of Realized Cap",
|
||||
title: title(`Realized ${metricTitle} (% of Realized Cap)`),
|
||||
@@ -278,7 +273,7 @@ function realizedMetricFolder({ pattern, metricTitle, color, title, toRcap }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Net P&L folder: Compare + windows + Cumulative + Per Block + optional % of Rcap + Change/
|
||||
* Net P&L folder: Compare + windows + Cumulative + optional % of Rcap + Change/
|
||||
* @param {Object} args
|
||||
* @param {NetPnlFullPattern | NetPnlBasicPattern} args.netPnl
|
||||
* @param {(name: string) => string} args.title
|
||||
@@ -307,11 +302,6 @@ function realizedNetFolder({ netPnl, title, toRcap, extraChange = [] }) {
|
||||
title: title("Net Realized P&L (Total)"),
|
||||
bottom: [baseline({ series: netPnl.cumulative.usd, name: "Net", unit: Unit.usd })],
|
||||
},
|
||||
{
|
||||
name: "Per Block",
|
||||
title: title("Net Realized P&L per Block"),
|
||||
bottom: [dotsBaseline({ series: netPnl.base.usd, name: "Net", unit: Unit.usd })],
|
||||
},
|
||||
...(toRcap ? [{
|
||||
name: "% of Realized Cap",
|
||||
title: title("Net Realized P&L (% of Realized Cap)"),
|
||||
@@ -464,11 +454,6 @@ function realizedSubfolderFull(r, title) {
|
||||
title: title("Peak Regret (Total)"),
|
||||
bottom: [line({ series: r.peakRegret.cumulative.usd, name: "Peak Regret", unit: Unit.usd })],
|
||||
},
|
||||
{
|
||||
name: "Per Block",
|
||||
title: title("Peak Regret per Block"),
|
||||
bottom: [dots({ series: r.peakRegret.base.usd, name: "Peak Regret", unit: Unit.usd })],
|
||||
},
|
||||
{
|
||||
name: "% of Realized Cap",
|
||||
title: title("Peak Regret (% of Realized Cap)"),
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
satsBtcUsdFrom,
|
||||
satsBtcUsdFullTree,
|
||||
revenueBtcSatsUsd,
|
||||
revenueRollingBtcSatsUsd,
|
||||
} from "./shared.js";
|
||||
import { brk } from "../client.js";
|
||||
|
||||
@@ -122,7 +123,6 @@ export function createMiningSection() {
|
||||
name: "Rewards",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: pool.rewards,
|
||||
name: "Rewards",
|
||||
title: `Rewards: ${name}`,
|
||||
}),
|
||||
},
|
||||
@@ -283,77 +283,44 @@ export function createMiningSection() {
|
||||
{
|
||||
name: "Revenue",
|
||||
tree: [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `Revenue ${w.title} Averages`,
|
||||
bottom: revenueRollingBtcSatsUsd({
|
||||
coinbase: mining.rewards.coinbase.average[w.key],
|
||||
subsidy: mining.rewards.subsidy.average[w.key],
|
||||
fee: mining.rewards.fees.average[w.key],
|
||||
}),
|
||||
})),
|
||||
{
|
||||
name: "Compare",
|
||||
tree: [
|
||||
{
|
||||
name: "Per Block",
|
||||
title: "Revenue Comparison",
|
||||
bottom: revenueBtcSatsUsd({
|
||||
coinbase: mining.rewards.coinbase,
|
||||
subsidy: mining.rewards.subsidy,
|
||||
fee: mining.rewards.fees,
|
||||
key: "base",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Revenue Comparison (Total)",
|
||||
bottom: revenueBtcSatsUsd({
|
||||
coinbase: mining.rewards.coinbase,
|
||||
subsidy: mining.rewards.subsidy,
|
||||
fee: mining.rewards.fees,
|
||||
key: "cumulative",
|
||||
}),
|
||||
},
|
||||
],
|
||||
name: "Cumulative",
|
||||
title: "Revenue Comparison (Total)",
|
||||
bottom: revenueBtcSatsUsd({
|
||||
coinbase: mining.rewards.coinbase,
|
||||
subsidy: mining.rewards.subsidy,
|
||||
fee: mining.rewards.fees,
|
||||
key: "cumulative",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Coinbase",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: mining.rewards.coinbase,
|
||||
name: "Coinbase",
|
||||
title: "Coinbase Rewards",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Subsidy",
|
||||
tree: [
|
||||
{
|
||||
name: "Per Block",
|
||||
title: "Block Subsidy",
|
||||
bottom: [
|
||||
...satsBtcUsdFrom({
|
||||
source: mining.rewards.subsidy,
|
||||
key: "base",
|
||||
name: "base",
|
||||
}),
|
||||
line({
|
||||
series: mining.rewards.subsidy.sma1y.usd,
|
||||
name: "1y SMA",
|
||||
color: colors.time._1y,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: "Block Subsidy (Total)",
|
||||
bottom: satsBtcUsdFrom({
|
||||
source: mining.rewards.subsidy,
|
||||
key: "cumulative",
|
||||
name: "all-time",
|
||||
}),
|
||||
},
|
||||
],
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: mining.rewards.subsidy,
|
||||
title: "Block Subsidy",
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Fees",
|
||||
tree: [
|
||||
...satsBtcUsdFullTree({
|
||||
pattern: mining.rewards.fees,
|
||||
name: "Fees",
|
||||
title: "Transaction Fee Revenue",
|
||||
}),
|
||||
{
|
||||
|
||||
@@ -4,16 +4,14 @@ import { colors } from "../utils/colors.js";
|
||||
import { brk } from "../client.js";
|
||||
import { Unit } from "../utils/units.js";
|
||||
import { entries } from "../utils/array.js";
|
||||
import { priceLine } from "./constants.js";
|
||||
import {
|
||||
line,
|
||||
dots,
|
||||
fromSupplyPattern,
|
||||
chartsFromFullPerBlock,
|
||||
chartsFromCount,
|
||||
chartsFromCountEntries,
|
||||
chartsFromAggregatedPerBlock,
|
||||
averagesTree,
|
||||
averagesArray,
|
||||
simpleDeltaTree,
|
||||
ROLLING_WINDOWS,
|
||||
chartsFromBlockAnd6b,
|
||||
@@ -169,14 +167,14 @@ export function createNetworkSection() {
|
||||
),
|
||||
})),
|
||||
},
|
||||
...activityTypes.map((t) =>
|
||||
averagesTree({
|
||||
...activityTypes.map((t) => ({
|
||||
name: t.name,
|
||||
tree: averagesArray({
|
||||
windows: addrs.activity[key][t.key],
|
||||
title: `${titlePrefix}${t.name} Addresses`,
|
||||
unit: Unit.count,
|
||||
name: t.name,
|
||||
}),
|
||||
),
|
||||
})),
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -308,7 +306,6 @@ export function createNetworkSection() {
|
||||
name: "Volume",
|
||||
tree: satsBtcUsdFullTree({
|
||||
pattern: transactions.volume.transferVolume,
|
||||
name: "base",
|
||||
title: "Transaction Volume",
|
||||
}),
|
||||
},
|
||||
@@ -429,31 +426,11 @@ export function createNetworkSection() {
|
||||
},
|
||||
{
|
||||
name: "Interval",
|
||||
tree: [
|
||||
{
|
||||
name: "Per Block",
|
||||
title: "Block Interval",
|
||||
bottom: [
|
||||
dots({
|
||||
series: blocks.interval.base,
|
||||
name: "base",
|
||||
unit: Unit.secs,
|
||||
}),
|
||||
line({
|
||||
series: blocks.interval._24h,
|
||||
name: "24h avg",
|
||||
color: colors.stat.avg,
|
||||
unit: Unit.secs,
|
||||
}),
|
||||
priceLine({ unit: Unit.secs, name: "Target", number: 600 }),
|
||||
],
|
||||
},
|
||||
averagesTree({
|
||||
windows: blocks.interval,
|
||||
title: "Block Interval",
|
||||
unit: Unit.secs,
|
||||
}),
|
||||
],
|
||||
tree: averagesArray({
|
||||
windows: blocks.interval,
|
||||
title: "Block Interval",
|
||||
unit: Unit.secs,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Size",
|
||||
@@ -509,17 +486,15 @@ export function createNetworkSection() {
|
||||
{
|
||||
name: "Created",
|
||||
color: colors.entity.output,
|
||||
base: outputs.count.total.sum,
|
||||
average: outputs.count.total.rolling.average,
|
||||
rolling: outputs.count.total.rolling.sum,
|
||||
sum: outputs.count.total.rolling.sum,
|
||||
cumulative: outputs.count.total.cumulative,
|
||||
},
|
||||
{
|
||||
name: "Spent",
|
||||
color: colors.entity.input,
|
||||
base: inputs.count.sum,
|
||||
average: inputs.count.rolling.average,
|
||||
rolling: inputs.count.rolling.sum,
|
||||
sum: inputs.count.rolling.sum,
|
||||
cumulative: inputs.count.cumulative,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -517,6 +517,61 @@ export function sumsArray({ windows, title, unit }) {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flat array of per-window charts with both sum (active) and average (off by default)
|
||||
* @param {Object} args
|
||||
* @param {{ _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }} args.sum
|
||||
* @param {{ _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }} args.average
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialChartOption[]}
|
||||
*/
|
||||
export function sumsAndAveragesArray({ sum, average, title, unit }) {
|
||||
return ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} ${w.title}`,
|
||||
bottom: [
|
||||
line({ series: sum[w.key], name: "Sum", color: w.color, unit }),
|
||||
line({
|
||||
series: average[w.key],
|
||||
name: "Avg",
|
||||
color: w.color,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Windowed sum+avg charts + cumulative
|
||||
* @param {Object} args
|
||||
* @param {{ _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }} args.sum
|
||||
* @param {{ _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }} args.average
|
||||
* @param {AnySeriesPattern} args.cumulative
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @param {Color} [args.color]
|
||||
* @returns {PartialChartOption[]}
|
||||
*/
|
||||
export function sumsAndAveragesCumulative({ sum, average, cumulative, title, unit, color }) {
|
||||
return [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `${title} Averages`,
|
||||
bottom: ROLLING_WINDOWS.map((w) =>
|
||||
line({ series: average[w.key], name: w.name, color: w.color, unit }),
|
||||
),
|
||||
},
|
||||
...sumsAndAveragesArray({ sum, average, title, unit }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: [{ series: cumulative, title: "all-time", color, unit }],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolling sums tree (Compare + individual windows in a folder)
|
||||
* @param {Object} args
|
||||
@@ -538,22 +593,21 @@ export function sumsTree({ windows, title, unit, series }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolling averages tree
|
||||
* Flat array of per-window average charts
|
||||
* @param {Object} args
|
||||
* @param {{ _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }} args.windows
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @param {string} [args.name]
|
||||
* @returns {PartialOptionsGroup}
|
||||
* @returns {PartialChartOption[]}
|
||||
*/
|
||||
export function averagesTree({ windows, title, unit, name = "Averages" }) {
|
||||
return rollingWindowsTree({
|
||||
windows,
|
||||
title,
|
||||
windowTitle: (w) => `${title} ${w.title} Average`,
|
||||
unit,
|
||||
name,
|
||||
});
|
||||
export function averagesArray({ windows, title, unit }) {
|
||||
return ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} ${w.title} Average`,
|
||||
bottom: [
|
||||
line({ series: windows[w.key], name: w.name, color: w.color, unit }),
|
||||
],
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -854,7 +908,7 @@ export function simpleDeltaTree({ delta, title, unit }) {
|
||||
// These split patterns into separate Sum/Distribution/Cumulative charts
|
||||
|
||||
/**
|
||||
* Split flat per-block pattern into charts (Sum/Rolling/Distribution/Cumulative)
|
||||
* Split flat per-block pattern into charts (Averages/Sums/Distribution/Cumulative)
|
||||
* Pattern has: .height, .cumulative, .sum (windowed), .average/.pct10/... (windowed, flat)
|
||||
* @param {Object} args
|
||||
* @param {FullPerBlockPattern} args.pattern
|
||||
@@ -873,14 +927,14 @@ export function chartsFromFull({
|
||||
? `${title} ${distributionSuffix}`
|
||||
: title;
|
||||
return [
|
||||
averagesTree({ windows: pattern.average, title, unit }),
|
||||
sumsTree({ windows: pattern.sum, title, unit }),
|
||||
...sumsAndAveragesCumulative({
|
||||
sum: pattern.sum,
|
||||
average: pattern.average,
|
||||
cumulative: pattern.cumulative,
|
||||
title,
|
||||
unit,
|
||||
}),
|
||||
distributionWindowsTree({ pattern, title: distTitle, unit }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: [{ series: pattern.cumulative, title: "all-time", unit }],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -914,18 +968,18 @@ export function chartsFromAggregated({
|
||||
? `${title} ${distributionSuffix}`
|
||||
: title;
|
||||
return [
|
||||
averagesTree({ windows: pattern.rolling.average, title, unit }),
|
||||
sumsTree({ windows: pattern.rolling.sum, title, unit }),
|
||||
...sumsAndAveragesCumulative({
|
||||
sum: pattern.rolling.sum,
|
||||
average: pattern.rolling.average,
|
||||
cumulative: pattern.cumulative,
|
||||
title,
|
||||
unit,
|
||||
}),
|
||||
distributionWindowsTree({
|
||||
pattern: pattern.rolling,
|
||||
title: distTitle,
|
||||
unit,
|
||||
}),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: [{ series: pattern.cumulative, title: "all-time", unit }],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -964,27 +1018,7 @@ export function chartsFromBlockAnd6b({ pattern, title, unit }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums + Cumulative charts (no Per Block)
|
||||
* @param {Object} args
|
||||
* @param {{ sum: { _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }, cumulative: AnySeriesPattern }} args.pattern
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @param {Color} [args.color]
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function chartsFromSumsCumulative({ pattern, title, unit, color }) {
|
||||
return [
|
||||
...sumsArray({ windows: pattern.sum, title, unit }),
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: [{ series: pattern.cumulative, title: "all-time", color, unit }],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Per Block + Sums + Cumulative charts
|
||||
* Averages + Sums + Cumulative charts
|
||||
* @param {Object} args
|
||||
* @param {CountPattern<any>} args.pattern
|
||||
* @param {string} args.title
|
||||
@@ -993,14 +1027,26 @@ export function chartsFromSumsCumulative({ pattern, title, unit, color }) {
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function chartsFromCount({ pattern, title, unit, color }) {
|
||||
return [
|
||||
averagesTree({ windows: pattern.average, title, unit }),
|
||||
...chartsFromSumsCumulative({ pattern, title, unit, color }),
|
||||
];
|
||||
return sumsAndAveragesCumulative({
|
||||
sum: pattern.sum,
|
||||
average: pattern.average,
|
||||
cumulative: pattern.cumulative,
|
||||
title,
|
||||
unit,
|
||||
color,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Split multiple named entries (each with base/sum/cumulative) into Per Block/Sums/Cumulative charts
|
||||
* Windowed sums + cumulative for multiple named entries (e.g. transaction versions)
|
||||
* @param {Object} args
|
||||
* @param {Array<[string, CountPattern<any>]>} args.entries
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
/**
|
||||
* Windowed sums + cumulative for multiple named entries (e.g. transaction versions)
|
||||
* @param {Object} args
|
||||
* @param {Array<[string, CountPattern<any>]>} args.entries
|
||||
* @param {string} args.title
|
||||
@@ -1008,49 +1054,45 @@ export function chartsFromCount({ pattern, title, unit, color }) {
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function chartsFromCountEntries({ entries, title, unit }) {
|
||||
return multiSeriesTree({
|
||||
entries: entries.map(([name, data], i, arr) => ({
|
||||
name,
|
||||
color: colors.at(i, arr.length),
|
||||
base: data.base,
|
||||
average: data.average,
|
||||
rolling: data.sum,
|
||||
cumulative: data.cumulative,
|
||||
const items = entries.map(([name, data], i, arr) => ({
|
||||
name,
|
||||
color: colors.at(i, arr.length),
|
||||
sum: data.sum,
|
||||
cumulative: data.cumulative,
|
||||
}));
|
||||
return [
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} ${w.title} Sum`,
|
||||
bottom: items.map((e) =>
|
||||
line({ series: e.sum[w.key], name: e.name, color: e.color, unit }),
|
||||
),
|
||||
})),
|
||||
title,
|
||||
unit,
|
||||
});
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: items.map((e) =>
|
||||
line({ series: e.cumulative, name: e.name, color: e.color, unit }),
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Per Block + Sums + Cumulative tree for multiple named series shown side-by-side
|
||||
* Windowed averages + sums + cumulative for multiple named series (e.g. UTXO flow)
|
||||
* @param {Object} args
|
||||
* @param {Array<{ name: string, color: Color, base: AnySeriesPattern, average: { _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }, rolling: { _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }, cumulative: AnySeriesPattern }>} args.entries
|
||||
* @param {Array<{ name: string, color: Color, average: { _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }, sum: { _24h: AnySeriesPattern, _1w: AnySeriesPattern, _1m: AnySeriesPattern, _1y: AnySeriesPattern }, cumulative: AnySeriesPattern }>} args.entries
|
||||
* @param {string} args.title
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function multiSeriesTree({ entries, title, unit }) {
|
||||
return [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `${title} Average`,
|
||||
bottom: ROLLING_WINDOWS.flatMap((w) =>
|
||||
entries.map((e) =>
|
||||
line({
|
||||
series: e.average[w.key],
|
||||
name: `${e.name} ${w.name}`,
|
||||
color: e.color,
|
||||
unit,
|
||||
}),
|
||||
),
|
||||
),
|
||||
},
|
||||
...ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} ${w.title} Sum`,
|
||||
title: `${title} ${w.title} Averages`,
|
||||
bottom: entries.map((e) =>
|
||||
line({ series: e.rolling[w.key], name: e.name, color: e.color, unit }),
|
||||
line({ series: e.average[w.key], name: e.name, color: e.color, unit }),
|
||||
),
|
||||
})),
|
||||
{
|
||||
|
||||
@@ -219,7 +219,6 @@ export function satsBtcUsdRolling({ pattern, name, color, defaultActive }) {
|
||||
* Build a full Sum / Rolling / Cumulative tree from a FullValuePattern
|
||||
* @param {Object} args
|
||||
* @param {FullValuePattern} args.pattern
|
||||
* @param {string} args.name
|
||||
* @param {string} args.title
|
||||
* @param {Color} [args.color]
|
||||
* @returns {PartialOptionsTree}
|
||||
|
||||
Reference in New Issue
Block a user