mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-12 19:48:15 -07:00
global: snapshot
This commit is contained in:
@@ -106,19 +106,19 @@ where
|
||||
&mut *p75_out,
|
||||
&mut *p90_out,
|
||||
] {
|
||||
v.checked_push_at(i, zero)?;
|
||||
v.truncate_push_at(i, zero)?;
|
||||
}
|
||||
} else {
|
||||
average_out.checked_push_at(i, T::from(window.average()))?;
|
||||
min_out.checked_push_at(i, T::from(window.min()))?;
|
||||
max_out.checked_push_at(i, T::from(window.max()))?;
|
||||
average_out.truncate_push_at(i, T::from(window.average()))?;
|
||||
min_out.truncate_push_at(i, T::from(window.min()))?;
|
||||
max_out.truncate_push_at(i, T::from(window.max()))?;
|
||||
let [p10, p25, p50, p75, p90] =
|
||||
window.percentiles(&[0.10, 0.25, 0.50, 0.75, 0.90]);
|
||||
p10_out.checked_push_at(i, T::from(p10))?;
|
||||
p25_out.checked_push_at(i, T::from(p25))?;
|
||||
median_out.checked_push_at(i, T::from(p50))?;
|
||||
p75_out.checked_push_at(i, T::from(p75))?;
|
||||
p90_out.checked_push_at(i, T::from(p90))?;
|
||||
p10_out.truncate_push_at(i, T::from(p10))?;
|
||||
p25_out.truncate_push_at(i, T::from(p25))?;
|
||||
median_out.truncate_push_at(i, T::from(p50))?;
|
||||
p75_out.truncate_push_at(i, T::from(p75))?;
|
||||
p90_out.truncate_push_at(i, T::from(p90))?;
|
||||
}
|
||||
|
||||
if average_out.batch_limit_reached() {
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
mod distribution_stats;
|
||||
mod per_resolution;
|
||||
mod window_24h;
|
||||
mod windows;
|
||||
mod windows_except_1m;
|
||||
mod windows_from_1w;
|
||||
|
||||
pub use distribution_stats::*;
|
||||
pub use per_resolution::*;
|
||||
pub use window_24h::*;
|
||||
pub use windows::*;
|
||||
pub use windows_except_1m::*;
|
||||
pub use windows_from_1w::*;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use brk_traversable::Traversable;
|
||||
|
||||
/// Generic single-24h-window container.
|
||||
#[derive(Traversable)]
|
||||
pub struct RollingWindow24h<Inner> {
|
||||
pub _24h: Inner,
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
use brk_traversable::Traversable;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct WindowsExcept1m<A> {
|
||||
pub _24h: A,
|
||||
pub _1w: A,
|
||||
pub _1y: A,
|
||||
}
|
||||
|
||||
impl<A> WindowsExcept1m<A> {
|
||||
pub const SUFFIXES: [&'static str; 3] = ["24h", "1w", "1y"];
|
||||
|
||||
pub fn try_from_fn<E>(
|
||||
mut f: impl FnMut(&str) -> std::result::Result<A, E>,
|
||||
) -> std::result::Result<Self, E> {
|
||||
Ok(Self {
|
||||
_24h: f(Self::SUFFIXES[0])?,
|
||||
_1w: f(Self::SUFFIXES[1])?,
|
||||
_1y: f(Self::SUFFIXES[2])?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_array(&self) -> [&A; 3] {
|
||||
[&self._24h, &self._1w, &self._1y]
|
||||
}
|
||||
|
||||
pub fn as_mut_array(&mut self) -> [&mut A; 3] {
|
||||
[&mut self._24h, &mut self._1w, &mut self._1y]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
use brk_traversable::Traversable;
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct WindowsFrom1w<A> {
|
||||
pub _1w: A,
|
||||
pub _1m: A,
|
||||
pub _1y: A,
|
||||
}
|
||||
|
||||
impl<A> WindowsFrom1w<A> {
|
||||
pub const SUFFIXES: [&'static str; 3] = ["1w", "1m", "1y"];
|
||||
|
||||
pub fn try_from_fn<E>(
|
||||
mut f: impl FnMut(&str) -> std::result::Result<A, E>,
|
||||
) -> std::result::Result<Self, E> {
|
||||
Ok(Self {
|
||||
_1w: f(Self::SUFFIXES[0])?,
|
||||
_1m: f(Self::SUFFIXES[1])?,
|
||||
_1y: f(Self::SUFFIXES[2])?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_array(&self) -> [&A; 3] {
|
||||
[&self._1w, &self._1m, &self._1y]
|
||||
}
|
||||
|
||||
pub fn as_mut_array(&mut self) -> [&mut A; 3] {
|
||||
[&mut self._1w, &mut self._1m, &mut self._1y]
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ mod rolling;
|
||||
mod rolling_full;
|
||||
mod rolling_sum;
|
||||
mod windows;
|
||||
mod with_sum_24h;
|
||||
|
||||
pub use base::*;
|
||||
pub use cumulative::*;
|
||||
@@ -19,3 +20,4 @@ pub use rolling::*;
|
||||
pub use rolling_full::*;
|
||||
pub use rolling_sum::*;
|
||||
pub use windows::*;
|
||||
pub use with_sum_24h::*;
|
||||
|
||||
@@ -6,9 +6,43 @@ use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{AmountPerBlock, WindowStarts, Windows},
|
||||
internal::{AmountPerBlock, RollingWindow24h, WindowStarts, Windows},
|
||||
};
|
||||
|
||||
/// Single 24h rolling sum as amount (sats + btc + cents + usd).
|
||||
///
|
||||
/// Tree: `_24h.sats.height`, `_24h.btc.height`, etc.
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct RollingWindow24hAmountPerBlock<M: StorageMode = Rw>(
|
||||
pub RollingWindow24h<AmountPerBlock<M>>,
|
||||
);
|
||||
|
||||
impl RollingWindow24hAmountPerBlock {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self(RollingWindow24h {
|
||||
_24h: AmountPerBlock::forced_import(db, &format!("{name}_24h"), version, indexes)?,
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rolling_sum(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
height_24h_ago: &impl ReadableVec<Height, Height>,
|
||||
sats_source: &impl ReadableVec<Height, Sats>,
|
||||
cents_source: &impl ReadableVec<Height, Cents>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self._24h
|
||||
.compute_rolling_sum(max_from, height_24h_ago, sats_source, cents_source, exit)
|
||||
}
|
||||
}
|
||||
|
||||
/// Rolling sum only, window-first then unit.
|
||||
///
|
||||
/// Tree: `_24h.sats.height`, `_24h.btc.height`, etc.
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
//! AmountPerBlockWithSum24h - AmountPerBlock raw + RollingWindow24hAmountPerBlock sum.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{AmountPerBlock, RollingWindow24hAmountPerBlock};
|
||||
|
||||
/// Amount per-block value (sats + cents) with 24h rolling sum (also amount).
|
||||
#[derive(Traversable)]
|
||||
pub struct AmountPerBlockWithSum24h<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub raw: AmountPerBlock<M>,
|
||||
pub sum: RollingWindow24hAmountPerBlock<M>,
|
||||
}
|
||||
@@ -19,7 +19,7 @@ use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
ComputedPerBlock, NumericValue, PercentPerBlock, PercentRollingWindows,
|
||||
RollingWindows, WindowStarts,
|
||||
RollingWindows, WindowStarts, WindowsExcept1m,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -168,7 +168,9 @@ where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: NumericValue + JsonSchema,
|
||||
{
|
||||
#[traversable(wrap = "change", rename = "1m")]
|
||||
pub change_1m: ComputedPerBlock<C, M>,
|
||||
#[traversable(wrap = "rate", rename = "1m")]
|
||||
pub rate_1m: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
@@ -227,14 +229,8 @@ where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: NumericValue + JsonSchema,
|
||||
{
|
||||
#[traversable(rename = "24h")]
|
||||
pub change_24h: ComputedPerBlock<C, M>,
|
||||
pub change_1w: ComputedPerBlock<C, M>,
|
||||
pub change_1y: ComputedPerBlock<C, M>,
|
||||
#[traversable(rename = "24h")]
|
||||
pub rate_24h: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
pub rate_1w: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
pub rate_1y: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
pub change: WindowsExcept1m<ComputedPerBlock<C, M>>,
|
||||
pub rate: WindowsExcept1m<PercentPerBlock<BasisPointsSigned32, M>>,
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
|
||||
@@ -250,42 +246,22 @@ where
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
change_24h: ComputedPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1w: ComputedPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1y: ComputedPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_24h: PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_1w: PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_1y: PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change: WindowsExcept1m::try_from_fn(|suffix| {
|
||||
ComputedPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_{suffix}"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?,
|
||||
rate: WindowsExcept1m::try_from_fn(|suffix| {
|
||||
PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_{suffix}"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?,
|
||||
_phantom: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
@@ -297,8 +273,8 @@ where
|
||||
source: &impl ReadableVec<Height, S>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let changes = [&mut self.change_24h, &mut self.change_1w, &mut self.change_1y];
|
||||
let rates = [&mut self.rate_24h, &mut self.rate_1w, &mut self.rate_1y];
|
||||
let changes = self.change.as_mut_array();
|
||||
let rates = self.rate.as_mut_array();
|
||||
let starts = [windows._24h, windows._1w, windows._1y];
|
||||
|
||||
for ((change_w, rate_w), starts) in changes.into_iter().zip(rates).zip(starts) {
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
CentsType, FiatPerBlock, NumericValue, PercentPerBlock, PercentRollingWindows,
|
||||
WindowStarts,
|
||||
Windows, WindowStarts, WindowsExcept1m,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -24,7 +24,9 @@ where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
#[traversable(wrap = "change", rename = "1m")]
|
||||
pub change_1m: FiatPerBlock<C, M>,
|
||||
#[traversable(wrap = "rate", rename = "1m")]
|
||||
pub rate_1m: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
@@ -82,14 +84,8 @@ where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
#[traversable(rename = "24h")]
|
||||
pub change_24h: FiatPerBlock<C, M>,
|
||||
pub change_1w: FiatPerBlock<C, M>,
|
||||
pub change_1y: FiatPerBlock<C, M>,
|
||||
#[traversable(rename = "24h")]
|
||||
pub rate_24h: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
pub rate_1w: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
pub rate_1y: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
pub change: WindowsExcept1m<FiatPerBlock<C, M>>,
|
||||
pub rate: WindowsExcept1m<PercentPerBlock<BasisPointsSigned32, M>>,
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
|
||||
@@ -105,42 +101,22 @@ where
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
change_24h: FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1w: FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1y: FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_24h: PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_1w: PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
rate_1y: PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change: WindowsExcept1m::try_from_fn(|suffix| {
|
||||
FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_{suffix}"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?,
|
||||
rate: WindowsExcept1m::try_from_fn(|suffix| {
|
||||
PercentPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate_{suffix}"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?,
|
||||
_phantom: std::marker::PhantomData,
|
||||
})
|
||||
}
|
||||
@@ -152,12 +128,8 @@ where
|
||||
source: &impl ReadableVec<Height, S>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let changes: [&mut FiatPerBlock<C>; 3] = [
|
||||
&mut self.change_24h,
|
||||
&mut self.change_1w,
|
||||
&mut self.change_1y,
|
||||
];
|
||||
let rates = [&mut self.rate_24h, &mut self.rate_1w, &mut self.rate_1y];
|
||||
let changes = self.change.as_mut_array();
|
||||
let rates = self.rate.as_mut_array();
|
||||
let starts = [windows._24h, windows._1w, windows._1y];
|
||||
|
||||
for ((change_w, rate_w), starts) in changes.into_iter().zip(rates).zip(starts) {
|
||||
@@ -181,10 +153,7 @@ where
|
||||
S: NumericValue + JsonSchema,
|
||||
C: CentsType,
|
||||
{
|
||||
pub change_24h: FiatPerBlock<C, M>,
|
||||
pub change_1w: FiatPerBlock<C, M>,
|
||||
pub change_1m: FiatPerBlock<C, M>,
|
||||
pub change_1y: FiatPerBlock<C, M>,
|
||||
pub change: Windows<FiatPerBlock<C, M>>,
|
||||
pub rate: PercentRollingWindows<BasisPointsSigned32, M>,
|
||||
_phantom: std::marker::PhantomData<S>,
|
||||
}
|
||||
@@ -201,30 +170,14 @@ where
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
change_24h: FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1w: FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1m: FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1m"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change_1y: FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
change: Windows::try_from_fn(|suffix| {
|
||||
FiatPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_change_{suffix}"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?,
|
||||
rate: PercentRollingWindows::forced_import(
|
||||
db,
|
||||
&format!("{name}_rate"),
|
||||
@@ -242,12 +195,7 @@ where
|
||||
source: &impl ReadableVec<Height, S>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let changes: [&mut FiatPerBlock<C>; 4] = [
|
||||
&mut self.change_24h,
|
||||
&mut self.change_1w,
|
||||
&mut self.change_1m,
|
||||
&mut self.change_1y,
|
||||
];
|
||||
let changes = self.change.as_mut_array();
|
||||
let rates = self.rate.0.as_mut_array();
|
||||
let starts = windows.as_array();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ mod fiat_delta;
|
||||
mod full;
|
||||
mod rolling_average;
|
||||
mod sum;
|
||||
mod with_sum_24h;
|
||||
|
||||
pub use aggregated::*;
|
||||
pub use base::*;
|
||||
@@ -23,3 +24,4 @@ pub use fiat_delta::*;
|
||||
pub use full::*;
|
||||
pub use rolling_average::*;
|
||||
pub use sum::*;
|
||||
pub use with_sum_24h::*;
|
||||
|
||||
@@ -90,12 +90,7 @@ where
|
||||
break;
|
||||
}
|
||||
let target = S1I::max_from(I::from(i), source_len);
|
||||
if cursor.position() <= target {
|
||||
cursor.advance(target - cursor.position());
|
||||
if let Some(v) = cursor.next() {
|
||||
f(v);
|
||||
}
|
||||
} else if let Some(v) = source.collect_one_at(target) {
|
||||
if let Some(v) = cursor.get(target) {
|
||||
f(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//! PerBlockWithSum24h - ComputedPerBlock + RollingWindow24hPerBlock rolling sum.
|
||||
//!
|
||||
//! Generic building block for metrics that store a per-block value
|
||||
//! plus its 24h rolling sum. Used across activity and realized metrics.
|
||||
|
||||
use brk_traversable::Traversable;
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Rw, StorageMode};
|
||||
|
||||
use crate::internal::{ComputedPerBlock, ComputedVecValue, RollingWindow24hPerBlock};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct PerBlockWithSum24h<T, M: StorageMode = Rw>
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub raw: ComputedPerBlock<T, M>,
|
||||
pub sum: RollingWindow24hPerBlock<T, M>,
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
mod base;
|
||||
mod lazy;
|
||||
mod with_sum_24h;
|
||||
|
||||
pub use base::*;
|
||||
pub use lazy::*;
|
||||
pub use with_sum_24h::*;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
//! FiatPerBlockWithSum24h - FiatPerBlock raw + RollingWindow24hFiatPerBlock sum.
|
||||
|
||||
use std::ops::SubAssign;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{CentsType, FiatPerBlock, RollingWindow24h},
|
||||
};
|
||||
|
||||
/// Single 24h rolling window backed by FiatPerBlock (cents + lazy usd).
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct RollingWindow24hFiatPerBlock<C: CentsType, M: StorageMode = Rw>(
|
||||
pub RollingWindow24h<FiatPerBlock<C, M>>,
|
||||
);
|
||||
|
||||
impl<C: CentsType> RollingWindow24hFiatPerBlock<C> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self(RollingWindow24h {
|
||||
_24h: FiatPerBlock::forced_import(db, &format!("{name}_24h"), version, indexes)?,
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rolling_sum(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
height_24h_ago: &impl ReadableVec<Height, Height>,
|
||||
source: &impl ReadableVec<Height, C>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
C: Default + SubAssign,
|
||||
{
|
||||
self._24h
|
||||
.cents
|
||||
.height
|
||||
.compute_rolling_sum(max_from, height_24h_ago, source, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Fiat per-block value (cents + usd) with 24h rolling sum (also fiat).
|
||||
#[derive(Traversable)]
|
||||
pub struct FiatPerBlockWithSum24h<C: CentsType, M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub raw: FiatPerBlock<C, M>,
|
||||
pub sum: RollingWindow24hFiatPerBlock<C, M>,
|
||||
}
|
||||
@@ -5,18 +5,18 @@ use vecdb::{Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{Bp32ToFloat, ComputedPerBlock, LazyPerBlock},
|
||||
internal::{BpsType, ComputedPerBlock, LazyPerBlock},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RatioPerBlock<M: StorageMode = Rw> {
|
||||
pub bps: ComputedPerBlock<BasisPoints32, M>,
|
||||
pub ratio: LazyPerBlock<StoredF32, BasisPoints32>,
|
||||
pub struct RatioPerBlock<B: BpsType = BasisPoints32, M: StorageMode = Rw> {
|
||||
pub bps: ComputedPerBlock<B, M>,
|
||||
pub ratio: LazyPerBlock<StoredF32, B>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::TWO;
|
||||
|
||||
impl RatioPerBlock {
|
||||
impl<B: BpsType> RatioPerBlock<B> {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
@@ -36,7 +36,7 @@ impl RatioPerBlock {
|
||||
|
||||
let bps = ComputedPerBlock::forced_import(db, &format!("{name}_bps"), v, indexes)?;
|
||||
|
||||
let ratio = LazyPerBlock::from_computed::<Bp32ToFloat>(
|
||||
let ratio = LazyPerBlock::from_computed::<B::ToRatio>(
|
||||
name,
|
||||
v,
|
||||
bps.height.read_only_boxed_clone(),
|
||||
@@ -45,7 +45,9 @@ impl RatioPerBlock {
|
||||
|
||||
Ok(Self { bps, ratio })
|
||||
}
|
||||
}
|
||||
|
||||
impl RatioPerBlock<BasisPoints32> {
|
||||
pub(crate) fn compute_ratio(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, Height, Indexes, Version};
|
||||
use brk_types::{BasisPoints32, Cents, Height, Indexes, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
@@ -13,7 +13,7 @@ pub struct RatioPerBlockExtended<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: RatioPerBlock<M>,
|
||||
pub base: RatioPerBlock<BasisPoints32, M>,
|
||||
#[traversable(flatten)]
|
||||
pub percentiles: RatioPerBlockPercentiles<M>,
|
||||
}
|
||||
|
||||
@@ -13,22 +13,23 @@ use crate::{
|
||||
|
||||
use super::{super::ComputedPerBlock, RatioPerBlock};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RatioBand<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub ratio: RatioPerBlock<BasisPoints32, M>,
|
||||
pub price: Price<ComputedPerBlock<Cents, M>>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RatioPerBlockPercentiles<M: StorageMode = Rw> {
|
||||
pub ratio_sma_1w: RatioPerBlock<M>,
|
||||
pub ratio_sma_1m: RatioPerBlock<M>,
|
||||
pub ratio_pct99: RatioPerBlock<M>,
|
||||
pub ratio_pct98: RatioPerBlock<M>,
|
||||
pub ratio_pct95: RatioPerBlock<M>,
|
||||
pub ratio_pct5: RatioPerBlock<M>,
|
||||
pub ratio_pct2: RatioPerBlock<M>,
|
||||
pub ratio_pct1: RatioPerBlock<M>,
|
||||
pub ratio_pct99_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub ratio_pct98_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub ratio_pct95_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub ratio_pct5_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub ratio_pct2_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub ratio_pct1_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub sma_1w: RatioPerBlock<BasisPoints32, M>,
|
||||
pub sma_1m: RatioPerBlock<BasisPoints32, M>,
|
||||
pub pct99: RatioBand<M>,
|
||||
pub pct98: RatioBand<M>,
|
||||
pub pct95: RatioBand<M>,
|
||||
pub pct5: RatioBand<M>,
|
||||
pub pct2: RatioBand<M>,
|
||||
pub pct1: RatioBand<M>,
|
||||
|
||||
#[traversable(skip)]
|
||||
expanding_pct: ExpandingPercentiles,
|
||||
@@ -62,21 +63,24 @@ impl RatioPerBlockPercentiles {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! import_band {
|
||||
($suffix:expr) => {
|
||||
RatioBand {
|
||||
ratio: import_ratio!($suffix),
|
||||
price: import_price!($suffix),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
ratio_sma_1w: import_ratio!("ratio_sma_1w"),
|
||||
ratio_sma_1m: import_ratio!("ratio_sma_1m"),
|
||||
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"),
|
||||
ratio_pct5_price: import_price!("ratio_pct5"),
|
||||
ratio_pct2_price: import_price!("ratio_pct2"),
|
||||
ratio_pct1_price: import_price!("ratio_pct1"),
|
||||
sma_1w: import_ratio!("ratio_sma_1w"),
|
||||
sma_1m: import_ratio!("ratio_sma_1m"),
|
||||
pct99: import_band!("ratio_pct99"),
|
||||
pct98: import_band!("ratio_pct98"),
|
||||
pct95: import_band!("ratio_pct95"),
|
||||
pct5: import_band!("ratio_pct5"),
|
||||
pct2: import_band!("ratio_pct2"),
|
||||
pct1: import_band!("ratio_pct1"),
|
||||
expanding_pct: ExpandingPercentiles::default(),
|
||||
})
|
||||
}
|
||||
@@ -89,14 +93,14 @@ impl RatioPerBlockPercentiles {
|
||||
ratio_source: &impl ReadableVec<Height, StoredF32>,
|
||||
metric_price: &impl ReadableVec<Height, Cents>,
|
||||
) -> Result<()> {
|
||||
self.ratio_sma_1w.bps.height.compute_rolling_average(
|
||||
self.sma_1w.bps.height.compute_rolling_average(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback.height_1w_ago,
|
||||
ratio_source,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.ratio_sma_1m.bps.height.compute_rolling_average(
|
||||
self.sma_1m.bps.height.compute_rolling_average(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback.height_1m_ago,
|
||||
ratio_source,
|
||||
@@ -131,12 +135,12 @@ impl RatioPerBlockPercentiles {
|
||||
|
||||
let new_ratios = ratio_source.collect_range_at(start, ratio_len);
|
||||
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,
|
||||
&mut self.pct1.ratio.bps.height,
|
||||
&mut self.pct2.ratio.bps.height,
|
||||
&mut self.pct5.ratio.bps.height,
|
||||
&mut self.pct95.ratio.bps.height,
|
||||
&mut self.pct98.ratio.bps.height,
|
||||
&mut self.pct99.ratio.bps.height,
|
||||
];
|
||||
const PCTS: [f64; 6] = [0.01, 0.02, 0.05, 0.95, 0.98, 0.99];
|
||||
let mut out = [0u32; 6];
|
||||
@@ -158,24 +162,25 @@ impl RatioPerBlockPercentiles {
|
||||
|
||||
// Cents bands
|
||||
macro_rules! compute_band {
|
||||
($usd_field:ident, $band_source:expr) => {
|
||||
self.$usd_field
|
||||
($band:ident) => {
|
||||
self.$band
|
||||
.price
|
||||
.cents
|
||||
.compute_binary::<Cents, BasisPoints32, PriceTimesRatioBp32Cents>(
|
||||
starting_indexes.height,
|
||||
metric_price,
|
||||
$band_source,
|
||||
&self.$band.ratio.bps.height,
|
||||
exit,
|
||||
)?;
|
||||
};
|
||||
}
|
||||
|
||||
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);
|
||||
compute_band!(pct99);
|
||||
compute_band!(pct98);
|
||||
compute_band!(pct95);
|
||||
compute_band!(pct5);
|
||||
compute_band!(pct2);
|
||||
compute_band!(pct1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -184,12 +189,12 @@ impl RatioPerBlockPercentiles {
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = &mut EagerVec<PcoVec<Height, BasisPoints32>>> {
|
||||
[
|
||||
&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,
|
||||
&mut self.pct1.ratio.bps.height,
|
||||
&mut self.pct2.ratio.bps.height,
|
||||
&mut self.pct5.ratio.bps.height,
|
||||
&mut self.pct95.ratio.bps.height,
|
||||
&mut self.pct98.ratio.bps.height,
|
||||
&mut self.pct99.ratio.bps.height,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, Height, Indexes, Version};
|
||||
use brk_types::{BasisPoints32, Cents, Height, Indexes, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode};
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct PriceWithRatioPerBlock<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub inner: RatioPerBlock<M>,
|
||||
pub inner: RatioPerBlock<BasisPoints32, M>,
|
||||
pub price: Price<ComputedPerBlock<Cents, M>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ use crate::{blocks, indexes, internal::StdDevPerBlockExtended};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RatioPerBlockStdDevBands<M: StorageMode = Rw> {
|
||||
pub ratio_sd: StdDevPerBlockExtended<M>,
|
||||
pub ratio_sd_4y: StdDevPerBlockExtended<M>,
|
||||
pub ratio_sd_2y: StdDevPerBlockExtended<M>,
|
||||
pub ratio_sd_1y: StdDevPerBlockExtended<M>,
|
||||
pub all: StdDevPerBlockExtended<M>,
|
||||
pub _4y: StdDevPerBlockExtended<M>,
|
||||
pub _2y: StdDevPerBlockExtended<M>,
|
||||
pub _1y: StdDevPerBlockExtended<M>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::new(4);
|
||||
@@ -38,10 +38,10 @@ impl RatioPerBlockStdDevBands {
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
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),
|
||||
all: import_sd!("ratio", "", usize::MAX),
|
||||
_1y: import_sd!("ratio", "1y", 365),
|
||||
_2y: import_sd!("ratio", "2y", 2 * 365),
|
||||
_4y: import_sd!("ratio", "4y", 4 * 365),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -54,10 +54,10 @@ impl RatioPerBlockStdDevBands {
|
||||
metric_price: &impl ReadableVec<Height, Cents>,
|
||||
) -> Result<()> {
|
||||
for sd in [
|
||||
&mut self.ratio_sd,
|
||||
&mut self.ratio_sd_4y,
|
||||
&mut self.ratio_sd_2y,
|
||||
&mut self.ratio_sd_1y,
|
||||
&mut self.all,
|
||||
&mut self._4y,
|
||||
&mut self._2y,
|
||||
&mut self._1y,
|
||||
] {
|
||||
sd.compute_all(blocks, starting_indexes, exit, ratio_source)?;
|
||||
sd.compute_cents_bands(starting_indexes, metric_price, exit)?;
|
||||
|
||||
@@ -15,7 +15,7 @@ use vecdb::{Database, EagerVec, Exit, PcoVec, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{ComputedPerBlock, ComputedVecValue, NumericValue, Windows},
|
||||
internal::{ComputedPerBlock, ComputedVecValue, NumericValue, RollingWindow24h, Windows, WindowsFrom1w},
|
||||
};
|
||||
|
||||
/// Rolling window start heights — the 4 height-ago vecs (24h, 1w, 1m, 1y).
|
||||
@@ -61,16 +61,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Single 24h rolling window (1 stored vec).
|
||||
#[derive(Traversable)]
|
||||
pub struct RollingWindow24h<T, M: StorageMode = Rw>
|
||||
/// Single 24h rolling window backed by ComputedPerBlock (1 stored vec).
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct RollingWindow24hPerBlock<T, M: StorageMode = Rw>(
|
||||
pub RollingWindow24h<ComputedPerBlock<T, M>>,
|
||||
)
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub _24h: ComputedPerBlock<T, M>,
|
||||
}
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema;
|
||||
|
||||
impl<T> RollingWindow24h<T>
|
||||
impl<T> RollingWindow24hPerBlock<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
@@ -80,14 +80,14 @@ where
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
Ok(Self(RollingWindow24h {
|
||||
_24h: ComputedPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_24h"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rolling_sum(
|
||||
@@ -108,15 +108,11 @@ where
|
||||
}
|
||||
|
||||
/// Extended rolling windows: 1w + 1m + 1y (3 stored vecs).
|
||||
#[derive(Traversable)]
|
||||
pub struct RollingWindowsFrom1w<T, M: StorageMode = Rw>
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
#[traversable(transparent)]
|
||||
pub struct RollingWindowsFrom1w<T, M: StorageMode = Rw>(pub WindowsFrom1w<ComputedPerBlock<T, M>>)
|
||||
where
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema,
|
||||
{
|
||||
pub _1w: ComputedPerBlock<T, M>,
|
||||
pub _1m: ComputedPerBlock<T, M>,
|
||||
pub _1y: ComputedPerBlock<T, M>,
|
||||
}
|
||||
T: ComputedVecValue + PartialOrd + JsonSchema;
|
||||
|
||||
impl<T> RollingWindowsFrom1w<T>
|
||||
where
|
||||
@@ -128,34 +124,9 @@ where
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
_1w: ComputedPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_1w"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
_1m: ComputedPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_1m"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
_1y: ComputedPerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_1y"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_array(&self) -> [&ComputedPerBlock<T>; 3] {
|
||||
[&self._1w, &self._1m, &self._1y]
|
||||
}
|
||||
|
||||
pub fn as_mut_array(&mut self) -> [&mut ComputedPerBlock<T>; 3] {
|
||||
[&mut self._1w, &mut self._1m, &mut self._1y]
|
||||
Ok(Self(WindowsFrom1w::try_from_fn(|suffix| {
|
||||
ComputedPerBlock::forced_import(db, &format!("{name}_{suffix}"), version, indexes)
|
||||
})?))
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rolling_sum(
|
||||
@@ -168,15 +139,11 @@ where
|
||||
where
|
||||
T: Default + SubAssign,
|
||||
{
|
||||
self._1w
|
||||
.height
|
||||
.compute_rolling_sum(max_from, windows._1w, source, exit)?;
|
||||
self._1m
|
||||
.height
|
||||
.compute_rolling_sum(max_from, windows._1m, source, exit)?;
|
||||
self._1y
|
||||
.height
|
||||
.compute_rolling_sum(max_from, windows._1y, source, exit)?;
|
||||
let starts = [windows._1w, windows._1m, windows._1y];
|
||||
for (w, starts) in self.0.as_mut_array().into_iter().zip(starts) {
|
||||
w.height
|
||||
.compute_rolling_sum(max_from, starts, source, exit)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,31 @@ use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, Height, Indexes, StoredF32, Version};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Database, EagerVec, Exit, PcoVec, ReadableVec, Rw, StorageMode, VecIndex,
|
||||
WritableVec,
|
||||
AnyStoredVec, AnyVec, Database, EagerVec, Exit, Ident, PcoVec, ReadableCloneableVec,
|
||||
ReadableVec, Rw, StorageMode, VecIndex, WritableVec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
blocks, indexes,
|
||||
internal::{ComputedPerBlock, Price, PriceTimesRatioCents},
|
||||
internal::{ComputedPerBlock, LazyPerBlock, Price, PriceTimesRatioCents},
|
||||
};
|
||||
|
||||
use super::StdDevPerBlock;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct StdDevBand<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub value: ComputedPerBlock<StoredF32, M>,
|
||||
pub price: Price<ComputedPerBlock<Cents, M>>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct LazyStdDevBand<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub value: LazyPerBlock<StoredF32>,
|
||||
pub price: Price<ComputedPerBlock<Cents, M>>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct StdDevPerBlockExtended<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
@@ -20,32 +34,19 @@ pub struct StdDevPerBlockExtended<M: StorageMode = Rw> {
|
||||
|
||||
pub zscore: ComputedPerBlock<StoredF32, M>,
|
||||
|
||||
pub p0_5sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub p1sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub p1_5sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub p2sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub p2_5sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub p3sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub m0_5sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub m1sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub m1_5sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub m2sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub m2_5sd: ComputedPerBlock<StoredF32, M>,
|
||||
pub m3sd: ComputedPerBlock<StoredF32, M>,
|
||||
|
||||
pub _0sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub p0_5sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub p1sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub p1_5sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub p2sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub p2_5sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub p3sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub m0_5sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub m1sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub m1_5sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub m2sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub m2_5sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub m3sd_price: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub _0sd: LazyStdDevBand<M>,
|
||||
pub p0_5sd: StdDevBand<M>,
|
||||
pub p1sd: StdDevBand<M>,
|
||||
pub p1_5sd: StdDevBand<M>,
|
||||
pub p2sd: StdDevBand<M>,
|
||||
pub p2_5sd: StdDevBand<M>,
|
||||
pub p3sd: StdDevBand<M>,
|
||||
pub m0_5sd: StdDevBand<M>,
|
||||
pub m1sd: StdDevBand<M>,
|
||||
pub m1_5sd: StdDevBand<M>,
|
||||
pub m2sd: StdDevBand<M>,
|
||||
pub m2_5sd: StdDevBand<M>,
|
||||
pub m3sd: StdDevBand<M>,
|
||||
}
|
||||
|
||||
impl StdDevPerBlockExtended {
|
||||
@@ -77,41 +78,50 @@ impl StdDevPerBlockExtended {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! import_band {
|
||||
($suffix:expr) => {
|
||||
StdDevBand {
|
||||
value: import!($suffix),
|
||||
price: import_price!($suffix),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let base = StdDevPerBlock::forced_import(
|
||||
db,
|
||||
name,
|
||||
period,
|
||||
days,
|
||||
parent_version,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
let _0sd = LazyStdDevBand {
|
||||
value: LazyPerBlock::from_computed::<Ident>(
|
||||
&format!("{name}_0sd{p}"),
|
||||
version,
|
||||
base.sma.height.read_only_boxed_clone(),
|
||||
&base.sma,
|
||||
),
|
||||
price: import_price!("0sd"),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
base: StdDevPerBlock::forced_import(
|
||||
db,
|
||||
name,
|
||||
period,
|
||||
days,
|
||||
parent_version,
|
||||
indexes,
|
||||
)?,
|
||||
base,
|
||||
zscore: import!("zscore"),
|
||||
p0_5sd: import!("p0_5sd"),
|
||||
p1sd: import!("p1sd"),
|
||||
p1_5sd: import!("p1_5sd"),
|
||||
p2sd: import!("p2sd"),
|
||||
p2_5sd: import!("p2_5sd"),
|
||||
p3sd: import!("p3sd"),
|
||||
m0_5sd: import!("m0_5sd"),
|
||||
m1sd: import!("m1sd"),
|
||||
m1_5sd: import!("m1_5sd"),
|
||||
m2sd: import!("m2sd"),
|
||||
m2_5sd: import!("m2_5sd"),
|
||||
m3sd: import!("m3sd"),
|
||||
_0sd_price: import_price!("0sd"),
|
||||
p0_5sd_price: import_price!("p0_5sd"),
|
||||
p1sd_price: import_price!("p1sd"),
|
||||
p1_5sd_price: import_price!("p1_5sd"),
|
||||
p2sd_price: import_price!("p2sd"),
|
||||
p2_5sd_price: import_price!("p2_5sd"),
|
||||
p3sd_price: import_price!("p3sd"),
|
||||
m0_5sd_price: import_price!("m0_5sd"),
|
||||
m1sd_price: import_price!("m1sd"),
|
||||
m1_5sd_price: import_price!("m1_5sd"),
|
||||
m2sd_price: import_price!("m2sd"),
|
||||
m2_5sd_price: import_price!("m2_5sd"),
|
||||
m3sd_price: import_price!("m3sd"),
|
||||
_0sd,
|
||||
p0_5sd: import_band!("p0_5sd"),
|
||||
p1sd: import_band!("p1sd"),
|
||||
p1_5sd: import_band!("p1_5sd"),
|
||||
p2sd: import_band!("p2sd"),
|
||||
p2_5sd: import_band!("p2_5sd"),
|
||||
p3sd: import_band!("p3sd"),
|
||||
m0_5sd: import_band!("m0_5sd"),
|
||||
m1sd: import_band!("m1sd"),
|
||||
m1_5sd: import_band!("m1_5sd"),
|
||||
m2sd: import_band!("m2sd"),
|
||||
m2_5sd: import_band!("m2_5sd"),
|
||||
m3sd: import_band!("m3sd"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -214,9 +224,9 @@ impl StdDevPerBlockExtended {
|
||||
metric_price: &impl ReadableVec<Height, Cents>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
macro_rules! compute_band {
|
||||
($usd_field:ident, $band_source:expr) => {
|
||||
self.$usd_field
|
||||
macro_rules! compute_band_price {
|
||||
($price:expr, $band_source:expr) => {
|
||||
$price
|
||||
.cents
|
||||
.compute_binary::<Cents, StoredF32, PriceTimesRatioCents>(
|
||||
starting_indexes.height,
|
||||
@@ -227,19 +237,19 @@ impl StdDevPerBlockExtended {
|
||||
};
|
||||
}
|
||||
|
||||
compute_band!(_0sd_price, &self.base.sma.height);
|
||||
compute_band!(p0_5sd_price, &self.p0_5sd.height);
|
||||
compute_band!(p1sd_price, &self.p1sd.height);
|
||||
compute_band!(p1_5sd_price, &self.p1_5sd.height);
|
||||
compute_band!(p2sd_price, &self.p2sd.height);
|
||||
compute_band!(p2_5sd_price, &self.p2_5sd.height);
|
||||
compute_band!(p3sd_price, &self.p3sd.height);
|
||||
compute_band!(m0_5sd_price, &self.m0_5sd.height);
|
||||
compute_band!(m1sd_price, &self.m1sd.height);
|
||||
compute_band!(m1_5sd_price, &self.m1_5sd.height);
|
||||
compute_band!(m2sd_price, &self.m2sd.height);
|
||||
compute_band!(m2_5sd_price, &self.m2_5sd.height);
|
||||
compute_band!(m3sd_price, &self.m3sd.height);
|
||||
compute_band_price!(&mut self._0sd.price, &self.base.sma.height);
|
||||
compute_band_price!(&mut self.p0_5sd.price, &self.p0_5sd.value.height);
|
||||
compute_band_price!(&mut self.p1sd.price, &self.p1sd.value.height);
|
||||
compute_band_price!(&mut self.p1_5sd.price, &self.p1_5sd.value.height);
|
||||
compute_band_price!(&mut self.p2sd.price, &self.p2sd.value.height);
|
||||
compute_band_price!(&mut self.p2_5sd.price, &self.p2_5sd.value.height);
|
||||
compute_band_price!(&mut self.p3sd.price, &self.p3sd.value.height);
|
||||
compute_band_price!(&mut self.m0_5sd.price, &self.m0_5sd.value.height);
|
||||
compute_band_price!(&mut self.m1sd.price, &self.m1sd.value.height);
|
||||
compute_band_price!(&mut self.m1_5sd.price, &self.m1_5sd.value.height);
|
||||
compute_band_price!(&mut self.m2sd.price, &self.m2sd.value.height);
|
||||
compute_band_price!(&mut self.m2_5sd.price, &self.m2_5sd.value.height);
|
||||
compute_band_price!(&mut self.m3sd.price, &self.m3sd.value.height);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -248,18 +258,18 @@ impl StdDevPerBlockExtended {
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = &mut EagerVec<PcoVec<Height, StoredF32>>> {
|
||||
[
|
||||
&mut self.p0_5sd.height,
|
||||
&mut self.p1sd.height,
|
||||
&mut self.p1_5sd.height,
|
||||
&mut self.p2sd.height,
|
||||
&mut self.p2_5sd.height,
|
||||
&mut self.p3sd.height,
|
||||
&mut self.m0_5sd.height,
|
||||
&mut self.m1sd.height,
|
||||
&mut self.m1_5sd.height,
|
||||
&mut self.m2sd.height,
|
||||
&mut self.m2_5sd.height,
|
||||
&mut self.m3sd.height,
|
||||
&mut self.p0_5sd.value.height,
|
||||
&mut self.p1sd.value.height,
|
||||
&mut self.p1_5sd.value.height,
|
||||
&mut self.p2sd.value.height,
|
||||
&mut self.p2_5sd.value.height,
|
||||
&mut self.p3sd.value.height,
|
||||
&mut self.m0_5sd.value.height,
|
||||
&mut self.m1sd.value.height,
|
||||
&mut self.m1_5sd.value.height,
|
||||
&mut self.m2sd.value.height,
|
||||
&mut self.m2_5sd.value.height,
|
||||
&mut self.m3sd.value.height,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user