global: BIG snapshot

This commit is contained in:
nym21
2026-01-04 01:47:03 +01:00
parent c33444a92e
commit 3cae817915
127 changed files with 4750 additions and 9474 deletions

View File

@@ -14,68 +14,59 @@ use crate::{
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let last = || VecBuilderOptions::default().add_last();
let sum_cum = || VecBuilderOptions::default().add_sum().add_cumulative();
Ok(Self {
dateindex_to_block_count_target: LazyVecFrom1::init(
"block_count_target",
version + v0,
version,
indexes.time.dateindex_to_dateindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)),
),
weekindex_to_block_count_target: LazyVecFrom1::init(
"block_count_target",
version + v0,
version,
indexes.time.weekindex_to_weekindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)),
),
monthindex_to_block_count_target: LazyVecFrom1::init(
"block_count_target",
version + v0,
version,
indexes.time.monthindex_to_monthindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)),
),
quarterindex_to_block_count_target: LazyVecFrom1::init(
"block_count_target",
version + v0,
version,
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)),
),
semesterindex_to_block_count_target: LazyVecFrom1::init(
"block_count_target",
version + v0,
version,
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)),
),
yearindex_to_block_count_target: LazyVecFrom1::init(
"block_count_target",
version + v0,
version,
indexes.time.yearindex_to_yearindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)),
),
decadeindex_to_block_count_target: LazyVecFrom1::init(
"block_count_target",
version + v0,
version,
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)),
),
height_to_24h_block_count: EagerVec::forced_import(
db,
"24h_block_count",
version + v0,
)?,
height_to_24h_block_count: EagerVec::forced_import(db, "24h_block_count", version)?,
indexes_to_block_count: ComputedVecsFromHeight::forced_import(
db,
"block_count",
Source::Compute,
version + v0,
version,
indexes,
sum_cum(),
)?,
@@ -83,7 +74,7 @@ impl Vecs {
db,
"1w_block_count",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -91,7 +82,7 @@ impl Vecs {
db,
"1m_block_count",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -99,7 +90,7 @@ impl Vecs {
db,
"1y_block_count",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,

View File

@@ -10,7 +10,6 @@ use crate::{
impl Vecs {
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let v0 = Version::ZERO;
let v2 = Version::TWO;
let last = || VecBuilderOptions::default().add_last();
@@ -19,7 +18,7 @@ impl Vecs {
db,
"difficultyepoch",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,

View File

@@ -10,7 +10,6 @@ use crate::{
impl Vecs {
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let v0 = Version::ZERO;
let v2 = Version::TWO;
let last = || VecBuilderOptions::default().add_last();
@@ -19,7 +18,7 @@ impl Vecs {
db,
"halvingepoch",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,

View File

@@ -9,8 +9,8 @@ use vecdb::{Database, PAGE_SIZE};
use crate::{indexes, price};
use super::{
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, MiningVecs,
RewardsVecs, SizeVecs, TimeVecs, Vecs, WeightVecs,
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, MiningVecs, RewardsVecs, SizeVecs,
TimeVecs, Vecs, WeightVecs,
};
impl Vecs {
@@ -24,7 +24,7 @@ impl Vecs {
let db = Database::open(&parent_path.join(super::DB_NAME))?;
db.set_min_len(PAGE_SIZE * 50_000_000)?;
let version = parent_version + Version::ZERO;
let version = parent_version;
let compute_dollars = price.is_some();
let count = CountVecs::forced_import(&db, version, indexes)?;

View File

@@ -16,7 +16,6 @@ impl Vecs {
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let stats = || {
VecBuilderOptions::default()
.add_average()
@@ -26,7 +25,7 @@ impl Vecs {
let height_to_interval = LazyVecFrom1::init(
"interval",
version + v0,
version,
indexer.vecs.block.height_to_timestamp.boxed_clone(),
|height: Height, timestamp_iter| {
let timestamp = timestamp_iter.get(height)?;
@@ -46,7 +45,7 @@ impl Vecs {
db,
"block_interval",
Source::Vec(height_to_interval.boxed_clone()),
version + v0,
version,
indexes,
stats(),
)?,

View File

@@ -5,8 +5,8 @@ use vecdb::{Database, IterableCloneableVec};
use super::Vecs;
use crate::{
internal::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source, VecBuilderOptions},
indexes,
internal::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source, VecBuilderOptions},
};
impl Vecs {
@@ -16,7 +16,6 @@ impl Vecs {
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let v4 = Version::new(4);
let v5 = Version::new(5);
@@ -36,7 +35,7 @@ impl Vecs {
db,
"hash_rate_1w_sma",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -44,7 +43,7 @@ impl Vecs {
db,
"hash_rate_1m_sma",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -52,7 +51,7 @@ impl Vecs {
db,
"hash_rate_2m_sma",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -60,7 +59,7 @@ impl Vecs {
db,
"hash_rate_1y_sma",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -148,7 +147,7 @@ impl Vecs {
db,
"difficulty",
Source::Vec(indexer.vecs.block.height_to_difficulty.boxed_clone()),
version + v0,
version,
indexes,
last(),
)?,
@@ -156,7 +155,7 @@ impl Vecs {
db,
"difficulty_as_hash",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -164,7 +163,7 @@ impl Vecs {
db,
"difficulty_adjustment",
Source::Compute,
version + v0,
version,
indexes,
sum(),
)?,

View File

@@ -4,8 +4,8 @@ use vecdb::{Database, EagerVec, ImportableVec};
use super::Vecs;
use crate::{
internal::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions},
indexes,
internal::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions},
};
impl Vecs {
@@ -15,25 +15,20 @@ impl Vecs {
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v0 = Version::ZERO;
let last = || VecBuilderOptions::default().add_last();
Ok(Self {
height_to_24h_coinbase_sum: EagerVec::forced_import(
db,
"24h_coinbase_sum",
version + v0,
)?,
height_to_24h_coinbase_sum: EagerVec::forced_import(db, "24h_coinbase_sum", version)?,
height_to_24h_coinbase_usd_sum: EagerVec::forced_import(
db,
"24h_coinbase_usd_sum",
version + v0,
version,
)?,
indexes_to_coinbase: ComputedValueVecsFromHeight::forced_import(
db,
"coinbase",
Source::Compute,
version + v0,
version,
VecBuilderOptions::default()
.add_sum()
.add_cumulative()
@@ -47,7 +42,7 @@ impl Vecs {
db,
"subsidy",
Source::Compute,
version + v0,
version,
VecBuilderOptions::default()
.add_percentiles()
.add_sum()
@@ -61,16 +56,16 @@ impl Vecs {
db,
"unclaimed_rewards",
Source::Compute,
version + v0,
version,
VecBuilderOptions::default().add_sum().add_cumulative(),
compute_dollars,
indexes,
)?,
dateindex_to_fee_dominance: EagerVec::forced_import(db, "fee_dominance", version + v0)?,
dateindex_to_fee_dominance: EagerVec::forced_import(db, "fee_dominance", version)?,
dateindex_to_subsidy_dominance: EagerVec::forced_import(
db,
"subsidy_dominance",
version + v0,
version,
)?,
indexes_to_subsidy_usd_1y_sma: compute_dollars
.then(|| {
@@ -78,7 +73,7 @@ impl Vecs {
db,
"subsidy_usd_1y_sma",
Source::Compute,
version + v0,
version,
indexes,
last(),
)

View File

@@ -16,7 +16,6 @@ impl Vecs {
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let full_stats = || {
VecBuilderOptions::default()
.add_average()
@@ -28,7 +27,7 @@ impl Vecs {
let height_to_vbytes = LazyVecFrom1::init(
"vbytes",
version + v0,
version,
indexer.vecs.block.height_to_weight.boxed_clone(),
|height: Height, weight_iter| {
weight_iter
@@ -42,7 +41,7 @@ impl Vecs {
db,
"block_size",
Source::Vec(indexer.vecs.block.height_to_total_size.boxed_clone()),
version + v0,
version,
indexes,
full_stats(),
)?,
@@ -50,7 +49,7 @@ impl Vecs {
db,
"block_vbytes",
Source::Vec(height_to_vbytes.boxed_clone()),
version + v0,
version,
indexes,
full_stats(),
)?,

View File

@@ -18,13 +18,12 @@ impl Vecs {
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let height_to_timestamp_fixed =
EagerVec::forced_import(db, "timestamp_fixed", version + Version::ZERO)?;
let height_to_timestamp_fixed = EagerVec::forced_import(db, "timestamp_fixed", version)?;
Ok(Self {
height_to_date: LazyVecFrom1::init(
"date",
version + Version::ZERO,
version,
indexer.vecs.block.height_to_timestamp.boxed_clone(),
|height: Height, timestamp_iter| {
timestamp_iter.get_at(height.to_usize()).map(Date::from)
@@ -32,14 +31,14 @@ impl Vecs {
),
height_to_date_fixed: LazyVecFrom1::init(
"date_fixed",
version + Version::ZERO,
version,
height_to_timestamp_fixed.boxed_clone(),
|height: Height, timestamp_iter| timestamp_iter.get(height).map(Date::from),
),
height_to_timestamp_fixed,
difficultyepoch_to_timestamp: LazyVecFrom2::init(
"timestamp",
version + Version::ZERO,
version,
indexes.block.difficultyepoch_to_first_height.boxed_clone(),
indexer.vecs.block.height_to_timestamp.boxed_clone(),
|di: DifficultyEpoch, first_height_iter, timestamp_iter| {
@@ -52,7 +51,7 @@ impl Vecs {
db,
"timestamp",
Source::Compute,
version + Version::ZERO,
version,
indexes,
VecBuilderOptions::default().add_first(),
)?,

View File

@@ -6,7 +6,9 @@ use vecdb::{Database, IterableCloneableVec};
use super::Vecs;
use crate::{
indexes,
internal::{ComputedVecsFromHeight, LazyVecsFromHeight, Source, VecBuilderOptions, WeightToFullness},
internal::{
ComputedVecsFromHeight, LazyVecsFromHeight, Source, VecBuilderOptions, WeightToFullness,
},
};
impl Vecs {
@@ -16,7 +18,6 @@ impl Vecs {
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let full_stats = || {
VecBuilderOptions::default()
.add_average()
@@ -30,14 +31,14 @@ impl Vecs {
db,
"block_weight",
Source::Vec(indexer.vecs.block.height_to_weight.boxed_clone()),
version + v0,
version,
indexes,
full_stats(),
)?;
let indexes_to_block_fullness = LazyVecsFromHeight::from_computed::<WeightToFullness>(
"block_fullness",
version + v0,
version,
indexer.vecs.block.height_to_weight.boxed_clone(),
&indexes_to_block_weight,
);

View File

@@ -6,7 +6,7 @@ use brk_types::Version;
use vecdb::{Database, PAGE_SIZE};
use super::{
ActivityVecs, AdjustedVecs, CapVecs, PricingVecs, SupplyVecs, ValueVecs, Vecs, DB_NAME,
ActivityVecs, AdjustedVecs, CapVecs, PricingVecs, SupplyVecs, ValueVecs, Vecs, DB_NAME, VERSION,
};
use crate::{indexes, price};
@@ -21,15 +21,15 @@ impl Vecs {
db.set_min_len(PAGE_SIZE * 1_000_000)?;
let compute_dollars = price.is_some();
let v0 = parent_version;
let v1 = parent_version + Version::ONE;
let version = parent_version + VERSION;
let v1 = version + Version::ONE;
let activity = ActivityVecs::forced_import(&db, v0, indexes)?;
let activity = ActivityVecs::forced_import(&db, version, indexes)?;
let supply = SupplyVecs::forced_import(&db, v1, indexes, compute_dollars)?;
let value = ValueVecs::forced_import(&db, v1, indexes)?;
let cap = CapVecs::forced_import(&db, v1, indexes)?;
let pricing = PricingVecs::forced_import(&db, v0, indexes, price)?;
let adjusted = AdjustedVecs::forced_import(&db, v0, indexes)?;
let pricing = PricingVecs::forced_import(&db, version, indexes, price)?;
let adjusted = AdjustedVecs::forced_import(&db, version, indexes)?;
let this = Self {
db,

View File

@@ -9,6 +9,7 @@ mod compute;
mod import;
use brk_traversable::Traversable;
use brk_types::Version;
use vecdb::Database;
pub use activity::Vecs as ActivityVecs;
@@ -19,6 +20,7 @@ pub use supply::Vecs as SupplyVecs;
pub use value::Vecs as ValueVecs;
pub const DB_NAME: &str = "cointime";
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
pub struct Vecs {

View File

@@ -2,8 +2,8 @@ use brk_traversable::Traversable;
use brk_types::{StoredF32, StoredI16, StoredU16, Version};
use super::{
internal::{ConstantVecs, ReturnF32Tenths, ReturnI16, ReturnU16},
indexes,
internal::{ConstantVecs, ReturnF32Tenths, ReturnI16, ReturnU16},
};
pub const DB_NAME: &str = "constants";
@@ -15,9 +15,13 @@ pub struct Vecs {
pub constant_2: ConstantVecs<StoredU16>,
pub constant_3: ConstantVecs<StoredU16>,
pub constant_4: ConstantVecs<StoredU16>,
pub constant_20: ConstantVecs<StoredU16>,
pub constant_30: ConstantVecs<StoredU16>,
pub constant_38_2: ConstantVecs<StoredF32>,
pub constant_50: ConstantVecs<StoredU16>,
pub constant_61_8: ConstantVecs<StoredF32>,
pub constant_70: ConstantVecs<StoredU16>,
pub constant_80: ConstantVecs<StoredU16>,
pub constant_100: ConstantVecs<StoredU16>,
pub constant_600: ConstantVecs<StoredU16>,
pub constant_minus_1: ConstantVecs<StoredI16>,
@@ -28,7 +32,7 @@ pub struct Vecs {
impl Vecs {
pub fn new(version: Version, indexes: &indexes::Vecs) -> Self {
let v = version + Version::ZERO;
let v = version;
Self {
constant_0: ConstantVecs::new::<ReturnU16<0>>("constant_0", v, indexes),
@@ -36,9 +40,13 @@ impl Vecs {
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_20: ConstantVecs::new::<ReturnU16<20>>("constant_20", v, indexes),
constant_30: ConstantVecs::new::<ReturnU16<30>>("constant_30", 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_70: ConstantVecs::new::<ReturnU16<70>>("constant_70", v, indexes),
constant_80: ConstantVecs::new::<ReturnU16<80>>("constant_80", 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),

View File

@@ -5,12 +5,12 @@ use brk_cohort::{
};
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version};
use brk_types::{DateIndex, Dollars, Height, Version};
use derive_deref::{Deref, DerefMut};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Database, Exit, IterableVec};
use crate::{ComputeIndexes, indexes, price, distribution::DynCohortVecs};
use crate::{ComputeIndexes, distribution::DynCohortVecs, indexes, price};
use crate::distribution::metrics::SupplyMetrics;
@@ -35,7 +35,7 @@ impl AddressCohorts {
states_path: &Path,
all_supply: Option<&SupplyMetrics>,
) -> Result<Self> {
let v = version + VERSION + Version::ZERO;
let v = version + VERSION;
// Helper to create a cohort - only amount_range cohorts have state
let create = |filter: Filter,
@@ -119,18 +119,16 @@ impl AddressCohorts {
/// Second phase of post-processing: compute relative metrics.
#[allow(clippy::too_many_arguments)]
pub fn compute_rest_part2<S, HM, DM>(
pub fn compute_rest_part2<HM, DM>(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
height_to_supply: &S,
height_to_market_cap: Option<&HM>,
dateindex_to_market_cap: Option<&DM>,
exit: &Exit,
) -> Result<()>
where
S: IterableVec<Height, Bitcoin> + Sync,
HM: IterableVec<Height, Dollars> + Sync,
DM: IterableVec<DateIndex, Dollars> + Sync,
{
@@ -139,7 +137,6 @@ impl AddressCohorts {
indexes,
price,
starting_indexes,
height_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
exit,

View File

@@ -3,7 +3,7 @@ use std::path::Path;
use brk_cohort::{CohortContext, Filter, Filtered};
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, DateIndex, Dollars, Height, StoredU64, Version};
use brk_types::{DateIndex, Dollars, Height, StoredU64, Version};
use rayon::prelude::*;
use vecdb::{
AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, ImportableVec,
@@ -12,9 +12,10 @@ use vecdb::{
use crate::{
ComputeIndexes,
internal::{ComputedVecsFromHeight, Source, VecBuilderOptions},
indexes, price,
distribution::state::AddressCohortState,
indexes,
internal::{ComputedVecsFromHeight, Source, VecBuilderOptions},
price,
};
use crate::distribution::metrics::{CohortMetrics, ImportConfig, SupplyMetrics};
@@ -73,11 +74,8 @@ impl AddressCohortVecs {
price,
};
let height_to_addr_count = EagerVec::forced_import(
db,
&cfg.name("addr_count"),
version + VERSION + Version::ZERO,
)?;
let height_to_addr_count =
EagerVec::forced_import(db, &cfg.name("addr_count"), version + VERSION)?;
Ok(Self {
starting_height: None,
@@ -91,7 +89,7 @@ impl AddressCohortVecs {
db,
&cfg.name("addr_count"),
Source::Vec(height_to_addr_count.boxed_clone()),
version + VERSION + Version::ZERO,
version + VERSION,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -290,7 +288,6 @@ impl CohortVecs for AddressCohortVecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
height_to_supply: &impl IterableVec<Height, Bitcoin>,
height_to_market_cap: Option<&impl IterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl IterableVec<DateIndex, Dollars>>,
exit: &Exit,
@@ -299,7 +296,6 @@ impl CohortVecs for AddressCohortVecs {
indexes,
price,
starting_indexes,
height_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
exit,

View File

@@ -1,5 +1,5 @@
use brk_error::Result;
use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version};
use brk_types::{DateIndex, Dollars, Height, Version};
use vecdb::{Exit, IterableVec};
use crate::{ComputeIndexes, indexes, price};
@@ -63,7 +63,6 @@ pub trait CohortVecs: DynCohortVecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
height_to_supply: &impl IterableVec<Height, Bitcoin>,
height_to_market_cap: Option<&impl IterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl IterableVec<DateIndex, Dollars>>,
exit: &Exit,

View File

@@ -6,16 +6,17 @@ use brk_cohort::{
};
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, DateIndex, Dollars, Height, Sats, Version};
use brk_types::{DateIndex, Dollars, Height, Sats, Version};
use derive_deref::{Deref, DerefMut};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Database, Exit, IterableVec};
use crate::{
ComputeIndexes,
internal::{PERCENTILES, PERCENTILES_LEN},
indexes, price,
distribution::DynCohortVecs,
indexes,
internal::{PERCENTILES, PERCENTILES_LEN},
price,
};
use super::{super::traits::CohortVecs, vecs::UTXOCohortVecs};
@@ -35,7 +36,7 @@ impl UTXOCohorts {
price: Option<&price::Vecs>,
states_path: &Path,
) -> Result<Self> {
let v = version + VERSION + Version::ZERO;
let v = version + VERSION;
// Create "all" cohort first - it doesn't need global sources (it IS the global source)
let all = UTXOCohortVecs::forced_import(
@@ -202,18 +203,16 @@ impl UTXOCohorts {
/// Second phase of post-processing: compute relative metrics.
#[allow(clippy::too_many_arguments)]
pub fn compute_rest_part2<S, HM, DM>(
pub fn compute_rest_part2<HM, DM>(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
height_to_supply: &S,
height_to_market_cap: Option<&HM>,
dateindex_to_market_cap: Option<&DM>,
exit: &Exit,
) -> Result<()>
where
S: IterableVec<Height, Bitcoin> + Sync,
HM: IterableVec<Height, Dollars> + Sync,
DM: IterableVec<DateIndex, Dollars> + Sync,
{
@@ -222,7 +221,6 @@ impl UTXOCohorts {
indexes,
price,
starting_indexes,
height_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
exit,

View File

@@ -3,7 +3,7 @@ use std::path::Path;
use brk_cohort::{CohortContext, Filter, Filtered, StateLevel};
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version};
use brk_types::{DateIndex, Dollars, Height, Version};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Database, Exit, IterableVec};
@@ -242,7 +242,6 @@ impl CohortVecs for UTXOCohortVecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
height_to_supply: &impl IterableVec<Height, Bitcoin>,
height_to_market_cap: Option<&impl IterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl IterableVec<DateIndex, Dollars>>,
exit: &Exit,
@@ -251,7 +250,6 @@ impl CohortVecs for UTXOCohortVecs {
indexes,
price,
starting_indexes,
height_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
exit,

View File

@@ -1,5 +1,5 @@
use brk_error::Result;
use brk_types::{Bitcoin, DateIndex, Dollars, Height};
use brk_types::{DateIndex, Dollars, Height};
use log::info;
use vecdb::{Exit, IterableVec};
@@ -49,19 +49,17 @@ pub fn compute_rest_part1(
///
/// Computes supply ratios, market cap ratios, etc. using total references.
#[allow(clippy::too_many_arguments)]
pub fn compute_rest_part2<S, HM, DM>(
pub fn compute_rest_part2<HM, DM>(
utxo_cohorts: &mut UTXOCohorts,
address_cohorts: &mut AddressCohorts,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
height_to_supply: &S,
height_to_market_cap: Option<&HM>,
dateindex_to_market_cap: Option<&DM>,
exit: &Exit,
) -> Result<()>
where
S: IterableVec<Height, Bitcoin> + Sync,
HM: IterableVec<Height, Dollars> + Sync,
DM: IterableVec<DateIndex, Dollars> + Sync,
{
@@ -71,7 +69,6 @@ where
indexes,
price,
starting_indexes,
height_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
exit,
@@ -81,7 +78,6 @@ where
indexes,
price,
starting_indexes,
height_to_supply,
height_to_market_cap,
dateindex_to_market_cap,
exit,

View File

@@ -8,9 +8,9 @@ use vecdb::{
};
use crate::{
ComputeIndexes,
ComputeIndexes, indexes,
internal::{ComputedValueVecsFromHeight, ComputedVecsFromHeight, Source, VecBuilderOptions},
indexes, price,
price,
};
use super::ImportConfig;
@@ -40,17 +40,16 @@ pub struct ActivityMetrics {
impl ActivityMetrics {
/// Import activity metrics from database.
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
let v0 = Version::ZERO;
let compute_dollars = cfg.compute_dollars();
let sum_cum = VecBuilderOptions::default().add_sum().add_cumulative();
let height_to_sent: EagerVec<PcoVec<Height, Sats>> =
EagerVec::forced_import(cfg.db, &cfg.name("sent"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("sent"), cfg.version)?;
let indexes_to_sent = ComputedValueVecsFromHeight::forced_import(
cfg.db,
&cfg.name("sent"),
Source::Vec(height_to_sent.boxed_clone()),
cfg.version + v0,
cfg.version,
sum_cum,
compute_dollars,
cfg.indexes,
@@ -63,20 +62,20 @@ impl ActivityMetrics {
height_to_satblocks_destroyed: EagerVec::forced_import(
cfg.db,
&cfg.name("satblocks_destroyed"),
cfg.version + v0,
cfg.version,
)?,
height_to_satdays_destroyed: EagerVec::forced_import(
cfg.db,
&cfg.name("satdays_destroyed"),
cfg.version + v0,
cfg.version,
)?,
indexes_to_coinblocks_destroyed: ComputedVecsFromHeight::forced_import(
cfg.db,
&cfg.name("coinblocks_destroyed"),
Source::Compute,
cfg.version + v0,
cfg.version,
cfg.indexes,
sum_cum,
)?,
@@ -85,7 +84,7 @@ impl ActivityMetrics {
cfg.db,
&cfg.name("coindays_destroyed"),
Source::Compute,
cfg.version + v0,
cfg.version,
cfg.indexes,
sum_cum,
)?,

View File

@@ -33,22 +33,21 @@ pub struct CostBasisMetrics {
impl CostBasisMetrics {
/// Import cost basis metrics from database.
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
let v0 = Version::ZERO;
let extended = cfg.extended();
let last = VecBuilderOptions::default().add_last();
let height_to_min_cost_basis =
EagerVec::forced_import(cfg.db, &cfg.name("min_cost_basis"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("min_cost_basis"), cfg.version)?;
let height_to_max_cost_basis =
EagerVec::forced_import(cfg.db, &cfg.name("max_cost_basis"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("max_cost_basis"), cfg.version)?;
Ok(Self {
indexes_to_min_cost_basis: ComputedVecsFromHeight::forced_import(
cfg.db,
&cfg.name("min_cost_basis"),
Source::Vec(height_to_min_cost_basis.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?,
@@ -56,7 +55,7 @@ impl CostBasisMetrics {
cfg.db,
&cfg.name("max_cost_basis"),
Source::Vec(height_to_max_cost_basis.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?,
@@ -67,7 +66,7 @@ impl CostBasisMetrics {
CostBasisPercentiles::forced_import(
cfg.db,
&cfg.name(""),
cfg.version + v0,
cfg.version,
cfg.indexes,
true,
)

View File

@@ -17,7 +17,7 @@ pub use unrealized::*;
use brk_cohort::Filter;
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version};
use brk_types::{DateIndex, Dollars, Height, Version};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Exit, IterableVec};
@@ -319,7 +319,6 @@ impl CohortMetrics {
indexes: &indexes::Vecs,
price: Option<&price_vecs::Vecs>,
starting_indexes: &ComputeIndexes,
height_to_supply: &impl IterableVec<Height, Bitcoin>,
height_to_market_cap: Option<&impl IterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl IterableVec<DateIndex, Dollars>>,
exit: &Exit,
@@ -329,7 +328,7 @@ impl CohortMetrics {
indexes,
price,
starting_indexes,
height_to_supply,
&self.supply.height_to_supply_value.bitcoin,
height_to_market_cap,
dateindex_to_market_cap,
exit,

View File

@@ -9,13 +9,14 @@ use vecdb::{
use crate::{
ComputeIndexes,
distribution::state::RealizedState,
indexes,
internal::{
ComputedRatioVecsFromDateIndex, ComputedVecsFromDateIndex, ComputedVecsFromHeight,
LazyVecsFrom2FromHeight, LazyVecsFromDateIndex, LazyVecsFromHeight, PercentageDollarsF32,
Source, StoredF32Identity, VecBuilderOptions,
},
indexes, price,
distribution::state::RealizedState,
price,
utils::OptionExt,
};
@@ -93,7 +94,6 @@ pub struct RealizedMetrics {
impl RealizedMetrics {
/// Import realized metrics from database.
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
let v0 = Version::ZERO;
let v1 = Version::ONE;
let v3 = Version::new(3);
let extended = cfg.extended();
@@ -103,13 +103,13 @@ impl RealizedMetrics {
let sum_cum = VecBuilderOptions::default().add_sum().add_cumulative();
let height_to_realized_loss: EagerVec<PcoVec<Height, Dollars>> =
EagerVec::forced_import(cfg.db, &cfg.name("realized_loss"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("realized_loss"), cfg.version)?;
let indexes_to_realized_loss = ComputedVecsFromHeight::forced_import(
cfg.db,
&cfg.name("realized_loss"),
Source::Vec(height_to_realized_loss.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
sum_cum,
)?;
@@ -126,7 +126,7 @@ impl RealizedMetrics {
cfg.db,
&cfg.name("realized_value"),
Source::Compute,
cfg.version + v0,
cfg.version,
cfg.indexes,
sum,
)?;
@@ -145,25 +145,25 @@ impl RealizedMetrics {
// Extract vecs needed for lazy ratio construction
let height_to_realized_cap: EagerVec<PcoVec<Height, Dollars>> =
EagerVec::forced_import(cfg.db, &cfg.name("realized_cap"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("realized_cap"), cfg.version)?;
let indexes_to_realized_cap = ComputedVecsFromHeight::forced_import(
cfg.db,
&cfg.name("realized_cap"),
Source::Vec(height_to_realized_cap.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?;
let height_to_realized_profit: EagerVec<PcoVec<Height, Dollars>> =
EagerVec::forced_import(cfg.db, &cfg.name("realized_profit"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("realized_profit"), cfg.version)?;
let indexes_to_realized_profit = ComputedVecsFromHeight::forced_import(
cfg.db,
&cfg.name("realized_profit"),
Source::Vec(height_to_realized_profit.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
sum_cum,
)?;
@@ -172,7 +172,7 @@ impl RealizedMetrics {
cfg.db,
&cfg.name("net_realized_pnl"),
Source::Compute,
cfg.version + v0,
cfg.version,
cfg.indexes,
sum_cum,
)?;
@@ -216,32 +216,24 @@ impl RealizedMetrics {
cfg.db,
&cfg.name("realized_price"),
Source::Compute,
cfg.version + v0,
cfg.version + v1,
cfg.indexes,
last,
)?;
let height_to_value_created =
EagerVec::forced_import(cfg.db, &cfg.name("value_created"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("value_created"), cfg.version)?;
let height_to_value_destroyed =
EagerVec::forced_import(cfg.db, &cfg.name("value_destroyed"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("value_destroyed"), cfg.version)?;
let height_to_adjusted_value_created = compute_adjusted
.then(|| {
EagerVec::forced_import(
cfg.db,
&cfg.name("adjusted_value_created"),
cfg.version + v0,
)
EagerVec::forced_import(cfg.db, &cfg.name("adjusted_value_created"), cfg.version)
})
.transpose()?;
let height_to_adjusted_value_destroyed = compute_adjusted
.then(|| {
EagerVec::forced_import(
cfg.db,
&cfg.name("adjusted_value_destroyed"),
cfg.version + v0,
)
EagerVec::forced_import(cfg.db, &cfg.name("adjusted_value_destroyed"), cfg.version)
})
.transpose()?;
@@ -250,7 +242,7 @@ impl RealizedMetrics {
cfg.db,
&cfg.name("realized_price"),
Some(&indexes_to_realized_price),
cfg.version + v0,
cfg.version + v1,
cfg.indexes,
extended,
cfg.price,
@@ -260,7 +252,7 @@ impl RealizedMetrics {
// ratio = close / realized_price = market_cap / realized_cap = MVRV
let indexes_to_mvrv = LazyVecsFromDateIndex::from_computed::<StoredF32Identity>(
&cfg.name("mvrv"),
cfg.version + v0,
cfg.version,
indexes_to_realized_price_extra
.ratio
.dateindex
@@ -283,7 +275,7 @@ impl RealizedMetrics {
cfg.db,
&cfg.name("realized_cap_rel_to_own_market_cap"),
Source::Compute,
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)
@@ -293,7 +285,7 @@ impl RealizedMetrics {
cfg.db,
&cfg.name("realized_cap_30d_delta"),
Source::Compute,
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?,
@@ -329,7 +321,7 @@ impl RealizedMetrics {
cfg.db,
&cfg.name("value_created"),
Source::Vec(height_to_value_created.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
sum,
)?,
@@ -337,7 +329,7 @@ impl RealizedMetrics {
cfg.db,
&cfg.name("value_destroyed"),
Source::Vec(height_to_value_destroyed.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
sum,
)?,
@@ -356,7 +348,7 @@ impl RealizedMetrics {
.unwrap()
.boxed_clone(),
),
cfg.version + v0,
cfg.version,
cfg.indexes,
sum,
)
@@ -373,7 +365,7 @@ impl RealizedMetrics {
.unwrap()
.boxed_clone(),
),
cfg.version + v0,
cfg.version,
cfg.indexes,
sum,
)

View File

@@ -108,7 +108,6 @@ impl RelativeMetrics {
supply: &SupplyMetrics,
all_supply: Option<&SupplyMetrics>,
) -> Result<Self> {
let v0 = Version::ZERO;
let v1 = Version::ONE;
let v2 = Version::new(2);
let extended = cfg.extended();
@@ -227,7 +226,7 @@ impl RelativeMetrics {
height_to_unrealized_profit_rel_to_market_cap: global_market_cap_height.map(|mc| {
LazyVecFrom2::transformed::<PercentageDollarsF32>(
&cfg.name("unrealized_profit_rel_to_market_cap"),
cfg.version + v0,
cfg.version,
unrealized.height_to_unrealized_profit.boxed_clone(),
mc.boxed_clone(),
)
@@ -235,7 +234,7 @@ impl RelativeMetrics {
height_to_unrealized_loss_rel_to_market_cap: global_market_cap_height.map(|mc| {
LazyVecFrom2::transformed::<PercentageDollarsF32>(
&cfg.name("unrealized_loss_rel_to_market_cap"),
cfg.version + v0,
cfg.version,
unrealized.height_to_unrealized_loss.boxed_clone(),
mc.boxed_clone(),
)
@@ -243,7 +242,7 @@ impl RelativeMetrics {
height_to_neg_unrealized_loss_rel_to_market_cap: global_market_cap_height.map(|mc| {
LazyVecFrom2::transformed::<NegPercentageDollarsF32>(
&cfg.name("neg_unrealized_loss_rel_to_market_cap"),
cfg.version + v0,
cfg.version,
unrealized.height_to_unrealized_loss.boxed_clone(),
mc.boxed_clone(),
)
@@ -401,7 +400,7 @@ impl RelativeMetrics {
height_to_unrealized_profit_rel_to_own_total_unrealized_pnl: extended.then(|| {
LazyVecFrom2::transformed::<Ratio32>(
&cfg.name("unrealized_profit_rel_to_own_total_unrealized_pnl"),
cfg.version + v0,
cfg.version,
unrealized.height_to_unrealized_profit.boxed_clone(),
unrealized.height_to_total_unrealized_pnl.boxed_clone(),
)
@@ -409,7 +408,7 @@ impl RelativeMetrics {
height_to_unrealized_loss_rel_to_own_total_unrealized_pnl: extended.then(|| {
LazyVecFrom2::transformed::<Ratio32>(
&cfg.name("unrealized_loss_rel_to_own_total_unrealized_pnl"),
cfg.version + v0,
cfg.version,
unrealized.height_to_unrealized_loss.boxed_clone(),
unrealized.height_to_total_unrealized_pnl.boxed_clone(),
)
@@ -417,7 +416,7 @@ impl RelativeMetrics {
height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: extended.then(|| {
LazyVecFrom2::transformed::<NegRatio32>(
&cfg.name("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"),
cfg.version + v0,
cfg.version,
unrealized.height_to_unrealized_loss.boxed_clone(),
unrealized.height_to_total_unrealized_pnl.boxed_clone(),
)

View File

@@ -8,13 +8,13 @@ use vecdb::{
};
use crate::{
ComputeIndexes,
ComputeIndexes, indexes,
internal::{
ComputedHeightValueVecs, ComputedValueVecsFromDateIndex, ComputedVecsFromHeight,
HalfClosePriceTimesSats, HalveDollars, HalveSats, HalveSatsToBitcoin, LazyHeightValueVecs,
LazyValueVecsFromDateIndex, Source, VecBuilderOptions,
},
indexes, price,
price,
};
use super::ImportConfig;
@@ -47,13 +47,12 @@ pub struct SupplyMetrics {
impl SupplyMetrics {
/// Import supply metrics from database.
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
let v0 = Version::ZERO;
let v1 = Version::ONE;
let compute_dollars = cfg.compute_dollars();
let last = VecBuilderOptions::default().add_last();
let height_to_supply: EagerVec<PcoVec<Height, Sats>> =
EagerVec::forced_import(cfg.db, &cfg.name("supply"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("supply"), cfg.version)?;
let price_source = cfg
.price
@@ -63,7 +62,7 @@ impl SupplyMetrics {
cfg.db,
&cfg.name("supply"),
Source::Vec(height_to_supply.boxed_clone()),
cfg.version + v0,
cfg.version,
price_source.clone(),
)?;
@@ -86,25 +85,25 @@ impl SupplyMetrics {
&cfg.name("supply_half"),
height_to_supply.boxed_clone(),
price_source,
cfg.version + v0,
cfg.version,
);
let indexes_to_supply_half =
LazyValueVecsFromDateIndex::from_source::<HalveSats, HalveSatsToBitcoin, HalveDollars>(
&cfg.name("supply_half"),
&indexes_to_supply,
cfg.version + v0,
cfg.version,
);
let height_to_utxo_count =
EagerVec::forced_import(cfg.db, &cfg.name("utxo_count"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("utxo_count"), cfg.version)?;
Ok(Self {
indexes_to_utxo_count: ComputedVecsFromHeight::forced_import(
cfg.db,
&cfg.name("utxo_count"),
Source::Vec(height_to_utxo_count.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?,

View File

@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Dollars, Height, Sats, Version};
use brk_types::{DateIndex, Dollars, Height, Sats};
use rayon::prelude::*;
use vecdb::{
AnyStoredVec, AnyVec, EagerVec, Exit, GenericStoredVec, ImportableVec, IterableCloneableVec,
@@ -9,11 +9,11 @@ use vecdb::{
use crate::{
ComputeIndexes,
distribution::state::UnrealizedState,
internal::{
ComputedHeightValueVecs, ComputedValueVecsFromDateIndex, ComputedVecsFromDateIndex,
DollarsMinus, DollarsPlus, LazyVecsFromDateIndex, Source, VecBuilderOptions,
},
distribution::state::UnrealizedState,
};
use super::ImportConfig;
@@ -57,23 +57,22 @@ pub struct UnrealizedMetrics {
impl UnrealizedMetrics {
/// Import unrealized metrics from database.
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
let v0 = Version::ZERO;
let compute_dollars = cfg.compute_dollars();
let last = VecBuilderOptions::default().add_last();
let dateindex_to_supply_in_profit =
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_profit"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_profit"), cfg.version)?;
let dateindex_to_supply_in_loss =
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version)?;
let dateindex_to_unrealized_profit =
EagerVec::forced_import(cfg.db, &cfg.name("unrealized_profit"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("unrealized_profit"), cfg.version)?;
let dateindex_to_unrealized_loss =
EagerVec::forced_import(cfg.db, &cfg.name("unrealized_loss"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("unrealized_loss"), cfg.version)?;
let height_to_unrealized_loss: EagerVec<PcoVec<Height, Dollars>> =
EagerVec::forced_import(cfg.db, &cfg.name("unrealized_loss"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("unrealized_loss"), cfg.version)?;
let height_to_neg_unrealized_loss = LazyVecFrom1::transformed::<Negate>(
&cfg.name("neg_unrealized_loss"),
cfg.version + v0,
cfg.version,
height_to_unrealized_loss.boxed_clone(),
);
@@ -81,26 +80,26 @@ impl UnrealizedMetrics {
cfg.db,
&cfg.name("unrealized_loss"),
Source::Vec(dateindex_to_unrealized_loss.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?;
let indexes_to_neg_unrealized_loss = LazyVecsFromDateIndex::from_computed::<Negate>(
&cfg.name("neg_unrealized_loss"),
cfg.version + v0,
cfg.version,
Some(dateindex_to_unrealized_loss.boxed_clone()),
&indexes_to_unrealized_loss,
);
// Extract profit sources for lazy net/total vecs
let height_to_unrealized_profit: EagerVec<PcoVec<Height, Dollars>> =
EagerVec::forced_import(cfg.db, &cfg.name("unrealized_profit"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("unrealized_profit"), cfg.version)?;
let indexes_to_unrealized_profit = ComputedVecsFromDateIndex::forced_import(
cfg.db,
&cfg.name("unrealized_profit"),
Source::Vec(dateindex_to_unrealized_profit.boxed_clone()),
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?;
@@ -108,13 +107,13 @@ impl UnrealizedMetrics {
// Create lazy height vecs from profit/loss sources
let height_to_net_unrealized_pnl = LazyVecFrom2::transformed::<DollarsMinus>(
&cfg.name("net_unrealized_pnl"),
cfg.version + v0,
cfg.version,
height_to_unrealized_profit.boxed_clone(),
height_to_unrealized_loss.boxed_clone(),
);
let height_to_total_unrealized_pnl = LazyVecFrom2::transformed::<DollarsPlus>(
&cfg.name("total_unrealized_pnl"),
cfg.version + v0,
cfg.version,
height_to_unrealized_profit.boxed_clone(),
height_to_unrealized_loss.boxed_clone(),
);
@@ -124,7 +123,7 @@ impl UnrealizedMetrics {
cfg.db,
&cfg.name("net_unrealized_pnl"),
Source::Compute,
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?;
@@ -132,15 +131,15 @@ impl UnrealizedMetrics {
cfg.db,
&cfg.name("total_unrealized_pnl"),
Source::Compute,
cfg.version + v0,
cfg.version,
cfg.indexes,
last,
)?;
let height_to_supply_in_profit: EagerVec<PcoVec<Height, Sats>> =
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_profit"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_profit"), cfg.version)?;
let height_to_supply_in_loss: EagerVec<PcoVec<Height, Sats>> =
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version + v0)?;
EagerVec::forced_import(cfg.db, &cfg.name("supply_in_loss"), cfg.version)?;
let price_source = cfg
.price
@@ -150,14 +149,14 @@ impl UnrealizedMetrics {
cfg.db,
&cfg.name("supply_in_profit"),
Source::Vec(height_to_supply_in_profit.boxed_clone()),
cfg.version + v0,
cfg.version,
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,
cfg.version,
price_source,
)?;
@@ -168,7 +167,7 @@ impl UnrealizedMetrics {
cfg.db,
&cfg.name("supply_in_profit"),
Source::Vec(dateindex_to_supply_in_profit.boxed_clone()),
cfg.version + v0,
cfg.version,
last,
compute_dollars,
cfg.indexes,
@@ -178,7 +177,7 @@ impl UnrealizedMetrics {
cfg.db,
&cfg.name("supply_in_loss"),
Source::Vec(dateindex_to_supply_in_loss.boxed_clone()),
cfg.version + v0,
cfg.version,
last,
compute_dollars,
cfg.indexes,

View File

@@ -19,8 +19,7 @@ use crate::{
compute::{StartMode, determine_start_mode, process_blocks, recover_state, reset_state},
state::BlockState,
},
indexes,
inputs,
indexes, inputs,
internal::{ComputedVecsFromHeight, Source, VecBuilderOptions},
outputs, price, transactions,
};
@@ -63,7 +62,7 @@ const SAVED_STAMPED_CHANGES: u16 = 10;
impl Vecs {
pub fn forced_import(
parent: &Path,
version: Version,
parent_version: Version,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
@@ -74,7 +73,7 @@ impl Vecs {
db.set_min_len(PAGE_SIZE * 20_000_000)?;
db.set_min_regions(50_000)?;
let v0 = version + VERSION + Version::ZERO;
let version = parent_version + VERSION;
let utxo_cohorts = UTXOCohorts::forced_import(&db, version, indexes, price, &states_path)?;
@@ -90,37 +89,37 @@ impl Vecs {
// Create address data BytesVecs first so we can also use them for identity mappings
let loadedaddressindex_to_loadedaddressdata = BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "loadedaddressdata", v0)
vecdb::ImportOptions::new(&db, "loadedaddressdata", version)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?;
let emptyaddressindex_to_emptyaddressdata = BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "emptyaddressdata", v0)
vecdb::ImportOptions::new(&db, "emptyaddressdata", version)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?;
// Identity mappings for traversable
let loadedaddressindex_to_loadedaddressindex = LazyVecFrom1::init(
"loadedaddressindex",
v0,
version,
loadedaddressindex_to_loadedaddressdata.boxed_clone(),
|index, _| Some(index),
);
let emptyaddressindex_to_emptyaddressindex = LazyVecFrom1::init(
"emptyaddressindex",
v0,
version,
emptyaddressindex_to_emptyaddressdata.boxed_clone(),
|index, _| Some(index),
);
// Extract address type height vecs before struct literal to use as sources
let addresstype_to_height_to_addr_count =
AddressTypeToHeightToAddressCount::forced_import(&db, "addr_count", v0)?;
AddressTypeToHeightToAddressCount::forced_import(&db, "addr_count", version)?;
let addresstype_to_height_to_empty_addr_count =
AddressTypeToHeightToAddressCount::forced_import(&db, "empty_addr_count", v0)?;
AddressTypeToHeightToAddressCount::forced_import(&db, "empty_addr_count", version)?;
let this = Self {
chain_state: BytesVec::forced_import_with(
vecdb::ImportOptions::new(&db, "chain", v0)
vecdb::ImportOptions::new(&db, "chain", version)
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?,
@@ -128,7 +127,7 @@ impl Vecs {
&db,
"addr_count",
Source::Compute,
v0,
version,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -136,23 +135,24 @@ impl Vecs {
&db,
"empty_addr_count",
Source::Compute,
v0,
version,
indexes,
VecBuilderOptions::default().add_last(),
)?,
addresstype_to_indexes_to_addr_count: AddressTypeToIndexesToAddressCount::forced_import(
&db,
"addr_count",
v0,
indexes,
&addresstype_to_height_to_addr_count,
)?,
addresstype_to_indexes_to_addr_count:
AddressTypeToIndexesToAddressCount::forced_import(
&db,
"addr_count",
version,
indexes,
&addresstype_to_height_to_addr_count,
)?,
addresstype_to_indexes_to_empty_addr_count:
AddressTypeToIndexesToAddressCount::forced_import(
&db,
"empty_addr_count",
v0,
version,
indexes,
&addresstype_to_height_to_empty_addr_count,
)?,
@@ -162,7 +162,7 @@ impl Vecs {
utxo_cohorts,
address_cohorts,
any_address_indexes: AnyAddressIndexesVecs::forced_import(&db, v0)?,
any_address_indexes: AnyAddressIndexesVecs::forced_import(&db, version)?,
addresses_data: AddressesDataVecs {
loaded: loadedaddressindex_to_loadedaddressdata,
empty: emptyaddressindex_to_emptyaddressdata,
@@ -328,11 +328,52 @@ impl Vecs {
exit,
)?;
// 6b. Compute address count dateindex vecs (per-addresstype)
self.addresstype_to_indexes_to_addr_count.compute(
indexes,
starting_indexes,
exit,
&self.addresstype_to_height_to_addr_count,
)?;
self.addresstype_to_indexes_to_empty_addr_count.compute(
indexes,
starting_indexes,
exit,
&self.addresstype_to_height_to_empty_addr_count,
)?;
// 6c. Compute global address count dateindex vecs (sum of all address types)
let addr_count_sources: Vec<_> =
self.addresstype_to_height_to_addr_count.values().collect();
self.indexes_to_addr_count
.compute_all(indexes, starting_indexes, exit, |height_vec| {
Ok(height_vec.compute_sum_of_others(
starting_indexes.height,
&addr_count_sources,
exit,
)?)
})?;
let empty_addr_count_sources: Vec<_> = self
.addresstype_to_height_to_empty_addr_count
.values()
.collect();
self.indexes_to_empty_addr_count.compute_all(
indexes,
starting_indexes,
exit,
|height_vec| {
Ok(height_vec.compute_sum_of_others(
starting_indexes.height,
&empty_addr_count_sources,
exit,
)?)
},
)?;
// 7. Compute rest part2 (relative metrics)
let supply_metrics = &self.utxo_cohorts.all.metrics.supply;
let height_to_supply = &supply_metrics.height_to_supply_value.bitcoin.clone();
let height_to_market_cap = supply_metrics
.height_to_supply_value
.dollars
@@ -354,7 +395,6 @@ impl Vecs {
indexes,
price,
starting_indexes,
height_to_supply,
height_to_market_cap_ref,
dateindex_to_market_cap_ref,
exit,

View File

@@ -24,7 +24,7 @@ impl Vecs {
db,
"input_count",
Source::Vec(indexes.transaction.txindex_to_input_count.boxed_clone()),
version + Version::ZERO,
version,
indexes,
full_stats(),
)?,

View File

@@ -17,7 +17,7 @@ impl Vecs {
let db = Database::open(&parent_path.join(super::DB_NAME))?;
db.set_min_len(PAGE_SIZE * 50_000_000)?;
let version = parent_version + Version::ZERO;
let version = parent_version;
let spent = SpentVecs::forced_import(&db, version)?;
let count = CountVecs::forced_import(&db, version, indexes)?;

View File

@@ -60,7 +60,7 @@ where
first: options.first.then(|| {
Box::new(LazyVecFrom2::init(
&maybe_suffix("first"),
version + VERSION + Version::ZERO,
version + VERSION,
source_extra
.first
.as_ref()
@@ -77,7 +77,7 @@ where
last: options.last.then(|| {
Box::new(LazyVecFrom2::init(
name,
version + VERSION + Version::ZERO,
version + VERSION,
source_extra.last.as_ref().map_or_else(
|| {
source
@@ -102,7 +102,7 @@ where
min: options.min.then(|| {
Box::new(LazyVecFrom2::init(
&maybe_suffix("min"),
version + VERSION + Version::ZERO,
version + VERSION,
source_extra
.min
.as_ref()
@@ -121,7 +121,7 @@ where
max: options.max.then(|| {
Box::new(LazyVecFrom2::init(
&maybe_suffix("max"),
version + VERSION + Version::ZERO,
version + VERSION,
source_extra
.max
.as_ref()
@@ -140,7 +140,7 @@ where
average: options.average.then(|| {
Box::new(LazyVecFrom2::init(
&maybe_suffix("avg"),
version + VERSION + Version::ZERO,
version + VERSION,
source_extra
.average
.as_ref()
@@ -172,7 +172,7 @@ where
} else {
maybe_suffix("sum")
}),
version + VERSION + Version::ZERO,
version + VERSION,
source_extra
.sum
.as_ref()
@@ -200,7 +200,7 @@ where
cumulative: options.cumulative.then(|| {
Box::new(LazyVecFrom2::init(
&suffix("cumulative"),
version + VERSION + Version::ZERO,
version + VERSION,
source_extra.cumulative.u().boxed_clone(),
len_source.clone(),
|i: I, source, len_source| {

View File

@@ -1,7 +1,8 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, TreeNode, Version, WeekIndex,
YearIndex,
};
use schemars::JsonSchema;
use vecdb::{
@@ -9,7 +10,7 @@ use vecdb::{
PcoVec,
};
use crate::{ComputeIndexes, internal::LazyVecsBuilder, indexes, utils::OptionExt};
use crate::{ComputeIndexes, indexes, internal::LazyVecsBuilder, utils::OptionExt};
use crate::internal::{ComputedVecValue, EagerVecsBuilder, Source, VecBuilderOptions};
@@ -45,12 +46,12 @@ where
) -> Result<Self> {
let dateindex = source
.is_compute()
.then(|| EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap());
.then(|| EagerVec::forced_import(db, name, version + VERSION).unwrap());
let dateindex_extra = EagerVecsBuilder::forced_import(
db,
name,
version + VERSION + Version::ZERO,
version + VERSION,
options.copy_self_extra(),
)?;
@@ -61,7 +62,7 @@ where
Ok(Self {
weekindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
dateindex_source.clone(),
&dateindex_extra,
indexes.time.weekindex_to_weekindex.boxed_clone(),
@@ -69,7 +70,7 @@ where
),
monthindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
dateindex_source.clone(),
&dateindex_extra,
indexes.time.monthindex_to_monthindex.boxed_clone(),
@@ -77,7 +78,7 @@ where
),
quarterindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
dateindex_source.clone(),
&dateindex_extra,
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
@@ -85,7 +86,7 @@ where
),
semesterindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
dateindex_source.clone(),
&dateindex_extra,
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
@@ -93,7 +94,7 @@ where
),
yearindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
dateindex_source.clone(),
&dateindex_extra,
indexes.time.yearindex_to_yearindex.boxed_clone(),
@@ -101,7 +102,7 @@ where
),
decadeindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
dateindex_source.clone(),
&dateindex_extra,
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
@@ -151,9 +152,9 @@ impl<T> Traversable for ComputedVecsFromDateIndex<T>
where
T: ComputedVecValue + JsonSchema,
{
fn to_tree_node(&self) -> brk_traversable::TreeNode {
fn to_tree_node(&self) -> TreeNode {
let dateindex_extra_node = self.dateindex_extra.to_tree_node();
brk_traversable::TreeNode::Branch(
TreeNode::Branch(
[
self.dateindex
.as_ref()

View File

@@ -3,7 +3,7 @@ use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
Version, WeekIndex, YearIndex,
TreeNode, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{
@@ -12,9 +12,8 @@ use vecdb::{
};
use crate::{
ComputeIndexes,
ComputeIndexes, indexes,
internal::{LazyVecsBuilder, Source},
indexes,
utils::OptionExt,
};
@@ -56,17 +55,16 @@ where
) -> Result<Self> {
let height = source
.is_compute()
.then(|| EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap());
.then(|| EagerVec::forced_import(db, name, version + VERSION).unwrap());
let height_extra = EagerVecsBuilder::forced_import(
db,
name,
version + VERSION + Version::ZERO,
version + VERSION,
options.copy_self_extra(),
)?;
let dateindex =
EagerVecsBuilder::forced_import(db, name, version + VERSION + Version::ZERO, options)?;
let dateindex = EagerVecsBuilder::forced_import(db, name, version + VERSION, options)?;
let options = options.remove_percentiles();
@@ -75,7 +73,7 @@ where
Ok(Self {
weekindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.weekindex_to_weekindex.boxed_clone(),
@@ -83,7 +81,7 @@ where
),
monthindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.monthindex_to_monthindex.boxed_clone(),
@@ -91,7 +89,7 @@ where
),
quarterindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
@@ -99,7 +97,7 @@ where
),
semesterindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
@@ -107,7 +105,7 @@ where
),
yearindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.yearindex_to_yearindex.boxed_clone(),
@@ -115,19 +113,22 @@ where
),
decadeindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
options.into(),
),
// halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION + Version::ZERO, format, options)?,
// halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION , format, options)?,
difficultyepoch: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
height_source,
&height_extra,
indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(),
indexes
.block
.difficultyepoch_to_difficultyepoch
.boxed_clone(),
options.into(),
),
height,
@@ -193,9 +194,9 @@ impl<T> Traversable for ComputedVecsFromHeight<T>
where
T: ComputedVecValue + JsonSchema,
{
fn to_tree_node(&self) -> brk_traversable::TreeNode {
fn to_tree_node(&self) -> TreeNode {
let height_extra_node = self.height_extra.to_tree_node();
brk_traversable::TreeNode::Branch(
TreeNode::Branch(
[
self.height
.as_ref()

View File

@@ -1,7 +1,7 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DifficultyEpoch, Height, Version};
use brk_types::{DifficultyEpoch, Height, TreeNode, Version};
use schemars::JsonSchema;
use vecdb::{
AnyExportableVec, Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec,
@@ -36,12 +36,12 @@ where
indexes: &indexes::Vecs,
options: VecBuilderOptions,
) -> Result<Self> {
let height = EagerVec::forced_import(db, name, version + VERSION + Version::ZERO)?;
let height = EagerVec::forced_import(db, name, version + VERSION)?;
let height_extra = EagerVecsBuilder::forced_import(
db,
name,
version + VERSION + Version::ZERO,
version + VERSION,
options.copy_self_extra(),
)?;
@@ -50,15 +50,18 @@ where
Ok(Self {
difficultyepoch: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
Some(height.boxed_clone()),
&height_extra,
indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(),
indexes
.block
.difficultyepoch_to_difficultyepoch
.boxed_clone(),
options.into(),
),
height,
height_extra,
// halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION + Version::ZERO, format, options)?,
// halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION , format, options)?,
})
}
@@ -84,9 +87,9 @@ impl<T> Traversable for ComputedVecsFromHeightStrict<T>
where
T: ComputedVecValue + JsonSchema,
{
fn to_tree_node(&self) -> brk_traversable::TreeNode {
fn to_tree_node(&self) -> TreeNode {
let height_extra_node = self.height_extra.to_tree_node();
brk_traversable::TreeNode::Branch(
TreeNode::Branch(
[
Some(("height".to_string(), self.height.to_tree_node())),
if height_extra_node.is_empty() {

View File

@@ -3,7 +3,7 @@ use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{
Bitcoin, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, Height, MonthIndex, QuarterIndex,
Sats, SemesterIndex, TxIndex, Version, WeekIndex, YearIndex,
Sats, SemesterIndex, TreeNode, TxIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{
@@ -12,9 +12,9 @@ use vecdb::{
};
use crate::{
ComputeIndexes,
ComputeIndexes, indexes,
internal::{LazyVecsBuilder, Source},
indexes, price,
price,
utils::OptionExt,
};
@@ -54,22 +54,20 @@ where
indexes: &indexes::Vecs,
options: VecBuilderOptions,
) -> Result<Self> {
let txindex = source.is_compute().then(|| {
Box::new(EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap())
});
let txindex = source
.is_compute()
.then(|| Box::new(EagerVec::forced_import(db, name, version + VERSION).unwrap()));
let height =
EagerVecsBuilder::forced_import(db, name, version + VERSION + Version::ZERO, options)?;
let height = EagerVecsBuilder::forced_import(db, name, version + VERSION, options)?;
let options = options.remove_percentiles();
let dateindex =
EagerVecsBuilder::forced_import(db, name, version + VERSION + Version::ZERO, options)?;
let dateindex = EagerVecsBuilder::forced_import(db, name, version + VERSION, options)?;
Ok(Self {
weekindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.weekindex_to_weekindex.boxed_clone(),
@@ -77,15 +75,18 @@ where
),
difficultyepoch: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&height,
indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(),
indexes
.block
.difficultyepoch_to_difficultyepoch
.boxed_clone(),
options.into(),
),
monthindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.monthindex_to_monthindex.boxed_clone(),
@@ -93,7 +94,7 @@ where
),
quarterindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
@@ -101,7 +102,7 @@ where
),
semesterindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
@@ -109,7 +110,7 @@ where
),
yearindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.yearindex_to_yearindex.boxed_clone(),
@@ -117,7 +118,7 @@ where
),
decadeindex: LazyVecsBuilder::forced_import(
name,
version + VERSION + Version::ZERO,
version + VERSION,
None,
&dateindex,
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
@@ -127,7 +128,7 @@ where
txindex,
height,
dateindex,
// halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION + Version::ZERO, format, options)?,
// halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION , format, options)?,
})
}
@@ -402,8 +403,8 @@ impl<T> Traversable for ComputedVecsFromTxindex<T>
where
T: ComputedVecValue + JsonSchema,
{
fn to_tree_node(&self) -> brk_traversable::TreeNode {
brk_traversable::TreeNode::Branch(
fn to_tree_node(&self) -> TreeNode {
TreeNode::Branch(
[
self.txindex
.as_ref()

View File

@@ -1,11 +1,14 @@
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, TreeNode, Version, WeekIndex,
YearIndex,
};
use schemars::JsonSchema;
use vecdb::{AnyExportableVec, BinaryTransform, IterableCloneableVec, LazyVecFrom2};
use crate::internal::{ComputedVecValue, ComputedVecsFromDateIndex, ComputedVecsFromHeight, LazyTransform2Builder};
use crate::internal::{
ComputedVecValue, ComputedVecsFromDateIndex, ComputedVecsFromHeight, LazyTransform2Builder,
};
const VERSION: Version = Version::ZERO;
@@ -215,8 +218,8 @@ where
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
fn to_tree_node(&self) -> brk_traversable::TreeNode {
brk_traversable::TreeNode::Branch(
fn to_tree_node(&self) -> TreeNode {
TreeNode::Branch(
[
self.dateindex
.as_ref()

View File

@@ -1,7 +1,7 @@
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
Version, WeekIndex, YearIndex,
TreeNode, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{AnyExportableVec, BinaryTransform, IterableBoxedVec, LazyVecFrom2};
@@ -192,9 +192,9 @@ where
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
fn to_tree_node(&self) -> brk_traversable::TreeNode {
fn to_tree_node(&self) -> TreeNode {
let height_extra_node = self.height_extra.to_tree_node();
brk_traversable::TreeNode::Branch(
TreeNode::Branch(
[
Some(("height".to_string(), self.height.to_tree_node())),
if height_extra_node.is_empty() {

View File

@@ -1,6 +1,7 @@
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, TreeNode, Version, WeekIndex,
YearIndex,
};
use schemars::JsonSchema;
use vecdb::{AnyExportableVec, IterableBoxedVec, LazyVecFrom1, UnaryTransform};
@@ -65,9 +66,9 @@ where
T: ComputedVecValue + JsonSchema,
S1T: ComputedVecValue,
{
fn to_tree_node(&self) -> brk_traversable::TreeNode {
fn to_tree_node(&self) -> TreeNode {
let dateindex_extra_node = self.dateindex_extra.to_tree_node();
brk_traversable::TreeNode::Branch(
TreeNode::Branch(
[
self.dateindex
.as_ref()

View File

@@ -1,7 +1,7 @@
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
Version, WeekIndex, YearIndex,
TreeNode, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{AnyExportableVec, IterableBoxedVec, LazyVecFrom1, UnaryTransform};
@@ -72,9 +72,9 @@ where
T: ComputedVecValue + JsonSchema,
S1T: ComputedVecValue,
{
fn to_tree_node(&self) -> brk_traversable::TreeNode {
fn to_tree_node(&self) -> TreeNode {
let height_extra_node = self.height_extra.to_tree_node();
brk_traversable::TreeNode::Branch(
TreeNode::Branch(
[
Some(("height".to_string(), self.height.to_tree_node())),
if height_extra_node.is_empty() {

View File

@@ -1,17 +1,19 @@
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex,
YearIndex,
DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, TreeNode, Version,
WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use serde::Serialize;
use vecdb::{Formattable, IterableCloneableVec, LazyVecFrom1, UnaryTransform, VecValue};
use vecdb::{
AnyExportableVec, Formattable, IterableCloneableVec, LazyVecFrom1, UnaryTransform, VecValue,
};
use crate::indexes;
use crate::{indexes, internal::ComputedVecValue};
/// Lazy constant vecs for all index levels.
/// Uses const generic transforms to return the same value for every index.
#[derive(Clone, Traversable)]
#[derive(Clone)]
pub struct ConstantVecs<T>
where
T: VecValue + Formattable + Serialize + JsonSchema,
@@ -83,3 +85,44 @@ impl<T: VecValue + Formattable + Serialize + JsonSchema> ConstantVecs<T> {
}
}
}
impl<T> Traversable for ConstantVecs<T>
where
T: ComputedVecValue + JsonSchema,
{
fn to_tree_node(&self) -> TreeNode {
TreeNode::Branch(
[
Some(("height".to_string(), self.height.to_tree_node())),
Some(("dateindex".to_string(), self.dateindex.to_tree_node())),
Some(("weekindex".to_string(), self.weekindex.to_tree_node())),
Some(("monthindex".to_string(), self.monthindex.to_tree_node())),
Some(("quarterindex".to_string(), self.quarterindex.to_tree_node())),
Some((
"semesterindex".to_string(),
self.semesterindex.to_tree_node(),
)),
Some(("yearindex".to_string(), self.yearindex.to_tree_node())),
Some(("decadeindex".to_string(), self.decadeindex.to_tree_node())),
]
.into_iter()
.flatten()
.collect(),
)
.merge_branches()
.unwrap()
}
fn iter_any_exportable(&self) -> impl Iterator<Item = &dyn AnyExportableVec> {
let mut regular_iter: Box<dyn Iterator<Item = &dyn AnyExportableVec>> =
Box::new(self.height.iter_any_exportable());
regular_iter = Box::new(regular_iter.chain(self.dateindex.iter_any_exportable()));
regular_iter = Box::new(regular_iter.chain(self.weekindex.iter_any_exportable()));
regular_iter = Box::new(regular_iter.chain(self.monthindex.iter_any_exportable()));
regular_iter = Box::new(regular_iter.chain(self.quarterindex.iter_any_exportable()));
regular_iter = Box::new(regular_iter.chain(self.semesterindex.iter_any_exportable()));
regular_iter = Box::new(regular_iter.chain(self.yearindex.iter_any_exportable()));
regular_iter = Box::new(regular_iter.chain(self.decadeindex.iter_any_exportable()));
regular_iter
}
}

View File

@@ -35,14 +35,14 @@ impl LazyValueVecsFromDateIndex {
let sats = LazyVecsFromDateIndex::from_computed::<SatsTransform>(
name,
v + Version::ZERO,
v,
source.sats.dateindex.as_ref().map(|v| v.boxed_clone()),
&source.sats,
);
let bitcoin = LazyVecsFromDateIndex::from_computed::<BitcoinTransform>(
&format!("{name}_btc"),
v + Version::ZERO,
v,
source.sats.dateindex.as_ref().map(|v| v.boxed_clone()),
&source.sats,
);
@@ -50,7 +50,7 @@ impl LazyValueVecsFromDateIndex {
let dollars = source.dollars.as_ref().map(|dollars_source| {
LazyVecsFromDateIndex::from_computed::<DollarsTransform>(
&format!("{name}_usd"),
v + Version::ZERO,
v,
dollars_source.dateindex.as_ref().map(|v| v.boxed_clone()),
dollars_source,
)

View File

@@ -32,15 +32,11 @@ impl LazyHeightValueVecs {
{
let v = version + VERSION;
let sats = LazyVecFrom1::transformed::<SatsTransform>(
name,
v + Version::ZERO,
sats_source.clone(),
);
let sats = LazyVecFrom1::transformed::<SatsTransform>(name, v, sats_source.clone());
let bitcoin = LazyVecFrom1::transformed::<BitcoinTransform>(
&format!("{name}_btc"),
v + Version::ZERO,
v,
sats_source.clone(),
);
@@ -48,7 +44,7 @@ impl LazyHeightValueVecs {
let dollars = price_source.map(|price| {
LazyVecFrom2::transformed::<DollarsTransform>(
&format!("{name}_usd"),
v + Version::ZERO,
v,
price,
sats_source,
)

View File

@@ -27,7 +27,7 @@ impl ComputedHeightValueVecs {
) -> Result<Self> {
let sats = source
.is_compute()
.then(|| EagerVec::forced_import(db, name, version + VERSION + Version::ZERO).unwrap());
.then(|| EagerVec::forced_import(db, name, version + VERSION).unwrap());
let sats_source: IterableBoxedVec<Height, Sats> = source
.vec()
@@ -35,14 +35,14 @@ impl ComputedHeightValueVecs {
let bitcoin = LazyVecFrom1::transformed::<SatsToBitcoin>(
&format!("{name}_btc"),
version + VERSION + Version::ZERO,
version + VERSION,
sats_source.clone(),
);
let dollars = price_source.map(|price| {
LazyVecFrom2::transformed::<ClosePriceTimesSats>(
&format!("{name}_usd"),
version + VERSION + Version::ZERO,
version + VERSION,
price,
sats_source.clone(),
)

View File

@@ -4,11 +4,12 @@ use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec};
use super::Vecs;
use crate::{
indexes,
internal::{
ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, LazyVecsFromDateIndex,
PercentageDiffCloseDollars, Source, StoredU16ToYears, VecBuilderOptions,
},
indexes, price,
price,
};
impl Vecs {
@@ -18,14 +19,13 @@ impl Vecs {
indexes: &indexes::Vecs,
price: &price::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let last = VecBuilderOptions::default().add_last();
let indexes_to_price_ath = ComputedVecsFromDateIndex::forced_import(
db,
"price_ath",
Source::Compute,
version + v0,
version,
indexes,
last,
)?;
@@ -34,7 +34,7 @@ impl Vecs {
db,
"max_days_between_price_aths",
Source::Compute,
version + v0,
version,
indexes,
last,
)?;
@@ -42,7 +42,7 @@ impl Vecs {
let indexes_to_max_years_between_price_aths =
LazyVecsFromDateIndex::from_computed::<StoredU16ToYears>(
"max_years_between_price_aths",
version + v0,
version,
indexes_to_max_days_between_price_aths
.dateindex
.as_ref()
@@ -53,21 +53,21 @@ impl Vecs {
let indexes_to_price_drawdown =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"price_drawdown",
version + v0,
version,
&price.usd.timeindexes_to_price_close,
&indexes_to_price_ath,
);
Ok(Self {
height_to_price_ath: EagerVec::forced_import(db, "price_ath", version + v0)?,
height_to_price_drawdown: EagerVec::forced_import(db, "price_drawdown", version + v0)?,
height_to_price_ath: EagerVec::forced_import(db, "price_ath", version)?,
height_to_price_drawdown: EagerVec::forced_import(db, "price_drawdown", version)?,
indexes_to_price_ath,
indexes_to_price_drawdown,
indexes_to_days_since_price_ath: ComputedVecsFromDateIndex::forced_import(
db,
"days_since_price_ath",
Source::Compute,
version + v0,
version,
indexes,
last,
)?,

View File

@@ -31,8 +31,9 @@ impl Vecs {
// Moving average metrics (independent)
self.moving_average.compute(price, starting_indexes, exit)?;
// DCA metrics
self.dca.compute(price, starting_indexes, exit)?;
// DCA metrics (depends on lookback for lump sum comparison)
self.dca
.compute(price, &self.lookback, starting_indexes, exit)?;
self.indicators.compute(
&blocks.rewards,

View File

@@ -0,0 +1,213 @@
use brk_traversable::Traversable;
use brk_types::{Date, DateIndex};
/// DCA class years
pub const DCA_CLASS_YEARS: ByDcaClass<u16> = ByDcaClass {
_2015: 2015,
_2016: 2016,
_2017: 2017,
_2018: 2018,
_2019: 2019,
_2020: 2020,
_2021: 2021,
_2022: 2022,
_2023: 2023,
_2024: 2024,
_2025: 2025,
};
/// DCA class names
pub const DCA_CLASS_NAMES: ByDcaClass<&'static str> = ByDcaClass {
_2015: "dca_class_2015",
_2016: "dca_class_2016",
_2017: "dca_class_2017",
_2018: "dca_class_2018",
_2019: "dca_class_2019",
_2020: "dca_class_2020",
_2021: "dca_class_2021",
_2022: "dca_class_2022",
_2023: "dca_class_2023",
_2024: "dca_class_2024",
_2025: "dca_class_2025",
};
/// Generic wrapper for DCA year class data
#[derive(Default, Clone, Traversable)]
pub struct ByDcaClass<T> {
pub _2015: T,
pub _2016: T,
pub _2017: T,
pub _2018: T,
pub _2019: T,
pub _2020: T,
pub _2021: T,
pub _2022: T,
pub _2023: T,
pub _2024: T,
pub _2025: T,
}
impl<T> ByDcaClass<T> {
pub fn new<F>(mut create: F) -> Self
where
F: FnMut(&'static str, u16, DateIndex) -> T,
{
let n = DCA_CLASS_NAMES;
let y = DCA_CLASS_YEARS;
Self {
_2015: create(n._2015, y._2015, Self::dateindex(y._2015)),
_2016: create(n._2016, y._2016, Self::dateindex(y._2016)),
_2017: create(n._2017, y._2017, Self::dateindex(y._2017)),
_2018: create(n._2018, y._2018, Self::dateindex(y._2018)),
_2019: create(n._2019, y._2019, Self::dateindex(y._2019)),
_2020: create(n._2020, y._2020, Self::dateindex(y._2020)),
_2021: create(n._2021, y._2021, Self::dateindex(y._2021)),
_2022: create(n._2022, y._2022, Self::dateindex(y._2022)),
_2023: create(n._2023, y._2023, Self::dateindex(y._2023)),
_2024: create(n._2024, y._2024, Self::dateindex(y._2024)),
_2025: create(n._2025, y._2025, Self::dateindex(y._2025)),
}
}
pub fn try_new<F, E>(mut create: F) -> Result<Self, E>
where
F: FnMut(&'static str, u16, DateIndex) -> Result<T, E>,
{
let n = DCA_CLASS_NAMES;
let y = DCA_CLASS_YEARS;
Ok(Self {
_2015: create(n._2015, y._2015, Self::dateindex(y._2015))?,
_2016: create(n._2016, y._2016, Self::dateindex(y._2016))?,
_2017: create(n._2017, y._2017, Self::dateindex(y._2017))?,
_2018: create(n._2018, y._2018, Self::dateindex(y._2018))?,
_2019: create(n._2019, y._2019, Self::dateindex(y._2019))?,
_2020: create(n._2020, y._2020, Self::dateindex(y._2020))?,
_2021: create(n._2021, y._2021, Self::dateindex(y._2021))?,
_2022: create(n._2022, y._2022, Self::dateindex(y._2022))?,
_2023: create(n._2023, y._2023, Self::dateindex(y._2023))?,
_2024: create(n._2024, y._2024, Self::dateindex(y._2024))?,
_2025: create(n._2025, y._2025, Self::dateindex(y._2025))?,
})
}
pub fn dateindex(year: u16) -> DateIndex {
DateIndex::try_from(Date::new(year, 1, 1)).unwrap()
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
[
&self._2015,
&self._2016,
&self._2017,
&self._2018,
&self._2019,
&self._2020,
&self._2021,
&self._2022,
&self._2023,
&self._2024,
&self._2025,
]
.into_iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
[
&mut self._2015,
&mut self._2016,
&mut self._2017,
&mut self._2018,
&mut self._2019,
&mut self._2020,
&mut self._2021,
&mut self._2022,
&mut self._2023,
&mut self._2024,
&mut self._2025,
]
.into_iter()
}
pub fn iter_mut_with_dateindex(&mut self) -> impl Iterator<Item = (&mut T, DateIndex)> {
let y = DCA_CLASS_YEARS;
[
(&mut self._2015, Self::dateindex(y._2015)),
(&mut self._2016, Self::dateindex(y._2016)),
(&mut self._2017, Self::dateindex(y._2017)),
(&mut self._2018, Self::dateindex(y._2018)),
(&mut self._2019, Self::dateindex(y._2019)),
(&mut self._2020, Self::dateindex(y._2020)),
(&mut self._2021, Self::dateindex(y._2021)),
(&mut self._2022, Self::dateindex(y._2022)),
(&mut self._2023, Self::dateindex(y._2023)),
(&mut self._2024, Self::dateindex(y._2024)),
(&mut self._2025, Self::dateindex(y._2025)),
]
.into_iter()
}
pub fn dateindexes() -> [DateIndex; 11] {
let y = DCA_CLASS_YEARS;
[
Self::dateindex(y._2015),
Self::dateindex(y._2016),
Self::dateindex(y._2017),
Self::dateindex(y._2018),
Self::dateindex(y._2019),
Self::dateindex(y._2020),
Self::dateindex(y._2021),
Self::dateindex(y._2022),
Self::dateindex(y._2023),
Self::dateindex(y._2024),
Self::dateindex(y._2025),
]
}
pub fn zip<U>(self, other: ByDcaClass<U>) -> ByDcaClass<(T, U)> {
ByDcaClass {
_2015: (self._2015, other._2015),
_2016: (self._2016, other._2016),
_2017: (self._2017, other._2017),
_2018: (self._2018, other._2018),
_2019: (self._2019, other._2019),
_2020: (self._2020, other._2020),
_2021: (self._2021, other._2021),
_2022: (self._2022, other._2022),
_2023: (self._2023, other._2023),
_2024: (self._2024, other._2024),
_2025: (self._2025, other._2025),
}
}
pub fn zip_ref<'a, U>(&'a self, other: &'a ByDcaClass<U>) -> ByDcaClass<(&'a T, &'a U)> {
ByDcaClass {
_2015: (&self._2015, &other._2015),
_2016: (&self._2016, &other._2016),
_2017: (&self._2017, &other._2017),
_2018: (&self._2018, &other._2018),
_2019: (&self._2019, &other._2019),
_2020: (&self._2020, &other._2020),
_2021: (&self._2021, &other._2021),
_2022: (&self._2022, &other._2022),
_2023: (&self._2023, &other._2023),
_2024: (&self._2024, &other._2024),
_2025: (&self._2025, &other._2025),
}
}
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> ByDcaClass<U> {
ByDcaClass {
_2015: f(self._2015),
_2016: f(self._2016),
_2017: f(self._2017),
_2018: f(self._2018),
_2019: f(self._2019),
_2020: f(self._2020),
_2021: f(self._2021),
_2022: f(self._2022),
_2023: f(self._2023),
_2024: f(self._2024),
_2025: f(self._2025),
}
}
}

View File

@@ -0,0 +1,395 @@
use brk_traversable::Traversable;
/// DCA period identifiers with their day counts
pub const DCA_PERIOD_DAYS: ByDcaPeriod<u32> = ByDcaPeriod {
_1w: 7,
_1m: 30,
_3m: 3 * 30,
_6m: 6 * 30,
_1y: 365,
_2y: 2 * 365,
_3y: 3 * 365,
_4y: 4 * 365,
_5y: 5 * 365,
_6y: 6 * 365,
_8y: 8 * 365,
_10y: 10 * 365,
};
/// DCA period names
pub const DCA_PERIOD_NAMES: ByDcaPeriod<&'static str> = ByDcaPeriod {
_1w: "1w",
_1m: "1m",
_3m: "3m",
_6m: "6m",
_1y: "1y",
_2y: "2y",
_3y: "3y",
_4y: "4y",
_5y: "5y",
_6y: "6y",
_8y: "8y",
_10y: "10y",
};
/// DCA CAGR period days (only periods >= 2y)
pub const DCA_CAGR_DAYS: ByDcaCagr<u32> = ByDcaCagr {
_2y: 2 * 365,
_3y: 3 * 365,
_4y: 4 * 365,
_5y: 5 * 365,
_6y: 6 * 365,
_8y: 8 * 365,
_10y: 10 * 365,
};
/// DCA CAGR period names
pub const DCA_CAGR_NAMES: ByDcaCagr<&'static str> = ByDcaCagr {
_2y: "2y",
_3y: "3y",
_4y: "4y",
_5y: "5y",
_6y: "6y",
_8y: "8y",
_10y: "10y",
};
/// Generic wrapper for DCA period-based data
#[derive(Default, Clone, Traversable)]
pub struct ByDcaPeriod<T> {
pub _1w: T,
pub _1m: T,
pub _3m: T,
pub _6m: T,
pub _1y: T,
pub _2y: T,
pub _3y: T,
pub _4y: T,
pub _5y: T,
pub _6y: T,
pub _8y: T,
pub _10y: T,
}
impl<T> ByDcaPeriod<T> {
pub fn new<F>(mut create: F) -> Self
where
F: FnMut(&'static str, u32) -> T,
{
let n = DCA_PERIOD_NAMES;
let d = DCA_PERIOD_DAYS;
Self {
_1w: create(n._1w, d._1w),
_1m: create(n._1m, d._1m),
_3m: create(n._3m, d._3m),
_6m: create(n._6m, d._6m),
_1y: create(n._1y, d._1y),
_2y: create(n._2y, d._2y),
_3y: create(n._3y, d._3y),
_4y: create(n._4y, d._4y),
_5y: create(n._5y, d._5y),
_6y: create(n._6y, d._6y),
_8y: create(n._8y, d._8y),
_10y: create(n._10y, d._10y),
}
}
pub fn try_new<F, E>(mut create: F) -> Result<Self, E>
where
F: FnMut(&'static str, u32) -> Result<T, E>,
{
let n = DCA_PERIOD_NAMES;
let d = DCA_PERIOD_DAYS;
Ok(Self {
_1w: create(n._1w, d._1w)?,
_1m: create(n._1m, d._1m)?,
_3m: create(n._3m, d._3m)?,
_6m: create(n._6m, d._6m)?,
_1y: create(n._1y, d._1y)?,
_2y: create(n._2y, d._2y)?,
_3y: create(n._3y, d._3y)?,
_4y: create(n._4y, d._4y)?,
_5y: create(n._5y, d._5y)?,
_6y: create(n._6y, d._6y)?,
_8y: create(n._8y, d._8y)?,
_10y: create(n._10y, d._10y)?,
})
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
[
&self._1w,
&self._1m,
&self._3m,
&self._6m,
&self._1y,
&self._2y,
&self._3y,
&self._4y,
&self._5y,
&self._6y,
&self._8y,
&self._10y,
]
.into_iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
[
&mut self._1w,
&mut self._1m,
&mut self._3m,
&mut self._6m,
&mut self._1y,
&mut self._2y,
&mut self._3y,
&mut self._4y,
&mut self._5y,
&mut self._6y,
&mut self._8y,
&mut self._10y,
]
.into_iter()
}
pub fn iter_with_days(&self) -> impl Iterator<Item = (&T, u32)> {
let d = DCA_PERIOD_DAYS;
[
(&self._1w, d._1w),
(&self._1m, d._1m),
(&self._3m, d._3m),
(&self._6m, d._6m),
(&self._1y, d._1y),
(&self._2y, d._2y),
(&self._3y, d._3y),
(&self._4y, d._4y),
(&self._5y, d._5y),
(&self._6y, d._6y),
(&self._8y, d._8y),
(&self._10y, d._10y),
]
.into_iter()
}
pub fn iter_mut_with_days(&mut self) -> impl Iterator<Item = (&mut T, u32)> {
let d = DCA_PERIOD_DAYS;
[
(&mut self._1w, d._1w),
(&mut self._1m, d._1m),
(&mut self._3m, d._3m),
(&mut self._6m, d._6m),
(&mut self._1y, d._1y),
(&mut self._2y, d._2y),
(&mut self._3y, d._3y),
(&mut self._4y, d._4y),
(&mut self._5y, d._5y),
(&mut self._6y, d._6y),
(&mut self._8y, d._8y),
(&mut self._10y, d._10y),
]
.into_iter()
}
pub fn zip_mut<'a, U>(&'a mut self, other: &'a ByDcaPeriod<U>) -> impl Iterator<Item = (&'a mut T, &'a U)> {
[
(&mut self._1w, &other._1w),
(&mut self._1m, &other._1m),
(&mut self._3m, &other._3m),
(&mut self._6m, &other._6m),
(&mut self._1y, &other._1y),
(&mut self._2y, &other._2y),
(&mut self._3y, &other._3y),
(&mut self._4y, &other._4y),
(&mut self._5y, &other._5y),
(&mut self._6y, &other._6y),
(&mut self._8y, &other._8y),
(&mut self._10y, &other._10y),
]
.into_iter()
}
pub fn zip_mut_with_days<'a, U>(
&'a mut self,
other: &'a ByDcaPeriod<U>,
) -> impl Iterator<Item = (&'a mut T, &'a U, u32)> {
let d = DCA_PERIOD_DAYS;
[
(&mut self._1w, &other._1w, d._1w),
(&mut self._1m, &other._1m, d._1m),
(&mut self._3m, &other._3m, d._3m),
(&mut self._6m, &other._6m, d._6m),
(&mut self._1y, &other._1y, d._1y),
(&mut self._2y, &other._2y, d._2y),
(&mut self._3y, &other._3y, d._3y),
(&mut self._4y, &other._4y, d._4y),
(&mut self._5y, &other._5y, d._5y),
(&mut self._6y, &other._6y, d._6y),
(&mut self._8y, &other._8y, d._8y),
(&mut self._10y, &other._10y, d._10y),
]
.into_iter()
}
pub fn zip_ref<'a, U>(&'a self, other: &'a ByDcaPeriod<U>) -> ByDcaPeriod<(&'a T, &'a U)> {
ByDcaPeriod {
_1w: (&self._1w, &other._1w),
_1m: (&self._1m, &other._1m),
_3m: (&self._3m, &other._3m),
_6m: (&self._6m, &other._6m),
_1y: (&self._1y, &other._1y),
_2y: (&self._2y, &other._2y),
_3y: (&self._3y, &other._3y),
_4y: (&self._4y, &other._4y),
_5y: (&self._5y, &other._5y),
_6y: (&self._6y, &other._6y),
_8y: (&self._8y, &other._8y),
_10y: (&self._10y, &other._10y),
}
}
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> ByDcaPeriod<U> {
ByDcaPeriod {
_1w: f(self._1w),
_1m: f(self._1m),
_3m: f(self._3m),
_6m: f(self._6m),
_1y: f(self._1y),
_2y: f(self._2y),
_3y: f(self._3y),
_4y: f(self._4y),
_5y: f(self._5y),
_6y: f(self._6y),
_8y: f(self._8y),
_10y: f(self._10y),
}
}
pub fn zip_mut2_with_days<'a, U, V>(
&'a mut self,
other1: &'a ByDcaPeriod<U>,
other2: &'a ByDcaPeriod<V>,
) -> impl Iterator<Item = (&'a mut T, &'a U, &'a V, u32)> {
let d = DCA_PERIOD_DAYS;
[
(&mut self._1w, &other1._1w, &other2._1w, d._1w),
(&mut self._1m, &other1._1m, &other2._1m, d._1m),
(&mut self._3m, &other1._3m, &other2._3m, d._3m),
(&mut self._6m, &other1._6m, &other2._6m, d._6m),
(&mut self._1y, &other1._1y, &other2._1y, d._1y),
(&mut self._2y, &other1._2y, &other2._2y, d._2y),
(&mut self._3y, &other1._3y, &other2._3y, d._3y),
(&mut self._4y, &other1._4y, &other2._4y, d._4y),
(&mut self._5y, &other1._5y, &other2._5y, d._5y),
(&mut self._6y, &other1._6y, &other2._6y, d._6y),
(&mut self._8y, &other1._8y, &other2._8y, d._8y),
(&mut self._10y, &other1._10y, &other2._10y, d._10y),
]
.into_iter()
}
}
/// Generic wrapper for DCA CAGR data (periods >= 2 years)
#[derive(Default, Clone, Traversable)]
pub struct ByDcaCagr<T> {
pub _2y: T,
pub _3y: T,
pub _4y: T,
pub _5y: T,
pub _6y: T,
pub _8y: T,
pub _10y: T,
}
impl<T> ByDcaCagr<T> {
pub fn new<F>(mut create: F) -> Self
where
F: FnMut(&'static str, u32) -> T,
{
let n = DCA_CAGR_NAMES;
let d = DCA_CAGR_DAYS;
Self {
_2y: create(n._2y, d._2y),
_3y: create(n._3y, d._3y),
_4y: create(n._4y, d._4y),
_5y: create(n._5y, d._5y),
_6y: create(n._6y, d._6y),
_8y: create(n._8y, d._8y),
_10y: create(n._10y, d._10y),
}
}
pub fn try_new<F, E>(mut create: F) -> Result<Self, E>
where
F: FnMut(&'static str, u32) -> Result<T, E>,
{
let n = DCA_CAGR_NAMES;
let d = DCA_CAGR_DAYS;
Ok(Self {
_2y: create(n._2y, d._2y)?,
_3y: create(n._3y, d._3y)?,
_4y: create(n._4y, d._4y)?,
_5y: create(n._5y, d._5y)?,
_6y: create(n._6y, d._6y)?,
_8y: create(n._8y, d._8y)?,
_10y: create(n._10y, d._10y)?,
})
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
[
&self._2y,
&self._3y,
&self._4y,
&self._5y,
&self._6y,
&self._8y,
&self._10y,
]
.into_iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
[
&mut self._2y,
&mut self._3y,
&mut self._4y,
&mut self._5y,
&mut self._6y,
&mut self._8y,
&mut self._10y,
]
.into_iter()
}
pub fn iter_mut_with_days(&mut self) -> impl Iterator<Item = (&mut T, u32)> {
let d = DCA_CAGR_DAYS;
[
(&mut self._2y, d._2y),
(&mut self._3y, d._3y),
(&mut self._4y, d._4y),
(&mut self._5y, d._5y),
(&mut self._6y, d._6y),
(&mut self._8y, d._8y),
(&mut self._10y, d._10y),
]
.into_iter()
}
/// Zip with the matching subset of a ByDcaPeriod
pub fn zip_mut_with_period<'a, U>(
&'a mut self,
period: &'a ByDcaPeriod<U>,
) -> impl Iterator<Item = (&'a mut T, &'a U, u32)> {
let d = DCA_CAGR_DAYS;
[
(&mut self._2y, &period._2y, d._2y),
(&mut self._3y, &period._3y, d._3y),
(&mut self._4y, &period._4y, d._4y),
(&mut self._5y, &period._5y, d._5y),
(&mut self._6y, &period._6y, d._6y),
(&mut self._8y, &period._8y, d._8y),
(&mut self._10y, &period._10y, d._10y),
]
.into_iter()
}
}

View File

@@ -1,11 +1,11 @@
use brk_error::Result;
use brk_types::{Date, DateIndex};
use vecdb::Exit;
use super::Vecs;
use crate::{
market::lookback,
price,
traits::{ComputeDCAAveragePriceViaLen, ComputeDCAStackViaLen},
traits::{ComputeDCAAveragePriceViaLen, ComputeDCAStackViaLen, ComputeLumpSumStackViaLen},
utils::OptionExt,
ComputeIndexes,
};
@@ -14,334 +14,79 @@ impl Vecs {
pub fn compute(
&mut self,
price: &price::Vecs,
lookback: &lookback::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
let close = price.usd.timeindexes_to_price_close.dateindex.u();
// DCA by period - stack and avg_price
self._1w_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 7, exit)?;
Ok(())
})?;
self._1w_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._1w_dca_stack.dateindex.u(),
7,
exit,
)?;
// DCA by period - stack
for (stack, days) in self.period_stack.iter_mut_with_days() {
stack.compute_all(Some(price), starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, days as usize, exit)?;
Ok(())
})?;
}
self._1m_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 30, exit)?;
Ok(())
})?;
self._1m_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
// DCA by period - avg_price (needs stack's dateindex)
for (avg_price, stack, days) in self
.period_avg_price
.zip_mut_with_days(&self.period_stack)
{
avg_price.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._1m_dca_stack.dateindex.u(),
30,
exit,
)?;
Ok(())
})?;
self._3m_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 3 * 30, exit)?;
Ok(())
})?;
self._3m_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._3m_dca_stack.dateindex.u(),
3 * 30,
exit,
)?;
Ok(())
})?;
self._6m_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 6 * 30, exit)?;
Ok(())
})?;
self._6m_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._6m_dca_stack.dateindex.u(),
6 * 30,
exit,
)?;
Ok(())
})?;
self._1y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 365, exit)?;
Ok(())
})?;
self._1y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._1y_dca_stack.dateindex.u(),
365,
exit,
)?;
Ok(())
})?;
self._2y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 2 * 365, exit)?;
Ok(())
})?;
self._2y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._2y_dca_stack.dateindex.u(),
2 * 365,
exit,
)?;
Ok(())
})?;
self._3y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 3 * 365, exit)?;
Ok(())
})?;
self._3y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._3y_dca_stack.dateindex.u(),
3 * 365,
exit,
)?;
Ok(())
})?;
self._4y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 4 * 365, exit)?;
Ok(())
})?;
self._4y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._4y_dca_stack.dateindex.u(),
4 * 365,
exit,
)?;
Ok(())
})?;
self._5y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 5 * 365, exit)?;
Ok(())
})?;
self._5y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._5y_dca_stack.dateindex.u(),
5 * 365,
exit,
)?;
Ok(())
})?;
self._6y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 6 * 365, exit)?;
Ok(())
})?;
self._6y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._6y_dca_stack.dateindex.u(),
6 * 365,
exit,
)?;
Ok(())
})?;
self._8y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 8 * 365, exit)?;
Ok(())
})?;
self._8y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._8y_dca_stack.dateindex.u(),
8 * 365,
exit,
)?;
Ok(())
})?;
self._10y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 10 * 365, exit)?;
Ok(())
})?;
self._10y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._10y_dca_stack.dateindex.u(),
10 * 365,
stack.sats.dateindex.u(),
days as usize,
exit,
)?;
Ok(())
})?;
}
// DCA by period - CAGR (computed from returns)
self._2y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._2y_dca_returns.dateindex.u(),
2 * 365,
exit,
)?;
Ok(())
})?;
self._3y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._3y_dca_returns.dateindex.u(),
3 * 365,
exit,
)?;
Ok(())
})?;
self._4y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._4y_dca_returns.dateindex.u(),
4 * 365,
exit,
)?;
Ok(())
})?;
self._5y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._5y_dca_returns.dateindex.u(),
5 * 365,
exit,
)?;
Ok(())
})?;
self._6y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._6y_dca_returns.dateindex.u(),
6 * 365,
exit,
)?;
Ok(())
})?;
self._8y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._8y_dca_returns.dateindex.u(),
8 * 365,
exit,
)?;
Ok(())
})?;
self._10y_dca_cagr
.compute_all(starting_indexes, exit, |v| {
for (cagr, returns, days) in self
.period_cagr
.zip_mut_with_period(&self.period_returns)
{
cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._10y_dca_returns.dateindex.u(),
10 * 365,
returns.dateindex.u(),
days as usize,
exit,
)?;
Ok(())
})?;
}
// Lump sum by period - stack (for comparison with DCA)
let lookback_dca = lookback.price_ago.as_dca_period();
for (stack, lookback_price, days) in self
.period_lump_sum_stack
.zip_mut_with_days(&lookback_dca)
{
stack.compute_all(Some(price), starting_indexes, exit, |v| {
v.compute_lump_sum_stack_via_len(
starting_indexes.dateindex,
close,
lookback_price.dateindex.u(),
days as usize,
exit,
)?;
Ok(())
})?;
}
// DCA by year class - stack and avg_price
// Each year class computes DCA from Jan 1 of that year
[
(
2025,
&mut self.dca_class_2025_stack,
&mut self.dca_class_2025_avg_price,
),
(
2024,
&mut self.dca_class_2024_stack,
&mut self.dca_class_2024_avg_price,
),
(
2023,
&mut self.dca_class_2023_stack,
&mut self.dca_class_2023_avg_price,
),
(
2022,
&mut self.dca_class_2022_stack,
&mut self.dca_class_2022_avg_price,
),
(
2021,
&mut self.dca_class_2021_stack,
&mut self.dca_class_2021_avg_price,
),
(
2020,
&mut self.dca_class_2020_stack,
&mut self.dca_class_2020_avg_price,
),
(
2019,
&mut self.dca_class_2019_stack,
&mut self.dca_class_2019_avg_price,
),
(
2018,
&mut self.dca_class_2018_stack,
&mut self.dca_class_2018_avg_price,
),
(
2017,
&mut self.dca_class_2017_stack,
&mut self.dca_class_2017_avg_price,
),
(
2016,
&mut self.dca_class_2016_stack,
&mut self.dca_class_2016_avg_price,
),
(
2015,
&mut self.dca_class_2015_stack,
&mut self.dca_class_2015_avg_price,
),
]
.into_iter()
.try_for_each(|(year, stack, avg_price)| -> Result<()> {
let dateindex = DateIndex::try_from(Date::new(year, 1, 1)).unwrap();
stack.compute_all(starting_indexes, exit, |v| {
let dateindexes = super::ByDcaClass::<()>::dateindexes();
for ((stack, avg_price), dateindex) in self
.class_stack
.iter_mut()
.zip(self.class_avg_price.iter_mut())
.zip(dateindexes)
{
stack.compute_all(Some(price), starting_indexes, exit, |v| {
v.compute_dca_stack_via_from(starting_indexes.dateindex, close, dateindex, exit)?;
Ok(())
})?;
@@ -349,15 +94,13 @@ impl Vecs {
avg_price.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_from(
starting_indexes.dateindex,
stack.dateindex.u(),
stack.sats.dateindex.u(),
dateindex,
exit,
)?;
Ok(())
})?;
Ok(())
})?;
}
Ok(())
}

View File

@@ -2,13 +2,14 @@ use brk_error::Result;
use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use super::{ByDcaCagr, ByDcaClass, ByDcaPeriod, DCA_CLASS_NAMES, DCA_PERIOD_NAMES, Vecs};
use crate::{
indexes,
internal::{
ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, PercentageDiffCloseDollars, Source,
VecBuilderOptions,
ComputedValueVecsFromDateIndex, ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex,
PercentageDiffCloseDollars, Source, VecBuilderOptions,
},
indexes, price,
price,
};
impl Vecs {
@@ -18,680 +19,117 @@ impl Vecs {
indexes: &indexes::Vecs,
price: &price::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let last = VecBuilderOptions::default().add_last();
// DCA by period - stack
let _1w_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"1w_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1m_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"1m_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3m_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"3m_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6m_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"6m_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"1y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _2y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"2y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"3y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _4y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"4y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _5y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"5y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"6y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _8y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"8y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _10y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"10y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let period_stack = ByDcaPeriod::try_new(|name, _days| {
ComputedValueVecsFromDateIndex::forced_import(
db,
&format!("{name}_dca_stack"),
Source::Compute,
version,
last,
true,
indexes,
)
})?;
// DCA by period - avg price
let _1w_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"1w_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1m_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"1m_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3m_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"3m_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6m_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"6m_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"1y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _2y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"2y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"3y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _4y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"4y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _5y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"5y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"6y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _8y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"8y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _10y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"10y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let period_avg_price = ByDcaPeriod::try_new(|name, _days| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_dca_avg_price"),
Source::Compute,
version,
indexes,
last,
)
})?;
// DCA by period - returns (lazy)
let _1w_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1w_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_1w_dca_avg_price,
);
let _1m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1m_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_1m_dca_avg_price,
);
let _3m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"3m_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_3m_dca_avg_price,
);
let _6m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"6m_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_6m_dca_avg_price,
);
let _1y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1y_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_1y_dca_avg_price,
);
let _2y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"2y_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_2y_dca_avg_price,
);
let _3y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"3y_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_3y_dca_avg_price,
);
let _4y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"4y_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_4y_dca_avg_price,
);
let _5y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"5y_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_5y_dca_avg_price,
);
let _6y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"6y_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_6y_dca_avg_price,
);
let _8y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"8y_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_8y_dca_avg_price,
);
let _10y_dca_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"10y_dca_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&_10y_dca_avg_price,
);
// DCA by period - returns (lazy, derived from price and avg_price)
let period_returns =
DCA_PERIOD_NAMES
.zip_ref(&period_avg_price)
.map(|(name, avg_price)| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
&format!("{name}_dca_returns"),
version,
&price.usd.timeindexes_to_price_close,
avg_price,
)
});
// DCA by period - CAGR
let _2y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"2y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"3y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _4y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"4y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _5y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"5y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"6y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _8y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"8y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _10y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"10y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let period_cagr = ByDcaCagr::try_new(|name, _days| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_dca_cagr"),
Source::Compute,
version,
indexes,
last,
)
})?;
// Lump sum by period - stack
let period_lump_sum_stack = ByDcaPeriod::try_new(|name, _days| {
ComputedValueVecsFromDateIndex::forced_import(
db,
&format!("{name}_lump_sum_stack"),
Source::Compute,
version,
last,
true,
indexes,
)
})?;
// DCA by year class - stack
let dca_class_2025_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2025_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2024_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2024_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2023_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2023_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2022_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2022_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2021_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2021_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2020_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2020_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2019_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2019_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2018_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2018_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2017_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2017_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2016_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2016_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2015_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2015_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let class_stack = ByDcaClass::try_new(|name, _year, _dateindex| {
ComputedValueVecsFromDateIndex::forced_import(
db,
&format!("{name}_stack"),
Source::Compute,
version,
last,
true,
indexes,
)
})?;
// DCA by year class - avg price
let dca_class_2025_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2025_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2024_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2024_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2023_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2023_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2022_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2022_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2021_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2021_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2020_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2020_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2019_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2019_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2018_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2018_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2017_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2017_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2016_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2016_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2015_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2015_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let class_avg_price = ByDcaClass::try_new(|name, _year, _dateindex| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_avg_price"),
Source::Compute,
version,
indexes,
last,
)
})?;
// DCA by year class - returns (lazy)
let dca_class_2025_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2025_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2025_avg_price,
);
let dca_class_2024_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2024_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2024_avg_price,
);
let dca_class_2023_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2023_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2023_avg_price,
);
let dca_class_2022_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2022_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2022_avg_price,
);
let dca_class_2021_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2021_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2021_avg_price,
);
let dca_class_2020_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2020_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2020_avg_price,
);
let dca_class_2019_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2019_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2019_avg_price,
);
let dca_class_2018_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2018_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2018_avg_price,
);
let dca_class_2017_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2017_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2017_avg_price,
);
let dca_class_2016_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2016_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2016_avg_price,
);
let dca_class_2015_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2015_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&dca_class_2015_avg_price,
);
let class_returns = DCA_CLASS_NAMES
.zip_ref(&class_avg_price)
.map(|(name, avg_price)| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
&format!("{name}_returns"),
version,
&price.usd.timeindexes_to_price_close,
avg_price,
)
});
Ok(Self {
_1w_dca_stack,
_1m_dca_stack,
_3m_dca_stack,
_6m_dca_stack,
_1y_dca_stack,
_2y_dca_stack,
_3y_dca_stack,
_4y_dca_stack,
_5y_dca_stack,
_6y_dca_stack,
_8y_dca_stack,
_10y_dca_stack,
_1w_dca_avg_price,
_1m_dca_avg_price,
_3m_dca_avg_price,
_6m_dca_avg_price,
_1y_dca_avg_price,
_2y_dca_avg_price,
_3y_dca_avg_price,
_4y_dca_avg_price,
_5y_dca_avg_price,
_6y_dca_avg_price,
_8y_dca_avg_price,
_10y_dca_avg_price,
_1w_dca_returns,
_1m_dca_returns,
_3m_dca_returns,
_6m_dca_returns,
_1y_dca_returns,
_2y_dca_returns,
_3y_dca_returns,
_4y_dca_returns,
_5y_dca_returns,
_6y_dca_returns,
_8y_dca_returns,
_10y_dca_returns,
_2y_dca_cagr,
_3y_dca_cagr,
_4y_dca_cagr,
_5y_dca_cagr,
_6y_dca_cagr,
_8y_dca_cagr,
_10y_dca_cagr,
dca_class_2025_stack,
dca_class_2024_stack,
dca_class_2023_stack,
dca_class_2022_stack,
dca_class_2021_stack,
dca_class_2020_stack,
dca_class_2019_stack,
dca_class_2018_stack,
dca_class_2017_stack,
dca_class_2016_stack,
dca_class_2015_stack,
dca_class_2025_avg_price,
dca_class_2024_avg_price,
dca_class_2023_avg_price,
dca_class_2022_avg_price,
dca_class_2021_avg_price,
dca_class_2020_avg_price,
dca_class_2019_avg_price,
dca_class_2018_avg_price,
dca_class_2017_avg_price,
dca_class_2016_avg_price,
dca_class_2015_avg_price,
dca_class_2025_returns,
dca_class_2024_returns,
dca_class_2023_returns,
dca_class_2022_returns,
dca_class_2021_returns,
dca_class_2020_returns,
dca_class_2019_returns,
dca_class_2018_returns,
dca_class_2017_returns,
dca_class_2016_returns,
dca_class_2015_returns,
period_stack,
period_avg_price,
period_returns,
period_cagr,
period_lump_sum_stack,
class_stack,
class_avg_price,
class_returns,
})
}
}

View File

@@ -1,5 +1,9 @@
mod by_class;
mod by_period;
mod compute;
mod import;
mod vecs;
pub use by_class::*;
pub use by_period::*;
pub use vecs::Vecs;

View File

@@ -1,98 +1,25 @@
use brk_traversable::Traversable;
use brk_types::{Close, Dollars, Sats, StoredF32};
use brk_types::{Close, Dollars, StoredF32};
use crate::internal::{ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex};
use super::{ByDcaCagr, ByDcaClass, ByDcaPeriod};
use crate::internal::{
ComputedValueVecsFromDateIndex, ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex,
};
/// Dollar-cost averaging metrics by time period and year class
#[derive(Clone, Traversable)]
pub struct Vecs {
// DCA by period - stack
pub _1w_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _1m_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _3m_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _6m_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _1y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _2y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _3y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _4y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _5y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _6y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _8y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _10y_dca_stack: ComputedVecsFromDateIndex<Sats>,
// DCA by period
pub period_stack: ByDcaPeriod<ComputedValueVecsFromDateIndex>,
pub period_avg_price: ByDcaPeriod<ComputedVecsFromDateIndex<Dollars>>,
pub period_returns: ByDcaPeriod<LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>>,
pub period_cagr: ByDcaCagr<ComputedVecsFromDateIndex<StoredF32>>,
// DCA by period - avg price
pub _1w_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _1m_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _3m_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _6m_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _1y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _2y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _3y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _4y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _5y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _6y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _8y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _10y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
// Lump sum by period (for comparison with DCA)
pub period_lump_sum_stack: ByDcaPeriod<ComputedValueVecsFromDateIndex>,
// DCA by period - returns (lazy)
pub _1w_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _1m_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _3m_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _6m_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _1y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _2y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _3y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _4y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _5y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _6y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _8y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _10y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
// DCA by period - CAGR
pub _2y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _3y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _4y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _5y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _6y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _8y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _10y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
// DCA by year class - stack
pub dca_class_2025_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2024_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2023_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2022_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2021_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2020_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2019_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2018_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2017_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2016_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2015_stack: ComputedVecsFromDateIndex<Sats>,
// DCA by year class - avg price
pub dca_class_2025_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2024_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2023_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2022_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2021_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2020_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2019_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2018_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2017_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2016_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2015_avg_price: ComputedVecsFromDateIndex<Dollars>,
// DCA by year class - returns (lazy)
pub dca_class_2025_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2024_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2023_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2022_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2021_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2020_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2019_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2018_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2017_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2016_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2015_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
// DCA by year class
pub class_stack: ByDcaClass<ComputedValueVecsFromDateIndex>,
pub class_avg_price: ByDcaClass<ComputedVecsFromDateIndex<Dollars>>,
pub class_returns: ByDcaClass<LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>>,
}

View File

@@ -24,7 +24,7 @@ impl Vecs {
let db = Database::open(&parent_path.join(super::DB_NAME))?;
db.set_min_len(PAGE_SIZE * 1_000_000)?;
let version = parent_version + Version::ZERO;
let version = parent_version;
let price = price.expect("price required for market");
@@ -35,7 +35,15 @@ impl Vecs {
let range = RangeVecs::forced_import(&db, version, indexes)?;
let moving_average = MovingAverageVecs::forced_import(&db, version, indexes, Some(price))?;
let dca = DcaVecs::forced_import(&db, version, indexes, price)?;
let indicators = IndicatorsVecs::forced_import(&db, version, indexes, true, distribution, transactions, &moving_average)?;
let indicators = IndicatorsVecs::forced_import(
&db,
version,
indexes,
true,
distribution,
transactions,
&moving_average,
)?;
let this = Self {
db,

View File

@@ -39,7 +39,7 @@ impl Vecs {
})?;
}
let returns_dateindex = returns._1d_price_returns.dateindex.u();
let returns_dateindex = returns.price_returns._1d.dateindex.u();
self.dateindex_to_rsi_gains.compute_transform(
starting_indexes.dateindex,
@@ -55,14 +55,14 @@ impl Vecs {
exit,
)?;
self.dateindex_to_rsi_avg_gain_14d.compute_sma(
self.dateindex_to_rsi_avg_gain_14d.compute_rma(
starting_indexes.dateindex,
&self.dateindex_to_rsi_gains,
14,
exit,
)?;
self.dateindex_to_rsi_avg_loss_14d.compute_sma(
self.dateindex_to_rsi_avg_loss_14d.compute_rma(
starting_indexes.dateindex,
&self.dateindex_to_rsi_losses,
14,

View File

@@ -12,6 +12,8 @@ use crate::{
transactions,
};
const VERSION: Version = Version::ZERO;
impl Vecs {
pub fn forced_import(
db: &Database,
@@ -22,7 +24,7 @@ impl Vecs {
transactions: &transactions::Vecs,
moving_average: &moving_average::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let v = version + VERSION;
let last = || VecBuilderOptions::default().add_last();
let indexes_to_nvt = distribution
@@ -37,44 +39,45 @@ impl Vecs {
.map(|(market_cap, volume)| {
LazyVecsFrom2FromDateIndex::from_dateindex_and_height::<Ratio32>(
"nvt",
version + v0,
v,
market_cap,
volume,
)
});
let dateindex_to_rsi_gains = EagerVec::forced_import(db, "rsi_gains", version + v0)?;
let dateindex_to_rsi_losses = EagerVec::forced_import(db, "rsi_losses", version + v0)?;
let dateindex_to_rsi_gains = EagerVec::forced_import(db, "rsi_gains", v)?;
let dateindex_to_rsi_losses = EagerVec::forced_import(db, "rsi_losses", v)?;
// v1: Changed from SMA to RMA (Wilder's smoothing)
let dateindex_to_rsi_avg_gain_14d =
EagerVec::forced_import(db, "rsi_avg_gain_14d", version + v0)?;
EagerVec::forced_import(db, "rsi_avg_gain_14d", v + Version::ONE)?;
let dateindex_to_rsi_avg_loss_14d =
EagerVec::forced_import(db, "rsi_avg_loss_14d", version + v0)?;
EagerVec::forced_import(db, "rsi_avg_loss_14d", v + Version::ONE)?;
let dateindex_to_rsi_14d = LazyVecFrom2::transformed::<RsiFormula>(
"rsi_14d",
version + v0,
v,
dateindex_to_rsi_avg_gain_14d.boxed_clone(),
dateindex_to_rsi_avg_loss_14d.boxed_clone(),
);
let dateindex_to_macd_line = EagerVec::forced_import(db, "macd_line", version + v0)?;
let dateindex_to_macd_signal = EagerVec::forced_import(db, "macd_signal", version + v0)?;
let dateindex_to_macd_line = EagerVec::forced_import(db, "macd_line", v)?;
let dateindex_to_macd_signal = EagerVec::forced_import(db, "macd_signal", v)?;
let dateindex_to_macd_histogram = LazyVecFrom2::transformed::<DifferenceF32>(
"macd_histogram",
version + v0,
v,
dateindex_to_macd_line.boxed_clone(),
dateindex_to_macd_signal.boxed_clone(),
);
let dateindex_to_rsi_14d_min = EagerVec::forced_import(db, "rsi_14d_min", version + v0)?;
let dateindex_to_rsi_14d_max = EagerVec::forced_import(db, "rsi_14d_max", version + v0)?;
let dateindex_to_stoch_rsi = EagerVec::forced_import(db, "stoch_rsi", version + v0)?;
let dateindex_to_stoch_rsi_k = EagerVec::forced_import(db, "stoch_rsi_k", version + v0)?;
let dateindex_to_stoch_rsi_d = EagerVec::forced_import(db, "stoch_rsi_d", version + v0)?;
let dateindex_to_rsi_14d_min = EagerVec::forced_import(db, "rsi_14d_min", v)?;
let dateindex_to_rsi_14d_max = EagerVec::forced_import(db, "rsi_14d_max", v)?;
let dateindex_to_stoch_rsi = EagerVec::forced_import(db, "stoch_rsi", v)?;
let dateindex_to_stoch_rsi_k = EagerVec::forced_import(db, "stoch_rsi_k", v)?;
let dateindex_to_stoch_rsi_d = EagerVec::forced_import(db, "stoch_rsi_d", v)?;
let dateindex_to_stoch_k = EagerVec::forced_import(db, "stoch_k", version + v0)?;
let dateindex_to_stoch_d = EagerVec::forced_import(db, "stoch_d", version + v0)?;
let dateindex_to_stoch_k = EagerVec::forced_import(db, "stoch_k", v)?;
let dateindex_to_stoch_d = EagerVec::forced_import(db, "stoch_d", v)?;
let dateindex_to_gini = EagerVec::forced_import(db, "gini", version + v0)?;
let dateindex_to_gini = EagerVec::forced_import(db, "gini", v)?;
// Pi Cycle Top: 111d SMA / (2 * 350d SMA) - signals top when > 1
let dateindex_to_pi_cycle = moving_average
@@ -86,7 +89,7 @@ impl Vecs {
.map(|(sma_111, sma_350_x2)| {
LazyVecFrom2::transformed::<Ratio32>(
"pi_cycle",
version + v0,
v,
sma_111.boxed_clone(),
sma_350_x2.boxed_clone(),
)
@@ -99,7 +102,7 @@ impl Vecs {
db,
"puell_multiple",
Source::Compute,
version + v0,
v,
indexes,
last(),
)

View File

@@ -0,0 +1,215 @@
use brk_traversable::Traversable;
use crate::market::dca::ByDcaPeriod;
/// Lookback period days (includes 1d, unlike DCA)
pub const LOOKBACK_PERIOD_DAYS: ByLookbackPeriod<u32> = ByLookbackPeriod {
_1d: 1,
_1w: 7,
_1m: 30,
_3m: 3 * 30,
_6m: 6 * 30,
_1y: 365,
_2y: 2 * 365,
_3y: 3 * 365,
_4y: 4 * 365,
_5y: 5 * 365,
_6y: 6 * 365,
_8y: 8 * 365,
_10y: 10 * 365,
};
/// Lookback period names
pub const LOOKBACK_PERIOD_NAMES: ByLookbackPeriod<&'static str> = ByLookbackPeriod {
_1d: "1d",
_1w: "1w",
_1m: "1m",
_3m: "3m",
_6m: "6m",
_1y: "1y",
_2y: "2y",
_3y: "3y",
_4y: "4y",
_5y: "5y",
_6y: "6y",
_8y: "8y",
_10y: "10y",
};
/// Generic wrapper for lookback period-based data (includes 1d)
#[derive(Default, Clone, Traversable)]
pub struct ByLookbackPeriod<T> {
pub _1d: T,
pub _1w: T,
pub _1m: T,
pub _3m: T,
pub _6m: T,
pub _1y: T,
pub _2y: T,
pub _3y: T,
pub _4y: T,
pub _5y: T,
pub _6y: T,
pub _8y: T,
pub _10y: T,
}
impl<T> ByLookbackPeriod<T> {
pub fn new<F>(mut create: F) -> Self
where
F: FnMut(&'static str, u32) -> T,
{
let n = LOOKBACK_PERIOD_NAMES;
let d = LOOKBACK_PERIOD_DAYS;
Self {
_1d: create(n._1d, d._1d),
_1w: create(n._1w, d._1w),
_1m: create(n._1m, d._1m),
_3m: create(n._3m, d._3m),
_6m: create(n._6m, d._6m),
_1y: create(n._1y, d._1y),
_2y: create(n._2y, d._2y),
_3y: create(n._3y, d._3y),
_4y: create(n._4y, d._4y),
_5y: create(n._5y, d._5y),
_6y: create(n._6y, d._6y),
_8y: create(n._8y, d._8y),
_10y: create(n._10y, d._10y),
}
}
pub fn try_new<F, E>(mut create: F) -> Result<Self, E>
where
F: FnMut(&'static str, u32) -> Result<T, E>,
{
let n = LOOKBACK_PERIOD_NAMES;
let d = LOOKBACK_PERIOD_DAYS;
Ok(Self {
_1d: create(n._1d, d._1d)?,
_1w: create(n._1w, d._1w)?,
_1m: create(n._1m, d._1m)?,
_3m: create(n._3m, d._3m)?,
_6m: create(n._6m, d._6m)?,
_1y: create(n._1y, d._1y)?,
_2y: create(n._2y, d._2y)?,
_3y: create(n._3y, d._3y)?,
_4y: create(n._4y, d._4y)?,
_5y: create(n._5y, d._5y)?,
_6y: create(n._6y, d._6y)?,
_8y: create(n._8y, d._8y)?,
_10y: create(n._10y, d._10y)?,
})
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
[
&self._1d,
&self._1w,
&self._1m,
&self._3m,
&self._6m,
&self._1y,
&self._2y,
&self._3y,
&self._4y,
&self._5y,
&self._6y,
&self._8y,
&self._10y,
]
.into_iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
[
&mut self._1d,
&mut self._1w,
&mut self._1m,
&mut self._3m,
&mut self._6m,
&mut self._1y,
&mut self._2y,
&mut self._3y,
&mut self._4y,
&mut self._5y,
&mut self._6y,
&mut self._8y,
&mut self._10y,
]
.into_iter()
}
pub fn iter_mut_with_days(&mut self) -> impl Iterator<Item = (&mut T, u32)> {
let d = LOOKBACK_PERIOD_DAYS;
[
(&mut self._1d, d._1d),
(&mut self._1w, d._1w),
(&mut self._1m, d._1m),
(&mut self._3m, d._3m),
(&mut self._6m, d._6m),
(&mut self._1y, d._1y),
(&mut self._2y, d._2y),
(&mut self._3y, d._3y),
(&mut self._4y, d._4y),
(&mut self._5y, d._5y),
(&mut self._6y, d._6y),
(&mut self._8y, d._8y),
(&mut self._10y, d._10y),
]
.into_iter()
}
/// Get the DCA-matching subset (excludes 1d)
pub fn as_dca_period(&self) -> ByDcaPeriod<&T> {
ByDcaPeriod {
_1w: &self._1w,
_1m: &self._1m,
_3m: &self._3m,
_6m: &self._6m,
_1y: &self._1y,
_2y: &self._2y,
_3y: &self._3y,
_4y: &self._4y,
_5y: &self._5y,
_6y: &self._6y,
_8y: &self._8y,
_10y: &self._10y,
}
}
pub fn zip_ref<'a, U>(&'a self, other: &'a ByLookbackPeriod<U>) -> ByLookbackPeriod<(&'a T, &'a U)> {
ByLookbackPeriod {
_1d: (&self._1d, &other._1d),
_1w: (&self._1w, &other._1w),
_1m: (&self._1m, &other._1m),
_3m: (&self._3m, &other._3m),
_6m: (&self._6m, &other._6m),
_1y: (&self._1y, &other._1y),
_2y: (&self._2y, &other._2y),
_3y: (&self._3y, &other._3y),
_4y: (&self._4y, &other._4y),
_5y: (&self._5y, &other._5y),
_6y: (&self._6y, &other._6y),
_8y: (&self._8y, &other._8y),
_10y: (&self._10y, &other._10y),
}
}
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> ByLookbackPeriod<U> {
ByLookbackPeriod {
_1d: f(self._1d),
_1w: f(self._1w),
_1m: f(self._1m),
_3m: f(self._3m),
_6m: f(self._6m),
_1y: f(self._1y),
_2y: f(self._2y),
_3y: f(self._3y),
_4y: f(self._4y),
_5y: f(self._5y),
_6y: f(self._6y),
_8y: f(self._8y),
_10y: f(self._10y),
}
}
}

View File

@@ -13,71 +13,12 @@ impl Vecs {
) -> Result<()> {
let close = price.usd.timeindexes_to_price_close.dateindex.u();
self.price_1d_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 1, exit)?;
Ok(())
})?;
self.price_1w_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 7, exit)?;
Ok(())
})?;
self.price_1m_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 30, exit)?;
Ok(())
})?;
self.price_3m_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 3 * 30, exit)?;
Ok(())
})?;
self.price_6m_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 6 * 30, exit)?;
Ok(())
})?;
self.price_1y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 365, exit)?;
Ok(())
})?;
self.price_2y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 2 * 365, exit)?;
Ok(())
})?;
self.price_3y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 3 * 365, exit)?;
Ok(())
})?;
self.price_4y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 4 * 365, exit)?;
Ok(())
})?;
self.price_5y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 5 * 365, exit)?;
Ok(())
})?;
self.price_6y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 6 * 365, exit)?;
Ok(())
})?;
self.price_8y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 8 * 365, exit)?;
Ok(())
})?;
self.price_10y_ago
.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 10 * 365, exit)?;
for (price_ago, days) in self.price_ago.iter_mut_with_days() {
price_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, days as usize, exit)?;
Ok(())
})?;
}
Ok(())
}

View File

@@ -2,140 +2,27 @@ use brk_error::Result;
use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use super::{ByLookbackPeriod, Vecs};
use crate::{
indexes,
internal::{ComputedVecsFromDateIndex, Source, VecBuilderOptions},
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let last = VecBuilderOptions::default().add_last();
let price_1d_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_1d_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_1w_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_1w_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_1m_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_1m_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_3m_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_3m_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_6m_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_6m_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_1y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_1y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_2y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_2y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_3y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_3y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_4y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_4y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_5y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_5y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_6y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_6y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_8y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_8y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_10y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_10y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_ago = ByLookbackPeriod::try_new(|name, _days| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("price_{name}_ago"),
Source::Compute,
version,
indexes,
last,
)
})?;
Ok(Self {
price_1d_ago,
price_1w_ago,
price_1m_ago,
price_3m_ago,
price_6m_ago,
price_1y_ago,
price_2y_ago,
price_3y_ago,
price_4y_ago,
price_5y_ago,
price_6y_ago,
price_8y_ago,
price_10y_ago,
})
Ok(Self { price_ago })
}
}

View File

@@ -1,5 +1,7 @@
mod by_period;
mod compute;
mod import;
mod vecs;
pub use by_period::*;
pub use vecs::Vecs;

View File

@@ -1,22 +1,11 @@
use brk_traversable::Traversable;
use brk_types::Dollars;
use super::ByLookbackPeriod;
use crate::internal::ComputedVecsFromDateIndex;
/// Price lookback metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub price_1d_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_1w_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_1m_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_3m_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_6m_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_1y_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_2y_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_3y_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_4y_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_5y_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_6y_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_8y_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_10y_ago: ComputedVecsFromDateIndex<Dollars>,
pub price_ago: ByLookbackPeriod<ComputedVecsFromDateIndex<Dollars>>,
}

View File

@@ -4,8 +4,9 @@ use vecdb::{Database, IterableCloneableVec};
use super::Vecs;
use crate::{
indexes,
internal::{ComputedRatioVecsFromDateIndex, DollarsTimesTenths, LazyVecsFromDateIndex},
indexes, price,
price,
};
impl Vecs {
@@ -15,13 +16,11 @@ impl Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let v0 = Version::ZERO;
let indexes_to_price_1w_sma = ComputedRatioVecsFromDateIndex::forced_import(
db,
"price_1w_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -30,7 +29,7 @@ impl Vecs {
db,
"price_8d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -39,7 +38,7 @@ impl Vecs {
db,
"price_13d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -48,7 +47,7 @@ impl Vecs {
db,
"price_21d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -57,7 +56,7 @@ impl Vecs {
db,
"price_1m_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -66,7 +65,7 @@ impl Vecs {
db,
"price_34d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -75,7 +74,7 @@ impl Vecs {
db,
"price_55d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -84,7 +83,7 @@ impl Vecs {
db,
"price_89d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -93,7 +92,7 @@ impl Vecs {
db,
"price_111d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -102,7 +101,7 @@ impl Vecs {
db,
"price_144d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -111,7 +110,7 @@ impl Vecs {
db,
"price_200d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -120,7 +119,7 @@ impl Vecs {
db,
"price_350d_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -129,7 +128,7 @@ impl Vecs {
db,
"price_1y_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -138,7 +137,7 @@ impl Vecs {
db,
"price_2y_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -147,7 +146,7 @@ impl Vecs {
db,
"price_200w_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -156,7 +155,7 @@ impl Vecs {
db,
"price_4y_sma",
None,
version + v0,
version,
indexes,
true,
price,
@@ -166,7 +165,7 @@ impl Vecs {
db,
"price_1w_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -175,7 +174,7 @@ impl Vecs {
db,
"price_8d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -184,7 +183,7 @@ impl Vecs {
db,
"price_12d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -193,7 +192,7 @@ impl Vecs {
db,
"price_13d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -202,7 +201,7 @@ impl Vecs {
db,
"price_21d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -211,7 +210,7 @@ impl Vecs {
db,
"price_26d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -220,7 +219,7 @@ impl Vecs {
db,
"price_1m_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -229,7 +228,7 @@ impl Vecs {
db,
"price_34d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -238,7 +237,7 @@ impl Vecs {
db,
"price_55d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -247,7 +246,7 @@ impl Vecs {
db,
"price_89d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -256,7 +255,7 @@ impl Vecs {
db,
"price_144d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -265,7 +264,7 @@ impl Vecs {
db,
"price_200d_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -274,7 +273,7 @@ impl Vecs {
db,
"price_1y_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -283,7 +282,7 @@ impl Vecs {
db,
"price_2y_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -292,7 +291,7 @@ impl Vecs {
db,
"price_200w_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -301,7 +300,7 @@ impl Vecs {
db,
"price_4y_ema",
None,
version + v0,
version,
indexes,
true,
price,
@@ -311,7 +310,7 @@ impl Vecs {
let indexes_to_price_200d_sma_x2_4 =
LazyVecsFromDateIndex::from_computed::<DollarsTimesTenths<24>>(
"price_200d_sma_x2_4",
version + v0,
version,
price_200d_sma_source
.dateindex
.as_ref()
@@ -321,7 +320,7 @@ impl Vecs {
let indexes_to_price_200d_sma_x0_8 =
LazyVecsFromDateIndex::from_computed::<DollarsTimesTenths<8>>(
"price_200d_sma_x0_8",
version + v0,
version,
price_200d_sma_source
.dateindex
.as_ref()
@@ -333,7 +332,7 @@ impl Vecs {
let indexes_to_price_350d_sma_x2 =
LazyVecsFromDateIndex::from_computed::<DollarsTimesTenths<20>>(
"price_350d_sma_x2",
version + v0,
version,
price_350d_sma_source
.dateindex
.as_ref()

View File

@@ -4,13 +4,12 @@ use vecdb::{Database, EagerVec, ImportableVec};
use super::Vecs;
use crate::{
internal::{ComputedVecsFromDateIndex, Source, VecBuilderOptions},
indexes,
internal::{ComputedVecsFromDateIndex, Source, VecBuilderOptions},
};
impl Vecs {
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let v0 = Version::ZERO;
let v1 = Version::ONE;
let last = VecBuilderOptions::default().add_last();
@@ -82,12 +81,12 @@ impl Vecs {
dateindex_to_price_true_range: EagerVec::forced_import(
db,
"price_true_range",
version + v0,
version,
)?,
dateindex_to_price_true_range_2w_sum: EagerVec::forced_import(
db,
"price_true_range_2w_sum",
version + v0,
version,
)?,
indexes_to_price_2w_choppiness_index: ComputedVecsFromDateIndex::forced_import(
db,

View File

@@ -7,73 +7,22 @@ use crate::{utils::OptionExt, ComputeIndexes};
impl Vecs {
pub fn compute(&mut self, starting_indexes: &ComputeIndexes, exit: &Exit) -> Result<()> {
// CAGR computed from returns
self._2y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._2y_price_returns.dateindex.u(),
2 * 365,
exit,
)?;
Ok(())
})?;
self._3y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._3y_price_returns.dateindex.u(),
3 * 365,
exit,
)?;
Ok(())
})?;
self._4y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._4y_price_returns.dateindex.u(),
4 * 365,
exit,
)?;
Ok(())
})?;
self._5y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._5y_price_returns.dateindex.u(),
5 * 365,
exit,
)?;
Ok(())
})?;
self._6y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._6y_price_returns.dateindex.u(),
6 * 365,
exit,
)?;
Ok(())
})?;
self._8y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._8y_price_returns.dateindex.u(),
8 * 365,
exit,
)?;
Ok(())
})?;
self._10y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._10y_price_returns.dateindex.u(),
10 * 365,
exit,
)?;
Ok(())
})?;
// CAGR computed from returns (2y+ periods only)
let price_returns_dca = self.price_returns.as_dca_period();
for (cagr, returns, days) in self.cagr.zip_mut_with_period(&price_returns_dca) {
cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
returns.dateindex.u(),
days as usize,
exit,
)?;
Ok(())
})?;
}
// Returns standard deviation (computed from 1d returns)
let _1d_price_returns_dateindex = self._1d_price_returns.dateindex.u();
let _1d_price_returns_dateindex = self.price_returns._1d.dateindex.u();
self.indexes_to_1d_returns_1w_sd.compute_all(
starting_indexes,

View File

@@ -2,15 +2,17 @@ use brk_error::Result;
use brk_types::Version;
use vecdb::{Database, EagerVec, ImportableVec};
use super::super::lookback;
use super::super::lookback::{self, LOOKBACK_PERIOD_NAMES};
use super::Vecs;
use crate::{
indexes,
internal::{
ComputedStandardDeviationVecsFromDateIndex, ComputedVecsFromDateIndex,
LazyVecsFrom2FromDateIndex, PercentageDiffCloseDollars, Source,
StandardDeviationVecsOptions, VecBuilderOptions,
},
indexes, price,
market::dca::ByDcaCagr,
price,
};
impl Vecs {
@@ -21,160 +23,33 @@ impl Vecs {
price: &price::Vecs,
lookback: &lookback::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let v1 = Version::ONE;
let last = VecBuilderOptions::default().add_last();
// Price returns (lazy, from price.close and lookback.price_*_ago)
let _1d_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1d_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_1d_ago,
);
let _1w_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1w_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_1w_ago,
);
let _1m_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1m_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_1m_ago,
);
let _3m_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"3m_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_3m_ago,
);
let _6m_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"6m_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_6m_ago,
);
let _1y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1y_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_1y_ago,
);
let _2y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"2y_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_2y_ago,
);
let _3y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"3y_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_3y_ago,
);
let _4y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"4y_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_4y_ago,
);
let _5y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"5y_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_5y_ago,
);
let _6y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"6y_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_6y_ago,
);
let _8y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"8y_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_8y_ago,
);
let _10y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"10y_price_returns",
version + v0,
&price.usd.timeindexes_to_price_close,
&lookback.price_10y_ago,
);
// Price returns (lazy, from price.close and lookback.price_ago)
let price_returns =
LOOKBACK_PERIOD_NAMES
.zip_ref(&lookback.price_ago)
.map(|(name, price_ago)| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
&format!("{name}_price_returns"),
version,
&price.usd.timeindexes_to_price_close,
price_ago,
)
});
// CAGR (computed)
let _2y_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"2y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3y_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"3y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _4y_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"4y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _5y_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"5y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6y_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"6y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _8y_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"8y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _10y_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"10y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
// CAGR (computed, 2y+ only)
let cagr = ByDcaCagr::try_new(|name, _days| {
ComputedVecsFromDateIndex::forced_import(
db,
&format!("{name}_cagr"),
Source::Compute,
version,
indexes,
last,
)
})?;
// Returns standard deviation (computed from 1d returns)
let indexes_to_1d_returns_1w_sd =
@@ -213,7 +88,7 @@ impl Vecs {
// Downside returns and deviation (for Sortino ratio)
let dateindex_to_downside_returns =
EagerVec::forced_import(db, "downside_returns", version + v0)?;
EagerVec::forced_import(db, "downside_returns", version)?;
let indexes_to_downside_1w_sd = ComputedStandardDeviationVecsFromDateIndex::forced_import(
db,
"downside_1w_sd",
@@ -246,27 +121,8 @@ impl Vecs {
)?;
Ok(Self {
_1d_price_returns,
_1w_price_returns,
_1m_price_returns,
_3m_price_returns,
_6m_price_returns,
_1y_price_returns,
_2y_price_returns,
_3y_price_returns,
_4y_price_returns,
_5y_price_returns,
_6y_price_returns,
_8y_price_returns,
_10y_price_returns,
_2y_cagr,
_3y_cagr,
_4y_cagr,
_5y_cagr,
_6y_cagr,
_8y_cagr,
_10y_cagr,
price_returns,
cagr,
indexes_to_1d_returns_1w_sd,
indexes_to_1d_returns_1m_sd,

View File

@@ -2,37 +2,22 @@ use brk_traversable::Traversable;
use brk_types::{Close, DateIndex, Dollars, StoredF32};
use vecdb::{EagerVec, PcoVec};
use crate::internal::{
ComputedStandardDeviationVecsFromDateIndex, ComputedVecsFromDateIndex,
LazyVecsFrom2FromDateIndex,
use crate::{
internal::{
ComputedStandardDeviationVecsFromDateIndex, ComputedVecsFromDateIndex,
LazyVecsFrom2FromDateIndex,
},
market::{dca::ByDcaCagr, lookback::ByLookbackPeriod},
};
/// Price returns, CAGR, and returns standard deviation metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
// Price returns (lazy, from price.close and history.price_*_ago)
pub _1d_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _1w_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _1m_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _3m_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _6m_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _1y_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _2y_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _3y_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _4y_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _5y_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _6y_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _8y_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _10y_price_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
// Price returns (lazy, from price.close and lookback.price_ago)
pub price_returns: ByLookbackPeriod<LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>>,
// CAGR (computed from returns)
pub _2y_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _3y_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _4y_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _5y_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _6y_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _8y_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _10y_cagr: ComputedVecsFromDateIndex<StoredF32>,
// CAGR (computed from returns, 2y+ only)
pub cagr: ByDcaCagr<ComputedVecsFromDateIndex<StoredF32>>,
// Returns standard deviation (computed from 1d returns)
pub indexes_to_1d_returns_1w_sd: ComputedStandardDeviationVecsFromDateIndex,

View File

@@ -51,7 +51,8 @@ impl Vecs {
);
let dateindex_to_sharpe_1w = returns
._1w_price_returns
.price_returns
._1w
.dateindex
.as_ref()
.zip(indexes_to_price_1w_volatility.dateindex.as_ref())
@@ -65,7 +66,8 @@ impl Vecs {
});
let dateindex_to_sharpe_1m = returns
._1m_price_returns
.price_returns
._1m
.dateindex
.as_ref()
.zip(indexes_to_price_1m_volatility.dateindex.as_ref())
@@ -79,7 +81,8 @@ impl Vecs {
});
let dateindex_to_sharpe_1y = returns
._1y_price_returns
.price_returns
._1y
.dateindex
.as_ref()
.zip(indexes_to_price_1y_volatility.dateindex.as_ref())
@@ -94,7 +97,8 @@ impl Vecs {
// Sortino ratio = returns / downside volatility
let dateindex_to_sortino_1w = returns
._1w_price_returns
.price_returns
._1w
.dateindex
.as_ref()
.zip(returns.indexes_to_downside_1w_sd.sd.dateindex.as_ref())
@@ -108,7 +112,8 @@ impl Vecs {
});
let dateindex_to_sortino_1m = returns
._1m_price_returns
.price_returns
._1m
.dateindex
.as_ref()
.zip(returns.indexes_to_downside_1m_sd.sd.dateindex.as_ref())
@@ -122,7 +127,8 @@ impl Vecs {
});
let dateindex_to_sortino_1y = returns
._1y_price_returns
.price_returns
._1y
.dateindex
.as_ref()
.zip(returns.indexes_to_downside_1y_sd.sd.dateindex.as_ref())

View File

@@ -24,7 +24,7 @@ impl Vecs {
db,
"output_count",
Source::Vec(indexes.transaction.txindex_to_output_count.boxed_clone()),
version + Version::ZERO,
version,
indexes,
full_stats(),
)?,
@@ -32,7 +32,7 @@ impl Vecs {
db,
"exact_utxo_count",
Source::Compute,
version + Version::ZERO,
version,
indexes,
full_stats(),
)?,

View File

@@ -17,7 +17,7 @@ impl Vecs {
let db = Database::open(&parent_path.join(super::DB_NAME))?;
db.set_min_len(PAGE_SIZE * 10_000_000)?;
let version = parent_version + Version::ZERO;
let version = parent_version;
let spent = SpentVecs::forced_import(&db, version)?;
let count = CountVecs::forced_import(&db, version, indexes)?;

View File

@@ -14,9 +14,9 @@ use vecdb::{
mod vecs;
use crate::{
blocks, transactions,
blocks,
indexes::{self, ComputeIndexes},
price,
price, transactions,
};
pub const DB_NAME: &str = "pools";
@@ -46,14 +46,14 @@ impl Vecs {
let version = parent_version + Version::new(3) + Version::new(pools.len() as u64);
let this = Self {
height_to_pool: BytesVec::forced_import(&db, "pool", version + Version::ZERO)?,
height_to_pool: BytesVec::forced_import(&db, "pool", version)?,
vecs: pools
.iter()
.map(|pool| {
vecs::Vecs::forced_import(
&db,
pool.slug,
version + Version::ZERO,
version,
indexes,
price,
blocks,

View File

@@ -7,15 +7,15 @@ use vecdb::{
};
use crate::{
blocks, transactions,
blocks,
indexes::{self, ComputeIndexes},
internal::{
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight,
DollarsPlus, LazyValueVecsFrom2FromHeight, LazyVecsFrom2FromDateIndex,
LazyVecsFrom2FromHeight, MaskSats, PercentageU32F32, SatsPlus, SatsPlusToBitcoin, Source,
VecBuilderOptions,
},
indexes::{self, ComputeIndexes},
price,
price, transactions,
};
#[derive(Clone, Traversable)]
@@ -51,7 +51,7 @@ impl Vecs {
) -> Result<Self> {
let suffix = |s: &str| format!("{}_{s}", slug);
let compute_dollars = price.is_some();
let version = parent_version + Version::ZERO;
let version = parent_version;
let last = VecBuilderOptions::default().add_last();
let sum_cum = VecBuilderOptions::default().add_sum().add_cumulative();
@@ -91,7 +91,8 @@ impl Vecs {
.unwrap()
.boxed_clone(),
blocks
.rewards.indexes_to_subsidy
.rewards
.indexes_to_subsidy
.sats
.height
.as_ref()
@@ -117,7 +118,13 @@ impl Vecs {
.as_ref()
.unwrap()
.boxed_clone(),
transactions.fees.indexes_to_fee.sats.height.unwrap_sum().boxed_clone(),
transactions
.fees
.indexes_to_fee
.sats
.height
.unwrap_sum()
.boxed_clone(),
);
let indexes_to_fee = ComputedValueVecsFromHeight::forced_import(
@@ -140,7 +147,8 @@ impl Vecs {
.unwrap()
.boxed_clone(),
blocks
.count.indexes_to_block_count
.count
.indexes_to_block_count
.height
.as_ref()
.unwrap()
@@ -157,7 +165,8 @@ impl Vecs {
.unwrap()
.boxed_clone(),
blocks
.count.indexes_to_block_count
.count
.indexes_to_block_count
.height
.as_ref()
.unwrap()

View File

@@ -27,7 +27,7 @@ impl Vecs {
let db = Database::open(&parent_path.join(DB_NAME))?;
db.set_min_len(PAGE_SIZE * 1_000_000)?;
let version = parent_version + Version::ZERO;
let version = parent_version;
let this = Self {
height_to_position: PcoVec::forced_import(&db, "position", version + Version::TWO)?,

View File

@@ -20,7 +20,6 @@ impl Vecs {
indexes: &indexes::Vecs,
outputs: &outputs::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let full_stats = || {
VecBuilderOptions::default()
.add_average()
@@ -34,7 +33,7 @@ impl Vecs {
db,
"p2a_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -42,7 +41,7 @@ impl Vecs {
db,
"p2ms_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -50,7 +49,7 @@ impl Vecs {
db,
"p2pk33_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -58,7 +57,7 @@ impl Vecs {
db,
"p2pk65_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -66,7 +65,7 @@ impl Vecs {
db,
"p2pkh_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -74,7 +73,7 @@ impl Vecs {
db,
"p2sh_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -82,7 +81,7 @@ impl Vecs {
db,
"p2tr_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -90,7 +89,7 @@ impl Vecs {
db,
"p2wpkh_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -98,7 +97,7 @@ impl Vecs {
db,
"p2wsh_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -108,7 +107,7 @@ impl Vecs {
db,
"segwit_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?;
@@ -119,7 +118,7 @@ impl Vecs {
let indexes_to_taproot_adoption =
LazyVecsFrom2FromHeight::from_height_and_txindex::<PercentageU64F32>(
"taproot_adoption",
version + v0,
version,
indexes_to_p2tr_count.height.u().boxed_clone(),
outputs.count.indexes_to_count.height.sum.u().boxed_clone(),
&indexes_to_p2tr_count,
@@ -128,7 +127,7 @@ impl Vecs {
let indexes_to_segwit_adoption =
LazyVecsFrom2FromHeight::from_height_and_txindex::<PercentageU64F32>(
"segwit_adoption",
version + v0,
version,
indexes_to_segwit_count.height.u().boxed_clone(),
outputs.count.indexes_to_count.height.sum.u().boxed_clone(),
&indexes_to_segwit_count,
@@ -149,7 +148,7 @@ impl Vecs {
db,
"opreturn_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?,
@@ -157,7 +156,7 @@ impl Vecs {
db,
"emptyoutput_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?,
@@ -165,7 +164,7 @@ impl Vecs {
db,
"unknownoutput_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?,

View File

@@ -20,7 +20,7 @@ impl Vecs {
let db = Database::open(&parent_path.join(super::DB_NAME))?;
db.set_min_len(PAGE_SIZE * 50_000_000)?;
let version = parent_version + Version::ZERO;
let version = parent_version;
let compute_dollars = price.is_some();
let count = CountVecs::forced_import(&db, version, indexes, outputs)?;

View File

@@ -15,16 +15,13 @@ impl Vecs {
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v0 = Version::ZERO;
let height_to_opreturn_value =
EagerVec::forced_import(db, "opreturn_value", version + v0)?;
let height_to_opreturn_value = EagerVec::forced_import(db, "opreturn_value", version)?;
let indexes_to_opreturn_value = ComputedValueVecsFromHeight::forced_import(
db,
"opreturn_value",
Source::Vec(height_to_opreturn_value.boxed_clone()),
version + v0,
version,
VecBuilderOptions::default()
.add_sum()
.add_cumulative()

View File

@@ -15,28 +15,25 @@ impl Vecs {
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v0 = Version::ZERO;
let height_to_opreturn = EagerVec::forced_import(db, "opreturn_supply", version + v0)?;
let height_to_opreturn = EagerVec::forced_import(db, "opreturn_supply", version)?;
let indexes_to_opreturn = ComputedValueVecsFromHeight::forced_import(
db,
"opreturn_supply",
Source::Vec(height_to_opreturn.boxed_clone()),
version + v0,
version,
VecBuilderOptions::default().add_last().add_cumulative(),
compute_dollars,
indexes,
)?;
let height_to_unspendable =
EagerVec::forced_import(db, "unspendable_supply", version + v0)?;
let height_to_unspendable = EagerVec::forced_import(db, "unspendable_supply", version)?;
let indexes_to_unspendable = ComputedValueVecsFromHeight::forced_import(
db,
"unspendable_supply",
Source::Vec(height_to_unspendable.boxed_clone()),
version + v0,
version,
VecBuilderOptions::default().add_last().add_cumulative(),
compute_dollars,
indexes,

View File

@@ -9,21 +9,19 @@ use crate::{
impl Vecs {
pub fn import(version: Version, distribution: &distribution::Vecs) -> Self {
let v0 = Version::ZERO;
// Reference distribution's actual circulating supply lazily
let supply_metrics = &distribution.utxo_cohorts.all.metrics.supply;
let height_to_sats = LazyVecFrom1::init(
"circulating_sats",
version + v0,
version,
supply_metrics.height_to_supply.boxed_clone(),
|height, iter| iter.get(height),
);
let height_to_btc = LazyVecFrom1::transformed::<SatsToBitcoin>(
"circulating_btc",
version + v0,
version,
supply_metrics.height_to_supply.boxed_clone(),
);
@@ -34,7 +32,7 @@ impl Vecs {
.map(|d| {
LazyVecFrom1::init(
"circulating_usd",
version + v0,
version,
d.boxed_clone(),
|height, iter| iter.get(height),
)
@@ -45,7 +43,7 @@ impl Vecs {
SatsIdentity,
SatsToBitcoin,
DollarsIdentity,
>("circulating", &supply_metrics.indexes_to_supply, version + v0);
>("circulating", &supply_metrics.indexes_to_supply, version);
Self {
height_to_sats,

View File

@@ -9,18 +9,12 @@ use crate::{
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let indexes_to_inflation_rate = ComputedVecsFromDateIndex::forced_import(
db,
"inflation_rate",
Source::Compute,
version + v0,
version,
indexes,
VecBuilderOptions::default().add_average(),
)?;

View File

@@ -9,7 +9,6 @@ use crate::{
impl Vecs {
pub fn import(version: Version, distribution: &distribution::Vecs) -> Self {
let v0 = Version::ZERO;
let supply_metrics = &distribution.utxo_cohorts.all.metrics.supply;
// Market cap by height (lazy from distribution's supply in USD)
@@ -18,19 +17,16 @@ impl Vecs {
.dollars
.as_ref()
.map(|d| {
LazyVecFrom1::init(
"market_cap",
version + v0,
d.boxed_clone(),
|height, iter| iter.get(height),
)
LazyVecFrom1::init("market_cap", version, d.boxed_clone(), |height, iter| {
iter.get(height)
})
});
// Market cap by indexes (lazy from distribution's supply in USD)
let indexes = supply_metrics.indexes_to_supply.dollars.as_ref().map(|d| {
LazyVecsFromDateIndex::from_computed::<DollarsIdentity>(
"market_cap",
version + v0,
version,
d.dateindex.as_ref().map(|v| v.boxed_clone()),
d,
)

View File

@@ -15,13 +15,11 @@ impl Vecs {
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v0 = Version::ZERO;
let indexes_to_btc = ComputedVecsFromDateIndex::forced_import(
db,
"btc_velocity",
Source::Compute,
version + v0,
version,
indexes,
VecBuilderOptions::default().add_average(),
)?;
@@ -31,7 +29,7 @@ impl Vecs {
db,
"usd_velocity",
Source::Compute,
version + v0,
version,
indexes,
VecBuilderOptions::default().add_average(),
)

View File

@@ -210,6 +210,53 @@ impl ComputeDCAAveragePriceViaLen for EagerVec<PcoVec<DateIndex, Dollars>> {
}
}
pub trait ComputeLumpSumStackViaLen {
fn compute_lump_sum_stack_via_len(
&mut self,
max_from: DateIndex,
closes: &impl IterableVec<DateIndex, Close<Dollars>>,
lookback_prices: &impl IterableVec<DateIndex, Dollars>,
len: usize,
exit: &Exit,
) -> Result<()>;
}
impl ComputeLumpSumStackViaLen for EagerVec<PcoVec<DateIndex, Sats>> {
/// Compute lump sum stack: sats you would have if you invested (len * DCA_AMOUNT) at the lookback price
fn compute_lump_sum_stack_via_len(
&mut self,
max_from: DateIndex,
closes: &impl IterableVec<DateIndex, Close<Dollars>>,
lookback_prices: &impl IterableVec<DateIndex, Dollars>,
len: usize,
exit: &Exit,
) -> Result<()> {
self.validate_computed_version_or_reset(closes.version())?;
let index = max_from.to_usize().min(self.len());
let total_invested = DCA_AMOUNT * len;
lookback_prices
.iter()
.enumerate()
.skip(index)
.try_for_each(|(i, lookback_price)| {
let stack = if lookback_price == Dollars::ZERO {
Sats::ZERO
} else {
Sats::from(Bitcoin::from(total_invested / lookback_price))
};
self.truncate_push_at(i, stack)
})?;
let _lock = exit.lock();
self.write()?;
Ok(())
}
}
pub trait ComputeFromBitcoin<I> {
fn compute_from_bitcoin(
&mut self,

View File

@@ -16,8 +16,6 @@ impl Vecs {
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let full_stats = || {
VecBuilderOptions::default()
.add_average()
@@ -29,7 +27,7 @@ impl Vecs {
let txindex_to_is_coinbase = LazyVecFrom2::init(
"is_coinbase",
version + v0,
version,
indexer.vecs.tx.txindex_to_height.boxed_clone(),
indexer.vecs.tx.height_to_first_txindex.boxed_clone(),
|index: TxIndex, txindex_to_height_iter, height_to_first_txindex_iter| {
@@ -45,7 +43,7 @@ impl Vecs {
db,
"tx_count",
Source::Compute,
version + v0,
version,
indexes,
full_stats(),
)?,

View File

@@ -5,8 +5,9 @@ use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec};
use super::Vecs;
use crate::{
indexes, price,
indexes,
internal::{ComputedValueVecsFromTxindex, ComputedVecsFromTxindex, Source, VecBuilderOptions},
price,
};
impl Vecs {
@@ -17,8 +18,6 @@ impl Vecs {
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let v0 = Version::ZERO;
let stats = || {
VecBuilderOptions::default()
.add_average()
@@ -26,10 +25,10 @@ impl Vecs {
.add_percentiles()
};
let txindex_to_input_value = EagerVec::forced_import(db, "input_value", version + v0)?;
let txindex_to_output_value = EagerVec::forced_import(db, "output_value", version + v0)?;
let txindex_to_fee = EagerVec::forced_import(db, "fee", version + v0)?;
let txindex_to_fee_rate = EagerVec::forced_import(db, "fee_rate", version + v0)?;
let txindex_to_input_value = EagerVec::forced_import(db, "input_value", version)?;
let txindex_to_output_value = EagerVec::forced_import(db, "output_value", version)?;
let txindex_to_fee = EagerVec::forced_import(db, "fee", version)?;
let txindex_to_fee_rate = EagerVec::forced_import(db, "fee_rate", version)?;
Ok(Self {
txindex_to_input_value,
@@ -42,7 +41,7 @@ impl Vecs {
indexer,
indexes,
Source::Vec(txindex_to_fee.boxed_clone()),
version + v0,
version,
price,
VecBuilderOptions::default()
.add_sum()
@@ -55,7 +54,7 @@ impl Vecs {
db,
"fee_rate",
Source::Vec(txindex_to_fee_rate.boxed_clone()),
version + v0,
version,
indexes,
stats(),
)?,

View File

@@ -21,7 +21,7 @@ impl Vecs {
let db = Database::open(&parent_path.join(super::DB_NAME))?;
db.set_min_len(PAGE_SIZE * 50_000_000)?;
let version = parent_version + Version::ZERO;
let version = parent_version;
let compute_dollars = price.is_some();
let count = CountVecs::forced_import(&db, version, indexer, indexes)?;

View File

@@ -16,8 +16,6 @@ impl Vecs {
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let stats = || {
VecBuilderOptions::default()
.add_average()
@@ -27,7 +25,7 @@ impl Vecs {
let txindex_to_weight = LazyVecFrom2::init(
"weight",
version + v0,
version,
indexer.vecs.tx.txindex_to_base_size.boxed_clone(),
indexer.vecs.tx.txindex_to_total_size.boxed_clone(),
|index: TxIndex, txindex_to_base_size_iter, txindex_to_total_size_iter| {
@@ -42,7 +40,7 @@ impl Vecs {
// Derive directly from eager sources to avoid Lazy <- Lazy
let txindex_to_vsize = LazyVecFrom2::init(
"vsize",
version + v0,
version,
indexer.vecs.tx.txindex_to_base_size.boxed_clone(),
indexer.vecs.tx.txindex_to_total_size.boxed_clone(),
|index: TxIndex, txindex_to_base_size_iter, txindex_to_total_size_iter| {
@@ -59,7 +57,7 @@ impl Vecs {
db,
"tx_vsize",
Source::Vec(txindex_to_vsize.boxed_clone()),
version + v0,
version,
indexes,
stats(),
)?,
@@ -67,7 +65,7 @@ impl Vecs {
db,
"tx_weight",
Source::Vec(txindex_to_weight.boxed_clone()),
version + v0,
version,
indexes,
stats(),
)?,

View File

@@ -9,12 +9,7 @@ use crate::{
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let sum_cum = || VecBuilderOptions::default().add_sum().add_cumulative();
Ok(Self {
@@ -22,7 +17,7 @@ impl Vecs {
db,
"tx_v1",
Source::Compute,
version + v0,
version,
indexes,
sum_cum(),
)?,
@@ -30,7 +25,7 @@ impl Vecs {
db,
"tx_v2",
Source::Compute,
version + v0,
version,
indexes,
sum_cum(),
)?,
@@ -38,7 +33,7 @@ impl Vecs {
db,
"tx_v3",
Source::Compute,
version + v0,
version,
indexes,
sum_cum(),
)?,

View File

@@ -4,8 +4,8 @@ use vecdb::Database;
use super::Vecs;
use crate::{
internal::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions},
indexes,
internal::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions},
};
impl Vecs {
@@ -15,7 +15,6 @@ impl Vecs {
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v0 = Version::ZERO;
let v2 = Version::TWO;
let last = || VecBuilderOptions::default().add_last();
@@ -24,7 +23,7 @@ impl Vecs {
db,
"sent_sum",
Source::Compute,
version + v0,
version,
VecBuilderOptions::default().add_sum(),
compute_dollars,
indexes,
@@ -33,7 +32,7 @@ impl Vecs {
db,
"annualized_volume",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -41,7 +40,7 @@ impl Vecs {
db,
"annualized_volume_btc",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,
@@ -49,7 +48,7 @@ impl Vecs {
db,
"annualized_volume_usd",
Source::Compute,
version + v0,
version,
indexes,
last(),
)?,