global: chain + cointime datasets

This commit is contained in:
nym21
2025-09-13 18:26:28 +02:00
parent 38d5c7dff6
commit 01aa425f81
13 changed files with 807 additions and 305 deletions
Generated
+6 -6
View File
@@ -4143,9 +4143,9 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
[[package]]
name = "seqdb"
version = "0.2.13"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f414b042f74d09ee406a7178d4e1ac2f6dfce797b7e305c8d78d8bd92d060b"
checksum = "0068ee8855b29d0251d0277ffb2c2d8872afe0a7124fc9f33a29102af1096f90"
dependencies = [
"allocative",
"allocative_derive",
@@ -5001,9 +5001,9 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23"
[[package]]
name = "vecdb"
version = "0.2.13"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe0477b8e5824c50d8370775795d288b2f853f5a00e758f105020db0f713f1"
checksum = "9e834cf5275445308e2ab867847d059ac7603de71c35dbe6c197726d1db7c74b"
dependencies = [
"allocative",
"allocative_derive",
@@ -5023,9 +5023,9 @@ dependencies = [
[[package]]
name = "vecdb_derive"
version = "0.2.13"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c44db4c3f8d08f575daea88915f19f597909fca73c415baa1edccb6cab9a252"
checksum = "2c9acc9a0b85d010ddcd2a4825d2a804520d9c52759bb9b0bc5ef7c4a1e7fce1"
dependencies = [
"quote",
"syn 2.0.106",
+1 -1
View File
@@ -76,7 +76,7 @@ serde_derive = "1.0.219"
serde_json = { version = "1.0.143", features = ["float_roundtrip"] }
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
# vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
vecdb = { version = "0.2.13", features = ["derive"]}
vecdb = { version = "0.2.14", features = ["derive"]}
zerocopy = "0.8.27"
zerocopy-derive = "0.8.27"
+94 -13
View File
@@ -5,9 +5,9 @@ use brk_error::Result;
use brk_indexer::Indexer;
use brk_structs::{
Bitcoin, CheckedSub, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch,
Height, InputIndex, MonthIndex, OutputIndex, QuarterIndex, Sats, SemesterIndex, StoredBool,
StoredF32, StoredF64, StoredU32, StoredU64, Timestamp, TxIndex, TxVersion, Version, WeekIndex,
Weight, YearIndex,
Height, InputIndex, MonthIndex, ONE_DAY_IN_SEC_F64, OutputIndex, QuarterIndex, Sats,
SemesterIndex, StoredBool, StoredF32, StoredF64, StoredU32, StoredU64, Timestamp, TxIndex,
TxVersion, Version, WeekIndex, Weight, YearIndex,
};
use vecdb::{
AnyCloneableIterableVec, AnyCollectableVec, AnyIterableVec, Database, EagerVec, Exit,
@@ -136,8 +136,11 @@ pub struct Vecs {
pub indexes_to_annualized_volume: ComputedVecsFromDateIndex<Sats>,
pub indexes_to_annualized_volume_btc: ComputedVecsFromDateIndex<Bitcoin>,
pub indexes_to_annualized_volume_usd: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_velocity_btc: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_velocity_usd: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_tx_btc_velocity: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_tx_usd_velocity: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_tx_per_sec: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_outputs_per_sec: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_inputs_per_sec: ComputedVecsFromDateIndex<StoredF32>,
}
impl Vecs {
@@ -1093,22 +1096,46 @@ impl Vecs {
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_velocity_btc: ComputedVecsFromDateIndex::forced_import(
indexes_to_tx_btc_velocity: ComputedVecsFromDateIndex::forced_import(
&db,
"velocity_btc",
"tx_btc_velocity",
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_velocity_usd: ComputedVecsFromDateIndex::forced_import(
indexes_to_tx_usd_velocity: ComputedVecsFromDateIndex::forced_import(
&db,
"velocity_usd",
"tx_usd_velocity",
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_tx_per_sec: ComputedVecsFromDateIndex::forced_import(
&db,
"tx_per_sec",
Source::Compute,
version + Version::TWO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_outputs_per_sec: ComputedVecsFromDateIndex::forced_import(
&db,
"outputs_per_sec",
Source::Compute,
version + Version::TWO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_inputs_per_sec: ComputedVecsFromDateIndex::forced_import(
&db,
"inputs_per_sec",
Source::Compute,
version + Version::TWO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
txindex_to_is_coinbase,
inputindex_to_value,
@@ -2160,7 +2187,7 @@ impl Vecs {
Ok(())
})?;
self.indexes_to_velocity_btc
self.indexes_to_tx_btc_velocity
.compute_all(starting_indexes, exit, |v| {
v.compute_divide(
starting_indexes.dateindex,
@@ -2189,7 +2216,7 @@ impl Vecs {
Ok(())
})?;
self.indexes_to_velocity_usd
self.indexes_to_tx_usd_velocity
.compute_all(starting_indexes, exit, |v| {
v.compute_divide(
starting_indexes.dateindex,
@@ -2209,6 +2236,57 @@ impl Vecs {
})?;
}
self.indexes_to_tx_per_sec
.compute_all(starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.dateindex,
self.indexes_to_tx_count.dateindex.unwrap_sum(),
&indexes.dateindex_to_date,
|(i, tx_count, date, ..)| {
(
i,
(*tx_count as f64 / (date.completion() * ONE_DAY_IN_SEC_F64)).into(),
)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_inputs_per_sec
.compute_all(starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.dateindex,
self.indexes_to_input_count.dateindex.unwrap_sum(),
&indexes.dateindex_to_date,
|(i, tx_count, date, ..)| {
(
i,
(*tx_count as f64 / (date.completion() * ONE_DAY_IN_SEC_F64)).into(),
)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_outputs_per_sec
.compute_all(starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.dateindex,
self.indexes_to_output_count.dateindex.unwrap_sum(),
&indexes.dateindex_to_date,
|(i, tx_count, date, ..)| {
(
i,
(*tx_count as f64 / (date.completion() * ONE_DAY_IN_SEC_F64)).into(),
)
},
exit,
)?;
Ok(())
})?;
Ok(())
}
@@ -2326,8 +2404,11 @@ impl Vecs {
iter = Box::new(iter.chain(self.indexes_to_annualized_volume.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_annualized_volume_btc.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_annualized_volume_usd.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_velocity_btc.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_velocity_usd.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_tx_btc_velocity.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_tx_usd_velocity.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_tx_per_sec.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_outputs_per_sec.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_inputs_per_sec.iter_any_collectable()));
iter = Box::new(
iter.chain(
self.indexes_to_subsidy_usd_1y_sma
+118 -35
View File
@@ -1,9 +1,11 @@
use std::path::Path;
use brk_error::Result;
use brk_structs::{Bitcoin, CheckedSub, Dollars, StoredF64, Version};
use brk_structs::{Bitcoin, CheckedSub, Dollars, StoredF32, StoredF64, Version};
use vecdb::{AnyCollectableVec, Database, Exit, PAGE_SIZE, VecIterator};
use crate::grouped::ComputedVecsFromDateIndex;
use super::{
Indexes, chain,
grouped::{
@@ -13,8 +15,6 @@ use super::{
indexes, price, stateful,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone)]
pub struct Vecs {
db: Database,
@@ -42,27 +42,32 @@ pub struct Vecs {
pub indexes_to_cointime_price: ComputedVecsFromHeight<Dollars>,
pub indexes_to_cointime_cap: ComputedVecsFromHeight<Dollars>,
pub indexes_to_cointime_price_ratio: ComputedRatioVecsFromDateIndex,
pub indexes_to_cointime_adj_inflation_rate: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_cointime_adj_tx_btc_velocity: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_cointime_adj_tx_usd_velocity: ComputedVecsFromDateIndex<StoredF64>,
// pub indexes_to_thermo_cap_rel_to_investor_cap: ComputedValueVecsFromHeight,
}
impl Vecs {
pub fn forced_import(
parent: &Path,
version: Version,
parent_path: &Path,
parent_version: Version,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let db = Database::open(&parent.join("cointime"))?;
let db = Database::open(&parent_path.join("cointime"))?;
db.set_min_len(PAGE_SIZE * 1_000_000)?;
let compute_dollars = price.is_some();
let version = parent_version + Version::ZERO;
let this = Self {
indexes_to_coinblocks_created: ComputedVecsFromHeight::forced_import(
&db,
"coinblocks_created",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
@@ -70,7 +75,7 @@ impl Vecs {
&db,
"coinblocks_stored",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
@@ -78,7 +83,7 @@ impl Vecs {
&db,
"liveliness",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -86,7 +91,7 @@ impl Vecs {
&db,
"vaultedness",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -94,7 +99,7 @@ impl Vecs {
&db,
"activity_to_vaultedness_ratio",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -102,7 +107,7 @@ impl Vecs {
&db,
"vaulted_supply",
Source::Compute,
version + VERSION + Version::ONE,
version + Version::ONE,
VecBuilderOptions::default().add_last(),
compute_dollars,
indexes,
@@ -111,7 +116,7 @@ impl Vecs {
&db,
"active_supply",
Source::Compute,
version + VERSION + Version::ONE,
version + Version::ONE,
VecBuilderOptions::default().add_last(),
compute_dollars,
indexes,
@@ -120,7 +125,7 @@ impl Vecs {
&db,
"thermo_cap",
Source::Compute,
version + VERSION + Version::ONE,
version + Version::ONE,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -128,7 +133,7 @@ impl Vecs {
&db,
"investor_cap",
Source::Compute,
version + VERSION + Version::ONE,
version + Version::ONE,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -136,7 +141,7 @@ impl Vecs {
&db,
"vaulted_cap",
Source::Compute,
version + VERSION + Version::ONE,
version + Version::ONE,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -144,7 +149,7 @@ impl Vecs {
&db,
"active_cap",
Source::Compute,
version + VERSION + Version::ONE,
version + Version::ONE,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -152,7 +157,7 @@ impl Vecs {
&db,
"vaulted_price",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -160,7 +165,7 @@ impl Vecs {
&db,
"vaulted_price",
Source::None,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
true,
)?,
@@ -168,7 +173,7 @@ impl Vecs {
&db,
"active_price",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -176,7 +181,7 @@ impl Vecs {
&db,
"active_price",
Source::None,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
true,
)?,
@@ -184,7 +189,7 @@ impl Vecs {
&db,
"true_market_mean",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -192,7 +197,7 @@ impl Vecs {
&db,
"true_market_mean",
Source::None,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
true,
)?,
@@ -200,7 +205,7 @@ impl Vecs {
&db,
"cointime_value_destroyed",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
@@ -208,7 +213,7 @@ impl Vecs {
&db,
"cointime_value_created",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
@@ -216,7 +221,7 @@ impl Vecs {
&db,
"cointime_value_stored",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_sum().add_cumulative(),
)?,
@@ -224,7 +229,7 @@ impl Vecs {
&db,
"cointime_price",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -232,7 +237,7 @@ impl Vecs {
&db,
"cointime_cap",
Source::Compute,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
@@ -240,10 +245,34 @@ impl Vecs {
&db,
"cointime_price",
Source::None,
version + VERSION + Version::ZERO,
version + Version::ZERO,
indexes,
true,
)?,
indexes_to_cointime_adj_inflation_rate: ComputedVecsFromDateIndex::forced_import(
&db,
"cointime_adj_inflation_rate",
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_cointime_adj_tx_btc_velocity: ComputedVecsFromDateIndex::forced_import(
&db,
"cointime_adj_tx_btc_velocity",
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
indexes_to_cointime_adj_tx_usd_velocity: ComputedVecsFromDateIndex::forced_import(
&db,
"cointime_adj_tx_usd_velocity",
Source::Compute,
version + Version::ZERO,
indexes,
VecBuilderOptions::default().add_last(),
)?,
db,
};
@@ -392,6 +421,32 @@ impl Vecs {
},
)?;
self.indexes_to_cointime_adj_inflation_rate
.compute_all(starting_indexes, exit, |v| {
v.compute_multiply(
starting_indexes.dateindex,
self.indexes_to_activity_to_vaultedness_ratio
.dateindex
.unwrap_last(),
chain.indexes_to_inflation_rate.dateindex.as_ref().unwrap(),
exit,
)?;
Ok(())
})?;
self.indexes_to_cointime_adj_tx_btc_velocity
.compute_all(starting_indexes, exit, |v| {
v.compute_multiply(
starting_indexes.dateindex,
self.indexes_to_activity_to_vaultedness_ratio
.dateindex
.unwrap_last(),
chain.indexes_to_tx_btc_velocity.dateindex.as_ref().unwrap(),
exit,
)?;
Ok(())
})?;
if let Some(price) = price {
let realized_cap = stateful
.utxo_cohorts
@@ -603,6 +658,22 @@ impl Vecs {
exit,
Some(self.indexes_to_cointime_price.dateindex.unwrap_last()),
)?;
self.indexes_to_cointime_adj_tx_usd_velocity.compute_all(
starting_indexes,
exit,
|v| {
v.compute_multiply(
starting_indexes.dateindex,
self.indexes_to_activity_to_vaultedness_ratio
.dateindex
.unwrap_last(),
chain.indexes_to_tx_usd_velocity.dateindex.as_ref().unwrap(),
exit,
)?;
Ok(())
},
)?;
}
Ok(())
@@ -612,6 +683,24 @@ impl Vecs {
let mut iter: Box<dyn Iterator<Item = &dyn AnyCollectableVec>> =
Box::new(std::iter::empty());
iter = Box::new(
iter.chain(
self.indexes_to_cointime_adj_inflation_rate
.iter_any_collectable(),
),
);
iter = Box::new(
iter.chain(
self.indexes_to_cointime_adj_tx_btc_velocity
.iter_any_collectable(),
),
);
iter = Box::new(
iter.chain(
self.indexes_to_cointime_adj_tx_usd_velocity
.iter_any_collectable(),
),
);
iter = Box::new(iter.chain(self.indexes_to_coinblocks_created.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_coinblocks_stored.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_liveliness.iter_any_collectable()));
@@ -622,20 +711,16 @@ impl Vecs {
.iter_any_collectable(),
),
);
iter = Box::new(iter.chain(self.indexes_to_vaulted_supply.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_active_supply.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_thermo_cap.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_investor_cap.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_vaulted_cap.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_active_cap.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_vaulted_price.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_vaulted_price_ratio.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_active_price.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_active_price_ratio.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_true_market_mean.iter_any_collectable()));
iter = Box::new(
iter.chain(
@@ -643,7 +728,6 @@ impl Vecs {
.iter_any_collectable(),
),
);
iter = Box::new(iter.chain(self.indexes_to_cointime_price.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_cointime_cap.iter_any_collectable()));
iter = Box::new(iter.chain(self.indexes_to_cointime_price_ratio.iter_any_collectable()));
@@ -660,7 +744,6 @@ impl Vecs {
),
);
iter = Box::new(iter.chain(self.indexes_to_cointime_value_stored.iter_any_collectable()));
iter
}
}
File diff suppressed because it is too large Load Diff
+24 -1
View File
@@ -1,8 +1,10 @@
use jiff::{Span, civil::Date as Date_, tz::TimeZone};
use jiff::{Span, Zoned, civil::Date as Date_, tz::TimeZone};
use serde::{Serialize, Serializer};
use vecdb::StoredCompressed;
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::ONE_DAY_IN_SEC_F64;
use super::{DateIndex, Timestamp};
#[derive(
@@ -51,6 +53,21 @@ impl Date {
pub fn today() -> Self {
Self::from(Timestamp::now())
}
pub fn completion(&self) -> f64 {
let date = Date_::from(*self);
let now = Zoned::now().with_time_zone(TimeZone::UTC);
let today = now.date();
if date < today {
1.0
} else if date == today {
let rounded = jiff::Timestamp::from(*self);
now.timestamp().duration_since(rounded).as_secs_f64() / ONE_DAY_IN_SEC_F64
} else {
0.0
}
}
}
impl Default for Date {
@@ -71,6 +88,12 @@ impl From<Date> for Date_ {
}
}
impl From<Date> for jiff::Timestamp {
fn from(value: Date) -> Self {
Self::from(Timestamp::from(value))
}
}
impl From<Timestamp> for Date {
fn from(value: Timestamp) -> Self {
Self::from(Date_::from(
+38
View File
@@ -9,6 +9,8 @@ use serde::{Serialize, Serializer, ser::SerializeTuple};
use vecdb::StoredCompressed;
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::StoredF64;
use super::{Cents, Dollars, Sats};
#[derive(Debug, Default, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)]
@@ -217,6 +219,15 @@ where
}
}
impl<T> From<Open<T>> for StoredF64
where
StoredF64: From<T>,
{
fn from(value: Open<T>) -> Self {
Self::from(value.0)
}
}
impl<T> From<Close<T>> for Open<T>
where
T: Copy,
@@ -315,6 +326,15 @@ where
}
}
impl<T> From<High<T>> for StoredF64
where
StoredF64: From<T>,
{
fn from(value: High<T>) -> Self {
Self::from(value.0)
}
}
impl<T> From<Close<T>> for High<T>
where
T: Copy,
@@ -413,6 +433,15 @@ where
}
}
impl<T> From<Low<T>> for StoredF64
where
StoredF64: From<T>,
{
fn from(value: Low<T>) -> Self {
Self::from(value.0)
}
}
impl<T> From<Close<T>> for Low<T>
where
T: Copy,
@@ -530,6 +559,15 @@ where
}
}
impl<T> From<Close<T>> for StoredF64
where
StoredF64: From<T>,
{
fn from(value: Close<T>) -> Self {
Self::from(value.0)
}
}
// impl<A, B> From<Close<A>> for Close<B>
// where
// B: From<A>,
@@ -153,6 +153,13 @@ impl Mul<usize> for StoredF32 {
}
}
impl Mul<StoredF32> for StoredF32 {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Self(self.0 * rhs.0)
}
}
impl Mul<StoredF32> for usize {
type Output = StoredF32;
fn mul(self, rhs: StoredF32) -> Self::Output {
@@ -64,6 +64,20 @@ impl Mul<usize> for StoredF64 {
}
}
impl Mul<StoredF64> for StoredF64 {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
Self(self.0 * rhs.0)
}
}
impl Mul<Dollars> for StoredF64 {
type Output = Self;
fn mul(self, rhs: Dollars) -> Self::Output {
Self(self.0 * *rhs)
}
}
impl Div<usize> for StoredF64 {
type Output = Self;
fn div(self, rhs: usize) -> Self::Output {
+3 -11
View File
@@ -28,9 +28,9 @@ use super::Date;
)]
pub struct Timestamp(u32);
const ONE_HOUR_IN_SEC: u32 = 60 * 60;
const ONE_DAY_IN_SEC: u32 = 24 * 60 * 60;
const ONE_DAY_IN_SEC_F64: f64 = ONE_DAY_IN_SEC as f64;
pub const ONE_HOUR_IN_SEC: u32 = 60 * 60;
pub const ONE_DAY_IN_SEC: u32 = 24 * 60 * 60;
pub const ONE_DAY_IN_SEC_F64: f64 = ONE_DAY_IN_SEC as f64;
impl Timestamp {
pub const ZERO: Self = Self(0);
@@ -75,14 +75,6 @@ impl Timestamp {
pub fn now() -> Self {
Self::from(jiff::Timestamp::now())
}
pub fn day_completion(&self) -> f64 {
let rounded = jiff::Timestamp::from(Self::from(Date::from(*self)));
ONE_DAY_IN_SEC_F64
/ jiff::Timestamp::from(*self)
.duration_since(rounded)
.as_secs_f64()
}
}
impl From<u32> for Timestamp {
@@ -289,7 +289,7 @@ function createChartElement({
choices: /** @type {const} */ (["lin", "log"]),
id: utils.stringToId(`${id} ${paneIndex} ${unit}`),
defaultValue:
unit === "USD" && seriesType !== "Baseline" ? "log" : "lin",
unit === "usd" && seriesType !== "Baseline" ? "log" : "lin",
key: `${id}-price-scale-${paneIndex}`,
signals,
});
@@ -681,7 +681,7 @@ function createChartElement({
data,
options,
}) {
color ||= unit === "USD" ? colors.green : colors.orange;
color ||= unit === "usd" ? colors.green : colors.orange;
/** @type {LineISeries} */
const iseries = /** @type {any} */ (
+80 -77
View File
@@ -12,57 +12,57 @@
/**
* @typedef {"" |
* "BTC" |
* "Cents" |
* "coinblocks" |
* "coindays" |
* "satblocks" |
* "satdays" |
* "Count" |
* "Date" |
* "Difficulty" |
* "ExaHash / Second" |
* "Gigabytes" |
* "Hash" |
* "Index" |
* "percentage" |
* "Ratio" |
* "Sats" |
* "secs" |
* "Timestamp" |
* "tx" |
* "Type" |
* "USD/(TH/s)/day" |
* "USD/(PH/s)/day" |
* "Sats/(TH/s)/day" |
* "Sats/(PH/s)/day" |
* "USD" |
* "Version" |
* "WU" |
* "Bool" |
* "Days" |
* "%mcap" |
* "blocks" |
* "%all" |
* "%cmcap" |
* "%cp+l" |
* "%mcap" |
* "%pnl" |
* "%rcap" |
* "%self" |
* "%all" |
* "Years" |
* "H/s" |
* "Locktime" |
* "sat/vB" |
* "%pnl" |
* "constant" |
* "vB" |
* "block" |
* "id" |
* "/sec" |
* "address data" |
* "block" |
* "blocks" |
* "bool" |
* "btc" |
* "bytes" |
* "cents" |
* "coinblocks" |
* "coindays" |
* "constant" |
* "count" |
* "date" |
* "days" |
* "difficulty" |
* "epoch" |
* "gigabytes" |
* "h/s" |
* "hash" |
* "height" |
* "id" |
* "index" |
* "locktime" |
* "percentage" |
* "ratio" |
* "sat/vb" |
* "satblocks" |
* "satdays" |
* "sats" |
* "sats/(ph/s)/day" |
* "sats/(th/s)/day" |
* "sd" |
* "Epoch" |
* "Height" |
* "Bytes"
* } Unit
* "secs" |
* "timestamp" |
* "tx" |
* "type" |
* "usd" |
* "usd/(ph/s)/day" |
* "usd/(th/s)/day" |
* "vb" |
* "version" |
* "wu" |
* "years" |
* "" } Unit
*/
const localhost = window.location.hostname === "localhost";
@@ -765,16 +765,16 @@ function createUtils() {
id.endsWith("dominance")
)))
) {
setUnit("Sats");
setUnit("sats");
}
if (
(!unit || thoroughUnitCheck) &&
!id.startsWith("velocity") &&
!id.endsWith("velocity") &&
((id.includes("_btc") &&
!(id.includes("0k_btc") || id.includes("1k_btc"))) ||
id.endsWith("_btc"))
) {
setUnit("BTC");
setUnit("btc");
}
if ((!unit || thoroughUnitCheck) && id === "chain") {
setUnit("block");
@@ -798,7 +798,7 @@ function createUtils() {
id === "price_ath" ||
id === "market_cap" ||
id.startsWith("price_true_range") ||
(id.includes("_usd") && !id.startsWith("velocity")) ||
(id.includes("_usd") && !id.endsWith("velocity")) ||
id.includes("cointime_value") ||
id.endsWith("_ago") ||
id.endsWith("price_paid") ||
@@ -817,10 +817,10 @@ function createUtils() {
!id.includes("hash_rate")) ||
id === "ath")
) {
setUnit("USD");
setUnit("usd");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("cents")) {
setUnit("Cents");
setUnit("cents");
}
if (
((!unit || thoroughUnitCheck) &&
@@ -843,15 +843,15 @@ function createUtils() {
id.includes("liveliness") ||
id.includes("vaultedness") ||
id == "puell_multiple" ||
id.startsWith("velocity")
id.endsWith("velocity")
) {
setUnit("Ratio");
setUnit("ratio");
}
if (
(!unit || thoroughUnitCheck) &&
(id === "price_drawdown" ||
id === "difficulty_adjustment" ||
id.startsWith("inflation_rate") ||
id.endsWith("inflation_rate") ||
id.endsWith("_oscillator") ||
id.endsWith("_dominance") ||
id.endsWith("_returns") ||
@@ -869,25 +869,25 @@ function createUtils() {
id.includes("blocks_mined") ||
(id.includes("tx_v") && !id.includes("vsize")))
) {
setUnit("Count");
setUnit("count");
}
if (
(!unit || thoroughUnitCheck) &&
(id.startsWith("hash_rate") || id.endsWith("as_hash"))
) {
setUnit("H/s");
setUnit("h/s");
}
if ((!unit || thoroughUnitCheck) && id === "pool") {
setUnit("id");
}
if ((!unit || thoroughUnitCheck) && id.includes("fee_rate")) {
setUnit("sat/vB");
setUnit("sat/vb");
}
if ((!unit || thoroughUnitCheck) && id.startsWith("is_")) {
setUnit("Bool");
setUnit("bool");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("type")) {
setUnit("Type");
setUnit("type");
}
if (
(!unit || thoroughUnitCheck) &&
@@ -895,12 +895,15 @@ function createUtils() {
) {
setUnit("secs");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("_per_sec")) {
setUnit("/sec");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("locktime")) {
setUnit("Locktime");
setUnit("locktime");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("version")) {
setUnit("Version");
setUnit("version");
}
if (
(!unit || thoroughUnitCheck) &&
@@ -910,7 +913,7 @@ function createUtils() {
id.endsWith("total_size") ||
id.includes("block_size"))
) {
setUnit("Bytes");
setUnit("bytes");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("_sd")) {
setUnit("sd");
@@ -919,25 +922,25 @@ function createUtils() {
(!unit || thoroughUnitCheck) &&
(id.includes("vsize") || id.includes("vbytes"))
) {
setUnit("vB");
setUnit("vb");
}
if ((!unit || thoroughUnitCheck) && id.includes("weight")) {
setUnit("WU");
setUnit("wu");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("index")) {
setUnit("Index");
setUnit("index");
}
if (
(!unit || thoroughUnitCheck) &&
(id === "date" || id === "date_fixed")
) {
setUnit("Date");
setUnit("date");
}
if (
(!unit || thoroughUnitCheck) &&
(id === "timestamp" || id === "timestamp_fixed")
) {
setUnit("Timestamp");
setUnit("timestamp");
}
if ((!unit || thoroughUnitCheck) && id.includes("coinblocks")) {
setUnit("coinblocks");
@@ -952,7 +955,7 @@ function createUtils() {
setUnit("satdays");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("height")) {
setUnit("Height");
setUnit("height");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("rel_to_market_cap")) {
setUnit("%mcap");
@@ -986,25 +989,25 @@ function createUtils() {
setUnit("%self");
}
if ((!unit || thoroughUnitCheck) && id.endsWith("epoch")) {
setUnit("Epoch");
setUnit("epoch");
}
if ((!unit || thoroughUnitCheck) && id === "difficulty") {
setUnit("Difficulty");
setUnit("difficulty");
}
if ((!unit || thoroughUnitCheck) && id === "blockhash") {
setUnit("Hash");
setUnit("hash");
}
if ((!unit || thoroughUnitCheck) && id.startsWith("hash_price_phs")) {
setUnit("USD/(PH/s)/day");
setUnit("usd/(ph/s)/day");
}
if ((!unit || thoroughUnitCheck) && id.startsWith("hash_price_ths")) {
setUnit("USD/(TH/s)/day");
setUnit("usd/(th/s)/day");
}
if ((!unit || thoroughUnitCheck) && id.startsWith("hash_value_phs")) {
setUnit("Sats/(PH/s)/day");
setUnit("sats/(ph/s)/day");
}
if ((!unit || thoroughUnitCheck) && id.startsWith("hash_value_ths")) {
setUnit("Sats/(TH/s)/day");
setUnit("sats/(th/s)/day");
}
if (
@@ -1013,10 +1016,10 @@ function createUtils() {
id.includes("days_since") ||
id.startsWith("days_before"))
) {
setUnit("Days");
setUnit("days");
}
if ((!unit || thoroughUnitCheck) && id.includes("years_between")) {
setUnit("Years");
setUnit("years");
}
if ((!unit || thoroughUnitCheck) && id.startsWith("constant")) {
setUnit("constant");
+265 -24
View File
@@ -1468,7 +1468,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
: []),
createPriceLine({
number: 1,
unit: "Ratio",
unit: "ratio",
}),
],
},
@@ -1537,7 +1537,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
...createPriceLines({
numbers: [0, 1, 2, 3, 4, -1, -2, -3, -4],
unit: "Ratio",
unit: "ratio",
}),
],
},
@@ -1653,7 +1653,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
...createPriceLines({
numbers: [0, 1, 2, 3, 4, -1, -2, -3, -4],
unit: "Ratio",
unit: "ratio",
}),
],
})),
@@ -2133,7 +2133,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
),
createPriceLine({
unit: "Ratio",
unit: "ratio",
number: 1,
}),
],
@@ -2166,7 +2166,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
defaultActive: false,
}),
createPriceLine({
unit: "USD",
unit: "usd",
defaultActive: false,
}),
]
@@ -2191,6 +2191,16 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
color: colors.red,
defaultActive: false,
}),
...(`${fixKey(args.key)}realized_profit_to_loss_ratio` in
vecIdToIndexes
? [
createBaseSeries({
key: `${fixKey(args.key)}realized_profit_to_loss_ratio`,
name: "proft / loss",
color: colors.yellow,
}),
]
: []),
createBaseSeries({
key: `${fixKey(args.key)}total_realized_pnl`,
name: "Total",
@@ -2240,7 +2250,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
unit: "%rcap",
}),
createPriceLine({
unit: "USD",
unit: "usd",
defaultActive: false,
}),
],
@@ -2297,7 +2307,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
unit: "%rcap",
}),
createPriceLine({
unit: "USD",
unit: "usd",
}),
]),
},
@@ -2392,7 +2402,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
: []),
createPriceLine({
number: 1,
unit: "Ratio",
unit: "ratio",
}),
];
}),
@@ -2420,7 +2430,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
]);
}),
createPriceLine({
unit: "USD",
unit: "usd",
}),
],
},
@@ -2445,7 +2455,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
]);
}),
createPriceLine({
unit: "USD",
unit: "usd",
}),
],
},
@@ -2461,6 +2471,16 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
name,
color,
}),
...(`${key}realized_profit_to_loss_ratio` in
vecIdToIndexes
? [
createBaseSeries({
key: `${key}realized_profit_to_loss_ratio`,
name,
color,
}),
]
: []),
]);
}),
],
@@ -2486,7 +2506,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
]),
createPriceLine({
unit: "USD",
unit: "usd",
}),
createPriceLine({
unit: "%rcap",
@@ -2538,7 +2558,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
]),
createPriceLine({
unit: "USD",
unit: "usd",
}),
],
},
@@ -2573,7 +2593,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
]),
createPriceLine({
unit: "USD",
unit: "usd",
}),
createPriceLine({
unit: "%mcap",
@@ -2602,7 +2622,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
]),
createPriceLine({
number: 1,
unit: "Ratio",
unit: "ratio",
}),
],
},
@@ -2633,7 +2653,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
),
createPriceLine({
number: 1,
unit: "Ratio",
unit: "ratio",
}),
],
},
@@ -2643,7 +2663,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
],
},
]),
{
name: "Sell Side Risk",
title: `Sell Side Risk Ratio ${title}`,
@@ -2675,6 +2694,146 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
]),
},
{
name: "value",
tree: [
...(!("list" in args)
? [
{
name: "created",
title: `value created ${title}`,
bottom: list.flatMap(({ color, name, key }) => {
const normalKey = `${fixKey(key)}value_created`;
const adjKey = `${fixKey(key)}adjusted_value_created`;
return [
createBaseSeries({
key: normalKey,
name: "normal",
color: colors.emerald,
}),
...(adjKey in vecIdToIndexes
? [
createBaseSeries({
key: adjKey,
name: "adjusted",
color: colors.lime,
}),
]
: []),
];
}),
},
{
name: "destroyed",
title: `value destroyed ${title}`,
bottom: list.flatMap(({ color, name, key }) => {
const normalKey = `${fixKey(key)}value_destroyed`;
const adjKey = `${fixKey(key)}adjusted_value_destroyed`;
return [
createBaseSeries({
key: normalKey,
name: "normal",
color: colors.red,
}),
...(adjKey in vecIdToIndexes
? [
createBaseSeries({
key: adjKey,
name: "adjusted",
color: colors.pink,
}),
]
: []),
];
}),
},
]
: [
{
name: "created",
tree: [
{
name: "Normal",
title: `Value Created ${title}`,
bottom: list.flatMap(({ color, name, key }) => [
createBaseSeries({
key: `${fixKey(key)}value_created`,
name,
color,
}),
]),
},
...(() => {
const reducedList = list
.map(({ color, name, key }) => ({
color,
name,
key: `${fixKey(key)}adjusted_value_created`,
}))
.filter(({ key }) => key in vecIdToIndexes);
return reducedList.length
? [
{
name: "Adjusted",
title: `Adjusted value created ${title}`,
bottom: reducedList.map(
({ color, name, key }) =>
createBaseSeries({
key,
name,
color,
}),
),
},
]
: [];
})(),
],
},
{
name: "destroyed",
tree: [
{
name: "Normal",
title: `Value destroyed ${title}`,
bottom: list.flatMap(({ color, name, key }) => [
createBaseSeries({
key: `${fixKey(key)}value_destroyed`,
name,
color,
}),
]),
},
...(() => {
const reducedList = list
.map(({ color, name, key }) => ({
color,
name,
key: `${fixKey(key)}adjusted_value_destroyed`,
}))
.filter(({ key }) => key in vecIdToIndexes);
return reducedList.length
? [
{
name: "Adjusted",
title: `Adjusted value destroyed ${title}`,
bottom: reducedList.map(
({ color, name, key }) =>
createBaseSeries({
key,
name,
color,
}),
),
},
]
: [];
})(),
],
},
]),
],
},
],
},
{
@@ -2780,7 +2939,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
]
: []),
createPriceLine({
unit: "USD",
unit: "usd",
defaultActive: false,
}),
createPriceLine({
@@ -2885,7 +3044,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
: []),
]),
createPriceLine({
unit: "USD",
unit: "usd",
}),
createPriceLine({
unit: "%mcap",
@@ -3230,11 +3389,11 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
color: colors.red,
}),
createPriceLine({
unit: "Index",
unit: "index",
number: 61.8,
}),
createPriceLine({
unit: "Index",
unit: "index",
number: 38.2,
}),
],
@@ -3589,19 +3748,29 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
},
{
name: "Velocity",
title: "Transaction Velocity",
title: "Transactions Velocity",
bottom: [
createBaseSeries({
key: "velocity_btc",
key: "tx_btc_velocity",
name: "bitcoin",
}),
createBaseSeries({
key: "velocity_usd",
key: "tx_usd_velocity",
name: "dollars",
color: colors.emerald,
}),
],
},
{
name: "Speed",
title: "Transactions Per Second",
bottom: [
createBaseSeries({
key: "tx_per_sec",
name: "Transactions",
}),
],
},
],
},
{
@@ -3620,6 +3789,16 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
],
},
{
name: "Speed",
title: "Inputs Per Second",
bottom: [
createBaseSeries({
key: "inputs_per_sec",
name: "Inputs",
}),
],
},
// {
// name: "Value",
// title: "Transaction Input Value",
@@ -3639,13 +3818,23 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
bottom: [
createAverageSeries({ concat: "output_count" }),
createCumulativeSeries({
concat: "input_count",
concat: "output_count",
}),
...createMinMaxPercentilesSeries({
concat: "output_count",
}),
],
},
{
name: "Speed",
title: "Outputs Per Second",
bottom: [
createBaseSeries({
key: "outputs_per_sec",
name: "Outputs",
}),
],
},
// {
// name: "Value",
// title: "Transaction Output Value",
@@ -4453,6 +4642,11 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
name: "Vaultedness",
color: colors.lime,
}),
createBaseSeries({
key: "activity_to_vaultedness_ratio",
name: "Liveliness / Vaultedness",
color: colors.purple,
}),
],
},
{
@@ -4494,6 +4688,53 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) {
}),
],
},
{
name: "Adjusted",
tree: [
{
name: "inflation",
title: "Cointime-Adjusted inflation rate",
bottom: [
createBaseSeries({
key: "inflation_rate",
name: "base",
color: colors.orange,
}),
createBaseSeries({
key: "cointime_adj_inflation_rate",
name: "base",
color: colors.purple,
}),
],
},
{
name: "Velocity",
title: "Cointime-Adjusted transactions velocity",
bottom: [
createBaseSeries({
key: "tx_btc_velocity",
name: "btc",
color: colors.orange,
}),
createBaseSeries({
key: "cointime_adj_tx_btc_velocity",
name: "adj. btc",
color: colors.red,
}),
createBaseSeries({
key: "tx_usd_velocity",
name: "usd",
color: colors.emerald,
}),
createBaseSeries({
key: "cointime_adj_tx_usd_velocity",
name: "adj. usd",
color: colors.lime,
}),
],
},
],
},
],
},
],