global: sats version of all prices

This commit is contained in:
nym21
2026-01-26 15:04:45 +01:00
parent f066fcda32
commit 3d01822d27
53 changed files with 2843 additions and 1688 deletions

View File

@@ -0,0 +1,135 @@
//! Lazy binary price wrapper with both USD and sats representations.
//!
//! For binary operations (e.g., price × ratio) that produce price values.
//! Both dollars and sats are computed lazily from the same sources.
use brk_traversable::Traversable;
use brk_types::{Dollars, SatsFract, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableCloneableVec, LazyVecFrom1};
use super::{ComputedFromDateLast, LazyBinaryFromDateLast};
use crate::internal::{ComputedFromHeightLast, ComputedVecValue, DollarsToSatsFract, LazyTransformLast, NumericValue};
/// Lazy binary price with both USD and sats representations.
///
/// Wraps a binary operation that produces Dollars and lazily converts to sats.
/// Derefs to the dollars metric.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryPrice<S1T, S2T>
where
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dollars: LazyBinaryFromDateLast<Dollars, S1T, S2T>,
pub sats: LazyUnaryFromBinaryLast<SatsFract, Dollars, S1T, S2T>,
}
/// Lazy unary transform chain on a LazyBinaryFromDateLast output.
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyUnaryFromBinaryLast<T, ST, S1T, S2T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
ST: ComputedVecValue,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
pub dateindex: LazyVecFrom1<brk_types::DateIndex, T, brk_types::DateIndex, ST>,
pub weekindex: LazyTransformLast<brk_types::WeekIndex, T, ST>,
pub monthindex: LazyTransformLast<brk_types::MonthIndex, T, ST>,
pub quarterindex: LazyTransformLast<brk_types::QuarterIndex, T, ST>,
pub semesterindex: LazyTransformLast<brk_types::SemesterIndex, T, ST>,
pub yearindex: LazyTransformLast<brk_types::YearIndex, T, ST>,
pub decadeindex: LazyTransformLast<brk_types::DecadeIndex, T, ST>,
_phantom: std::marker::PhantomData<(S1T, S2T)>,
}
impl<S1T, S2T> LazyBinaryPrice<S1T, S2T>
where
S1T: ComputedVecValue + JsonSchema + 'static,
S2T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from height-based price and dateindex-based ratio sources.
pub fn from_height_and_dateindex_last<F: BinaryTransform<S1T, S2T, Dollars>>(
name: &str,
version: Version,
source1: &ComputedFromHeightLast<S1T>,
source2: &ComputedFromDateLast<S2T>,
) -> Self
where
S1T: NumericValue,
{
let dollars = LazyBinaryFromDateLast::from_height_and_dateindex_last::<F>(
name, version, source1, source2,
);
Self::from_dollars(name, version, dollars)
}
/// Create from two computed dateindex sources.
pub fn from_computed_both_last<F: BinaryTransform<S1T, S2T, Dollars>>(
name: &str,
version: Version,
source1: &ComputedFromDateLast<S1T>,
source2: &ComputedFromDateLast<S2T>,
) -> Self {
let dollars = LazyBinaryFromDateLast::from_computed_both_last::<F>(
name, version, source1, source2,
);
Self::from_dollars(name, version, dollars)
}
/// Create sats version from dollars.
fn from_dollars(
name: &str,
version: Version,
dollars: LazyBinaryFromDateLast<Dollars, S1T, S2T>,
) -> Self {
let sats_name = format!("{name}_sats");
let sats = LazyUnaryFromBinaryLast {
dateindex: LazyVecFrom1::transformed::<DollarsToSatsFract>(
&sats_name,
version,
dollars.dateindex.boxed_clone(),
),
weekindex: LazyTransformLast::from_boxed::<DollarsToSatsFract>(
&sats_name,
version,
dollars.weekindex.boxed_clone(),
),
monthindex: LazyTransformLast::from_boxed::<DollarsToSatsFract>(
&sats_name,
version,
dollars.monthindex.boxed_clone(),
),
quarterindex: LazyTransformLast::from_boxed::<DollarsToSatsFract>(
&sats_name,
version,
dollars.quarterindex.boxed_clone(),
),
semesterindex: LazyTransformLast::from_boxed::<DollarsToSatsFract>(
&sats_name,
version,
dollars.semesterindex.boxed_clone(),
),
yearindex: LazyTransformLast::from_boxed::<DollarsToSatsFract>(
&sats_name,
version,
dollars.yearindex.boxed_clone(),
),
decadeindex: LazyTransformLast::from_boxed::<DollarsToSatsFract>(
&sats_name,
version,
dollars.decadeindex.boxed_clone(),
),
_phantom: std::marker::PhantomData,
};
Self { dollars, sats }
}
}

View File

@@ -0,0 +1,60 @@
//! Lazy price wrapper with both USD and sats representations.
//!
//! Both dollars and sats are computed from the same source.
use brk_traversable::Traversable;
use brk_types::{Dollars, SatsFract, Version};
use derive_more::{Deref, DerefMut};
use vecdb::UnaryTransform;
use super::{ComputedFromDateLast, LazyFromDateLast};
use crate::internal::{ComputedVecValue, DollarsToSatsFract};
/// Lazy price with both USD and sats representations.
///
/// Both are computed from the same source via separate transforms.
/// Derefs to the dollars metric.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyPrice<ST>
where
ST: ComputedVecValue,
{
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dollars: LazyFromDateLast<Dollars, ST>,
pub sats: LazyFromDateLast<SatsFract, ST>,
}
/// Composed transform: ST -> Dollars -> SatsFract
pub struct ComposedDollarsToSatsFract<F>(std::marker::PhantomData<F>);
impl<F, ST> UnaryTransform<ST, SatsFract> for ComposedDollarsToSatsFract<F>
where
F: UnaryTransform<ST, Dollars>,
{
#[inline(always)]
fn apply(source: ST) -> SatsFract {
DollarsToSatsFract::apply(F::apply(source))
}
}
impl<ST> LazyPrice<ST>
where
ST: ComputedVecValue + schemars::JsonSchema + 'static,
{
pub fn from_source<F: UnaryTransform<ST, Dollars>>(
name: &str,
version: Version,
source: &ComputedFromDateLast<ST>,
) -> Self {
let dollars = LazyFromDateLast::from_source::<F>(name, version, source);
let sats = LazyFromDateLast::from_source::<ComposedDollarsToSatsFract<F>>(
&format!("{name}_sats"),
version,
source,
);
Self { dollars, sats }
}
}

View File

@@ -5,16 +5,20 @@ mod binary_sum_cum;
mod first;
mod last;
mod lazy;
mod lazy_binary_price;
mod lazy_distribution;
mod lazy_full;
mod lazy_last;
mod lazy_price;
mod lazy_sum;
mod lazy_sum_cum;
mod max;
mod min;
mod percentiles;
mod price;
mod ratio;
mod stddev;
mod unary_last;
mod value_derived_last;
mod value_last;
mod value_lazy_last;
@@ -26,16 +30,20 @@ pub use binary_sum_cum::*;
pub use first::*;
pub use last::*;
pub use lazy::*;
pub use lazy_binary_price::*;
pub use lazy_distribution::*;
pub use lazy_full::*;
pub use lazy_last::*;
pub use lazy_price::*;
pub use lazy_sum::*;
pub use lazy_sum_cum::*;
pub use max::*;
pub use min::*;
pub use percentiles::*;
pub use price::*;
pub use ratio::*;
pub use stddev::*;
pub use unary_last::*;
pub use value_derived_last::*;
pub use value_last::*;
pub use value_lazy_last::*;

View File

@@ -8,7 +8,7 @@ use vecdb::{
use crate::{ComputeIndexes, indexes};
use super::ComputedFromDateLast;
use super::Price;
pub const PERCENTILES: [u8; 19] = [
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95,
@@ -17,7 +17,7 @@ pub const PERCENTILES_LEN: usize = PERCENTILES.len();
#[derive(Clone)]
pub struct CostBasisPercentiles {
pub vecs: [Option<ComputedFromDateLast<Dollars>>; PERCENTILES_LEN],
pub vecs: [Option<Price>; PERCENTILES_LEN],
}
const VERSION: Version = Version::ZERO;
@@ -37,8 +37,7 @@ impl CostBasisPercentiles {
} else {
format!("{name}_cost_basis_pct{p:02}")
};
ComputedFromDateLast::forced_import(db, &metric_name, version + VERSION, indexes)
.unwrap()
Price::forced_import(db, &metric_name, version + VERSION, indexes).unwrap()
})
});
@@ -81,7 +80,7 @@ impl CostBasisPercentiles {
Ok(())
}
pub fn get(&self, percentile: u8) -> Option<&ComputedFromDateLast<Dollars>> {
pub fn get(&self, percentile: u8) -> Option<&Price> {
PERCENTILES
.iter()
.position(|&p| p == percentile)

View File

@@ -0,0 +1,48 @@
//! Price wrapper that provides both USD and sats representations.
//!
//! The struct derefs to dollars, making it transparent for existing code.
//! Access `.sats` for the sats representation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, SatsFract, Version};
use derive_more::{Deref, DerefMut};
use vecdb::Database;
use super::{ComputedFromDateLast, LazyUnaryFromDateLast};
use crate::{indexes, internal::DollarsToSatsFract};
/// Price metric with both USD and sats representations.
///
/// Derefs to the dollars metric, so existing code works unchanged.
/// Access `.sats` for the sats exchange rate version.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct Price {
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dollars: ComputedFromDateLast<Dollars>,
pub sats: LazyUnaryFromDateLast<SatsFract, Dollars>,
}
impl Price {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dollars = ComputedFromDateLast::forced_import(db, name, version, indexes)?;
Ok(Self::from_computed(name, version, dollars))
}
pub fn from_computed(name: &str, version: Version, dollars: ComputedFromDateLast<Dollars>) -> Self {
let sats = LazyUnaryFromDateLast::from_computed_last::<DollarsToSatsFract>(
&format!("{name}_sats"),
version,
&dollars,
);
Self { dollars, sats }
}
}

View File

@@ -9,19 +9,19 @@ use vecdb::{
use crate::{
ComputeIndexes, indexes,
internal::{
ComputedFromDateStdDev, LazyBinaryFromDateLast, PriceTimesRatio,
ComputedFromDateStdDev, LazyBinaryPrice, PriceTimesRatio,
StandardDeviationVecsOptions,
},
price,
utils::get_percentile,
};
use super::ComputedFromDateLast;
use super::{ComputedFromDateLast, Price};
use crate::internal::ComputedFromHeightLast;
#[derive(Clone, Traversable)]
pub struct ComputedFromDateRatio {
pub price: Option<ComputedFromDateLast<Dollars>>,
pub price: Option<Price>,
pub ratio: ComputedFromDateLast<StoredF32>,
pub ratio_1w_sma: Option<ComputedFromDateLast<StoredF32>>,
@@ -32,12 +32,12 @@ pub struct ComputedFromDateRatio {
pub ratio_pct5: Option<ComputedFromDateLast<StoredF32>>,
pub ratio_pct2: Option<ComputedFromDateLast<StoredF32>>,
pub ratio_pct1: Option<ComputedFromDateLast<StoredF32>>,
pub ratio_pct99_usd: Option<LazyBinaryFromDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct98_usd: Option<LazyBinaryFromDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct95_usd: Option<LazyBinaryFromDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct5_usd: Option<LazyBinaryFromDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct2_usd: Option<LazyBinaryFromDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct1_usd: Option<LazyBinaryFromDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct99_usd: Option<LazyBinaryPrice<Dollars, StoredF32>>,
pub ratio_pct98_usd: Option<LazyBinaryPrice<Dollars, StoredF32>>,
pub ratio_pct95_usd: Option<LazyBinaryPrice<Dollars, StoredF32>>,
pub ratio_pct5_usd: Option<LazyBinaryPrice<Dollars, StoredF32>>,
pub ratio_pct2_usd: Option<LazyBinaryPrice<Dollars, StoredF32>>,
pub ratio_pct1_usd: Option<LazyBinaryPrice<Dollars, StoredF32>>,
pub ratio_sd: Option<ComputedFromDateStdDev>,
pub ratio_4y_sd: Option<ComputedFromDateStdDev>,
@@ -70,7 +70,7 @@ impl ComputedFromDateRatio {
// Only compute internally when metric_price is None
let price = metric_price
.is_none()
.then(|| ComputedFromDateLast::forced_import(db, name, v, indexes).unwrap());
.then(|| Price::forced_import(db, name, v, indexes).unwrap());
macro_rules! import_sd {
($suffix:expr, $days:expr) => {
@@ -98,7 +98,7 @@ impl ComputedFromDateRatio {
($ratio:expr, $suffix:expr) => {
if let Some(mp) = metric_price {
$ratio.as_ref().map(|r| {
LazyBinaryFromDateLast::from_height_and_dateindex_last::<PriceTimesRatio>(
LazyBinaryPrice::from_height_and_dateindex_last::<PriceTimesRatio>(
&format!("{name}_{}", $suffix),
v,
mp,
@@ -107,7 +107,7 @@ impl ComputedFromDateRatio {
})
} else {
price.as_ref().zip($ratio.as_ref()).map(|(p, r)| {
LazyBinaryFromDateLast::from_computed_both_last::<PriceTimesRatio>(
LazyBinaryPrice::from_computed_both_last::<PriceTimesRatio>(
&format!("{name}_{}", $suffix),
v,
p,

View File

@@ -10,7 +10,7 @@ use vecdb::{
use crate::{ComputeIndexes, indexes, price};
use crate::internal::{ClosePriceTimesRatio, ComputedFromDateLast, LazyBinaryFromDateLast};
use crate::internal::{ClosePriceTimesRatio, ComputedFromDateLast, LazyBinaryPrice};
#[derive(Clone, Traversable)]
pub struct ComputedFromDateStdDev {
@@ -35,19 +35,19 @@ pub struct ComputedFromDateStdDev {
pub m2_5sd: Option<ComputedFromDateLast<StoredF32>>,
pub m3sd: Option<ComputedFromDateLast<StoredF32>>,
pub _0sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p0_5sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p1sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p1_5sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p2sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p2_5sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p3sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m0_5sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m1sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m1_5sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m2sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m2_5sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m3sd_usd: Option<LazyBinaryFromDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub _0sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub p0_5sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub p1sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub p1_5sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub p2sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub p2_5sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub p3sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub m0_5sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub m1sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub m1_5sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub m2sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub m2_5sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
pub m3sd_usd: Option<LazyBinaryPrice<Close<Dollars>, StoredF32>>,
}
#[derive(Debug, Default)]
@@ -140,7 +140,7 @@ impl ComputedFromDateStdDev {
.zip($band.as_ref())
.filter(|_| options.price_bands())
.map(|(p, b)| {
LazyBinaryFromDateLast::from_computed_both_last::<ClosePriceTimesRatio>(
LazyBinaryPrice::from_computed_both_last::<ClosePriceTimesRatio>(
&format!("{name}_{}", $suffix),
version,
p,

View File

@@ -0,0 +1,58 @@
//! Unary transform composite from DateIndex - Last aggregation only.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, LazyVecFrom1, UnaryTransform};
use crate::internal::{ComputedFromDateLast, ComputedVecValue, LazyTransformLast};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyUnaryFromDateLast<T, ST>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
ST: ComputedVecValue,
{
pub dateindex: LazyVecFrom1<DateIndex, T, DateIndex, ST>,
pub weekindex: LazyTransformLast<WeekIndex, T, ST>,
pub monthindex: LazyTransformLast<MonthIndex, T, ST>,
pub quarterindex: LazyTransformLast<QuarterIndex, T, ST>,
pub semesterindex: LazyTransformLast<SemesterIndex, T, ST>,
pub yearindex: LazyTransformLast<YearIndex, T, ST>,
pub decadeindex: LazyTransformLast<DecadeIndex, T, ST>,
}
impl<T, ST> LazyUnaryFromDateLast<T, ST>
where
T: ComputedVecValue + JsonSchema + 'static,
ST: ComputedVecValue + JsonSchema,
{
pub fn from_computed_last<F: UnaryTransform<ST, T>>(
name: &str,
version: Version,
source: &ComputedFromDateLast<ST>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformLast::from_lazy_last::<F, _, _>(name, v, &source.$p)
};
}
Self {
dateindex: LazyVecFrom1::transformed::<F>(name, v, source.dateindex.boxed_clone()),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -15,6 +15,8 @@ mod lazy_computed_full;
mod lazy_computed_sum_cum;
mod lazy_last;
mod lazy_sum;
mod price;
mod unary_last;
mod lazy_sum_cum;
mod sum;
mod sum_cum;
@@ -46,6 +48,8 @@ pub use lazy_computed_full::*;
pub use lazy_computed_sum_cum::*;
pub use lazy_last::*;
pub use lazy_sum::*;
pub use price::*;
pub use unary_last::*;
pub use lazy_sum_cum::*;
pub use sum::*;
pub use sum_cum::*;

View File

@@ -0,0 +1,49 @@
//! Price wrapper for height-based metrics with both USD and sats representations.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, SatsFract, Version};
use derive_more::{Deref, DerefMut};
use vecdb::Database;
use super::{ComputedFromHeightLast, LazyUnaryFromHeightLast};
use crate::{indexes, internal::DollarsToSatsFract};
/// Price metric (height-based) with both USD and sats representations.
///
/// Derefs to the dollars metric, so existing code works unchanged.
/// Access `.sats` for the sats exchange rate version.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct PriceFromHeight {
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dollars: ComputedFromHeightLast<Dollars>,
pub sats: LazyUnaryFromHeightLast<SatsFract, Dollars>,
}
impl PriceFromHeight {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dollars = ComputedFromHeightLast::forced_import(db, name, version, indexes)?;
Ok(Self::from_computed(name, version, dollars))
}
pub fn from_computed(
name: &str,
version: Version,
dollars: ComputedFromHeightLast<Dollars>,
) -> Self {
let sats = LazyUnaryFromHeightLast::from_computed_last::<DollarsToSatsFract>(
&format!("{name}_sats"),
version,
&dollars,
);
Self { dollars, sats }
}
}

View File

@@ -0,0 +1,65 @@
//! Unary transform composite from Height - Last aggregation only.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, LazyVecFrom1, UnaryTransform};
use crate::internal::{
ComputedFromHeightLast, ComputedVecValue, LazyTransformLast, NumericValue,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyUnaryFromHeightLast<T, ST>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
ST: ComputedVecValue,
{
pub height: LazyVecFrom1<Height, T, Height, ST>,
pub dateindex: LazyTransformLast<DateIndex, T, ST>,
pub weekindex: LazyTransformLast<WeekIndex, T, ST>,
pub monthindex: LazyTransformLast<MonthIndex, T, ST>,
pub quarterindex: LazyTransformLast<QuarterIndex, T, ST>,
pub semesterindex: LazyTransformLast<SemesterIndex, T, ST>,
pub yearindex: LazyTransformLast<YearIndex, T, ST>,
pub decadeindex: LazyTransformLast<DecadeIndex, T, ST>,
pub difficultyepoch: LazyTransformLast<DifficultyEpoch, T, ST>,
}
impl<T, ST> LazyUnaryFromHeightLast<T, ST>
where
T: ComputedVecValue + JsonSchema + 'static,
ST: NumericValue + JsonSchema,
{
pub fn from_computed_last<F: UnaryTransform<ST, T>>(
name: &str,
version: Version,
source: &ComputedFromHeightLast<ST>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformLast::from_lazy_last::<F, _, _>(name, v, &source.$p)
};
}
Self {
height: LazyVecFrom1::transformed::<F>(name, v, source.height.boxed_clone()),
dateindex: LazyTransformLast::from_last_vec::<F>(name, v, &source.rest.dateindex),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
difficultyepoch: period!(difficultyepoch),
}
}
}

View File

@@ -6,6 +6,8 @@ mod last;
mod lazy_ohlc;
mod max;
mod min;
mod price;
mod unary_last;
mod value_last;
pub use binary_last::*;
@@ -16,4 +18,6 @@ pub use last::*;
pub use lazy_ohlc::*;
pub use max::*;
pub use min::*;
pub use price::*;
pub use unary_last::*;
pub use value_last::*;

View File

@@ -0,0 +1,49 @@
//! Price wrapper for height+date-based metrics with both USD and sats representations.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, SatsFract, Version};
use derive_more::{Deref, DerefMut};
use vecdb::Database;
use super::{ComputedFromHeightAndDateLast, LazyUnaryFromHeightAndDateLast};
use crate::{indexes, internal::DollarsToSatsFract};
/// Price metric (height+date-based) with both USD and sats representations.
///
/// Derefs to the dollars metric, so existing code works unchanged.
/// Access `.sats` for the sats exchange rate version.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct PriceFromHeightAndDate {
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dollars: ComputedFromHeightAndDateLast<Dollars>,
pub sats: LazyUnaryFromHeightAndDateLast<SatsFract, Dollars>,
}
impl PriceFromHeightAndDate {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dollars = ComputedFromHeightAndDateLast::forced_import(db, name, version, indexes)?;
Ok(Self::from_computed(name, version, dollars))
}
pub fn from_computed(
name: &str,
version: Version,
dollars: ComputedFromHeightAndDateLast<Dollars>,
) -> Self {
let sats = LazyUnaryFromHeightAndDateLast::from_computed_last::<DollarsToSatsFract>(
&format!("{name}_sats"),
version,
&dollars,
);
Self { dollars, sats }
}
}

View File

@@ -0,0 +1,71 @@
//! Unary transform composite from Height+Date - Last aggregation only.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, LazyVecFrom1, UnaryTransform};
use crate::internal::{ComputedFromHeightAndDateLast, ComputedVecValue, LazyTransformLast};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyUnaryFromHeightAndDateLast<T, ST>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
ST: ComputedVecValue,
{
pub height: LazyVecFrom1<Height, T, Height, ST>,
pub dateindex: LazyTransformLast<DateIndex, T, ST>,
pub weekindex: LazyTransformLast<WeekIndex, T, ST>,
pub monthindex: LazyTransformLast<MonthIndex, T, ST>,
pub quarterindex: LazyTransformLast<QuarterIndex, T, ST>,
pub semesterindex: LazyTransformLast<SemesterIndex, T, ST>,
pub yearindex: LazyTransformLast<YearIndex, T, ST>,
pub decadeindex: LazyTransformLast<DecadeIndex, T, ST>,
pub difficultyepoch: LazyTransformLast<DifficultyEpoch, T, ST>,
}
impl<T, ST> LazyUnaryFromHeightAndDateLast<T, ST>
where
T: ComputedVecValue + JsonSchema + 'static,
ST: ComputedVecValue + JsonSchema,
{
pub fn from_computed_last<F: UnaryTransform<ST, T>>(
name: &str,
version: Version,
source: &ComputedFromHeightAndDateLast<ST>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformLast::from_lazy_last::<F, _, _>(name, v, &source.rest.$p)
};
}
Self {
height: LazyVecFrom1::transformed::<F>(name, v, source.height.boxed_clone()),
dateindex: LazyTransformLast(LazyVecFrom1::transformed::<F>(
name,
v,
source.rest.dateindex.boxed_clone(),
)),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
difficultyepoch: LazyTransformLast::from_lazy_last::<F, _, _>(
name,
v,
&source.difficultyepoch,
),
}
}
}