mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snapshot
This commit is contained in:
@@ -1085,40 +1085,6 @@ pub struct CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern {
|
||||
pub sopr: AdjustedRatioValuePattern,
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern {
|
||||
pub average: SeriesPattern1<StoredU64>,
|
||||
pub cumulative: SeriesPattern1<StoredU64>,
|
||||
pub max: SeriesPattern1<StoredU64>,
|
||||
pub median: SeriesPattern1<StoredU64>,
|
||||
pub min: SeriesPattern1<StoredU64>,
|
||||
pub pct10: SeriesPattern1<StoredU64>,
|
||||
pub pct25: SeriesPattern1<StoredU64>,
|
||||
pub pct75: SeriesPattern1<StoredU64>,
|
||||
pub pct90: SeriesPattern1<StoredU64>,
|
||||
pub rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern,
|
||||
pub sum: SeriesPattern1<StoredU64>,
|
||||
}
|
||||
|
||||
impl AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern {
|
||||
/// Create a new pattern node with accumulated series name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
average: SeriesPattern1::new(client.clone(), _m(&acc, "average")),
|
||||
cumulative: SeriesPattern1::new(client.clone(), _m(&acc, "cumulative")),
|
||||
max: SeriesPattern1::new(client.clone(), _m(&acc, "max")),
|
||||
median: SeriesPattern1::new(client.clone(), _m(&acc, "median")),
|
||||
min: SeriesPattern1::new(client.clone(), _m(&acc, "min")),
|
||||
pct10: SeriesPattern1::new(client.clone(), _m(&acc, "pct10")),
|
||||
pct25: SeriesPattern1::new(client.clone(), _m(&acc, "pct25")),
|
||||
pct75: SeriesPattern1::new(client.clone(), _m(&acc, "pct75")),
|
||||
pct90: SeriesPattern1::new(client.clone(), _m(&acc, "pct90")),
|
||||
rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern::new(client.clone(), acc.clone()),
|
||||
sum: SeriesPattern1::new(client.clone(), _m(&acc, "sum")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct AverageBaseCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern2 {
|
||||
pub average: _1m1w1y24hPattern<StoredU64>,
|
||||
@@ -2498,6 +2464,24 @@ impl CentsSatsUsdPattern {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct CumulativeRollingSumPattern {
|
||||
pub cumulative: SeriesPattern1<StoredU64>,
|
||||
pub rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern,
|
||||
pub sum: SeriesPattern1<StoredU64>,
|
||||
}
|
||||
|
||||
impl CumulativeRollingSumPattern {
|
||||
/// Create a new pattern node with accumulated series name.
|
||||
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
|
||||
Self {
|
||||
cumulative: SeriesPattern1::new(client.clone(), _m(&acc, "cumulative")),
|
||||
rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern::new(client.clone(), acc.clone()),
|
||||
sum: SeriesPattern1::new(client.clone(), _m(&acc, "sum")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pattern struct for repeated tree structure.
|
||||
pub struct DeltaHalfTotalPattern {
|
||||
pub delta: AbsoluteRatePattern,
|
||||
@@ -3418,7 +3402,7 @@ impl SeriesTree_Transactions_Volume {
|
||||
pub struct SeriesTree_Inputs {
|
||||
pub raw: SeriesTree_Inputs_Raw,
|
||||
pub spent: SeriesTree_Inputs_Spent,
|
||||
pub count: AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern,
|
||||
pub count: CumulativeRollingSumPattern,
|
||||
}
|
||||
|
||||
impl SeriesTree_Inputs {
|
||||
@@ -3426,7 +3410,7 @@ impl SeriesTree_Inputs {
|
||||
Self {
|
||||
raw: SeriesTree_Inputs_Raw::new(client.clone(), format!("{base_path}_raw")),
|
||||
spent: SeriesTree_Inputs_Spent::new(client.clone(), format!("{base_path}_spent")),
|
||||
count: AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern::new(client.clone(), "input_count".to_string()),
|
||||
count: CumulativeRollingSumPattern::new(client.clone(), "input_count".to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3520,14 +3504,14 @@ impl SeriesTree_Outputs_Spent {
|
||||
|
||||
/// Series tree node.
|
||||
pub struct SeriesTree_Outputs_Count {
|
||||
pub total: AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern,
|
||||
pub total: CumulativeRollingSumPattern,
|
||||
pub unspent: SeriesPattern1<StoredU64>,
|
||||
}
|
||||
|
||||
impl SeriesTree_Outputs_Count {
|
||||
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
|
||||
Self {
|
||||
total: AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern::new(client.clone(), "output_count".to_string()),
|
||||
total: CumulativeRollingSumPattern::new(client.clone(), "output_count".to_string()),
|
||||
unspent: SeriesPattern1::new(client.clone(), "utxo_count_bis".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ pub(crate) fn process_blocks(
|
||||
let height_to_first_txout_index = &indexer.vecs.outputs.first_txout_index;
|
||||
let height_to_first_txin_index = &indexer.vecs.inputs.first_txin_index;
|
||||
let height_to_tx_count = &transactions.count.total.base.height;
|
||||
let height_to_output_count = &outputs.count.total.full.sum.height;
|
||||
let height_to_input_count = &inputs.count.full.sum.height;
|
||||
let height_to_output_count = &outputs.count.total.sum.height;
|
||||
let height_to_input_count = &inputs.count.sum.height;
|
||||
let tx_index_to_output_count = &indexes.tx_index.output_count;
|
||||
let tx_index_to_input_count = &indexes.tx_index.input_count;
|
||||
|
||||
|
||||
@@ -16,17 +16,15 @@ impl Vecs {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let window_starts = blocks.lookback.window_starts();
|
||||
self.0
|
||||
.compute(starting_indexes.height, &window_starts, exit, |full| {
|
||||
full.compute_with_skip(
|
||||
starting_indexes.height,
|
||||
&indexes.tx_index.input_count,
|
||||
&indexer.vecs.transactions.first_tx_index,
|
||||
&indexes.height.tx_index_count,
|
||||
exit,
|
||||
0,
|
||||
)
|
||||
})?;
|
||||
self.0.compute(
|
||||
starting_indexes.height,
|
||||
&indexes.tx_index.input_count,
|
||||
&indexer.vecs.transactions.first_tx_index,
|
||||
&indexes.height.tx_index_count,
|
||||
&window_starts,
|
||||
exit,
|
||||
0,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
//! PerBlockAggregated - PerBlockDistributionFull (distribution + sum + cumulative) + RollingComplete.
|
||||
//!
|
||||
//! For metrics aggregated per-block from finer-grained sources (e.g., per-tx data),
|
||||
//! where we want full per-block stats plus rolling window stats.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use brk_types::Height;
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, Rw, StorageMode};
|
||||
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode, VecIndex, VecValue, Version};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, PerBlockDistributionFull, NumericValue, RollingComplete, WindowStarts},
|
||||
internal::{
|
||||
CachedWindowStarts, NumericValue, PerBlock, RollingComplete, WindowStarts,
|
||||
algo::compute_aggregations,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
@@ -19,8 +17,8 @@ pub struct PerBlockAggregated<T, M: StorageMode = Rw>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
#[traversable(flatten)]
|
||||
pub full: PerBlockDistributionFull<T, M>,
|
||||
pub sum: PerBlock<T, M>,
|
||||
pub cumulative: PerBlock<T, M>,
|
||||
pub rolling: RollingComplete<T, M>,
|
||||
}
|
||||
|
||||
@@ -35,34 +33,63 @@ where
|
||||
indexes: &indexes::Vecs,
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
let full = PerBlockDistributionFull::forced_import(db, name, version, indexes)?;
|
||||
let sum = PerBlock::forced_import(db, &format!("{name}_sum"), version, indexes)?;
|
||||
let cumulative =
|
||||
PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?;
|
||||
let rolling = RollingComplete::forced_import(
|
||||
db,
|
||||
name,
|
||||
version,
|
||||
indexes,
|
||||
&full.cumulative.height,
|
||||
&cumulative.height,
|
||||
cached_starts,
|
||||
)?;
|
||||
|
||||
Ok(Self { full, rolling })
|
||||
Ok(Self {
|
||||
sum,
|
||||
cumulative,
|
||||
rolling,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute PerBlockDistributionFull stats via closure, then rolling distribution from the per-block sum.
|
||||
pub(crate) fn compute(
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn compute<A>(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
source: &impl ReadableVec<A, T>,
|
||||
first_indexes: &impl ReadableVec<Height, A>,
|
||||
count_indexes: &impl ReadableVec<Height, brk_types::StoredU64>,
|
||||
windows: &WindowStarts<'_>,
|
||||
exit: &Exit,
|
||||
compute_full: impl FnOnce(&mut PerBlockDistributionFull<T>) -> Result<()>,
|
||||
skip_count: usize,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: From<f64> + Default + Copy + Ord,
|
||||
f64: From<T>,
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
compute_full(&mut self.full)?;
|
||||
compute_aggregations(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
exit,
|
||||
skip_count,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(&mut self.sum.height),
|
||||
Some(&mut self.cumulative.height),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)?;
|
||||
self.rolling
|
||||
.compute(max_from, windows, &self.full.sum.height, exit)?;
|
||||
.compute(max_from, windows, &self.sum.height, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::Height;
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
Database, Exit, ReadableVec, Rw, StorageMode,
|
||||
VecIndex, VecValue, Version,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{ComputedVecValue, NumericValue, PerBlock, algo::compute_aggregations},
|
||||
};
|
||||
|
||||
use super::PerBlockDistribution;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct PerBlockDistributionFull<T: ComputedVecValue + PartialOrd + JsonSchema, M: StorageMode = Rw> {
|
||||
pub sum: PerBlock<T, M>,
|
||||
pub cumulative: PerBlock<T, M>,
|
||||
#[traversable(flatten)]
|
||||
pub distribution: PerBlockDistribution<T, M>,
|
||||
}
|
||||
|
||||
impl<T: NumericValue + JsonSchema> PerBlockDistributionFull<T> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
distribution: PerBlockDistribution::forced_import(db, name, version, indexes)?,
|
||||
sum: PerBlock::forced_import(db, &format!("{name}_sum"), version, indexes)?,
|
||||
cumulative: PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute_with_skip<A>(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
source: &impl ReadableVec<A, T>,
|
||||
first_indexes: &impl ReadableVec<Height, A>,
|
||||
count_indexes: &impl ReadableVec<Height, brk_types::StoredU64>,
|
||||
exit: &Exit,
|
||||
skip_count: usize,
|
||||
) -> Result<()>
|
||||
where
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
let d = &mut self.distribution.0;
|
||||
compute_aggregations(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
exit,
|
||||
skip_count,
|
||||
None,
|
||||
None,
|
||||
Some(&mut d.min.height),
|
||||
Some(&mut d.max.height),
|
||||
Some(&mut d.average.height),
|
||||
Some(&mut self.sum.height),
|
||||
Some(&mut self.cumulative.height),
|
||||
Some(&mut d.median.height),
|
||||
Some(&mut d.pct10.height),
|
||||
Some(&mut d.pct25.height),
|
||||
Some(&mut d.pct75.height),
|
||||
Some(&mut d.pct90.height),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ mod base;
|
||||
mod cumulative;
|
||||
mod cumulative_sum;
|
||||
mod distribution;
|
||||
mod distribution_full;
|
||||
mod full;
|
||||
mod lazy_distribution;
|
||||
mod lazy_rolling;
|
||||
@@ -17,7 +16,6 @@ pub use base::*;
|
||||
pub use cumulative::*;
|
||||
pub use cumulative_sum::*;
|
||||
pub use distribution::*;
|
||||
pub use distribution_full::*;
|
||||
pub use full::*;
|
||||
pub use lazy_distribution::*;
|
||||
pub use lazy_rolling::*;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Dollars, Height, StoredF32, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{DeltaChange, DeltaRate, LazyDeltaVec, LazyVecFrom1, ReadableCloneableVec, VecValue};
|
||||
|
||||
@@ -7,7 +8,7 @@ use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
BpsType, CachedWindowStarts, CentsType, DerivedResolutions, LazyPerBlock, NumericValue,
|
||||
Resolutions, Windows,
|
||||
Percent, Resolutions, Windows,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -31,16 +32,14 @@ where
|
||||
/// Single-slot lazy delta percent: BPS delta + lazy ratio + lazy percent views.
|
||||
///
|
||||
/// Mirrors `PercentPerBlock<B>` but with lazy delta for the BPS source.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyDeltaPercentFromHeight<S, B>
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct LazyDeltaPercentFromHeight<S, B>(
|
||||
pub Percent<LazyDeltaFromHeight<S, B, DeltaRate>, LazyPerBlock<StoredF32, B>>,
|
||||
)
|
||||
where
|
||||
S: VecValue,
|
||||
B: BpsType,
|
||||
{
|
||||
pub bps: LazyDeltaFromHeight<S, B, DeltaRate>,
|
||||
pub ratio: LazyPerBlock<StoredF32, B>,
|
||||
pub percent: LazyPerBlock<StoredF32, B>,
|
||||
}
|
||||
B: BpsType;
|
||||
|
||||
/// Lazy rolling deltas for all 4 window durations (24h, 1w, 1m, 1y).
|
||||
///
|
||||
@@ -151,11 +150,11 @@ where
|
||||
)),
|
||||
};
|
||||
|
||||
let rate = LazyDeltaPercentFromHeight {
|
||||
let rate = LazyDeltaPercentFromHeight(Percent {
|
||||
bps,
|
||||
ratio,
|
||||
percent,
|
||||
};
|
||||
});
|
||||
|
||||
(absolute, rate)
|
||||
};
|
||||
@@ -304,11 +303,11 @@ where
|
||||
)),
|
||||
};
|
||||
|
||||
let rate = LazyDeltaPercentFromHeight {
|
||||
let rate = LazyDeltaPercentFromHeight(Percent {
|
||||
bps,
|
||||
ratio,
|
||||
percent,
|
||||
};
|
||||
});
|
||||
|
||||
(absolute, rate)
|
||||
};
|
||||
|
||||
@@ -19,22 +19,20 @@ impl Vecs {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let window_starts = blocks.lookback.window_starts();
|
||||
self.total
|
||||
.compute(starting_indexes.height, &window_starts, exit, |full| {
|
||||
full.compute_with_skip(
|
||||
starting_indexes.height,
|
||||
&indexes.tx_index.output_count,
|
||||
&indexer.vecs.transactions.first_tx_index,
|
||||
&indexes.height.tx_index_count,
|
||||
exit,
|
||||
0,
|
||||
)
|
||||
})?;
|
||||
self.total.compute(
|
||||
starting_indexes.height,
|
||||
&indexes.tx_index.output_count,
|
||||
&indexer.vecs.transactions.first_tx_index,
|
||||
&indexes.height.tx_index_count,
|
||||
&window_starts,
|
||||
exit,
|
||||
0,
|
||||
)?;
|
||||
|
||||
self.unspent.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&self.total.full.cumulative.height,
|
||||
&inputs_count.full.cumulative.height,
|
||||
&self.total.cumulative.height,
|
||||
&inputs_count.cumulative.height,
|
||||
&scripts_count.op_return.cumulative.height,
|
||||
|(h, output_count, input_count, op_return_count, ..)| {
|
||||
let block_count = u64::from(h + 1_usize);
|
||||
|
||||
@@ -39,14 +39,14 @@ impl Vecs {
|
||||
self.taproot.compute_binary::<_, _, RatioU64Bp16>(
|
||||
starting_indexes.height,
|
||||
&count.p2tr.base.height,
|
||||
&outputs_count.total.full.sum.height,
|
||||
&outputs_count.total.sum.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.segwit.compute_binary::<_, _, RatioU64Bp16>(
|
||||
starting_indexes.height,
|
||||
&count.segwit.base.height,
|
||||
&outputs_count.total.full.sum.height,
|
||||
&outputs_count.total.sum.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ impl Vecs {
|
||||
.height
|
||||
.compute_binary::<_, Timestamp, PerSec>(
|
||||
starting_indexes.height,
|
||||
&inputs_count.full.sum.height,
|
||||
&inputs_count.sum.height,
|
||||
&blocks.interval.base,
|
||||
exit,
|
||||
)?;
|
||||
@@ -58,7 +58,7 @@ impl Vecs {
|
||||
.height
|
||||
.compute_binary::<_, Timestamp, PerSec>(
|
||||
starting_indexes.height,
|
||||
&outputs_count.total.full.sum.height,
|
||||
&outputs_count.total.sum.height,
|
||||
&blocks.interval.base,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -1795,43 +1795,6 @@ function create_10y1m1w1y2y3m3y4y5y6m6y8yPattern3(client, acc) {
|
||||
* @property {AdjustedRatioValuePattern} sopr
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern
|
||||
* @property {SeriesPattern1<StoredU64>} average
|
||||
* @property {SeriesPattern1<StoredU64>} cumulative
|
||||
* @property {SeriesPattern1<StoredU64>} max
|
||||
* @property {SeriesPattern1<StoredU64>} median
|
||||
* @property {SeriesPattern1<StoredU64>} min
|
||||
* @property {SeriesPattern1<StoredU64>} pct10
|
||||
* @property {SeriesPattern1<StoredU64>} pct25
|
||||
* @property {SeriesPattern1<StoredU64>} pct75
|
||||
* @property {SeriesPattern1<StoredU64>} pct90
|
||||
* @property {AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern} rolling
|
||||
* @property {SeriesPattern1<StoredU64>} sum
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated series name
|
||||
* @returns {AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern}
|
||||
*/
|
||||
function createAverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern(client, acc) {
|
||||
return {
|
||||
average: createSeriesPattern1(client, _m(acc, 'average')),
|
||||
cumulative: createSeriesPattern1(client, _m(acc, 'cumulative')),
|
||||
max: createSeriesPattern1(client, _m(acc, 'max')),
|
||||
median: createSeriesPattern1(client, _m(acc, 'median')),
|
||||
min: createSeriesPattern1(client, _m(acc, 'min')),
|
||||
pct10: createSeriesPattern1(client, _m(acc, 'pct10')),
|
||||
pct25: createSeriesPattern1(client, _m(acc, 'pct25')),
|
||||
pct75: createSeriesPattern1(client, _m(acc, 'pct75')),
|
||||
pct90: createSeriesPattern1(client, _m(acc, 'pct90')),
|
||||
rolling: createAverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern(client, acc),
|
||||
sum: createSeriesPattern1(client, _m(acc, 'sum')),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} AverageBaseCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern2
|
||||
* @property {_1m1w1y24hPattern<StoredU64>} average
|
||||
@@ -3395,6 +3358,27 @@ function createCentsSatsUsdPattern(client, acc) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} CumulativeRollingSumPattern
|
||||
* @property {SeriesPattern1<StoredU64>} cumulative
|
||||
* @property {AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern} rolling
|
||||
* @property {SeriesPattern1<StoredU64>} sum
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a CumulativeRollingSumPattern pattern node
|
||||
* @param {BrkClientBase} client
|
||||
* @param {string} acc - Accumulated series name
|
||||
* @returns {CumulativeRollingSumPattern}
|
||||
*/
|
||||
function createCumulativeRollingSumPattern(client, acc) {
|
||||
return {
|
||||
cumulative: createSeriesPattern1(client, _m(acc, 'cumulative')),
|
||||
rolling: createAverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern(client, acc),
|
||||
sum: createSeriesPattern1(client, _m(acc, 'sum')),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} DeltaHalfTotalPattern
|
||||
* @property {AbsoluteRatePattern} delta
|
||||
@@ -4125,7 +4109,7 @@ function createUnspentPattern(client, acc) {
|
||||
* @typedef {Object} SeriesTree_Inputs
|
||||
* @property {SeriesTree_Inputs_Raw} raw
|
||||
* @property {SeriesTree_Inputs_Spent} spent
|
||||
* @property {AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern} count
|
||||
* @property {CumulativeRollingSumPattern} count
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -4166,7 +4150,7 @@ function createUnspentPattern(client, acc) {
|
||||
|
||||
/**
|
||||
* @typedef {Object} SeriesTree_Outputs_Count
|
||||
* @property {AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern} total
|
||||
* @property {CumulativeRollingSumPattern} total
|
||||
* @property {SeriesPattern1<StoredU64>} unspent
|
||||
*/
|
||||
|
||||
@@ -7645,7 +7629,7 @@ class BrkClient extends BrkClientBase {
|
||||
txoutIndex: createSeriesPattern20(this, 'txout_index'),
|
||||
value: createSeriesPattern20(this, 'value'),
|
||||
},
|
||||
count: createAverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern(this, 'input_count'),
|
||||
count: createCumulativeRollingSumPattern(this, 'input_count'),
|
||||
},
|
||||
outputs: {
|
||||
raw: {
|
||||
@@ -7659,7 +7643,7 @@ class BrkClient extends BrkClientBase {
|
||||
txinIndex: createSeriesPattern21(this, 'txin_index'),
|
||||
},
|
||||
count: {
|
||||
total: createAverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern(this, 'output_count'),
|
||||
total: createCumulativeRollingSumPattern(this, 'output_count'),
|
||||
unspent: createSeriesPattern1(this, 'utxo_count_bis'),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2221,23 +2221,6 @@ class CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
pass
|
||||
|
||||
class AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated series name."""
|
||||
self.average: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'average'))
|
||||
self.cumulative: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'cumulative'))
|
||||
self.max: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'max'))
|
||||
self.median: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'median'))
|
||||
self.min: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'min'))
|
||||
self.pct10: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'pct10'))
|
||||
self.pct25: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'pct25'))
|
||||
self.pct75: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'pct75'))
|
||||
self.pct90: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'pct90'))
|
||||
self.rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern = AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern(client, acc)
|
||||
self.sum: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'sum'))
|
||||
|
||||
class AverageBaseCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2916,6 +2899,15 @@ class CentsSatsUsdPattern:
|
||||
self.sats: SeriesPattern1[SatsFract] = SeriesPattern1(client, _m(acc, 'sats'))
|
||||
self.usd: SeriesPattern1[Dollars] = SeriesPattern1(client, acc)
|
||||
|
||||
class CumulativeRollingSumPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated series name."""
|
||||
self.cumulative: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'cumulative'))
|
||||
self.rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern = AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern(client, acc)
|
||||
self.sum: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'sum'))
|
||||
|
||||
class DeltaHalfTotalPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -3369,7 +3361,7 @@ class SeriesTree_Inputs:
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.raw: SeriesTree_Inputs_Raw = SeriesTree_Inputs_Raw(client)
|
||||
self.spent: SeriesTree_Inputs_Spent = SeriesTree_Inputs_Spent(client)
|
||||
self.count: AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern = AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern(client, 'input_count')
|
||||
self.count: CumulativeRollingSumPattern = CumulativeRollingSumPattern(client, 'input_count')
|
||||
|
||||
class SeriesTree_Outputs_Raw:
|
||||
"""Series tree node."""
|
||||
@@ -3391,7 +3383,7 @@ class SeriesTree_Outputs_Count:
|
||||
"""Series tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.total: AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern = AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern(client, 'output_count')
|
||||
self.total: CumulativeRollingSumPattern = CumulativeRollingSumPattern(client, 'output_count')
|
||||
self.unspent: SeriesPattern1[StoredU64] = SeriesPattern1(client, 'utxo_count_bis')
|
||||
|
||||
class SeriesTree_Outputs:
|
||||
|
||||
@@ -13,11 +13,12 @@ import {
|
||||
chartsFromFullPerBlock,
|
||||
chartsFromCount,
|
||||
chartsFromCountEntries,
|
||||
chartsFromSumPerBlock,
|
||||
chartsFromAggregatedPerBlock,
|
||||
rollingWindowsTree,
|
||||
|
||||
ROLLING_WINDOWS,
|
||||
chartsFromBlockAnd6b,
|
||||
multiSeriesTree,
|
||||
simpleDeltaTree,
|
||||
percentRatio,
|
||||
percentRatioDots,
|
||||
@@ -737,27 +738,32 @@ export function createNetworkSection() {
|
||||
}),
|
||||
{
|
||||
name: "Flow",
|
||||
title: "UTXO Flow",
|
||||
bottom: [
|
||||
line({
|
||||
series: outputs.count.total.sum,
|
||||
name: "Created",
|
||||
color: colors.entity.output,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
series: inputs.count.sum,
|
||||
name: "Spent",
|
||||
color: colors.entity.input,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
],
|
||||
tree: multiSeriesTree({
|
||||
entries: [
|
||||
{
|
||||
name: "Created",
|
||||
color: colors.entity.output,
|
||||
base: outputs.count.total.sum,
|
||||
rolling: outputs.count.total.rolling.sum,
|
||||
cumulative: outputs.count.total.cumulative,
|
||||
},
|
||||
{
|
||||
name: "Spent",
|
||||
color: colors.entity.input,
|
||||
base: inputs.count.sum,
|
||||
rolling: inputs.count.rolling.sum,
|
||||
cumulative: inputs.count.cumulative,
|
||||
},
|
||||
],
|
||||
title: "UTXO Flow",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Inputs",
|
||||
tree: chartsFromSumPerBlock({
|
||||
tree: chartsFromAggregatedPerBlock({
|
||||
pattern: inputs.count,
|
||||
title: "Input Count",
|
||||
unit: Unit.count,
|
||||
@@ -765,7 +771,7 @@ export function createNetworkSection() {
|
||||
},
|
||||
{
|
||||
name: "Outputs",
|
||||
tree: chartsFromSumPerBlock({
|
||||
tree: chartsFromAggregatedPerBlock({
|
||||
pattern: outputs.count.total,
|
||||
title: "Output Count",
|
||||
unit: Unit.count,
|
||||
|
||||
@@ -758,67 +758,6 @@ export function simpleDeltaTree({ delta, title, unit }) {
|
||||
// ============================================================================
|
||||
// These split patterns into separate Sum/Distribution/Cumulative charts
|
||||
|
||||
/**
|
||||
* Create distribution series (avg + percentiles)
|
||||
* @param {DistributionStats} pattern
|
||||
* @param {Unit} unit
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
function distributionSeries(pattern, unit) {
|
||||
const { stat } = colors;
|
||||
return [
|
||||
dots({ series: pattern.average, name: "avg", color: stat.avg, unit }),
|
||||
dots({
|
||||
series: pattern.median,
|
||||
name: "median",
|
||||
color: stat.median,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
}),
|
||||
dots({
|
||||
series: pattern.max,
|
||||
name: "max",
|
||||
color: stat.max,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
}),
|
||||
dots({
|
||||
series: pattern.min,
|
||||
name: "min",
|
||||
color: stat.min,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
}),
|
||||
dots({
|
||||
series: pattern.pct75,
|
||||
name: "pct75",
|
||||
color: stat.pct75,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
}),
|
||||
dots({
|
||||
series: pattern.pct25,
|
||||
name: "pct25",
|
||||
color: stat.pct25,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
}),
|
||||
dots({
|
||||
series: pattern.pct90,
|
||||
name: "pct90",
|
||||
color: stat.pct90,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
}),
|
||||
dots({
|
||||
series: pattern.pct10,
|
||||
name: "pct10",
|
||||
color: stat.pct10,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create btc/sats/usd series from patterns
|
||||
@@ -910,7 +849,7 @@ export const chartsFromFullPerBlock = (args) =>
|
||||
* @param {string} [args.distributionSuffix]
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export function chartsFromSum({
|
||||
export function chartsFromAggregated({
|
||||
pattern,
|
||||
title,
|
||||
unit,
|
||||
@@ -922,17 +861,12 @@ export function chartsFromSum({
|
||||
: title;
|
||||
return [
|
||||
{
|
||||
name: "Sum",
|
||||
name: "Per Block",
|
||||
title,
|
||||
bottom: [{ series: pattern.sum, title: "sum", color: stat.sum, unit }],
|
||||
bottom: [{ series: pattern.sum, title: "base", color: stat.sum, unit }],
|
||||
},
|
||||
rollingWindowsTree({ windows: pattern.rolling.sum, title, unit }),
|
||||
distributionWindowsTree({ pattern: pattern.rolling, title: distTitle, unit }),
|
||||
{
|
||||
name: "Distribution",
|
||||
title: `${distTitle} Distribution`,
|
||||
bottom: distributionSeries(pattern, unit),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
@@ -949,8 +883,8 @@ export function chartsFromSum({
|
||||
* @param {Unit} args.unit
|
||||
* @returns {PartialOptionsTree}
|
||||
*/
|
||||
export const chartsFromSumPerBlock = (args) =>
|
||||
chartsFromSum({ ...args, distributionSuffix: "per Block" });
|
||||
export const chartsFromAggregatedPerBlock = (args) =>
|
||||
chartsFromAggregated({ ...args, distributionSuffix: "per Block" });
|
||||
|
||||
/**
|
||||
* Create Per Block + Per 6 Blocks stats charts from a _6bBlockTxPattern
|
||||
@@ -1024,12 +958,34 @@ 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,
|
||||
rolling: data.sum,
|
||||
cumulative: data.cumulative,
|
||||
})),
|
||||
title,
|
||||
unit,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Per Block + Sums + Cumulative tree for multiple named series shown side-by-side
|
||||
* @param {Object} args
|
||||
* @param {Array<{ name: string, color: Color, base: AnySeriesPattern, rolling: { _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: "Per Block",
|
||||
title,
|
||||
bottom: entries.map(([name, data], i, arr) =>
|
||||
line({ series: data.base, name, color: colors.at(i, arr.length), unit }),
|
||||
bottom: entries.map((e) =>
|
||||
line({ series: e.base, name: e.name, color: e.color, unit }),
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -1037,16 +993,16 @@ export function chartsFromCountEntries({ entries, title, unit }) {
|
||||
tree: ROLLING_WINDOWS.map((w) => ({
|
||||
name: w.name,
|
||||
title: `${title} (${w.name})`,
|
||||
bottom: entries.map(([name, data], i, arr) =>
|
||||
line({ series: data.sum[w.key], name, color: colors.at(i, arr.length), unit }),
|
||||
bottom: entries.map((e) =>
|
||||
line({ series: e.rolling[w.key], name: e.name, color: e.color, unit }),
|
||||
),
|
||||
})),
|
||||
},
|
||||
{
|
||||
name: "Cumulative",
|
||||
title: `${title} (Total)`,
|
||||
bottom: entries.map(([name, data], i, arr) =>
|
||||
line({ series: data.cumulative, name, color: colors.at(i, arr.length), unit }),
|
||||
bottom: entries.map((e) =>
|
||||
line({ series: e.cumulative, name: e.name, color: e.color, unit }),
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user