global: cost basis -> urpd

This commit is contained in:
nym21
2026-04-22 22:23:52 +02:00
parent 84e924b77e
commit 3faa989691
30 changed files with 950 additions and 507 deletions

View File

@@ -1,9 +1,9 @@
use std::{cmp::Reverse, collections::BinaryHeap, fs, path::Path};
use brk_cohort::{AGE_RANGE_NAMES, Filtered, PROFITABILITY_RANGE_COUNT, TERM_NAMES};
use brk_cohort::{AGE_RANGE_NAMES, CohortContext, Filtered, PROFITABILITY_RANGE_COUNT, TERM_NAMES};
use rayon::prelude::*;
use brk_error::Result;
use brk_types::{BasisPoints16, Cents, CentsCompact, CostBasisDistribution, Date, Dollars, Sats};
use brk_types::{BasisPoints16, Cents, CentsCompact, UrpdRaw, Date, Dollars, Sats};
use crate::distribution::metrics::{CostBasis, ProfitabilityMetrics};
@@ -78,7 +78,8 @@ impl UTXOCohorts {
merged.push((rounded, sats));
}
}
write_distribution(states_path, name.id, date, merged)
let full = CohortContext::Utxo.prefixed(name.id);
write_distribution(states_path, &full, date, merged)
})?;
let maps: Vec<_> = self
@@ -150,15 +151,15 @@ fn push_profitability(
fn write_distribution(
states_path: &Path,
name: &str,
full_name: &str,
date: Date,
merged: Vec<(CentsCompact, Sats)>,
) -> Result<()> {
let dir = states_path.join(format!("utxo_{name}_cost_basis/by_date"));
let dir = states_path.join(full_name).join("urpd");
fs::create_dir_all(&dir)?;
fs::write(
dir.join(date.to_string()),
CostBasisDistribution::serialize_iter(merged.into_iter())?,
UrpdRaw::serialize_iter(merged.into_iter())?,
)?;
Ok(())
}

View File

@@ -6,7 +6,7 @@ use std::{
use brk_error::{Error, Result};
use brk_types::{
Cents, CentsCompact, CentsSats, CentsSquaredSats, CostBasisDistribution, Height, Sats,
Cents, CentsCompact, CentsSats, CentsSquaredSats, UrpdRaw, Height, Sats,
};
use rustc_hash::FxHashMap;
use vecdb::{Bytes, unlikely};
@@ -78,23 +78,18 @@ pub struct CostBasisRaw {
}
impl CostBasisRaw {
pub(super) fn path_by_height(&self) -> PathBuf {
self.pathbuf.join("by_height")
}
pub(super) fn path_state(&self, height: Height) -> PathBuf {
self.path_by_height().join(height.to_string())
self.pathbuf.join(height.to_string())
}
pub(super) fn read_dir(
&self,
keep_only_before: Option<Height>,
) -> Result<BTreeMap<Height, PathBuf>> {
let by_height = self.path_by_height();
if !by_height.exists() {
if !self.pathbuf.exists() {
return Ok(BTreeMap::new());
}
Ok(fs::read_dir(&by_height)?
Ok(fs::read_dir(&self.pathbuf)?
.filter_map(|entry| {
let path = entry.ok()?.path();
let name = path.file_name()?.to_str()?;
@@ -150,7 +145,7 @@ impl CostBasisRaw {
impl CostBasisOps for CostBasisRaw {
fn create(path: &Path, name: &str) -> Self {
Self {
pathbuf: path.join(format!("{name}_cost_basis")),
pathbuf: path.join(name).join("cost_basis"),
state: None,
pending_cap: PendingCapDelta::default(),
}
@@ -170,7 +165,7 @@ impl CostBasisOps for CostBasisRaw {
self.state = Some(if data.len() == 16 {
RawState::deserialize(&data)?
} else {
let (_, rest) = CostBasisDistribution::deserialize_with_rest(&data)?;
let (_, rest) = UrpdRaw::deserialize_with_rest(&data)?;
RawState::deserialize(rest)?
});
self.pending_cap = PendingCapDelta::default();
@@ -219,7 +214,7 @@ impl CostBasisOps for CostBasisRaw {
fn clean(&mut self) -> Result<()> {
let _ = fs::remove_dir_all(&self.pathbuf);
fs::create_dir_all(self.path_by_height())?;
fs::create_dir_all(&self.pathbuf)?;
Ok(())
}
@@ -245,7 +240,7 @@ impl CostBasisOps for CostBasisRaw {
#[derive(Clone, Debug)]
pub struct CostBasisData<S: Accumulate> {
raw: CostBasisRaw,
map: Option<CostBasisDistribution>,
map: Option<UrpdRaw>,
pending: FxHashMap<CentsCompact, PendingDelta>,
cache: Option<CachedUnrealizedState<S>>,
rounding_digits: Option<i32>,
@@ -367,7 +362,7 @@ impl<S: Accumulate> CostBasisOps for CostBasisData<S> {
"No cost basis state found at or before height".into(),
))?;
let data = fs::read(path)?;
let (base, rest) = CostBasisDistribution::deserialize_with_rest(&data)?;
let (base, rest) = UrpdRaw::deserialize_with_rest(&data)?;
self.map = Some(base);
self.raw.state = Some(RawState::deserialize(rest)?);
debug_assert!(
@@ -449,7 +444,7 @@ impl<S: Accumulate> CostBasisOps for CostBasisData<S> {
fn init(&mut self) {
self.raw.init();
self.map.replace(CostBasisDistribution::default());
self.map.replace(UrpdRaw::default());
self.pending.clear();
self.cache = None;
self.capitalized_cap_raw = CentsSquaredSats::ZERO;