mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-13 20:18:12 -07:00
global: snapshot
This commit is contained in:
+21
-6
@@ -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,
|
||||
)?;
|
||||
|
||||
Reference in New Issue
Block a user