computer: fixes

This commit is contained in:
nym21
2026-02-07 22:38:25 +01:00
parent 9cba9bfec4
commit ba60b7e4f6
23 changed files with 564 additions and 269 deletions

View File

@@ -45,8 +45,8 @@ pub struct RealizedMetrics {
pub investor_price_extra: ComputedFromDateRatio,
// === Floor/Ceiling Price Bands (lazy: realized²/investor, investor²/realized) ===
pub floor_price: LazyBinaryPriceFromHeight,
pub ceiling_price: LazyBinaryPriceFromHeight,
pub lower_price_band: LazyBinaryPriceFromHeight,
pub upper_price_band: LazyBinaryPriceFromHeight,
// === Raw values for aggregation (needed to compute investor_price for aggregated cohorts) ===
/// Raw Σ(price × sats) for realized cap aggregation
@@ -292,24 +292,22 @@ impl RealizedMetrics {
)?;
// Floor price = realized² / investor (lower band)
let floor_price = LazyBinaryPriceFromHeight::forced_import::<DollarsSquaredDivide>(
cfg.db,
&cfg.name("floor_price"),
cfg.version,
realized_price.dollars.height.boxed_clone(),
investor_price.dollars.height.boxed_clone(),
cfg.indexes,
)?;
let lower_price_band =
LazyBinaryPriceFromHeight::from_price_and_lazy_price::<DollarsSquaredDivide>(
&cfg.name("lower_price_band"),
cfg.version,
&realized_price,
&investor_price,
);
// Ceiling price = investor² / realized (upper band)
let ceiling_price = LazyBinaryPriceFromHeight::forced_import::<DollarsSquaredDivide>(
cfg.db,
&cfg.name("ceiling_price"),
cfg.version,
investor_price.dollars.height.boxed_clone(),
realized_price.dollars.height.boxed_clone(),
cfg.indexes,
)?;
let upper_price_band =
LazyBinaryPriceFromHeight::from_lazy_price_and_price::<DollarsSquaredDivide>(
&cfg.name("upper_price_band"),
cfg.version,
&investor_price,
&realized_price,
);
// Raw values for aggregation
let cap_raw = BytesVec::forced_import(cfg.db, &cfg.name("cap_raw"), cfg.version)?;
@@ -456,8 +454,8 @@ impl RealizedMetrics {
investor_price_extra,
// === Floor/Ceiling Price Bands ===
floor_price,
ceiling_price,
lower_price_band,
upper_price_band,
cap_raw,
investor_cap_raw,
@@ -1178,10 +1176,6 @@ impl RealizedMetrics {
)?;
}
// Floor/ceiling price bands (derive stored dateindex from lazy height)
self.floor_price.dollars.derive_from(indexes, starting_indexes, exit)?;
self.ceiling_price.dollars.derive_from(indexes, starting_indexes, exit)?;
Ok(())
}
}

View File

@@ -68,11 +68,17 @@ impl CohortState {
}
pub fn cost_basis_data_first_key_value(&self) -> Option<(CentsUnsigned, &Sats)> {
self.cost_basis_data.as_ref()?.first_key_value().map(|(k, v)| (k.into(), v))
self.cost_basis_data
.as_ref()?
.first_key_value()
.map(|(k, v)| (k.into(), v))
}
pub fn cost_basis_data_last_key_value(&self) -> Option<(CentsUnsigned, &Sats)> {
self.cost_basis_data.as_ref()?.last_key_value().map(|(k, v)| (k.into(), v))
self.cost_basis_data
.as_ref()?
.last_key_value()
.map(|(k, v)| (k.into(), v))
}
pub fn reset_single_iteration_values(&mut self) {
@@ -94,11 +100,10 @@ impl CohortState {
pub fn increment_snapshot(&mut self, s: &CostBasisSnapshot) {
self.supply += &s.supply_state;
if s.supply_state.value > Sats::ZERO && self.realized.is_some() {
self.realized
.as_mut()
.unwrap()
.increment_snapshot(s.price_sats, s.investor_cap);
if s.supply_state.value > Sats::ZERO
&& let Some(realized) = self.realized.as_mut()
{
realized.increment_snapshot(s.price_sats, s.investor_cap);
self.cost_basis_data.as_mut().unwrap().increment(
s.realized_price,
s.supply_state.value,
@@ -118,11 +123,10 @@ impl CohortState {
pub fn decrement_snapshot(&mut self, s: &CostBasisSnapshot) {
self.supply -= &s.supply_state;
if s.supply_state.value > Sats::ZERO && self.realized.is_some() {
self.realized
.as_mut()
.unwrap()
.decrement_snapshot(s.price_sats, s.investor_cap);
if s.supply_state.value > Sats::ZERO
&& let Some(realized) = self.realized.as_mut()
{
realized.decrement_snapshot(s.price_sats, s.investor_cap);
self.cost_basis_data.as_mut().unwrap().decrement(
s.realized_price,
s.supply_state.value,
@@ -147,12 +151,10 @@ impl CohortState {
realized.receive(price, sats);
self.cost_basis_data.as_mut().unwrap().increment(
price,
sats,
price_sats,
investor_cap,
);
self.cost_basis_data
.as_mut()
.unwrap()
.increment(price, sats, price_sats, investor_cap);
}
}
@@ -298,7 +300,10 @@ impl CohortState {
) -> (UnrealizedState, Option<UnrealizedState>) {
match self.cost_basis_data.as_mut() {
Some(p) => p.compute_unrealized_states(height_price, date_price),
None => (UnrealizedState::ZERO, date_price.map(|_| UnrealizedState::ZERO)),
None => (
UnrealizedState::ZERO,
date_price.map(|_| UnrealizedState::ZERO),
),
}
}
@@ -310,16 +315,22 @@ impl CohortState {
}
pub fn min_price(&self) -> Option<CentsUnsigned> {
self.cost_basis_data.as_ref()?.first_key_value().map(|(k, _)| k.into())
self.cost_basis_data
.as_ref()?
.first_key_value()
.map(|(k, _)| k.into())
}
pub fn max_price(&self) -> Option<CentsUnsigned> {
self.cost_basis_data.as_ref()?.last_key_value().map(|(k, _)| k.into())
self.cost_basis_data
.as_ref()?
.last_key_value()
.map(|(k, _)| k.into())
}
pub fn cost_basis_data_iter(
&self,
) -> Option<impl Iterator<Item = (CentsUnsigned, &Sats)>> {
self.cost_basis_data.as_ref().map(|p| p.iter().map(|(k, v)| (k.into(), v)))
pub fn cost_basis_data_iter(&self) -> Option<impl Iterator<Item = (CentsUnsigned, &Sats)>> {
self.cost_basis_data
.as_ref()
.map(|p| p.iter().map(|(k, v)| (k.into(), v)))
}
}

View File

@@ -457,6 +457,88 @@ where
}
}
/// Create from a ComputedFromHeightLast (block last with derived dates) and a LazyFromHeightLast.
pub fn from_block_last_and_lazy_block_last<F, S2SourceT>(
name: &str,
version: Version,
source1: &ComputedFromHeightLast<S1T>,
source2: &LazyFromHeightLast<S2T, S2SourceT>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1T: NumericValue,
S2SourceT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
/// Create from a LazyFromHeightLast and a ComputedFromHeightLast (reversed source order).
pub fn from_lazy_block_last_and_block_last<F, S1SourceT>(
name: &str,
version: Version,
source1: &LazyFromHeightLast<S1T, S1SourceT>,
source2: &ComputedFromHeightLast<S2T>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S2T: NumericValue,
S1SourceT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
/// Create from a LazyDateDerivedLast source and a BinaryDateLast source.
pub fn from_derived_last_and_binary_last<F, S2aT, S2bT>(
name: &str,

View File

@@ -7,7 +7,7 @@ use brk_types::{
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec, UnaryTransform};
use crate::internal::{ComputedFromHeightLast, ComputedFromDateLast, ComputedVecValue, LazyDateDerivedLast, LazyTransformLast, NumericValue};
use crate::internal::{ComputedFromHeightLast, ComputedFromDateLast, ComputedVecValue, LazyBinaryFromDateLast, LazyDateDerivedLast, LazyTransformLast, NumericValue};
const VERSION: Version = Version::ZERO;
@@ -84,4 +84,34 @@ where
{
Self::from_derived::<F>(name, version, source.dateindex.boxed_clone(), &source.dates)
}
/// Create by unary-transforming a LazyBinaryFromDateLast source.
pub fn from_binary<F, S1aT, S1bT>(
name: &str,
version: Version,
source: &LazyBinaryFromDateLast<S1T, S1aT, S1bT>,
) -> Self
where
F: UnaryTransform<S1T, T>,
S1aT: ComputedVecValue + JsonSchema,
S1bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformLast::from_boxed::<F>(name, v, source.$p.boxed_clone())
};
}
Self {
dateindex: period!(dateindex),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -2,6 +2,8 @@
//!
//! Both dollars and sats are computed from the same source.
use std::marker::PhantomData;
use brk_traversable::Traversable;
use brk_types::{Dollars, SatsFract, Version};
use derive_more::{Deref, DerefMut};
@@ -28,7 +30,7 @@ where
}
/// Composed transform: ST -> Dollars -> SatsFract
pub struct ComposedDollarsToSatsFract<F>(std::marker::PhantomData<F>);
pub struct ComposedDollarsToSatsFract<F>(PhantomData<F>);
impl<F, ST> UnaryTransform<ST, SatsFract> for ComposedDollarsToSatsFract<F>
where

View File

@@ -80,6 +80,58 @@ where
}
}
pub fn from_block_last_and_lazy_block_last<F, S2SourceT>(
name: &str,
version: Version,
source1: &ComputedFromHeightLast<S1T>,
source2: &LazyFromHeightLast<S2T, S2SourceT>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1T: NumericValue,
S2SourceT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryHeightDerivedLast::from_block_last_and_lazy_block_last::<F, _>(
name, v, source1, source2,
),
}
}
pub fn from_lazy_block_last_and_block_last<F, S1SourceT>(
name: &str,
version: Version,
source1: &LazyFromHeightLast<S1T, S1SourceT>,
source2: &ComputedFromHeightLast<S2T>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S2T: NumericValue,
S1SourceT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryHeightDerivedLast::from_lazy_block_last_and_block_last::<F, _>(
name, v, source1, source2,
),
}
}
pub fn from_computed_height_date_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,

View File

@@ -1,63 +1,72 @@
//! Lazy binary price wrapper with both USD and sats representations.
//! Fully lazy binary price wrapper with both USD and sats representations.
//!
//! Height-level value is lazy binary: transform(source1[h], source2[h]).
//! Sats are derived lazily from the dollars output.
//! All levels (height, dateindex, date periods, difficultyepoch) are lazy.
//! Derives dateindex from the two source dateindexes rather than storing it.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, Height, SatsFract, Version};
use brk_types::{CentsUnsigned, Dollars, SatsFract, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, Database, IterableBoxedVec, IterableCloneableVec};
use vecdb::BinaryTransform;
use super::LazyBinaryComputedFromHeightLast;
use crate::{
indexes,
internal::{ComputedVecValue, DollarsToSatsFract, LazyFromHeightLast, NumericValue},
use crate::internal::{
DollarsToSatsFract, LazyBinaryFromHeightLast, LazyFromHeightLast, LazyPriceFromCents,
PriceFromHeight,
};
/// Lazy binary price metric with both USD and sats representations.
/// Fully lazy binary price metric with both USD and sats representations.
///
/// Dollars: lazy binary transform at height, stored at dateindex.
/// Sats: lazy unary transform of dollars (fully lazy).
/// Dollars: lazy binary transform at all levels (height, dateindex, date periods, difficultyepoch).
/// Sats: lazy unary transform of dollars.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryPriceFromHeight<S1T = Dollars, S2T = Dollars>
where
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub struct LazyBinaryPriceFromHeight {
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dollars: LazyBinaryComputedFromHeightLast<Dollars, S1T, S2T>,
pub dollars: LazyBinaryFromHeightLast<Dollars, Dollars, Dollars>,
pub sats: LazyFromHeightLast<SatsFract, Dollars>,
}
impl<S1T, S2T> LazyBinaryPriceFromHeight<S1T, S2T>
where
S1T: NumericValue + JsonSchema,
S2T: NumericValue + JsonSchema,
{
pub fn forced_import<F: BinaryTransform<S1T, S2T, Dollars>>(
db: &Database,
impl LazyBinaryPriceFromHeight {
/// Create from a PriceFromHeight (source1) and a LazyPriceFromCents (source2).
pub fn from_price_and_lazy_price<F: BinaryTransform<Dollars, Dollars, Dollars>>(
name: &str,
version: Version,
source1: IterableBoxedVec<Height, S1T>,
source2: IterableBoxedVec<Height, S2T>,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dollars = LazyBinaryComputedFromHeightLast::forced_import::<F>(
db, name, version, source1, source2, indexes,
)?;
source1: &PriceFromHeight,
source2: &LazyPriceFromCents,
) -> Self {
let dollars = LazyBinaryFromHeightLast::from_block_last_and_lazy_block_last::<
F,
CentsUnsigned,
>(name, version, &source1.dollars, &source2.dollars);
let sats = LazyFromHeightLast::from_lazy_binary_computed::<DollarsToSatsFract, S1T, S2T>(
let sats = LazyFromHeightLast::from_binary::<DollarsToSatsFract, _, _>(
&format!("{name}_sats"),
version,
dollars.height.boxed_clone(),
&dollars,
);
Ok(Self { dollars, sats })
Self { dollars, sats }
}
/// Create from a LazyPriceFromCents (source1) and a PriceFromHeight (source2).
pub fn from_lazy_price_and_price<F: BinaryTransform<Dollars, Dollars, Dollars>>(
name: &str,
version: Version,
source1: &LazyPriceFromCents,
source2: &PriceFromHeight,
) -> Self {
let dollars = LazyBinaryFromHeightLast::from_lazy_block_last_and_block_last::<
F,
CentsUnsigned,
>(name, version, &source1.dollars, &source2.dollars);
let sats = LazyFromHeightLast::from_binary::<DollarsToSatsFract, _, _>(
&format!("{name}_sats"),
version,
&dollars,
);
Self { dollars, sats }
}
}

View File

@@ -8,7 +8,8 @@ use vecdb::{IterableBoxedVec, IterableCloneableVec, LazyVecFrom1, UnaryTransform
use crate::internal::{
ComputedFromHeightAndDateLast, ComputedFromHeightLast, ComputedHeightDerivedLast,
ComputedVecValue, LazyBinaryComputedFromHeightLast, LazyHeightDerivedLast, NumericValue,
ComputedVecValue, LazyBinaryComputedFromHeightLast, LazyBinaryFromHeightLast,
LazyHeightDerivedLast, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
@@ -96,4 +97,22 @@ where
rest: LazyHeightDerivedLast::from_derived_computed::<F>(name, v, &source.rest),
}
}
/// Create by unary-transforming a LazyBinaryFromHeightLast source.
pub fn from_binary<F, S1aT, S1bT>(
name: &str,
version: Version,
source: &LazyBinaryFromHeightLast<S1T, S1aT, S1bT>,
) -> Self
where
F: UnaryTransform<S1T, T>,
S1aT: ComputedVecValue + JsonSchema,
S1bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, source.height.boxed_clone()),
rest: LazyHeightDerivedLast::from_binary::<F, _, _>(name, v, &source.rest),
}
}
}

View File

@@ -5,30 +5,30 @@ mod binary_sum_cum;
mod distribution;
mod full;
mod last;
mod lazy_distribution;
mod lazy_full;
mod lazy_transform_distribution;
mod lazy_binary_computed_distribution;
mod lazy_binary_computed_full;
mod lazy_binary_computed_last;
mod lazy_binary_price;
mod lazy_binary_computed_sum;
mod lazy_binary_computed_sum_cum;
mod lazy_binary_price;
mod lazy_computed_full;
mod lazy_computed_sum_cum;
mod lazy_distribution;
mod lazy_full;
mod lazy_last;
mod lazy_price_from_cents;
mod lazy_sum;
mod price;
mod unary_last;
mod lazy_sum_cum;
mod lazy_transform_distribution;
mod lazy_value;
mod price;
mod sum;
mod sum_cum;
mod unary_last;
mod value_binary;
mod value_full;
mod value_last;
mod value_lazy_binary_last;
mod lazy_value;
mod value_lazy_computed_sum_cum;
mod value_lazy_last;
mod value_lazy_sum_cum;
@@ -42,30 +42,30 @@ pub use binary_sum_cum::*;
pub use distribution::*;
pub use full::*;
pub use last::*;
pub use lazy_distribution::*;
pub use lazy_full::*;
pub use lazy_transform_distribution::*;
pub use lazy_binary_computed_distribution::*;
pub use lazy_binary_computed_full::*;
pub use lazy_binary_computed_last::*;
pub use lazy_binary_price::*;
pub use lazy_binary_computed_sum::*;
pub use lazy_binary_computed_sum_cum::*;
pub use lazy_binary_price::*;
pub use lazy_computed_full::*;
pub use lazy_computed_sum_cum::*;
pub use lazy_distribution::*;
pub use lazy_full::*;
pub use lazy_last::*;
pub use lazy_price_from_cents::*;
pub use lazy_sum::*;
pub use price::*;
pub use unary_last::*;
pub use lazy_sum_cum::*;
pub use lazy_transform_distribution::*;
pub use lazy_value::*;
pub use price::*;
pub use sum::*;
pub use sum_cum::*;
pub use unary_last::*;
pub use value_binary::*;
pub use value_full::*;
pub use value_last::*;
pub use value_lazy_binary_last::*;
pub use lazy_value::*;
pub use value_lazy_computed_sum_cum::*;
pub use value_lazy_last::*;
pub use value_lazy_sum_cum::*;

View File

@@ -86,6 +86,32 @@ where
}
}
pub fn from_lazy_block_last_and_block_last<F, S1SourceT>(
name: &str,
version: Version,
source1: &LazyFromHeightLast<S1T, S1SourceT>,
source2: &ComputedFromHeightLast<S2T>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S2T: NumericValue,
S1SourceT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
Self {
dates: LazyBinaryFromDateLast::from_lazy_block_last_and_block_last::<F, _>(
name, v, source1, source2,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.rest.difficultyepoch.boxed_clone(),
source2.rest.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_computed_height_date_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
@@ -114,6 +140,32 @@ where
}
}
pub fn from_block_last_and_lazy_block_last<F, S2SourceT>(
name: &str,
version: Version,
source1: &ComputedFromHeightLast<S1T>,
source2: &LazyFromHeightLast<S2T, S2SourceT>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1T: NumericValue,
S2SourceT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
Self {
dates: LazyBinaryFromDateLast::from_block_last_and_lazy_block_last::<F, _>(
name, v, source1, source2,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.rest.difficultyepoch.boxed_clone(),
source2.rest.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_computed_height_date_and_block_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,

View File

@@ -8,7 +8,7 @@ use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{
ComputedFromHeightLast, ComputedHeightDerivedLast, ComputedFromHeightAndDateLast, ComputedVecValue,
LazyFromDateLast, LazyTransformLast, NumericValue,
LazyBinaryHeightDerivedLast, LazyFromDateLast, LazyTransformLast, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
@@ -81,6 +81,29 @@ where
}
}
/// Create by unary-transforming a LazyBinaryHeightDerivedLast source.
pub fn from_binary<F, S1aT, S1bT>(
name: &str,
version: Version,
source: &LazyBinaryHeightDerivedLast<S1T, S1aT, S1bT>,
) -> Self
where
F: UnaryTransform<S1T, T>,
S1aT: ComputedVecValue + JsonSchema,
S1bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
Self {
dates: LazyFromDateLast::from_binary::<F, _, _>(name, v, &source.dates),
difficultyepoch: LazyTransformLast::from_boxed::<F>(
name,
v,
source.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_computed_height_date<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,

View File

@@ -3,11 +3,11 @@ mod cents_unsigned_to_sats_fract;
mod close_price_times_sats;
mod difference_f32;
mod dollar_halve;
mod dollars_squared_divide;
mod dollar_identity;
mod dollar_minus;
mod dollar_plus;
mod dollar_times_tenths;
mod dollars_squared_divide;
mod dollars_to_sats_fract;
mod f32_identity;
mod half_close_price_times_sats;
@@ -46,11 +46,11 @@ pub use cents_unsigned_to_sats_fract::*;
pub use close_price_times_sats::*;
pub use difference_f32::*;
pub use dollar_halve::*;
pub use dollars_squared_divide::*;
pub use dollar_identity::*;
pub use dollar_minus::*;
pub use dollar_plus::*;
pub use dollar_times_tenths::*;
pub use dollars_squared_divide::*;
pub use dollars_to_sats_fract::*;
pub use f32_identity::*;
pub use half_close_price_times_sats::*;