mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-21 07:14:47 -07:00
global: add some market charts
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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<Height, Sats>> = 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<Height, Sats>>,
|
||||
@@ -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(
|
||||
|
||||
@@ -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<Self> {
|
||||
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,
|
||||
|
||||
253
crates/brk_computer/src/storage/vecs/market.rs
Normal file
253
crates/brk_computer/src/storage/vecs/market.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
@@ -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<marketprice::Vecs>,
|
||||
pub fetched: Option<fetched::Vecs>,
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -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<Self> {
|
||||
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| {
|
||||
|
||||
@@ -59,3 +59,18 @@ impl Div<usize> for Cents {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,10 @@ use super::{Bitcoin, Cents, Sats};
|
||||
)]
|
||||
pub struct Dollars(f64);
|
||||
|
||||
impl Dollars {
|
||||
pub const ZERO: Self = Self(0.0);
|
||||
}
|
||||
|
||||
impl From<f64> for Dollars {
|
||||
fn from(value: f64) -> Self {
|
||||
Self(value)
|
||||
@@ -73,7 +77,7 @@ impl Mul<Bitcoin> 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),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,3 +156,18 @@ impl From<Sats> for u64 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::CheckedSub;
|
||||
#[derive(
|
||||
Debug,
|
||||
Deref,
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
|
||||
@@ -16,6 +16,7 @@ use super::{
|
||||
Debug,
|
||||
Deref,
|
||||
Clone,
|
||||
Default,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
|
||||
@@ -53,7 +53,12 @@ pub trait VecIterator<'a>: BaseVecIterator<Item = (Self::I, Value<'a, Self::T>)>
|
||||
|
||||
#[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]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}"`);
|
||||
|
||||
@@ -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",
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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],
|
||||
|
||||
Reference in New Issue
Block a user