mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snapshot
This commit is contained in:
@@ -3,13 +3,13 @@ use rayon::prelude::*;
|
||||
|
||||
use crate::Filter;
|
||||
|
||||
use super::{ByAmountRange, ByGreatEqualAmount, ByLowerThanAmount};
|
||||
use super::{AmountRange, OverAmount, UnderAmount};
|
||||
|
||||
#[derive(Default, Clone, Traversable)]
|
||||
pub struct AddressGroups<T> {
|
||||
pub ge_amount: ByGreatEqualAmount<T>,
|
||||
pub amount_range: ByAmountRange<T>,
|
||||
pub lt_amount: ByLowerThanAmount<T>,
|
||||
pub over_amount: OverAmount<T>,
|
||||
pub amount_range: AmountRange<T>,
|
||||
pub under_amount: UnderAmount<T>,
|
||||
}
|
||||
|
||||
impl<T> AddressGroups<T> {
|
||||
@@ -18,9 +18,9 @@ impl<T> AddressGroups<T> {
|
||||
F: FnMut(Filter, &'static str) -> T,
|
||||
{
|
||||
Self {
|
||||
ge_amount: ByGreatEqualAmount::new(&mut create),
|
||||
amount_range: ByAmountRange::new(&mut create),
|
||||
lt_amount: ByLowerThanAmount::new(&mut create),
|
||||
over_amount: OverAmount::new(&mut create),
|
||||
amount_range: AmountRange::new(&mut create),
|
||||
under_amount: UnderAmount::new(&mut create),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,34 +29,34 @@ impl<T> AddressGroups<T> {
|
||||
F: Fn(Filter, &'static str) -> Result<T, E>,
|
||||
{
|
||||
Ok(Self {
|
||||
ge_amount: ByGreatEqualAmount::try_new(create)?,
|
||||
amount_range: ByAmountRange::try_new(create)?,
|
||||
lt_amount: ByLowerThanAmount::try_new(create)?,
|
||||
over_amount: OverAmount::try_new(create)?,
|
||||
amount_range: AmountRange::try_new(create)?,
|
||||
under_amount: UnderAmount::try_new(create)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||
self.ge_amount
|
||||
self.over_amount
|
||||
.iter()
|
||||
.chain(self.amount_range.iter())
|
||||
.chain(self.lt_amount.iter())
|
||||
.chain(self.under_amount.iter())
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
|
||||
self.ge_amount
|
||||
self.over_amount
|
||||
.iter_mut()
|
||||
.chain(self.amount_range.iter_mut())
|
||||
.chain(self.lt_amount.iter_mut())
|
||||
.chain(self.under_amount.iter_mut())
|
||||
}
|
||||
|
||||
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
self.ge_amount
|
||||
self.over_amount
|
||||
.par_iter_mut()
|
||||
.chain(self.amount_range.par_iter_mut())
|
||||
.chain(self.lt_amount.par_iter_mut())
|
||||
.chain(self.under_amount.par_iter_mut())
|
||||
}
|
||||
|
||||
pub fn iter_separate(&self) -> impl Iterator<Item = &T> {
|
||||
@@ -75,7 +75,7 @@ impl<T> AddressGroups<T> {
|
||||
}
|
||||
|
||||
pub fn iter_overlapping_mut(&mut self) -> impl Iterator<Item = &mut T> {
|
||||
self.lt_amount.iter_mut().chain(self.ge_amount.iter_mut())
|
||||
self.under_amount.iter_mut().chain(self.over_amount.iter_mut())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ pub const AGE_BOUNDARIES: [usize; 20] = [
|
||||
];
|
||||
|
||||
/// Age range bounds (end = usize::MAX means unbounded)
|
||||
pub const AGE_RANGE_BOUNDS: ByAgeRange<Range<usize>> = ByAgeRange {
|
||||
pub const AGE_RANGE_BOUNDS: AgeRange<Range<usize>> = AgeRange {
|
||||
up_to_1h: 0..HOURS_1H,
|
||||
_1h_to_1d: HOURS_1H..HOURS_1D,
|
||||
_1d_to_1w: HOURS_1D..HOURS_1W,
|
||||
@@ -63,7 +63,7 @@ pub const AGE_RANGE_BOUNDS: ByAgeRange<Range<usize>> = ByAgeRange {
|
||||
};
|
||||
|
||||
/// Age range filters
|
||||
pub const AGE_RANGE_FILTERS: ByAgeRange<Filter> = ByAgeRange {
|
||||
pub const AGE_RANGE_FILTERS: AgeRange<Filter> = AgeRange {
|
||||
up_to_1h: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS.up_to_1h)),
|
||||
_1h_to_1d: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS._1h_to_1d)),
|
||||
_1d_to_1w: Filter::Time(TimeFilter::Range(AGE_RANGE_BOUNDS._1d_to_1w)),
|
||||
@@ -88,7 +88,7 @@ pub const AGE_RANGE_FILTERS: ByAgeRange<Filter> = ByAgeRange {
|
||||
};
|
||||
|
||||
/// Age range names
|
||||
pub const AGE_RANGE_NAMES: ByAgeRange<CohortName> = ByAgeRange {
|
||||
pub const AGE_RANGE_NAMES: AgeRange<CohortName> = AgeRange {
|
||||
up_to_1h: CohortName::new("under_1h_old", "<1h", "Under 1 Hour Old"),
|
||||
_1h_to_1d: CohortName::new("1h_to_1d_old", "1h-1d", "1 Hour to 1 Day Old"),
|
||||
_1d_to_1w: CohortName::new("1d_to_1w_old", "1d-1w", "1 Day to 1 Week Old"),
|
||||
@@ -112,14 +112,14 @@ pub const AGE_RANGE_NAMES: ByAgeRange<CohortName> = ByAgeRange {
|
||||
from_15y: CohortName::new("over_15y_old", "15y+", "15+ Years Old"),
|
||||
};
|
||||
|
||||
impl ByAgeRange<CohortName> {
|
||||
impl AgeRange<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&AGE_RANGE_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByAgeRange<T> {
|
||||
pub struct AgeRange<T> {
|
||||
pub up_to_1h: T,
|
||||
pub _1h_to_1d: T,
|
||||
pub _1d_to_1w: T,
|
||||
@@ -143,7 +143,7 @@ pub struct ByAgeRange<T> {
|
||||
pub from_15y: T,
|
||||
}
|
||||
|
||||
impl<T> ByAgeRange<T> {
|
||||
impl<T> AgeRange<T> {
|
||||
/// Get mutable reference by Age. O(1).
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self, age: Age) -> &mut T {
|
||||
@@ -13,7 +13,7 @@ pub struct AmountBucket(u8);
|
||||
|
||||
impl AmountBucket {
|
||||
/// Returns (self, other) if buckets differ, None if same.
|
||||
/// Use with `ByAmountRange::get_mut_by_bucket` to avoid recomputing.
|
||||
/// Use with `AmountRange::get_mut_by_bucket` to avoid recomputing.
|
||||
#[inline(always)]
|
||||
pub fn transition_to(self, other: Self) -> Option<(Self, Self)> {
|
||||
if self != other {
|
||||
@@ -59,7 +59,7 @@ pub fn amounts_in_different_buckets(a: Sats, b: Sats) -> bool {
|
||||
}
|
||||
|
||||
/// Amount range bounds
|
||||
pub const AMOUNT_RANGE_BOUNDS: ByAmountRange<Range<Sats>> = ByAmountRange {
|
||||
pub const AMOUNT_RANGE_BOUNDS: AmountRange<Range<Sats>> = AmountRange {
|
||||
_0sats: Sats::ZERO..Sats::_1,
|
||||
_1sat_to_10sats: Sats::_1..Sats::_10,
|
||||
_10sats_to_100sats: Sats::_10..Sats::_100,
|
||||
@@ -78,7 +78,7 @@ pub const AMOUNT_RANGE_BOUNDS: ByAmountRange<Range<Sats>> = ByAmountRange {
|
||||
};
|
||||
|
||||
/// Amount range names
|
||||
pub const AMOUNT_RANGE_NAMES: ByAmountRange<CohortName> = ByAmountRange {
|
||||
pub const AMOUNT_RANGE_NAMES: AmountRange<CohortName> = AmountRange {
|
||||
_0sats: CohortName::new("with_0sats", "0 sats", "0 Sats"),
|
||||
_1sat_to_10sats: CohortName::new("above_1sat_under_10sats", "1-10 sats", "1-10 Sats"),
|
||||
_10sats_to_100sats: CohortName::new("above_10sats_under_100sats", "10-100 sats", "10-100 Sats"),
|
||||
@@ -121,7 +121,7 @@ pub const AMOUNT_RANGE_NAMES: ByAmountRange<CohortName> = ByAmountRange {
|
||||
};
|
||||
|
||||
/// Amount range filters
|
||||
pub const AMOUNT_RANGE_FILTERS: ByAmountRange<Filter> = ByAmountRange {
|
||||
pub const AMOUNT_RANGE_FILTERS: AmountRange<Filter> = AmountRange {
|
||||
_0sats: Filter::Amount(AmountFilter::Range(AMOUNT_RANGE_BOUNDS._0sats)),
|
||||
_1sat_to_10sats: Filter::Amount(AmountFilter::Range(AMOUNT_RANGE_BOUNDS._1sat_to_10sats)),
|
||||
_10sats_to_100sats: Filter::Amount(AmountFilter::Range(AMOUNT_RANGE_BOUNDS._10sats_to_100sats)),
|
||||
@@ -152,7 +152,7 @@ pub const AMOUNT_RANGE_FILTERS: ByAmountRange<Filter> = ByAmountRange {
|
||||
};
|
||||
|
||||
#[derive(Debug, Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByAmountRange<T> {
|
||||
pub struct AmountRange<T> {
|
||||
pub _0sats: T,
|
||||
pub _1sat_to_10sats: T,
|
||||
pub _10sats_to_100sats: T,
|
||||
@@ -170,13 +170,13 @@ pub struct ByAmountRange<T> {
|
||||
pub _100k_btc_or_more: T,
|
||||
}
|
||||
|
||||
impl ByAmountRange<CohortName> {
|
||||
impl AmountRange<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&AMOUNT_RANGE_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByAmountRange<T> {
|
||||
impl<T> AmountRange<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> T,
|
||||
@@ -385,7 +385,7 @@ impl<T> ByAmountRange<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Add for ByAmountRange<T>
|
||||
impl<T> Add for AmountRange<T>
|
||||
where
|
||||
T: Add<Output = T>,
|
||||
{
|
||||
@@ -411,7 +411,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign for ByAmountRange<T>
|
||||
impl<T> AddAssign for AmountRange<T>
|
||||
where
|
||||
T: AddAssign,
|
||||
{
|
||||
@@ -2,15 +2,15 @@ use std::ops::{Add, AddAssign};
|
||||
|
||||
use brk_types::OutputType;
|
||||
|
||||
use super::{BySpendableType, ByUnspendableType};
|
||||
use super::{SpendableType, UnspendableType};
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct GroupedByType<T> {
|
||||
pub spendable: BySpendableType<T>,
|
||||
pub unspendable: ByUnspendableType<T>,
|
||||
pub struct ByType<T> {
|
||||
pub spendable: SpendableType<T>,
|
||||
pub unspendable: UnspendableType<T>,
|
||||
}
|
||||
|
||||
impl<T> GroupedByType<T> {
|
||||
impl<T> ByType<T> {
|
||||
pub fn get(&self, output_type: OutputType) -> &T {
|
||||
match output_type {
|
||||
OutputType::P2PK65 => &self.spendable.p2pk65,
|
||||
@@ -46,7 +46,7 @@ impl<T> GroupedByType<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Add for GroupedByType<T>
|
||||
impl<T> Add for ByType<T>
|
||||
where
|
||||
T: Add<Output = T>,
|
||||
{
|
||||
@@ -59,7 +59,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign for GroupedByType<T>
|
||||
impl<T> AddAssign for ByType<T>
|
||||
where
|
||||
T: AddAssign,
|
||||
{
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#[derive(Default, Clone)]
|
||||
pub struct GroupedByValue<T> {
|
||||
pub up_to_1cent: T,
|
||||
pub from_1c_to_10c: T,
|
||||
pub from_10c_to_1d: T,
|
||||
pub from_1d_to_10d: T,
|
||||
pub from_10usd_to_100usd: T,
|
||||
pub from_100usd_to_1_000usd: T,
|
||||
pub from_1_000usd_to_10_000usd: T,
|
||||
pub from_10_000usd_to_100_000usd: T,
|
||||
pub from_100_000usd_to_1_000_000usd: T,
|
||||
pub from_1_000_000usd_to_10_000_000usd: T,
|
||||
pub from_10_000_000usd_to_100_000_000usd: T,
|
||||
pub from_100_000_000usd_to_1_000_000_000usd: T,
|
||||
pub from_1_000_000_000usd: T,
|
||||
// ...
|
||||
}
|
||||
|
||||
impl<T> GroupedByValue<T> {
|
||||
pub fn as_mut_vec(&mut self) -> Vec<&mut T> {
|
||||
vec![
|
||||
&mut self.up_to_1cent,
|
||||
&mut self.from_1c_to_10c,
|
||||
&mut self.from_10c_to_1d,
|
||||
&mut self.from_1d_to_10d,
|
||||
&mut self.from_10usd_to_100usd,
|
||||
&mut self.from_100usd_to_1_000usd,
|
||||
&mut self.from_1_000usd_to_10_000usd,
|
||||
&mut self.from_10_000usd_to_100_000usd,
|
||||
&mut self.from_100_000usd_to_1_000_000usd,
|
||||
&mut self.from_1_000_000usd_to_10_000_000usd,
|
||||
&mut self.from_10_000_000usd_to_100_000_000usd,
|
||||
&mut self.from_100_000_000usd_to_1_000_000_000usd,
|
||||
&mut self.from_1_000_000_000usd,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use serde::Serialize;
|
||||
use super::{CohortName, Filter};
|
||||
|
||||
/// Class values
|
||||
pub const CLASS_VALUES: ByClass<Year> = ByClass {
|
||||
pub const CLASS_VALUES: Class<Year> = Class {
|
||||
_2009: Year::new(2009),
|
||||
_2010: Year::new(2010),
|
||||
_2011: Year::new(2011),
|
||||
@@ -28,7 +28,7 @@ pub const CLASS_VALUES: ByClass<Year> = ByClass {
|
||||
};
|
||||
|
||||
/// Class filters
|
||||
pub const CLASS_FILTERS: ByClass<Filter> = ByClass {
|
||||
pub const CLASS_FILTERS: Class<Filter> = Class {
|
||||
_2009: Filter::Class(CLASS_VALUES._2009),
|
||||
_2010: Filter::Class(CLASS_VALUES._2010),
|
||||
_2011: Filter::Class(CLASS_VALUES._2011),
|
||||
@@ -50,7 +50,7 @@ pub const CLASS_FILTERS: ByClass<Filter> = ByClass {
|
||||
};
|
||||
|
||||
/// Class names
|
||||
pub const CLASS_NAMES: ByClass<CohortName> = ByClass {
|
||||
pub const CLASS_NAMES: Class<CohortName> = Class {
|
||||
_2009: CohortName::new("class_2009", "2009", "Class 2009"),
|
||||
_2010: CohortName::new("class_2010", "2010", "Class 2010"),
|
||||
_2011: CohortName::new("class_2011", "2011", "Class 2011"),
|
||||
@@ -72,7 +72,7 @@ pub const CLASS_NAMES: ByClass<CohortName> = ByClass {
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByClass<T> {
|
||||
pub struct Class<T> {
|
||||
pub _2009: T,
|
||||
pub _2010: T,
|
||||
pub _2011: T,
|
||||
@@ -93,13 +93,13 @@ pub struct ByClass<T> {
|
||||
pub _2026: T,
|
||||
}
|
||||
|
||||
impl ByClass<CohortName> {
|
||||
impl Class<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&CLASS_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByClass<T> {
|
||||
impl<T> Class<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> T,
|
||||
@@ -89,7 +89,7 @@ impl Filter {
|
||||
}
|
||||
|
||||
/// Whether to compute adjusted metrics (adjusted SOPR, adjusted value created/destroyed)
|
||||
/// For UTXO context: true for All, STH, and max_age (LowerThan)
|
||||
/// For UTXO context: true for All, STH, and under_age (LowerThan)
|
||||
/// For Address context: always false
|
||||
/// Note: LTH doesn't need adjusted (everything >= 5 months is already > 1 hour)
|
||||
/// Note: age ranges don't need adjusted (0-1h data lives in its own cohort)
|
||||
|
||||
@@ -2,56 +2,56 @@
|
||||
|
||||
mod address;
|
||||
mod amount_filter;
|
||||
mod age_range;
|
||||
mod amount_range;
|
||||
mod by_address_type;
|
||||
mod by_age_range;
|
||||
mod by_amount_range;
|
||||
mod by_any_address;
|
||||
mod by_epoch;
|
||||
mod by_ge_amount;
|
||||
mod by_loss;
|
||||
mod by_lt_amount;
|
||||
mod by_max_age;
|
||||
mod by_min_age;
|
||||
mod by_profitability_range;
|
||||
mod by_profit;
|
||||
mod by_spendable_type;
|
||||
mod by_term;
|
||||
mod by_type;
|
||||
mod by_unspendable_type;
|
||||
mod by_class;
|
||||
mod class;
|
||||
mod cohort_context;
|
||||
mod cohort_name;
|
||||
mod filter;
|
||||
mod filtered;
|
||||
mod loss;
|
||||
mod over_age;
|
||||
mod over_amount;
|
||||
mod profit;
|
||||
mod profitability_range;
|
||||
mod spendable_type;
|
||||
mod state_level;
|
||||
mod time_filter;
|
||||
mod under_age;
|
||||
mod under_amount;
|
||||
mod unspendable_type;
|
||||
mod utxo;
|
||||
|
||||
pub use brk_types::{Age, Term};
|
||||
|
||||
pub use address::*;
|
||||
pub use amount_filter::*;
|
||||
pub use age_range::*;
|
||||
pub use amount_range::*;
|
||||
pub use by_address_type::*;
|
||||
pub use by_age_range::*;
|
||||
pub use by_amount_range::*;
|
||||
pub use by_any_address::*;
|
||||
pub use by_epoch::*;
|
||||
pub use by_ge_amount::*;
|
||||
pub use by_loss::*;
|
||||
pub use by_lt_amount::*;
|
||||
pub use by_max_age::*;
|
||||
pub use by_min_age::*;
|
||||
pub use by_profitability_range::*;
|
||||
pub use by_profit::*;
|
||||
pub use by_spendable_type::*;
|
||||
pub use by_term::*;
|
||||
pub use by_type::*;
|
||||
pub use by_unspendable_type::*;
|
||||
pub use by_class::*;
|
||||
pub use class::*;
|
||||
pub use cohort_context::*;
|
||||
pub use cohort_name::*;
|
||||
pub use filter::*;
|
||||
pub use filtered::*;
|
||||
pub use loss::*;
|
||||
pub use over_age::*;
|
||||
pub use over_amount::*;
|
||||
pub use profit::*;
|
||||
pub use profitability_range::*;
|
||||
pub use spendable_type::*;
|
||||
pub use state_level::*;
|
||||
pub use time_filter::*;
|
||||
pub use under_age::*;
|
||||
pub use under_amount::*;
|
||||
pub use unspendable_type::*;
|
||||
pub use utxo::*;
|
||||
|
||||
@@ -5,7 +5,7 @@ use serde::Serialize;
|
||||
use super::CohortName;
|
||||
|
||||
/// "At least X% loss" threshold names (10 thresholds).
|
||||
pub const LOSS_NAMES: ByLoss<CohortName> = ByLoss {
|
||||
pub const LOSS_NAMES: Loss<CohortName> = Loss {
|
||||
breakeven: CohortName::new("utxos_in_loss", "<0%", "In Loss (Below Breakeven)"),
|
||||
_10pct: CohortName::new("utxos_over_10pct_in_loss", "≥10%L", "10%+ Loss"),
|
||||
_20pct: CohortName::new("utxos_over_20pct_in_loss", "≥20%L", "20%+ Loss"),
|
||||
@@ -15,13 +15,12 @@ pub const LOSS_NAMES: ByLoss<CohortName> = ByLoss {
|
||||
_60pct: CohortName::new("utxos_over_60pct_in_loss", "≥60%L", "60%+ Loss"),
|
||||
_70pct: CohortName::new("utxos_over_70pct_in_loss", "≥70%L", "70%+ Loss"),
|
||||
_80pct: CohortName::new("utxos_over_80pct_in_loss", "≥80%L", "80%+ Loss"),
|
||||
_90pct: CohortName::new("utxos_over_90pct_in_loss", "≥90%L", "90%+ Loss"),
|
||||
};
|
||||
|
||||
/// Number of loss thresholds.
|
||||
pub const LOSS_COUNT: usize = 10;
|
||||
pub const LOSS_COUNT: usize = 9;
|
||||
|
||||
impl ByLoss<CohortName> {
|
||||
impl Loss<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&LOSS_NAMES
|
||||
}
|
||||
@@ -31,7 +30,7 @@ impl ByLoss<CohortName> {
|
||||
///
|
||||
/// Each is a suffix sum over the profitability ranges, from most loss-making up.
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByLoss<T> {
|
||||
pub struct Loss<T> {
|
||||
pub breakeven: T,
|
||||
pub _10pct: T,
|
||||
pub _20pct: T,
|
||||
@@ -41,10 +40,9 @@ pub struct ByLoss<T> {
|
||||
pub _60pct: T,
|
||||
pub _70pct: T,
|
||||
pub _80pct: T,
|
||||
pub _90pct: T,
|
||||
}
|
||||
|
||||
impl<T> ByLoss<T> {
|
||||
impl<T> Loss<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(&'static str) -> T,
|
||||
@@ -60,7 +58,6 @@ impl<T> ByLoss<T> {
|
||||
_60pct: create(n._60pct.id),
|
||||
_70pct: create(n._70pct.id),
|
||||
_80pct: create(n._80pct.id),
|
||||
_90pct: create(n._90pct.id),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +76,6 @@ impl<T> ByLoss<T> {
|
||||
_60pct: create(n._60pct.id)?,
|
||||
_70pct: create(n._70pct.id)?,
|
||||
_80pct: create(n._80pct.id)?,
|
||||
_90pct: create(n._90pct.id)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -94,7 +90,6 @@ impl<T> ByLoss<T> {
|
||||
&self._60pct,
|
||||
&self._70pct,
|
||||
&self._80pct,
|
||||
&self._90pct,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@@ -110,7 +105,6 @@ impl<T> ByLoss<T> {
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@@ -129,7 +123,6 @@ impl<T> ByLoss<T> {
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
]
|
||||
.into_par_iter()
|
||||
}
|
||||
@@ -146,7 +139,6 @@ impl<T> ByLoss<T> {
|
||||
&mut self._60pct,
|
||||
&mut self._70pct,
|
||||
&mut self._80pct,
|
||||
&mut self._90pct,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ use super::{
|
||||
HOURS_10Y, HOURS_12Y, TimeFilter,
|
||||
};
|
||||
|
||||
/// Min age thresholds in hours
|
||||
pub const MIN_AGE_HOURS: ByMinAge<usize> = ByMinAge {
|
||||
/// Over-age thresholds in hours
|
||||
pub const OVER_AGE_HOURS: OverAge<usize> = OverAge {
|
||||
_1d: HOURS_1D,
|
||||
_1w: HOURS_1W,
|
||||
_1m: HOURS_1M,
|
||||
@@ -30,30 +30,30 @@ pub const MIN_AGE_HOURS: ByMinAge<usize> = ByMinAge {
|
||||
_12y: HOURS_12Y,
|
||||
};
|
||||
|
||||
/// Min age filters (GreaterOrEqual threshold in hours)
|
||||
pub const MIN_AGE_FILTERS: ByMinAge<Filter> = ByMinAge {
|
||||
_1d: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1d)),
|
||||
_1w: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1w)),
|
||||
_1m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1m)),
|
||||
_2m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._2m)),
|
||||
_3m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._3m)),
|
||||
_4m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._4m)),
|
||||
_5m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._5m)),
|
||||
_6m: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._6m)),
|
||||
_1y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._1y)),
|
||||
_2y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._2y)),
|
||||
_3y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._3y)),
|
||||
_4y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._4y)),
|
||||
_5y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._5y)),
|
||||
_6y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._6y)),
|
||||
_7y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._7y)),
|
||||
_8y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._8y)),
|
||||
_10y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._10y)),
|
||||
_12y: Filter::Time(TimeFilter::GreaterOrEqual(MIN_AGE_HOURS._12y)),
|
||||
/// Over-age filters (GreaterOrEqual threshold in hours)
|
||||
pub const OVER_AGE_FILTERS: OverAge<Filter> = OverAge {
|
||||
_1d: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._1d)),
|
||||
_1w: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._1w)),
|
||||
_1m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._1m)),
|
||||
_2m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._2m)),
|
||||
_3m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._3m)),
|
||||
_4m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._4m)),
|
||||
_5m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._5m)),
|
||||
_6m: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._6m)),
|
||||
_1y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._1y)),
|
||||
_2y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._2y)),
|
||||
_3y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._3y)),
|
||||
_4y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._4y)),
|
||||
_5y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._5y)),
|
||||
_6y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._6y)),
|
||||
_7y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._7y)),
|
||||
_8y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._8y)),
|
||||
_10y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._10y)),
|
||||
_12y: Filter::Time(TimeFilter::GreaterOrEqual(OVER_AGE_HOURS._12y)),
|
||||
};
|
||||
|
||||
/// Min age names
|
||||
pub const MIN_AGE_NAMES: ByMinAge<CohortName> = ByMinAge {
|
||||
/// Over-age names
|
||||
pub const OVER_AGE_NAMES: OverAge<CohortName> = OverAge {
|
||||
_1d: CohortName::new("over_1d_old", "1d+", "Over 1 Day Old"),
|
||||
_1w: CohortName::new("over_1w_old", "1w+", "Over 1 Week Old"),
|
||||
_1m: CohortName::new("over_1m_old", "1m+", "Over 1 Month Old"),
|
||||
@@ -75,7 +75,7 @@ pub const MIN_AGE_NAMES: ByMinAge<CohortName> = ByMinAge {
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByMinAge<T> {
|
||||
pub struct OverAge<T> {
|
||||
pub _1d: T,
|
||||
pub _1w: T,
|
||||
pub _1m: T,
|
||||
@@ -96,19 +96,19 @@ pub struct ByMinAge<T> {
|
||||
pub _12y: T,
|
||||
}
|
||||
|
||||
impl ByMinAge<CohortName> {
|
||||
impl OverAge<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&MIN_AGE_NAMES
|
||||
&OVER_AGE_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByMinAge<T> {
|
||||
impl<T> OverAge<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> T,
|
||||
{
|
||||
let f = MIN_AGE_FILTERS;
|
||||
let n = MIN_AGE_NAMES;
|
||||
let f = OVER_AGE_FILTERS;
|
||||
let n = OVER_AGE_NAMES;
|
||||
Self {
|
||||
_1d: create(f._1d.clone(), n._1d.id),
|
||||
_1w: create(f._1w.clone(), n._1w.id),
|
||||
@@ -135,8 +135,8 @@ impl<T> ByMinAge<T> {
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> Result<T, E>,
|
||||
{
|
||||
let f = MIN_AGE_FILTERS;
|
||||
let n = MIN_AGE_NAMES;
|
||||
let f = OVER_AGE_FILTERS;
|
||||
let n = OVER_AGE_NAMES;
|
||||
Ok(Self {
|
||||
_1d: create(f._1d.clone(), n._1d.id)?,
|
||||
_1w: create(f._1w.clone(), n._1w.id)?,
|
||||
@@ -5,8 +5,8 @@ use serde::Serialize;
|
||||
|
||||
use super::{AmountFilter, CohortName, Filter};
|
||||
|
||||
/// Greater-or-equal amount thresholds
|
||||
pub const GE_AMOUNT_THRESHOLDS: ByGreatEqualAmount<Sats> = ByGreatEqualAmount {
|
||||
/// Over-amount thresholds
|
||||
pub const OVER_AMOUNT_THRESHOLDS: OverAmount<Sats> = OverAmount {
|
||||
_1sat: Sats::_1,
|
||||
_10sats: Sats::_10,
|
||||
_100sats: Sats::_100,
|
||||
@@ -22,8 +22,8 @@ pub const GE_AMOUNT_THRESHOLDS: ByGreatEqualAmount<Sats> = ByGreatEqualAmount {
|
||||
_10k_btc: Sats::_10K_BTC,
|
||||
};
|
||||
|
||||
/// Greater-or-equal amount names
|
||||
pub const GE_AMOUNT_NAMES: ByGreatEqualAmount<CohortName> = ByGreatEqualAmount {
|
||||
/// Over-amount names
|
||||
pub const OVER_AMOUNT_NAMES: OverAmount<CohortName> = OverAmount {
|
||||
_1sat: CohortName::new("over_1sat", "1+ sats", "Over 1 Sat"),
|
||||
_10sats: CohortName::new("over_10sats", "10+ sats", "Over 10 Sats"),
|
||||
_100sats: CohortName::new("over_100sats", "100+ sats", "Over 100 Sats"),
|
||||
@@ -39,27 +39,27 @@ pub const GE_AMOUNT_NAMES: ByGreatEqualAmount<CohortName> = ByGreatEqualAmount {
|
||||
_10k_btc: CohortName::new("over_10k_btc", "10k+ BTC", "Over 10K BTC"),
|
||||
};
|
||||
|
||||
/// Greater-or-equal amount filters
|
||||
pub const GE_AMOUNT_FILTERS: ByGreatEqualAmount<Filter> = ByGreatEqualAmount {
|
||||
_1sat: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1sat)),
|
||||
_10sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10sats)),
|
||||
_100sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._100sats)),
|
||||
_1k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1k_sats)),
|
||||
_10k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10k_sats)),
|
||||
/// Over-amount filters
|
||||
pub const OVER_AMOUNT_FILTERS: OverAmount<Filter> = OverAmount {
|
||||
_1sat: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1sat)),
|
||||
_10sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10sats)),
|
||||
_100sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._100sats)),
|
||||
_1k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1k_sats)),
|
||||
_10k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10k_sats)),
|
||||
_100k_sats: Filter::Amount(AmountFilter::GreaterOrEqual(
|
||||
GE_AMOUNT_THRESHOLDS._100k_sats,
|
||||
OVER_AMOUNT_THRESHOLDS._100k_sats,
|
||||
)),
|
||||
_1m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1m_sats)),
|
||||
_10m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10m_sats)),
|
||||
_1btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1btc)),
|
||||
_10btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10btc)),
|
||||
_100btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._100btc)),
|
||||
_1k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._1k_btc)),
|
||||
_10k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(GE_AMOUNT_THRESHOLDS._10k_btc)),
|
||||
_1m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1m_sats)),
|
||||
_10m_sats: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10m_sats)),
|
||||
_1btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1btc)),
|
||||
_10btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10btc)),
|
||||
_100btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._100btc)),
|
||||
_1k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._1k_btc)),
|
||||
_10k_btc: Filter::Amount(AmountFilter::GreaterOrEqual(OVER_AMOUNT_THRESHOLDS._10k_btc)),
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByGreatEqualAmount<T> {
|
||||
pub struct OverAmount<T> {
|
||||
pub _1sat: T,
|
||||
pub _10sats: T,
|
||||
pub _100sats: T,
|
||||
@@ -75,19 +75,19 @@ pub struct ByGreatEqualAmount<T> {
|
||||
pub _10k_btc: T,
|
||||
}
|
||||
|
||||
impl ByGreatEqualAmount<CohortName> {
|
||||
impl OverAmount<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&GE_AMOUNT_NAMES
|
||||
&OVER_AMOUNT_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByGreatEqualAmount<T> {
|
||||
impl<T> OverAmount<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> T,
|
||||
{
|
||||
let f = GE_AMOUNT_FILTERS;
|
||||
let n = GE_AMOUNT_NAMES;
|
||||
let f = OVER_AMOUNT_FILTERS;
|
||||
let n = OVER_AMOUNT_NAMES;
|
||||
Self {
|
||||
_1sat: create(f._1sat.clone(), n._1sat.id),
|
||||
_10sats: create(f._10sats.clone(), n._10sats.id),
|
||||
@@ -109,8 +109,8 @@ impl<T> ByGreatEqualAmount<T> {
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> Result<T, E>,
|
||||
{
|
||||
let f = GE_AMOUNT_FILTERS;
|
||||
let n = GE_AMOUNT_NAMES;
|
||||
let f = OVER_AMOUNT_FILTERS;
|
||||
let n = OVER_AMOUNT_NAMES;
|
||||
Ok(Self {
|
||||
_1sat: create(f._1sat.clone(), n._1sat.id)?,
|
||||
_10sats: create(f._10sats.clone(), n._10sats.id)?,
|
||||
@@ -5,7 +5,7 @@ use serde::Serialize;
|
||||
use super::CohortName;
|
||||
|
||||
/// "At least X% profit" threshold names (15 thresholds).
|
||||
pub const PROFIT_NAMES: ByProfit<CohortName> = ByProfit {
|
||||
pub const PROFIT_NAMES: Profit<CohortName> = Profit {
|
||||
breakeven: CohortName::new("utxos_in_profit", "≥0%", "In Profit (Breakeven+)"),
|
||||
_10pct: CohortName::new("utxos_over_10pct_in_profit", "≥10%", "10%+ Profit"),
|
||||
_20pct: CohortName::new("utxos_over_20pct_in_profit", "≥20%", "20%+ Profit"),
|
||||
@@ -20,13 +20,12 @@ pub const PROFIT_NAMES: ByProfit<CohortName> = ByProfit {
|
||||
_200pct: CohortName::new("utxos_over_200pct_in_profit", "≥200%", "200%+ Profit"),
|
||||
_300pct: CohortName::new("utxos_over_300pct_in_profit", "≥300%", "300%+ Profit"),
|
||||
_500pct: CohortName::new("utxos_over_500pct_in_profit", "≥500%", "500%+ Profit"),
|
||||
_1000pct: CohortName::new("utxos_over_1000pct_in_profit", "≥1000%", "1000%+ Profit"),
|
||||
};
|
||||
|
||||
/// Number of profit thresholds.
|
||||
pub const PROFIT_COUNT: usize = 15;
|
||||
pub const PROFIT_COUNT: usize = 14;
|
||||
|
||||
impl ByProfit<CohortName> {
|
||||
impl Profit<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&PROFIT_NAMES
|
||||
}
|
||||
@@ -36,7 +35,7 @@ impl ByProfit<CohortName> {
|
||||
///
|
||||
/// Each is a prefix sum over the profitability ranges, from most profitable down.
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByProfit<T> {
|
||||
pub struct Profit<T> {
|
||||
pub breakeven: T,
|
||||
pub _10pct: T,
|
||||
pub _20pct: T,
|
||||
@@ -51,10 +50,9 @@ pub struct ByProfit<T> {
|
||||
pub _200pct: T,
|
||||
pub _300pct: T,
|
||||
pub _500pct: T,
|
||||
pub _1000pct: T,
|
||||
}
|
||||
|
||||
impl<T> ByProfit<T> {
|
||||
impl<T> Profit<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(&'static str) -> T,
|
||||
@@ -75,7 +73,6 @@ impl<T> ByProfit<T> {
|
||||
_200pct: create(n._200pct.id),
|
||||
_300pct: create(n._300pct.id),
|
||||
_500pct: create(n._500pct.id),
|
||||
_1000pct: create(n._1000pct.id),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +96,6 @@ impl<T> ByProfit<T> {
|
||||
_200pct: create(n._200pct.id)?,
|
||||
_300pct: create(n._300pct.id)?,
|
||||
_500pct: create(n._500pct.id)?,
|
||||
_1000pct: create(n._1000pct.id)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -119,7 +115,6 @@ impl<T> ByProfit<T> {
|
||||
&self._200pct,
|
||||
&self._300pct,
|
||||
&self._500pct,
|
||||
&self._1000pct,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@@ -140,7 +135,6 @@ impl<T> ByProfit<T> {
|
||||
&mut self._200pct,
|
||||
&mut self._300pct,
|
||||
&mut self._500pct,
|
||||
&mut self._1000pct,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@@ -164,7 +158,6 @@ impl<T> ByProfit<T> {
|
||||
&mut self._200pct,
|
||||
&mut self._300pct,
|
||||
&mut self._500pct,
|
||||
&mut self._1000pct,
|
||||
]
|
||||
.into_par_iter()
|
||||
}
|
||||
@@ -186,7 +179,6 @@ impl<T> ByProfit<T> {
|
||||
&mut self._200pct,
|
||||
&mut self._300pct,
|
||||
&mut self._500pct,
|
||||
&mut self._1000pct,
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ pub fn compute_profitability_boundaries(spot: Cents) -> [Cents; PROFITABILITY_BO
|
||||
}
|
||||
|
||||
/// Profitability range names (25 ranges, from most profitable to most in loss)
|
||||
pub const PROFITABILITY_RANGE_NAMES: ByProfitabilityRange<CohortName> = ByProfitabilityRange {
|
||||
pub const PROFITABILITY_RANGE_NAMES: ProfitabilityRange<CohortName> = ProfitabilityRange {
|
||||
over_1000pct_in_profit: CohortName::new("utxos_over_1000pct_in_profit", ">1000%", "Over 1000% Profit"),
|
||||
_500pct_to_1000pct_in_profit: CohortName::new("utxos_500pct_to_1000pct_in_profit", "500-1000%", "500-1000% Profit"),
|
||||
_300pct_to_500pct_in_profit: CohortName::new("utxos_300pct_to_500pct_in_profit", "300-500%", "300-500% Profit"),
|
||||
@@ -110,7 +110,7 @@ pub const PROFITABILITY_RANGE_NAMES: ByProfitabilityRange<CohortName> = ByProfit
|
||||
_90pct_to_100pct_in_loss: CohortName::new("utxos_90pct_to_100pct_in_loss", "90-100%L", "90-100% Loss"),
|
||||
};
|
||||
|
||||
impl ByProfitabilityRange<CohortName> {
|
||||
impl ProfitabilityRange<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&PROFITABILITY_RANGE_NAMES
|
||||
}
|
||||
@@ -121,7 +121,7 @@ impl ByProfitabilityRange<CohortName> {
|
||||
/// During the k-way merge (ascending price order), the cursor starts at bucket 0
|
||||
/// (over_1000pct_in_profit, lowest cost basis) and advances as price crosses each boundary.
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByProfitabilityRange<T> {
|
||||
pub struct ProfitabilityRange<T> {
|
||||
pub over_1000pct_in_profit: T,
|
||||
pub _500pct_to_1000pct_in_profit: T,
|
||||
pub _300pct_to_500pct_in_profit: T,
|
||||
@@ -152,7 +152,7 @@ pub struct ByProfitabilityRange<T> {
|
||||
/// Number of profitability range buckets.
|
||||
pub const PROFITABILITY_RANGE_COUNT: usize = 25;
|
||||
|
||||
impl<T> ByProfitabilityRange<T> {
|
||||
impl<T> ProfitabilityRange<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(&'static str) -> T,
|
||||
@@ -8,7 +8,7 @@ use serde::Serialize;
|
||||
use super::{CohortName, Filter};
|
||||
|
||||
/// Spendable type values
|
||||
pub const SPENDABLE_TYPE_VALUES: BySpendableType<OutputType> = BySpendableType {
|
||||
pub const SPENDABLE_TYPE_VALUES: SpendableType<OutputType> = SpendableType {
|
||||
p2pk65: OutputType::P2PK65,
|
||||
p2pk33: OutputType::P2PK33,
|
||||
p2pkh: OutputType::P2PKH,
|
||||
@@ -23,7 +23,7 @@ pub const SPENDABLE_TYPE_VALUES: BySpendableType<OutputType> = BySpendableType {
|
||||
};
|
||||
|
||||
/// Spendable type filters
|
||||
pub const SPENDABLE_TYPE_FILTERS: BySpendableType<Filter> = BySpendableType {
|
||||
pub const SPENDABLE_TYPE_FILTERS: SpendableType<Filter> = SpendableType {
|
||||
p2pk65: Filter::Type(SPENDABLE_TYPE_VALUES.p2pk65),
|
||||
p2pk33: Filter::Type(SPENDABLE_TYPE_VALUES.p2pk33),
|
||||
p2pkh: Filter::Type(SPENDABLE_TYPE_VALUES.p2pkh),
|
||||
@@ -38,7 +38,7 @@ pub const SPENDABLE_TYPE_FILTERS: BySpendableType<Filter> = BySpendableType {
|
||||
};
|
||||
|
||||
/// Spendable type names
|
||||
pub const SPENDABLE_TYPE_NAMES: BySpendableType<CohortName> = BySpendableType {
|
||||
pub const SPENDABLE_TYPE_NAMES: SpendableType<CohortName> = SpendableType {
|
||||
p2pk65: CohortName::new("p2pk65", "P2PK65", "Pay to Public Key (65 bytes)"),
|
||||
p2pk33: CohortName::new("p2pk33", "P2PK33", "Pay to Public Key (33 bytes)"),
|
||||
p2pkh: CohortName::new("p2pkh", "P2PKH", "Pay to Public Key Hash"),
|
||||
@@ -53,7 +53,7 @@ pub const SPENDABLE_TYPE_NAMES: BySpendableType<CohortName> = BySpendableType {
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Debug, Traversable, Serialize)]
|
||||
pub struct BySpendableType<T> {
|
||||
pub struct SpendableType<T> {
|
||||
pub p2pk65: T,
|
||||
pub p2pk33: T,
|
||||
pub p2pkh: T,
|
||||
@@ -67,13 +67,13 @@ pub struct BySpendableType<T> {
|
||||
pub empty: T,
|
||||
}
|
||||
|
||||
impl BySpendableType<CohortName> {
|
||||
impl SpendableType<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&SPENDABLE_TYPE_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BySpendableType<T> {
|
||||
impl<T> SpendableType<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> T,
|
||||
@@ -222,7 +222,7 @@ impl<T> BySpendableType<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Add for BySpendableType<T>
|
||||
impl<T> Add for SpendableType<T>
|
||||
where
|
||||
T: Add<Output = T>,
|
||||
{
|
||||
@@ -244,7 +244,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign for BySpendableType<T>
|
||||
impl<T> AddAssign for SpendableType<T>
|
||||
where
|
||||
T: AddAssign,
|
||||
{
|
||||
@@ -8,8 +8,8 @@ use super::{
|
||||
HOURS_12Y, HOURS_15Y, TimeFilter,
|
||||
};
|
||||
|
||||
/// Max age thresholds in hours
|
||||
pub const MAX_AGE_HOURS: ByMaxAge<usize> = ByMaxAge {
|
||||
/// Under-age thresholds in hours
|
||||
pub const UNDER_AGE_HOURS: UnderAge<usize> = UnderAge {
|
||||
_1w: HOURS_1W,
|
||||
_1m: HOURS_1M,
|
||||
_2m: HOURS_2M,
|
||||
@@ -30,30 +30,30 @@ pub const MAX_AGE_HOURS: ByMaxAge<usize> = ByMaxAge {
|
||||
_15y: HOURS_15Y,
|
||||
};
|
||||
|
||||
/// Max age filters (LowerThan threshold in hours)
|
||||
pub const MAX_AGE_FILTERS: ByMaxAge<Filter> = ByMaxAge {
|
||||
_1w: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1w)),
|
||||
_1m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1m)),
|
||||
_2m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._2m)),
|
||||
_3m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._3m)),
|
||||
_4m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._4m)),
|
||||
_5m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._5m)),
|
||||
_6m: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._6m)),
|
||||
_1y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._1y)),
|
||||
_2y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._2y)),
|
||||
_3y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._3y)),
|
||||
_4y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._4y)),
|
||||
_5y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._5y)),
|
||||
_6y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._6y)),
|
||||
_7y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._7y)),
|
||||
_8y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._8y)),
|
||||
_10y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._10y)),
|
||||
_12y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._12y)),
|
||||
_15y: Filter::Time(TimeFilter::LowerThan(MAX_AGE_HOURS._15y)),
|
||||
/// Under-age filters (LowerThan threshold in hours)
|
||||
pub const UNDER_AGE_FILTERS: UnderAge<Filter> = UnderAge {
|
||||
_1w: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._1w)),
|
||||
_1m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._1m)),
|
||||
_2m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._2m)),
|
||||
_3m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._3m)),
|
||||
_4m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._4m)),
|
||||
_5m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._5m)),
|
||||
_6m: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._6m)),
|
||||
_1y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._1y)),
|
||||
_2y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._2y)),
|
||||
_3y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._3y)),
|
||||
_4y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._4y)),
|
||||
_5y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._5y)),
|
||||
_6y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._6y)),
|
||||
_7y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._7y)),
|
||||
_8y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._8y)),
|
||||
_10y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._10y)),
|
||||
_12y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._12y)),
|
||||
_15y: Filter::Time(TimeFilter::LowerThan(UNDER_AGE_HOURS._15y)),
|
||||
};
|
||||
|
||||
/// Max age names
|
||||
pub const MAX_AGE_NAMES: ByMaxAge<CohortName> = ByMaxAge {
|
||||
/// Under-age names
|
||||
pub const UNDER_AGE_NAMES: UnderAge<CohortName> = UnderAge {
|
||||
_1w: CohortName::new("under_1w_old", "<1w", "Under 1 Week Old"),
|
||||
_1m: CohortName::new("under_1m_old", "<1m", "Under 1 Month Old"),
|
||||
_2m: CohortName::new("under_2m_old", "<2m", "Under 2 Months Old"),
|
||||
@@ -75,7 +75,7 @@ pub const MAX_AGE_NAMES: ByMaxAge<CohortName> = ByMaxAge {
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByMaxAge<T> {
|
||||
pub struct UnderAge<T> {
|
||||
pub _1w: T,
|
||||
pub _1m: T,
|
||||
pub _2m: T,
|
||||
@@ -96,19 +96,19 @@ pub struct ByMaxAge<T> {
|
||||
pub _15y: T,
|
||||
}
|
||||
|
||||
impl ByMaxAge<CohortName> {
|
||||
impl UnderAge<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
&MAX_AGE_NAMES
|
||||
&UNDER_AGE_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByMaxAge<T> {
|
||||
impl<T> UnderAge<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> T,
|
||||
{
|
||||
let f = MAX_AGE_FILTERS;
|
||||
let n = MAX_AGE_NAMES;
|
||||
let f = UNDER_AGE_FILTERS;
|
||||
let n = UNDER_AGE_NAMES;
|
||||
Self {
|
||||
_1w: create(f._1w.clone(), n._1w.id),
|
||||
_1m: create(f._1m.clone(), n._1m.id),
|
||||
@@ -135,8 +135,8 @@ impl<T> ByMaxAge<T> {
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> Result<T, E>,
|
||||
{
|
||||
let f = MAX_AGE_FILTERS;
|
||||
let n = MAX_AGE_NAMES;
|
||||
let f = UNDER_AGE_FILTERS;
|
||||
let n = UNDER_AGE_NAMES;
|
||||
Ok(Self {
|
||||
_1w: create(f._1w.clone(), n._1w.id)?,
|
||||
_1m: create(f._1m.clone(), n._1m.id)?,
|
||||
@@ -5,8 +5,8 @@ use serde::Serialize;
|
||||
|
||||
use super::{AmountFilter, CohortName, Filter};
|
||||
|
||||
/// Lower-than amount thresholds
|
||||
pub const LT_AMOUNT_THRESHOLDS: ByLowerThanAmount<Sats> = ByLowerThanAmount {
|
||||
/// Under-amount thresholds
|
||||
pub const UNDER_AMOUNT_THRESHOLDS: UnderAmount<Sats> = UnderAmount {
|
||||
_10sats: Sats::_10,
|
||||
_100sats: Sats::_100,
|
||||
_1k_sats: Sats::_1K,
|
||||
@@ -22,8 +22,8 @@ pub const LT_AMOUNT_THRESHOLDS: ByLowerThanAmount<Sats> = ByLowerThanAmount {
|
||||
_100k_btc: Sats::_100K_BTC,
|
||||
};
|
||||
|
||||
/// Lower-than amount names
|
||||
pub const LT_AMOUNT_NAMES: ByLowerThanAmount<CohortName> = ByLowerThanAmount {
|
||||
/// Under-amount names
|
||||
pub const UNDER_AMOUNT_NAMES: UnderAmount<CohortName> = UnderAmount {
|
||||
_10sats: CohortName::new("under_10sats", "<10 sats", "Under 10 Sats"),
|
||||
_100sats: CohortName::new("under_100sats", "<100 sats", "Under 100 Sats"),
|
||||
_1k_sats: CohortName::new("under_1k_sats", "<1k sats", "Under 1K Sats"),
|
||||
@@ -39,25 +39,25 @@ pub const LT_AMOUNT_NAMES: ByLowerThanAmount<CohortName> = ByLowerThanAmount {
|
||||
_100k_btc: CohortName::new("under_100k_btc", "<100k BTC", "Under 100K BTC"),
|
||||
};
|
||||
|
||||
/// Lower-than amount filters
|
||||
pub const LT_AMOUNT_FILTERS: ByLowerThanAmount<Filter> = ByLowerThanAmount {
|
||||
_10sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10sats)),
|
||||
_100sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._100sats)),
|
||||
_1k_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._1k_sats)),
|
||||
_10k_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10k_sats)),
|
||||
_100k_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._100k_sats)),
|
||||
_1m_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._1m_sats)),
|
||||
_10m_sats: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10m_sats)),
|
||||
_1btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._1btc)),
|
||||
_10btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10btc)),
|
||||
_100btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._100btc)),
|
||||
_1k_btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._1k_btc)),
|
||||
_10k_btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._10k_btc)),
|
||||
_100k_btc: Filter::Amount(AmountFilter::LowerThan(LT_AMOUNT_THRESHOLDS._100k_btc)),
|
||||
/// Under-amount filters
|
||||
pub const UNDER_AMOUNT_FILTERS: UnderAmount<Filter> = UnderAmount {
|
||||
_10sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10sats)),
|
||||
_100sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._100sats)),
|
||||
_1k_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._1k_sats)),
|
||||
_10k_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10k_sats)),
|
||||
_100k_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._100k_sats)),
|
||||
_1m_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._1m_sats)),
|
||||
_10m_sats: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10m_sats)),
|
||||
_1btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._1btc)),
|
||||
_10btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10btc)),
|
||||
_100btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._100btc)),
|
||||
_1k_btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._1k_btc)),
|
||||
_10k_btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._10k_btc)),
|
||||
_100k_btc: Filter::Amount(AmountFilter::LowerThan(UNDER_AMOUNT_THRESHOLDS._100k_btc)),
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Traversable, Serialize)]
|
||||
pub struct ByLowerThanAmount<T> {
|
||||
pub struct UnderAmount<T> {
|
||||
pub _10sats: T,
|
||||
pub _100sats: T,
|
||||
pub _1k_sats: T,
|
||||
@@ -73,19 +73,19 @@ pub struct ByLowerThanAmount<T> {
|
||||
pub _100k_btc: T,
|
||||
}
|
||||
|
||||
impl ByLowerThanAmount<CohortName> {
|
||||
impl UnderAmount<CohortName> {
|
||||
pub const fn names() -> &'static Self {
|
||||
<_AMOUNT_NAMES
|
||||
&UNDER_AMOUNT_NAMES
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ByLowerThanAmount<T> {
|
||||
impl<T> UnderAmount<T> {
|
||||
pub fn new<F>(mut create: F) -> Self
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> T,
|
||||
{
|
||||
let f = LT_AMOUNT_FILTERS;
|
||||
let n = LT_AMOUNT_NAMES;
|
||||
let f = UNDER_AMOUNT_FILTERS;
|
||||
let n = UNDER_AMOUNT_NAMES;
|
||||
Self {
|
||||
_10sats: create(f._10sats.clone(), n._10sats.id),
|
||||
_100sats: create(f._100sats.clone(), n._100sats.id),
|
||||
@@ -107,8 +107,8 @@ impl<T> ByLowerThanAmount<T> {
|
||||
where
|
||||
F: FnMut(Filter, &'static str) -> Result<T, E>,
|
||||
{
|
||||
let f = LT_AMOUNT_FILTERS;
|
||||
let n = LT_AMOUNT_NAMES;
|
||||
let f = UNDER_AMOUNT_FILTERS;
|
||||
let n = UNDER_AMOUNT_NAMES;
|
||||
Ok(Self {
|
||||
_10sats: create(f._10sats.clone(), n._10sats.id)?,
|
||||
_100sats: create(f._100sats.clone(), n._100sats.id)?,
|
||||
@@ -3,17 +3,17 @@ use std::ops::{Add, AddAssign};
|
||||
use brk_traversable::Traversable;
|
||||
|
||||
#[derive(Default, Clone, Debug, Traversable)]
|
||||
pub struct ByUnspendableType<T> {
|
||||
pub struct UnspendableType<T> {
|
||||
pub opreturn: T,
|
||||
}
|
||||
|
||||
impl<T> ByUnspendableType<T> {
|
||||
impl<T> UnspendableType<T> {
|
||||
pub fn as_vec(&self) -> [&T; 1] {
|
||||
[&self.opreturn]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Add for ByUnspendableType<T>
|
||||
impl<T> Add for UnspendableType<T>
|
||||
where
|
||||
T: Add<Output = T>,
|
||||
{
|
||||
@@ -25,7 +25,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AddAssign for ByUnspendableType<T>
|
||||
impl<T> AddAssign for UnspendableType<T>
|
||||
where
|
||||
T: AddAssign,
|
||||
{
|
||||
@@ -2,23 +2,23 @@ use brk_traversable::Traversable;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::{
|
||||
ByAgeRange, ByAmountRange, ByEpoch, ByGreatEqualAmount, ByLowerThanAmount, ByMaxAge, ByMinAge,
|
||||
ByClass, BySpendableType, ByTerm, Filter,
|
||||
AgeRange, AmountRange, ByEpoch, OverAmount, UnderAmount, UnderAge, OverAge,
|
||||
Class, SpendableType, ByTerm, Filter,
|
||||
};
|
||||
|
||||
#[derive(Default, Clone, Traversable)]
|
||||
pub struct UTXOGroups<T> {
|
||||
pub all: T,
|
||||
pub age_range: ByAgeRange<T>,
|
||||
pub age_range: AgeRange<T>,
|
||||
pub epoch: ByEpoch<T>,
|
||||
pub class: ByClass<T>,
|
||||
pub min_age: ByMinAge<T>,
|
||||
pub ge_amount: ByGreatEqualAmount<T>,
|
||||
pub amount_range: ByAmountRange<T>,
|
||||
pub class: Class<T>,
|
||||
pub over_age: OverAge<T>,
|
||||
pub over_amount: OverAmount<T>,
|
||||
pub amount_range: AmountRange<T>,
|
||||
pub term: ByTerm<T>,
|
||||
pub type_: BySpendableType<T>,
|
||||
pub max_age: ByMaxAge<T>,
|
||||
pub lt_amount: ByLowerThanAmount<T>,
|
||||
pub type_: SpendableType<T>,
|
||||
pub under_age: UnderAge<T>,
|
||||
pub under_amount: UnderAmount<T>,
|
||||
}
|
||||
|
||||
impl<T> UTXOGroups<T> {
|
||||
@@ -28,16 +28,16 @@ impl<T> UTXOGroups<T> {
|
||||
{
|
||||
Self {
|
||||
all: create(Filter::All, ""),
|
||||
age_range: ByAgeRange::new(&mut create),
|
||||
age_range: AgeRange::new(&mut create),
|
||||
epoch: ByEpoch::new(&mut create),
|
||||
class: ByClass::new(&mut create),
|
||||
min_age: ByMinAge::new(&mut create),
|
||||
ge_amount: ByGreatEqualAmount::new(&mut create),
|
||||
amount_range: ByAmountRange::new(&mut create),
|
||||
class: Class::new(&mut create),
|
||||
over_age: OverAge::new(&mut create),
|
||||
over_amount: OverAmount::new(&mut create),
|
||||
amount_range: AmountRange::new(&mut create),
|
||||
term: ByTerm::new(&mut create),
|
||||
type_: BySpendableType::new(&mut create),
|
||||
max_age: ByMaxAge::new(&mut create),
|
||||
lt_amount: ByLowerThanAmount::new(&mut create),
|
||||
type_: SpendableType::new(&mut create),
|
||||
under_age: UnderAge::new(&mut create),
|
||||
under_amount: UnderAmount::new(&mut create),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,14 +45,14 @@ impl<T> UTXOGroups<T> {
|
||||
[&self.all]
|
||||
.into_iter()
|
||||
.chain(self.term.iter())
|
||||
.chain(self.max_age.iter())
|
||||
.chain(self.min_age.iter())
|
||||
.chain(self.ge_amount.iter())
|
||||
.chain(self.under_age.iter())
|
||||
.chain(self.over_age.iter())
|
||||
.chain(self.over_amount.iter())
|
||||
.chain(self.age_range.iter())
|
||||
.chain(self.epoch.iter())
|
||||
.chain(self.class.iter())
|
||||
.chain(self.amount_range.iter())
|
||||
.chain(self.lt_amount.iter())
|
||||
.chain(self.under_amount.iter())
|
||||
.chain(self.type_.iter())
|
||||
}
|
||||
|
||||
@@ -60,14 +60,14 @@ impl<T> UTXOGroups<T> {
|
||||
[&mut self.all]
|
||||
.into_iter()
|
||||
.chain(self.term.iter_mut())
|
||||
.chain(self.max_age.iter_mut())
|
||||
.chain(self.min_age.iter_mut())
|
||||
.chain(self.ge_amount.iter_mut())
|
||||
.chain(self.under_age.iter_mut())
|
||||
.chain(self.over_age.iter_mut())
|
||||
.chain(self.over_amount.iter_mut())
|
||||
.chain(self.age_range.iter_mut())
|
||||
.chain(self.epoch.iter_mut())
|
||||
.chain(self.class.iter_mut())
|
||||
.chain(self.amount_range.iter_mut())
|
||||
.chain(self.lt_amount.iter_mut())
|
||||
.chain(self.under_amount.iter_mut())
|
||||
.chain(self.type_.iter_mut())
|
||||
}
|
||||
|
||||
@@ -78,14 +78,14 @@ impl<T> UTXOGroups<T> {
|
||||
[&mut self.all]
|
||||
.into_par_iter()
|
||||
.chain(self.term.par_iter_mut())
|
||||
.chain(self.max_age.par_iter_mut())
|
||||
.chain(self.min_age.par_iter_mut())
|
||||
.chain(self.ge_amount.par_iter_mut())
|
||||
.chain(self.under_age.par_iter_mut())
|
||||
.chain(self.over_age.par_iter_mut())
|
||||
.chain(self.over_amount.par_iter_mut())
|
||||
.chain(self.age_range.par_iter_mut())
|
||||
.chain(self.epoch.par_iter_mut())
|
||||
.chain(self.class.par_iter_mut())
|
||||
.chain(self.amount_range.par_iter_mut())
|
||||
.chain(self.lt_amount.par_iter_mut())
|
||||
.chain(self.under_amount.par_iter_mut())
|
||||
.chain(self.type_.par_iter_mut())
|
||||
}
|
||||
|
||||
@@ -123,10 +123,10 @@ impl<T> UTXOGroups<T> {
|
||||
[&mut self.all]
|
||||
.into_iter()
|
||||
.chain(self.term.iter_mut())
|
||||
.chain(self.max_age.iter_mut())
|
||||
.chain(self.min_age.iter_mut())
|
||||
.chain(self.lt_amount.iter_mut())
|
||||
.chain(self.ge_amount.iter_mut())
|
||||
.chain(self.under_age.iter_mut())
|
||||
.chain(self.over_age.iter_mut())
|
||||
.chain(self.under_amount.iter_mut())
|
||||
.chain(self.over_amount.iter_mut())
|
||||
}
|
||||
|
||||
/// Iterator over aggregate cohorts (all, sth, lth) that compute values from sub-cohorts.
|
||||
|
||||
Reference in New Issue
Block a user