global: snapshot

This commit is contained in:
nym21
2026-03-07 17:05:45 +01:00
parent d4faedfba1
commit cbad78962f
18 changed files with 349 additions and 82 deletions
@@ -12,8 +12,8 @@ use crate::{
CentsType, ComputedFromHeight, ComputedFromHeightCumulative,
ComputedFromHeightCumulativeSum, ComputedFromHeightRatio, FiatFromHeight, NumericValue,
PercentFromHeight, PercentRollingEmas1w1m, PercentRollingWindows, Price, RollingEmas1w1m,
RollingEmas2w, RollingWindows, ValueFromHeight, ValueFromHeightChange,
ValueFromHeightCumulative,
RollingEmas2w, RollingWindow24h, RollingWindows, RollingWindowsFrom1w,
ValueFromHeight, ValueFromHeightChange, ValueFromHeightCumulative,
},
};
@@ -71,6 +71,16 @@ impl<T: NumericValue + JsonSchema> ConfigImport for RollingWindows<T> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
impl<T: NumericValue + JsonSchema> ConfigImport for RollingWindow24h<T> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
impl<T: NumericValue + JsonSchema> ConfigImport for RollingWindowsFrom1w<T> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
}
}
impl<T: NumericValue + JsonSchema> ConfigImport for RollingEmas1w1m<T> {
fn config_import(cfg: &ImportConfig, suffix: &str, offset: Version) -> Result<Self> {
Self::forced_import(cfg.db, &cfg.name(suffix), cfg.version + offset, cfg.indexes)
@@ -26,17 +26,15 @@ impl RealizedAdjusted {
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
Ok(RealizedAdjusted {
adjusted_value_created: cfg.import("adjusted_value_created", Version::ZERO)?,
adjusted_value_destroyed: cfg
.import("adjusted_value_destroyed", Version::ZERO)?,
adjusted_value_created_sum: cfg
.import("adjusted_value_created", Version::ONE)?,
adjusted_value_destroyed_sum: cfg
.import("adjusted_value_destroyed", Version::ONE)?,
adjusted_value_destroyed: cfg.import("adjusted_value_destroyed", Version::ZERO)?,
adjusted_value_created_sum: cfg.import("adjusted_value_created", Version::ONE)?,
adjusted_value_destroyed_sum: cfg.import("adjusted_value_destroyed", Version::ONE)?,
adjusted_sopr: cfg.import("adjusted_sopr", Version::ONE)?,
adjusted_sopr_ema: cfg.import("adjusted_sopr_24h", Version::ONE)?,
})
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn compute_rest_part2(
&mut self,
blocks: &blocks::Vecs,
@@ -10,9 +10,8 @@ use crate::{
blocks,
distribution::state::RealizedOps,
internal::{
ByUnit, ComputedFromHeight, ComputedFromHeightCumulative, LazyFromHeight,
NegCentsUnsignedToDollars, RatioCents64, RollingWindows, SatsToCents,
ValueFromHeightCumulative,
ComputedFromHeight, ComputedFromHeightCumulative, LazyFromHeight,
NegCentsUnsignedToDollars, RatioCents64, RollingWindow24h, ValueFromHeightCumulative,
},
prices,
};
@@ -35,9 +34,9 @@ pub struct RealizedBase<M: StorageMode = Rw> {
pub value_created: ComputedFromHeight<Cents, M>,
pub value_destroyed: ComputedFromHeight<Cents, M>,
pub value_created_sum: RollingWindows<Cents, M>,
pub value_destroyed_sum: RollingWindows<Cents, M>,
pub sopr: RollingWindows<StoredF64, M>,
pub value_created_sum: RollingWindow24h<Cents, M>,
pub value_destroyed_sum: RollingWindow24h<Cents, M>,
pub sopr: RollingWindow24h<StoredF64, M>,
pub sent_in_profit: ValueFromHeightCumulative<M>,
pub sent_in_loss: ValueFromHeightCumulative<M>,
@@ -182,35 +181,26 @@ impl RealizedBase {
exit,
)?;
// SOPR: rolling sums of stateful value_created/destroyed, then ratio, then EMAs
let window_starts = blocks.count.window_starts();
// SOPR 24h: rolling sum of stateful value_created/destroyed, then ratio
self.value_created_sum.compute_rolling_sum(
starting_indexes.height,
&window_starts,
&blocks.count.height_24h_ago,
&self.value_created.height,
exit,
)?;
self.value_destroyed_sum.compute_rolling_sum(
starting_indexes.height,
&window_starts,
&blocks.count.height_24h_ago,
&self.value_destroyed.height,
exit,
)?;
for ((sopr, vc), vd) in self
.sopr
.as_mut_array()
.into_iter()
.zip(self.value_created_sum.as_array())
.zip(self.value_destroyed_sum.as_array())
{
sopr.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&vc.height,
&vd.height,
exit,
)?;
}
self.sopr._24h.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&self.value_created_sum._24h.height,
&self.value_destroyed_sum._24h.height,
exit,
)?;
Ok(())
}
@@ -19,7 +19,7 @@ use crate::{
ComputedFromHeightRatioStdDevBands, LazyFromHeight, PercentFromHeight,
PercentRollingEmas1w1m, PercentRollingWindows, Price, RatioCents64, RatioCentsBp32,
RatioCentsSignedCentsBps32, RatioCentsSignedDollarsBps32, RatioDollarsBp32,
RollingEmas1w1m, RollingEmas2w, RollingWindows,
RollingEmas1w1m, RollingEmas2w, RollingWindows, RollingWindowsFrom1w,
},
prices,
};
@@ -82,6 +82,10 @@ pub struct RealizedFull<M: StorageMode = Rw> {
pub sopr_24h_ema: RollingEmas1w1m<StoredF64, M>,
pub value_created_sum_extended: RollingWindowsFrom1w<Cents, M>,
pub value_destroyed_sum_extended: RollingWindowsFrom1w<Cents, M>,
pub sopr_extended: RollingWindowsFrom1w<StoredF64, M>,
pub sent_in_profit_ema: RollingEmas2w<M>,
pub sent_in_loss_ema: RollingEmas2w<M>,
@@ -154,6 +158,9 @@ impl RealizedFull {
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)?;
let sopr_24h_ema = cfg.import("sopr_24h", v1)?;
let value_created_sum_extended = cfg.import("value_created", v1)?;
let value_destroyed_sum_extended = cfg.import("value_destroyed", v1)?;
let sopr_extended = cfg.import("sopr", v1)?;
let sent_in_profit_ema = cfg.import("sent_in_profit", v0)?;
let sent_in_loss_ema = cfg.import("sent_in_loss", v0)?;
@@ -195,6 +202,9 @@ impl RealizedFull {
realized_loss_ema_1w,
net_realized_pnl_ema_1w,
sopr_24h_ema,
value_created_sum_extended,
value_destroyed_sum_extended,
sopr_extended,
sent_in_profit_ema,
sent_in_loss_ema,
realized_price_ratio_percentiles: ComputedFromHeightRatioPercentiles::forced_import(
@@ -314,6 +324,35 @@ impl RealizedFull {
exit,
)?;
// Extended rolling windows (1w, 1m, 1y) for value_created/destroyed/sopr
let window_starts = blocks.count.window_starts();
self.value_created_sum_extended.compute_rolling_sum(
starting_indexes.height,
&window_starts,
&self.core.value_created.height,
exit,
)?;
self.value_destroyed_sum_extended.compute_rolling_sum(
starting_indexes.height,
&window_starts,
&self.core.value_destroyed.height,
exit,
)?;
for ((sopr, vc), vd) in self
.sopr_extended
.as_mut_array()
.into_iter()
.zip(self.value_created_sum_extended.as_array())
.zip(self.value_destroyed_sum_extended.as_array())
{
sopr.compute_binary::<Cents, Cents, RatioCents64>(
starting_indexes.height,
&vc.height,
&vd.height,
exit,
)?;
}
// Realized P/L rel to realized cap
self.realized_profit_rel_to_realized_cap
.compute_binary::<Cents, Cents, RatioCentsBp32>(
@@ -60,3 +60,127 @@ where
Ok(())
}
}
/// Single 24h rolling window (1 stored vec).
#[derive(Traversable)]
pub struct RollingWindow24h<T, M: StorageMode = Rw>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
#[traversable(rename = "24h")]
pub _24h: ComputedFromHeight<T, M>,
}
impl<T> RollingWindow24h<T>
where
T: NumericValue + JsonSchema,
{
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Ok(Self {
_24h: ComputedFromHeight::forced_import(
db,
&format!("{name}_24h"),
version,
indexes,
)?,
})
}
pub(crate) fn compute_rolling_sum(
&mut self,
max_from: Height,
height_24h_ago: &impl ReadableVec<Height, Height>,
source: &impl ReadableVec<Height, T>,
exit: &Exit,
) -> Result<()>
where
T: Default + SubAssign,
{
self._24h
.height
.compute_rolling_sum(max_from, height_24h_ago, source, exit)?;
Ok(())
}
}
/// Extended rolling windows: 1w + 1m + 1y (3 stored vecs).
#[derive(Traversable)]
pub struct RollingWindowsFrom1w<T, M: StorageMode = Rw>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
#[traversable(rename = "1w")]
pub _1w: ComputedFromHeight<T, M>,
#[traversable(rename = "1m")]
pub _1m: ComputedFromHeight<T, M>,
#[traversable(rename = "1y")]
pub _1y: ComputedFromHeight<T, M>,
}
impl<T> RollingWindowsFrom1w<T>
where
T: NumericValue + JsonSchema,
{
pub(crate) fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Ok(Self {
_1w: ComputedFromHeight::forced_import(
db,
&format!("{name}_1w"),
version,
indexes,
)?,
_1m: ComputedFromHeight::forced_import(
db,
&format!("{name}_1m"),
version,
indexes,
)?,
_1y: ComputedFromHeight::forced_import(
db,
&format!("{name}_1y"),
version,
indexes,
)?,
})
}
pub fn as_array(&self) -> [&ComputedFromHeight<T>; 3] {
[&self._1w, &self._1m, &self._1y]
}
pub fn as_mut_array(&mut self) -> [&mut ComputedFromHeight<T>; 3] {
[&mut self._1w, &mut self._1m, &mut self._1y]
}
pub(crate) fn compute_rolling_sum(
&mut self,
max_from: Height,
windows: &WindowStarts<'_>,
source: &impl ReadableVec<Height, T>,
exit: &Exit,
) -> Result<()>
where
T: Default + SubAssign,
{
self._1w
.height
.compute_rolling_sum(max_from, windows._1w, source, exit)?;
self._1m
.height
.compute_rolling_sum(max_from, windows._1m, source, exit)?;
self._1y
.height
.compute_rolling_sum(max_from, windows._1y, source, exit)?;
Ok(())
}
}