global: snapshot

This commit is contained in:
nym21
2026-03-16 18:38:16 +01:00
parent ae067739ce
commit 5848d25612
55 changed files with 1366 additions and 1384 deletions

View File

@@ -28,7 +28,7 @@ impl Vecs {
exit,
)?;
self.blocks_before_next.height.compute_transform(
self.blocks_to_retarget.height.compute_transform(
starting_indexes.height,
&indexes.height.identity,
|(h, ..)| (h, StoredU32::from(h.left_before_next_diff_adj())),

View File

@@ -20,25 +20,25 @@ impl Vecs {
) -> Result<Self> {
let v2 = Version::TWO;
let as_hash = LazyPerBlock::from_height_source::<DifficultyToHashF64>(
"difficulty_as_hash",
let hashrate = LazyPerBlock::from_height_source::<DifficultyToHashF64>(
"difficulty_hashrate",
version,
indexer.vecs.blocks.difficulty.read_only_boxed_clone(),
indexes,
);
let blocks_before_next = PerBlock::forced_import(
let blocks_to_retarget = PerBlock::forced_import(
db,
"blocks_before_next_difficulty_adjustment",
"blocks_to_retarget",
version + v2,
indexes,
)?;
let days_before_next = LazyPerBlock::from_computed::<BlocksToDaysF32>(
"days_before_next_difficulty_adjustment",
let days_to_retarget = LazyPerBlock::from_computed::<BlocksToDaysF32>(
"days_to_retarget",
version + v2,
blocks_before_next.height.read_only_boxed_clone(),
&blocks_before_next,
blocks_to_retarget.height.read_only_boxed_clone(),
&blocks_to_retarget,
);
Ok(Self {
@@ -48,7 +48,7 @@ impl Vecs {
version,
indexes,
),
as_hash,
hashrate,
adjustment: PercentPerBlock::forced_import(
db,
"difficulty_adjustment",
@@ -56,8 +56,8 @@ impl Vecs {
indexes,
)?,
epoch: PerBlock::forced_import(db, "difficulty_epoch", version, indexes)?,
blocks_before_next,
days_before_next,
blocks_to_retarget,
days_to_retarget,
})
}
}

View File

@@ -6,9 +6,9 @@ use crate::internal::{LazyPerBlock, PerBlock, Resolutions, PercentPerBlock};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub value: Resolutions<StoredF64>,
pub as_hash: LazyPerBlock<StoredF64>,
pub hashrate: LazyPerBlock<StoredF64>,
pub adjustment: PercentPerBlock<BasisPointsSigned32, M>,
pub epoch: PerBlock<Epoch, M>,
pub blocks_before_next: PerBlock<StoredU32, M>,
pub days_before_next: LazyPerBlock<StoredF32, StoredU32>,
pub blocks_to_retarget: PerBlock<StoredU32, M>,
pub days_to_retarget: LazyPerBlock<StoredF32, StoredU32>,
}

View File

@@ -19,7 +19,7 @@ impl Vecs {
exit,
)?;
self.blocks_before_next.height.compute_transform(
self.blocks_to_halving.height.compute_transform(
starting_indexes.height,
&indexes.height.identity,
|(h, ..)| (h, StoredU32::from(h.left_before_next_halving())),

View File

@@ -16,21 +16,21 @@ impl Vecs {
) -> Result<Self> {
let v2 = Version::TWO;
let blocks_before_next = PerBlock::forced_import(
db, "blocks_before_next_halving", version + v2, indexes,
let blocks_to_halving = PerBlock::forced_import(
db, "blocks_to_halving", version + v2, indexes,
)?;
let days_before_next = LazyPerBlock::from_computed::<BlocksToDaysF32>(
"days_before_next_halving",
let days_to_halving = LazyPerBlock::from_computed::<BlocksToDaysF32>(
"days_to_halving",
version + v2,
blocks_before_next.height.read_only_boxed_clone(),
&blocks_before_next,
blocks_to_halving.height.read_only_boxed_clone(),
&blocks_to_halving,
);
Ok(Self {
epoch: PerBlock::forced_import(db, "halving_epoch", version, indexes)?,
blocks_before_next,
days_before_next,
blocks_to_halving,
days_to_halving,
})
}
}

View File

@@ -6,6 +6,6 @@ use crate::internal::{LazyPerBlock, PerBlock};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub epoch: PerBlock<Halving, M>,
pub blocks_before_next: PerBlock<StoredU32, M>,
pub days_before_next: LazyPerBlock<StoredF32, StoredU32>,
pub blocks_to_halving: PerBlock<StoredU32, M>,
pub days_to_halving: LazyPerBlock<StoredF32, StoredU32>,
}

View File

@@ -35,7 +35,7 @@ impl Vecs {
)?,
liveliness,
vaultedness,
ratio: PerBlock::forced_import(db, "activity_to_vaultedness_ratio", version, indexes)?,
ratio: PerBlock::forced_import(db, "activity_to_vaultedness", version, indexes)?,
})
}
}

View File

@@ -15,5 +15,6 @@ pub struct Vecs<M: StorageMode = Rw> {
pub terminal: PriceWithRatioExtendedPerBlock<M>,
pub delta: PriceWithRatioExtendedPerBlock<M>,
#[traversable(hidden)]
pub cumulative_market_cap: PerBlock<Dollars, M>,
}

View File

@@ -113,39 +113,39 @@ impl ActivityCountVecs {
pub(crate) fn min_stateful_len(&self) -> usize {
self.reactivated
.height
.base
.len()
.min(self.sending.height.len())
.min(self.receiving.height.len())
.min(self.both.height.len())
.min(self.sending.base.len())
.min(self.receiving.base.len())
.min(self.both.base.len())
}
pub(crate) fn par_iter_height_mut(
&mut self,
) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
[
&mut self.reactivated.height as &mut dyn AnyStoredVec,
&mut self.sending.height as &mut dyn AnyStoredVec,
&mut self.receiving.height as &mut dyn AnyStoredVec,
&mut self.both.height as &mut dyn AnyStoredVec,
&mut self.reactivated.base as &mut dyn AnyStoredVec,
&mut self.sending.base as &mut dyn AnyStoredVec,
&mut self.receiving.base as &mut dyn AnyStoredVec,
&mut self.both.base as &mut dyn AnyStoredVec,
]
.into_par_iter()
}
pub(crate) fn reset_height(&mut self) -> Result<()> {
self.reactivated.height.reset()?;
self.sending.height.reset()?;
self.receiving.height.reset()?;
self.both.height.reset()?;
self.reactivated.base.reset()?;
self.sending.base.reset()?;
self.receiving.base.reset()?;
self.both.base.reset()?;
Ok(())
}
#[inline(always)]
pub(crate) fn push_height(&mut self, counts: &BlockActivityCounts) {
self.reactivated.height.push(counts.reactivated.into());
self.sending.height.push(counts.sending.into());
self.receiving.height.push(counts.receiving.into());
self.both.height.push(counts.both.into());
self.reactivated.base.push(counts.reactivated.into());
self.sending.base.push(counts.sending.into());
self.receiving.base.push(counts.receiving.into());
self.both.base.push(counts.both.into());
}
pub(crate) fn compute_rest(
@@ -206,10 +206,10 @@ impl AddressTypeToActivityCountVecs {
) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
let mut vecs: Vec<&mut dyn AnyStoredVec> = Vec::new();
for type_vecs in self.0.values_mut() {
vecs.push(&mut type_vecs.reactivated.height);
vecs.push(&mut type_vecs.sending.height);
vecs.push(&mut type_vecs.receiving.height);
vecs.push(&mut type_vecs.both.height);
vecs.push(&mut type_vecs.reactivated.base);
vecs.push(&mut type_vecs.sending.base);
vecs.push(&mut type_vecs.receiving.base);
vecs.push(&mut type_vecs.both.base);
}
vecs.into_par_iter()
}

View File

@@ -11,33 +11,33 @@ use crate::{
#[derive(Traversable)]
pub struct ActivityCore<M: StorageMode = Rw> {
pub sent: PerBlockCumulativeWithSums<Sats, Sats, M>,
pub transfer_volume: PerBlockCumulativeWithSums<Sats, Sats, M>,
pub coindays_destroyed: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
#[traversable(wrap = "sent", rename = "in_profit")]
pub sent_in_profit: AmountPerBlockCumulativeWithSums<M>,
#[traversable(wrap = "sent", rename = "in_loss")]
pub sent_in_loss: AmountPerBlockCumulativeWithSums<M>,
#[traversable(wrap = "transfer_volume", rename = "in_profit")]
pub transfer_volume_in_profit: AmountPerBlockCumulativeWithSums<M>,
#[traversable(wrap = "transfer_volume", rename = "in_loss")]
pub transfer_volume_in_loss: AmountPerBlockCumulativeWithSums<M>,
}
impl ActivityCore {
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
let v1 = Version::ONE;
Ok(Self {
sent: cfg.import("sent", v1)?,
transfer_volume: cfg.import("transfer_volume", v1)?,
coindays_destroyed: cfg.import("coindays_destroyed", v1)?,
sent_in_profit: cfg.import("sent_in_profit", v1)?,
sent_in_loss: cfg.import("sent_in_loss", v1)?,
transfer_volume_in_profit: cfg.import("transfer_volume_in_profit", v1)?,
transfer_volume_in_loss: cfg.import("transfer_volume_in_loss", v1)?,
})
}
pub(crate) fn min_len(&self) -> usize {
self.sent
self.transfer_volume
.base
.height
.len()
.min(self.coindays_destroyed.base.height.len())
.min(self.sent_in_profit.base.sats.height.len())
.min(self.sent_in_loss.base.sats.height.len())
.min(self.transfer_volume_in_profit.base.sats.height.len())
.min(self.transfer_volume_in_loss.base.sats.height.len())
}
#[inline(always)]
@@ -45,16 +45,16 @@ impl ActivityCore {
&mut self,
state: &CohortState<impl RealizedOps, impl CostBasisOps>,
) {
self.sent.base.height.push(state.sent);
self.transfer_volume.base.height.push(state.sent);
self.coindays_destroyed.base.height.push(
StoredF64::from(Bitcoin::from(state.satdays_destroyed)),
);
self.sent_in_profit
self.transfer_volume_in_profit
.base
.sats
.height
.push(state.realized.sent_in_profit());
self.sent_in_loss
self.transfer_volume_in_loss
.base
.sats
.height
@@ -63,12 +63,12 @@ impl ActivityCore {
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
vec![
&mut self.sent.base.height as &mut dyn AnyStoredVec,
&mut self.transfer_volume.base.height as &mut dyn AnyStoredVec,
&mut self.coindays_destroyed.base.height,
&mut self.sent_in_profit.base.sats.height,
&mut self.sent_in_profit.base.cents.height,
&mut self.sent_in_loss.base.sats.height,
&mut self.sent_in_loss.base.cents.height,
&mut self.transfer_volume_in_profit.base.sats.height,
&mut self.transfer_volume_in_profit.base.cents.height,
&mut self.transfer_volume_in_loss.base.sats.height,
&mut self.transfer_volume_in_loss.base.cents.height,
]
}
@@ -82,18 +82,18 @@ impl ActivityCore {
others: &[&Self],
exit: &Exit,
) -> Result<()> {
self.sent.base.height.compute_sum_of_others(
self.transfer_volume.base.height.compute_sum_of_others(
starting_indexes.height,
&others
.iter()
.map(|v| &v.sent.base.height)
.map(|v| &v.transfer_volume.base.height)
.collect::<Vec<_>>(),
exit,
)?;
sum_others!(self, starting_indexes, others, exit; coindays_destroyed.base.height);
sum_others!(self, starting_indexes, others, exit; sent_in_profit.base.sats.height);
sum_others!(self, starting_indexes, others, exit; sent_in_loss.base.sats.height);
sum_others!(self, starting_indexes, others, exit; transfer_volume_in_profit.base.sats.height);
sum_others!(self, starting_indexes, others, exit; transfer_volume_in_loss.base.sats.height);
Ok(())
}
@@ -103,7 +103,7 @@ impl ActivityCore {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.sent
self.transfer_volume
.compute_rest(starting_indexes.height, exit)?;
self.coindays_destroyed
.compute_rest(starting_indexes.height, exit)?;
@@ -116,9 +116,9 @@ impl ActivityCore {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.sent_in_profit
self.transfer_volume_in_profit
.compute_rest(starting_indexes.height, prices, exit)?;
self.sent_in_loss
self.transfer_volume_in_loss
.compute_rest(starting_indexes.height, prices, exit)?;
Ok(())
}

View File

@@ -85,7 +85,7 @@ impl ActivityFull {
self.dormancy.height.compute_transform2(
starting_indexes.height,
&self.inner.coindays_destroyed.base.height,
&self.inner.sent.base.height,
&self.inner.transfer_volume.base.height,
|(i, cdd, sent_sats, ..)| {
let sent_btc = f64::from(Bitcoin::from(sent_sats));
if sent_btc == 0.0 {

View File

@@ -31,7 +31,7 @@ use super::RealizedCore;
#[derive(Traversable)]
pub struct RealizedProfit<M: StorageMode = Rw> {
pub rel_to_rcap: PercentPerBlock<BasisPoints32, M>,
pub to_rcap: PercentPerBlock<BasisPoints32, M>,
pub value_created: PerBlockCumulativeWithSums<Cents, Cents, M>,
pub value_destroyed: PerBlockCumulativeWithSums<Cents, Cents, M>,
pub distribution_flow: LazyPerBlock<Dollars, Cents>,
@@ -39,7 +39,7 @@ pub struct RealizedProfit<M: StorageMode = Rw> {
#[derive(Traversable)]
pub struct RealizedLoss<M: StorageMode = Rw> {
pub rel_to_rcap: PercentPerBlock<BasisPoints32, M>,
pub to_rcap: PercentPerBlock<BasisPoints32, M>,
pub value_created: PerBlockCumulativeWithSums<Cents, Cents, M>,
pub value_destroyed: PerBlockCumulativeWithSums<Cents, Cents, M>,
pub capitulation_flow: LazyPerBlock<Dollars, Cents>,
@@ -47,11 +47,11 @@ pub struct RealizedLoss<M: StorageMode = Rw> {
#[derive(Traversable)]
pub struct RealizedNetPnl<M: StorageMode = Rw> {
pub rel_to_rcap: PercentPerBlock<BasisPointsSigned32, M>,
#[traversable(wrap = "change_1m", rename = "rel_to_rcap")]
pub change_1m_rel_to_rcap: PercentPerBlock<BasisPointsSigned32, M>,
#[traversable(wrap = "change_1m", rename = "rel_to_mcap")]
pub change_1m_rel_to_mcap: PercentPerBlock<BasisPointsSigned32, M>,
pub to_rcap: PercentPerBlock<BasisPointsSigned32, M>,
#[traversable(wrap = "change_1m", rename = "to_rcap")]
pub change_1m_to_rcap: PercentPerBlock<BasisPointsSigned32, M>,
#[traversable(wrap = "change_1m", rename = "to_mcap")]
pub change_1m_to_mcap: PercentPerBlock<BasisPointsSigned32, M>,
}
#[derive(Traversable)]
@@ -64,14 +64,14 @@ pub struct RealizedSopr<M: StorageMode = Rw> {
pub struct RealizedPeakRegret<M: StorageMode = Rw> {
#[traversable(flatten)]
pub value: PerBlockCumulative<Cents, M>,
pub rel_to_rcap: PercentPerBlock<BasisPoints32, M>,
pub to_rcap: PercentPerBlock<BasisPoints32, M>,
}
#[derive(Traversable)]
pub struct RealizedInvestor<M: StorageMode = Rw> {
pub price: PriceWithRatioExtendedPerBlock<M>,
pub lower_price_band: Price<PerBlock<Cents, M>>,
pub upper_price_band: Price<PerBlock<Cents, M>>,
pub investor_lower_band: Price<PerBlock<Cents, M>>,
pub investor_upper_band: Price<PerBlock<Cents, M>>,
#[traversable(hidden)]
pub cap_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
}
@@ -96,8 +96,8 @@ pub struct RealizedFull<M: StorageMode = Rw> {
#[traversable(hidden)]
pub cap_raw: M::Stored<BytesVec<Height, CentsSats>>,
#[traversable(wrap = "cap", rename = "rel_to_own_mcap")]
pub cap_rel_to_own_mcap: PercentPerBlock<BasisPoints32, M>,
#[traversable(wrap = "cap", rename = "to_own_mcap")]
pub cap_to_own_mcap: PercentPerBlock<BasisPoints32, M>,
#[traversable(wrap = "price", rename = "percentiles")]
pub price_ratio_percentiles: RatioPerBlockPercentiles<M>,
@@ -124,7 +124,7 @@ impl RealizedFull {
&profit_value_destroyed.base,
);
let profit = RealizedProfit {
rel_to_rcap: cfg.import("realized_profit_rel_to_rcap", Version::new(2))?,
to_rcap: cfg.import("realized_profit_to_rcap", Version::new(2))?,
value_created: cfg.import("profit_value_created", v1)?,
value_destroyed: profit_value_destroyed,
distribution_flow: profit_flow,
@@ -140,7 +140,7 @@ impl RealizedFull {
&loss_value_destroyed.base,
);
let loss = RealizedLoss {
rel_to_rcap: cfg.import("realized_loss_rel_to_rcap", Version::new(2))?,
to_rcap: cfg.import("realized_loss_to_rcap", Version::new(2))?,
value_created: cfg.import("loss_value_created", v1)?,
value_destroyed: loss_value_destroyed,
capitulation_flow,
@@ -153,12 +153,12 @@ impl RealizedFull {
// Net PnL
let net_pnl = RealizedNetPnl {
rel_to_rcap: cfg
.import("net_realized_pnl_rel_to_rcap", Version::new(2))?,
change_1m_rel_to_rcap: cfg
.import("net_pnl_change_1m_rel_to_rcap", Version::new(4))?,
change_1m_rel_to_mcap: cfg
.import("net_pnl_change_1m_rel_to_mcap", Version::new(4))?,
to_rcap: cfg
.import("net_realized_pnl_to_rcap", Version::new(2))?,
change_1m_to_rcap: cfg
.import("net_pnl_change_1m_to_rcap", Version::new(4))?,
change_1m_to_mcap: cfg
.import("net_pnl_change_1m_to_mcap", Version::new(4))?,
};
// SOPR
@@ -169,15 +169,15 @@ impl RealizedFull {
// Peak regret
let peak_regret = RealizedPeakRegret {
value: cfg.import("realized_peak_regret", Version::new(2))?,
rel_to_rcap: cfg
.import("realized_peak_regret_rel_to_rcap", Version::new(2))?,
to_rcap: cfg
.import("realized_peak_regret_to_rcap", Version::new(2))?,
};
// Investor
let investor = RealizedInvestor {
price: cfg.import("investor_price", v0)?,
lower_price_band: cfg.import("lower_price_band", v0)?,
upper_price_band: cfg.import("upper_price_band", v0)?,
investor_lower_band: cfg.import("investor_lower_band", v0)?,
investor_upper_band: cfg.import("investor_upper_band", v0)?,
cap_raw: cfg.import("investor_cap_raw", v0)?,
};
@@ -197,7 +197,7 @@ impl RealizedFull {
investor,
profit_to_loss_ratio: cfg.import("realized_profit_to_loss_ratio", v1)?,
cap_raw: cfg.import("cap_raw", v0)?,
cap_rel_to_own_mcap: cfg.import("realized_cap_rel_to_own_mcap", v1)?,
cap_to_own_mcap: cfg.import("realized_cap_to_own_mcap", v1)?,
price_ratio_percentiles: RatioPerBlockPercentiles::forced_import(
cfg.db,
&realized_price_name,
@@ -403,7 +403,7 @@ impl RealizedFull {
// Profit/loss/net_pnl rel to realized cap
self.profit
.rel_to_rcap
.to_rcap
.compute_binary::<Cents, Cents, RatioCentsBp32>(
starting_indexes.height,
&self.core.minimal.profit.base.cents.height,
@@ -411,7 +411,7 @@ impl RealizedFull {
exit,
)?;
self.loss
.rel_to_rcap
.to_rcap
.compute_binary::<Cents, Cents, RatioCentsBp32>(
starting_indexes.height,
&self.core.minimal.loss.base.cents.height,
@@ -419,7 +419,7 @@ impl RealizedFull {
exit,
)?;
self.net_pnl
.rel_to_rcap
.to_rcap
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
starting_indexes.height,
&self.core.net_pnl.base.cents.height,
@@ -453,7 +453,7 @@ impl RealizedFull {
// Net PnL 1m change relative to rcap and mcap
self.net_pnl
.change_1m_rel_to_rcap
.change_1m_to_rcap
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
starting_indexes.height,
&self.core.net_pnl.delta.absolute._1m.cents.height,
@@ -461,7 +461,7 @@ impl RealizedFull {
exit,
)?;
self.net_pnl
.change_1m_rel_to_mcap
.change_1m_to_mcap
.compute_binary::<CentsSigned, Dollars, RatioCentsSignedDollarsBps32>(
starting_indexes.height,
&self.core.net_pnl.delta.absolute._1m.cents.height,
@@ -471,7 +471,7 @@ impl RealizedFull {
// Peak regret rel to rcap
self.peak_regret
.rel_to_rcap
.to_rcap
.compute_binary::<Cents, Cents, RatioCentsBp32>(
starting_indexes.height,
&self.peak_regret.value.base.height,
@@ -487,7 +487,7 @@ impl RealizedFull {
)?;
self.investor
.lower_price_band
.investor_lower_band
.cents
.height
.compute_transform2(
@@ -507,7 +507,7 @@ impl RealizedFull {
)?;
self.investor
.upper_price_band
.investor_upper_band
.cents
.height
.compute_transform2(
@@ -542,7 +542,7 @@ impl RealizedFull {
}
// Realized cap relative to own market cap
self.cap_rel_to_own_mcap
self.cap_to_own_mcap
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height,
&self.core.minimal.cap.usd.height,

View File

@@ -10,12 +10,12 @@ use crate::distribution::metrics::{ImportConfig, UnrealizedCore};
/// Extended relative metrics for own market cap (extended && rel_to_all).
#[derive(Traversable)]
pub struct RelativeExtendedOwnMarketCap<M: StorageMode = Rw> {
#[traversable(wrap = "unrealized/profit", rename = "rel_to_own_mcap")]
pub unrealized_profit_rel_to_own_mcap: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/loss", rename = "rel_to_own_mcap")]
pub unrealized_loss_rel_to_own_mcap: PercentPerBlock<BasisPoints32, M>,
#[traversable(wrap = "unrealized/net_pnl", rename = "rel_to_own_mcap")]
pub net_unrealized_pnl_rel_to_own_mcap: PercentPerBlock<BasisPointsSigned32, M>,
#[traversable(wrap = "unrealized/profit", rename = "to_own_mcap")]
pub unrealized_profit_to_own_mcap: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/loss", rename = "to_own_mcap")]
pub unrealized_loss_to_own_mcap: PercentPerBlock<BasisPoints32, M>,
#[traversable(wrap = "unrealized/net_pnl", rename = "to_own_mcap")]
pub net_unrealized_pnl_to_own_mcap: PercentPerBlock<BasisPointsSigned32, M>,
}
impl RelativeExtendedOwnMarketCap {
@@ -23,12 +23,12 @@ impl RelativeExtendedOwnMarketCap {
let v2 = Version::new(2);
Ok(Self {
unrealized_profit_rel_to_own_mcap: cfg
.import("unrealized_profit_rel_to_own_mcap", v2)?,
unrealized_loss_rel_to_own_mcap: cfg
.import("unrealized_loss_rel_to_own_mcap", Version::new(3))?,
net_unrealized_pnl_rel_to_own_mcap: cfg
.import("net_unrealized_pnl_rel_to_own_mcap", Version::new(3))?,
unrealized_profit_to_own_mcap: cfg
.import("unrealized_profit_to_own_mcap", v2)?,
unrealized_loss_to_own_mcap: cfg
.import("unrealized_loss_to_own_mcap", Version::new(3))?,
net_unrealized_pnl_to_own_mcap: cfg
.import("net_unrealized_pnl_to_own_mcap", Version::new(3))?,
})
}
@@ -39,21 +39,21 @@ impl RelativeExtendedOwnMarketCap {
own_market_cap: &impl ReadableVec<Height, Dollars>,
exit: &Exit,
) -> Result<()> {
self.unrealized_profit_rel_to_own_mcap
self.unrealized_profit_to_own_mcap
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
max_from,
&unrealized.profit.base.usd.height,
own_market_cap,
exit,
)?;
self.unrealized_loss_rel_to_own_mcap
self.unrealized_loss_to_own_mcap
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
max_from,
&unrealized.loss.base.usd.height,
own_market_cap,
exit,
)?;
self.net_unrealized_pnl_rel_to_own_mcap
self.net_unrealized_pnl_to_own_mcap
.compute_binary::<Dollars, Dollars, RatioDollarsBps32>(
max_from,
&unrealized.net_pnl.usd.height,

View File

@@ -10,12 +10,12 @@ use crate::distribution::metrics::{ImportConfig, UnrealizedCore};
/// Extended relative metrics for own total unrealized PnL (extended only).
#[derive(Traversable)]
pub struct RelativeExtendedOwnPnl<M: StorageMode = Rw> {
#[traversable(wrap = "unrealized/profit", rename = "rel_to_own_gross")]
pub unrealized_profit_rel_to_own_gross_pnl: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/loss", rename = "rel_to_own_gross")]
pub unrealized_loss_rel_to_own_gross_pnl: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/net_pnl", rename = "rel_to_own_gross")]
pub net_unrealized_pnl_rel_to_own_gross_pnl: PercentPerBlock<BasisPointsSigned32, M>,
#[traversable(wrap = "unrealized/profit", rename = "to_own_gross_pnl")]
pub unrealized_profit_to_own_gross_pnl: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/loss", rename = "to_own_gross_pnl")]
pub unrealized_loss_to_own_gross_pnl: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/net_pnl", rename = "to_own_gross_pnl")]
pub net_unrealized_pnl_to_own_gross_pnl: PercentPerBlock<BasisPointsSigned32, M>,
}
@@ -24,12 +24,12 @@ impl RelativeExtendedOwnPnl {
let v1 = Version::ONE;
Ok(Self {
unrealized_profit_rel_to_own_gross_pnl: cfg
.import("unrealized_profit_rel_to_own_gross_pnl", v1)?,
unrealized_loss_rel_to_own_gross_pnl: cfg
.import("unrealized_loss_rel_to_own_gross_pnl", v1)?,
net_unrealized_pnl_rel_to_own_gross_pnl: cfg
.import("net_unrealized_pnl_rel_to_own_gross_pnl", Version::new(3))?,
unrealized_profit_to_own_gross_pnl: cfg
.import("unrealized_profit_to_own_gross_pnl", v1)?,
unrealized_loss_to_own_gross_pnl: cfg
.import("unrealized_loss_to_own_gross_pnl", v1)?,
net_unrealized_pnl_to_own_gross_pnl: cfg
.import("net_unrealized_pnl_to_own_gross_pnl", Version::new(3))?,
})
}
@@ -40,21 +40,21 @@ impl RelativeExtendedOwnPnl {
gross_pnl_usd: &impl ReadableVec<Height, Dollars>,
exit: &Exit,
) -> Result<()> {
self.unrealized_profit_rel_to_own_gross_pnl
self.unrealized_profit_to_own_gross_pnl
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
max_from,
&unrealized.profit.base.usd.height,
gross_pnl_usd,
exit,
)?;
self.unrealized_loss_rel_to_own_gross_pnl
self.unrealized_loss_to_own_gross_pnl
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
max_from,
&unrealized.loss.base.usd.height,
gross_pnl_usd,
exit,
)?;
self.net_unrealized_pnl_rel_to_own_gross_pnl
self.net_unrealized_pnl_to_own_gross_pnl
.compute_binary::<Dollars, Dollars, RatioDollarsBps32>(
max_from,
&unrealized.net_pnl.usd.height,

View File

@@ -11,15 +11,15 @@ use crate::{
/// Full relative metrics (sth/lth/all tier).
#[derive(Traversable)]
pub struct RelativeFull<M: StorageMode = Rw> {
#[traversable(wrap = "supply/in_profit", rename = "rel_to_own")]
pub supply_in_profit_rel_to_own: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "supply/in_loss", rename = "rel_to_own")]
pub supply_in_loss_rel_to_own: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "supply/in_profit", rename = "to_own")]
pub supply_in_profit_to_own: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "supply/in_loss", rename = "to_own")]
pub supply_in_loss_to_own: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/profit", rename = "rel_to_mcap")]
pub unrealized_profit_rel_to_mcap: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/loss", rename = "rel_to_mcap")]
pub unrealized_loss_rel_to_mcap: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/profit", rename = "to_mcap")]
pub unrealized_profit_to_mcap: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "unrealized/loss", rename = "to_mcap")]
pub unrealized_loss_to_mcap: PercentPerBlock<BasisPoints16, M>,
}
impl RelativeFull {
@@ -28,13 +28,13 @@ impl RelativeFull {
let v2 = Version::new(2);
Ok(Self {
supply_in_profit_rel_to_own: cfg
.import("supply_in_profit_rel_to_own", v1)?,
supply_in_loss_rel_to_own: cfg.import("supply_in_loss_rel_to_own", v1)?,
unrealized_profit_rel_to_mcap: cfg
.import("unrealized_profit_rel_to_mcap", v2)?,
unrealized_loss_rel_to_mcap: cfg
.import("unrealized_loss_rel_to_mcap", v2)?,
supply_in_profit_to_own: cfg
.import("supply_in_profit_to_own", v1)?,
supply_in_loss_to_own: cfg.import("supply_in_loss_to_own", v1)?,
unrealized_profit_to_mcap: cfg
.import("unrealized_profit_to_mcap", v2)?,
unrealized_loss_to_mcap: cfg
.import("unrealized_loss_to_mcap", v2)?,
})
}
@@ -46,14 +46,14 @@ impl RelativeFull {
market_cap: &impl ReadableVec<Height, Dollars>,
exit: &Exit,
) -> Result<()> {
self.supply_in_profit_rel_to_own
self.supply_in_profit_to_own
.compute_binary::<Sats, Sats, RatioSatsBp16>(
max_from,
&supply.in_profit.sats.height,
&supply.total.sats.height,
exit,
)?;
self.supply_in_loss_rel_to_own
self.supply_in_loss_to_own
.compute_binary::<Sats, Sats, RatioSatsBp16>(
max_from,
&supply.in_loss.sats.height,
@@ -61,14 +61,14 @@ impl RelativeFull {
exit,
)?;
self.unrealized_profit_rel_to_mcap
self.unrealized_profit_to_mcap
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
max_from,
&unrealized.profit.base.usd.height,
market_cap,
exit,
)?;
self.unrealized_loss_rel_to_mcap
self.unrealized_loss_to_mcap
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
max_from,
&unrealized.loss.base.usd.height,

View File

@@ -10,23 +10,23 @@ use crate::distribution::metrics::{ImportConfig, SupplyCore};
/// Relative-to-all metrics (not present for the "all" cohort itself).
#[derive(Traversable)]
pub struct RelativeToAll<M: StorageMode = Rw> {
#[traversable(wrap = "supply", rename = "rel_to_circulating")]
pub supply_rel_to_circulating: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "supply/in_profit", rename = "rel_to_circulating")]
pub supply_in_profit_rel_to_circulating: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "supply/in_loss", rename = "rel_to_circulating")]
pub supply_in_loss_rel_to_circulating: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "supply", rename = "to_circulating")]
pub supply_to_circulating: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "supply/in_profit", rename = "to_circulating")]
pub supply_in_profit_to_circulating: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "supply/in_loss", rename = "to_circulating")]
pub supply_in_loss_to_circulating: PercentPerBlock<BasisPoints16, M>,
}
impl RelativeToAll {
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
Ok(Self {
supply_rel_to_circulating: cfg
.import("supply_rel_to_circulating", Version::ONE)?,
supply_in_profit_rel_to_circulating: cfg
.import("supply_in_profit_rel_to_circulating", Version::ONE)?,
supply_in_loss_rel_to_circulating: cfg
.import("supply_in_loss_rel_to_circulating", Version::ONE)?,
supply_to_circulating: cfg
.import("supply_to_circulating", Version::ONE)?,
supply_in_profit_to_circulating: cfg
.import("supply_in_profit_to_circulating", Version::ONE)?,
supply_in_loss_to_circulating: cfg
.import("supply_in_loss_to_circulating", Version::ONE)?,
})
}
@@ -37,21 +37,21 @@ impl RelativeToAll {
all_supply_sats: &impl ReadableVec<Height, Sats>,
exit: &Exit,
) -> Result<()> {
self.supply_rel_to_circulating
self.supply_to_circulating
.compute_binary::<Sats, Sats, RatioSatsBp16>(
max_from,
&supply.total.sats.height,
all_supply_sats,
exit,
)?;
self.supply_in_profit_rel_to_circulating
self.supply_in_profit_to_circulating
.compute_binary::<Sats, Sats, RatioSatsBp16>(
max_from,
&supply.in_profit.sats.height,
all_supply_sats,
exit,
)?;
self.supply_in_loss_rel_to_circulating
self.supply_in_loss_to_circulating
.compute_binary::<Sats, Sats, RatioSatsBp16>(
max_from,
&supply.in_loss.sats.height,

View File

@@ -69,7 +69,7 @@ pub struct Vecs<M: StorageMode = Rw> {
pub utxo_cohorts: UTXOCohorts<M>,
#[traversable(wrap = "cohorts", rename = "address")]
pub address_cohorts: AddressCohorts<M>,
#[traversable(wrap = "cointime")]
#[traversable(wrap = "cointime/activity")]
pub coinblocks_destroyed: PerBlockCumulativeWithSums<StoredF64, StoredF64, M>,
pub addresses: AddressMetricsVecs<M>,

View File

@@ -69,12 +69,12 @@ impl Vecs {
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height,
market_cap,
&transactions.volume.sent_sum.sum._24h.usd.height,
&transactions.volume.transfer_volume.sum._24h.usd.height,
exit,
)?;
// Thermocap Multiple: market_cap / thermo_cap
self.thermocap_multiple
self.thermo_cap_multiple
.bps
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height,
@@ -178,7 +178,7 @@ impl Vecs {
)?;
// Seller Exhaustion Constant: % supply_in_profit × 30d_volatility
self.seller_exhaustion_constant
self.seller_exhaustion
.height
.compute_transform3(
starting_indexes.height,

View File

@@ -24,8 +24,8 @@ impl Vecs {
let nvt = RatioPerBlock::forced_import_raw(&db, "nvt", v, indexes)?;
let gini = PercentPerBlock::forced_import(&db, "gini", v, indexes)?;
let rhodl_ratio = RatioPerBlock::forced_import_raw(&db, "rhodl_ratio", v, indexes)?;
let thermocap_multiple =
RatioPerBlock::forced_import_raw(&db, "thermocap_multiple", v, indexes)?;
let thermo_cap_multiple =
RatioPerBlock::forced_import_raw(&db, "thermo_cap_multiple", v, indexes)?;
let coindays_destroyed_supply_adjusted =
PerBlock::forced_import(&db, "coindays_destroyed_supply_adjusted", v, indexes)?;
let coinyears_destroyed_supply_adjusted =
@@ -35,8 +35,8 @@ impl Vecs {
flow: PerBlock::forced_import(&db, "dormancy_flow", v, indexes)?,
};
let stock_to_flow = PerBlock::forced_import(&db, "stock_to_flow", v, indexes)?;
let seller_exhaustion_constant =
PerBlock::forced_import(&db, "seller_exhaustion_constant", v, indexes)?;
let seller_exhaustion =
PerBlock::forced_import(&db, "seller_exhaustion", v, indexes)?;
let this = Self {
db,
@@ -44,12 +44,12 @@ impl Vecs {
nvt,
gini,
rhodl_ratio,
thermocap_multiple,
thermo_cap_multiple,
coindays_destroyed_supply_adjusted,
coinyears_destroyed_supply_adjusted,
dormancy,
stock_to_flow,
seller_exhaustion_constant,
seller_exhaustion,
};
finalize_db(&this.db, &this)?;
Ok(this)

View File

@@ -18,10 +18,10 @@ pub struct Vecs<M: StorageMode = Rw> {
pub nvt: RatioPerBlock<BasisPoints32, M>,
pub gini: PercentPerBlock<BasisPoints16, M>,
pub rhodl_ratio: RatioPerBlock<BasisPoints32, M>,
pub thermocap_multiple: RatioPerBlock<BasisPoints32, M>,
pub thermo_cap_multiple: RatioPerBlock<BasisPoints32, M>,
pub coindays_destroyed_supply_adjusted: PerBlock<StoredF32, M>,
pub coinyears_destroyed_supply_adjusted: PerBlock<StoredF32, M>,
pub dormancy: DormancyVecs<M>,
pub stock_to_flow: PerBlock<StoredF32, M>,
pub seller_exhaustion_constant: PerBlock<StoredF32, M>,
pub seller_exhaustion: PerBlock<StoredF32, M>,
}

View File

@@ -10,13 +10,13 @@ use crate::internal::{ComputedVecValue, algo::compute_aggregations};
use super::Distribution;
/// Full stats aggregate: distribution + sum + cumulative
/// Full stats aggregate: sum + cumulative + distribution
#[derive(Traversable)]
pub struct DistributionFull<I: VecIndex, T: ComputedVecValue + JsonSchema, M: StorageMode = Rw> {
#[traversable(flatten)]
pub distribution: Distribution<I, T, M>,
pub sum: M::Stored<EagerVec<PcoVec<I, T>>>,
pub cumulative: M::Stored<EagerVec<PcoVec<I, T>>>,
#[traversable(flatten)]
pub distribution: Distribution<I, T, M>,
}
impl<I: VecIndex, T: ComputedVecValue + JsonSchema> DistributionFull<I, T> {

View File

@@ -12,75 +12,14 @@ use crate::{
},
};
/// One window slot: 8 distribution stats, each a AmountPerBlock.
/// Rolling distribution across 4 windows, stat-first naming.
///
/// Tree: `average.sats.height`, `min.sats.height`, etc.
#[derive(Traversable)]
pub struct RollingDistributionSlot<M: StorageMode = Rw> {
#[traversable(flatten)]
pub distribution: DistributionStats<AmountPerBlock<M>>,
}
impl RollingDistributionSlot {
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Ok(Self {
distribution: DistributionStats::try_from_fn(|suffix| {
AmountPerBlock::forced_import(db, &format!("{name}_{suffix}"), version, indexes)
})?,
})
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn compute(
&mut self,
max_from: Height,
starts: &impl ReadableVec<Height, Height>,
sats_source: &impl ReadableVec<Height, Sats>,
cents_source: &impl ReadableVec<Height, Cents>,
exit: &Exit,
sats_cache: &mut Option<(usize, Vec<f64>)>,
cents_cache: &mut Option<(usize, Vec<f64>)>,
) -> Result<()> {
let d = &mut self.distribution;
macro_rules! compute_unit {
($unit:ident, $source:expr, $cache:expr) => {
compute_rolling_distribution_from_starts(
max_from,
starts,
$source,
&mut d.average.$unit.height,
&mut d.min.$unit.height,
&mut d.max.$unit.height,
&mut d.pct10.$unit.height,
&mut d.pct25.$unit.height,
&mut d.median.$unit.height,
&mut d.pct75.$unit.height,
&mut d.pct90.$unit.height,
exit,
$cache,
)?
};
}
compute_unit!(sats, sats_source, sats_cache);
compute_unit!(cents, cents_source, cents_cache);
Ok(())
}
}
/// Rolling distribution across 4 windows, window-first.
///
/// Tree: `_24h.average.sats.height`, `_24h.min.sats.height`, etc.
/// Tree: `average._24h.sats.height`, `max._24h.sats.height`, etc.
/// Series: `{name}_average_24h`, `{name}_max_24h`, etc.
#[derive(Deref, DerefMut, Traversable)]
#[traversable(transparent)]
pub struct RollingDistributionAmountPerBlock<M: StorageMode = Rw>(
pub Windows<RollingDistributionSlot<M>>,
pub DistributionStats<Windows<AmountPerBlock<M>>>,
);
impl RollingDistributionAmountPerBlock {
@@ -90,13 +29,15 @@ impl RollingDistributionAmountPerBlock {
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Ok(Self(Windows::try_from_fn(|suffix| {
RollingDistributionSlot::forced_import(
db,
&format!("{name}_{suffix}"),
version,
indexes,
)
Ok(Self(DistributionStats::try_from_fn(|stat_suffix| {
Windows::try_from_fn(|window_suffix| {
AmountPerBlock::forced_import(
db,
&format!("{name}_{stat_suffix}_{window_suffix}"),
version,
indexes,
)
})
})?))
}
@@ -110,22 +51,38 @@ impl RollingDistributionAmountPerBlock {
) -> Result<()> {
let mut sats_cache = None;
let mut cents_cache = None;
for (slot, starts) in self
.0
.as_mut_array_largest_first()
.into_iter()
.zip(windows.as_array_largest_first())
{
slot.compute(
max_from,
*starts,
sats_source,
cents_source,
exit,
&mut sats_cache,
&mut cents_cache,
)?;
macro_rules! compute_window {
($w:ident, $starts:expr) => {{
macro_rules! compute_unit {
($unit:ident, $source:expr, $cache:expr) => {
compute_rolling_distribution_from_starts(
max_from,
$starts,
$source,
&mut self.0.average.$w.$unit.height,
&mut self.0.min.$w.$unit.height,
&mut self.0.max.$w.$unit.height,
&mut self.0.pct10.$w.$unit.height,
&mut self.0.pct25.$w.$unit.height,
&mut self.0.median.$w.$unit.height,
&mut self.0.pct75.$w.$unit.height,
&mut self.0.pct90.$w.$unit.height,
exit,
$cache,
)?
};
}
compute_unit!(sats, sats_source, &mut sats_cache);
compute_unit!(cents, cents_source, &mut cents_cache);
}};
}
// Largest window first: its cache covers all smaller windows.
compute_window!(_1y, windows._1y);
compute_window!(_1m, windows._1m);
compute_window!(_1w, windows._1w);
compute_window!(_24h, windows._24h);
Ok(())
}
}

View File

@@ -19,7 +19,7 @@ pub struct PerBlockRollingAverage<T, M: StorageMode = Rw>
where
T: NumericValue + JsonSchema,
{
pub height: M::Stored<EagerVec<PcoVec<Height, T>>>,
pub base: M::Stored<EagerVec<PcoVec<Height, T>>>,
#[traversable(hidden)]
pub cumulative: M::Stored<EagerVec<PcoVec<Height, f64>>>,
#[traversable(flatten)]
@@ -37,7 +37,7 @@ where
indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts,
) -> Result<Self> {
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, version)?;
let base: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, version)?;
let cumulative: EagerVec<PcoVec<Height, f64>> =
EagerVec::forced_import(db, &format!("{name}_cumulative"), version)?;
let average = LazyRollingAvgsFromHeight::new(
@@ -49,7 +49,7 @@ where
);
Ok(Self {
height,
base,
cumulative,
average,
})
@@ -62,14 +62,14 @@ where
exit: &Exit,
compute_height: impl FnOnce(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
) -> Result<()> {
compute_height(&mut self.height)?;
compute_height(&mut self.base)?;
self.compute_rest(max_from, exit)
}
/// Compute cumulative from already-populated height data. Rolling averages are lazy.
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
self.cumulative
.compute_cumulative(max_from, &self.height, exit)?;
.compute_cumulative(max_from, &self.base, exit)?;
Ok(())
}
}

View File

@@ -21,8 +21,7 @@ where
{
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub inner: PerBlock<S, M>,
pub base: PerBlock<S, M>,
pub delta: LazyRollingDeltasFromHeight<S, C, B>,
}
@@ -40,16 +39,16 @@ where
indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts,
) -> Result<Self> {
let inner = PerBlock::forced_import(db, name, version, indexes)?;
let base = PerBlock::forced_import(db, name, version, indexes)?;
let delta = LazyRollingDeltasFromHeight::new(
&format!("{name}_delta"),
version + delta_version_offset,
&inner.height,
&base.height,
cached_starts,
indexes,
);
Ok(Self { inner, delta })
Ok(Self { base, delta })
}
}

View File

@@ -37,14 +37,14 @@ impl<B: BpsType> PercentPerBlockRollingAverage<B> {
let ratio = LazyPerBlock::from_height_source::<B::ToRatio>(
&format!("{name}_ratio"),
version,
bps.height.read_only_boxed_clone(),
bps.base.read_only_boxed_clone(),
indexes,
);
let percent = LazyPerBlock::from_height_source::<B::ToPercent>(
name,
version,
bps.height.read_only_boxed_clone(),
bps.base.read_only_boxed_clone(),
indexes,
);

View File

@@ -120,7 +120,7 @@ impl Vecs {
}
// Lump sum by period - stack
let lookback_dca = lookback.price_lookback.as_dca_period();
let lookback_dca = lookback.price_past.as_dca_period();
for (stack, lookback_price, days) in
self.period.lump_sum_stack.zip_mut_with_days(&lookback_dca)
{

View File

@@ -15,9 +15,9 @@ impl Vecs {
) -> Result<()> {
let price = &prices.spot.cents.height;
for (price_lookback, days) in self.price_lookback.iter_mut_with_days() {
for (price_past, days) in self.price_past.iter_mut_with_days() {
let window_starts = blocks.lookback.start_vec(days as usize);
price_lookback.cents.height.compute_lookback(
price_past.cents.height.compute_lookback(
starting_indexes.height,
window_starts,
price,

View File

@@ -11,10 +11,10 @@ impl Vecs {
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let price_lookback = ByLookbackPeriod::try_new(|name, _days| {
Price::forced_import(db, &format!("price_lookback_{name}"), version, indexes)
let price_past = ByLookbackPeriod::try_new(|name, _days| {
Price::forced_import(db, &format!("price_past_{name}"), version, indexes)
})?;
Ok(Self { price_lookback })
Ok(Self { price_past })
}
}

View File

@@ -7,5 +7,5 @@ use crate::internal::{PerBlock, Price};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
#[traversable(flatten)]
pub price_lookback: ByLookbackPeriod<Price<PerBlock<Cents, M>>>,
pub price_past: ByLookbackPeriod<Price<PerBlock<Cents, M>>>,
}

View File

@@ -18,7 +18,7 @@ impl Vecs {
for ((returns, _), (lookback_price, _)) in self
.periods
.iter_mut_with_days()
.zip(lookback.price_lookback.iter_with_days())
.zip(lookback.price_past.iter_with_days())
{
returns.compute_binary::<Dollars, Dollars, RatioDiffDollarsBps32>(
starting_indexes.height,

View File

@@ -57,19 +57,13 @@ impl Vecs {
&returns.periods._1m.ratio.height,
&returns.periods._1y.ratio.height,
];
for ((rsi_chain, ret), &m) in self
.rsi
.as_mut_array()
.into_iter()
.zip(return_sources)
.zip(&TF_MULTIPLIERS)
{
for (rsi_chain, ret) in self.rsi.as_mut_array().into_iter().zip(return_sources) {
rsi::compute(
rsi_chain,
blocks,
ret,
14 * m,
3 * m,
14,
3,
starting_indexes,
exit,
)?;

View File

@@ -106,7 +106,8 @@ impl Vecs {
) -> Result<Self> {
let v = version + VERSION;
let rsi = Windows::try_from_fn(|tf| RsiChain::forced_import(db, tf, v, indexes))?;
let rsi =
Windows::try_from_fn(|tf| RsiChain::forced_import(db, tf, v + Version::ONE, indexes))?;
let macd = Windows::try_from_fn(|tf| MacdChain::forced_import(db, tf, v, indexes))?;
let stoch_k = PercentPerBlock::forced_import(db, "stoch_k", v, indexes)?;

View File

@@ -23,7 +23,7 @@ impl Vecs {
self.rate.base.height.compute_transform2(
starting_indexes.height,
&count_vecs.total.sum._24h.height,
&difficulty_vecs.as_hash.height,
&difficulty_vecs.hashrate.height,
|(i, block_count_sum, difficulty_as_hash, ..)| {
(
i,

View File

@@ -147,7 +147,7 @@ impl Vecs {
exit,
)?;
self.fee_ratio_multiple
self.fee_to_subsidy_ratio
.compute_binary::<Dollars, Dollars, RatioDollarsBp32, _, _>(
starting_indexes.height,
self.coinbase.sum.as_array().map(|w| &w.usd.height),

View File

@@ -55,9 +55,9 @@ impl Vecs {
)?,
subsidy_dominance_rolling,
subsidy_sma_1y: FiatPerBlock::forced_import(db, "subsidy_sma_1y", version, indexes)?,
fee_ratio_multiple: RatioRollingWindows::forced_import(
fee_to_subsidy_ratio: RatioRollingWindows::forced_import(
db,
"fee_ratio_multiple",
"fee_to_subsidy_ratio",
version,
indexes,
)?,

View File

@@ -24,6 +24,6 @@ pub struct Vecs<M: StorageMode = Rw> {
pub subsidy_dominance_rolling: LazyPercentRollingWindows<BasisPoints16>,
#[traversable(wrap = "subsidy", rename = "sma_1y")]
pub subsidy_sma_1y: FiatPerBlock<Cents, M>,
#[traversable(wrap = "fees", rename = "ratio_multiple")]
pub fee_ratio_multiple: RatioRollingWindows<BasisPoints32, M>,
#[traversable(wrap = "fees", rename = "to_subsidy_ratio")]
pub fee_to_subsidy_ratio: RatioRollingWindows<BasisPoints32, M>,
}

View File

@@ -61,14 +61,14 @@ impl Vecs {
pub(crate) fn compute(
&mut self,
starting_indexes: &Indexes,
height_to_pool: &impl ReadableVec<Height, PoolSlug>,
pool: &impl ReadableVec<Height, PoolSlug>,
blocks: &blocks::Vecs,
prices: &prices::Vecs,
mining: &mining::Vecs,
exit: &Exit,
) -> Result<()> {
self.base
.compute(starting_indexes, height_to_pool, blocks, exit)?;
.compute(starting_indexes, pool, blocks, exit)?;
for (dom, (mined, total)) in self.dominance_rolling.as_mut_array().into_iter().zip(
self.base

View File

@@ -52,7 +52,7 @@ impl Vecs {
pub(crate) fn compute(
&mut self,
starting_indexes: &Indexes,
height_to_pool: &impl ReadableVec<Height, PoolSlug>,
pool: &impl ReadableVec<Height, PoolSlug>,
blocks: &blocks::Vecs,
exit: &Exit,
) -> Result<()> {
@@ -60,7 +60,7 @@ impl Vecs {
.compute(starting_indexes.height, exit, |vec| {
vec.compute_transform(
starting_indexes.height,
height_to_pool,
pool,
|(h, id, ..)| {
(
h,

View File

@@ -29,7 +29,7 @@ pub struct Vecs<M: StorageMode = Rw> {
db: Database,
pools: &'static Pools,
pub height_to_pool: M::Stored<BytesVec<Height, PoolSlug>>,
pub pool: M::Stored<BytesVec<Height, PoolSlug>>,
pub major: BTreeMap<PoolSlug, major::Vecs<M>>,
pub minor: BTreeMap<PoolSlug, minor::Vecs<M>>,
}
@@ -64,7 +64,7 @@ impl Vecs {
}
let this = Self {
height_to_pool: BytesVec::forced_import(&db, "pool", version)?,
pool: BytesVec::forced_import(&db, "pool", version)?,
major: major_map,
minor: minor_map,
pools,
@@ -86,12 +86,12 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.compute_height_to_pool(indexer, indexes, starting_indexes, exit)?;
self.compute_pool(indexer, indexes, starting_indexes, exit)?;
self.major.par_iter_mut().try_for_each(|(_, vecs)| {
vecs.compute(
starting_indexes,
&self.height_to_pool,
&self.pool,
blocks,
prices,
mining,
@@ -100,7 +100,7 @@ impl Vecs {
})?;
self.minor.par_iter_mut().try_for_each(|(_, vecs)| {
vecs.compute(starting_indexes, &self.height_to_pool, blocks, exit)
vecs.compute(starting_indexes, &self.pool, blocks, exit)
})?;
let _lock = exit.lock();
@@ -108,14 +108,14 @@ impl Vecs {
Ok(())
}
fn compute_height_to_pool(
fn compute_pool(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.height_to_pool
self.pool
.validate_computed_version_or_reset(indexer.stores.height_to_coinbase_tag.version())?;
let first_txout_index = indexer.vecs.transactions.first_txout_index.reader();
@@ -135,7 +135,7 @@ impl Vecs {
let min = starting_indexes
.height
.to_usize()
.min(self.height_to_pool.len());
.min(self.pool.len());
// Cursors avoid per-height PcoVec page decompression.
// Heights are sequential, tx_index values derived from them are monotonically
@@ -144,7 +144,7 @@ impl Vecs {
first_tx_index_cursor.advance(min);
let mut output_count_cursor = indexes.tx_index.output_count.cursor();
self.height_to_pool.truncate_if_needed_at(min)?;
self.pool.truncate_if_needed_at(min)?;
indexer
.stores
@@ -181,12 +181,12 @@ impl Vecs {
.or_else(|| self.pools.find_from_coinbase_tag(&coinbase_tag))
.unwrap_or(unknown);
self.height_to_pool.push(pool.slug);
self.pool.push(pool.slug);
Ok(())
})?;
let _lock = exit.lock();
self.height_to_pool.write()?;
self.pool.write()?;
Ok(())
}
}

View File

@@ -17,7 +17,7 @@ impl Vecs {
let op_return_height = &scripts.value.op_return.base.sats.height;
let unclaimed_height = &mining.rewards.unclaimed.base.sats.height;
self.unspendable.compute(
self.total.compute(
starting_indexes.height,
prices,
exit,

View File

@@ -13,7 +13,7 @@ impl Vecs {
cached_starts: &CachedWindowStarts,
) -> Result<Self> {
Ok(Self {
unspendable: AmountPerBlockCumulativeWithSums::forced_import(
total: AmountPerBlockCumulativeWithSums::forced_import(
db,
"unspendable_supply",
version,

View File

@@ -4,6 +4,7 @@ use vecdb::{Rw, StorageMode};
use crate::internal::AmountPerBlockCumulativeWithSums;
#[derive(Traversable)]
#[traversable(transparent)]
pub struct Vecs<M: StorageMode = Rw> {
pub unspendable: AmountPerBlockCumulativeWithSums<M>,
pub total: AmountPerBlockCumulativeWithSums<M>,
}

View File

@@ -64,7 +64,7 @@ impl Vecs {
)?;
let hodled_or_lost =
LazyAmountPerBlock::identity("hodled_or_lost_coins", &cointime.supply.vaulted, version);
LazyAmountPerBlock::identity("hodled_or_lost_supply", &cointime.supply.vaulted, version);
let this = Self {
db,

View File

@@ -21,7 +21,7 @@ impl Vecs {
self.native.height.compute_rolling_ratio(
starting_indexes.height,
&blocks.lookback._1y,
&transactions.volume.sent_sum.base.sats.height,
&transactions.volume.transfer_volume.base.sats.height,
&circulating_supply.sats.height,
exit,
)?;
@@ -30,7 +30,7 @@ impl Vecs {
self.fiat.height.compute_rolling_ratio(
starting_indexes.height,
&blocks.lookback._1y,
&transactions.volume.sent_sum.base.usd.height,
&transactions.volume.transfer_volume.base.usd.height,
&circulating_supply.usd.height,
exit,
)?;

View File

@@ -25,7 +25,7 @@ impl Vecs {
// sent_sum and received_sum are independent — parallelize
let (r1, r2) = rayon::join(
|| {
self.sent_sum.compute(
self.transfer_volume.compute(
starting_indexes.height,
prices,
exit,
@@ -42,7 +42,7 @@ impl Vecs {
)
},
|| {
self.received_sum.compute(
self.output_volume.compute(
starting_indexes.height,
prices,
exit,
@@ -66,7 +66,7 @@ impl Vecs {
.compute_binary::<_, Timestamp, PerSec>(
starting_indexes.height,
&count_vecs.total.base.height,
&blocks.interval.height,
&blocks.interval.base,
exit,
)?;
self.inputs_per_sec
@@ -74,7 +74,7 @@ impl Vecs {
.compute_binary::<_, Timestamp, PerSec>(
starting_indexes.height,
&inputs_count.full.sum,
&blocks.interval.height,
&blocks.interval.base,
exit,
)?;
self.outputs_per_sec
@@ -82,7 +82,7 @@ impl Vecs {
.compute_binary::<_, Timestamp, PerSec>(
starting_indexes.height,
&outputs_count.total.full.sum,
&blocks.interval.height,
&blocks.interval.base,
exit,
)?;

View File

@@ -17,16 +17,16 @@ impl Vecs {
) -> Result<Self> {
let v2 = Version::TWO;
Ok(Self {
sent_sum: AmountPerBlockCumulativeWithSums::forced_import(
transfer_volume: AmountPerBlockCumulativeWithSums::forced_import(
db,
"sent_sum",
"exact_transfer_volume",
version,
indexes,
cached_starts,
)?,
received_sum: AmountPerBlockCumulativeWithSums::forced_import(
output_volume: AmountPerBlockCumulativeWithSums::forced_import(
db,
"received_sum",
"output_volume",
version,
indexes,
cached_starts,

View File

@@ -6,8 +6,8 @@ use crate::internal::{AmountPerBlockCumulativeWithSums, PerBlock};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub sent_sum: AmountPerBlockCumulativeWithSums<M>,
pub received_sum: AmountPerBlockCumulativeWithSums<M>,
pub transfer_volume: AmountPerBlockCumulativeWithSums<M>,
pub output_volume: AmountPerBlockCumulativeWithSums<M>,
pub tx_per_sec: PerBlock<StoredF32, M>,
pub outputs_per_sec: PerBlock<StoredF32, M>,
pub inputs_per_sec: PerBlock<StoredF32, M>,