global: snapshot

This commit is contained in:
nym21
2025-05-13 11:46:03 +02:00
parent 88a0c9ea03
commit 9d674cd49b
27 changed files with 354 additions and 157 deletions

View File

@@ -0,0 +1,846 @@
use std::path::Path;
use brk_core::{CheckedSub, StoredUsize};
use brk_exit::Exit;
use brk_vec::{
AnyCollectableVec, AnyIterableVec, Compressed, EagerVec, Result, StoredIndex, StoredType,
Version,
};
use color_eyre::eyre::ContextCompat;
use crate::utils::get_percentile;
use super::ComputedType;
#[derive(Clone, Debug)]
pub struct ComputedVecBuilder<I, T>
where
I: StoredIndex,
T: ComputedType,
{
first: Option<EagerVec<I, T>>,
average: Option<EagerVec<I, T>>,
sum: Option<EagerVec<I, T>>,
max: Option<EagerVec<I, T>>,
_90p: Option<EagerVec<I, T>>,
_75p: Option<EagerVec<I, T>>,
median: Option<EagerVec<I, T>>,
_25p: Option<EagerVec<I, T>>,
_10p: Option<EagerVec<I, T>>,
min: Option<EagerVec<I, T>>,
last: Option<EagerVec<I, T>>,
total: Option<EagerVec<I, T>>,
}
const VERSION: Version = Version::ZERO;
impl<I, T> ComputedVecBuilder<I, T>
where
I: StoredIndex,
T: ComputedType,
{
pub fn forced_import(
path: &Path,
name: &str,
version: Version,
compressed: Compressed,
options: StorableVecGeneatorOptions,
) -> color_eyre::Result<Self> {
let key = I::to_string().split("::").last().unwrap().to_lowercase();
let only_one_active = options.is_only_one_active();
let default = || path.join(format!("{key}_to_{name}"));
let prefix = |s: &str| path.join(format!("{key}_to_{s}_{name}"));
let maybe_prefix = |s: &str| {
if only_one_active {
default()
} else {
prefix(s)
}
};
let suffix = |s: &str| path.join(format!("{key}_to_{name}_{s}"));
let maybe_suffix = |s: &str| {
if only_one_active {
default()
} else {
suffix(s)
}
};
let version = VERSION + version;
let s = Self {
first: options.first.then(|| {
EagerVec::forced_import(&maybe_prefix("first"), version + Version::ZERO, compressed)
.unwrap()
}),
last: options.last.then(|| {
EagerVec::forced_import(
&path.join(format!("{key}_to_{name}")),
version + Version::ZERO,
compressed,
)
.unwrap()
}),
min: options.min.then(|| {
EagerVec::forced_import(&maybe_suffix("min"), version + Version::ZERO, compressed)
.unwrap()
}),
max: options.max.then(|| {
EagerVec::forced_import(&maybe_suffix("max"), version + Version::ZERO, compressed)
.unwrap()
}),
median: options.median.then(|| {
EagerVec::forced_import(
&maybe_suffix("median"),
version + Version::ZERO,
compressed,
)
.unwrap()
}),
average: options.average.then(|| {
EagerVec::forced_import(
&maybe_suffix("average"),
version + Version::ZERO,
compressed,
)
.unwrap()
}),
sum: options.sum.then(|| {
EagerVec::forced_import(&maybe_suffix("sum"), version + Version::ZERO, compressed)
.unwrap()
}),
total: options.total.then(|| {
EagerVec::forced_import(&prefix("total"), version + Version::ZERO, compressed)
.unwrap()
}),
_90p: options._90p.then(|| {
EagerVec::forced_import(&maybe_suffix("90p"), version + Version::ZERO, compressed)
.unwrap()
}),
_75p: options._75p.then(|| {
EagerVec::forced_import(&maybe_suffix("75p"), version + Version::ZERO, compressed)
.unwrap()
}),
_25p: options._25p.then(|| {
EagerVec::forced_import(&maybe_suffix("25p"), version + Version::ZERO, compressed)
.unwrap()
}),
_10p: options._10p.then(|| {
EagerVec::forced_import(&maybe_suffix("10p"), version + Version::ZERO, compressed)
.unwrap()
}),
};
Ok(s)
}
pub fn extend(
&mut self,
max_from: I,
source: &impl AnyIterableVec<I, T>,
exit: &Exit,
) -> Result<()> {
if self.total.is_none() {
return Ok(());
};
let index = self.starting_index(max_from);
let total_vec = self.total.as_mut().unwrap();
let mut total = index.decremented().map_or(T::from(0_usize), |index| {
total_vec.iter().unwrap_get_inner(index)
});
source.iter_at(index).try_for_each(|(i, v)| -> Result<()> {
total = total.clone() + v.into_inner();
total_vec.forced_push_at(i, total.clone(), exit)
})?;
self.safe_flush(exit)?;
Ok(())
}
pub fn compute<I2>(
&mut self,
max_from: I,
source: &impl AnyIterableVec<I2, T>,
first_indexes: &impl AnyIterableVec<I, I2>,
count_indexes: &impl AnyIterableVec<I, StoredUsize>,
exit: &Exit,
) -> Result<()>
where
I2: StoredIndex + StoredType + CheckedSub<I2>,
{
self.validate_computed_version_or_reset_file(
source.version() + first_indexes.version() + count_indexes.version(),
)?;
let index = self.starting_index(max_from);
let mut count_indexes_iter = count_indexes.iter();
let mut source_iter = source.iter();
let total_vec = self.total.as_mut();
let mut total = total_vec.map(|total_vec| {
index.decremented().map_or(T::from(0_usize), |index| {
total_vec.iter().unwrap_get_inner(index)
})
});
first_indexes
.iter_at(index)
.try_for_each(|(i, first_index)| -> Result<()> {
let first_index = first_index.into_inner();
let count_index = count_indexes_iter.unwrap_get_inner(i);
if let Some(first) = self.first.as_mut() {
let f = source_iter
.get_inner(first_index)
.unwrap_or_else(|| T::from(0_usize));
first.forced_push_at(index, f, exit)?;
}
if let Some(last) = self.last.as_mut() {
let count_index = *count_index;
if count_index == 0 {
panic!("should compute last if count can be 0")
}
let last_index = first_index + (count_index - 1);
let v = source_iter.unwrap_get_inner(last_index);
// .context("to work")
// .inspect_err(|_| {
// dbg!(first_index, count_index, last_index);
// })
// .unwrap()
// .into_inner();
last.forced_push_at(index, v, exit)?;
}
let needs_sum_or_total = self.sum.is_some() || self.total.is_some();
let needs_average_sum_or_total = needs_sum_or_total || self.average.is_some();
let needs_sorted = self.max.is_some()
|| self._90p.is_some()
|| self._75p.is_some()
|| self.median.is_some()
|| self._25p.is_some()
|| self._10p.is_some()
|| self.min.is_some();
let needs_values = needs_sorted || needs_average_sum_or_total;
if needs_values {
source_iter.set(first_index);
let mut values = (&mut source_iter)
.take(*count_index)
.map(|(_, v)| v.into_inner())
.collect::<Vec<_>>();
if needs_sorted {
values.sort_unstable();
if let Some(max) = self.max.as_mut() {
max.forced_push_at(
i,
values
.last()
.context("expect some")
.inspect_err(|_| {
dbg!(
&values,
max.path(),
first_indexes.name(),
first_index,
count_indexes.name(),
count_index,
source.len(),
source.name()
);
})
.unwrap()
.clone(),
exit,
)?;
}
if let Some(_90p) = self._90p.as_mut() {
_90p.forced_push_at(i, get_percentile(&values, 0.90), exit)?;
}
if let Some(_75p) = self._75p.as_mut() {
_75p.forced_push_at(i, get_percentile(&values, 0.75), exit)?;
}
if let Some(median) = self.median.as_mut() {
median.forced_push_at(i, get_percentile(&values, 0.50), exit)?;
}
if let Some(_25p) = self._25p.as_mut() {
_25p.forced_push_at(i, get_percentile(&values, 0.25), exit)?;
}
if let Some(_10p) = self._10p.as_mut() {
_10p.forced_push_at(i, get_percentile(&values, 0.10), exit)?;
}
if let Some(min) = self.min.as_mut() {
min.forced_push_at(i, values.first().unwrap().clone(), exit)?;
}
}
if needs_average_sum_or_total {
let len = values.len();
let sum = values.into_iter().fold(T::from(0), |a, b| a + b);
if let Some(average) = self.average.as_mut() {
let avg = sum.clone() / len;
average.forced_push_at(i, avg, exit)?;
}
if needs_sum_or_total {
if let Some(sum_vec) = self.sum.as_mut() {
sum_vec.forced_push_at(i, sum.clone(), exit)?;
}
if let Some(total_vec) = self.total.as_mut() {
let t = total.as_ref().unwrap().clone() + sum;
total.replace(t.clone());
total_vec.forced_push_at(i, t, exit)?;
}
}
}
}
Ok(())
})?;
self.safe_flush(exit)?;
Ok(())
}
#[allow(clippy::wrong_self_convention)]
pub fn from_aligned<I2>(
&mut self,
max_from: I,
source: &ComputedVecBuilder<I2, T>,
first_indexes: &impl AnyIterableVec<I, I2>,
count_indexes: &impl AnyIterableVec<I, StoredUsize>,
exit: &Exit,
) -> Result<()>
where
I2: StoredIndex + StoredType + CheckedSub<I2>,
{
if self._90p.is_some()
|| self._75p.is_some()
|| self.median.is_some()
|| self._25p.is_some()
|| self._10p.is_some()
{
panic!("unsupported");
}
self.validate_computed_version_or_reset_file(
VERSION + first_indexes.version() + count_indexes.version(),
)?;
let index = self.starting_index(max_from);
let mut count_indexes_iter = count_indexes.iter();
let mut source_first_iter = source.first.as_ref().map(|f| f.iter());
let mut source_last_iter = source.last.as_ref().map(|f| f.iter());
let mut source_max_iter = source.max.as_ref().map(|f| f.iter());
let mut source_min_iter = source.min.as_ref().map(|f| f.iter());
let mut source_average_iter = source.average.as_ref().map(|f| f.iter());
let mut source_sum_iter = source.sum.as_ref().map(|f| f.iter());
let mut total = self.total.as_mut().map(|total_vec| {
index.decremented().map_or(T::from(0_usize), |index| {
total_vec.iter().unwrap_get_inner(index)
})
});
first_indexes
.iter_at(index)
.try_for_each(|(i, first_index, ..)| -> Result<()> {
let first_index = first_index.into_inner();
let count_index = count_indexes_iter.unwrap_get_inner(i);
if let Some(first) = self.first.as_mut() {
let v = source_first_iter
.as_mut()
.unwrap()
.unwrap_get_inner(first_index);
first.forced_push_at(index, v, exit)?;
}
if let Some(last) = self.last.as_mut() {
let count_index = *count_index;
if count_index == 0 {
panic!("should compute last if count can be 0")
}
let last_index = first_index + (count_index - 1);
let v = source_last_iter
.as_mut()
.unwrap()
.unwrap_get_inner(last_index);
last.forced_push_at(index, v, exit)?;
}
let needs_sum_or_total = self.sum.is_some() || self.total.is_some();
let needs_average_sum_or_total = needs_sum_or_total || self.average.is_some();
let needs_sorted = self.max.is_some() || self.min.is_some();
let needs_values = needs_sorted || needs_average_sum_or_total;
if needs_values {
if needs_sorted {
if let Some(max) = self.max.as_mut() {
let source_max_iter = source_max_iter.as_mut().unwrap();
source_max_iter.set(first_index);
let mut values = source_max_iter
.take(*count_index)
.map(|(_, v)| v.into_inner())
.collect::<Vec<_>>();
values.sort_unstable();
max.forced_push_at(i, values.last().unwrap().clone(), exit)?;
}
if let Some(min) = self.min.as_mut() {
let source_min_iter = source_min_iter.as_mut().unwrap();
source_min_iter.set(first_index);
let mut values = source_min_iter
.take(*count_index)
.map(|(_, v)| v.into_inner())
.collect::<Vec<_>>();
values.sort_unstable();
min.forced_push_at(i, values.first().unwrap().clone(), exit)?;
}
}
if needs_average_sum_or_total {
if let Some(average) = self.average.as_mut() {
let source_average_iter = source_average_iter.as_mut().unwrap();
source_average_iter.set(first_index);
let values = source_average_iter
.take(*count_index)
.map(|(_, v)| v.into_inner())
.collect::<Vec<_>>();
let len = values.len();
let total = values.into_iter().fold(T::from(0), |a, b| a + b);
// TODO: Multiply by count then divide by total
// Right now it's not 100% accurate as there could be more or less elements in the lower timeframe (28 days vs 31 days in a month for example)
let avg = total / len;
average.forced_push_at(i, avg, exit)?;
}
if needs_sum_or_total {
let source_sum_iter = source_sum_iter.as_mut().unwrap();
source_sum_iter.set(first_index);
let values = source_sum_iter
.take(*count_index)
.map(|(_, v)| v.into_inner())
.collect::<Vec<_>>();
let sum = values.into_iter().fold(T::from(0), |a, b| a + b);
if let Some(sum_vec) = self.sum.as_mut() {
sum_vec.forced_push_at(i, sum.clone(), exit)?;
}
if let Some(total_vec) = self.total.as_mut() {
let t = total.as_ref().unwrap().clone() + sum;
total.replace(t.clone());
total_vec.forced_push_at(i, t, exit)?;
}
}
}
}
Ok(())
})?;
self.safe_flush(exit)?;
Ok(())
}
fn starting_index(&self, max_from: I) -> I {
max_from.min(I::from(
self.vecs().into_iter().map(|v| v.len()).min().unwrap(),
))
}
pub fn unwrap_first(&mut self) -> &mut EagerVec<I, T> {
self.first.as_mut().unwrap()
}
#[allow(unused)]
pub fn unwrap_average(&mut self) -> &mut EagerVec<I, T> {
self.average.as_mut().unwrap()
}
pub fn unwrap_sum(&mut self) -> &mut EagerVec<I, T> {
self.sum.as_mut().unwrap()
}
pub fn unwrap_max(&mut self) -> &mut EagerVec<I, T> {
self.max.as_mut().unwrap()
}
#[allow(unused)]
pub fn unwrap_90p(&mut self) -> &mut EagerVec<I, T> {
self._90p.as_mut().unwrap()
}
#[allow(unused)]
pub fn unwrap_75p(&mut self) -> &mut EagerVec<I, T> {
self._75p.as_mut().unwrap()
}
#[allow(unused)]
pub fn unwrap_median(&mut self) -> &mut EagerVec<I, T> {
self.median.as_mut().unwrap()
}
#[allow(unused)]
pub fn unwrap_25p(&mut self) -> &mut EagerVec<I, T> {
self._25p.as_mut().unwrap()
}
#[allow(unused)]
pub fn unwrap_10p(&mut self) -> &mut EagerVec<I, T> {
self._10p.as_mut().unwrap()
}
pub fn unwrap_min(&mut self) -> &mut EagerVec<I, T> {
self.min.as_mut().unwrap()
}
pub fn unwrap_last(&mut self) -> &mut EagerVec<I, T> {
self.last.as_mut().unwrap()
}
#[allow(unused)]
pub fn unwrap_total(&mut self) -> &mut EagerVec<I, T> {
self.total.as_mut().unwrap()
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
let mut v: Vec<&dyn AnyCollectableVec> = vec![];
if let Some(first) = self.first.as_ref() {
v.push(first);
}
if let Some(last) = self.last.as_ref() {
v.push(last);
}
if let Some(min) = self.min.as_ref() {
v.push(min);
}
if let Some(max) = self.max.as_ref() {
v.push(max);
}
if let Some(median) = self.median.as_ref() {
v.push(median);
}
if let Some(average) = self.average.as_ref() {
v.push(average);
}
if let Some(sum) = self.sum.as_ref() {
v.push(sum);
}
if let Some(total) = self.total.as_ref() {
v.push(total);
}
if let Some(_90p) = self._90p.as_ref() {
v.push(_90p);
}
if let Some(_75p) = self._75p.as_ref() {
v.push(_75p);
}
if let Some(_25p) = self._25p.as_ref() {
v.push(_25p);
}
if let Some(_10p) = self._10p.as_ref() {
v.push(_10p);
}
v
}
pub fn safe_flush(&mut self, exit: &Exit) -> Result<()> {
if let Some(first) = self.first.as_mut() {
first.safe_flush(exit)?;
}
if let Some(last) = self.last.as_mut() {
last.safe_flush(exit)?;
}
if let Some(min) = self.min.as_mut() {
min.safe_flush(exit)?;
}
if let Some(max) = self.max.as_mut() {
max.safe_flush(exit)?;
}
if let Some(median) = self.median.as_mut() {
median.safe_flush(exit)?;
}
if let Some(average) = self.average.as_mut() {
average.safe_flush(exit)?;
}
if let Some(sum) = self.sum.as_mut() {
sum.safe_flush(exit)?;
}
if let Some(total) = self.total.as_mut() {
total.safe_flush(exit)?;
}
if let Some(_90p) = self._90p.as_mut() {
_90p.safe_flush(exit)?;
}
if let Some(_75p) = self._75p.as_mut() {
_75p.safe_flush(exit)?;
}
if let Some(_25p) = self._25p.as_mut() {
_25p.safe_flush(exit)?;
}
if let Some(_10p) = self._10p.as_mut() {
_10p.safe_flush(exit)?;
}
Ok(())
}
fn validate_computed_version_or_reset_file(&mut self, version: Version) -> Result<()> {
if let Some(first) = self.first.as_mut() {
first.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(last) = self.last.as_mut() {
last.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(min) = self.min.as_mut() {
min.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(max) = self.max.as_mut() {
max.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(median) = self.median.as_mut() {
median.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(average) = self.average.as_mut() {
average.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(sum) = self.sum.as_mut() {
sum.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(total) = self.total.as_mut() {
total.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(_90p) = self._90p.as_mut() {
_90p.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(_75p) = self._75p.as_mut() {
_75p.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(_25p) = self._25p.as_mut() {
_25p.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
if let Some(_10p) = self._10p.as_mut() {
_10p.validate_computed_version_or_reset_file(Version::ZERO + version)?;
}
Ok(())
}
}
#[derive(Default, Clone, Copy)]
pub struct StorableVecGeneatorOptions {
average: bool,
sum: bool,
max: bool,
_90p: bool,
_75p: bool,
median: bool,
_25p: bool,
_10p: bool,
min: bool,
first: bool,
last: bool,
total: bool,
}
impl StorableVecGeneatorOptions {
pub fn add_first(mut self) -> Self {
self.first = true;
self
}
pub fn add_last(mut self) -> Self {
self.last = true;
self
}
pub fn add_min(mut self) -> Self {
self.min = true;
self
}
pub fn add_max(mut self) -> Self {
self.max = true;
self
}
#[allow(unused)]
pub fn add_median(mut self) -> Self {
self.median = true;
self
}
pub fn add_average(mut self) -> Self {
self.average = true;
self
}
pub fn add_sum(mut self) -> Self {
self.sum = true;
self
}
#[allow(unused)]
pub fn add_90p(mut self) -> Self {
self._90p = true;
self
}
#[allow(unused)]
pub fn add_75p(mut self) -> Self {
self._75p = true;
self
}
#[allow(unused)]
pub fn add_25p(mut self) -> Self {
self._25p = true;
self
}
#[allow(unused)]
pub fn add_10p(mut self) -> Self {
self._10p = true;
self
}
pub fn add_total(mut self) -> Self {
self.total = true;
self
}
#[allow(unused)]
pub fn rm_min(mut self) -> Self {
self.min = false;
self
}
#[allow(unused)]
pub fn rm_max(mut self) -> Self {
self.max = false;
self
}
#[allow(unused)]
pub fn rm_median(mut self) -> Self {
self.median = false;
self
}
#[allow(unused)]
pub fn rm_average(mut self) -> Self {
self.average = false;
self
}
#[allow(unused)]
pub fn rm_sum(mut self) -> Self {
self.sum = false;
self
}
#[allow(unused)]
pub fn rm_90p(mut self) -> Self {
self._90p = false;
self
}
#[allow(unused)]
pub fn rm_75p(mut self) -> Self {
self._75p = false;
self
}
#[allow(unused)]
pub fn rm_25p(mut self) -> Self {
self._25p = false;
self
}
#[allow(unused)]
pub fn rm_10p(mut self) -> Self {
self._10p = false;
self
}
#[allow(unused)]
pub fn rm_total(mut self) -> Self {
self.total = false;
self
}
pub fn add_minmax(mut self) -> Self {
self.min = true;
self.max = true;
self
}
pub fn add_percentiles(mut self) -> Self {
self._90p = true;
self._75p = true;
self.median = true;
self._25p = true;
self._10p = true;
self
}
pub fn remove_percentiles(mut self) -> Self {
self._90p = false;
self._75p = false;
self.median = false;
self._25p = false;
self._10p = false;
self
}
pub fn is_only_one_active(&self) -> bool {
[
self.average,
self.sum,
self.max,
self._90p,
self._75p,
self.median,
self._25p,
self._10p,
self.min,
self.first,
self.last,
self.total,
]
.iter()
.filter(|b| **b)
.count()
== 1
}
pub fn copy_self_extra(&self) -> Self {
Self {
total: self.total,
..Self::default()
}
}
}

View File

@@ -0,0 +1,164 @@
use std::path::Path;
use brk_core::{DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{AnyCollectableVec, Compressed, EagerVec, Result, Version};
use crate::vecs::{Indexes, indexes};
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
#[derive(Clone)]
pub struct ComputedVecsFromDateIndex<T>
where
T: ComputedType + PartialOrd,
{
pub dateindex: EagerVec<DateIndex, T>,
pub dateindex_extra: ComputedVecBuilder<DateIndex, T>,
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
pub yearindex: ComputedVecBuilder<YearIndex, T>,
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedVecsFromDateIndex<T>
where
T: ComputedType,
{
pub fn forced_import(
path: &Path,
name: &str,
version: Version,
compressed: Compressed,
options: StorableVecGeneatorOptions,
) -> color_eyre::Result<Self> {
let version = VERSION + version;
let dateindex_extra = ComputedVecBuilder::forced_import(
path,
name,
version,
compressed,
options.copy_self_extra(),
)?;
let options = options.remove_percentiles();
Ok(Self {
dateindex: EagerVec::forced_import(
&path.join(format!("dateindex_to_{name}")),
version,
compressed,
)?,
dateindex_extra,
weekindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
monthindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
quarterindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
yearindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
decadeindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
})
}
pub fn compute<F>(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
mut compute: F,
) -> color_eyre::Result<()>
where
F: FnMut(
&mut EagerVec<DateIndex, T>,
&Indexer,
&indexes::Vecs,
&Indexes,
&Exit,
) -> Result<()>,
{
compute(
&mut self.dateindex,
indexer,
indexes,
starting_indexes,
exit,
)?;
self.compute_rest(indexes, starting_indexes, exit)
}
pub fn compute_rest(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> color_eyre::Result<()> {
self.dateindex_extra
.extend(starting_indexes.dateindex, &self.dateindex, exit)?;
self.weekindex.compute(
starting_indexes.weekindex,
&self.dateindex,
&indexes.weekindex_to_first_dateindex,
&indexes.weekindex_to_dateindex_count,
exit,
)?;
self.monthindex.compute(
starting_indexes.monthindex,
&self.dateindex,
&indexes.monthindex_to_first_dateindex,
&indexes.monthindex_to_dateindex_count,
exit,
)?;
self.quarterindex.from_aligned(
starting_indexes.quarterindex,
&self.monthindex,
&indexes.quarterindex_to_first_monthindex,
&indexes.quarterindex_to_monthindex_count,
exit,
)?;
self.yearindex.from_aligned(
starting_indexes.yearindex,
&self.monthindex,
&indexes.yearindex_to_first_monthindex,
&indexes.yearindex_to_monthindex_count,
exit,
)?;
self.decadeindex.from_aligned(
starting_indexes.decadeindex,
&self.yearindex,
&indexes.decadeindex_to_first_yearindex,
&indexes.decadeindex_to_yearindex_count,
exit,
)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
vec![&self.dateindex as &dyn AnyCollectableVec],
self.dateindex_extra.vecs(),
self.weekindex.vecs(),
self.monthindex.vecs(),
self.quarterindex.vecs(),
self.yearindex.vecs(),
self.decadeindex.vecs(),
]
.concat()
}
}

View File

@@ -0,0 +1,222 @@
use std::path::Path;
use brk_core::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex,
};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{AnyCollectableVec, AnyIterableVec, Compressed, EagerVec, Result, Version};
use crate::vecs::{Indexes, indexes};
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
#[derive(Clone)]
pub struct ComputedVecsFromHeight<T>
where
T: ComputedType + PartialOrd,
{
pub height: Option<EagerVec<Height, T>>,
pub height_extra: ComputedVecBuilder<Height, T>,
pub dateindex: ComputedVecBuilder<DateIndex, T>,
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
pub yearindex: ComputedVecBuilder<YearIndex, T>,
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedVecsFromHeight<T>
where
T: ComputedType + Ord + From<f64>,
f64: From<T>,
{
pub fn forced_import(
path: &Path,
name: &str,
compute_source: bool,
version: Version,
compressed: Compressed,
options: StorableVecGeneatorOptions,
) -> color_eyre::Result<Self> {
let version = VERSION + version;
let height = compute_source.then(|| {
EagerVec::forced_import(&path.join(format!("height_to_{name}")), version, compressed)
.unwrap()
});
let height_extra = ComputedVecBuilder::forced_import(
path,
name,
version,
compressed,
options.copy_self_extra(),
)?;
let dateindex =
ComputedVecBuilder::forced_import(path, name, version, compressed, options)?;
let options = options.remove_percentiles();
Ok(Self {
height,
height_extra,
dateindex,
weekindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
difficultyepoch: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
monthindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
quarterindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
yearindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
// halvingepoch: StorableVecGeneator::forced_import(path, name, version, compressed, options)?,
decadeindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
})
}
pub fn compute_all<F>(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
mut compute: F,
) -> color_eyre::Result<()>
where
F: FnMut(&mut EagerVec<Height, T>, &Indexer, &indexes::Vecs, &Indexes, &Exit) -> Result<()>,
{
compute(
self.height.as_mut().unwrap(),
indexer,
indexes,
starting_indexes,
exit,
)?;
let height: Option<&EagerVec<Height, T>> = None;
self.compute_rest(indexes, starting_indexes, exit, height)?;
Ok(())
}
pub fn compute_rest(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
height: Option<&impl AnyIterableVec<Height, T>>,
) -> color_eyre::Result<()> {
if let Some(height) = height {
self.height_extra
.extend(starting_indexes.height, height, exit)?;
self.dateindex.compute(
starting_indexes.dateindex,
height,
&indexes.dateindex_to_first_height,
&indexes.dateindex_to_height_count,
exit,
)?;
self.difficultyepoch.compute(
starting_indexes.difficultyepoch,
height,
&indexes.difficultyepoch_to_first_height,
&indexes.difficultyepoch_to_height_count,
exit,
)?;
} else {
let height = self.height.as_ref().unwrap();
self.height_extra
.extend(starting_indexes.height, height, exit)?;
self.dateindex.compute(
starting_indexes.dateindex,
height,
&indexes.dateindex_to_first_height,
&indexes.dateindex_to_height_count,
exit,
)?;
self.difficultyepoch.compute(
starting_indexes.difficultyepoch,
height,
&indexes.difficultyepoch_to_first_height,
&indexes.difficultyepoch_to_height_count,
exit,
)?;
}
self.weekindex.from_aligned(
starting_indexes.weekindex,
&self.dateindex,
&indexes.weekindex_to_first_dateindex,
&indexes.weekindex_to_dateindex_count,
exit,
)?;
self.monthindex.from_aligned(
starting_indexes.monthindex,
&self.dateindex,
&indexes.monthindex_to_first_dateindex,
&indexes.monthindex_to_dateindex_count,
exit,
)?;
self.quarterindex.from_aligned(
starting_indexes.quarterindex,
&self.monthindex,
&indexes.quarterindex_to_first_monthindex,
&indexes.quarterindex_to_monthindex_count,
exit,
)?;
self.yearindex.from_aligned(
starting_indexes.yearindex,
&self.monthindex,
&indexes.yearindex_to_first_monthindex,
&indexes.yearindex_to_monthindex_count,
exit,
)?;
self.decadeindex.from_aligned(
starting_indexes.decadeindex,
&self.yearindex,
&indexes.decadeindex_to_first_yearindex,
&indexes.decadeindex_to_yearindex_count,
exit,
)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.height
.as_ref()
.map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]),
self.height_extra.vecs(),
self.dateindex.vecs(),
self.weekindex.vecs(),
self.difficultyepoch.vecs(),
self.monthindex.vecs(),
self.quarterindex.vecs(),
self.yearindex.vecs(),
// self.halvingepoch.vecs(),
self.decadeindex.vecs(),
]
.concat()
}
}

View File

@@ -0,0 +1,98 @@
use std::path::Path;
use brk_core::{DifficultyEpoch, Height};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{AnyCollectableVec, Compressed, EagerVec, Result, Version};
use crate::vecs::{Indexes, indexes};
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
#[derive(Clone)]
pub struct ComputedVecsFromHeightStrict<T>
where
T: ComputedType + PartialOrd,
{
pub height: EagerVec<Height, T>,
pub height_extra: ComputedVecBuilder<Height, T>,
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedVecsFromHeightStrict<T>
where
T: ComputedType + Ord + From<f64>,
f64: From<T>,
{
pub fn forced_import(
path: &Path,
name: &str,
version: Version,
compressed: Compressed,
options: StorableVecGeneatorOptions,
) -> color_eyre::Result<Self> {
let version = VERSION + version;
let height =
EagerVec::forced_import(&path.join(format!("height_to_{name}")), version, compressed)?;
let height_extra = ComputedVecBuilder::forced_import(
path,
name,
version,
compressed,
options.copy_self_extra(),
)?;
let options = options.remove_percentiles();
Ok(Self {
height,
height_extra,
difficultyepoch: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
// halvingepoch: StorableVecGeneator::forced_import(path, name, version, compressed, options)?,
})
}
pub fn compute<F>(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
mut compute: F,
) -> color_eyre::Result<()>
where
F: FnMut(&mut EagerVec<Height, T>, &Indexer, &indexes::Vecs, &Indexes, &Exit) -> Result<()>,
{
compute(&mut self.height, indexer, indexes, starting_indexes, exit)?;
self.height_extra
.extend(starting_indexes.height, &self.height, exit)?;
self.difficultyepoch.compute(
starting_indexes.difficultyepoch,
&self.height,
&indexes.difficultyepoch_to_first_height,
&indexes.difficultyepoch_to_height_count,
exit,
)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
vec![&self.height as &dyn AnyCollectableVec],
self.height_extra.vecs(),
self.difficultyepoch.vecs(),
// self.halvingepoch.vecs(),
]
.concat()
}
}

View File

@@ -0,0 +1,222 @@
use std::path::Path;
use brk_core::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, TxIndex, WeekIndex,
YearIndex,
};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{
AnyCollectableVec, CollectableVec, Compressed, EagerVec, Result, StoredVec, Version,
};
use crate::vecs::{Indexes, indexes};
use super::{ComputedType, ComputedVecBuilder, StorableVecGeneatorOptions};
#[derive(Clone)]
pub struct ComputedVecsFromTxindex<T>
where
T: ComputedType + PartialOrd,
{
pub txindex: Option<EagerVec<TxIndex, T>>,
pub height: ComputedVecBuilder<Height, T>,
pub dateindex: ComputedVecBuilder<DateIndex, T>,
pub weekindex: ComputedVecBuilder<WeekIndex, T>,
pub difficultyepoch: ComputedVecBuilder<DifficultyEpoch, T>,
pub monthindex: ComputedVecBuilder<MonthIndex, T>,
pub quarterindex: ComputedVecBuilder<QuarterIndex, T>,
pub yearindex: ComputedVecBuilder<YearIndex, T>,
// TODO: pub halvingepoch: StorableVecGeneator<Halvingepoch, T>,
pub decadeindex: ComputedVecBuilder<DecadeIndex, T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedVecsFromTxindex<T>
where
T: ComputedType + Ord + From<f64>,
f64: From<T>,
{
pub fn forced_import(
path: &Path,
name: &str,
compute_source: bool,
version: Version,
compressed: Compressed,
options: StorableVecGeneatorOptions,
) -> color_eyre::Result<Self> {
let version = VERSION + version;
let txindex = compute_source.then(|| {
EagerVec::forced_import(
&path.join(format!("txindex_to_{name}")),
version,
compressed,
)
.unwrap()
});
let height = ComputedVecBuilder::forced_import(path, name, version, compressed, options)?;
let options = options.remove_percentiles();
Ok(Self {
txindex,
height,
dateindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
weekindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
difficultyepoch: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
monthindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
quarterindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
yearindex: ComputedVecBuilder::forced_import(path, name, version, compressed, options)?,
// halvingepoch: StorableVecGeneator::forced_import(path, name, version, compressed, options)?,
decadeindex: ComputedVecBuilder::forced_import(
path, name, version, compressed, options,
)?,
})
}
#[allow(unused)]
pub fn compute_all<F>(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
mut compute: F,
) -> color_eyre::Result<()>
where
F: FnMut(
&mut EagerVec<TxIndex, T>,
&Indexer,
&indexes::Vecs,
&Indexes,
&Exit,
) -> Result<()>,
{
compute(
self.txindex.as_mut().unwrap(),
indexer,
indexes,
starting_indexes,
exit,
)?;
let txindex: Option<&StoredVec<TxIndex, T>> = None;
self.compute_rest(indexer, indexes, starting_indexes, exit, txindex)?;
Ok(())
}
pub fn compute_rest(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
txindex: Option<&impl CollectableVec<TxIndex, T>>,
) -> color_eyre::Result<()> {
if let Some(txindex) = txindex {
self.height.compute(
starting_indexes.height,
txindex,
&indexer.vecs().height_to_first_txindex,
&indexes.height_to_txindex_count,
exit,
)?;
} else {
let txindex = self.txindex.as_ref().unwrap();
self.height.compute(
starting_indexes.height,
txindex,
&indexer.vecs().height_to_first_txindex,
&indexes.height_to_txindex_count,
exit,
)?;
}
self.dateindex.from_aligned(
starting_indexes.dateindex,
&self.height,
&indexes.dateindex_to_first_height,
&indexes.dateindex_to_height_count,
exit,
)?;
self.weekindex.from_aligned(
starting_indexes.weekindex,
&self.dateindex,
&indexes.weekindex_to_first_dateindex,
&indexes.weekindex_to_dateindex_count,
exit,
)?;
self.monthindex.from_aligned(
starting_indexes.monthindex,
&self.dateindex,
&indexes.monthindex_to_first_dateindex,
&indexes.monthindex_to_dateindex_count,
exit,
)?;
self.quarterindex.from_aligned(
starting_indexes.quarterindex,
&self.monthindex,
&indexes.quarterindex_to_first_monthindex,
&indexes.quarterindex_to_monthindex_count,
exit,
)?;
self.yearindex.from_aligned(
starting_indexes.yearindex,
&self.monthindex,
&indexes.yearindex_to_first_monthindex,
&indexes.yearindex_to_monthindex_count,
exit,
)?;
self.decadeindex.from_aligned(
starting_indexes.decadeindex,
&self.yearindex,
&indexes.decadeindex_to_first_yearindex,
&indexes.decadeindex_to_yearindex_count,
exit,
)?;
self.difficultyepoch.from_aligned(
starting_indexes.difficultyepoch,
&self.height,
&indexes.difficultyepoch_to_first_height,
&indexes.difficultyepoch_to_height_count,
exit,
)?;
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.txindex
.as_ref()
.map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]),
self.height.vecs(),
self.dateindex.vecs(),
self.weekindex.vecs(),
self.difficultyepoch.vecs(),
self.monthindex.vecs(),
self.quarterindex.vecs(),
self.yearindex.vecs(),
// self.halvingepoch.vecs(),
self.decadeindex.vecs(),
]
.concat()
}
}

View File

@@ -0,0 +1,19 @@
mod builder;
mod from_dateindex;
mod from_height;
mod from_height_strict;
mod from_txindex;
mod ratio_from_dateindex;
mod r#type;
mod value_from_height;
mod value_from_txindex;
pub use builder::*;
pub use from_dateindex::*;
pub use from_height::*;
pub use from_height_strict::*;
pub use from_txindex::*;
pub use ratio_from_dateindex::*;
use r#type::*;
pub use value_from_height::*;
pub use value_from_txindex::*;

View File

@@ -0,0 +1,872 @@
use std::{f32, path::Path};
use brk_core::{Date, DateIndex, Dollars, StoredF32};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{
AnyCollectableVec, AnyIterableVec, AnyVec, CollectableVec, Compressed, EagerVec, Result,
StoredIndex, VecIterator, Version,
};
// use rayon::prelude::*;
use crate::{
utils::get_percentile,
vecs::{Indexes, fetched, indexes},
};
use super::{ComputedVecsFromDateIndex, StorableVecGeneatorOptions};
#[derive(Clone)]
pub struct ComputedRatioVecsFromDateIndex {
pub price: ComputedVecsFromDateIndex<Dollars>,
pub ratio: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_sma: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_1w_sma: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_1y_sma_momentum_oscillator: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_standard_deviation: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p99_9: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p99_5: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p99: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p1: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p0_5: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p0_1: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p1sd: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p2sd: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p3sd: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_m1sd: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_m2sd: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_m3sd: ComputedVecsFromDateIndex<StoredF32>,
pub ratio_p99_9_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_p99_5_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_p99_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_p1_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_p0_5_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_p0_1_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_p1sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_p2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_p3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_m1sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_m2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
pub ratio_m3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
}
const VERSION: Version = Version::ZERO;
impl ComputedRatioVecsFromDateIndex {
pub fn forced_import(
path: &Path,
name: &str,
// _compute_source: bool,
version: Version,
compressed: Compressed,
options: StorableVecGeneatorOptions,
) -> color_eyre::Result<Self> {
Ok(Self {
price: ComputedVecsFromDateIndex::forced_import(
path,
name,
VERSION + version,
compressed,
options,
)?,
ratio: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_sma: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_sma"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_1w_sma: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_1w_sma"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_1m_sma: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_1m_sma"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_1y_sma: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_1y_sma"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_1y_sma_momentum_oscillator: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_1y_sma_momentum_oscillator"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_standard_deviation: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_standard_deviation"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p99_9: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p99_9"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p99_5: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p99_5"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p99: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p99"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p1: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p1"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p0_5: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p0_5"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p0_1: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p0_1"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p1sd: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p1sd"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p2sd: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p2sd"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p3sd: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p3sd"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_m1sd: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_m1sd"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_m2sd: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_m2sd"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_m3sd: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_m3sd"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p99_9_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p99_9_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p99_5_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p99_5_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p99_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p99_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p1_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p1_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p0_5_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p0_5_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p0_1_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p0_1_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p1sd_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p1sd_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p2sd_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p2sd_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_p3sd_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_p3sd_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_m1sd_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_m1sd_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_m2sd_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_m2sd_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
ratio_m3sd_as_price: ComputedVecsFromDateIndex::forced_import(
path,
&format!("{name}_ratio_m3sd_as_price"),
VERSION + version + Version::TWO,
compressed,
options,
)?,
})
}
pub fn compute<F>(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
fetched: &fetched::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
compute: F,
) -> color_eyre::Result<()>
where
F: FnMut(
&mut EagerVec<DateIndex, Dollars>,
&Indexer,
&indexes::Vecs,
&Indexes,
&Exit,
) -> Result<()>,
{
self.price
.compute(indexer, indexes, starting_indexes, exit, compute)?;
let closes = &fetched.timeindexes_to_close.dateindex;
self.ratio.compute(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
let mut price = self.price.dateindex.into_iter();
v.compute_transform(
starting_indexes.dateindex,
closes,
|(i, close, ..)| {
let price = price.unwrap_get_inner(i);
if price == Dollars::ZERO {
(i, StoredF32::from(1.0))
} else {
(i, StoredF32::from(*close / price))
}
},
exit,
)
},
)?;
let min_ratio_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
self.ratio_sma.compute(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma_(
starting_indexes.dateindex,
&self.ratio.dateindex,
usize::MAX,
exit,
Some(min_ratio_date),
)
},
)?;
self.ratio_1w_sma.compute(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma_(
starting_indexes.dateindex,
&self.ratio.dateindex,
7,
exit,
Some(min_ratio_date),
)
},
)?;
self.ratio_1m_sma.compute(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma_(
starting_indexes.dateindex,
&self.ratio.dateindex,
30,
exit,
Some(min_ratio_date),
)
},
)?;
self.ratio_1y_sma.compute(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_sma_(
starting_indexes.dateindex,
&self.ratio.dateindex,
365,
exit,
Some(min_ratio_date),
)
},
)?;
self.ratio_1y_sma_momentum_oscillator.compute(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
let mut ratio_1y_sma_iter = self.ratio_1y_sma.dateindex.into_iter();
v.compute_transform(
starting_indexes.dateindex,
&self.ratio.dateindex,
|(i, ratio, ..)| {
(
i,
StoredF32::from(*ratio / *ratio_1y_sma_iter.unwrap_get_inner(i) - 1.0),
)
},
exit,
)
},
)?;
let ratio_version = self.ratio.dateindex.version();
self.mut_ratio_vecs()
.iter_mut()
.try_for_each(|v| -> Result<()> {
v.validate_computed_version_or_reset_file(
Version::ZERO + v.inner_version() + ratio_version,
)
})?;
let starting_dateindex = self
.mut_ratio_vecs()
.iter()
.map(|v| DateIndex::from(v.len()))
.min()
.unwrap()
.min(starting_indexes.dateindex);
let mut sorted = self.ratio.dateindex.collect_range(
Some(min_ratio_date.unwrap_to_usize()),
Some(starting_dateindex.unwrap_to_usize()),
)?;
sorted.sort_unstable();
// if sorted.len() != starting_dateindex.unwrap_to_usize() - min_ratio_date.unwrap_to_usize() {
// unreachable!();
// }
let mut sma_iter = self.ratio_sma.dateindex.into_iter();
let nan = StoredF32::from(f32::NAN);
self.ratio
.dateindex
.iter_at(starting_dateindex)
.try_for_each(|(index, ratio)| -> Result<()> {
if index < min_ratio_date {
self.ratio_p0_1.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_p0_5.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_p1.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_p99.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_p99_5
.dateindex
.forced_push_at(index, nan, exit)?;
self.ratio_p99_9
.dateindex
.forced_push_at(index, nan, exit)?;
self.ratio_standard_deviation
.dateindex
.forced_push_at(index, nan, exit)?;
self.ratio_p1sd.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_p2sd.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_p3sd.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_m1sd.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_m2sd.dateindex.forced_push_at(index, nan, exit)?;
self.ratio_m3sd.dateindex.forced_push_at(index, nan, exit)?;
} else {
let ratio = ratio.into_inner();
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
sorted.insert(pos, ratio);
self.ratio_p0_1.dateindex.forced_push_at(
index,
get_percentile(&sorted, 0.001),
exit,
)?;
self.ratio_p0_5.dateindex.forced_push_at(
index,
get_percentile(&sorted, 0.005),
exit,
)?;
self.ratio_p1.dateindex.forced_push_at(
index,
get_percentile(&sorted, 0.01),
exit,
)?;
self.ratio_p99.dateindex.forced_push_at(
index,
get_percentile(&sorted, 0.99),
exit,
)?;
self.ratio_p99_5.dateindex.forced_push_at(
index,
get_percentile(&sorted, 0.995),
exit,
)?;
self.ratio_p99_9.dateindex.forced_push_at(
index,
get_percentile(&sorted, 0.999),
exit,
)?;
let avg = sma_iter.unwrap_get_inner(index);
let sd = StoredF32::from(
(sorted.iter().map(|v| (**v - *avg).powi(2)).sum::<f32>()
/ (index.unwrap_to_usize() + 1) as f32)
.sqrt(),
);
self.ratio_standard_deviation
.dateindex
.forced_push_at(index, sd, exit)?;
self.ratio_p1sd
.dateindex
.forced_push_at(index, avg + sd, exit)?;
self.ratio_p2sd
.dateindex
.forced_push_at(index, avg + 2 * sd, exit)?;
self.ratio_p3sd
.dateindex
.forced_push_at(index, avg + 3 * sd, exit)?;
self.ratio_m1sd
.dateindex
.forced_push_at(index, avg - sd, exit)?;
self.ratio_m2sd
.dateindex
.forced_push_at(index, avg - 2 * sd, exit)?;
self.ratio_m3sd
.dateindex
.forced_push_at(index, avg - 3 * sd, exit)?;
}
Ok(())
})?;
self.mut_ratio_vecs()
.into_iter()
.try_for_each(|v| v.safe_flush(exit))?;
self.ratio_p99_9
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p99_5
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p99
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p1
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p0_5
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p0_1
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_standard_deviation
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p1sd
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p2sd
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p3sd
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_m1sd
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_m2sd
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_m3sd
.compute_rest(indexes, starting_indexes, exit)?;
self.ratio_p99_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p99.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_p99_5_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p99_5.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_p99_9_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p99_9.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_p1_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p1.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_p0_5_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p0_5.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_p0_1_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p0_1.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_p1sd_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p1sd.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_p2sd_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p2sd.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_p3sd_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_p3sd.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_m1sd_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_m1sd.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_m2sd_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_m2sd.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
self.ratio_m3sd_as_price.compute(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
let mut iter = self.ratio_m3sd.dateindex.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&self.price.dateindex,
|(i, price, ..)| {
let multiplier = iter.unwrap_get_inner(i);
(i, price * multiplier)
},
exit,
)
},
)?;
Ok(())
}
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<DateIndex, StoredF32>> {
vec![
&mut self.ratio_standard_deviation.dateindex,
&mut self.ratio_p99_9.dateindex,
&mut self.ratio_p99_5.dateindex,
&mut self.ratio_p99.dateindex,
&mut self.ratio_p1.dateindex,
&mut self.ratio_p0_5.dateindex,
&mut self.ratio_p0_1.dateindex,
&mut self.ratio_p1sd.dateindex,
&mut self.ratio_p2sd.dateindex,
&mut self.ratio_p3sd.dateindex,
&mut self.ratio_m1sd.dateindex,
&mut self.ratio_m2sd.dateindex,
&mut self.ratio_m3sd.dateindex,
]
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.price.vecs(),
self.ratio.vecs(),
self.ratio_sma.vecs(),
self.ratio_1w_sma.vecs(),
self.ratio_1m_sma.vecs(),
self.ratio_1y_sma.vecs(),
self.ratio_1y_sma_momentum_oscillator.vecs(),
self.ratio_standard_deviation.vecs(),
self.ratio_p99_9.vecs(),
self.ratio_p99_5.vecs(),
self.ratio_p99.vecs(),
self.ratio_p1.vecs(),
self.ratio_p0_5.vecs(),
self.ratio_p0_1.vecs(),
self.ratio_p1sd.vecs(),
self.ratio_p2sd.vecs(),
self.ratio_p3sd.vecs(),
self.ratio_m1sd.vecs(),
self.ratio_m2sd.vecs(),
self.ratio_m3sd.vecs(),
self.ratio_p99_9_as_price.vecs(),
self.ratio_p99_5_as_price.vecs(),
self.ratio_p99_as_price.vecs(),
self.ratio_p1_as_price.vecs(),
self.ratio_p0_5_as_price.vecs(),
self.ratio_p0_1_as_price.vecs(),
self.ratio_p1sd_as_price.vecs(),
self.ratio_p2sd_as_price.vecs(),
self.ratio_p3sd_as_price.vecs(),
self.ratio_m1sd_as_price.vecs(),
self.ratio_m2sd_as_price.vecs(),
self.ratio_m3sd_as_price.vecs(),
]
.concat()
}
}

View File

@@ -0,0 +1,13 @@
use std::ops::{Add, Div};
use brk_vec::StoredType;
pub trait ComputedType
where
Self: StoredType + From<usize> + Div<usize, Output = Self> + Add<Output = Self> + Ord,
{
}
impl<T> ComputedType for T where
T: StoredType + From<usize> + Div<usize, Output = Self> + Add<Output = Self> + Ord
{
}

View File

@@ -0,0 +1,165 @@
use std::path::Path;
use brk_core::{Bitcoin, Dollars, Height, Sats};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{
AnyCollectableVec, CollectableVec, Compressed, EagerVec, Result, StoredVec, Version,
};
use crate::vecs::{Indexes, fetched, indexes};
use super::{ComputedVecsFromHeight, StorableVecGeneatorOptions};
#[derive(Clone)]
pub struct ComputedValueVecsFromHeight {
pub sats: ComputedVecsFromHeight<Sats>,
pub bitcoin: ComputedVecsFromHeight<Bitcoin>,
pub dollars: Option<ComputedVecsFromHeight<Dollars>>,
}
const VERSION: Version = Version::ONE;
impl ComputedValueVecsFromHeight {
pub fn forced_import(
path: &Path,
name: &str,
compute_source: bool,
version: Version,
compressed: Compressed,
options: StorableVecGeneatorOptions,
compute_dollars: bool,
) -> color_eyre::Result<Self> {
Ok(Self {
sats: ComputedVecsFromHeight::forced_import(
path,
name,
compute_source,
VERSION + version,
compressed,
options,
)?,
bitcoin: ComputedVecsFromHeight::forced_import(
path,
&format!("{name}_in_btc"),
true,
VERSION + version,
compressed,
options,
)?,
dollars: compute_dollars.then(|| {
ComputedVecsFromHeight::forced_import(
path,
&format!("{name}_in_usd"),
true,
VERSION + version,
compressed,
options,
)
.unwrap()
}),
})
}
pub fn compute_all<F>(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
fetched: Option<&fetched::Vecs>,
starting_indexes: &Indexes,
exit: &Exit,
mut compute: F,
) -> color_eyre::Result<()>
where
F: FnMut(
&mut EagerVec<Height, Sats>,
&Indexer,
&indexes::Vecs,
&Indexes,
&Exit,
) -> Result<()>,
{
compute(
self.sats.height.as_mut().unwrap(),
indexer,
indexes,
starting_indexes,
exit,
)?;
let height: Option<&StoredVec<Height, Sats>> = None;
self.compute_rest(indexer, indexes, fetched, starting_indexes, exit, height)?;
Ok(())
}
pub fn compute_rest(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
fetched: Option<&fetched::Vecs>,
starting_indexes: &Indexes,
exit: &Exit,
height: Option<&impl CollectableVec<Height, Sats>>,
) -> color_eyre::Result<()> {
if let Some(height) = height {
self.sats
.compute_rest(indexes, starting_indexes, exit, Some(height))?;
self.bitcoin.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_from_sats(starting_indexes.height, height, exit)
},
)?;
} else {
let height: Option<&StoredVec<Height, Sats>> = None;
self.sats
.compute_rest(indexes, starting_indexes, exit, height)?;
self.bitcoin.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_from_sats(
starting_indexes.height,
self.sats.height.as_ref().unwrap(),
exit,
)
},
)?;
}
let txindex = self.bitcoin.height.as_ref().unwrap();
let price = &fetched.as_ref().unwrap().chainindexes_to_close.height;
if let Some(dollars) = self.dollars.as_mut() {
dollars.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_from_bitcoin(starting_indexes.height, txindex, price, exit)
},
)?;
}
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.sats.vecs(),
self.bitcoin.vecs(),
self.dollars.as_ref().map_or(vec![], |v| v.vecs()),
]
.concat()
}
}

View File

@@ -0,0 +1,223 @@
use std::path::Path;
use brk_core::{Bitcoin, Close, Dollars, Height, Sats, TxIndex};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{
AnyCollectableVec, BoxedAnyIterableVec, CloneableAnyIterableVec, CollectableVec, Compressed,
Computation, ComputedVecFrom3, LazyVecFrom1, StoredIndex, StoredVec, Version,
};
use crate::vecs::{Indexes, fetched, indexes};
use super::{ComputedVecsFromTxindex, StorableVecGeneatorOptions};
#[derive(Clone)]
pub struct ComputedValueVecsFromTxindex {
pub sats: ComputedVecsFromTxindex<Sats>,
pub bitcoin_txindex: LazyVecFrom1<TxIndex, Bitcoin, TxIndex, Sats>,
pub bitcoin: ComputedVecsFromTxindex<Bitcoin>,
#[allow(clippy::type_complexity)]
pub dollars_txindex: Option<
ComputedVecFrom3<
TxIndex,
Dollars,
TxIndex,
Bitcoin,
TxIndex,
Height,
Height,
Close<Dollars>,
>,
>,
pub dollars: Option<ComputedVecsFromTxindex<Dollars>>,
}
const VERSION: Version = Version::ONE;
impl ComputedValueVecsFromTxindex {
#[allow(clippy::too_many_arguments)]
pub fn forced_import(
path: &Path,
name: &str,
indexes: &indexes::Vecs,
source: Option<BoxedAnyIterableVec<TxIndex, Sats>>,
version: Version,
computation: Computation,
compressed: Compressed,
fetched: Option<&fetched::Vecs>,
options: StorableVecGeneatorOptions,
) -> color_eyre::Result<Self> {
let compute_source = source.is_none();
let compute_dollars = fetched.is_some();
let sats = ComputedVecsFromTxindex::forced_import(
path,
name,
compute_source,
VERSION + version,
compressed,
options,
)?;
let bitcoin_txindex = LazyVecFrom1::init(
"txindex_to_{name}_in_btc",
VERSION + version,
source.map_or_else(|| sats.txindex.as_ref().unwrap().boxed_clone(), |s| s),
|txindex: TxIndex, iter| {
iter.next_at(txindex.unwrap_to_usize()).map(|(_, value)| {
let sats = value.into_inner();
Bitcoin::from(sats)
})
},
);
let bitcoin = ComputedVecsFromTxindex::forced_import(
path,
&format!("{name}_in_btc"),
false,
VERSION + version,
compressed,
options,
)?;
let dollars_txindex = fetched.map(|fetched| {
ComputedVecFrom3::forced_import_or_init_from_3(
computation,
path,
"txindex_to_{name}_in_usd",
VERSION + version,
compressed,
bitcoin_txindex.boxed_clone(),
indexes.txindex_to_height.boxed_clone(),
fetched.chainindexes_to_close.height.boxed_clone(),
|txindex: TxIndex,
txindex_to_btc_iter,
txindex_to_height_iter,
height_to_close_iter| {
let txindex = txindex.unwrap_to_usize();
txindex_to_btc_iter.next_at(txindex).and_then(|(_, value)| {
let btc = value.into_inner();
txindex_to_height_iter
.next_at(txindex)
.and_then(|(_, value)| {
let height = value.into_inner();
height_to_close_iter
.next_at(height.unwrap_to_usize())
.map(|(_, close)| *close.into_inner() * btc)
})
})
},
)
.unwrap()
});
Ok(Self {
sats,
bitcoin_txindex,
bitcoin,
dollars_txindex,
dollars: compute_dollars.then(|| {
ComputedVecsFromTxindex::forced_import(
path,
&format!("{name}_in_usd"),
false,
VERSION + version,
compressed,
options,
)
.unwrap()
}),
})
}
// pub fn compute_all<F>(
// &mut self,
// indexer: &Indexer,
// indexes: &indexes::Vecs,
// fetched: Option<&marketprice::Vecs>,
// starting_indexes: &Indexes,
// exit: &Exit,
// mut compute: F,
// ) -> color_eyre::Result<()>
// where
// F: FnMut(
// &mut EagerVec<TxIndex, Sats>,
// &Indexer,
// &indexes::Vecs,
// &Indexes,
// &Exit,
// ) -> Result<()>,
// {
// compute(
// self.sats.txindex.as_mut().unwrap(),
// indexer,
// indexes,
// starting_indexes,
// exit,
// )?;
// let txindex: Option<&StoredVec<TxIndex, Sats>> = None;
// self.compute_rest(
// indexer,
// indexes,
// fetched,
// starting_indexes,
// exit,
// txindex,
// )?;
// Ok(())
// }
pub fn compute_rest(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
txindex: Option<&impl CollectableVec<TxIndex, Sats>>,
) -> color_eyre::Result<()> {
if let Some(txindex) = txindex {
self.sats
.compute_rest(indexer, indexes, starting_indexes, exit, Some(txindex))?;
} else {
let txindex: Option<&StoredVec<TxIndex, Sats>> = None;
self.sats
.compute_rest(indexer, indexes, starting_indexes, exit, txindex)?;
}
self.bitcoin.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(&self.bitcoin_txindex),
)?;
if let Some(dollars) = self.dollars.as_mut() {
let dollars_txindex = self.dollars_txindex.as_mut().unwrap();
dollars_txindex.compute_if_necessary(starting_indexes.txindex, exit)?;
dollars.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(dollars_txindex),
)?;
}
Ok(())
}
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
[
self.sats.vecs(),
self.bitcoin.vecs(),
self.dollars.as_ref().map_or(vec![], |v| v.vecs()),
]
.concat()
}
}