diff --git a/Cargo.lock b/Cargo.lock index 6ea258c8f..cd9ac76b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -750,7 +750,7 @@ dependencies = [ "css-module-lexer", "dunce", "futures", - "indexmap 2.11.0", + "indexmap 2.11.1", "itertools", "itoa", "memchr", @@ -1020,7 +1020,7 @@ dependencies = [ "fast-glob", "form_urlencoded", "futures", - "indexmap 2.11.0", + "indexmap 2.11.1", "infer", "itoa", "memchr", @@ -1772,12 +1772,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.0", ] [[package]] @@ -2349,9 +2349,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" dependencies = [ "equivalent", "hashbrown 0.15.5", @@ -2379,7 +2379,7 @@ dependencies = [ "crossbeam-utils", "dashmap", "env_logger", - "indexmap 2.11.0", + "indexmap 2.11.1", "itoa", "log", "num-format", @@ -2595,9 +2595,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" @@ -3218,7 +3218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0784392356fa78dd4c9047fce7c9046c141f8990736792d00310bf40935b1870" dependencies = [ "cfg-if", - "indexmap 2.11.0", + "indexmap 2.11.1", "json-strip-comments", "once_cell", "papaya", @@ -3311,7 +3311,7 @@ dependencies = [ "base64 0.22.1", "compact_str", "cow-utils", - "indexmap 2.11.0", + "indexmap 2.11.1", "itoa", "memchr", "oxc-browserslist", @@ -3504,7 +3504,7 @@ checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" dependencies = [ "fixedbitset", "hashbrown 0.15.5", - "indexmap 2.11.0", + "indexmap 2.11.1", "serde", ] @@ -3965,15 +3965,15 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ "bitflags 2.9.4", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.0", ] [[package]] @@ -4118,9 +4118,9 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[package]] name = "seqdb" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078349d3b0b862848f518737b1228fdbaa725819688036db54363aa6c960ead" +checksum = "c97f1528725c4bb77e7f804440e353ef2c55dd73dceffc0ef856873b01a5216b" dependencies = [ "allocative", "allocative_derive", @@ -4179,7 +4179,7 @@ version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ - "indexmap 2.11.0", + "indexmap 2.11.1", "itoa", "memchr", "ryu", @@ -4227,7 +4227,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.11.0", + "indexmap 2.11.1", "schemars 0.9.0", "schemars 1.0.4", "serde", @@ -4629,7 +4629,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" dependencies = [ - "indexmap 2.11.0", + "indexmap 2.11.1", "serde", "serde_spanned", "toml_datetime 0.7.0", @@ -4659,7 +4659,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.11.0", + "indexmap 2.11.1", "toml_datetime 0.6.11", "winnow", ] @@ -4976,9 +4976,9 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23" [[package]] name = "vecdb" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3b3745eeee3b56f0db302a3ccaa2b400b5c881adf7319afde753b2fed83aae" +checksum = "f0f9d0664d3ddb92e67ecc155b748ba16bb2d0c04a92276a33be6eac1a38d533" dependencies = [ "allocative", "allocative_derive", @@ -4998,9 +4998,9 @@ dependencies = [ [[package]] name = "vecdb_derive" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb14e5900ae8ba26112c438311b274de59e566a180d7795a584a83e3faa5cb9f" +checksum = "d263723d1fbfeed0a279d8983e6b7f58ece72a6fa2bf4772d630b72d1ba2b298" dependencies = [ "quote", "syn 2.0.106", @@ -5524,7 +5524,7 @@ dependencies = [ "arbitrary", "crc32fast", "flate2", - "indexmap 2.11.0", + "indexmap 2.11.1", "memchr", "zopfli", ] diff --git a/Cargo.toml b/Cargo.toml index 8f4c6f3d9..2f32137e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,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.11", features = ["derive"]} +vecdb = { version = "0.2.12", features = ["derive"]} zerocopy = "0.8.27" zerocopy-derive = "0.8.27" diff --git a/crates/brk_computer/src/constants.rs b/crates/brk_computer/src/constants.rs index 9d0ac9323..08feb0b2a 100644 --- a/crates/brk_computer/src/constants.rs +++ b/crates/brk_computer/src/constants.rs @@ -2,7 +2,7 @@ use std::path::Path; use brk_error::Result; use brk_indexer::Indexer; -use brk_structs::{StoredI16, StoredU16, Version}; +use brk_structs::{StoredF32, StoredI16, StoredU16, Version}; use vecdb::{AnyCollectableVec, AnyVec, Database, Exit}; use crate::grouped::Source; @@ -24,7 +24,9 @@ pub struct Vecs { pub constant_2: ComputedVecsFromHeight, pub constant_3: ComputedVecsFromHeight, pub constant_4: ComputedVecsFromHeight, + pub constant_38_2: ComputedVecsFromHeight, pub constant_50: ComputedVecsFromHeight, + pub constant_61_8: ComputedVecsFromHeight, pub constant_100: ComputedVecsFromHeight, pub constant_600: ComputedVecsFromHeight, pub constant_minus_1: ComputedVecsFromHeight, @@ -78,6 +80,14 @@ impl Vecs { indexes, VecBuilderOptions::default().add_last(), )?, + constant_38_2: ComputedVecsFromHeight::forced_import( + &db, + "constant_38_2", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, constant_50: ComputedVecsFromHeight::forced_import( &db, "constant_50", @@ -86,6 +96,14 @@ impl Vecs { indexes, VecBuilderOptions::default().add_last(), )?, + constant_61_8: ComputedVecsFromHeight::forced_import( + &db, + "constant_61_8", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, constant_100: ComputedVecsFromHeight::forced_import( &db, "constant_100", @@ -223,6 +241,30 @@ impl Vecs { ) })?; + [ + (&mut self.constant_38_2, 38.2), + (&mut self.constant_61_8, 61.8), + ] + .into_iter() + .try_for_each(|(vec, value)| { + vec.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |vec, _, indexes, starting_indexes, exit| { + vec.compute_to( + starting_indexes.height, + indexes.height_to_date.len(), + indexes.height_to_date.version(), + |i| (i, StoredF32::from(value)), + exit, + )?; + Ok(()) + }, + ) + })?; + Ok(()) } @@ -233,7 +275,9 @@ impl Vecs { self.constant_2.vecs(), self.constant_3.vecs(), self.constant_4.vecs(), + self.constant_38_2.vecs(), self.constant_50.vecs(), + self.constant_61_8.vecs(), self.constant_100.vecs(), self.constant_600.vecs(), self.constant_minus_1.vecs(), diff --git a/crates/brk_computer/src/grouped/builder_eager.rs b/crates/brk_computer/src/grouped/builder_eager.rs index 672b5cdce..8c31b1a6b 100644 --- a/crates/brk_computer/src/grouped/builder_eager.rs +++ b/crates/brk_computer/src/grouped/builder_eager.rs @@ -20,11 +20,11 @@ where pub average: Option>>, pub sum: Option>>, pub max: Option>>, - pub p90: Option>>, - pub p75: Option>>, + pub pct90: Option>>, + pub pct75: Option>>, pub median: Option>>, - pub p25: Option>>, - pub p10: Option>>, + pub pct25: Option>>, + pub pct10: Option>>, pub min: Option>>, pub last: Option>>, pub cumulative: Option>>, @@ -152,44 +152,44 @@ where .unwrap(), ) }), - p90: options.p90.then(|| { + pct90: options.pct90.then(|| { Box::new( EagerVec::forced_import( db, - &maybe_suffix("p90"), + &maybe_suffix("pct90"), version + VERSION + Version::ZERO, format, ) .unwrap(), ) }), - p75: options.p75.then(|| { + pct75: options.pct75.then(|| { Box::new( EagerVec::forced_import( db, - &maybe_suffix("p75"), + &maybe_suffix("pct75"), version + VERSION + Version::ZERO, format, ) .unwrap(), ) }), - p25: options.p25.then(|| { + pct25: options.pct25.then(|| { Box::new( EagerVec::forced_import( db, - &maybe_suffix("p25"), + &maybe_suffix("pct25"), version + VERSION + Version::ZERO, format, ) .unwrap(), ) }), - p10: options.p10.then(|| { + pct10: options.pct10.then(|| { Box::new( EagerVec::forced_import( db, - &maybe_suffix("p10"), + &maybe_suffix("pct10"), version + VERSION + Version::ZERO, format, ) @@ -293,11 +293,11 @@ where let needs_average_sum_or_cumulative = needs_sum_or_cumulative || self.average.is_some(); let needs_sorted = self.max.is_some() - || self.p90.is_some() - || self.p75.is_some() + || self.pct90.is_some() + || self.pct75.is_some() || self.median.is_some() - || self.p25.is_some() - || self.p10.is_some() + || self.pct25.is_some() + || self.pct10.is_some() || self.min.is_some(); let needs_values = needs_sorted || needs_average_sum_or_cumulative; @@ -334,24 +334,24 @@ where )?; } - if let Some(p90) = self.p90.as_mut() { - p90.forced_push_at(index, get_percentile(&values, 0.90), exit)?; + if let Some(pct90) = self.pct90.as_mut() { + pct90.forced_push_at(index, get_percentile(&values, 0.90), exit)?; } - if let Some(p75) = self.p75.as_mut() { - p75.forced_push_at(index, get_percentile(&values, 0.75), exit)?; + if let Some(pct75) = self.pct75.as_mut() { + pct75.forced_push_at(index, get_percentile(&values, 0.75), exit)?; } if let Some(median) = self.median.as_mut() { median.forced_push_at(index, get_percentile(&values, 0.50), exit)?; } - if let Some(p25) = self.p25.as_mut() { - p25.forced_push_at(index, get_percentile(&values, 0.25), exit)?; + if let Some(pct25) = self.pct25.as_mut() { + pct25.forced_push_at(index, get_percentile(&values, 0.25), exit)?; } - if let Some(p10) = self.p10.as_mut() { - p10.forced_push_at(index, get_percentile(&values, 0.10), exit)?; + if let Some(pct10) = self.pct10.as_mut() { + pct10.forced_push_at(index, get_percentile(&values, 0.10), exit)?; } if let Some(min) = self.min.as_mut() { @@ -402,11 +402,11 @@ where where I2: StoredIndex + StoredRaw + CheckedSub, { - if self.p90.is_some() - || self.p75.is_some() + if self.pct90.is_some() + || self.pct75.is_some() || self.median.is_some() - || self.p25.is_some() - || self.p10.is_some() + || self.pct25.is_some() + || self.pct10.is_some() { panic!("unsupported"); } @@ -559,24 +559,24 @@ where self.max.as_ref().unwrap() } #[allow(unused)] - pub fn unwrap_p90(&self) -> &EagerVec { - self.p90.as_ref().unwrap() + pub fn unwrap_pct90(&self) -> &EagerVec { + self.pct90.as_ref().unwrap() } #[allow(unused)] - pub fn unwrap_p75(&self) -> &EagerVec { - self.p75.as_ref().unwrap() + pub fn unwrap_pct75(&self) -> &EagerVec { + self.pct75.as_ref().unwrap() } #[allow(unused)] pub fn unwrap_median(&self) -> &EagerVec { self.median.as_ref().unwrap() } #[allow(unused)] - pub fn unwrap_p25(&self) -> &EagerVec { - self.p25.as_ref().unwrap() + pub fn unwrap_pct25(&self) -> &EagerVec { + self.pct25.as_ref().unwrap() } #[allow(unused)] - pub fn unwrap_p10(&self) -> &EagerVec { - self.p10.as_ref().unwrap() + pub fn unwrap_pct10(&self) -> &EagerVec { + self.pct10.as_ref().unwrap() } pub fn unwrap_min(&self) -> &EagerVec { self.min.as_ref().unwrap() @@ -616,17 +616,17 @@ where if let Some(cumulative) = self.cumulative.as_ref() { v.push(cumulative.as_ref()); } - if let Some(p90) = self.p90.as_ref() { - v.push(p90.as_ref()); + if let Some(pct90) = self.pct90.as_ref() { + v.push(pct90.as_ref()); } - if let Some(p75) = self.p75.as_ref() { - v.push(p75.as_ref()); + if let Some(pct75) = self.pct75.as_ref() { + v.push(pct75.as_ref()); } - if let Some(p25) = self.p25.as_ref() { - v.push(p25.as_ref()); + if let Some(pct25) = self.pct25.as_ref() { + v.push(pct25.as_ref()); } - if let Some(p10) = self.p10.as_ref() { - v.push(p10.as_ref()); + if let Some(pct10) = self.pct10.as_ref() { + v.push(pct10.as_ref()); } v @@ -657,17 +657,17 @@ where if let Some(cumulative) = self.cumulative.as_mut() { cumulative.safe_flush(exit)?; } - if let Some(p90) = self.p90.as_mut() { - p90.safe_flush(exit)?; + if let Some(pct90) = self.pct90.as_mut() { + pct90.safe_flush(exit)?; } - if let Some(p75) = self.p75.as_mut() { - p75.safe_flush(exit)?; + if let Some(pct75) = self.pct75.as_mut() { + pct75.safe_flush(exit)?; } - if let Some(p25) = self.p25.as_mut() { - p25.safe_flush(exit)?; + if let Some(pct25) = self.pct25.as_mut() { + pct25.safe_flush(exit)?; } - if let Some(p10) = self.p10.as_mut() { - p10.safe_flush(exit)?; + if let Some(pct10) = self.pct10.as_mut() { + pct10.safe_flush(exit)?; } Ok(()) @@ -698,17 +698,17 @@ where if let Some(cumulative) = self.cumulative.as_mut() { cumulative.validate_computed_version_or_reset(Version::ZERO + version)?; } - if let Some(p90) = self.p90.as_mut() { - p90.validate_computed_version_or_reset(Version::ZERO + version)?; + if let Some(pct90) = self.pct90.as_mut() { + pct90.validate_computed_version_or_reset(Version::ZERO + version)?; } - if let Some(p75) = self.p75.as_mut() { - p75.validate_computed_version_or_reset(Version::ZERO + version)?; + if let Some(pct75) = self.pct75.as_mut() { + pct75.validate_computed_version_or_reset(Version::ZERO + version)?; } - if let Some(p25) = self.p25.as_mut() { - p25.validate_computed_version_or_reset(Version::ZERO + version)?; + if let Some(pct25) = self.pct25.as_mut() { + pct25.validate_computed_version_or_reset(Version::ZERO + version)?; } - if let Some(p10) = self.p10.as_mut() { - p10.validate_computed_version_or_reset(Version::ZERO + version)?; + if let Some(pct10) = self.pct10.as_mut() { + pct10.validate_computed_version_or_reset(Version::ZERO + version)?; } Ok(()) @@ -720,11 +720,11 @@ pub struct VecBuilderOptions { average: bool, sum: bool, max: bool, - p90: bool, - p75: bool, + pct90: bool, + pct75: bool, median: bool, - p25: bool, - p10: bool, + pct25: bool, + pct10: bool, min: bool, first: bool, last: bool, @@ -744,24 +744,24 @@ impl VecBuilderOptions { self.max } - pub fn p90(&self) -> bool { - self.p90 + pub fn pct90(&self) -> bool { + self.pct90 } - pub fn p75(&self) -> bool { - self.p75 + pub fn pct75(&self) -> bool { + self.pct75 } pub fn median(&self) -> bool { self.median } - pub fn p25(&self) -> bool { - self.p25 + pub fn pct25(&self) -> bool { + self.pct25 } - pub fn p10(&self) -> bool { - self.p10 + pub fn pct10(&self) -> bool { + self.pct10 } pub fn min(&self) -> bool { @@ -817,26 +817,26 @@ impl VecBuilderOptions { } #[allow(unused)] - pub fn add_p90(mut self) -> Self { - self.p90 = true; + pub fn add_pct90(mut self) -> Self { + self.pct90 = true; self } #[allow(unused)] - pub fn add_p75(mut self) -> Self { - self.p75 = true; + pub fn add_pct75(mut self) -> Self { + self.pct75 = true; self } #[allow(unused)] - pub fn add_p25(mut self) -> Self { - self.p25 = true; + pub fn add_pct25(mut self) -> Self { + self.pct25 = true; self } #[allow(unused)] - pub fn add_p10(mut self) -> Self { - self.p10 = true; + pub fn add_pct10(mut self) -> Self { + self.pct10 = true; self } @@ -876,26 +876,26 @@ impl VecBuilderOptions { } #[allow(unused)] - pub fn rm_p90(mut self) -> Self { - self.p90 = false; + pub fn rm_pct90(mut self) -> Self { + self.pct90 = false; self } #[allow(unused)] - pub fn rm_p75(mut self) -> Self { - self.p75 = false; + pub fn rm_pct75(mut self) -> Self { + self.pct75 = false; self } #[allow(unused)] - pub fn rm_p25(mut self) -> Self { - self.p25 = false; + pub fn rm_pct25(mut self) -> Self { + self.pct25 = false; self } #[allow(unused)] - pub fn rm_p10(mut self) -> Self { - self.p10 = false; + pub fn rm_pct10(mut self) -> Self { + self.pct10 = false; self } @@ -912,20 +912,20 @@ impl VecBuilderOptions { } pub fn add_percentiles(mut self) -> Self { - self.p90 = true; - self.p75 = true; + self.pct90 = true; + self.pct75 = true; self.median = true; - self.p25 = true; - self.p10 = true; + self.pct25 = true; + self.pct10 = true; self } pub fn remove_percentiles(mut self) -> Self { - self.p90 = false; - self.p75 = false; + self.pct90 = false; + self.pct75 = false; self.median = false; - self.p25 = false; - self.p10 = false; + self.pct25 = false; + self.pct10 = false; self } @@ -934,11 +934,11 @@ impl VecBuilderOptions { self.average, self.sum, self.max, - self.p90, - self.p75, + self.pct90, + self.pct75, self.median, - self.p25, - self.p10, + self.pct25, + self.pct10, self.min, self.first, self.last, diff --git a/crates/brk_computer/src/grouped/from_txindex.rs b/crates/brk_computer/src/grouped/from_txindex.rs index c286d1f73..a773f973d 100644 --- a/crates/brk_computer/src/grouped/from_txindex.rs +++ b/crates/brk_computer/src/grouped/from_txindex.rs @@ -320,24 +320,24 @@ impl ComputedVecsFromTxindex { exit, )?; } - if let Some(_90p) = self.height.p90.as_mut() { - _90p.forced_push_at( + if let Some(pct90) = self.height.pct90.as_mut() { + pct90.forced_push_at( height, Bitcoin::from( sats.height - .unwrap_p90() + .unwrap_pct90() .into_iter() .unwrap_get_inner(height), ), exit, )?; } - if let Some(_75p) = self.height.p75.as_mut() { - _75p.forced_push_at( + if let Some(pct75) = self.height.pct75.as_mut() { + pct75.forced_push_at( height, Bitcoin::from( sats.height - .unwrap_p75() + .unwrap_pct75() .into_iter() .unwrap_get_inner(height), ), @@ -356,24 +356,24 @@ impl ComputedVecsFromTxindex { exit, )?; } - if let Some(_25p) = self.height.p25.as_mut() { - _25p.forced_push_at( + if let Some(pct25) = self.height.pct25.as_mut() { + pct25.forced_push_at( height, Bitcoin::from( sats.height - .unwrap_p25() + .unwrap_pct25() .into_iter() .unwrap_get_inner(height), ), exit, )?; } - if let Some(_10p) = self.height.p10.as_mut() { - _10p.forced_push_at( + if let Some(pct10) = self.height.pct10.as_mut() { + pct10.forced_push_at( height, Bitcoin::from( sats.height - .unwrap_p10() + .unwrap_pct10() .into_iter() .unwrap_get_inner(height), ), @@ -503,25 +503,25 @@ impl ComputedVecsFromTxindex { exit, )?; } - if let Some(_90p) = self.height.p90.as_mut() { - _90p.forced_push_at( + if let Some(pct90) = self.height.pct90.as_mut() { + pct90.forced_push_at( height, price * bitcoin .height - .unwrap_p90() + .unwrap_pct90() .into_iter() .unwrap_get_inner(height), exit, )?; } - if let Some(_75p) = self.height.p75.as_mut() { - _75p.forced_push_at( + if let Some(pct75) = self.height.pct75.as_mut() { + pct75.forced_push_at( height, price * bitcoin .height - .unwrap_p75() + .unwrap_pct75() .into_iter() .unwrap_get_inner(height), exit, @@ -539,25 +539,25 @@ impl ComputedVecsFromTxindex { exit, )?; } - if let Some(_25p) = self.height.p25.as_mut() { - _25p.forced_push_at( + if let Some(pct25) = self.height.pct25.as_mut() { + pct25.forced_push_at( height, price * bitcoin .height - .unwrap_p25() + .unwrap_pct25() .into_iter() .unwrap_get_inner(height), exit, )?; } - if let Some(_10p) = self.height.p10.as_mut() { - _10p.forced_push_at( + if let Some(pct10) = self.height.pct10.as_mut() { + pct10.forced_push_at( height, price * bitcoin .height - .unwrap_p10() + .unwrap_pct10() .into_iter() .unwrap_get_inner(height), exit, diff --git a/crates/brk_computer/src/market.rs b/crates/brk_computer/src/market.rs index 91d32bad2..94af307e7 100644 --- a/crates/brk_computer/src/market.rs +++ b/crates/brk_computer/src/market.rs @@ -35,9 +35,20 @@ pub struct Vecs { pub indexes_to_price_1w_volatility: ComputedVecsFromDateIndex, pub indexes_to_price_1m_volatility: ComputedVecsFromDateIndex, pub indexes_to_price_1y_volatility: ComputedVecsFromDateIndex, - // pub indexes_to_price_true_range: ComputedVecsFromDateIndex, - // pub indexes_to_price_2w_choppiness_index: ComputedVecsFromDateIndex, - // + + pub indexes_to_price_1w_min: ComputedVecsFromDateIndex, + pub indexes_to_price_1w_max: ComputedVecsFromDateIndex, + pub indexes_to_price_2w_min: ComputedVecsFromDateIndex, + pub indexes_to_price_2w_max: ComputedVecsFromDateIndex, + pub indexes_to_price_1m_min: ComputedVecsFromDateIndex, + pub indexes_to_price_1m_max: ComputedVecsFromDateIndex, + pub indexes_to_price_1y_min: ComputedVecsFromDateIndex, + pub indexes_to_price_1y_max: ComputedVecsFromDateIndex, + + pub dateindex_to_price_true_range: EagerVec, + pub dateindex_to_price_true_range_2w_sum: EagerVec, + pub indexes_to_price_2w_choppiness_index: ComputedVecsFromDateIndex, + pub indexes_to_price_1w_sma: ComputedRatioVecsFromDateIndex, pub indexes_to_price_8d_sma: ComputedRatioVecsFromDateIndex, pub indexes_to_price_13d_sma: ComputedRatioVecsFromDateIndex, @@ -1420,22 +1431,88 @@ impl Vecs { indexes, VecBuilderOptions::default().add_last(), )?, - // indexes_to_price_true_range: ComputedVecsFromDateIndex::forced_import( - // &db, - // "price_true_range", - // Source::Compute, - // version + Version::ZERO, - // indexes, - // VecBuilderOptions::default().add_last(), - // )?, - // indexes_to_price_2w_choppiness_index: ComputedVecsFromDateIndex::forced_import( - // &db, - // "price_2w_choppiness_index", - // Source::Compute, - // version + Version::ZERO, - // indexes, - // VecBuilderOptions::default().add_last(), - // )?, + dateindex_to_price_true_range: EagerVec::forced_import_compressed( + &db, + "price_true_range", + version + Version::ZERO, + )?, + dateindex_to_price_true_range_2w_sum: EagerVec::forced_import_compressed( + &db, + "price_true_range_2w_sum", + version + Version::ZERO, + )?, + indexes_to_price_1w_min: ComputedVecsFromDateIndex::forced_import( + &db, + "price_1w_min", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, + indexes_to_price_1w_max: ComputedVecsFromDateIndex::forced_import( + &db, + "price_1w_max", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, + indexes_to_price_2w_min: ComputedVecsFromDateIndex::forced_import( + &db, + "price_2w_min", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, + indexes_to_price_2w_max: ComputedVecsFromDateIndex::forced_import( + &db, + "price_2w_max", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, + indexes_to_price_1m_min: ComputedVecsFromDateIndex::forced_import( + &db, + "price_1m_min", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, + indexes_to_price_1m_max: ComputedVecsFromDateIndex::forced_import( + &db, + "price_1m_max", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, + indexes_to_price_1y_min: ComputedVecsFromDateIndex::forced_import( + &db, + "price_1y_min", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, + indexes_to_price_1y_max: ComputedVecsFromDateIndex::forced_import( + &db, + "price_1y_max", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, + indexes_to_price_2w_choppiness_index: ComputedVecsFromDateIndex::forced_import( + &db, + "price_2w_choppiness_index", + Source::Compute, + version + Version::ONE, + indexes, + VecBuilderOptions::default().add_last(), + )?, db, }; @@ -1470,7 +1547,7 @@ impl Vecs { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - self.height_to_price_ath.compute_max( + self.height_to_price_ath.compute_all_time_high( starting_indexes.height, &price.chainindexes_to_price_high.height, exit, @@ -1488,7 +1565,7 @@ impl Vecs { starting_indexes, exit, |v, _, _, starting_indexes, exit| { - v.compute_max( + v.compute_all_time_high( starting_indexes.dateindex, price.timeindexes_to_price_high.dateindex.as_ref().unwrap(), exit, @@ -2251,6 +2328,182 @@ impl Vecs { }, )?; + self.dateindex_to_price_true_range.compute_transform3( + starting_indexes.dateindex, + price.timeindexes_to_price_open.dateindex.as_ref().unwrap(), + price.timeindexes_to_price_high.dateindex.as_ref().unwrap(), + price.timeindexes_to_price_low.dateindex.as_ref().unwrap(), + |(i, open, high, low, ..)| { + let high_min_low = **high - **low; + let high_min_open = (**high - **open).abs(); + let low_min_open = (**low - **open).abs(); + (i, high_min_low.max(high_min_open).max(low_min_open).into()) + }, + exit, + )?; + + self.dateindex_to_price_true_range_2w_sum.compute_sum( + starting_indexes.dateindex, + &self.dateindex_to_price_true_range, + 14, + exit, + )?; + + self.indexes_to_price_1w_max.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_max( + starting_indexes.dateindex, + price.timeindexes_to_price_high.dateindex.as_ref().unwrap(), + 7, + exit, + )?; + Ok(()) + }, + )?; + + self.indexes_to_price_1w_min.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_min( + starting_indexes.dateindex, + price.timeindexes_to_price_low.dateindex.as_ref().unwrap(), + 7, + exit, + )?; + Ok(()) + }, + )?; + + self.indexes_to_price_2w_max.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_max( + starting_indexes.dateindex, + price.timeindexes_to_price_high.dateindex.as_ref().unwrap(), + 14, + exit, + )?; + Ok(()) + }, + )?; + + self.indexes_to_price_2w_min.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_min( + starting_indexes.dateindex, + price.timeindexes_to_price_low.dateindex.as_ref().unwrap(), + 14, + exit, + )?; + Ok(()) + }, + )?; + + self.indexes_to_price_1m_max.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_max( + starting_indexes.dateindex, + price.timeindexes_to_price_high.dateindex.as_ref().unwrap(), + 30, + exit, + )?; + Ok(()) + }, + )?; + + self.indexes_to_price_1m_min.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_min( + starting_indexes.dateindex, + price.timeindexes_to_price_low.dateindex.as_ref().unwrap(), + 30, + exit, + )?; + Ok(()) + }, + )?; + + self.indexes_to_price_1y_max.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_max( + starting_indexes.dateindex, + price.timeindexes_to_price_high.dateindex.as_ref().unwrap(), + 365, + exit, + )?; + Ok(()) + }, + )?; + + self.indexes_to_price_1y_min.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_min( + starting_indexes.dateindex, + price.timeindexes_to_price_low.dateindex.as_ref().unwrap(), + 365, + exit, + )?; + Ok(()) + }, + )?; + + self.indexes_to_price_2w_choppiness_index.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + let n = 14; + let log10n = (n as f32).log10(); + v.compute_transform3( + starting_indexes.dateindex, + &self.dateindex_to_price_true_range_2w_sum, + self.indexes_to_price_2w_max.dateindex.as_ref().unwrap(), + self.indexes_to_price_2w_min.dateindex.as_ref().unwrap(), + |(i, tr_sum, max, min, ..)| { + ( + i, + StoredF32::from( + 100.0 * (*tr_sum / (*max - *min) as f32).log10() / log10n, + ), + ) + }, + exit, + )?; + Ok(()) + }, + )?; + Ok(()) } @@ -2406,7 +2659,21 @@ impl Vecs { self.indexes_to_price_1w_volatility.vecs(), self.indexes_to_price_1m_volatility.vecs(), self.indexes_to_price_1y_volatility.vecs(), - vec![&self.height_to_price_ath, &self.height_to_price_drawdown], + self.indexes_to_price_2w_choppiness_index.vecs(), + self.indexes_to_price_1w_min.vecs(), + self.indexes_to_price_1w_max.vecs(), + self.indexes_to_price_2w_min.vecs(), + self.indexes_to_price_2w_max.vecs(), + self.indexes_to_price_1m_min.vecs(), + self.indexes_to_price_1m_max.vecs(), + self.indexes_to_price_1y_min.vecs(), + self.indexes_to_price_1y_max.vecs(), + vec![ + &self.height_to_price_ath, + &self.height_to_price_drawdown, + &self.dateindex_to_price_true_range, + &self.dateindex_to_price_true_range_2w_sum, + ], ] .into_iter() .flatten() diff --git a/crates/brk_structs/src/structs/dollars.rs b/crates/brk_structs/src/structs/dollars.rs index 8d788cca7..db7f7b447 100644 --- a/crates/brk_structs/src/structs/dollars.rs +++ b/crates/brk_structs/src/structs/dollars.rs @@ -10,6 +10,8 @@ use serde::{Deserialize, Serialize}; use vecdb::{CheckedSub, StoredCompressed}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; +use crate::{Low, Open}; + use super::{Bitcoin, Cents, Close, High, Sats, StoredF32, StoredF64}; #[derive( @@ -80,8 +82,8 @@ impl From for f64 { } } -impl From> for Dollars { - fn from(value: Close) -> Self { +impl From> for Dollars { + fn from(value: Open) -> Self { Self(value.0) } } @@ -92,6 +94,18 @@ impl From> for Dollars { } } +impl From> for Dollars { + fn from(value: Low) -> Self { + Self(value.0) + } +} + +impl From> for Dollars { + fn from(value: Close) -> Self { + Self(value.0) + } +} + impl From for Dollars { fn from(value: usize) -> Self { Self(value as f64) diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000..b67e7d534 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.89.0" diff --git a/websites/bitview/scripts/chart.js b/websites/bitview/scripts/chart.js index 654f181c5..754347f65 100644 --- a/websites/bitview/scripts/chart.js +++ b/websites/bitview/scripts/chart.js @@ -367,7 +367,7 @@ export function init({ case null: case CANDLE: { series = chart.addCandlestickSeries({ - vecId: "ohlc_in_sats", + vecId: "price_ohlc_in_sats", name: "Price", unit: topUnit, inverse: true, @@ -378,7 +378,7 @@ export function init({ } case LINE: { series = chart.addLineSeries({ - vecId: "close_in_sats", + vecId: "price_close_in_sats", name: "Price", unit: topUnit, color: colors.default, diff --git a/websites/bitview/scripts/main.js b/websites/bitview/scripts/main.js index c7cc12a28..1ae520e30 100644 --- a/websites/bitview/scripts/main.js +++ b/websites/bitview/scripts/main.js @@ -783,11 +783,14 @@ function createUtils() { id === "price_open" || id === "price_ath" || id === "market_cap" || + id.startsWith("price_true_range") || id.includes("_usd") || id.includes("cointime_value") || id.endsWith("_ago") || id.endsWith("price_paid") || id.endsWith("_price") || + (id.startsWith("price") && + (id.endsWith("min") || id.endsWith("max"))) || (id.endsWith("_cap") && !id.includes("rel_to")) || id.endsWith("value_created") || id.endsWith("value_destroyed") || diff --git a/websites/bitview/scripts/options.js b/websites/bitview/scripts/options.js index 377891911..22f12a4df 100644 --- a/websites/bitview/scripts/options.js +++ b/websites/bitview/scripts/options.js @@ -163,18 +163,18 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) { * @typedef {"_median"} MedianSuffix * @typedef {EndsWith} VecIdMedian * @typedef {WithoutSuffix} VecIdMedianBase - * @typedef {"_p90"} _p90Suffix - * @typedef {EndsWith<_p90Suffix>} VecIdp90 - * @typedef {WithoutSuffix} VecIdp90Base - * @typedef {"_p75"} _p75Suffix - * @typedef {EndsWith<_p75Suffix>} VecIdp75 - * @typedef {WithoutSuffix} VecIdp75Base - * @typedef {"_p25"} _p25Suffix - * @typedef {EndsWith<_p25Suffix>} VecIdp25 - * @typedef {WithoutSuffix} VecIdp25Base - * @typedef {"_p10"} _p10Suffix - * @typedef {EndsWith<_p10Suffix>} VecIdp10 - * @typedef {WithoutSuffix} VecIdp10Base + * @typedef {"_pct90"} _pct90Suffix + * @typedef {EndsWith<_pct90Suffix>} VecIdpct90 + * @typedef {WithoutSuffix} VecIdpct90Base + * @typedef {"_pct75"} _pct75Suffix + * @typedef {EndsWith<_pct75Suffix>} VecIdpct75 + * @typedef {WithoutSuffix} VecIdpct75Base + * @typedef {"_pct25"} _pct25Suffix + * @typedef {EndsWith<_pct25Suffix>} VecIdpct25 + * @typedef {WithoutSuffix} VecIdpct25Base + * @typedef {"_pct10"} _pct10Suffix + * @typedef {EndsWith<_pct10Suffix>} VecIdpct10 + * @typedef {WithoutSuffix} VecIdpct10Base * @typedef {"_max"} MaxSuffix * @typedef {EndsWith} VecIdMax * @typedef {WithoutSuffix} VecIdMaxBase @@ -1094,7 +1094,10 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) { lineStyle, }) { return /** @satisfies {FetchedLineSeriesBlueprint} */ ({ - key: `constant_${number >= 0 ? number : `minus_${Math.abs(number)}`}`, + key: `constant_${number >= 0 ? number : `minus_${Math.abs(number)}`}`.replace( + ".", + "_", + ), title: name ?? `${number}`, unit, defaultActive, @@ -1229,7 +1232,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) { /** * @param {Object} args - * @param {VecIdMinBase & VecIdMaxBase & VecIdp90Base & VecIdp75Base & VecIdMedianBase & VecIdp25Base & VecIdp10Base} args.concat + * @param {VecIdMinBase & VecIdMaxBase & VecIdpct90Base & VecIdpct75Base & VecIdMedianBase & VecIdpct25Base & VecIdpct10Base} args.concat * @param {string} [args.title] */ function createMinMaxPercentilesSeries({ concat, title = "" }) { @@ -1253,26 +1256,26 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) { defaultActive: false, }, { - key: `${concat}_p75`, - title: `p75 ${title}`, + key: `${concat}_pct75`, + title: `pct75 ${title}`, color: colors.red, defaultActive: false, }, { - key: `${concat}_p25`, - title: `p25 ${title}`, + key: `${concat}_pct25`, + title: `pct25 ${title}`, color: colors.yellow, defaultActive: false, }, { - key: `${concat}_p90`, - title: `p90 ${title}`, + key: `${concat}_pct90`, + title: `pct90 ${title}`, color: colors.rose, defaultActive: false, }, { - key: `${concat}_p10`, - title: `p10 ${title}`, + key: `${concat}_pct10`, + title: `pct10 ${title}`, color: colors.lime, defaultActive: false, }, @@ -1280,7 +1283,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) { } /** - * @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdp90Base & VecIdp75Base & VecIdMedianBase & VecIdp25Base & VecIdp10Base} key + * @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdpct90Base & VecIdpct75Base & VecIdMedianBase & VecIdpct25Base & VecIdpct10Base} key */ function createSumCumulativeMinMaxPercentilesSeries(key) { return [ @@ -1290,7 +1293,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) { } /** - * @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdp90Base & VecIdp75Base & VecIdMedianBase & VecIdp25Base & VecIdp10Base} key + * @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdpct90Base & VecIdpct75Base & VecIdMedianBase & VecIdpct25Base & VecIdpct10Base} key */ function createAverageSumCumulativeMinMaxPercentilesSeries(key) { return [ @@ -1301,7 +1304,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) { /** * @param {Object} args - * @param {VecId & VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdp90Base & VecIdp75Base & VecIdMedianBase & VecIdp25Base & VecIdp10Base} args.key + * @param {VecId & VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdpct90Base & VecIdpct75Base & VecIdMedianBase & VecIdpct25Base & VecIdpct10Base} args.key * @param {string} args.name */ function createBaseAverageSumCumulativeMinMaxPercentilesSeries({ @@ -3170,6 +3173,72 @@ function createPartialOptions({ env, colors, vecIdToIndexes, pools }) { }), ], }, + { + name: "MinMax", + tree: [ + { + key: "1w", + title: "1 Week", + }, + { + key: "2w", + title: "2 Week", + }, + { + key: "1m", + title: "1 Month", + }, + { + key: "1y", + title: "1 Year", + }, + ].map(({ key, title }) => ({ + name: key, + title: `Bitcoin Price ${title} MinMax Bands`, + top: [ + createBaseSeries({ + key: `price_${key}_min`, + name: "min", + color: colors.red, + }), + createBaseSeries({ + key: `price_${key}_max`, + name: "max", + color: colors.green, + }), + ], + })), + }, + { + name: "True range", + title: "Bitcoin Price True Range", + bottom: [ + createBaseSeries({ + key: "price_true_range", + name: "value", + color: colors.yellow, + }), + ], + }, + { + name: "Choppiness", + title: "Bitcoin Price Choppiness Index", + bottom: [ + createBaseSeries({ + key: "price_2w_choppiness_index", + name: "2w", + color: colors.red, + }), + createPriceLine({ + unit: "Index", + number: 61.8, + }), + createPriceLine({ + unit: "Index", + number: 38.2, + }), + ], + }, { name: "Mayer multiple", title: "Mayer multiple", diff --git a/websites/bitview/scripts/table.js b/websites/bitview/scripts/table.js index 59fd524c3..ebe647995 100644 --- a/websites/bitview/scripts/table.js +++ b/websites/bitview/scripts/table.js @@ -520,7 +520,9 @@ function createIndexToVecIds(vecIdToIndexes) { */ function serializeValue({ value, unit }) { const t = typeof value; - if (typeof value === "string") { + if (value === null) { + return "null"; + } else if (typeof value === "string") { return value; } else if (t !== "number") { return JSON.stringify(value).replaceAll('"', "").slice(1, -1);