mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-24 01:18:10 -07:00
global: snapshot part 3
This commit is contained in:
@@ -5,7 +5,10 @@ use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{AmountPerBlock, CachedWindowStarts, LazyRollingSumsAmountFromHeight, SatsToCents},
|
||||
internal::{
|
||||
AmountPerBlock, CachedWindowStarts, LazyRollingAvgsAmountFromHeight,
|
||||
LazyRollingSumsAmountFromHeight, SatsToCents,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
@@ -14,6 +17,7 @@ pub struct AmountPerBlockCumulativeWithSums<M: StorageMode = Rw> {
|
||||
pub base: AmountPerBlock<M>,
|
||||
pub cumulative: AmountPerBlock<M>,
|
||||
pub sum: LazyRollingSumsAmountFromHeight,
|
||||
pub average: LazyRollingAvgsAmountFromHeight,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::TWO;
|
||||
@@ -39,11 +43,20 @@ impl AmountPerBlockCumulativeWithSums {
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let average = LazyRollingAvgsAmountFromHeight::new(
|
||||
&format!("{name}_average"),
|
||||
v,
|
||||
&cumulative.sats.height,
|
||||
&cumulative.cents.height,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
base,
|
||||
cumulative,
|
||||
sum,
|
||||
average,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@ use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode};
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
AmountPerBlock, CachedWindowStarts, LazyRollingSumsAmountFromHeight,
|
||||
RollingDistributionAmountPerBlock, SatsToCents, WindowStarts,
|
||||
AmountPerBlock, CachedWindowStarts, LazyRollingAvgsAmountFromHeight,
|
||||
LazyRollingSumsAmountFromHeight, RollingDistributionAmountPerBlock, SatsToCents,
|
||||
WindowStarts,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -17,8 +18,9 @@ pub struct AmountPerBlockFull<M: StorageMode = Rw> {
|
||||
pub base: AmountPerBlock<M>,
|
||||
pub cumulative: AmountPerBlock<M>,
|
||||
pub sum: LazyRollingSumsAmountFromHeight,
|
||||
pub average: LazyRollingAvgsAmountFromHeight,
|
||||
#[traversable(flatten)]
|
||||
pub rolling: RollingDistributionAmountPerBlock<M>,
|
||||
pub distribution: RollingDistributionAmountPerBlock<M>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::TWO;
|
||||
@@ -34,12 +36,8 @@ impl AmountPerBlockFull {
|
||||
let v = version + VERSION;
|
||||
|
||||
let base = AmountPerBlock::forced_import(db, name, v, indexes)?;
|
||||
let cumulative = AmountPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_cumulative"),
|
||||
v,
|
||||
indexes,
|
||||
)?;
|
||||
let cumulative =
|
||||
AmountPerBlock::forced_import(db, &format!("{name}_cumulative"), v, indexes)?;
|
||||
let sum = LazyRollingSumsAmountFromHeight::new(
|
||||
&format!("{name}_sum"),
|
||||
v,
|
||||
@@ -48,14 +46,22 @@ impl AmountPerBlockFull {
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let rolling =
|
||||
RollingDistributionAmountPerBlock::forced_import(db, name, v, indexes)?;
|
||||
let average = LazyRollingAvgsAmountFromHeight::new(
|
||||
&format!("{name}_average"),
|
||||
v,
|
||||
&cumulative.sats.height,
|
||||
&cumulative.cents.height,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let rolling = RollingDistributionAmountPerBlock::forced_import(db, name, v, indexes)?;
|
||||
|
||||
Ok(Self {
|
||||
base,
|
||||
cumulative,
|
||||
sum,
|
||||
rolling,
|
||||
average,
|
||||
distribution: rolling,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -89,7 +95,7 @@ impl AmountPerBlockFull {
|
||||
.height
|
||||
.compute_cumulative(max_from, &self.base.cents.height, exit)?;
|
||||
|
||||
self.rolling.compute(
|
||||
self.distribution.compute(
|
||||
max_from,
|
||||
windows,
|
||||
&self.base.sats.height,
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Cents, Dollars, Height, Sats, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{DeltaAvg, LazyDeltaVec, LazyVecFrom1, ReadableCloneableVec};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
CachedWindowStarts, CentsUnsignedToDollars, DerivedResolutions, LazyPerBlock,
|
||||
LazyRollingAvgFromHeight, Resolutions, SatsToBitcoin, Windows,
|
||||
},
|
||||
};
|
||||
|
||||
/// Single window slot: lazy rolling average for Amount (sats + btc + cents + usd).
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyRollingAvgAmountFromHeight {
|
||||
pub btc: LazyPerBlock<Bitcoin, Sats>,
|
||||
pub sats: LazyRollingAvgFromHeight<Sats>,
|
||||
pub usd: LazyPerBlock<Dollars, Cents>,
|
||||
pub cents: LazyRollingAvgFromHeight<Cents>,
|
||||
}
|
||||
|
||||
/// Lazy rolling averages for all 4 windows, for Amount (sats + btc + cents + usd).
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct LazyRollingAvgsAmountFromHeight(pub Windows<LazyRollingAvgAmountFromHeight>);
|
||||
|
||||
impl LazyRollingAvgsAmountFromHeight {
|
||||
pub fn new(
|
||||
name: &str,
|
||||
version: Version,
|
||||
cumulative_sats: &(impl ReadableCloneableVec<Height, Sats> + 'static),
|
||||
cumulative_cents: &(impl ReadableCloneableVec<Height, Cents> + 'static),
|
||||
cached_starts: &CachedWindowStarts,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
let cum_sats = cumulative_sats.read_only_boxed_clone();
|
||||
let cum_cents = cumulative_cents.read_only_boxed_clone();
|
||||
|
||||
let make_slot = |suffix: &str, cached_start: &vecdb::CachedVec<Height, Height>| {
|
||||
let full_name = format!("{name}_{suffix}");
|
||||
let cached = cached_start.clone();
|
||||
let starts_version = cached.version();
|
||||
|
||||
// Sats lazy rolling avg
|
||||
let sats_avg = LazyDeltaVec::<Height, Sats, Sats, DeltaAvg>::new(
|
||||
&format!("{full_name}_sats"),
|
||||
version,
|
||||
cum_sats.clone(),
|
||||
starts_version,
|
||||
{
|
||||
let cached = cached.clone();
|
||||
move || cached.get()
|
||||
},
|
||||
);
|
||||
let sats_resolutions = Resolutions::forced_import(
|
||||
&format!("{full_name}_sats"),
|
||||
sats_avg.read_only_boxed_clone(),
|
||||
version,
|
||||
indexes,
|
||||
);
|
||||
let sats = LazyRollingAvgFromHeight {
|
||||
height: sats_avg,
|
||||
resolutions: Box::new(sats_resolutions),
|
||||
};
|
||||
|
||||
// Btc lazy from sats
|
||||
let btc = LazyPerBlock {
|
||||
height: LazyVecFrom1::transformed::<SatsToBitcoin>(
|
||||
&full_name,
|
||||
version,
|
||||
sats.height.read_only_boxed_clone(),
|
||||
),
|
||||
resolutions: Box::new(DerivedResolutions::from_derived_computed::<SatsToBitcoin>(
|
||||
&full_name,
|
||||
version,
|
||||
&sats.resolutions,
|
||||
)),
|
||||
};
|
||||
|
||||
// Cents rolling avg
|
||||
let cents_avg = LazyDeltaVec::<Height, Cents, Cents, DeltaAvg>::new(
|
||||
&format!("{full_name}_cents"),
|
||||
version,
|
||||
cum_cents.clone(),
|
||||
starts_version,
|
||||
move || cached.get(),
|
||||
);
|
||||
let cents_resolutions = Resolutions::forced_import(
|
||||
&format!("{full_name}_cents"),
|
||||
cents_avg.read_only_boxed_clone(),
|
||||
version,
|
||||
indexes,
|
||||
);
|
||||
let cents = LazyRollingAvgFromHeight {
|
||||
height: cents_avg,
|
||||
resolutions: Box::new(cents_resolutions),
|
||||
};
|
||||
|
||||
// Usd lazy from cents
|
||||
let usd = LazyPerBlock {
|
||||
height: LazyVecFrom1::transformed::<CentsUnsignedToDollars>(
|
||||
&format!("{full_name}_usd"),
|
||||
version,
|
||||
cents.height.read_only_boxed_clone(),
|
||||
),
|
||||
resolutions: Box::new(DerivedResolutions::from_derived_computed::<
|
||||
CentsUnsignedToDollars,
|
||||
>(
|
||||
&format!("{full_name}_usd"), version, ¢s.resolutions
|
||||
)),
|
||||
};
|
||||
|
||||
LazyRollingAvgAmountFromHeight {
|
||||
btc,
|
||||
sats,
|
||||
usd,
|
||||
cents,
|
||||
}
|
||||
};
|
||||
|
||||
Self(cached_starts.0.map_with_suffix(make_slot))
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ mod cumulative_sum;
|
||||
mod full;
|
||||
mod lazy;
|
||||
mod lazy_derived_resolutions;
|
||||
mod lazy_rolling_avg;
|
||||
mod lazy_rolling_sum;
|
||||
mod rolling_distribution;
|
||||
mod with_deltas;
|
||||
@@ -14,6 +15,7 @@ pub use cumulative_sum::*;
|
||||
pub use full::*;
|
||||
pub use lazy::*;
|
||||
pub use lazy_derived_resolutions::*;
|
||||
pub use lazy_rolling_avg::*;
|
||||
pub use lazy_rolling_sum::*;
|
||||
pub use rolling_distribution::*;
|
||||
pub use with_deltas::*;
|
||||
|
||||
@@ -9,9 +9,7 @@ use vecdb::{
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
CachedWindowStarts, NumericValue, PerBlock, RollingComplete, WindowStarts,
|
||||
},
|
||||
internal::{CachedWindowStarts, NumericValue, PerBlock, RollingComplete, WindowStarts},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
@@ -70,8 +68,7 @@ where
|
||||
f64: From<T>,
|
||||
A: VecIndex + VecValue + brk_types::CheckedSub<A>,
|
||||
{
|
||||
let combined_version =
|
||||
source.version() + first_indexes.version() + count_indexes.version();
|
||||
let combined_version = source.version() + first_indexes.version() + count_indexes.version();
|
||||
|
||||
let mut index = max_from;
|
||||
index = {
|
||||
@@ -121,7 +118,7 @@ where
|
||||
);
|
||||
|
||||
self.sum.height.push(sum_val);
|
||||
cumulative_val = cumulative_val + sum_val;
|
||||
cumulative_val += sum_val;
|
||||
self.cumulative.height.push(cumulative_val);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -17,7 +17,10 @@ use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CachedWindowStarts, PerBlock, LazyRollingSumsFromHeight, NumericValue},
|
||||
internal::{
|
||||
CachedWindowStarts, LazyRollingAvgsFromHeight, LazyRollingSumsFromHeight, NumericValue,
|
||||
PerBlock,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
@@ -29,6 +32,7 @@ where
|
||||
pub base: PerBlock<T, M>,
|
||||
pub cumulative: PerBlock<C, M>,
|
||||
pub sum: LazyRollingSumsFromHeight<C>,
|
||||
pub average: LazyRollingAvgsFromHeight<C>,
|
||||
}
|
||||
|
||||
impl<T, C> PerBlockCumulativeWithSums<T, C>
|
||||
@@ -53,11 +57,19 @@ where
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let average = LazyRollingAvgsFromHeight::new(
|
||||
&format!("{name}_average"),
|
||||
version,
|
||||
&cumulative.height,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
base,
|
||||
cumulative,
|
||||
sum,
|
||||
average,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ where
|
||||
{
|
||||
pub base: M::Stored<EagerVec<PcoVec<Height, T>>>,
|
||||
#[traversable(hidden)]
|
||||
pub cumulative: M::Stored<EagerVec<PcoVec<Height, f64>>>,
|
||||
pub cumulative: M::Stored<EagerVec<PcoVec<Height, T>>>,
|
||||
#[traversable(flatten)]
|
||||
pub average: LazyRollingAvgsFromHeight<T>,
|
||||
}
|
||||
@@ -38,8 +38,8 @@ where
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
let base: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, version)?;
|
||||
let cumulative: EagerVec<PcoVec<Height, f64>> =
|
||||
EagerVec::forced_import(db, &format!("{name}_cumulative"), version)?;
|
||||
let cumulative: EagerVec<PcoVec<Height, T>> =
|
||||
EagerVec::forced_import(db, &format!("{name}_cumulative"), version + Version::ONE)?;
|
||||
let average = LazyRollingAvgsFromHeight::new(
|
||||
&format!("{name}_average"),
|
||||
version + Version::ONE,
|
||||
|
||||
@@ -12,7 +12,7 @@ pub struct LazyRollingAvgFromHeight<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub height: LazyDeltaVec<Height, f64, T, DeltaAvg>,
|
||||
pub height: LazyDeltaVec<Height, T, T, DeltaAvg>,
|
||||
#[traversable(flatten)]
|
||||
pub resolutions: Box<Resolutions<T>>,
|
||||
}
|
||||
|
||||
@@ -12,10 +12,11 @@ use crate::{
|
||||
use super::LazyRollingAvgFromHeight;
|
||||
|
||||
/// Lazy rolling averages for all 4 window durations (24h, 1w, 1m, 1y),
|
||||
/// derived from an f64 cumulative vec + cached window starts.
|
||||
/// derived from a cumulative vec + cached window starts.
|
||||
///
|
||||
/// Nothing is stored on disk — all values are computed on-the-fly via
|
||||
/// `LazyDeltaVec<Height, f64, T, DeltaAvg>`: `(cum[h] - cum[start-1]) / (h - start + 1)`.
|
||||
/// `LazyDeltaVec<Height, T, T, DeltaAvg>`: `(cum[h] - cum[start-1]) / (h - start + 1)`.
|
||||
/// T is converted to f64 internally for division, then back to T.
|
||||
#[derive(Clone, Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct LazyRollingAvgsFromHeight<T>(pub Windows<LazyRollingAvgFromHeight<T>>)
|
||||
@@ -29,7 +30,7 @@ where
|
||||
pub fn new(
|
||||
name: &str,
|
||||
version: Version,
|
||||
cumulative: &(impl ReadableCloneableVec<Height, f64> + 'static),
|
||||
cumulative: &(impl ReadableCloneableVec<Height, T> + 'static),
|
||||
cached_starts: &CachedWindowStarts,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Self {
|
||||
@@ -39,7 +40,7 @@ where
|
||||
let full_name = format!("{name}_{suffix}");
|
||||
let cached = cached_start.clone();
|
||||
let starts_version = cached.version();
|
||||
let avg = LazyDeltaVec::<Height, f64, T, DeltaAvg>::new(
|
||||
let avg = LazyDeltaVec::<Height, T, T, DeltaAvg>::new(
|
||||
&full_name,
|
||||
version,
|
||||
cum_source.clone(),
|
||||
|
||||
@@ -10,18 +10,19 @@ use vecdb::{Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
CachedWindowStarts, NumericValue, LazyRollingSumsFromHeight, RollingDistribution,
|
||||
WindowStarts,
|
||||
CachedWindowStarts, NumericValue, LazyRollingAvgsFromHeight, LazyRollingSumsFromHeight,
|
||||
RollingDistribution, WindowStarts,
|
||||
},
|
||||
};
|
||||
|
||||
/// Lazy rolling sums + stored rolling distribution (8 stats × 4 windows).
|
||||
/// Lazy rolling sums + lazy rolling averages + stored rolling distribution (7 stats × 4 windows).
|
||||
#[derive(Traversable)]
|
||||
pub struct RollingComplete<T, M: StorageMode = Rw>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub sum: LazyRollingSumsFromHeight<T>,
|
||||
pub average: LazyRollingAvgsFromHeight<T>,
|
||||
#[traversable(flatten)]
|
||||
pub distribution: RollingDistribution<T, M>,
|
||||
}
|
||||
@@ -45,9 +46,20 @@ where
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let average = LazyRollingAvgsFromHeight::new(
|
||||
&format!("{name}_average"),
|
||||
version,
|
||||
cumulative,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let distribution = RollingDistribution::forced_import(db, name, version, indexes)?;
|
||||
|
||||
Ok(Self { sum, distribution })
|
||||
Ok(Self {
|
||||
sum,
|
||||
average,
|
||||
distribution,
|
||||
})
|
||||
}
|
||||
|
||||
/// Compute rolling distribution stats across all 4 windows.
|
||||
|
||||
@@ -6,12 +6,12 @@ use vecdb::{ReadableCloneableVec, UnaryTransform};
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
CachedWindowStarts, ComputedVecValue, LazyRollingDistribution, LazyRollingSumsFromHeight,
|
||||
NumericValue, RollingComplete,
|
||||
CachedWindowStarts, ComputedVecValue, LazyRollingAvgsFromHeight,
|
||||
LazyRollingDistribution, LazyRollingSumsFromHeight, NumericValue, RollingComplete,
|
||||
},
|
||||
};
|
||||
|
||||
/// Lazy analog of `RollingComplete<T>`: lazy rolling sums + lazy rolling distribution.
|
||||
/// Lazy analog of `RollingComplete<T>`: lazy rolling sums + lazy rolling averages + lazy rolling distribution.
|
||||
/// Zero stored vecs.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyRollingComplete<T, S1T>
|
||||
@@ -20,6 +20,7 @@ where
|
||||
S1T: ComputedVecValue + JsonSchema,
|
||||
{
|
||||
pub sum: LazyRollingSumsFromHeight<T>,
|
||||
pub average: LazyRollingAvgsFromHeight<T>,
|
||||
#[traversable(flatten)]
|
||||
pub distribution: LazyRollingDistribution<T, S1T>,
|
||||
}
|
||||
@@ -44,11 +45,22 @@ where
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let average = LazyRollingAvgsFromHeight::new(
|
||||
&format!("{name}_average"),
|
||||
version,
|
||||
cumulative,
|
||||
cached_starts,
|
||||
indexes,
|
||||
);
|
||||
let distribution = LazyRollingDistribution::from_rolling_distribution::<F>(
|
||||
name,
|
||||
version,
|
||||
&source.distribution,
|
||||
);
|
||||
Self { sum, distribution }
|
||||
Self {
|
||||
sum,
|
||||
average,
|
||||
distribution,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ impl<T: VecValue> UnaryTransform<T, T> for Identity<T> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct HalveSats;
|
||||
|
||||
impl UnaryTransform<Sats, Sats> for HalveSats {
|
||||
|
||||
Reference in New Issue
Block a user