global: snapshot

This commit is contained in:
nym21
2026-03-18 12:51:31 +01:00
parent b397b811f9
commit 455dc683eb
14 changed files with 198 additions and 329 deletions

View File

@@ -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()),
}
}

View File

@@ -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;

View File

@@ -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(())
}

View File

@@ -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(())
}
}

View File

@@ -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),
)
}
}

View File

@@ -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::*;

View File

@@ -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)
};

View File

@@ -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);

View File

@@ -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,
)?;

View File

@@ -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,
)?;

View File

@@ -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'),
},
},

View File

@@ -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:

View File

@@ -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,

View File

@@ -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 }),
),
},
];