mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-22 16:38:11 -07:00
global: big snapshot
This commit is contained in:
@@ -4,30 +4,22 @@ use brk_types::{Cents, Height, Indexes, StoredF64, Version};
|
||||
use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
blocks,
|
||||
internal::{ComputedPerBlock, RatioCents64, RollingWindows},
|
||||
distribution::metrics::ImportConfig,
|
||||
internal::{ComputedPerBlockCumulativeWithSums, RatioCents64, RollingWindows},
|
||||
};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct AdjustedSopr<M: StorageMode = Rw> {
|
||||
pub value_created: ComputedPerBlock<Cents, M>,
|
||||
pub value_destroyed: ComputedPerBlock<Cents, M>,
|
||||
#[traversable(wrap = "value_created", rename = "sum")]
|
||||
pub value_created_sum: RollingWindows<Cents, M>,
|
||||
#[traversable(wrap = "value_destroyed", rename = "sum")]
|
||||
pub value_destroyed_sum: RollingWindows<Cents, M>,
|
||||
pub value_created: ComputedPerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub value_destroyed: ComputedPerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub ratio: RollingWindows<StoredF64, M>,
|
||||
}
|
||||
|
||||
impl AdjustedSopr {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
value_created: cfg.import("adj_value_created", Version::ZERO)?,
|
||||
value_destroyed: cfg.import("adj_value_destroyed", Version::ZERO)?,
|
||||
value_created_sum: cfg.import("adj_value_created", Version::ONE)?,
|
||||
value_destroyed_sum: cfg.import("adj_value_destroyed", Version::ONE)?,
|
||||
value_created: cfg.import("adj_value_created", Version::ONE)?,
|
||||
value_destroyed: cfg.import("adj_value_destroyed", Version::ONE)?,
|
||||
ratio: cfg.import("asopr", Version::ONE)?,
|
||||
})
|
||||
}
|
||||
@@ -35,7 +27,6 @@ impl AdjustedSopr {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
base_value_created: &impl ReadableVec<Height, Cents>,
|
||||
base_value_destroyed: &impl ReadableVec<Height, Cents>,
|
||||
@@ -44,41 +35,32 @@ impl AdjustedSopr {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// Compute value_created = base.value_created - under_1h.value_created
|
||||
self.value_created.height.compute_subtract(
|
||||
self.value_created.raw.height.compute_subtract(
|
||||
starting_indexes.height,
|
||||
base_value_created,
|
||||
under_1h_value_created,
|
||||
exit,
|
||||
)?;
|
||||
self.value_destroyed.height.compute_subtract(
|
||||
self.value_destroyed.raw.height.compute_subtract(
|
||||
starting_indexes.height,
|
||||
base_value_destroyed,
|
||||
under_1h_value_destroyed,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Adjusted value created/destroyed rolling sums
|
||||
let window_starts = blocks.lookback.window_starts();
|
||||
self.value_created_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.value_created.height,
|
||||
exit,
|
||||
)?;
|
||||
self.value_destroyed_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.value_destroyed.height,
|
||||
exit,
|
||||
)?;
|
||||
// Cumulatives (rolling sums are lazy)
|
||||
self.value_created
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.value_destroyed
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
// SOPR ratios from rolling sums
|
||||
// SOPR ratios from lazy rolling sums
|
||||
for ((sopr, vc), vd) in self
|
||||
.ratio
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.value_created_sum.as_array())
|
||||
.zip(self.value_destroyed_sum.as_array())
|
||||
.zip(self.value_created.sum.as_array())
|
||||
.zip(self.value_destroyed.sum.as_array())
|
||||
{
|
||||
sopr.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, StoredF64, Version};
|
||||
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,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
blocks,
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
internal::{
|
||||
ComputedPerBlock, FiatRollingDelta1m, LazyPerBlock,
|
||||
NegCentsUnsignedToDollars, PerBlockWithSum24h, RatioCents64,
|
||||
RollingWindow24hPerBlock,
|
||||
FiatPerBlockCumulativeWithSumsAndDeltas, LazyPerBlock, NegCentsUnsignedToDollars,
|
||||
RatioCents64, RollingWindow24hPerBlock,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -33,23 +31,14 @@ pub struct RealizedCore<M: StorageMode = Rw> {
|
||||
#[traversable(flatten)]
|
||||
pub minimal: RealizedMinimal<M>,
|
||||
|
||||
#[traversable(wrap = "profit", rename = "cumulative")]
|
||||
pub profit_cumulative: ComputedPerBlock<Cents, M>,
|
||||
#[traversable(wrap = "loss", rename = "cumulative")]
|
||||
pub loss_cumulative: ComputedPerBlock<Cents, M>,
|
||||
|
||||
#[traversable(wrap = "cap", rename = "delta")]
|
||||
pub cap_delta: FiatRollingDelta1m<Cents, CentsSigned, M>,
|
||||
|
||||
#[traversable(wrap = "loss", rename = "negative")]
|
||||
pub neg_loss: LazyPerBlock<Dollars, Cents>,
|
||||
pub net_pnl: PerBlockWithSum24h<CentsSigned, M>,
|
||||
pub net_pnl: FiatPerBlockCumulativeWithSumsAndDeltas<CentsSigned, CentsSigned, BasisPointsSigned32, M>,
|
||||
pub sopr: RealizedSoprCore<M>,
|
||||
}
|
||||
|
||||
impl RealizedCore {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v0 = Version::ZERO;
|
||||
let v1 = Version::ONE;
|
||||
|
||||
let minimal = RealizedMinimal::forced_import(cfg)?;
|
||||
@@ -61,13 +50,19 @@ impl RealizedCore {
|
||||
cfg.indexes,
|
||||
);
|
||||
|
||||
let net_pnl = FiatPerBlockCumulativeWithSumsAndDeltas::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("net_realized_pnl"),
|
||||
cfg.version + v1,
|
||||
Version::new(4),
|
||||
cfg.indexes,
|
||||
cfg.cached_starts,
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
minimal,
|
||||
profit_cumulative: cfg.import("realized_profit_cumulative", v0)?,
|
||||
loss_cumulative: cfg.import("realized_loss_cumulative", v0)?,
|
||||
cap_delta: cfg.import("realized_cap_delta", v1)?,
|
||||
neg_loss: neg_realized_loss,
|
||||
net_pnl: cfg.import("net_realized_pnl", v1)?,
|
||||
net_pnl,
|
||||
sopr: RealizedSoprCore {
|
||||
ratio: cfg.import("sopr", v1)?,
|
||||
},
|
||||
@@ -102,25 +97,13 @@ impl RealizedCore {
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.minimal
|
||||
.compute_rest_part1(blocks, starting_indexes, exit)?;
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.profit_cumulative.height.compute_cumulative(
|
||||
starting_indexes.height,
|
||||
&self.minimal.profit.raw.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.loss_cumulative.height.compute_cumulative(
|
||||
starting_indexes.height,
|
||||
&self.minimal.loss.raw.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.net_pnl.raw.height.compute_transform2(
|
||||
self.net_pnl.raw.cents.height.compute_transform2(
|
||||
starting_indexes.height,
|
||||
&self.minimal.profit.raw.cents.height,
|
||||
&self.minimal.loss.raw.cents.height,
|
||||
@@ -138,7 +121,6 @@ impl RealizedCore {
|
||||
|
||||
pub(crate) fn compute_rest_part2(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
height_to_supply: &impl ReadableVec<Height, Bitcoin>,
|
||||
@@ -147,19 +129,8 @@ impl RealizedCore {
|
||||
self.minimal
|
||||
.compute_rest_part2(prices, starting_indexes, height_to_supply, exit)?;
|
||||
|
||||
self.cap_delta.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback._1m,
|
||||
&self.minimal.cap.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.net_pnl.sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback._24h,
|
||||
&self.net_pnl.raw.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_pnl
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
self.sopr
|
||||
.ratio
|
||||
|
||||
@@ -14,9 +14,10 @@ use crate::{
|
||||
blocks,
|
||||
distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState},
|
||||
internal::{
|
||||
CentsUnsignedToDollars, ComputedPerBlock, ComputedPerBlockCumulative, FiatPerBlock,
|
||||
FiatRollingDelta1m, FiatRollingDeltaExcept1m, LazyPerBlock, PercentPerBlock,
|
||||
PercentRollingWindows, Price, PriceWithRatioExtendedPerBlock, RatioCents64, RatioCentsBp32,
|
||||
CentsUnsignedToDollars, ComputedPerBlock, ComputedPerBlockCumulative,
|
||||
ComputedPerBlockCumulativeWithSums, FiatPerBlockCumulativeWithSums,
|
||||
LazyPerBlock, PercentPerBlock, PercentRollingWindows, Price,
|
||||
PriceWithRatioExtendedPerBlock, RatioCents64, RatioCentsBp32,
|
||||
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDollarsBp32,
|
||||
RatioPerBlockPercentiles, RatioPerBlockStdDevBands, RatioSma, RollingWindows,
|
||||
RollingWindowsFrom1w,
|
||||
@@ -31,47 +32,22 @@ use super::RealizedCore;
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedProfit<M: StorageMode = Rw> {
|
||||
pub rel_to_rcap: PercentPerBlock<BasisPoints32, M>,
|
||||
pub value_created: ComputedPerBlock<Cents, M>,
|
||||
pub value_destroyed: ComputedPerBlock<Cents, M>,
|
||||
#[traversable(wrap = "value_created", rename = "sum")]
|
||||
pub value_created_sum: RollingWindows<Cents, M>,
|
||||
#[traversable(wrap = "value_destroyed", rename = "sum")]
|
||||
pub value_destroyed_sum: RollingWindows<Cents, M>,
|
||||
pub value_created: ComputedPerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub value_destroyed: ComputedPerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub distribution_flow: LazyPerBlock<Dollars, Cents>,
|
||||
#[traversable(rename = "sum")]
|
||||
pub sum_extended: RollingWindowsFrom1w<Cents, M>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedLoss<M: StorageMode = Rw> {
|
||||
pub rel_to_rcap: PercentPerBlock<BasisPoints32, M>,
|
||||
pub value_created: ComputedPerBlock<Cents, M>,
|
||||
pub value_destroyed: ComputedPerBlock<Cents, M>,
|
||||
#[traversable(wrap = "value_created", rename = "sum")]
|
||||
pub value_created_sum: RollingWindows<Cents, M>,
|
||||
#[traversable(wrap = "value_destroyed", rename = "sum")]
|
||||
pub value_destroyed_sum: RollingWindows<Cents, M>,
|
||||
pub value_created: ComputedPerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub value_destroyed: ComputedPerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub capitulation_flow: LazyPerBlock<Dollars, Cents>,
|
||||
#[traversable(rename = "sum")]
|
||||
pub sum_extended: RollingWindowsFrom1w<Cents, M>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedGrossPnl<M: StorageMode = Rw> {
|
||||
pub raw: FiatPerBlock<Cents, M>,
|
||||
pub sum: RollingWindows<Cents, M>,
|
||||
pub sell_side_risk_ratio: PercentRollingWindows<BasisPoints32, M>,
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedNetPnl<M: StorageMode = Rw> {
|
||||
pub rel_to_rcap: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
pub cumulative: ComputedPerBlock<CentsSigned, M>,
|
||||
#[traversable(rename = "sum")]
|
||||
pub sum_extended: RollingWindowsFrom1w<CentsSigned, M>,
|
||||
pub delta: FiatRollingDelta1m<CentsSigned, CentsSigned, M>,
|
||||
#[traversable(rename = "delta")]
|
||||
pub delta_extended: FiatRollingDeltaExcept1m<CentsSigned, CentsSigned, M>,
|
||||
#[traversable(wrap = "change_1m", rename = "rel_to_rcap")]
|
||||
pub change_1m_rel_to_rcap: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
#[traversable(wrap = "change_1m", rename = "rel_to_mcap")]
|
||||
@@ -80,10 +56,6 @@ pub struct RealizedNetPnl<M: StorageMode = Rw> {
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedSopr<M: StorageMode = Rw> {
|
||||
#[traversable(wrap = "value_created", rename = "sum")]
|
||||
pub value_created_sum_extended: RollingWindowsFrom1w<Cents, M>,
|
||||
#[traversable(wrap = "value_destroyed", rename = "sum")]
|
||||
pub value_destroyed_sum_extended: RollingWindowsFrom1w<Cents, M>,
|
||||
#[traversable(rename = "ratio")]
|
||||
pub ratio_extended: RollingWindowsFrom1w<StoredF64, M>,
|
||||
}
|
||||
@@ -100,7 +72,7 @@ pub struct RealizedInvestor<M: StorageMode = Rw> {
|
||||
pub price: PriceWithRatioExtendedPerBlock<M>,
|
||||
pub lower_price_band: Price<ComputedPerBlock<Cents, M>>,
|
||||
pub upper_price_band: Price<ComputedPerBlock<Cents, M>>,
|
||||
#[traversable(wrap = "cap", rename = "raw")]
|
||||
#[traversable(hidden)]
|
||||
pub cap_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
}
|
||||
|
||||
@@ -113,7 +85,8 @@ pub struct RealizedFull<M: StorageMode = Rw> {
|
||||
|
||||
pub profit: RealizedProfit<M>,
|
||||
pub loss: RealizedLoss<M>,
|
||||
pub gross_pnl: RealizedGrossPnl<M>,
|
||||
pub gross_pnl: FiatPerBlockCumulativeWithSums<Cents, M>,
|
||||
pub sell_side_risk_ratio: PercentRollingWindows<BasisPoints32, M>,
|
||||
pub net_pnl: RealizedNetPnl<M>,
|
||||
pub sopr: RealizedSopr<M>,
|
||||
pub peak_regret: RealizedPeakRegret<M>,
|
||||
@@ -121,10 +94,7 @@ pub struct RealizedFull<M: StorageMode = Rw> {
|
||||
|
||||
pub profit_to_loss_ratio: RollingWindows<StoredF64, M>,
|
||||
|
||||
#[traversable(wrap = "cap", rename = "delta")]
|
||||
pub cap_delta_extended: FiatRollingDeltaExcept1m<Cents, CentsSigned, M>,
|
||||
|
||||
#[traversable(wrap = "cap", rename = "raw")]
|
||||
#[traversable(hidden)]
|
||||
pub cap_raw: M::Stored<BytesVec<Height, CentsSats>>,
|
||||
#[traversable(wrap = "cap", rename = "rel_to_own_mcap")]
|
||||
pub cap_rel_to_own_mcap: PercentPerBlock<BasisPoints32, M>,
|
||||
@@ -145,58 +115,46 @@ impl RealizedFull {
|
||||
let core = RealizedCore::forced_import(cfg)?;
|
||||
|
||||
// Profit
|
||||
let profit_value_destroyed: ComputedPerBlock<Cents> =
|
||||
cfg.import("profit_value_destroyed", v0)?;
|
||||
let profit_value_destroyed: ComputedPerBlockCumulativeWithSums<Cents, Cents> =
|
||||
cfg.import("profit_value_destroyed", v1)?;
|
||||
let profit_flow = LazyPerBlock::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("profit_flow"),
|
||||
&cfg.name("distribution_flow"),
|
||||
cfg.version,
|
||||
profit_value_destroyed.height.read_only_boxed_clone(),
|
||||
&profit_value_destroyed,
|
||||
profit_value_destroyed.raw.height.read_only_boxed_clone(),
|
||||
&profit_value_destroyed.raw,
|
||||
);
|
||||
let profit = RealizedProfit {
|
||||
rel_to_rcap: cfg.import("realized_profit_rel_to_rcap", Version::new(2))?,
|
||||
value_created: cfg.import("profit_value_created", v0)?,
|
||||
value_created: cfg.import("profit_value_created", v1)?,
|
||||
value_destroyed: profit_value_destroyed,
|
||||
value_created_sum: cfg.import("profit_value_created", v1)?,
|
||||
value_destroyed_sum: cfg.import("profit_value_destroyed", v1)?,
|
||||
distribution_flow: profit_flow,
|
||||
sum_extended: cfg.import("realized_profit", v1)?,
|
||||
};
|
||||
|
||||
// Loss
|
||||
let loss_value_destroyed: ComputedPerBlock<Cents> =
|
||||
cfg.import("loss_value_destroyed", v0)?;
|
||||
let loss_value_destroyed: ComputedPerBlockCumulativeWithSums<Cents, Cents> =
|
||||
cfg.import("loss_value_destroyed", v1)?;
|
||||
let capitulation_flow = LazyPerBlock::from_computed::<CentsUnsignedToDollars>(
|
||||
&cfg.name("capitulation_flow"),
|
||||
cfg.version,
|
||||
loss_value_destroyed.height.read_only_boxed_clone(),
|
||||
&loss_value_destroyed,
|
||||
loss_value_destroyed.raw.height.read_only_boxed_clone(),
|
||||
&loss_value_destroyed.raw,
|
||||
);
|
||||
let loss = RealizedLoss {
|
||||
rel_to_rcap: cfg.import("realized_loss_rel_to_rcap", Version::new(2))?,
|
||||
value_created: cfg.import("loss_value_created", v0)?,
|
||||
value_created: cfg.import("loss_value_created", v1)?,
|
||||
value_destroyed: loss_value_destroyed,
|
||||
value_created_sum: cfg.import("loss_value_created", v1)?,
|
||||
value_destroyed_sum: cfg.import("loss_value_destroyed", v1)?,
|
||||
capitulation_flow,
|
||||
sum_extended: cfg.import("realized_loss", v1)?,
|
||||
};
|
||||
|
||||
// Gross PnL
|
||||
let gross_pnl = RealizedGrossPnl {
|
||||
raw: cfg.import("realized_gross_pnl", v0)?,
|
||||
sum: cfg.import("gross_pnl_sum", v1)?,
|
||||
sell_side_risk_ratio: cfg.import("sell_side_risk_ratio", Version::new(2))?,
|
||||
};
|
||||
let gross_pnl: FiatPerBlockCumulativeWithSums<Cents> =
|
||||
cfg.import("realized_gross_pnl", v1)?;
|
||||
let sell_side_risk_ratio = cfg.import("sell_side_risk_ratio", Version::new(2))?;
|
||||
|
||||
// Net PnL
|
||||
let net_pnl = RealizedNetPnl {
|
||||
rel_to_rcap: cfg
|
||||
.import("net_realized_pnl_rel_to_rcap", Version::new(2))?,
|
||||
cumulative: cfg.import("net_realized_pnl_cumulative", v1)?,
|
||||
sum_extended: cfg.import("net_realized_pnl", v1)?,
|
||||
delta: cfg.import("net_pnl_delta", Version::new(5))?,
|
||||
delta_extended: cfg.import("net_pnl_delta", Version::new(5))?,
|
||||
change_1m_rel_to_rcap: cfg
|
||||
.import("net_pnl_change_1m_rel_to_rcap", Version::new(4))?,
|
||||
change_1m_rel_to_mcap: cfg
|
||||
@@ -205,8 +163,6 @@ impl RealizedFull {
|
||||
|
||||
// SOPR
|
||||
let sopr = RealizedSopr {
|
||||
value_created_sum_extended: cfg.import("value_created", v1)?,
|
||||
value_destroyed_sum_extended: cfg.import("value_destroyed", v1)?,
|
||||
ratio_extended: cfg.import("sopr", v1)?,
|
||||
};
|
||||
|
||||
@@ -234,12 +190,12 @@ impl RealizedFull {
|
||||
profit,
|
||||
loss,
|
||||
gross_pnl,
|
||||
sell_side_risk_ratio,
|
||||
net_pnl,
|
||||
sopr,
|
||||
peak_regret,
|
||||
investor,
|
||||
profit_to_loss_ratio: cfg.import("realized_profit_to_loss_ratio", v1)?,
|
||||
cap_delta_extended: cfg.import("realized_cap_delta", Version::new(5))?,
|
||||
cap_raw: cfg.import("cap_raw", v0)?,
|
||||
cap_rel_to_own_mcap: cfg.import("realized_cap_rel_to_own_mcap", v1)?,
|
||||
price_ratio_percentiles: RatioPerBlockPercentiles::forced_import(
|
||||
@@ -266,11 +222,12 @@ impl RealizedFull {
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
self.profit
|
||||
.value_created
|
||||
.raw
|
||||
.height
|
||||
.len()
|
||||
.min(self.profit.value_destroyed.height.len())
|
||||
.min(self.loss.value_created.height.len())
|
||||
.min(self.loss.value_destroyed.height.len())
|
||||
.min(self.profit.value_destroyed.raw.height.len())
|
||||
.min(self.loss.value_created.raw.height.len())
|
||||
.min(self.loss.value_destroyed.raw.height.len())
|
||||
.min(self.investor.price.cents.height.len())
|
||||
.min(self.cap_raw.len())
|
||||
.min(self.investor.cap_raw.len())
|
||||
@@ -285,18 +242,22 @@ impl RealizedFull {
|
||||
self.core.truncate_push(height, state)?;
|
||||
self.profit
|
||||
.value_created
|
||||
.raw
|
||||
.height
|
||||
.truncate_push(height, state.realized.profit_value_created())?;
|
||||
self.profit
|
||||
.value_destroyed
|
||||
.raw
|
||||
.height
|
||||
.truncate_push(height, state.realized.profit_value_destroyed())?;
|
||||
self.loss
|
||||
.value_created
|
||||
.raw
|
||||
.height
|
||||
.truncate_push(height, state.realized.loss_value_created())?;
|
||||
self.loss
|
||||
.value_destroyed
|
||||
.raw
|
||||
.height
|
||||
.truncate_push(height, state.realized.loss_value_destroyed())?;
|
||||
self.investor
|
||||
@@ -320,10 +281,10 @@ 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.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.profit.value_destroyed.height);
|
||||
vecs.push(&mut self.loss.value_created.height);
|
||||
vecs.push(&mut self.loss.value_destroyed.height);
|
||||
vecs.push(&mut self.profit.value_created.raw.height as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.profit.value_destroyed.raw.height);
|
||||
vecs.push(&mut self.loss.value_created.raw.height);
|
||||
vecs.push(&mut self.loss.value_destroyed.raw.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);
|
||||
@@ -350,18 +311,22 @@ impl RealizedFull {
|
||||
) -> Result<()> {
|
||||
self.profit
|
||||
.value_created
|
||||
.raw
|
||||
.height
|
||||
.truncate_push(height, accum.profit_value_created)?;
|
||||
self.profit
|
||||
.value_destroyed
|
||||
.raw
|
||||
.height
|
||||
.truncate_push(height, accum.profit_value_destroyed)?;
|
||||
self.loss
|
||||
.value_created
|
||||
.raw
|
||||
.height
|
||||
.truncate_push(height, accum.loss_value_created)?;
|
||||
self.loss
|
||||
.value_destroyed
|
||||
.raw
|
||||
.height
|
||||
.truncate_push(height, accum.loss_value_destroyed)?;
|
||||
self.cap_raw
|
||||
@@ -395,18 +360,11 @@ impl RealizedFull {
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core
|
||||
.compute_rest_part1(blocks, starting_indexes, exit)?;
|
||||
|
||||
self.net_pnl.cumulative.height.compute_cumulative(
|
||||
starting_indexes.height,
|
||||
&self.core.net_pnl.raw.height,
|
||||
exit,
|
||||
)?;
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.peak_regret
|
||||
.value
|
||||
@@ -424,45 +382,20 @@ impl RealizedFull {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.core.compute_rest_part2(
|
||||
blocks,
|
||||
prices,
|
||||
starting_indexes,
|
||||
height_to_supply,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let window_starts = blocks.lookback.window_starts();
|
||||
|
||||
// Net PnL rolling sums (1w, 1m, 1y)
|
||||
self.net_pnl.sum_extended.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.net_pnl.raw.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// SOPR: value created/destroyed rolling sums and ratios
|
||||
self.sopr.value_created_sum_extended.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.minimal.sopr.value_created.raw.height,
|
||||
exit,
|
||||
)?;
|
||||
self.sopr
|
||||
.value_destroyed_sum_extended
|
||||
.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.minimal.sopr.value_destroyed.raw.height,
|
||||
exit,
|
||||
)?;
|
||||
// SOPR ratios from lazy rolling sums
|
||||
for ((sopr, vc), vd) in self
|
||||
.sopr
|
||||
.ratio_extended
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.sopr.value_created_sum_extended.as_array())
|
||||
.zip(self.sopr.value_destroyed_sum_extended.as_array())
|
||||
.zip(self.core.minimal.sopr.value_created.sum.as_array()[1..].iter())
|
||||
.zip(self.core.minimal.sopr.value_destroyed.sum.as_array()[1..].iter())
|
||||
{
|
||||
sopr.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
@@ -493,36 +426,24 @@ impl RealizedFull {
|
||||
.rel_to_rcap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.core.net_pnl.raw.height,
|
||||
&self.core.net_pnl.raw.cents.height,
|
||||
&self.core.minimal.cap.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Profit/loss value created/destroyed rolling sums
|
||||
self.profit.value_created_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.profit.value_created.height,
|
||||
exit,
|
||||
)?;
|
||||
self.profit.value_destroyed_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.profit.value_destroyed.height,
|
||||
exit,
|
||||
)?;
|
||||
self.loss.value_created_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.loss.value_created.height,
|
||||
exit,
|
||||
)?;
|
||||
self.loss.value_destroyed_sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.loss.value_destroyed.height,
|
||||
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.raw.cents.height.compute_add(
|
||||
@@ -531,32 +452,15 @@ impl RealizedFull {
|
||||
&self.core.minimal.loss.raw.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.gross_pnl
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
self.gross_pnl.sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.gross_pnl.raw.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Net PnL delta (1m base + 24h/1w/1y extended)
|
||||
self.net_pnl.delta.compute(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback._1m,
|
||||
&self.net_pnl.cumulative.height,
|
||||
exit,
|
||||
)?;
|
||||
self.net_pnl.delta_extended.compute(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.net_pnl.cumulative.height,
|
||||
exit,
|
||||
)?;
|
||||
// Net PnL 1m change relative to rcap and mcap
|
||||
self.net_pnl
|
||||
.change_1m_rel_to_rcap
|
||||
.compute_binary::<CentsSigned, Cents, RatioCentsSignedCentsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_pnl.delta.change_1m.cents.height,
|
||||
&self.core.net_pnl.delta.change._1m.cents.height,
|
||||
&self.core.minimal.cap.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
@@ -564,19 +468,11 @@ impl RealizedFull {
|
||||
.change_1m_rel_to_mcap
|
||||
.compute_binary::<CentsSigned, Dollars, RatioCentsSignedDollarsBps32>(
|
||||
starting_indexes.height,
|
||||
&self.net_pnl.delta.change_1m.cents.height,
|
||||
&self.core.net_pnl.delta.change._1m.cents.height,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Realized cap delta extended (24h/1w/1y — 1m is in RealizedCore)
|
||||
self.cap_delta_extended.compute(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.minimal.cap.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Peak regret rel to rcap
|
||||
self.peak_regret
|
||||
.rel_to_rcap
|
||||
@@ -636,7 +532,6 @@ impl RealizedFull {
|
||||
|
||||
// Sell-side risk ratios
|
||||
for (ssrr, rv) in self
|
||||
.gross_pnl
|
||||
.sell_side_risk_ratio
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
@@ -644,26 +539,12 @@ impl RealizedFull {
|
||||
{
|
||||
ssrr.compute_binary::<Cents, Cents, RatioCentsBp32>(
|
||||
starting_indexes.height,
|
||||
&rv.height,
|
||||
&rv.cents.height,
|
||||
&self.core.minimal.cap.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
// Profit/loss sum extended (1w, 1m, 1y)
|
||||
self.profit.sum_extended.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.minimal.profit.raw.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.loss.sum_extended.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&window_starts,
|
||||
&self.core.minimal.loss.raw.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Realized cap relative to own market cap
|
||||
self.cap_rel_to_own_mcap
|
||||
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
|
||||
@@ -674,25 +555,17 @@ impl RealizedFull {
|
||||
)?;
|
||||
|
||||
// Realized profit to loss ratios
|
||||
self.profit_to_loss_ratio
|
||||
._24h
|
||||
.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&self.core.minimal.profit.sum._24h.cents.height,
|
||||
&self.core.minimal.loss.sum._24h.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
for ((ratio, profit), loss) in self
|
||||
.profit_to_loss_ratio
|
||||
.as_mut_array_from_1w()
|
||||
.as_mut_array()
|
||||
.into_iter()
|
||||
.zip(self.profit.sum_extended.as_array())
|
||||
.zip(self.loss.sum_extended.as_array())
|
||||
.zip(self.core.minimal.profit.sum.as_array())
|
||||
.zip(self.core.minimal.loss.sum.as_array())
|
||||
{
|
||||
ratio.compute_binary::<Cents, Cents, RatioCents64>(
|
||||
starting_indexes.height,
|
||||
&profit.height,
|
||||
&loss.height,
|
||||
&profit.cents.height,
|
||||
&loss.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints32, Bitcoin, Cents, Height, Indexes, Sats, StoredF32,
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Height, Indexes, Sats, StoredF32,
|
||||
Version,
|
||||
};
|
||||
use vecdb::{
|
||||
@@ -9,11 +9,10 @@ use vecdb::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
blocks,
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
internal::{
|
||||
FiatPerBlock, FiatPerBlockWithSum24h, Identity, LazyPerBlock,
|
||||
PerBlockWithSum24h, PriceWithRatioPerBlock,
|
||||
ComputedPerBlockCumulativeWithSums, FiatPerBlockCumulativeWithSums,
|
||||
FiatPerBlockWithDeltas, Identity, LazyPerBlock, PriceWithRatioPerBlock,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -22,17 +21,15 @@ use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedSoprMinimal<M: StorageMode = Rw> {
|
||||
pub value_created: PerBlockWithSum24h<Cents, M>,
|
||||
pub value_destroyed: PerBlockWithSum24h<Cents, M>,
|
||||
pub value_created: ComputedPerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
pub value_destroyed: ComputedPerBlockCumulativeWithSums<Cents, Cents, M>,
|
||||
}
|
||||
|
||||
/// Minimal realized metrics: cap (fiat), profit/loss (fiat + 24h sum),
|
||||
/// price, mvrv, sopr (value_created/destroyed with 24h sums).
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedMinimal<M: StorageMode = Rw> {
|
||||
pub cap: FiatPerBlock<Cents, M>,
|
||||
pub profit: FiatPerBlockWithSum24h<Cents, M>,
|
||||
pub loss: FiatPerBlockWithSum24h<Cents, M>,
|
||||
pub cap: FiatPerBlockWithDeltas<Cents, CentsSigned, BasisPointsSigned32, M>,
|
||||
pub profit: FiatPerBlockCumulativeWithSums<Cents, M>,
|
||||
pub loss: FiatPerBlockCumulativeWithSums<Cents, M>,
|
||||
pub price: PriceWithRatioPerBlock<M>,
|
||||
pub mvrv: LazyPerBlock<StoredF32>,
|
||||
|
||||
@@ -43,7 +40,14 @@ impl RealizedMinimal {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
let v1 = Version::ONE;
|
||||
|
||||
let cap: FiatPerBlock<Cents> = cfg.import("realized_cap", Version::ZERO)?;
|
||||
let cap = FiatPerBlockWithDeltas::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("realized_cap"),
|
||||
cfg.version,
|
||||
v1,
|
||||
cfg.indexes,
|
||||
cfg.cached_starts,
|
||||
)?;
|
||||
|
||||
let price: PriceWithRatioPerBlock = cfg.import("realized_price", v1)?;
|
||||
let mvrv = LazyPerBlock::from_lazy::<Identity<StoredF32>, BasisPoints32>(
|
||||
@@ -119,34 +123,17 @@ impl RealizedMinimal {
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
&mut self,
|
||||
blocks: &blocks::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.profit.sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback._24h,
|
||||
&self.profit.raw.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.loss.sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback._24h,
|
||||
&self.loss.raw.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.sopr.value_created.sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback._24h,
|
||||
&self.sopr.value_created.raw.height,
|
||||
exit,
|
||||
)?;
|
||||
self.sopr.value_destroyed.sum.compute_rolling_sum(
|
||||
starting_indexes.height,
|
||||
&blocks.lookback._24h,
|
||||
&self.sopr.value_destroyed.raw.height,
|
||||
exit,
|
||||
)?;
|
||||
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)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -12,19 +12,14 @@ use brk_error::Result;
|
||||
use brk_types::{Height, Indexes};
|
||||
use vecdb::Exit;
|
||||
|
||||
use crate::{blocks, distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState}};
|
||||
use crate::distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState};
|
||||
|
||||
/// Polymorphic dispatch for realized metric types.
|
||||
///
|
||||
/// Both `RealizedCore` and `RealizedFull` have the same inherent methods
|
||||
/// but with different behavior (Full checks/pushes more fields).
|
||||
/// This trait enables `CohortMetricsBase` to dispatch correctly via associated type.
|
||||
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 truncate_push(&mut self, height: Height, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) -> Result<()>;
|
||||
fn compute_rest_part1(&mut self, blocks: &blocks::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
@@ -40,8 +35,8 @@ impl RealizedLike for RealizedCore {
|
||||
fn truncate_push(&mut self, height: Height, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) -> Result<()> {
|
||||
self.truncate_push(height, state)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, blocks: &blocks::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(blocks, starting_indexes, exit)
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(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)
|
||||
@@ -55,8 +50,8 @@ impl RealizedLike for RealizedFull {
|
||||
fn truncate_push(&mut self, height: Height, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) -> Result<()> {
|
||||
self.truncate_push(height, state)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, blocks: &blocks::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(blocks, starting_indexes, exit)
|
||||
fn compute_rest_part1(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.compute_rest_part1(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)
|
||||
|
||||
Reference in New Issue
Block a user