mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-02 03:03:39 -07:00
global: snapshot
This commit is contained in:
@@ -165,33 +165,14 @@ where
|
||||
|
||||
if values.is_empty() {
|
||||
// Handle edge case where all items were skipped
|
||||
if let Some(ref mut max_vec) = max {
|
||||
max_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
}
|
||||
if let Some(ref mut pct90_vec) = pct90 {
|
||||
pct90_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
}
|
||||
if let Some(ref mut pct75_vec) = pct75 {
|
||||
pct75_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
}
|
||||
if let Some(ref mut median_vec) = median {
|
||||
median_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
}
|
||||
if let Some(ref mut pct25_vec) = pct25 {
|
||||
pct25_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
}
|
||||
if let Some(ref mut pct10_vec) = pct10 {
|
||||
pct10_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
}
|
||||
if let Some(ref mut min_vec) = min {
|
||||
min_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
}
|
||||
if let Some(ref mut average_vec) = average {
|
||||
average_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
}
|
||||
if let Some(ref mut sum_vec) = sum {
|
||||
sum_vec.truncate_push_at(idx, T::from(0_usize))?;
|
||||
macro_rules! push_zero {
|
||||
($($vec:ident),*) => {
|
||||
$(if let Some(ref mut v) = $vec {
|
||||
v.truncate_push_at(idx, T::from(0_usize))?;
|
||||
})*
|
||||
};
|
||||
}
|
||||
push_zero!(max, pct90, pct75, median, pct25, pct10, min, average, sum);
|
||||
if let Some(ref mut cumulative_vec) = cumulative {
|
||||
let t = cumulative_val.unwrap();
|
||||
cumulative_vec.truncate_push_at(idx, t)?;
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredF32, Version};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, UnaryTransform, VecValue};
|
||||
|
||||
use crate::indexes;
|
||||
|
||||
use super::{ComputedFromHeight, LazyFromHeight};
|
||||
use crate::internal::NumericValue;
|
||||
|
||||
/// Basis-point storage with lazy ratio float view (÷10000).
|
||||
///
|
||||
/// Stores integer basis points on disk (Pco-compressed),
|
||||
/// exposes a lazy StoredF32 ratio (e.g., 25000 bps → 2.5).
|
||||
#[derive(Traversable)]
|
||||
pub struct Float32FromHeight<B, M: StorageMode = Rw>
|
||||
where
|
||||
B: NumericValue + JsonSchema,
|
||||
{
|
||||
pub bps: ComputedFromHeight<B, M>,
|
||||
pub float: LazyFromHeight<StoredF32, B>,
|
||||
}
|
||||
|
||||
impl<B> Float32FromHeight<B>
|
||||
where
|
||||
B: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn forced_import<F: UnaryTransform<B, StoredF32>>(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let bps = ComputedFromHeight::forced_import(db, name, version, indexes)?;
|
||||
|
||||
let float = LazyFromHeight::from_computed::<F>(
|
||||
&format!("{name}_float"),
|
||||
version,
|
||||
bps.height.read_only_boxed_clone(),
|
||||
&bps,
|
||||
);
|
||||
|
||||
Ok(Self { bps, float })
|
||||
}
|
||||
|
||||
pub(crate) fn compute_binary<S1T, S2T, F>(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
source1: &impl ReadableVec<Height, S1T>,
|
||||
source2: &impl ReadableVec<Height, S2T>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
S1T: VecValue,
|
||||
S2T: VecValue,
|
||||
F: BinaryTransform<S1T, S2T, B>,
|
||||
{
|
||||
self.bps.compute_binary::<S1T, S2T, F>(max_from, source1, source2, exit)
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,10 @@ mod cumulative;
|
||||
mod cumulative_sum;
|
||||
mod distribution;
|
||||
mod fiat;
|
||||
mod float32;
|
||||
mod full;
|
||||
mod lazy_base;
|
||||
mod percent;
|
||||
mod percent_distribution;
|
||||
mod percentiles;
|
||||
mod price;
|
||||
mod ratio;
|
||||
@@ -24,10 +24,10 @@ pub use cumulative::*;
|
||||
pub use cumulative_sum::*;
|
||||
pub use distribution::*;
|
||||
pub use fiat::*;
|
||||
pub use float32::*;
|
||||
pub use full::*;
|
||||
pub use lazy_base::*;
|
||||
pub use percent::*;
|
||||
pub use percent_distribution::*;
|
||||
pub use percentiles::*;
|
||||
pub use price::*;
|
||||
pub use ratio::*;
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredF32, Version};
|
||||
use brk_types::{
|
||||
BasisPoints16, BasisPointsSigned16, BasisPointsSigned32, Height, StoredF32, Version,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{BinaryTransform, Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, UnaryTransform, VecValue};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::NumericValue,
|
||||
internal::{
|
||||
Bp16ToFloat, Bp16ToPercent, Bps16ToFloat, Bps16ToPercent, Bps32ToFloat, Bps32ToPercent,
|
||||
NumericValue,
|
||||
},
|
||||
traits::ComputeDrawdown,
|
||||
};
|
||||
|
||||
@@ -44,7 +49,7 @@ where
|
||||
RatioTransform: UnaryTransform<B, StoredF32>,
|
||||
PercentTransform: UnaryTransform<B, StoredF32>,
|
||||
{
|
||||
let bps = ComputedFromHeight::forced_import(db, name, version, indexes)?;
|
||||
let bps = ComputedFromHeight::forced_import(db, &format!("{name}_bps"), version, indexes)?;
|
||||
|
||||
let ratio = LazyFromHeight::from_computed::<RatioTransform>(
|
||||
&format!("{name}_ratio"),
|
||||
@@ -54,7 +59,7 @@ where
|
||||
);
|
||||
|
||||
let percent = LazyFromHeight::from_computed::<PercentTransform>(
|
||||
&format!("{name}_percent"),
|
||||
name,
|
||||
version,
|
||||
bps.height.read_only_boxed_clone(),
|
||||
&bps,
|
||||
@@ -63,6 +68,45 @@ where
|
||||
Ok(Self { bps, ratio, percent })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl PercentFromHeight<BasisPoints16> {
|
||||
pub(crate) fn forced_import_bp16(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Self::forced_import::<Bp16ToFloat, Bp16ToPercent>(db, name, version, indexes)
|
||||
}
|
||||
}
|
||||
|
||||
impl PercentFromHeight<BasisPointsSigned16> {
|
||||
pub(crate) fn forced_import_bps16(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Self::forced_import::<Bps16ToFloat, Bps16ToPercent>(db, name, version, indexes)
|
||||
}
|
||||
}
|
||||
|
||||
impl PercentFromHeight<BasisPointsSigned32> {
|
||||
pub(crate) fn forced_import_bps32(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Self::forced_import::<Bps32ToFloat, Bps32ToPercent>(db, name, version, indexes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> PercentFromHeight<B>
|
||||
where
|
||||
B: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn compute_binary<S1T, S2T, F>(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, Height, StoredF32, Version};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, EagerVec, Exit, PcoVec, ReadableCloneableVec, Rw, StorageMode, UnaryTransform};
|
||||
|
||||
use crate::{indexes, internal::{Bp16ToFloat, Bp16ToPercent, NumericValue, WindowStarts}};
|
||||
|
||||
use super::{ComputedFromHeightDistribution, LazyFromHeight};
|
||||
|
||||
/// Like PercentFromHeight but with rolling distribution stats on the bps data.
|
||||
#[derive(Traversable)]
|
||||
pub struct PercentFromHeightDistribution<B, M: StorageMode = Rw>
|
||||
where
|
||||
B: NumericValue + JsonSchema,
|
||||
{
|
||||
pub bps: ComputedFromHeightDistribution<B, M>,
|
||||
pub ratio: LazyFromHeight<StoredF32, B>,
|
||||
pub percent: LazyFromHeight<StoredF32, B>,
|
||||
}
|
||||
|
||||
impl<B> PercentFromHeightDistribution<B>
|
||||
where
|
||||
B: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn forced_import<RatioTransform, PercentTransform>(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self>
|
||||
where
|
||||
RatioTransform: UnaryTransform<B, StoredF32>,
|
||||
PercentTransform: UnaryTransform<B, StoredF32>,
|
||||
{
|
||||
let bps = ComputedFromHeightDistribution::forced_import(db, &format!("{name}_bps"), version, indexes)?;
|
||||
|
||||
let ratio = LazyFromHeight::from_height_source::<RatioTransform>(
|
||||
&format!("{name}_ratio"),
|
||||
version,
|
||||
bps.height.read_only_boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
let percent = LazyFromHeight::from_height_source::<PercentTransform>(
|
||||
name,
|
||||
version,
|
||||
bps.height.read_only_boxed_clone(),
|
||||
indexes,
|
||||
);
|
||||
|
||||
Ok(Self { bps, ratio, percent })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl PercentFromHeightDistribution<BasisPoints16> {
|
||||
pub(crate) fn forced_import_bp16(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Self::forced_import::<Bp16ToFloat, Bp16ToPercent>(db, name, version, indexes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> PercentFromHeightDistribution<B>
|
||||
where
|
||||
B: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
windows: &WindowStarts<'_>,
|
||||
exit: &Exit,
|
||||
compute_height: impl FnOnce(&mut EagerVec<PcoVec<Height, B>>) -> Result<()>,
|
||||
) -> Result<()>
|
||||
where
|
||||
B: Copy + Ord + From<f64> + Default,
|
||||
f64: From<B>,
|
||||
{
|
||||
self.bps.compute(max_from, windows, exit, compute_height)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::{Traversable, TreeNode};
|
||||
use brk_types::{Cents, Height, StoredF32, Version};
|
||||
use brk_types::{BasisPoints16, Cents, Height, Version};
|
||||
use vecdb::{AnyExportableVec, Database, ReadOnlyClone, Ro, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::indexes;
|
||||
@@ -16,9 +16,9 @@ pub const PERCENTILES_LEN: usize = PERCENTILES.len();
|
||||
pub(crate) fn compute_spot_percentile_rank(
|
||||
percentile_prices: &[Cents; PERCENTILES_LEN],
|
||||
spot: Cents,
|
||||
) -> StoredF32 {
|
||||
) -> BasisPoints16 {
|
||||
if spot == Cents::ZERO && percentile_prices[0] == Cents::ZERO {
|
||||
return StoredF32::NAN;
|
||||
return BasisPoints16::ZERO;
|
||||
}
|
||||
|
||||
let spot_f64 = f64::from(spot);
|
||||
@@ -27,10 +27,10 @@ pub(crate) fn compute_spot_percentile_rank(
|
||||
let p5 = f64::from(percentile_prices[0]);
|
||||
if spot_f64 <= p5 {
|
||||
if p5 == 0.0 {
|
||||
return StoredF32::from(0.0);
|
||||
return BasisPoints16::ZERO;
|
||||
}
|
||||
// Linear extrapolation: rank = 5 * (spot / p5)
|
||||
return StoredF32::from((5.0 * spot_f64 / p5).max(0.0));
|
||||
// Linear extrapolation: rank = 5% * (spot / p5)
|
||||
return BasisPoints16::from((0.05 * spot_f64 / p5).max(0.0));
|
||||
}
|
||||
|
||||
// Above highest percentile (p95) - extrapolate towards 100
|
||||
@@ -38,11 +38,11 @@ pub(crate) fn compute_spot_percentile_rank(
|
||||
let p90 = f64::from(percentile_prices[PERCENTILES_LEN - 2]);
|
||||
if spot_f64 >= p95 {
|
||||
if p95 == p90 {
|
||||
return StoredF32::from(100.0);
|
||||
return BasisPoints16::ONE;
|
||||
}
|
||||
// Linear extrapolation using p90-p95 slope
|
||||
let slope = 5.0 / (p95 - p90);
|
||||
return StoredF32::from((95.0 + (spot_f64 - p95) * slope).min(100.0));
|
||||
let slope = 0.05 / (p95 - p90);
|
||||
return BasisPoints16::from((0.95 + (spot_f64 - p95) * slope).min(1.0));
|
||||
}
|
||||
|
||||
// Find the band containing spot and interpolate
|
||||
@@ -51,20 +51,20 @@ pub(crate) fn compute_spot_percentile_rank(
|
||||
let upper = f64::from(percentile_prices[i + 1]);
|
||||
|
||||
if spot_f64 >= lower && spot_f64 <= upper {
|
||||
let lower_pct = f64::from(PERCENTILES[i]);
|
||||
let upper_pct = f64::from(PERCENTILES[i + 1]);
|
||||
let lower_pct = f64::from(PERCENTILES[i]) / 100.0;
|
||||
let upper_pct = f64::from(PERCENTILES[i + 1]) / 100.0;
|
||||
|
||||
if upper == lower {
|
||||
return StoredF32::from(lower_pct);
|
||||
return BasisPoints16::from(lower_pct);
|
||||
}
|
||||
|
||||
// Linear interpolation
|
||||
let ratio = (spot_f64 - lower) / (upper - lower);
|
||||
return StoredF32::from(lower_pct + ratio * (upper_pct - lower_pct));
|
||||
return BasisPoints16::from(lower_pct + ratio * (upper_pct - lower_pct));
|
||||
}
|
||||
}
|
||||
|
||||
StoredF32::NAN
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
|
||||
pub struct PercentilesVecs<M: StorageMode = Rw> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, Height, StoredF32, Version};
|
||||
use brk_types::{BasisPoints32, Cents, Height, StoredF32, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Database, EagerVec, Exit, PcoVec, ReadableVec, Rw, StorageMode, VecIndex, WritableVec};
|
||||
|
||||
use crate::{
|
||||
@@ -8,18 +8,18 @@ use crate::{
|
||||
internal::{ComputedFromHeightStdDevExtended, Price, TDigest},
|
||||
};
|
||||
|
||||
use super::super::ComputedFromHeight;
|
||||
use super::{ComputedFromHeightRatio, super::ComputedFromHeight};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct ComputedFromHeightRatioExtension<M: StorageMode = Rw> {
|
||||
pub ratio_sma_1w: ComputedFromHeight<StoredF32, M>,
|
||||
pub ratio_sma_1m: ComputedFromHeight<StoredF32, M>,
|
||||
pub ratio_pct99: ComputedFromHeight<StoredF32, M>,
|
||||
pub ratio_pct98: ComputedFromHeight<StoredF32, M>,
|
||||
pub ratio_pct95: ComputedFromHeight<StoredF32, M>,
|
||||
pub ratio_pct5: ComputedFromHeight<StoredF32, M>,
|
||||
pub ratio_pct2: ComputedFromHeight<StoredF32, M>,
|
||||
pub ratio_pct1: ComputedFromHeight<StoredF32, M>,
|
||||
pub ratio_sma_1w: ComputedFromHeightRatio<M>,
|
||||
pub ratio_sma_1m: ComputedFromHeightRatio<M>,
|
||||
pub ratio_pct99: ComputedFromHeightRatio<M>,
|
||||
pub ratio_pct98: ComputedFromHeightRatio<M>,
|
||||
pub ratio_pct95: ComputedFromHeightRatio<M>,
|
||||
pub ratio_pct5: ComputedFromHeightRatio<M>,
|
||||
pub ratio_pct2: ComputedFromHeightRatio<M>,
|
||||
pub ratio_pct1: ComputedFromHeightRatio<M>,
|
||||
pub ratio_pct99_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub ratio_pct98_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
pub ratio_pct95_price: Price<ComputedFromHeight<Cents, M>>,
|
||||
@@ -47,9 +47,9 @@ impl ComputedFromHeightRatioExtension {
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
macro_rules! import {
|
||||
macro_rules! import_ratio {
|
||||
($suffix:expr) => {
|
||||
ComputedFromHeight::forced_import(
|
||||
ComputedFromHeightRatio::forced_import_raw(
|
||||
db,
|
||||
&format!("{name}_{}", $suffix),
|
||||
v,
|
||||
@@ -78,18 +78,18 @@ impl ComputedFromHeightRatioExtension {
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
ratio_sma_1w: import!("ratio_sma_1w"),
|
||||
ratio_sma_1m: import!("ratio_sma_1m"),
|
||||
ratio_sma_1w: import_ratio!("ratio_sma_1w"),
|
||||
ratio_sma_1m: import_ratio!("ratio_sma_1m"),
|
||||
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),
|
||||
ratio_pct99: import!("ratio_pct99"),
|
||||
ratio_pct98: import!("ratio_pct98"),
|
||||
ratio_pct95: import!("ratio_pct95"),
|
||||
ratio_pct5: import!("ratio_pct5"),
|
||||
ratio_pct2: import!("ratio_pct2"),
|
||||
ratio_pct1: import!("ratio_pct1"),
|
||||
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"),
|
||||
@@ -109,14 +109,14 @@ impl ComputedFromHeightRatioExtension {
|
||||
ratio_source: &impl ReadableVec<Height, StoredF32>,
|
||||
) -> Result<()> {
|
||||
// SMA using lookback vecs
|
||||
self.ratio_sma_1w.height.compute_rolling_average(
|
||||
self.ratio_sma_1w.bps.height.compute_rolling_average(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
ratio_source,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.ratio_sma_1m.height.compute_rolling_average(
|
||||
self.ratio_sma_1m.bps.height.compute_rolling_average(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1m_ago,
|
||||
ratio_source,
|
||||
@@ -124,14 +124,14 @@ impl ComputedFromHeightRatioExtension {
|
||||
)?;
|
||||
|
||||
let ratio_version = ratio_source.version();
|
||||
self.mut_ratio_vecs()
|
||||
self.mut_pct_vecs()
|
||||
.try_for_each(|v| -> Result<()> {
|
||||
v.validate_computed_version_or_reset(ratio_version)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let starting_height = self
|
||||
.mut_ratio_vecs()
|
||||
.mut_pct_vecs()
|
||||
.map(|v| Height::from(v.len()))
|
||||
.min()
|
||||
.unwrap()
|
||||
@@ -154,13 +154,13 @@ impl ComputedFromHeightRatioExtension {
|
||||
|
||||
// Process new blocks [start, ratio_len)
|
||||
let new_ratios = ratio_source.collect_range_at(start, ratio_len);
|
||||
let mut pct_vecs: [&mut EagerVec<PcoVec<Height, StoredF32>>; 6] = [
|
||||
&mut self.ratio_pct1.height,
|
||||
&mut self.ratio_pct2.height,
|
||||
&mut self.ratio_pct5.height,
|
||||
&mut self.ratio_pct95.height,
|
||||
&mut self.ratio_pct98.height,
|
||||
&mut self.ratio_pct99.height,
|
||||
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,
|
||||
];
|
||||
const PCTS: [f64; 6] = [0.01, 0.02, 0.05, 0.95, 0.98, 0.99];
|
||||
let mut out = [0.0f64; 6];
|
||||
@@ -170,14 +170,14 @@ impl ComputedFromHeightRatioExtension {
|
||||
self.tdigest.quantiles(&PCTS, &mut out);
|
||||
let idx = start + offset;
|
||||
for (vec, &val) in pct_vecs.iter_mut().zip(out.iter()) {
|
||||
vec.truncate_push_at(idx, StoredF32::from(val as f32))?;
|
||||
vec.truncate_push_at(idx, BasisPoints32::from(val))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let _lock = exit.lock();
|
||||
self.mut_ratio_vecs()
|
||||
self.mut_pct_vecs()
|
||||
.try_for_each(|v| v.flush())?;
|
||||
}
|
||||
|
||||
@@ -201,13 +201,13 @@ impl ComputedFromHeightRatioExtension {
|
||||
metric_price: &impl ReadableVec<Height, Cents>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
use crate::internal::PriceTimesRatioCents;
|
||||
use crate::internal::PriceTimesRatioBp32Cents;
|
||||
|
||||
macro_rules! compute_band {
|
||||
($usd_field:ident, $band_source:expr) => {
|
||||
self.$usd_field
|
||||
.cents
|
||||
.compute_binary::<Cents, StoredF32, PriceTimesRatioCents>(
|
||||
.compute_binary::<Cents, BasisPoints32, PriceTimesRatioBp32Cents>(
|
||||
starting_indexes.height,
|
||||
metric_price,
|
||||
$band_source,
|
||||
@@ -216,12 +216,12 @@ impl ComputedFromHeightRatioExtension {
|
||||
};
|
||||
}
|
||||
|
||||
compute_band!(ratio_pct99_price, &self.ratio_pct99.height);
|
||||
compute_band!(ratio_pct98_price, &self.ratio_pct98.height);
|
||||
compute_band!(ratio_pct95_price, &self.ratio_pct95.height);
|
||||
compute_band!(ratio_pct5_price, &self.ratio_pct5.height);
|
||||
compute_band!(ratio_pct2_price, &self.ratio_pct2.height);
|
||||
compute_band!(ratio_pct1_price, &self.ratio_pct1.height);
|
||||
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);
|
||||
|
||||
// Stddev cents bands
|
||||
self.ratio_sd
|
||||
@@ -236,16 +236,16 @@ impl ComputedFromHeightRatioExtension {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mut_ratio_vecs(
|
||||
fn mut_pct_vecs(
|
||||
&mut self,
|
||||
) -> impl Iterator<Item = &mut EagerVec<PcoVec<Height, StoredF32>>> {
|
||||
) -> impl Iterator<Item = &mut EagerVec<PcoVec<Height, BasisPoints32>>> {
|
||||
[
|
||||
&mut self.ratio_pct1.height,
|
||||
&mut self.ratio_pct2.height,
|
||||
&mut self.ratio_pct5.height,
|
||||
&mut self.ratio_pct95.height,
|
||||
&mut self.ratio_pct98.height,
|
||||
&mut self.ratio_pct99.height,
|
||||
&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,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
@@ -8,16 +8,17 @@ pub use price_extended::*;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Cents, Height, StoredF32, Version};
|
||||
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
|
||||
use brk_types::{BasisPoints32, Cents, Height, StoredF32, Version};
|
||||
use vecdb::{Database, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{ComputeIndexes, indexes};
|
||||
use crate::{ComputeIndexes, indexes, internal::Bp32ToFloat};
|
||||
|
||||
use super::ComputedFromHeight;
|
||||
use super::{ComputedFromHeight, LazyFromHeight};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct ComputedFromHeightRatio<M: StorageMode = Rw> {
|
||||
pub ratio: ComputedFromHeight<StoredF32, M>,
|
||||
pub bps: ComputedFromHeight<BasisPoints32, M>,
|
||||
pub ratio: LazyFromHeight<StoredF32, BasisPoints32>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::TWO;
|
||||
@@ -28,12 +29,28 @@ impl ComputedFromHeightRatio {
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Self::forced_import_raw(db, &format!("{name}_ratio"), version, indexes)
|
||||
}
|
||||
|
||||
pub(crate) fn forced_import_raw(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
Ok(Self {
|
||||
ratio: ComputedFromHeight::forced_import(db, &format!("{name}_ratio"), v, indexes)?,
|
||||
})
|
||||
let bps = ComputedFromHeight::forced_import(db, &format!("{name}_bps"), v, indexes)?;
|
||||
|
||||
let ratio = LazyFromHeight::from_computed::<Bp32ToFloat>(
|
||||
name,
|
||||
v,
|
||||
bps.height.read_only_boxed_clone(),
|
||||
&bps,
|
||||
);
|
||||
|
||||
Ok(Self { bps, ratio })
|
||||
}
|
||||
|
||||
/// Compute ratio = close_price / metric_price at height level (both in cents)
|
||||
@@ -44,15 +61,15 @@ impl ComputedFromHeightRatio {
|
||||
metric_price: &impl ReadableVec<Height, Cents>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.ratio.height.compute_transform2(
|
||||
self.bps.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
close_price,
|
||||
metric_price,
|
||||
|(i, close, price, ..)| {
|
||||
if price == Cents::ZERO {
|
||||
(i, StoredF32::from(1.0))
|
||||
(i, BasisPoints32::from(1.0))
|
||||
} else {
|
||||
(i, StoredF32::from(f64::from(close) / f64::from(price)))
|
||||
(i, BasisPoints32::from(f64::from(close) / f64::from(price)))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredF32, Version};
|
||||
use brk_types::{BasisPoints16, Height, StoredF32, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode, UnaryTransform};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{Emas1w1m, NumericValue, PercentFromHeight},
|
||||
internal::{Bp16ToFloat, Bp16ToPercent, Emas1w1m, NumericValue, PercentFromHeight},
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -45,6 +45,23 @@ where
|
||||
})?))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl PercentRollingEmas1w1m<BasisPoints16> {
|
||||
pub(crate) fn forced_import_bp16(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Self::forced_import::<Bp16ToFloat, Bp16ToPercent>(db, name, version, indexes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> PercentRollingEmas1w1m<B>
|
||||
where
|
||||
B: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn compute_from_24h(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{StoredF32, Version};
|
||||
use brk_types::{BasisPoints16, StoredF32, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Rw, StorageMode, UnaryTransform};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{NumericValue, PercentFromHeight, Windows},
|
||||
internal::{Bp16ToFloat, Bp16ToPercent, NumericValue, PercentFromHeight, Windows},
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -45,3 +45,14 @@ where
|
||||
})?))
|
||||
}
|
||||
}
|
||||
|
||||
impl PercentRollingWindows<BasisPoints16> {
|
||||
pub(crate) fn forced_import_bp16(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Self::forced_import::<Bp16ToFloat, Bp16ToPercent>(db, name, version, indexes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{BasisPoints16, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bp16ToFloat;
|
||||
|
||||
impl UnaryTransform<BasisPoints16, StoredF32> for Bp16ToFloat {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints16) -> StoredF32 {
|
||||
StoredF32::from(bp.to_f32())
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{BasisPoints16, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bp16ToPercent;
|
||||
|
||||
impl UnaryTransform<BasisPoints16, StoredF32> for Bp16ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints16) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{BasisPoints32, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bp32ToFloat;
|
||||
|
||||
impl UnaryTransform<BasisPoints32, StoredF32> for Bp32ToFloat {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints32) -> StoredF32 {
|
||||
StoredF32::from(bp.to_f32())
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{BasisPoints32, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bp32ToPercent;
|
||||
|
||||
impl UnaryTransform<BasisPoints32, StoredF32> for Bp32ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints32) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{BasisPointsSigned16, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bps16ToFloat;
|
||||
|
||||
impl UnaryTransform<BasisPointsSigned16, StoredF32> for Bps16ToFloat {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned16) -> StoredF32 {
|
||||
StoredF32::from(bp.to_f32())
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{BasisPointsSigned16, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bps16ToPercent;
|
||||
|
||||
impl UnaryTransform<BasisPointsSigned16, StoredF32> for Bps16ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned16) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{BasisPointsSigned32, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bps32ToFloat;
|
||||
|
||||
impl UnaryTransform<BasisPointsSigned32, StoredF32> for Bps32ToFloat {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned32) -> StoredF32 {
|
||||
StoredF32::from(bp.to_f32())
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{BasisPointsSigned32, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bps32ToPercent;
|
||||
|
||||
impl UnaryTransform<BasisPointsSigned32, StoredF32> for Bps32ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned32) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
use brk_types::{BasisPoints16, BasisPoints32, BasisPointsSigned16, BasisPointsSigned32, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bp16ToFloat;
|
||||
|
||||
impl UnaryTransform<BasisPoints16, StoredF32> for Bp16ToFloat {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints16) -> StoredF32 {
|
||||
StoredF32::from(bp.to_f32())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bp32ToFloat;
|
||||
|
||||
impl UnaryTransform<BasisPoints32, StoredF32> for Bp32ToFloat {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints32) -> StoredF32 {
|
||||
StoredF32::from(bp.to_f32())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bps16ToFloat;
|
||||
|
||||
impl UnaryTransform<BasisPointsSigned16, StoredF32> for Bps16ToFloat {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned16) -> StoredF32 {
|
||||
StoredF32::from(bp.to_f32())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bps32ToFloat;
|
||||
|
||||
impl UnaryTransform<BasisPointsSigned32, StoredF32> for Bps32ToFloat {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned32) -> StoredF32 {
|
||||
StoredF32::from(bp.to_f32())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
use brk_types::{BasisPoints16, BasisPointsSigned16, BasisPointsSigned32, StoredF32};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct Bp16ToPercent;
|
||||
|
||||
impl UnaryTransform<BasisPoints16, StoredF32> for Bp16ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints16) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bps16ToPercent;
|
||||
|
||||
impl UnaryTransform<BasisPointsSigned16, StoredF32> for Bps16ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned16) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Bps32ToPercent;
|
||||
|
||||
impl UnaryTransform<BasisPointsSigned32, StoredF32> for Bps32ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned32) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
use brk_types::{Cents, CentsSigned, Dollars, Sats};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// CentsUnsigned -> Dollars (convert cents to dollars for display)
|
||||
pub struct CentsUnsignedToDollars;
|
||||
|
||||
impl UnaryTransform<Cents, Dollars> for CentsUnsignedToDollars {
|
||||
#[inline(always)]
|
||||
fn apply(cents: Cents) -> Dollars {
|
||||
cents.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Cents -> -Dollars (negate after converting to dollars)
|
||||
/// Avoids lazy-from-lazy by combining both transforms.
|
||||
pub struct NegCentsUnsignedToDollars;
|
||||
|
||||
impl UnaryTransform<Cents, Dollars> for NegCentsUnsignedToDollars {
|
||||
#[inline(always)]
|
||||
fn apply(cents: Cents) -> Dollars {
|
||||
-Dollars::from(cents)
|
||||
}
|
||||
}
|
||||
|
||||
/// CentsSigned -> Dollars (convert signed cents to dollars for display)
|
||||
pub struct CentsSignedToDollars;
|
||||
|
||||
impl UnaryTransform<CentsSigned, Dollars> for CentsSignedToDollars {
|
||||
#[inline(always)]
|
||||
fn apply(cents: CentsSigned) -> Dollars {
|
||||
cents.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// CentsUnsigned -> Sats (sats per dollar: 1 BTC / price)
|
||||
pub struct CentsUnsignedToSats;
|
||||
|
||||
impl UnaryTransform<Cents, Sats> for CentsUnsignedToSats {
|
||||
#[inline(always)]
|
||||
fn apply(cents: Cents) -> Sats {
|
||||
let dollars = Dollars::from(cents);
|
||||
if dollars == Dollars::ZERO {
|
||||
Sats::ZERO
|
||||
} else {
|
||||
Sats::ONE_BTC / dollars
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::Cents;
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Cents -> Cents/2 (for supply_halved_cents)
|
||||
pub struct HalveCents;
|
||||
|
||||
impl UnaryTransform<Cents, Cents> for HalveCents {
|
||||
#[inline(always)]
|
||||
fn apply(cents: Cents) -> Cents {
|
||||
cents / 2u64
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::{CentsSigned, Dollars};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// CentsSigned -> Dollars (convert signed cents to dollars for display)
|
||||
pub struct CentsSignedToDollars;
|
||||
|
||||
impl UnaryTransform<CentsSigned, Dollars> for CentsSignedToDollars {
|
||||
#[inline(always)]
|
||||
fn apply(cents: CentsSigned) -> Dollars {
|
||||
cents.into()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::{Cents, Dollars};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// CentsUnsigned -> Dollars (convert cents to dollars for display)
|
||||
pub struct CentsUnsignedToDollars;
|
||||
|
||||
impl UnaryTransform<Cents, Dollars> for CentsUnsignedToDollars {
|
||||
#[inline(always)]
|
||||
fn apply(cents: Cents) -> Dollars {
|
||||
cents.into()
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
use brk_types::{Cents, Dollars, Sats};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// CentsUnsigned -> Sats (sats per dollar: 1 BTC / price)
|
||||
pub struct CentsUnsignedToSats;
|
||||
|
||||
impl UnaryTransform<Cents, Sats> for CentsUnsignedToSats {
|
||||
#[inline(always)]
|
||||
fn apply(cents: Cents) -> Sats {
|
||||
let dollars = Dollars::from(cents);
|
||||
if dollars == Dollars::ZERO {
|
||||
Sats::ZERO
|
||||
} else {
|
||||
Sats::ONE_BTC / dollars
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::Dollars;
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Dollars -> Dollars/2 (for supply_halved_usd)
|
||||
pub struct HalveDollars;
|
||||
|
||||
impl UnaryTransform<Dollars, Dollars> for HalveDollars {
|
||||
#[inline(always)]
|
||||
fn apply(dollars: Dollars) -> Dollars {
|
||||
dollars.halved()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
use brk_types::{Bitcoin, Cents, Dollars, Sats};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Sats -> Sats/2 (for supply_halved)
|
||||
pub struct HalveSats;
|
||||
|
||||
impl UnaryTransform<Sats, Sats> for HalveSats {
|
||||
#[inline(always)]
|
||||
fn apply(sats: Sats) -> Sats {
|
||||
sats / 2
|
||||
}
|
||||
}
|
||||
|
||||
/// Sats -> Bitcoin/2 (halve then convert to bitcoin)
|
||||
/// Avoids lazy-from-lazy by combining both transforms
|
||||
pub struct HalveSatsToBitcoin;
|
||||
|
||||
impl UnaryTransform<Sats, Bitcoin> for HalveSatsToBitcoin {
|
||||
#[inline(always)]
|
||||
fn apply(sats: Sats) -> Bitcoin {
|
||||
Bitcoin::from(sats / 2)
|
||||
}
|
||||
}
|
||||
|
||||
/// Cents -> Cents/2 (for supply_halved_cents)
|
||||
pub struct HalveCents;
|
||||
|
||||
impl UnaryTransform<Cents, Cents> for HalveCents {
|
||||
#[inline(always)]
|
||||
fn apply(cents: Cents) -> Cents {
|
||||
cents / 2u64
|
||||
}
|
||||
}
|
||||
|
||||
/// Dollars -> Dollars/2 (for supply_halved_usd)
|
||||
pub struct HalveDollars;
|
||||
|
||||
impl UnaryTransform<Dollars, Dollars> for HalveDollars {
|
||||
#[inline(always)]
|
||||
fn apply(dollars: Dollars) -> Dollars {
|
||||
dollars.halved()
|
||||
}
|
||||
}
|
||||
@@ -1,86 +1,43 @@
|
||||
mod bp16_to_float;
|
||||
mod bp16_to_percent;
|
||||
mod bp32_to_float;
|
||||
mod bp32_to_percent;
|
||||
mod bps16_to_float;
|
||||
mod bps16_to_percent;
|
||||
mod bps32_to_float;
|
||||
mod bps32_to_percent;
|
||||
mod block_count_target;
|
||||
mod cents_halve;
|
||||
mod identity;
|
||||
mod bps_to_float;
|
||||
mod bps_to_percent;
|
||||
mod cents_convert;
|
||||
mod cents_plus;
|
||||
mod cents_signed_to_dollars;
|
||||
mod cents_subtract_to_cents_signed;
|
||||
mod cents_times_tenths;
|
||||
mod cents_to_dollars;
|
||||
mod cents_to_sats;
|
||||
mod dollar_halve;
|
||||
mod days_to_years;
|
||||
mod dollars_to_sats_fract;
|
||||
mod neg_cents_to_dollars;
|
||||
mod ohlc_cents_to_dollars;
|
||||
mod ohlc_cents_to_sats;
|
||||
mod percentage_diff_close_cents;
|
||||
mod percentage_diff_close_dollars;
|
||||
mod price_times_ratio_cents;
|
||||
mod ratio32;
|
||||
mod ratio_cents64;
|
||||
mod halve;
|
||||
mod identity;
|
||||
mod ohlc;
|
||||
mod per_sec;
|
||||
mod ratio_bp16;
|
||||
mod ratio_bps16;
|
||||
mod ratio_bps32;
|
||||
mod ratio_u64_f32;
|
||||
mod return_f32_tenths;
|
||||
mod return_i8;
|
||||
mod return_u16;
|
||||
mod sats_to_cents;
|
||||
|
||||
mod sat_halve;
|
||||
mod sat_halve_to_bitcoin;
|
||||
mod price_times_ratio_cents;
|
||||
mod ratio;
|
||||
mod ratio_cents64;
|
||||
mod return_const;
|
||||
mod sat_mask;
|
||||
mod sat_to_bitcoin;
|
||||
mod days_to_years;
|
||||
mod sats_to_cents;
|
||||
mod volatility;
|
||||
|
||||
pub use bp16_to_float::*;
|
||||
pub use bp16_to_percent::*;
|
||||
pub use bp32_to_float::*;
|
||||
pub use bp32_to_percent::*;
|
||||
pub use bps16_to_float::*;
|
||||
pub use bps16_to_percent::*;
|
||||
pub use bps32_to_float::*;
|
||||
pub use bps32_to_percent::*;
|
||||
pub use block_count_target::*;
|
||||
pub use cents_halve::*;
|
||||
pub use identity::*;
|
||||
pub use bps_to_float::*;
|
||||
pub use bps_to_percent::*;
|
||||
pub use cents_convert::*;
|
||||
pub use cents_plus::*;
|
||||
pub use cents_signed_to_dollars::*;
|
||||
pub use cents_subtract_to_cents_signed::*;
|
||||
pub use cents_times_tenths::*;
|
||||
pub use cents_to_dollars::*;
|
||||
pub use cents_to_sats::*;
|
||||
pub use neg_cents_to_dollars::*;
|
||||
pub use ohlc_cents_to_dollars::*;
|
||||
pub use ohlc_cents_to_sats::*;
|
||||
pub use dollar_halve::*;
|
||||
pub use days_to_years::*;
|
||||
pub use dollars_to_sats_fract::*;
|
||||
pub use percentage_diff_close_cents::*;
|
||||
pub use percentage_diff_close_dollars::*;
|
||||
pub use price_times_ratio_cents::*;
|
||||
pub use ratio32::*;
|
||||
pub use ratio_cents64::*;
|
||||
pub use halve::*;
|
||||
pub use identity::*;
|
||||
pub use ohlc::*;
|
||||
pub use per_sec::*;
|
||||
pub use ratio_bp16::*;
|
||||
pub use ratio_bps16::*;
|
||||
pub use ratio_bps32::*;
|
||||
pub use ratio_u64_f32::*;
|
||||
pub use return_f32_tenths::*;
|
||||
pub use return_i8::*;
|
||||
pub use return_u16::*;
|
||||
pub use sats_to_cents::*;
|
||||
pub use sat_halve::*;
|
||||
pub use sat_halve_to_bitcoin::*;
|
||||
pub use price_times_ratio_cents::*;
|
||||
pub use ratio::*;
|
||||
pub use ratio_cents64::*;
|
||||
pub use return_const::*;
|
||||
pub use sat_mask::*;
|
||||
pub use sat_to_bitcoin::*;
|
||||
pub use days_to_years::*;
|
||||
pub use sats_to_cents::*;
|
||||
pub use volatility::*;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
use brk_types::{Cents, Dollars};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Cents -> -Dollars (negate after converting to dollars)
|
||||
/// Avoids lazy-from-lazy by combining both transforms.
|
||||
pub struct NegCentsUnsignedToDollars;
|
||||
|
||||
impl UnaryTransform<Cents, Dollars> for NegCentsUnsignedToDollars {
|
||||
#[inline(always)]
|
||||
fn apply(cents: Cents) -> Dollars {
|
||||
-Dollars::from(cents)
|
||||
}
|
||||
}
|
||||
+10
-1
@@ -1,8 +1,17 @@
|
||||
use brk_types::{Close, High, Low, OHLCCents, OHLCSats, Open};
|
||||
use brk_types::{Close, High, Low, OHLCCents, OHLCDollars, OHLCSats, Open};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
use super::CentsUnsignedToSats;
|
||||
|
||||
pub struct OhlcCentsToDollars;
|
||||
|
||||
impl UnaryTransform<OHLCCents, OHLCDollars> for OhlcCentsToDollars {
|
||||
#[inline(always)]
|
||||
fn apply(cents: OHLCCents) -> OHLCDollars {
|
||||
OHLCDollars::from(cents)
|
||||
}
|
||||
}
|
||||
|
||||
/// OHLCCents -> OHLCSats with high/low swapped (inverse price relationship).
|
||||
pub struct OhlcCentsToSats;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
use brk_types::{OHLCCents, OHLCDollars};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
pub struct OhlcCentsToDollars;
|
||||
|
||||
impl UnaryTransform<OHLCCents, OHLCDollars> for OhlcCentsToDollars {
|
||||
#[inline(always)]
|
||||
fn apply(cents: OHLCCents) -> OHLCDollars {
|
||||
OHLCDollars::from(cents)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
use brk_types::{Cents, StoredF32};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
/// (Cents, Cents) -> StoredF32 percentage difference ((a/b - 1) * 100)
|
||||
pub struct PercentageDiffCents;
|
||||
|
||||
impl BinaryTransform<Cents, Cents, StoredF32> for PercentageDiffCents {
|
||||
#[inline(always)]
|
||||
fn apply(close: Cents, base: Cents) -> StoredF32 {
|
||||
let base_f64 = f64::from(base);
|
||||
if base_f64 == 0.0 {
|
||||
StoredF32::default()
|
||||
} else {
|
||||
StoredF32::from((f64::from(close) / base_f64 - 1.0) * 100.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
use brk_types::{Dollars, StoredF32};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
/// (Dollars, Dollars) -> StoredF32 percentage difference ((a/b - 1) × 100)
|
||||
pub struct PercentageDiffDollars;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, StoredF32> for PercentageDiffDollars {
|
||||
#[inline(always)]
|
||||
fn apply(close: Dollars, base: Dollars) -> StoredF32 {
|
||||
if base == Dollars::ZERO {
|
||||
StoredF32::default()
|
||||
} else {
|
||||
StoredF32::from((*close / *base - 1.0) * 100.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use brk_types::{Cents, StoredF32};
|
||||
use brk_types::{BasisPoints32, Cents, StoredF32};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
pub struct PriceTimesRatioCents;
|
||||
@@ -9,3 +9,12 @@ impl BinaryTransform<Cents, StoredF32, Cents> for PriceTimesRatioCents {
|
||||
Cents::from(f64::from(price) * f64::from(ratio))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PriceTimesRatioBp32Cents;
|
||||
|
||||
impl BinaryTransform<Cents, BasisPoints32, Cents> for PriceTimesRatioBp32Cents {
|
||||
#[inline(always)]
|
||||
fn apply(price: Cents, ratio: BasisPoints32) -> Cents {
|
||||
Cents::from(f64::from(price) * f64::from(ratio))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
use brk_types::{
|
||||
BasisPoints16, BasisPoints32, BasisPointsSigned16, BasisPointsSigned32, Cents, CentsSigned,
|
||||
Dollars, Sats, StoredF32, StoredU32, StoredU64,
|
||||
};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
// === BasisPoints16 (unsigned) ratios ===
|
||||
|
||||
/// (StoredU64, StoredU64) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioU64Bp16;
|
||||
|
||||
impl BinaryTransform<StoredU64, StoredU64, BasisPoints16> for RatioU64Bp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: StoredU64, denominator: StoredU64) -> BasisPoints16 {
|
||||
if *denominator > 0 {
|
||||
BasisPoints16::from(*numerator as f64 / *denominator as f64)
|
||||
} else {
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Sats, Sats) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioSatsBp16;
|
||||
|
||||
impl BinaryTransform<Sats, Sats, BasisPoints16> for RatioSatsBp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Sats, denominator: Sats) -> BasisPoints16 {
|
||||
if *denominator > 0 {
|
||||
BasisPoints16::from(*numerator as f64 / *denominator as f64)
|
||||
} else {
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Cents, Cents) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioCentsBp16;
|
||||
|
||||
impl BinaryTransform<Cents, Cents, BasisPoints16> for RatioCentsBp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Cents, denominator: Cents) -> BasisPoints16 {
|
||||
if denominator == Cents::ZERO {
|
||||
BasisPoints16::ZERO
|
||||
} else {
|
||||
BasisPoints16::from(numerator.inner() as f64 / denominator.inner() as f64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (StoredU32, StoredU32) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioU32Bp16;
|
||||
|
||||
impl BinaryTransform<StoredU32, StoredU32, BasisPoints16> for RatioU32Bp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: StoredU32, denominator: StoredU32) -> BasisPoints16 {
|
||||
if *denominator > 0 {
|
||||
BasisPoints16::from(*numerator as f64 / *denominator as f64)
|
||||
} else {
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioDollarsBp16;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPoints16> for RatioDollarsBp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Dollars, denominator: Dollars) -> BasisPoints16 {
|
||||
let ratio = *(numerator / denominator);
|
||||
if ratio.is_finite() {
|
||||
BasisPoints16::from(ratio)
|
||||
} else {
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === BasisPointsSigned16 (signed) ratios ===
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPointsSigned16 ratio (a/b × 10000)
|
||||
pub struct RatioDollarsBps16;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPointsSigned16> for RatioDollarsBps16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Dollars, denominator: Dollars) -> BasisPointsSigned16 {
|
||||
let ratio = *(numerator / denominator);
|
||||
if ratio.is_finite() {
|
||||
BasisPointsSigned16::from(ratio)
|
||||
} else {
|
||||
BasisPointsSigned16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPointsSigned16 negated ratio (-(a/b) × 10000)
|
||||
pub struct NegRatioDollarsBps16;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPointsSigned16> for NegRatioDollarsBps16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Dollars, denominator: Dollars) -> BasisPointsSigned16 {
|
||||
let ratio = *(numerator / denominator);
|
||||
if ratio.is_finite() {
|
||||
BasisPointsSigned16::from(-ratio)
|
||||
} else {
|
||||
BasisPointsSigned16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (CentsSigned, Cents) -> BasisPointsSigned16 ratio (a/b × 10000)
|
||||
pub struct RatioCentsSignedCentsBps16;
|
||||
|
||||
impl BinaryTransform<CentsSigned, Cents, BasisPointsSigned16> for RatioCentsSignedCentsBps16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: CentsSigned, denominator: Cents) -> BasisPointsSigned16 {
|
||||
if denominator == Cents::ZERO {
|
||||
BasisPointsSigned16::ZERO
|
||||
} else {
|
||||
BasisPointsSigned16::from(numerator.inner() as f64 / denominator.inner() as f64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (CentsSigned, Dollars) -> BasisPointsSigned16 ratio (a/b × 10000)
|
||||
pub struct RatioCentsSignedDollarsBps16;
|
||||
|
||||
impl BinaryTransform<CentsSigned, Dollars, BasisPointsSigned16> for RatioCentsSignedDollarsBps16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: CentsSigned, denominator: Dollars) -> BasisPointsSigned16 {
|
||||
let d: f64 = denominator.into();
|
||||
if d > 0.0 {
|
||||
BasisPointsSigned16::from(numerator.inner() as f64 / 100.0 / d)
|
||||
} else {
|
||||
BasisPointsSigned16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === BasisPoints32 (unsigned) ratios ===
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPoints32 ratio (a / b × 10000)
|
||||
pub struct RatioDollarsBp32;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPoints32> for RatioDollarsBp32 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Dollars, denominator: Dollars) -> BasisPoints32 {
|
||||
BasisPoints32::from(f64::from(numerator) / f64::from(denominator))
|
||||
}
|
||||
}
|
||||
|
||||
// === BasisPointsSigned32 (signed) ratio diffs ===
|
||||
|
||||
/// (StoredF32, StoredF32) -> BasisPointsSigned32 ratio diff ((a/b - 1) × 10000)
|
||||
pub struct RatioDiffF32Bps32;
|
||||
|
||||
impl BinaryTransform<StoredF32, StoredF32, BasisPointsSigned32> for RatioDiffF32Bps32 {
|
||||
#[inline(always)]
|
||||
fn apply(value: StoredF32, base: StoredF32) -> BasisPointsSigned32 {
|
||||
if base.is_nan() || *base == 0.0 {
|
||||
BasisPointsSigned32::ZERO
|
||||
} else {
|
||||
BasisPointsSigned32::from((*value / *base - 1.0) as f64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPointsSigned32 ratio diff ((a/b - 1) × 10000)
|
||||
pub struct RatioDiffDollarsBps32;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPointsSigned32> for RatioDiffDollarsBps32 {
|
||||
#[inline(always)]
|
||||
fn apply(close: Dollars, base: Dollars) -> BasisPointsSigned32 {
|
||||
let base_f64: f64 = base.into();
|
||||
if base_f64 == 0.0 {
|
||||
BasisPointsSigned32::ZERO
|
||||
} else {
|
||||
BasisPointsSigned32::from(f64::from(close) / base_f64 - 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Cents, Cents) -> BasisPointsSigned32 ratio diff ((a/b - 1) × 10000)
|
||||
pub struct RatioDiffCentsBps32;
|
||||
|
||||
impl BinaryTransform<Cents, Cents, BasisPointsSigned32> for RatioDiffCentsBps32 {
|
||||
#[inline(always)]
|
||||
fn apply(close: Cents, base: Cents) -> BasisPointsSigned32 {
|
||||
let base_f64 = f64::from(base);
|
||||
if base_f64 == 0.0 {
|
||||
BasisPointsSigned32::ZERO
|
||||
} else {
|
||||
BasisPointsSigned32::from(f64::from(close) / base_f64 - 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
use brk_types::{Dollars, StoredF32};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
/// (Dollars, Dollars) -> StoredF32 ratio
|
||||
/// Used for computing percentage ratios like profit/total, loss/total, etc.
|
||||
pub struct Ratio32;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, StoredF32> for Ratio32 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Dollars, denominator: Dollars) -> StoredF32 {
|
||||
StoredF32::from(numerator / denominator)
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
use brk_types::{BasisPoints16, Cents, Dollars, Sats, StoredU32, StoredU64};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
/// (StoredU64, StoredU64) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioU64Bp16;
|
||||
|
||||
impl BinaryTransform<StoredU64, StoredU64, BasisPoints16> for RatioU64Bp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: StoredU64, denominator: StoredU64) -> BasisPoints16 {
|
||||
if *denominator > 0 {
|
||||
BasisPoints16::from(*numerator as f64 / *denominator as f64)
|
||||
} else {
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Sats, Sats) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioSatsBp16;
|
||||
|
||||
impl BinaryTransform<Sats, Sats, BasisPoints16> for RatioSatsBp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Sats, denominator: Sats) -> BasisPoints16 {
|
||||
if *denominator > 0 {
|
||||
BasisPoints16::from(*numerator as f64 / *denominator as f64)
|
||||
} else {
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Cents, Cents) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioCentsBp16;
|
||||
|
||||
impl BinaryTransform<Cents, Cents, BasisPoints16> for RatioCentsBp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Cents, denominator: Cents) -> BasisPoints16 {
|
||||
if denominator == Cents::ZERO {
|
||||
BasisPoints16::ZERO
|
||||
} else {
|
||||
BasisPoints16::from(numerator.inner() as f64 / denominator.inner() as f64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (StoredU32, StoredU32) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioU32Bp16;
|
||||
|
||||
impl BinaryTransform<StoredU32, StoredU32, BasisPoints16> for RatioU32Bp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: StoredU32, denominator: StoredU32) -> BasisPoints16 {
|
||||
if *denominator > 0 {
|
||||
BasisPoints16::from(*numerator as f64 / *denominator as f64)
|
||||
} else {
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPoints16 ratio (a/b × 10000)
|
||||
pub struct RatioDollarsBp16;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPoints16> for RatioDollarsBp16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Dollars, denominator: Dollars) -> BasisPoints16 {
|
||||
let ratio = *(numerator / denominator);
|
||||
if ratio.is_finite() {
|
||||
BasisPoints16::from(ratio)
|
||||
} else {
|
||||
BasisPoints16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
use brk_types::{BasisPointsSigned16, Cents, CentsSigned, Dollars};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPointsSigned16 ratio (a/b × 10000)
|
||||
pub struct RatioDollarsBps16;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPointsSigned16> for RatioDollarsBps16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Dollars, denominator: Dollars) -> BasisPointsSigned16 {
|
||||
let ratio = *(numerator / denominator);
|
||||
if ratio.is_finite() {
|
||||
BasisPointsSigned16::from(ratio)
|
||||
} else {
|
||||
BasisPointsSigned16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPointsSigned16 negated ratio (-(a/b) × 10000)
|
||||
pub struct NegRatioDollarsBps16;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPointsSigned16> for NegRatioDollarsBps16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: Dollars, denominator: Dollars) -> BasisPointsSigned16 {
|
||||
let ratio = *(numerator / denominator);
|
||||
if ratio.is_finite() {
|
||||
BasisPointsSigned16::from(-ratio)
|
||||
} else {
|
||||
BasisPointsSigned16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (CentsSigned, Cents) -> BasisPointsSigned16 ratio (a/b × 10000)
|
||||
pub struct RatioCentsSignedCentsBps16;
|
||||
|
||||
impl BinaryTransform<CentsSigned, Cents, BasisPointsSigned16> for RatioCentsSignedCentsBps16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: CentsSigned, denominator: Cents) -> BasisPointsSigned16 {
|
||||
if denominator == Cents::ZERO {
|
||||
BasisPointsSigned16::ZERO
|
||||
} else {
|
||||
BasisPointsSigned16::from(numerator.inner() as f64 / denominator.inner() as f64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (CentsSigned, Dollars) -> BasisPointsSigned16 ratio (a/b × 10000)
|
||||
pub struct RatioCentsSignedDollarsBps16;
|
||||
|
||||
impl BinaryTransform<CentsSigned, Dollars, BasisPointsSigned16> for RatioCentsSignedDollarsBps16 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: CentsSigned, denominator: Dollars) -> BasisPointsSigned16 {
|
||||
let d: f64 = denominator.into();
|
||||
if d > 0.0 {
|
||||
// Convert cents to dollars first, then compute ratio
|
||||
BasisPointsSigned16::from(numerator.inner() as f64 / 100.0 / d)
|
||||
} else {
|
||||
BasisPointsSigned16::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
use brk_types::{BasisPointsSigned32, Cents, Dollars};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
/// (Dollars, Dollars) -> BasisPointsSigned32 ratio diff ((a/b - 1) × 10000)
|
||||
pub struct RatioDiffDollarsBps32;
|
||||
|
||||
impl BinaryTransform<Dollars, Dollars, BasisPointsSigned32> for RatioDiffDollarsBps32 {
|
||||
#[inline(always)]
|
||||
fn apply(close: Dollars, base: Dollars) -> BasisPointsSigned32 {
|
||||
let base_f64: f64 = base.into();
|
||||
if base_f64 == 0.0 {
|
||||
BasisPointsSigned32::ZERO
|
||||
} else {
|
||||
BasisPointsSigned32::from(f64::from(close) / base_f64 - 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// (Cents, Cents) -> BasisPointsSigned32 ratio diff ((a/b - 1) × 10000)
|
||||
pub struct RatioDiffCentsBps32;
|
||||
|
||||
impl BinaryTransform<Cents, Cents, BasisPointsSigned32> for RatioDiffCentsBps32 {
|
||||
#[inline(always)]
|
||||
fn apply(close: Cents, base: Cents) -> BasisPointsSigned32 {
|
||||
let base_f64 = f64::from(base);
|
||||
if base_f64 == 0.0 {
|
||||
BasisPointsSigned32::ZERO
|
||||
} else {
|
||||
BasisPointsSigned32::from(f64::from(close) / base_f64 - 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
use brk_types::{StoredF32, StoredU64};
|
||||
use vecdb::BinaryTransform;
|
||||
|
||||
/// (StoredU64, StoredU64) -> StoredF32 ratio (a/b)
|
||||
/// Used for adoption ratio calculations (script_count / total_outputs)
|
||||
pub struct RatioU64F32;
|
||||
|
||||
impl BinaryTransform<StoredU64, StoredU64, StoredF32> for RatioU64F32 {
|
||||
#[inline(always)]
|
||||
fn apply(numerator: StoredU64, denominator: StoredU64) -> StoredF32 {
|
||||
if *denominator > 0 {
|
||||
StoredF32::from(*numerator as f64 / *denominator as f64)
|
||||
} else {
|
||||
StoredF32::from(0.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
use brk_types::{StoredF32, StoredI8, StoredU16};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Returns a constant f32 value from tenths (V=382 -> 38.2), ignoring the input.
|
||||
pub struct ReturnF32Tenths<const V: u16>;
|
||||
|
||||
impl<S, const V: u16> UnaryTransform<S, StoredF32> for ReturnF32Tenths<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredF32 {
|
||||
StoredF32::from(V as f32 / 10.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a constant u16 value, ignoring the input.
|
||||
pub struct ReturnU16<const V: u16>;
|
||||
|
||||
impl<S, const V: u16> UnaryTransform<S, StoredU16> for ReturnU16<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredU16 {
|
||||
StoredU16::new(V)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a constant i8 value, ignoring the input.
|
||||
pub struct ReturnI8<const V: i8>;
|
||||
|
||||
impl<S, const V: i8> UnaryTransform<S, StoredI8> for ReturnI8<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredI8 {
|
||||
StoredI8::new(V)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::StoredF32;
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Returns a constant f32 value from tenths (V=382 -> 38.2), ignoring the input.
|
||||
pub struct ReturnF32Tenths<const V: u16>;
|
||||
|
||||
impl<S, const V: u16> UnaryTransform<S, StoredF32> for ReturnF32Tenths<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredF32 {
|
||||
StoredF32::from(V as f32 / 10.0)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::StoredI8;
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Returns a constant i8 value, ignoring the input.
|
||||
pub struct ReturnI8<const V: i8>;
|
||||
|
||||
impl<S, const V: i8> UnaryTransform<S, StoredI8> for ReturnI8<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredI8 {
|
||||
StoredI8::new(V)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::StoredU16;
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Returns a constant u16 value, ignoring the input.
|
||||
pub struct ReturnU16<const V: u16>;
|
||||
|
||||
impl<S, const V: u16> UnaryTransform<S, StoredU16> for ReturnU16<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredU16 {
|
||||
StoredU16::new(V)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use brk_types::Sats;
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Sats -> Sats/2 (for supply_halved)
|
||||
pub struct HalveSats;
|
||||
|
||||
impl UnaryTransform<Sats, Sats> for HalveSats {
|
||||
#[inline(always)]
|
||||
fn apply(sats: Sats) -> Sats {
|
||||
sats / 2
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
use brk_types::{Bitcoin, Sats};
|
||||
use vecdb::UnaryTransform;
|
||||
|
||||
/// Sats -> Bitcoin/2 (halve then convert to bitcoin)
|
||||
/// Avoids lazy-from-lazy by combining both transforms
|
||||
pub struct HalveSatsToBitcoin;
|
||||
|
||||
impl UnaryTransform<Sats, Bitcoin> for HalveSatsToBitcoin {
|
||||
#[inline(always)]
|
||||
fn apply(sats: Sats) -> Bitcoin {
|
||||
Bitcoin::from(sats / 2)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user