From 9f20664c6eaad38cebcb87e18c744c5ed64a3b1c Mon Sep 17 00:00:00 2001 From: nym21 Date: Fri, 9 May 2025 16:04:54 +0200 Subject: [PATCH] global: add some market charts --- README.md | 1 + .../vecs/{marketprice.rs => fetched.rs} | 0 .../storage/vecs/grouped/value_from_height.rs | 17 +- .../vecs/grouped/value_from_txindex.rs | 14 +- .../brk_computer/src/storage/vecs/market.rs | 253 ++++++++++++++++++ crates/brk_computer/src/storage/vecs/mod.rs | 35 ++- .../src/storage/vecs/transactions.rs | 16 +- crates/brk_core/src/structs/cents.rs | 15 ++ crates/brk_core/src/structs/dollars.rs | 6 +- crates/brk_core/src/structs/sats.rs | 15 ++ crates/brk_core/src/structs/stored_f64.rs | 1 + crates/brk_core/src/structs/stored_usize.rs | 1 + crates/brk_vec/src/traits/iterator.rs | 7 +- websites/kibo.money/index.html | 6 +- websites/kibo.money/scripts/main.js | 14 +- websites/kibo.money/scripts/options.js | 88 +++++- .../kibo.money/scripts/vecid-to-indexes.js | 6 + 17 files changed, 449 insertions(+), 46 deletions(-) rename crates/brk_computer/src/storage/vecs/{marketprice.rs => fetched.rs} (100%) create mode 100644 crates/brk_computer/src/storage/vecs/market.rs diff --git a/README.md b/README.md index 62465a0a4..2f208d645 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ If you'd like to have your own instance hosted for you please contact [hosting@b - Configurated for speed (`raw + eager`) - Updates delivered at your convenience - Direct communication for feature requests and support +- Bitcoin Core or Knots with desired version - Optional subdomains: `*.bitcoinresearchkit.org`, `*.kibo.money` and `*.satonomics.xyz` - Logo featured in the Readme if desired diff --git a/crates/brk_computer/src/storage/vecs/marketprice.rs b/crates/brk_computer/src/storage/vecs/fetched.rs similarity index 100% rename from crates/brk_computer/src/storage/vecs/marketprice.rs rename to crates/brk_computer/src/storage/vecs/fetched.rs diff --git a/crates/brk_computer/src/storage/vecs/grouped/value_from_height.rs b/crates/brk_computer/src/storage/vecs/grouped/value_from_height.rs index 08cbd4cb0..a44c5918a 100644 --- a/crates/brk_computer/src/storage/vecs/grouped/value_from_height.rs +++ b/crates/brk_computer/src/storage/vecs/grouped/value_from_height.rs @@ -8,7 +8,7 @@ use brk_vec::{ }; use crate::storage::{ - marketprice, + fetched, vecs::{Indexes, indexes}, }; @@ -68,7 +68,7 @@ impl ComputedValueVecsFromHeight { &mut self, indexer: &Indexer, indexes: &indexes::Vecs, - marketprices: Option<&marketprice::Vecs>, + fetched: Option<&fetched::Vecs>, starting_indexes: &Indexes, exit: &Exit, mut compute: F, @@ -91,14 +91,7 @@ impl ComputedValueVecsFromHeight { )?; let height: Option<&StoredVec> = None; - self.compute_rest( - indexer, - indexes, - marketprices, - starting_indexes, - exit, - height, - )?; + self.compute_rest(indexer, indexes, fetched, starting_indexes, exit, height)?; Ok(()) } @@ -107,7 +100,7 @@ impl ComputedValueVecsFromHeight { &mut self, indexer: &Indexer, indexes: &indexes::Vecs, - marketprices: Option<&marketprice::Vecs>, + fetched: Option<&fetched::Vecs>, starting_indexes: &Indexes, exit: &Exit, height: Option<&impl CollectableVec>, @@ -147,7 +140,7 @@ impl ComputedValueVecsFromHeight { } let txindex = self.bitcoin.height.as_ref().unwrap(); - let price = &marketprices.as_ref().unwrap().chainindexes_to_close.height; + let price = &fetched.as_ref().unwrap().chainindexes_to_close.height; if let Some(dollars) = self.dollars.as_mut() { dollars.compute_all( diff --git a/crates/brk_computer/src/storage/vecs/grouped/value_from_txindex.rs b/crates/brk_computer/src/storage/vecs/grouped/value_from_txindex.rs index 3ec8d330d..7daa6cead 100644 --- a/crates/brk_computer/src/storage/vecs/grouped/value_from_txindex.rs +++ b/crates/brk_computer/src/storage/vecs/grouped/value_from_txindex.rs @@ -9,7 +9,7 @@ use brk_vec::{ }; use crate::storage::{ - marketprice, + fetched, vecs::{Indexes, indexes}, }; @@ -48,11 +48,11 @@ impl ComputedValueVecsFromTxindex { version: Version, computation: Computation, compressed: Compressed, - marketprices: Option<&marketprice::Vecs>, + fetched: Option<&fetched::Vecs>, options: StorableVecGeneatorOptions, ) -> color_eyre::Result { let compute_source = source.is_none(); - let compute_dollars = marketprices.is_some(); + let compute_dollars = fetched.is_some(); let sats = ComputedVecsFromTxindex::forced_import( path, @@ -84,7 +84,7 @@ impl ComputedValueVecsFromTxindex { options, )?; - let dollars_txindex = marketprices.map(|marketprices| { + let dollars_txindex = fetched.map(|fetched| { ComputedVecFrom3::forced_import_or_init_from_3( computation, path, @@ -93,7 +93,7 @@ impl ComputedValueVecsFromTxindex { compressed, bitcoin_txindex.boxed_clone(), indexes.txindex_to_height.boxed_clone(), - marketprices.chainindexes_to_close.height.boxed_clone(), + fetched.chainindexes_to_close.height.boxed_clone(), |txindex: TxIndex, txindex_to_btc_iter, txindex_to_height_iter, @@ -138,7 +138,7 @@ impl ComputedValueVecsFromTxindex { // &mut self, // indexer: &Indexer, // indexes: &indexes::Vecs, - // marketprices: Option<&marketprice::Vecs>, + // fetched: Option<&marketprice::Vecs>, // starting_indexes: &Indexes, // exit: &Exit, // mut compute: F, @@ -164,7 +164,7 @@ impl ComputedValueVecsFromTxindex { // self.compute_rest( // indexer, // indexes, - // marketprices, + // fetched, // starting_indexes, // exit, // txindex, diff --git a/crates/brk_computer/src/storage/vecs/market.rs b/crates/brk_computer/src/storage/vecs/market.rs new file mode 100644 index 000000000..ef43aa5f4 --- /dev/null +++ b/crates/brk_computer/src/storage/vecs/market.rs @@ -0,0 +1,253 @@ +use std::{fs, path::Path}; + +use brk_core::{Dollars, StoredF64, StoredUsize}; +use brk_exit::Exit; +use brk_indexer::Indexer; +use brk_vec::{AnyCollectableVec, Compressed, Computation, StoredIndex, VecIterator, Version}; + +use super::{ + Indexes, fetched, + grouped::{ComputedVecsFromDateindex, StorableVecGeneatorOptions}, + indexes, transactions, +}; + +#[derive(Clone)] +pub struct Vecs { + pub indexes_to_marketcap: ComputedVecsFromDateindex, + pub indexes_to_ath: ComputedVecsFromDateindex, + pub indexes_to_drawdown: ComputedVecsFromDateindex, + pub indexes_to_days_since_ath: ComputedVecsFromDateindex, + pub indexes_to_max_days_between_ath: ComputedVecsFromDateindex, + pub indexes_to_max_years_between_ath: ComputedVecsFromDateindex, +} + +impl Vecs { + pub fn forced_import( + path: &Path, + _computation: Computation, + compressed: Compressed, + ) -> color_eyre::Result { + fs::create_dir_all(path)?; + + Ok(Self { + indexes_to_marketcap: ComputedVecsFromDateindex::forced_import( + path, + "marketcap", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_last(), + )?, + indexes_to_ath: ComputedVecsFromDateindex::forced_import( + path, + "ath", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_last(), + )?, + indexes_to_drawdown: ComputedVecsFromDateindex::forced_import( + path, + "drawdown", + Version::ONE, + compressed, + StorableVecGeneatorOptions::default().add_last(), + )?, + indexes_to_days_since_ath: ComputedVecsFromDateindex::forced_import( + path, + "days_since_ath", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_last(), + )?, + indexes_to_max_days_between_ath: ComputedVecsFromDateindex::forced_import( + path, + "max_days_between_ath", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_last(), + )?, + indexes_to_max_years_between_ath: ComputedVecsFromDateindex::forced_import( + path, + "max_years_between_ath", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_last(), + )?, + }) + } + + pub fn compute( + &mut self, + indexer: &Indexer, + indexes: &indexes::Vecs, + fetched: &fetched::Vecs, + transactions: &mut transactions::Vecs, + starting_indexes: &Indexes, + exit: &Exit, + ) -> color_eyre::Result<()> { + self.indexes_to_marketcap.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + let mut total_subsidy_in_btc = transactions + .indexes_to_subsidy + .bitcoin + .dateindex + .unwrap_total() + .into_iter(); + v.compute_transform( + starting_indexes.dateindex, + &fetched.timeindexes_to_close.dateindex, + |(i, close, ..)| { + let supply = total_subsidy_in_btc.unwrap_get_inner(i); + (i, *close * supply) + }, + exit, + ) + }, + )?; + + self.indexes_to_ath.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + let mut prev = None; + v.compute_transform( + starting_indexes.dateindex, + &fetched.timeindexes_to_high.dateindex, + |(i, high, slf)| { + if prev.is_none() { + let i = i.unwrap_to_usize(); + prev.replace(if i > 0 { + slf.into_iter().unwrap_get_inner_(i - 1) + } else { + Dollars::ZERO + }); + } + let ath = prev.unwrap().max(*high); + prev.replace(ath); + (i, ath) + }, + exit, + ) + }, + )?; + + self.indexes_to_drawdown.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + let mut close_iter = fetched.timeindexes_to_close.dateindex.into_iter(); + + v.compute_transform( + starting_indexes.dateindex, + &self.indexes_to_ath.dateindex, + |(i, ath, ..)| { + if ath == Dollars::ZERO { + return (i, StoredF64::default()); + } + let close = *close_iter.unwrap_get_inner(i); + let drawdown = StoredF64::from((*ath - *close) / *ath * -100.0); + (i, drawdown) + }, + exit, + ) + }, + )?; + + self.indexes_to_days_since_ath.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + let mut high_iter = fetched.timeindexes_to_high.dateindex.into_iter(); + let mut prev = None; + v.compute_transform( + starting_indexes.dateindex, + &self.indexes_to_ath.dateindex, + |(i, ath, slf)| { + if prev.is_none() { + let i = i.unwrap_to_usize(); + prev.replace(if i > 0 { + slf.into_iter().unwrap_get_inner_(i - 1) + } else { + StoredUsize::default() + }); + } + let days = if *high_iter.unwrap_get_inner(i) == ath { + StoredUsize::default() + } else { + prev.unwrap() + StoredUsize::from(1) + }; + prev.replace(days); + (i, days) + }, + exit, + ) + }, + )?; + + self.indexes_to_max_days_between_ath.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + let mut prev = None; + v.compute_transform( + starting_indexes.dateindex, + &self.indexes_to_days_since_ath.dateindex, + |(i, days, slf)| { + if prev.is_none() { + let i = i.unwrap_to_usize(); + prev.replace(if i > 0 { + slf.into_iter().unwrap_get_inner_(i - 1) + } else { + StoredUsize::ZERO + }); + } + let max = prev.unwrap().max(days); + prev.replace(max); + (i, max) + }, + exit, + ) + }, + )?; + + self.indexes_to_max_years_between_ath.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_transform( + starting_indexes.dateindex, + &self.indexes_to_max_days_between_ath.dateindex, + |(i, max, ..)| (i, StoredF64::from(*max as f64 / 365.0)), + exit, + ) + }, + )?; + + Ok(()) + } + + pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> { + [ + self.indexes_to_marketcap.vecs(), + self.indexes_to_ath.vecs(), + self.indexes_to_drawdown.vecs(), + self.indexes_to_days_since_ath.vecs(), + self.indexes_to_max_days_between_ath.vecs(), + self.indexes_to_max_years_between_ath.vecs(), + ] + .concat() + } +} diff --git a/crates/brk_computer/src/storage/vecs/mod.rs b/crates/brk_computer/src/storage/vecs/mod.rs index 199b0e8e2..c75c74005 100644 --- a/crates/brk_computer/src/storage/vecs/mod.rs +++ b/crates/brk_computer/src/storage/vecs/mod.rs @@ -6,9 +6,10 @@ use brk_indexer::Indexer; use brk_vec::{AnyCollectableVec, Compressed, Computation}; pub mod blocks; +pub mod fetched; pub mod grouped; pub mod indexes; -pub mod marketprice; +pub mod market; pub mod mining; pub mod transactions; @@ -19,8 +20,9 @@ pub struct Vecs { pub indexes: indexes::Vecs, pub blocks: blocks::Vecs, pub mining: mining::Vecs, + pub market: market::Vecs, pub transactions: transactions::Vecs, - pub marketprice: Option, + pub fetched: Option, } impl Vecs { @@ -35,22 +37,23 @@ impl Vecs { let indexes = indexes::Vecs::forced_import(path, indexer, computation, compressed)?; - let marketprice = - fetch.then(|| marketprice::Vecs::forced_import(path, computation, compressed).unwrap()); + let fetched = + fetch.then(|| fetched::Vecs::forced_import(path, computation, compressed).unwrap()); Ok(Self { blocks: blocks::Vecs::forced_import(path, computation, compressed)?, mining: mining::Vecs::forced_import(path, computation, compressed)?, + market: market::Vecs::forced_import(path, computation, compressed)?, transactions: transactions::Vecs::forced_import( path, indexer, &indexes, computation, compressed, - marketprice.as_ref(), + fetched.as_ref(), )?, indexes, - marketprice, + fetched, }) } @@ -69,8 +72,8 @@ impl Vecs { self.mining .compute(indexer, &self.indexes, &starting_indexes, exit)?; - if let Some(marketprice) = self.marketprice.as_mut() { - marketprice.compute( + if let Some(fetched) = self.fetched.as_mut() { + fetched.compute( indexer, &self.indexes, &starting_indexes, @@ -83,10 +86,21 @@ impl Vecs { indexer, &self.indexes, &starting_indexes, - self.marketprice.as_ref(), + self.fetched.as_ref(), exit, )?; + if let Some(fetched) = self.fetched.as_ref() { + self.market.compute( + indexer, + &self.indexes, + fetched, + &mut self.transactions, + &starting_indexes, + exit, + )?; + } + Ok(()) } @@ -95,8 +109,9 @@ impl Vecs { self.indexes.vecs(), self.blocks.vecs(), self.mining.vecs(), + self.market.vecs(), self.transactions.vecs(), - self.marketprice.as_ref().map_or(vec![], |v| v.vecs()), + self.fetched.as_ref().map_or(vec![], |v| v.vecs()), ] .concat() } diff --git a/crates/brk_computer/src/storage/vecs/transactions.rs b/crates/brk_computer/src/storage/vecs/transactions.rs index bc53cc8f9..6fef32281 100644 --- a/crates/brk_computer/src/storage/vecs/transactions.rs +++ b/crates/brk_computer/src/storage/vecs/transactions.rs @@ -13,12 +13,12 @@ use brk_vec::{ }; use super::{ - Indexes, + Indexes, fetched, grouped::{ ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromHeight, ComputedVecsFromTxindex, StorableVecGeneatorOptions, }, - indexes, marketprice, + indexes, }; #[derive(Clone)] @@ -94,9 +94,9 @@ impl Vecs { indexes: &indexes::Vecs, computation: Computation, compressed: Compressed, - marketprices: Option<&marketprice::Vecs>, + fetched: Option<&fetched::Vecs>, ) -> color_eyre::Result { - let compute_dollars = marketprices.is_some(); + let compute_dollars = fetched.is_some(); fs::create_dir_all(path)?; @@ -455,7 +455,7 @@ impl Vecs { Version::ZERO, computation, compressed, - marketprices, + fetched, StorableVecGeneatorOptions::default() .add_sum() .add_total() @@ -700,7 +700,7 @@ impl Vecs { indexer: &Indexer, indexes: &indexes::Vecs, starting_indexes: &Indexes, - marketprices: Option<&marketprice::Vecs>, + fetched: Option<&fetched::Vecs>, exit: &Exit, ) -> color_eyre::Result<()> { self.indexes_to_tx_count.compute_all( @@ -845,7 +845,7 @@ impl Vecs { self.indexes_to_coinbase.compute_all( indexer, indexes, - marketprices, + fetched, starting_indexes, exit, |vec, indexer, _, starting_indexes, exit| { @@ -878,7 +878,7 @@ impl Vecs { self.indexes_to_subsidy.compute_all( indexer, indexes, - marketprices, + fetched, starting_indexes, exit, |vec, _, _, starting_indexes, exit| { diff --git a/crates/brk_core/src/structs/cents.rs b/crates/brk_core/src/structs/cents.rs index 7cb1a3d43..e892790ba 100644 --- a/crates/brk_core/src/structs/cents.rs +++ b/crates/brk_core/src/structs/cents.rs @@ -59,3 +59,18 @@ impl Div for Cents { Self(self.0 / rhs as u64) } } + +impl From for Cents { + fn from(value: u128) -> Self { + if value > u64::MAX as u128 { + panic!("u128 bigger than u64") + } + Self(value as u64) + } +} + +impl From for u128 { + fn from(value: Cents) -> Self { + value.0 as u128 + } +} diff --git a/crates/brk_core/src/structs/dollars.rs b/crates/brk_core/src/structs/dollars.rs index 32a014a33..15d061ef9 100644 --- a/crates/brk_core/src/structs/dollars.rs +++ b/crates/brk_core/src/structs/dollars.rs @@ -22,6 +22,10 @@ use super::{Bitcoin, Cents, Sats}; )] pub struct Dollars(f64); +impl Dollars { + pub const ZERO: Self = Self(0.0); +} + impl From for Dollars { fn from(value: f64) -> Self { Self(value) @@ -73,7 +77,7 @@ impl Mul for Dollars { type Output = Dollars; fn mul(self, rhs: Bitcoin) -> Self::Output { Self::from(Cents::from( - u64::from(Sats::from(rhs)) * u64::from(Cents::from(self)) / u64::from(Sats::ONE_BTC), + u128::from(Sats::from(rhs)) * u128::from(Cents::from(self)) / u128::from(Sats::ONE_BTC), )) } } diff --git a/crates/brk_core/src/structs/sats.rs b/crates/brk_core/src/structs/sats.rs index 920f0deed..8ecd232e2 100644 --- a/crates/brk_core/src/structs/sats.rs +++ b/crates/brk_core/src/structs/sats.rs @@ -156,3 +156,18 @@ impl From for u64 { value.0 } } + +impl From for Sats { + fn from(value: u128) -> Self { + if value > u64::MAX as u128 { + panic!("u128 bigger than u64") + } + Self(value as u64) + } +} + +impl From for u128 { + fn from(value: Sats) -> Self { + value.0 as u128 + } +} diff --git a/crates/brk_core/src/structs/stored_f64.rs b/crates/brk_core/src/structs/stored_f64.rs index 356c82f25..42b63c755 100644 --- a/crates/brk_core/src/structs/stored_f64.rs +++ b/crates/brk_core/src/structs/stored_f64.rs @@ -9,6 +9,7 @@ use crate::CheckedSub; #[derive( Debug, Deref, + Default, Clone, Copy, PartialEq, diff --git a/crates/brk_core/src/structs/stored_usize.rs b/crates/brk_core/src/structs/stored_usize.rs index 26c209b16..d24ef950c 100644 --- a/crates/brk_core/src/structs/stored_usize.rs +++ b/crates/brk_core/src/structs/stored_usize.rs @@ -16,6 +16,7 @@ use super::{ Debug, Deref, Clone, + Default, Copy, PartialEq, Eq, diff --git a/crates/brk_vec/src/traits/iterator.rs b/crates/brk_vec/src/traits/iterator.rs index f08a2a6b2..6ed1258da 100644 --- a/crates/brk_vec/src/traits/iterator.rs +++ b/crates/brk_vec/src/traits/iterator.rs @@ -53,7 +53,12 @@ pub trait VecIterator<'a>: BaseVecIterator)> #[inline] fn unwrap_get_inner(&mut self, i: Self::I) -> Self::T { - self.get_(i.unwrap_to_usize()).unwrap().into_inner() + self.unwrap_get_inner_(i.unwrap_to_usize()) + } + + #[inline] + fn unwrap_get_inner_(&mut self, i: usize) -> Self::T { + self.get_(i).unwrap().into_inner() } #[inline] diff --git a/websites/kibo.money/index.html b/websites/kibo.money/index.html index 5bdae76f6..47339f1d8 100644 --- a/websites/kibo.money/index.html +++ b/websites/kibo.money/index.html @@ -441,9 +441,9 @@ h1, h2 { text-transform: uppercase; - font-size: var(--font-size-2xl); - line-height: var(--line-height-2xl); - font-weight: 300; + font-size: var(--font-size-xl); + line-height: var(--line-height-xl); + font-weight: 350; } h3 { diff --git a/websites/kibo.money/scripts/main.js b/websites/kibo.money/scripts/main.js index 63b86c1a6..ae7c7ad21 100644 --- a/websites/kibo.money/scripts/main.js +++ b/websites/kibo.money/scripts/main.js @@ -25,7 +25,7 @@ * "Hash" | * "Index" | * "mb" | - * "%" | + * "percentage" | * "Ratio" | * "Sats" | * "Seconds" | @@ -37,6 +37,8 @@ * "Version" | * "WU" | * "Bool" | + * "Days" | + * "Years" | * "Locktime" | * "sat/vB" | * "vB" @@ -686,6 +688,10 @@ function createUtils() { unit = "Index"; } else if (id.includes("type")) { unit = "Type"; + } else if (id.includes("days-")) { + unit = "Days"; + } else if (id.includes("years-")) { + unit = "Years"; } else if (id === "rawlocktime") { unit = "Locktime"; } else if (id.startsWith("is-")) { @@ -722,7 +728,9 @@ function createUtils() { id.includes("high") || id.includes("low") || id.includes("close") || - id.includes("ohlc") + id.includes("ohlc") || + id.includes("marketcap") || + id.includes("ath") ) { unit = "USD"; } else if (id.includes("count") || id.match(/v[1-3]/g)) { @@ -743,6 +751,8 @@ function createUtils() { unit = "Version"; } else if (id === "value") { unit = "Sats"; + } else if (id === "drawdown") { + unit = "percentage"; } else { console.log(); throw Error(`Unit not set for "${id}"`); diff --git a/websites/kibo.money/scripts/options.js b/websites/kibo.money/scripts/options.js index 89e8161f3..508ef9fba 100644 --- a/websites/kibo.money/scripts/options.js +++ b/websites/kibo.money/scripts/options.js @@ -168,9 +168,10 @@ function createPartialOptions(colors) { * @param {Object} args * @param {ChartableVecId} args.key * @param {string} args.name + * @param {Color} [args.color] */ - function createBaseSeries({ key, name }) { - return { key, title: name }; + function createBaseSeries({ key, name, color }) { + return { key, title: name, color }; } /** @@ -564,6 +565,89 @@ function createPartialOptions(colors) { }, ], }, + { + name: "Market", + tree: [ + { + name: "Capitalization", + title: "Market Capitalization", + bottom: [ + createBaseSeries({ + key: "marketcap", + name: "Capitalization", + }), + ], + }, + { + name: "All Time High", + tree: [ + { + name: "Value", + title: "All Time High", + top: [ + createBaseSeries({ + key: "ath", + name: "ath", + }), + ], + }, + { + name: "drawdown", + title: "All Time High Drawdown", + top: [ + createBaseSeries({ + key: "ath", + name: "ath", + }), + ], + bottom: [ + createBaseSeries({ + key: "drawdown", + name: "Drawdown", + color: colors.red, + }), + ], + }, + { + name: "days since", + title: "Number of days Since All Time High", + top: [ + createBaseSeries({ + key: "ath", + name: "ath", + }), + ], + bottom: [ + createBaseSeries({ + key: "days-since-ath", + name: "Days", + }), + ], + }, + { + name: "max between", + title: "Maximum time between All Time Highs", + top: [ + createBaseSeries({ + key: "ath", + name: "ath", + }), + ], + bottom: [ + createBaseSeries({ + key: "max-days-between-ath", + name: "Days", + }), + createBaseSeries({ + key: "max-years-between-ath", + name: "Years", + }), + ], + }, + ], + }, + ], + }, ], }, { diff --git a/websites/kibo.money/scripts/vecid-to-indexes.js b/websites/kibo.money/scripts/vecid-to-indexes.js index 7c4b0fc28..ea6069e67 100644 --- a/websites/kibo.money/scripts/vecid-to-indexes.js +++ b/websites/kibo.money/scripts/vecid-to-indexes.js @@ -56,6 +56,7 @@ export function createVecIdToIndexes() { const YearIndex = /** @satisfies {YearIndex} */ (23); return /** @type {const} */ ({ + ath: [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "base-size": [TxIndex], "block-count": [Height], "block-count-sum": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex], @@ -108,9 +109,11 @@ export function createVecIdToIndexes() { "date-fixed": [Height], dateindex: [DateIndex, Height], "dateindex-count": [MonthIndex, WeekIndex], + "days-since-ath": [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex], decadeindex: [DecadeIndex, YearIndex], difficulty: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], difficultyepoch: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], + drawdown: [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "emptyoutput-count": [Height], "emptyoutput-count-10p": [DateIndex], "emptyoutput-count-25p": [DateIndex], @@ -202,6 +205,9 @@ export function createVecIdToIndexes() { low: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "low-in-cents": [DateIndex, Height], "low-in-sats": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], + marketcap: [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex], + "max-days-between-ath": [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex], + "max-years-between-ath": [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex], monthindex: [DateIndex, MonthIndex], "monthindex-count": [QuarterIndex, YearIndex], ohlc: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],