mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-19 15:08:12 -07:00
global: snapshot
This commit is contained in:
@@ -1,124 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
CheckedSub, Database, EagerVec, Exit, ImportableVec, PcoVec, ReadableVec, Ro, Rw, StorageMode,
|
||||
StoredVec, VecIndex, VecValue, Version,
|
||||
};
|
||||
|
||||
use crate::internal::{
|
||||
ComputedVecValue, DistributionStats,
|
||||
algo::{compute_aggregations, compute_aggregations_nblock_window},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Distribution<I: VecIndex, T: ComputedVecValue + JsonSchema, M: StorageMode = Rw> {
|
||||
pub average: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
pub min: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
pub max: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
pub pct10: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
pub pct25: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
pub median: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
pub pct75: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
pub pct90: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
}
|
||||
|
||||
impl<I: VecIndex, T: ComputedVecValue + JsonSchema> Distribution<I, T> {
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
let s = DistributionStats::<()>::SUFFIXES;
|
||||
Ok(Self {
|
||||
average: EagerVec::forced_import(db, &format!("{name}_{}", s[0]), version)?,
|
||||
min: EagerVec::forced_import(db, &format!("{name}_{}", s[1]), version)?,
|
||||
max: EagerVec::forced_import(db, &format!("{name}_{}", s[2]), version)?,
|
||||
pct10: EagerVec::forced_import(db, &format!("{name}_{}", s[3]), version)?,
|
||||
pct25: EagerVec::forced_import(db, &format!("{name}_{}", s[4]), version)?,
|
||||
median: EagerVec::forced_import(db, &format!("{name}_{}", s[5]), version)?,
|
||||
pct75: EagerVec::forced_import(db, &format!("{name}_{}", s[6]), version)?,
|
||||
pct90: EagerVec::forced_import(db, &format!("{name}_{}", s[7]), version)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute distribution stats, skipping first N items from all calculations.
|
||||
///
|
||||
/// Use `skip_count: 1` to exclude coinbase transactions from fee/feerate stats.
|
||||
pub(crate) fn compute_with_skip<A>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl ReadableVec<A, T>,
|
||||
first_indexes: &impl ReadableVec<I, A>,
|
||||
count_indexes: &impl ReadableVec<I, brk_types::StoredU64>,
|
||||
exit: &Exit,
|
||||
skip_count: usize,
|
||||
) -> Result<()>
|
||||
where
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
compute_aggregations(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
exit,
|
||||
skip_count,
|
||||
None, // first
|
||||
None, // last
|
||||
Some(&mut self.min),
|
||||
Some(&mut self.max),
|
||||
Some(&mut self.average),
|
||||
None, // sum
|
||||
None, // cumulative
|
||||
Some(&mut self.median),
|
||||
Some(&mut self.pct10),
|
||||
Some(&mut self.pct25),
|
||||
Some(&mut self.pct75),
|
||||
Some(&mut self.pct90),
|
||||
)
|
||||
}
|
||||
|
||||
/// Compute distribution stats from a fixed n-block rolling window.
|
||||
///
|
||||
/// For each index `i`, aggregates all source items from blocks `max(0, i - n_blocks + 1)..=i`.
|
||||
pub(crate) fn compute_from_nblocks<A>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &(impl ReadableVec<A, T> + Sized),
|
||||
first_indexes: &impl ReadableVec<I, A>,
|
||||
count_indexes: &impl ReadableVec<I, brk_types::StoredU64>,
|
||||
n_blocks: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: CheckedSub,
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
compute_aggregations_nblock_window(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
n_blocks,
|
||||
exit,
|
||||
&mut self.min,
|
||||
&mut self.max,
|
||||
&mut self.average,
|
||||
&mut self.median,
|
||||
&mut self.pct10,
|
||||
&mut self.pct25,
|
||||
&mut self.pct75,
|
||||
&mut self.pct90,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn read_only_clone(&self) -> Distribution<I, T, Ro> {
|
||||
Distribution {
|
||||
average: StoredVec::read_only_clone(&self.average),
|
||||
min: StoredVec::read_only_clone(&self.min),
|
||||
max: StoredVec::read_only_clone(&self.max),
|
||||
pct10: StoredVec::read_only_clone(&self.pct10),
|
||||
pct25: StoredVec::read_only_clone(&self.pct25),
|
||||
median: StoredVec::read_only_clone(&self.median),
|
||||
pct75: StoredVec::read_only_clone(&self.pct75),
|
||||
pct90: StoredVec::read_only_clone(&self.pct90),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
Database, EagerVec, Exit, ImportableVec, PcoVec, ReadableVec, Ro, Rw, StorageMode, StoredVec,
|
||||
VecIndex, VecValue, Version,
|
||||
};
|
||||
|
||||
use crate::internal::{ComputedVecValue, algo::compute_aggregations};
|
||||
|
||||
use super::Distribution;
|
||||
|
||||
/// Full stats aggregate: sum + cumulative + distribution
|
||||
#[derive(Traversable)]
|
||||
pub struct DistributionFull<I: VecIndex, T: ComputedVecValue + JsonSchema, M: StorageMode = Rw> {
|
||||
pub sum: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
pub cumulative: M::Stored<EagerVec<PcoVec<I, T>>>,
|
||||
#[traversable(flatten)]
|
||||
pub distribution: Distribution<I, T, M>,
|
||||
}
|
||||
|
||||
impl<I: VecIndex, T: ComputedVecValue + JsonSchema> DistributionFull<I, T> {
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
Ok(Self {
|
||||
distribution: Distribution::forced_import(db, name, version)?,
|
||||
sum: EagerVec::forced_import(db, &format!("{name}_sum"), version)?,
|
||||
cumulative: EagerVec::forced_import(db, &format!("{name}_cumulative"), version)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute all stats, skipping first N items from all calculations.
|
||||
///
|
||||
/// Use `skip_count: 1` to exclude coinbase transactions from fee/feerate stats.
|
||||
pub(crate) fn compute_with_skip<A>(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
source: &impl ReadableVec<A, T>,
|
||||
first_indexes: &impl ReadableVec<I, A>,
|
||||
count_indexes: &impl ReadableVec<I, brk_types::StoredU64>,
|
||||
exit: &Exit,
|
||||
skip_count: usize,
|
||||
) -> Result<()>
|
||||
where
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
compute_aggregations(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
exit,
|
||||
skip_count,
|
||||
None, // first
|
||||
None, // last
|
||||
Some(&mut self.distribution.min),
|
||||
Some(&mut self.distribution.max),
|
||||
Some(&mut self.distribution.average),
|
||||
Some(&mut self.sum),
|
||||
Some(&mut self.cumulative),
|
||||
Some(&mut self.distribution.median),
|
||||
Some(&mut self.distribution.pct10),
|
||||
Some(&mut self.distribution.pct25),
|
||||
Some(&mut self.distribution.pct75),
|
||||
Some(&mut self.distribution.pct90),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn read_only_clone(&self) -> DistributionFull<I, T, Ro> {
|
||||
DistributionFull {
|
||||
distribution: self.distribution.read_only_clone(),
|
||||
sum: StoredVec::read_only_clone(&self.sum),
|
||||
cumulative: StoredVec::read_only_clone(&self.cumulative),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
mod distribution;
|
||||
mod distribution_full;
|
||||
mod lazy_distribution;
|
||||
|
||||
pub use distribution::*;
|
||||
pub use distribution_full::*;
|
||||
pub use lazy_distribution::*;
|
||||
@@ -4,10 +4,12 @@ mod per_resolution;
|
||||
mod window_24h;
|
||||
mod windows;
|
||||
mod windows_from_1w;
|
||||
mod percent;
|
||||
mod windows_to_1m;
|
||||
|
||||
pub use constant::*;
|
||||
pub use distribution_stats::*;
|
||||
pub use percent::*;
|
||||
pub use per_resolution::*;
|
||||
pub use window_24h::*;
|
||||
pub use windows::*;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
use brk_traversable::Traversable;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Percent<A, B = A, C = B> {
|
||||
pub bps: A,
|
||||
pub ratio: B,
|
||||
pub percent: C,
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
mod aggregate;
|
||||
pub(crate) mod algo;
|
||||
mod amount;
|
||||
mod containers;
|
||||
@@ -9,7 +8,6 @@ mod indexes;
|
||||
mod traits;
|
||||
mod transform;
|
||||
|
||||
pub(crate) use aggregate::*;
|
||||
pub(crate) use amount::*;
|
||||
pub(crate) use containers::*;
|
||||
pub(crate) use per_block::*;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! PerBlockAggregated - DistributionFull (distribution + sum + cumulative) + RollingComplete.
|
||||
//! 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.
|
||||
@@ -11,7 +11,7 @@ use vecdb::{Database, Exit, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, DistributionFull, NumericValue, RollingComplete, WindowStarts},
|
||||
internal::{CachedWindowStarts, PerBlockDistributionFull, NumericValue, RollingComplete, WindowStarts},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
@@ -20,7 +20,7 @@ where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
#[traversable(flatten)]
|
||||
pub full: DistributionFull<Height, T, M>,
|
||||
pub full: PerBlockDistributionFull<T, M>,
|
||||
pub rolling: RollingComplete<T, M>,
|
||||
}
|
||||
|
||||
@@ -35,26 +35,26 @@ where
|
||||
indexes: &indexes::Vecs,
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
let full = DistributionFull::forced_import(db, name, version)?;
|
||||
let full = PerBlockDistributionFull::forced_import(db, name, version, indexes)?;
|
||||
let rolling = RollingComplete::forced_import(
|
||||
db,
|
||||
name,
|
||||
version,
|
||||
indexes,
|
||||
&full.cumulative,
|
||||
&full.cumulative.height,
|
||||
cached_starts,
|
||||
)?;
|
||||
|
||||
Ok(Self { full, rolling })
|
||||
}
|
||||
|
||||
/// Compute DistributionFull stats via closure, then rolling distribution from the per-block sum.
|
||||
/// Compute PerBlockDistributionFull stats via closure, then rolling distribution from the per-block sum.
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
windows: &WindowStarts<'_>,
|
||||
exit: &Exit,
|
||||
compute_full: impl FnOnce(&mut DistributionFull<Height, T>) -> Result<()>,
|
||||
compute_full: impl FnOnce(&mut PerBlockDistributionFull<T>) -> Result<()>,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: From<f64> + Default + Copy + Ord,
|
||||
@@ -62,7 +62,7 @@ where
|
||||
{
|
||||
compute_full(&mut self.full)?;
|
||||
self.rolling
|
||||
.compute(max_from, windows, &self.full.sum, exit)?;
|
||||
.compute(max_from, windows, &self.full.sum.height, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::Height;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{
|
||||
CheckedSub, Database, Exit, ReadableVec, Rw, StorageMode,
|
||||
VecIndex, VecValue, Version,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
ComputedVecValue, DistributionStats, NumericValue, PerBlock,
|
||||
algo::{compute_aggregations, compute_aggregations_nblock_window},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct PerBlockDistribution<T: ComputedVecValue + PartialOrd + JsonSchema, M: StorageMode = Rw>(
|
||||
pub DistributionStats<PerBlock<T, M>>,
|
||||
);
|
||||
|
||||
impl<T: NumericValue + JsonSchema> PerBlockDistribution<T> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self(DistributionStats::try_from_fn(|suffix| {
|
||||
PerBlock::forced_import(db, &format!("{name}_{suffix}"), 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 s = &mut self.0;
|
||||
compute_aggregations(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
exit,
|
||||
skip_count,
|
||||
None,
|
||||
None,
|
||||
Some(&mut s.min.height),
|
||||
Some(&mut s.max.height),
|
||||
Some(&mut s.average.height),
|
||||
None,
|
||||
None,
|
||||
Some(&mut s.median.height),
|
||||
Some(&mut s.pct10.height),
|
||||
Some(&mut s.pct25.height),
|
||||
Some(&mut s.pct75.height),
|
||||
Some(&mut s.pct90.height),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_nblocks<A>(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
source: &(impl ReadableVec<A, T> + Sized),
|
||||
first_indexes: &impl ReadableVec<Height, A>,
|
||||
count_indexes: &impl ReadableVec<Height, brk_types::StoredU64>,
|
||||
n_blocks: usize,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: CheckedSub,
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
let s = &mut self.0;
|
||||
compute_aggregations_nblock_window(
|
||||
max_from,
|
||||
source,
|
||||
first_indexes,
|
||||
count_indexes,
|
||||
n_blocks,
|
||||
exit,
|
||||
&mut s.min.height,
|
||||
&mut s.max.height,
|
||||
&mut s.average.height,
|
||||
&mut s.median.height,
|
||||
&mut s.pct10.height,
|
||||
&mut s.pct25.height,
|
||||
&mut s.pct75.height,
|
||||
&mut s.pct90.height,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
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),
|
||||
)
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -3,10 +3,10 @@ use brk_types::{Height, Version};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{LazyVecFrom1, ReadableCloneableVec, UnaryTransform, VecIndex};
|
||||
|
||||
use crate::internal::{ComputedVecValue, Distribution, DistributionStats};
|
||||
use crate::internal::{ComputedVecValue, PerBlockDistribution, DistributionStats};
|
||||
|
||||
/// Lazy analog of `Distribution<I, T>`: 8 `LazyVecFrom1` fields,
|
||||
/// each derived by transforming the corresponding field of a source `Distribution<I, S1T>`.
|
||||
/// Lazy analog of `Distribution<T>`: 8 `LazyVecFrom1` fields,
|
||||
/// each derived by transforming the corresponding field of a source `PerBlockDistribution<S1T>`.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyDistribution<I, T, S1T>
|
||||
where
|
||||
@@ -27,54 +27,54 @@ where
|
||||
impl<T, S1T> LazyDistribution<Height, T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S1T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub(crate) fn from_distribution<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
version: Version,
|
||||
source: &Distribution<Height, S1T>,
|
||||
source: &PerBlockDistribution<S1T>,
|
||||
) -> Self {
|
||||
let s = DistributionStats::<()>::SUFFIXES;
|
||||
Self {
|
||||
average: LazyVecFrom1::transformed::<F>(
|
||||
&format!("{name}_{}", s[0]),
|
||||
version,
|
||||
source.average.read_only_boxed_clone(),
|
||||
source.average.height.read_only_boxed_clone(),
|
||||
),
|
||||
min: LazyVecFrom1::transformed::<F>(
|
||||
&format!("{name}_{}", s[1]),
|
||||
version,
|
||||
source.min.read_only_boxed_clone(),
|
||||
source.min.height.read_only_boxed_clone(),
|
||||
),
|
||||
max: LazyVecFrom1::transformed::<F>(
|
||||
&format!("{name}_{}", s[2]),
|
||||
version,
|
||||
source.max.read_only_boxed_clone(),
|
||||
source.max.height.read_only_boxed_clone(),
|
||||
),
|
||||
pct10: LazyVecFrom1::transformed::<F>(
|
||||
&format!("{name}_{}", s[3]),
|
||||
version,
|
||||
source.pct10.read_only_boxed_clone(),
|
||||
source.pct10.height.read_only_boxed_clone(),
|
||||
),
|
||||
pct25: LazyVecFrom1::transformed::<F>(
|
||||
&format!("{name}_{}", s[4]),
|
||||
version,
|
||||
source.pct25.read_only_boxed_clone(),
|
||||
source.pct25.height.read_only_boxed_clone(),
|
||||
),
|
||||
median: LazyVecFrom1::transformed::<F>(
|
||||
&format!("{name}_{}", s[5]),
|
||||
version,
|
||||
source.median.read_only_boxed_clone(),
|
||||
source.median.height.read_only_boxed_clone(),
|
||||
),
|
||||
pct75: LazyVecFrom1::transformed::<F>(
|
||||
&format!("{name}_{}", s[6]),
|
||||
version,
|
||||
source.pct75.read_only_boxed_clone(),
|
||||
source.pct75.height.read_only_boxed_clone(),
|
||||
),
|
||||
pct90: LazyVecFrom1::transformed::<F>(
|
||||
&format!("{name}_{}", s[7]),
|
||||
version,
|
||||
source.pct90.read_only_boxed_clone(),
|
||||
source.pct90.height.read_only_boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,13 @@ mod aggregated;
|
||||
mod base;
|
||||
mod cumulative;
|
||||
mod cumulative_sum;
|
||||
mod distribution;
|
||||
mod distribution_full;
|
||||
mod full;
|
||||
mod lazy_distribution;
|
||||
mod lazy_rolling;
|
||||
mod resolutions;
|
||||
mod rolling;
|
||||
mod lazy_rolling;
|
||||
mod full;
|
||||
mod rolling_average;
|
||||
mod with_deltas;
|
||||
|
||||
@@ -13,9 +16,12 @@ pub use aggregated::*;
|
||||
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::*;
|
||||
pub use resolutions::*;
|
||||
pub use rolling::*;
|
||||
pub use lazy_rolling::*;
|
||||
pub use full::*;
|
||||
pub use rolling_average::*;
|
||||
pub use with_deltas::*;
|
||||
|
||||
@@ -2,11 +2,11 @@ use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{LazyVecFrom1, ReadableBoxedVec, ReadableCloneableVec, UnaryTransform};
|
||||
use vecdb::{LazyVecFrom1, ReadOnlyClone, ReadableBoxedVec, ReadableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{PerBlock, ComputedVecValue, DerivedResolutions, NumericValue},
|
||||
internal::{ComputedVecValue, DerivedResolutions, NumericValue, PerBlock},
|
||||
};
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
@@ -38,7 +38,9 @@ where
|
||||
{
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(name, version, height_source),
|
||||
resolutions: Box::new(DerivedResolutions::from_computed::<F>(name, version, source)),
|
||||
resolutions: Box::new(DerivedResolutions::from_computed::<F>(
|
||||
name, version, source,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,3 +88,14 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S1T> ReadOnlyClone for LazyPerBlock<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
S1T: ComputedVecValue,
|
||||
{
|
||||
type ReadOnly = Self;
|
||||
fn read_only_clone(&self) -> Self {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredF32, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
BinaryTransform, Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, VecValue,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{BpsType, algo::ComputeDrawdown},
|
||||
internal::{BpsType, Percent, algo::ComputeDrawdown},
|
||||
};
|
||||
|
||||
use crate::internal::{PerBlock, LazyPerBlock};
|
||||
use crate::internal::{LazyPerBlock, PerBlock};
|
||||
|
||||
/// Basis-point storage with both ratio and percentage float views.
|
||||
///
|
||||
@@ -18,12 +19,11 @@ use crate::internal::{PerBlock, LazyPerBlock};
|
||||
/// exposes two lazy StoredF32 views:
|
||||
/// - `ratio`: bps / 10000 (e.g., 4523 bps -> 0.4523)
|
||||
/// - `percent`: bps / 100 (e.g., 4523 bps -> 45.23%)
|
||||
#[derive(Traversable)]
|
||||
pub struct PercentPerBlock<B: BpsType, M: StorageMode = Rw> {
|
||||
pub bps: PerBlock<B, M>,
|
||||
pub ratio: LazyPerBlock<StoredF32, B>,
|
||||
pub percent: LazyPerBlock<StoredF32, B>,
|
||||
}
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct PercentPerBlock<B: BpsType, M: StorageMode = Rw>(
|
||||
pub Percent<PerBlock<B, M>, LazyPerBlock<StoredF32, B>>,
|
||||
);
|
||||
|
||||
impl<B: BpsType> PercentPerBlock<B> {
|
||||
pub(crate) fn forced_import(
|
||||
@@ -44,11 +44,11 @@ impl<B: BpsType> PercentPerBlock<B> {
|
||||
|
||||
let percent = LazyPerBlock::from_computed::<B::ToPercent>(name, version, bps_clone, &bps);
|
||||
|
||||
Ok(Self {
|
||||
Ok(Self(Percent {
|
||||
bps,
|
||||
ratio,
|
||||
percent,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn compute_binary<S1T, S2T, F>(
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{StoredF32, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{ReadableCloneableVec, UnaryTransform};
|
||||
|
||||
use crate::internal::{BpsType, LazyPerBlock, PercentPerBlock};
|
||||
use crate::internal::{BpsType, LazyPerBlock, Percent, PercentPerBlock};
|
||||
|
||||
/// Fully lazy variant of `PercentPerBlock` — no stored vecs.
|
||||
///
|
||||
/// BPS values are lazily derived from a source `PercentPerBlock` via a unary transform,
|
||||
/// and ratio/percent float views are chained from the lazy BPS.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyPercentPerBlock<B: BpsType> {
|
||||
pub bps: LazyPerBlock<B, B>,
|
||||
pub ratio: LazyPerBlock<StoredF32, B>,
|
||||
pub percent: LazyPerBlock<StoredF32, B>,
|
||||
}
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct LazyPercentPerBlock<B: BpsType>(
|
||||
pub Percent<LazyPerBlock<B, B>, LazyPerBlock<StoredF32, B>>,
|
||||
);
|
||||
|
||||
impl<B: BpsType> LazyPercentPerBlock<B> {
|
||||
/// Create from a stored `PercentPerBlock` source via a BPS-to-BPS unary transform.
|
||||
@@ -37,10 +37,10 @@ impl<B: BpsType> LazyPercentPerBlock<B> {
|
||||
|
||||
let percent = LazyPerBlock::from_lazy::<B::ToPercent, B>(name, version, &bps);
|
||||
|
||||
Self {
|
||||
Self(Percent {
|
||||
bps,
|
||||
ratio,
|
||||
percent,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
mod base;
|
||||
mod lazy;
|
||||
mod lazy_windows;
|
||||
mod rolling_average;
|
||||
mod vec;
|
||||
mod windows;
|
||||
|
||||
pub use base::*;
|
||||
pub use lazy::*;
|
||||
pub use lazy_windows::*;
|
||||
pub use rolling_average::*;
|
||||
pub use vec::*;
|
||||
pub use windows::*;
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredF32, Version};
|
||||
use vecdb::{Database, EagerVec, Exit, PcoVec, ReadableCloneableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{BpsType, CachedWindowStarts},
|
||||
};
|
||||
|
||||
use crate::internal::{PerBlockRollingAverage, LazyPerBlock};
|
||||
|
||||
/// Like PercentPerBlock but with rolling average stats on the bps data.
|
||||
#[derive(Traversable)]
|
||||
pub struct PercentPerBlockRollingAverage<B: BpsType, M: StorageMode = Rw> {
|
||||
pub bps: PerBlockRollingAverage<B, M>,
|
||||
pub ratio: LazyPerBlock<StoredF32, B>,
|
||||
pub percent: LazyPerBlock<StoredF32, B>,
|
||||
}
|
||||
|
||||
impl<B: BpsType> PercentPerBlockRollingAverage<B> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
let bps = PerBlockRollingAverage::forced_import(
|
||||
db,
|
||||
&format!("{name}_bps"),
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?;
|
||||
|
||||
let ratio = LazyPerBlock::from_height_source::<B::ToRatio>(
|
||||
&format!("{name}_ratio"),
|
||||
version,
|
||||
bps.base.read_only_boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
let percent = LazyPerBlock::from_height_source::<B::ToPercent>(
|
||||
name,
|
||||
version,
|
||||
bps.base.read_only_boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
bps,
|
||||
ratio,
|
||||
percent,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
exit: &Exit,
|
||||
compute_height: impl FnOnce(&mut EagerVec<PcoVec<Height, B>>) -> Result<()>,
|
||||
) -> Result<()> {
|
||||
self.bps.compute(max_from, exit, compute_height)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredF32, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
Database, EagerVec, ImportableVec, LazyVecFrom1, PcoVec, ReadableCloneableVec, Rw, StorageMode,
|
||||
};
|
||||
|
||||
use crate::internal::{BpsType, Percent};
|
||||
|
||||
/// Lightweight percent container: BPS height vec + lazy ratio + lazy percent.
|
||||
/// No resolutions, no rolling stats.
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub struct PercentVec<B: BpsType, M: StorageMode = Rw>(
|
||||
pub Percent<M::Stored<EagerVec<PcoVec<Height, B>>>, LazyVecFrom1<Height, StoredF32, Height, B>>,
|
||||
);
|
||||
|
||||
impl<B: BpsType> PercentVec<B> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
) -> brk_error::Result<Self> {
|
||||
let bps: EagerVec<PcoVec<Height, B>> =
|
||||
EagerVec::forced_import(db, &format!("{name}_bps"), version)?;
|
||||
let bps_clone = bps.read_only_boxed_clone();
|
||||
|
||||
let ratio = LazyVecFrom1::transformed::<B::ToRatio>(
|
||||
&format!("{name}_ratio"),
|
||||
version,
|
||||
bps_clone.clone(),
|
||||
);
|
||||
|
||||
let percent = LazyVecFrom1::transformed::<B::ToPercent>(name, version, bps_clone);
|
||||
|
||||
Ok(Self(Percent {
|
||||
bps,
|
||||
ratio,
|
||||
percent,
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -1,37 +1,36 @@
|
||||
//! TxDerivedDistribution - per-block + rolling window distribution stats from tx-level data.
|
||||
//!
|
||||
//! Computes true distribution stats (average, min, max, median, percentiles) by reading
|
||||
//! actual tx values for each scope: current block, last 6 blocks.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Indexes, TxIndex};
|
||||
use brk_types::{Indexes, TxIndex};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode, Version};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{ComputedVecValue, Distribution, NumericValue},
|
||||
internal::{ComputedVecValue, NumericValue, PerBlockDistribution},
|
||||
};
|
||||
|
||||
/// 6-block rolling window distribution with 8 distribution stat vecs.
|
||||
#[derive(Traversable)]
|
||||
pub struct BlockRollingDistribution<T, M: StorageMode = Rw>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub _6b: Distribution<Height, T, M>,
|
||||
pub _6b: PerBlockDistribution<T, M>,
|
||||
}
|
||||
|
||||
impl<T> BlockRollingDistribution<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
_6b: Distribution::forced_import(db, &format!("{name}_6b"), version)?,
|
||||
_6b: PerBlockDistribution::forced_import(db, &format!("{name}_6b"), version, indexes)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -41,20 +40,28 @@ pub struct TxDerivedDistribution<T, M: StorageMode = Rw>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub block: Distribution<Height, T, M>,
|
||||
pub block: PerBlockDistribution<T, M>,
|
||||
#[traversable(flatten)]
|
||||
pub rolling: BlockRollingDistribution<T, M>,
|
||||
pub distribution: BlockRollingDistribution<T, M>,
|
||||
}
|
||||
|
||||
impl<T> TxDerivedDistribution<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
let block = Distribution::forced_import(db, name, version)?;
|
||||
let rolling = BlockRollingDistribution::forced_import(db, name, version)?;
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let block = PerBlockDistribution::forced_import(db, name, version, indexes)?;
|
||||
let distribution = BlockRollingDistribution::forced_import(db, name, version, indexes)?;
|
||||
|
||||
Ok(Self { block, rolling })
|
||||
Ok(Self {
|
||||
block,
|
||||
distribution,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn derive_from(
|
||||
@@ -72,10 +79,6 @@ where
|
||||
self.derive_from_with_skip(indexer, indexes, starting_indexes, tx_index_source, exit, 0)
|
||||
}
|
||||
|
||||
/// Derive from source, skipping first N transactions per block from per-block stats.
|
||||
///
|
||||
/// Use `skip_count: 1` to exclude coinbase transactions from fee/feerate stats.
|
||||
/// Rolling window distributions do NOT skip (negligible impact over many blocks).
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn derive_from_with_skip(
|
||||
&mut self,
|
||||
@@ -90,7 +93,6 @@ where
|
||||
T: Copy + Ord + From<f64> + Default,
|
||||
f64: From<T>,
|
||||
{
|
||||
// Per-block distribution (supports skip for coinbase exclusion)
|
||||
self.block.compute_with_skip(
|
||||
starting_indexes.height,
|
||||
tx_index_source,
|
||||
@@ -100,8 +102,7 @@ where
|
||||
skip_count,
|
||||
)?;
|
||||
|
||||
// 6-block rolling: true distribution from all txs in last 6 blocks
|
||||
self.rolling._6b.compute_from_nblocks(
|
||||
self.distribution._6b.compute_from_nblocks(
|
||||
starting_indexes.height,
|
||||
tx_index_source,
|
||||
&indexer.vecs.transactions.first_tx_index,
|
||||
|
||||
@@ -29,9 +29,9 @@ impl<T> PerTxDistribution<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
|
||||
pub(crate) fn forced_import(db: &Database, name: &str, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
||||
let tx_index = EagerVec::forced_import(db, name, version)?;
|
||||
let distribution = TxDerivedDistribution::forced_import(db, name, version)?;
|
||||
let distribution = TxDerivedDistribution::forced_import(db, name, version, indexes)?;
|
||||
Ok(Self {
|
||||
tx_index,
|
||||
distribution,
|
||||
|
||||
@@ -14,8 +14,6 @@ where
|
||||
pub _6b: LazyDistribution<Height, T, S1T>,
|
||||
}
|
||||
|
||||
/// Lazy analog of `TxDerivedDistribution<T>`: per-block + 6-block rolling,
|
||||
/// each derived by transforming the corresponding source distribution.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyTxDerivedDistribution<T, S1T>
|
||||
where
|
||||
@@ -24,13 +22,13 @@ where
|
||||
{
|
||||
pub block: LazyDistribution<Height, T, S1T>,
|
||||
#[traversable(flatten)]
|
||||
pub rolling: LazyBlockRollingDistribution<T, S1T>,
|
||||
pub distribution: LazyBlockRollingDistribution<T, S1T>,
|
||||
}
|
||||
|
||||
impl<T, S1T> LazyTxDerivedDistribution<T, S1T>
|
||||
where
|
||||
T: ComputedVecValue + JsonSchema + 'static,
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
S1T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub(crate) fn from_tx_derived<F: UnaryTransform<S1T, T>>(
|
||||
name: &str,
|
||||
@@ -38,13 +36,16 @@ where
|
||||
source: &TxDerivedDistribution<S1T>,
|
||||
) -> Self {
|
||||
let block = LazyDistribution::from_distribution::<F>(name, version, &source.block);
|
||||
let rolling = LazyBlockRollingDistribution {
|
||||
let distribution = LazyBlockRollingDistribution {
|
||||
_6b: LazyDistribution::from_distribution::<F>(
|
||||
&format!("{name}_6b"),
|
||||
version,
|
||||
&source.rolling._6b,
|
||||
&source.distribution._6b,
|
||||
),
|
||||
};
|
||||
Self { block, rolling }
|
||||
Self {
|
||||
block,
|
||||
distribution,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,10 @@ where
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
tx_index: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
|
||||
) -> Result<Self> {
|
||||
let distribution = TxDerivedDistribution::forced_import(db, name, version)?;
|
||||
let distribution = TxDerivedDistribution::forced_import(db, name, version, indexes)?;
|
||||
Ok(Self {
|
||||
tx_index,
|
||||
distribution,
|
||||
|
||||
@@ -28,4 +28,4 @@ pub use ratio::{
|
||||
RatioCentsSignedDollarsBps32, RatioDiffCentsBps32, RatioDiffDollarsBps32, RatioDiffF32Bps32,
|
||||
RatioDollarsBp16, RatioDollarsBp32, RatioDollarsBps32, RatioSatsBp16, RatioU64Bp16,
|
||||
};
|
||||
pub use specialized::{BlockCountTarget, OhlcCentsToDollars, OhlcCentsToSats};
|
||||
pub use specialized::{BlockCountTarget24h, BlockCountTarget1w, BlockCountTarget1m, BlockCountTarget1y, OhlcCentsToDollars, OhlcCentsToSats};
|
||||
|
||||
@@ -1,132 +1,36 @@
|
||||
use brk_types::{
|
||||
Close, Day1, Day3, Epoch, Halving, Height, High, Hour1, Hour4, Hour12, Low,
|
||||
Minute10, Minute30, Month1, Month3, Month6, OHLCCents, OHLCDollars, OHLCSats, Open, StoredU64,
|
||||
Week1, Year1, Year10,
|
||||
Close, Day1, Day3, Epoch, Halving, Height, High, Hour1, Hour4, Hour12, Low, Minute10, Minute30,
|
||||
Month1, Month3, Month6, OHLCCents, OHLCDollars, OHLCSats, Open, StoredU64, Week1, Year1,
|
||||
Year10,
|
||||
};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
use super::CentsUnsignedToSats;
|
||||
use crate::blocks::{
|
||||
TARGET_BLOCKS_PER_DAY, TARGET_BLOCKS_PER_DAY3, TARGET_BLOCKS_PER_DECADE,
|
||||
TARGET_BLOCKS_PER_HALVING, TARGET_BLOCKS_PER_HOUR1, TARGET_BLOCKS_PER_HOUR4,
|
||||
TARGET_BLOCKS_PER_HOUR12, TARGET_BLOCKS_PER_MINUTE10, TARGET_BLOCKS_PER_MINUTE30,
|
||||
TARGET_BLOCKS_PER_MONTH, TARGET_BLOCKS_PER_QUARTER, TARGET_BLOCKS_PER_SEMESTER,
|
||||
TARGET_BLOCKS_PER_WEEK, TARGET_BLOCKS_PER_YEAR,
|
||||
TARGET_BLOCKS_PER_DAY, TARGET_BLOCKS_PER_MONTH, TARGET_BLOCKS_PER_WEEK, TARGET_BLOCKS_PER_YEAR,
|
||||
};
|
||||
|
||||
pub struct BlockCountTarget;
|
||||
|
||||
impl UnaryTransform<Height, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Height) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_DAY)
|
||||
}
|
||||
macro_rules! const_block_target {
|
||||
($name:ident, $value:expr) => {
|
||||
pub struct $name;
|
||||
const_block_target!(@impl $name, $value, Height, Minute10, Minute30, Hour1, Hour4, Hour12, Day1, Day3, Week1, Month1, Month3, Month6, Year1, Year10, Halving, Epoch);
|
||||
};
|
||||
(@impl $name:ident, $value:expr, $($idx:ty),*) => {
|
||||
$(
|
||||
impl UnaryTransform<$idx, StoredU64> for $name {
|
||||
#[inline(always)]
|
||||
fn apply(_: $idx) -> StoredU64 {
|
||||
StoredU64::from($value)
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
impl UnaryTransform<Minute10, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Minute10) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_MINUTE10)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Minute30, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Minute30) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_MINUTE30)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Hour1, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Hour1) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_HOUR1)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Hour4, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Hour4) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_HOUR4)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Hour12, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Hour12) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_HOUR12)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Day1, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Day1) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_DAY)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Day3, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Day3) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_DAY3)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Week1, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Week1) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_WEEK)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Month1, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Month1) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_MONTH)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Month3, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Month3) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_QUARTER)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Month6, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Month6) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Year1, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Year1) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_YEAR)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Year10, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Year10) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_DECADE)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Halving, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Halving) -> StoredU64 {
|
||||
StoredU64::from(TARGET_BLOCKS_PER_HALVING)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnaryTransform<Epoch, StoredU64> for BlockCountTarget {
|
||||
#[inline(always)]
|
||||
fn apply(_: Epoch) -> StoredU64 {
|
||||
StoredU64::from(2016u64)
|
||||
}
|
||||
}
|
||||
const_block_target!(BlockCountTarget24h, TARGET_BLOCKS_PER_DAY);
|
||||
const_block_target!(BlockCountTarget1w, TARGET_BLOCKS_PER_WEEK);
|
||||
const_block_target!(BlockCountTarget1m, TARGET_BLOCKS_PER_MONTH);
|
||||
const_block_target!(BlockCountTarget1y, TARGET_BLOCKS_PER_YEAR);
|
||||
|
||||
pub struct OhlcCentsToDollars;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user