mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-14 12:38:13 -07:00
global: snapshot
This commit is contained in:
@@ -263,8 +263,8 @@ impl CostBasisOps for CostBasisRaw {
|
|||||||
/// Composes `CostBasisRaw` for scalar tracking, adds map, pending, and cache.
|
/// Composes `CostBasisRaw` for scalar tracking, adds map, pending, and cache.
|
||||||
///
|
///
|
||||||
/// Generic over the accumulator `S`:
|
/// Generic over the accumulator `S`:
|
||||||
/// - `CachedStateRaw`: tracks all fields including invested capital + investor cap (128 bytes)
|
/// - `WithCapital`: tracks all fields including invested capital + investor cap (128 bytes)
|
||||||
/// - `CachedStateCore`: tracks only supply + unrealized profit/loss (64 bytes, 1 cache line)
|
/// - `WithoutCapital`: tracks only supply + unrealized profit/loss (64 bytes, 1 cache line)
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CostBasisData<S: Accumulate> {
|
pub struct CostBasisData<S: Accumulate> {
|
||||||
raw: CostBasisRaw,
|
raw: CostBasisRaw,
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ impl UnrealizedState {
|
|||||||
/// Core cache state: supply + unrealized profit/loss only (64 bytes, 1 cache line).
|
/// Core cache state: supply + unrealized profit/loss only (64 bytes, 1 cache line).
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct WithoutCapital {
|
pub struct WithoutCapital {
|
||||||
supply_in_profit: Sats,
|
pub(crate) supply_in_profit: Sats,
|
||||||
supply_in_loss: Sats,
|
pub(crate) supply_in_loss: Sats,
|
||||||
unrealized_profit: u128,
|
pub(crate) unrealized_profit: u128,
|
||||||
unrealized_loss: u128,
|
pub(crate) unrealized_loss: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Full cache state: core + invested capital + investor cap (128 bytes, 2 cache lines).
|
/// Full cache state: core + invested capital + investor cap (128 bytes, 2 cache lines).
|
||||||
@@ -56,21 +56,6 @@ pub struct WithCapital {
|
|||||||
investor_cap_in_loss: u128,
|
investor_cap_in_loss: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WithCapital {
|
|
||||||
fn to_output(&self) -> UnrealizedState {
|
|
||||||
let base = self.core.to_output();
|
|
||||||
UnrealizedState {
|
|
||||||
invested_capital_in_profit: div_btc(self.invested_capital_in_profit),
|
|
||||||
invested_capital_in_loss: div_btc(self.invested_capital_in_loss),
|
|
||||||
investor_cap_in_profit_raw: self.investor_cap_in_profit,
|
|
||||||
investor_cap_in_loss_raw: self.investor_cap_in_loss,
|
|
||||||
invested_capital_in_profit_raw: self.invested_capital_in_profit,
|
|
||||||
invested_capital_in_loss_raw: self.invested_capital_in_loss,
|
|
||||||
..base
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn div_btc(raw: u128) -> Cents {
|
fn div_btc(raw: u128) -> Cents {
|
||||||
if raw == 0 {
|
if raw == 0 {
|
||||||
@@ -80,7 +65,25 @@ fn div_btc(raw: u128) -> Cents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WithoutCapital {
|
/// Trait for accumulating profit/loss across BTreeMap entries.
|
||||||
|
/// `WithoutCapital` skips capital tracking; `WithCapital` tracks all fields.
|
||||||
|
pub trait Accumulate: Default + Clone + Send + Sync + 'static {
|
||||||
|
fn to_output(&self) -> UnrealizedState;
|
||||||
|
fn core(&self) -> &WithoutCapital;
|
||||||
|
fn core_mut(&mut self) -> &mut WithoutCapital;
|
||||||
|
|
||||||
|
fn supply_in_profit(&self) -> Sats { self.core().supply_in_profit }
|
||||||
|
fn supply_in_loss(&self) -> Sats { self.core().supply_in_loss }
|
||||||
|
fn unrealized_profit(&mut self) -> &mut u128 { &mut self.core_mut().unrealized_profit }
|
||||||
|
fn unrealized_loss(&mut self) -> &mut u128 { &mut self.core_mut().unrealized_loss }
|
||||||
|
|
||||||
|
fn accumulate_profit(&mut self, price_u128: u128, sats: Sats);
|
||||||
|
fn accumulate_loss(&mut self, price_u128: u128, sats: Sats);
|
||||||
|
fn deaccumulate_profit(&mut self, price_u128: u128, sats: Sats);
|
||||||
|
fn deaccumulate_loss(&mut self, price_u128: u128, sats: Sats);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Accumulate for WithoutCapital {
|
||||||
fn to_output(&self) -> UnrealizedState {
|
fn to_output(&self) -> UnrealizedState {
|
||||||
UnrealizedState {
|
UnrealizedState {
|
||||||
supply_in_profit: self.supply_in_profit,
|
supply_in_profit: self.supply_in_profit,
|
||||||
@@ -90,79 +93,69 @@ impl WithoutCapital {
|
|||||||
..UnrealizedState::ZERO
|
..UnrealizedState::ZERO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for accumulating profit/loss across BTreeMap entries.
|
fn core(&self) -> &WithoutCapital { self }
|
||||||
/// `WithoutCapital` skips capital tracking; `WithCapital` tracks all fields.
|
fn core_mut(&mut self) -> &mut WithoutCapital { self }
|
||||||
pub trait Accumulate: Default + Clone + Send + Sync + 'static {
|
|
||||||
fn to_output(&self) -> UnrealizedState;
|
|
||||||
|
|
||||||
fn supply_in_profit(&self) -> &Sats;
|
|
||||||
fn supply_in_loss(&self) -> &Sats;
|
|
||||||
fn unrealized_profit(&mut self) -> &mut u128;
|
|
||||||
fn unrealized_loss(&mut self) -> &mut u128;
|
|
||||||
|
|
||||||
fn accumulate_profit(&mut self, price_u128: u128, invested_capital: u128, sats: Sats);
|
|
||||||
fn accumulate_loss(&mut self, price_u128: u128, invested_capital: u128, sats: Sats);
|
|
||||||
fn deaccumulate_profit(&mut self, price_u128: u128, invested_capital: u128, sats: Sats);
|
|
||||||
fn deaccumulate_loss(&mut self, price_u128: u128, invested_capital: u128, sats: Sats);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Accumulate for WithoutCapital {
|
|
||||||
fn to_output(&self) -> UnrealizedState { self.to_output() }
|
|
||||||
|
|
||||||
fn supply_in_profit(&self) -> &Sats { &self.supply_in_profit }
|
|
||||||
fn supply_in_loss(&self) -> &Sats { &self.supply_in_loss }
|
|
||||||
fn unrealized_profit(&mut self) -> &mut u128 { &mut self.unrealized_profit }
|
|
||||||
fn unrealized_loss(&mut self) -> &mut u128 { &mut self.unrealized_loss }
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn accumulate_profit(&mut self, _price_u128: u128, _invested_capital: u128, sats: Sats) {
|
fn accumulate_profit(&mut self, _price_u128: u128, sats: Sats) {
|
||||||
self.supply_in_profit += sats;
|
self.supply_in_profit += sats;
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn accumulate_loss(&mut self, _price_u128: u128, _invested_capital: u128, sats: Sats) {
|
fn accumulate_loss(&mut self, _price_u128: u128, sats: Sats) {
|
||||||
self.supply_in_loss += sats;
|
self.supply_in_loss += sats;
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deaccumulate_profit(&mut self, _price_u128: u128, _invested_capital: u128, sats: Sats) {
|
fn deaccumulate_profit(&mut self, _price_u128: u128, sats: Sats) {
|
||||||
self.supply_in_profit -= sats;
|
self.supply_in_profit -= sats;
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deaccumulate_loss(&mut self, _price_u128: u128, _invested_capital: u128, sats: Sats) {
|
fn deaccumulate_loss(&mut self, _price_u128: u128, sats: Sats) {
|
||||||
self.supply_in_loss -= sats;
|
self.supply_in_loss -= sats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Accumulate for WithCapital {
|
impl Accumulate for WithCapital {
|
||||||
fn to_output(&self) -> UnrealizedState { self.to_output() }
|
fn to_output(&self) -> UnrealizedState {
|
||||||
|
UnrealizedState {
|
||||||
|
invested_capital_in_profit: div_btc(self.invested_capital_in_profit),
|
||||||
|
invested_capital_in_loss: div_btc(self.invested_capital_in_loss),
|
||||||
|
investor_cap_in_profit_raw: self.investor_cap_in_profit,
|
||||||
|
investor_cap_in_loss_raw: self.investor_cap_in_loss,
|
||||||
|
invested_capital_in_profit_raw: self.invested_capital_in_profit,
|
||||||
|
invested_capital_in_loss_raw: self.invested_capital_in_loss,
|
||||||
|
..Accumulate::to_output(&self.core)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn supply_in_profit(&self) -> &Sats { &self.core.supply_in_profit }
|
fn core(&self) -> &WithoutCapital { &self.core }
|
||||||
fn supply_in_loss(&self) -> &Sats { &self.core.supply_in_loss }
|
fn core_mut(&mut self) -> &mut WithoutCapital { &mut self.core }
|
||||||
fn unrealized_profit(&mut self) -> &mut u128 { &mut self.core.unrealized_profit }
|
|
||||||
fn unrealized_loss(&mut self) -> &mut u128 { &mut self.core.unrealized_loss }
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn accumulate_profit(&mut self, price_u128: u128, invested_capital: u128, sats: Sats) {
|
fn accumulate_profit(&mut self, price_u128: u128, sats: Sats) {
|
||||||
self.core.supply_in_profit += sats;
|
self.core.supply_in_profit += sats;
|
||||||
|
let invested_capital = price_u128 * sats.as_u128();
|
||||||
self.invested_capital_in_profit += invested_capital;
|
self.invested_capital_in_profit += invested_capital;
|
||||||
self.investor_cap_in_profit += price_u128 * invested_capital;
|
self.investor_cap_in_profit += price_u128 * invested_capital;
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn accumulate_loss(&mut self, price_u128: u128, invested_capital: u128, sats: Sats) {
|
fn accumulate_loss(&mut self, price_u128: u128, sats: Sats) {
|
||||||
self.core.supply_in_loss += sats;
|
self.core.supply_in_loss += sats;
|
||||||
|
let invested_capital = price_u128 * sats.as_u128();
|
||||||
self.invested_capital_in_loss += invested_capital;
|
self.invested_capital_in_loss += invested_capital;
|
||||||
self.investor_cap_in_loss += price_u128 * invested_capital;
|
self.investor_cap_in_loss += price_u128 * invested_capital;
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deaccumulate_profit(&mut self, price_u128: u128, invested_capital: u128, sats: Sats) {
|
fn deaccumulate_profit(&mut self, price_u128: u128, sats: Sats) {
|
||||||
self.core.supply_in_profit -= sats;
|
self.core.supply_in_profit -= sats;
|
||||||
|
let invested_capital = price_u128 * sats.as_u128();
|
||||||
self.invested_capital_in_profit -= invested_capital;
|
self.invested_capital_in_profit -= invested_capital;
|
||||||
self.investor_cap_in_profit -= price_u128 * invested_capital;
|
self.investor_cap_in_profit -= price_u128 * invested_capital;
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deaccumulate_loss(&mut self, price_u128: u128, invested_capital: u128, sats: Sats) {
|
fn deaccumulate_loss(&mut self, price_u128: u128, sats: Sats) {
|
||||||
self.core.supply_in_loss -= sats;
|
self.core.supply_in_loss -= sats;
|
||||||
|
let invested_capital = price_u128 * sats.as_u128();
|
||||||
self.invested_capital_in_loss -= invested_capital;
|
self.invested_capital_in_loss -= invested_capital;
|
||||||
self.investor_cap_in_loss -= price_u128 * invested_capital;
|
self.investor_cap_in_loss -= price_u128 * invested_capital;
|
||||||
}
|
}
|
||||||
@@ -199,9 +192,7 @@ impl<S: Accumulate> CachedUnrealizedState<S> {
|
|||||||
if let Some(ref output) = self.cached_output {
|
if let Some(ref output) = self.cached_output {
|
||||||
return output.clone();
|
return output.clone();
|
||||||
}
|
}
|
||||||
let output = self.state.to_output();
|
self.cached_output.insert(self.state.to_output()).clone()
|
||||||
self.cached_output = Some(output.clone());
|
|
||||||
output
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn on_receive(&mut self, price: Cents, sats: Sats) {
|
pub(crate) fn on_receive(&mut self, price: Cents, sats: Sats) {
|
||||||
@@ -209,16 +200,15 @@ impl<S: Accumulate> CachedUnrealizedState<S> {
|
|||||||
let price: CentsCompact = price.into();
|
let price: CentsCompact = price.into();
|
||||||
let sats_u128 = sats.as_u128();
|
let sats_u128 = sats.as_u128();
|
||||||
let price_u128 = price.as_u128();
|
let price_u128 = price.as_u128();
|
||||||
let invested_capital = price_u128 * sats_u128;
|
|
||||||
|
|
||||||
if price <= self.at_price {
|
if price <= self.at_price {
|
||||||
self.state.accumulate_profit(price_u128, invested_capital, sats);
|
self.state.accumulate_profit(price_u128, sats);
|
||||||
if price < self.at_price {
|
if price < self.at_price {
|
||||||
let diff = (self.at_price - price).as_u128();
|
let diff = (self.at_price - price).as_u128();
|
||||||
*self.state.unrealized_profit() += diff * sats_u128;
|
*self.state.unrealized_profit() += diff * sats_u128;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.state.accumulate_loss(price_u128, invested_capital, sats);
|
self.state.accumulate_loss(price_u128, sats);
|
||||||
let diff = (price - self.at_price).as_u128();
|
let diff = (price - self.at_price).as_u128();
|
||||||
*self.state.unrealized_loss() += diff * sats_u128;
|
*self.state.unrealized_loss() += diff * sats_u128;
|
||||||
}
|
}
|
||||||
@@ -229,16 +219,15 @@ impl<S: Accumulate> CachedUnrealizedState<S> {
|
|||||||
let price: CentsCompact = price.into();
|
let price: CentsCompact = price.into();
|
||||||
let sats_u128 = sats.as_u128();
|
let sats_u128 = sats.as_u128();
|
||||||
let price_u128 = price.as_u128();
|
let price_u128 = price.as_u128();
|
||||||
let invested_capital = price_u128 * sats_u128;
|
|
||||||
|
|
||||||
if price <= self.at_price {
|
if price <= self.at_price {
|
||||||
self.state.deaccumulate_profit(price_u128, invested_capital, sats);
|
self.state.deaccumulate_profit(price_u128, sats);
|
||||||
if price < self.at_price {
|
if price < self.at_price {
|
||||||
let diff = (self.at_price - price).as_u128();
|
let diff = (self.at_price - price).as_u128();
|
||||||
*self.state.unrealized_profit() -= diff * sats_u128;
|
*self.state.unrealized_profit() -= diff * sats_u128;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.state.deaccumulate_loss(price_u128, invested_capital, sats);
|
self.state.deaccumulate_loss(price_u128, sats);
|
||||||
let diff = (price - self.at_price).as_u128();
|
let diff = (price - self.at_price).as_u128();
|
||||||
*self.state.unrealized_loss() -= diff * sats_u128;
|
*self.state.unrealized_loss() -= diff * sats_u128;
|
||||||
}
|
}
|
||||||
@@ -256,10 +245,9 @@ impl<S: Accumulate> CachedUnrealizedState<S> {
|
|||||||
{
|
{
|
||||||
let sats_u128 = sats.as_u128();
|
let sats_u128 = sats.as_u128();
|
||||||
let price_u128 = price.as_u128();
|
let price_u128 = price.as_u128();
|
||||||
let invested_capital = price_u128 * sats_u128;
|
|
||||||
|
|
||||||
self.state.deaccumulate_loss(price_u128, invested_capital, sats);
|
self.state.deaccumulate_loss(price_u128, sats);
|
||||||
self.state.accumulate_profit(price_u128, invested_capital, sats);
|
self.state.accumulate_profit(price_u128, sats);
|
||||||
|
|
||||||
let original_loss = (price - old_price).as_u128();
|
let original_loss = (price - old_price).as_u128();
|
||||||
*self.state.unrealized_loss() -= original_loss * sats_u128;
|
*self.state.unrealized_loss() -= original_loss * sats_u128;
|
||||||
@@ -282,10 +270,9 @@ impl<S: Accumulate> CachedUnrealizedState<S> {
|
|||||||
{
|
{
|
||||||
let sats_u128 = sats.as_u128();
|
let sats_u128 = sats.as_u128();
|
||||||
let price_u128 = price.as_u128();
|
let price_u128 = price.as_u128();
|
||||||
let invested_capital = price_u128 * sats_u128;
|
|
||||||
|
|
||||||
self.state.deaccumulate_profit(price_u128, invested_capital, sats);
|
self.state.deaccumulate_profit(price_u128, sats);
|
||||||
self.state.accumulate_loss(price_u128, invested_capital, sats);
|
self.state.accumulate_loss(price_u128, sats);
|
||||||
|
|
||||||
if price < old_price {
|
if price < old_price {
|
||||||
let original_profit = (old_price - price).as_u128();
|
let original_profit = (old_price - price).as_u128();
|
||||||
@@ -310,16 +297,15 @@ impl<S: Accumulate> CachedUnrealizedState<S> {
|
|||||||
for (&price, &sats) in map.iter() {
|
for (&price, &sats) in map.iter() {
|
||||||
let sats_u128 = sats.as_u128();
|
let sats_u128 = sats.as_u128();
|
||||||
let price_u128 = price.as_u128();
|
let price_u128 = price.as_u128();
|
||||||
let invested_capital = price_u128 * sats_u128;
|
|
||||||
|
|
||||||
if price <= current_price {
|
if price <= current_price {
|
||||||
state.accumulate_profit(price_u128, invested_capital, sats);
|
state.accumulate_profit(price_u128, sats);
|
||||||
if price < current_price {
|
if price < current_price {
|
||||||
let diff = (current_price - price).as_u128();
|
let diff = (current_price - price).as_u128();
|
||||||
*state.unrealized_profit() += diff * sats_u128;
|
*state.unrealized_profit() += diff * sats_u128;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state.accumulate_loss(price_u128, invested_capital, sats);
|
state.accumulate_loss(price_u128, sats);
|
||||||
let diff = (price - current_price).as_u128();
|
let diff = (price - current_price).as_u128();
|
||||||
*state.unrealized_loss() += diff * sats_u128;
|
*state.unrealized_loss() += diff * sats_u128;
|
||||||
}
|
}
|
||||||
@@ -328,4 +314,3 @@ impl<S: Accumulate> CachedUnrealizedState<S> {
|
|||||||
state
|
state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user