mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-21 16:08:10 -07:00
global: snap
This commit is contained in:
@@ -144,8 +144,8 @@ impl AllCohortMetrics {
|
||||
&self.unrealized.invested_capital.in_loss.cents.height,
|
||||
&self.supply.in_profit.sats.height,
|
||||
&self.supply.in_loss.sats.height,
|
||||
&self.unrealized.investor_cap_in_profit_raw,
|
||||
&self.unrealized.investor_cap_in_loss_raw,
|
||||
&self.unrealized.capitalized_cap_in_profit_raw,
|
||||
&self.unrealized.capitalized_cap_in_loss_raw,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -120,8 +120,8 @@ impl ExtendedCohortMetrics {
|
||||
&self.unrealized.invested_capital.in_loss.cents.height,
|
||||
&self.supply.in_profit.sats.height,
|
||||
&self.supply.in_loss.sats.height,
|
||||
&self.unrealized.investor_cap_in_profit_raw,
|
||||
&self.unrealized.investor_cap_in_loss_raw,
|
||||
&self.unrealized.capitalized_cap_in_profit_raw,
|
||||
&self.unrealized.capitalized_cap_in_loss_raw,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -153,8 +153,8 @@ impl CostBasis {
|
||||
invested_cap_in_loss: &impl ReadableVec<Height, Cents>,
|
||||
supply_in_profit_sats: &impl ReadableVec<Height, Sats>,
|
||||
supply_in_loss_sats: &impl ReadableVec<Height, Sats>,
|
||||
investor_cap_in_profit_raw: &impl ReadableVec<Height, CentsSquaredSats>,
|
||||
investor_cap_in_loss_raw: &impl ReadableVec<Height, CentsSquaredSats>,
|
||||
capitalized_cap_in_profit_raw: &impl ReadableVec<Height, CentsSquaredSats>,
|
||||
capitalized_cap_in_loss_raw: &impl ReadableVec<Height, CentsSquaredSats>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.in_profit.per_coin.cents.height.compute_transform3(
|
||||
@@ -193,29 +193,29 @@ impl CostBasis {
|
||||
)?;
|
||||
self.in_profit.per_dollar.cents.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
investor_cap_in_profit_raw,
|
||||
capitalized_cap_in_profit_raw,
|
||||
invested_cap_in_profit,
|
||||
spot,
|
||||
|(h, investor_cap, invested_cents, spot, ..)| {
|
||||
|(h, capitalized_cap, invested_cents, spot, ..)| {
|
||||
let invested_raw = invested_cents.as_u128() * Sats::ONE_BTC_U128;
|
||||
if invested_raw == 0 {
|
||||
return (h, spot);
|
||||
}
|
||||
(h, Cents::new((investor_cap.inner() / invested_raw) as u64))
|
||||
(h, Cents::new((capitalized_cap.inner() / invested_raw) as u64))
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
self.in_loss.per_dollar.cents.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
investor_cap_in_loss_raw,
|
||||
capitalized_cap_in_loss_raw,
|
||||
invested_cap_in_loss,
|
||||
spot,
|
||||
|(h, investor_cap, invested_cents, spot, ..)| {
|
||||
|(h, capitalized_cap, invested_cents, spot, ..)| {
|
||||
let invested_raw = invested_cents.as_u128() * Sats::ONE_BTC_U128;
|
||||
if invested_raw == 0 {
|
||||
return (h, spot);
|
||||
}
|
||||
(h, Cents::new((investor_cap.inner() / invested_raw) as u64))
|
||||
(h, Cents::new((capitalized_cap.inner() / invested_raw) as u64))
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -45,7 +45,7 @@ pub struct RealizedPeakRegret<M: StorageMode = Rw> {
|
||||
}
|
||||
|
||||
#[derive(Traversable)]
|
||||
pub struct RealizedInvestor<M: StorageMode = Rw> {
|
||||
pub struct RealizedCapitalized<M: StorageMode = Rw> {
|
||||
pub price: PriceWithRatioExtendedPerBlock<M>,
|
||||
#[traversable(hidden)]
|
||||
pub cap_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
@@ -63,7 +63,7 @@ pub struct RealizedFull<M: StorageMode = Rw> {
|
||||
pub net_pnl: RealizedNetPnl<M>,
|
||||
pub sopr: RealizedSopr<M>,
|
||||
pub peak_regret: RealizedPeakRegret<M>,
|
||||
pub investor: RealizedInvestor<M>,
|
||||
pub capitalized: RealizedCapitalized<M>,
|
||||
|
||||
pub profit_to_loss_ratio: RollingWindows<StoredF64, M>,
|
||||
|
||||
@@ -108,10 +108,10 @@ impl RealizedFull {
|
||||
value: cfg.import("realized_peak_regret", Version::new(3))?,
|
||||
};
|
||||
|
||||
// Investor
|
||||
let investor = RealizedInvestor {
|
||||
price: cfg.import("investor_price", v0)?,
|
||||
cap_raw: cfg.import("investor_cap_raw", v0)?,
|
||||
// Capitalized
|
||||
let capitalized = RealizedCapitalized {
|
||||
price: cfg.import("capitalized_price", v0)?,
|
||||
cap_raw: cfg.import("capitalized_cap_raw", v0)?,
|
||||
};
|
||||
|
||||
// Price ratio stats
|
||||
@@ -125,7 +125,7 @@ impl RealizedFull {
|
||||
net_pnl,
|
||||
sopr,
|
||||
peak_regret,
|
||||
investor,
|
||||
capitalized,
|
||||
profit_to_loss_ratio: cfg.import("realized_profit_to_loss_ratio", v1)?,
|
||||
cap_raw: cfg.import("cap_raw", v0)?,
|
||||
cap_to_own_mcap: cfg.import("realized_cap_to_own_mcap", v1)?,
|
||||
@@ -151,13 +151,13 @@ impl RealizedFull {
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
self.investor
|
||||
self.capitalized
|
||||
.price
|
||||
.cents
|
||||
.height
|
||||
.len()
|
||||
.min(self.cap_raw.len())
|
||||
.min(self.investor.cap_raw.len())
|
||||
.min(self.capitalized.cap_raw.len())
|
||||
.min(self.peak_regret.value.block.cents.len())
|
||||
}
|
||||
|
||||
@@ -167,15 +167,15 @@ impl RealizedFull {
|
||||
state: &CohortState<RealizedState, CostBasisData<WithCapital>>,
|
||||
) {
|
||||
self.core.push_state(state);
|
||||
self.investor
|
||||
self.capitalized
|
||||
.price
|
||||
.cents
|
||||
.height
|
||||
.push(state.realized.investor_price());
|
||||
.push(state.realized.capitalized_price());
|
||||
self.cap_raw.push(state.realized.cap_raw());
|
||||
self.investor
|
||||
self.capitalized
|
||||
.cap_raw
|
||||
.push(state.realized.investor_cap_raw());
|
||||
.push(state.realized.capitalized_cap_raw());
|
||||
self.peak_regret
|
||||
.value
|
||||
.block
|
||||
@@ -185,9 +185,9 @@ 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.investor.price.cents.height);
|
||||
vecs.push(&mut self.capitalized.price.cents.height);
|
||||
vecs.push(&mut self.cap_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.investor.cap_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.capitalized.cap_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.peak_regret.value.block.cents);
|
||||
vecs
|
||||
}
|
||||
@@ -207,17 +207,17 @@ impl RealizedFull {
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_accum(&mut self, accum: &RealizedFullAccum) {
|
||||
self.cap_raw.push(accum.cap_raw);
|
||||
self.investor.cap_raw.push(accum.investor_cap_raw);
|
||||
self.capitalized.cap_raw.push(accum.capitalized_cap_raw);
|
||||
|
||||
let investor_price = {
|
||||
let capitalized_price = {
|
||||
let cap = accum.cap_raw.as_u128();
|
||||
if cap == 0 {
|
||||
Cents::ZERO
|
||||
} else {
|
||||
Cents::new((accum.investor_cap_raw / cap) as u64)
|
||||
Cents::new((accum.capitalized_cap_raw / cap) as u64)
|
||||
}
|
||||
};
|
||||
self.investor.price.cents.height.push(investor_price);
|
||||
self.capitalized.price.cents.height.push(capitalized_price);
|
||||
|
||||
self.peak_regret.value.block.cents.push(accum.peak_regret());
|
||||
}
|
||||
@@ -298,8 +298,8 @@ impl RealizedFull {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// Investor price ratio, percentiles and bands
|
||||
self.investor
|
||||
// Capitalized price ratio, percentiles and bands
|
||||
self.capitalized
|
||||
.price
|
||||
.compute_rest(prices, starting_indexes, exit)?;
|
||||
|
||||
@@ -374,14 +374,14 @@ impl RealizedFull {
|
||||
#[derive(Default)]
|
||||
pub struct RealizedFullAccum {
|
||||
pub(crate) cap_raw: CentsSats,
|
||||
pub(crate) investor_cap_raw: CentsSquaredSats,
|
||||
pub(crate) capitalized_cap_raw: CentsSquaredSats,
|
||||
peak_regret: CentsSats,
|
||||
}
|
||||
|
||||
impl RealizedFullAccum {
|
||||
pub(crate) fn add(&mut self, state: &RealizedState) {
|
||||
self.cap_raw += state.cap_raw();
|
||||
self.investor_cap_raw += state.investor_cap_raw();
|
||||
self.capitalized_cap_raw += state.capitalized_cap_raw();
|
||||
self.peak_regret += CentsSats::new(state.peak_regret_raw());
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ pub struct UnrealizedFull<M: StorageMode = Rw> {
|
||||
pub gross_pnl: FiatPerBlock<Cents, M>,
|
||||
pub invested_capital: UnrealizedInvestedCapital<M>,
|
||||
|
||||
pub investor_cap_in_profit_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
pub investor_cap_in_loss_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
pub capitalized_cap_in_profit_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
pub capitalized_cap_in_loss_raw: M::Stored<BytesVec<Height, CentsSquaredSats>>,
|
||||
|
||||
pub sentiment: UnrealizedSentiment<M>,
|
||||
}
|
||||
@@ -53,8 +53,8 @@ impl UnrealizedFull {
|
||||
in_loss: cfg.import("invested_capital_in_loss", v1)?,
|
||||
};
|
||||
|
||||
let investor_cap_in_profit_raw = cfg.import("investor_cap_in_profit_raw", v0)?;
|
||||
let investor_cap_in_loss_raw = cfg.import("investor_cap_in_loss_raw", v0)?;
|
||||
let capitalized_cap_in_profit_raw = cfg.import("capitalized_cap_in_profit_raw", v0)?;
|
||||
let capitalized_cap_in_loss_raw = cfg.import("capitalized_cap_in_loss_raw", v0)?;
|
||||
|
||||
let sentiment = UnrealizedSentiment {
|
||||
pain_index: cfg.import("pain_index", v1)?,
|
||||
@@ -66,33 +66,33 @@ impl UnrealizedFull {
|
||||
inner,
|
||||
gross_pnl,
|
||||
invested_capital,
|
||||
investor_cap_in_profit_raw,
|
||||
investor_cap_in_loss_raw,
|
||||
capitalized_cap_in_profit_raw,
|
||||
capitalized_cap_in_loss_raw,
|
||||
sentiment,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
// Only check per-block pushed vecs (investor_cap_raw).
|
||||
// Only check per-block pushed vecs (capitalized_cap_raw).
|
||||
// Core-level vecs (profit/loss) are aggregated from age_range, not stateful.
|
||||
self.investor_cap_in_profit_raw
|
||||
self.capitalized_cap_in_profit_raw
|
||||
.len()
|
||||
.min(self.investor_cap_in_loss_raw.len())
|
||||
.min(self.capitalized_cap_in_loss_raw.len())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state_all(&mut self, state: &UnrealizedState) {
|
||||
self.inner.push_state(state);
|
||||
self.investor_cap_in_profit_raw
|
||||
.push(CentsSquaredSats::new(state.investor_cap_in_profit_raw));
|
||||
self.investor_cap_in_loss_raw
|
||||
.push(CentsSquaredSats::new(state.investor_cap_in_loss_raw));
|
||||
self.capitalized_cap_in_profit_raw
|
||||
.push(CentsSquaredSats::new(state.capitalized_cap_in_profit_raw));
|
||||
self.capitalized_cap_in_loss_raw
|
||||
.push(CentsSquaredSats::new(state.capitalized_cap_in_loss_raw));
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
let mut vecs = self.inner.collect_vecs_mut();
|
||||
vecs.push(&mut self.investor_cap_in_profit_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.investor_cap_in_loss_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.capitalized_cap_in_profit_raw as &mut dyn AnyStoredVec);
|
||||
vecs.push(&mut self.capitalized_cap_in_loss_raw as &mut dyn AnyStoredVec);
|
||||
vecs
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ impl UnrealizedFull {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute sentiment using investor_price (original formula).
|
||||
/// Compute sentiment using capitalized_price (original formula).
|
||||
/// Called after cost_basis.in_profit/loss are computed at the cohort level.
|
||||
pub(crate) fn compute_sentiment(
|
||||
&mut self,
|
||||
@@ -162,45 +162,45 @@ impl UnrealizedFull {
|
||||
spot: &impl ReadableVec<Height, Cents>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
// greed = spot - investor_price_winners
|
||||
// investor_price = investor_cap / invested_cap
|
||||
// greed = spot - capitalized_price_winners
|
||||
// capitalized_price = capitalized_cap / invested_cap
|
||||
// invested_cap is in Cents (already / ONE_BTC), multiply back for CentsSats scale
|
||||
self.sentiment.greed_index.cents.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&self.investor_cap_in_profit_raw,
|
||||
&self.capitalized_cap_in_profit_raw,
|
||||
&self.invested_capital.in_profit.cents.height,
|
||||
spot,
|
||||
|(h, investor_cap, invested_cap_cents, spot, ..)| {
|
||||
|(h, capitalized_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_raw;
|
||||
let capitalized_price = capitalized_cap.inner() / invested_cap_raw;
|
||||
let spot_u128 = spot.as_u128();
|
||||
(
|
||||
h,
|
||||
Cents::new(spot_u128.saturating_sub(investor_price) as u64),
|
||||
Cents::new(spot_u128.saturating_sub(capitalized_price) as u64),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
// pain = investor_price_losers - spot
|
||||
// pain = capitalized_price_losers - spot
|
||||
self.sentiment.pain_index.cents.height.compute_transform3(
|
||||
starting_indexes.height,
|
||||
&self.investor_cap_in_loss_raw,
|
||||
&self.capitalized_cap_in_loss_raw,
|
||||
&self.invested_capital.in_loss.cents.height,
|
||||
spot,
|
||||
|(h, investor_cap, invested_cap_cents, spot, ..)| {
|
||||
|(h, capitalized_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_raw;
|
||||
let capitalized_price = capitalized_cap.inner() / invested_cap_raw;
|
||||
let spot_u128 = spot.as_u128();
|
||||
(
|
||||
h,
|
||||
Cents::new(investor_price.saturating_sub(spot_u128) as u64),
|
||||
Cents::new(capitalized_price.saturating_sub(spot_u128) as u64),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
|
||||
Reference in New Issue
Block a user