mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-29 19:58:10 -07:00
computer: snapshot
This commit is contained in:
@@ -1,258 +1,48 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{StoredF32, StoredI16, StoredU16, Version};
|
||||
use vecdb::{AnyVec, Database, Exit, PAGE_SIZE};
|
||||
|
||||
use crate::grouped::Source;
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromHeight, VecBuilderOptions},
|
||||
grouped::{ConstantVecs, ReturnF32Tenths, ReturnI16, ReturnU16},
|
||||
indexes,
|
||||
};
|
||||
|
||||
pub const DB_NAME: &str = "constants";
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
db: Database,
|
||||
|
||||
pub constant_0: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_1: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_2: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_3: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_4: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_38_2: ComputedVecsFromHeight<StoredF32>,
|
||||
pub constant_50: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_61_8: ComputedVecsFromHeight<StoredF32>,
|
||||
pub constant_100: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_600: ComputedVecsFromHeight<StoredU16>,
|
||||
pub constant_minus_1: ComputedVecsFromHeight<StoredI16>,
|
||||
pub constant_minus_2: ComputedVecsFromHeight<StoredI16>,
|
||||
pub constant_minus_3: ComputedVecsFromHeight<StoredI16>,
|
||||
pub constant_minus_4: ComputedVecsFromHeight<StoredI16>,
|
||||
pub constant_0: ConstantVecs<StoredU16>,
|
||||
pub constant_1: ConstantVecs<StoredU16>,
|
||||
pub constant_2: ConstantVecs<StoredU16>,
|
||||
pub constant_3: ConstantVecs<StoredU16>,
|
||||
pub constant_4: ConstantVecs<StoredU16>,
|
||||
pub constant_38_2: ConstantVecs<StoredF32>,
|
||||
pub constant_50: ConstantVecs<StoredU16>,
|
||||
pub constant_61_8: ConstantVecs<StoredF32>,
|
||||
pub constant_100: ConstantVecs<StoredU16>,
|
||||
pub constant_600: ConstantVecs<StoredU16>,
|
||||
pub constant_minus_1: ConstantVecs<StoredI16>,
|
||||
pub constant_minus_2: ConstantVecs<StoredI16>,
|
||||
pub constant_minus_3: ConstantVecs<StoredI16>,
|
||||
pub constant_minus_4: ConstantVecs<StoredI16>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
parent_path: &Path,
|
||||
parent_version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let db = Database::open(&parent_path.join(DB_NAME))?;
|
||||
db.set_min_len(PAGE_SIZE * 1_000_000)?;
|
||||
pub fn new(version: Version, indexes: &indexes::Vecs) -> Self {
|
||||
let v = version + Version::ZERO;
|
||||
|
||||
let version = parent_version + Version::ZERO;
|
||||
|
||||
let this = Self {
|
||||
constant_0: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_0",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_1: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_1",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_2: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_2",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_3: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_3",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_4: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_4",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_38_2: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_38_2",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_50: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_50",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_61_8: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_61_8",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_100: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_100",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_600: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_600",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_minus_1: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_minus_1",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_minus_2: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_minus_2",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_minus_3: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_minus_3",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
constant_minus_4: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"constant_minus_4",
|
||||
Source::Compute,
|
||||
version + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
|
||||
db,
|
||||
};
|
||||
|
||||
this.db.retain_regions(
|
||||
this.iter_any_exportable()
|
||||
.flat_map(|v| v.region_names())
|
||||
.collect(),
|
||||
)?;
|
||||
this.db.compact()?;
|
||||
|
||||
Ok(this)
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_(indexes, starting_indexes, exit)?;
|
||||
let _lock = exit.lock();
|
||||
self.db.compact()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
[
|
||||
(&mut self.constant_0, 0),
|
||||
(&mut self.constant_1, 1),
|
||||
(&mut self.constant_2, 2),
|
||||
(&mut self.constant_3, 3),
|
||||
(&mut self.constant_4, 4),
|
||||
(&mut self.constant_50, 50),
|
||||
(&mut self.constant_100, 100),
|
||||
(&mut self.constant_600, 600),
|
||||
]
|
||||
.into_iter()
|
||||
.try_for_each(|(vec, value)| {
|
||||
vec.compute_all(indexes, starting_indexes, exit, |vec| {
|
||||
vec.compute_to(
|
||||
starting_indexes.height,
|
||||
indexes.height_to_date.len(),
|
||||
indexes.height_to_date.version(),
|
||||
|i| (i, StoredU16::new(value)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})
|
||||
})?;
|
||||
|
||||
[
|
||||
(&mut self.constant_minus_1, -1),
|
||||
(&mut self.constant_minus_2, -2),
|
||||
(&mut self.constant_minus_3, 3),
|
||||
(&mut self.constant_minus_4, 4),
|
||||
]
|
||||
.into_iter()
|
||||
.try_for_each(|(vec, value)| {
|
||||
vec.compute_all(indexes, starting_indexes, exit, |vec| {
|
||||
vec.compute_to(
|
||||
starting_indexes.height,
|
||||
indexes.height_to_date.len(),
|
||||
indexes.height_to_date.version(),
|
||||
|i| (i, StoredI16::new(value)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})
|
||||
})?;
|
||||
|
||||
[
|
||||
(&mut self.constant_38_2, 38.2),
|
||||
(&mut self.constant_61_8, 61.8),
|
||||
]
|
||||
.into_iter()
|
||||
.try_for_each(|(vec, value)| {
|
||||
vec.compute_all(indexes, starting_indexes, exit, |vec| {
|
||||
vec.compute_to(
|
||||
starting_indexes.height,
|
||||
indexes.height_to_date.len(),
|
||||
indexes.height_to_date.version(),
|
||||
|i| (i, StoredF32::from(value)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
Self {
|
||||
constant_0: ConstantVecs::new::<ReturnU16<0>>("constant_0", v, indexes),
|
||||
constant_1: ConstantVecs::new::<ReturnU16<1>>("constant_1", v, indexes),
|
||||
constant_2: ConstantVecs::new::<ReturnU16<2>>("constant_2", v, indexes),
|
||||
constant_3: ConstantVecs::new::<ReturnU16<3>>("constant_3", v, indexes),
|
||||
constant_4: ConstantVecs::new::<ReturnU16<4>>("constant_4", v, indexes),
|
||||
constant_38_2: ConstantVecs::new::<ReturnF32Tenths<382>>("constant_38_2", v, indexes),
|
||||
constant_50: ConstantVecs::new::<ReturnU16<50>>("constant_50", v, indexes),
|
||||
constant_61_8: ConstantVecs::new::<ReturnF32Tenths<618>>("constant_61_8", v, indexes),
|
||||
constant_100: ConstantVecs::new::<ReturnU16<100>>("constant_100", v, indexes),
|
||||
constant_600: ConstantVecs::new::<ReturnU16<600>>("constant_600", v, indexes),
|
||||
constant_minus_1: ConstantVecs::new::<ReturnI16<-1>>("constant_minus_1", v, indexes),
|
||||
constant_minus_2: ConstantVecs::new::<ReturnI16<-2>>("constant_minus_2", v, indexes),
|
||||
constant_minus_3: ConstantVecs::new::<ReturnI16<-3>>("constant_minus_3", v, indexes),
|
||||
constant_minus_4: ConstantVecs::new::<ReturnI16<-4>>("constant_minus_4", v, indexes),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex,
|
||||
YearIndex,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use vecdb::{Formattable, IterableCloneableVec, LazyVecFrom1, UnaryTransform, VecValue};
|
||||
|
||||
use crate::indexes;
|
||||
|
||||
/// Lazy constant vecs for all index levels.
|
||||
/// Uses const generic transforms to return the same value for every index.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ConstantVecs<T>
|
||||
where
|
||||
T: VecValue + Formattable + Serialize + JsonSchema,
|
||||
{
|
||||
pub height: LazyVecFrom1<Height, T, Height, Height>,
|
||||
pub dateindex: LazyVecFrom1<DateIndex, T, DateIndex, DateIndex>,
|
||||
pub weekindex: LazyVecFrom1<WeekIndex, T, WeekIndex, WeekIndex>,
|
||||
pub monthindex: LazyVecFrom1<MonthIndex, T, MonthIndex, MonthIndex>,
|
||||
pub quarterindex: LazyVecFrom1<QuarterIndex, T, QuarterIndex, QuarterIndex>,
|
||||
pub semesterindex: LazyVecFrom1<SemesterIndex, T, SemesterIndex, SemesterIndex>,
|
||||
pub yearindex: LazyVecFrom1<YearIndex, T, YearIndex, YearIndex>,
|
||||
pub decadeindex: LazyVecFrom1<DecadeIndex, T, DecadeIndex, DecadeIndex>,
|
||||
}
|
||||
|
||||
impl<T: VecValue + Formattable + Serialize + JsonSchema> ConstantVecs<T> {
|
||||
/// Create constant vecs using a transform that ignores input and returns a constant.
|
||||
pub fn new<F>(name: &str, version: Version, indexes: &indexes::Vecs) -> Self
|
||||
where
|
||||
F: UnaryTransform<Height, T>
|
||||
+ UnaryTransform<DateIndex, T>
|
||||
+ UnaryTransform<WeekIndex, T>
|
||||
+ UnaryTransform<MonthIndex, T>
|
||||
+ UnaryTransform<QuarterIndex, T>
|
||||
+ UnaryTransform<SemesterIndex, T>
|
||||
+ UnaryTransform<YearIndex, T>
|
||||
+ UnaryTransform<DecadeIndex, T>,
|
||||
{
|
||||
Self {
|
||||
height: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.height_to_height.boxed_clone(),
|
||||
),
|
||||
dateindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.dateindex_to_dateindex.boxed_clone(),
|
||||
),
|
||||
weekindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.weekindex_to_weekindex.boxed_clone(),
|
||||
),
|
||||
monthindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.monthindex_to_monthindex.boxed_clone(),
|
||||
),
|
||||
quarterindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.quarterindex_to_quarterindex.boxed_clone(),
|
||||
),
|
||||
semesterindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.semesterindex_to_semesterindex.boxed_clone(),
|
||||
),
|
||||
yearindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.yearindex_to_yearindex.boxed_clone(),
|
||||
),
|
||||
decadeindex: LazyVecFrom1::transformed::<F>(
|
||||
name,
|
||||
version,
|
||||
indexes.decadeindex_to_decadeindex.boxed_clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ use super::{ComputedVecValue, ComputedVecsFromDateIndex, LazyTransformBuilder};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Fully lazy version of `ComputedVecsFromDateIndex` where all vecs are lazy transforms.
|
||||
#[derive(Clone)]
|
||||
pub struct LazyVecsFromDateIndex<T, S1T = T>
|
||||
where
|
||||
@@ -42,11 +41,19 @@ where
|
||||
let v = version + VERSION;
|
||||
Self {
|
||||
dateindex: dateindex_source.map(|s| LazyVecFrom1::transformed::<F>(name, v, s)),
|
||||
dateindex_extra: LazyTransformBuilder::from_eager::<F>(name, v, &source.dateindex_extra),
|
||||
dateindex_extra: LazyTransformBuilder::from_eager::<F>(
|
||||
name,
|
||||
v,
|
||||
&source.dateindex_extra,
|
||||
),
|
||||
weekindex: LazyTransformBuilder::from_lazy::<F, _, _>(name, v, &source.weekindex),
|
||||
monthindex: LazyTransformBuilder::from_lazy::<F, _, _>(name, v, &source.monthindex),
|
||||
quarterindex: LazyTransformBuilder::from_lazy::<F, _, _>(name, v, &source.quarterindex),
|
||||
semesterindex: LazyTransformBuilder::from_lazy::<F, _, _>(name, v, &source.semesterindex),
|
||||
semesterindex: LazyTransformBuilder::from_lazy::<F, _, _>(
|
||||
name,
|
||||
v,
|
||||
&source.semesterindex,
|
||||
),
|
||||
yearindex: LazyTransformBuilder::from_lazy::<F, _, _>(name, v, &source.yearindex),
|
||||
decadeindex: LazyTransformBuilder::from_lazy::<F, _, _>(name, v, &source.decadeindex),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Sats, Version};
|
||||
use vecdb::{IterableCloneableVec, UnaryTransform};
|
||||
|
||||
use super::{ComputedValueVecsFromDateIndex, LazyVecsFromDateIndex};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Fully lazy version of `ComputedValueVecsFromDateIndex` where all fields are lazy transforms.
|
||||
/// Used for computed values like supply_half where sources are stored sats and dollars vecs.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyValueVecsFromDateIndex {
|
||||
pub sats: LazyVecsFromDateIndex<Sats, Sats>,
|
||||
pub bitcoin: LazyVecsFromDateIndex<Bitcoin, Sats>,
|
||||
pub dollars: Option<LazyVecsFromDateIndex<Dollars, Dollars>>,
|
||||
}
|
||||
|
||||
impl LazyValueVecsFromDateIndex {
|
||||
/// Create lazy dateindex value vecs from source vecs via transforms.
|
||||
///
|
||||
/// - `SatsTransform`: Transform from Sats -> Sats (e.g., HalveSats)
|
||||
/// - `BitcoinTransform`: Transform from Sats -> Bitcoin (e.g., HalveSatsToBitcoin)
|
||||
/// - `DollarsTransform`: Transform from Dollars -> Dollars (e.g., HalveDollars)
|
||||
pub fn from_source<SatsTransform, BitcoinTransform, DollarsTransform>(
|
||||
name: &str,
|
||||
source: &ComputedValueVecsFromDateIndex,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
|
||||
DollarsTransform: UnaryTransform<Dollars, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = LazyVecsFromDateIndex::from_computed::<SatsTransform>(
|
||||
name,
|
||||
v + Version::ZERO,
|
||||
source.sats.dateindex.as_ref().map(|v| v.boxed_clone()),
|
||||
&source.sats,
|
||||
);
|
||||
|
||||
let bitcoin = LazyVecsFromDateIndex::from_computed::<BitcoinTransform>(
|
||||
&format!("{name}_btc"),
|
||||
v + Version::ZERO,
|
||||
source.sats.dateindex.as_ref().map(|v| v.boxed_clone()),
|
||||
&source.sats,
|
||||
);
|
||||
|
||||
let dollars = source.dollars.as_ref().map(|dollars_source| {
|
||||
LazyVecsFromDateIndex::from_computed::<DollarsTransform>(
|
||||
&format!("{name}_usd"),
|
||||
v + Version::ZERO,
|
||||
dollars_source.dateindex.as_ref().map(|v| v.boxed_clone()),
|
||||
dollars_source,
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
|
||||
use vecdb::{BinaryTransform, IterableBoxedVec, LazyVecFrom1, LazyVecFrom2, UnaryTransform};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
/// Fully lazy version of `ComputedHeightValueVecs` where all fields are lazy transforms.
|
||||
/// Used for computed values like supply_half where sources are stored sats and dollars vecs.
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct LazyHeightValueVecs {
|
||||
pub sats: LazyVecFrom1<Height, Sats, Height, Sats>,
|
||||
pub bitcoin: LazyVecFrom1<Height, Bitcoin, Height, Sats>,
|
||||
pub dollars: Option<LazyVecFrom2<Height, Dollars, Height, Close<Dollars>, Height, Sats>>,
|
||||
}
|
||||
|
||||
impl LazyHeightValueVecs {
|
||||
/// Create lazy height value vecs from sats and price sources via transforms.
|
||||
///
|
||||
/// - `SatsTransform`: Transform from Sats -> Sats (e.g., HalveSats)
|
||||
/// - `BitcoinTransform`: Transform from Sats -> Bitcoin (e.g., HalveSatsToBitcoin)
|
||||
/// - `DollarsTransform`: Binary transform from (Close<Dollars>, Sats) -> Dollars (e.g., HalfClosePriceTimesSats)
|
||||
pub fn from_sources<SatsTransform, BitcoinTransform, DollarsTransform>(
|
||||
name: &str,
|
||||
sats_source: IterableBoxedVec<Height, Sats>,
|
||||
price_source: Option<IterableBoxedVec<Height, Close<Dollars>>>,
|
||||
version: Version,
|
||||
) -> Self
|
||||
where
|
||||
SatsTransform: UnaryTransform<Sats, Sats>,
|
||||
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
|
||||
DollarsTransform: BinaryTransform<Close<Dollars>, Sats, Dollars>,
|
||||
{
|
||||
let v = version + VERSION;
|
||||
|
||||
let sats = LazyVecFrom1::transformed::<SatsTransform>(
|
||||
name,
|
||||
v + Version::ZERO,
|
||||
sats_source.clone(),
|
||||
);
|
||||
|
||||
let bitcoin = LazyVecFrom1::transformed::<BitcoinTransform>(
|
||||
&format!("{name}_btc"),
|
||||
v + Version::ZERO,
|
||||
sats_source.clone(),
|
||||
);
|
||||
|
||||
// dollars is binary transform: price × sats (with optional halving etc)
|
||||
let dollars = price_source.map(|price| {
|
||||
LazyVecFrom2::transformed::<DollarsTransform>(
|
||||
&format!("{name}_usd"),
|
||||
v + Version::ZERO,
|
||||
price,
|
||||
sats_source,
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ mod builder_lazy;
|
||||
mod builder_transform;
|
||||
mod builder_transform2;
|
||||
mod computed;
|
||||
mod constant;
|
||||
mod computed_from_dateindex;
|
||||
mod computed_from_height;
|
||||
mod computed_from_height_strict;
|
||||
@@ -10,6 +11,8 @@ mod computed_from_txindex;
|
||||
mod lazy2_from_dateindex;
|
||||
mod lazy_from_dateindex;
|
||||
mod lazy_from_height;
|
||||
mod lazy_value_from_dateindex;
|
||||
mod lazy_value_height;
|
||||
// mod lazy_from_height_strict;
|
||||
// mod lazy_from_txindex;
|
||||
mod price_percentiles;
|
||||
@@ -27,12 +30,15 @@ pub use builder_lazy::*;
|
||||
pub use builder_transform::*;
|
||||
pub use builder_transform2::*;
|
||||
use computed::*;
|
||||
pub use constant::*;
|
||||
pub use computed_from_dateindex::*;
|
||||
pub use computed_from_height::*;
|
||||
pub use computed_from_height_strict::*;
|
||||
pub use computed_from_txindex::*;
|
||||
pub use lazy_from_dateindex::*;
|
||||
pub use lazy_from_height::*;
|
||||
pub use lazy_value_from_dateindex::*;
|
||||
pub use lazy_value_height::*;
|
||||
pub use lazy2_from_dateindex::*;
|
||||
// pub use lazy_from_height_strict::*;
|
||||
// pub use lazy_from_txindex::*;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Date, DateIndex, Dollars, StoredF32, Version};
|
||||
use vecdb::{PcoVec,
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, IterableVec,
|
||||
TypedVecIterator, VecIndex,
|
||||
PcoVec, VecIndex,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Indexes,
|
||||
grouped::{
|
||||
ComputedStandardDeviationVecsFromDateIndex, StandardDeviationVecsOptions, source::Source,
|
||||
ComputedStandardDeviationVecsFromDateIndex, LazyVecsFrom2FromDateIndex, PriceTimesRatio,
|
||||
StandardDeviationVecsOptions, source::Source,
|
||||
},
|
||||
indexes, price,
|
||||
utils::{get_percentile, OptionExt},
|
||||
utils::{OptionExt, get_percentile},
|
||||
};
|
||||
|
||||
use super::{ComputedVecsFromDateIndex, VecBuilderOptions};
|
||||
@@ -30,12 +31,12 @@ pub struct ComputedRatioVecsFromDateIndex {
|
||||
pub ratio_pct5: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub ratio_pct2: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub ratio_pct1: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub ratio_pct99_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub ratio_pct98_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub ratio_pct95_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub ratio_pct5_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub ratio_pct2_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub ratio_pct1_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub ratio_pct99_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct98_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct95_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct5_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct2_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub ratio_pct1_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
|
||||
pub ratio_sd: Option<ComputedStandardDeviationVecsFromDateIndex>,
|
||||
pub ratio_4y_sd: Option<ComputedStandardDeviationVecsFromDateIndex>,
|
||||
@@ -61,23 +62,60 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
macro_rules! import {
|
||||
($suffix:expr) => {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
db, &format!("{name}_{}", $suffix), Source::Compute, v, indexes, opts,
|
||||
).unwrap()
|
||||
db,
|
||||
&format!("{name}_{}", $suffix),
|
||||
Source::Compute,
|
||||
v,
|
||||
indexes,
|
||||
opts,
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
}
|
||||
// Create sources first so lazy vecs can reference them
|
||||
let price = source.is_compute().then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(db, name, Source::Compute, v, indexes, opts)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
macro_rules! import_sd {
|
||||
($suffix:expr, $days:expr) => {
|
||||
ComputedStandardDeviationVecsFromDateIndex::forced_import(
|
||||
db, &format!("{name}_{}", $suffix), $days, Source::Compute, v, indexes,
|
||||
db,
|
||||
&format!("{name}_{}", $suffix),
|
||||
$days,
|
||||
Source::Compute,
|
||||
v,
|
||||
indexes,
|
||||
StandardDeviationVecsOptions::default().add_all(),
|
||||
).unwrap()
|
||||
price.as_ref(),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
let ratio_pct99 = extended.then(|| import!("ratio_pct99"));
|
||||
let ratio_pct98 = extended.then(|| import!("ratio_pct98"));
|
||||
let ratio_pct95 = extended.then(|| import!("ratio_pct95"));
|
||||
let ratio_pct5 = extended.then(|| import!("ratio_pct5"));
|
||||
let ratio_pct2 = extended.then(|| import!("ratio_pct2"));
|
||||
let ratio_pct1 = extended.then(|| import!("ratio_pct1"));
|
||||
|
||||
// Create lazy usd vecs from price and ratio sources
|
||||
macro_rules! lazy_usd {
|
||||
($ratio:expr, $suffix:expr) => {
|
||||
price.as_ref().zip($ratio.as_ref()).map(|(p, r)| {
|
||||
LazyVecsFrom2FromDateIndex::from_computed::<PriceTimesRatio>(
|
||||
&format!("{name}_{}", $suffix),
|
||||
v,
|
||||
p,
|
||||
r,
|
||||
)
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
price: source.is_compute().then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(db, name, Source::Compute, v, indexes, opts).unwrap()
|
||||
}),
|
||||
ratio: import!("ratio"),
|
||||
ratio_1w_sma: extended.then(|| import!("ratio_1w_sma")),
|
||||
ratio_1m_sma: extended.then(|| import!("ratio_1m_sma")),
|
||||
@@ -85,18 +123,19 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
ratio_1y_sd: extended.then(|| import_sd!("ratio_1y", 365)),
|
||||
ratio_2y_sd: extended.then(|| import_sd!("ratio_2y", 2 * 365)),
|
||||
ratio_4y_sd: extended.then(|| import_sd!("ratio_4y", 4 * 365)),
|
||||
ratio_pct99: extended.then(|| import!("ratio_pct99")),
|
||||
ratio_pct98: extended.then(|| import!("ratio_pct98")),
|
||||
ratio_pct95: extended.then(|| import!("ratio_pct95")),
|
||||
ratio_pct5: extended.then(|| import!("ratio_pct5")),
|
||||
ratio_pct2: extended.then(|| import!("ratio_pct2")),
|
||||
ratio_pct1: extended.then(|| import!("ratio_pct1")),
|
||||
ratio_pct99_usd: extended.then(|| import!("ratio_pct99_usd")),
|
||||
ratio_pct98_usd: extended.then(|| import!("ratio_pct98_usd")),
|
||||
ratio_pct95_usd: extended.then(|| import!("ratio_pct95_usd")),
|
||||
ratio_pct5_usd: extended.then(|| import!("ratio_pct5_usd")),
|
||||
ratio_pct2_usd: extended.then(|| import!("ratio_pct2_usd")),
|
||||
ratio_pct1_usd: extended.then(|| import!("ratio_pct1_usd")),
|
||||
ratio_pct99_usd: lazy_usd!(&ratio_pct99, "ratio_pct99_usd"),
|
||||
ratio_pct98_usd: lazy_usd!(&ratio_pct98, "ratio_pct98_usd"),
|
||||
ratio_pct95_usd: lazy_usd!(&ratio_pct95, "ratio_pct95_usd"),
|
||||
ratio_pct5_usd: lazy_usd!(&ratio_pct5, "ratio_pct5_usd"),
|
||||
ratio_pct2_usd: lazy_usd!(&ratio_pct2, "ratio_pct2_usd"),
|
||||
ratio_pct1_usd: lazy_usd!(&ratio_pct1, "ratio_pct1_usd"),
|
||||
price,
|
||||
ratio_pct99,
|
||||
ratio_pct98,
|
||||
ratio_pct95,
|
||||
ratio_pct5,
|
||||
ratio_pct2,
|
||||
ratio_pct1,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -128,9 +167,8 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
) -> Result<()> {
|
||||
let closes = price.timeindexes_to_price_close.dateindex.u();
|
||||
|
||||
let price = price_opt.unwrap_or_else(|| unsafe {
|
||||
std::mem::transmute(&self.price.u().dateindex)
|
||||
});
|
||||
let price =
|
||||
price_opt.unwrap_or_else(|| unsafe { std::mem::transmute(&self.price.u().dateindex) });
|
||||
|
||||
self.ratio.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_transform2(
|
||||
@@ -283,83 +321,18 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
None as Option<&EagerVec<PcoVec<_, _>>>,
|
||||
)?;
|
||||
|
||||
let date_to_price = price_opt.unwrap_or_else(|| unsafe {
|
||||
std::mem::transmute(&self.price.u().dateindex)
|
||||
});
|
||||
|
||||
self.ratio_pct99_usd
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(starting_indexes, exit, |vec| {
|
||||
let mut iter = self
|
||||
.ratio_pct99
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.get_unwrap(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let compute_usd =
|
||||
|usd: Option<&mut ComputedVecsFromDateIndex<Dollars>>,
|
||||
source: Option<&ComputedVecsFromDateIndex<StoredF32>>| {
|
||||
usd.unwrap().compute_all(starting_indexes, exit, |vec| {
|
||||
let mut iter = source.unwrap().dateindex.u().into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
date_to_price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.get_unwrap(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})
|
||||
};
|
||||
|
||||
compute_usd(self.ratio_pct1_usd.as_mut(), self.ratio_pct1.as_ref())?;
|
||||
compute_usd(self.ratio_pct2_usd.as_mut(), self.ratio_pct2.as_ref())?;
|
||||
compute_usd(self.ratio_pct5_usd.as_mut(), self.ratio_pct5.as_ref())?;
|
||||
compute_usd(self.ratio_pct95_usd.as_mut(), self.ratio_pct95.as_ref())?;
|
||||
compute_usd(self.ratio_pct98_usd.as_mut(), self.ratio_pct98.as_ref())?;
|
||||
compute_usd(self.ratio_pct99_usd.as_mut(), self.ratio_pct99.as_ref())?;
|
||||
|
||||
self.ratio_sd.um().compute_all(
|
||||
starting_indexes,
|
||||
exit,
|
||||
self.ratio.dateindex.u(),
|
||||
Some(date_to_price),
|
||||
)?;
|
||||
self.ratio_4y_sd.um().compute_all(
|
||||
starting_indexes,
|
||||
exit,
|
||||
self.ratio.dateindex.u(),
|
||||
Some(date_to_price),
|
||||
)?;
|
||||
self.ratio_2y_sd.um().compute_all(
|
||||
starting_indexes,
|
||||
exit,
|
||||
self.ratio.dateindex.u(),
|
||||
Some(date_to_price),
|
||||
)?;
|
||||
self.ratio_1y_sd.um().compute_all(
|
||||
starting_indexes,
|
||||
exit,
|
||||
self.ratio.dateindex.u(),
|
||||
Some(date_to_price),
|
||||
)?;
|
||||
self.ratio_sd
|
||||
.um()
|
||||
.compute_all(starting_indexes, exit, self.ratio.dateindex.u())?;
|
||||
self.ratio_4y_sd
|
||||
.um()
|
||||
.compute_all(starting_indexes, exit, self.ratio.dateindex.u())?;
|
||||
self.ratio_2y_sd
|
||||
.um()
|
||||
.compute_all(starting_indexes, exit, self.ratio.dateindex.u())?;
|
||||
self.ratio_1y_sd
|
||||
.um()
|
||||
.compute_all(starting_indexes, exit, self.ratio.dateindex.u())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,13 +4,15 @@ use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Date, DateIndex, Dollars, StoredF32, Version};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, BoxedVecIterator, CollectableVec, Database, EagerVec, Exit,
|
||||
GenericStoredVec, IterableVec, PcoVec, VecIndex,
|
||||
AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, IterableVec,
|
||||
PcoVec, VecIndex,
|
||||
};
|
||||
|
||||
use crate::{Indexes, grouped::source::Source, indexes, utils::OptionExt};
|
||||
|
||||
use super::{ComputedVecsFromDateIndex, VecBuilderOptions};
|
||||
use super::{
|
||||
ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, PriceTimesRatio, VecBuilderOptions,
|
||||
};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ComputedStandardDeviationVecsFromDateIndex {
|
||||
@@ -35,19 +37,19 @@ pub struct ComputedStandardDeviationVecsFromDateIndex {
|
||||
pub m2_5sd: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub m3sd: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
|
||||
pub _0sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub p0_5sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub p1sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub p1_5sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub p2sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub p2_5sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub p3sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub m0_5sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub m1sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub m1_5sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub m2sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub m2_5sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub m3sd_usd: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub _0sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub p0_5sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub p1sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub p1_5sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub p2sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub p2_5sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub p3sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub m0_5sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub m1sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub m1_5sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub m2sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub m2_5sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
pub m3sd_usd: Option<LazyVecsFrom2FromDateIndex<Dollars, Dollars, StoredF32>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@@ -104,6 +106,7 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
||||
parent_version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
options: StandardDeviationVecsOptions,
|
||||
price: Option<&ComputedVecsFromDateIndex<Dollars>>,
|
||||
) -> Result<Self> {
|
||||
let opts = VecBuilderOptions::default().add_last();
|
||||
let version = parent_version + Version::ONE;
|
||||
@@ -122,36 +125,70 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
||||
};
|
||||
}
|
||||
|
||||
// Create sources first so lazy vecs can reference them
|
||||
let sma_vec = sma.is_compute().then(|| import!("sma"));
|
||||
let p0_5sd = options.bands().then(|| import!("p0_5sd"));
|
||||
let p1sd = options.bands().then(|| import!("p1sd"));
|
||||
let p1_5sd = options.bands().then(|| import!("p1_5sd"));
|
||||
let p2sd = options.bands().then(|| import!("p2sd"));
|
||||
let p2_5sd = options.bands().then(|| import!("p2_5sd"));
|
||||
let p3sd = options.bands().then(|| import!("p3sd"));
|
||||
let m0_5sd = options.bands().then(|| import!("m0_5sd"));
|
||||
let m1sd = options.bands().then(|| import!("m1sd"));
|
||||
let m1_5sd = options.bands().then(|| import!("m1_5sd"));
|
||||
let m2sd = options.bands().then(|| import!("m2sd"));
|
||||
let m2_5sd = options.bands().then(|| import!("m2_5sd"));
|
||||
let m3sd = options.bands().then(|| import!("m3sd"));
|
||||
|
||||
// Create lazy USD vecs from price and band sources
|
||||
macro_rules! lazy_usd {
|
||||
($band:expr, $suffix:expr) => {
|
||||
price
|
||||
.zip($band.as_ref())
|
||||
.filter(|_| options.price_bands())
|
||||
.map(|(p, b)| {
|
||||
LazyVecsFrom2FromDateIndex::from_computed::<PriceTimesRatio>(
|
||||
&format!("{name}_{}", $suffix),
|
||||
version,
|
||||
p,
|
||||
b,
|
||||
)
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
days,
|
||||
sma: sma.is_compute().then(|| import!("sma")),
|
||||
sd: import!("sd"),
|
||||
p0_5sd: options.bands().then(|| import!("p0_5sd")),
|
||||
p1sd: options.bands().then(|| import!("p1sd")),
|
||||
p1_5sd: options.bands().then(|| import!("p1_5sd")),
|
||||
p2sd: options.bands().then(|| import!("p2sd")),
|
||||
p2_5sd: options.bands().then(|| import!("p2_5sd")),
|
||||
p3sd: options.bands().then(|| import!("p3sd")),
|
||||
m0_5sd: options.bands().then(|| import!("m0_5sd")),
|
||||
m1sd: options.bands().then(|| import!("m1sd")),
|
||||
m1_5sd: options.bands().then(|| import!("m1_5sd")),
|
||||
m2sd: options.bands().then(|| import!("m2sd")),
|
||||
m2_5sd: options.bands().then(|| import!("m2_5sd")),
|
||||
m3sd: options.bands().then(|| import!("m3sd")),
|
||||
_0sd_usd: options.price_bands().then(|| import!("0sd_usd")),
|
||||
p0_5sd_usd: options.price_bands().then(|| import!("p0_5sd_usd")),
|
||||
p1sd_usd: options.price_bands().then(|| import!("p1sd_usd")),
|
||||
p1_5sd_usd: options.price_bands().then(|| import!("p1_5sd_usd")),
|
||||
p2sd_usd: options.price_bands().then(|| import!("p2sd_usd")),
|
||||
p2_5sd_usd: options.price_bands().then(|| import!("p2_5sd_usd")),
|
||||
p3sd_usd: options.price_bands().then(|| import!("p3sd_usd")),
|
||||
m0_5sd_usd: options.price_bands().then(|| import!("m0_5sd_usd")),
|
||||
m1sd_usd: options.price_bands().then(|| import!("m1sd_usd")),
|
||||
m1_5sd_usd: options.price_bands().then(|| import!("m1_5sd_usd")),
|
||||
m2sd_usd: options.price_bands().then(|| import!("m2sd_usd")),
|
||||
m2_5sd_usd: options.price_bands().then(|| import!("m2_5sd_usd")),
|
||||
m3sd_usd: options.price_bands().then(|| import!("m3sd_usd")),
|
||||
zscore: options.zscore().then(|| import!("zscore")),
|
||||
// Lazy USD vecs
|
||||
_0sd_usd: lazy_usd!(&sma_vec, "0sd_usd"),
|
||||
p0_5sd_usd: lazy_usd!(&p0_5sd, "p0_5sd_usd"),
|
||||
p1sd_usd: lazy_usd!(&p1sd, "p1sd_usd"),
|
||||
p1_5sd_usd: lazy_usd!(&p1_5sd, "p1_5sd_usd"),
|
||||
p2sd_usd: lazy_usd!(&p2sd, "p2sd_usd"),
|
||||
p2_5sd_usd: lazy_usd!(&p2_5sd, "p2_5sd_usd"),
|
||||
p3sd_usd: lazy_usd!(&p3sd, "p3sd_usd"),
|
||||
m0_5sd_usd: lazy_usd!(&m0_5sd, "m0_5sd_usd"),
|
||||
m1sd_usd: lazy_usd!(&m1sd, "m1sd_usd"),
|
||||
m1_5sd_usd: lazy_usd!(&m1_5sd, "m1_5sd_usd"),
|
||||
m2sd_usd: lazy_usd!(&m2sd, "m2sd_usd"),
|
||||
m2_5sd_usd: lazy_usd!(&m2_5sd, "m2_5sd_usd"),
|
||||
m3sd_usd: lazy_usd!(&m3sd, "m3sd_usd"),
|
||||
// Stored band sources
|
||||
sma: sma_vec,
|
||||
p0_5sd,
|
||||
p1sd,
|
||||
p1_5sd,
|
||||
p2sd,
|
||||
p2_5sd,
|
||||
p3sd,
|
||||
m0_5sd,
|
||||
m1sd,
|
||||
m1_5sd,
|
||||
m2sd,
|
||||
m2_5sd,
|
||||
m3sd,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -160,7 +197,6 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
source: &impl CollectableVec<DateIndex, StoredF32>,
|
||||
price_opt: Option<&impl IterableVec<DateIndex, Dollars>>,
|
||||
) -> Result<()> {
|
||||
let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
|
||||
|
||||
@@ -179,17 +215,15 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
||||
})?;
|
||||
|
||||
let sma_opt: Option<&EagerVec<PcoVec<DateIndex, StoredF32>>> = None;
|
||||
self.compute_rest(starting_indexes, exit, sma_opt, source, price_opt)
|
||||
self.compute_rest(starting_indexes, exit, sma_opt, source)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
sma_opt: Option<&impl IterableVec<DateIndex, StoredF32>>,
|
||||
source: &impl CollectableVec<DateIndex, StoredF32>,
|
||||
price_opt: Option<&impl IterableVec<DateIndex, Dollars>>,
|
||||
) -> Result<()> {
|
||||
let sma = sma_opt.unwrap_or_else(|| unsafe { mem::transmute(&self.sma.u().dateindex) });
|
||||
|
||||
@@ -371,153 +405,6 @@ impl ComputedStandardDeviationVecsFromDateIndex {
|
||||
})?;
|
||||
}
|
||||
|
||||
let Some(price) = price_opt else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let compute_usd =
|
||||
|usd: &mut ComputedVecsFromDateIndex<Dollars>,
|
||||
mut iter: BoxedVecIterator<DateIndex, StoredF32>| {
|
||||
usd.compute_all(starting_indexes, exit, |vec| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
price,
|
||||
|(i, price, ..)| {
|
||||
let multiplier = iter.get_unwrap(i);
|
||||
(i, price * multiplier)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})
|
||||
};
|
||||
|
||||
if self._0sd_usd.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
compute_usd(self._0sd_usd.um(), sma.iter())?;
|
||||
compute_usd(
|
||||
self.p0_5sd_usd.um(),
|
||||
self.p0_5sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.p1sd_usd.um(),
|
||||
self.p1sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.p1_5sd_usd.um(),
|
||||
self.p1_5sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.p2sd_usd.um(),
|
||||
self.p2sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.p2_5sd_usd.um(),
|
||||
self.p2_5sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.p3sd_usd.um(),
|
||||
self.p3sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.m0_5sd_usd.um(),
|
||||
self.m0_5sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.m1sd_usd.um(),
|
||||
self.m1sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.m1_5sd_usd.um(),
|
||||
self.m1_5sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.m2sd_usd.um(),
|
||||
self.m2sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.m2_5sd_usd.um(),
|
||||
self.m2_5sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
compute_usd(
|
||||
self.m3sd_usd.um(),
|
||||
self.m3sd
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter(),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use brk_types::{Bitcoin, Dollars, Sats, StoredF32, StoredF64};
|
||||
use brk_types::{Bitcoin, Close, Dollars, Sats, StoredF32};
|
||||
use vecdb::{BinaryTransform, UnaryTransform};
|
||||
|
||||
/// (Dollars, Dollars) -> Dollars addition
|
||||
@@ -57,16 +57,6 @@ impl UnaryTransform<Sats, Bitcoin> for SatsToBitcoin {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sats -> StoredF64 via Bitcoin (for coinblocks/coindays)
|
||||
pub struct SatsToStoredF64;
|
||||
|
||||
impl UnaryTransform<Sats, StoredF64> for SatsToStoredF64 {
|
||||
#[inline(always)]
|
||||
fn apply(sats: Sats) -> StoredF64 {
|
||||
StoredF64::from(Bitcoin::from(sats))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sats -> Sats/2 (for supply_half)
|
||||
pub struct HalveSats;
|
||||
|
||||
@@ -76,3 +66,100 @@ impl UnaryTransform<Sats, Sats> for HalveSats {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/// Dollars -> Dollars/2 (for supply_half_usd)
|
||||
pub struct HalveDollars;
|
||||
|
||||
impl UnaryTransform<Dollars, Dollars> for HalveDollars {
|
||||
#[inline(always)]
|
||||
fn apply(dollars: Dollars) -> Dollars {
|
||||
dollars.halved()
|
||||
}
|
||||
}
|
||||
|
||||
/// Dollars * StoredF32 -> Dollars (price × ratio)
|
||||
pub struct PriceTimesRatio;
|
||||
|
||||
impl BinaryTransform<Dollars, StoredF32, Dollars> for PriceTimesRatio {
|
||||
#[inline(always)]
|
||||
fn apply(price: Dollars, ratio: StoredF32) -> Dollars {
|
||||
price * ratio
|
||||
}
|
||||
}
|
||||
|
||||
/// Close<Dollars> * Sats -> Dollars (price × sats / 1e8)
|
||||
/// Same as PriceTimesSats but accepts Close<Dollars> price source.
|
||||
pub struct ClosePriceTimesSats;
|
||||
|
||||
impl BinaryTransform<Close<Dollars>, Sats, Dollars> for ClosePriceTimesSats {
|
||||
#[inline(always)]
|
||||
fn apply(price: Close<Dollars>, sats: Sats) -> Dollars {
|
||||
*price * Bitcoin::from(sats)
|
||||
}
|
||||
}
|
||||
|
||||
/// Close<Dollars> * Sats -> Dollars/2 (price × sats / 1e8 / 2)
|
||||
/// Computes halved dollars directly from sats, avoiding lazy-from-lazy chains.
|
||||
pub struct HalfClosePriceTimesSats;
|
||||
|
||||
impl BinaryTransform<Close<Dollars>, Sats, Dollars> for HalfClosePriceTimesSats {
|
||||
#[inline(always)]
|
||||
fn apply(price: Close<Dollars>, sats: Sats) -> Dollars {
|
||||
(*price * Bitcoin::from(sats)).halved()
|
||||
}
|
||||
}
|
||||
|
||||
// === Constant Transforms (using const generics) ===
|
||||
|
||||
use brk_types::{StoredI16, StoredU16};
|
||||
|
||||
/// 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 i16 value, ignoring the input.
|
||||
pub struct ReturnI16<const V: i16>;
|
||||
|
||||
impl<S, const V: i16> UnaryTransform<S, StoredI16> for ReturnI16<V> {
|
||||
#[inline(always)]
|
||||
fn apply(_: S) -> StoredI16 {
|
||||
StoredI16::new(V)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
|
||||
/// Dollars * (V/10) -> Dollars (e.g., V=8 -> * 0.8, V=24 -> * 2.4)
|
||||
pub struct DollarsTimesTenths<const V: u16>;
|
||||
|
||||
impl<const V: u16> UnaryTransform<Dollars, Dollars> for DollarsTimesTenths<V> {
|
||||
#[inline(always)]
|
||||
fn apply(d: Dollars) -> Dollars {
|
||||
d * (V as f64 / 10.0)
|
||||
}
|
||||
}
|
||||
@@ -111,45 +111,6 @@ impl ComputedValueVecsFromTxindex {
|
||||
})
|
||||
}
|
||||
|
||||
// pub fn compute_all<F>(
|
||||
// &mut self,
|
||||
// indexer: &Indexer,
|
||||
// indexes: &indexes::Vecs,
|
||||
// price: Option<&marketprice::Vecs>,
|
||||
// starting_indexes: &Indexes,
|
||||
// exit: &Exit,
|
||||
// mut compute: F,
|
||||
// ) -> Result<()>
|
||||
// where
|
||||
// F: FnMut(
|
||||
// &mut EagerVec<PcoVec<TxIndex, Sats>>,
|
||||
// &Indexer,
|
||||
// &indexes::Vecs,
|
||||
// &Indexes,
|
||||
// &Exit,
|
||||
// ) -> Result<()>,
|
||||
// {
|
||||
// compute(
|
||||
// self.sats.txindex.um(),
|
||||
// indexer,
|
||||
// indexes,
|
||||
// starting_indexes,
|
||||
// exit,
|
||||
// )?;
|
||||
|
||||
// let txindex: Option<&PcoVec<TxIndex, Sats>> = None;
|
||||
// self.compute_rest(
|
||||
// indexer,
|
||||
// indexes,
|
||||
// fetched,
|
||||
// starting_indexes,
|
||||
// exit,
|
||||
// txindex,
|
||||
// )?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
|
||||
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, LazyVecFrom1, PcoVec};
|
||||
|
||||
use crate::{
|
||||
Indexes,
|
||||
grouped::{SatsToBitcoin, Source},
|
||||
price,
|
||||
traits::ComputeFromBitcoin,
|
||||
utils::OptionExt,
|
||||
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
|
||||
use vecdb::{
|
||||
Database, EagerVec, ImportableVec, IterableBoxedVec, IterableCloneableVec, LazyVecFrom1,
|
||||
LazyVecFrom2, PcoVec,
|
||||
};
|
||||
|
||||
use crate::grouped::{ClosePriceTimesSats, SatsToBitcoin, Source};
|
||||
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct ComputedHeightValueVecs {
|
||||
pub sats: Option<EagerVec<PcoVec<Height, Sats>>>,
|
||||
pub bitcoin: LazyVecFrom1<Height, Bitcoin, Height, Sats>,
|
||||
pub dollars: Option<EagerVec<PcoVec<Height, Dollars>>>,
|
||||
pub dollars: Option<LazyVecFrom2<Height, Dollars, Height, Close<Dollars>, Height, Sats>>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -26,74 +23,35 @@ impl ComputedHeightValueVecs {
|
||||
name: &str,
|
||||
source: Source<Height, Sats>,
|
||||
version: Version,
|
||||
compute_dollars: bool,
|
||||
price_source: Option<IterableBoxedVec<Height, Close<Dollars>>>,
|
||||
) -> Result<Self> {
|
||||
let sats = source
|
||||
.is_compute()
|
||||
.then(|| EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap());
|
||||
|
||||
let bitcoin = match &source {
|
||||
Source::Compute => LazyVecFrom1::transformed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
let sats_source: IterableBoxedVec<Height, Sats> = source
|
||||
.vec()
|
||||
.unwrap_or_else(|| sats.as_ref().unwrap().boxed_clone());
|
||||
|
||||
let bitcoin = LazyVecFrom1::transformed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
version + VERSION + Version::ZERO,
|
||||
sats_source.clone(),
|
||||
);
|
||||
|
||||
let dollars = price_source.map(|price| {
|
||||
LazyVecFrom2::transformed::<ClosePriceTimesSats>(
|
||||
&format!("{name}_usd"),
|
||||
version + VERSION + Version::ZERO,
|
||||
sats.as_ref().unwrap().boxed_clone(),
|
||||
),
|
||||
Source::Vec(boxed) => LazyVecFrom1::transformed::<SatsToBitcoin>(
|
||||
&format!("{name}_btc"),
|
||||
version + VERSION + Version::ZERO,
|
||||
boxed.clone(),
|
||||
),
|
||||
Source::None => {
|
||||
panic!("Source::None not supported for lazy bitcoin - use Source::Vec instead")
|
||||
}
|
||||
};
|
||||
price,
|
||||
sats_source.clone(),
|
||||
)
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
sats,
|
||||
bitcoin,
|
||||
dollars: compute_dollars.then(|| {
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&format!("{name}_usd"),
|
||||
version + VERSION + Version::ZERO,
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
dollars,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute_all<F>(
|
||||
&mut self,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
mut compute: F,
|
||||
) -> Result<()>
|
||||
where
|
||||
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
|
||||
{
|
||||
compute(self.sats.um())?;
|
||||
|
||||
self.compute_rest(price, starting_indexes, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn compute_rest(
|
||||
&mut self,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
if let Some(dollars) = self.dollars.as_mut() {
|
||||
dollars.compute_from_bitcoin(
|
||||
starting_indexes.height,
|
||||
&self.bitcoin,
|
||||
&price.u().chainindexes_to_price_close.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,11 +96,8 @@ impl Computer {
|
||||
);
|
||||
|
||||
let i = Instant::now();
|
||||
let (price, constants, market) = thread::scope(|s| -> Result<_> {
|
||||
let constants_handle = big_thread().spawn_scoped(s, || {
|
||||
constants::Vecs::forced_import(&computed_path, VERSION, &indexes)
|
||||
})?;
|
||||
|
||||
let constants = constants::Vecs::new(VERSION, &indexes);
|
||||
let (price, market) = thread::scope(|s| -> Result<_> {
|
||||
let market_handle = big_thread().spawn_scoped(s, || {
|
||||
market::Vecs::forced_import(&computed_path, VERSION, &indexes)
|
||||
})?;
|
||||
@@ -109,10 +106,9 @@ impl Computer {
|
||||
.is_some()
|
||||
.then(|| price::Vecs::forced_import(&computed_path, VERSION, &indexes).unwrap());
|
||||
|
||||
let constants = constants_handle.join().unwrap()?;
|
||||
let market = market_handle.join().unwrap()?;
|
||||
|
||||
Ok((price, constants, market))
|
||||
Ok((price, market))
|
||||
})?;
|
||||
info!("Imported price/constants/market in {:?}", i.elapsed());
|
||||
|
||||
@@ -176,7 +172,6 @@ impl Computer {
|
||||
blks::DB_NAME,
|
||||
chain::DB_NAME,
|
||||
cointime::DB_NAME,
|
||||
constants::DB_NAME,
|
||||
indexes::DB_NAME,
|
||||
market::DB_NAME,
|
||||
pools::DB_NAME,
|
||||
@@ -246,15 +241,6 @@ impl Computer {
|
||||
Ok(())
|
||||
});
|
||||
|
||||
let constants = scope.spawn(|| -> Result<()> {
|
||||
info!("Computing constants...");
|
||||
let i = Instant::now();
|
||||
self.constants
|
||||
.compute(&self.indexes, &starting_indexes, exit)?;
|
||||
info!("Computed constants in {:?}", i.elapsed());
|
||||
Ok(())
|
||||
});
|
||||
|
||||
// Txins must complete before txouts (txouts needs txinindex_to_txoutindex)
|
||||
// and before chain (chain needs txinindex_to_value)
|
||||
info!("Computing txins...");
|
||||
@@ -291,7 +277,6 @@ impl Computer {
|
||||
}
|
||||
|
||||
blks.join().unwrap()?;
|
||||
constants.join().unwrap()?;
|
||||
txouts.join().unwrap()?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
use std::thread;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_types::{Date, DateIndex, Dollars, StoredF32, StoredU16};
|
||||
use vecdb::{EagerVec, Exit, GenericStoredVec, PcoVec, TypedVecIterator, VecIndex};
|
||||
use brk_types::{Date, DateIndex, StoredF32, StoredU16};
|
||||
use vecdb::{Exit, GenericStoredVec, TypedVecIterator, VecIndex};
|
||||
|
||||
use crate::{
|
||||
price,
|
||||
Indexes, price,
|
||||
traits::{ComputeDCAAveragePriceViaLen, ComputeDCAStackViaLen, ComputeDrawdown},
|
||||
utils::OptionExt,
|
||||
Indexes,
|
||||
};
|
||||
|
||||
use super::Vecs;
|
||||
@@ -576,57 +575,20 @@ impl Vecs {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.indexes_to_price_200d_sma_x0_8
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_price_200d_sma
|
||||
.price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
|(i, v, ..)| (i, v * 0.8),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.indexes_to_price_200d_sma_x2_4
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_price_200d_sma
|
||||
.price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
|(i, v, ..)| (i, v * 2.4),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.indexes_to_1d_returns_1w_sd.compute_all(
|
||||
starting_indexes,
|
||||
exit,
|
||||
self._1d_price_returns.dateindex.u(),
|
||||
None as Option<&EagerVec<PcoVec<DateIndex, Dollars>>>,
|
||||
)?;
|
||||
self.indexes_to_1d_returns_1m_sd.compute_all(
|
||||
starting_indexes,
|
||||
exit,
|
||||
self._1d_price_returns.dateindex.u(),
|
||||
None as Option<&EagerVec<PcoVec<DateIndex, Dollars>>>,
|
||||
)?;
|
||||
self.indexes_to_1d_returns_1y_sd.compute_all(
|
||||
starting_indexes,
|
||||
exit,
|
||||
self._1d_price_returns.dateindex.u(),
|
||||
None as Option<&EagerVec<PcoVec<DateIndex, Dollars>>>,
|
||||
)?;
|
||||
|
||||
self.indexes_to_price_1w_volatility
|
||||
|
||||
@@ -3,12 +3,13 @@ use std::path::Path;
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::Version;
|
||||
use vecdb::{Database, EagerVec, ImportableVec, PAGE_SIZE};
|
||||
use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec, PAGE_SIZE};
|
||||
|
||||
use crate::{
|
||||
grouped::{
|
||||
ComputedRatioVecsFromDateIndex, ComputedStandardDeviationVecsFromDateIndex,
|
||||
ComputedVecsFromDateIndex, Source, StandardDeviationVecsOptions, VecBuilderOptions,
|
||||
ComputedVecsFromDateIndex, DollarsTimesTenths, LazyVecsFromDateIndex, Source,
|
||||
StandardDeviationVecsOptions, VecBuilderOptions,
|
||||
},
|
||||
indexes,
|
||||
};
|
||||
@@ -74,6 +75,7 @@ impl Vecs {
|
||||
version + $v,
|
||||
indexes,
|
||||
StandardDeviationVecsOptions::default(),
|
||||
None, // No USD conversion for market returns
|
||||
)?
|
||||
};
|
||||
}
|
||||
@@ -88,6 +90,25 @@ impl Vecs {
|
||||
};
|
||||
}
|
||||
|
||||
let indexes_to_price_200d_sma = ratio_di!("price_200d_sma");
|
||||
let price_200d_sma_source = indexes_to_price_200d_sma.price.as_ref().unwrap();
|
||||
let indexes_to_price_200d_sma_x2_4 = LazyVecsFromDateIndex::from_computed::<
|
||||
DollarsTimesTenths<24>,
|
||||
>(
|
||||
"price_200d_sma_x2_4",
|
||||
version + v0,
|
||||
price_200d_sma_source.dateindex.as_ref().map(|v| v.boxed_clone()),
|
||||
price_200d_sma_source,
|
||||
);
|
||||
let indexes_to_price_200d_sma_x0_8 = LazyVecsFromDateIndex::from_computed::<
|
||||
DollarsTimesTenths<8>,
|
||||
>(
|
||||
"price_200d_sma_x0_8",
|
||||
version + v0,
|
||||
price_200d_sma_source.dateindex.as_ref().map(|v| v.boxed_clone()),
|
||||
price_200d_sma_source,
|
||||
);
|
||||
|
||||
let this = Self {
|
||||
height_to_price_ath: eager_h!("price_ath", v0),
|
||||
height_to_price_drawdown: eager_h!("price_drawdown", v0),
|
||||
@@ -112,7 +133,7 @@ impl Vecs {
|
||||
indexes_to_price_55d_sma: ratio_di!("price_55d_sma"),
|
||||
indexes_to_price_89d_sma: ratio_di!("price_89d_sma"),
|
||||
indexes_to_price_144d_sma: ratio_di!("price_144d_sma"),
|
||||
indexes_to_price_200d_sma: ratio_di!("price_200d_sma"),
|
||||
indexes_to_price_200d_sma,
|
||||
indexes_to_price_1y_sma: ratio_di!("price_1y_sma"),
|
||||
indexes_to_price_2y_sma: ratio_di!("price_2y_sma"),
|
||||
indexes_to_price_200w_sma: ratio_di!("price_200w_sma"),
|
||||
@@ -247,8 +268,8 @@ impl Vecs {
|
||||
dca_class_2016_returns: computed_di!("dca_class_2016_returns"),
|
||||
dca_class_2015_returns: computed_di!("dca_class_2015_returns"),
|
||||
|
||||
indexes_to_price_200d_sma_x2_4: computed_di!("price_200d_sma_x2_4"),
|
||||
indexes_to_price_200d_sma_x0_8: computed_di!("price_200d_sma_x0_8"),
|
||||
indexes_to_price_200d_sma_x2_4,
|
||||
indexes_to_price_200d_sma_x0_8,
|
||||
dateindex_to_price_true_range: eager_di!("price_true_range", v0),
|
||||
dateindex_to_price_true_range_2w_sum: eager_di!("price_true_range_2w_sum", v0),
|
||||
indexes_to_price_1w_min: computed_di!("price_1w_min", v1),
|
||||
|
||||
@@ -7,7 +7,7 @@ use vecdb::{Database, EagerVec, PcoVec};
|
||||
|
||||
use crate::grouped::{
|
||||
ComputedRatioVecsFromDateIndex, ComputedStandardDeviationVecsFromDateIndex,
|
||||
ComputedVecsFromDateIndex,
|
||||
ComputedVecsFromDateIndex, LazyVecsFromDateIndex,
|
||||
};
|
||||
|
||||
pub const DB_NAME: &str = "market";
|
||||
@@ -74,8 +74,8 @@ pub struct Vecs {
|
||||
pub indexes_to_price_200w_ema: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_price_4y_ema: ComputedRatioVecsFromDateIndex,
|
||||
|
||||
pub indexes_to_price_200d_sma_x2_4: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub indexes_to_price_200d_sma_x0_8: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub indexes_to_price_200d_sma_x2_4: LazyVecsFromDateIndex<Dollars>,
|
||||
pub indexes_to_price_200d_sma_x0_8: LazyVecsFromDateIndex<Dollars>,
|
||||
|
||||
pub price_1d_ago: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub price_1w_ago: ComputedVecsFromDateIndex<Dollars>,
|
||||
|
||||
@@ -10,8 +10,9 @@ use vecdb::{
|
||||
use crate::{
|
||||
Indexes,
|
||||
grouped::{
|
||||
ComputedHeightValueVecs, ComputedValueVecsFromDateIndex, ComputedVecsFromHeight, Source,
|
||||
VecBuilderOptions,
|
||||
ComputedHeightValueVecs, ComputedValueVecsFromDateIndex, ComputedVecsFromHeight,
|
||||
HalfClosePriceTimesSats, HalveDollars, HalveSats, HalveSatsToBitcoin, LazyHeightValueVecs,
|
||||
LazyValueVecsFromDateIndex, Source, VecBuilderOptions,
|
||||
},
|
||||
indexes, price,
|
||||
stateful::states::SupplyState,
|
||||
@@ -37,11 +38,11 @@ pub struct SupplyMetrics {
|
||||
/// UTXO count indexed by various dimensions
|
||||
pub indexes_to_utxo_count: ComputedVecsFromHeight<StoredU64>,
|
||||
|
||||
/// Half of supply value (used for computing median)
|
||||
pub height_to_supply_half_value: ComputedHeightValueVecs,
|
||||
/// Half of supply value (used for computing median) - lazy from supply_value
|
||||
pub height_to_supply_half_value: LazyHeightValueVecs,
|
||||
|
||||
/// Half of supply indexed by date
|
||||
pub indexes_to_supply_half: ComputedValueVecsFromDateIndex,
|
||||
/// Half of supply indexed by date - lazy from indexes_to_supply
|
||||
pub indexes_to_supply_half: LazyValueVecsFromDateIndex,
|
||||
}
|
||||
|
||||
impl SupplyMetrics {
|
||||
@@ -55,27 +56,48 @@ impl SupplyMetrics {
|
||||
let height_to_supply: EagerVec<PcoVec<Height, Sats>> =
|
||||
EagerVec::forced_import(cfg.db, &cfg.name("supply"), cfg.version + v0)?;
|
||||
|
||||
let price_source = cfg
|
||||
.price
|
||||
.map(|p| p.chainindexes_to_price_close.height.boxed_clone());
|
||||
|
||||
let height_to_supply_value = ComputedHeightValueVecs::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("supply"),
|
||||
Source::Vec(height_to_supply.boxed_clone()),
|
||||
cfg.version + v0,
|
||||
compute_dollars,
|
||||
price_source.clone(),
|
||||
)?;
|
||||
|
||||
let indexes_to_supply = ComputedValueVecsFromDateIndex::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("supply"),
|
||||
Source::Compute,
|
||||
cfg.version + v1,
|
||||
last,
|
||||
compute_dollars,
|
||||
cfg.indexes,
|
||||
)?;
|
||||
|
||||
// Create lazy supply_half from supply sources
|
||||
let height_to_supply_half_value =
|
||||
LazyHeightValueVecs::from_sources::<HalveSats, HalveSatsToBitcoin, HalfClosePriceTimesSats>(
|
||||
&cfg.name("supply_half"),
|
||||
height_to_supply.boxed_clone(),
|
||||
price_source,
|
||||
cfg.version + v0,
|
||||
);
|
||||
|
||||
let indexes_to_supply_half =
|
||||
LazyValueVecsFromDateIndex::from_source::<HalveSats, HalveSatsToBitcoin, HalveDollars>(
|
||||
&cfg.name("supply_half"),
|
||||
&indexes_to_supply,
|
||||
cfg.version + v0,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
height_to_supply,
|
||||
height_to_supply_value,
|
||||
|
||||
indexes_to_supply: ComputedValueVecsFromDateIndex::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("supply"),
|
||||
Source::Compute,
|
||||
cfg.version + v1,
|
||||
last,
|
||||
compute_dollars,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
indexes_to_supply,
|
||||
|
||||
height_to_utxo_count: EagerVec::forced_import(
|
||||
cfg.db,
|
||||
@@ -92,23 +114,8 @@ impl SupplyMetrics {
|
||||
last,
|
||||
)?,
|
||||
|
||||
height_to_supply_half_value: ComputedHeightValueVecs::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("supply_half"),
|
||||
Source::Compute,
|
||||
cfg.version + v0,
|
||||
compute_dollars,
|
||||
)?,
|
||||
|
||||
indexes_to_supply_half: ComputedValueVecsFromDateIndex::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("supply_half"),
|
||||
Source::Compute,
|
||||
cfg.version + v0,
|
||||
last,
|
||||
compute_dollars,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
height_to_supply_half_value,
|
||||
indexes_to_supply_half,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -183,9 +190,6 @@ impl SupplyMetrics {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.height_to_supply_value
|
||||
.compute_rest(price, starting_indexes, exit)?;
|
||||
|
||||
self.indexes_to_supply
|
||||
.compute_all(price, starting_indexes, exit, |v| {
|
||||
let mut dateindex_to_height_count_iter =
|
||||
@@ -214,28 +218,6 @@ impl SupplyMetrics {
|
||||
Some(&self.height_to_utxo_count),
|
||||
)?;
|
||||
|
||||
self.height_to_supply_half_value
|
||||
.compute_all(price, starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
&self.height_to_supply,
|
||||
|(h, v, ..)| (h, v / 2),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.indexes_to_supply_half
|
||||
.compute_all(price, starting_indexes, exit, |v| {
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_supply.sats.dateindex.as_ref().unwrap(),
|
||||
|(i, sats, ..)| (i, sats / 2),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,19 +142,23 @@ impl UnrealizedMetrics {
|
||||
let height_to_supply_in_loss: EagerVec<PcoVec<Height, Sats>> =
|
||||
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version + v0)?;
|
||||
|
||||
let price_source = cfg
|
||||
.price
|
||||
.map(|p| p.chainindexes_to_price_close.height.boxed_clone());
|
||||
|
||||
let height_to_supply_in_profit_value = ComputedHeightValueVecs::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("supply_in_profit"),
|
||||
Source::Vec(height_to_supply_in_profit.boxed_clone()),
|
||||
cfg.version + v0,
|
||||
compute_dollars,
|
||||
price_source.clone(),
|
||||
)?;
|
||||
let height_to_supply_in_loss_value = ComputedHeightValueVecs::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("supply_in_loss"),
|
||||
Source::Vec(height_to_supply_in_loss.boxed_clone()),
|
||||
cfg.version + v0,
|
||||
compute_dollars,
|
||||
price_source,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
@@ -341,13 +345,6 @@ impl UnrealizedMetrics {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute supply value from sats
|
||||
self.height_to_supply_in_profit_value
|
||||
.compute_rest(price, starting_indexes, exit)?;
|
||||
self.height_to_supply_in_loss_value
|
||||
.compute_rest(price, starting_indexes, exit)?;
|
||||
|
||||
// Compute indexes from dateindex sources
|
||||
self.indexes_to_supply_in_profit.compute_rest(
|
||||
price,
|
||||
starting_indexes,
|
||||
|
||||
@@ -2,11 +2,11 @@ use std::ops::{Add, AddAssign, SubAssign};
|
||||
|
||||
use brk_types::{CheckedSub, LoadedAddressData, Sats};
|
||||
use schemars::JsonSchema;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vecdb::{Bytes, Formattable};
|
||||
|
||||
/// Current supply state tracking UTXO count and total value
|
||||
#[derive(Debug, Default, Clone, Serialize, JsonSchema)]
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct SupplyState {
|
||||
/// Number of unspent transaction outputs
|
||||
pub utxo_count: u64,
|
||||
|
||||
Reference in New Issue
Block a user