mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
computer: snapshot
This commit is contained in:
106
crates/brk_computer/src/internal/from_height/amount/base.rs
Normal file
106
crates/brk_computer/src/internal/from_height/amount/base.rs
Normal 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(),
|
||||
¢s,
|
||||
);
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
¢s,
|
||||
);
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
71
crates/brk_computer/src/internal/from_height/ratio/base.rs
Normal file
71
crates/brk_computer/src/internal/from_height/ratio/base.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
75
crates/brk_computer/src/internal/from_height/stddev/base.rs
Normal file
75
crates/brk_computer/src/internal/from_height/stddev/base.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user