mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-30 04:08:11 -07:00
global: snapshot
This commit is contained in:
@@ -20,9 +20,9 @@ use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredU32, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use rayon::prelude::*;
|
||||
use vecdb::{AnyStoredVec, AnyVec, Database, Rw, StorageMode, WritableVec};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Database, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{indexes, internal::ComputedFromHeightDistribution};
|
||||
use crate::{indexes, internal::{ComputedFromHeightDistribution, WindowStarts}};
|
||||
|
||||
/// Per-block activity counts - reset each block.
|
||||
///
|
||||
@@ -187,6 +187,20 @@ impl ActivityCountVecs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
windows: &WindowStarts<'_>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.reactivated.compute_rest(max_from, windows, exit)?;
|
||||
self.sending.compute_rest(max_from, windows, exit)?;
|
||||
self.receiving.compute_rest(max_from, windows, exit)?;
|
||||
self.balance_increased.compute_rest(max_from, windows, exit)?;
|
||||
self.balance_decreased.compute_rest(max_from, windows, exit)?;
|
||||
self.both.compute_rest(max_from, windows, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Per-address-type activity count vecs.
|
||||
@@ -253,6 +267,18 @@ impl AddressTypeToActivityCountVecs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
windows: &WindowStarts<'_>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
for type_vecs in self.0.values_mut() {
|
||||
type_vecs.compute_rest(max_from, windows, exit)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push_height(
|
||||
&mut self,
|
||||
height: Height,
|
||||
@@ -315,6 +341,17 @@ impl AddressActivityVecs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
windows: &WindowStarts<'_>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.all.compute_rest(max_from, windows, exit)?;
|
||||
self.by_addresstype.compute_rest(max_from, windows, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn truncate_push_height(
|
||||
&mut self,
|
||||
height: Height,
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
//! New address count: delta of total_addr_count (global + per-type)
|
||||
//! New address count: per-block delta of total_addr_count (global + per-type)
|
||||
|
||||
//! New address count: delta of total_addr_count (global + per-type)
|
||||
|
||||
use brk_cohort::{ByAddressType, zip_by_addresstype};
|
||||
use brk_cohort::ByAddressType;
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, StoredU64, Version};
|
||||
use vecdb::{Database, Exit, Ident, Rw, StorageMode};
|
||||
use vecdb::{Database, Exit, Rw, StorageMode};
|
||||
|
||||
use crate::{indexes, internal::{LazyComputedFromHeightFull, WindowStarts}};
|
||||
use crate::{indexes, internal::{ComputedFromHeightCumulativeFull, WindowStarts}};
|
||||
|
||||
use super::TotalAddrCountVecs;
|
||||
|
||||
/// New address count per block (global + per-type)
|
||||
#[derive(Traversable)]
|
||||
pub struct NewAddrCountVecs<M: StorageMode = Rw> {
|
||||
pub all: LazyComputedFromHeightFull<StoredU64, StoredU64, M>,
|
||||
pub all: ComputedFromHeightCumulativeFull<StoredU64, M>,
|
||||
#[traversable(flatten)]
|
||||
pub by_addresstype: ByAddressType<LazyComputedFromHeightFull<StoredU64, StoredU64, M>>,
|
||||
pub by_addresstype: ByAddressType<ComputedFromHeightCumulativeFull<StoredU64, M>>,
|
||||
}
|
||||
|
||||
impl NewAddrCountVecs {
|
||||
@@ -25,23 +23,20 @@ impl NewAddrCountVecs {
|
||||
db: &Database,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
total_addr_count: &TotalAddrCountVecs,
|
||||
) -> Result<Self> {
|
||||
let all = LazyComputedFromHeightFull::forced_import::<Ident>(
|
||||
let all = ComputedFromHeightCumulativeFull::forced_import(
|
||||
db,
|
||||
"new_addr_count",
|
||||
version,
|
||||
&total_addr_count.all.height,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
let by_addresstype: ByAddressType<LazyComputedFromHeightFull<StoredU64, StoredU64>> =
|
||||
zip_by_addresstype(&total_addr_count.by_addresstype, |name, total| {
|
||||
LazyComputedFromHeightFull::forced_import::<Ident>(
|
||||
let by_addresstype: ByAddressType<ComputedFromHeightCumulativeFull<StoredU64>> =
|
||||
ByAddressType::new_with_name(|name| {
|
||||
ComputedFromHeightCumulativeFull::forced_import(
|
||||
db,
|
||||
&format!("{name}_new_addr_count"),
|
||||
version,
|
||||
&total.height,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
@@ -56,12 +51,23 @@ impl NewAddrCountVecs {
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
windows: &WindowStarts<'_>,
|
||||
total_addr_count: &TotalAddrCountVecs,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.all.compute(max_from, windows, exit)?;
|
||||
for vecs in self.by_addresstype.values_mut() {
|
||||
vecs.compute(max_from, windows, exit)?;
|
||||
self.all.compute(max_from, windows, exit, |height_vec| {
|
||||
Ok(height_vec.compute_change(max_from, &total_addr_count.all.height, 1, exit)?)
|
||||
})?;
|
||||
|
||||
for ((_, new), (_, total)) in self
|
||||
.by_addresstype
|
||||
.iter_mut()
|
||||
.zip(total_addr_count.by_addresstype.iter())
|
||||
{
|
||||
new.compute(max_from, windows, exit, |height_vec| {
|
||||
Ok(height_vec.compute_change(max_from, &total.height, 1, exit)?)
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use vecdb::{AnyStoredVec, AnyVec, EagerVec, Exit, ImportableVec, PcoVec, Rw, Sto
|
||||
|
||||
use crate::{
|
||||
ComputeIndexes, blocks,
|
||||
internal::{ComputedFromHeightCumulativeSum, LazyComputedValueFromHeightCumulative, ValueEmaFromHeight},
|
||||
internal::{ComputedFromHeightCumulativeSum, ValueFromHeightCumulative, ValueFromHeightLast},
|
||||
};
|
||||
|
||||
use super::ImportConfig;
|
||||
@@ -15,10 +15,10 @@ use super::ImportConfig;
|
||||
#[derive(Traversable)]
|
||||
pub struct ActivityMetrics<M: StorageMode = Rw> {
|
||||
/// Total satoshis sent at each height + derived indexes
|
||||
pub sent: LazyComputedValueFromHeightCumulative<M>,
|
||||
pub sent: ValueFromHeightCumulative<M>,
|
||||
|
||||
/// 14-day EMA of sent supply (sats, btc, usd)
|
||||
pub sent_14d_ema: ValueEmaFromHeight<M>,
|
||||
pub sent_14d_ema: ValueFromHeightLast<M>,
|
||||
|
||||
/// Satoshi-blocks destroyed (supply * blocks_old when spent)
|
||||
pub satblocks_destroyed: M::Stored<EagerVec<PcoVec<Height, Sats>>>,
|
||||
@@ -37,14 +37,14 @@ impl ActivityMetrics {
|
||||
/// Import activity metrics from database.
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
sent: LazyComputedValueFromHeightCumulative::forced_import(
|
||||
sent: ValueFromHeightCumulative::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("sent"),
|
||||
cfg.version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
|
||||
sent_14d_ema: ValueEmaFromHeight::forced_import(
|
||||
sent_14d_ema: ValueFromHeightLast::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("sent_14d_ema"),
|
||||
cfg.version,
|
||||
@@ -165,8 +165,8 @@ impl ActivityMetrics {
|
||||
) -> Result<()> {
|
||||
let window_starts = blocks.count.window_starts();
|
||||
|
||||
// 14-day rolling average of sent (sats and dollars)
|
||||
self.sent_14d_ema.compute_rolling_average(
|
||||
// 14-day EMA of sent (sats and dollars)
|
||||
self.sent_14d_ema.compute_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent.base.sats.height,
|
||||
|
||||
@@ -262,7 +262,7 @@ impl RealizedAdjusted {
|
||||
// Adjusted SOPR EMAs
|
||||
self.adjusted_sopr_24h_7d_ema
|
||||
.height
|
||||
.compute_rolling_average(
|
||||
.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.adjusted_sopr.height,
|
||||
@@ -270,7 +270,7 @@ impl RealizedAdjusted {
|
||||
)?;
|
||||
self.adjusted_sopr_24h_30d_ema
|
||||
.height
|
||||
.compute_rolling_average(
|
||||
.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1m_ago,
|
||||
&self.adjusted_sopr.height,
|
||||
|
||||
@@ -13,9 +13,9 @@ use crate::{
|
||||
distribution::state::RealizedState,
|
||||
internal::{
|
||||
CentsUnsignedToDollars, ComputedFromHeightCumulative, ComputedFromHeightLast,
|
||||
ComputedFromHeightRatio, DollarsPlus, LazyComputedValueFromHeightCumulative, LazyFromHeightLast,
|
||||
ComputedFromHeightRatio, DollarsPlus, ValueFromHeightCumulative, LazyFromHeightLast,
|
||||
PercentageDollarsF32, Price, Ratio64,
|
||||
StoredF32Identity, ValueEmaFromHeight,
|
||||
StoredF32Identity, ValueFromHeightLast,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -130,10 +130,10 @@ pub struct RealizedBase<M: StorageMode = Rw> {
|
||||
pub peak_regret_rel_to_realized_cap: ComputedFromHeightLast<StoredF32, M>,
|
||||
|
||||
// === Sent in Profit/Loss ===
|
||||
pub sent_in_profit: LazyComputedValueFromHeightCumulative<M>,
|
||||
pub sent_in_profit_14d_ema: ValueEmaFromHeight<M>,
|
||||
pub sent_in_loss: LazyComputedValueFromHeightCumulative<M>,
|
||||
pub sent_in_loss_14d_ema: ValueEmaFromHeight<M>,
|
||||
pub sent_in_profit: ValueFromHeightCumulative<M>,
|
||||
pub sent_in_profit_14d_ema: ValueFromHeightLast<M>,
|
||||
pub sent_in_loss: ValueFromHeightCumulative<M>,
|
||||
pub sent_in_loss_14d_ema: ValueFromHeightLast<M>,
|
||||
}
|
||||
|
||||
impl RealizedBase {
|
||||
@@ -540,25 +540,25 @@ impl RealizedBase {
|
||||
)?,
|
||||
peak_regret,
|
||||
peak_regret_rel_to_realized_cap,
|
||||
sent_in_profit: LazyComputedValueFromHeightCumulative::forced_import(
|
||||
sent_in_profit: ValueFromHeightCumulative::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("sent_in_profit"),
|
||||
cfg.version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
sent_in_profit_14d_ema: ValueEmaFromHeight::forced_import(
|
||||
sent_in_profit_14d_ema: ValueFromHeightLast::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("sent_in_profit_14d_ema"),
|
||||
cfg.version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
sent_in_loss: LazyComputedValueFromHeightCumulative::forced_import(
|
||||
sent_in_loss: ValueFromHeightCumulative::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("sent_in_loss"),
|
||||
cfg.version,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
sent_in_loss_14d_ema: ValueEmaFromHeight::forced_import(
|
||||
sent_in_loss_14d_ema: ValueFromHeightLast::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("sent_in_loss_14d_ema"),
|
||||
cfg.version,
|
||||
@@ -1021,14 +1021,14 @@ impl RealizedBase {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// 7d rolling averages
|
||||
self.realized_profit_7d_ema.height.compute_rolling_average(
|
||||
// 7d EMAs
|
||||
self.realized_profit_7d_ema.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.realized_profit.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_7d_ema.height.compute_rolling_average(
|
||||
self.realized_loss_7d_ema.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.realized_loss.height,
|
||||
@@ -1036,22 +1036,22 @@ impl RealizedBase {
|
||||
)?;
|
||||
self.net_realized_pnl_7d_ema
|
||||
.height
|
||||
.compute_rolling_average(
|
||||
.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.net_realized_pnl.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// 14-day rolling average of sent in profit/loss
|
||||
self.sent_in_profit_14d_ema.compute_rolling_average(
|
||||
// 14-day EMA of sent in profit/loss
|
||||
self.sent_in_profit_14d_ema.compute_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent_in_profit.base.sats.height,
|
||||
&self.sent_in_profit.base.usd.height,
|
||||
exit,
|
||||
)?;
|
||||
self.sent_in_loss_14d_ema.compute_rolling_average(
|
||||
self.sent_in_loss_14d_ema.compute_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_2w_ago,
|
||||
&self.sent_in_loss.base.sats.height,
|
||||
@@ -1060,13 +1060,13 @@ impl RealizedBase {
|
||||
)?;
|
||||
|
||||
// SOPR EMAs
|
||||
self.sopr_24h_7d_ema.height.compute_rolling_average(
|
||||
self.sopr_24h_7d_ema.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.sopr.height,
|
||||
exit,
|
||||
)?;
|
||||
self.sopr_24h_30d_ema.height.compute_rolling_average(
|
||||
self.sopr_24h_30d_ema.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1m_ago,
|
||||
&self.sopr.height,
|
||||
@@ -1076,7 +1076,7 @@ impl RealizedBase {
|
||||
// Sell side risk EMAs
|
||||
self.sell_side_risk_ratio_24h_7d_ema
|
||||
.height
|
||||
.compute_rolling_average(
|
||||
.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1w_ago,
|
||||
&self.sell_side_risk_ratio.height,
|
||||
@@ -1084,7 +1084,7 @@ impl RealizedBase {
|
||||
)?;
|
||||
self.sell_side_risk_ratio_24h_30d_ema
|
||||
.height
|
||||
.compute_rolling_average(
|
||||
.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
&blocks.count.height_1m_ago,
|
||||
&self.sell_side_risk_ratio.height,
|
||||
|
||||
@@ -8,7 +8,7 @@ use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::internal::{
|
||||
HalveDollars, HalveSats, HalveSatsToBitcoin,
|
||||
LazyValueFromHeightLast, ValueChangeFromHeight, ValueFromHeightLast,
|
||||
LazyValueFromHeightLast, ValueFromHeightChange, ValueFromHeightLast,
|
||||
};
|
||||
|
||||
use super::ImportConfig;
|
||||
@@ -19,7 +19,7 @@ pub struct SupplyMetrics<M: StorageMode = Rw> {
|
||||
pub total: ValueFromHeightLast<M>,
|
||||
pub halved: LazyValueFromHeightLast,
|
||||
/// 30-day change in supply (net position change) - sats, btc, usd
|
||||
pub _30d_change: ValueChangeFromHeight<M>,
|
||||
pub _30d_change: ValueFromHeightChange<M>,
|
||||
}
|
||||
|
||||
impl SupplyMetrics {
|
||||
@@ -38,7 +38,7 @@ impl SupplyMetrics {
|
||||
HalveDollars,
|
||||
>(&cfg.name("supply_halved"), &supply, cfg.version);
|
||||
|
||||
let _30d_change = ValueChangeFromHeight::forced_import(
|
||||
let _30d_change = ValueFromHeightChange::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("_30d_change"),
|
||||
cfg.version,
|
||||
|
||||
@@ -52,7 +52,7 @@ pub struct Vecs<M: StorageMode = Rw> {
|
||||
|
||||
/// Total addresses ever seen (addr_count + empty_addr_count) - stored, global + per-type
|
||||
pub total_addr_count: TotalAddrCountVecs<M>,
|
||||
/// New addresses per block (delta of total) - lazy height, stored day1 stats, global + per-type
|
||||
/// New addresses per block (delta of total) - stored height + cumulative + rolling, global + per-type
|
||||
pub new_addr_count: NewAddrCountVecs<M>,
|
||||
/// Growth rate (new / addr_count) - stored ratio with distribution stats, global + per-type
|
||||
pub growth_rate: GrowthRateVecs<M>,
|
||||
@@ -117,9 +117,9 @@ impl Vecs {
|
||||
// Stored total = addr_count + empty_addr_count (global + per-type, with all derived indexes)
|
||||
let total_addr_count = TotalAddrCountVecs::forced_import(&db, version, indexes)?;
|
||||
|
||||
// Lazy delta of total (global + per-type)
|
||||
// Per-block delta of total (global + per-type)
|
||||
let new_addr_count =
|
||||
NewAddrCountVecs::forced_import(&db, version, indexes, &total_addr_count)?;
|
||||
NewAddrCountVecs::forced_import(&db, version, indexes)?;
|
||||
|
||||
// Growth rate: new / addr_count (global + per-type)
|
||||
let growth_rate = GrowthRateVecs::forced_import(&db, version, indexes)?;
|
||||
@@ -352,10 +352,12 @@ impl Vecs {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// 6d. Compute new_addr_count cumulative + rolling (height is lazy delta)
|
||||
let window_starts = blocks.count.window_starts();
|
||||
|
||||
self.address_activity
|
||||
.compute_rest(starting_indexes.height, &window_starts, exit)?;
|
||||
self.new_addr_count
|
||||
.compute(starting_indexes.height, &window_starts, exit)?;
|
||||
.compute(starting_indexes.height, &window_starts, &self.total_addr_count, exit)?;
|
||||
|
||||
// 6e. Compute growth_rate = new_addr_count / addr_count
|
||||
self.growth_rate.compute(
|
||||
|
||||
Reference in New Issue
Block a user