global: snapshot

This commit is contained in:
nym21
2026-03-03 22:10:05 +01:00
parent 28f6b0f18b
commit 269c1d5fdf
99 changed files with 1565 additions and 1146 deletions
@@ -1,20 +1,20 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{StoredF32, Version};
use brk_types::{Height, StoredF32, Version};
use schemars::JsonSchema;
use vecdb::{Database, ReadableCloneableVec, Rw, StorageMode, UnaryTransform};
use vecdb::{BinaryTransform, Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, UnaryTransform, VecValue};
use crate::indexes;
use super::{ComputedFromHeight, LazyFromHeight};
use crate::internal::NumericValue;
/// Basis-point storage with lazy float view.
/// Basis-point storage with lazy ratio float view (÷10000).
///
/// Stores integer basis points on disk (Pco-compressed),
/// exposes a lazy StoredF32 view (bps / 100).
/// exposes a lazy StoredF32 ratio (e.g., 25000 bps → 2.5).
#[derive(Traversable)]
pub struct BpsFromHeight<B, M: StorageMode = Rw>
pub struct Float32FromHeight<B, M: StorageMode = Rw>
where
B: NumericValue + JsonSchema,
{
@@ -22,7 +22,7 @@ where
pub float: LazyFromHeight<StoredF32, B>,
}
impl<B> BpsFromHeight<B>
impl<B> Float32FromHeight<B>
where
B: NumericValue + JsonSchema,
{
@@ -43,4 +43,19 @@ where
Ok(Self { bps, float })
}
pub(crate) fn compute_binary<S1T, S2T, F>(
&mut self,
max_from: Height,
source1: &impl ReadableVec<Height, S1T>,
source2: &impl ReadableVec<Height, S2T>,
exit: &Exit,
) -> Result<()>
where
S1T: VecValue,
S2T: VecValue,
F: BinaryTransform<S1T, S2T, B>,
{
self.bps.compute_binary::<S1T, S2T, F>(max_from, source1, source2, exit)
}
}
@@ -1,14 +1,15 @@
mod aggregated;
mod base;
mod bps;
mod by_unit;
mod constant;
mod cumulative;
mod cumulative_sum;
mod distribution;
mod fiat;
mod float32;
mod full;
mod lazy_base;
mod percent;
mod percentiles;
mod price;
mod ratio;
@@ -17,15 +18,16 @@ mod value;
pub use aggregated::*;
pub use base::*;
pub use bps::*;
pub use by_unit::*;
pub use constant::*;
pub use cumulative::*;
pub use cumulative_sum::*;
pub use distribution::*;
pub use fiat::*;
pub use float32::*;
pub use full::*;
pub use lazy_base::*;
pub use percent::*;
pub use percentiles::*;
pub use price::*;
pub use ratio::*;
@@ -0,0 +1,96 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, StoredF32, Version};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, UnaryTransform, VecValue};
use crate::{
indexes,
internal::NumericValue,
traits::ComputeDrawdown,
};
use super::{ComputedFromHeight, LazyFromHeight};
/// Basis-point storage with both ratio and percentage float views.
///
/// Stores integer basis points on disk (Pco-compressed),
/// exposes two lazy StoredF32 views:
/// - `ratio`: bps ÷ 10000 (e.g., 4523 bps → 0.4523)
/// - `percent`: bps ÷ 100 (e.g., 4523 bps → 45.23%)
///
/// Use for dominance, adoption, RSI, and other percentage-valued metrics.
#[derive(Traversable)]
pub struct PercentFromHeight<B, M: StorageMode = Rw>
where
B: NumericValue + JsonSchema,
{
pub bps: ComputedFromHeight<B, M>,
pub ratio: LazyFromHeight<StoredF32, B>,
pub percent: LazyFromHeight<StoredF32, B>,
}
impl<B> PercentFromHeight<B>
where
B: NumericValue + JsonSchema,
{
pub(crate) fn forced_import<RatioTransform, PercentTransform>(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self>
where
RatioTransform: UnaryTransform<B, StoredF32>,
PercentTransform: UnaryTransform<B, StoredF32>,
{
let bps = ComputedFromHeight::forced_import(db, name, version, indexes)?;
let ratio = LazyFromHeight::from_computed::<RatioTransform>(
&format!("{name}_ratio"),
version,
bps.height.read_only_boxed_clone(),
&bps,
);
let percent = LazyFromHeight::from_computed::<PercentTransform>(
&format!("{name}_percent"),
version,
bps.height.read_only_boxed_clone(),
&bps,
);
Ok(Self { bps, ratio, percent })
}
pub(crate) fn compute_binary<S1T, S2T, F>(
&mut self,
max_from: Height,
source1: &impl ReadableVec<Height, S1T>,
source2: &impl ReadableVec<Height, S2T>,
exit: &Exit,
) -> Result<()>
where
S1T: VecValue,
S2T: VecValue,
F: BinaryTransform<S1T, S2T, B>,
{
self.bps.compute_binary::<S1T, S2T, F>(max_from, source1, source2, exit)
}
pub(crate) fn compute_drawdown<C, A>(
&mut self,
max_from: Height,
current: &impl ReadableVec<Height, C>,
ath: &impl ReadableVec<Height, A>,
exit: &Exit,
) -> Result<()>
where
C: VecValue,
A: VecValue,
f64: From<C> + From<A>,
vecdb::EagerVec<vecdb::PcoVec<Height, B>>: ComputeDrawdown<Height>,
{
self.bps.height.compute_drawdown(max_from, current, ath, exit)
}
}
@@ -12,8 +12,8 @@ use super::super::ComputedFromHeight;
#[derive(Traversable)]
pub struct ComputedFromHeightRatioExtension<M: StorageMode = Rw> {
pub ratio_1w_sma: ComputedFromHeight<StoredF32, M>,
pub ratio_1m_sma: ComputedFromHeight<StoredF32, M>,
pub ratio_sma_1w: ComputedFromHeight<StoredF32, M>,
pub ratio_sma_1m: ComputedFromHeight<StoredF32, M>,
pub ratio_pct99: ComputedFromHeight<StoredF32, M>,
pub ratio_pct98: ComputedFromHeight<StoredF32, M>,
pub ratio_pct95: ComputedFromHeight<StoredF32, M>,
@@ -28,9 +28,9 @@ pub struct ComputedFromHeightRatioExtension<M: StorageMode = Rw> {
pub ratio_pct1_price: Price<ComputedFromHeight<Cents, M>>,
pub ratio_sd: ComputedFromHeightStdDevExtended<M>,
pub ratio_4y_sd: ComputedFromHeightStdDevExtended<M>,
pub ratio_2y_sd: ComputedFromHeightStdDevExtended<M>,
pub ratio_1y_sd: ComputedFromHeightStdDevExtended<M>,
pub ratio_sd_4y: ComputedFromHeightStdDevExtended<M>,
pub ratio_sd_2y: ComputedFromHeightStdDevExtended<M>,
pub ratio_sd_1y: ComputedFromHeightStdDevExtended<M>,
#[traversable(skip)]
tdigest: TDigest,
@@ -59,10 +59,11 @@ impl ComputedFromHeightRatioExtension {
}
macro_rules! import_sd {
($suffix:expr, $days:expr) => {
($suffix:expr, $period:expr, $days:expr) => {
ComputedFromHeightStdDevExtended::forced_import(
db,
&format!("{name}_{}", $suffix),
$period,
$days,
v,
indexes,
@@ -77,12 +78,12 @@ impl ComputedFromHeightRatioExtension {
}
Ok(Self {
ratio_1w_sma: import!("ratio_1w_sma"),
ratio_1m_sma: import!("ratio_1m_sma"),
ratio_sd: import_sd!("ratio", usize::MAX),
ratio_1y_sd: import_sd!("ratio_1y", 365),
ratio_2y_sd: import_sd!("ratio_2y", 2 * 365),
ratio_4y_sd: import_sd!("ratio_4y", 4 * 365),
ratio_sma_1w: import!("ratio_sma_1w"),
ratio_sma_1m: import!("ratio_sma_1m"),
ratio_sd: import_sd!("ratio", "", usize::MAX),
ratio_sd_1y: import_sd!("ratio", "1y", 365),
ratio_sd_2y: import_sd!("ratio", "2y", 2 * 365),
ratio_sd_4y: import_sd!("ratio", "4y", 4 * 365),
ratio_pct99: import!("ratio_pct99"),
ratio_pct98: import!("ratio_pct98"),
ratio_pct95: import!("ratio_pct95"),
@@ -108,14 +109,14 @@ impl ComputedFromHeightRatioExtension {
ratio_source: &impl ReadableVec<Height, StoredF32>,
) -> Result<()> {
// SMA using lookback vecs
self.ratio_1w_sma.height.compute_rolling_average(
self.ratio_sma_1w.height.compute_rolling_average(
starting_indexes.height,
&blocks.count.height_1w_ago,
ratio_source,
exit,
)?;
self.ratio_1m_sma.height.compute_rolling_average(
self.ratio_sma_1m.height.compute_rolling_average(
starting_indexes.height,
&blocks.count.height_1m_ago,
ratio_source,
@@ -183,11 +184,11 @@ impl ComputedFromHeightRatioExtension {
// Compute stddev at height level
self.ratio_sd
.compute_all(blocks, starting_indexes, exit, ratio_source)?;
self.ratio_4y_sd
self.ratio_sd_4y
.compute_all(blocks, starting_indexes, exit, ratio_source)?;
self.ratio_2y_sd
self.ratio_sd_2y
.compute_all(blocks, starting_indexes, exit, ratio_source)?;
self.ratio_1y_sd
self.ratio_sd_1y
.compute_all(blocks, starting_indexes, exit, ratio_source)?;
Ok(())
@@ -225,11 +226,11 @@ impl ComputedFromHeightRatioExtension {
// Stddev cents bands
self.ratio_sd
.compute_cents_bands(starting_indexes, metric_price, exit)?;
self.ratio_4y_sd
self.ratio_sd_4y
.compute_cents_bands(starting_indexes, metric_price, exit)?;
self.ratio_2y_sd
self.ratio_sd_2y
.compute_cents_bands(starting_indexes, metric_price, exit)?;
self.ratio_1y_sd
self.ratio_sd_1y
.compute_cents_bands(starting_indexes, metric_price, exit)?;
Ok(())
@@ -51,17 +51,19 @@ impl ComputedFromHeightStdDevExtended {
pub(crate) fn forced_import(
db: &Database,
name: &str,
period: &str,
days: usize,
parent_version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let version = parent_version + Version::TWO;
let p = super::period_suffix(period);
macro_rules! import {
($suffix:expr) => {
ComputedFromHeight::forced_import(
db,
&format!("{name}_{}", $suffix),
&format!("{name}_{}{p}", $suffix),
version,
indexes,
)?
@@ -70,12 +72,12 @@ impl ComputedFromHeightStdDevExtended {
macro_rules! import_price {
($suffix:expr) => {
Price::forced_import(db, &format!("{name}_{}", $suffix), version, indexes)?
Price::forced_import(db, &format!("{name}_{}{p}", $suffix), version, indexes)?
};
}
Ok(Self {
base: ComputedFromHeightStdDev::forced_import(db, name, days, parent_version, indexes)?,
base: ComputedFromHeightStdDev::forced_import(db, name, period, days, parent_version, indexes)?,
zscore: import!("zscore"),
p0_5sd: import!("p0_5sd"),
p1sd: import!("p1sd"),
@@ -11,6 +11,14 @@ use crate::{ComputeIndexes, blocks, indexes};
use crate::internal::ComputedFromHeight;
fn period_suffix(period: &str) -> String {
if period.is_empty() {
String::new()
} else {
format!("_{period}")
}
}
#[derive(Traversable)]
pub struct ComputedFromHeightStdDev<M: StorageMode = Rw> {
days: usize,
@@ -22,21 +30,23 @@ impl ComputedFromHeightStdDev {
pub(crate) fn forced_import(
db: &Database,
name: &str,
period: &str,
days: usize,
parent_version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let version = parent_version + Version::TWO;
let p = period_suffix(period);
let sma = ComputedFromHeight::forced_import(
db,
&format!("{name}_sma"),
&format!("{name}_sma{p}"),
version,
indexes,
)?;
let sd = ComputedFromHeight::forced_import(
db,
&format!("{name}_sd"),
&format!("{name}_sd{p}"),
version,
indexes,
)?;