mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: BIG snapshot
This commit is contained in:
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
)?,
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)?,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)?,
|
||||
|
||||
@@ -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,
|
||||
|
||||
213
crates/brk_computer/src/market/dca/by_class.rs
Normal file
213
crates/brk_computer/src/market/dca/by_class.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
395
crates/brk_computer/src/market/dca/by_period.rs
Normal file
395
crates/brk_computer/src/market/dca/by_period.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>>,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
|
||||
215
crates/brk_computer/src/market/lookback/by_period.rs
Normal file
215
crates/brk_computer/src/market/lookback/by_period.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mod by_period;
|
||||
mod compute;
|
||||
mod import;
|
||||
mod vecs;
|
||||
|
||||
pub use by_period::*;
|
||||
pub use vecs::Vecs;
|
||||
|
||||
@@ -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>>,
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)?,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
)?;
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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(),
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
@@ -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(),
|
||||
)?,
|
||||
|
||||
Reference in New Issue
Block a user