global: snapshot part 16

This commit is contained in:
nym21
2026-03-21 17:15:53 +01:00
parent b45c6ec05f
commit 2991562234
31 changed files with 355 additions and 423 deletions

View File

@@ -1134,38 +1134,6 @@ pub struct AverageBaseCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern<T> {
pub sum: _1m1w1y24hPattern<T>,
}
/// Pattern struct for repeated tree structure.
pub struct AverageGainsLossesRsiStochPattern {
pub average_gain: SeriesPattern1<StoredF32>,
pub average_loss: SeriesPattern1<StoredF32>,
pub gains: SeriesPattern1<StoredF32>,
pub losses: SeriesPattern1<StoredF32>,
pub rsi: BpsPercentRatioPattern3,
pub rsi_max: BpsPercentRatioPattern3,
pub rsi_min: BpsPercentRatioPattern3,
pub stoch_rsi: BpsPercentRatioPattern3,
pub stoch_rsi_d: BpsPercentRatioPattern3,
pub stoch_rsi_k: BpsPercentRatioPattern3,
}
impl AverageGainsLossesRsiStochPattern {
/// Create a new pattern node with accumulated series name.
pub fn new(client: Arc<BrkClientBase>, acc: String, disc: String) -> Self {
Self {
average_gain: SeriesPattern1::new(client.clone(), _m(&acc, &format!("average_gain_{disc}", disc=disc))),
average_loss: SeriesPattern1::new(client.clone(), _m(&acc, &format!("average_loss_{disc}", disc=disc))),
gains: SeriesPattern1::new(client.clone(), _m(&acc, &format!("gains_{disc}", disc=disc))),
losses: SeriesPattern1::new(client.clone(), _m(&acc, &format!("losses_{disc}", disc=disc))),
rsi: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &disc)),
rsi_max: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("max_{disc}", disc=disc))),
rsi_min: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("min_{disc}", disc=disc))),
stoch_rsi: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("stoch_{disc}", disc=disc))),
stoch_rsi_d: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("stoch_d_{disc}", disc=disc))),
stoch_rsi_k: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("stoch_k_{disc}", disc=disc))),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct AllP2aP2pk33P2pk65P2pkhP2shP2trP2wpkhP2wshPattern3 {
pub all: SeriesPattern1<StoredU64>,
@@ -2528,7 +2496,7 @@ impl CentsSatsUsdPattern {
pub struct CumulativeRollingSumPattern {
pub cumulative: SeriesPattern1<StoredU64>,
pub rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern,
pub sum: SeriesPattern1<StoredU64>,
pub sum: SeriesPattern18<StoredU64>,
}
impl CumulativeRollingSumPattern {
@@ -2537,7 +2505,7 @@ impl CumulativeRollingSumPattern {
Self {
cumulative: SeriesPattern1::new(client.clone(), _m(&acc, "cumulative")),
rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern::new(client.clone(), acc.clone()),
sum: SeriesPattern1::new(client.clone(), _m(&acc, "sum")),
sum: SeriesPattern18::new(client.clone(), _m(&acc, "sum")),
}
}
}
@@ -2592,6 +2560,24 @@ pub struct RatioTransferValuePattern {
pub value_destroyed: AverageBlockCumulativeSumPattern<Cents>,
}
/// Pattern struct for repeated tree structure.
pub struct RsiStochPattern {
pub rsi: BpsPercentRatioPattern3,
pub stoch_rsi_d: BpsPercentRatioPattern3,
pub stoch_rsi_k: BpsPercentRatioPattern3,
}
impl RsiStochPattern {
/// Create a new pattern node with accumulated series name.
pub fn new(client: Arc<BrkClientBase>, acc: String, disc: String) -> Self {
Self {
rsi: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &disc)),
stoch_rsi_d: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("stoch_d_{disc}", disc=disc))),
stoch_rsi_k: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("stoch_k_{disc}", disc=disc))),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct _6bBlockTxPattern<T> {
pub _6b: MaxMedianMinPct10Pct25Pct75Pct90Pattern<T>,
@@ -2676,7 +2662,7 @@ impl AllSthPattern {
/// Pattern struct for repeated tree structure.
pub struct BaseSumPattern {
pub base: SeriesPattern1<Dollars>,
pub base: SeriesPattern18<Dollars>,
pub sum: _1m1w1y24hPattern<Dollars>,
}
@@ -2684,7 +2670,7 @@ impl BaseSumPattern {
/// Create a new pattern node with accumulated series name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
base: SeriesPattern1::new(client.clone(), acc.clone()),
base: SeriesPattern18::new(client.clone(), acc.clone()),
sum: _1m1w1y24hPattern::new(client.clone(), _m(&acc, "sum")),
}
}
@@ -2706,6 +2692,22 @@ impl BaseDeltaPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct BlockCumulativePattern {
pub block: BtcCentsSatsUsdPattern2,
pub cumulative: BtcCentsSatsUsdPattern3,
}
impl BlockCumulativePattern {
/// Create a new pattern node with accumulated series name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
block: BtcCentsSatsUsdPattern2::new(client.clone(), acc.clone()),
cumulative: BtcCentsSatsUsdPattern3::new(client.clone(), _m(&acc, "cumulative")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct BlocksDominancePattern {
pub blocks_mined: AverageBlockCumulativeSumPattern2,
@@ -4076,13 +4078,13 @@ impl SeriesTree_Scripts_Count {
/// Series tree node.
pub struct SeriesTree_Scripts_Value {
pub op_return: AverageBlockCumulativeSumPattern3,
pub op_return: BlockCumulativePattern,
}
impl SeriesTree_Scripts_Value {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
op_return: AverageBlockCumulativeSumPattern3::new(client.clone(), "op_return_value".to_string()),
op_return: BlockCumulativePattern::new(client.clone(), "op_return_value".to_string()),
}
}
}
@@ -4107,7 +4109,7 @@ pub struct SeriesTree_Mining_Rewards {
pub coinbase: AverageBlockCumulativeSumPattern3,
pub subsidy: SeriesTree_Mining_Rewards_Subsidy,
pub fees: SeriesTree_Mining_Rewards_Fees,
pub unclaimed: SeriesTree_Mining_Rewards_Unclaimed,
pub unclaimed: BlockCumulativePattern,
}
impl SeriesTree_Mining_Rewards {
@@ -4116,7 +4118,7 @@ impl SeriesTree_Mining_Rewards {
coinbase: AverageBlockCumulativeSumPattern3::new(client.clone(), "coinbase".to_string()),
subsidy: SeriesTree_Mining_Rewards_Subsidy::new(client.clone(), format!("{base_path}_subsidy")),
fees: SeriesTree_Mining_Rewards_Fees::new(client.clone(), format!("{base_path}_fees")),
unclaimed: SeriesTree_Mining_Rewards_Unclaimed::new(client.clone(), format!("{base_path}_unclaimed")),
unclaimed: BlockCumulativePattern::new(client.clone(), "unclaimed_rewards".to_string()),
}
}
}
@@ -4128,7 +4130,6 @@ pub struct SeriesTree_Mining_Rewards_Subsidy {
pub sum: _1m1w1y24hPattern4,
pub average: _1m1w1y24hPattern3,
pub dominance: _1m1w1y24hBpsPercentRatioPattern,
pub sma_1y: CentsUsdPattern3,
}
impl SeriesTree_Mining_Rewards_Subsidy {
@@ -4139,7 +4140,6 @@ impl SeriesTree_Mining_Rewards_Subsidy {
sum: _1m1w1y24hPattern4::new(client.clone(), "subsidy_sum".to_string()),
average: _1m1w1y24hPattern3::new(client.clone(), "subsidy_average".to_string()),
dominance: _1m1w1y24hBpsPercentRatioPattern::new(client.clone(), "subsidy_dominance".to_string()),
sma_1y: CentsUsdPattern3::new(client.clone(), "subsidy_sma_1y".to_string()),
}
}
}
@@ -4200,21 +4200,6 @@ impl SeriesTree_Mining_Rewards_Fees_ToSubsidyRatio {
}
}
/// Series tree node.
pub struct SeriesTree_Mining_Rewards_Unclaimed {
pub block: BtcCentsSatsUsdPattern2,
pub cumulative: BtcCentsSatsUsdPattern3,
}
impl SeriesTree_Mining_Rewards_Unclaimed {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
block: BtcCentsSatsUsdPattern2::new(client.clone(), "unclaimed_rewards".to_string()),
cumulative: BtcCentsSatsUsdPattern3::new(client.clone(), "unclaimed_rewards_cumulative".to_string()),
}
}
}
/// Series tree node.
pub struct SeriesTree_Mining_Hashrate {
pub rate: SeriesTree_Mining_Hashrate_Rate,
@@ -5715,8 +5700,6 @@ impl SeriesTree_Market_Dca_Class_Return {
/// Series tree node.
pub struct SeriesTree_Market_Technical {
pub rsi: SeriesTree_Market_Technical_Rsi,
pub stoch_k: BpsPercentRatioPattern3,
pub stoch_d: BpsPercentRatioPattern3,
pub pi_cycle: BpsRatioPattern2,
pub macd: SeriesTree_Market_Technical_Macd,
}
@@ -5725,8 +5708,6 @@ impl SeriesTree_Market_Technical {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
rsi: SeriesTree_Market_Technical_Rsi::new(client.clone(), format!("{base_path}_rsi")),
stoch_k: BpsPercentRatioPattern3::new(client.clone(), "stoch_k".to_string()),
stoch_d: BpsPercentRatioPattern3::new(client.clone(), "stoch_d".to_string()),
pi_cycle: BpsRatioPattern2::new(client.clone(), "pi_cycle".to_string()),
macd: SeriesTree_Market_Technical_Macd::new(client.clone(), format!("{base_path}_macd")),
}
@@ -5735,17 +5716,17 @@ impl SeriesTree_Market_Technical {
/// Series tree node.
pub struct SeriesTree_Market_Technical_Rsi {
pub _24h: AverageGainsLossesRsiStochPattern,
pub _1w: AverageGainsLossesRsiStochPattern,
pub _1m: AverageGainsLossesRsiStochPattern,
pub _24h: RsiStochPattern,
pub _1w: RsiStochPattern,
pub _1m: RsiStochPattern,
}
impl SeriesTree_Market_Technical_Rsi {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
_24h: AverageGainsLossesRsiStochPattern::new(client.clone(), "rsi".to_string(), "24h".to_string()),
_1w: AverageGainsLossesRsiStochPattern::new(client.clone(), "rsi".to_string(), "1w".to_string()),
_1m: AverageGainsLossesRsiStochPattern::new(client.clone(), "rsi".to_string(), "1m".to_string()),
_24h: RsiStochPattern::new(client.clone(), "rsi".to_string(), "24h".to_string()),
_1w: RsiStochPattern::new(client.clone(), "rsi".to_string(), "1w".to_string()),
_1m: RsiStochPattern::new(client.clone(), "rsi".to_string(), "1m".to_string()),
}
}
}
@@ -6267,7 +6248,7 @@ impl SeriesTree_Prices_Spot {
pub struct SeriesTree_Supply {
pub state: SeriesPattern18<SupplyState>,
pub circulating: BtcCentsSatsUsdPattern3,
pub burned: AverageBlockCumulativeSumPattern3,
pub burned: BlockCumulativePattern,
pub inflation_rate: BpsPercentRatioPattern,
pub velocity: SeriesTree_Supply_Velocity,
pub market_cap: CentsDeltaUsdPattern,
@@ -6280,7 +6261,7 @@ impl SeriesTree_Supply {
Self {
state: SeriesPattern18::new(client.clone(), "supply_state".to_string()),
circulating: BtcCentsSatsUsdPattern3::new(client.clone(), "circulating_supply".to_string()),
burned: AverageBlockCumulativeSumPattern3::new(client.clone(), "unspendable_supply".to_string()),
burned: BlockCumulativePattern::new(client.clone(), "unspendable_supply".to_string()),
inflation_rate: BpsPercentRatioPattern::new(client.clone(), "inflation_rate".to_string()),
velocity: SeriesTree_Supply_Velocity::new(client.clone(), format!("{base_path}_velocity")),
market_cap: CentsDeltaUsdPattern::new(client.clone(), "market_cap".to_string()),

View File

@@ -67,8 +67,8 @@ pub(crate) fn process_blocks(
let height_to_first_txout_index = &indexer.vecs.outputs.first_txout_index;
let height_to_first_txin_index = &indexer.vecs.inputs.first_txin_index;
let height_to_tx_count = &transactions.count.total.block;
let height_to_output_count = &outputs.count.total.sum.height;
let height_to_input_count = &inputs.count.sum.height;
let height_to_output_count = &outputs.count.total.sum;
let height_to_input_count = &inputs.count.sum;
let tx_index_to_output_count = &indexes.tx_index.output_count;
let tx_index_to_input_count = &indexes.tx_index.input_count;

View File

@@ -3,7 +3,8 @@ use brk_traversable::Traversable;
use brk_types::{BasisPointsSigned32, Bitcoin, Cents, CentsSigned, Dollars, Height, Indexes, StoredF64, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{
AnyStoredVec, Exit, ReadableCloneableVec, ReadableVec, Rw, StorageMode, WritableVec,
AnyStoredVec, Exit, LazyVecFrom1, ReadableCloneableVec, ReadableVec, Rw, StorageMode,
WritableVec,
};
use crate::{
@@ -22,7 +23,7 @@ use super::RealizedMinimal;
#[derive(Clone, Traversable)]
pub struct NegRealizedLoss {
#[traversable(flatten)]
pub base: LazyPerBlock<Dollars, Cents>,
pub base: LazyVecFrom1<Height, Dollars, Height, Cents>,
pub sum: Windows<LazyPerBlock<Dollars, Cents>>,
}
@@ -51,11 +52,10 @@ impl RealizedCore {
let minimal = RealizedMinimal::forced_import(cfg)?;
let neg_loss_base = LazyPerBlock::from_height_source::<NegCentsUnsignedToDollars>(
let neg_loss_base = LazyVecFrom1::transformed::<NegCentsUnsignedToDollars>(
&cfg.name("realized_loss_neg"),
cfg.version + Version::ONE,
minimal.loss.block.cents.read_only_boxed_clone(),
cfg.indexes,
);
let neg_loss_sum = minimal.loss.sum.0.map_with_suffix(|suffix, slot| {

View File

@@ -22,7 +22,7 @@ impl Vecs {
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(
starting_indexes.height,
&mining.rewards.subsidy.block.usd,
&mining.rewards.subsidy_sma_1y.usd.height,
&mining.rewards.subsidy.average._1y.usd.height,
exit,
)?;

View File

@@ -1,7 +1,7 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use vecdb::{Database, Exit, Rw, StorageMode};
use brk_types::{Height, Sats, Version};
use vecdb::{Database, EagerVec, Exit, PcoVec, Rw, StorageMode};
use crate::{
indexes,
@@ -57,4 +57,15 @@ impl AmountPerBlockCumulative {
Ok(())
}
pub(crate) fn compute_with(
&mut self,
max_from: Height,
prices: &prices::Vecs,
exit: &Exit,
compute_sats: impl FnOnce(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
) -> Result<()> {
compute_sats(&mut self.block.sats)?;
self.compute(prices, max_from, exit)
}
}

View File

@@ -3,8 +3,8 @@ use brk_traversable::Traversable;
use brk_types::Height;
use schemars::JsonSchema;
use vecdb::{
AnyStoredVec, AnyVec, Database, Exit, ReadableVec, Rw, StorageMode, VecIndex, VecValue,
Version, WritableVec,
AnyStoredVec, AnyVec, Database, EagerVec, Exit, ImportableVec, PcoVec, ReadableVec, Rw,
StorageMode, VecIndex, VecValue, Version, WritableVec,
};
use crate::{
@@ -17,7 +17,7 @@ pub struct PerBlockAggregated<T, M: StorageMode = Rw>
where
T: NumericValue + JsonSchema,
{
pub sum: PerBlock<T, M>,
pub sum: M::Stored<EagerVec<PcoVec<Height, T>>>,
pub cumulative: PerBlock<T, M>,
pub rolling: RollingComplete<T, M>,
}
@@ -33,7 +33,7 @@ where
indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts,
) -> Result<Self> {
let sum = PerBlock::forced_import(db, &format!("{name}_sum"), version, indexes)?;
let sum = EagerVec::forced_import(db, &format!("{name}_sum"), version)?;
let cumulative =
PerBlock::forced_import(db, &format!("{name}_cumulative"), version, indexes)?;
let rolling = RollingComplete::forced_import(
@@ -73,9 +73,8 @@ where
let mut index = max_from;
index = {
self.sum
.height
.validate_computed_version_or_reset(combined_version)?;
index.min(Height::from(self.sum.height.len()))
index.min(Height::from(self.sum.len()))
};
index = {
self.cumulative
@@ -86,7 +85,7 @@ where
let start = index.to_usize();
self.sum.height.truncate_if_needed_at(start)?;
self.sum.truncate_if_needed_at(start)?;
self.cumulative.height.truncate_if_needed_at(start)?;
let mut cumulative_val = index.decremented().map_or(T::from(0_usize), |idx| {
@@ -117,7 +116,7 @@ where
|acc, val| acc + val,
);
self.sum.height.push(sum_val);
self.sum.push(sum_val);
cumulative_val += sum_val;
self.cumulative.height.push(cumulative_val);
@@ -125,12 +124,11 @@ where
})?;
let _lock = exit.lock();
self.sum.height.write()?;
self.sum.write()?;
self.cumulative.height.write()?;
drop(_lock);
self.rolling
.compute(max_from, windows, &self.sum.height, exit)?;
self.rolling.compute(max_from, windows, &self.sum, exit)?;
Ok(())
}
}

View File

@@ -58,10 +58,9 @@ impl Vecs {
r3?;
r4?;
// Phase 3: Depends on returns, range, moving_average
// Phase 3: Depends on returns, moving_average
self.technical.compute(
&self.returns,
&self.range,
prices,
blocks,
&self.moving_average,

View File

@@ -1,9 +1,9 @@
use brk_error::Result;
use brk_types::{BasisPoints16, Dollars, Indexes};
use brk_types::{Dollars, Indexes};
use vecdb::Exit;
use super::{
super::{moving_average, range, returns},
super::{moving_average, returns},
Vecs, macd, rsi,
};
use crate::{blocks, internal::{RatioDollarsBp32, WindowsTo1m}, prices};
@@ -13,37 +13,12 @@ impl Vecs {
pub(crate) fn compute(
&mut self,
returns: &returns::Vecs,
range: &range::Vecs,
prices: &prices::Vecs,
blocks: &blocks::Vecs,
moving_average: &moving_average::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.stoch_k.bps.height.compute_transform3(
starting_indexes.height,
&prices.spot.usd.height,
&range.min._2w.usd.height,
&range.max._2w.usd.height,
|(h, close, low, high, ..)| {
let range = *high - *low;
let stoch = if range == 0.0 {
BasisPoints16::ZERO
} else {
BasisPoints16::from((*close - *low) / range)
};
(h, stoch)
},
exit,
)?;
self.stoch_d.bps.height.compute_rolling_average(
starting_indexes.height,
&blocks.lookback._3d,
&self.stoch_k.bps.height,
exit,
)?;
let daily_returns = &returns.periods._24h.ratio.height;
for (rsi_chain, &m) in self.rsi.as_mut_array().into_iter().zip(&WindowsTo1m::<()>::DAYS) {
rsi::compute(

View File

@@ -110,15 +110,10 @@ impl Vecs {
WindowsTo1m::try_from_fn(|tf| RsiChain::forced_import(db, tf, v + Version::TWO, indexes))?;
let macd = WindowsTo1m::try_from_fn(|tf| MacdChain::forced_import(db, tf, v, indexes))?;
let stoch_k = PercentPerBlock::forced_import(db, "stoch_k", v, indexes)?;
let stoch_d = PercentPerBlock::forced_import(db, "stoch_d", v, indexes)?;
let pi_cycle = RatioPerBlock::forced_import_raw(db, "pi_cycle", v, indexes)?;
Ok(Self {
rsi,
stoch_k,
stoch_d,
pi_cycle,
macd,
})

View File

@@ -6,13 +6,20 @@ use crate::internal::{PerBlock, PercentPerBlock, RatioPerBlock, WindowsTo1m};
#[derive(Traversable)]
pub struct RsiChain<M: StorageMode = Rw> {
#[traversable(hidden)]
pub gains: PerBlock<StoredF32, M>,
#[traversable(hidden)]
pub losses: PerBlock<StoredF32, M>,
#[traversable(hidden)]
pub average_gain: PerBlock<StoredF32, M>,
#[traversable(hidden)]
pub average_loss: PerBlock<StoredF32, M>,
pub rsi: PercentPerBlock<BasisPoints16, M>,
#[traversable(hidden)]
pub rsi_min: PercentPerBlock<BasisPoints16, M>,
#[traversable(hidden)]
pub rsi_max: PercentPerBlock<BasisPoints16, M>,
#[traversable(hidden)]
pub stoch_rsi: PercentPerBlock<BasisPoints16, M>,
pub stoch_rsi_k: PercentPerBlock<BasisPoints16, M>,
pub stoch_rsi_d: PercentPerBlock<BasisPoints16, M>,
@@ -31,9 +38,6 @@ pub struct MacdChain<M: StorageMode = Rw> {
pub struct Vecs<M: StorageMode = Rw> {
pub rsi: WindowsTo1m<RsiChain<M>>,
pub stoch_k: PercentPerBlock<BasisPoints16, M>,
pub stoch_d: PercentPerBlock<BasisPoints16, M>,
pub pi_cycle: RatioPerBlock<BasisPoints32, M>,
pub macd: WindowsTo1m<MacdChain<M>>,

View File

@@ -133,13 +133,6 @@ impl Vecs {
exit,
)?;
self.subsidy_sma_1y.cents.height.compute_rolling_average(
starting_indexes.height,
&lookback._1y,
&self.subsidy.block.cents,
exit,
)?;
self.fee_to_subsidy_ratio
.compute_binary::<Dollars, Dollars, RatioDollarsBp32, _, _>(
starting_indexes.height,

View File

@@ -7,7 +7,7 @@ use crate::{
indexes,
internal::{
AmountPerBlockCumulative, AmountPerBlockCumulativeRolling, AmountPerBlockFull,
CachedWindowStarts, FiatPerBlock, LazyPercentRollingWindows, OneMinusBp16,
CachedWindowStarts, LazyPercentRollingWindows, OneMinusBp16,
PercentPerBlock, PercentRollingWindows, RatioRollingWindows,
},
};
@@ -55,7 +55,6 @@ impl Vecs {
indexes,
)?,
subsidy_dominance_rolling,
subsidy_sma_1y: FiatPerBlock::forced_import(db, "subsidy_sma_1y", version, indexes)?,
fee_to_subsidy_ratio: RatioRollingWindows::forced_import(
db,
"fee_to_subsidy_ratio",

View File

@@ -1,11 +1,10 @@
use brk_traversable::Traversable;
use brk_types::{BasisPoints16, BasisPoints32, Cents};
use brk_types::{BasisPoints16, BasisPoints32};
use vecdb::{Rw, StorageMode};
use crate::internal::{
AmountPerBlockCumulative, AmountPerBlockCumulativeRolling, AmountPerBlockFull,
FiatPerBlock, LazyPercentRollingWindows, PercentPerBlock, PercentRollingWindows,
RatioRollingWindows,
LazyPercentRollingWindows, PercentPerBlock, PercentRollingWindows, RatioRollingWindows,
};
#[derive(Traversable)]
@@ -22,8 +21,6 @@ pub struct Vecs<M: StorageMode = Rw> {
pub subsidy_dominance: PercentPerBlock<BasisPoints16, M>,
#[traversable(wrap = "subsidy", rename = "dominance")]
pub subsidy_dominance_rolling: LazyPercentRollingWindows<BasisPoints16>,
#[traversable(wrap = "subsidy", rename = "sma_1y")]
pub subsidy_sma_1y: FiatPerBlock<Cents, M>,
#[traversable(wrap = "fees", rename = "to_subsidy_ratio")]
pub fee_to_subsidy_ratio: RatioRollingWindows<BasisPoints32, M>,
}

View File

@@ -22,7 +22,7 @@ impl Vecs {
let version = parent_version;
let count = CountVecs::forced_import(&db, version, indexes, cached_starts)?;
let value = ValueVecs::forced_import(&db, version, indexes, cached_starts)?;
let value = ValueVecs::forced_import(&db, version, indexes)?;
let this = Self { db, count, value };
finalize_db(&this.db, &this)?;

View File

@@ -14,7 +14,7 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.op_return.compute(
self.op_return.compute_with(
starting_indexes.height,
prices,
exit,

View File

@@ -3,22 +3,20 @@ use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{indexes, internal::{AmountPerBlockCumulativeRolling, CachedWindowStarts}};
use crate::{indexes, internal::AmountPerBlockCumulative};
impl Vecs {
pub(crate) fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts,
) -> Result<Self> {
Ok(Self {
op_return: AmountPerBlockCumulativeRolling::forced_import(
op_return: AmountPerBlockCumulative::forced_import(
db,
"op_return_value",
version,
indexes,
cached_starts,
)?,
})
}

View File

@@ -1,9 +1,9 @@
use brk_traversable::Traversable;
use vecdb::{Rw, StorageMode};
use crate::internal::AmountPerBlockCumulativeRolling;
use crate::internal::AmountPerBlockCumulative;
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub op_return: AmountPerBlockCumulativeRolling<M>,
pub op_return: AmountPerBlockCumulative<M>,
}

View File

@@ -1,6 +1,6 @@
use brk_error::Result;
use brk_types::{Height, Indexes, Sats};
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, VecIndex, WritableVec};
use brk_types::{Indexes, Sats};
use vecdb::{Exit, VecIndex};
use super::Vecs;
use crate::{mining, prices, scripts};
@@ -14,46 +14,21 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let op_return_height = &scripts.value.op_return.block.sats;
let unclaimed_height = &mining.rewards.unclaimed.block.sats;
self.total.compute(
self.total.compute_with(
starting_indexes.height,
prices,
exit,
|height_vec| {
let unspendable_dep_version =
op_return_height.version() + unclaimed_height.version();
height_vec.validate_computed_version_or_reset(unspendable_dep_version)?;
let op_return_target = op_return_height.len();
if op_return_target > 0 {
let target_height = Height::from(op_return_target - 1);
let current_len = height_vec.len();
let starting_height =
Height::from(current_len.min(starting_indexes.height.to_usize()));
if starting_height <= target_height {
let start = starting_height.to_usize();
let end = target_height.to_usize() + 1;
let unclaimed_data = unclaimed_height.collect_range_at(start, end);
height_vec.truncate_if_needed(starting_height)?;
op_return_height.fold_range_at(start, end, start, |idx, op_return| {
let unclaimed = unclaimed_data[idx - start];
let genesis = if idx == 0 {
Sats::FIFTY_BTC
} else {
Sats::ZERO
};
let unspendable = genesis + op_return + unclaimed;
height_vec.push(unspendable);
idx + 1
});
}
}
height_vec.write()?;
Ok(())
|sats| {
Ok(sats.compute_transform2(
starting_indexes.height,
&scripts.value.op_return.block.sats,
&mining.rewards.unclaimed.block.sats,
|(h, op_return, unclaimed, ..)| {
let genesis = if h.to_usize() == 0 { Sats::FIFTY_BTC } else { Sats::ZERO };
(h, genesis + op_return + unclaimed)
},
exit,
)?)
},
)?;

View File

@@ -3,22 +3,20 @@ use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{indexes, internal::{AmountPerBlockCumulativeRolling, CachedWindowStarts}};
use crate::{indexes, internal::AmountPerBlockCumulative};
impl Vecs {
pub(crate) fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
cached_starts: &CachedWindowStarts,
) -> Result<Self> {
Ok(Self {
total: AmountPerBlockCumulativeRolling::forced_import(
total: AmountPerBlockCumulative::forced_import(
db,
"unspendable_supply",
version,
indexes,
cached_starts,
)?,
})
}

View File

@@ -1,10 +1,10 @@
use brk_traversable::Traversable;
use vecdb::{Rw, StorageMode};
use crate::internal::AmountPerBlockCumulativeRolling;
use crate::internal::AmountPerBlockCumulative;
#[derive(Traversable)]
#[traversable(transparent)]
pub struct Vecs<M: StorageMode = Rw> {
pub total: AmountPerBlockCumulativeRolling<M>,
pub total: AmountPerBlockCumulative<M>,
}

View File

@@ -34,7 +34,7 @@ impl Vecs {
let circulating =
LazyAmountPerBlock::identity("circulating_supply", &supply_metrics.total, version);
let burned = burned::Vecs::forced_import(&db, version, indexes, cached_starts)?;
let burned = burned::Vecs::forced_import(&db, version, indexes)?;
// Inflation rate
let inflation_rate = PercentPerBlock::forced_import(

View File

@@ -1852,42 +1852,6 @@ function createAverageBlockCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern(
* @property {_1m1w1y24hPattern<T>} sum
*/
/**
* @typedef {Object} AverageGainsLossesRsiStochPattern
* @property {SeriesPattern1<StoredF32>} averageGain
* @property {SeriesPattern1<StoredF32>} averageLoss
* @property {SeriesPattern1<StoredF32>} gains
* @property {SeriesPattern1<StoredF32>} losses
* @property {BpsPercentRatioPattern3} rsi
* @property {BpsPercentRatioPattern3} rsiMax
* @property {BpsPercentRatioPattern3} rsiMin
* @property {BpsPercentRatioPattern3} stochRsi
* @property {BpsPercentRatioPattern3} stochRsiD
* @property {BpsPercentRatioPattern3} stochRsiK
*/
/**
* Create a AverageGainsLossesRsiStochPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated series name
* @param {string} disc - Discriminator suffix
* @returns {AverageGainsLossesRsiStochPattern}
*/
function createAverageGainsLossesRsiStochPattern(client, acc, disc) {
return {
averageGain: createSeriesPattern1(client, _m(_m(acc, 'average_gain'), disc)),
averageLoss: createSeriesPattern1(client, _m(_m(acc, 'average_loss'), disc)),
gains: createSeriesPattern1(client, _m(_m(acc, 'gains'), disc)),
losses: createSeriesPattern1(client, _m(_m(acc, 'losses'), disc)),
rsi: createBpsPercentRatioPattern3(client, _m(acc, disc)),
rsiMax: createBpsPercentRatioPattern3(client, _m(_m(acc, 'max'), disc)),
rsiMin: createBpsPercentRatioPattern3(client, _m(_m(acc, 'min'), disc)),
stochRsi: createBpsPercentRatioPattern3(client, _m(_m(acc, 'stoch'), disc)),
stochRsiD: createBpsPercentRatioPattern3(client, _m(_m(acc, 'stoch_d'), disc)),
stochRsiK: createBpsPercentRatioPattern3(client, _m(_m(acc, 'stoch_k'), disc)),
};
}
/**
* @typedef {Object} AllP2aP2pk33P2pk65P2pkhP2shP2trP2wpkhP2wshPattern3
* @property {SeriesPattern1<StoredU64>} all
@@ -3437,7 +3401,7 @@ function createCentsSatsUsdPattern(client, acc) {
* @typedef {Object} CumulativeRollingSumPattern
* @property {SeriesPattern1<StoredU64>} cumulative
* @property {AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern} rolling
* @property {SeriesPattern1<StoredU64>} sum
* @property {SeriesPattern18<StoredU64>} sum
*/
/**
@@ -3450,7 +3414,7 @@ function createCumulativeRollingSumPattern(client, acc) {
return {
cumulative: createSeriesPattern1(client, _m(acc, 'cumulative')),
rolling: createAverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern(client, acc),
sum: createSeriesPattern1(client, _m(acc, 'sum')),
sum: createSeriesPattern18(client, _m(acc, 'sum')),
};
}
@@ -3510,6 +3474,28 @@ function createNuplRealizedSupplyPattern(client, acc) {
* @property {AverageBlockCumulativeSumPattern<Cents>} valueDestroyed
*/
/**
* @typedef {Object} RsiStochPattern
* @property {BpsPercentRatioPattern3} rsi
* @property {BpsPercentRatioPattern3} stochRsiD
* @property {BpsPercentRatioPattern3} stochRsiK
*/
/**
* Create a RsiStochPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated series name
* @param {string} disc - Discriminator suffix
* @returns {RsiStochPattern}
*/
function createRsiStochPattern(client, acc, disc) {
return {
rsi: createBpsPercentRatioPattern3(client, _m(acc, disc)),
stochRsiD: createBpsPercentRatioPattern3(client, _m(_m(acc, 'stoch_d'), disc)),
stochRsiK: createBpsPercentRatioPattern3(client, _m(_m(acc, 'stoch_k'), disc)),
};
}
/**
* @template T
* @typedef {Object} _6bBlockTxPattern
@@ -3611,7 +3597,7 @@ function createAllSthPattern(client, acc) {
/**
* @typedef {Object} BaseSumPattern
* @property {SeriesPattern1<Dollars>} base
* @property {SeriesPattern18<Dollars>} base
* @property {_1m1w1y24hPattern<Dollars>} sum
*/
@@ -3623,7 +3609,7 @@ function createAllSthPattern(client, acc) {
*/
function createBaseSumPattern(client, acc) {
return {
base: createSeriesPattern1(client, acc),
base: createSeriesPattern18(client, acc),
sum: create_1m1w1y24hPattern(client, _m(acc, 'sum')),
};
}
@@ -3647,6 +3633,25 @@ function createBaseDeltaPattern(client, acc) {
};
}
/**
* @typedef {Object} BlockCumulativePattern
* @property {BtcCentsSatsUsdPattern2} block
* @property {BtcCentsSatsUsdPattern3} cumulative
*/
/**
* Create a BlockCumulativePattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated series name
* @returns {BlockCumulativePattern}
*/
function createBlockCumulativePattern(client, acc) {
return {
block: createBtcCentsSatsUsdPattern2(client, acc),
cumulative: createBtcCentsSatsUsdPattern3(client, _m(acc, 'cumulative')),
};
}
/**
* @typedef {Object} BlocksDominancePattern
* @property {AverageBlockCumulativeSumPattern2} blocksMined
@@ -4470,7 +4475,7 @@ function createUnspentPattern(client, acc) {
/**
* @typedef {Object} SeriesTree_Scripts_Value
* @property {AverageBlockCumulativeSumPattern3} opReturn
* @property {BlockCumulativePattern} opReturn
*/
/**
@@ -4484,7 +4489,7 @@ function createUnspentPattern(client, acc) {
* @property {AverageBlockCumulativeSumPattern3} coinbase
* @property {SeriesTree_Mining_Rewards_Subsidy} subsidy
* @property {SeriesTree_Mining_Rewards_Fees} fees
* @property {SeriesTree_Mining_Rewards_Unclaimed} unclaimed
* @property {BlockCumulativePattern} unclaimed
*/
/**
@@ -4494,7 +4499,6 @@ function createUnspentPattern(client, acc) {
* @property {_1m1w1y24hPattern4} sum
* @property {_1m1w1y24hPattern3} average
* @property {_1m1w1y24hBpsPercentRatioPattern} dominance
* @property {CentsUsdPattern3} sma1y
*/
/**
@@ -4522,12 +4526,6 @@ function createUnspentPattern(client, acc) {
* @property {BpsRatioPattern2} _1y
*/
/**
* @typedef {Object} SeriesTree_Mining_Rewards_Unclaimed
* @property {BtcCentsSatsUsdPattern2} block
* @property {BtcCentsSatsUsdPattern3} cumulative
*/
/**
* @typedef {Object} SeriesTree_Mining_Hashrate
* @property {SeriesTree_Mining_Hashrate_Rate} rate
@@ -5173,17 +5171,15 @@ function createUnspentPattern(client, acc) {
/**
* @typedef {Object} SeriesTree_Market_Technical
* @property {SeriesTree_Market_Technical_Rsi} rsi
* @property {BpsPercentRatioPattern3} stochK
* @property {BpsPercentRatioPattern3} stochD
* @property {BpsRatioPattern2} piCycle
* @property {SeriesTree_Market_Technical_Macd} macd
*/
/**
* @typedef {Object} SeriesTree_Market_Technical_Rsi
* @property {AverageGainsLossesRsiStochPattern} _24h
* @property {AverageGainsLossesRsiStochPattern} _1w
* @property {AverageGainsLossesRsiStochPattern} _1m
* @property {RsiStochPattern} _24h
* @property {RsiStochPattern} _1w
* @property {RsiStochPattern} _1m
*/
/**
@@ -5430,7 +5426,7 @@ function createUnspentPattern(client, acc) {
* @typedef {Object} SeriesTree_Supply
* @property {SeriesPattern18<SupplyState>} state
* @property {BtcCentsSatsUsdPattern3} circulating
* @property {AverageBlockCumulativeSumPattern3} burned
* @property {BlockCumulativePattern} burned
* @property {BpsPercentRatioPattern} inflationRate
* @property {SeriesTree_Supply_Velocity} velocity
* @property {CentsDeltaUsdPattern} marketCap
@@ -7836,7 +7832,7 @@ class BrkClient extends BrkClientBase {
unknownOutput: createAverageBlockCumulativeSumPattern(this, 'unknown_output_count'),
},
value: {
opReturn: createAverageBlockCumulativeSumPattern3(this, 'op_return_value'),
opReturn: createBlockCumulativePattern(this, 'op_return_value'),
},
},
mining: {
@@ -7848,7 +7844,6 @@ class BrkClient extends BrkClientBase {
sum: create_1m1w1y24hPattern4(this, 'subsidy_sum'),
average: create_1m1w1y24hPattern3(this, 'subsidy_average'),
dominance: create_1m1w1y24hBpsPercentRatioPattern(this, 'subsidy_dominance'),
sma1y: createCentsUsdPattern3(this, 'subsidy_sma_1y'),
},
fees: {
block: createBtcCentsSatsUsdPattern2(this, 'fees'),
@@ -7870,10 +7865,7 @@ class BrkClient extends BrkClientBase {
_1y: createBpsRatioPattern2(this, 'fee_to_subsidy_ratio_1y'),
},
},
unclaimed: {
block: createBtcCentsSatsUsdPattern2(this, 'unclaimed_rewards'),
cumulative: createBtcCentsSatsUsdPattern3(this, 'unclaimed_rewards_cumulative'),
},
unclaimed: createBlockCumulativePattern(this, 'unclaimed_rewards'),
},
hashrate: {
rate: {
@@ -8312,12 +8304,10 @@ class BrkClient extends BrkClientBase {
},
technical: {
rsi: {
_24h: createAverageGainsLossesRsiStochPattern(this, 'rsi', '24h'),
_1w: createAverageGainsLossesRsiStochPattern(this, 'rsi', '1w'),
_1m: createAverageGainsLossesRsiStochPattern(this, 'rsi', '1m'),
_24h: createRsiStochPattern(this, 'rsi', '24h'),
_1w: createRsiStochPattern(this, 'rsi', '1w'),
_1m: createRsiStochPattern(this, 'rsi', '1m'),
},
stochK: createBpsPercentRatioPattern3(this, 'stoch_k'),
stochD: createBpsPercentRatioPattern3(this, 'stoch_d'),
piCycle: createBpsRatioPattern2(this, 'pi_cycle'),
macd: {
_24h: {
@@ -8534,7 +8524,7 @@ class BrkClient extends BrkClientBase {
supply: {
state: createSeriesPattern18(this, 'supply_state'),
circulating: createBtcCentsSatsUsdPattern3(this, 'circulating_supply'),
burned: createAverageBlockCumulativeSumPattern3(this, 'unspendable_supply'),
burned: createBlockCumulativePattern(this, 'unspendable_supply'),
inflationRate: createBpsPercentRatioPattern(this, 'inflation_rate'),
velocity: {
native: createSeriesPattern1(this, 'velocity'),

View File

@@ -2246,22 +2246,6 @@ class AverageBaseCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern(Generic[T]
"""Pattern struct for repeated tree structure."""
pass
class AverageGainsLossesRsiStochPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str, disc: str):
"""Create pattern node with accumulated series name."""
self.average_gain: SeriesPattern1[StoredF32] = SeriesPattern1(client, _m(acc, f'average_gain_{disc}'))
self.average_loss: SeriesPattern1[StoredF32] = SeriesPattern1(client, _m(acc, f'average_loss_{disc}'))
self.gains: SeriesPattern1[StoredF32] = SeriesPattern1(client, _m(acc, f'gains_{disc}'))
self.losses: SeriesPattern1[StoredF32] = SeriesPattern1(client, _m(acc, f'losses_{disc}'))
self.rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, disc))
self.rsi_max: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'max_{disc}'))
self.rsi_min: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'min_{disc}'))
self.stoch_rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'stoch_{disc}'))
self.stoch_rsi_d: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'stoch_d_{disc}'))
self.stoch_rsi_k: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'stoch_k_{disc}'))
class AllP2aP2pk33P2pk65P2pkhP2shP2trP2wpkhP2wshPattern3:
"""Pattern struct for repeated tree structure."""
@@ -2942,7 +2926,7 @@ class CumulativeRollingSumPattern:
"""Create pattern node with accumulated series name."""
self.cumulative: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'cumulative'))
self.rolling: AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern = AverageMaxMedianMinPct10Pct25Pct75Pct90SumPattern(client, acc)
self.sum: SeriesPattern1[StoredU64] = SeriesPattern1(client, _m(acc, 'sum'))
self.sum: SeriesPattern18[StoredU64] = SeriesPattern18(client, _m(acc, 'sum'))
class GreedNetPainPattern:
"""Pattern struct for repeated tree structure."""
@@ -2970,6 +2954,15 @@ class RatioTransferValuePattern:
"""Pattern struct for repeated tree structure."""
pass
class RsiStochPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str, disc: str):
"""Create pattern node with accumulated series name."""
self.rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, disc))
self.stoch_rsi_d: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'stoch_d_{disc}'))
self.stoch_rsi_k: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'stoch_k_{disc}'))
class _6bBlockTxPattern(Generic[T]):
"""Pattern struct for repeated tree structure."""
@@ -3016,7 +3009,7 @@ class BaseSumPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated series name."""
self.base: SeriesPattern1[Dollars] = SeriesPattern1(client, acc)
self.base: SeriesPattern18[Dollars] = SeriesPattern18(client, acc)
self.sum: _1m1w1y24hPattern[Dollars] = _1m1w1y24hPattern(client, _m(acc, 'sum'))
class BaseDeltaPattern:
@@ -3027,6 +3020,14 @@ class BaseDeltaPattern:
self.base: SeriesPattern1[StoredU64] = SeriesPattern1(client, acc)
self.delta: AbsoluteRatePattern = AbsoluteRatePattern(client, _m(acc, 'delta'))
class BlockCumulativePattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated series name."""
self.block: BtcCentsSatsUsdPattern2 = BtcCentsSatsUsdPattern2(client, acc)
self.cumulative: BtcCentsSatsUsdPattern3 = BtcCentsSatsUsdPattern3(client, _m(acc, 'cumulative'))
class BlocksDominancePattern:
"""Pattern struct for repeated tree structure."""
@@ -3663,7 +3664,7 @@ class SeriesTree_Scripts_Value:
"""Series tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.op_return: AverageBlockCumulativeSumPattern3 = AverageBlockCumulativeSumPattern3(client, 'op_return_value')
self.op_return: BlockCumulativePattern = BlockCumulativePattern(client, 'op_return_value')
class SeriesTree_Scripts:
"""Series tree node."""
@@ -3682,7 +3683,6 @@ class SeriesTree_Mining_Rewards_Subsidy:
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'subsidy_sum')
self.average: _1m1w1y24hPattern3 = _1m1w1y24hPattern3(client, 'subsidy_average')
self.dominance: _1m1w1y24hBpsPercentRatioPattern = _1m1w1y24hBpsPercentRatioPattern(client, 'subsidy_dominance')
self.sma_1y: CentsUsdPattern3 = CentsUsdPattern3(client, 'subsidy_sma_1y')
class SeriesTree_Mining_Rewards_Fees_ToSubsidyRatio:
"""Series tree node."""
@@ -3711,13 +3711,6 @@ class SeriesTree_Mining_Rewards_Fees:
self.dominance: _1m1w1y24hBpsPercentRatioPattern = _1m1w1y24hBpsPercentRatioPattern(client, 'fee_dominance')
self.to_subsidy_ratio: SeriesTree_Mining_Rewards_Fees_ToSubsidyRatio = SeriesTree_Mining_Rewards_Fees_ToSubsidyRatio(client)
class SeriesTree_Mining_Rewards_Unclaimed:
"""Series tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.block: BtcCentsSatsUsdPattern2 = BtcCentsSatsUsdPattern2(client, 'unclaimed_rewards')
self.cumulative: BtcCentsSatsUsdPattern3 = BtcCentsSatsUsdPattern3(client, 'unclaimed_rewards_cumulative')
class SeriesTree_Mining_Rewards:
"""Series tree node."""
@@ -3725,7 +3718,7 @@ class SeriesTree_Mining_Rewards:
self.coinbase: AverageBlockCumulativeSumPattern3 = AverageBlockCumulativeSumPattern3(client, 'coinbase')
self.subsidy: SeriesTree_Mining_Rewards_Subsidy = SeriesTree_Mining_Rewards_Subsidy(client)
self.fees: SeriesTree_Mining_Rewards_Fees = SeriesTree_Mining_Rewards_Fees(client)
self.unclaimed: SeriesTree_Mining_Rewards_Unclaimed = SeriesTree_Mining_Rewards_Unclaimed(client)
self.unclaimed: BlockCumulativePattern = BlockCumulativePattern(client, 'unclaimed_rewards')
class SeriesTree_Mining_Hashrate_Rate_Sma:
"""Series tree node."""
@@ -4438,9 +4431,9 @@ class SeriesTree_Market_Technical_Rsi:
"""Series tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self._24h: AverageGainsLossesRsiStochPattern = AverageGainsLossesRsiStochPattern(client, 'rsi', '24h')
self._1w: AverageGainsLossesRsiStochPattern = AverageGainsLossesRsiStochPattern(client, 'rsi', '1w')
self._1m: AverageGainsLossesRsiStochPattern = AverageGainsLossesRsiStochPattern(client, 'rsi', '1m')
self._24h: RsiStochPattern = RsiStochPattern(client, 'rsi', '24h')
self._1w: RsiStochPattern = RsiStochPattern(client, 'rsi', '1w')
self._1m: RsiStochPattern = RsiStochPattern(client, 'rsi', '1m')
class SeriesTree_Market_Technical_Macd_24h:
"""Series tree node."""
@@ -4485,8 +4478,6 @@ class SeriesTree_Market_Technical:
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.rsi: SeriesTree_Market_Technical_Rsi = SeriesTree_Market_Technical_Rsi(client)
self.stoch_k: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'stoch_k')
self.stoch_d: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'stoch_d')
self.pi_cycle: BpsRatioPattern2 = BpsRatioPattern2(client, 'pi_cycle')
self.macd: SeriesTree_Market_Technical_Macd = SeriesTree_Market_Technical_Macd(client)
@@ -4729,7 +4720,7 @@ class SeriesTree_Supply:
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.state: SeriesPattern18[SupplyState] = SeriesPattern18(client, 'supply_state')
self.circulating: BtcCentsSatsUsdPattern3 = BtcCentsSatsUsdPattern3(client, 'circulating_supply')
self.burned: AverageBlockCumulativeSumPattern3 = AverageBlockCumulativeSumPattern3(client, 'unspendable_supply')
self.burned: BlockCumulativePattern = BlockCumulativePattern(client, 'unspendable_supply')
self.inflation_rate: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'inflation_rate')
self.velocity: SeriesTree_Supply_Velocity = SeriesTree_Supply_Velocity(client)
self.market_cap: CentsDeltaUsdPattern = CentsDeltaUsdPattern(client, 'market_cap')

View File

@@ -41,7 +41,7 @@ function volumeTree(tv, color, title) {
return [
...satsBtcUsdFullTree({
pattern: tv,
title: title("Sent Volume"),
title: title("Transfer Volume"),
color,
}),
{
@@ -49,7 +49,7 @@ function volumeTree(tv, color, title) {
tree: [
...ROLLING_WINDOWS.map((w) => ({
name: w.name,
title: title(`Sent Volume Profitability (${w.title})`),
title: title(`Transfer Volume Profitability (${w.title})`),
bottom: [
...satsBtcUsd({
pattern: tv.inProfit.sum[w.key],
@@ -65,7 +65,7 @@ function volumeTree(tv, color, title) {
})),
{
name: "Cumulative",
title: title("Cumulative Sent Volume Profitability"),
title: title("Cumulative Transfer Volume"),
bottom: [
...satsBtcUsd({
pattern: tv.inProfit.cumulative,
@@ -83,7 +83,7 @@ function volumeTree(tv, color, title) {
name: "In Profit",
tree: satsBtcUsdFullTree({
pattern: tv.inProfit,
title: title("Sent In Profit"),
title: title("Transfer Volume In Profit"),
color: colors.profit,
}),
},
@@ -91,7 +91,7 @@ function volumeTree(tv, color, title) {
name: "In Loss",
tree: satsBtcUsdFullTree({
pattern: tv.inLoss,
title: title("Sent In Loss"),
title: title("Transfer Volume In Loss"),
color: colors.loss,
}),
},
@@ -360,7 +360,7 @@ export function createActivitySectionMinimal({ cohort, title }) {
name: "Activity",
tree: satsBtcUsdFullTree({
pattern: cohort.tree.activity.transferVolume,
title: title("Volume"),
title: title("Transfer Volume"),
}),
};
}
@@ -399,7 +399,7 @@ function groupedProfitabilityArray(list, all, title, getInProfit, getInLoss) {
list,
all,
title,
metricTitle: "Sent In Profit",
metricTitle: "Transfer Volume In Profit",
getMetric: (c) => getInProfit(c),
}),
},
@@ -409,7 +409,7 @@ function groupedProfitabilityArray(list, all, title, getInProfit, getInLoss) {
list,
all,
title,
metricTitle: "Sent In Loss",
metricTitle: "Transfer Volume In Loss",
getMetric: (c) => getInLoss(c),
}),
},
@@ -431,7 +431,7 @@ function groupedVolumeTree(list, all, title, getTransferVolume) {
list,
all,
title,
metricTitle: "Sent Volume",
metricTitle: "Transfer Volume",
getMetric: (c) => getTransferVolume(c),
}),
...groupedProfitabilityArray(

View File

@@ -136,7 +136,7 @@ function groupedWeightFolder({ list, all, getAvgPrice, getInProfit, getInLoss, g
return [
{
name: "Average",
title: title(`${avgTitle} Comparison`),
title: title(`Cost Basis ${avgTitle} (${weightLabel})`),
top: mapCohortsWithAll(list, all, (c) =>
price({ series: getAvgPrice(c), name: c.name, color: c.color }),
),

View File

@@ -82,7 +82,7 @@ function singleDeltaItems(delta, unit, title, name) {
{
...rollingPercentRatioTree({
windows: delta.rate,
title: title(`${name} Rate`),
title: title(`${name} Growth Rate`),
}),
name: "Growth Rate",
},
@@ -121,7 +121,7 @@ function groupedDeltaItems(list, all, getDelta, unit, title, name) {
name: "Growth Rate",
tree: ROLLING_WINDOWS.map((w) => ({
name: w.name,
title: title(`${name} Rate (${w.title})`),
title: title(`${name} Growth Rate (${w.title})`),
bottom: flatMapCohortsWithAll(list, all, (c) =>
percentRatioBaseline({
pattern: getDelta(c).rate[w.key],
@@ -212,17 +212,18 @@ function ownSupplyChart(supply, title) {
* Count folder (UTXO or Address) with value + change
* @param {{ base: AnySeriesPattern, delta: DeltaPattern }} pattern
* @param {string} name
* @param {string} chartTitle
* @param {Color} color
* @param {(name: string) => string} title
* @returns {PartialOptionsGroup}
*/
function countFolder(pattern, name, color, title) {
function countFolder(pattern, name, chartTitle, color, title) {
return {
name,
tree: [
{
name: "Count",
title: title(name),
title: title(chartTitle),
bottom: [
line({
series: pattern.base,
@@ -259,7 +260,7 @@ export function createHoldingsSection({ cohort, title }) {
...singleDeltaItems(supply.delta, Unit.sats, title, "Change"),
],
},
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", cohort.color, title),
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
];
}
@@ -283,8 +284,8 @@ export function createHoldingsSectionAll({ cohort, title }) {
...singleDeltaItems(supply.delta, Unit.sats, title, "Change"),
],
},
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", cohort.color, title),
countFolder(cohort.addressCount, "Addresses", cohort.color, title),
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
countFolder(cohort.addressCount, "Addresses", "Address Count", cohort.color, title),
];
}
@@ -309,7 +310,7 @@ export function createHoldingsSectionWithRelative({ cohort, title }) {
...singleDeltaItems(supply.delta, Unit.sats, title, "Change"),
],
},
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", cohort.color, title),
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
];
}
@@ -333,7 +334,7 @@ export function createHoldingsSectionWithOwnSupply({ cohort, title }) {
...singleDeltaItems(supply.delta, Unit.sats, title, "Change"),
],
},
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", cohort.color, title),
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
];
}
@@ -356,7 +357,7 @@ export function createHoldingsSectionWithProfitLoss({ cohort, title }) {
...singleDeltaItems(supply.delta, Unit.sats, title, "Change"),
],
},
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", cohort.color, title),
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
];
}
@@ -379,8 +380,8 @@ export function createHoldingsSectionAddress({ cohort, title }) {
...singleDeltaItems(supply.delta, Unit.sats, title, "Change"),
],
},
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", cohort.color, title),
countFolder(cohort.addressCount, "Addresses", cohort.color, title),
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
countFolder(cohort.addressCount, "Addresses", "Address Count", cohort.color, title),
];
}
@@ -402,8 +403,8 @@ export function createHoldingsSectionAddressAmount({ cohort, title }) {
...singleDeltaItems(supply.delta, Unit.sats, title, "Change"),
],
},
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", cohort.color, title),
countFolder(cohort.addressCount, "Addresses", cohort.color, title),
countFolder(cohort.tree.outputs.unspentCount, "UTXOs", "UTXO Count", cohort.color, title),
countFolder(cohort.addressCount, "Addresses", "Address Count", cohort.color, title),
];
}

View File

@@ -65,6 +65,7 @@ import {
createProfitabilitySectionWithInvestedCapitalPct,
createProfitabilitySectionLongTerm,
createGroupedProfitabilitySection,
createGroupedProfitabilitySectionWithProfitLoss,
createGroupedProfitabilitySectionWithNupl,
createGroupedProfitabilitySectionWithInvestedCapitalPct,
} from "./profitability.js";
@@ -91,7 +92,7 @@ export { buildCohortData } from "./data.js";
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderAll(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -111,7 +112,7 @@ export function createCohortFolderAll(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderFull(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -131,7 +132,7 @@ export function createCohortFolderFull(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderWithAdjusted(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -150,7 +151,7 @@ export function createCohortFolderWithAdjusted(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderWithNupl(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -170,7 +171,7 @@ export function createCohortFolderWithNupl(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderLongTerm(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -190,7 +191,7 @@ export function createCohortFolderLongTerm(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderAgeRange(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -210,7 +211,7 @@ export function createCohortFolderAgeRange(cohort) {
*/
export function createCohortFolderAgeRangeWithMatured(cohort) {
const folder = createCohortFolderAgeRange(cohort);
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
folder.tree.push({
name: "Matured",
tree: satsBtcUsdFullTree({
@@ -227,7 +228,7 @@ export function createCohortFolderAgeRangeWithMatured(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderBasicWithMarketCap(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -247,7 +248,7 @@ export function createCohortFolderBasicWithMarketCap(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderAddress(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -266,7 +267,7 @@ export function createCohortFolderAddress(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createCohortFolderWithoutRelative(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -285,7 +286,7 @@ export function createCohortFolderWithoutRelative(cohort) {
* @returns {PartialOptionsGroup}
*/
export function createAddressCohortFolder(cohort) {
const title = formatCohortTitle(cohort.name);
const title = formatCohortTitle(cohort.title);
return {
name: cohort.name || "all",
tree: [
@@ -455,7 +456,7 @@ export function createGroupedCohortFolderAddress({
...createGroupedHoldingsSectionAddress({ list, all, title }),
createGroupedValuationSection({ list, all, title }),
createGroupedPricesSection({ list, all, title }),
createGroupedProfitabilitySection({
createGroupedProfitabilitySectionWithProfitLoss({
list,
all,
title,

View File

@@ -100,6 +100,19 @@ function relPnlChart(profit, loss, name, title) {
};
}
/** @param {{ percent: AnySeriesPattern, ratio: AnySeriesPattern }} net @param {{ percent: AnySeriesPattern, ratio: AnySeriesPattern }} profit @param {{ percent: AnySeriesPattern, ratio: AnySeriesPattern }} loss @param {string} name @param {(name: string) => string} title */
function relPnlChartWithNet(net, profit, loss, name, title) {
return {
name,
title: title(`Unrealized P&L (${name})`),
bottom: [
...percentRatioBaseline({ pattern: net, name: "Net" }),
...percentRatio({ pattern: profit, name: "Profit", color: colors.profit }),
...percentRatio({ pattern: loss, name: "Loss", color: colors.loss }),
],
};
}
/**
* Core unrealized items: Overview + Net + NUPL + Profit + Loss
* @param {{ profit: { usd: AnySeriesPattern }, loss: { usd: AnySeriesPattern, negative: AnySeriesPattern }, netPnl: { usd: AnySeriesPattern }, nupl: NuplPattern }} u
@@ -142,6 +155,30 @@ function unrealizedCore(u, title) {
];
}
/**
* Core unrealized items + Gross
* @param {{ profit: { usd: AnySeriesPattern }, loss: { usd: AnySeriesPattern, negative: AnySeriesPattern }, netPnl: { usd: AnySeriesPattern }, grossPnl: { usd: AnySeriesPattern }, nupl: NuplPattern }} u
* @param {(name: string) => string} title
* @returns {PartialOptionsTree}
*/
function unrealizedCoreWithGross(u, title) {
return [
...unrealizedCore(u, title),
{
name: "Gross",
title: title("Gross Unrealized P&L"),
bottom: [
line({
series: u.grossPnl.usd,
name: "Gross",
color: colors.gross,
unit: Unit.usd,
}),
],
},
];
}
/**
* % of Own P&L chart
* @param {AllRelativePattern | FullRelativePattern} u
@@ -173,7 +210,7 @@ function ownPnlChart(u, title) {
/** @param {AllRelativePattern} u @param {(name: string) => string} title */
function unrealizedTreeAll(u, title) {
return [
...unrealizedCore(u, title),
...unrealizedCoreWithGross(u, title),
ownPnlChart(u, title),
relPnlChart(u.profit.toMcap, u.loss.toMcap, "% of Market Cap", title),
];
@@ -182,22 +219,17 @@ function unrealizedTreeAll(u, title) {
/** @param {FullRelativePattern} u @param {(name: string) => string} title */
function unrealizedTreeFull(u, title) {
return [
...unrealizedCore(u, title),
...unrealizedCoreWithGross(u, title),
ownPnlChart(u, title),
relPnlChart(u.profit.toMcap, u.loss.toMcap, "% of Market Cap", title),
relPnlChart(
u.profit.toOwnMcap,
u.loss.toOwnMcap,
"% of Own Market Cap",
title,
),
relPnlChartWithNet(u.netPnl.toOwnMcap, u.profit.toOwnMcap, u.loss.toOwnMcap, "% of Own Market Cap", title),
];
}
/** @param {FullRelativePattern} u @param {(name: string) => string} title */
function unrealizedTreeLongTerm(u, title) {
return [
...unrealizedCore(u, title),
...unrealizedCoreWithGross(u, title),
ownPnlChart(u, title),
{
name: "% of Market Cap",
@@ -208,12 +240,7 @@ function unrealizedTreeLongTerm(u, title) {
color: colors.loss,
}),
},
relPnlChart(
u.profit.toOwnMcap,
u.loss.toOwnMcap,
"% of Own Market Cap",
title,
),
relPnlChartWithNet(u.netPnl.toOwnMcap, u.profit.toOwnMcap, u.loss.toOwnMcap, "% of Own Market Cap", title),
];
}
@@ -300,7 +327,7 @@ function realizedMetricFolder({ pattern, metricTitle, color, title }) {
})),
{
name: "Cumulative",
title: title(`Realized ${metricTitle} (Total)`),
title: title(`Cumulative Realized ${metricTitle}`),
bottom: [
line({
series: pattern.cumulative.usd,
@@ -350,7 +377,7 @@ function realizedNetFolder({ netPnl, title, extraChange = [] }) {
})),
{
name: "Cumulative",
title: title("Net Realized P&L (Total)"),
title: title("Cumulative Net Realized P&L"),
bottom: [
baseline({
series: netPnl.cumulative.usd,
@@ -372,7 +399,7 @@ function realizedNetFolder({ netPnl, title, extraChange = [] }) {
tree: [
...rollingPercentRatioTree({
windows: netPnl.delta.rate,
title: title("Net Realized P&L Rate"),
title: title("Net Realized P&L Growth Rate"),
}).tree,
...extraChange,
],
@@ -587,7 +614,7 @@ function realizedSubfolderFull(r, title) {
})),
{
name: "Cumulative",
title: title("Peak Regret (Total)"),
title: title("Cumulative Peak Regret"),
bottom: [
line({
series: r.peakRegret.cumulative.usd,
@@ -706,6 +733,16 @@ export function createProfitabilitySectionWithProfitLoss({ cohort, title }) {
{
name: "Unrealized",
tree: [
{
name: "Overview",
title: title("Unrealized P&L"),
bottom: [
line({ series: u.profit.usd, name: "Profit", color: colors.profit, unit: Unit.usd }),
line({ series: u.loss.negative, name: "Neg. Loss", color: colors.loss, unit: Unit.usd }),
line({ series: u.loss.usd, name: "Loss", color: colors.loss, unit: Unit.usd, defaultActive: false }),
priceLine({ unit: Unit.usd }),
],
},
{ name: "NUPL", title: title("NUPL"), bottom: nuplSeries(u.nupl) },
{
name: "Profit",
@@ -840,32 +877,49 @@ export function createProfitabilitySectionWithInvestedCapitalPct({
* @param {(name: string) => string} title
* @returns {PartialOptionsGroup}
*/
/**
* Grouped realized profit + loss items
* @param {readonly UtxoCohortObject[]} list
* @param {CohortAll} all
* @param {(name: string) => string} title
* @returns {PartialOptionsTree}
*/
function groupedRealizedProfitLossItems(list, all, title) {
return [
{ name: "Profit", tree: groupedWindowsCumulativeUsd({ list, all, title, metricTitle: "Realized Profit", getMetric: (c) => c.tree.realized.profit }) },
{ name: "Loss", tree: groupedWindowsCumulativeUsd({ list, all, title, metricTitle: "Realized Loss", getMetric: (c) => c.tree.realized.loss }) },
];
}
/**
* Grouped realized net item
* @param {readonly (CohortAgeRange | CohortWithAdjusted | CohortAll | CohortFull | CohortLongTerm)[]} list
* @param {CohortAll} all
* @param {(name: string) => string} title
* @returns {PartialOptionsGroup}
*/
function groupedRealizedNetItem(list, all, title) {
return { name: "Net", tree: groupedWindowsCumulativeUsd({ list, all, title, metricTitle: "Net Realized P&L", getMetric: (c) => c.tree.realized.netPnl, seriesFn: baseline }) };
}
/**
* @param {readonly UtxoCohortObject[]} list
* @param {CohortAll} all
* @param {(name: string) => string} title
* @returns {PartialOptionsGroup}
*/
function groupedRealizedSubfolder(list, all, title) {
return {
name: "Realized",
tree: [
{
name: "Profit",
tree: groupedWindowsCumulativeUsd({
list,
all,
title,
metricTitle: "Realized Profit",
getMetric: (c) => c.tree.realized.profit,
}),
},
{
name: "Loss",
tree: groupedWindowsCumulativeUsd({
list,
all,
title,
metricTitle: "Realized Loss",
getMetric: (c) => c.tree.realized.loss,
}),
},
],
};
return { name: "Realized", tree: groupedRealizedProfitLossItems(list, all, title) };
}
/**
* @param {readonly (CohortAgeRange | CohortWithAdjusted)[]} list
* @param {CohortAll} all
* @param {(name: string) => string} title
* @returns {PartialOptionsGroup}
*/
function groupedRealizedSubfolderMid(list, all, title) {
return { name: "Realized", tree: [groupedRealizedNetItem(list, all, title), ...groupedRealizedProfitLossItems(list, all, title)] };
}
/**
@@ -896,7 +950,7 @@ function groupedRealizedNetPnlDeltaItems(list, all, title) {
name: "Growth Rate",
tree: ROLLING_WINDOWS.map((w) => ({
name: w.name,
title: title(`Net Realized P&L Rate (${w.title})`),
title: title(`Net Realized P&L Growth Rate (${w.title})`),
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
percentRatioBaseline({
pattern: tree.realized.netPnl.delta.rate[w.key],
@@ -934,26 +988,7 @@ function groupedRealizedSubfolderFull(list, all, title) {
...groupedRealizedNetPnlDeltaItems(list, all, title),
],
},
{
name: "Profit",
tree: groupedWindowsCumulativeUsd({
list,
all,
title,
metricTitle: "Realized Profit",
getMetric: (c) => c.tree.realized.profit,
}),
},
{
name: "Loss",
tree: groupedWindowsCumulativeUsd({
list,
all,
title,
metricTitle: "Realized Loss",
getMetric: (c) => c.tree.realized.loss,
}),
},
...groupedRealizedProfitLossItems(list, all, title),
{
name: "Gross",
tree: groupedWindowsCumulativeUsd({
@@ -1234,7 +1269,7 @@ export function createGroupedProfitabilitySectionWithInvestedCapitalPct({
name: "Profitability",
tree: [
{ name: "Unrealized", tree: groupedUnrealizedMid(list, all, title) },
groupedRealizedSubfolder(list, all, title),
groupedRealizedSubfolderMid(list, all, title),
],
};
}

View File

@@ -20,7 +20,7 @@ import { ratioBottomSeries, mapCohortsWithAll, flatMapCohortsWithAll } from "../
function singleDeltaItems(tree, title) {
return [
{ ...sumsTreeBaseline({ windows: mapWindows(tree.realized.cap.delta.absolute, (c) => c.usd), title: title("Realized Cap Change"), unit: Unit.usd }), name: "Change" },
{ ...rollingPercentRatioTree({ windows: tree.realized.cap.delta.rate, title: title("Realized Cap Rate") }), name: "Growth Rate" },
{ ...rollingPercentRatioTree({ windows: tree.realized.cap.delta.rate, title: title("Realized Cap Growth Rate") }), name: "Growth Rate" },
];
}
@@ -54,7 +54,7 @@ function groupedDeltaAndMvrv(list, all, title) {
name: "Growth Rate",
tree: ROLLING_WINDOWS.map((w) => ({
name: w.name,
title: title(`Realized Cap Rate (${w.title})`),
title: title(`Realized Cap Growth Rate (${w.title})`),
bottom: flatMapCohortsWithAll(list, all, ({ name, color, tree }) =>
percentRatioBaseline({ pattern: tree.realized.cap.delta.rate[w.key], name, color }),
),

View File

@@ -5,13 +5,13 @@ import { entries, includes } from "../utils/array.js";
import { colors } from "../utils/colors.js";
import {
line,
baseline,
dots,
dotted,
distributionBtcSatsUsd,
statsAtWindow,
ROLLING_WINDOWS,
percentRatio,
percentRatioBaseline,
chartsFromCount,
} from "./series.js";
import {
@@ -438,7 +438,7 @@ export function createMiningSection() {
{
name: "Adjustment",
title: "Difficulty Adjustment",
bottom: [baseline({ series: blocks.difficulty.adjustment.percent, name: "Change", unit: Unit.percentage })],
bottom: percentRatioBaseline({ pattern: blocks.difficulty.adjustment, name: "Change" }),
},
{
name: "Countdown",

View File

@@ -15,40 +15,31 @@ function walkSeries(node, map, path) {
for (const [key, value] of Object.entries(node)) {
const kn = key.toLowerCase();
if (
key === "lookback" ||
key === "cumulativeMarketCap" ||
key === "sd24h" ||
key === "spot" ||
key === "ohlc" ||
key === "state" ||
key === "emaSlow" ||
key === "emaFast" ||
key.endsWith("Raw") ||
key.endsWith("Cents") ||
key.endsWith("State") ||
key.endsWith("Start") ||
kn === "cents" ||
kn === "bps" ||
kn === "mvrv" ||
kn === "constants" ||
kn === "blockhash" ||
kn === "date" ||
kn === "ohlc" ||
kn === "split" ||
kn === "outpoint" ||
kn === "positions" ||
kn === "heighttopool" ||
kn === "txid" ||
kn === "spot" ||
kn.startsWith("timestamp") ||
kn.startsWith("satdays") ||
kn.startsWith("satblocks") ||
kn.startsWith("coinyears") ||
kn.endsWith("index") ||
kn.endsWith("indexes")
)
continue;
walkSeries(/** @type {TreeNode | null | undefined} */ (value), map, [
...path,
key,
]);
const newPath = [...path, key];
const joined = newPath.join(".");
if (
joined.endsWith(".count.total.average") ||
joined.endsWith(".versions.v1.average") ||
joined.endsWith(".versions.v2.average") ||
joined.endsWith(".versions.v3.average")
)
continue;
walkSeries(/** @type {TreeNode | null | undefined} */ (value), map, newPath);
}
}
}