global: fmt

This commit is contained in:
nym21
2026-03-28 11:56:51 +01:00
parent b6e56c4e9f
commit 24d2b7b142
213 changed files with 6888 additions and 2527 deletions

View File

@@ -38,8 +38,7 @@ impl Vecs {
let r1 = s.spawn(|| count.compute(indexer, starting_indexes, exit));
let r2 = s.spawn(|| interval.compute(indexer, starting_indexes, exit));
let r3 = s.spawn(|| weight.compute(indexer, starting_indexes, exit));
let r4 =
s.spawn(|| difficulty.compute(indexer, indexes, starting_indexes, exit));
let r4 = s.spawn(|| difficulty.compute(indexer, indexes, starting_indexes, exit));
let r5 = s.spawn(|| halving.compute(indexes, starting_indexes, exit));
size.compute(indexer, &*lookback, starting_indexes, exit)?;
r1.join().unwrap()?;

View File

@@ -6,8 +6,8 @@ use super::Vecs;
use crate::{
indexes,
internal::{
BlockCountTarget24h, BlockCountTarget1w, BlockCountTarget1m, BlockCountTarget1y,
CachedWindowStarts, PerBlockCumulativeRolling, ConstantVecs, Windows,
BlockCountTarget1m, BlockCountTarget1w, BlockCountTarget1y, BlockCountTarget24h,
CachedWindowStarts, ConstantVecs, PerBlockCumulativeRolling, Windows,
},
};
@@ -20,10 +20,26 @@ impl Vecs {
) -> Result<Self> {
Ok(Self {
target: Windows {
_24h: ConstantVecs::new::<BlockCountTarget24h>("block_count_target_24h", version, indexes),
_1w: ConstantVecs::new::<BlockCountTarget1w>("block_count_target_1w", version, indexes),
_1m: ConstantVecs::new::<BlockCountTarget1m>("block_count_target_1m", version, indexes),
_1y: ConstantVecs::new::<BlockCountTarget1y>("block_count_target_1y", version, indexes),
_24h: ConstantVecs::new::<BlockCountTarget24h>(
"block_count_target_24h",
version,
indexes,
),
_1w: ConstantVecs::new::<BlockCountTarget1w>(
"block_count_target_1w",
version,
indexes,
),
_1m: ConstantVecs::new::<BlockCountTarget1m>(
"block_count_target_1m",
version,
indexes,
),
_1y: ConstantVecs::new::<BlockCountTarget1y>(
"block_count_target_1y",
version,
indexes,
),
},
total: PerBlockCumulativeRolling::forced_import(
db,

View File

@@ -2,7 +2,7 @@ use brk_traversable::Traversable;
use brk_types::{StoredU32, StoredU64};
use vecdb::{Rw, StorageMode};
use crate::internal::{PerBlockCumulativeRolling, ConstantVecs, Windows};
use crate::internal::{ConstantVecs, PerBlockCumulativeRolling, Windows};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {

View File

@@ -27,12 +27,8 @@ impl Vecs {
indexes,
);
let blocks_to_retarget = PerBlock::forced_import(
db,
"blocks_to_retarget",
version + v2,
indexes,
)?;
let blocks_to_retarget =
PerBlock::forced_import(db, "blocks_to_retarget", version + v2, indexes)?;
let days_to_retarget = LazyPerBlock::from_computed::<BlocksToDaysF32>(
"days_to_retarget",

View File

@@ -2,7 +2,7 @@ use brk_traversable::Traversable;
use brk_types::{BasisPointsSigned32, Epoch, StoredF32, StoredF64, StoredU32};
use vecdb::{Rw, StorageMode};
use crate::internal::{LazyPerBlock, PerBlock, Resolutions, PercentPerBlock};
use crate::internal::{LazyPerBlock, PerBlock, PercentPerBlock, Resolutions};
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub value: Resolutions<StoredF64>,

View File

@@ -16,9 +16,8 @@ impl Vecs {
) -> Result<Self> {
let v2 = Version::TWO;
let blocks_to_halving = PerBlock::forced_import(
db, "blocks_to_halving", version + v2, indexes,
)?;
let blocks_to_halving =
PerBlock::forced_import(db, "blocks_to_halving", version + v2, indexes)?;
let days_to_halving = LazyPerBlock::from_computed::<BlocksToDaysF32>(
"days_to_halving",

View File

@@ -10,8 +10,7 @@ use crate::{
};
use super::{
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, LookbackVecs, SizeVecs, Vecs,
WeightVecs,
CountVecs, DifficultyVecs, HalvingVecs, IntervalVecs, LookbackVecs, SizeVecs, Vecs, WeightVecs,
};
impl Vecs {

View File

@@ -13,27 +13,26 @@ impl Vecs {
exit: &Exit,
) -> Result<()> {
let mut prev_timestamp = None;
self.0
.compute(starting_indexes.height, exit, |vec| {
vec.compute_transform(
starting_indexes.height,
&indexer.vecs.blocks.timestamp,
|(h, timestamp, ..)| {
let interval = if let Some(prev_h) = h.decremented() {
let prev = prev_timestamp.unwrap_or_else(|| {
indexer.vecs.blocks.timestamp.collect_one(prev_h).unwrap()
});
timestamp.checked_sub(prev).unwrap_or(Timestamp::ZERO)
} else {
Timestamp::ZERO
};
prev_timestamp = Some(timestamp);
(h, interval)
},
exit,
)?;
Ok(())
})?;
self.0.compute(starting_indexes.height, exit, |vec| {
vec.compute_transform(
starting_indexes.height,
&indexer.vecs.blocks.timestamp,
|(h, timestamp, ..)| {
let interval = if let Some(prev_h) = h.decremented() {
let prev = prev_timestamp.unwrap_or_else(|| {
indexer.vecs.blocks.timestamp.collect_one(prev_h).unwrap()
});
timestamp.checked_sub(prev).unwrap_or(Timestamp::ZERO)
} else {
Timestamp::ZERO
};
prev_timestamp = Some(timestamp);
(h, interval)
},
exit,
)?;
Ok(())
})?;
Ok(())
}

View File

@@ -3,7 +3,10 @@ use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{indexes, internal::{CachedWindowStarts, PerBlockRollingAverage}};
use crate::{
indexes,
internal::{CachedWindowStarts, PerBlockRollingAverage},
};
impl Vecs {
pub(crate) fn forced_import(

View File

@@ -1,11 +1,14 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Indexes, Timestamp, Version};
use vecdb::{AnyVec, CachedVec, Cursor, Database, EagerVec, Exit, ImportableVec, PcoVec, ReadableVec, Rw, StorageMode, VecIndex};
use vecdb::{
AnyVec, CachedVec, Cursor, Database, EagerVec, Exit, ImportableVec, PcoVec, ReadableVec, Rw,
StorageMode, VecIndex,
};
use crate::{
indexes,
internal::{CachedWindowStarts, Windows, WindowStarts},
internal::{CachedWindowStarts, WindowStarts, Windows},
};
#[derive(Traversable)]
@@ -112,10 +115,49 @@ impl Vecs {
Ok(Self {
cached_window_starts,
_1h, _24h, _3d, _1w, _8d, _9d, _12d, _13d, _2w, _21d, _26d,
_1m, _34d, _55d, _2m, _9w, _12w, _89d, _3m, _14w, _111d, _144d,
_6m, _26w, _200d, _9m, _350d, _12m, _1y, _14m, _2y, _26m, _3y,
_200w, _4y, _5y, _6y, _8y, _9y, _10y, _12y, _14y, _26y,
_1h,
_24h,
_3d,
_1w,
_8d,
_9d,
_12d,
_13d,
_2w,
_21d,
_26d,
_1m,
_34d,
_55d,
_2m,
_9w,
_12w,
_89d,
_3m,
_14w,
_111d,
_144d,
_6m,
_26w,
_200d,
_9m,
_350d,
_12m,
_1y,
_14m,
_2y,
_26m,
_3y,
_200w,
_4y,
_5y,
_6y,
_8y,
_9y,
_10y,
_12y,
_14y,
_26y,
})
}
@@ -128,7 +170,6 @@ impl Vecs {
}
}
pub fn start_vec(&self, days: usize) -> &EagerVec<PcoVec<Height, Height>> {
match days {
1 => &self._24h,
@@ -183,9 +224,7 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.compute_rolling_start_hours(indexes, starting_indexes, exit, 1, |s| {
&mut s._1h
})?;
self.compute_rolling_start_hours(indexes, starting_indexes, exit, 1, |s| &mut s._1h)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1, |s| &mut s._24h)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 3, |s| &mut s._3d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 7, |s| &mut s._1w)?;
@@ -205,47 +244,29 @@ impl Vecs {
self.compute_rolling_start(indexes, starting_indexes, exit, 89, |s| &mut s._89d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 90, |s| &mut s._3m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 98, |s| &mut s._14w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 111, |s| {
&mut s._111d
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 144, |s| {
&mut s._144d
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 111, |s| &mut s._111d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 144, |s| &mut s._144d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 180, |s| &mut s._6m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 182, |s| &mut s._26w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 200, |s| {
&mut s._200d
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 200, |s| &mut s._200d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 270, |s| &mut s._9m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 350, |s| {
&mut s._350d
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 350, |s| &mut s._350d)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 360, |s| &mut s._12m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 365, |s| &mut s._1y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 420, |s| &mut s._14m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 730, |s| &mut s._2y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 780, |s| &mut s._26m)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1095, |s| &mut s._3y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1400, |s| {
&mut s._200w
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1400, |s| &mut s._200w)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1460, |s| &mut s._4y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 1825, |s| &mut s._5y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 2190, |s| &mut s._6y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 2920, |s| &mut s._8y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 3285, |s| &mut s._9y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 3650, |s| {
&mut s._10y
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 4380, |s| {
&mut s._12y
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 5110, |s| {
&mut s._14y
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 9490, |s| {
&mut s._26y
})?;
self.compute_rolling_start(indexes, starting_indexes, exit, 3650, |s| &mut s._10y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 4380, |s| &mut s._12y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 5110, |s| &mut s._14y)?;
self.compute_rolling_start(indexes, starting_indexes, exit, 9490, |s| &mut s._26y)?;
Ok(())
}
@@ -261,9 +282,13 @@ impl Vecs {
where
F: FnOnce(&mut Self) -> &mut EagerVec<PcoVec<Height, Height>>,
{
self.compute_rolling_start_inner(indexes, starting_indexes, exit, get_field, |t, prev_ts| {
t.difference_in_days_between(prev_ts) >= days
})
self.compute_rolling_start_inner(
indexes,
starting_indexes,
exit,
get_field,
|t, prev_ts| t.difference_in_days_between(prev_ts) >= days,
)
}
fn compute_rolling_start_hours<F>(
@@ -277,9 +302,13 @@ impl Vecs {
where
F: FnOnce(&mut Self) -> &mut EagerVec<PcoVec<Height, Height>>,
{
self.compute_rolling_start_inner(indexes, starting_indexes, exit, get_field, |t, prev_ts| {
t.difference_in_hours_between(prev_ts) >= hours
})
self.compute_rolling_start_inner(
indexes,
starting_indexes,
exit,
get_field,
|t, prev_ts| t.difference_in_hours_between(prev_ts) >= hours,
)
}
fn compute_rolling_start_inner<F, D>(

View File

@@ -28,10 +28,18 @@ impl Vecs {
Ok(Self {
coinblocks_created: PerBlockCumulativeRolling::forced_import(
db, "coinblocks_created", version, indexes, cached_starts,
db,
"coinblocks_created",
version,
indexes,
cached_starts,
)?,
coinblocks_stored: PerBlockCumulativeRolling::forced_import(
db, "coinblocks_stored", version, indexes, cached_starts,
db,
"coinblocks_stored",
version,
indexes,
cached_starts,
)?,
liveliness,
vaultedness,

View File

@@ -22,11 +22,8 @@ impl Vecs {
let circulating_supply = &all_metrics.supply.total.btc.height;
let realized_price = &all_metrics.realized.price.cents.height;
self.vaulted.compute_all(
prices,
starting_indexes,
exit,
|v| {
self.vaulted
.compute_all(prices, starting_indexes, exit, |v| {
Ok(v.compute_transform2(
starting_indexes.height,
realized_price,
@@ -36,14 +33,10 @@ impl Vecs {
},
exit,
)?)
},
)?;
})?;
self.active.compute_all(
prices,
starting_indexes,
exit,
|v| {
self.active
.compute_all(prices, starting_indexes, exit, |v| {
Ok(v.compute_transform2(
starting_indexes.height,
realized_price,
@@ -53,14 +46,10 @@ impl Vecs {
},
exit,
)?)
},
)?;
})?;
self.true_market_mean.compute_all(
prices,
starting_indexes,
exit,
|v| {
self.true_market_mean
.compute_all(prices, starting_indexes, exit, |v| {
Ok(v.compute_transform2(
starting_indexes.height,
&cap.investor.cents.height,
@@ -70,14 +59,10 @@ impl Vecs {
},
exit,
)?)
},
)?;
})?;
self.cointime.compute_all(
prices,
starting_indexes,
exit,
|v| {
self.cointime
.compute_all(prices, starting_indexes, exit, |v| {
Ok(v.compute_transform2(
starting_indexes.height,
&cap.cointime.cents.height,
@@ -87,8 +72,7 @@ impl Vecs {
},
exit,
)?)
},
)?;
})?;
Ok(())
}

View File

@@ -3,10 +3,7 @@ use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{
indexes,
internal::PriceWithRatioExtendedPerBlock,
};
use crate::{indexes, internal::PriceWithRatioExtendedPerBlock};
impl Vecs {
pub(crate) fn forced_import(

View File

@@ -38,7 +38,8 @@ impl Vecs {
exit,
)?;
self.vaulted.compute(prices, starting_indexes.height, exit)?;
self.vaulted
.compute(prices, starting_indexes.height, exit)?;
self.active.compute(prices, starting_indexes.height, exit)?;
Ok(())

View File

@@ -12,12 +12,7 @@ impl Vecs {
indexes: &indexes::Vecs,
) -> Result<Self> {
Ok(Self {
vaulted: AmountPerBlock::forced_import(
db,
"vaulted_supply",
version,
indexes,
)?,
vaulted: AmountPerBlock::forced_import(db, "vaulted_supply", version, indexes)?,
active: AmountPerBlock::forced_import(db, "active_supply", version, indexes)?,
})
}

View File

@@ -31,52 +31,49 @@ impl Vecs {
Ok(())
})?;
self.created
.compute(starting_indexes.height, exit, |vec| {
vec.compute_multiply(
starting_indexes.height,
&prices.spot.usd.height,
&activity.coinblocks_created.block,
exit,
)?;
Ok(())
})?;
self.created.compute(starting_indexes.height, exit, |vec| {
vec.compute_multiply(
starting_indexes.height,
&prices.spot.usd.height,
&activity.coinblocks_created.block,
exit,
)?;
Ok(())
})?;
self.stored
.compute(starting_indexes.height, exit, |vec| {
vec.compute_multiply(
starting_indexes.height,
&prices.spot.usd.height,
&activity.coinblocks_stored.block,
exit,
)?;
Ok(())
})?;
self.stored.compute(starting_indexes.height, exit, |vec| {
vec.compute_multiply(
starting_indexes.height,
&prices.spot.usd.height,
&activity.coinblocks_stored.block,
exit,
)?;
Ok(())
})?;
// VOCDD: Value of Coin Days Destroyed = price × (CDD / circulating_supply)
// Supply-adjusted to account for growing supply over time
// This is a key input for Reserve Risk / HODL Bank calculation
self.vocdd
.compute(starting_indexes.height, exit, |vec| {
vec.compute_transform3(
starting_indexes.height,
&prices.spot.usd.height,
&coindays_destroyed.block,
circulating_supply,
|(i, price, cdd, supply, _): (_, Dollars, StoredF64, Bitcoin, _)| {
let supply_f64 = f64::from(supply);
if supply_f64 == 0.0 {
(i, StoredF64::from(0.0))
} else {
// VOCDD = price × (CDD / supply)
let vocdd = f64::from(price) * f64::from(cdd) / supply_f64;
(i, StoredF64::from(vocdd))
}
},
exit,
)?;
Ok(())
})?;
self.vocdd.compute(starting_indexes.height, exit, |vec| {
vec.compute_transform3(
starting_indexes.height,
&prices.spot.usd.height,
&coindays_destroyed.block,
circulating_supply,
|(i, price, cdd, supply, _): (_, Dollars, StoredF64, Bitcoin, _)| {
let supply_f64 = f64::from(supply);
if supply_f64 == 0.0 {
(i, StoredF64::from(0.0))
} else {
// VOCDD = price × (CDD / supply)
let vocdd = f64::from(price) * f64::from(cdd) / supply_f64;
(i, StoredF64::from(vocdd))
}
},
exit,
)?;
Ok(())
})?;
Ok(())
}

View File

@@ -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(())

View File

@@ -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

View File

@@ -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};

View File

@@ -45,9 +45,6 @@ impl DeltaVecs {
)
});
Self {
all,
by_addr_type,
}
Self { all, by_addr_type }
}
}

View File

@@ -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;

View File

@@ -44,10 +44,7 @@ impl NewAddrCountVecs {
)
})?;
Ok(Self {
all,
by_addr_type,
})
Ok(Self { all, by_addr_type })
}
pub(crate) fn compute(

View File

@@ -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.

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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());

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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};

View File

@@ -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);

View File

@@ -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)

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
})
},
);

View File

@@ -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(),

View File

@@ -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() {

View File

@@ -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());
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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)
}
}

View File

@@ -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,

View File

@@ -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(())
}
}

View File

@@ -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(())
}

View File

@@ -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(())
}

View File

@@ -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(())
}

View File

@@ -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)?,

View File

@@ -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);

View File

@@ -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,
)?;

View File

@@ -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

View File

@@ -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(

View File

@@ -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(())
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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))?,
})

View File

@@ -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(())
}
}

View File

@@ -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)?,
})
}

View File

@@ -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

View File

@@ -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(())
}
}

View File

@@ -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).

View File

@@ -1,5 +1,5 @@
mod base;
mod core;
pub use base::SupplyBase;
pub use self::core::SupplyCore;
pub use base::SupplyBase;

View File

@@ -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> {

View File

@@ -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

View File

@@ -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,
)
}
}

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;

View File

@@ -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) {

View File

@@ -1,11 +1,10 @@
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{
Addr, AddrBytes, EmptyOutputIndex, OpReturnIndex, P2AAddrIndex, P2ABytes,
P2MSOutputIndex, P2PK33AddrIndex, P2PK33Bytes, P2PK65AddrIndex, P2PK65Bytes,
P2PKHAddrIndex, P2PKHBytes, P2SHAddrIndex, P2SHBytes, P2TRAddrIndex, P2TRBytes,
P2WPKHAddrIndex, P2WPKHBytes, P2WSHAddrIndex, P2WSHBytes, TxIndex, UnknownOutputIndex,
Version,
Addr, AddrBytes, EmptyOutputIndex, OpReturnIndex, P2AAddrIndex, P2ABytes, P2MSOutputIndex,
P2PK33AddrIndex, P2PK33Bytes, P2PK65AddrIndex, P2PK65Bytes, P2PKHAddrIndex, P2PKHBytes,
P2SHAddrIndex, P2SHBytes, P2TRAddrIndex, P2TRBytes, P2WPKHAddrIndex, P2WPKHBytes,
P2WSHAddrIndex, P2WSHBytes, TxIndex, UnknownOutputIndex, Version,
};
use vecdb::{LazyVecFrom1, ReadableCloneableVec};
@@ -27,15 +26,13 @@ pub struct Vecs {
#[derive(Clone, Traversable)]
pub struct P2PK33Vecs {
pub identity:
LazyVecFrom1<P2PK33AddrIndex, P2PK33AddrIndex, P2PK33AddrIndex, P2PK33Bytes>,
pub identity: LazyVecFrom1<P2PK33AddrIndex, P2PK33AddrIndex, P2PK33AddrIndex, P2PK33Bytes>,
pub addr: LazyVecFrom1<P2PK33AddrIndex, Addr, P2PK33AddrIndex, P2PK33Bytes>,
}
#[derive(Clone, Traversable)]
pub struct P2PK65Vecs {
pub identity:
LazyVecFrom1<P2PK65AddrIndex, P2PK65AddrIndex, P2PK65AddrIndex, P2PK65Bytes>,
pub identity: LazyVecFrom1<P2PK65AddrIndex, P2PK65AddrIndex, P2PK65AddrIndex, P2PK65Bytes>,
pub addr: LazyVecFrom1<P2PK65AddrIndex, Addr, P2PK65AddrIndex, P2PK65Bytes>,
}
@@ -59,8 +56,7 @@ pub struct P2TRVecs {
#[derive(Clone, Traversable)]
pub struct P2WPKHVecs {
pub identity:
LazyVecFrom1<P2WPKHAddrIndex, P2WPKHAddrIndex, P2WPKHAddrIndex, P2WPKHBytes>,
pub identity: LazyVecFrom1<P2WPKHAddrIndex, P2WPKHAddrIndex, P2WPKHAddrIndex, P2WPKHBytes>,
pub addr: LazyVecFrom1<P2WPKHAddrIndex, Addr, P2WPKHAddrIndex, P2WPKHBytes>,
}
@@ -215,7 +211,12 @@ impl Vecs {
identity: LazyVecFrom1::init(
"p2ms_output_index",
version,
indexer.vecs.scripts.p2ms.to_tx_index.read_only_boxed_clone(),
indexer
.vecs
.scripts
.p2ms
.to_tx_index
.read_only_boxed_clone(),
|index, _| index,
),
},
@@ -226,7 +227,8 @@ impl Vecs {
indexer
.vecs
.scripts
.empty.to_tx_index
.empty
.to_tx_index
.read_only_boxed_clone(),
|index, _| index,
),
@@ -238,7 +240,8 @@ impl Vecs {
indexer
.vecs
.scripts
.unknown.to_tx_index
.unknown
.to_tx_index
.read_only_boxed_clone(),
|index, _| index,
),
@@ -250,7 +253,8 @@ impl Vecs {
indexer
.vecs
.scripts
.op_return.to_tx_index
.op_return
.to_tx_index
.read_only_boxed_clone(),
|index, _| index,
),

View File

@@ -1,7 +1,7 @@
use brk_traversable::Traversable;
use brk_types::{
Day1, Day3, Epoch, Halving, Height, Hour1, Hour4, Hour12, Minute10, Minute30,
Month1, Month3, Month6, StoredU64, Version, Week1, Year1, Year10,
Day1, Day3, Epoch, Halving, Height, Hour1, Hour4, Hour12, Minute10, Minute30, Month1, Month3,
Month6, StoredU64, Version, Week1, Year1, Year10,
};
use vecdb::{Database, EagerVec, ImportableVec, PcoVec, Rw, StorageMode};

View File

@@ -35,7 +35,6 @@ use vecdb::{CachedVec, Database, Exit, ReadableVec, Rw, StorageMode};
use crate::internal::db_utils::{finalize_db, open_db};
pub use addr::Vecs as AddrVecs;
pub use timestamp::Timestamps;
pub use cached_mappings::CachedMappings;
pub use day1::Vecs as Day1Vecs;
pub use day3::Vecs as Day3Vecs;
@@ -50,6 +49,7 @@ pub use minute30::Vecs as Minute30Vecs;
pub use month1::Vecs as Month1Vecs;
pub use month3::Vecs as Month3Vecs;
pub use month6::Vecs as Month6Vecs;
pub use timestamp::Timestamps;
pub use tx_index::Vecs as TxIndexVecs;
pub use txin_index::Vecs as TxInIndexVecs;
pub use txout_index::Vecs as TxOutIndexVecs;
@@ -190,20 +190,10 @@ impl Vecs {
self.compute_timestamp_mappings(&starting_indexes, exit)?;
let starting_day1 = self.compute_calendar_mappings(
indexer,
&starting_indexes,
prev_height,
exit,
)?;
let starting_day1 =
self.compute_calendar_mappings(indexer, &starting_indexes, prev_height, exit)?;
self.compute_period_vecs(
indexer,
&starting_indexes,
prev_height,
starting_day1,
exit,
)?;
self.compute_period_vecs(indexer, &starting_indexes, prev_height, starting_day1, exit)?;
self.timestamp.compute_per_resolution(
indexer,

View File

@@ -2,7 +2,7 @@ use brk_error::Result;
use brk_types::{Bitcoin, Dollars, Indexes, StoredF32};
use vecdb::Exit;
use super::{gini, Vecs};
use super::{Vecs, gini};
use crate::{distribution, internal::RatioDollarsBp32, market, mining, transactions};
impl Vecs {
@@ -126,22 +126,20 @@ impl Vecs {
)?;
// Supply-Adjusted Dormancy = dormancy / circulating_supply_btc
self.dormancy.supply_adjusted
.height
.compute_transform2(
starting_indexes.height,
&all_activity.dormancy._24h.height,
supply_total_sats,
|(i, dormancy, supply_sats, ..)| {
let supply = f64::from(Bitcoin::from(supply_sats));
if supply == 0.0 {
(i, StoredF32::from(0.0f32))
} else {
(i, StoredF32::from((f64::from(dormancy) / supply) as f32))
}
},
exit,
)?;
self.dormancy.supply_adjusted.height.compute_transform2(
starting_indexes.height,
&all_activity.dormancy._24h.height,
supply_total_sats,
|(i, dormancy, supply_sats, ..)| {
let supply = f64::from(Bitcoin::from(supply_sats));
if supply == 0.0 {
(i, StoredF32::from(0.0f32))
} else {
(i, StoredF32::from((f64::from(dormancy) / supply) as f32))
}
},
exit,
)?;
// Stock-to-Flow: supply / annual_issuance
// annual_issuance ≈ subsidy_per_block × 52560 (blocks/year)
@@ -154,9 +152,10 @@ impl Vecs {
if annual_flow == 0.0 {
(i, StoredF32::from(0.0f32))
} else {
(i, StoredF32::from(
(supply_sats.as_u128() as f64 / annual_flow) as f32,
))
(
i,
StoredF32::from((supply_sats.as_u128() as f64 / annual_flow) as f32),
)
}
},
exit,
@@ -180,26 +179,25 @@ impl Vecs {
)?;
// Seller Exhaustion Constant: % supply_in_profit × 30d_volatility
self.seller_exhaustion
.height
.compute_transform3(
starting_indexes.height,
&all_metrics.supply.in_profit.sats.height,
&market.volatility._1m.height,
supply_total_sats,
|(i, profit_sats, volatility, total_sats, ..)| {
let total = total_sats.as_u128() as f64;
if total == 0.0 {
(i, StoredF32::from(0.0f32))
} else {
let pct_in_profit = profit_sats.as_u128() as f64 / total;
(i, StoredF32::from(
(pct_in_profit * f64::from(volatility)) as f32,
))
}
},
exit,
)?;
self.seller_exhaustion.height.compute_transform3(
starting_indexes.height,
&all_metrics.supply.in_profit.sats.height,
&market.volatility._1m.height,
supply_total_sats,
|(i, profit_sats, volatility, total_sats, ..)| {
let total = total_sats.as_u128() as f64;
if total == 0.0 {
(i, StoredF32::from(0.0f32))
} else {
let pct_in_profit = profit_sats.as_u128() as f64 / total;
(
i,
StoredF32::from((pct_in_profit * f64::from(volatility)) as f32),
)
}
},
exit,
)?;
let exit = exit.clone();
self.db.run_bg(move |db| {

View File

@@ -6,7 +6,10 @@ use brk_types::Version;
use super::{Vecs, realized_envelope::RealizedEnvelope};
use crate::{
indexes,
internal::{PerBlock, PercentPerBlock, RatioPerBlock, db_utils::{finalize_db, open_db}},
internal::{
PerBlock, PercentPerBlock, RatioPerBlock,
db_utils::{finalize_db, open_db},
},
};
const VERSION: Version = Version::new(1);
@@ -35,8 +38,7 @@ impl Vecs {
flow: PerBlock::forced_import(&db, "dormancy_flow", v, indexes)?,
};
let stock_to_flow = PerBlock::forced_import(&db, "stock_to_flow", v, indexes)?;
let seller_exhaustion =
PerBlock::forced_import(&db, "seller_exhaustion", v, indexes)?;
let seller_exhaustion = PerBlock::forced_import(&db, "seller_exhaustion", v, indexes)?;
let realized_envelope = RealizedEnvelope::forced_import(&db, v, indexes)?;

View File

@@ -4,9 +4,7 @@ use brk_types::{Cents, Height, Indexes, StoredI8, Version};
use vecdb::{AnyVec, Database, EagerVec, Exit, PcoVec, ReadableVec, Rw, StorageMode, WritableVec};
use crate::{
cointime,
distribution,
indexes,
cointime, distribution, indexes,
internal::{PerBlock, Price, RatioPerBlockPercentiles},
prices,
};
@@ -82,16 +80,48 @@ impl RealizedEnvelope {
}
// Lower percentiles: max across all models (tightest lower bound)
self.pct0_5.cents.height.compute_max_of_others(starting_indexes.height, &sources!(pct0_5), exit)?;
self.pct1.cents.height.compute_max_of_others(starting_indexes.height, &sources!(pct1), exit)?;
self.pct2.cents.height.compute_max_of_others(starting_indexes.height, &sources!(pct2), exit)?;
self.pct5.cents.height.compute_max_of_others(starting_indexes.height, &sources!(pct5), exit)?;
self.pct0_5.cents.height.compute_max_of_others(
starting_indexes.height,
&sources!(pct0_5),
exit,
)?;
self.pct1.cents.height.compute_max_of_others(
starting_indexes.height,
&sources!(pct1),
exit,
)?;
self.pct2.cents.height.compute_max_of_others(
starting_indexes.height,
&sources!(pct2),
exit,
)?;
self.pct5.cents.height.compute_max_of_others(
starting_indexes.height,
&sources!(pct5),
exit,
)?;
// Upper percentiles: min across all models (tightest upper bound)
self.pct95.cents.height.compute_min_of_others(starting_indexes.height, &sources!(pct95), exit)?;
self.pct98.cents.height.compute_min_of_others(starting_indexes.height, &sources!(pct98), exit)?;
self.pct99.cents.height.compute_min_of_others(starting_indexes.height, &sources!(pct99), exit)?;
self.pct99_5.cents.height.compute_min_of_others(starting_indexes.height, &sources!(pct99_5), exit)?;
self.pct95.cents.height.compute_min_of_others(
starting_indexes.height,
&sources!(pct95),
exit,
)?;
self.pct98.cents.height.compute_min_of_others(
starting_indexes.height,
&sources!(pct98),
exit,
)?;
self.pct99.cents.height.compute_min_of_others(
starting_indexes.height,
&sources!(pct99),
exit,
)?;
self.pct99_5.cents.height.compute_min_of_others(
starting_indexes.height,
&sources!(pct99_5),
exit,
)?;
let spot = &prices.spot.cents.height;
@@ -121,10 +151,15 @@ impl RealizedEnvelope {
&self.pct99_5.cents.height,
];
let dep_version: Version = bands.iter().map(|b| b.version()).sum::<Version>() + spot.version();
let dep_version: Version =
bands.iter().map(|b| b.version()).sum::<Version>() + spot.version();
self.index.height.validate_computed_version_or_reset(dep_version)?;
self.index.height.truncate_if_needed(starting_indexes.height)?;
self.index
.height
.validate_computed_version_or_reset(dep_version)?;
self.index
.height
.truncate_if_needed(starting_indexes.height)?;
self.index.height.repeat_until_complete(exit, |vec| {
let skip = vec.len();
@@ -142,14 +177,30 @@ impl RealizedEnvelope {
let price = spot_batch[j];
let mut score: i8 = 0;
if price < b[3][j] { score -= 1; }
if price < b[2][j] { score -= 1; }
if price < b[1][j] { score -= 1; }
if price < b[0][j] { score -= 1; }
if price > b[4][j] { score += 1; }
if price > b[5][j] { score += 1; }
if price > b[6][j] { score += 1; }
if price > b[7][j] { score += 1; }
if price < b[3][j] {
score -= 1;
}
if price < b[2][j] {
score -= 1;
}
if price < b[1][j] {
score -= 1;
}
if price < b[0][j] {
score -= 1;
}
if price > b[4][j] {
score += 1;
}
if price > b[5][j] {
score += 1;
}
if price > b[6][j] {
score += 1;
}
if price > b[7][j] {
score += 1;
}
vec.push(StoredI8::new(score));
}
@@ -182,8 +233,12 @@ impl RealizedEnvelope {
.sum::<Version>()
+ spot.version();
self.score.height.validate_computed_version_or_reset(dep_version)?;
self.score.height.truncate_if_needed(starting_indexes.height)?;
self.score
.height
.validate_computed_version_or_reset(dep_version)?;
self.score
.height
.truncate_if_needed(starting_indexes.height)?;
self.score.height.repeat_until_complete(exit, |vec| {
let skip = vec.len();
@@ -233,14 +288,30 @@ impl RealizedEnvelope {
let mut total: i8 = 0;
for model in &bands {
if price < model[3][j] { total -= 1; }
if price < model[2][j] { total -= 1; }
if price < model[1][j] { total -= 1; }
if price < model[0][j] { total -= 1; }
if price > model[4][j] { total += 1; }
if price > model[5][j] { total += 1; }
if price > model[6][j] { total += 1; }
if price > model[7][j] { total += 1; }
if price < model[3][j] {
total -= 1;
}
if price < model[2][j] {
total -= 1;
}
if price < model[1][j] {
total -= 1;
}
if price < model[0][j] {
total -= 1;
}
if price > model[4][j] {
total += 1;
}
if price > model[5][j] {
total += 1;
}
if price > model[6][j] {
total += 1;
}
if price > model[7][j] {
total += 1;
}
}
vec.push(StoredI8::new(total));

View File

@@ -17,8 +17,7 @@ impl Vecs {
) -> Result<()> {
self.db.sync_bg_tasks()?;
self.spent
.compute(indexer, starting_indexes, exit)?;
self.spent.compute(indexer, starting_indexes, exit)?;
self.count
.compute(indexer, indexes, blocks, starting_indexes, exit)?;

View File

@@ -3,7 +3,10 @@ use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{indexes, internal::{CachedWindowStarts, PerBlockAggregated}};
use crate::{
indexes,
internal::{CachedWindowStarts, PerBlockAggregated},
};
impl Vecs {
pub(crate) fn forced_import(

View File

@@ -7,6 +7,4 @@ use vecdb::{Rw, StorageMode};
use crate::internal::PerBlockAggregated;
#[derive(Deref, DerefMut, Traversable)]
pub struct Vecs<M: StorageMode = Rw>(
#[traversable(flatten)] pub PerBlockAggregated<StoredU64, M>,
);
pub struct Vecs<M: StorageMode = Rw>(#[traversable(flatten)] pub PerBlockAggregated<StoredU64, M>);

View File

@@ -5,7 +5,10 @@ use brk_types::Version;
use crate::{
indexes,
internal::{CachedWindowStarts, db_utils::{finalize_db, open_db}},
internal::{
CachedWindowStarts,
db_utils::{finalize_db, open_db},
},
};
use super::{CountVecs, SpentVecs, Vecs};

View File

@@ -146,5 +146,4 @@ mod tests {
assert_eq!(ep.count(), 0);
assert_eq!(quantile(&ep, 0.5), 0);
}
}

View File

@@ -137,8 +137,7 @@ where
} else {
min_out.push(T::from(window.min()));
max_out.push(T::from(window.max()));
let [p10, p25, p50, p75, p90] =
window.percentiles(&[0.10, 0.25, 0.50, 0.75, 0.90]);
let [p10, p25, p50, p75, p90] = window.percentiles(&[0.10, 0.25, 0.50, 0.75, 0.90]);
p10_out.push(T::from(p10));
p25_out.push(T::from(p25));
median_out.push(T::from(p50));
@@ -165,13 +164,7 @@ where
// Final flush
let _lock = exit.lock();
for v in [
min_out,
max_out,
p10_out,
p25_out,
median_out,
p75_out,
p90_out,
min_out, max_out, p10_out, p25_out, median_out, p75_out, p90_out,
] {
v.write()?;
}

View File

@@ -1,7 +1,7 @@
use brk_traversable::Traversable;
use brk_types::{
Day1, Day3, Epoch, Halving, Height, Hour1, Hour4, Hour12, Minute10, Minute30,
Month1, Month3, Month6, Version, Week1, Year1, Year10,
Day1, Day3, Epoch, Halving, Height, Hour1, Hour4, Hour12, Minute10, Minute30, Month1, Month3,
Month6, Version, Week1, Year1, Year10,
};
use schemars::JsonSchema;
use serde::Serialize;

View File

@@ -12,9 +12,8 @@ pub struct DistributionStats<A> {
}
impl<A> DistributionStats<A> {
pub const SUFFIXES: [&'static str; 7] = [
"min", "max", "pct10", "pct25", "median", "pct75", "pct90",
];
pub const SUFFIXES: [&'static str; 7] =
["min", "max", "pct10", "pct25", "median", "pct75", "pct90"];
pub fn try_from_fn<E>(
mut f: impl FnMut(&str) -> std::result::Result<A, E>,

View File

@@ -1,16 +1,16 @@
mod constant;
mod distribution_stats;
mod per_resolution;
mod percent;
mod window_24h;
mod windows;
mod windows_from_1w;
mod percent;
mod windows_to_1m;
pub use constant::*;
pub use distribution_stats::*;
pub use percent::*;
pub use per_resolution::*;
pub use percent::*;
pub use window_24h::*;
pub use windows::*;
pub use windows_from_1w::*;

View File

@@ -2,8 +2,8 @@ use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{
Day1, Day3, Epoch, Halving, Height, Hour1, Hour4, Hour12, Indexes, Minute10,
Minute30, Month1, Month3, Month6, Version, Week1, Year1, Year10,
Day1, Day3, Epoch, Halving, Height, Hour1, Hour4, Hour12, Indexes, Minute10, Minute30, Month1,
Month3, Month6, Version, Week1, Year1, Year10,
};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;

View File

@@ -1,7 +1,7 @@
use brk_traversable::Traversable;
use brk_types::{
Day1, Day3, Epoch, Halving, Hour1, Hour4, Hour12, Minute10, Minute30, Month1,
Month3, Month6, Version, Week1, Year1, Year10,
Day1, Day3, Epoch, Halving, Hour1, Hour4, Hour12, Minute10, Minute30, Month1, Month3, Month6,
Version, Week1, Year1, Year10,
};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;

View File

@@ -3,17 +3,17 @@ mod amount;
mod cache_budget;
mod containers;
pub(crate) mod db_utils;
mod indexes;
mod per_block;
mod per_tx;
mod indexes;
mod traits;
mod transform;
pub(crate) use amount::*;
pub(crate) use cache_budget::*;
pub(crate) use containers::*;
pub(crate) use indexes::*;
pub(crate) use per_block::*;
pub(crate) use per_tx::*;
pub(crate) use indexes::*;
pub(crate) use traits::*;
pub use transform::*;

View File

@@ -5,9 +5,7 @@ use vecdb::{Database, Exit, ReadableCloneableVec, Rw, StorageMode};
use crate::{
indexes,
internal::{
CentsUnsignedToDollars, PerBlock, LazyPerBlock, SatsToBitcoin, SatsToCents,
},
internal::{CentsUnsignedToDollars, LazyPerBlock, PerBlock, SatsToBitcoin, SatsToCents},
prices,
};
@@ -26,8 +24,7 @@ impl AmountPerBlock {
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let sats =
PerBlock::forced_import(db, &format!("{name}_sats"), version, indexes)?;
let sats = PerBlock::forced_import(db, &format!("{name}_sats"), version, indexes)?;
let btc = LazyPerBlock::from_computed::<SatsToBitcoin>(
name,
@@ -36,8 +33,7 @@ impl AmountPerBlock {
&sats,
);
let cents =
PerBlock::forced_import(db, &format!("{name}_cents"), version, indexes)?;
let cents = PerBlock::forced_import(db, &format!("{name}_cents"), version, indexes)?;
let usd = LazyPerBlock::from_computed::<CentsUnsignedToDollars>(
&format!("{name}_usd"),
@@ -68,6 +64,4 @@ impl AmountPerBlock {
)?;
Ok(())
}
}

View File

@@ -1,7 +1,10 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Cents, Dollars, Height, Sats, Version};
use vecdb::{Database, EagerVec, Exit, ImportableVec, LazyVecFrom1, PcoVec, ReadableCloneableVec, Rw, StorageMode};
use vecdb::{
Database, EagerVec, Exit, ImportableVec, LazyVecFrom1, PcoVec, ReadableCloneableVec, Rw,
StorageMode,
};
use crate::{
internal::{CentsUnsignedToDollars, SatsToBitcoin, SatsToCents},
@@ -21,11 +24,8 @@ impl AmountBlock {
pub(crate) fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
let sats: EagerVec<PcoVec<Height, Sats>> =
EagerVec::forced_import(db, &format!("{name}_sats"), version)?;
let btc = LazyVecFrom1::transformed::<SatsToBitcoin>(
name,
version,
sats.read_only_boxed_clone(),
);
let btc =
LazyVecFrom1::transformed::<SatsToBitcoin>(name, version, sats.read_only_boxed_clone());
let cents: EagerVec<PcoVec<Height, Cents>> =
EagerVec::forced_import(db, &format!("{name}_cents"), version)?;
let usd = LazyVecFrom1::transformed::<CentsUnsignedToDollars>(
@@ -33,7 +33,12 @@ impl AmountBlock {
version,
cents.read_only_boxed_clone(),
);
Ok(Self { btc, sats, usd, cents })
Ok(Self {
btc,
sats,
usd,
cents,
})
}
pub(crate) fn compute_cents(

View File

@@ -37,8 +37,7 @@ impl AmountPerBlockFull {
let inner =
AmountPerBlockCumulativeRolling::forced_import(db, name, v, indexes, cached_starts)?;
let distribution =
RollingDistributionAmountPerBlock::forced_import(db, name, v, indexes)?;
let distribution = RollingDistributionAmountPerBlock::forced_import(db, name, v, indexes)?;
Ok(Self {
inner,

View File

@@ -5,7 +5,9 @@ use brk_types::{Bitcoin, Cents, Dollars, Height, Sats, Version};
use derive_more::{Deref, DerefMut};
use vecdb::UnaryTransform;
use crate::internal::{AmountPerBlock, Identity, LazyAmount, LazyAmountDerivedResolutions, SatsToBitcoin};
use crate::internal::{
AmountPerBlock, Identity, LazyAmount, LazyAmountDerivedResolutions, SatsToBitcoin,
};
/// Lazy value wrapper with height + all derived last transforms from AmountPerBlock.
#[derive(Clone, Deref, DerefMut, Traversable)]

View File

@@ -11,7 +11,7 @@ use vecdb::{
use crate::indexes;
use crate::internal::{Resolutions, ComputedVecValue, NumericValue};
use crate::internal::{ComputedVecValue, NumericValue, Resolutions};
#[derive(Deref, DerefMut, Traversable)]
#[traversable(merge)]
@@ -38,12 +38,8 @@ where
) -> Result<Self> {
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, version)?;
let resolutions = Resolutions::forced_import(
name,
height.read_only_boxed_clone(),
version,
indexes,
);
let resolutions =
Resolutions::forced_import(name, height.read_only_boxed_clone(), version, indexes);
Ok(Self {
height,

View File

@@ -63,8 +63,7 @@ impl<T: NumericValue + JsonSchema> PerBlockDistribution<T> {
let pct75 = &mut pct75.height;
let pct90 = &mut pct90.height;
let combined_version =
source.version() + first_indexes.version() + count_indexes.version();
let combined_version = source.version() + first_indexes.version() + count_indexes.version();
let mut index = max_from;
for vec in [
@@ -182,8 +181,7 @@ impl<T: NumericValue + JsonSchema> PerBlockDistribution<T> {
let pct75 = &mut pct75.height;
let pct90 = &mut pct90.height;
let combined_version =
source.version() + first_indexes.version() + count_indexes.version();
let combined_version = source.version() + first_indexes.version() + count_indexes.version();
let mut index = max_from;
for vec in [

View File

@@ -3,7 +3,7 @@ use brk_types::{Height, Version};
use schemars::JsonSchema;
use vecdb::{LazyVecFrom1, ReadableCloneableVec, UnaryTransform, VecIndex};
use crate::internal::{ComputedVecValue, PerBlockDistribution, DistributionStats};
use crate::internal::{ComputedVecValue, DistributionStats, PerBlockDistribution};
/// Lazy analog of `Distribution<T>`: 7 `LazyVecFrom1` fields,
/// each derived by transforming the corresponding field of a source `PerBlockDistribution<S1T>`.

View File

@@ -6,8 +6,8 @@ use vecdb::{ReadableCloneableVec, UnaryTransform};
use crate::{
indexes,
internal::{
CachedWindowStarts, PerBlockFull, ComputedVecValue, LazyPerBlock, LazyRollingComplete,
NumericValue,
CachedWindowStarts, ComputedVecValue, LazyPerBlock, LazyRollingComplete, NumericValue,
PerBlockFull,
},
};

View File

@@ -11,7 +11,7 @@ use vecdb::{Database, Exit, ReadableVec, Rw, StorageMode};
use crate::{
indexes,
internal::{CachedWindowStarts, PerBlock, NumericValue, RollingComplete, WindowStarts},
internal::{CachedWindowStarts, NumericValue, PerBlock, RollingComplete, WindowStarts},
};
#[derive(Traversable)]

View File

@@ -7,9 +7,7 @@ use vecdb::{Rw, StorageMode};
use crate::{
indexes,
internal::{
BpsType, CachedWindowStarts, PerBlock, LazyRollingDeltasFromHeight, NumericValue,
},
internal::{BpsType, CachedWindowStarts, LazyRollingDeltasFromHeight, NumericValue, PerBlock},
};
#[derive(Deref, DerefMut, Traversable)]

View File

@@ -7,8 +7,7 @@ use vecdb::{Database, ReadableCloneableVec, Rw, StorageMode, UnaryTransform};
use crate::{
indexes,
internal::{
CentsSignedToDollars, CentsUnsignedToDollars, PerBlock, LazyPerBlock,
NumericValue,
CentsSignedToDollars, CentsUnsignedToDollars, LazyPerBlock, NumericValue, PerBlock,
},
};
@@ -40,8 +39,7 @@ impl<C: CentsType> FiatPerBlock<C> {
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let cents =
PerBlock::forced_import(db, &format!("{name}_cents"), version, indexes)?;
let cents = PerBlock::forced_import(db, &format!("{name}_cents"), version, indexes)?;
let usd = LazyPerBlock::from_computed::<C::ToDollars>(
name,
version,

Some files were not shown because too many files have changed in this diff Show More