global: MASSIVE snapshot

This commit is contained in:
nym21
2026-01-07 01:16:37 +01:00
parent e832ffbe23
commit cb0abc324e
487 changed files with 21155 additions and 13627 deletions

View File

@@ -2,17 +2,14 @@ use brk_cohort::ByAddressType;
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, StoredU64, Version};
use derive_deref::{Deref, DerefMut};
use derive_more::{Deref, DerefMut};
use rayon::prelude::*;
use vecdb::{
AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, ImportableVec,
IterableCloneableVec, PcoVec, TypedVecIterator,
};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedVecsFromHeight, Source, VecBuilderOptions},
};
use crate::{ComputeIndexes, indexes, internal::DerivedComputedBlockLast};
/// Address count per address type (runtime state).
#[derive(Debug, Default, Deref, DerefMut)]
@@ -142,11 +139,13 @@ impl AddressTypeToHeightToAddressCount {
/// Address count per address type, indexed by various indexes (dateindex, etc.).
#[derive(Clone, Deref, DerefMut, Traversable)]
pub struct AddressTypeToIndexesToAddressCount(ByAddressType<ComputedVecsFromHeight<StoredU64>>);
pub struct AddressTypeToIndexesToAddressCount(ByAddressType<DerivedComputedBlockLast<StoredU64>>);
impl From<ByAddressType<ComputedVecsFromHeight<StoredU64>>> for AddressTypeToIndexesToAddressCount {
impl From<ByAddressType<DerivedComputedBlockLast<StoredU64>>>
for AddressTypeToIndexesToAddressCount
{
#[inline]
fn from(value: ByAddressType<ComputedVecsFromHeight<StoredU64>>) -> Self {
fn from(value: ByAddressType<DerivedComputedBlockLast<StoredU64>>) -> Self {
Self(value)
}
}
@@ -160,17 +159,16 @@ impl AddressTypeToIndexesToAddressCount {
sources: &AddressTypeToHeightToAddressCount,
) -> Result<Self> {
Ok(Self::from(ByAddressType::<
ComputedVecsFromHeight<StoredU64>,
DerivedComputedBlockLast<StoredU64>,
>::try_zip_with_name(
sources,
|type_name, source| {
ComputedVecsFromHeight::forced_import(
DerivedComputedBlockLast::forced_import(
db,
&format!("{type_name}_{name}"),
Source::Vec(source.boxed_clone()),
source.boxed_clone(),
version,
indexes,
VecBuilderOptions::default().add_last(),
)
},
)?))
@@ -183,53 +181,53 @@ impl AddressTypeToIndexesToAddressCount {
exit: &Exit,
addresstype_to_height_to_addresscount: &AddressTypeToHeightToAddressCount,
) -> Result<()> {
self.p2pk65.compute_rest(
self.p2pk65.derive_from(
indexes,
starting_indexes,
&addresstype_to_height_to_addresscount.p2pk65,
exit,
Some(&addresstype_to_height_to_addresscount.p2pk65),
)?;
self.p2pk33.compute_rest(
self.p2pk33.derive_from(
indexes,
starting_indexes,
&addresstype_to_height_to_addresscount.p2pk33,
exit,
Some(&addresstype_to_height_to_addresscount.p2pk33),
)?;
self.p2pkh.compute_rest(
self.p2pkh.derive_from(
indexes,
starting_indexes,
&addresstype_to_height_to_addresscount.p2pkh,
exit,
Some(&addresstype_to_height_to_addresscount.p2pkh),
)?;
self.p2sh.compute_rest(
self.p2sh.derive_from(
indexes,
starting_indexes,
&addresstype_to_height_to_addresscount.p2sh,
exit,
Some(&addresstype_to_height_to_addresscount.p2sh),
)?;
self.p2wpkh.compute_rest(
self.p2wpkh.derive_from(
indexes,
starting_indexes,
&addresstype_to_height_to_addresscount.p2wpkh,
exit,
Some(&addresstype_to_height_to_addresscount.p2wpkh),
)?;
self.p2wsh.compute_rest(
self.p2wsh.derive_from(
indexes,
starting_indexes,
&addresstype_to_height_to_addresscount.p2wsh,
exit,
Some(&addresstype_to_height_to_addresscount.p2wsh),
)?;
self.p2tr.compute_rest(
self.p2tr.derive_from(
indexes,
starting_indexes,
&addresstype_to_height_to_addresscount.p2tr,
exit,
Some(&addresstype_to_height_to_addresscount.p2tr),
)?;
self.p2a.compute_rest(
self.p2a.derive_from(
indexes,
starting_indexes,
&addresstype_to_height_to_addresscount.p2a,
exit,
Some(&addresstype_to_height_to_addresscount.p2a),
)?;
Ok(())
}

View File

@@ -1,5 +1,5 @@
use brk_types::Height;
use derive_deref::{Deref, DerefMut};
use derive_more::{Deref, DerefMut};
use rustc_hash::FxHashMap;
use super::vec::AddressTypeToVec;

View File

@@ -2,7 +2,7 @@ use std::{collections::hash_map::Entry, mem};
use brk_cohort::ByAddressType;
use brk_types::{OutputType, TypeIndex};
use derive_deref::{Deref, DerefMut};
use derive_more::{Deref, DerefMut};
use rustc_hash::FxHashMap;
use smallvec::{Array, SmallVec};

View File

@@ -1,5 +1,5 @@
use brk_cohort::ByAddressType;
use derive_deref::{Deref, DerefMut};
use derive_more::{Deref, DerefMut};
/// A vector for each address type.
#[derive(Debug, Deref, DerefMut)]

View File

@@ -6,7 +6,7 @@ use brk_cohort::{
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Dollars, Height, Version};
use derive_deref::{Deref, DerefMut};
use derive_more::{Deref, DerefMut};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Database, Exit, IterableVec};

View File

@@ -14,7 +14,7 @@ use crate::{
ComputeIndexes,
distribution::state::AddressCohortState,
indexes,
internal::{ComputedVecsFromHeight, Source, VecBuilderOptions},
internal::DerivedComputedBlockLast,
price,
};
@@ -42,7 +42,7 @@ pub struct AddressCohortVecs {
pub height_to_addr_count: EagerVec<PcoVec<Height, StoredU64>>,
/// Address count indexed by various dimensions
pub indexes_to_addr_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_addr_count: DerivedComputedBlockLast<StoredU64>,
}
impl AddressCohortVecs {
@@ -86,13 +86,12 @@ impl AddressCohortVecs {
metrics: CohortMetrics::forced_import(&cfg, all_supply)?,
indexes_to_addr_count: ComputedVecsFromHeight::forced_import(
indexes_to_addr_count: DerivedComputedBlockLast::forced_import(
db,
&cfg.name("addr_count"),
Source::Vec(height_to_addr_count.boxed_clone()),
height_to_addr_count.boxed_clone(),
version + VERSION,
indexes,
VecBuilderOptions::default().add_last(),
)?,
height_to_addr_count,
})
@@ -248,11 +247,11 @@ impl DynCohortVecs for AddressCohortVecs {
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.indexes_to_addr_count.compute_rest(
self.indexes_to_addr_count.derive_from(
indexes,
starting_indexes,
&self.height_to_addr_count,
exit,
Some(&self.height_to_addr_count),
)?;
self.metrics
.compute_rest_part1(indexes, price, starting_indexes, exit)?;

View File

@@ -7,7 +7,7 @@ use brk_cohort::{
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Dollars, Height, Sats, Version};
use derive_deref::{Deref, DerefMut};
use derive_more::{Deref, DerefMut};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Database, Exit, IterableVec};

View File

@@ -20,7 +20,6 @@ use crate::{
state::{BlockState, Transacted},
},
inputs, outputs,
utils::OptionExt,
};
use super::{
@@ -63,10 +62,10 @@ pub fn process_blocks(
let height_to_first_txoutindex = &indexer.vecs.txout.height_to_first_txoutindex;
let height_to_first_txinindex = &indexer.vecs.txin.height_to_first_txinindex;
// From transactions and inputs/outputs (via .height.u() or .height.unwrap_sum() patterns):
let height_to_tx_count = transactions.count.indexes_to_tx_count.height.u();
let height_to_output_count = outputs.count.indexes_to_count.height.unwrap_sum();
let height_to_input_count = inputs.count.indexes_to_count.height.unwrap_sum();
// From transactions and inputs/outputs (via .height or .height.sum_cum.sum patterns):
let height_to_tx_count = &transactions.count.indexes_to_tx_count.height;
let height_to_output_count = &outputs.count.indexes_to_count.height.sum_cum.sum.0;
let height_to_input_count = &inputs.count.indexes_to_count.height.sum_cum.sum.0;
// From blocks:
let height_to_timestamp = &blocks.time.height_to_timestamp_fixed;
let height_to_date = &blocks.time.height_to_date_fixed;
@@ -77,7 +76,7 @@ pub fn process_blocks(
// From price (optional):
let height_to_price = price.map(|p| &p.usd.chainindexes_to_price_close.height);
let dateindex_to_price = price.map(|p| p.usd.timeindexes_to_price_close.dateindex.u());
let dateindex_to_price = price.map(|p| &p.usd.timeindexes_to_price_close.dateindex);
// Access pre-computed vectors from context for thread-safe access
let height_to_price_vec = &ctx.height_to_price;

View File

@@ -9,8 +9,7 @@ use vecdb::{
use crate::{
ComputeIndexes, indexes,
internal::{ComputedValueVecsFromHeight, ComputedVecsFromHeight, Source, VecBuilderOptions},
price,
internal::{ComputedBlockSumCum, DerivedValueBlockSumCum},
};
use super::ImportConfig;
@@ -21,8 +20,8 @@ pub struct ActivityMetrics {
/// Total satoshis sent at each height
pub height_to_sent: EagerVec<PcoVec<Height, Sats>>,
/// Sent amounts indexed by various dimensions
pub indexes_to_sent: ComputedValueVecsFromHeight,
/// Sent amounts indexed by various dimensions (derives from height_to_sent)
pub indexes_to_sent: DerivedValueBlockSumCum,
/// Satoshi-blocks destroyed (supply * blocks_old when spent)
pub height_to_satblocks_destroyed: EagerVec<PcoVec<Height, Sats>>,
@@ -31,28 +30,24 @@ pub struct ActivityMetrics {
pub height_to_satdays_destroyed: EagerVec<PcoVec<Height, Sats>>,
/// Coin-blocks destroyed (in BTC rather than sats)
pub indexes_to_coinblocks_destroyed: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_coinblocks_destroyed: ComputedBlockSumCum<StoredF64>,
/// Coin-days destroyed (in BTC rather than sats)
pub indexes_to_coindays_destroyed: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_coindays_destroyed: ComputedBlockSumCum<StoredF64>,
}
impl ActivityMetrics {
/// Import activity metrics from database.
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
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)?;
let indexes_to_sent = ComputedValueVecsFromHeight::forced_import(
let indexes_to_sent = DerivedValueBlockSumCum::forced_import(
cfg.db,
&cfg.name("sent"),
Source::Vec(height_to_sent.boxed_clone()),
cfg.version,
sum_cum,
compute_dollars,
cfg.indexes,
height_to_sent.boxed_clone(),
cfg.price,
)?;
Ok(Self {
@@ -71,22 +66,18 @@ impl ActivityMetrics {
cfg.version,
)?,
indexes_to_coinblocks_destroyed: ComputedVecsFromHeight::forced_import(
indexes_to_coinblocks_destroyed: ComputedBlockSumCum::forced_import(
cfg.db,
&cfg.name("coinblocks_destroyed"),
Source::Compute,
cfg.version,
cfg.indexes,
sum_cum,
)?,
indexes_to_coindays_destroyed: ComputedVecsFromHeight::forced_import(
indexes_to_coindays_destroyed: ComputedBlockSumCum::forced_import(
cfg.db,
&cfg.name("coindays_destroyed"),
Source::Compute,
cfg.version,
cfg.indexes,
sum_cum,
)?,
})
}
@@ -174,16 +165,14 @@ impl ActivityMetrics {
pub fn compute_rest_part1(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.indexes_to_sent.compute_rest(
self.indexes_to_sent.derive_from(
indexes,
price,
starting_indexes,
&self.height_to_sent,
exit,
Some(&self.height_to_sent),
)?;
self.indexes_to_coinblocks_destroyed

View File

@@ -10,7 +10,7 @@ use vecdb::{
use crate::{
ComputeIndexes,
distribution::state::CohortState,
internal::{ComputedVecsFromHeight, CostBasisPercentiles, Source, VecBuilderOptions},
internal::{CostBasisPercentiles, DerivedComputedBlockLast},
};
use super::ImportConfig;
@@ -20,11 +20,11 @@ use super::ImportConfig;
pub struct CostBasisMetrics {
/// Minimum cost basis for any UTXO at this height
pub height_to_min_cost_basis: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_min_cost_basis: ComputedVecsFromHeight<Dollars>,
pub indexes_to_min_cost_basis: DerivedComputedBlockLast<Dollars>,
/// Maximum cost basis for any UTXO at this height
pub height_to_max_cost_basis: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_max_cost_basis: ComputedVecsFromHeight<Dollars>,
pub indexes_to_max_cost_basis: DerivedComputedBlockLast<Dollars>,
/// Cost basis distribution percentiles (median, quartiles, etc.)
pub percentiles: Option<CostBasisPercentiles>,
@@ -34,7 +34,6 @@ impl CostBasisMetrics {
/// Import cost basis metrics from database.
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
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)?;
@@ -43,21 +42,19 @@ impl CostBasisMetrics {
EagerVec::forced_import(cfg.db, &cfg.name("max_cost_basis"), cfg.version)?;
Ok(Self {
indexes_to_min_cost_basis: ComputedVecsFromHeight::forced_import(
indexes_to_min_cost_basis: DerivedComputedBlockLast::forced_import(
cfg.db,
&cfg.name("min_cost_basis"),
Source::Vec(height_to_min_cost_basis.boxed_clone()),
height_to_min_cost_basis.boxed_clone(),
cfg.version,
cfg.indexes,
last,
)?,
indexes_to_max_cost_basis: ComputedVecsFromHeight::forced_import(
indexes_to_max_cost_basis: DerivedComputedBlockLast::forced_import(
cfg.db,
&cfg.name("max_cost_basis"),
Source::Vec(height_to_max_cost_basis.boxed_clone()),
height_to_max_cost_basis.boxed_clone(),
cfg.version,
cfg.indexes,
last,
)?,
height_to_min_cost_basis,
height_to_max_cost_basis,
@@ -145,8 +142,7 @@ impl CostBasisMetrics {
.vecs
.iter_mut()
.flatten()
.filter_map(|v| v.dateindex.as_mut())
.map(|v| v as &mut dyn AnyStoredVec),
.map(|v| &mut v.dateindex as &mut dyn AnyStoredVec),
);
}
vecs.into_par_iter()
@@ -193,18 +189,18 @@ impl CostBasisMetrics {
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.indexes_to_min_cost_basis.compute_rest(
self.indexes_to_min_cost_basis.derive_from(
indexes,
starting_indexes,
&self.height_to_min_cost_basis,
exit,
Some(&self.height_to_min_cost_basis),
)?;
self.indexes_to_max_cost_basis.compute_rest(
self.indexes_to_max_cost_basis.derive_from(
indexes,
starting_indexes,
&self.height_to_max_cost_basis,
exit,
Some(&self.height_to_max_cost_basis),
)?;
Ok(())

View File

@@ -295,7 +295,7 @@ impl CohortMetrics {
self.supply
.compute_rest_part1(indexes, price, starting_indexes, exit)?;
self.activity
.compute_rest_part1(indexes, price, starting_indexes, exit)?;
.compute_rest_part1(indexes, starting_indexes, exit)?;
if let Some(realized) = self.realized.as_mut() {
realized.compute_rest_part1(indexes, starting_indexes, exit)?;

View File

@@ -12,12 +12,12 @@ use crate::{
distribution::state::RealizedState,
indexes,
internal::{
ComputedRatioVecsFromDateIndex, ComputedVecsFromDateIndex, ComputedVecsFromHeight,
DollarsMinus, LazyVecsFrom2FromHeight, LazyVecsFromDateIndex, LazyVecsFromHeight,
PercentageDollarsF32, Source, StoredF32Identity, VecBuilderOptions,
BinaryBlockSum, BinaryBlockSumCumLast, ComputedBlockLast, ComputedBlockSum,
ComputedBlockSumCum, ComputedDateLast, ComputedRatioVecsDate, DerivedComputedBlockLast,
DerivedComputedBlockSum, DerivedComputedBlockSumCum, DollarsMinus, LazyBlockSum,
LazyBlockSumCum, LazyDateLast, PercentageDollarsF32, StoredF32Identity,
},
price,
utils::OptionExt,
};
use super::ImportConfig;
@@ -27,48 +27,48 @@ use super::ImportConfig;
pub struct RealizedMetrics {
// === Realized Cap ===
pub height_to_realized_cap: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_realized_cap: ComputedVecsFromHeight<Dollars>,
pub indexes_to_realized_price: ComputedVecsFromHeight<Dollars>,
pub indexes_to_realized_price_extra: ComputedRatioVecsFromDateIndex,
pub indexes_to_realized_cap_rel_to_own_market_cap: Option<ComputedVecsFromHeight<StoredF32>>,
pub indexes_to_realized_cap_30d_delta: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_realized_cap: DerivedComputedBlockLast<Dollars>,
pub indexes_to_realized_price: ComputedBlockLast<Dollars>,
pub indexes_to_realized_price_extra: ComputedRatioVecsDate,
pub indexes_to_realized_cap_rel_to_own_market_cap: Option<ComputedBlockLast<StoredF32>>,
pub indexes_to_realized_cap_30d_delta: ComputedDateLast<Dollars>,
// === MVRV (Market Value to Realized Value) ===
// Proxy for indexes_to_realized_price_extra.ratio (close / realized_price = market_cap / realized_cap)
pub indexes_to_mvrv: LazyVecsFromDateIndex<StoredF32>,
pub indexes_to_mvrv: LazyDateLast<StoredF32>,
// === Realized Profit/Loss ===
pub height_to_realized_profit: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_realized_profit: ComputedVecsFromHeight<Dollars>,
pub indexes_to_realized_profit: DerivedComputedBlockSumCum<Dollars>,
pub height_to_realized_loss: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_realized_loss: ComputedVecsFromHeight<Dollars>,
pub indexes_to_neg_realized_loss: LazyVecsFromHeight<Dollars>,
pub indexes_to_net_realized_pnl: ComputedVecsFromHeight<Dollars>,
pub indexes_to_realized_value: ComputedVecsFromHeight<Dollars>,
pub indexes_to_realized_loss: DerivedComputedBlockSumCum<Dollars>,
pub indexes_to_neg_realized_loss: LazyBlockSumCum<Dollars>,
pub indexes_to_net_realized_pnl: ComputedBlockSumCum<Dollars>,
pub indexes_to_realized_value: ComputedBlockSum<Dollars>,
// === Realized vs Realized Cap Ratios (lazy) ===
pub indexes_to_realized_profit_rel_to_realized_cap:
LazyVecsFrom2FromHeight<StoredF32, Dollars, Dollars>,
BinaryBlockSumCumLast<StoredF32, Dollars, Dollars>,
pub indexes_to_realized_loss_rel_to_realized_cap:
LazyVecsFrom2FromHeight<StoredF32, Dollars, Dollars>,
BinaryBlockSumCumLast<StoredF32, Dollars, Dollars>,
pub indexes_to_net_realized_pnl_rel_to_realized_cap:
LazyVecsFrom2FromHeight<StoredF32, Dollars, Dollars>,
BinaryBlockSumCumLast<StoredF32, Dollars, Dollars>,
// === Total Realized PnL ===
pub indexes_to_total_realized_pnl: LazyVecsFromHeight<Dollars>,
pub indexes_to_total_realized_pnl: LazyBlockSum<Dollars>,
pub dateindex_to_realized_profit_to_loss_ratio: Option<EagerVec<PcoVec<DateIndex, StoredF64>>>,
// === Value Created/Destroyed ===
pub height_to_value_created: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_value_created: ComputedVecsFromHeight<Dollars>,
#[traversable(rename = "value_created_sum")]
pub indexes_to_value_created: DerivedComputedBlockSum<Dollars>,
pub height_to_value_destroyed: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_value_destroyed: ComputedVecsFromHeight<Dollars>,
#[traversable(rename = "value_destroyed_sum")]
pub indexes_to_value_destroyed: DerivedComputedBlockSum<Dollars>,
// === Adjusted Value (lazy: cohort - up_to_1h) ===
pub indexes_to_adjusted_value_created:
Option<LazyVecsFrom2FromHeight<Dollars, Dollars, Dollars>>,
pub indexes_to_adjusted_value_destroyed:
Option<LazyVecsFrom2FromHeight<Dollars, Dollars, Dollars>>,
pub indexes_to_adjusted_value_created: Option<BinaryBlockSum<Dollars, Dollars, Dollars>>,
pub indexes_to_adjusted_value_destroyed: Option<BinaryBlockSum<Dollars, Dollars, Dollars>>,
// === SOPR (Spent Output Profit Ratio) ===
pub dateindex_to_sopr: EagerVec<PcoVec<DateIndex, StoredF64>>,
@@ -84,11 +84,11 @@ pub struct RealizedMetrics {
pub dateindex_to_sell_side_risk_ratio_30d_ema: EagerVec<PcoVec<DateIndex, StoredF32>>,
// === Net Realized PnL Deltas ===
pub indexes_to_net_realized_pnl_cumulative_30d_delta: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_net_realized_pnl_cumulative_30d_delta: ComputedDateLast<Dollars>,
pub indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap:
ComputedVecsFromDateIndex<StoredF32>,
ComputedDateLast<StoredF32>,
pub indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_market_cap:
ComputedVecsFromDateIndex<StoredF32>,
ComputedDateLast<StoredF32>,
}
impl RealizedMetrics {
@@ -98,23 +98,19 @@ impl RealizedMetrics {
let v3 = Version::new(3);
let extended = cfg.extended();
let compute_adjusted = cfg.compute_adjusted();
let last = VecBuilderOptions::default().add_last();
let sum = VecBuilderOptions::default().add_sum();
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)?;
let indexes_to_realized_loss = ComputedVecsFromHeight::forced_import(
let indexes_to_realized_loss = DerivedComputedBlockSumCum::forced_import(
cfg.db,
&cfg.name("realized_loss"),
Source::Vec(height_to_realized_loss.boxed_clone()),
height_to_realized_loss.boxed_clone(),
cfg.version,
cfg.indexes,
sum_cum,
)?;
let indexes_to_neg_realized_loss = LazyVecsFromHeight::from_computed::<Negate>(
let indexes_to_neg_realized_loss = LazyBlockSumCum::from_derived::<Negate>(
&cfg.name("neg_realized_loss"),
cfg.version + v1,
height_to_realized_loss.boxed_clone(),
@@ -122,24 +118,18 @@ impl RealizedMetrics {
);
// realized_value is the source for total_realized_pnl (they're identical)
let indexes_to_realized_value = ComputedVecsFromHeight::forced_import(
let indexes_to_realized_value = ComputedBlockSum::forced_import(
cfg.db,
&cfg.name("realized_value"),
Source::Compute,
cfg.version,
cfg.indexes,
sum,
)?;
// total_realized_pnl is a lazy alias to realized_value
let indexes_to_total_realized_pnl = LazyVecsFromHeight::from_computed::<Ident>(
let indexes_to_total_realized_pnl = LazyBlockSum::from_computed::<Ident>(
&cfg.name("total_realized_pnl"),
cfg.version + v1,
indexes_to_realized_value
.height
.as_ref()
.unwrap()
.boxed_clone(),
indexes_to_realized_value.height.boxed_clone(),
&indexes_to_realized_value,
);
@@ -147,39 +137,35 @@ impl RealizedMetrics {
let height_to_realized_cap: EagerVec<PcoVec<Height, Dollars>> =
EagerVec::forced_import(cfg.db, &cfg.name("realized_cap"), cfg.version)?;
let indexes_to_realized_cap = ComputedVecsFromHeight::forced_import(
let indexes_to_realized_cap = DerivedComputedBlockLast::forced_import(
cfg.db,
&cfg.name("realized_cap"),
Source::Vec(height_to_realized_cap.boxed_clone()),
height_to_realized_cap.boxed_clone(),
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)?;
let indexes_to_realized_profit = ComputedVecsFromHeight::forced_import(
let indexes_to_realized_profit = DerivedComputedBlockSumCum::forced_import(
cfg.db,
&cfg.name("realized_profit"),
Source::Vec(height_to_realized_profit.boxed_clone()),
height_to_realized_profit.boxed_clone(),
cfg.version,
cfg.indexes,
sum_cum,
)?;
let indexes_to_net_realized_pnl = ComputedVecsFromHeight::forced_import(
let indexes_to_net_realized_pnl = ComputedBlockSumCum::forced_import(
cfg.db,
&cfg.name("net_realized_pnl"),
Source::Compute,
cfg.version,
cfg.indexes,
sum_cum,
)?;
// Construct lazy ratio vecs (before struct assignment to satisfy borrow checker)
let indexes_to_realized_profit_rel_to_realized_cap =
LazyVecsFrom2FromHeight::from_computed::<PercentageDollarsF32>(
BinaryBlockSumCumLast::from_derived::<PercentageDollarsF32>(
&cfg.name("realized_profit_rel_to_realized_cap"),
cfg.version + v1,
height_to_realized_profit.boxed_clone(),
@@ -189,7 +175,7 @@ impl RealizedMetrics {
);
let indexes_to_realized_loss_rel_to_realized_cap =
LazyVecsFrom2FromHeight::from_computed::<PercentageDollarsF32>(
BinaryBlockSumCumLast::from_derived::<PercentageDollarsF32>(
&cfg.name("realized_loss_rel_to_realized_cap"),
cfg.version + v1,
height_to_realized_loss.boxed_clone(),
@@ -199,26 +185,20 @@ impl RealizedMetrics {
);
let indexes_to_net_realized_pnl_rel_to_realized_cap =
LazyVecsFrom2FromHeight::from_computed::<PercentageDollarsF32>(
BinaryBlockSumCumLast::from_computed_derived::<PercentageDollarsF32>(
&cfg.name("net_realized_pnl_rel_to_realized_cap"),
cfg.version + v1,
indexes_to_net_realized_pnl
.height
.as_ref()
.unwrap()
.boxed_clone(),
indexes_to_net_realized_pnl.height.boxed_clone(),
height_to_realized_cap.boxed_clone(),
&indexes_to_net_realized_pnl,
&indexes_to_realized_cap,
);
let indexes_to_realized_price = ComputedVecsFromHeight::forced_import(
let indexes_to_realized_price = ComputedBlockLast::forced_import(
cfg.db,
&cfg.name("realized_price"),
Source::Compute,
cfg.version + v1,
cfg.indexes,
last,
)?;
let height_to_value_created =
@@ -226,28 +206,26 @@ impl RealizedMetrics {
let height_to_value_destroyed =
EagerVec::forced_import(cfg.db, &cfg.name("value_destroyed"), cfg.version)?;
let indexes_to_value_created = ComputedVecsFromHeight::forced_import(
let indexes_to_value_created = DerivedComputedBlockSum::forced_import(
cfg.db,
&cfg.name("value_created"),
Source::Vec(height_to_value_created.boxed_clone()),
height_to_value_created.boxed_clone(),
cfg.version,
cfg.indexes,
sum,
)?;
let indexes_to_value_destroyed = ComputedVecsFromHeight::forced_import(
let indexes_to_value_destroyed = DerivedComputedBlockSum::forced_import(
cfg.db,
&cfg.name("value_destroyed"),
Source::Vec(height_to_value_destroyed.boxed_clone()),
height_to_value_destroyed.boxed_clone(),
cfg.version,
cfg.indexes,
sum,
)?;
// Create lazy adjusted vecs if compute_adjusted and up_to_1h is available
let indexes_to_adjusted_value_created = (compute_adjusted && cfg.up_to_1h_realized.is_some())
.then(|| {
let indexes_to_adjusted_value_created =
(compute_adjusted && cfg.up_to_1h_realized.is_some()).then(|| {
let up_to_1h = cfg.up_to_1h_realized.unwrap();
LazyVecsFrom2FromHeight::from_computed::<DollarsMinus>(
BinaryBlockSum::from_derived::<DollarsMinus>(
&cfg.name("adjusted_value_created"),
cfg.version,
height_to_value_created.boxed_clone(),
@@ -259,7 +237,7 @@ impl RealizedMetrics {
let indexes_to_adjusted_value_destroyed =
(compute_adjusted && cfg.up_to_1h_realized.is_some()).then(|| {
let up_to_1h = cfg.up_to_1h_realized.unwrap();
LazyVecsFrom2FromHeight::from_computed::<DollarsMinus>(
BinaryBlockSum::from_derived::<DollarsMinus>(
&cfg.name("adjusted_value_destroyed"),
cfg.version,
height_to_value_destroyed.boxed_clone(),
@@ -270,7 +248,7 @@ impl RealizedMetrics {
});
// Create realized_price_extra first so we can reference its ratio for MVRV proxy
let indexes_to_realized_price_extra = ComputedRatioVecsFromDateIndex::forced_import(
let indexes_to_realized_price_extra = ComputedRatioVecsDate::forced_import(
cfg.db,
&cfg.name("realized_price"),
Some(&indexes_to_realized_price),
@@ -282,14 +260,9 @@ impl RealizedMetrics {
// MVRV is a lazy proxy for realized_price_extra.ratio
// ratio = close / realized_price = market_cap / realized_cap = MVRV
let indexes_to_mvrv = LazyVecsFromDateIndex::from_computed::<StoredF32Identity>(
let indexes_to_mvrv = LazyDateLast::from_source::<StoredF32Identity>(
&cfg.name("mvrv"),
cfg.version,
indexes_to_realized_price_extra
.ratio
.dateindex
.as_ref()
.map(|v| v.boxed_clone()),
&indexes_to_realized_price_extra.ratio,
);
@@ -303,23 +276,19 @@ impl RealizedMetrics {
indexes_to_mvrv,
indexes_to_realized_cap_rel_to_own_market_cap: extended
.then(|| {
ComputedVecsFromHeight::forced_import(
ComputedBlockLast::forced_import(
cfg.db,
&cfg.name("realized_cap_rel_to_own_market_cap"),
Source::Compute,
cfg.version,
cfg.indexes,
last,
)
})
.transpose()?,
indexes_to_realized_cap_30d_delta: ComputedVecsFromDateIndex::forced_import(
indexes_to_realized_cap_30d_delta: ComputedDateLast::forced_import(
cfg.db,
&cfg.name("realized_cap_30d_delta"),
Source::Compute,
cfg.version,
cfg.indexes,
last,
)?,
// === Realized Profit/Loss ===
@@ -416,32 +385,25 @@ impl RealizedMetrics {
)?,
// === Net Realized PnL Deltas ===
indexes_to_net_realized_pnl_cumulative_30d_delta:
ComputedVecsFromDateIndex::forced_import(
cfg.db,
&cfg.name("net_realized_pnl_cumulative_30d_delta"),
Source::Compute,
cfg.version + v3,
cfg.indexes,
last,
)?,
indexes_to_net_realized_pnl_cumulative_30d_delta: ComputedDateLast::forced_import(
cfg.db,
&cfg.name("net_realized_pnl_cumulative_30d_delta"),
cfg.version + v3,
cfg.indexes,
)?,
indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap:
ComputedVecsFromDateIndex::forced_import(
ComputedDateLast::forced_import(
cfg.db,
&cfg.name("net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap"),
Source::Compute,
cfg.version + v3,
cfg.indexes,
last,
)?,
indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_market_cap:
ComputedVecsFromDateIndex::forced_import(
ComputedDateLast::forced_import(
cfg.db,
&cfg.name("net_realized_pnl_cumulative_30d_delta_rel_to_market_cap"),
Source::Compute,
cfg.version + v3,
cfg.indexes,
last,
)?,
})
}
@@ -558,25 +520,25 @@ impl RealizedMetrics {
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.indexes_to_realized_cap.compute_rest(
self.indexes_to_realized_cap.derive_from(
indexes,
starting_indexes,
&self.height_to_realized_cap,
exit,
Some(&self.height_to_realized_cap),
)?;
self.indexes_to_realized_profit.compute_rest(
self.indexes_to_realized_profit.derive_from(
indexes,
starting_indexes,
&self.height_to_realized_profit,
exit,
Some(&self.height_to_realized_profit),
)?;
self.indexes_to_realized_loss.compute_rest(
self.indexes_to_realized_loss.derive_from(
indexes,
starting_indexes,
&self.height_to_realized_loss,
exit,
Some(&self.height_to_realized_loss),
)?;
// net_realized_pnl = profit - loss
@@ -605,18 +567,18 @@ impl RealizedMetrics {
Ok(())
})?;
self.indexes_to_value_created.compute_rest(
self.indexes_to_value_created.derive_from(
indexes,
starting_indexes,
&self.height_to_value_created,
exit,
Some(&self.height_to_value_created),
)?;
self.indexes_to_value_destroyed.compute_rest(
self.indexes_to_value_destroyed.derive_from(
indexes,
starting_indexes,
&self.height_to_value_destroyed,
exit,
Some(&self.height_to_value_destroyed),
)?;
Ok(())
@@ -651,7 +613,7 @@ impl RealizedMetrics {
price,
starting_indexes,
exit,
Some(self.indexes_to_realized_price.dateindex.unwrap_last()),
Some(&self.indexes_to_realized_price.dateindex.0),
)?;
}
@@ -660,7 +622,7 @@ impl RealizedMetrics {
.compute_all(starting_indexes, exit, |vec| {
vec.compute_change(
starting_indexes.dateindex,
self.indexes_to_realized_cap.dateindex.unwrap_last(),
&self.indexes_to_realized_cap.dateindex.0,
30,
exit,
)?;
@@ -670,8 +632,8 @@ impl RealizedMetrics {
// SOPR = value_created / value_destroyed
self.dateindex_to_sopr.compute_divide(
starting_indexes.dateindex,
self.indexes_to_value_created.dateindex.unwrap_sum(),
self.indexes_to_value_destroyed.dateindex.unwrap_sum(),
&self.indexes_to_value_created.dateindex.0,
&self.indexes_to_value_destroyed.dateindex.0,
exit,
)?;
@@ -692,17 +654,13 @@ impl RealizedMetrics {
// Optional: adjusted SOPR (lazy: cohort - up_to_1h)
if let (Some(adjusted_sopr), Some(adj_created), Some(adj_destroyed)) = (
self.dateindex_to_adjusted_sopr.as_mut(),
self.indexes_to_adjusted_value_created
.as_ref()
.and_then(|v| v.dateindex.sum.as_ref()),
self.indexes_to_adjusted_value_destroyed
.as_ref()
.and_then(|v| v.dateindex.sum.as_ref()),
self.indexes_to_adjusted_value_created.as_ref(),
self.indexes_to_adjusted_value_destroyed.as_ref(),
) {
adjusted_sopr.compute_divide(
starting_indexes.dateindex,
adj_created.as_ref(),
adj_destroyed.as_ref(),
&*adj_created.dateindex,
&*adj_destroyed.dateindex,
exit,
)?;
@@ -728,8 +686,8 @@ impl RealizedMetrics {
// sell_side_risk_ratio = realized_value / realized_cap
self.dateindex_to_sell_side_risk_ratio.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_realized_value.dateindex.unwrap_sum(),
self.indexes_to_realized_cap.dateindex.unwrap_last(),
&self.indexes_to_realized_value.dateindex.0,
&self.indexes_to_realized_cap.dateindex.0,
exit,
)?;
@@ -752,9 +710,7 @@ impl RealizedMetrics {
.compute_all(starting_indexes, exit, |vec| {
vec.compute_change(
starting_indexes.dateindex,
self.indexes_to_net_realized_pnl
.dateindex
.unwrap_cumulative(),
&self.indexes_to_net_realized_pnl.dateindex.cumulative.0,
30,
exit,
)?;
@@ -766,10 +722,10 @@ impl RealizedMetrics {
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_net_realized_pnl_cumulative_30d_delta
.dateindex
.u(),
self.indexes_to_realized_cap.dateindex.unwrap_last(),
&self
.indexes_to_net_realized_pnl_cumulative_30d_delta
.dateindex,
&self.indexes_to_realized_cap.dateindex.0,
exit,
)?;
Ok(())
@@ -781,9 +737,9 @@ impl RealizedMetrics {
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_net_realized_pnl_cumulative_30d_delta
.dateindex
.u(),
&self
.indexes_to_net_realized_pnl_cumulative_30d_delta
.dateindex,
dateindex_to_market_cap,
exit,
)?;
@@ -811,8 +767,8 @@ impl RealizedMetrics {
if let Some(ratio) = self.dateindex_to_realized_profit_to_loss_ratio.as_mut() {
ratio.compute_divide(
starting_indexes.dateindex,
self.indexes_to_realized_profit.dateindex.unwrap_sum(),
self.indexes_to_realized_loss.dateindex.unwrap_sum(),
&self.indexes_to_realized_profit.dateindex.sum.0,
&self.indexes_to_realized_loss.dateindex.sum.0,
exit,
)?;
}

View File

@@ -4,7 +4,7 @@ use brk_types::{Bitcoin, Dollars, Height, Sats, StoredF32, StoredF64, Version};
use vecdb::{IterableCloneableVec, LazyVecFrom2};
use crate::internal::{
LazyVecsFrom2FromDateIndex, NegPercentageDollarsF32, NegRatio32, PercentageBtcF64,
BinaryDateLast, NegPercentageDollarsF32, NegRatio32, PercentageBtcF64,
PercentageDollarsF32, PercentageSatsF64, Ratio32,
};
@@ -15,28 +15,31 @@ use super::{ImportConfig, SupplyMetrics, UnrealizedMetrics};
#[derive(Clone, Traversable)]
pub struct RelativeMetrics {
// === Supply Relative to Circulating Supply (lazy from global supply) ===
// KISS: both sources are ComputedVecsDateLast<Sats>
pub indexes_to_supply_rel_to_circulating_supply:
Option<LazyVecsFrom2FromDateIndex<StoredF64, Sats, Sats>>,
Option<BinaryDateLast<StoredF64, Sats, Sats>>,
// === Supply in Profit/Loss Relative to Own Supply (lazy) ===
pub height_to_supply_in_profit_rel_to_own_supply:
LazyVecFrom2<Height, StoredF64, Height, Bitcoin, Height, Bitcoin>,
pub height_to_supply_in_loss_rel_to_own_supply:
LazyVecFrom2<Height, StoredF64, Height, Bitcoin, Height, Bitcoin>,
// KISS: both unrealized and supply are now KISS types
pub indexes_to_supply_in_profit_rel_to_own_supply:
LazyVecsFrom2FromDateIndex<StoredF64, Sats, Sats>,
BinaryDateLast<StoredF64, Sats, Sats>,
pub indexes_to_supply_in_loss_rel_to_own_supply:
LazyVecsFrom2FromDateIndex<StoredF64, Sats, Sats>,
BinaryDateLast<StoredF64, Sats, Sats>,
// === Supply in Profit/Loss Relative to Circulating Supply (lazy from global supply) ===
pub height_to_supply_in_profit_rel_to_circulating_supply:
Option<LazyVecFrom2<Height, StoredF64, Height, Bitcoin, Height, Bitcoin>>,
pub height_to_supply_in_loss_rel_to_circulating_supply:
Option<LazyVecFrom2<Height, StoredF64, Height, Bitcoin, Height, Bitcoin>>,
// KISS: both unrealized and global_supply are now KISS types
pub indexes_to_supply_in_profit_rel_to_circulating_supply:
Option<LazyVecsFrom2FromDateIndex<StoredF64, Sats, Sats>>,
Option<BinaryDateLast<StoredF64, Sats, Sats>>,
pub indexes_to_supply_in_loss_rel_to_circulating_supply:
Option<LazyVecsFrom2FromDateIndex<StoredF64, Sats, Sats>>,
Option<BinaryDateLast<StoredF64, Sats, Sats>>,
// === Unrealized vs Market Cap (lazy from global market cap) ===
pub height_to_unrealized_profit_rel_to_market_cap:
@@ -47,18 +50,20 @@ pub struct RelativeMetrics {
Option<LazyVecFrom2<Height, StoredF32, Height, Dollars, Height, Dollars>>,
pub height_to_net_unrealized_pnl_rel_to_market_cap:
Option<LazyVecFrom2<Height, StoredF32, Height, Dollars, Height, Dollars>>,
// KISS: DerivedDateLast + ComputedVecsDateLast
pub indexes_to_unrealized_profit_rel_to_market_cap:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
pub indexes_to_unrealized_loss_rel_to_market_cap:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
pub indexes_to_neg_unrealized_loss_rel_to_market_cap:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
// KISS: both ComputedVecsDateLast
pub indexes_to_net_unrealized_pnl_rel_to_market_cap:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
// === NUPL (Net Unrealized Profit/Loss) ===
// Proxy for indexes_to_net_unrealized_pnl_rel_to_market_cap
pub indexes_to_nupl: Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
// KISS: both ComputedVecsDateLast
pub indexes_to_nupl: Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
// === Unrealized vs Own Market Cap (lazy) ===
pub height_to_unrealized_profit_rel_to_own_market_cap:
@@ -69,14 +74,16 @@ pub struct RelativeMetrics {
Option<LazyVecFrom2<Height, StoredF32, Height, Dollars, Height, Dollars>>,
pub height_to_net_unrealized_pnl_rel_to_own_market_cap:
Option<LazyVecFrom2<Height, StoredF32, Height, Dollars, Height, Dollars>>,
// KISS: DerivedDateLast + ComputedVecsDateLast
pub indexes_to_unrealized_profit_rel_to_own_market_cap:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
pub indexes_to_unrealized_loss_rel_to_own_market_cap:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
pub indexes_to_neg_unrealized_loss_rel_to_own_market_cap:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
// KISS: both ComputedVecsDateLast
pub indexes_to_net_unrealized_pnl_rel_to_own_market_cap:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
// === Unrealized vs Own Total Unrealized PnL (lazy) ===
pub height_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
@@ -87,14 +94,15 @@ pub struct RelativeMetrics {
Option<LazyVecFrom2<Height, StoredF32, Height, Dollars, Height, Dollars>>,
pub height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
Option<LazyVecFrom2<Height, StoredF32, Height, Dollars, Height, Dollars>>,
// KISS: DerivedDateLast + DerivedDateLast
pub indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
pub indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
pub indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
pub indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
Option<LazyVecsFrom2FromDateIndex<StoredF32, Dollars, Dollars>>,
Option<BinaryDateLast<StoredF32, Dollars, Dollars>>,
}
impl RelativeMetrics {
@@ -115,6 +123,7 @@ impl RelativeMetrics {
// Global sources from "all" cohort
let global_supply_sats = all_supply.map(|s| &s.indexes_to_supply.sats);
let global_supply_sats_dateindex = all_supply.map(|s| &s.indexes_to_supply.sats_dateindex);
let global_supply_btc = all_supply.map(|s| &s.height_to_supply_value.bitcoin);
let global_market_cap = all_supply.and_then(|s| s.indexes_to_supply.dollars.as_ref());
let global_market_cap_height =
@@ -129,10 +138,12 @@ impl RelativeMetrics {
indexes_to_supply_rel_to_circulating_supply: (compute_rel_to_all
&& global_supply_sats.is_some())
.then(|| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageSatsF64>(
BinaryDateLast::from_both_derived_last::<PercentageSatsF64>(
&cfg.name("supply_rel_to_circulating_supply"),
cfg.version + v1,
supply.indexes_to_supply.sats_dateindex.boxed_clone(),
&supply.indexes_to_supply.sats,
global_supply_sats_dateindex.unwrap().boxed_clone(),
global_supply_sats.unwrap(),
)
}),
@@ -159,20 +170,23 @@ impl RelativeMetrics {
supply.height_to_supply_value.bitcoin.boxed_clone(),
),
indexes_to_supply_in_profit_rel_to_own_supply:
LazyVecsFrom2FromDateIndex::from_computed::<PercentageSatsF64>(
BinaryDateLast::from_both_derived_last::<PercentageSatsF64>(
&cfg.name("supply_in_profit_rel_to_own_supply"),
cfg.version + v1,
unrealized.dateindex_to_supply_in_profit.boxed_clone(),
&unrealized.indexes_to_supply_in_profit.sats,
supply.indexes_to_supply.sats_dateindex.boxed_clone(),
&supply.indexes_to_supply.sats,
),
indexes_to_supply_in_loss_rel_to_own_supply:
BinaryDateLast::from_both_derived_last::<PercentageSatsF64>(
&cfg.name("supply_in_loss_rel_to_own_supply"),
cfg.version + v1,
unrealized.dateindex_to_supply_in_loss.boxed_clone(),
&unrealized.indexes_to_supply_in_loss.sats,
supply.indexes_to_supply.sats_dateindex.boxed_clone(),
&supply.indexes_to_supply.sats,
),
indexes_to_supply_in_loss_rel_to_own_supply: LazyVecsFrom2FromDateIndex::from_computed::<
PercentageSatsF64,
>(
&cfg.name("supply_in_loss_rel_to_own_supply"),
cfg.version + v1,
&unrealized.indexes_to_supply_in_loss.sats,
&supply.indexes_to_supply.sats,
),
// === Supply in Profit/Loss Relative to Circulating Supply (lazy from global supply) ===
height_to_supply_in_profit_rel_to_circulating_supply: (compute_rel_to_all
@@ -204,20 +218,24 @@ impl RelativeMetrics {
indexes_to_supply_in_profit_rel_to_circulating_supply: (compute_rel_to_all
&& global_supply_sats.is_some())
.then(|| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageSatsF64>(
BinaryDateLast::from_both_derived_last::<PercentageSatsF64>(
&cfg.name("supply_in_profit_rel_to_circulating_supply"),
cfg.version + v1,
unrealized.dateindex_to_supply_in_profit.boxed_clone(),
&unrealized.indexes_to_supply_in_profit.sats,
global_supply_sats_dateindex.unwrap().boxed_clone(),
global_supply_sats.unwrap(),
)
}),
indexes_to_supply_in_loss_rel_to_circulating_supply: (compute_rel_to_all
&& global_supply_sats.is_some())
.then(|| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageSatsF64>(
BinaryDateLast::from_both_derived_last::<PercentageSatsF64>(
&cfg.name("supply_in_loss_rel_to_circulating_supply"),
cfg.version + v1,
unrealized.dateindex_to_supply_in_loss.boxed_clone(),
&unrealized.indexes_to_supply_in_loss.sats,
global_supply_sats_dateindex.unwrap().boxed_clone(),
global_supply_sats.unwrap(),
)
}),
@@ -255,32 +273,36 @@ impl RelativeMetrics {
mc.boxed_clone(),
)
}),
// KISS: market_cap is now ComputedVecsDateLast
indexes_to_unrealized_profit_rel_to_market_cap: global_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDollarsF32>(
BinaryDateLast::from_derived_last_and_computed_last::<PercentageDollarsF32>(
&cfg.name("unrealized_profit_rel_to_market_cap"),
cfg.version + v2,
unrealized.dateindex_to_unrealized_profit.boxed_clone(),
&unrealized.indexes_to_unrealized_profit,
mc,
)
}),
indexes_to_unrealized_loss_rel_to_market_cap: global_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDollarsF32>(
BinaryDateLast::from_derived_last_and_computed_last::<PercentageDollarsF32>(
&cfg.name("unrealized_loss_rel_to_market_cap"),
cfg.version + v2,
unrealized.dateindex_to_unrealized_loss.boxed_clone(),
&unrealized.indexes_to_unrealized_loss,
mc,
)
}),
indexes_to_neg_unrealized_loss_rel_to_market_cap: global_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<NegPercentageDollarsF32>(
BinaryDateLast::from_derived_last_and_computed_last::<NegPercentageDollarsF32>(
&cfg.name("neg_unrealized_loss_rel_to_market_cap"),
cfg.version + v2,
unrealized.dateindex_to_unrealized_loss.boxed_clone(),
&unrealized.indexes_to_unrealized_loss,
mc,
)
}),
indexes_to_net_unrealized_pnl_rel_to_market_cap: global_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDollarsF32>(
BinaryDateLast::from_computed_both_last::<PercentageDollarsF32>(
&cfg.name("net_unrealized_pnl_rel_to_market_cap"),
cfg.version + v2,
&unrealized.indexes_to_net_unrealized_pnl,
@@ -290,7 +312,7 @@ impl RelativeMetrics {
// NUPL is a proxy for net_unrealized_pnl_rel_to_market_cap
indexes_to_nupl: global_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDollarsF32>(
BinaryDateLast::from_computed_both_last::<PercentageDollarsF32>(
&cfg.name("nupl"),
cfg.version + v2,
&unrealized.indexes_to_net_unrealized_pnl,
@@ -347,12 +369,14 @@ impl RelativeMetrics {
})
})
.flatten(),
// KISS: own_market_cap is now ComputedVecsDateLast
indexes_to_unrealized_profit_rel_to_own_market_cap: (extended && compute_rel_to_all)
.then(|| {
own_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDollarsF32>(
BinaryDateLast::from_derived_last_and_computed_last::<PercentageDollarsF32>(
&cfg.name("unrealized_profit_rel_to_own_market_cap"),
cfg.version + v2,
unrealized.dateindex_to_unrealized_profit.boxed_clone(),
&unrealized.indexes_to_unrealized_profit,
mc,
)
@@ -362,9 +386,10 @@ impl RelativeMetrics {
indexes_to_unrealized_loss_rel_to_own_market_cap: (extended && compute_rel_to_all)
.then(|| {
own_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDollarsF32>(
BinaryDateLast::from_derived_last_and_computed_last::<PercentageDollarsF32>(
&cfg.name("unrealized_loss_rel_to_own_market_cap"),
cfg.version + v2,
unrealized.dateindex_to_unrealized_loss.boxed_clone(),
&unrealized.indexes_to_unrealized_loss,
mc,
)
@@ -374,9 +399,10 @@ impl RelativeMetrics {
indexes_to_neg_unrealized_loss_rel_to_own_market_cap: (extended && compute_rel_to_all)
.then(|| {
own_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<NegPercentageDollarsF32>(
BinaryDateLast::from_derived_last_and_computed_last::<NegPercentageDollarsF32>(
&cfg.name("neg_unrealized_loss_rel_to_own_market_cap"),
cfg.version + v2,
unrealized.dateindex_to_unrealized_loss.boxed_clone(),
&unrealized.indexes_to_unrealized_loss,
mc,
)
@@ -386,7 +412,7 @@ impl RelativeMetrics {
indexes_to_net_unrealized_pnl_rel_to_own_market_cap: (extended && compute_rel_to_all)
.then(|| {
own_market_cap.map(|mc| {
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDollarsF32>(
BinaryDateLast::from_computed_both_last::<PercentageDollarsF32>(
&cfg.name("net_unrealized_pnl_rel_to_own_market_cap"),
cfg.version + v2,
&unrealized.indexes_to_net_unrealized_pnl,
@@ -430,31 +456,34 @@ impl RelativeMetrics {
)
}),
indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl: extended.then(|| {
LazyVecsFrom2FromDateIndex::from_computed::<Ratio32>(
BinaryDateLast::from_derived_last_and_computed_last::<Ratio32>(
&cfg.name("unrealized_profit_rel_to_own_total_unrealized_pnl"),
cfg.version + v1,
unrealized.dateindex_to_unrealized_profit.boxed_clone(),
&unrealized.indexes_to_unrealized_profit,
&unrealized.indexes_to_total_unrealized_pnl,
)
}),
indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl: extended.then(|| {
LazyVecsFrom2FromDateIndex::from_computed::<Ratio32>(
BinaryDateLast::from_derived_last_and_computed_last::<Ratio32>(
&cfg.name("unrealized_loss_rel_to_own_total_unrealized_pnl"),
cfg.version + v1,
unrealized.dateindex_to_unrealized_loss.boxed_clone(),
&unrealized.indexes_to_unrealized_loss,
&unrealized.indexes_to_total_unrealized_pnl,
)
}),
indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: extended.then(|| {
LazyVecsFrom2FromDateIndex::from_computed::<NegRatio32>(
BinaryDateLast::from_derived_last_and_computed_last::<NegRatio32>(
&cfg.name("neg_unrealized_loss_rel_to_own_total_unrealized_pnl"),
cfg.version + v1,
unrealized.dateindex_to_unrealized_loss.boxed_clone(),
&unrealized.indexes_to_unrealized_loss,
&unrealized.indexes_to_total_unrealized_pnl,
)
}),
indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: extended.then(|| {
LazyVecsFrom2FromDateIndex::from_computed::<Ratio32>(
BinaryDateLast::from_computed_both_last::<Ratio32>(
&cfg.name("net_unrealized_pnl_rel_to_own_total_unrealized_pnl"),
cfg.version + v1,
&unrealized.indexes_to_net_unrealized_pnl,

View File

@@ -10,9 +10,8 @@ use vecdb::{
use crate::{
ComputeIndexes, indexes,
internal::{
ComputedHeightValueVecs, ComputedValueVecsFromDateIndex, ComputedVecsFromHeight,
HalfClosePriceTimesSats, HalveDollars, HalveSats, HalveSatsToBitcoin, LazyHeightValueVecs,
LazyValueVecsFromDateIndex, Source, VecBuilderOptions,
DerivedComputedBlockLast, HalfClosePriceTimesSats, HalveDollars, HalveSats,
HalveSatsToBitcoin, LazyBlockValue, LazyDerivedBlockValue, LazyValueDateLast, ValueDateLast,
},
price,
};
@@ -22,26 +21,13 @@ use super::ImportConfig;
/// Supply and UTXO count metrics for a cohort.
#[derive(Clone, Traversable)]
pub struct SupplyMetrics {
/// Total supply at each height
pub height_to_supply: EagerVec<PcoVec<Height, Sats>>,
/// Supply value in BTC and USD (computed from height_to_supply)
pub height_to_supply_value: ComputedHeightValueVecs,
/// Supply indexed by date
pub indexes_to_supply: ComputedValueVecsFromDateIndex,
/// UTXO count at each height
pub height_to_supply_value: LazyDerivedBlockValue,
pub indexes_to_supply: ValueDateLast,
pub height_to_utxo_count: EagerVec<PcoVec<Height, StoredU64>>,
/// UTXO count indexed by various dimensions
pub indexes_to_utxo_count: ComputedVecsFromHeight<StoredU64>,
/// Half of supply value (used for computing median) - lazy from supply_value
pub height_to_supply_half_value: LazyHeightValueVecs,
/// Half of supply indexed by date - lazy from indexes_to_supply
pub indexes_to_supply_half: LazyValueVecsFromDateIndex,
pub indexes_to_utxo_count: DerivedComputedBlockLast<StoredU64>,
pub height_to_supply_half_value: LazyBlockValue,
pub indexes_to_supply_half: LazyValueDateLast,
}
impl SupplyMetrics {
@@ -49,7 +35,6 @@ impl SupplyMetrics {
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
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)?;
@@ -58,26 +43,23 @@ impl SupplyMetrics {
.price
.map(|p| p.usd.chainindexes_to_price_close.height.boxed_clone());
let height_to_supply_value = ComputedHeightValueVecs::forced_import(
cfg.db,
let height_to_supply_value = LazyDerivedBlockValue::from_source(
&cfg.name("supply"),
Source::Vec(height_to_supply.boxed_clone()),
height_to_supply.boxed_clone(),
cfg.version,
price_source.clone(),
)?;
);
let indexes_to_supply = ComputedValueVecsFromDateIndex::forced_import(
let indexes_to_supply = ValueDateLast::forced_import(
cfg.db,
&cfg.name("supply"),
Source::Compute,
cfg.version + v1,
last,
compute_dollars,
cfg.indexes,
)?;
// Create lazy supply_half from supply sources
let height_to_supply_half_value = LazyHeightValueVecs::from_sources::<
let height_to_supply_half_value = LazyBlockValue::from_sources::<
HalveSats,
HalveSatsToBitcoin,
HalfClosePriceTimesSats,
@@ -89,7 +71,7 @@ impl SupplyMetrics {
);
let indexes_to_supply_half =
LazyValueVecsFromDateIndex::from_source::<HalveSats, HalveSatsToBitcoin, HalveDollars>(
LazyValueDateLast::from_source::<HalveSats, HalveSatsToBitcoin, HalveDollars>(
&cfg.name("supply_half"),
&indexes_to_supply,
cfg.version,
@@ -99,13 +81,12 @@ impl SupplyMetrics {
EagerVec::forced_import(cfg.db, &cfg.name("utxo_count"), cfg.version)?;
Ok(Self {
indexes_to_utxo_count: ComputedVecsFromHeight::forced_import(
indexes_to_utxo_count: DerivedComputedBlockLast::forced_import(
cfg.db,
&cfg.name("utxo_count"),
Source::Vec(height_to_utxo_count.boxed_clone()),
height_to_utxo_count.boxed_clone(),
cfg.version,
cfg.indexes,
last,
)?,
height_to_supply,
height_to_supply_value,
@@ -208,11 +189,11 @@ impl SupplyMetrics {
Ok(())
})?;
self.indexes_to_utxo_count.compute_rest(
self.indexes_to_utxo_count.derive_from(
indexes,
starting_indexes,
&self.height_to_utxo_count,
exit,
Some(&self.height_to_utxo_count),
)?;
Ok(())

View File

@@ -11,8 +11,8 @@ use crate::{
ComputeIndexes,
distribution::state::UnrealizedState,
internal::{
ComputedHeightValueVecs, ComputedValueVecsFromDateIndex, ComputedVecsFromDateIndex,
DollarsMinus, DollarsPlus, LazyVecsFromDateIndex, Source, VecBuilderOptions,
ComputedDateLast, DerivedDateLast, DollarsMinus, DollarsPlus, LazyDateLast,
LazyDerivedBlockValue, ValueDerivedDateLast,
},
};
@@ -23,42 +23,41 @@ use super::ImportConfig;
pub struct UnrealizedMetrics {
// === Supply in Profit/Loss ===
pub height_to_supply_in_profit: EagerVec<PcoVec<Height, Sats>>,
pub indexes_to_supply_in_profit: ComputedValueVecsFromDateIndex,
pub indexes_to_supply_in_profit: ValueDerivedDateLast,
pub height_to_supply_in_loss: EagerVec<PcoVec<Height, Sats>>,
pub indexes_to_supply_in_loss: ComputedValueVecsFromDateIndex,
pub indexes_to_supply_in_loss: ValueDerivedDateLast,
pub dateindex_to_supply_in_profit: EagerVec<PcoVec<DateIndex, Sats>>,
pub dateindex_to_supply_in_loss: EagerVec<PcoVec<DateIndex, Sats>>,
pub height_to_supply_in_profit_value: ComputedHeightValueVecs,
pub height_to_supply_in_loss_value: ComputedHeightValueVecs,
pub height_to_supply_in_profit_value: LazyDerivedBlockValue,
pub height_to_supply_in_loss_value: LazyDerivedBlockValue,
// === Unrealized Profit/Loss ===
pub height_to_unrealized_profit: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_unrealized_profit: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_unrealized_profit: DerivedDateLast<Dollars>,
pub height_to_unrealized_loss: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_unrealized_loss: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_unrealized_loss: DerivedDateLast<Dollars>,
pub dateindex_to_unrealized_profit: EagerVec<PcoVec<DateIndex, Dollars>>,
pub dateindex_to_unrealized_loss: EagerVec<PcoVec<DateIndex, Dollars>>,
// === Negated and Net ===
pub height_to_neg_unrealized_loss: LazyVecFrom1<Height, Dollars, Height, Dollars>,
pub indexes_to_neg_unrealized_loss: LazyVecsFromDateIndex<Dollars>,
pub indexes_to_neg_unrealized_loss: LazyDateLast<Dollars>,
// net = profit - loss (height is lazy, indexes computed)
pub height_to_net_unrealized_pnl:
LazyVecFrom2<Height, Dollars, Height, Dollars, Height, Dollars>,
pub indexes_to_net_unrealized_pnl: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_net_unrealized_pnl: ComputedDateLast<Dollars>,
// total = profit + loss (height is lazy, indexes computed)
pub height_to_total_unrealized_pnl:
LazyVecFrom2<Height, Dollars, Height, Dollars, Height, Dollars>,
pub indexes_to_total_unrealized_pnl: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_total_unrealized_pnl: ComputedDateLast<Dollars>,
}
impl UnrealizedMetrics {
/// Import unrealized metrics from database.
pub fn forced_import(cfg: &ImportConfig) -> Result<Self> {
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)?;
@@ -76,33 +75,29 @@ impl UnrealizedMetrics {
height_to_unrealized_loss.boxed_clone(),
);
let indexes_to_unrealized_loss = ComputedVecsFromDateIndex::forced_import(
cfg.db,
let indexes_to_unrealized_loss = DerivedDateLast::from_source(
&cfg.name("unrealized_loss"),
Source::Vec(dateindex_to_unrealized_loss.boxed_clone()),
cfg.version,
dateindex_to_unrealized_loss.boxed_clone(),
cfg.indexes,
last,
)?;
);
let indexes_to_neg_unrealized_loss = LazyVecsFromDateIndex::from_computed::<Negate>(
let indexes_to_neg_unrealized_loss = LazyDateLast::from_derived::<Negate>(
&cfg.name("neg_unrealized_loss"),
cfg.version,
Some(dateindex_to_unrealized_loss.boxed_clone()),
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)?;
let indexes_to_unrealized_profit = ComputedVecsFromDateIndex::forced_import(
cfg.db,
let indexes_to_unrealized_profit = DerivedDateLast::from_source(
&cfg.name("unrealized_profit"),
Source::Vec(dateindex_to_unrealized_profit.boxed_clone()),
cfg.version,
dateindex_to_unrealized_profit.boxed_clone(),
cfg.indexes,
last,
)?;
);
// Create lazy height vecs from profit/loss sources
let height_to_net_unrealized_pnl = LazyVecFrom2::transformed::<DollarsMinus>(
@@ -119,21 +114,17 @@ impl UnrealizedMetrics {
);
// indexes_to_net/total remain computed (needed by relative.rs)
let indexes_to_net_unrealized_pnl = ComputedVecsFromDateIndex::forced_import(
let indexes_to_net_unrealized_pnl = ComputedDateLast::forced_import(
cfg.db,
&cfg.name("net_unrealized_pnl"),
Source::Compute,
cfg.version,
cfg.indexes,
last,
)?;
let indexes_to_total_unrealized_pnl = ComputedVecsFromDateIndex::forced_import(
let indexes_to_total_unrealized_pnl = ComputedDateLast::forced_import(
cfg.db,
&cfg.name("total_unrealized_pnl"),
Source::Compute,
cfg.version,
cfg.indexes,
last,
)?;
let height_to_supply_in_profit: EagerVec<PcoVec<Height, Sats>> =
@@ -145,40 +136,36 @@ impl UnrealizedMetrics {
.price
.map(|p| p.usd.chainindexes_to_price_close.height.boxed_clone());
let height_to_supply_in_profit_value = ComputedHeightValueVecs::forced_import(
cfg.db,
let height_to_supply_in_profit_value = LazyDerivedBlockValue::from_source(
&cfg.name("supply_in_profit"),
Source::Vec(height_to_supply_in_profit.boxed_clone()),
height_to_supply_in_profit.boxed_clone(),
cfg.version,
price_source.clone(),
)?;
let height_to_supply_in_loss_value = ComputedHeightValueVecs::forced_import(
cfg.db,
);
let height_to_supply_in_loss_value = LazyDerivedBlockValue::from_source(
&cfg.name("supply_in_loss"),
Source::Vec(height_to_supply_in_loss.boxed_clone()),
height_to_supply_in_loss.boxed_clone(),
cfg.version,
price_source,
)?;
);
Ok(Self {
// === Supply in Profit/Loss ===
height_to_supply_in_profit,
indexes_to_supply_in_profit: ComputedValueVecsFromDateIndex::forced_import(
indexes_to_supply_in_profit: ValueDerivedDateLast::from_source(
cfg.db,
&cfg.name("supply_in_profit"),
Source::Vec(dateindex_to_supply_in_profit.boxed_clone()),
dateindex_to_supply_in_profit.boxed_clone(),
cfg.version,
last,
compute_dollars,
cfg.indexes,
)?,
height_to_supply_in_loss,
indexes_to_supply_in_loss: ComputedValueVecsFromDateIndex::forced_import(
indexes_to_supply_in_loss: ValueDerivedDateLast::from_source(
cfg.db,
&cfg.name("supply_in_loss"),
Source::Vec(dateindex_to_supply_in_loss.boxed_clone()),
dateindex_to_supply_in_loss.boxed_clone(),
cfg.version,
last,
compute_dollars,
cfg.indexes,
)?,
@@ -362,31 +349,14 @@ impl UnrealizedMetrics {
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.indexes_to_supply_in_profit.compute_rest(
price,
starting_indexes,
exit,
Some(&self.dateindex_to_supply_in_profit),
)?;
// KISS: compute_rest doesn't need source vec - lazy vecs are set up during import
self.indexes_to_supply_in_profit
.compute_rest(price, starting_indexes, exit)?;
self.indexes_to_supply_in_loss.compute_rest(
price,
starting_indexes,
exit,
Some(&self.dateindex_to_supply_in_loss),
)?;
self.indexes_to_supply_in_loss
.compute_rest(price, starting_indexes, exit)?;
self.indexes_to_unrealized_profit.compute_rest(
starting_indexes,
exit,
Some(&self.dateindex_to_unrealized_profit),
)?;
self.indexes_to_unrealized_loss.compute_rest(
starting_indexes,
exit,
Some(&self.dateindex_to_unrealized_loss),
)?;
// indexes_to_unrealized_profit/loss are Derived - no compute needed (lazy only)
// height_to_net/total are lazy, but indexes still need compute
// total_unrealized_pnl = profit + loss

View File

@@ -2,12 +2,9 @@ use std::path::Path;
use brk_error::Result;
use brk_types::{Sats, SupplyState};
use derive_deref::{Deref, DerefMut};
use derive_more::{Deref, DerefMut};
use super::{
super::cost_basis::RealizedState,
base::CohortState,
};
use super::{super::cost_basis::RealizedState, base::CohortState};
#[derive(Clone, Deref, DerefMut)]
pub struct UTXOCohortState(CohortState);

View File

@@ -7,7 +7,7 @@ use std::{
use brk_error::{Error, Result};
use brk_types::{CentsCompact, Dollars, Height, Sats, SupplyState};
use derive_deref::{Deref, DerefMut};
use derive_more::{Deref, DerefMut};
use pco::standalone::{simple_decompress, simpler_compress};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};

View File

@@ -20,7 +20,7 @@ use crate::{
state::BlockState,
},
indexes, inputs,
internal::{ComputedVecsFromHeight, Source, VecBuilderOptions},
internal::ComputedBlockLast,
outputs, price, transactions,
};
@@ -49,8 +49,8 @@ pub struct Vecs {
pub addresstype_to_indexes_to_addr_count: AddressTypeToIndexesToAddressCount,
pub addresstype_to_indexes_to_empty_addr_count: AddressTypeToIndexesToAddressCount,
pub indexes_to_addr_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_empty_addr_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_addr_count: ComputedBlockLast<StoredU64>,
pub indexes_to_empty_addr_count: ComputedBlockLast<StoredU64>,
pub loadedaddressindex_to_loadedaddressindex:
LazyVecFrom1<LoadedAddressIndex, LoadedAddressIndex, LoadedAddressIndex, LoadedAddressData>,
pub emptyaddressindex_to_emptyaddressindex:
@@ -123,21 +123,17 @@ impl Vecs {
.with_saved_stamped_changes(SAVED_STAMPED_CHANGES),
)?,
indexes_to_addr_count: ComputedVecsFromHeight::forced_import(
indexes_to_addr_count: ComputedBlockLast::forced_import(
&db,
"addr_count",
Source::Compute,
version,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_empty_addr_count: ComputedVecsFromHeight::forced_import(
indexes_to_empty_addr_count: ComputedBlockLast::forced_import(
&db,
"empty_addr_count",
Source::Compute,
version,
indexes,
VecBuilderOptions::default().add_last(),
)?,
addresstype_to_indexes_to_addr_count:
@@ -380,11 +376,12 @@ impl Vecs {
.as_ref()
.cloned();
// KISS: dateindex is no longer Option, just clone directly
let dateindex_to_market_cap = supply_metrics
.indexes_to_supply
.dollars
.as_ref()
.and_then(|v| v.dateindex.as_ref().cloned());
.map(|v| v.dateindex.clone());
let height_to_market_cap_ref = height_to_market_cap.as_ref();
let dateindex_to_market_cap_ref = dateindex_to_market_cap.as_ref();