computer: snapshot

This commit is contained in:
nym21
2026-03-09 12:13:33 +01:00
parent 0da380a55b
commit e4bd11317a
6 changed files with 259 additions and 255 deletions

View File

@@ -0,0 +1,106 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Cents, Dollars, Height, Sats, Version};
use vecdb::{AnyVec, Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
use crate::{
indexes,
internal::{
CentsUnsignedToDollars, ComputedFromHeight, LazyFromHeight, SatsToBitcoin, SatsToCents,
Windows,
},
prices,
};
#[derive(Traversable)]
pub struct AmountFromHeight<M: StorageMode = Rw> {
pub sats: ComputedFromHeight<Sats, M>,
pub btc: LazyFromHeight<Bitcoin, Sats>,
pub cents: ComputedFromHeight<Cents, M>,
pub usd: LazyFromHeight<Dollars, Cents>,
}
impl AmountFromHeight {
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let sats =
ComputedFromHeight::forced_import(db, &format!("{name}_sats"), version, indexes)?;
let btc = LazyFromHeight::from_computed::<SatsToBitcoin>(
name,
version,
sats.height.read_only_boxed_clone(),
&sats,
);
let cents =
ComputedFromHeight::forced_import(db, &format!("{name}_cents"), version, indexes)?;
let usd = LazyFromHeight::from_computed::<CentsUnsignedToDollars>(
&format!("{name}_usd"),
version,
cents.height.read_only_boxed_clone(),
&cents,
);
Ok(Self {
sats,
btc,
cents,
usd,
})
}
pub(crate) fn min_stateful_len(&self) -> usize {
self.sats.height.len()
}
pub(crate) fn compute(
&mut self,
prices: &prices::Vecs,
max_from: Height,
exit: &Exit,
) -> Result<()> {
self.cents.compute_binary::<Sats, Cents, SatsToCents>(
max_from,
&self.sats.height,
&prices.price.cents.height,
exit,
)?;
Ok(())
}
pub(crate) fn compute_rolling_sum(
&mut self,
max_from: Height,
window_starts: &impl ReadableVec<Height, Height>,
sats_source: &impl ReadableVec<Height, Sats>,
cents_source: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.sats
.height
.compute_rolling_sum(max_from, window_starts, sats_source, exit)?;
self.cents
.height
.compute_rolling_sum(max_from, window_starts, cents_source, exit)?;
Ok(())
}
}
impl Windows<AmountFromHeight> {
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Windows::try_from_fn(|suffix| {
AmountFromHeight::forced_import(db, &format!("{name}_{suffix}"), version, indexes)
})
}
}

View File

@@ -1,3 +1,4 @@
mod base;
mod cumulative;
mod cumulative_sum;
mod full;
@@ -8,119 +9,13 @@ mod rolling_full;
mod rolling_sum;
mod windows;
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Cents, Dollars, Height, Sats, Version};
use vecdb::{AnyVec, Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
use crate::{
indexes,
internal::{
CentsUnsignedToDollars, ComputedFromHeight, LazyFromHeight, SatsToBitcoin, SatsToCents,
Windows,
},
prices,
};
pub use base::*;
pub use cumulative::*;
pub use cumulative_sum::*;
pub use full::*;
pub use lazy::*;
pub use lazy_derived::*;
pub use rolling::*;
pub use rolling_full::*;
pub use rolling_sum::*;
pub use lazy_derived::*;
pub use windows::*;
#[derive(Traversable)]
pub struct AmountFromHeight<M: StorageMode = Rw> {
pub sats: ComputedFromHeight<Sats, M>,
pub btc: LazyFromHeight<Bitcoin, Sats>,
pub cents: ComputedFromHeight<Cents, M>,
pub usd: LazyFromHeight<Dollars, Cents>,
}
impl AmountFromHeight {
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let sats =
ComputedFromHeight::forced_import(db, &format!("{name}_sats"), version, indexes)?;
let btc = LazyFromHeight::from_computed::<SatsToBitcoin>(
name,
version,
sats.height.read_only_boxed_clone(),
&sats,
);
let cents =
ComputedFromHeight::forced_import(db, &format!("{name}_cents"), version, indexes)?;
let usd = LazyFromHeight::from_computed::<CentsUnsignedToDollars>(
&format!("{name}_usd"),
version,
cents.height.read_only_boxed_clone(),
&cents,
);
Ok(Self {
sats,
btc,
cents,
usd,
})
}
pub(crate) fn min_stateful_len(&self) -> usize {
self.sats.height.len()
}
pub(crate) fn compute(
&mut self,
prices: &prices::Vecs,
max_from: Height,
exit: &Exit,
) -> Result<()> {
self.cents.compute_binary::<Sats, Cents, SatsToCents>(
max_from,
&self.sats.height,
&prices.price.cents.height,
exit,
)?;
Ok(())
}
pub(crate) fn compute_rolling_sum(
&mut self,
max_from: Height,
window_starts: &impl ReadableVec<Height, Height>,
sats_source: &impl ReadableVec<Height, Sats>,
cents_source: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.sats
.height
.compute_rolling_sum(max_from, window_starts, sats_source, exit)?;
self.cents
.height
.compute_rolling_sum(max_from, window_starts, cents_source, exit)?;
Ok(())
}
}
impl Windows<AmountFromHeight> {
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Windows::try_from_fn(|suffix| {
AmountFromHeight::forced_import(db, &format!("{name}_{suffix}"), version, indexes)
})
}
}

View File

@@ -0,0 +1,71 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{BasisPoints32, Cents, Height, Indexes, StoredF32, Version};
use vecdb::{Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
use crate::{
indexes,
internal::{Bp32ToFloat, ComputedFromHeight, LazyFromHeight},
};
#[derive(Traversable)]
pub struct ComputedFromHeightRatio<M: StorageMode = Rw> {
pub bps: ComputedFromHeight<BasisPoints32, M>,
pub ratio: LazyFromHeight<StoredF32, BasisPoints32>,
}
const VERSION: Version = Version::TWO;
impl ComputedFromHeightRatio {
pub(crate) fn forced_import(
db: &Database,
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;
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 })
}
pub(crate) fn compute_ratio(
&mut self,
starting_indexes: &Indexes,
close_price: &impl ReadableVec<Height, Cents>,
metric_price: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.bps.height.compute_transform2(
starting_indexes.height,
close_price,
metric_price,
|(i, close, price, ..)| {
if price == Cents::ZERO {
(i, BasisPoints32::from(1.0))
} else {
(i, BasisPoints32::from(f64::from(close) / f64::from(price)))
}
},
exit,
)?;
Ok(())
}
}

View File

@@ -1,80 +1,11 @@
mod base;
mod extended;
mod percentiles;
mod price_extended;
mod std_dev_bands;
pub use base::*;
pub use extended::*;
pub use percentiles::*;
pub use price_extended::*;
pub use std_dev_bands::*;
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{BasisPoints32, Cents, Height, Indexes, StoredF32, Version};
use vecdb::{Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
use crate::{indexes, internal::Bp32ToFloat};
use super::{ComputedFromHeight, LazyFromHeight};
#[derive(Traversable)]
pub struct ComputedFromHeightRatio<M: StorageMode = Rw> {
pub bps: ComputedFromHeight<BasisPoints32, M>,
pub ratio: LazyFromHeight<StoredF32, BasisPoints32>,
}
const VERSION: Version = Version::TWO;
impl ComputedFromHeightRatio {
pub(crate) fn forced_import(
db: &Database,
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;
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 })
}
pub(crate) fn compute_ratio(
&mut self,
starting_indexes: &Indexes,
close_price: &impl ReadableVec<Height, Cents>,
metric_price: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.bps.height.compute_transform2(
starting_indexes.height,
close_price,
metric_price,
|(i, close, price, ..)| {
if price == Cents::ZERO {
(i, BasisPoints32::from(1.0))
} else {
(i, BasisPoints32::from(f64::from(close) / f64::from(price)))
}
},
exit,
)?;
Ok(())
}
}

View File

@@ -0,0 +1,75 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Indexes, StoredF32, Version};
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
use crate::{blocks, indexes, internal::ComputedFromHeight};
use super::period_suffix;
#[derive(Traversable)]
pub struct ComputedFromHeightStdDev<M: StorageMode = Rw> {
days: usize,
pub sma: ComputedFromHeight<StoredF32, M>,
pub sd: ComputedFromHeight<StoredF32, M>,
}
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{p}"), version, indexes)?;
let sd = ComputedFromHeight::forced_import(db, &format!("{name}_sd{p}"), version, indexes)?;
Ok(Self { days, sma, sd })
}
pub(crate) fn compute_all(
&mut self,
blocks: &blocks::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
source: &impl ReadableVec<Height, StoredF32>,
) -> Result<()> {
if self.days == usize::MAX {
self.sma
.height
.compute_sma_(starting_indexes.height, source, usize::MAX, exit, None)?;
self.sd.height.compute_expanding_sd(
starting_indexes.height,
source,
&self.sma.height,
exit,
)?;
return Ok(());
}
let window_starts = blocks.lookback.start_vec(self.days);
self.sma.height.compute_rolling_average(
starting_indexes.height,
window_starts,
source,
exit,
)?;
self.sd.height.compute_rolling_sd(
starting_indexes.height,
window_starts,
source,
&self.sma.height,
exit,
)?;
Ok(())
}
}

View File

@@ -1,16 +1,9 @@
mod base;
mod extended;
pub use base::*;
pub use extended::*;
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Indexes, StoredF32, Version};
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
use crate::{blocks, indexes};
use crate::internal::ComputedFromHeight;
fn period_suffix(period: &str) -> String {
if period.is_empty() {
String::new()
@@ -18,70 +11,3 @@ fn period_suffix(period: &str) -> String {
format!("_{period}")
}
}
#[derive(Traversable)]
pub struct ComputedFromHeightStdDev<M: StorageMode = Rw> {
days: usize,
pub sma: ComputedFromHeight<StoredF32, M>,
pub sd: ComputedFromHeight<StoredF32, M>,
}
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{p}"), version, indexes)?;
let sd = ComputedFromHeight::forced_import(db, &format!("{name}_sd{p}"), version, indexes)?;
Ok(Self { days, sma, sd })
}
pub(crate) fn compute_all(
&mut self,
blocks: &blocks::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
source: &impl ReadableVec<Height, StoredF32>,
) -> Result<()> {
if self.days == usize::MAX {
self.sma
.height
.compute_sma_(starting_indexes.height, source, usize::MAX, exit, None)?;
self.sd.height.compute_expanding_sd(
starting_indexes.height,
source,
&self.sma.height,
exit,
)?;
return Ok(());
}
let window_starts = blocks.lookback.start_vec(self.days);
self.sma.height.compute_rolling_average(
starting_indexes.height,
window_starts,
source,
exit,
)?;
self.sd.height.compute_rolling_sd(
starting_indexes.height,
window_starts,
source,
&self.sma.height,
exit,
)?;
Ok(())
}
}