global: snapshot

This commit is contained in:
nym21
2026-03-01 20:06:25 +01:00
parent 7bf0220f25
commit 4abb00b86d
71 changed files with 2432 additions and 2157 deletions

View File

@@ -828,7 +828,7 @@ impl UTXOCohorts<Rw> {
pub(crate) fn truncate_push_aggregate_percentiles(
&mut self,
height: Height,
spot: Dollars,
spot: Cents,
day1_opt: Option<Day1>,
states_path: &Path,
) -> Result<()> {
@@ -895,7 +895,7 @@ impl UTXOCohorts<Rw> {
.collect();
if total_sats == 0 {
let nan_prices = [Dollars::NAN; PERCENTILES_LEN];
let nan_prices = [Cents::ZERO; PERCENTILES_LEN];
target
.extended
.percentiles
@@ -928,8 +928,8 @@ impl UTXOCohorts<Rw> {
let sat_targets = PERCENTILES.map(|p| total_sats * u64::from(p) / 100);
let usd_targets = PERCENTILES.map(|p| total_usd * u128::from(p) / 100);
let mut sat_result = [Dollars::NAN; PERCENTILES_LEN];
let mut usd_result = [Dollars::NAN; PERCENTILES_LEN];
let mut sat_result = [Cents::ZERO; PERCENTILES_LEN];
let mut usd_result = [Cents::ZERO; PERCENTILES_LEN];
let mut cumsum_sats: u64 = 0;
let mut cumsum_usd: u128 = 0;
@@ -953,13 +953,12 @@ impl UTXOCohorts<Rw> {
cumsum_usd += usd;
if sat_idx < PERCENTILES_LEN || usd_idx < PERCENTILES_LEN {
let dollars = price.to_dollars();
while sat_idx < PERCENTILES_LEN && cumsum_sats >= sat_targets[sat_idx] {
sat_result[sat_idx] = dollars;
sat_result[sat_idx] = price;
sat_idx += 1;
}
while usd_idx < PERCENTILES_LEN && cumsum_usd >= usd_targets[usd_idx] {
usd_result[usd_idx] = dollars;
usd_result[usd_idx] = price;
usd_idx += 1;
}
}

View File

@@ -451,10 +451,9 @@ pub(crate) fn process_blocks(
)?;
// Compute and push percentiles for aggregate cohorts (all, sth, lth)
let spot = block_price.to_dollars();
vecs.utxo_cohorts.truncate_push_aggregate_percentiles(
height,
spot,
block_price,
day1_opt,
&vecs.states_path,
)?;

View File

@@ -170,7 +170,7 @@ impl ActivityMetrics {
starting_indexes.height,
&blocks.count.height_2w_ago,
&self.sent.base.sats.height,
&self.sent.base.usd.height,
&self.sent.base.cents.height,
exit,
)?;

View File

@@ -99,8 +99,8 @@ impl AdjustedCohortMetrics {
prices: &prices::Vecs,
starting_indexes: &ComputeIndexes,
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Cents>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Cents>,
all_supply_sats: &impl ReadableVec<Height, Sats>,
exit: &Exit,
) -> Result<()> {

View File

@@ -87,10 +87,9 @@ impl CohortMetricsBase for AllCohortMetrics {
self.unrealized
.base
.truncate_push(height, &height_unrealized_state)?;
let spot = height_price.to_dollars();
self.cost_basis
.extended
.truncate_push_percentiles(height, state, spot)?;
.truncate_push_percentiles(height, state, height_price)?;
Ok(())
}
fn collect_all_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
@@ -140,8 +139,8 @@ impl AllCohortMetrics {
prices: &prices::Vecs,
starting_indexes: &ComputeIndexes,
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Cents>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.realized.compute_rest_part2(

View File

@@ -56,8 +56,7 @@ impl CohortMetricsBase for ExtendedCohortMetrics {
self.cost_basis.truncate_push_minmax(height, state)?;
let (height_unrealized_state, _) = state.compute_unrealized_states(height_price, None);
self.unrealized.base.truncate_push(height, &height_unrealized_state)?;
let spot = height_price.to_dollars();
self.cost_basis.extended.truncate_push_percentiles(height, state, spot)?;
self.cost_basis.extended.truncate_push_percentiles(height, state, height_price)?;
Ok(())
}
fn collect_all_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {

View File

@@ -55,8 +55,7 @@ impl CohortMetricsBase for ExtendedAdjustedCohortMetrics {
self.cost_basis.truncate_push_minmax(height, state)?;
let (height_unrealized_state, _) = state.compute_unrealized_states(height_price, None);
self.unrealized.base.truncate_push(height, &height_unrealized_state)?;
let spot = height_price.to_dollars();
self.cost_basis.extended.truncate_push_percentiles(height, state, spot)?;
self.cost_basis.extended.truncate_push_percentiles(height, state, height_price)?;
Ok(())
}
fn collect_all_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
@@ -102,8 +101,8 @@ impl ExtendedAdjustedCohortMetrics {
prices: &prices::Vecs,
starting_indexes: &ComputeIndexes,
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Cents>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Cents>,
all_supply_sats: &impl ReadableVec<Height, Sats>,
exit: &Exit,
) -> Result<()> {

View File

@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, Height};
use brk_types::{Cents, Height};
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
use crate::{
@@ -15,10 +15,10 @@ use crate::distribution::metrics::ImportConfig;
#[derive(Traversable)]
pub struct CostBasisBase<M: StorageMode = Rw> {
/// Minimum cost basis for any UTXO at this height
pub min: Price<ComputedFromHeightLast<Dollars, M>>,
pub min: Price<ComputedFromHeightLast<Cents, M>>,
/// Maximum cost basis for any UTXO at this height
pub max: Price<ComputedFromHeightLast<Dollars, M>>,
pub max: Price<ComputedFromHeightLast<Cents, M>>,
}
impl CostBasisBase {
@@ -40,7 +40,7 @@ impl CostBasisBase {
}
pub(crate) fn min_stateful_height_len(&self) -> usize {
self.min.usd.height.len().min(self.max.usd.height.len())
self.min.cents.height.len().min(self.max.cents.height.len())
}
pub(crate) fn truncate_push_minmax(
@@ -48,27 +48,27 @@ impl CostBasisBase {
height: Height,
state: &CohortState,
) -> Result<()> {
self.min.usd.height.truncate_push(
self.min.cents.height.truncate_push(
height,
state
.cost_basis_data_first_key_value()
.map(|(cents, _)| cents.into())
.unwrap_or(Dollars::NAN),
.map(|(cents, _)| cents)
.unwrap_or(Cents::ZERO),
)?;
self.max.usd.height.truncate_push(
self.max.cents.height.truncate_push(
height,
state
.cost_basis_data_last_key_value()
.map(|(cents, _)| cents.into())
.unwrap_or(Dollars::NAN),
.map(|(cents, _)| cents)
.unwrap_or(Cents::ZERO),
)?;
Ok(())
}
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
vec![
&mut self.min.usd.height as &mut dyn AnyStoredVec,
&mut self.max.usd.height,
&mut self.min.cents.height as &mut dyn AnyStoredVec,
&mut self.max.cents.height,
]
}
@@ -78,14 +78,14 @@ impl CostBasisBase {
others: &[&Self],
exit: &Exit,
) -> Result<()> {
self.min.usd.height.compute_min_of_others(
self.min.cents.height.compute_min_of_others(
starting_indexes.height,
&others.iter().map(|v| &v.min.usd.height).collect::<Vec<_>>(),
&others.iter().map(|v| &v.min.cents.height).collect::<Vec<_>>(),
exit,
)?;
self.max.usd.height.compute_max_of_others(
self.max.cents.height.compute_max_of_others(
starting_indexes.height,
&others.iter().map(|v| &v.max.usd.height).collect::<Vec<_>>(),
&others.iter().map(|v| &v.max.cents.height).collect::<Vec<_>>(),
exit,
)?;
Ok(())

View File

@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, Height, StoredF32, Version};
use brk_types::{Cents, Height, StoredF32, Version};
use vecdb::{AnyStoredVec, Rw, StorageMode, WritableVec};
use crate::{
@@ -62,14 +62,14 @@ impl CostBasisExtended {
&mut self,
height: Height,
state: &mut CohortState,
spot: Dollars,
spot: Cents,
) -> Result<()> {
let computed = state.compute_percentiles();
let sat_prices = computed
.as_ref()
.map(|p| p.sat_weighted.map(|c| c.to_dollars()))
.unwrap_or([Dollars::NAN; PERCENTILES_LEN]);
.map(|p| p.sat_weighted)
.unwrap_or([Cents::ZERO; PERCENTILES_LEN]);
self.percentiles.truncate_push(height, &sat_prices)?;
let rank = compute_spot_percentile_rank(&sat_prices, spot);
@@ -79,8 +79,8 @@ impl CostBasisExtended {
let usd_prices = computed
.as_ref()
.map(|p| p.usd_weighted.map(|c| c.to_dollars()))
.unwrap_or([Dollars::NAN; PERCENTILES_LEN]);
.map(|p| p.usd_weighted)
.unwrap_or([Cents::ZERO; PERCENTILES_LEN]);
self.invested_capital.truncate_push(height, &usd_prices)?;
let rank = compute_spot_percentile_rank(&usd_prices, spot);
@@ -97,13 +97,13 @@ impl CostBasisExtended {
self.percentiles
.vecs
.iter_mut()
.map(|v| &mut v.usd.height as &mut dyn AnyStoredVec),
.map(|v| &mut v.cents.height as &mut dyn AnyStoredVec),
);
vecs.extend(
self.invested_capital
.vecs
.iter_mut()
.map(|v| &mut v.usd.height as &mut dyn AnyStoredVec),
.map(|v| &mut v.cents.height as &mut dyn AnyStoredVec),
);
vecs.push(&mut self.spot_cost_basis_percentile.height);
vecs.push(&mut self.spot_invested_capital_percentile.height);

View File

@@ -1,11 +1,11 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, Height, StoredF64, Version};
use brk_types::{Cents, Height, StoredF64, Version};
use vecdb::{Exit, Ident, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
use crate::{
ComputeIndexes, blocks,
internal::{ComputedFromHeightLast, LazyFromHeightLast, Ratio64},
internal::{ComputedFromHeightLast, LazyFromHeightLast, RatioCents64},
};
use crate::distribution::metrics::ImportConfig;
@@ -14,18 +14,18 @@ use crate::distribution::metrics::ImportConfig;
#[derive(Traversable)]
pub struct RealizedAdjusted<M: StorageMode = Rw> {
// === Adjusted Value (computed: cohort - up_to_1h) ===
pub adjusted_value_created: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_destroyed: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_created: ComputedFromHeightLast<Cents, M>,
pub adjusted_value_destroyed: ComputedFromHeightLast<Cents, M>,
// === Adjusted Value Created/Destroyed Rolling Sums ===
pub adjusted_value_created_24h: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_created_7d: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_created_30d: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_created_1y: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_destroyed_24h: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_destroyed_7d: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_destroyed_30d: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_destroyed_1y: ComputedFromHeightLast<Dollars, M>,
pub adjusted_value_created_24h: ComputedFromHeightLast<Cents, M>,
pub adjusted_value_created_7d: ComputedFromHeightLast<Cents, M>,
pub adjusted_value_created_30d: ComputedFromHeightLast<Cents, M>,
pub adjusted_value_created_1y: ComputedFromHeightLast<Cents, M>,
pub adjusted_value_destroyed_24h: ComputedFromHeightLast<Cents, M>,
pub adjusted_value_destroyed_7d: ComputedFromHeightLast<Cents, M>,
pub adjusted_value_destroyed_30d: ComputedFromHeightLast<Cents, M>,
pub adjusted_value_destroyed_1y: ComputedFromHeightLast<Cents, M>,
// === Adjusted SOPR (rolling window ratios) ===
pub adjusted_sopr: LazyFromHeightLast<StoredF64>,
@@ -150,10 +150,10 @@ impl RealizedAdjusted {
&mut self,
blocks: &blocks::Vecs,
starting_indexes: &ComputeIndexes,
base_value_created: &impl ReadableVec<Height, Dollars>,
base_value_destroyed: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Dollars>,
base_value_created: &impl ReadableVec<Height, Cents>,
base_value_destroyed: &impl ReadableVec<Height, Cents>,
up_to_1h_value_created: &impl ReadableVec<Height, Cents>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
// Compute adjusted_value_created = base.value_created - up_to_1h.value_created
@@ -231,28 +231,28 @@ impl RealizedAdjusted {
// SOPR ratios from rolling sums
self.adjusted_sopr_24h
.compute_binary::<Dollars, Dollars, Ratio64>(
.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.adjusted_value_created_24h.height,
&self.adjusted_value_destroyed_24h.height,
exit,
)?;
self.adjusted_sopr_7d
.compute_binary::<Dollars, Dollars, Ratio64>(
.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.adjusted_value_created_7d.height,
&self.adjusted_value_destroyed_7d.height,
exit,
)?;
self.adjusted_sopr_30d
.compute_binary::<Dollars, Dollars, Ratio64>(
.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.adjusted_value_created_30d.height,
&self.adjusted_value_destroyed_30d.height,
exit,
)?;
self.adjusted_sopr_1y
.compute_binary::<Dollars, Dollars, Ratio64>(
.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.adjusted_value_created_1y.height,
&self.adjusted_value_destroyed_1y.height,

View File

@@ -1,10 +1,10 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{
Bitcoin, Cents, CentsSats, CentsSquaredSats, Dollars, Height, StoredF32, StoredF64, Version,
Bitcoin, Cents, CentsSats, CentsSigned, CentsSquaredSats, Dollars, Height, Sats, StoredF32, StoredF64, Version,
};
use vecdb::{
AnyStoredVec, AnyVec, BytesVec, Exit, Ident, ImportableVec, Negate, ReadableCloneableVec,
AnyStoredVec, AnyVec, BytesVec, Exit, Ident, ImportableVec, ReadableCloneableVec,
ReadableVec, Rw, StorageMode, WritableVec,
};
@@ -12,9 +12,9 @@ use crate::{
ComputeIndexes, blocks,
distribution::state::RealizedState,
internal::{
CentsUnsignedToDollars, ComputedFromHeightCumulative, ComputedFromHeightLast,
ComputedFromHeightRatio, DollarsPlus, ValueFromHeightCumulative, LazyFromHeightLast,
PercentageDollarsF32, Price, Ratio64,
CentsPlus, CentsUnsignedToDollars, ComputedFromHeightCumulative, ComputedFromHeightLast,
ComputedFromHeightRatio, NegCentsUnsignedToDollars, ValueFromHeightCumulative, LazyFromHeightLast,
PercentageCentsF32, PercentageCentsSignedCentsF32, PercentageCentsSignedDollarsF32, Price, RatioCents64,
StoredF32Identity, ValueFromHeightLast,
},
prices,
@@ -28,18 +28,17 @@ pub struct RealizedBase<M: StorageMode = Rw> {
// === Realized Cap ===
pub realized_cap_cents: ComputedFromHeightLast<Cents, M>,
pub realized_cap: LazyFromHeightLast<Dollars, Cents>,
pub realized_price: Price<ComputedFromHeightLast<Dollars, M>>,
pub realized_price: Price<ComputedFromHeightLast<Cents, M>>,
pub realized_price_extra: ComputedFromHeightRatio<M>,
pub realized_cap_30d_delta: ComputedFromHeightLast<Dollars, M>,
pub realized_cap_30d_delta: ComputedFromHeightLast<CentsSigned, M>,
// === Investor Price ===
pub investor_price_cents: ComputedFromHeightLast<Cents, M>,
pub investor_price: Price<LazyFromHeightLast<Dollars, Cents>>,
pub investor_price: Price<ComputedFromHeightLast<Cents, M>>,
pub investor_price_extra: ComputedFromHeightRatio<M>,
// === Floor/Ceiling Price Bands ===
pub lower_price_band: Price<ComputedFromHeightLast<Dollars, M>>,
pub upper_price_band: Price<ComputedFromHeightLast<Dollars, M>>,
pub lower_price_band: Price<ComputedFromHeightLast<Cents, M>>,
pub upper_price_band: Price<ComputedFromHeightLast<Cents, M>>,
// === Raw values for aggregation ===
pub cap_raw: M::Stored<BytesVec<Height, CentsSats>>,
@@ -49,14 +48,14 @@ pub struct RealizedBase<M: StorageMode = Rw> {
pub mvrv: LazyFromHeightLast<StoredF32>,
// === Realized Profit/Loss ===
pub realized_profit: ComputedFromHeightCumulative<Dollars, M>,
pub realized_profit_7d_ema: ComputedFromHeightLast<Dollars, M>,
pub realized_loss: ComputedFromHeightCumulative<Dollars, M>,
pub realized_loss_7d_ema: ComputedFromHeightLast<Dollars, M>,
pub neg_realized_loss: LazyFromHeightLast<Dollars>,
pub net_realized_pnl: ComputedFromHeightCumulative<Dollars, M>,
pub net_realized_pnl_7d_ema: ComputedFromHeightLast<Dollars, M>,
pub realized_value: ComputedFromHeightLast<Dollars, M>,
pub realized_profit: ComputedFromHeightCumulative<Cents, M>,
pub realized_profit_7d_ema: ComputedFromHeightLast<Cents, M>,
pub realized_loss: ComputedFromHeightCumulative<Cents, M>,
pub realized_loss_7d_ema: ComputedFromHeightLast<Cents, M>,
pub neg_realized_loss: LazyFromHeightLast<Dollars, Cents>,
pub net_realized_pnl: ComputedFromHeightCumulative<CentsSigned, M>,
pub net_realized_pnl_7d_ema: ComputedFromHeightLast<CentsSigned, M>,
pub realized_value: ComputedFromHeightLast<Cents, M>,
// === Realized vs Realized Cap Ratios ===
pub realized_profit_rel_to_realized_cap: ComputedFromHeightLast<StoredF32, M>,
@@ -64,31 +63,31 @@ pub struct RealizedBase<M: StorageMode = Rw> {
pub net_realized_pnl_rel_to_realized_cap: ComputedFromHeightLast<StoredF32, M>,
// === Total Realized PnL ===
pub total_realized_pnl: LazyFromHeightLast<Dollars>,
pub total_realized_pnl: LazyFromHeightLast<Dollars, Cents>,
// === Value Created/Destroyed Splits (stored) ===
pub profit_value_created: ComputedFromHeightLast<Dollars, M>,
pub profit_value_destroyed: ComputedFromHeightLast<Dollars, M>,
pub loss_value_created: ComputedFromHeightLast<Dollars, M>,
pub loss_value_destroyed: ComputedFromHeightLast<Dollars, M>,
pub profit_value_created: ComputedFromHeightLast<Cents, M>,
pub profit_value_destroyed: ComputedFromHeightLast<Cents, M>,
pub loss_value_created: ComputedFromHeightLast<Cents, M>,
pub loss_value_destroyed: ComputedFromHeightLast<Cents, M>,
// === Value Created/Destroyed Totals ===
pub value_created: ComputedFromHeightLast<Dollars, M>,
pub value_destroyed: ComputedFromHeightLast<Dollars, M>,
pub value_created: ComputedFromHeightLast<Cents, M>,
pub value_destroyed: ComputedFromHeightLast<Cents, M>,
// === Capitulation/Profit Flow (lazy aliases) ===
pub capitulation_flow: LazyFromHeightLast<Dollars>,
pub profit_flow: LazyFromHeightLast<Dollars>,
pub capitulation_flow: LazyFromHeightLast<Dollars, Cents>,
pub profit_flow: LazyFromHeightLast<Dollars, Cents>,
// === Value Created/Destroyed Rolling Sums ===
pub value_created_24h: ComputedFromHeightLast<Dollars, M>,
pub value_created_7d: ComputedFromHeightLast<Dollars, M>,
pub value_created_30d: ComputedFromHeightLast<Dollars, M>,
pub value_created_1y: ComputedFromHeightLast<Dollars, M>,
pub value_destroyed_24h: ComputedFromHeightLast<Dollars, M>,
pub value_destroyed_7d: ComputedFromHeightLast<Dollars, M>,
pub value_destroyed_30d: ComputedFromHeightLast<Dollars, M>,
pub value_destroyed_1y: ComputedFromHeightLast<Dollars, M>,
pub value_created_24h: ComputedFromHeightLast<Cents, M>,
pub value_created_7d: ComputedFromHeightLast<Cents, M>,
pub value_created_30d: ComputedFromHeightLast<Cents, M>,
pub value_created_1y: ComputedFromHeightLast<Cents, M>,
pub value_destroyed_24h: ComputedFromHeightLast<Cents, M>,
pub value_destroyed_7d: ComputedFromHeightLast<Cents, M>,
pub value_destroyed_30d: ComputedFromHeightLast<Cents, M>,
pub value_destroyed_1y: ComputedFromHeightLast<Cents, M>,
// === SOPR (rolling window ratios) ===
pub sopr: LazyFromHeightLast<StoredF64>,
@@ -102,10 +101,10 @@ pub struct RealizedBase<M: StorageMode = Rw> {
pub sopr_30d_ema: LazyFromHeightLast<StoredF64>,
// === Sell Side Risk Rolling Sum Intermediates ===
pub realized_value_24h: ComputedFromHeightLast<Dollars, M>,
pub realized_value_7d: ComputedFromHeightLast<Dollars, M>,
pub realized_value_30d: ComputedFromHeightLast<Dollars, M>,
pub realized_value_1y: ComputedFromHeightLast<Dollars, M>,
pub realized_value_24h: ComputedFromHeightLast<Cents, M>,
pub realized_value_7d: ComputedFromHeightLast<Cents, M>,
pub realized_value_30d: ComputedFromHeightLast<Cents, M>,
pub realized_value_1y: ComputedFromHeightLast<Cents, M>,
// === Sell Side Risk (rolling window ratios) ===
pub sell_side_risk_ratio: LazyFromHeightLast<StoredF32>,
@@ -119,14 +118,14 @@ pub struct RealizedBase<M: StorageMode = Rw> {
pub sell_side_risk_ratio_30d_ema: LazyFromHeightLast<StoredF32>,
// === Net Realized PnL Deltas ===
pub net_realized_pnl_cumulative_30d_delta: ComputedFromHeightLast<Dollars, M>,
pub net_realized_pnl_cumulative_30d_delta: ComputedFromHeightLast<CentsSigned, M>,
pub net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap:
ComputedFromHeightLast<StoredF32, M>,
pub net_realized_pnl_cumulative_30d_delta_rel_to_market_cap:
ComputedFromHeightLast<StoredF32, M>,
// === Peak Regret ===
pub peak_regret: ComputedFromHeightCumulative<Dollars, M>,
pub peak_regret: ComputedFromHeightCumulative<Cents, M>,
pub peak_regret_rel_to_realized_cap: ComputedFromHeightLast<StoredF32, M>,
// === Sent in Profit/Loss ===
@@ -185,7 +184,7 @@ impl RealizedBase {
cfg.indexes,
)?;
let neg_realized_loss = LazyFromHeightLast::from_height_source::<Negate>(
let neg_realized_loss = LazyFromHeightLast::from_height_source::<NegCentsUnsignedToDollars>(
&cfg.name("neg_realized_loss"),
cfg.version + v1,
realized_loss.height.read_only_boxed_clone(),
@@ -220,7 +219,7 @@ impl RealizedBase {
cfg.indexes,
)?;
let total_realized_pnl = LazyFromHeightLast::from_computed::<Ident>(
let total_realized_pnl = LazyFromHeightLast::from_computed::<CentsUnsignedToDollars>(
&cfg.name("total_realized_pnl"),
cfg.version + v1,
realized_value.height.read_only_boxed_clone(),
@@ -255,19 +254,13 @@ impl RealizedBase {
cfg.indexes,
)?;
let investor_price_cents = ComputedFromHeightLast::forced_import(
let investor_price = Price::forced_import(
cfg.db,
&cfg.name("investor_price_cents"),
&cfg.name("investor_price"),
cfg.version,
cfg.indexes,
)?;
let investor_price = Price::from_computed::<CentsUnsignedToDollars>(
&cfg.name("investor_price"),
cfg.version,
&investor_price_cents,
);
let investor_price_extra = ComputedFromHeightRatio::forced_import(
cfg.db,
&cfg.name("investor_price"),
@@ -331,13 +324,13 @@ impl RealizedBase {
cfg.indexes,
)?;
let capitulation_flow = LazyFromHeightLast::from_computed::<Ident>(
let capitulation_flow = LazyFromHeightLast::from_computed::<CentsUnsignedToDollars>(
&cfg.name("capitulation_flow"),
cfg.version,
loss_value_destroyed.height.read_only_boxed_clone(),
&loss_value_destroyed,
);
let profit_flow = LazyFromHeightLast::from_computed::<Ident>(
let profit_flow = LazyFromHeightLast::from_computed::<CentsUnsignedToDollars>(
&cfg.name("profit_flow"),
cfg.version,
profit_value_destroyed.height.read_only_boxed_clone(),
@@ -460,7 +453,6 @@ impl RealizedBase {
cfg.version,
cfg.indexes,
)?,
investor_price_cents,
investor_price,
investor_price_extra,
lower_price_band,
@@ -574,7 +566,7 @@ impl RealizedBase {
.len()
.min(self.realized_profit.height.len())
.min(self.realized_loss.height.len())
.min(self.investor_price_cents.height.len())
.min(self.investor_price.cents.height.len())
.min(self.cap_raw.len())
.min(self.investor_cap_raw.len())
.min(self.profit_value_created.height.len())
@@ -593,11 +585,11 @@ impl RealizedBase {
.truncate_push(height, state.cap())?;
self.realized_profit
.height
.truncate_push(height, state.profit().to_dollars())?;
.truncate_push(height, state.profit())?;
self.realized_loss
.height
.truncate_push(height, state.loss().to_dollars())?;
self.investor_price_cents
.truncate_push(height, state.loss())?;
self.investor_price.cents
.height
.truncate_push(height, state.investor_price())?;
self.cap_raw.truncate_push(height, state.cap_raw())?;
@@ -605,19 +597,19 @@ impl RealizedBase {
.truncate_push(height, state.investor_cap_raw())?;
self.profit_value_created
.height
.truncate_push(height, state.profit_value_created().to_dollars())?;
.truncate_push(height, state.profit_value_created())?;
self.profit_value_destroyed
.height
.truncate_push(height, state.profit_value_destroyed().to_dollars())?;
.truncate_push(height, state.profit_value_destroyed())?;
self.loss_value_created
.height
.truncate_push(height, state.loss_value_created().to_dollars())?;
.truncate_push(height, state.loss_value_created())?;
self.loss_value_destroyed
.height
.truncate_push(height, state.loss_value_destroyed().to_dollars())?;
.truncate_push(height, state.loss_value_destroyed())?;
self.peak_regret
.height
.truncate_push(height, state.peak_regret().to_dollars())?;
.truncate_push(height, state.peak_regret())?;
self.sent_in_profit
.base
.sats
@@ -638,7 +630,7 @@ impl RealizedBase {
&mut self.realized_cap_cents.height as &mut dyn AnyStoredVec,
&mut self.realized_profit.height,
&mut self.realized_loss.height,
&mut self.investor_price_cents.height,
&mut self.investor_price.cents.height,
&mut self.cap_raw as &mut dyn AnyStoredVec,
&mut self.investor_cap_raw as &mut dyn AnyStoredVec,
&mut self.profit_value_created.height,
@@ -686,9 +678,9 @@ impl RealizedBase {
// Aggregate raw values for investor_price computation
let investor_price_dep_version = others
.iter()
.map(|o| o.investor_price_cents.height.version())
.map(|o| o.investor_price.cents.height.version())
.fold(vecdb::Version::ZERO, |acc, v| acc + v);
self.investor_price_cents
self.investor_price.cents
.height
.validate_computed_version_or_reset(investor_price_dep_version)?;
@@ -696,7 +688,7 @@ impl RealizedBase {
.cap_raw
.len()
.min(self.investor_cap_raw.len())
.min(self.investor_price_cents.height.len());
.min(self.investor_price.cents.height.len());
let end = others.iter().map(|o| o.cap_raw.len()).min().unwrap_or(0);
// Pre-collect all cohort data to avoid per-element BytesVec reads in nested loop
@@ -730,14 +722,14 @@ impl RealizedBase {
} else {
Cents::new((sum_investor_cap / sum_cap.inner()) as u64)
};
self.investor_price_cents
self.investor_price.cents
.height
.truncate_push(height, investor_price)?;
}
{
let _lock = exit.lock();
self.investor_price_cents.height.write()?;
self.investor_price.cents.height.write()?;
}
self.profit_value_created.height.compute_sum_of_others(
@@ -813,10 +805,13 @@ impl RealizedBase {
self.net_realized_pnl
.compute(starting_indexes.height, exit, |vec| {
vec.compute_subtract(
vec.compute_transform2(
starting_indexes.height,
&self.realized_profit.height,
&self.realized_loss.height,
|(i, profit, loss, ..)| {
(i, CentsSigned::new(profit.inner() as i64 - loss.inner() as i64))
},
exit,
)?;
Ok(())
@@ -846,47 +841,64 @@ impl RealizedBase {
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
exit: &Exit,
) -> Result<()> {
self.realized_price.usd.height.compute_divide(
self.realized_price.cents.height.compute_transform2(
starting_indexes.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
height_to_supply,
|(i, cap_cents, supply, ..)| {
let cap = cap_cents.as_u128();
let supply_sats = Sats::from(supply).as_u128();
if supply_sats == 0 {
(i, Cents::ZERO)
} else {
(i, Cents::from(cap * Sats::ONE_BTC_U128 / supply_sats))
}
},
exit,
)?;
self.realized_price_extra.compute_ratio(
starting_indexes,
&prices.price.usd.height,
&self.realized_price.usd.height,
&prices.price.cents.height,
&self.realized_price.cents.height,
exit,
)?;
self.investor_price_extra.compute_ratio(
starting_indexes,
&prices.price.usd.height,
&self.investor_price.usd.height,
&prices.price.cents.height,
&self.investor_price.cents.height,
exit,
)?;
self.lower_price_band.usd.height.compute_transform2(
self.lower_price_band.cents.height.compute_transform2(
starting_indexes.height,
&self.realized_price.usd.height,
&self.investor_price.usd.height,
&self.realized_price.cents.height,
&self.investor_price.cents.height,
|(i, rp, ip, ..)| {
let rp = f64::from(rp);
let ip = f64::from(ip);
(i, Dollars::from(rp * rp / ip))
let rp = rp.as_u128();
let ip = ip.as_u128();
if ip == 0 {
(i, Cents::ZERO)
} else {
(i, Cents::from(rp * rp / ip))
}
},
exit,
)?;
self.upper_price_band.usd.height.compute_transform2(
self.upper_price_band.cents.height.compute_transform2(
starting_indexes.height,
&self.investor_price.usd.height,
&self.realized_price.usd.height,
&self.investor_price.cents.height,
&self.realized_price.cents.height,
|(i, ip, rp, ..)| {
let ip = f64::from(ip);
let rp = f64::from(rp);
(i, Dollars::from(ip * ip / rp))
let ip = ip.as_u128();
let rp = rp.as_u128();
if rp == 0 {
(i, Cents::ZERO)
} else {
(i, Cents::from(ip * ip / rp))
}
},
exit,
)?;
@@ -894,20 +906,20 @@ impl RealizedBase {
self.realized_cap_30d_delta.height.compute_rolling_change(
starting_indexes.height,
&blocks.count.height_1m_ago,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
// Compute value_created/destroyed from stored components
self.value_created
.compute_binary::<Dollars, Dollars, DollarsPlus>(
.compute_binary::<Cents, Cents, CentsPlus>(
starting_indexes.height,
&self.profit_value_created.height,
&self.loss_value_created.height,
exit,
)?;
self.value_destroyed
.compute_binary::<Dollars, Dollars, DollarsPlus>(
.compute_binary::<Cents, Cents, CentsPlus>(
starting_indexes.height,
&self.profit_value_destroyed.height,
&self.loss_value_destroyed.height,
@@ -990,25 +1002,25 @@ impl RealizedBase {
);
// Compute SOPR from rolling sums
self.sopr_24h.compute_binary::<Dollars, Dollars, Ratio64>(
self.sopr_24h.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.value_created_24h.height,
&self.value_destroyed_24h.height,
exit,
)?;
self.sopr_7d.compute_binary::<Dollars, Dollars, Ratio64>(
self.sopr_7d.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.value_created_7d.height,
&self.value_destroyed_7d.height,
exit,
)?;
self.sopr_30d.compute_binary::<Dollars, Dollars, Ratio64>(
self.sopr_30d.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.value_created_30d.height,
&self.value_destroyed_30d.height,
exit,
)?;
self.sopr_1y.compute_binary::<Dollars, Dollars, Ratio64>(
self.sopr_1y.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.value_created_1y.height,
&self.value_destroyed_1y.height,
@@ -1017,31 +1029,31 @@ impl RealizedBase {
// Compute sell-side risk ratios
self.sell_side_risk_ratio_24h
.compute_binary::<Dollars, Dollars, PercentageDollarsF32>(
.compute_binary::<Cents, Cents, PercentageCentsF32>(
starting_indexes.height,
&self.realized_value_24h.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
self.sell_side_risk_ratio_7d
.compute_binary::<Dollars, Dollars, PercentageDollarsF32>(
.compute_binary::<Cents, Cents, PercentageCentsF32>(
starting_indexes.height,
&self.realized_value_7d.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
self.sell_side_risk_ratio_30d
.compute_binary::<Dollars, Dollars, PercentageDollarsF32>(
.compute_binary::<Cents, Cents, PercentageCentsF32>(
starting_indexes.height,
&self.realized_value_30d.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
self.sell_side_risk_ratio_1y
.compute_binary::<Dollars, Dollars, PercentageDollarsF32>(
.compute_binary::<Cents, Cents, PercentageCentsF32>(
starting_indexes.height,
&self.realized_value_1y.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
@@ -1072,14 +1084,14 @@ impl RealizedBase {
starting_indexes.height,
&blocks.count.height_2w_ago,
&self.sent_in_profit.base.sats.height,
&self.sent_in_profit.base.usd.height,
&self.sent_in_profit.base.cents.height,
exit,
)?;
self.sent_in_loss_14d_ema.compute_ema(
starting_indexes.height,
&blocks.count.height_2w_ago,
&self.sent_in_loss.base.sats.height,
&self.sent_in_loss.base.usd.height,
&self.sent_in_loss.base.cents.height,
exit,
)?;
@@ -1117,31 +1129,31 @@ impl RealizedBase {
// Realized profit/loss/net relative to realized cap
self.realized_profit_rel_to_realized_cap
.compute_binary::<Dollars, Dollars, PercentageDollarsF32>(
.compute_binary::<Cents, Cents, PercentageCentsF32>(
starting_indexes.height,
&self.realized_profit.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
self.realized_loss_rel_to_realized_cap
.compute_binary::<Dollars, Dollars, PercentageDollarsF32>(
.compute_binary::<Cents, Cents, PercentageCentsF32>(
starting_indexes.height,
&self.realized_loss.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
self.net_realized_pnl_rel_to_realized_cap
.compute_binary::<Dollars, Dollars, PercentageDollarsF32>(
.compute_binary::<CentsSigned, Cents, PercentageCentsSignedCentsF32>(
starting_indexes.height,
&self.net_realized_pnl.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
self.peak_regret_rel_to_realized_cap
.compute_binary::<Dollars, Dollars, PercentageDollarsF32>(
.compute_binary::<Cents, Cents, PercentageCentsF32>(
starting_indexes.height,
&self.peak_regret.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
@@ -1156,17 +1168,15 @@ impl RealizedBase {
)?;
self.net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap
.height
.compute_percentage(
.compute_binary::<CentsSigned, Cents, PercentageCentsSignedCentsF32>(
starting_indexes.height,
&self.net_realized_pnl_cumulative_30d_delta.height,
&self.realized_cap.height,
&self.realized_cap_cents.height,
exit,
)?;
self.net_realized_pnl_cumulative_30d_delta_rel_to_market_cap
.height
.compute_percentage(
.compute_binary::<CentsSigned, Dollars, PercentageCentsSignedDollarsF32>(
starting_indexes.height,
&self.net_realized_pnl_cumulative_30d_delta.height,
height_to_market_cap,

View File

@@ -1,11 +1,11 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Dollars, Height, StoredF32, StoredF64, Version};
use brk_types::{Cents, Dollars, Height, StoredF32, StoredF64, Version};
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
use crate::{
ComputeIndexes, blocks,
internal::{ComputedFromHeightLast, ComputedFromHeightRatioExtension, Ratio64},
internal::{ComputedFromHeightLast, ComputedFromHeightRatioExtension, RatioCents64},
};
use crate::distribution::metrics::ImportConfig;
@@ -18,14 +18,14 @@ pub struct RealizedExtended<M: StorageMode = Rw> {
pub realized_cap_rel_to_own_market_cap: ComputedFromHeightLast<StoredF32, M>,
// === Realized Profit/Loss Rolling Sums ===
pub realized_profit_24h: ComputedFromHeightLast<Dollars, M>,
pub realized_profit_7d: ComputedFromHeightLast<Dollars, M>,
pub realized_profit_30d: ComputedFromHeightLast<Dollars, M>,
pub realized_profit_1y: ComputedFromHeightLast<Dollars, M>,
pub realized_loss_24h: ComputedFromHeightLast<Dollars, M>,
pub realized_loss_7d: ComputedFromHeightLast<Dollars, M>,
pub realized_loss_30d: ComputedFromHeightLast<Dollars, M>,
pub realized_loss_1y: ComputedFromHeightLast<Dollars, M>,
pub realized_profit_24h: ComputedFromHeightLast<Cents, M>,
pub realized_profit_7d: ComputedFromHeightLast<Cents, M>,
pub realized_profit_30d: ComputedFromHeightLast<Cents, M>,
pub realized_profit_1y: ComputedFromHeightLast<Cents, M>,
pub realized_loss_24h: ComputedFromHeightLast<Cents, M>,
pub realized_loss_7d: ComputedFromHeightLast<Cents, M>,
pub realized_loss_30d: ComputedFromHeightLast<Cents, M>,
pub realized_loss_1y: ComputedFromHeightLast<Cents, M>,
// === Realized Profit to Loss Ratio (from rolling sums) ===
pub realized_profit_to_loss_ratio_24h: ComputedFromHeightLast<StoredF64, M>,
@@ -158,28 +158,28 @@ impl RealizedExtended {
// Realized profit to loss ratios
self.realized_profit_to_loss_ratio_24h
.compute_binary::<Dollars, Dollars, Ratio64>(
.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.realized_profit_24h.height,
&self.realized_loss_24h.height,
exit,
)?;
self.realized_profit_to_loss_ratio_7d
.compute_binary::<Dollars, Dollars, Ratio64>(
.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.realized_profit_7d.height,
&self.realized_loss_7d.height,
exit,
)?;
self.realized_profit_to_loss_ratio_30d
.compute_binary::<Dollars, Dollars, Ratio64>(
.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.realized_profit_30d.height,
&self.realized_loss_30d.height,
exit,
)?;
self.realized_profit_to_loss_ratio_1y
.compute_binary::<Dollars, Dollars, Ratio64>(
.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.realized_profit_1y.height,
&self.realized_loss_1y.height,
@@ -193,9 +193,9 @@ impl RealizedExtended {
exit,
&base.realized_price_extra.ratio.height,
)?;
self.realized_price_ratio_ext.compute_usd_bands(
self.realized_price_ratio_ext.compute_cents_bands(
starting_indexes,
&base.realized_price.usd.height,
&base.realized_price.cents.height,
exit,
)?;
@@ -205,9 +205,9 @@ impl RealizedExtended {
exit,
&base.investor_price_extra.ratio.height,
)?;
self.investor_price_ratio_ext.compute_usd_bands(
self.investor_price_ratio_ext.compute_cents_bands(
starting_indexes,
&base.investor_price.usd.height,
&base.investor_price.cents.height,
exit,
)?;

View File

@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height};
use brk_types::{Bitcoin, Cents, Dollars, Height};
use derive_more::{Deref, DerefMut};
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
@@ -36,8 +36,8 @@ impl RealizedWithAdjusted {
starting_indexes: &ComputeIndexes,
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Cents>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.base.compute_rest_part2_base(

View File

@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height};
use brk_types::{Bitcoin, Cents, Dollars, Height};
use derive_more::{Deref, DerefMut};
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
@@ -43,8 +43,8 @@ impl RealizedWithExtendedAdjusted {
starting_indexes: &ComputeIndexes,
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Dollars>,
up_to_1h_value_created: &impl ReadableVec<Height, Cents>,
up_to_1h_value_destroyed: &impl ReadableVec<Height, Cents>,
exit: &Exit,
) -> Result<()> {
self.base.compute_rest_part2_base(

View File

@@ -67,7 +67,7 @@ impl SupplyMetrics {
pub(crate) fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
vec![
&mut self.total.base.sats.height as &mut dyn AnyStoredVec,
&mut self.total.base.usd.height as &mut dyn AnyStoredVec,
&mut self.total.base.cents.height as &mut dyn AnyStoredVec,
]
.into_par_iter()
}
@@ -117,7 +117,7 @@ impl SupplyMetrics {
starting_indexes.height,
&blocks.count.height_1m_ago,
&self.total.sats.height,
&self.total.usd.height,
&self.total.cents.height,
exit,
)
}

View File

@@ -237,9 +237,9 @@ impl UnrealizedBase {
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
vec![
&mut self.supply_in_profit.base.sats.height as &mut dyn AnyStoredVec,
&mut self.supply_in_profit.base.usd.height as &mut dyn AnyStoredVec,
&mut self.supply_in_profit.base.cents.height as &mut dyn AnyStoredVec,
&mut self.supply_in_loss.base.sats.height as &mut dyn AnyStoredVec,
&mut self.supply_in_loss.base.usd.height as &mut dyn AnyStoredVec,
&mut self.supply_in_loss.base.cents.height as &mut dyn AnyStoredVec,
&mut self.unrealized_profit.height,
&mut self.unrealized_loss.height,
&mut self.invested_capital_in_profit.height,