mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-29 22:39:26 -07:00
global: snapshot
This commit is contained in:
@@ -528,7 +528,6 @@ impl UTXOCohorts<Rw> {
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_market_cap,
|
||||
ss,
|
||||
exit,
|
||||
)
|
||||
@@ -540,7 +539,6 @@ impl UTXOCohorts<Rw> {
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_market_cap,
|
||||
ss,
|
||||
exit,
|
||||
)
|
||||
@@ -557,7 +555,6 @@ impl UTXOCohorts<Rw> {
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_market_cap,
|
||||
ss,
|
||||
exit,
|
||||
)
|
||||
@@ -569,7 +566,6 @@ impl UTXOCohorts<Rw> {
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_market_cap,
|
||||
ss,
|
||||
exit,
|
||||
)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use brk_cohort::Filter;
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Dollars, Height, Indexes, Sats, Version};
|
||||
use brk_types::{Height, Indexes, Sats, Version};
|
||||
use vecdb::{AnyStoredVec, Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{blocks, prices};
|
||||
@@ -133,7 +133,6 @@ impl CoreCohortMetrics {
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
all_supply_sats: &impl ReadableVec<Height, Sats>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
@@ -149,7 +148,6 @@ impl CoreCohortMetrics {
|
||||
starting_indexes.height,
|
||||
&self.unrealized,
|
||||
&self.supply.total.sats.height,
|
||||
height_to_market_cap,
|
||||
all_supply_sats,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes,
|
||||
StoredF64, Version,
|
||||
};
|
||||
use brk_types::{Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, StoredF64, Version};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec,
|
||||
@@ -15,8 +12,8 @@ use crate::{
|
||||
internal::{
|
||||
ComputedFromHeight, ComputedFromHeightCumulative,
|
||||
ComputedFromHeightRatioPercentiles, FiatFromHeight,
|
||||
LazyFromHeight, NegCentsUnsignedToDollars, PercentFromHeight, RatioCents64,
|
||||
RatioCentsBp32, RatioCentsSignedCentsBps32, RollingWindows, ValueFromHeightCumulative,
|
||||
LazyFromHeight, NegCentsUnsignedToDollars, RatioCents64,
|
||||
RollingWindows, ValueFromHeightCumulative,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -38,10 +35,6 @@ pub struct RealizedBase<M: StorageMode = Rw> {
|
||||
pub net_realized_pnl: ComputedFromHeightCumulative<CentsSigned, M>,
|
||||
pub gross_pnl: FiatFromHeight<Cents, M>,
|
||||
|
||||
pub realized_profit_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub realized_loss_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub net_realized_pnl_rel_to_realized_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
|
||||
pub value_created: ComputedFromHeight<Cents, M>,
|
||||
pub value_destroyed: ComputedFromHeight<Cents, M>,
|
||||
pub value_created_sum: RollingWindows<Cents, M>,
|
||||
@@ -71,13 +64,6 @@ impl RealizedBase {
|
||||
let net_realized_pnl = cfg.import("net_realized_pnl", v0)?;
|
||||
let gross_pnl = cfg.import("realized_gross_pnl", v0)?;
|
||||
|
||||
let realized_profit_rel_to_realized_cap =
|
||||
cfg.import("realized_profit_rel_to_realized_cap", Version::new(2))?;
|
||||
let realized_loss_rel_to_realized_cap =
|
||||
cfg.import("realized_loss_rel_to_realized_cap", Version::new(2))?;
|
||||
let net_realized_pnl_rel_to_realized_cap =
|
||||
cfg.import("net_realized_pnl_rel_to_realized_cap", Version::new(2))?;
|
||||
|
||||
let value_created = cfg.import("value_created", v0)?;
|
||||
let value_destroyed = cfg.import("value_destroyed", v0)?;
|
||||
let value_created_sum = cfg.import("value_created", v1)?;
|
||||
@@ -98,9 +84,6 @@ impl RealizedBase {
|
||||
neg_realized_loss,
|
||||
net_realized_pnl,
|
||||
gross_pnl,
|
||||
realized_profit_rel_to_realized_cap,
|
||||
realized_loss_rel_to_realized_cap,
|
||||
net_realized_pnl_rel_to_realized_cap,
|
||||
value_created,
|
||||
value_destroyed,
|
||||
value_created_sum,
|
||||
@@ -221,28 +204,6 @@ impl RealizedBase {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.realized_profit_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.minimal.realized_profit.height,
|
||||
&self.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.minimal.realized_loss.height,
|
||||
&self.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_realized_pnl_rel_to_realized_cap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_realized_pnl.height,
|
||||
&self.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// SOPR: rolling sums of stateful value_created/destroyed, then ratio, then EMAs
|
||||
let window_starts = blocks.count.window_starts();
|
||||
self.value_created_sum.compute_rolling_sum(
|
||||
|
||||
@@ -35,6 +35,10 @@ pub struct RealizedFull<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub core: RealizedBase<M>,
|
||||
|
||||
pub realized_profit_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub realized_loss_rel_to_realized_cap: PercentFromHeight<BasisPoints32, M>,
|
||||
pub net_realized_pnl_rel_to_realized_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
|
||||
pub profit_value_created: ComputedFromHeight<Cents, M>,
|
||||
pub profit_value_destroyed: ComputedFromHeight<Cents, M>,
|
||||
pub loss_value_created: ComputedFromHeight<Cents, M>,
|
||||
@@ -134,6 +138,13 @@ impl RealizedFull {
|
||||
let investor_price_name = cfg.name("investor_price");
|
||||
let investor_price_version = cfg.version;
|
||||
|
||||
let realized_profit_rel_to_realized_cap =
|
||||
cfg.import("realized_profit_rel_to_realized_cap", Version::new(2))?;
|
||||
let realized_loss_rel_to_realized_cap =
|
||||
cfg.import("realized_loss_rel_to_realized_cap", Version::new(2))?;
|
||||
let net_realized_pnl_rel_to_realized_cap =
|
||||
cfg.import("net_realized_pnl_rel_to_realized_cap", Version::new(2))?;
|
||||
|
||||
let realized_profit_ema_1w = cfg.import("realized_profit_ema_1w", v0)?;
|
||||
let realized_loss_ema_1w = cfg.import("realized_loss_ema_1w", v0)?;
|
||||
let net_realized_pnl_ema_1w = cfg.import("net_realized_pnl_ema_1w", v0)?;
|
||||
@@ -143,6 +154,9 @@ impl RealizedFull {
|
||||
|
||||
Ok(Self {
|
||||
core,
|
||||
realized_profit_rel_to_realized_cap,
|
||||
realized_loss_rel_to_realized_cap,
|
||||
net_realized_pnl_rel_to_realized_cap,
|
||||
profit_value_created,
|
||||
profit_value_destroyed,
|
||||
loss_value_created,
|
||||
@@ -288,6 +302,29 @@ impl RealizedFull {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Realized P/L rel to realized cap
|
||||
self.realized_profit_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.core.minimal.realized_profit.height,
|
||||
&self.core.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.realized_loss_rel_to_realized_cap
|
||||
.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&self.core.minimal.realized_loss.height,
|
||||
&self.core.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_realized_pnl_rel_to_realized_cap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.core.net_realized_pnl.height,
|
||||
&self.core.minimal.realized_cap_cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// EMAs
|
||||
self.realized_profit_ema_1w.height.compute_rolling_ema(
|
||||
starting_indexes.height,
|
||||
|
||||
@@ -1,61 +1,28 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, BasisPointsSigned32, Dollars, Height, Sats, StoredF32, Version};
|
||||
use vecdb::{Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
|
||||
use brk_types::{BasisPoints16, Height, Sats, Version};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::internal::{
|
||||
Bps32ToFloat, LazyFromHeight, NegRatioDollarsBps32, PercentFromHeight, RatioDollarsBp16,
|
||||
RatioDollarsBps32, RatioSatsBp16,
|
||||
};
|
||||
use crate::internal::{PercentFromHeight, RatioSatsBp16};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, UnrealizedBase};
|
||||
|
||||
/// Relative metrics for the Complete tier (~6 fields).
|
||||
///
|
||||
/// Excludes source-only fields (invested_capital_in_profit/loss_rel_to_realized_cap).
|
||||
/// Relative metrics for the Complete tier.
|
||||
#[derive(Traversable)]
|
||||
pub struct RelativeBase<M: StorageMode = Rw> {
|
||||
pub supply_in_profit_rel_to_own_supply: PercentFromHeight<BasisPoints16, M>,
|
||||
pub supply_in_loss_rel_to_own_supply: PercentFromHeight<BasisPoints16, M>,
|
||||
|
||||
pub unrealized_profit_rel_to_market_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub unrealized_loss_rel_to_market_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub net_unrealized_pnl_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub neg_unrealized_loss_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub nupl: LazyFromHeight<StoredF32, BasisPointsSigned32>,
|
||||
}
|
||||
|
||||
impl RelativeBase {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v1 = Version::ONE;
|
||||
let v2 = Version::new(2);
|
||||
|
||||
let net_unrealized_pnl_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32> =
|
||||
cfg.import("net_unrealized_pnl_rel_to_market_cap", Version::new(3))?;
|
||||
|
||||
let nupl = LazyFromHeight::from_computed::<Bps32ToFloat>(
|
||||
&cfg.name("nupl"),
|
||||
cfg.version + Version::new(3),
|
||||
net_unrealized_pnl_rel_to_market_cap
|
||||
.bps
|
||||
.height
|
||||
.read_only_boxed_clone(),
|
||||
&net_unrealized_pnl_rel_to_market_cap.bps,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
supply_in_profit_rel_to_own_supply: cfg
|
||||
.import("supply_in_profit_rel_to_own_supply", v1)?,
|
||||
supply_in_loss_rel_to_own_supply: cfg
|
||||
.import("supply_in_loss_rel_to_own_supply", v1)?,
|
||||
unrealized_profit_rel_to_market_cap: cfg
|
||||
.import("unrealized_profit_rel_to_market_cap", v2)?,
|
||||
unrealized_loss_rel_to_market_cap: cfg
|
||||
.import("unrealized_loss_rel_to_market_cap", v2)?,
|
||||
net_unrealized_pnl_rel_to_market_cap,
|
||||
neg_unrealized_loss_rel_to_market_cap: cfg
|
||||
.import("neg_unrealized_loss_rel_to_market_cap", Version::new(3))?,
|
||||
nupl,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -64,7 +31,6 @@ impl RelativeBase {
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedBase,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.supply_in_profit_rel_to_own_supply
|
||||
@@ -81,34 +47,6 @@ impl RelativeBase {
|
||||
supply_total_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized_profit_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.unrealized_profit.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized_loss_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.unrealized_loss.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.net_unrealized_pnl_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBps32>(
|
||||
max_from,
|
||||
&unrealized.net_unrealized_pnl.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.neg_unrealized_loss_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, NegRatioDollarsBps32>(
|
||||
max_from,
|
||||
&unrealized.unrealized_loss.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, Dollars, Height, Sats, Version};
|
||||
use brk_types::{
|
||||
BasisPoints16, BasisPointsSigned32, Dollars, Height, Sats, StoredF32, Version,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
use vecdb::{Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::internal::{PercentFromHeight, RatioDollarsBp16};
|
||||
use crate::internal::{
|
||||
Bps32ToFloat, LazyFromHeight, NegRatioDollarsBps32, PercentFromHeight, RatioDollarsBp16,
|
||||
RatioDollarsBps32,
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, RealizedBase, UnrealizedFull};
|
||||
|
||||
use super::RelativeBase;
|
||||
|
||||
/// Full relative metrics (Source/Extended tier).
|
||||
///
|
||||
/// Contains all Complete-tier fields (via Deref to RelativeBase) plus:
|
||||
/// - Source-only: invested_capital_in_profit/loss_rel_to_realized_cap
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct RelativeFull<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
@@ -21,7 +23,12 @@ pub struct RelativeFull<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub base: RelativeBase<M>,
|
||||
|
||||
// --- Source-only fields ---
|
||||
pub unrealized_profit_rel_to_market_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub unrealized_loss_rel_to_market_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub net_unrealized_pnl_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub neg_unrealized_loss_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32, M>,
|
||||
pub nupl: LazyFromHeight<StoredF32, BasisPointsSigned32>,
|
||||
|
||||
pub invested_capital_in_profit_rel_to_realized_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
pub invested_capital_in_loss_rel_to_realized_cap: PercentFromHeight<BasisPoints16, M>,
|
||||
}
|
||||
@@ -30,8 +37,32 @@ impl RelativeFull {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let base = RelativeBase::forced_import(cfg)?;
|
||||
|
||||
let v2 = Version::new(2);
|
||||
let v3 = Version::new(3);
|
||||
|
||||
let net_unrealized_pnl_rel_to_market_cap: PercentFromHeight<BasisPointsSigned32> =
|
||||
cfg.import("net_unrealized_pnl_rel_to_market_cap", v3)?;
|
||||
|
||||
let nupl = LazyFromHeight::from_computed::<Bps32ToFloat>(
|
||||
&cfg.name("nupl"),
|
||||
cfg.version + v3,
|
||||
net_unrealized_pnl_rel_to_market_cap
|
||||
.bps
|
||||
.height
|
||||
.read_only_boxed_clone(),
|
||||
&net_unrealized_pnl_rel_to_market_cap.bps,
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
base,
|
||||
unrealized_profit_rel_to_market_cap: cfg
|
||||
.import("unrealized_profit_rel_to_market_cap", v2)?,
|
||||
unrealized_loss_rel_to_market_cap: cfg
|
||||
.import("unrealized_loss_rel_to_market_cap", v2)?,
|
||||
net_unrealized_pnl_rel_to_market_cap,
|
||||
neg_unrealized_loss_rel_to_market_cap: cfg
|
||||
.import("neg_unrealized_loss_rel_to_market_cap", v3)?,
|
||||
nupl,
|
||||
invested_capital_in_profit_rel_to_realized_cap: cfg.import(
|
||||
"invested_capital_in_profit_rel_to_realized_cap",
|
||||
Version::ZERO,
|
||||
@@ -52,16 +83,42 @@ impl RelativeFull {
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute Complete-tier fields
|
||||
self.base.compute(
|
||||
max_from,
|
||||
&unrealized.base,
|
||||
supply_total_sats,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Source-only
|
||||
self.unrealized_profit_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.unrealized_profit.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized_loss_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
&unrealized.unrealized_loss.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.net_unrealized_pnl_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBps32>(
|
||||
max_from,
|
||||
&unrealized.net_unrealized_pnl.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.neg_unrealized_loss_rel_to_market_cap
|
||||
.compute_binary::<Dollars, Dollars, NegRatioDollarsBps32>(
|
||||
max_from,
|
||||
&unrealized.unrealized_loss.usd.height,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.invested_capital_in_profit_rel_to_realized_cap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp16>(
|
||||
max_from,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Dollars, Height, Sats};
|
||||
use brk_types::{Height, Sats};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
@@ -33,7 +33,6 @@ impl RelativeBaseWithRelToAll {
|
||||
max_from: Height,
|
||||
unrealized: &UnrealizedBase,
|
||||
supply_total_sats: &impl ReadableVec<Height, Sats>,
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
all_supply_sats: &impl ReadableVec<Height, Sats>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
@@ -41,7 +40,6 @@ impl RelativeBaseWithRelToAll {
|
||||
max_from,
|
||||
unrealized,
|
||||
supply_total_sats,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.rel_to_all.compute(
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, Height, Indexes, PoolSlug, StoredU32};
|
||||
use vecdb::{
|
||||
BinaryTransform, Database, Exit, ReadableVec, Rw, StorageMode, Version,
|
||||
};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{BinaryTransform, Database, Exit, ReadableVec, Rw, StorageMode, Version};
|
||||
|
||||
use crate::{
|
||||
blocks, indexes,
|
||||
internal::{
|
||||
ComputedFromHeightCumulativeSum, MaskSats, PercentFromHeight,
|
||||
PercentRollingWindows, RatioU32Bp16, ValueFromHeightCumulativeSum,
|
||||
MaskSats, PercentRollingWindows, RatioU32Bp16, RollingWindows,
|
||||
ValueFromHeightCumulativeSum,
|
||||
},
|
||||
mining, prices,
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
slug: PoolSlug,
|
||||
use super::minor;
|
||||
|
||||
pub blocks_mined: ComputedFromHeightCumulativeSum<StoredU32, M>,
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
#[traversable(merge)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
#[traversable(flatten)]
|
||||
pub base: minor::Vecs<M>,
|
||||
|
||||
#[traversable(wrap = "blocks_mined", rename = "sum")]
|
||||
pub blocks_mined_sum: RollingWindows<StoredU32, M>,
|
||||
pub rewards: ValueFromHeightCumulativeSum<M>,
|
||||
pub dominance: PercentFromHeight<BasisPoints16, M>,
|
||||
pub dominance_rolling: PercentRollingWindows<BasisPoints16, M>,
|
||||
}
|
||||
|
||||
@@ -28,33 +33,27 @@ impl Vecs {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
slug: PoolSlug,
|
||||
parent_version: Version,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let suffix = |s: &str| format!("{}_{s}", slug);
|
||||
let version = parent_version;
|
||||
|
||||
let blocks_mined = ComputedFromHeightCumulativeSum::forced_import(
|
||||
db,
|
||||
&suffix("blocks_mined"),
|
||||
version,
|
||||
indexes,
|
||||
)?;
|
||||
let base = minor::Vecs::forced_import(db, slug, version, indexes)?;
|
||||
|
||||
let blocks_mined_sum =
|
||||
RollingWindows::forced_import(db, &suffix("blocks_mined"), version, indexes)?;
|
||||
|
||||
let rewards =
|
||||
ValueFromHeightCumulativeSum::forced_import(db, &suffix("rewards"), version, indexes)?;
|
||||
|
||||
let dominance =
|
||||
PercentFromHeight::forced_import(db, &suffix("dominance"), version, indexes)?;
|
||||
let dominance_rolling =
|
||||
PercentRollingWindows::forced_import(db, &suffix("dominance"), version, indexes)?;
|
||||
|
||||
Ok(Self {
|
||||
dominance,
|
||||
dominance_rolling,
|
||||
slug,
|
||||
blocks_mined,
|
||||
base,
|
||||
blocks_mined_sum,
|
||||
rewards,
|
||||
dominance_rolling,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -68,42 +67,28 @@ impl Vecs {
|
||||
mining: &mining::Vecs,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.base
|
||||
.compute(starting_indexes, height_to_pool, blocks, exit)?;
|
||||
|
||||
let window_starts = blocks.count.window_starts();
|
||||
|
||||
self.blocks_mined
|
||||
.compute(starting_indexes.height, &window_starts, exit, |vec| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
height_to_pool,
|
||||
|(h, id, ..)| {
|
||||
(
|
||||
h,
|
||||
if id == self.slug {
|
||||
StoredU32::ONE
|
||||
} else {
|
||||
StoredU32::ZERO
|
||||
},
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
self.blocks_mined_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.base.blocks_mined.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.dominance
|
||||
.compute_binary::<StoredU32, StoredU32, RatioU32Bp16>(
|
||||
starting_indexes.height,
|
||||
&self.blocks_mined.cumulative.height,
|
||||
&blocks.count.block_count.cumulative.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
for ((dom, mined), total) in self
|
||||
for (dom, (mined, total)) in self
|
||||
.dominance_rolling
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.blocks_mined.sum.as_array())
|
||||
.zip(blocks.count.block_count_sum.as_array())
|
||||
.zip(
|
||||
self.blocks_mined_sum
|
||||
.as_array()
|
||||
.into_iter()
|
||||
.zip(blocks.count.block_count_sum.as_array()),
|
||||
)
|
||||
{
|
||||
dom.compute_binary::<StoredU32, StoredU32, RatioU32Bp16>(
|
||||
starting_indexes.height,
|
||||
@@ -121,7 +106,7 @@ impl Vecs {
|
||||
|vec| {
|
||||
Ok(vec.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.blocks_mined.height,
|
||||
&self.base.blocks_mined.height,
|
||||
&mining.rewards.coinbase.base.sats.height,
|
||||
|(h, mask, val, ..)| (h, MaskSats::apply(mask, val)),
|
||||
exit,
|
||||
85
crates/brk_computer/src/pools/minor.rs
Normal file
85
crates/brk_computer/src/pools/minor.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPoints16, Height, Indexes, PoolSlug, StoredU32};
|
||||
use vecdb::{
|
||||
Database, Exit, ReadableVec, Rw, StorageMode, Version,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
blocks, indexes,
|
||||
internal::{ComputedFromHeightCumulative, PercentFromHeight, RatioU32Bp16},
|
||||
};
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct Vecs<M: StorageMode = Rw> {
|
||||
#[traversable(skip)]
|
||||
slug: PoolSlug,
|
||||
|
||||
pub blocks_mined: ComputedFromHeightCumulative<StoredU32, M>,
|
||||
pub dominance: PercentFromHeight<BasisPoints16, M>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub(crate) fn forced_import(
|
||||
db: &Database,
|
||||
slug: PoolSlug,
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
let suffix = |s: &str| format!("{}_{s}", slug);
|
||||
|
||||
let blocks_mined = ComputedFromHeightCumulative::forced_import(
|
||||
db,
|
||||
&suffix("blocks_mined"),
|
||||
version,
|
||||
indexes,
|
||||
)?;
|
||||
|
||||
let dominance =
|
||||
PercentFromHeight::forced_import(db, &suffix("dominance"), version, indexes)?;
|
||||
|
||||
Ok(Self {
|
||||
slug,
|
||||
blocks_mined,
|
||||
dominance,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_pool: &impl ReadableVec<Height, PoolSlug>,
|
||||
blocks: &blocks::Vecs,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.blocks_mined
|
||||
.compute(starting_indexes.height, exit, |vec| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
height_to_pool,
|
||||
|(h, id, ..)| {
|
||||
(
|
||||
h,
|
||||
if id == self.slug {
|
||||
StoredU32::ONE
|
||||
} else {
|
||||
StoredU32::ZERO
|
||||
},
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.dominance
|
||||
.compute_binary::<StoredU32, StoredU32, RatioU32Bp16>(
|
||||
starting_indexes.height,
|
||||
&self.blocks_mined.cumulative.height,
|
||||
&blocks.count.block_count.cumulative.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@ use vecdb::{
|
||||
VecIndex, Version, WritableVec,
|
||||
};
|
||||
|
||||
mod vecs;
|
||||
pub mod major;
|
||||
pub mod minor;
|
||||
|
||||
use crate::{
|
||||
blocks, indexes,
|
||||
@@ -29,7 +30,8 @@ pub struct Vecs<M: StorageMode = Rw> {
|
||||
pools: &'static Pools,
|
||||
|
||||
pub height_to_pool: M::Stored<BytesVec<Height, PoolSlug>>,
|
||||
pub vecs: BTreeMap<PoolSlug, vecs::Vecs<M>>,
|
||||
pub major: BTreeMap<PoolSlug, major::Vecs<M>>,
|
||||
pub minor: BTreeMap<PoolSlug, minor::Vecs<M>>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -43,15 +45,27 @@ impl Vecs {
|
||||
|
||||
let version = parent_version + Version::new(3) + Version::new(pools.len() as u32);
|
||||
|
||||
let mut major_map = BTreeMap::new();
|
||||
let mut minor_map = BTreeMap::new();
|
||||
|
||||
for pool in pools.iter() {
|
||||
if pool.slug.is_major() {
|
||||
major_map.insert(
|
||||
pool.slug,
|
||||
major::Vecs::forced_import(&db, pool.slug, version, indexes)?,
|
||||
);
|
||||
} else {
|
||||
minor_map.insert(
|
||||
pool.slug,
|
||||
minor::Vecs::forced_import(&db, pool.slug, version, indexes)?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let this = Self {
|
||||
height_to_pool: BytesVec::forced_import(&db, "pool", version)?,
|
||||
vecs: pools
|
||||
.iter()
|
||||
.map(|pool| {
|
||||
vecs::Vecs::forced_import(&db, pool.slug, version, indexes)
|
||||
.map(|vecs| (pool.slug, vecs))
|
||||
})
|
||||
.collect::<Result<BTreeMap<_, _>>>()?,
|
||||
major: major_map,
|
||||
minor: minor_map,
|
||||
pools,
|
||||
db,
|
||||
};
|
||||
@@ -73,7 +87,7 @@ impl Vecs {
|
||||
) -> Result<()> {
|
||||
self.compute_height_to_pool(indexer, indexes, starting_indexes, exit)?;
|
||||
|
||||
self.vecs.par_iter_mut().try_for_each(|(_, vecs)| {
|
||||
self.major.par_iter_mut().try_for_each(|(_, vecs)| {
|
||||
vecs.compute(
|
||||
starting_indexes,
|
||||
&self.height_to_pool,
|
||||
@@ -84,6 +98,10 @@ impl Vecs {
|
||||
)
|
||||
})?;
|
||||
|
||||
self.minor.par_iter_mut().try_for_each(|(_, vecs)| {
|
||||
vecs.compute(starting_indexes, &self.height_to_pool, blocks, exit)
|
||||
})?;
|
||||
|
||||
let _lock = exit.lock();
|
||||
self.db.compact()?;
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user