global: snapshot

This commit is contained in:
nym21
2026-03-04 10:25:41 +01:00
parent 269c1d5fdf
commit 0d63724903
91 changed files with 972 additions and 972 deletions
@@ -1,61 +0,0 @@
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;
use super::{ComputedFromHeight, LazyFromHeight};
use crate::internal::NumericValue;
/// Basis-point storage with lazy ratio float view (÷10000).
///
/// Stores integer basis points on disk (Pco-compressed),
/// exposes a lazy StoredF32 ratio (e.g., 25000 bps → 2.5).
#[derive(Traversable)]
pub struct Float32FromHeight<B, M: StorageMode = Rw>
where
B: NumericValue + JsonSchema,
{
pub bps: ComputedFromHeight<B, M>,
pub float: LazyFromHeight<StoredF32, B>,
}
impl<B> Float32FromHeight<B>
where
B: NumericValue + JsonSchema,
{
pub(crate) fn forced_import<F: UnaryTransform<B, StoredF32>>(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let bps = ComputedFromHeight::forced_import(db, name, version, indexes)?;
let float = LazyFromHeight::from_computed::<F>(
&format!("{name}_float"),
version,
bps.height.read_only_boxed_clone(),
&bps,
);
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)
}
}
@@ -6,10 +6,10 @@ mod cumulative;
mod cumulative_sum;
mod distribution;
mod fiat;
mod float32;
mod full;
mod lazy_base;
mod percent;
mod percent_distribution;
mod percentiles;
mod price;
mod ratio;
@@ -24,10 +24,10 @@ 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 percent_distribution::*;
pub use percentiles::*;
pub use price::*;
pub use ratio::*;
@@ -1,12 +1,17 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, StoredF32, Version};
use brk_types::{
BasisPoints16, BasisPointsSigned16, BasisPointsSigned32, Height, StoredF32, Version,
};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, UnaryTransform, VecValue};
use crate::{
indexes,
internal::NumericValue,
internal::{
Bp16ToFloat, Bp16ToPercent, Bps16ToFloat, Bps16ToPercent, Bps32ToFloat, Bps32ToPercent,
NumericValue,
},
traits::ComputeDrawdown,
};
@@ -44,7 +49,7 @@ where
RatioTransform: UnaryTransform<B, StoredF32>,
PercentTransform: UnaryTransform<B, StoredF32>,
{
let bps = ComputedFromHeight::forced_import(db, name, version, indexes)?;
let bps = ComputedFromHeight::forced_import(db, &format!("{name}_bps"), version, indexes)?;
let ratio = LazyFromHeight::from_computed::<RatioTransform>(
&format!("{name}_ratio"),
@@ -54,7 +59,7 @@ where
);
let percent = LazyFromHeight::from_computed::<PercentTransform>(
&format!("{name}_percent"),
name,
version,
bps.height.read_only_boxed_clone(),
&bps,
@@ -63,6 +68,45 @@ where
Ok(Self { bps, ratio, percent })
}
}
impl PercentFromHeight<BasisPoints16> {
pub(crate) fn forced_import_bp16(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Self::forced_import::<Bp16ToFloat, Bp16ToPercent>(db, name, version, indexes)
}
}
impl PercentFromHeight<BasisPointsSigned16> {
pub(crate) fn forced_import_bps16(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Self::forced_import::<Bps16ToFloat, Bps16ToPercent>(db, name, version, indexes)
}
}
impl PercentFromHeight<BasisPointsSigned32> {
pub(crate) fn forced_import_bps32(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Self::forced_import::<Bps32ToFloat, Bps32ToPercent>(db, name, version, indexes)
}
}
impl<B> PercentFromHeight<B>
where
B: NumericValue + JsonSchema,
{
pub(crate) fn compute_binary<S1T, S2T, F>(
&mut self,
max_from: Height,
@@ -0,0 +1,85 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{BasisPoints16, Height, StoredF32, Version};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, PcoVec, ReadableCloneableVec, Rw, StorageMode, UnaryTransform};
use crate::{indexes, internal::{Bp16ToFloat, Bp16ToPercent, NumericValue, WindowStarts}};
use super::{ComputedFromHeightDistribution, LazyFromHeight};
/// Like PercentFromHeight but with rolling distribution stats on the bps data.
#[derive(Traversable)]
pub struct PercentFromHeightDistribution<B, M: StorageMode = Rw>
where
B: NumericValue + JsonSchema,
{
pub bps: ComputedFromHeightDistribution<B, M>,
pub ratio: LazyFromHeight<StoredF32, B>,
pub percent: LazyFromHeight<StoredF32, B>,
}
impl<B> PercentFromHeightDistribution<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 = ComputedFromHeightDistribution::forced_import(db, &format!("{name}_bps"), version, indexes)?;
let ratio = LazyFromHeight::from_height_source::<RatioTransform>(
&format!("{name}_ratio"),
version,
bps.height.read_only_boxed_clone(),
indexes,
);
let percent = LazyFromHeight::from_height_source::<PercentTransform>(
name,
version,
bps.height.read_only_boxed_clone(),
indexes,
);
Ok(Self { bps, ratio, percent })
}
}
impl PercentFromHeightDistribution<BasisPoints16> {
pub(crate) fn forced_import_bp16(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Self::forced_import::<Bp16ToFloat, Bp16ToPercent>(db, name, version, indexes)
}
}
impl<B> PercentFromHeightDistribution<B>
where
B: NumericValue + JsonSchema,
{
pub(crate) fn compute(
&mut self,
max_from: Height,
windows: &WindowStarts<'_>,
exit: &Exit,
compute_height: impl FnOnce(&mut EagerVec<PcoVec<Height, B>>) -> Result<()>,
) -> Result<()>
where
B: Copy + Ord + From<f64> + Default,
f64: From<B>,
{
self.bps.compute(max_from, windows, exit, compute_height)
}
}
@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_traversable::{Traversable, TreeNode};
use brk_types::{Cents, Height, StoredF32, Version};
use brk_types::{BasisPoints16, Cents, Height, Version};
use vecdb::{AnyExportableVec, Database, ReadOnlyClone, Ro, Rw, StorageMode, WritableVec};
use crate::indexes;
@@ -16,9 +16,9 @@ pub const PERCENTILES_LEN: usize = PERCENTILES.len();
pub(crate) fn compute_spot_percentile_rank(
percentile_prices: &[Cents; PERCENTILES_LEN],
spot: Cents,
) -> StoredF32 {
) -> BasisPoints16 {
if spot == Cents::ZERO && percentile_prices[0] == Cents::ZERO {
return StoredF32::NAN;
return BasisPoints16::ZERO;
}
let spot_f64 = f64::from(spot);
@@ -27,10 +27,10 @@ pub(crate) fn compute_spot_percentile_rank(
let p5 = f64::from(percentile_prices[0]);
if spot_f64 <= p5 {
if p5 == 0.0 {
return StoredF32::from(0.0);
return BasisPoints16::ZERO;
}
// Linear extrapolation: rank = 5 * (spot / p5)
return StoredF32::from((5.0 * spot_f64 / p5).max(0.0));
// Linear extrapolation: rank = 5% * (spot / p5)
return BasisPoints16::from((0.05 * spot_f64 / p5).max(0.0));
}
// Above highest percentile (p95) - extrapolate towards 100
@@ -38,11 +38,11 @@ pub(crate) fn compute_spot_percentile_rank(
let p90 = f64::from(percentile_prices[PERCENTILES_LEN - 2]);
if spot_f64 >= p95 {
if p95 == p90 {
return StoredF32::from(100.0);
return BasisPoints16::ONE;
}
// Linear extrapolation using p90-p95 slope
let slope = 5.0 / (p95 - p90);
return StoredF32::from((95.0 + (spot_f64 - p95) * slope).min(100.0));
let slope = 0.05 / (p95 - p90);
return BasisPoints16::from((0.95 + (spot_f64 - p95) * slope).min(1.0));
}
// Find the band containing spot and interpolate
@@ -51,20 +51,20 @@ pub(crate) fn compute_spot_percentile_rank(
let upper = f64::from(percentile_prices[i + 1]);
if spot_f64 >= lower && spot_f64 <= upper {
let lower_pct = f64::from(PERCENTILES[i]);
let upper_pct = f64::from(PERCENTILES[i + 1]);
let lower_pct = f64::from(PERCENTILES[i]) / 100.0;
let upper_pct = f64::from(PERCENTILES[i + 1]) / 100.0;
if upper == lower {
return StoredF32::from(lower_pct);
return BasisPoints16::from(lower_pct);
}
// Linear interpolation
let ratio = (spot_f64 - lower) / (upper - lower);
return StoredF32::from(lower_pct + ratio * (upper_pct - lower_pct));
return BasisPoints16::from(lower_pct + ratio * (upper_pct - lower_pct));
}
}
StoredF32::NAN
BasisPoints16::ZERO
}
pub struct PercentilesVecs<M: StorageMode = Rw> {
@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Cents, Height, StoredF32, Version};
use brk_types::{BasisPoints32, Cents, Height, StoredF32, Version};
use vecdb::{AnyStoredVec, AnyVec, Database, EagerVec, Exit, PcoVec, ReadableVec, Rw, StorageMode, VecIndex, WritableVec};
use crate::{
@@ -8,18 +8,18 @@ use crate::{
internal::{ComputedFromHeightStdDevExtended, Price, TDigest},
};
use super::super::ComputedFromHeight;
use super::{ComputedFromHeightRatio, super::ComputedFromHeight};
#[derive(Traversable)]
pub struct ComputedFromHeightRatioExtension<M: StorageMode = Rw> {
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>,
pub ratio_pct5: ComputedFromHeight<StoredF32, M>,
pub ratio_pct2: ComputedFromHeight<StoredF32, M>,
pub ratio_pct1: ComputedFromHeight<StoredF32, M>,
pub ratio_sma_1w: ComputedFromHeightRatio<M>,
pub ratio_sma_1m: ComputedFromHeightRatio<M>,
pub ratio_pct99: ComputedFromHeightRatio<M>,
pub ratio_pct98: ComputedFromHeightRatio<M>,
pub ratio_pct95: ComputedFromHeightRatio<M>,
pub ratio_pct5: ComputedFromHeightRatio<M>,
pub ratio_pct2: ComputedFromHeightRatio<M>,
pub ratio_pct1: ComputedFromHeightRatio<M>,
pub ratio_pct99_price: Price<ComputedFromHeight<Cents, M>>,
pub ratio_pct98_price: Price<ComputedFromHeight<Cents, M>>,
pub ratio_pct95_price: Price<ComputedFromHeight<Cents, M>>,
@@ -47,9 +47,9 @@ impl ComputedFromHeightRatioExtension {
) -> Result<Self> {
let v = version + VERSION;
macro_rules! import {
macro_rules! import_ratio {
($suffix:expr) => {
ComputedFromHeight::forced_import(
ComputedFromHeightRatio::forced_import_raw(
db,
&format!("{name}_{}", $suffix),
v,
@@ -78,18 +78,18 @@ impl ComputedFromHeightRatioExtension {
}
Ok(Self {
ratio_sma_1w: import!("ratio_sma_1w"),
ratio_sma_1m: import!("ratio_sma_1m"),
ratio_sma_1w: import_ratio!("ratio_sma_1w"),
ratio_sma_1m: import_ratio!("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"),
ratio_pct5: import!("ratio_pct5"),
ratio_pct2: import!("ratio_pct2"),
ratio_pct1: import!("ratio_pct1"),
ratio_pct99: import_ratio!("ratio_pct99"),
ratio_pct98: import_ratio!("ratio_pct98"),
ratio_pct95: import_ratio!("ratio_pct95"),
ratio_pct5: import_ratio!("ratio_pct5"),
ratio_pct2: import_ratio!("ratio_pct2"),
ratio_pct1: import_ratio!("ratio_pct1"),
ratio_pct99_price: import_price!("ratio_pct99"),
ratio_pct98_price: import_price!("ratio_pct98"),
ratio_pct95_price: import_price!("ratio_pct95"),
@@ -109,14 +109,14 @@ impl ComputedFromHeightRatioExtension {
ratio_source: &impl ReadableVec<Height, StoredF32>,
) -> Result<()> {
// SMA using lookback vecs
self.ratio_sma_1w.height.compute_rolling_average(
self.ratio_sma_1w.bps.height.compute_rolling_average(
starting_indexes.height,
&blocks.count.height_1w_ago,
ratio_source,
exit,
)?;
self.ratio_sma_1m.height.compute_rolling_average(
self.ratio_sma_1m.bps.height.compute_rolling_average(
starting_indexes.height,
&blocks.count.height_1m_ago,
ratio_source,
@@ -124,14 +124,14 @@ impl ComputedFromHeightRatioExtension {
)?;
let ratio_version = ratio_source.version();
self.mut_ratio_vecs()
self.mut_pct_vecs()
.try_for_each(|v| -> Result<()> {
v.validate_computed_version_or_reset(ratio_version)?;
Ok(())
})?;
let starting_height = self
.mut_ratio_vecs()
.mut_pct_vecs()
.map(|v| Height::from(v.len()))
.min()
.unwrap()
@@ -154,13 +154,13 @@ impl ComputedFromHeightRatioExtension {
// Process new blocks [start, ratio_len)
let new_ratios = ratio_source.collect_range_at(start, ratio_len);
let mut pct_vecs: [&mut EagerVec<PcoVec<Height, StoredF32>>; 6] = [
&mut self.ratio_pct1.height,
&mut self.ratio_pct2.height,
&mut self.ratio_pct5.height,
&mut self.ratio_pct95.height,
&mut self.ratio_pct98.height,
&mut self.ratio_pct99.height,
let mut pct_vecs: [&mut EagerVec<PcoVec<Height, BasisPoints32>>; 6] = [
&mut self.ratio_pct1.bps.height,
&mut self.ratio_pct2.bps.height,
&mut self.ratio_pct5.bps.height,
&mut self.ratio_pct95.bps.height,
&mut self.ratio_pct98.bps.height,
&mut self.ratio_pct99.bps.height,
];
const PCTS: [f64; 6] = [0.01, 0.02, 0.05, 0.95, 0.98, 0.99];
let mut out = [0.0f64; 6];
@@ -170,14 +170,14 @@ impl ComputedFromHeightRatioExtension {
self.tdigest.quantiles(&PCTS, &mut out);
let idx = start + offset;
for (vec, &val) in pct_vecs.iter_mut().zip(out.iter()) {
vec.truncate_push_at(idx, StoredF32::from(val as f32))?;
vec.truncate_push_at(idx, BasisPoints32::from(val))?;
}
}
}
{
let _lock = exit.lock();
self.mut_ratio_vecs()
self.mut_pct_vecs()
.try_for_each(|v| v.flush())?;
}
@@ -201,13 +201,13 @@ impl ComputedFromHeightRatioExtension {
metric_price: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
use crate::internal::PriceTimesRatioCents;
use crate::internal::PriceTimesRatioBp32Cents;
macro_rules! compute_band {
($usd_field:ident, $band_source:expr) => {
self.$usd_field
.cents
.compute_binary::<Cents, StoredF32, PriceTimesRatioCents>(
.compute_binary::<Cents, BasisPoints32, PriceTimesRatioBp32Cents>(
starting_indexes.height,
metric_price,
$band_source,
@@ -216,12 +216,12 @@ impl ComputedFromHeightRatioExtension {
};
}
compute_band!(ratio_pct99_price, &self.ratio_pct99.height);
compute_band!(ratio_pct98_price, &self.ratio_pct98.height);
compute_band!(ratio_pct95_price, &self.ratio_pct95.height);
compute_band!(ratio_pct5_price, &self.ratio_pct5.height);
compute_band!(ratio_pct2_price, &self.ratio_pct2.height);
compute_band!(ratio_pct1_price, &self.ratio_pct1.height);
compute_band!(ratio_pct99_price, &self.ratio_pct99.bps.height);
compute_band!(ratio_pct98_price, &self.ratio_pct98.bps.height);
compute_band!(ratio_pct95_price, &self.ratio_pct95.bps.height);
compute_band!(ratio_pct5_price, &self.ratio_pct5.bps.height);
compute_band!(ratio_pct2_price, &self.ratio_pct2.bps.height);
compute_band!(ratio_pct1_price, &self.ratio_pct1.bps.height);
// Stddev cents bands
self.ratio_sd
@@ -236,16 +236,16 @@ impl ComputedFromHeightRatioExtension {
Ok(())
}
fn mut_ratio_vecs(
fn mut_pct_vecs(
&mut self,
) -> impl Iterator<Item = &mut EagerVec<PcoVec<Height, StoredF32>>> {
) -> impl Iterator<Item = &mut EagerVec<PcoVec<Height, BasisPoints32>>> {
[
&mut self.ratio_pct1.height,
&mut self.ratio_pct2.height,
&mut self.ratio_pct5.height,
&mut self.ratio_pct95.height,
&mut self.ratio_pct98.height,
&mut self.ratio_pct99.height,
&mut self.ratio_pct1.bps.height,
&mut self.ratio_pct2.bps.height,
&mut self.ratio_pct5.bps.height,
&mut self.ratio_pct95.bps.height,
&mut self.ratio_pct98.bps.height,
&mut self.ratio_pct99.bps.height,
]
.into_iter()
}
@@ -8,16 +8,17 @@ pub use price_extended::*;
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Cents, Height, StoredF32, Version};
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
use brk_types::{BasisPoints32, Cents, Height, StoredF32, Version};
use vecdb::{Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
use crate::{ComputeIndexes, indexes};
use crate::{ComputeIndexes, indexes, internal::Bp32ToFloat};
use super::ComputedFromHeight;
use super::{ComputedFromHeight, LazyFromHeight};
#[derive(Traversable)]
pub struct ComputedFromHeightRatio<M: StorageMode = Rw> {
pub ratio: ComputedFromHeight<StoredF32, M>,
pub bps: ComputedFromHeight<BasisPoints32, M>,
pub ratio: LazyFromHeight<StoredF32, BasisPoints32>,
}
const VERSION: Version = Version::TWO;
@@ -28,12 +29,28 @@ impl ComputedFromHeightRatio {
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Self::forced_import_raw(db, &format!("{name}_ratio"), version, indexes)
}
pub(crate) fn forced_import_raw(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
Ok(Self {
ratio: ComputedFromHeight::forced_import(db, &format!("{name}_ratio"), v, indexes)?,
})
let bps = ComputedFromHeight::forced_import(db, &format!("{name}_bps"), v, indexes)?;
let ratio = LazyFromHeight::from_computed::<Bp32ToFloat>(
name,
v,
bps.height.read_only_boxed_clone(),
&bps,
);
Ok(Self { bps, ratio })
}
/// Compute ratio = close_price / metric_price at height level (both in cents)
@@ -44,15 +61,15 @@ impl ComputedFromHeightRatio {
metric_price: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.ratio.height.compute_transform2(
self.bps.height.compute_transform2(
starting_indexes.height,
close_price,
metric_price,
|(i, close, price, ..)| {
if price == Cents::ZERO {
(i, StoredF32::from(1.0))
(i, BasisPoints32::from(1.0))
} else {
(i, StoredF32::from(f64::from(close) / f64::from(price)))
(i, BasisPoints32::from(f64::from(close) / f64::from(price)))
}
},
exit,