mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snapshot
This commit is contained in:
@@ -542,9 +542,9 @@ impl UTXOCohorts<Rw> {
|
||||
.metrics
|
||||
.realized
|
||||
.minimal
|
||||
.sopr
|
||||
.value_created
|
||||
.transfer_volume
|
||||
.base
|
||||
.cents
|
||||
.height
|
||||
.read_only_clone();
|
||||
let under_1h_value_destroyed = self
|
||||
@@ -552,7 +552,6 @@ impl UTXOCohorts<Rw> {
|
||||
.under_1h
|
||||
.metrics
|
||||
.realized
|
||||
.minimal
|
||||
.sopr
|
||||
.value_destroyed
|
||||
.base
|
||||
|
||||
@@ -128,8 +128,8 @@ impl AllCohortMetrics {
|
||||
|
||||
self.asopr.compute_rest_part2(
|
||||
starting_indexes,
|
||||
&self.realized.minimal.sopr.value_created.base.height,
|
||||
&self.realized.minimal.sopr.value_destroyed.base.height,
|
||||
&self.realized.minimal.transfer_volume.base.cents.height,
|
||||
&self.realized.core.sopr.value_destroyed.base.height,
|
||||
under_1h_value_created,
|
||||
under_1h_value_destroyed,
|
||||
exit,
|
||||
|
||||
@@ -114,7 +114,7 @@ impl CoreCohortMetrics {
|
||||
.compute_sent_profitability(prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
|
||||
self.unrealized.compute_rest(starting_indexes, exit)?;
|
||||
|
||||
|
||||
@@ -80,8 +80,8 @@ impl ExtendedAdjustedCohortMetrics {
|
||||
|
||||
self.asopr.compute_rest_part2(
|
||||
starting_indexes,
|
||||
&self.inner.realized.minimal.sopr.value_created.base.height,
|
||||
&self.inner.realized.minimal.sopr.value_destroyed.base.height,
|
||||
&self.inner.realized.minimal.transfer_volume.base.cents.height,
|
||||
&self.inner.realized.core.sopr.value_destroyed.base.height,
|
||||
under_1h_value_created,
|
||||
under_1h_value_destroyed,
|
||||
exit,
|
||||
|
||||
@@ -90,7 +90,7 @@ impl MinimalCohortMetrics {
|
||||
) -> Result<()> {
|
||||
self.supply.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ impl TypeCohortMetrics {
|
||||
) -> Result<()> {
|
||||
self.supply.compute(prices, starting_indexes.height, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,8 @@ use crate::{
|
||||
indexes,
|
||||
internal::{
|
||||
AmountPerBlock, AmountPerBlockCumulative, AmountPerBlockCumulativeWithSums,
|
||||
CachedWindowStarts, CentsType, PerBlock,
|
||||
PerBlockCumulative, PerBlockCumulativeWithSums,
|
||||
FiatPerBlock, FiatPerBlockCumulativeWithSums, NumericValue,
|
||||
PercentPerBlock, PercentRollingWindows, Price,
|
||||
CachedWindowStarts, CentsType, FiatPerBlock, FiatPerBlockCumulativeWithSums, NumericValue,
|
||||
PerBlock, PerBlockCumulativeWithSums, PercentPerBlock, PercentRollingWindows, Price,
|
||||
PriceWithRatioExtendedPerBlock, PriceWithRatioPerBlock, RatioPerBlock,
|
||||
RollingWindow24hPerBlock, RollingWindows, RollingWindowsFrom1w,
|
||||
},
|
||||
@@ -56,11 +54,6 @@ impl<T: NumericValue + JsonSchema> ConfigImport for PerBlock<T> {
|
||||
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
|
||||
}
|
||||
}
|
||||
impl<T: NumericValue + JsonSchema> ConfigImport for PerBlockCumulative<T> {
|
||||
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
|
||||
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
|
||||
}
|
||||
}
|
||||
impl<T, C> ConfigImport for PerBlockCumulativeWithSums<T, C>
|
||||
where
|
||||
T: NumericValue + JsonSchema + Into<C>,
|
||||
|
||||
@@ -228,7 +228,7 @@ pub trait CohortMetricsBase:
|
||||
.compute_sent_profitability(prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized_mut()
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
|
||||
self.unrealized_mut()
|
||||
.compute_rest(prices, starting_indexes, exit)?;
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
#[derive(Traversable)]
|
||||
pub struct AdjustedSopr<M: StorageMode = Rw> {
|
||||
pub ratio: RollingWindows<StoredF64, M>,
|
||||
pub value_created: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub transfer_volume: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub value_destroyed: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ impl AdjustedSopr {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
ratio: cfg.import("asopr", Version::ONE)?,
|
||||
value_created: cfg.import("adj_value_created", Version::ONE)?,
|
||||
transfer_volume: cfg.import("adj_value_created", Version::ONE)?,
|
||||
value_destroyed: cfg.import("adj_value_destroyed", Version::ONE)?,
|
||||
})
|
||||
}
|
||||
@@ -28,17 +28,16 @@ impl AdjustedSopr {
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
base_value_created: &impl ReadableVec<Height, Cents>,
|
||||
base_transfer_volume: &impl ReadableVec<Height, Cents>,
|
||||
base_value_destroyed: &impl ReadableVec<Height, Cents>,
|
||||
under_1h_value_created: &impl ReadableVec<Height, Cents>,
|
||||
under_1h_transfer_volume: &impl ReadableVec<Height, Cents>,
|
||||
under_1h_value_destroyed: &impl ReadableVec<Height, Cents>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute value_created = base.value_created - under_1h.value_created
|
||||
self.value_created.base.height.compute_subtract(
|
||||
self.transfer_volume.base.height.compute_subtract(
|
||||
starting_indexes.height,
|
||||
base_value_created,
|
||||
under_1h_value_created,
|
||||
base_transfer_volume,
|
||||
under_1h_transfer_volume,
|
||||
exit,
|
||||
)?;
|
||||
self.value_destroyed.base.height.compute_subtract(
|
||||
@@ -48,23 +47,21 @@ impl AdjustedSopr {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Cumulatives (rolling sums are lazy)
|
||||
self.value_created
|
||||
self.transfer_volume
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.value_destroyed
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
// SOPR ratios from lazy rolling sums
|
||||
for ((sopr, vc), vd) in self
|
||||
for ((sopr, tv), vd) in self
|
||||
.ratio
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.value_created.sum.as_array())
|
||||
.zip(self.transfer_volume.sum.as_array())
|
||||
.zip(self.value_destroyed.sum.as_array())
|
||||
{
|
||||
sopr.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&vc.height,
|
||||
&tv.height,
|
||||
&vd.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -3,14 +3,14 @@ use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, StoredF64, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
AnyStoredVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode,
|
||||
AnyStoredVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
internal::{
|
||||
FiatPerBlockCumulativeWithSumsAndDeltas, LazyPerBlock, NegCentsUnsignedToDollars,
|
||||
RatioCents64, RollingWindow24hPerBlock, Windows,
|
||||
PerBlockCumulativeWithSums, RatioCents64, RollingWindow24hPerBlock, Windows,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -28,6 +28,7 @@ pub struct NegRealizedLoss {
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedSoprCore<M: StorageMode = Rw> {
|
||||
pub value_destroyed: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub ratio: RollingWindow24hPerBlock<StoredF64, M>,
|
||||
}
|
||||
|
||||
@@ -80,11 +81,20 @@ impl RealizedCore {
|
||||
cfg.cached_starts,
|
||||
)?;
|
||||
|
||||
let value_destroyed = PerBlockCumulativeWithSums::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("value_destroyed"),
|
||||
cfg.version + v1,
|
||||
cfg.indexes,
|
||||
cfg.cached_starts,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
minimal,
|
||||
neg_loss,
|
||||
net_pnl,
|
||||
sopr: RealizedSoprCore {
|
||||
value_destroyed,
|
||||
ratio: cfg.import("sopr", v1)?,
|
||||
},
|
||||
})
|
||||
@@ -97,10 +107,13 @@ impl RealizedCore {
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
|
||||
self.minimal.push_state(state);
|
||||
self.sopr.value_destroyed.base.height.push(state.realized.value_destroyed());
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
self.minimal.collect_vecs_mut()
|
||||
let mut vecs = self.minimal.collect_vecs_mut();
|
||||
vecs.push(&mut self.sopr.value_destroyed.base.height);
|
||||
vecs
|
||||
}
|
||||
|
||||
pub(crate) fn compute_from_stateful(
|
||||
@@ -113,16 +126,22 @@ impl RealizedCore {
|
||||
self.minimal
|
||||
.compute_from_stateful(starting_indexes, &minimal_refs, exit)?;
|
||||
|
||||
sum_others!(self, starting_indexes, others, exit; sopr.value_destroyed.base.height);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.minimal
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
|
||||
self.sopr
|
||||
.value_destroyed
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
self.net_pnl.base.cents.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
@@ -158,8 +177,8 @@ impl RealizedCore {
|
||||
._24h
|
||||
.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&self.minimal.sopr.value_created.sum._24h.height,
|
||||
&self.minimal.sopr.value_destroyed.sum._24h.height,
|
||||
&self.minimal.transfer_volume.sum._24h.cents.height,
|
||||
&self.sopr.value_destroyed.sum._24h.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use brk_types::{
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, BytesVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode,
|
||||
AnyStoredVec, AnyVec, BytesVec, Exit, ReadableVec, Rw, StorageMode,
|
||||
WritableVec,
|
||||
};
|
||||
|
||||
@@ -14,9 +14,8 @@ use crate::{
|
||||
blocks,
|
||||
distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState},
|
||||
internal::{
|
||||
CentsUnsignedToDollars,
|
||||
PerBlockCumulativeWithSums, FiatPerBlockCumulativeWithSums,
|
||||
LazyPerBlock, PercentPerBlock, PercentRollingWindows,
|
||||
FiatPerBlockCumulativeWithSums,
|
||||
PercentPerBlock, PercentRollingWindows,
|
||||
PriceWithRatioExtendedPerBlock, RatioCents64, RatioCentsBp32,
|
||||
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDollarsBp32,
|
||||
RatioPerBlockPercentiles, RatioPerBlockStdDevBands, RatioSma, RollingWindows,
|
||||
@@ -30,19 +29,13 @@ use crate::distribution::metrics::ImportConfig;
|
||||
use super::RealizedCore;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedProfit<M: StorageMode = Rw> {
|
||||
pub struct RealizedProfitFull<M: StorageMode = Rw> {
|
||||
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>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedLoss<M: StorageMode = Rw> {
|
||||
pub struct RealizedLossFull<M: StorageMode = Rw> {
|
||||
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>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
@@ -81,8 +74,8 @@ pub struct RealizedFull<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub core: RealizedCore<M>,
|
||||
|
||||
pub profit: RealizedProfit<M>,
|
||||
pub loss: RealizedLoss<M>,
|
||||
pub profit: RealizedProfitFull<M>,
|
||||
pub loss: RealizedLossFull<M>,
|
||||
pub gross_pnl: FiatPerBlockCumulativeWithSums<Cents, M>,
|
||||
pub sell_side_risk_ratio: PercentRollingWindows<BasisPoints32, M>,
|
||||
pub net_pnl: RealizedNetPnl<M>,
|
||||
@@ -112,36 +105,11 @@ impl RealizedFull {
|
||||
|
||||
let core = RealizedCore::forced_import(cfg)?;
|
||||
|
||||
// Profit
|
||||
let profit_value_destroyed: PerBlockCumulativeWithSums<Cents, Cents> =
|
||||
cfg.import("profit_value_destroyed", v1)?;
|
||||
let profit_flow = LazyPerBlock::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("distribution_flow"),
|
||||
cfg.version,
|
||||
profit_value_destroyed.base.height.read_only_boxed_clone(),
|
||||
&profit_value_destroyed.base,
|
||||
);
|
||||
let profit = RealizedProfit {
|
||||
let profit = RealizedProfitFull {
|
||||
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,
|
||||
};
|
||||
|
||||
// Loss
|
||||
let loss_value_destroyed: PerBlockCumulativeWithSums<Cents, Cents> =
|
||||
cfg.import("loss_value_destroyed", v1)?;
|
||||
let capitulation_flow = LazyPerBlock::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("capitulation_flow"),
|
||||
cfg.version,
|
||||
loss_value_destroyed.base.height.read_only_boxed_clone(),
|
||||
&loss_value_destroyed.base,
|
||||
);
|
||||
let loss = RealizedLoss {
|
||||
let loss = RealizedLossFull {
|
||||
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,
|
||||
};
|
||||
|
||||
// Gross PnL
|
||||
@@ -216,15 +184,7 @@ impl RealizedFull {
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
self.profit
|
||||
.value_created
|
||||
.base
|
||||
.height
|
||||
.len()
|
||||
.min(self.profit.value_destroyed.base.height.len())
|
||||
.min(self.loss.value_created.base.height.len())
|
||||
.min(self.loss.value_destroyed.base.height.len())
|
||||
.min(self.investor.price.cents.height.len())
|
||||
self.investor.price.cents.height.len()
|
||||
.min(self.cap_raw.len())
|
||||
.min(self.investor.cap_raw.len())
|
||||
.min(self.peak_regret.value.base.cents.height.len())
|
||||
@@ -236,26 +196,6 @@ impl RealizedFull {
|
||||
state: &CohortState<RealizedState, CostBasisData<WithCapital>>,
|
||||
) {
|
||||
self.core.push_state(state);
|
||||
self.profit
|
||||
.value_created
|
||||
.base
|
||||
.height
|
||||
.push(state.realized.profit_value_created());
|
||||
self.profit
|
||||
.value_destroyed
|
||||
.base
|
||||
.height
|
||||
.push(state.realized.profit_value_destroyed());
|
||||
self.loss
|
||||
.value_created
|
||||
.base
|
||||
.height
|
||||
.push(state.realized.loss_value_created());
|
||||
self.loss
|
||||
.value_destroyed
|
||||
.base
|
||||
.height
|
||||
.push(state.realized.loss_value_destroyed());
|
||||
self.investor
|
||||
.price
|
||||
.cents
|
||||
@@ -276,10 +216,6 @@ impl RealizedFull {
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.core.collect_vecs_mut();
|
||||
vecs.push(&mut self.profit.value_created.base.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.profit.value_destroyed.base.height);
|
||||
vecs.push(&mut self.loss.value_created.base.height);
|
||||
vecs.push(&mut self.loss.value_destroyed.base.height);
|
||||
vecs.push(&mut self.investor.price.cents.height);
|
||||
vecs.push(&mut self.cap_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.investor.cap_raw as &mut dyn AnyStoredVec);
|
||||
@@ -304,26 +240,6 @@ impl RealizedFull {
|
||||
&mut self,
|
||||
accum: &RealizedFullAccum,
|
||||
) {
|
||||
self.profit
|
||||
.value_created
|
||||
.base
|
||||
.height
|
||||
.push(accum.profit_value_created());
|
||||
self.profit
|
||||
.value_destroyed
|
||||
.base
|
||||
.height
|
||||
.push(accum.profit_value_destroyed());
|
||||
self.loss
|
||||
.value_created
|
||||
.base
|
||||
.height
|
||||
.push(accum.loss_value_created());
|
||||
self.loss
|
||||
.value_destroyed
|
||||
.base
|
||||
.height
|
||||
.push(accum.loss_value_destroyed());
|
||||
self.cap_raw
|
||||
.push(accum.cap_raw);
|
||||
self.investor
|
||||
@@ -354,11 +270,12 @@ impl RealizedFull {
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
|
||||
self.peak_regret
|
||||
.value
|
||||
@@ -388,12 +305,12 @@ impl RealizedFull {
|
||||
.ratio_extended
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.core.minimal.sopr.value_created.sum.as_array()[1..].iter())
|
||||
.zip(self.core.minimal.sopr.value_destroyed.sum.as_array()[1..].iter())
|
||||
.zip(self.core.minimal.transfer_volume.sum.0.as_array()[1..].iter())
|
||||
.zip(self.core.sopr.value_destroyed.sum.as_array()[1..].iter())
|
||||
{
|
||||
sopr.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&vc.height,
|
||||
&vc.cents.height,
|
||||
&vd.height,
|
||||
exit,
|
||||
)?;
|
||||
@@ -425,20 +342,6 @@ impl RealizedFull {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Profit/loss value created/destroyed cumulatives (rolling sums are lazy)
|
||||
self.profit
|
||||
.value_created
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.profit
|
||||
.value_destroyed
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.loss
|
||||
.value_created
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.loss
|
||||
.value_destroyed
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
// Gross PnL
|
||||
self.gross_pnl.base.cents.height.compute_add(
|
||||
starting_indexes.height,
|
||||
@@ -554,10 +457,6 @@ impl RealizedFull {
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RealizedFullAccum {
|
||||
profit_value_created: CentsSats,
|
||||
profit_value_destroyed: CentsSats,
|
||||
loss_value_created: CentsSats,
|
||||
loss_value_destroyed: CentsSats,
|
||||
pub(crate) cap_raw: CentsSats,
|
||||
pub(crate) investor_cap_raw: CentsSquaredSats,
|
||||
peak_regret: CentsSats,
|
||||
@@ -565,31 +464,11 @@ pub struct RealizedFullAccum {
|
||||
|
||||
impl RealizedFullAccum {
|
||||
pub(crate) fn add(&mut self, state: &RealizedState) {
|
||||
self.profit_value_created += CentsSats::new(state.profit_value_created_raw());
|
||||
self.profit_value_destroyed += CentsSats::new(state.profit_value_destroyed_raw());
|
||||
self.loss_value_created += CentsSats::new(state.loss_value_created_raw());
|
||||
self.loss_value_destroyed += CentsSats::new(state.loss_value_destroyed_raw());
|
||||
self.cap_raw += state.cap_raw();
|
||||
self.investor_cap_raw += state.investor_cap_raw();
|
||||
self.peak_regret += CentsSats::new(state.peak_regret_raw());
|
||||
}
|
||||
|
||||
pub(crate) fn profit_value_created(&self) -> Cents {
|
||||
self.profit_value_created.to_cents()
|
||||
}
|
||||
|
||||
pub(crate) fn profit_value_destroyed(&self) -> Cents {
|
||||
self.profit_value_destroyed.to_cents()
|
||||
}
|
||||
|
||||
pub(crate) fn loss_value_created(&self) -> Cents {
|
||||
self.loss_value_created.to_cents()
|
||||
}
|
||||
|
||||
pub(crate) fn loss_value_destroyed(&self) -> Cents {
|
||||
self.loss_value_destroyed.to_cents()
|
||||
}
|
||||
|
||||
pub(crate) fn peak_regret(&self) -> Cents {
|
||||
self.peak_regret.to_cents()
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use vecdb::{
|
||||
use crate::{
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
internal::{
|
||||
PerBlockCumulativeWithSums, FiatPerBlockCumulativeWithSums,
|
||||
AmountPerBlockCumulativeWithSums, FiatPerBlockCumulativeWithSums,
|
||||
FiatPerBlockWithDeltas, Identity, LazyPerBlock, PriceWithRatioPerBlock,
|
||||
},
|
||||
prices,
|
||||
@@ -19,12 +19,6 @@ use crate::{
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedSoprMinimal<M: StorageMode = Rw> {
|
||||
pub value_created: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub value_destroyed: PerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedMinimal<M: StorageMode = Rw> {
|
||||
pub cap: FiatPerBlockWithDeltas<Cents, CentsSigned, BasisPointsSigned32, M>,
|
||||
@@ -33,7 +27,7 @@ pub struct RealizedMinimal<M: StorageMode = Rw> {
|
||||
pub price: PriceWithRatioPerBlock<M>,
|
||||
pub mvrv: LazyPerBlock<StoredF32>,
|
||||
|
||||
pub sopr: RealizedSoprMinimal<M>,
|
||||
pub transfer_volume: AmountPerBlockCumulativeWithSums<M>,
|
||||
}
|
||||
|
||||
impl RealizedMinimal {
|
||||
@@ -56,16 +50,21 @@ impl RealizedMinimal {
|
||||
&price.ratio,
|
||||
);
|
||||
|
||||
let transfer_volume = AmountPerBlockCumulativeWithSums::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("transfer_volume"),
|
||||
cfg.version,
|
||||
cfg.indexes,
|
||||
cfg.cached_starts,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
cap,
|
||||
profit: cfg.import("realized_profit", v1)?,
|
||||
loss: cfg.import("realized_loss", v1)?,
|
||||
price,
|
||||
mvrv,
|
||||
sopr: RealizedSoprMinimal {
|
||||
value_created: cfg.import("value_created", v1)?,
|
||||
value_destroyed: cfg.import("value_destroyed", v1)?,
|
||||
},
|
||||
transfer_volume,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -76,8 +75,7 @@ impl RealizedMinimal {
|
||||
.len()
|
||||
.min(self.profit.base.cents.height.len())
|
||||
.min(self.loss.base.cents.height.len())
|
||||
.min(self.sopr.value_created.base.height.len())
|
||||
.min(self.sopr.value_destroyed.base.height.len())
|
||||
.min(self.transfer_volume.base.sats.height.len())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -85,16 +83,7 @@ impl RealizedMinimal {
|
||||
self.cap.cents.height.push(state.realized.cap());
|
||||
self.profit.base.cents.height.push(state.realized.profit());
|
||||
self.loss.base.cents.height.push(state.realized.loss());
|
||||
self.sopr
|
||||
.value_created
|
||||
.base
|
||||
.height
|
||||
.push(state.realized.value_created());
|
||||
self.sopr
|
||||
.value_destroyed
|
||||
.base
|
||||
.height
|
||||
.push(state.realized.value_destroyed());
|
||||
self.transfer_volume.base.sats.height.push(state.sent);
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
@@ -102,8 +91,7 @@ impl RealizedMinimal {
|
||||
&mut self.cap.cents.height as &mut dyn AnyStoredVec,
|
||||
&mut self.profit.base.cents.height,
|
||||
&mut self.loss.base.cents.height,
|
||||
&mut self.sopr.value_created.base.height,
|
||||
&mut self.sopr.value_destroyed.base.height,
|
||||
&mut self.transfer_volume.base.sats.height,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -116,24 +104,20 @@ impl RealizedMinimal {
|
||||
sum_others!(self, starting_indexes, others, exit; cap.cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; profit.base.cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; loss.base.cents.height);
|
||||
sum_others!(self, starting_indexes, others, exit; sopr.value_created.base.height);
|
||||
sum_others!(self, starting_indexes, others, exit; sopr.value_destroyed.base.height);
|
||||
sum_others!(self, starting_indexes, others, exit; transfer_volume.base.sats.height);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.profit.compute_rest(starting_indexes.height, exit)?;
|
||||
self.loss.compute_rest(starting_indexes.height, exit)?;
|
||||
self.sopr
|
||||
.value_created
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.sopr
|
||||
.value_destroyed
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.transfer_volume
|
||||
.compute_rest(starting_indexes.height, prices, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ use brk_error::Result;
|
||||
use brk_types::Indexes;
|
||||
use vecdb::Exit;
|
||||
|
||||
use crate::distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState};
|
||||
use crate::{distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState}, prices};
|
||||
|
||||
pub trait RealizedLike: Send + Sync {
|
||||
fn as_core(&self) -> &RealizedCore;
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore;
|
||||
fn min_stateful_len(&self) -> usize;
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>);
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
@@ -36,8 +36,8 @@ impl RealizedLike for RealizedCore {
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.push_state(state)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(starting_indexes, exit)
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(prices, starting_indexes, exit)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&RealizedCore], exit: &Exit) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
@@ -52,8 +52,8 @@ impl RealizedLike for RealizedFull {
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.push_state(state)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(starting_indexes, exit)
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(prices, starting_indexes, exit)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&RealizedCore], exit: &Exit) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
|
||||
@@ -96,8 +96,8 @@ impl<R: RealizedOps, C: CostBasisOps> CohortState<R, C> {
|
||||
}
|
||||
|
||||
pub(crate) fn reset_single_iteration_values(&mut self) {
|
||||
self.sent = Sats::ZERO;
|
||||
if R::TRACK_ACTIVITY {
|
||||
self.sent = Sats::ZERO;
|
||||
self.satdays_destroyed = Sats::ZERO;
|
||||
}
|
||||
self.realized.reset_single_iteration_values();
|
||||
@@ -196,8 +196,8 @@ impl<R: RealizedOps, C: CostBasisOps> CohortState<R, C> {
|
||||
pre: &SendPrecomputed,
|
||||
) {
|
||||
self.supply -= supply;
|
||||
self.sent += pre.sats;
|
||||
if R::TRACK_ACTIVITY {
|
||||
self.sent += pre.sats;
|
||||
self.satdays_destroyed += pre.age.satdays_destroyed(pre.sats);
|
||||
}
|
||||
|
||||
@@ -241,8 +241,8 @@ impl<R: RealizedOps, C: CostBasisOps> CohortState<R, C> {
|
||||
self.supply -= supply;
|
||||
|
||||
if supply.value > Sats::ZERO {
|
||||
self.sent += supply.value;
|
||||
if R::TRACK_ACTIVITY {
|
||||
self.sent += supply.value;
|
||||
self.satdays_destroyed += age.satdays_destroyed(supply.value);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@ pub trait RealizedOps: Default + Clone + Send + Sync + 'static {
|
||||
fn cap(&self) -> Cents;
|
||||
fn profit(&self) -> Cents;
|
||||
fn loss(&self) -> Cents;
|
||||
fn value_created(&self) -> Cents {
|
||||
Cents::ZERO
|
||||
}
|
||||
fn value_destroyed(&self) -> Cents {
|
||||
Cents::ZERO
|
||||
}
|
||||
@@ -46,7 +43,6 @@ pub struct MinimalRealizedState {
|
||||
cap_raw: u128,
|
||||
profit_raw: u128,
|
||||
loss_raw: u128,
|
||||
value_created_raw: u128,
|
||||
value_destroyed_raw: u128,
|
||||
}
|
||||
|
||||
@@ -76,13 +72,6 @@ impl RealizedOps for MinimalRealizedState {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_created(&self) -> Cents {
|
||||
if self.value_created_raw == 0 {
|
||||
return Cents::ZERO;
|
||||
}
|
||||
Cents::new((self.value_created_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_destroyed(&self) -> Cents {
|
||||
if self.value_destroyed_raw == 0 {
|
||||
@@ -103,7 +92,6 @@ impl RealizedOps for MinimalRealizedState {
|
||||
fn reset_single_iteration_values(&mut self) {
|
||||
self.profit_raw = 0;
|
||||
self.loss_raw = 0;
|
||||
self.value_created_raw = 0;
|
||||
self.value_destroyed_raw = 0;
|
||||
}
|
||||
|
||||
@@ -145,7 +133,6 @@ impl RealizedOps for MinimalRealizedState {
|
||||
Ordering::Equal => {}
|
||||
}
|
||||
self.cap_raw -= prev_ps.as_u128();
|
||||
self.value_created_raw += current_ps.as_u128();
|
||||
self.value_destroyed_raw += prev_ps.as_u128();
|
||||
}
|
||||
}
|
||||
@@ -177,11 +164,6 @@ impl RealizedOps for CoreRealizedState {
|
||||
self.minimal.loss()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_created(&self) -> Cents {
|
||||
self.minimal.value_created()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_destroyed(&self) -> Cents {
|
||||
self.minimal.value_destroyed()
|
||||
@@ -263,14 +245,6 @@ pub struct RealizedState {
|
||||
core: CoreRealizedState,
|
||||
/// Raw investor cap: Σ(price² × sats)
|
||||
investor_cap_raw: CentsSquaredSats,
|
||||
/// sell_price × sats for profit cases
|
||||
profit_value_created_raw: u128,
|
||||
/// cost_basis × sats for profit cases
|
||||
profit_value_destroyed_raw: u128,
|
||||
/// sell_price × sats for loss cases
|
||||
loss_value_created_raw: u128,
|
||||
/// cost_basis × sats for loss cases (= capitulation_flow)
|
||||
loss_value_destroyed_raw: u128,
|
||||
/// Raw realized peak regret: Σ((peak - sell_price) × sats)
|
||||
peak_regret_raw: u128,
|
||||
}
|
||||
@@ -293,22 +267,9 @@ impl RealizedOps for RealizedState {
|
||||
self.core.loss()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_created(&self) -> Cents {
|
||||
let raw = self.profit_value_created_raw + self.loss_value_created_raw;
|
||||
if raw == 0 {
|
||||
return Cents::ZERO;
|
||||
}
|
||||
Cents::new((raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_destroyed(&self) -> Cents {
|
||||
let raw = self.profit_value_destroyed_raw + self.loss_value_destroyed_raw;
|
||||
if raw == 0 {
|
||||
return Cents::ZERO;
|
||||
}
|
||||
Cents::new((raw / Sats::ONE_BTC_U128) as u64)
|
||||
self.core.value_destroyed()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -334,10 +295,6 @@ impl RealizedOps for RealizedState {
|
||||
#[inline]
|
||||
fn reset_single_iteration_values(&mut self) {
|
||||
self.core.reset_single_iteration_values();
|
||||
self.profit_value_created_raw = 0;
|
||||
self.profit_value_destroyed_raw = 0;
|
||||
self.loss_value_created_raw = 0;
|
||||
self.loss_value_destroyed_raw = 0;
|
||||
self.peak_regret_raw = 0;
|
||||
}
|
||||
|
||||
@@ -370,24 +327,9 @@ impl RealizedOps for RealizedState {
|
||||
ath_ps: CentsSats,
|
||||
prev_investor_cap: CentsSquaredSats,
|
||||
) {
|
||||
// Delegate cap/profit/loss + value_created/destroyed + sent tracking to core
|
||||
self.core
|
||||
.send(sats, current_ps, prev_ps, ath_ps, prev_investor_cap);
|
||||
|
||||
// Per-component value flow tracking
|
||||
let current = current_ps.as_u128();
|
||||
let prev = prev_ps.as_u128();
|
||||
match current_ps.cmp(&prev_ps) {
|
||||
Ordering::Greater | Ordering::Equal => {
|
||||
self.profit_value_created_raw += current;
|
||||
self.profit_value_destroyed_raw += prev;
|
||||
}
|
||||
Ordering::Less => {
|
||||
self.loss_value_created_raw += current;
|
||||
self.loss_value_destroyed_raw += prev;
|
||||
}
|
||||
}
|
||||
|
||||
self.peak_regret_raw += (ath_ps - current_ps).as_u128();
|
||||
self.investor_cap_raw -= prev_investor_cap;
|
||||
}
|
||||
@@ -417,42 +359,6 @@ impl RealizedState {
|
||||
self.investor_cap_raw
|
||||
}
|
||||
|
||||
/// Get profit value created as CentsUnsigned (sell_price × sats for profit cases).
|
||||
#[inline]
|
||||
pub(crate) fn profit_value_created(&self) -> Cents {
|
||||
if self.profit_value_created_raw == 0 {
|
||||
return Cents::ZERO;
|
||||
}
|
||||
Cents::new((self.profit_value_created_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
/// Get profit value destroyed as CentsUnsigned (cost_basis × sats for profit cases).
|
||||
#[inline]
|
||||
pub(crate) fn profit_value_destroyed(&self) -> Cents {
|
||||
if self.profit_value_destroyed_raw == 0 {
|
||||
return Cents::ZERO;
|
||||
}
|
||||
Cents::new((self.profit_value_destroyed_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
/// Get loss value created as CentsUnsigned (sell_price × sats for loss cases).
|
||||
#[inline]
|
||||
pub(crate) fn loss_value_created(&self) -> Cents {
|
||||
if self.loss_value_created_raw == 0 {
|
||||
return Cents::ZERO;
|
||||
}
|
||||
Cents::new((self.loss_value_created_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
/// Get loss value destroyed as CentsUnsigned (cost_basis × sats for loss cases).
|
||||
#[inline]
|
||||
pub(crate) fn loss_value_destroyed(&self) -> Cents {
|
||||
if self.loss_value_destroyed_raw == 0 {
|
||||
return Cents::ZERO;
|
||||
}
|
||||
Cents::new((self.loss_value_destroyed_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
/// Get realized peak regret as CentsUnsigned.
|
||||
#[inline]
|
||||
pub(crate) fn peak_regret(&self) -> Cents {
|
||||
@@ -462,30 +368,6 @@ impl RealizedState {
|
||||
Cents::new((self.peak_regret_raw / Sats::ONE_BTC_U128) as u64)
|
||||
}
|
||||
|
||||
/// Raw profit value created for lossless aggregation.
|
||||
#[inline]
|
||||
pub(crate) fn profit_value_created_raw(&self) -> u128 {
|
||||
self.profit_value_created_raw
|
||||
}
|
||||
|
||||
/// Raw profit value destroyed for lossless aggregation.
|
||||
#[inline]
|
||||
pub(crate) fn profit_value_destroyed_raw(&self) -> u128 {
|
||||
self.profit_value_destroyed_raw
|
||||
}
|
||||
|
||||
/// Raw loss value created for lossless aggregation.
|
||||
#[inline]
|
||||
pub(crate) fn loss_value_created_raw(&self) -> u128 {
|
||||
self.loss_value_created_raw
|
||||
}
|
||||
|
||||
/// Raw loss value destroyed for lossless aggregation.
|
||||
#[inline]
|
||||
pub(crate) fn loss_value_destroyed_raw(&self) -> u128 {
|
||||
self.loss_value_destroyed_raw
|
||||
}
|
||||
|
||||
/// Raw peak regret for lossless aggregation.
|
||||
#[inline]
|
||||
pub(crate) fn peak_regret_raw(&self) -> u128 {
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
//! PerBlockCumulative - base PerBlock + cumulative PerBlock.
|
||||
//!
|
||||
//! Like PerBlockCumulativeWithSums but without RollingWindows.
|
||||
//! Used for distribution metrics where rolling is optional per cohort.
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Version};
|
||||
use schemars::JsonSchema;
|
||||
use vecdb::{Database, Exit, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{PerBlock, NumericValue},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct PerBlockCumulative<T, M: StorageMode = Rw>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub base: PerBlock<T, M>,
|
||||
pub cumulative: PerBlock<T, M>,
|
||||
}
|
||||
|
||||
impl<T> PerBlockCumulative<T>
|
||||
where
|
||||
T: NumericValue + JsonSchema,
|
||||
{
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
name: &str,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let base = PerBlock::forced_import(db, name, version, indexes)?;
|
||||
let cumulative =
|
||||
PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?;
|
||||
|
||||
Ok(Self { base, cumulative })
|
||||
}
|
||||
|
||||
/// Compute cumulative from already-filled base vec.
|
||||
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()>
|
||||
where
|
||||
T: Default,
|
||||
{
|
||||
self.cumulative
|
||||
.height
|
||||
.compute_cumulative(max_from, &self.base.height, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
mod aggregated;
|
||||
mod base;
|
||||
mod cumulative;
|
||||
mod cumulative_sum;
|
||||
mod distribution;
|
||||
mod full;
|
||||
@@ -13,7 +12,6 @@ mod with_deltas;
|
||||
|
||||
pub use aggregated::*;
|
||||
pub use base::*;
|
||||
pub use cumulative::*;
|
||||
pub use cumulative_sum::*;
|
||||
pub use distribution::*;
|
||||
pub use full::*;
|
||||
|
||||
@@ -44,7 +44,7 @@ pub struct Bp16ToPercent;
|
||||
impl UnaryTransform<BasisPoints16, StoredF32> for Bp16ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints16) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
StoredF32::from(bp.to_f32() * 100.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ pub struct Bp32ToPercent;
|
||||
impl UnaryTransform<BasisPoints32, StoredF32> for Bp32ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPoints32) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
StoredF32::from(bp.to_f32() * 100.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ pub struct Bps16ToPercent;
|
||||
impl UnaryTransform<BasisPointsSigned16, StoredF32> for Bps16ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned16) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
StoredF32::from(bp.to_f32() * 100.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,6 @@ pub struct Bps32ToPercent;
|
||||
impl UnaryTransform<BasisPointsSigned32, StoredF32> for Bps32ToPercent {
|
||||
#[inline(always)]
|
||||
fn apply(bp: BasisPointsSigned32) -> StoredF32 {
|
||||
StoredF32::from(bp.inner() as f32 / 100.0)
|
||||
StoredF32::from(bp.to_f32() * 100.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::Indexes;
|
||||
use brk_types::{Indexes, Sats};
|
||||
use vecdb::Exit;
|
||||
|
||||
/// Initial block subsidy (50 BTC) in sats, as f64 for floating-point comparisons.
|
||||
const INITIAL_SUBSIDY: f64 = Sats::ONE_BTC_U64 as f64 * 50.0;
|
||||
|
||||
use super::Vecs;
|
||||
use crate::{blocks, distribution, mining, prices, scripts, transactions};
|
||||
|
||||
@@ -28,15 +31,24 @@ impl Vecs {
|
||||
)?;
|
||||
|
||||
// 2. Compute inflation rate: (supply[h] / supply[1y_ago]) - 1
|
||||
// Skip when lookback supply <= first block (50 BTC = 5B sats),
|
||||
// i.e. the lookback points to block 0 or 1 in the genesis era.
|
||||
let circulating_supply = &distribution.utxo_cohorts.all.metrics.supply.total.sats;
|
||||
self.inflation_rate
|
||||
.bps
|
||||
.height
|
||||
.compute_rolling_ratio_change(
|
||||
.compute_rolling_from_window_starts(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback._1y,
|
||||
&circulating_supply.height,
|
||||
exit,
|
||||
|current, previous| {
|
||||
if previous.is_nan() || previous <= INITIAL_SUBSIDY {
|
||||
f64::NAN
|
||||
} else {
|
||||
current / previous - 1.0
|
||||
}
|
||||
},
|
||||
)?;
|
||||
|
||||
// 3. Compute velocity at height level
|
||||
|
||||
@@ -37,8 +37,12 @@ impl Vecs {
|
||||
let burned = burned::Vecs::forced_import(&db, version, indexes, cached_starts)?;
|
||||
|
||||
// Inflation rate
|
||||
let inflation_rate =
|
||||
PercentPerBlock::forced_import(&db, "inflation_rate", version, indexes)?;
|
||||
let inflation_rate = PercentPerBlock::forced_import(
|
||||
&db,
|
||||
"inflation_rate",
|
||||
version + Version::ONE,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
// Velocity
|
||||
let velocity = super::velocity::Vecs::forced_import(&db, version, indexes)?;
|
||||
|
||||
Reference in New Issue
Block a user