mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-07-17 14:08:10 -07:00
global: fmt
This commit is contained in:
@@ -148,11 +148,7 @@ impl ActivityCountVecs {
|
||||
self.both.block.push(counts.both.into());
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
|
||||
self.reactivated.compute_rest(max_from, exit)?;
|
||||
self.sending.compute_rest(max_from, exit)?;
|
||||
self.receiving.compute_rest(max_from, exit)?;
|
||||
@@ -180,8 +176,8 @@ impl AddrTypeToActivityCountVecs {
|
||||
indexes: &indexes::Vecs,
|
||||
cached_starts: &CachedWindowStarts,
|
||||
) -> Result<Self> {
|
||||
Ok(Self::from(
|
||||
ByAddrType::<ActivityCountVecs>::new_with_name(|type_name| {
|
||||
Ok(Self::from(ByAddrType::<ActivityCountVecs>::new_with_name(
|
||||
|type_name| {
|
||||
ActivityCountVecs::forced_import(
|
||||
db,
|
||||
&format!("{type_name}_{name}"),
|
||||
@@ -189,8 +185,8 @@ impl AddrTypeToActivityCountVecs {
|
||||
indexes,
|
||||
cached_starts,
|
||||
)
|
||||
})?,
|
||||
))
|
||||
},
|
||||
)?))
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
@@ -221,11 +217,7 @@ impl AddrTypeToActivityCountVecs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
|
||||
for type_vecs in self.0.values_mut() {
|
||||
type_vecs.compute_rest(max_from, exit)?;
|
||||
}
|
||||
@@ -259,7 +251,11 @@ impl AddrActivityVecs {
|
||||
Ok(Self {
|
||||
all: ActivityCountVecs::forced_import(db, name, version, indexes, cached_starts)?,
|
||||
by_addr_type: AddrTypeToActivityCountVecs::forced_import(
|
||||
db, name, version, indexes, cached_starts,
|
||||
db,
|
||||
name,
|
||||
version,
|
||||
indexes,
|
||||
cached_starts,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
@@ -284,11 +280,7 @@ impl AddrActivityVecs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
max_from: Height,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, max_from: Height, exit: &Exit) -> Result<()> {
|
||||
self.all.compute_rest(max_from, exit)?;
|
||||
self.by_addr_type.compute_rest(max_from, exit)?;
|
||||
Ok(())
|
||||
|
||||
@@ -12,9 +12,7 @@ use vecdb::{
|
||||
use crate::{indexes, internal::PerBlock};
|
||||
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
pub struct AddrCountVecs<M: StorageMode = Rw>(
|
||||
#[traversable(flatten)] pub PerBlock<StoredU64, M>,
|
||||
);
|
||||
pub struct AddrCountVecs<M: StorageMode = Rw>(#[traversable(flatten)] pub PerBlock<StoredU64, M>);
|
||||
|
||||
impl AddrCountVecs {
|
||||
pub(crate) fn forced_import(
|
||||
@@ -23,9 +21,7 @@ impl AddrCountVecs {
|
||||
version: Version,
|
||||
indexes: &indexes::Vecs,
|
||||
) -> Result<Self> {
|
||||
Ok(Self(PerBlock::forced_import(
|
||||
db, name, version, indexes,
|
||||
)?))
|
||||
Ok(Self(PerBlock::forced_import(db, name, version, indexes)?))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,42 +53,17 @@ impl From<(&AddrTypeToAddrCountVecs, Height)> for AddrTypeToAddrCount {
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2pkh: groups
|
||||
.p2pkh
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2sh: groups
|
||||
.p2sh
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2pkh: groups.p2pkh.height.collect_one(prev_height).unwrap().into(),
|
||||
p2sh: groups.p2sh.height.collect_one(prev_height).unwrap().into(),
|
||||
p2wpkh: groups
|
||||
.p2wpkh
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2wsh: groups
|
||||
.p2wsh
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2tr: groups
|
||||
.p2tr
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2a: groups
|
||||
.p2a
|
||||
.height
|
||||
.collect_one(prev_height)
|
||||
.unwrap()
|
||||
.into(),
|
||||
p2wsh: groups.p2wsh.height.collect_one(prev_height).unwrap().into(),
|
||||
p2tr: groups.p2tr.height.collect_one(prev_height).unwrap().into(),
|
||||
p2a: groups.p2a.height.collect_one(prev_height).unwrap().into(),
|
||||
})
|
||||
} else {
|
||||
Default::default()
|
||||
@@ -177,7 +148,10 @@ impl AddrCountsVecs {
|
||||
}
|
||||
|
||||
pub(crate) fn min_stateful_len(&self) -> usize {
|
||||
self.all.height.len().min(self.by_addr_type.min_stateful_len())
|
||||
self.all
|
||||
.height
|
||||
.len()
|
||||
.min(self.by_addr_type.min_stateful_len())
|
||||
}
|
||||
|
||||
pub(crate) fn par_iter_height_mut(
|
||||
@@ -199,11 +173,7 @@ impl AddrCountsVecs {
|
||||
self.by_addr_type.push_height(addr_counts);
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
let sources = self.by_addr_type.by_height();
|
||||
self.all
|
||||
.height
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
EmptyAddrData, EmptyAddrIndex, FundedAddrData, FundedAddrIndex, Height,
|
||||
};
|
||||
use brk_types::{EmptyAddrData, EmptyAddrIndex, FundedAddrData, FundedAddrIndex, Height};
|
||||
use rayon::prelude::*;
|
||||
use vecdb::{AnyStoredVec, BytesVec, Rw, Stamp, StorageMode, WritableVec};
|
||||
|
||||
|
||||
@@ -45,9 +45,6 @@ impl DeltaVecs {
|
||||
)
|
||||
});
|
||||
|
||||
Self {
|
||||
all,
|
||||
by_addr_type,
|
||||
}
|
||||
Self { all, by_addr_type }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ use brk_error::{Error, Result};
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
AnyAddrIndex, Height, OutputType, P2AAddrIndex, P2PK33AddrIndex, P2PK65AddrIndex,
|
||||
P2PKHAddrIndex, P2SHAddrIndex, P2TRAddrIndex, P2WPKHAddrIndex, P2WSHAddrIndex,
|
||||
TypeIndex, Version,
|
||||
P2PKHAddrIndex, P2SHAddrIndex, P2TRAddrIndex, P2WPKHAddrIndex, P2WSHAddrIndex, TypeIndex,
|
||||
Version,
|
||||
};
|
||||
use rayon::prelude::*;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
@@ -44,10 +44,7 @@ impl NewAddrCountVecs {
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
all,
|
||||
by_addr_type,
|
||||
})
|
||||
Ok(Self { all, by_addr_type })
|
||||
}
|
||||
|
||||
pub(crate) fn compute(
|
||||
|
||||
@@ -24,20 +24,11 @@ impl TotalAddrCountVecs {
|
||||
) -> Result<Self> {
|
||||
let all = PerBlock::forced_import(db, "total_addr_count", version, indexes)?;
|
||||
|
||||
let by_addr_type: ByAddrType<PerBlock<StoredU64>> =
|
||||
ByAddrType::new_with_name(|name| {
|
||||
PerBlock::forced_import(
|
||||
db,
|
||||
&format!("{name}_total_addr_count"),
|
||||
version,
|
||||
indexes,
|
||||
)
|
||||
})?;
|
||||
let by_addr_type: ByAddrType<PerBlock<StoredU64>> = ByAddrType::new_with_name(|name| {
|
||||
PerBlock::forced_import(db, &format!("{name}_total_addr_count"), version, indexes)
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
all,
|
||||
by_addr_type,
|
||||
})
|
||||
Ok(Self { all, by_addr_type })
|
||||
}
|
||||
|
||||
/// Eagerly compute total = addr_count + empty_addr_count.
|
||||
|
||||
@@ -103,9 +103,7 @@ pub(crate) fn load_uncached_addr_data(
|
||||
// Check if this is a new address (type_index >= first for this height)
|
||||
let first = *first_addr_indexes.get(addr_type).unwrap();
|
||||
if first <= type_index {
|
||||
return Ok(Some(WithAddrDataSource::New(
|
||||
FundedAddrData::default(),
|
||||
)));
|
||||
return Ok(Some(WithAddrDataSource::New(FundedAddrData::default())));
|
||||
}
|
||||
|
||||
// Skip if already in cache
|
||||
|
||||
@@ -26,10 +26,7 @@ impl<'a> AddrLookup<'a> {
|
||||
&mut self,
|
||||
output_type: OutputType,
|
||||
type_index: TypeIndex,
|
||||
) -> (
|
||||
&mut WithAddrDataSource<FundedAddrData>,
|
||||
TrackingStatus,
|
||||
) {
|
||||
) -> (&mut WithAddrDataSource<FundedAddrData>, TrackingStatus) {
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
let map = self.funded.get_mut(output_type).unwrap();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use brk_error::Result;
|
||||
use brk_types::{
|
||||
AnyAddrIndex, EmptyAddrData, EmptyAddrIndex, FundedAddrData, FundedAddrIndex,
|
||||
OutputType, TypeIndex,
|
||||
AnyAddrIndex, EmptyAddrData, EmptyAddrIndex, FundedAddrData, FundedAddrIndex, OutputType,
|
||||
TypeIndex,
|
||||
};
|
||||
use vecdb::AnyVec;
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ pub(crate) fn process_received(
|
||||
empty_addr_count: &mut ByAddrType<u64>,
|
||||
activity_counts: &mut AddrTypeToActivityCounts,
|
||||
) {
|
||||
let max_type_len = received_data.iter().map(|(_, v)| v.len()).max().unwrap_or(0);
|
||||
let max_type_len = received_data
|
||||
.iter()
|
||||
.map(|(_, v)| v.len())
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
let mut aggregated: FxHashMap<TypeIndex, AggregatedReceive> =
|
||||
FxHashMap::with_capacity_and_hasher(max_type_len, Default::default());
|
||||
|
||||
|
||||
@@ -41,10 +41,7 @@ pub(crate) fn update_tx_counts(
|
||||
.get_mut(&type_index)
|
||||
{
|
||||
addr_data.tx_count += tx_count;
|
||||
} else if let Some(addr_data) = empty_cache
|
||||
.get_mut(addr_type)
|
||||
.unwrap()
|
||||
.get_mut(&type_index)
|
||||
} else if let Some(addr_data) = empty_cache.get_mut(addr_type).unwrap().get_mut(&type_index)
|
||||
{
|
||||
addr_data.tx_count += tx_count;
|
||||
}
|
||||
|
||||
@@ -90,9 +90,7 @@ pub(crate) fn process_inputs(
|
||||
};
|
||||
|
||||
let items: Vec<_> = if input_count < 128 {
|
||||
(0..input_count)
|
||||
.map(map_fn)
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
(0..input_count).map(map_fn).collect::<Result<Vec<_>>>()?
|
||||
} else {
|
||||
(0..input_count)
|
||||
.into_par_iter()
|
||||
@@ -109,10 +107,9 @@ pub(crate) fn process_inputs(
|
||||
Default::default(),
|
||||
);
|
||||
let mut sent_data = HeightToAddrTypeToVec::with_capacity(estimated_unique_heights);
|
||||
let mut addr_data =
|
||||
AddrTypeToTypeIndexMap::<WithAddrDataSource<FundedAddrData>>::with_capacity(
|
||||
estimated_per_type,
|
||||
);
|
||||
let mut addr_data = AddrTypeToTypeIndexMap::<WithAddrDataSource<FundedAddrData>>::with_capacity(
|
||||
estimated_per_type,
|
||||
);
|
||||
let mut tx_index_vecs =
|
||||
AddrTypeToTypeIndexMap::<SmallVec<[TxIndex; 4]>>::with_capacity(estimated_per_type);
|
||||
|
||||
|
||||
@@ -5,9 +5,7 @@ use rayon::prelude::*;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::distribution::{
|
||||
addr::{
|
||||
AddrTypeToTypeIndexMap, AddrTypeToVec, AddrsDataVecs, AnyAddrIndexesVecs,
|
||||
},
|
||||
addr::{AddrTypeToTypeIndexMap, AddrTypeToVec, AddrsDataVecs, AnyAddrIndexesVecs},
|
||||
compute::{TxOutData, VecsReaders},
|
||||
state::Transacted,
|
||||
};
|
||||
@@ -79,9 +77,7 @@ pub(crate) fn process_outputs(
|
||||
};
|
||||
|
||||
let items: Vec<_> = if output_count < 128 {
|
||||
(0..output_count)
|
||||
.map(map_fn)
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
(0..output_count).map(map_fn).collect::<Result<Vec<_>>>()?
|
||||
} else {
|
||||
(0..output_count)
|
||||
.into_par_iter()
|
||||
@@ -93,10 +89,9 @@ pub(crate) fn process_outputs(
|
||||
let estimated_per_type = (output_count / 8).max(8);
|
||||
let mut transacted = Transacted::default();
|
||||
let mut received_data = AddrTypeToVec::with_capacity(estimated_per_type);
|
||||
let mut addr_data =
|
||||
AddrTypeToTypeIndexMap::<WithAddrDataSource<FundedAddrData>>::with_capacity(
|
||||
estimated_per_type,
|
||||
);
|
||||
let mut addr_data = AddrTypeToTypeIndexMap::<WithAddrDataSource<FundedAddrData>>::with_capacity(
|
||||
estimated_per_type,
|
||||
);
|
||||
let mut tx_index_vecs =
|
||||
AddrTypeToTypeIndexMap::<SmallVec<[TxIndex; 4]>>::with_capacity(estimated_per_type);
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_cohort::{
|
||||
AddrGroups, AmountRange, OverAmount, UnderAmount, Filter, Filtered,
|
||||
};
|
||||
use brk_cohort::{AddrGroups, AmountRange, Filter, Filtered, OverAmount, UnderAmount};
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Height, Indexes, StoredU64, Version};
|
||||
|
||||
@@ -161,9 +161,7 @@ impl DynCohortVecs for AddrCohortVecs {
|
||||
}
|
||||
|
||||
if let Some(state) = self.state.as_ref() {
|
||||
self.addr_count
|
||||
.height
|
||||
.push(state.addr_count.into());
|
||||
self.addr_count.height.push(state.addr_count.into());
|
||||
self.metrics.supply.push_state(&state.inner);
|
||||
self.metrics.outputs.push_state(&state.inner);
|
||||
self.metrics.activity.push_state(&state.inner);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use brk_types::{CostBasisSnapshot, Cents, Height, Timestamp};
|
||||
use brk_types::{Cents, CostBasisSnapshot, Height, Timestamp};
|
||||
use vecdb::Rw;
|
||||
|
||||
use crate::distribution::state::Transacted;
|
||||
@@ -34,10 +34,16 @@ impl UTXOCohorts<Rw> {
|
||||
.unwrap()
|
||||
.receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
if let Some(v) = self.epoch.mut_vec_from_height(height) {
|
||||
v.state.as_mut().unwrap().receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
v.state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
}
|
||||
if let Some(v) = self.class.mut_vec_from_timestamp(timestamp) {
|
||||
v.state.as_mut().unwrap().receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
v.state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.receive_utxo_snapshot(&supply_state, &snapshot);
|
||||
}
|
||||
|
||||
// Update output type cohorts (skip types with no outputs this block)
|
||||
|
||||
@@ -64,10 +64,16 @@ impl UTXOCohorts<Rw> {
|
||||
.unwrap()
|
||||
.send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
if let Some(v) = self.epoch.mut_vec_from_height(receive_height) {
|
||||
v.state.as_mut().unwrap().send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
v.state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
}
|
||||
if let Some(v) = self.class.mut_vec_from_timestamp(block_state.timestamp) {
|
||||
v.state.as_mut().unwrap().send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
v.state
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.send_utxo_precomputed(&sent.spendable_supply, &pre);
|
||||
}
|
||||
} else if sent.spendable_supply.utxo_count > 0 {
|
||||
// Zero-value UTXOs: just subtract supply
|
||||
|
||||
@@ -67,9 +67,7 @@ impl UTXOCohorts<Rw> {
|
||||
idx
|
||||
} else {
|
||||
let mut idx = cached[boundary_idx];
|
||||
while idx < chain_state.len()
|
||||
&& *chain_state[idx].timestamp <= lower_timestamp
|
||||
{
|
||||
while idx < chain_state.len() && *chain_state[idx].timestamp <= lower_timestamp {
|
||||
idx += 1;
|
||||
}
|
||||
cached[boundary_idx] = idx;
|
||||
@@ -84,8 +82,7 @@ impl UTXOCohorts<Rw> {
|
||||
|
||||
// Move supply from younger cohort to older cohort
|
||||
for block_state in &chain_state[start_idx..end_idx] {
|
||||
let snapshot =
|
||||
CostBasisSnapshot::from_utxo(block_state.price, &block_state.supply);
|
||||
let snapshot = CostBasisSnapshot::from_utxo(block_state.price, &block_state.supply);
|
||||
if let Some(state) = age_cohorts[boundary_idx].as_mut() {
|
||||
state.decrement_snapshot(&snapshot);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ use brk_error::Result;
|
||||
use brk_types::{Cents, Height, Indexes, Version};
|
||||
use vecdb::{Exit, ReadableVec};
|
||||
|
||||
use crate::{distribution::{cohorts::traits::DynCohortVecs, metrics::CoreCohortMetrics}, prices};
|
||||
use crate::{
|
||||
distribution::{cohorts::traits::DynCohortVecs, metrics::CoreCohortMetrics},
|
||||
prices,
|
||||
};
|
||||
|
||||
use super::UTXOCohortVecs;
|
||||
|
||||
@@ -45,12 +48,8 @@ impl DynCohortVecs for UTXOCohortVecs<CoreCohortMetrics> {
|
||||
if let Some(state) = self.state.as_mut() {
|
||||
state.apply_pending();
|
||||
let unrealized_state = state.compute_unrealized_state(height_price);
|
||||
self.metrics
|
||||
.unrealized
|
||||
.push_state(&unrealized_state);
|
||||
self.metrics
|
||||
.supply
|
||||
.push_profitability(&unrealized_state);
|
||||
self.metrics.unrealized.push_state(&unrealized_state);
|
||||
self.metrics.supply.push_profitability(&unrealized_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ use brk_error::Result;
|
||||
use brk_types::{Cents, Height, Indexes, Version};
|
||||
use vecdb::{Exit, ReadableVec};
|
||||
|
||||
use crate::{distribution::cohorts::traits::DynCohortVecs, distribution::metrics::TypeCohortMetrics, prices};
|
||||
use crate::{
|
||||
distribution::cohorts::traits::DynCohortVecs, distribution::metrics::TypeCohortMetrics, prices,
|
||||
};
|
||||
|
||||
use super::UTXOCohortVecs;
|
||||
|
||||
@@ -45,12 +47,8 @@ impl DynCohortVecs for UTXOCohortVecs<TypeCohortMetrics> {
|
||||
if let Some(state) = self.state.as_mut() {
|
||||
state.apply_pending();
|
||||
let unrealized_state = state.compute_unrealized_state(height_price);
|
||||
self.metrics
|
||||
.unrealized
|
||||
.push_state(&unrealized_state);
|
||||
self.metrics
|
||||
.supply
|
||||
.push_profitability(&unrealized_state);
|
||||
self.metrics.unrealized.push_state(&unrealized_state);
|
||||
self.metrics.supply.push_profitability(&unrealized_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,42 +144,50 @@ pub(crate) fn process_blocks(
|
||||
let first_p2a_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2a.first_index
|
||||
.p2a
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2pk33_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2pk33.first_index
|
||||
.p2pk33
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2pk65_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2pk65.first_index
|
||||
.p2pk65
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2pkh_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2pkh.first_index
|
||||
.p2pkh
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2sh_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2sh.first_index
|
||||
.p2sh
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2tr_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2tr.first_index
|
||||
.p2tr
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2wpkh_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2wpkh.first_index
|
||||
.p2wpkh
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
let first_p2wsh_vec = indexer
|
||||
.vecs
|
||||
.addrs
|
||||
.p2wsh.first_index
|
||||
.p2wsh
|
||||
.first_index
|
||||
.collect_range_at(start_usize, end_usize);
|
||||
|
||||
// Track running totals - recover from previous height if resuming
|
||||
@@ -187,10 +195,8 @@ pub(crate) fn process_blocks(
|
||||
let (mut addr_counts, mut empty_addr_counts) = if starting_height > Height::ZERO {
|
||||
let addr_counts =
|
||||
AddrTypeToAddrCount::from((&vecs.addrs.funded.by_addr_type, starting_height));
|
||||
let empty_addr_counts = AddrTypeToAddrCount::from((
|
||||
&vecs.addrs.empty.by_addr_type,
|
||||
starting_height,
|
||||
));
|
||||
let empty_addr_counts =
|
||||
AddrTypeToAddrCount::from((&vecs.addrs.empty.by_addr_type, starting_height));
|
||||
(addr_counts, empty_addr_counts)
|
||||
} else {
|
||||
(
|
||||
@@ -274,12 +280,18 @@ pub(crate) fn process_blocks(
|
||||
// processing closures so outputs and inputs collection overlap each other
|
||||
// and tick-tock, instead of running sequentially before the join.
|
||||
let (matured, oi_result) = rayon::join(
|
||||
|| vecs.utxo_cohorts.tick_tock_next_block(chain_state, timestamp),
|
||||
|| {
|
||||
vecs.utxo_cohorts
|
||||
.tick_tock_next_block(chain_state, timestamp)
|
||||
},
|
||||
|| -> Result<_> {
|
||||
let (outputs_result, inputs_result) = rayon::join(
|
||||
|| {
|
||||
let txout_index_to_tx_index = txout_to_tx_index_buf
|
||||
.build(first_tx_index, tx_count, tx_index_to_output_count);
|
||||
let txout_index_to_tx_index = txout_to_tx_index_buf.build(
|
||||
first_tx_index,
|
||||
tx_count,
|
||||
tx_index_to_output_count,
|
||||
);
|
||||
let txout_data_vec =
|
||||
txout_iters.collect_block_outputs(first_txout_index, output_count);
|
||||
process_outputs(
|
||||
@@ -294,14 +306,21 @@ pub(crate) fn process_blocks(
|
||||
},
|
||||
|| -> Result<_> {
|
||||
if input_count > 1 {
|
||||
let txin_index_to_tx_index = txin_to_tx_index_buf
|
||||
.build(first_tx_index, tx_count, tx_index_to_input_count);
|
||||
let (input_values, input_prev_heights, input_output_types, input_type_indexes) =
|
||||
txin_iters.collect_block_inputs(
|
||||
first_txin_index + 1,
|
||||
input_count - 1,
|
||||
height,
|
||||
);
|
||||
let txin_index_to_tx_index = txin_to_tx_index_buf.build(
|
||||
first_tx_index,
|
||||
tx_count,
|
||||
tx_index_to_input_count,
|
||||
);
|
||||
let (
|
||||
input_values,
|
||||
input_prev_heights,
|
||||
input_output_types,
|
||||
input_type_indexes,
|
||||
) = txin_iters.collect_block_inputs(
|
||||
first_txin_index + 1,
|
||||
input_count - 1,
|
||||
height,
|
||||
);
|
||||
process_inputs(
|
||||
input_count - 1,
|
||||
&txin_index_to_tx_index[1..],
|
||||
@@ -380,9 +399,9 @@ pub(crate) fn process_blocks(
|
||||
blocks_old as u128 * u64::from(sent.spendable_supply.value) as u128
|
||||
})
|
||||
.sum();
|
||||
vecs.coinblocks_destroyed.block.push(
|
||||
StoredF64::from(total_satblocks as f64 / Sats::ONE_BTC_U128 as f64),
|
||||
);
|
||||
vecs.coinblocks_destroyed.block.push(StoredF64::from(
|
||||
total_satblocks as f64 / Sats::ONE_BTC_U128 as f64,
|
||||
));
|
||||
}
|
||||
|
||||
// Record maturation (sats crossing age boundaries)
|
||||
@@ -451,9 +470,11 @@ pub(crate) fn process_blocks(
|
||||
vecs.utxo_cohorts.update_fenwick_from_pending();
|
||||
|
||||
// Push to height-indexed vectors
|
||||
vecs.addrs.funded
|
||||
vecs.addrs
|
||||
.funded
|
||||
.push_height(addr_counts.sum(), &addr_counts);
|
||||
vecs.addrs.empty
|
||||
vecs.addrs
|
||||
.empty
|
||||
.push_height(empty_addr_counts.sum(), &empty_addr_counts);
|
||||
vecs.addrs.activity.push_height(&activity_counts);
|
||||
|
||||
@@ -467,11 +488,8 @@ pub(crate) fn process_blocks(
|
||||
block_price,
|
||||
);
|
||||
|
||||
vecs.utxo_cohorts.push_aggregate_percentiles(
|
||||
block_price,
|
||||
date_opt,
|
||||
&vecs.states_path,
|
||||
)?;
|
||||
vecs.utxo_cohorts
|
||||
.push_aggregate_percentiles(block_price, date_opt, &vecs.states_path)?;
|
||||
|
||||
// Periodic checkpoint flush
|
||||
if height != last_height
|
||||
@@ -534,20 +552,16 @@ fn push_cohort_states(
|
||||
// Phase 1: push + unrealized (no reset yet — states still needed for aggregation)
|
||||
rayon::join(
|
||||
|| {
|
||||
utxo_cohorts
|
||||
.par_iter_separate_mut()
|
||||
.for_each(|v| {
|
||||
v.push_state(height);
|
||||
v.push_unrealized_state(height_price);
|
||||
})
|
||||
utxo_cohorts.par_iter_separate_mut().for_each(|v| {
|
||||
v.push_state(height);
|
||||
v.push_unrealized_state(height_price);
|
||||
})
|
||||
},
|
||||
|| {
|
||||
addr_cohorts
|
||||
.par_iter_separate_mut()
|
||||
.for_each(|v| {
|
||||
v.push_state(height);
|
||||
v.push_unrealized_state(height_price);
|
||||
})
|
||||
addr_cohorts.par_iter_separate_mut().for_each(|v| {
|
||||
v.push_state(height);
|
||||
v.push_unrealized_state(height_price);
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -116,11 +116,10 @@ impl<'a> TxInReaders<'a> {
|
||||
current_height: Height,
|
||||
) -> (&[Sats], &[Height], &[OutputType], &[TypeIndex]) {
|
||||
let end = first_txin_index + input_count;
|
||||
self.txins.spent.value.collect_range_into_at(
|
||||
first_txin_index,
|
||||
end,
|
||||
&mut self.values_buf,
|
||||
);
|
||||
self.txins
|
||||
.spent
|
||||
.value
|
||||
.collect_range_into_at(first_txin_index, end, &mut self.values_buf);
|
||||
self.indexer.vecs.inputs.outpoint.collect_range_into_at(
|
||||
first_txin_index,
|
||||
end,
|
||||
@@ -138,8 +137,8 @@ impl<'a> TxInReaders<'a> {
|
||||
);
|
||||
|
||||
self.prev_heights_buf.clear();
|
||||
self.prev_heights_buf.extend(
|
||||
self.outpoints_buf.iter().map(|outpoint| {
|
||||
self.prev_heights_buf
|
||||
.extend(self.outpoints_buf.iter().map(|outpoint| {
|
||||
if outpoint.is_coinbase() {
|
||||
current_height
|
||||
} else {
|
||||
@@ -147,8 +146,7 @@ impl<'a> TxInReaders<'a> {
|
||||
.get(outpoint.tx_index())
|
||||
.unwrap_or(current_height)
|
||||
}
|
||||
}),
|
||||
);
|
||||
}));
|
||||
|
||||
(
|
||||
&self.values_buf,
|
||||
@@ -166,10 +164,7 @@ pub struct VecsReaders {
|
||||
}
|
||||
|
||||
impl VecsReaders {
|
||||
pub(crate) fn new(
|
||||
any_addr_indexes: &AnyAddrIndexesVecs,
|
||||
addrs_data: &AddrsDataVecs,
|
||||
) -> Self {
|
||||
pub(crate) fn new(any_addr_indexes: &AnyAddrIndexesVecs, addrs_data: &AddrsDataVecs) -> Self {
|
||||
Self {
|
||||
addr_type_index_to_any_addr_index: ByAddrType {
|
||||
p2a: any_addr_indexes.p2a.create_reader(),
|
||||
|
||||
@@ -185,10 +185,7 @@ fn rollback_states(
|
||||
heights.insert(chain_height);
|
||||
|
||||
let Ok(stamps) = addr_indexes_rollbacks else {
|
||||
warn!(
|
||||
"addr_indexes rollback failed: {:?}",
|
||||
addr_indexes_rollbacks
|
||||
);
|
||||
warn!("addr_indexes rollback failed: {:?}", addr_indexes_rollbacks);
|
||||
return Height::ZERO;
|
||||
};
|
||||
for (i, s) in stamps.iter().enumerate() {
|
||||
|
||||
@@ -5,7 +5,10 @@ use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
distribution::{
|
||||
metrics::ImportConfig,
|
||||
state::{CohortState, CostBasisOps, RealizedOps},
|
||||
},
|
||||
internal::{AmountPerBlockCumulativeRolling, PerBlockCumulativeRolling},
|
||||
prices,
|
||||
};
|
||||
@@ -46,19 +49,18 @@ impl ActivityCore {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(
|
||||
&mut self,
|
||||
state: &CohortState<impl RealizedOps, impl CostBasisOps>,
|
||||
) {
|
||||
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
|
||||
self.minimal.push_state(state);
|
||||
self.coindays_destroyed.block.push(
|
||||
StoredF64::from(Bitcoin::from(state.satdays_destroyed)),
|
||||
);
|
||||
self.coindays_destroyed
|
||||
.block
|
||||
.push(StoredF64::from(Bitcoin::from(state.satdays_destroyed)));
|
||||
self.transfer_volume_in_profit
|
||||
.block.sats
|
||||
.block
|
||||
.sats
|
||||
.push(state.realized.sent_in_profit());
|
||||
self.transfer_volume_in_loss
|
||||
.block.sats
|
||||
.block
|
||||
.sats
|
||||
.push(state.realized.sent_in_loss());
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ use vecdb::{AnyStoredVec, Exit, ReadableCloneableVec, Rw, StorageMode};
|
||||
use crate::internal::{Identity, LazyPerBlock, PerBlock, Windows};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
distribution::{
|
||||
metrics::ImportConfig,
|
||||
state::{CohortState, CostBasisOps, RealizedOps},
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
@@ -33,7 +36,12 @@ impl ActivityFull {
|
||||
let coinyears_destroyed = LazyPerBlock::from_height_source::<Identity<StoredF64>>(
|
||||
&cfg.name("coinyears_destroyed"),
|
||||
cfg.version + v1,
|
||||
inner.coindays_destroyed.sum._1y.height.read_only_boxed_clone(),
|
||||
inner
|
||||
.coindays_destroyed
|
||||
.sum
|
||||
._1y
|
||||
.height
|
||||
.read_only_boxed_clone(),
|
||||
cfg.indexes,
|
||||
);
|
||||
|
||||
@@ -89,7 +97,8 @@ impl ActivityFull {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.inner.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.inner
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
|
||||
for ((dormancy, cdd_sum), tv_sum) in self
|
||||
.dormancy
|
||||
|
||||
@@ -4,7 +4,10 @@ use brk_types::{Indexes, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::{metrics::ImportConfig, state::{CohortState, CostBasisOps, RealizedOps}},
|
||||
distribution::{
|
||||
metrics::ImportConfig,
|
||||
state::{CohortState, CostBasisOps, RealizedOps},
|
||||
},
|
||||
internal::AmountPerBlockCumulativeRolling,
|
||||
prices,
|
||||
};
|
||||
@@ -23,16 +26,11 @@ impl ActivityMinimal {
|
||||
}
|
||||
|
||||
pub(crate) fn min_len(&self) -> usize {
|
||||
self.transfer_volume
|
||||
.block.sats
|
||||
.len()
|
||||
self.transfer_volume.block.sats.len()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(
|
||||
&mut self,
|
||||
state: &CohortState<impl RealizedOps, impl CostBasisOps>,
|
||||
) {
|
||||
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
|
||||
self.transfer_volume.block.sats.push(state.sent);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,7 @@ pub trait ActivityLike: Send + Sync {
|
||||
fn as_core(&self) -> &ActivityCore;
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore;
|
||||
fn min_len(&self) -> usize;
|
||||
fn push_state<R: RealizedOps>(
|
||||
&mut self,
|
||||
state: &CohortState<R, impl CostBasisOps>,
|
||||
);
|
||||
fn push_state<R: RealizedOps>(&mut self, state: &CohortState<R, impl CostBasisOps>);
|
||||
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()>;
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
@@ -39,37 +36,69 @@ pub trait ActivityLike: Send + Sync {
|
||||
}
|
||||
|
||||
impl ActivityLike for ActivityCore {
|
||||
fn as_core(&self) -> &ActivityCore { self }
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore { self }
|
||||
fn min_len(&self) -> usize { self.min_len() }
|
||||
fn as_core(&self) -> &ActivityCore {
|
||||
self
|
||||
}
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore {
|
||||
self
|
||||
}
|
||||
fn min_len(&self) -> usize {
|
||||
self.min_len()
|
||||
}
|
||||
fn push_state<R: RealizedOps>(&mut self, state: &CohortState<R, impl CostBasisOps>) {
|
||||
self.push_state(state);
|
||||
}
|
||||
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
|
||||
self.validate_computed_versions(base_version)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&ActivityCore], exit: &Exit) -> Result<()> {
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&ActivityCore],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_rest_part1(prices, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl ActivityLike for ActivityFull {
|
||||
fn as_core(&self) -> &ActivityCore { &self.inner }
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore { &mut self.inner }
|
||||
fn min_len(&self) -> usize { self.full_min_len() }
|
||||
fn as_core(&self) -> &ActivityCore {
|
||||
&self.inner
|
||||
}
|
||||
fn as_core_mut(&mut self) -> &mut ActivityCore {
|
||||
&mut self.inner
|
||||
}
|
||||
fn min_len(&self) -> usize {
|
||||
self.full_min_len()
|
||||
}
|
||||
fn push_state<R: RealizedOps>(&mut self, state: &CohortState<R, impl CostBasisOps>) {
|
||||
self.full_push_state(state);
|
||||
}
|
||||
fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
|
||||
self.inner.validate_computed_versions(base_version)
|
||||
}
|
||||
fn compute_from_stateful(&mut self, starting_indexes: &Indexes, others: &[&ActivityCore], exit: &Exit) -> Result<()> {
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&ActivityCore],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
}
|
||||
fn compute_rest_part1(&mut self, prices: &prices::Vecs, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
fn compute_rest_part1(
|
||||
&mut self,
|
||||
prices: &prices::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_rest_part1(prices, starting_indexes, exit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use brk_cohort::Filter;
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
Cents, Dollars, Height, Indexes, Version,
|
||||
};
|
||||
use brk_types::{Cents, Dollars, Height, Indexes, Version};
|
||||
use vecdb::AnyStoredVec;
|
||||
use vecdb::{Exit, ReadOnlyClone, ReadableVec, Rw, StorageMode};
|
||||
|
||||
@@ -136,11 +134,8 @@ impl AllCohortMetrics {
|
||||
)?;
|
||||
|
||||
let all_utxo_count = self.outputs.unspent_count.height.read_only_clone();
|
||||
self.outputs.compute_part2(
|
||||
starting_indexes.height,
|
||||
&all_utxo_count,
|
||||
exit,
|
||||
)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, &all_utxo_count, exit)?;
|
||||
|
||||
self.cost_basis.compute_prices(
|
||||
starting_indexes,
|
||||
@@ -154,11 +149,8 @@ impl AllCohortMetrics {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.unrealized.compute_sentiment(
|
||||
starting_indexes,
|
||||
&prices.spot.cents.height,
|
||||
exit,
|
||||
)?;
|
||||
self.unrealized
|
||||
.compute_sentiment(starting_indexes, &prices.spot.cents.height, exit)?;
|
||||
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
|
||||
@@ -87,16 +87,12 @@ impl BasicCohortMetrics {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
&self.supply,
|
||||
all_supply_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.relative
|
||||
.compute(starting_indexes.height, &self.supply, all_supply_sats, exit)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -92,7 +92,10 @@ impl CoreCohortMetrics {
|
||||
)?;
|
||||
self.unrealized.compute_from_stateful(
|
||||
starting_indexes,
|
||||
&others.iter().map(|v| v.unrealized_core()).collect::<Vec<_>>(),
|
||||
&others
|
||||
.iter()
|
||||
.map(|v| v.unrealized_core())
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -105,16 +108,14 @@ impl CoreCohortMetrics {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.supply
|
||||
.compute(prices, starting_indexes.height, exit)?;
|
||||
self.supply.compute(prices, starting_indexes.height, exit)?;
|
||||
|
||||
self.outputs.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
self.activity
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.realized.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.unrealized.compute_rest(starting_indexes, exit)?;
|
||||
|
||||
@@ -144,14 +145,11 @@ impl CoreCohortMetrics {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.relative.compute(
|
||||
starting_indexes.height,
|
||||
&self.supply,
|
||||
all_supply_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.relative
|
||||
.compute(starting_indexes.height, &self.supply, all_supply_sats, exit)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -104,8 +104,7 @@ impl MinimalCohortMetrics {
|
||||
self.outputs.compute_rest(starting_indexes.height, exit)?;
|
||||
self.activity
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.realized.compute_rest_part1(starting_indexes, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -130,7 +129,8 @@ impl MinimalCohortMetrics {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -66,8 +66,7 @@ impl TypeCohortMetrics {
|
||||
self.outputs.compute_rest(starting_indexes.height, exit)?;
|
||||
self.activity
|
||||
.compute_rest_part1(prices, starting_indexes, exit)?;
|
||||
self.realized
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.realized.compute_rest_part1(starting_indexes, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -92,7 +91,8 @@ impl TypeCohortMetrics {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.outputs.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
self.outputs
|
||||
.compute_part2(starting_indexes.height, all_utxo_count, exit)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ use brk_types::CentsSquaredSats;
|
||||
use brk_types::{BasisPoints16, Cents, Height, Indexes, Sats, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::internal::{
|
||||
PERCENTILES_LEN, PerBlock, PercentPerBlock, PercentilesVecs, Price,
|
||||
};
|
||||
use crate::internal::{PERCENTILES_LEN, PerBlock, PercentPerBlock, PercentilesVecs, Price};
|
||||
|
||||
use super::ImportConfig;
|
||||
|
||||
@@ -33,12 +31,32 @@ impl CostBasis {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
in_profit: CostBasisSide {
|
||||
per_coin: Price::forced_import(cfg.db, &cfg.name("cost_basis_in_profit_per_coin"), cfg.version + Version::ONE, cfg.indexes)?,
|
||||
per_dollar: Price::forced_import(cfg.db, &cfg.name("cost_basis_in_profit_per_dollar"), cfg.version + Version::ONE, cfg.indexes)?,
|
||||
per_coin: Price::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis_in_profit_per_coin"),
|
||||
cfg.version + Version::ONE,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
per_dollar: Price::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis_in_profit_per_dollar"),
|
||||
cfg.version + Version::ONE,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
},
|
||||
in_loss: CostBasisSide {
|
||||
per_coin: Price::forced_import(cfg.db, &cfg.name("cost_basis_in_loss_per_coin"), cfg.version + Version::ONE, cfg.indexes)?,
|
||||
per_dollar: Price::forced_import(cfg.db, &cfg.name("cost_basis_in_loss_per_dollar"), cfg.version + Version::ONE, cfg.indexes)?,
|
||||
per_coin: Price::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis_in_loss_per_coin"),
|
||||
cfg.version + Version::ONE,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
per_dollar: Price::forced_import(
|
||||
cfg.db,
|
||||
&cfg.name("cost_basis_in_loss_per_dollar"),
|
||||
cfg.version + Version::ONE,
|
||||
cfg.indexes,
|
||||
)?,
|
||||
},
|
||||
min: cfg.import("cost_basis_min", Version::ZERO)?,
|
||||
max: cfg.import("cost_basis_max", Version::ZERO)?,
|
||||
|
||||
@@ -51,7 +51,12 @@ macro_rules! impl_cohort_accessors {
|
||||
fn unrealized_mut(&mut self) -> &mut Self::UnrealizedVecs {
|
||||
&mut self.unrealized
|
||||
}
|
||||
fn supply_and_unrealized_mut(&mut self) -> (&$crate::distribution::metrics::SupplyCore, &mut Self::UnrealizedVecs) {
|
||||
fn supply_and_unrealized_mut(
|
||||
&mut self,
|
||||
) -> (
|
||||
&$crate::distribution::metrics::SupplyCore,
|
||||
&mut Self::UnrealizedVecs,
|
||||
) {
|
||||
(&*self.supply, &mut self.unrealized)
|
||||
}
|
||||
};
|
||||
@@ -94,7 +99,12 @@ macro_rules! impl_cohort_accessors_inner {
|
||||
fn unrealized_mut(&mut self) -> &mut Self::UnrealizedVecs {
|
||||
&mut self.inner.unrealized
|
||||
}
|
||||
fn supply_and_unrealized_mut(&mut self) -> (&$crate::distribution::metrics::SupplyCore, &mut Self::UnrealizedVecs) {
|
||||
fn supply_and_unrealized_mut(
|
||||
&mut self,
|
||||
) -> (
|
||||
&$crate::distribution::metrics::SupplyCore,
|
||||
&mut Self::UnrealizedVecs,
|
||||
) {
|
||||
(&*self.inner.supply, &mut self.inner.unrealized)
|
||||
}
|
||||
};
|
||||
@@ -125,8 +135,7 @@ pub use realized::{
|
||||
pub use relative::{RelativeForAll, RelativeToAll, RelativeWithExtended};
|
||||
pub use supply::{SupplyBase, SupplyCore};
|
||||
pub use unrealized::{
|
||||
UnrealizedBasic, UnrealizedCore, UnrealizedFull, UnrealizedLike,
|
||||
UnrealizedMinimal,
|
||||
UnrealizedBasic, UnrealizedCore, UnrealizedFull, UnrealizedLike, UnrealizedMinimal,
|
||||
};
|
||||
|
||||
use brk_cohort::Filter;
|
||||
@@ -250,10 +259,7 @@ pub trait CohortMetricsBase:
|
||||
.min(self.unrealized().min_stateful_len())
|
||||
}
|
||||
|
||||
fn push_state(
|
||||
&mut self,
|
||||
state: &CohortState<RealizedState, CostBasisData<WithCapital>>,
|
||||
) {
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.supply_mut().push_state(state);
|
||||
self.outputs_mut().push_state(state);
|
||||
self.activity_mut().push_state(state);
|
||||
|
||||
@@ -6,7 +6,9 @@ use vecdb::{AnyStoredVec, AnyVec, Database, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
indexes,
|
||||
internal::{AmountPerBlock, AmountPerBlockWithDeltas, CachedWindowStarts, PerBlock, RatioPerBlock},
|
||||
internal::{
|
||||
AmountPerBlock, AmountPerBlockWithDeltas, CachedWindowStarts, PerBlock, RatioPerBlock,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
|
||||
@@ -183,22 +185,34 @@ impl ProfitabilityBucket {
|
||||
|
||||
self.supply.all.sats.height.compute_sum_of_others(
|
||||
max_from,
|
||||
&sources.iter().map(|s| &s.supply.all.sats.height).collect::<Vec<_>>(),
|
||||
&sources
|
||||
.iter()
|
||||
.map(|s| &s.supply.all.sats.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.supply.sth.sats.height.compute_sum_of_others(
|
||||
max_from,
|
||||
&sources.iter().map(|s| &s.supply.sth.sats.height).collect::<Vec<_>>(),
|
||||
&sources
|
||||
.iter()
|
||||
.map(|s| &s.supply.sth.sats.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.realized_cap.all.height.compute_sum_of_others(
|
||||
max_from,
|
||||
&sources.iter().map(|s| &s.realized_cap.all.height).collect::<Vec<_>>(),
|
||||
&sources
|
||||
.iter()
|
||||
.map(|s| &s.realized_cap.all.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
self.realized_cap.sth.height.compute_sum_of_others(
|
||||
max_from,
|
||||
&sources.iter().map(|s| &s.realized_cap.sth.height).collect::<Vec<_>>(),
|
||||
&sources
|
||||
.iter()
|
||||
.map(|s| &s.realized_cap.sth.height)
|
||||
.collect::<Vec<_>>(),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPointsSigned32, 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, LazyVecFrom1, ReadableCloneableVec, ReadableVec, Rw, StorageMode,
|
||||
@@ -42,7 +44,8 @@ pub struct RealizedCore<M: StorageMode = Rw> {
|
||||
|
||||
#[traversable(wrap = "loss", rename = "negative")]
|
||||
pub neg_loss: NegRealizedLoss,
|
||||
pub net_pnl: FiatPerBlockCumulativeWithSumsAndDeltas<CentsSigned, CentsSigned, BasisPointsSigned32, M>,
|
||||
pub net_pnl:
|
||||
FiatPerBlockCumulativeWithSumsAndDeltas<CentsSigned, CentsSigned, BasisPointsSigned32, M>,
|
||||
pub sopr: RealizedSoprCore<M>,
|
||||
}
|
||||
|
||||
@@ -107,7 +110,10 @@ impl RealizedCore {
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(&mut self, state: &CohortState<impl RealizedOps, impl CostBasisOps>) {
|
||||
self.minimal.push_state(state);
|
||||
self.sopr.value_destroyed.block.push(state.realized.value_destroyed());
|
||||
self.sopr
|
||||
.value_destroyed
|
||||
.block
|
||||
.push(state.realized.value_destroyed());
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
@@ -135,8 +141,7 @@ impl RealizedCore {
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.minimal
|
||||
.compute_rest_part1(starting_indexes, exit)?;
|
||||
self.minimal.compute_rest_part1(starting_indexes, exit)?;
|
||||
|
||||
self.sopr
|
||||
.value_destroyed
|
||||
@@ -169,8 +174,7 @@ impl RealizedCore {
|
||||
self.minimal
|
||||
.compute_rest_part2(prices, starting_indexes, height_to_supply, exit)?;
|
||||
|
||||
self.net_pnl
|
||||
.compute_rest(starting_indexes.height, exit)?;
|
||||
self.net_pnl.compute_rest(starting_indexes.height, exit)?;
|
||||
|
||||
self.sopr
|
||||
.ratio
|
||||
|
||||
@@ -178,7 +178,8 @@ impl RealizedFull {
|
||||
.push(state.realized.investor_cap_raw());
|
||||
self.peak_regret
|
||||
.value
|
||||
.block.cents
|
||||
.block
|
||||
.cents
|
||||
.push(state.realized.peak_regret());
|
||||
}
|
||||
|
||||
@@ -218,10 +219,7 @@ impl RealizedFull {
|
||||
};
|
||||
self.investor.price.cents.height.push(investor_price);
|
||||
|
||||
self.peak_regret
|
||||
.value
|
||||
.block.cents
|
||||
.push(accum.peak_regret());
|
||||
self.peak_regret.value.block.cents.push(accum.peak_regret());
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest_part1(
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Height, Indexes, Sats, StoredF32,
|
||||
Version,
|
||||
};
|
||||
use vecdb::{
|
||||
AnyStoredVec, AnyVec, Exit, ReadableVec, Rw, StorageMode, WritableVec,
|
||||
BasisPoints32, BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Height, Indexes, Sats,
|
||||
StoredF32, Version,
|
||||
};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
internal::{
|
||||
FiatPerBlockCumulativeWithSums,
|
||||
FiatPerBlockWithDeltas, Identity, LazyPerBlock, PriceWithRatioPerBlock,
|
||||
FiatPerBlockCumulativeWithSums, FiatPerBlockWithDeltas, Identity, LazyPerBlock,
|
||||
PriceWithRatioPerBlock,
|
||||
},
|
||||
prices,
|
||||
};
|
||||
@@ -111,23 +109,24 @@ impl RealizedMinimal {
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let cap = &self.cap.cents.height;
|
||||
self.price.compute_all(prices, starting_indexes, exit, |v| {
|
||||
Ok(v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
cap,
|
||||
height_to_supply,
|
||||
|(i, cap_cents, supply, ..)| {
|
||||
let cap = cap_cents.as_u128();
|
||||
let supply_sats = Sats::from(supply).as_u128();
|
||||
if supply_sats == 0 {
|
||||
(i, Cents::ZERO)
|
||||
} else {
|
||||
(i, Cents::from(cap * Sats::ONE_BTC_U128 / supply_sats))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
self.price
|
||||
.compute_all(prices, starting_indexes, exit, |v| {
|
||||
Ok(v.compute_transform2(
|
||||
starting_indexes.height,
|
||||
cap,
|
||||
height_to_supply,
|
||||
|(i, cap_cents, supply, ..)| {
|
||||
let cap = cap_cents.as_u128();
|
||||
let supply_sats = Sats::from(supply).as_u128();
|
||||
if supply_sats == 0 {
|
||||
(i, Cents::ZERO)
|
||||
} else {
|
||||
(i, Cents::from(cap * Sats::ONE_BTC_U128 / supply_sats))
|
||||
}
|
||||
},
|
||||
exit,
|
||||
)?)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ mod core;
|
||||
mod full;
|
||||
mod minimal;
|
||||
|
||||
pub use adjusted::AdjustedSopr;
|
||||
pub use self::core::RealizedCore;
|
||||
pub use adjusted::AdjustedSopr;
|
||||
pub use full::{RealizedFull, RealizedFullAccum};
|
||||
pub use minimal::RealizedMinimal;
|
||||
|
||||
@@ -12,7 +12,7 @@ use brk_error::Result;
|
||||
use brk_types::Indexes;
|
||||
use vecdb::Exit;
|
||||
|
||||
use crate::distribution::state::{WithCapital, CohortState, CostBasisData, RealizedState};
|
||||
use crate::distribution::state::{CohortState, CostBasisData, RealizedState, WithCapital};
|
||||
|
||||
pub trait RealizedLike: Send + Sync {
|
||||
fn as_core(&self) -> &RealizedCore;
|
||||
@@ -29,9 +29,15 @@ pub trait RealizedLike: Send + Sync {
|
||||
}
|
||||
|
||||
impl RealizedLike for RealizedCore {
|
||||
fn as_core(&self) -> &RealizedCore { self }
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore { self }
|
||||
fn min_stateful_len(&self) -> usize { self.min_stateful_len() }
|
||||
fn as_core(&self) -> &RealizedCore {
|
||||
self
|
||||
}
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore {
|
||||
self
|
||||
}
|
||||
fn min_stateful_len(&self) -> usize {
|
||||
self.min_stateful_len()
|
||||
}
|
||||
#[inline(always)]
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.push_state(state)
|
||||
@@ -39,15 +45,26 @@ impl RealizedLike for RealizedCore {
|
||||
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<()> {
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&RealizedCore],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
}
|
||||
}
|
||||
|
||||
impl RealizedLike for RealizedFull {
|
||||
fn as_core(&self) -> &RealizedCore { &self.core }
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore { &mut self.core }
|
||||
fn min_stateful_len(&self) -> usize { self.min_stateful_len() }
|
||||
fn as_core(&self) -> &RealizedCore {
|
||||
&self.core
|
||||
}
|
||||
fn as_core_mut(&mut self) -> &mut RealizedCore {
|
||||
&mut self.core
|
||||
}
|
||||
fn min_stateful_len(&self) -> usize {
|
||||
self.min_stateful_len()
|
||||
}
|
||||
#[inline(always)]
|
||||
fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
|
||||
self.push_state(state)
|
||||
@@ -55,7 +72,12 @@ impl RealizedLike for RealizedFull {
|
||||
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<()> {
|
||||
fn compute_from_stateful(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
others: &[&RealizedCore],
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_from_stateful(starting_indexes, others, exit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ impl RelativeExtendedOwnMarketCap {
|
||||
let v2 = Version::new(2);
|
||||
|
||||
Ok(Self {
|
||||
unrealized_profit_to_own_mcap: cfg
|
||||
.import("unrealized_profit_to_own_mcap", v2)?,
|
||||
unrealized_profit_to_own_mcap: cfg.import("unrealized_profit_to_own_mcap", v2)?,
|
||||
unrealized_loss_to_own_mcap: cfg
|
||||
.import("unrealized_loss_to_own_mcap", Version::new(3))?,
|
||||
net_unrealized_pnl_to_own_mcap: cfg
|
||||
|
||||
@@ -16,7 +16,6 @@ pub struct RelativeExtendedOwnPnl<M: StorageMode = Rw> {
|
||||
pub unrealized_loss_to_own_gross_pnl: PercentPerBlock<BasisPoints16, M>,
|
||||
#[traversable(wrap = "unrealized/net_pnl", rename = "to_own_gross_pnl")]
|
||||
pub net_unrealized_pnl_to_own_gross_pnl: PercentPerBlock<BasisPointsSigned32, M>,
|
||||
|
||||
}
|
||||
|
||||
impl RelativeExtendedOwnPnl {
|
||||
@@ -26,8 +25,7 @@ impl RelativeExtendedOwnPnl {
|
||||
Ok(Self {
|
||||
unrealized_profit_to_own_gross_pnl: cfg
|
||||
.import("unrealized_profit_to_own_gross_pnl", v1)?,
|
||||
unrealized_loss_to_own_gross_pnl: cfg
|
||||
.import("unrealized_loss_to_own_gross_pnl", v1)?,
|
||||
unrealized_loss_to_own_gross_pnl: cfg.import("unrealized_loss_to_own_gross_pnl", v1)?,
|
||||
net_unrealized_pnl_to_own_gross_pnl: cfg
|
||||
.import("net_unrealized_pnl_to_own_gross_pnl", Version::new(3))?,
|
||||
})
|
||||
|
||||
@@ -6,7 +6,7 @@ use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, SupplyCore, UnrealizedFull};
|
||||
|
||||
use super::{RelativeFull, RelativeExtendedOwnPnl};
|
||||
use super::{RelativeExtendedOwnPnl, RelativeFull};
|
||||
|
||||
/// Relative metrics for the "all" cohort (base + own_pnl, NO rel_to_all).
|
||||
#[derive(Deref, DerefMut, Traversable)]
|
||||
@@ -35,15 +35,14 @@ impl RelativeForAll {
|
||||
market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.base.compute(
|
||||
self.base
|
||||
.compute(max_from, supply, &unrealized.inner.basic, market_cap, exit)?;
|
||||
self.extended_own_pnl.compute(
|
||||
max_from,
|
||||
supply,
|
||||
&unrealized.inner.basic,
|
||||
market_cap,
|
||||
&unrealized.inner,
|
||||
&unrealized.gross_pnl.usd.height,
|
||||
exit,
|
||||
)?;
|
||||
self.extended_own_pnl
|
||||
.compute(max_from, &unrealized.inner, &unrealized.gross_pnl.usd.height, exit)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,10 @@ impl RelativeFull {
|
||||
let v2 = Version::new(2);
|
||||
|
||||
Ok(Self {
|
||||
supply_in_profit_to_own: cfg
|
||||
.import("supply_in_profit_to_own", v1)?,
|
||||
supply_in_profit_to_own: cfg.import("supply_in_profit_to_own", v1)?,
|
||||
supply_in_loss_to_own: cfg.import("supply_in_loss_to_own", v1)?,
|
||||
unrealized_profit_to_mcap: cfg
|
||||
.import("unrealized_profit_to_mcap", v2)?,
|
||||
unrealized_loss_to_mcap: cfg
|
||||
.import("unrealized_loss_to_mcap", v2)?,
|
||||
unrealized_profit_to_mcap: cfg.import("unrealized_profit_to_mcap", v2)?,
|
||||
unrealized_loss_to_mcap: cfg.import("unrealized_loss_to_mcap", v2)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@ pub struct RelativeToAll<M: StorageMode = Rw> {
|
||||
impl RelativeToAll {
|
||||
pub(crate) fn forced_import(cfg: &ImportConfig) -> Result<Self> {
|
||||
Ok(Self {
|
||||
supply_to_circulating: cfg
|
||||
.import("supply_to_circulating", Version::ONE)?,
|
||||
supply_to_circulating: cfg.import("supply_to_circulating", Version::ONE)?,
|
||||
supply_in_profit_to_circulating: cfg
|
||||
.import("supply_in_profit_to_circulating", Version::ONE)?,
|
||||
supply_in_loss_to_circulating: cfg
|
||||
|
||||
@@ -6,7 +6,7 @@ use vecdb::{Exit, ReadableVec, Rw, StorageMode};
|
||||
|
||||
use crate::distribution::metrics::{ImportConfig, SupplyCore, UnrealizedFull};
|
||||
|
||||
use super::{RelativeFull, RelativeExtendedOwnMarketCap, RelativeExtendedOwnPnl, RelativeToAll};
|
||||
use super::{RelativeExtendedOwnMarketCap, RelativeExtendedOwnPnl, RelativeFull, RelativeToAll};
|
||||
|
||||
/// Full extended relative metrics (base + rel_to_all + own_market_cap + own_pnl).
|
||||
/// Used by: sth, lth cohorts.
|
||||
@@ -45,23 +45,18 @@ impl RelativeWithExtended {
|
||||
own_market_cap: &impl ReadableVec<Height, Dollars>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.base.compute(
|
||||
max_from,
|
||||
supply,
|
||||
&unrealized.inner.basic,
|
||||
market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.rel_to_all.compute(
|
||||
max_from,
|
||||
supply,
|
||||
all_supply_sats,
|
||||
exit,
|
||||
)?;
|
||||
self.base
|
||||
.compute(max_from, supply, &unrealized.inner.basic, market_cap, exit)?;
|
||||
self.rel_to_all
|
||||
.compute(max_from, supply, all_supply_sats, exit)?;
|
||||
self.extended_own_market_cap
|
||||
.compute(max_from, &unrealized.inner, own_market_cap, exit)?;
|
||||
self.extended_own_pnl
|
||||
.compute(max_from, &unrealized.inner, &unrealized.gross_pnl.usd.height, exit)?;
|
||||
self.extended_own_pnl.compute(
|
||||
max_from,
|
||||
&unrealized.inner,
|
||||
&unrealized.gross_pnl.usd.height,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,13 @@ use brk_traversable::Traversable;
|
||||
use brk_types::{BasisPointsSigned32, Height, Indexes, Sats, SatsSigned, Version};
|
||||
use vecdb::{AnyStoredVec, AnyVec, Exit, Rw, StorageMode, WritableVec};
|
||||
|
||||
use crate::{distribution::state::{CohortState, CostBasisOps, RealizedOps}, prices};
|
||||
|
||||
use crate::internal::{
|
||||
AmountPerBlock, LazyRollingDeltasFromHeight,
|
||||
use crate::{
|
||||
distribution::state::{CohortState, CostBasisOps, RealizedOps},
|
||||
prices,
|
||||
};
|
||||
|
||||
use crate::internal::{AmountPerBlock, LazyRollingDeltasFromHeight};
|
||||
|
||||
use crate::distribution::metrics::ImportConfig;
|
||||
|
||||
/// Base supply metrics: total supply only (2 stored vecs).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mod base;
|
||||
mod core;
|
||||
|
||||
pub use base::SupplyBase;
|
||||
pub use self::core::SupplyCore;
|
||||
pub use base::SupplyBase;
|
||||
|
||||
@@ -54,14 +54,8 @@ impl UnrealizedBasic {
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn push_state(&mut self, state: &UnrealizedState) {
|
||||
self.profit
|
||||
.cents
|
||||
.height
|
||||
.push(state.unrealized_profit);
|
||||
self.loss
|
||||
.cents
|
||||
.height
|
||||
.push(state.unrealized_loss);
|
||||
self.profit.cents.height.push(state.unrealized_profit);
|
||||
self.loss.cents.height.push(state.unrealized_loss);
|
||||
}
|
||||
|
||||
pub(crate) fn collect_vecs_mut(&mut self) -> Vec<&mut dyn AnyStoredVec> {
|
||||
|
||||
@@ -5,10 +5,7 @@ use derive_more::{Deref, DerefMut};
|
||||
use vecdb::{AnyStoredVec, Exit, Rw, StorageMode};
|
||||
|
||||
use crate::{
|
||||
distribution::{
|
||||
metrics::ImportConfig,
|
||||
state::UnrealizedState,
|
||||
},
|
||||
distribution::{metrics::ImportConfig, state::UnrealizedState},
|
||||
internal::{CentsSubtractToCentsSigned, FiatPerBlock},
|
||||
};
|
||||
|
||||
@@ -60,11 +57,7 @@ impl UnrealizedCore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rest(
|
||||
&mut self,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
pub(crate) fn compute_rest(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
self.net_pnl
|
||||
.cents
|
||||
.height
|
||||
|
||||
@@ -77,6 +77,12 @@ impl UnrealizedLike for UnrealizedFull {
|
||||
supply_in_loss_sats: &(impl ReadableVec<Height, Sats> + Sync),
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_rest_all(prices, starting_indexes, supply_in_profit_sats, supply_in_loss_sats, exit)
|
||||
self.compute_rest_all(
|
||||
prices,
|
||||
starting_indexes,
|
||||
supply_in_profit_sats,
|
||||
supply_in_loss_sats,
|
||||
exit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_types::{Age, Cents, CentsCompact, CentsSats, CentsSquaredSats, CostBasisSnapshot, Height, Sats, SupplyState};
|
||||
use brk_types::{
|
||||
Age, Cents, CentsCompact, CentsSats, CentsSquaredSats, CostBasisSnapshot, Height, Sats,
|
||||
SupplyState,
|
||||
};
|
||||
|
||||
use super::super::{cost_basis::{Accumulate, CostBasisData, CostBasisOps, RealizedOps, UnrealizedState}, pending::PendingDelta};
|
||||
use super::super::{
|
||||
cost_basis::{Accumulate, CostBasisData, CostBasisOps, RealizedOps, UnrealizedState},
|
||||
pending::PendingDelta,
|
||||
};
|
||||
|
||||
pub struct SendPrecomputed {
|
||||
pub sats: Sats,
|
||||
@@ -193,11 +199,7 @@ impl<R: RealizedOps, C: CostBasisOps> CohortState<R, C> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn send_utxo_precomputed(
|
||||
&mut self,
|
||||
supply: &SupplyState,
|
||||
pre: &SendPrecomputed,
|
||||
) {
|
||||
pub(crate) fn send_utxo_precomputed(&mut self, supply: &SupplyState, pre: &SendPrecomputed) {
|
||||
self.supply -= supply;
|
||||
self.sent += pre.sats;
|
||||
self.spent_utxo_count += supply.utxo_count;
|
||||
@@ -205,8 +207,13 @@ impl<R: RealizedOps, C: CostBasisOps> CohortState<R, C> {
|
||||
self.satdays_destroyed += pre.age.satdays_destroyed(pre.sats);
|
||||
}
|
||||
|
||||
self.realized
|
||||
.send(pre.sats, pre.current_ps, pre.prev_ps, pre.ath_ps, pre.prev_investor_cap);
|
||||
self.realized.send(
|
||||
pre.sats,
|
||||
pre.current_ps,
|
||||
pre.prev_ps,
|
||||
pre.ath_ps,
|
||||
pre.prev_investor_cap,
|
||||
);
|
||||
|
||||
self.cost_basis
|
||||
.decrement(pre.prev_price, pre.sats, pre.prev_ps, pre.prev_investor_cap);
|
||||
|
||||
@@ -370,7 +370,11 @@ impl<S: Accumulate> CostBasisOps for CostBasisData<S> {
|
||||
let (base, rest) = CostBasisDistribution::deserialize_with_rest(&data)?;
|
||||
self.map = Some(base);
|
||||
self.raw.state = Some(RawState::deserialize(rest)?);
|
||||
debug_assert!(rest.len() >= 32, "CostBasisData state too short: {} bytes", rest.len());
|
||||
debug_assert!(
|
||||
rest.len() >= 32,
|
||||
"CostBasisData state too short: {} bytes",
|
||||
rest.len()
|
||||
);
|
||||
self.investor_cap_raw = CentsSquaredSats::from_bytes(&rest[16..32])?;
|
||||
self.pending.clear();
|
||||
self.raw.pending_cap = PendingCapDelta::default();
|
||||
@@ -435,7 +439,9 @@ impl<S: Accumulate> CostBasisOps for CostBasisData<S> {
|
||||
Path: {:?}\n\
|
||||
Current (after increments): {:?}\n\
|
||||
Trying to decrement by: {:?}",
|
||||
self.raw.pathbuf, self.investor_cap_raw, self.pending_investor_cap.dec
|
||||
self.raw.pathbuf,
|
||||
self.investor_cap_raw,
|
||||
self.pending_investor_cap.dec
|
||||
);
|
||||
self.investor_cap_raw -= self.pending_investor_cap.dec;
|
||||
self.pending_investor_cap = PendingInvestorCapDelta::default();
|
||||
|
||||
@@ -6,7 +6,7 @@ pub use data::*;
|
||||
pub use realized::*;
|
||||
pub use unrealized::UnrealizedState;
|
||||
|
||||
pub(crate) use unrealized::{Accumulate, WithoutCapital, WithCapital};
|
||||
pub(crate) use unrealized::{Accumulate, WithCapital, WithoutCapital};
|
||||
|
||||
// Internal use only
|
||||
pub(super) use unrealized::CachedUnrealizedState;
|
||||
|
||||
@@ -58,10 +58,18 @@ pub trait Accumulate: Default + Clone + Send + Sync + 'static {
|
||||
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 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);
|
||||
@@ -80,8 +88,12 @@ impl Accumulate for WithoutCapital {
|
||||
}
|
||||
}
|
||||
|
||||
fn core(&self) -> &WithoutCapital { self }
|
||||
fn core_mut(&mut self) -> &mut WithoutCapital { self }
|
||||
fn core(&self) -> &WithoutCapital {
|
||||
self
|
||||
}
|
||||
fn core_mut(&mut self) -> &mut WithoutCapital {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn accumulate_profit(&mut self, _price_u128: u128, sats: Sats) {
|
||||
@@ -110,8 +122,12 @@ impl Accumulate for WithCapital {
|
||||
}
|
||||
}
|
||||
|
||||
fn core(&self) -> &WithoutCapital { &self.core }
|
||||
fn core_mut(&mut self) -> &mut WithoutCapital { &mut self.core }
|
||||
fn core(&self) -> &WithoutCapital {
|
||||
&self.core
|
||||
}
|
||||
fn core_mut(&mut self) -> &mut WithoutCapital {
|
||||
&mut self.core
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn accumulate_profit(&mut self, price_u128: u128, sats: Sats) {
|
||||
|
||||
Reference in New Issue
Block a user