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

@@ -5,7 +5,7 @@ use vecdb::Database;
use super::Vecs;
use crate::{
indexes,
internal::{ComputedFromHeightLast, ComputedFromDateRatio},
internal::{ComputedFromDateRatio, PriceFromHeight},
price,
};
@@ -16,41 +16,61 @@ impl Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
macro_rules! computed_h {
($name:expr) => {
ComputedFromHeightLast::forced_import(db, $name, version, indexes)?
};
}
let vaulted_price = PriceFromHeight::forced_import(db, "vaulted_price", version, indexes)?;
let vaulted_price_ratio = ComputedFromDateRatio::forced_import(
db,
"vaulted_price",
Some(&vaulted_price),
version,
indexes,
true,
price,
)?;
// Extract price vecs before struct literal so they can be used as sources for ratios
let vaulted_price = computed_h!("vaulted_price");
let active_price = computed_h!("active_price");
let true_market_mean = computed_h!("true_market_mean");
let cointime_price = computed_h!("cointime_price");
let active_price = PriceFromHeight::forced_import(db, "active_price", version, indexes)?;
let active_price_ratio = ComputedFromDateRatio::forced_import(
db,
"active_price",
Some(&active_price),
version,
indexes,
true,
price,
)?;
macro_rules! ratio_di {
($name:expr, $source:expr) => {
ComputedFromDateRatio::forced_import(
db,
$name,
Some($source),
version,
indexes,
true,
price,
)?
};
}
let true_market_mean =
PriceFromHeight::forced_import(db, "true_market_mean", version, indexes)?;
let true_market_mean_ratio = ComputedFromDateRatio::forced_import(
db,
"true_market_mean",
Some(&true_market_mean),
version,
indexes,
true,
price,
)?;
let cointime_price =
PriceFromHeight::forced_import(db, "cointime_price", version, indexes)?;
let cointime_price_ratio = ComputedFromDateRatio::forced_import(
db,
"cointime_price",
Some(&cointime_price),
version,
indexes,
true,
price,
)?;
Ok(Self {
vaulted_price_ratio: ratio_di!("vaulted_price", &vaulted_price),
vaulted_price,
active_price_ratio: ratio_di!("active_price", &active_price),
vaulted_price_ratio,
active_price,
true_market_mean_ratio: ratio_di!("true_market_mean", &true_market_mean),
active_price_ratio,
true_market_mean,
cointime_price_ratio: ratio_di!("cointime_price", &cointime_price),
true_market_mean_ratio,
cointime_price,
cointime_price_ratio,
})
}
}

View File

@@ -1,16 +1,15 @@
use brk_traversable::Traversable;
use brk_types::Dollars;
use crate::internal::{ComputedFromHeightLast, ComputedFromDateRatio};
use crate::internal::{ComputedFromDateRatio, PriceFromHeight};
#[derive(Clone, Traversable)]
pub struct Vecs {
pub vaulted_price: ComputedFromHeightLast<Dollars>,
pub vaulted_price: PriceFromHeight,
pub vaulted_price_ratio: ComputedFromDateRatio,
pub active_price: ComputedFromHeightLast<Dollars>,
pub active_price: PriceFromHeight,
pub active_price_ratio: ComputedFromDateRatio,
pub true_market_mean: ComputedFromHeightLast<Dollars>,
pub true_market_mean: PriceFromHeight,
pub true_market_mean_ratio: ComputedFromDateRatio,
pub cointime_price: ComputedFromHeightLast<Dollars>,
pub cointime_price: PriceFromHeight,
pub cointime_price_ratio: ComputedFromDateRatio,
}

View File

@@ -8,7 +8,7 @@ use crate::{
ComputeIndexes,
distribution::state::CohortState,
indexes,
internal::{ComputedFromHeightLast, CostBasisPercentiles},
internal::{CostBasisPercentiles, PriceFromHeight},
};
use super::ImportConfig;
@@ -17,10 +17,10 @@ use super::ImportConfig;
#[derive(Clone, Traversable)]
pub struct CostBasisMetrics {
/// Minimum cost basis for any UTXO at this height
pub min: ComputedFromHeightLast<Dollars>,
pub min: PriceFromHeight,
/// Maximum cost basis for any UTXO at this height
pub max: ComputedFromHeightLast<Dollars>,
pub max: PriceFromHeight,
/// Cost basis distribution percentiles (median, quartiles, etc.)
pub percentiles: Option<CostBasisPercentiles>,
@@ -32,13 +32,13 @@ impl CostBasisMetrics {
let extended = cfg.extended();
Ok(Self {
min: ComputedFromHeightLast::forced_import(
min: PriceFromHeight::forced_import(
cfg.db,
&cfg.name("min_cost_basis"),
cfg.version,
cfg.indexes,
)?,
max: ComputedFromHeightLast::forced_import(
max: PriceFromHeight::forced_import(
cfg.db,
&cfg.name("max_cost_basis"),
cfg.version,

View File

@@ -14,7 +14,8 @@ use crate::{
internal::{
ComputedFromHeightLast, ComputedFromHeightSum, ComputedFromHeightSumCum, ComputedFromDateLast,
ComputedFromDateRatio, DollarsMinus, LazyBinaryFromHeightSum, LazyBinaryFromHeightSumCum,
LazyFromHeightSum, LazyFromHeightSumCum, LazyFromDateLast, PercentageDollarsF32, StoredF32Identity,
LazyFromHeightSum, LazyFromHeightSumCum, LazyFromDateLast, PercentageDollarsF32,
PriceFromHeight, StoredF32Identity,
},
price,
};
@@ -26,7 +27,7 @@ use super::ImportConfig;
pub struct RealizedMetrics {
// === Realized Cap ===
pub realized_cap: ComputedFromHeightLast<Dollars>,
pub realized_price: ComputedFromHeightLast<Dollars>,
pub realized_price: PriceFromHeight,
pub realized_price_extra: ComputedFromDateRatio,
pub realized_cap_rel_to_own_market_cap: Option<ComputedFromHeightLast<StoredF32>>,
pub realized_cap_30d_delta: ComputedFromDateLast<Dollars>,
@@ -169,7 +170,7 @@ impl RealizedMetrics {
&realized_cap,
);
let realized_price = ComputedFromHeightLast::forced_import(
let realized_price = PriceFromHeight::forced_import(
cfg.db,
&cfg.name("realized_price"),
cfg.version + v1,

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,
),
}
}
}

View File

@@ -1,4 +1,4 @@
use brk_types::{Close, Dollars, SatsFract};
use brk_types::{Dollars, SatsFract};
use vecdb::UnaryTransform;
/// Dollars -> SatsFract (exchange rate: sats per dollar at this price level)
@@ -8,21 +8,6 @@ pub struct DollarsToSatsFract;
impl UnaryTransform<Dollars, SatsFract> for DollarsToSatsFract {
#[inline(always)]
fn apply(usd: Dollars) -> SatsFract {
let usd_f64 = f64::from(usd);
if usd_f64 == 0.0 {
SatsFract::NAN
} else {
SatsFract::from(SatsFract::SATS_PER_BTC / usd_f64)
}
}
}
/// Close<Dollars> -> SatsFract
pub struct CloseDollarsToSatsFract;
impl UnaryTransform<Close<Dollars>, SatsFract> for CloseDollarsToSatsFract {
#[inline(always)]
fn apply(usd: Close<Dollars>) -> SatsFract {
DollarsToSatsFract::apply(*usd)
SatsFract::ONE_BTC / usd
}
}

View File

@@ -4,6 +4,7 @@ mod close_price_times_sats;
mod difference_f32;
mod dollar_halve;
mod dollar_identity;
mod dollars_to_sats_fract;
mod dollar_minus;
mod dollar_plus;
mod dollar_times_tenths;
@@ -44,6 +45,7 @@ pub use close_price_times_sats::*;
pub use difference_f32::*;
pub use dollar_halve::*;
pub use dollar_identity::*;
pub use dollars_to_sats_fract::*;
pub use dollar_minus::*;
pub use dollar_plus::*;
pub use dollar_times_tenths::*;

View File

@@ -6,8 +6,8 @@ use super::Vecs;
use crate::{
indexes,
internal::{
ComputedFromDateLast, ComputedFromHeightAndDateLast, LazyBinaryFromHeightAndDateLast, LazyFromDateLast,
PercentageDiffCloseDollars, StoredU16ToYears,
ComputedFromDateLast, LazyBinaryFromHeightAndDateLast, LazyFromDateLast,
PercentageDiffCloseDollars, PriceFromHeightAndDate, StoredU16ToYears,
},
price,
};
@@ -19,7 +19,7 @@ impl Vecs {
indexes: &indexes::Vecs,
price: &price::Vecs,
) -> Result<Self> {
let price_ath = ComputedFromHeightAndDateLast::forced_import(db, "price_ath", version, indexes)?;
let price_ath = PriceFromHeightAndDate::forced_import(db, "price_ath", version, indexes)?;
let max_days_between_price_aths =
ComputedFromDateLast::forced_import(db, "max_days_between_price_aths", version, indexes)?;

View File

@@ -2,13 +2,13 @@ use brk_traversable::Traversable;
use brk_types::{Close, Dollars, StoredF32, StoredU16};
use crate::internal::{
ComputedFromDateLast, ComputedFromHeightAndDateLast, LazyBinaryFromHeightAndDateLast, LazyFromDateLast,
ComputedFromDateLast, LazyBinaryFromHeightAndDateLast, LazyFromDateLast, PriceFromHeightAndDate,
};
/// All-time high related metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub price_ath: ComputedFromHeightAndDateLast<Dollars>,
pub price_ath: PriceFromHeightAndDate,
pub price_drawdown: LazyBinaryFromHeightAndDateLast<StoredF32, Close<Dollars>, Dollars>,
pub days_since_price_ath: ComputedFromDateLast<StoredU16>,
pub years_since_price_ath: LazyFromDateLast<StoredF32, StoredU16>,

View File

@@ -6,7 +6,7 @@ use super::{ByDcaCagr, ByDcaClass, ByDcaPeriod, DCA_CLASS_NAMES, DCA_PERIOD_NAME
use crate::{
indexes,
internal::{
ComputedFromDateLast, LazyBinaryFromDateLast, PercentageDiffCloseDollars,
ComputedFromDateLast, LazyBinaryFromDateLast, PercentageDiffCloseDollars, Price,
ValueFromDateLast,
},
market::lookback,
@@ -28,12 +28,7 @@ impl Vecs {
// DCA by period - average price
let period_average_price = ByDcaPeriod::try_new(|name, _days| {
ComputedFromDateLast::forced_import(
db,
&format!("{name}_dca_average_price"),
version,
indexes,
)
Price::forced_import(db, &format!("{name}_dca_average_price"), version, indexes)
})?;
let period_returns =
@@ -160,7 +155,7 @@ impl Vecs {
// DCA by year class - average price
let class_average_price = ByDcaClass::try_new(|name, _year, _dateindex| {
ComputedFromDateLast::forced_import(db, &format!("{name}_average_price"), version, indexes)
Price::forced_import(db, &format!("{name}_average_price"), version, indexes)
})?;
let class_returns =

View File

@@ -2,14 +2,14 @@ use brk_traversable::Traversable;
use brk_types::{Close, Dollars, StoredF32, StoredU32};
use super::{ByDcaCagr, ByDcaClass, ByDcaPeriod};
use crate::internal::{ComputedFromDateLast, LazyBinaryFromDateLast, ValueFromDateLast};
use crate::internal::{ComputedFromDateLast, LazyBinaryFromDateLast, Price, ValueFromDateLast};
/// Dollar-cost averaging metrics by time period and year class
#[derive(Clone, Traversable)]
pub struct Vecs {
// DCA by period - KISS types
pub period_stack: ByDcaPeriod<ValueFromDateLast>,
pub period_average_price: ByDcaPeriod<ComputedFromDateLast<Dollars>>,
pub period_average_price: ByDcaPeriod<Price>,
pub period_returns: ByDcaPeriod<LazyBinaryFromDateLast<StoredF32, Close<Dollars>, Dollars>>,
pub period_cagr: ByDcaCagr<ComputedFromDateLast<StoredF32>>,
@@ -31,7 +31,7 @@ pub struct Vecs {
// DCA by year class - KISS types
pub class_stack: ByDcaClass<ValueFromDateLast>,
pub class_average_price: ByDcaClass<ComputedFromDateLast<Dollars>>,
pub class_average_price: ByDcaClass<Price>,
pub class_returns: ByDcaClass<LazyBinaryFromDateLast<StoredF32, Close<Dollars>, Dollars>>,
// DCA by year class - profitability

View File

@@ -3,12 +3,12 @@ use brk_types::Version;
use vecdb::Database;
use super::{ByLookbackPeriod, Vecs};
use crate::{indexes, internal::ComputedFromDateLast};
use crate::{indexes, internal::Price};
impl Vecs {
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let price_ago = ByLookbackPeriod::try_new(|name, _days| {
ComputedFromDateLast::forced_import(db, &format!("price_{name}_ago"), version, indexes)
Price::forced_import(db, &format!("price_{name}_ago"), version, indexes)
})?;
Ok(Self { price_ago })

View File

@@ -1,12 +1,11 @@
use brk_traversable::Traversable;
use brk_types::Dollars;
use super::ByLookbackPeriod;
use crate::internal::ComputedFromDateLast;
use crate::internal::Price;
/// Price lookback metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
#[traversable(flatten)]
pub price_ago: ByLookbackPeriod<ComputedFromDateLast<Dollars>>,
pub price_ago: ByLookbackPeriod<Price>,
}

View File

@@ -5,7 +5,7 @@ use vecdb::Database;
use super::Vecs;
use crate::{
indexes,
internal::{ComputedFromDateRatio, DollarsTimesTenths, LazyFromDateLast},
internal::{ComputedFromDateRatio, DollarsTimesTenths, LazyPrice},
price,
};
@@ -307,19 +307,19 @@ impl Vecs {
)?;
let price_200d_sma_source = price_200d_sma.price.as_ref().unwrap();
let price_200d_sma_x2_4 = LazyFromDateLast::from_source::<DollarsTimesTenths<24>>(
let price_200d_sma_x2_4 = LazyPrice::from_source::<DollarsTimesTenths<24>>(
"price_200d_sma_x2_4",
version,
price_200d_sma_source,
);
let price_200d_sma_x0_8 = LazyFromDateLast::from_source::<DollarsTimesTenths<8>>(
let price_200d_sma_x0_8 = LazyPrice::from_source::<DollarsTimesTenths<8>>(
"price_200d_sma_x0_8",
version,
price_200d_sma_source,
);
let price_350d_sma_source = price_350d_sma.price.as_ref().unwrap();
let price_350d_sma_x2 = LazyFromDateLast::from_source::<DollarsTimesTenths<20>>(
let price_350d_sma_x2 = LazyPrice::from_source::<DollarsTimesTenths<20>>(
"price_350d_sma_x2",
version,
price_350d_sma_source,

View File

@@ -1,7 +1,7 @@
use brk_traversable::Traversable;
use brk_types::Dollars;
use crate::internal::{ComputedFromDateRatio, LazyFromDateLast};
use crate::internal::{ComputedFromDateRatio, LazyPrice};
/// Simple and exponential moving average metrics
#[derive(Clone, Traversable)]
@@ -40,7 +40,7 @@ pub struct Vecs {
pub price_200w_ema: ComputedFromDateRatio,
pub price_4y_ema: ComputedFromDateRatio,
pub price_200d_sma_x2_4: LazyFromDateLast<Dollars>,
pub price_200d_sma_x0_8: LazyFromDateLast<Dollars>,
pub price_350d_sma_x2: LazyFromDateLast<Dollars>,
pub price_200d_sma_x2_4: LazyPrice<Dollars>,
pub price_200d_sma_x0_8: LazyPrice<Dollars>,
pub price_350d_sma_x2: LazyPrice<Dollars>,
}

View File

@@ -3,67 +3,23 @@ use brk_types::Version;
use vecdb::{Database, EagerVec, ImportableVec};
use super::Vecs;
use crate::{indexes, internal::ComputedFromDateLast};
use crate::{indexes, internal::{ComputedFromDateLast, Price}};
impl Vecs {
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let v1 = Version::ONE;
Ok(Self {
price_1w_min: ComputedFromDateLast::forced_import(
db,
"price_1w_min",
version + v1,
indexes,
)?,
price_1w_max: ComputedFromDateLast::forced_import(
db,
"price_1w_max",
version + v1,
indexes,
)?,
price_2w_min: ComputedFromDateLast::forced_import(
db,
"price_2w_min",
version + v1,
indexes,
)?,
price_2w_max: ComputedFromDateLast::forced_import(
db,
"price_2w_max",
version + v1,
indexes,
)?,
price_1m_min: ComputedFromDateLast::forced_import(
db,
"price_1m_min",
version + v1,
indexes,
)?,
price_1m_max: ComputedFromDateLast::forced_import(
db,
"price_1m_max",
version + v1,
indexes,
)?,
price_1y_min: ComputedFromDateLast::forced_import(
db,
"price_1y_min",
version + v1,
indexes,
)?,
price_1y_max: ComputedFromDateLast::forced_import(
db,
"price_1y_max",
version + v1,
indexes,
)?,
price_1w_min: Price::forced_import(db, "price_1w_min", version + v1, indexes)?,
price_1w_max: Price::forced_import(db, "price_1w_max", version + v1, indexes)?,
price_2w_min: Price::forced_import(db, "price_2w_min", version + v1, indexes)?,
price_2w_max: Price::forced_import(db, "price_2w_max", version + v1, indexes)?,
price_1m_min: Price::forced_import(db, "price_1m_min", version + v1, indexes)?,
price_1m_max: Price::forced_import(db, "price_1m_max", version + v1, indexes)?,
price_1y_min: Price::forced_import(db, "price_1y_min", version + v1, indexes)?,
price_1y_max: Price::forced_import(db, "price_1y_max", version + v1, indexes)?,
price_true_range: EagerVec::forced_import(db, "price_true_range", version)?,
price_true_range_2w_sum: EagerVec::forced_import(
db,
"price_true_range_2w_sum",
version,
)?,
price_true_range_2w_sum: EagerVec::forced_import(db, "price_true_range_2w_sum", version)?,
price_2w_choppiness_index: ComputedFromDateLast::forced_import(
db,
"price_2w_choppiness_index",

View File

@@ -1,20 +1,20 @@
use brk_traversable::Traversable;
use brk_types::{DateIndex, Dollars, StoredF32};
use brk_types::{DateIndex, StoredF32};
use vecdb::{EagerVec, PcoVec};
use crate::internal::ComputedFromDateLast;
use crate::internal::{ComputedFromDateLast, Price};
/// Price range and choppiness metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub price_1w_min: ComputedFromDateLast<Dollars>,
pub price_1w_max: ComputedFromDateLast<Dollars>,
pub price_2w_min: ComputedFromDateLast<Dollars>,
pub price_2w_max: ComputedFromDateLast<Dollars>,
pub price_1m_min: ComputedFromDateLast<Dollars>,
pub price_1m_max: ComputedFromDateLast<Dollars>,
pub price_1y_min: ComputedFromDateLast<Dollars>,
pub price_1y_max: ComputedFromDateLast<Dollars>,
pub price_1w_min: Price,
pub price_1w_max: Price,
pub price_2w_min: Price,
pub price_2w_max: Price,
pub price_1m_min: Price,
pub price_1m_max: Price,
pub price_1y_min: Price,
pub price_1y_max: Price,
pub price_true_range: EagerVec<PcoVec<DateIndex, StoredF32>>,
pub price_true_range_2w_sum: EagerVec<PcoVec<DateIndex, StoredF32>>,
pub price_2w_choppiness_index: ComputedFromDateLast<StoredF32>,