global: snapshot part 0

This commit is contained in:
nym21
2026-03-19 22:21:23 +01:00
parent 2ce6a7cee2
commit 19bd17566f
12 changed files with 121 additions and 186 deletions
@@ -17,6 +17,12 @@ pub struct UnrealizedSentiment<M: StorageMode = Rw> {
pub net: FiatPerBlock<CentsSigned, M>,
}
#[derive(Traversable)]
pub struct UnrealizedInvestedCapital<M: StorageMode = Rw> {
pub in_profit: FiatPerBlock<Cents, M>,
pub in_loss: FiatPerBlock<Cents, M>,
}
#[derive(Deref, DerefMut, Traversable)]
pub struct UnrealizedFull<M: StorageMode = Rw> {
#[deref]
@@ -25,6 +31,7 @@ pub struct UnrealizedFull<M: StorageMode = Rw> {
pub inner: UnrealizedBase<M>,
pub gross_pnl: FiatPerBlock<Cents, M>,
pub invested_capital: UnrealizedInvestedCapital<M>,
pub sentiment: UnrealizedSentiment<M>,
}
@@ -42,9 +49,15 @@ impl UnrealizedFull {
net: cfg.import("net_sentiment", Version::ONE)?,
};
let invested_capital = UnrealizedInvestedCapital {
in_profit: cfg.import("invested_capital_in_profit", v0)?,
in_loss: cfg.import("invested_capital_in_loss", v0)?,
};
Ok(Self {
inner,
gross_pnl,
invested_capital,
sentiment,
})
}
@@ -57,6 +70,8 @@ impl UnrealizedFull {
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
let mut vecs = self.inner.collect_vecs_mut();
vecs.push(&mut self.gross_pnl.cents.height as &mut dyn AnyStoredVec);
vecs.push(&mut self.invested_capital.in_profit.cents.height as &mut dyn AnyStoredVec);
vecs.push(&mut self.invested_capital.in_loss.cents.height as &mut dyn AnyStoredVec);
vecs.push(&mut self.sentiment.pain_index.cents.height as &mut dyn AnyStoredVec);
vecs.push(&mut self.sentiment.greed_index.cents.height as &mut dyn AnyStoredVec);
vecs.push(&mut self.sentiment.net.cents.height as &mut dyn AnyStoredVec);
@@ -80,7 +95,33 @@ impl UnrealizedFull {
exit,
)?;
self.compute_rest_extended(prices, starting_indexes, supply_in_profit_sats, supply_in_loss_sats, exit)?;
// invested_capital_in_profit = supply_profit_sats × spot / ONE_BTC - unrealized_profit
self.invested_capital.in_profit.cents.height.compute_transform3(
starting_indexes.height,
supply_in_profit_sats,
&prices.spot.cents.height,
&self.inner.core.basic.profit.cents.height,
|(h, supply_sats, spot, profit, ..)| {
let market_value = supply_sats.as_u128() * spot.as_u128() / Sats::ONE_BTC_U128;
(h, Cents::new(market_value.saturating_sub(profit.as_u128()) as u64))
},
exit,
)?;
// invested_capital_in_loss = supply_loss_sats × spot / ONE_BTC + unrealized_loss
self.invested_capital.in_loss.cents.height.compute_transform3(
starting_indexes.height,
supply_in_loss_sats,
&prices.spot.cents.height,
&self.inner.core.basic.loss.cents.height,
|(h, supply_sats, spot, loss, ..)| {
let market_value = supply_sats.as_u128() * spot.as_u128() / Sats::ONE_BTC_U128;
(h, Cents::new((market_value + loss.as_u128()) as u64))
},
exit,
)?;
self.compute_rest_extended(prices, starting_indexes, exit)?;
self.sentiment
.net
@@ -100,40 +141,42 @@ impl UnrealizedFull {
&mut self,
prices: &prices::Vecs,
starting_indexes: &Indexes,
supply_in_profit_sats: &(impl ReadableVec<Height, Sats> + Sync),
supply_in_loss_sats: &(impl ReadableVec<Height, Sats> + Sync),
exit: &Exit,
) -> Result<()> {
// greed = spot - investor_price_winners
// investor_price = investor_cap / invested_cap (both in CentsSats)
// invested_cap is now in Cents (already divided by ONE_BTC), so multiply back
self.sentiment.greed_index.cents.height.compute_transform3(
starting_indexes.height,
&self.inner.investor_cap_in_profit_raw,
supply_in_profit_sats,
&self.invested_capital.in_profit.cents.height,
&prices.spot.cents.height,
|(h, investor_cap, supply_sats, spot, ..)| {
let invested_cap = supply_sats.as_u128() * spot.as_u128();
if invested_cap == 0 {
|(h, investor_cap, invested_cap_cents, spot, ..)| {
let invested_cap_raw = invested_cap_cents.as_u128() * Sats::ONE_BTC_U128;
if invested_cap_raw == 0 {
return (h, Cents::ZERO);
}
let investor_price = investor_cap.inner() / invested_cap;
let investor_price = investor_cap.inner() / invested_cap_raw;
let spot_u128 = spot.as_u128();
(h, Cents::new((spot_u128 - investor_price) as u64))
(h, Cents::new(spot_u128.saturating_sub(investor_price) as u64))
},
exit,
)?;
// pain = investor_price_losers - spot
self.sentiment.pain_index.cents.height.compute_transform3(
starting_indexes.height,
&self.inner.investor_cap_in_loss_raw,
supply_in_loss_sats,
&self.invested_capital.in_loss.cents.height,
&prices.spot.cents.height,
|(h, investor_cap, supply_sats, spot, ..)| {
let invested_cap = supply_sats.as_u128() * spot.as_u128();
if invested_cap == 0 {
|(h, investor_cap, invested_cap_cents, spot, ..)| {
let invested_cap_raw = invested_cap_cents.as_u128() * Sats::ONE_BTC_U128;
if invested_cap_raw == 0 {
return (h, Cents::ZERO);
}
let investor_price = investor_cap.inner() / invested_cap;
let investor_price = investor_cap.inner() / invested_cap_raw;
let spot_u128 = spot.as_u128();
(h, Cents::new((investor_price - spot_u128) as u64))
(h, Cents::new(investor_price.saturating_sub(spot_u128) as u64))
},
exit,
)?;