mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: snapshot part 16
This commit is contained in:
@@ -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()),
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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,
|
||||
)?;
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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>>,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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>,
|
||||
}
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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>,
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)?)
|
||||
},
|
||||
)?;
|
||||
|
||||
|
||||
@@ -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,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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>,
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 }),
|
||||
),
|
||||
|
||||
@@ -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),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 }),
|
||||
),
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user