Files
brk/crates/brk_computer/src/stateful/common.rs
2025-12-03 19:33:08 +01:00

2356 lines
99 KiB
Rust

use brk_error::{Error, Result};
use brk_grouper::{CohortContext, Filter};
use brk_traversable::Traversable;
use brk_types::{
Bitcoin, DateIndex, Dollars, Height, Sats, StoredF32, StoredF64, StoredU64, Version,
};
use vecdb::{
AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, ImportableVec,
IterableCloneableVec, IterableVec, PcoVec, TypedVecIterator,
};
use crate::{
Indexes,
grouped::{
ComputedHeightValueVecs, ComputedRatioVecsFromDateIndex, ComputedValueVecsFromDateIndex,
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight,
PricePercentiles, Source, VecBuilderOptions,
},
indexes, price,
states::CohortState,
utils::OptionExt,
};
#[derive(Clone, Traversable)]
pub struct Vecs {
#[traversable(skip)]
pub filter: Filter,
// Cumulative
pub height_to_realized_cap: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_supply: EagerVec<PcoVec<Height, Sats>>,
pub height_to_utxo_count: EagerVec<PcoVec<Height, StoredU64>>,
// Single
pub dateindex_to_supply_in_loss: Option<EagerVec<PcoVec<DateIndex, Sats>>>,
pub dateindex_to_supply_in_profit: Option<EagerVec<PcoVec<DateIndex, Sats>>>,
pub dateindex_to_unrealized_loss: Option<EagerVec<PcoVec<DateIndex, Dollars>>>,
pub dateindex_to_unrealized_profit: Option<EagerVec<PcoVec<DateIndex, Dollars>>>,
pub height_to_adjusted_value_created: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_adjusted_value_destroyed: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_max_price_paid: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_min_price_paid: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_realized_loss: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_realized_profit: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_supply_in_loss: Option<EagerVec<PcoVec<Height, Sats>>>,
pub height_to_supply_in_profit: Option<EagerVec<PcoVec<Height, Sats>>>,
pub height_to_unrealized_loss: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_unrealized_profit: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_value_created: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_value_destroyed: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub height_to_sent: EagerVec<PcoVec<Height, Sats>>,
pub height_to_satblocks_destroyed: EagerVec<PcoVec<Height, Sats>>,
pub height_to_satdays_destroyed: EagerVec<PcoVec<Height, Sats>>,
pub indexes_to_sent: ComputedValueVecsFromHeight,
pub indexes_to_coinblocks_destroyed: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_coindays_destroyed: ComputedVecsFromHeight<StoredF64>,
pub dateindex_to_sopr: Option<EagerVec<PcoVec<DateIndex, StoredF64>>>,
pub dateindex_to_sopr_7d_ema: Option<EagerVec<PcoVec<DateIndex, StoredF64>>>,
pub dateindex_to_sopr_30d_ema: Option<EagerVec<PcoVec<DateIndex, StoredF64>>>,
pub dateindex_to_adjusted_sopr: Option<EagerVec<PcoVec<DateIndex, StoredF64>>>,
pub dateindex_to_adjusted_sopr_7d_ema: Option<EagerVec<PcoVec<DateIndex, StoredF64>>>,
pub dateindex_to_adjusted_sopr_30d_ema: Option<EagerVec<PcoVec<DateIndex, StoredF64>>>,
pub indexes_to_realized_cap_30d_delta: Option<ComputedVecsFromDateIndex<Dollars>>,
pub dateindex_to_sell_side_risk_ratio: Option<EagerVec<PcoVec<DateIndex, StoredF32>>>,
pub dateindex_to_sell_side_risk_ratio_7d_ema: Option<EagerVec<PcoVec<DateIndex, StoredF32>>>,
pub dateindex_to_sell_side_risk_ratio_30d_ema: Option<EagerVec<PcoVec<DateIndex, StoredF32>>>,
pub indexes_to_adjusted_value_created: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_adjusted_value_destroyed: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_neg_realized_loss: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_net_realized_pnl: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_realized_cap: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_realized_loss: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_realized_price: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_realized_price_extra: Option<ComputedRatioVecsFromDateIndex>,
pub indexes_to_realized_profit: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_realized_value: Option<ComputedVecsFromHeight<Dollars>>,
pub height_to_supply_value: ComputedHeightValueVecs,
pub indexes_to_supply: ComputedValueVecsFromDateIndex,
pub indexes_to_utxo_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_value_created: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_value_destroyed: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_unrealized_profit: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_unrealized_loss: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_total_unrealized_pnl: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub indexes_to_total_unrealized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_total_realized_pnl: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub indexes_to_total_realized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_min_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_max_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
pub price_percentiles: Option<PricePercentiles>,
pub height_to_supply_half_value: ComputedHeightValueVecs,
pub indexes_to_supply_half: ComputedValueVecsFromDateIndex,
pub height_to_neg_unrealized_loss: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub indexes_to_neg_unrealized_loss: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_net_unrealized_pnl: Option<EagerVec<PcoVec<Height, Dollars>>>,
pub indexes_to_net_unrealized_pnl: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_unrealized_profit_rel_to_market_cap: Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_unrealized_loss_rel_to_market_cap: Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_neg_unrealized_loss_rel_to_market_cap:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_net_unrealized_pnl_rel_to_market_cap: Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub indexes_to_unrealized_profit_rel_to_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_unrealized_loss_rel_to_market_cap: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_neg_unrealized_loss_rel_to_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_net_unrealized_pnl_rel_to_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub height_to_unrealized_profit_rel_to_own_market_cap:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_unrealized_loss_rel_to_own_market_cap:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_neg_unrealized_loss_rel_to_own_market_cap:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_net_unrealized_pnl_rel_to_own_market_cap:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub indexes_to_unrealized_profit_rel_to_own_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_unrealized_loss_rel_to_own_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_neg_unrealized_loss_rel_to_own_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_net_unrealized_pnl_rel_to_own_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub height_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
Option<EagerVec<PcoVec<Height, StoredF32>>>,
pub indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_realized_cap_rel_to_own_market_cap: Option<ComputedVecsFromHeight<StoredF32>>,
pub indexes_to_realized_profit_rel_to_realized_cap: Option<ComputedVecsFromHeight<StoredF32>>,
pub indexes_to_realized_loss_rel_to_realized_cap: Option<ComputedVecsFromHeight<StoredF32>>,
pub indexes_to_net_realized_pnl_rel_to_realized_cap: Option<ComputedVecsFromHeight<StoredF32>>,
pub height_to_supply_in_loss_value: Option<ComputedHeightValueVecs>,
pub height_to_supply_in_profit_value: Option<ComputedHeightValueVecs>,
pub indexes_to_supply_in_loss: Option<ComputedValueVecsFromDateIndex>,
pub indexes_to_supply_in_profit: Option<ComputedValueVecsFromDateIndex>,
pub height_to_supply_in_loss_rel_to_own_supply: Option<EagerVec<PcoVec<Height, StoredF64>>>,
pub height_to_supply_in_profit_rel_to_own_supply: Option<EagerVec<PcoVec<Height, StoredF64>>>,
pub indexes_to_supply_in_loss_rel_to_own_supply: Option<ComputedVecsFromDateIndex<StoredF64>>,
pub indexes_to_supply_in_profit_rel_to_own_supply: Option<ComputedVecsFromDateIndex<StoredF64>>,
pub indexes_to_supply_rel_to_circulating_supply: Option<ComputedVecsFromHeight<StoredF64>>,
pub height_to_supply_in_loss_rel_to_circulating_supply:
Option<EagerVec<PcoVec<Height, StoredF64>>>,
pub height_to_supply_in_profit_rel_to_circulating_supply:
Option<EagerVec<PcoVec<Height, StoredF64>>>,
pub indexes_to_supply_in_loss_rel_to_circulating_supply:
Option<ComputedVecsFromDateIndex<StoredF64>>,
pub indexes_to_supply_in_profit_rel_to_circulating_supply:
Option<ComputedVecsFromDateIndex<StoredF64>>,
pub indexes_to_net_realized_pnl_cumulative_30d_delta:
Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub dateindex_to_realized_profit_to_loss_ratio: Option<EagerVec<PcoVec<DateIndex, StoredF64>>>,
}
impl Vecs {
#[allow(clippy::too_many_arguments)]
pub fn forced_import(
db: &Database,
filter: Filter,
context: CohortContext,
parent_version: Version,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let compute_dollars = price.is_some();
let extended = filter.is_extended(context);
let compute_rel_to_all = filter.compute_rel_to_all();
let compute_adjusted = filter.compute_adjusted(context);
let version = parent_version + Version::ZERO;
let name_prefix = filter.to_full_name(context);
let suffix = |s: &str| {
if name_prefix.is_empty() {
s.to_string()
} else {
format!("{name_prefix}_{s}")
}
};
// Helper macros for imports
macro_rules! eager {
($idx:ty, $val:ty, $name:expr, $v:expr) => {
EagerVec::<PcoVec<$idx, $val>>::forced_import(db, &suffix($name), version + $v).unwrap()
};
}
macro_rules! computed_h {
($name:expr, $source:expr, $v:expr, $opts:expr $(,)?) => {
ComputedVecsFromHeight::forced_import(db, &suffix($name), $source, version + $v, indexes, $opts).unwrap()
};
}
macro_rules! computed_di {
($name:expr, $source:expr, $v:expr, $opts:expr $(,)?) => {
ComputedVecsFromDateIndex::forced_import(db, &suffix($name), $source, version + $v, indexes, $opts).unwrap()
};
}
// Common option patterns
let v0 = Version::ZERO;
let v1 = Version::ONE;
let v2 = Version::TWO;
let v3 = Version::new(3);
let last = || VecBuilderOptions::default().add_last();
let sum = || VecBuilderOptions::default().add_sum();
let sum_cum = || VecBuilderOptions::default().add_sum().add_cumulative();
// Pre-create dateindex vecs that are used in computed vecs
let dateindex_to_supply_in_profit =
compute_dollars.then(|| eager!(DateIndex, Sats,"supply_in_profit", v0));
let dateindex_to_supply_in_loss = compute_dollars.then(|| eager!(DateIndex, Sats,"supply_in_loss", v0));
let dateindex_to_unrealized_profit =
compute_dollars.then(|| eager!(DateIndex, Dollars,"unrealized_profit", v0));
let dateindex_to_unrealized_loss =
compute_dollars.then(|| eager!(DateIndex, Dollars,"unrealized_loss", v0));
Ok(Self {
filter,
// Supply & UTXO count (always computed)
height_to_supply: EagerVec::forced_import(db, &suffix("supply"), version + v0)?,
height_to_supply_value: ComputedHeightValueVecs::forced_import(
db,
&suffix("supply"),
Source::None,
version + v0,
compute_dollars,
)?,
indexes_to_supply: ComputedValueVecsFromDateIndex::forced_import(
db,
&suffix("supply"),
Source::Compute,
version + v1,
last(),
compute_dollars,
indexes,
)?,
height_to_utxo_count: EagerVec::forced_import(db, &suffix("utxo_count"), version + v0)?,
indexes_to_utxo_count: computed_h!("utxo_count", Source::None, v0, last()),
height_to_supply_half_value: ComputedHeightValueVecs::forced_import(
db,
&suffix("supply_half"),
Source::Compute,
version + v0,
compute_dollars,
)?,
indexes_to_supply_half: ComputedValueVecsFromDateIndex::forced_import(
db,
&suffix("supply_half"),
Source::Compute,
version + v0,
last(),
compute_dollars,
indexes,
)?,
// Sent & destroyed (always computed)
height_to_sent: EagerVec::forced_import(db, &suffix("sent"), version + v0)?,
height_to_satblocks_destroyed: EagerVec::forced_import(
db,
&suffix("satblocks_destroyed"),
version + v0,
)?,
height_to_satdays_destroyed: EagerVec::forced_import(
db,
&suffix("satdays_destroyed"),
version + v0,
)?,
indexes_to_sent: ComputedValueVecsFromHeight::forced_import(
db,
&suffix("sent"),
Source::Compute,
version + v0,
sum(),
compute_dollars,
indexes,
)?,
indexes_to_coinblocks_destroyed: computed_h!(
"coinblocks_destroyed",
Source::Compute,
v2,
sum_cum(),
),
indexes_to_coindays_destroyed: computed_h!(
"coindays_destroyed",
Source::Compute,
v2,
sum_cum(),
),
// Realized cap & related (conditional on compute_dollars)
height_to_realized_cap: compute_dollars.then(|| eager!(Height, Dollars,"realized_cap", v0)),
indexes_to_realized_cap: compute_dollars
.then(|| computed_h!("realized_cap", Source::None, v0, last())),
indexes_to_realized_price: compute_dollars
.then(|| computed_h!("realized_price", Source::Compute, v0, last())),
indexes_to_realized_price_extra: compute_dollars.then(|| {
ComputedRatioVecsFromDateIndex::forced_import(
db,
&suffix("realized_price"),
Source::None,
version + v0,
indexes,
extended,
)
.unwrap()
}),
indexes_to_realized_cap_rel_to_own_market_cap: (compute_dollars && extended).then(|| {
computed_h!("realized_cap_rel_to_own_market_cap", Source::Compute, v0, last())
}),
indexes_to_realized_cap_30d_delta: compute_dollars
.then(|| computed_di!("realized_cap_30d_delta", Source::Compute, v0, last())),
// Realized profit & loss
height_to_realized_profit: compute_dollars.then(|| eager!(Height, Dollars,"realized_profit", v0)),
indexes_to_realized_profit: compute_dollars
.then(|| computed_h!("realized_profit", Source::None, v0, sum_cum())),
height_to_realized_loss: compute_dollars.then(|| eager!(Height, Dollars,"realized_loss", v0)),
indexes_to_realized_loss: compute_dollars
.then(|| computed_h!("realized_loss", Source::None, v0, sum_cum())),
indexes_to_neg_realized_loss: compute_dollars
.then(|| computed_h!("neg_realized_loss", Source::Compute, v1, sum_cum())),
indexes_to_net_realized_pnl: compute_dollars
.then(|| computed_h!("net_realized_pnl", Source::Compute, v0, sum_cum())),
indexes_to_realized_value: compute_dollars
.then(|| computed_h!("realized_value", Source::Compute, v0, sum())),
indexes_to_realized_profit_rel_to_realized_cap: compute_dollars
.then(|| computed_h!("realized_profit_rel_to_realized_cap", Source::Compute, v0, sum())),
indexes_to_realized_loss_rel_to_realized_cap: compute_dollars
.then(|| computed_h!("realized_loss_rel_to_realized_cap", Source::Compute, v0, sum())),
indexes_to_net_realized_pnl_rel_to_realized_cap: compute_dollars
.then(|| computed_h!("net_realized_pnl_rel_to_realized_cap", Source::Compute, v1, sum())),
height_to_total_realized_pnl: compute_dollars.then(|| eager!(Height, Dollars,"total_realized_pnl", v0)),
indexes_to_total_realized_pnl: compute_dollars
.then(|| computed_di!("total_realized_pnl", Source::Compute, v1, sum())),
dateindex_to_realized_profit_to_loss_ratio: (compute_dollars && extended)
.then(|| eager!(DateIndex, StoredF64,"realized_profit_to_loss_ratio", v1)),
// Value created & destroyed
height_to_value_created: compute_dollars.then(|| eager!(Height, Dollars,"value_created", v0)),
indexes_to_value_created: compute_dollars
.then(|| computed_h!("value_created", Source::None, v0, sum())),
height_to_value_destroyed: compute_dollars.then(|| eager!(Height, Dollars,"value_destroyed", v0)),
indexes_to_value_destroyed: compute_dollars
.then(|| computed_h!("value_destroyed", Source::None, v0, sum())),
height_to_adjusted_value_created: (compute_dollars && compute_adjusted)
.then(|| eager!(Height, Dollars,"adjusted_value_created", v0)),
indexes_to_adjusted_value_created: (compute_dollars && compute_adjusted)
.then(|| computed_h!("adjusted_value_created", Source::None, v0, sum())),
height_to_adjusted_value_destroyed: (compute_dollars && compute_adjusted)
.then(|| eager!(Height, Dollars,"adjusted_value_destroyed", v0)),
indexes_to_adjusted_value_destroyed: (compute_dollars && compute_adjusted)
.then(|| computed_h!("adjusted_value_destroyed", Source::None, v0, sum())),
// SOPR
dateindex_to_sopr: compute_dollars.then(|| eager!(DateIndex, StoredF64,"sopr", v1)),
dateindex_to_sopr_7d_ema: compute_dollars.then(|| eager!(DateIndex, StoredF64,"sopr_7d_ema", v1)),
dateindex_to_sopr_30d_ema: compute_dollars.then(|| eager!(DateIndex, StoredF64,"sopr_30d_ema", v1)),
dateindex_to_adjusted_sopr: (compute_dollars && compute_adjusted)
.then(|| eager!(DateIndex, StoredF64,"adjusted_sopr", v1)),
dateindex_to_adjusted_sopr_7d_ema: (compute_dollars && compute_adjusted)
.then(|| eager!(DateIndex, StoredF64,"adjusted_sopr_7d_ema", v1)),
dateindex_to_adjusted_sopr_30d_ema: (compute_dollars && compute_adjusted)
.then(|| eager!(DateIndex, StoredF64,"adjusted_sopr_30d_ema", v1)),
// Sell side risk ratio
dateindex_to_sell_side_risk_ratio: compute_dollars
.then(|| eager!(DateIndex, StoredF32,"sell_side_risk_ratio", v1)),
dateindex_to_sell_side_risk_ratio_7d_ema: compute_dollars
.then(|| eager!(DateIndex, StoredF32,"sell_side_risk_ratio_7d_ema", v1)),
dateindex_to_sell_side_risk_ratio_30d_ema: compute_dollars
.then(|| eager!(DateIndex, StoredF32,"sell_side_risk_ratio_30d_ema", v1)),
// Supply in profit/loss
height_to_supply_in_profit: compute_dollars.then(|| eager!(Height, Sats,"supply_in_profit", v0)),
indexes_to_supply_in_profit: compute_dollars.then(|| {
ComputedValueVecsFromDateIndex::forced_import(
db,
&suffix("supply_in_profit"),
dateindex_to_supply_in_profit.as_ref().map(|v| v.boxed_clone()).into(),
version + v0,
last(),
compute_dollars,
indexes,
)
.unwrap()
}),
height_to_supply_in_loss: compute_dollars.then(|| eager!(Height, Sats,"supply_in_loss", v0)),
indexes_to_supply_in_loss: compute_dollars.then(|| {
ComputedValueVecsFromDateIndex::forced_import(
db,
&suffix("supply_in_loss"),
dateindex_to_supply_in_loss.as_ref().map(|v| v.boxed_clone()).into(),
version + v0,
last(),
compute_dollars,
indexes,
)
.unwrap()
}),
height_to_supply_in_loss_value: compute_dollars.then(|| {
ComputedHeightValueVecs::forced_import(
db,
&suffix("supply_in_loss"),
Source::None,
version + v0,
compute_dollars,
)
.unwrap()
}),
height_to_supply_in_profit_value: compute_dollars.then(|| {
ComputedHeightValueVecs::forced_import(
db,
&suffix("supply_in_profit"),
Source::None,
version + v0,
compute_dollars,
)
.unwrap()
}),
height_to_supply_in_loss_rel_to_own_supply: compute_dollars
.then(|| eager!(Height, StoredF64,"supply_in_loss_rel_to_own_supply", v1)),
height_to_supply_in_profit_rel_to_own_supply: compute_dollars
.then(|| eager!(Height, StoredF64,"supply_in_profit_rel_to_own_supply", v1)),
indexes_to_supply_in_loss_rel_to_own_supply: compute_dollars
.then(|| computed_di!("supply_in_loss_rel_to_own_supply", Source::Compute, v1, last())),
indexes_to_supply_in_profit_rel_to_own_supply: compute_dollars
.then(|| computed_di!("supply_in_profit_rel_to_own_supply", Source::Compute, v1, last())),
indexes_to_supply_rel_to_circulating_supply: compute_rel_to_all
.then(|| computed_h!("supply_rel_to_circulating_supply", Source::Compute, v1, last())),
height_to_supply_in_loss_rel_to_circulating_supply: (compute_rel_to_all && compute_dollars)
.then(|| eager!(Height, StoredF64,"supply_in_loss_rel_to_circulating_supply", v1)),
height_to_supply_in_profit_rel_to_circulating_supply: (compute_rel_to_all && compute_dollars)
.then(|| eager!(Height, StoredF64,"supply_in_profit_rel_to_circulating_supply", v1)),
indexes_to_supply_in_loss_rel_to_circulating_supply: (compute_rel_to_all && compute_dollars)
.then(|| computed_di!("supply_in_loss_rel_to_circulating_supply", Source::Compute, v1, last())),
indexes_to_supply_in_profit_rel_to_circulating_supply: (compute_rel_to_all && compute_dollars)
.then(|| computed_di!("supply_in_profit_rel_to_circulating_supply", Source::Compute, v1, last())),
dateindex_to_supply_in_profit,
dateindex_to_supply_in_loss,
// Unrealized profit/loss
height_to_unrealized_profit: compute_dollars.then(|| eager!(Height, Dollars,"unrealized_profit", v0)),
indexes_to_unrealized_profit: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("unrealized_profit"),
dateindex_to_unrealized_profit.as_ref().map(|v| v.boxed_clone()).into(),
version + v0,
indexes,
last(),
)
.unwrap()
}),
height_to_unrealized_loss: compute_dollars.then(|| eager!(Height, Dollars,"unrealized_loss", v0)),
indexes_to_unrealized_loss: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
&suffix("unrealized_loss"),
dateindex_to_unrealized_loss.as_ref().map(|v| v.boxed_clone()).into(),
version + v0,
indexes,
last(),
)
.unwrap()
}),
dateindex_to_unrealized_profit,
dateindex_to_unrealized_loss,
height_to_total_unrealized_pnl: compute_dollars.then(|| eager!(Height, Dollars,"total_unrealized_pnl", v0)),
indexes_to_total_unrealized_pnl: compute_dollars
.then(|| computed_di!("total_unrealized_pnl", Source::Compute, v0, last())),
height_to_neg_unrealized_loss: compute_dollars.then(|| eager!(Height, Dollars,"neg_unrealized_loss", v0)),
indexes_to_neg_unrealized_loss: compute_dollars
.then(|| computed_di!("neg_unrealized_loss", Source::Compute, v0, last())),
height_to_net_unrealized_pnl: compute_dollars.then(|| eager!(Height, Dollars,"net_unrealized_pnl", v0)),
indexes_to_net_unrealized_pnl: compute_dollars
.then(|| computed_di!("net_unrealized_pnl", Source::Compute, v0, last())),
// Unrealized rel to market cap
height_to_unrealized_profit_rel_to_market_cap: compute_dollars
.then(|| eager!(Height, StoredF32,"unrealized_profit_rel_to_market_cap", v0)),
height_to_unrealized_loss_rel_to_market_cap: compute_dollars
.then(|| eager!(Height, StoredF32,"unrealized_loss_rel_to_market_cap", v0)),
height_to_neg_unrealized_loss_rel_to_market_cap: compute_dollars
.then(|| eager!(Height, StoredF32,"neg_unrealized_loss_rel_to_market_cap", v0)),
height_to_net_unrealized_pnl_rel_to_market_cap: compute_dollars
.then(|| eager!(Height, StoredF32,"net_unrealized_pnl_rel_to_market_cap", v1)),
indexes_to_unrealized_profit_rel_to_market_cap: compute_dollars
.then(|| computed_di!("unrealized_profit_rel_to_market_cap", Source::Compute, v1, last())),
indexes_to_unrealized_loss_rel_to_market_cap: compute_dollars
.then(|| computed_di!("unrealized_loss_rel_to_market_cap", Source::Compute, v1, last())),
indexes_to_neg_unrealized_loss_rel_to_market_cap: compute_dollars
.then(|| computed_di!("neg_unrealized_loss_rel_to_market_cap", Source::Compute, v1, last())),
indexes_to_net_unrealized_pnl_rel_to_market_cap: compute_dollars
.then(|| computed_di!("net_unrealized_pnl_rel_to_market_cap", Source::Compute, v1, last())),
// Unrealized rel to own market cap
height_to_unrealized_profit_rel_to_own_market_cap: (compute_dollars && extended && compute_rel_to_all)
.then(|| eager!(Height, StoredF32,"unrealized_profit_rel_to_own_market_cap", v1)),
height_to_unrealized_loss_rel_to_own_market_cap: (compute_dollars && extended && compute_rel_to_all)
.then(|| eager!(Height, StoredF32,"unrealized_loss_rel_to_own_market_cap", v1)),
height_to_neg_unrealized_loss_rel_to_own_market_cap: (compute_dollars && extended && compute_rel_to_all)
.then(|| eager!(Height, StoredF32,"neg_unrealized_loss_rel_to_own_market_cap", v1)),
height_to_net_unrealized_pnl_rel_to_own_market_cap: (compute_dollars && extended && compute_rel_to_all)
.then(|| eager!(Height, StoredF32,"net_unrealized_pnl_rel_to_own_market_cap", v2)),
indexes_to_unrealized_profit_rel_to_own_market_cap: (compute_dollars && extended && compute_rel_to_all)
.then(|| computed_di!("unrealized_profit_rel_to_own_market_cap", Source::Compute, v2, last())),
indexes_to_unrealized_loss_rel_to_own_market_cap: (compute_dollars && extended && compute_rel_to_all)
.then(|| computed_di!("unrealized_loss_rel_to_own_market_cap", Source::Compute, v2, last())),
indexes_to_neg_unrealized_loss_rel_to_own_market_cap: (compute_dollars && extended && compute_rel_to_all)
.then(|| computed_di!("neg_unrealized_loss_rel_to_own_market_cap", Source::Compute, v2, last())),
indexes_to_net_unrealized_pnl_rel_to_own_market_cap: (compute_dollars && extended && compute_rel_to_all)
.then(|| computed_di!("net_unrealized_pnl_rel_to_own_market_cap", Source::Compute, v2, last())),
// Unrealized rel to own total unrealized pnl
height_to_unrealized_profit_rel_to_own_total_unrealized_pnl: (compute_dollars && extended)
.then(|| eager!(Height, StoredF32,"unrealized_profit_rel_to_own_total_unrealized_pnl", v0)),
height_to_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars && extended)
.then(|| eager!(Height, StoredF32,"unrealized_loss_rel_to_own_total_unrealized_pnl", v0)),
height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars && extended)
.then(|| eager!(Height, StoredF32,"neg_unrealized_loss_rel_to_own_total_unrealized_pnl", v0)),
height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: (compute_dollars && extended)
.then(|| eager!(Height, StoredF32,"net_unrealized_pnl_rel_to_own_total_unrealized_pnl", v1)),
indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl: (compute_dollars && extended)
.then(|| computed_di!("unrealized_profit_rel_to_own_total_unrealized_pnl", Source::Compute, v1, last())),
indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars && extended)
.then(|| computed_di!("unrealized_loss_rel_to_own_total_unrealized_pnl", Source::Compute, v1, last())),
indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl: (compute_dollars && extended)
.then(|| computed_di!("neg_unrealized_loss_rel_to_own_total_unrealized_pnl", Source::Compute, v1, last())),
indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl: (compute_dollars && extended)
.then(|| computed_di!("net_unrealized_pnl_rel_to_own_total_unrealized_pnl", Source::Compute, v1, last())),
// Price paid
height_to_min_price_paid: compute_dollars.then(|| eager!(Height, Dollars,"min_price_paid", v0)),
height_to_max_price_paid: compute_dollars.then(|| eager!(Height, Dollars,"max_price_paid", v0)),
indexes_to_min_price_paid: compute_dollars
.then(|| computed_h!("min_price_paid", Source::None, v0, last())),
indexes_to_max_price_paid: compute_dollars
.then(|| computed_h!("max_price_paid", Source::None, v0, last())),
price_percentiles: (compute_dollars && extended).then(|| {
PricePercentiles::forced_import(db, &suffix(""), version + v0, indexes, true).unwrap()
}),
// Net realized pnl cumulative deltas
indexes_to_net_realized_pnl_cumulative_30d_delta: compute_dollars
.then(|| computed_di!("net_realized_pnl_cumulative_30d_delta", Source::Compute, v3, last())),
indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap: compute_dollars
.then(|| computed_di!("net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap", Source::Compute, v3, last())),
indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_market_cap: compute_dollars
.then(|| computed_di!("net_realized_pnl_cumulative_30d_delta_rel_to_market_cap", Source::Compute, v3, last())),
})
}
pub fn min_height_vecs_len(&self) -> usize {
[
self.height_to_supply.len(),
self.height_to_utxo_count.len(),
self.height_to_realized_cap
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_realized_profit
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_realized_loss
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_value_created
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_adjusted_value_created
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_value_destroyed
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_adjusted_value_destroyed
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_supply_in_profit
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_supply_in_loss
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_unrealized_profit
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_unrealized_loss
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_min_price_paid
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_max_price_paid
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_sent.len(),
self.height_to_satdays_destroyed.len(),
self.height_to_satblocks_destroyed.len(),
]
.into_iter()
.min()
.unwrap()
}
pub fn import_state(
&mut self,
starting_height: Height,
state: &mut CohortState,
) -> Result<Height> {
if let Some(mut prev_height) = starting_height.decremented() {
if self.height_to_realized_cap.as_mut().is_some() {
prev_height = state.import_at_or_before(prev_height)?;
}
state.supply.value = self.height_to_supply.into_iter().get_unwrap(prev_height);
state.supply.utxo_count = *self
.height_to_utxo_count
.into_iter()
.get_unwrap(prev_height);
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
state.realized.um().cap =
height_to_realized_cap.into_iter().get_unwrap(prev_height);
}
Ok(prev_height.incremented())
} else {
Err(Error::Str("Unset"))
}
}
pub fn validate_computed_versions(&mut self, base_version: Version) -> Result<()> {
self.height_to_supply.validate_computed_version_or_reset(
base_version + self.height_to_supply.inner_version(),
)?;
self.height_to_utxo_count
.validate_computed_version_or_reset(
base_version + self.height_to_utxo_count.inner_version(),
)?;
self.height_to_sent
.validate_computed_version_or_reset(
base_version + self.height_to_sent.inner_version(),
)?;
self.height_to_satblocks_destroyed
.validate_computed_version_or_reset(
base_version + self.height_to_satblocks_destroyed.inner_version(),
)?;
self.height_to_satdays_destroyed
.validate_computed_version_or_reset(
base_version + self.height_to_satdays_destroyed.inner_version(),
)?;
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut().as_mut() {
height_to_realized_cap.validate_computed_version_or_reset(
base_version + height_to_realized_cap.inner_version(),
)?;
let height_to_realized_profit_inner_version = self
.height_to_realized_profit
.u()
.inner_version();
self.height_to_realized_profit
.um()
.validate_computed_version_or_reset(
base_version + height_to_realized_profit_inner_version,
)?;
let height_to_realized_loss_inner_version = self
.height_to_realized_loss
.u()
.inner_version();
self.height_to_realized_loss
.um()
.validate_computed_version_or_reset(
base_version + height_to_realized_loss_inner_version,
)?;
let height_to_value_created_inner_version = self
.height_to_value_created
.u()
.inner_version();
self.height_to_value_created
.um()
.validate_computed_version_or_reset(
base_version + height_to_value_created_inner_version,
)?;
let height_to_value_destroyed_inner_version = self
.height_to_value_destroyed
.u()
.inner_version();
self.height_to_value_destroyed
.um()
.validate_computed_version_or_reset(
base_version + height_to_value_destroyed_inner_version,
)?;
let height_to_supply_in_profit_inner_version = self
.height_to_supply_in_profit
.u()
.inner_version();
self.height_to_supply_in_profit
.um()
.validate_computed_version_or_reset(
base_version + height_to_supply_in_profit_inner_version,
)?;
let height_to_supply_in_loss_inner_version = self
.height_to_supply_in_loss
.u()
.inner_version();
self.height_to_supply_in_loss
.um()
.validate_computed_version_or_reset(
base_version + height_to_supply_in_loss_inner_version,
)?;
let height_to_unrealized_profit_inner_version = self
.height_to_unrealized_profit
.u()
.inner_version();
self.height_to_unrealized_profit
.um()
.validate_computed_version_or_reset(
base_version + height_to_unrealized_profit_inner_version,
)?;
let height_to_unrealized_loss_inner_version = self
.height_to_unrealized_loss
.u()
.inner_version();
self.height_to_unrealized_loss
.um()
.validate_computed_version_or_reset(
base_version + height_to_unrealized_loss_inner_version,
)?;
let dateindex_to_supply_in_profit_inner_version = self
.dateindex_to_supply_in_profit
.u()
.inner_version();
self.dateindex_to_supply_in_profit
.um()
.validate_computed_version_or_reset(
base_version + dateindex_to_supply_in_profit_inner_version,
)?;
let dateindex_to_supply_in_loss_inner_version = self
.dateindex_to_supply_in_loss
.u()
.inner_version();
self.dateindex_to_supply_in_loss
.um()
.validate_computed_version_or_reset(
base_version + dateindex_to_supply_in_loss_inner_version,
)?;
let dateindex_to_unrealized_profit_inner_version = self
.dateindex_to_unrealized_profit
.u()
.inner_version();
self.dateindex_to_unrealized_profit
.um()
.validate_computed_version_or_reset(
base_version + dateindex_to_unrealized_profit_inner_version,
)?;
let dateindex_to_unrealized_loss_inner_version = self
.dateindex_to_unrealized_loss
.u()
.inner_version();
self.dateindex_to_unrealized_loss
.um()
.validate_computed_version_or_reset(
base_version + dateindex_to_unrealized_loss_inner_version,
)?;
let height_to_min_price_paid_inner_version = self
.height_to_min_price_paid
.u()
.inner_version();
self.height_to_min_price_paid
.um()
.validate_computed_version_or_reset(
base_version + height_to_min_price_paid_inner_version,
)?;
let height_to_max_price_paid_inner_version = self
.height_to_max_price_paid
.u()
.inner_version();
self.height_to_max_price_paid
.um()
.validate_computed_version_or_reset(
base_version + height_to_max_price_paid_inner_version,
)?;
if self.height_to_adjusted_value_created.is_some() {
let height_to_adjusted_value_created_inner_version = self
.height_to_adjusted_value_created
.u()
.inner_version();
self.height_to_adjusted_value_created
.um()
.validate_computed_version_or_reset(
base_version + height_to_adjusted_value_created_inner_version,
)?;
let height_to_adjusted_value_destroyed_inner_version = self
.height_to_adjusted_value_destroyed
.u()
.inner_version();
self.height_to_adjusted_value_destroyed
.um()
.validate_computed_version_or_reset(
base_version + height_to_adjusted_value_destroyed_inner_version,
)?;
}
}
Ok(())
}
pub fn truncate_push(&mut self, height: Height, state: &CohortState) -> Result<()> {
self.height_to_supply
.truncate_push(height, state.supply.value)?;
self.height_to_utxo_count
.truncate_push(height, StoredU64::from(state.supply.utxo_count))?;
self.height_to_sent.truncate_push(height, state.sent)?;
self.height_to_satblocks_destroyed
.truncate_push(height, state.satblocks_destroyed)?;
self.height_to_satdays_destroyed
.truncate_push(height, state.satdays_destroyed)?;
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
let realized = state.realized.as_ref().unwrap_or_else(|| {
dbg!((&state.realized, &state.supply));
panic!();
});
height_to_realized_cap.truncate_push(height, realized.cap)?;
self.height_to_realized_profit
.um()
.truncate_push(height, realized.profit)?;
self.height_to_realized_loss
.um()
.truncate_push(height, realized.loss)?;
self.height_to_value_created
.um()
.truncate_push(height, realized.value_created)?;
self.height_to_value_destroyed
.um()
.truncate_push(height, realized.value_destroyed)?;
if self.height_to_adjusted_value_created.is_some() {
self.height_to_adjusted_value_created
.um()
.truncate_push(height, realized.adj_value_created)?;
self.height_to_adjusted_value_destroyed
.um()
.truncate_push(height, realized.adj_value_destroyed)?;
}
}
Ok(())
}
pub fn compute_then_truncate_push_unrealized_states(
&mut self,
height: Height,
height_price: Option<Dollars>,
dateindex: Option<DateIndex>,
date_price: Option<Option<Dollars>>,
state: &CohortState,
) -> Result<()> {
if let Some(height_price) = height_price {
self.height_to_min_price_paid
.um()
.truncate_push(
height,
state
.price_to_amount_first_key_value()
.map(|(&dollars, _)| dollars)
.unwrap_or(Dollars::NAN),
)?;
self.height_to_max_price_paid
.um()
.truncate_push(
height,
state
.price_to_amount_last_key_value()
.map(|(&dollars, _)| dollars)
.unwrap_or(Dollars::NAN),
)?;
let (height_unrealized_state, date_unrealized_state) =
state.compute_unrealized_states(height_price, date_price.unwrap());
self.height_to_supply_in_profit
.um()
.truncate_push(height, height_unrealized_state.supply_in_profit)?;
self.height_to_supply_in_loss
.um()
.truncate_push(height, height_unrealized_state.supply_in_loss)?;
self.height_to_unrealized_profit
.um()
.truncate_push(height, height_unrealized_state.unrealized_profit)?;
self.height_to_unrealized_loss
.um()
.truncate_push(height, height_unrealized_state.unrealized_loss)?;
if let Some(date_unrealized_state) = date_unrealized_state {
let dateindex = dateindex.unwrap();
self.dateindex_to_supply_in_profit
.um()
.truncate_push(dateindex, date_unrealized_state.supply_in_profit)?;
self.dateindex_to_supply_in_loss
.um()
.truncate_push(dateindex, date_unrealized_state.supply_in_loss)?;
self.dateindex_to_unrealized_profit
.um()
.truncate_push(dateindex, date_unrealized_state.unrealized_profit)?;
self.dateindex_to_unrealized_loss
.um()
.truncate_push(dateindex, date_unrealized_state.unrealized_loss)?;
}
// Compute and push price percentiles
if let Some(price_percentiles) = self.price_percentiles.as_mut() {
let percentile_prices = state.compute_percentile_prices();
price_percentiles.truncate_push(height, &percentile_prices)?;
}
}
Ok(())
}
pub fn safe_flush_stateful_vecs(
&mut self,
height: Height,
exit: &Exit,
state: &mut CohortState,
) -> Result<()> {
self.height_to_supply.safe_flush(exit)?;
self.height_to_utxo_count.safe_flush(exit)?;
self.height_to_sent.safe_flush(exit)?;
self.height_to_satdays_destroyed.safe_flush(exit)?;
self.height_to_satblocks_destroyed.safe_flush(exit)?;
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
height_to_realized_cap.safe_flush(exit)?;
self.height_to_realized_profit
.um()
.safe_flush(exit)?;
self.height_to_realized_loss
.um()
.safe_flush(exit)?;
self.height_to_value_created
.um()
.safe_flush(exit)?;
self.height_to_value_destroyed
.um()
.safe_flush(exit)?;
self.height_to_supply_in_profit
.um()
.safe_flush(exit)?;
self.height_to_supply_in_loss
.um()
.safe_flush(exit)?;
self.height_to_unrealized_profit
.um()
.safe_flush(exit)?;
self.height_to_unrealized_loss
.um()
.safe_flush(exit)?;
self.dateindex_to_supply_in_profit
.um()
.safe_flush(exit)?;
self.dateindex_to_supply_in_loss
.um()
.safe_flush(exit)?;
self.dateindex_to_unrealized_profit
.um()
.safe_flush(exit)?;
self.dateindex_to_unrealized_loss
.um()
.safe_flush(exit)?;
self.height_to_min_price_paid
.um()
.safe_flush(exit)?;
self.height_to_max_price_paid
.um()
.safe_flush(exit)?;
if self.height_to_adjusted_value_created.is_some() {
self.height_to_adjusted_value_created
.um()
.safe_flush(exit)?;
self.height_to_adjusted_value_destroyed
.um()
.safe_flush(exit)?;
}
}
state.commit(height)?;
Ok(())
}
pub fn compute_from_stateful(
&mut self,
starting_indexes: &Indexes,
others: &[&Self],
exit: &Exit,
) -> Result<()> {
self.height_to_supply.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| &v.height_to_supply)
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_utxo_count.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| &v.height_to_utxo_count)
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_sent.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| &v.height_to_sent)
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_satblocks_destroyed.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| &v.height_to_satblocks_destroyed)
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_satdays_destroyed.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| &v.height_to_satdays_destroyed)
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
if let Some(height_to_realized_cap) = &mut self.height_to_realized_cap {
height_to_realized_cap.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_realized_cap.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_min_price_paid
.um()
.compute_min_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_min_price_paid.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_max_price_paid
.um()
.compute_max_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_max_price_paid.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_realized_profit
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_realized_profit.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_realized_loss
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_realized_loss.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_value_created
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_value_created.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_value_destroyed
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_value_destroyed.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_supply_in_profit
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_supply_in_profit.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_supply_in_loss
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_supply_in_loss.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_unrealized_profit
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_unrealized_profit.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_unrealized_loss
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_unrealized_loss.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.dateindex_to_supply_in_profit
.um()
.compute_sum_of_others(
starting_indexes.dateindex,
others
.iter()
.map(|v| v.dateindex_to_supply_in_profit.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.dateindex_to_supply_in_loss
.um()
.compute_sum_of_others(
starting_indexes.dateindex,
others
.iter()
.map(|v| v.dateindex_to_supply_in_loss.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.dateindex_to_unrealized_profit
.um()
.compute_sum_of_others(
starting_indexes.dateindex,
others
.iter()
.map(|v| v.dateindex_to_unrealized_profit.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.dateindex_to_unrealized_loss
.um()
.compute_sum_of_others(
starting_indexes.dateindex,
others
.iter()
.map(|v| v.dateindex_to_unrealized_loss.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_min_price_paid
.um()
.compute_min_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_min_price_paid.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_max_price_paid
.um()
.compute_max_of_others(
starting_indexes.height,
others
.iter()
.map(|v| v.height_to_max_price_paid.u())
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
if self.height_to_adjusted_value_created.is_some() {
self.height_to_adjusted_value_created
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| {
v.height_to_adjusted_value_created
.as_ref()
.unwrap_or(v.height_to_value_created.u())
})
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_adjusted_value_destroyed
.um()
.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| {
v.height_to_adjusted_value_destroyed
.as_ref()
.unwrap_or(v.height_to_value_destroyed.u())
})
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
}
}
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn compute_rest_part1(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.height_to_supply_value.compute_rest(
price,
starting_indexes,
exit,
Some(&self.height_to_supply),
)?;
self.indexes_to_supply
.compute_all(price, starting_indexes, exit, |v| {
let mut dateindex_to_height_count_iter =
indexes.dateindex_to_height_count.into_iter();
let mut height_to_supply_iter = self.height_to_supply.into_iter();
v.compute_transform(
starting_indexes.dateindex,
&indexes.dateindex_to_first_height,
|(i, height, ..)| {
let count = dateindex_to_height_count_iter.get_unwrap(i);
if count == StoredU64::default() {
unreachable!()
}
let supply = height_to_supply_iter.get_unwrap(height + (*count - 1));
(i, supply)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_utxo_count.compute_rest(
indexes,
starting_indexes,
exit,
Some(&self.height_to_utxo_count),
)?;
self.height_to_supply_half_value
.compute_all(price, starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.height,
&self.height_to_supply,
|(h, v, ..)| (h, v / 2),
exit,
)?;
Ok(())
})?;
self.indexes_to_supply_half
.compute_all(price, starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.dateindex,
self.indexes_to_supply.sats.dateindex.u(),
|(i, sats, ..)| (i, sats / 2),
exit,
)?;
Ok(())
})?;
self.indexes_to_sent
.compute_rest(indexes, price, starting_indexes, exit, Some(&self.height_to_sent))?;
self.indexes_to_coinblocks_destroyed
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.height,
&self.height_to_satblocks_destroyed,
|(i, v, ..)| (i, StoredF64::from(Bitcoin::from(v))),
exit,
)?;
Ok(())
})?;
self.indexes_to_coindays_destroyed
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.height,
&self.height_to_satdays_destroyed,
|(i, v, ..)| (i, StoredF64::from(Bitcoin::from(v))),
exit,
)?;
Ok(())
})?;
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn compute_rest_part2(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &Indexes,
height_to_supply: &impl IterableVec<Height, Bitcoin>,
dateindex_to_supply: &impl IterableVec<DateIndex, Bitcoin>,
height_to_market_cap: Option<&impl IterableVec<Height, Dollars>>,
dateindex_to_market_cap: Option<&impl IterableVec<DateIndex, Dollars>>,
height_to_realized_cap: Option<&impl IterableVec<Height, Dollars>>,
dateindex_to_realized_cap: Option<&impl IterableVec<DateIndex, Dollars>>,
exit: &Exit,
) -> Result<()> {
if let Some(v) = self.indexes_to_supply_rel_to_circulating_supply.as_mut() {
v.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_percentage(
starting_indexes.height,
&self.height_to_supply_value.bitcoin,
height_to_supply,
exit,
)?;
Ok(())
})?;
}
if let Some(indexes_to_realized_cap) = self.indexes_to_realized_cap.as_mut() {
let height_to_market_cap = height_to_market_cap.unwrap();
let dateindex_to_market_cap = dateindex_to_market_cap.unwrap();
indexes_to_realized_cap.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_realized_cap.u()),
)?;
self.indexes_to_realized_price
.um()
.compute_all(indexes, starting_indexes, exit, |vec| {
vec.compute_divide(
starting_indexes.height,
self.height_to_realized_cap.u(),
&self.height_to_supply_value.bitcoin,
exit,
)?;
Ok(())
})?;
self.indexes_to_realized_price_extra
.um()
.compute_rest(
price.u(),
starting_indexes,
exit,
Some(
self.indexes_to_realized_price
.u()
.dateindex
.unwrap_last(),
),
)?;
self.indexes_to_realized_profit
.um()
.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_realized_profit.u()),
)?;
self.indexes_to_realized_loss
.um()
.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_realized_loss.u()),
)?;
self.indexes_to_neg_realized_loss
.um()
.compute_all(indexes, starting_indexes, exit, |vec| {
vec.compute_transform(
starting_indexes.height,
self.height_to_realized_loss.u(),
|(i, v, ..)| (i, v * -1_i64),
exit,
)?;
Ok(())
})?;
self.indexes_to_value_created
.um()
.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_value_created.u()),
)?;
self.indexes_to_value_destroyed
.um()
.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_value_destroyed.u()),
)?;
self.indexes_to_realized_cap_30d_delta
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_change(
starting_indexes.dateindex,
self.indexes_to_realized_cap
.u()
.dateindex
.unwrap_last(),
30,
exit,
)?;
Ok(())
})?;
self.indexes_to_net_realized_pnl
.um()
.compute_all(indexes, starting_indexes, exit, |vec| {
vec.compute_subtract(
starting_indexes.height,
self.height_to_realized_profit.u(),
self.height_to_realized_loss.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_realized_value
.um()
.compute_all(indexes, starting_indexes, exit, |vec| {
vec.compute_add(
starting_indexes.height,
self.height_to_realized_profit.u(),
self.height_to_realized_loss.u(),
exit,
)?;
Ok(())
})?;
self.dateindex_to_sopr.um().compute_divide(
starting_indexes.dateindex,
self.indexes_to_value_created
.u()
.dateindex
.unwrap_sum(),
self.indexes_to_value_destroyed
.u()
.dateindex
.unwrap_sum(),
exit,
)?;
self.dateindex_to_sopr_7d_ema
.um()
.compute_ema(
starting_indexes.dateindex,
self.dateindex_to_sopr.u(),
7,
exit,
)?;
self.dateindex_to_sopr_30d_ema
.um()
.compute_ema(
starting_indexes.dateindex,
self.dateindex_to_sopr.u(),
30,
exit,
)?;
self.dateindex_to_sell_side_risk_ratio
.um()
.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_realized_value
.u()
.dateindex
.unwrap_sum(),
self.indexes_to_realized_cap
.u()
.dateindex
.unwrap_last(),
exit,
)?;
self.dateindex_to_sell_side_risk_ratio_7d_ema
.um()
.compute_ema(
starting_indexes.dateindex,
self.dateindex_to_sell_side_risk_ratio.u(),
7,
exit,
)?;
self.dateindex_to_sell_side_risk_ratio_30d_ema
.um()
.compute_ema(
starting_indexes.dateindex,
self.dateindex_to_sell_side_risk_ratio.u(),
30,
exit,
)?;
self.indexes_to_supply_in_profit
.um()
.compute_rest(
price,
starting_indexes,
exit,
Some(self.dateindex_to_supply_in_profit.u()),
)?;
self.indexes_to_supply_in_loss
.um()
.compute_rest(
price,
starting_indexes,
exit,
Some(self.dateindex_to_supply_in_loss.u()),
)?;
self.indexes_to_unrealized_profit
.um()
.compute_rest(
starting_indexes,
exit,
Some(self.dateindex_to_unrealized_profit.u()),
)?;
self.indexes_to_unrealized_loss
.um()
.compute_rest(
starting_indexes,
exit,
Some(self.dateindex_to_unrealized_loss.u()),
)?;
self.height_to_total_unrealized_pnl
.um()
.compute_add(
starting_indexes.height,
self.height_to_unrealized_profit.u(),
self.height_to_unrealized_loss.u(),
exit,
)?;
self.indexes_to_total_unrealized_pnl
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_add(
starting_indexes.dateindex,
self.dateindex_to_unrealized_profit.u(),
self.dateindex_to_unrealized_loss.u(),
exit,
)?;
Ok(())
})?;
self.height_to_total_realized_pnl
.um()
.compute_add(
starting_indexes.height,
self.height_to_realized_profit.u(),
self.height_to_realized_loss.u(),
exit,
)?;
self.indexes_to_total_realized_pnl
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_add(
starting_indexes.dateindex,
self.indexes_to_realized_profit
.u()
.dateindex
.unwrap_sum(),
self.indexes_to_realized_loss
.u()
.dateindex
.unwrap_sum(),
exit,
)?;
Ok(())
})?;
self.indexes_to_min_price_paid
.um()
.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_min_price_paid.u()),
)?;
self.indexes_to_max_price_paid
.um()
.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_max_price_paid.u()),
)?;
self.height_to_neg_unrealized_loss
.um()
.compute_transform(
starting_indexes.height,
self.height_to_unrealized_loss.u(),
|(h, v, ..)| (h, v * -1_i64),
exit,
)?;
self.indexes_to_neg_unrealized_loss
.um()
.compute_all(starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.dateindex,
self.dateindex_to_unrealized_loss.u(),
|(h, v, ..)| (h, v * -1_i64),
exit,
)?;
Ok(())
})?;
self.height_to_net_unrealized_pnl
.um()
.compute_subtract(
starting_indexes.height,
self.height_to_unrealized_profit.u(),
self.height_to_unrealized_loss.u(),
exit,
)?;
self.indexes_to_net_unrealized_pnl
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_subtract(
starting_indexes.dateindex,
self.dateindex_to_unrealized_profit.u(),
self.dateindex_to_unrealized_loss.u(),
exit,
)?;
Ok(())
})?;
self.height_to_unrealized_profit_rel_to_market_cap
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_profit.u(),
height_to_market_cap,
exit,
)?;
self.height_to_unrealized_loss_rel_to_market_cap
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_loss.u(),
height_to_market_cap,
exit,
)?;
self.height_to_neg_unrealized_loss_rel_to_market_cap
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_neg_unrealized_loss.u(),
height_to_market_cap,
exit,
)?;
self.height_to_net_unrealized_pnl_rel_to_market_cap
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_net_unrealized_pnl.u(),
height_to_market_cap,
exit,
)?;
self.indexes_to_unrealized_profit_rel_to_market_cap
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_profit.u(),
dateindex_to_market_cap,
exit,
)?;
Ok(())
})?;
self.indexes_to_unrealized_loss_rel_to_market_cap
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_loss.u(),
dateindex_to_market_cap,
exit,
)?;
Ok(())
})?;
self.indexes_to_neg_unrealized_loss_rel_to_market_cap
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_neg_unrealized_loss
.u()
.dateindex
.u(),
dateindex_to_market_cap,
exit,
)?;
Ok(())
})?;
self.indexes_to_net_unrealized_pnl_rel_to_market_cap
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_net_unrealized_pnl
.u()
.dateindex
.u(),
dateindex_to_market_cap,
exit,
)?;
Ok(())
})?;
if self
.height_to_unrealized_profit_rel_to_own_market_cap
.is_some()
{
self.height_to_unrealized_profit_rel_to_own_market_cap
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_profit.u(),
self.height_to_supply_value.dollars.u(),
exit,
)?;
self.height_to_unrealized_loss_rel_to_own_market_cap
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_loss.u(),
self.height_to_supply_value.dollars.u(),
exit,
)?;
self.height_to_neg_unrealized_loss_rel_to_own_market_cap
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_neg_unrealized_loss.u(),
self.height_to_supply_value.dollars.u(),
exit,
)?;
self.height_to_net_unrealized_pnl_rel_to_own_market_cap
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_net_unrealized_pnl.u(),
self.height_to_supply_value.dollars.u(),
exit,
)?;
self.indexes_to_unrealized_profit_rel_to_own_market_cap
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_profit.u(),
self.indexes_to_supply
.dollars
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
self.indexes_to_unrealized_loss_rel_to_own_market_cap
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_loss.u(),
self.indexes_to_supply
.dollars
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
self.indexes_to_neg_unrealized_loss_rel_to_own_market_cap
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_neg_unrealized_loss
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
self.indexes_to_supply
.dollars
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
self.indexes_to_net_unrealized_pnl_rel_to_own_market_cap
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_net_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
self.indexes_to_supply
.dollars
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
}
if self
.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.is_some()
{
self.height_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_profit.u(),
self.height_to_total_unrealized_pnl.u(),
exit,
)?;
self.height_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_unrealized_loss.u(),
self.height_to_total_unrealized_pnl.u(),
exit,
)?;
self.height_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_neg_unrealized_loss.u(),
self.height_to_total_unrealized_pnl.u(),
exit,
)?;
self.height_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.um()
.compute_percentage(
starting_indexes.height,
self.height_to_net_unrealized_pnl.u(),
self.height_to_total_unrealized_pnl.u(),
exit,
)?;
self.indexes_to_unrealized_profit_rel_to_own_total_unrealized_pnl
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_profit.u(),
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
self.indexes_to_unrealized_loss_rel_to_own_total_unrealized_pnl
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_unrealized_loss.u(),
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
self.indexes_to_neg_unrealized_loss_rel_to_own_total_unrealized_pnl
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_neg_unrealized_loss
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
self.indexes_to_net_unrealized_pnl_rel_to_own_total_unrealized_pnl
.um()
.compute_all(starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_net_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
self.indexes_to_total_unrealized_pnl
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
}
self.indexes_to_realized_profit_rel_to_realized_cap
.um()
.compute_all(indexes, starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.height,
self.height_to_realized_profit.u(),
*height_to_realized_cap.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_realized_loss_rel_to_realized_cap
.um()
.compute_all(indexes, starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.height,
self.height_to_realized_loss.u(),
*height_to_realized_cap.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_net_realized_pnl_rel_to_realized_cap
.um()
.compute_all(indexes, starting_indexes, exit, |vec| {
vec.compute_percentage(
starting_indexes.height,
self.indexes_to_net_realized_pnl
.u()
.height
.u(),
*height_to_realized_cap.u(),
exit,
)?;
Ok(())
})?;
self.height_to_supply_in_loss_value
.um()
.compute_rest(
price,
starting_indexes,
exit,
Some(self.height_to_supply_in_loss.u()),
)?;
self.height_to_supply_in_profit_value
.um()
.compute_rest(
price,
starting_indexes,
exit,
Some(self.height_to_supply_in_profit.u()),
)?;
self.height_to_supply_in_loss_rel_to_own_supply
.um()
.compute_percentage(
starting_indexes.height,
&self
.height_to_supply_in_loss_value
.u()
.bitcoin,
&self.height_to_supply_value.bitcoin,
exit,
)?;
self.height_to_supply_in_profit_rel_to_own_supply
.um()
.compute_percentage(
starting_indexes.height,
&self
.height_to_supply_in_profit_value
.u()
.bitcoin,
&self.height_to_supply_value.bitcoin,
exit,
)?;
self.indexes_to_supply_in_loss_rel_to_own_supply
.um()
.compute_all(starting_indexes, exit, |v| {
v.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_supply_in_loss
.u()
.bitcoin
.dateindex
.u(),
self.indexes_to_supply.bitcoin.dateindex.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_supply_in_profit_rel_to_own_supply
.um()
.compute_all(starting_indexes, exit, |v| {
v.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_supply_in_profit
.u()
.bitcoin
.dateindex
.u(),
self.indexes_to_supply.bitcoin.dateindex.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_net_realized_pnl_cumulative_30d_delta
.um()
.compute_all(starting_indexes, exit, |v| {
v.compute_change(
starting_indexes.dateindex,
self.indexes_to_net_realized_pnl
.u()
.dateindex
.unwrap_cumulative(),
30,
exit,
)?;
Ok(())
})?;
self.indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_realized_cap
.um()
.compute_all(starting_indexes, exit, |v| {
v.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_net_realized_pnl_cumulative_30d_delta
.u()
.dateindex
.u(),
*dateindex_to_realized_cap.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_net_realized_pnl_cumulative_30d_delta_rel_to_market_cap
.um()
.compute_all(starting_indexes, exit, |v| {
v.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_net_realized_pnl_cumulative_30d_delta
.u()
.dateindex
.u(),
dateindex_to_market_cap,
exit,
)?;
Ok(())
})?;
if self
.height_to_supply_in_profit_rel_to_circulating_supply
.as_mut()
.is_some()
{
self.height_to_supply_in_loss_rel_to_circulating_supply
.um()
.compute_percentage(
starting_indexes.height,
&self
.height_to_supply_in_loss_value
.u()
.bitcoin,
height_to_supply,
exit,
)?;
self.height_to_supply_in_profit_rel_to_circulating_supply
.um()
.compute_percentage(
starting_indexes.height,
&self
.height_to_supply_in_profit_value
.u()
.bitcoin,
height_to_supply,
exit,
)?;
self.indexes_to_supply_in_loss_rel_to_circulating_supply
.um()
.compute_all(starting_indexes, exit, |v| {
v.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_supply_in_loss
.as_ref()
.unwrap()
.bitcoin
.dateindex
.as_ref()
.unwrap(),
dateindex_to_supply,
exit,
)?;
Ok(())
})?;
self.indexes_to_supply_in_profit_rel_to_circulating_supply
.um()
.compute_all(starting_indexes, exit, |v| {
v.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_supply_in_profit
.as_ref()
.unwrap()
.bitcoin
.dateindex
.as_ref()
.unwrap(),
dateindex_to_supply,
exit,
)?;
Ok(())
})?;
}
if self.indexes_to_adjusted_value_created.is_some() {
self.indexes_to_adjusted_value_created
.um()
.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_adjusted_value_created.u()),
)?;
self.indexes_to_adjusted_value_destroyed
.um()
.compute_rest(
indexes,
starting_indexes,
exit,
Some(self.height_to_adjusted_value_destroyed.u()),
)?;
self.dateindex_to_adjusted_sopr
.um()
.compute_divide(
starting_indexes.dateindex,
self.indexes_to_adjusted_value_created
.u()
.dateindex
.unwrap_sum(),
self.indexes_to_adjusted_value_destroyed
.u()
.dateindex
.unwrap_sum(),
exit,
)?;
self.dateindex_to_adjusted_sopr_7d_ema
.um()
.compute_ema(
starting_indexes.dateindex,
self.dateindex_to_adjusted_sopr.u(),
7,
exit,
)?;
self.dateindex_to_adjusted_sopr_30d_ema
.um()
.compute_ema(
starting_indexes.dateindex,
self.dateindex_to_adjusted_sopr.u(),
30,
exit,
)?;
}
if let Some(indexes_to_realized_cap_rel_to_own_market_cap) =
self.indexes_to_realized_cap_rel_to_own_market_cap.as_mut()
{
indexes_to_realized_cap_rel_to_own_market_cap.compute_all(
indexes,
starting_indexes,
exit,
|v| {
v.compute_percentage(
starting_indexes.height,
self.height_to_realized_cap.u(),
self.height_to_supply_value.dollars.u(),
exit,
)?;
Ok(())
},
)?;
}
}
if let Some(dateindex_to_realized_profit_to_loss_ratio) =
self.dateindex_to_realized_profit_to_loss_ratio.as_mut()
{
dateindex_to_realized_profit_to_loss_ratio.compute_divide(
starting_indexes.dateindex,
self.indexes_to_realized_profit
.u()
.dateindex
.unwrap_sum(),
self.indexes_to_realized_loss
.u()
.dateindex
.unwrap_sum(),
exit,
)?;
}
Ok(())
}
}