global: add some market charts

This commit is contained in:
nym21
2025-05-09 16:04:54 +02:00
parent 851a6aac0e
commit 9f20664c6e
17 changed files with 449 additions and 46 deletions

View File

@@ -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`) - Configurated for speed (`raw + eager`)
- Updates delivered at your convenience - Updates delivered at your convenience
- Direct communication for feature requests and support - Direct communication for feature requests and support
- Bitcoin Core or Knots with desired version
- Optional subdomains: `*.bitcoinresearchkit.org`, `*.kibo.money` and `*.satonomics.xyz` - Optional subdomains: `*.bitcoinresearchkit.org`, `*.kibo.money` and `*.satonomics.xyz`
- Logo featured in the Readme if desired - Logo featured in the Readme if desired

View File

@@ -8,7 +8,7 @@ use brk_vec::{
}; };
use crate::storage::{ use crate::storage::{
marketprice, fetched,
vecs::{Indexes, indexes}, vecs::{Indexes, indexes},
}; };
@@ -68,7 +68,7 @@ impl ComputedValueVecsFromHeight {
&mut self, &mut self,
indexer: &Indexer, indexer: &Indexer,
indexes: &indexes::Vecs, indexes: &indexes::Vecs,
marketprices: Option<&marketprice::Vecs>, fetched: Option<&fetched::Vecs>,
starting_indexes: &Indexes, starting_indexes: &Indexes,
exit: &Exit, exit: &Exit,
mut compute: F, mut compute: F,
@@ -91,14 +91,7 @@ impl ComputedValueVecsFromHeight {
)?; )?;
let height: Option<&StoredVec<Height, Sats>> = None; let height: Option<&StoredVec<Height, Sats>> = None;
self.compute_rest( self.compute_rest(indexer, indexes, fetched, starting_indexes, exit, height)?;
indexer,
indexes,
marketprices,
starting_indexes,
exit,
height,
)?;
Ok(()) Ok(())
} }
@@ -107,7 +100,7 @@ impl ComputedValueVecsFromHeight {
&mut self, &mut self,
indexer: &Indexer, indexer: &Indexer,
indexes: &indexes::Vecs, indexes: &indexes::Vecs,
marketprices: Option<&marketprice::Vecs>, fetched: Option<&fetched::Vecs>,
starting_indexes: &Indexes, starting_indexes: &Indexes,
exit: &Exit, exit: &Exit,
height: Option<&impl CollectableVec<Height, Sats>>, height: Option<&impl CollectableVec<Height, Sats>>,
@@ -147,7 +140,7 @@ impl ComputedValueVecsFromHeight {
} }
let txindex = self.bitcoin.height.as_ref().unwrap(); 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() { if let Some(dollars) = self.dollars.as_mut() {
dollars.compute_all( dollars.compute_all(

View File

@@ -9,7 +9,7 @@ use brk_vec::{
}; };
use crate::storage::{ use crate::storage::{
marketprice, fetched,
vecs::{Indexes, indexes}, vecs::{Indexes, indexes},
}; };
@@ -48,11 +48,11 @@ impl ComputedValueVecsFromTxindex {
version: Version, version: Version,
computation: Computation, computation: Computation,
compressed: Compressed, compressed: Compressed,
marketprices: Option<&marketprice::Vecs>, fetched: Option<&fetched::Vecs>,
options: StorableVecGeneatorOptions, options: StorableVecGeneatorOptions,
) -> color_eyre::Result<Self> { ) -> color_eyre::Result<Self> {
let compute_source = source.is_none(); let compute_source = source.is_none();
let compute_dollars = marketprices.is_some(); let compute_dollars = fetched.is_some();
let sats = ComputedVecsFromTxindex::forced_import( let sats = ComputedVecsFromTxindex::forced_import(
path, path,
@@ -84,7 +84,7 @@ impl ComputedValueVecsFromTxindex {
options, options,
)?; )?;
let dollars_txindex = marketprices.map(|marketprices| { let dollars_txindex = fetched.map(|fetched| {
ComputedVecFrom3::forced_import_or_init_from_3( ComputedVecFrom3::forced_import_or_init_from_3(
computation, computation,
path, path,
@@ -93,7 +93,7 @@ impl ComputedValueVecsFromTxindex {
compressed, compressed,
bitcoin_txindex.boxed_clone(), bitcoin_txindex.boxed_clone(),
indexes.txindex_to_height.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: TxIndex,
txindex_to_btc_iter, txindex_to_btc_iter,
txindex_to_height_iter, txindex_to_height_iter,
@@ -138,7 +138,7 @@ impl ComputedValueVecsFromTxindex {
// &mut self, // &mut self,
// indexer: &Indexer, // indexer: &Indexer,
// indexes: &indexes::Vecs, // indexes: &indexes::Vecs,
// marketprices: Option<&marketprice::Vecs>, // fetched: Option<&marketprice::Vecs>,
// starting_indexes: &Indexes, // starting_indexes: &Indexes,
// exit: &Exit, // exit: &Exit,
// mut compute: F, // mut compute: F,
@@ -164,7 +164,7 @@ impl ComputedValueVecsFromTxindex {
// self.compute_rest( // self.compute_rest(
// indexer, // indexer,
// indexes, // indexes,
// marketprices, // fetched,
// starting_indexes, // starting_indexes,
// exit, // exit,
// txindex, // txindex,

View File

@@ -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<Dollars>,
pub indexes_to_ath: ComputedVecsFromDateindex<Dollars>,
pub indexes_to_drawdown: ComputedVecsFromDateindex<StoredF64>,
pub indexes_to_days_since_ath: ComputedVecsFromDateindex<StoredUsize>,
pub indexes_to_max_days_between_ath: ComputedVecsFromDateindex<StoredUsize>,
pub indexes_to_max_years_between_ath: ComputedVecsFromDateindex<StoredF64>,
}
impl Vecs {
pub fn forced_import(
path: &Path,
_computation: Computation,
compressed: Compressed,
) -> color_eyre::Result<Self> {
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()
}
}

View File

@@ -6,9 +6,10 @@ use brk_indexer::Indexer;
use brk_vec::{AnyCollectableVec, Compressed, Computation}; use brk_vec::{AnyCollectableVec, Compressed, Computation};
pub mod blocks; pub mod blocks;
pub mod fetched;
pub mod grouped; pub mod grouped;
pub mod indexes; pub mod indexes;
pub mod marketprice; pub mod market;
pub mod mining; pub mod mining;
pub mod transactions; pub mod transactions;
@@ -19,8 +20,9 @@ pub struct Vecs {
pub indexes: indexes::Vecs, pub indexes: indexes::Vecs,
pub blocks: blocks::Vecs, pub blocks: blocks::Vecs,
pub mining: mining::Vecs, pub mining: mining::Vecs,
pub market: market::Vecs,
pub transactions: transactions::Vecs, pub transactions: transactions::Vecs,
pub marketprice: Option<marketprice::Vecs>, pub fetched: Option<fetched::Vecs>,
} }
impl Vecs { impl Vecs {
@@ -35,22 +37,23 @@ impl Vecs {
let indexes = indexes::Vecs::forced_import(path, indexer, computation, compressed)?; let indexes = indexes::Vecs::forced_import(path, indexer, computation, compressed)?;
let marketprice = let fetched =
fetch.then(|| marketprice::Vecs::forced_import(path, computation, compressed).unwrap()); fetch.then(|| fetched::Vecs::forced_import(path, computation, compressed).unwrap());
Ok(Self { Ok(Self {
blocks: blocks::Vecs::forced_import(path, computation, compressed)?, blocks: blocks::Vecs::forced_import(path, computation, compressed)?,
mining: mining::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( transactions: transactions::Vecs::forced_import(
path, path,
indexer, indexer,
&indexes, &indexes,
computation, computation,
compressed, compressed,
marketprice.as_ref(), fetched.as_ref(),
)?, )?,
indexes, indexes,
marketprice, fetched,
}) })
} }
@@ -69,8 +72,8 @@ impl Vecs {
self.mining self.mining
.compute(indexer, &self.indexes, &starting_indexes, exit)?; .compute(indexer, &self.indexes, &starting_indexes, exit)?;
if let Some(marketprice) = self.marketprice.as_mut() { if let Some(fetched) = self.fetched.as_mut() {
marketprice.compute( fetched.compute(
indexer, indexer,
&self.indexes, &self.indexes,
&starting_indexes, &starting_indexes,
@@ -83,10 +86,21 @@ impl Vecs {
indexer, indexer,
&self.indexes, &self.indexes,
&starting_indexes, &starting_indexes,
self.marketprice.as_ref(), self.fetched.as_ref(),
exit, exit,
)?; )?;
if let Some(fetched) = self.fetched.as_ref() {
self.market.compute(
indexer,
&self.indexes,
fetched,
&mut self.transactions,
&starting_indexes,
exit,
)?;
}
Ok(()) Ok(())
} }
@@ -95,8 +109,9 @@ impl Vecs {
self.indexes.vecs(), self.indexes.vecs(),
self.blocks.vecs(), self.blocks.vecs(),
self.mining.vecs(), self.mining.vecs(),
self.market.vecs(),
self.transactions.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() .concat()
} }

View File

@@ -13,12 +13,12 @@ use brk_vec::{
}; };
use super::{ use super::{
Indexes, Indexes, fetched,
grouped::{ grouped::{
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromHeight, ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromHeight,
ComputedVecsFromTxindex, StorableVecGeneatorOptions, ComputedVecsFromTxindex, StorableVecGeneatorOptions,
}, },
indexes, marketprice, indexes,
}; };
#[derive(Clone)] #[derive(Clone)]
@@ -94,9 +94,9 @@ impl Vecs {
indexes: &indexes::Vecs, indexes: &indexes::Vecs,
computation: Computation, computation: Computation,
compressed: Compressed, compressed: Compressed,
marketprices: Option<&marketprice::Vecs>, fetched: Option<&fetched::Vecs>,
) -> color_eyre::Result<Self> { ) -> color_eyre::Result<Self> {
let compute_dollars = marketprices.is_some(); let compute_dollars = fetched.is_some();
fs::create_dir_all(path)?; fs::create_dir_all(path)?;
@@ -455,7 +455,7 @@ impl Vecs {
Version::ZERO, Version::ZERO,
computation, computation,
compressed, compressed,
marketprices, fetched,
StorableVecGeneatorOptions::default() StorableVecGeneatorOptions::default()
.add_sum() .add_sum()
.add_total() .add_total()
@@ -700,7 +700,7 @@ impl Vecs {
indexer: &Indexer, indexer: &Indexer,
indexes: &indexes::Vecs, indexes: &indexes::Vecs,
starting_indexes: &Indexes, starting_indexes: &Indexes,
marketprices: Option<&marketprice::Vecs>, fetched: Option<&fetched::Vecs>,
exit: &Exit, exit: &Exit,
) -> color_eyre::Result<()> { ) -> color_eyre::Result<()> {
self.indexes_to_tx_count.compute_all( self.indexes_to_tx_count.compute_all(
@@ -845,7 +845,7 @@ impl Vecs {
self.indexes_to_coinbase.compute_all( self.indexes_to_coinbase.compute_all(
indexer, indexer,
indexes, indexes,
marketprices, fetched,
starting_indexes, starting_indexes,
exit, exit,
|vec, indexer, _, starting_indexes, exit| { |vec, indexer, _, starting_indexes, exit| {
@@ -878,7 +878,7 @@ impl Vecs {
self.indexes_to_subsidy.compute_all( self.indexes_to_subsidy.compute_all(
indexer, indexer,
indexes, indexes,
marketprices, fetched,
starting_indexes, starting_indexes,
exit, exit,
|vec, _, _, starting_indexes, exit| { |vec, _, _, starting_indexes, exit| {

View File

@@ -59,3 +59,18 @@ impl Div<usize> for Cents {
Self(self.0 / rhs as u64) Self(self.0 / rhs as u64)
} }
} }
impl From<u128> for Cents {
fn from(value: u128) -> Self {
if value > u64::MAX as u128 {
panic!("u128 bigger than u64")
}
Self(value as u64)
}
}
impl From<Cents> for u128 {
fn from(value: Cents) -> Self {
value.0 as u128
}
}

View File

@@ -22,6 +22,10 @@ use super::{Bitcoin, Cents, Sats};
)] )]
pub struct Dollars(f64); pub struct Dollars(f64);
impl Dollars {
pub const ZERO: Self = Self(0.0);
}
impl From<f64> for Dollars { impl From<f64> for Dollars {
fn from(value: f64) -> Self { fn from(value: f64) -> Self {
Self(value) Self(value)
@@ -73,7 +77,7 @@ impl Mul<Bitcoin> for Dollars {
type Output = Dollars; type Output = Dollars;
fn mul(self, rhs: Bitcoin) -> Self::Output { fn mul(self, rhs: Bitcoin) -> Self::Output {
Self::from(Cents::from( 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),
)) ))
} }
} }

View File

@@ -156,3 +156,18 @@ impl From<Sats> for u64 {
value.0 value.0
} }
} }
impl From<u128> for Sats {
fn from(value: u128) -> Self {
if value > u64::MAX as u128 {
panic!("u128 bigger than u64")
}
Self(value as u64)
}
}
impl From<Sats> for u128 {
fn from(value: Sats) -> Self {
value.0 as u128
}
}

View File

@@ -9,6 +9,7 @@ use crate::CheckedSub;
#[derive( #[derive(
Debug, Debug,
Deref, Deref,
Default,
Clone, Clone,
Copy, Copy,
PartialEq, PartialEq,

View File

@@ -16,6 +16,7 @@ use super::{
Debug, Debug,
Deref, Deref,
Clone, Clone,
Default,
Copy, Copy,
PartialEq, PartialEq,
Eq, Eq,

View File

@@ -53,7 +53,12 @@ pub trait VecIterator<'a>: BaseVecIterator<Item = (Self::I, Value<'a, Self::T>)>
#[inline] #[inline]
fn unwrap_get_inner(&mut self, i: Self::I) -> Self::T { 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] #[inline]

View File

@@ -441,9 +441,9 @@
h1, h1,
h2 { h2 {
text-transform: uppercase; text-transform: uppercase;
font-size: var(--font-size-2xl); font-size: var(--font-size-xl);
line-height: var(--line-height-2xl); line-height: var(--line-height-xl);
font-weight: 300; font-weight: 350;
} }
h3 { h3 {

View File

@@ -25,7 +25,7 @@
* "Hash" | * "Hash" |
* "Index" | * "Index" |
* "mb" | * "mb" |
* "%" | * "percentage" |
* "Ratio" | * "Ratio" |
* "Sats" | * "Sats" |
* "Seconds" | * "Seconds" |
@@ -37,6 +37,8 @@
* "Version" | * "Version" |
* "WU" | * "WU" |
* "Bool" | * "Bool" |
* "Days" |
* "Years" |
* "Locktime" | * "Locktime" |
* "sat/vB" | * "sat/vB" |
* "vB" * "vB"
@@ -686,6 +688,10 @@ function createUtils() {
unit = "Index"; unit = "Index";
} else if (id.includes("type")) { } else if (id.includes("type")) {
unit = "Type"; unit = "Type";
} else if (id.includes("days-")) {
unit = "Days";
} else if (id.includes("years-")) {
unit = "Years";
} else if (id === "rawlocktime") { } else if (id === "rawlocktime") {
unit = "Locktime"; unit = "Locktime";
} else if (id.startsWith("is-")) { } else if (id.startsWith("is-")) {
@@ -722,7 +728,9 @@ function createUtils() {
id.includes("high") || id.includes("high") ||
id.includes("low") || id.includes("low") ||
id.includes("close") || id.includes("close") ||
id.includes("ohlc") id.includes("ohlc") ||
id.includes("marketcap") ||
id.includes("ath")
) { ) {
unit = "USD"; unit = "USD";
} else if (id.includes("count") || id.match(/v[1-3]/g)) { } else if (id.includes("count") || id.match(/v[1-3]/g)) {
@@ -743,6 +751,8 @@ function createUtils() {
unit = "Version"; unit = "Version";
} else if (id === "value") { } else if (id === "value") {
unit = "Sats"; unit = "Sats";
} else if (id === "drawdown") {
unit = "percentage";
} else { } else {
console.log(); console.log();
throw Error(`Unit not set for "${id}"`); throw Error(`Unit not set for "${id}"`);

View File

@@ -168,9 +168,10 @@ function createPartialOptions(colors) {
* @param {Object} args * @param {Object} args
* @param {ChartableVecId} args.key * @param {ChartableVecId} args.key
* @param {string} args.name * @param {string} args.name
* @param {Color} [args.color]
*/ */
function createBaseSeries({ key, name }) { function createBaseSeries({ key, name, color }) {
return { key, title: name }; 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",
}),
],
},
],
},
],
},
], ],
}, },
{ {

View File

@@ -56,6 +56,7 @@ export function createVecIdToIndexes() {
const YearIndex = /** @satisfies {YearIndex} */ (23); const YearIndex = /** @satisfies {YearIndex} */ (23);
return /** @type {const} */ ({ return /** @type {const} */ ({
ath: [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"base-size": [TxIndex], "base-size": [TxIndex],
"block-count": [Height], "block-count": [Height],
"block-count-sum": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "block-count-sum": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
@@ -108,9 +109,11 @@ export function createVecIdToIndexes() {
"date-fixed": [Height], "date-fixed": [Height],
dateindex: [DateIndex, Height], dateindex: [DateIndex, Height],
"dateindex-count": [MonthIndex, WeekIndex], "dateindex-count": [MonthIndex, WeekIndex],
"days-since-ath": [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
decadeindex: [DecadeIndex, YearIndex], decadeindex: [DecadeIndex, YearIndex],
difficulty: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], difficulty: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
difficultyepoch: [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": [Height],
"emptyoutput-count-10p": [DateIndex], "emptyoutput-count-10p": [DateIndex],
"emptyoutput-count-25p": [DateIndex], "emptyoutput-count-25p": [DateIndex],
@@ -202,6 +205,9 @@ export function createVecIdToIndexes() {
low: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], low: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"low-in-cents": [DateIndex, Height], "low-in-cents": [DateIndex, Height],
"low-in-sats": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "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: [DateIndex, MonthIndex],
"monthindex-count": [QuarterIndex, YearIndex], "monthindex-count": [QuarterIndex, YearIndex],
ohlc: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], ohlc: [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],