diff --git a/Cargo.lock b/Cargo.lock index c2dccf17d..13dd84a38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3895,9 +3895,9 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[package]] name = "seqdb" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567d567faf0a305d66eb0419fc50ba8faec58a3baa8624d7a1fd1c798395044c" +checksum = "c54ab988c96efa9d275ca2b12bf2d3c6adec993b8e82ea31a88c984abdaa14fa" dependencies = [ "libc", "log", @@ -4723,9 +4723,9 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23" [[package]] name = "vecdb" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "236493fb96b34fe7900a3bf62cbb1bd1c5991bc9db563dbbe7ce5cc8c3037cb1" +checksum = "3e5c4ec34c376be3a41435eeb7672d0ea0e9c1d60c5d1d90218912588f91abea" dependencies = [ "ctrlc", "log", @@ -4743,9 +4743,9 @@ dependencies = [ [[package]] name = "vecdb_derive" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d117eb4f82c996a7de2dd5bca1f53da20fa39ae97646405af29eccde67be041" +checksum = "778c4874c05822465e28cae6a7dead593a73124ec80afb85b85adae5ac883368" dependencies = [ "quote", "syn 2.0.106", diff --git a/Cargo.toml b/Cargo.toml index 5dcc3ae36..d2ef2667f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,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.4", features = ["derive"]} +vecdb = { version = "0.2.5", features = ["derive"]} zerocopy = "0.8.26" zerocopy-derive = "0.8.26" diff --git a/TODO.md b/TODO.md index 2f81e4134..48b8141d3 100644 --- a/TODO.md +++ b/TODO.md @@ -13,7 +13,7 @@ - remove configurable format (raw/compressed) and chose sane ones instead - linear reads: compressed (height/date/... + txindex_to_height + txindex_to_version + ...) - random reads: raw (outputindex_to_value + ...) - - add prices paid by percentile (percentile cost basis) back + - add costs basis by percentile (percentile cost basis) back - add support for per index computation - fix min feerate which is always ZERO due to coinbase transaction - before computing multiple sources check their length, panic if not equal diff --git a/crates/brk_computer/src/constants.rs b/crates/brk_computer/src/constants.rs index 1612762c2..23d034edf 100644 --- a/crates/brk_computer/src/constants.rs +++ b/crates/brk_computer/src/constants.rs @@ -26,6 +26,8 @@ pub struct Vecs { pub constant_4: ComputedVecsFromHeight, pub constant_50: ComputedVecsFromHeight, pub constant_100: ComputedVecsFromHeight, + pub constant_144: ComputedVecsFromHeight, + pub constant_600: ComputedVecsFromHeight, pub constant_minus_1: ComputedVecsFromHeight, pub constant_minus_2: ComputedVecsFromHeight, pub constant_minus_3: ComputedVecsFromHeight, @@ -93,6 +95,22 @@ impl Vecs { indexes, VecBuilderOptions::default().add_last(), )?, + constant_144: ComputedVecsFromHeight::forced_import( + &db, + "constant_144", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, + constant_600: ComputedVecsFromHeight::forced_import( + &db, + "constant_600", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, constant_minus_1: ComputedVecsFromHeight::forced_import( &db, "constant_minus_1", @@ -149,192 +167,62 @@ impl Vecs { starting_indexes: &Indexes, exit: &Exit, ) -> Result<()> { - self.constant_0.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, StoredU16::new(0)), - exit, - )?; - Ok(()) - }, - )?; + [ + (&mut self.constant_0, 0), + (&mut self.constant_1, 1), + (&mut self.constant_2, 2), + (&mut self.constant_3, 3), + (&mut self.constant_4, 4), + (&mut self.constant_50, 50), + (&mut self.constant_100, 100), + (&mut self.constant_144, 144), + (&mut self.constant_600, 600), + ] + .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, StoredU16::new(value)), + exit, + )?; + Ok(()) + }, + ) + })?; - self.constant_1.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, StoredU16::new(1)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_2.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, StoredU16::new(2)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_3.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, StoredU16::new(3)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_4.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, StoredU16::new(4)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_50.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, StoredU16::new(50)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_100.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, StoredU16::new(100)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_minus_1.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, StoredI16::new(-1)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_minus_2.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, StoredI16::new(-2)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_minus_3.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, StoredI16::new(-3)), - exit, - )?; - Ok(()) - }, - )?; - - self.constant_minus_4.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, StoredI16::new(-4)), - exit, - )?; - Ok(()) - }, - )?; + [ + (&mut self.constant_minus_1, -1), + (&mut self.constant_minus_2, -2), + (&mut self.constant_minus_3, 3), + (&mut self.constant_minus_4, 4), + ] + .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, StoredI16::new(value)), + exit, + )?; + Ok(()) + }, + ) + })?; Ok(()) } @@ -348,6 +236,8 @@ impl Vecs { self.constant_4.vecs(), self.constant_50.vecs(), self.constant_100.vecs(), + self.constant_144.vecs(), + self.constant_600.vecs(), self.constant_minus_1.vecs(), self.constant_minus_2.vecs(), self.constant_minus_3.vecs(), diff --git a/crates/brk_computer/src/grouped/ratio_from_dateindex.rs b/crates/brk_computer/src/grouped/ratio_from_dateindex.rs index 911f61387..b4a0f2525 100644 --- a/crates/brk_computer/src/grouped/ratio_from_dateindex.rs +++ b/crates/brk_computer/src/grouped/ratio_from_dateindex.rs @@ -320,26 +320,25 @@ impl ComputedRatioVecsFromDateIndex { price: &price::Vecs, starting_indexes: &Indexes, exit: &Exit, - date_to_price_opt: Option<&impl AnyIterableVec>, + price_opt: Option<&impl AnyIterableVec>, ) -> Result<()> { - let date_to_price = date_to_price_opt.unwrap_or_else(|| unsafe { + let closes = price.timeindexes_to_close.dateindex.as_ref().unwrap(); + + let price = price_opt.unwrap_or_else(|| unsafe { std::mem::transmute(&self.price.as_ref().unwrap().dateindex) }); - let closes = price.timeindexes_to_close.dateindex.as_ref().unwrap(); - self.ratio.compute_all( indexer, indexes, starting_indexes, exit, |v, _, _, starting_indexes, exit| { - let mut price = date_to_price.iter(); - v.compute_transform( + v.compute_transform2( starting_indexes.dateindex, closes, - |(i, close, ..)| { - let price = price.unwrap_get_inner(i); + price, + |(i, close, price, ..)| { if price == Dollars::ZERO { (i, StoredF32::from(1.0)) } else { @@ -553,7 +552,7 @@ impl ComputedRatioVecsFromDateIndex { None as Option<&EagerVec<_, _>>, )?; - let date_to_price = date_to_price_opt.unwrap_or_else(|| unsafe { + let date_to_price = price_opt.unwrap_or_else(|| unsafe { std::mem::transmute(&self.price.as_ref().unwrap().dateindex) }); diff --git a/crates/brk_computer/src/lib.rs b/crates/brk_computer/src/lib.rs index d694000d8..1a4da8476 100644 --- a/crates/brk_computer/src/lib.rs +++ b/crates/brk_computer/src/lib.rs @@ -52,6 +52,8 @@ impl Computer { indexer: &Indexer, fetcher: Option, ) -> Result { + info!("Importing computer..."); + let computed_path = outputs_path.join("computed"); let indexes = diff --git a/crates/brk_computer/src/market.rs b/crates/brk_computer/src/market.rs index fde4af2b8..946cb8983 100644 --- a/crates/brk_computer/src/market.rs +++ b/crates/brk_computer/src/market.rs @@ -48,6 +48,21 @@ pub struct Vecs { pub indexes_to_200w_sma: ComputedRatioVecsFromDateIndex, pub indexes_to_4y_sma: ComputedRatioVecsFromDateIndex, + pub indexes_to_1w_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_8d_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_13d_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_21d_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_1m_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_34d_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_55d_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_89d_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_144d_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_200d_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_1y_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_2y_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_200w_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_4y_ema: ComputedRatioVecsFromDateIndex, + pub indexes_to_200d_sma_x2_4: ComputedVecsFromDateIndex, pub indexes_to_200d_sma_x0_8: ComputedVecsFromDateIndex, @@ -350,6 +365,119 @@ impl Vecs { true, )?, + indexes_to_1w_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "1w_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_8d_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "8d_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_13d_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "13d_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_21d_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "21d_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_1m_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "1m_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_34d_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "34d_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_55d_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "55d_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_89d_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "89d_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_144d_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "144d_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_200d_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "200d_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_1y_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "1y_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_2y_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "2y_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_200w_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "200w_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + indexes_to_4y_ema: ComputedRatioVecsFromDateIndex::forced_import( + &db, + "4y_ema", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + true, + )?, + _1d_returns: ComputedVecsFromDateIndex::forced_import( &db, "1d_returns", @@ -1827,25 +1955,69 @@ impl Vecs { thread::scope(|s| -> Result<()> { [ - (&mut self.indexes_to_1w_sma, 7), - (&mut self.indexes_to_8d_sma, 8), - (&mut self.indexes_to_13d_sma, 13), - (&mut self.indexes_to_21d_sma, 21), - (&mut self.indexes_to_1m_sma, 30), - (&mut self.indexes_to_34d_sma, 34), - (&mut self.indexes_to_55d_sma, 55), - (&mut self.indexes_to_89d_sma, 89), - (&mut self.indexes_to_144d_sma, 144), - (&mut self.indexes_to_200d_sma, 200), - (&mut self.indexes_to_1y_sma, 365), - (&mut self.indexes_to_2y_sma, 2 * 365), - (&mut self.indexes_to_200w_sma, 200 * 7), - (&mut self.indexes_to_4y_sma, 4 * 365), + (&mut self.indexes_to_1w_sma, &mut self.indexes_to_1w_ema, 7), + (&mut self.indexes_to_8d_sma, &mut self.indexes_to_8d_ema, 8), + ( + &mut self.indexes_to_13d_sma, + &mut self.indexes_to_13d_ema, + 13, + ), + ( + &mut self.indexes_to_21d_sma, + &mut self.indexes_to_21d_ema, + 21, + ), + (&mut self.indexes_to_1m_sma, &mut self.indexes_to_1m_ema, 30), + ( + &mut self.indexes_to_34d_sma, + &mut self.indexes_to_34d_ema, + 34, + ), + ( + &mut self.indexes_to_55d_sma, + &mut self.indexes_to_55d_ema, + 55, + ), + ( + &mut self.indexes_to_89d_sma, + &mut self.indexes_to_89d_ema, + 89, + ), + ( + &mut self.indexes_to_144d_sma, + &mut self.indexes_to_144d_ema, + 144, + ), + ( + &mut self.indexes_to_200d_sma, + &mut self.indexes_to_200d_ema, + 200, + ), + ( + &mut self.indexes_to_1y_sma, + &mut self.indexes_to_1y_ema, + 365, + ), + ( + &mut self.indexes_to_2y_sma, + &mut self.indexes_to_2y_ema, + 2 * 365, + ), + ( + &mut self.indexes_to_200w_sma, + &mut self.indexes_to_200w_ema, + 200 * 7, + ), + ( + &mut self.indexes_to_4y_sma, + &mut self.indexes_to_4y_ema, + 4 * 365, + ), ] .into_iter() - .for_each(|(vecs, sma)| { + .for_each(|(sma, ema, days)| { s.spawn(move || -> Result<()> { - vecs.compute_all( + sma.compute_all( indexer, indexes, price, @@ -1855,7 +2027,24 @@ impl Vecs { v.compute_sma( starting_indexes.dateindex, price.timeindexes_to_close.dateindex.as_ref().unwrap(), - sma, + days, + exit, + )?; + Ok(()) + }, + )?; + + ema.compute_all( + indexer, + indexes, + price, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_ema( + starting_indexes.dateindex, + price.timeindexes_to_close.dateindex.as_ref().unwrap(), + days, exit, )?; Ok(()) @@ -1935,6 +2124,20 @@ impl Vecs { self.indexes_to_2y_sma.vecs(), self.indexes_to_200w_sma.vecs(), self.indexes_to_4y_sma.vecs(), + self.indexes_to_1w_ema.vecs(), + self.indexes_to_8d_ema.vecs(), + self.indexes_to_13d_ema.vecs(), + self.indexes_to_21d_ema.vecs(), + self.indexes_to_1m_ema.vecs(), + self.indexes_to_34d_ema.vecs(), + self.indexes_to_55d_ema.vecs(), + self.indexes_to_89d_ema.vecs(), + self.indexes_to_144d_ema.vecs(), + self.indexes_to_200d_ema.vecs(), + self.indexes_to_1y_ema.vecs(), + self.indexes_to_2y_ema.vecs(), + self.indexes_to_200w_ema.vecs(), + self.indexes_to_4y_ema.vecs(), self.indexes_to_200d_sma_x0_8.vecs(), self.indexes_to_200d_sma_x2_4.vecs(), self.price_1d_ago.vecs(), diff --git a/crates/brk_computer/src/stateful/common.rs b/crates/brk_computer/src/stateful/common.rs index a6147aeed..f7f27f2eb 100644 --- a/crates/brk_computer/src/stateful/common.rs +++ b/crates/brk_computer/src/stateful/common.rs @@ -50,10 +50,14 @@ pub struct Vecs { pub indexes_to_coinblocks_destroyed: ComputedVecsFromHeight, pub indexes_to_coindays_destroyed: ComputedVecsFromHeight, + pub dateindex_to_spent_output_profit_ratio: Option>, + pub dateindex_to_spent_output_profit_ratio_7d_ema: Option>, pub dateindex_to_adjusted_spent_output_profit_ratio: Option>, + pub dateindex_to_adjusted_spent_output_profit_ratio_7d_ema: + Option>, pub indexes_to_realized_cap_30d_change: Option>, pub dateindex_to_sell_side_risk_ratio: Option>, - pub dateindex_to_spent_output_profit_ratio: Option>, + pub dateindex_to_sell_side_risk_ratio_7d_ema: Option>, pub indexes_to_adjusted_value_created: Option>, pub indexes_to_adjusted_value_destroyed: Option>, pub indexes_to_negative_realized_loss: Option>, @@ -599,6 +603,15 @@ impl Vecs { ) .unwrap() }), + dateindex_to_sell_side_risk_ratio_7d_ema: compute_dollars.then(|| { + EagerVec::forced_import( + db, + &suffix("sell_side_risk_ratio_7d_ema"), + version + VERSION + Version::ONE, + format, + ) + .unwrap() + }), dateindex_to_spent_output_profit_ratio: compute_dollars.then(|| { EagerVec::forced_import( db, @@ -608,6 +621,15 @@ impl Vecs { ) .unwrap() }), + dateindex_to_spent_output_profit_ratio_7d_ema: compute_dollars.then(|| { + EagerVec::forced_import( + db, + &suffix("spent_output_profit_ratio_7d_ema"), + version + VERSION + Version::ZERO, + format, + ) + .unwrap() + }), dateindex_to_adjusted_spent_output_profit_ratio: (compute_dollars && compute_adjusted).then(|| { EagerVec::forced_import( db, @@ -617,6 +639,15 @@ impl Vecs { ) .unwrap() }), + dateindex_to_adjusted_spent_output_profit_ratio_7d_ema: (compute_dollars && compute_adjusted).then(|| { + EagerVec::forced_import( + db, + &suffix("adjusted_spent_output_profit_ratio_7d_ema"), + version + VERSION + Version::ZERO, + format, + ) + .unwrap() + }), height_to_halved_supply_value: ComputedHeightValueVecs::forced_import( db, &suffix("halved_supply"), @@ -2177,6 +2208,18 @@ impl Vecs { exit, )?; + self.dateindex_to_spent_output_profit_ratio_7d_ema + .as_mut() + .unwrap() + .compute_ema( + starting_indexes.dateindex, + self.dateindex_to_spent_output_profit_ratio + .as_ref() + .unwrap(), + 7, + exit, + )?; + self.dateindex_to_sell_side_risk_ratio .as_mut() .unwrap() @@ -2195,6 +2238,16 @@ impl Vecs { exit, )?; + self.dateindex_to_sell_side_risk_ratio_7d_ema + .as_mut() + .unwrap() + .compute_ema( + starting_indexes.dateindex, + self.dateindex_to_sell_side_risk_ratio.as_ref().unwrap(), + 7, + exit, + )?; + self.indexes_to_supply_in_profit .as_mut() .unwrap() @@ -2757,6 +2810,18 @@ impl Vecs { .unwrap_sum(), exit, )?; + + self.dateindex_to_adjusted_spent_output_profit_ratio_7d_ema + .as_mut() + .unwrap() + .compute_ema( + starting_indexes.dateindex, + self.dateindex_to_adjusted_spent_output_profit_ratio + .as_ref() + .unwrap(), + 7, + exit, + )?; } } @@ -2823,9 +2888,15 @@ impl Vecs { self.dateindex_to_spent_output_profit_ratio .as_ref() .map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]), + self.dateindex_to_spent_output_profit_ratio_7d_ema + .as_ref() + .map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]), self.dateindex_to_adjusted_spent_output_profit_ratio .as_ref() .map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]), + self.dateindex_to_adjusted_spent_output_profit_ratio_7d_ema + .as_ref() + .map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]), self.indexes_to_value_destroyed .as_ref() .map_or(vec![], |v| v.vecs()), @@ -2844,6 +2915,9 @@ impl Vecs { self.dateindex_to_sell_side_risk_ratio .as_ref() .map_or(vec![], |v| vec![v]), + self.dateindex_to_sell_side_risk_ratio_7d_ema + .as_ref() + .map_or(vec![], |v| vec![v]), self.height_to_supply_in_profit .as_ref() .map_or(vec![], |v| vec![v]), diff --git a/crates/brk_computer/src/stateful/utxo_cohorts.rs b/crates/brk_computer/src/stateful/utxo_cohorts.rs index 71d54ae3d..cebb25865 100644 --- a/crates/brk_computer/src/stateful/utxo_cohorts.rs +++ b/crates/brk_computer/src/stateful/utxo_cohorts.rs @@ -38,7 +38,7 @@ impl Vecs { db, None, format, - version + VERSION + Version::ZERO, + version + VERSION + Version::ONE, indexes, price, None, @@ -1644,7 +1644,13 @@ impl Vecs { let by_size_range = self.0.amount_range.as_vec(); [ - vec![(&mut self.0.all.1, self.0.epoch.vecs().to_vec())], + vec![( + &mut self.0.all.1, + by_date_range + .into_iter() + .map(|(_, v)| v) + .collect::>(), + )], self.0 .min_age .as_mut_vec() diff --git a/crates/brk_indexer/src/lib.rs b/crates/brk_indexer/src/lib.rs index b82897e79..9eeb67aca 100644 --- a/crates/brk_indexer/src/lib.rs +++ b/crates/brk_indexer/src/lib.rs @@ -36,20 +36,20 @@ pub struct Indexer { impl Indexer { pub fn forced_import(outputs_dir: &Path) -> Result { + info!("Importing indexer..."); + let db = Database::open(&outputs_dir.join("indexed/vecs"))?; + db.set_min_len(PAGE_SIZE * 50_000_000)?; + info!("Opened database"); let vecs = Vecs::forced_import(&db, VERSION + Version::ZERO)?; + info!("Imported vecs"); - db.set_min_len(PAGE_SIZE * 50_000_000)?; + let stores = + Stores::forced_import(&outputs_dir.join("indexed/stores"), VERSION + Version::ZERO)?; + info!("Imported stores"); - Ok(Self { - vecs, - stores: Stores::forced_import( - &outputs_dir.join("indexed/stores"), - VERSION + Version::ZERO, - )?, - db, - }) + Ok(Self { vecs, stores, db }) } pub fn index( diff --git a/crates/brk_structs/src/structs/ohlc.rs b/crates/brk_structs/src/structs/ohlc.rs index 671b199e4..15b846674 100644 --- a/crates/brk_structs/src/structs/ohlc.rs +++ b/crates/brk_structs/src/structs/ohlc.rs @@ -1,4 +1,7 @@ -use std::ops::{Add, AddAssign, Div}; +use std::{ + iter::Sum, + ops::{Add, AddAssign, Div}, +}; use derive_deref::{Deref, DerefMut}; use serde::{Serialize, Serializer, ser::SerializeTuple}; @@ -566,6 +569,12 @@ where } } +impl Sum for Close { + fn sum>(iter: I) -> Self { + Self(Dollars::from(iter.map(|v| f64::from(v.0)).sum::())) + } +} + // impl Mul for Close // where // T: Mul, diff --git a/crates/brk_structs/src/structs/sats.rs b/crates/brk_structs/src/structs/sats.rs index 63006bdd2..b9859a2e0 100644 --- a/crates/brk_structs/src/structs/sats.rs +++ b/crates/brk_structs/src/structs/sats.rs @@ -141,7 +141,7 @@ impl Mul for Sats { impl Sum for Sats { fn sum>(iter: I) -> Self { let sats: u64 = iter.map(|sats| sats.0).sum(); - Sats::from(sats) + Self::from(sats) } } diff --git a/crates/brk_structs/src/structs/stored_f32.rs b/crates/brk_structs/src/structs/stored_f32.rs index 1d68e03b8..50e901840 100644 --- a/crates/brk_structs/src/structs/stored_f32.rs +++ b/crates/brk_structs/src/structs/stored_f32.rs @@ -2,6 +2,7 @@ use core::panic; use std::{ cmp::Ordering, f32, + iter::Sum, ops::{Add, AddAssign, Div, Mul, Sub}, }; @@ -178,3 +179,9 @@ impl Printable for StoredF32 { &["f32"] } } + +impl Sum for StoredF32 { + fn sum>(iter: I) -> Self { + Self(iter.map(|v| v.0).sum::()) + } +} diff --git a/websites/default/assets/fonts/Lilex-Italic[wght]-2.601.woff2 b/websites/default/assets/fonts/Lilex-Italic[wght]-2.601.woff2 new file mode 100644 index 000000000..7864326d3 Binary files /dev/null and b/websites/default/assets/fonts/Lilex-Italic[wght]-2.601.woff2 differ diff --git a/websites/default/assets/fonts/Lilex[wght]-2.601.woff2 b/websites/default/assets/fonts/Lilex[wght]-2.601.woff2 new file mode 100644 index 000000000..7864326d3 Binary files /dev/null and b/websites/default/assets/fonts/Lilex[wght]-2.601.woff2 differ diff --git a/websites/default/index.html b/websites/default/index.html index 15ae556e0..86284aca5 100644 --- a/websites/default/index.html +++ b/websites/default/index.html @@ -215,7 +215,7 @@ --light-gray: oklch(90% 0.01 44); --gray: oklch(60% 0.01 44); --dark-gray: oklch(30% 0.01 44); - --black: oklch(17.5% 0.005 44); + --black: oklch(15% 0.005 44); --red: oklch(0.607 0.241 26.328); --orange: oklch(67.64% 0.191 44.41); --amber: oklch(0.7175 0.1835 64.199); @@ -285,6 +285,15 @@ font-style: normal; } + /*@font-face { + font-family: "Lilex"; + src: url("./assets/fonts/Lilex-Italic[wght]-2.601.woff2") + format("woff2"); + font-weight: 100 900; + font-display: block; + font-style: normal; + }*/ + /* * --- */ @@ -438,9 +447,9 @@ h1, h2 { text-transform: uppercase; - font-size: var(--font-size-lg); - line-height: var(--line-height-lg); - font-weight: 375; + font-size: var(--font-size-xl); + line-height: var(--line-height-xl); + font-weight: 325; } h3 { @@ -1117,7 +1126,7 @@ white-space: nowrap; overflow-x: auto; padding-bottom: 1rem; - margin-bottom: -2rem; + margin-bottom: -1.5rem; padding-left: var(--main-padding); margin-left: var(--negative-main-padding); padding-right: var(--main-padding); diff --git a/websites/default/packages/lightweight-charts/wrapper.js b/websites/default/packages/lightweight-charts/wrapper.js index abc28cdcd..1187c9fd7 100644 --- a/websites/default/packages/lightweight-charts/wrapper.js +++ b/websites/default/packages/lightweight-charts/wrapper.js @@ -50,6 +50,8 @@ import { const oklchToRGBA = createOklchToRGBA(); +const lineWidth = /** @type {any} */ (1.5); + /** * @param {Object} args * @param {string} args.id @@ -436,9 +438,9 @@ function createChartElement({ value: v, }; } else { - if (sameTime) { - console.log(data[offsetedI]); - } + // if (sameTime) { + // console.log(data[offsetedI]); + // } let [open, high, low, close] = v; data[offsetedI] = { time, @@ -690,7 +692,7 @@ function createChartElement({ ichart.addSeries( /** @type {SeriesDefinition<'Line'>} */ (LineSeries), { - lineWidth: /** @type {any} */ (1.5), + lineWidth, visible: defaultActive !== false, priceLineVisible: false, color: color(), @@ -744,7 +746,7 @@ function createChartElement({ ichart.addSeries( /** @type {SeriesDefinition<'Baseline'>} */ (BaselineSeries), { - lineWidth: /** @type {any} */ (1.5), + lineWidth, visible: defaultActive !== false, baseValue: { price: options?.baseValue?.price ?? 0, diff --git a/websites/default/scripts/chart.js b/websites/default/scripts/chart.js index 14ae5b51b..3fb99605e 100644 --- a/websites/default/scripts/chart.js +++ b/websites/default/scripts/chart.js @@ -500,6 +500,7 @@ function createIndexSelector({ option, vecIdToIndexes, signals, utils }) { const rawIndexes = new Set( [Object.values(o.top), Object.values(o.bottom)] .flat(2) + .filter((blueprint) => !blueprint.key.startsWith("constant_")) .map((blueprint) => vecIdToIndexes[blueprint.key]) .flat(), ); diff --git a/websites/default/scripts/main.js b/websites/default/scripts/main.js index c63b21c97..11a77c1f0 100644 --- a/websites/default/scripts/main.js +++ b/websites/default/scripts/main.js @@ -28,7 +28,7 @@ * "percentage" | * "Ratio" | * "Sats" | - * "Seconds" | + * "secs" | * "Timestamp" | * "tx" | * "Type" | @@ -727,7 +727,7 @@ function createUtils() { id.endsWith("stack") || (id.endsWith("value") && !id.includes("realized")) || ((id.includes("coinbase") || - id.includes("fee") || + (id.includes("fee") && !id.includes("feerate")) || id.includes("subsidy") || id.includes("rewards")) && !( @@ -762,7 +762,7 @@ function createUtils() { ((id.includes("realized") || id.includes("true_market_mean")) && !id.includes("ratio") && !id.includes("relative_to")) || - ((id.endsWith("sma") || id.includes("sma_x")) && + ((id.endsWith("sma") || id.includes("sma_x") || id.endsWith("ema")) && !id.includes("ratio")) || id === "ath") ) { @@ -777,7 +777,9 @@ function createUtils() { ((!unit || thoroughUnitCheck) && (id.endsWith("ratio") || (id.includes("ratio") && - (id.endsWith("sma") || id.endsWith("zscore"))) || + (id.endsWith("sma") || + id.endsWith("ema") || + id.endsWith("zscore"))) || id.endsWith("_5sd") || id.endsWith("1sd") || id.endsWith("2sd") || @@ -806,11 +808,15 @@ function createUtils() { (id.endsWith("count") || id.includes("_count_") || id.startsWith("block_count") || - id.includes("tx_v")) + (id.includes("tx_v") && !id.includes("vsize"))) ) { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "Count"; } + if ((!unit || thoroughUnitCheck) && id.includes("feerate")) { + if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); + unit = "sat/vB"; + } if ((!unit || thoroughUnitCheck) && id.startsWith("is_")) { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "Bool"; @@ -824,7 +830,7 @@ function createUtils() { (id === "interval" || id.startsWith("block_interval")) ) { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); - unit = "Seconds"; + unit = "secs"; } if ((!unit || thoroughUnitCheck) && id.endsWith("returns")) { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); @@ -864,10 +870,7 @@ function createUtils() { } if ( (!unit || thoroughUnitCheck) && - (id.endsWith("vsize") || - id.endsWith("vbytes") || - id.endsWith("_vbytes_sum") || - id.endsWith("_vbytes_cumulative")) + (id.includes("vsize") || id.includes("vbytes")) ) { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "vB"; @@ -2402,9 +2405,7 @@ function main() { return treeElement; }); - if (localhost) { - setTimeout(scrollToSelected, 10); - } + setTimeout(scrollToSelected, 10); }); } initFolders(); diff --git a/websites/default/scripts/options.js b/websites/default/scripts/options.js index 0d00c1d8c..a0a0f6cc8 100644 --- a/websites/default/scripts/options.js +++ b/websites/default/scripts/options.js @@ -908,7 +908,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { }, { key: "above_100k_btc", - name: "100K btc+", + name: "100K+ btc", title: "Above 100K BTC", color: colors.yellow, }, @@ -1066,13 +1066,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { /** * @param {Object} args * @param {number} [args.number] + * @param {string} [args.name] * @param {boolean} [args.defaultActive] * @param {Unit} args.unit */ - function createPriceLine({ number = 0, unit, defaultActive }) { + function createPriceLine({ number = 0, unit, defaultActive, name }) { return /** @satisfies {FetchedLineSeriesBlueprint} */ ({ key: `constant_${number >= 0 ? number : `minus_${Math.abs(number)}`}`, - title: `${number}`, + title: name ?? `${number}`, unit, defaultActive, color: colors.gray, @@ -1138,80 +1139,117 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { /** * @param {Object} args * @param {VecIdAverageBase} args.concat + * @param {string} [args.title] */ - function createAverageSeries({ concat }) { + function createAverageSeries({ concat, title = "" }) { return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({ key: `${concat}_average`, - title: "Average", + title: `Average ${title}`, }); } /** * @param {Object} args * @param {CumulativeVecIdBase} args.concat - * @param {string} [args.name] + * @param {Color} [args.sumColor] + * @param {Color} [args.cumulativeColor] + * @param {string} [args.common] */ - function createSumCumulativeSeries({ concat, name }) { + function createSumCumulativeSeries({ + concat, + common, + sumColor, + cumulativeColor, + }) { return /** @satisfies {AnyFetchedSeriesBlueprint[]} */ ([ - { + createSumSeries({ key: concat, - title: name ? `${name} Sum` : "Sum", - color: colors.orange, - }, - { - key: `${concat}_cumulative`, - title: name ? `Cumulative ${name}` : "Cumulative", - color: colors.red, - defaultActive: false, - }, + title: common, + color: sumColor, + }), + createCumulativeSeries({ + concat, + title: common, + color: cumulativeColor, + }), ]); } /** * @param {Object} args - * @param {VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.concat + * @param {CumulativeVecIdBase} args.key + * @param {string} [args.title] + * @param {Color} [args.color] */ - function createMinMaxPercentilesSeries({ concat }) { + function createSumSeries({ key, title = "", color }) { + return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({ + key, + title: `Sum ${title}`, + color: color ?? colors.orange, + }); + } + + /** + * @param {Object} args + * @param {CumulativeVecIdBase} args.concat + * @param {string} [args.title] + * @param {Color} [args.color] + */ + function createCumulativeSeries({ concat, title = "", color }) { + return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({ + key: `${concat}_cumulative`, + title: `Cumulative ${title}`, + color: color ?? colors.red, + defaultActive: false, + }); + } + + /** + * @param {Object} args + * @param {VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.concat + * @param {string} [args.title] + */ + function createMinMaxPercentilesSeries({ concat, title = "" }) { return /** @satisfies {AnyFetchedSeriesBlueprint[]} */ ([ { key: `${concat}_max`, - title: "Max", + title: `Max ${title}`, color: colors.pink, defaultActive: false, }, { key: `${concat}_min`, - title: "Min", + title: `Min ${title}`, color: colors.green, defaultActive: false, }, { key: `${concat}_median`, - title: "Median", + title: `Median ${title}`, color: colors.amber, defaultActive: false, }, { key: `${concat}_75p`, - title: "75p", + title: `75p ${title}`, color: colors.red, defaultActive: false, }, { key: `${concat}_25p`, - title: "25p", + title: `25p ${title}`, color: colors.yellow, defaultActive: false, }, { key: `${concat}_90p`, - title: "90p", + title: `90p ${title}`, color: colors.rose, defaultActive: false, }, { key: `${concat}_10p`, - title: "10p", + title: `10p ${title}`, color: colors.lime, defaultActive: false, }, @@ -1280,6 +1318,66 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { * @param {Color} [args.color] */ function createPriceWithRatioOptions({ name, title, legend, key, color }) { + const percentiles = [ + { + name: "p1", + color: colors.indigo, + }, + { + name: "p2", + color: colors.violet, + }, + { + name: "p5", + color: colors.purple, + }, + { + name: "p95", + color: colors.amber, + }, + { + name: "p98", + color: colors.orange, + }, + { + name: "p99", + color: colors.red, + }, + ]; + + const ratioAverages = /** @type {const} */ ([ + { + name: "1w sma", + key: "1w_sma", + color: colors.lime, + }, + { + name: "1m sma", + key: "1m_sma", + color: colors.teal, + }, + { + name: "1y sma", + key: "1y_sma", + color: colors.sky, + }, + { + name: "2y sma", + key: "2y_sma", + color: colors.indigo, + }, + { + name: "4y sma", + key: "4y_sma", + color: colors.purple, + }, + { + name: "all sma", + key: "sma", + color: colors.rose, + }, + ]); + return [ { name: "price", @@ -1302,44 +1400,17 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { color, }), ...(`${key}_ratio_p1sd_as_price` in vecIdToIndexes - ? [ + ? percentiles.map(({ name, color }) => createBaseSeries({ - key: `${key}_ratio_p1_as_price`, - name: "p1", - color: colors.indigo, + key: `${key}_ratio_${name}_as_price`, + name, + color, defaultActive: false, + options: { + lineStyle: 1, + }, }), - createBaseSeries({ - key: `${key}_ratio_p2_as_price`, - name: "p2", - color: colors.violet, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p5_as_price`, - name: "p5", - color: colors.purple, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p95_as_price`, - name: "p95", - color: colors.amber, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p98_as_price`, - name: "p98", - color: colors.orange, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p99_as_price`, - name: "p99", - color: colors.red, - defaultActive: false, - }), - ] + ) : []), ], bottom: [ @@ -1352,80 +1423,30 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { }, }), ...(`${key}_ratio_p1sd` in vecIdToIndexes - ? [ + ? percentiles.map(({ name, color }) => createBaseSeries({ - key: `${key}_ratio_p1`, - name: "p1", - color: colors.indigo, + key: `${key}_ratio_${name}`, + name, + color, defaultActive: false, + options: { + lineStyle: 1, + }, }), + ) + : []), + ...(`${key}_ratio_sma` in vecIdToIndexes + ? ratioAverages.map(({ name, key: keyAddon, color }) => createBaseSeries({ - key: `${key}_ratio_p2`, - name: "p2", - color: colors.violet, + key: `${key}_ratio_${keyAddon}`, + name, + color, defaultActive: false, + options: { + lineStyle: 1, + }, }), - createBaseSeries({ - key: `${key}_ratio_p5`, - name: "p5", - color: colors.purple, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p95`, - name: "p95", - color: colors.amber, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p98`, - name: "p98", - color: colors.orange, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p99`, - name: "p99", - color: colors.red, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_1w_sma`, - name: "1w sma", - color: colors.rose, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_1m_sma`, - name: "1m sma", - color: colors.pink, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_1y_sma`, - name: "1y sma", - color: colors.fuchsia, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_2y_sma`, - name: "2y sma", - color: colors.purple, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_4y_sma`, - name: "4y sma", - color: colors.violet, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_sma`, - name: "sma", - color: colors.indigo, - defaultActive: false, - }), - ] + ) : []), createPriceLine({ number: 1, @@ -1532,89 +1553,84 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { name: legend, color, }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}0sd_as_price`, - name: "0σ", - color: colors.lime, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}p0_5sd_as_price`, - name: "+0.5σ", - color: colors.yellow, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}p1sd_as_price`, - name: "+1σ", - color: colors.amber, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}p1_5sd_as_price`, - name: "+1.5σ", - color: colors.orange, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}p2sd_as_price`, - name: "+2σ", - color: colors.red, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}p2_5sd_as_price`, - name: "+2.5σ", - color: colors.rose, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}p3sd_as_price`, - name: "+3σ", - color: colors.pink, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}m0_5sd_as_price`, - name: "−0.5σ", - color: colors.teal, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}m1sd_as_price`, - name: "−1σ", - color: colors.cyan, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}m1_5sd_as_price`, - name: "−1.5σ", - color: colors.sky, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}m2sd_as_price`, - name: "−2σ", - color: colors.blue, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}m2_5sd_as_price`, - name: "−2.5σ", - color: colors.indigo, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_${keyAddon}m3sd_as_price`, - name: "−3σ", - color: colors.violet, - defaultActive: false, - }), + ...[ + { sdKey: "0sd", name: "0σ", color: colors.lime }, + { + sdKey: `p0_5sd`, + name: "+0.5σ", + color: colors.yellow, + }, + { + sdKey: `p1sd`, + name: "+1σ", + color: colors.amber, + }, + { + sdKey: `p1_5sd`, + name: "+1.5σ", + color: colors.orange, + }, + { + sdKey: `p2sd`, + name: "+2σ", + color: colors.red, + }, + { + sdKey: `p2_5sd`, + name: "+2.5σ", + color: colors.rose, + }, + { + sdKey: `p3sd`, + name: "+3σ", + color: colors.pink, + }, + { + sdKey: `m0_5sd`, + name: "−0.5σ", + color: colors.teal, + }, + { + sdKey: `m1sd`, + name: "−1σ", + color: colors.cyan, + }, + { + sdKey: `m1_5sd`, + name: "−1.5σ", + color: colors.sky, + }, + { + sdKey: `m2sd`, + name: "−2σ", + color: colors.blue, + }, + { + sdKey: `m2_5sd`, + name: "−2.5σ", + color: colors.indigo, + }, + { + sdKey: `m3sd`, + name: "−3σ", + color: colors.violet, + }, + ].map(({ sdKey, name, color }) => + createBaseSeries({ + key: `${key}_ratio_${keyAddon}${sdKey}_as_price`, + name, + color, + defaultActive: false, + options: { + lineStyle: 1, + }, + }), + ), ], bottom: [ /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ key: `${key}_ratio_${keyAddon}zscore`, - title: "All time", + title: "score", type: "Baseline", }), ...createPriceLines({ @@ -2256,7 +2272,19 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: soprKey, - title: "sopr", + title: "normal", + options: { + baseValue: { + price: 1, + }, + }, + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${soprKey}_7d_ema`, + title: "7d ema", + colors: [colors.lime, colors.rose], + defaultActive: false, options: { baseValue: { price: 1, @@ -2268,8 +2296,21 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: asoprKey, - title: "asopr", - colors: [colors.yellow, colors.pink], + title: "adjusted", + colors: [colors.avocado, colors.pink], + defaultActive: false, + options: { + baseValue: { + price: 1, + }, + }, + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${asoprKey}_7d_ema`, + title: "adj. 7d ema", + colors: [colors.yellow, colors.fuchsia], + defaultActive: false, options: { baseValue: { price: 1, @@ -2519,16 +2560,31 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { ], }, ]), + { name: "Sell Side Risk Ratio", title: `Sell Side Risk Ratio ${title}`, - bottom: list.flatMap(({ color, name, key }) => - createBaseSeries({ - key: `${fixKey(key)}sell_side_risk_ratio`, - name: useGroupName ? name : "Risk", - color: color, - }), - ), + bottom: !("list" in args) + ? list.flatMap(({ key }) => [ + createBaseSeries({ + key: `${fixKey(key)}sell_side_risk_ratio`, + name: "raw", + color: colors.orange, + }), + createBaseSeries({ + key: `${fixKey(key)}sell_side_risk_ratio_7d_ema`, + name: "7d ema", + color: colors.red, + defaultActive: false, + }), + ]) + : list.flatMap(({ color, name, key }) => [ + createBaseSeries({ + key: `${fixKey(key)}sell_side_risk_ratio`, + name, + color: color, + }), + ]), }, ], }, @@ -2627,11 +2683,11 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { ...("list" in args ? [ { - name: "Price paid", + name: "Cost Basis", tree: [ { name: "Average", - title: `Average Price Paid ${title}`, + title: `Average Cost Basis ${title}`, top: list.flatMap(({ color, name, key: _key }) => { const key = fixKey(_key); return /** @type {const} */ ([ @@ -2645,7 +2701,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { }, { name: "Min", - title: `Min Price Paid ${title}`, + title: `Min Cost Basis ${title}`, top: list.flatMap(({ color, name, key: _key }) => { const key = fixKey(_key); return /** @type {const} */ ([ @@ -2659,7 +2715,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { }, { name: "Max", - title: `Max Price Paid ${title}`, + title: `Max Cost Basis ${title}`, top: list.flatMap(({ color, name, key: _key }) => { const key = fixKey(_key); return /** @type {const} */ ([ @@ -2676,8 +2732,8 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { ] : [ { - name: "Price paid", - title: `Prices Paid ${title}`, + name: "Cost Basis", + title: `Costs Basis ${title}`, top: [ createBaseSeries({ key: `${fixKey(args.key)}realized_price`, @@ -2799,30 +2855,42 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { ], }, { - name: "Average", + name: "Averages", tree: [ { - name: "Compare", - title: "Market Price Moving Averages", - top: averages.map(({ days, key, name, color }) => - createBaseSeries({ - key: `${key}_sma`, - name: key, + nameAddon: "Simple", + keyAddon: "sma", + }, + { + nameAddon: "Exponential", + keyAddon: "ema", + }, + ].map(({ nameAddon, keyAddon }) => ({ + name: nameAddon, + tree: [ + { + name: "Compare", + title: `Market Price ${nameAddon} Moving Averages`, + top: averages.map(({ days, key, name, color }) => + createBaseSeries({ + key: `${key}_${keyAddon}`, + name: key, + color, + }), + ), + }, + ...averages.map(({ key, name, color }) => ({ + name, + tree: createPriceWithRatioOptions({ + key: `${key}_${keyAddon}`, + name, + title: `${name} Market Price ${nameAddon} Moving Average`, + legend: "average", color, }), - ), - }, - ...averages.map(({ key, name, color }) => ({ - name, - tree: createPriceWithRatioOptions({ - key: `${key}_sma`, - name, - title: `${name} Market Price Moving Average`, - legend: "average", - color, - }), - })), - ], + })), + ], + })), }, { name: "Performance", @@ -3107,17 +3175,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { name: "Unclaimed Rewards", title: "Unclaimed Rewards", bottom: [ - ...createBaseSumCumulativeSeries({ - key: "unclaimed_rewards", - name: "unclaimed", + ...createSumCumulativeSeries({ + concat: "unclaimed_rewards", }), - ...createBaseSumCumulativeSeries({ - key: "unclaimed_rewards_in_btc", - name: "unclaimed", + ...createSumCumulativeSeries({ + concat: "unclaimed_rewards_in_btc", }), - ...createBaseSumCumulativeSeries({ - key: "unclaimed_rewards_in_usd", - name: "unclaimed", + ...createSumCumulativeSeries({ + concat: "unclaimed_rewards_in_usd", }), ], }, @@ -3170,11 +3235,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { name: "Count", title: "Block Count", bottom: [ - createBaseSeries({ - key: "block_count", - name: "Count", + ...createSumCumulativeSeries({ + concat: "block_count", + }), + createPriceLine({ + unit: "Count", + name: "Target", + number: 144, }), - ...createSumCumulativeSeries({ concat: "block_count" }), ], }, { @@ -3189,6 +3257,11 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { ...createMinMaxPercentilesSeries({ concat: "block_interval", }), + createPriceLine({ + unit: "secs", + name: "Target", + number: 600, + }), ], }, { @@ -3199,29 +3272,31 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { key: "total_size", name: "Size", }), - ...createSumCumulativeSeries({ concat: "block_size" }), + ...createSumCumulativeSeries({ + concat: "block_size", + }), ], }, { - name: "Weight", - title: "Block Weight", + name: "Bytes", + title: "Block Bytes", bottom: [ createBaseSeries({ key: "weight", name: "Weight", }), - ...createSumCumulativeSeries({ concat: "block_weight" }), - ], - }, - { - name: "Vbytes", - title: "Block Virtual Bytes", - bottom: [ + ...createSumCumulativeSeries({ + concat: "block_weight", + common: "weight", + }), createBaseSeries({ key: "vbytes", name: "Vbytes", }), - ...createSumCumulativeSeries({ concat: "block_vbytes" }), + ...createSumCumulativeSeries({ + concat: "block_vbytes", + common: "Vbytes", + }), ], }, ], @@ -3238,22 +3313,18 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { }), }, { - name: "Weight", - title: "Transaction Weight", + name: "Bytes", + title: "Transaction Bytes", bottom: [ - createAverageSeries({ concat: "tx_weight" }), + createAverageSeries({ concat: "tx_weight", title: "Weight" }), ...createMinMaxPercentilesSeries({ concat: "tx_weight", + title: "Weight", }), - ], - }, - { - name: "vsize", - title: "Transaction Virtual Size", - bottom: [ - createAverageSeries({ concat: "tx_vsize" }), + createAverageSeries({ concat: "tx_vsize", title: "VSize" }), ...createMinMaxPercentilesSeries({ concat: "tx_vsize", + title: "VSize", }), ], }, @@ -3261,22 +3332,17 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { name: "Versions", title: "Transaction Versions", bottom: [ - createBaseSeries({ - key: "tx_v1", - name: "v1 Count", + [colors.orange, colors.red], + [colors.cyan, colors.blue], + [colors.lime, colors.green], + ].flatMap(([sumColor, cumulativeColor], index) => + createSumCumulativeSeries({ + concat: `tx_v${index + 1}`, + common: `v${index + 1}`, + sumColor, + cumulativeColor, }), - ...createSumCumulativeSeries({ concat: "tx_v1", name: "v1" }), - createBaseSeries({ - key: "tx_v2", - name: "v2 Count", - }), - ...createSumCumulativeSeries({ concat: "tx_v2", name: "v2" }), - createBaseSeries({ - key: "tx_v3", - name: "v3 Count", - }), - ...createSumCumulativeSeries({ concat: "tx_v3", name: "v3" }), - ], + ), }, ], }, @@ -3288,7 +3354,9 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { title: "Transaction Input Count", bottom: [ createAverageSeries({ concat: "input_count" }), - ...createSumCumulativeSeries({ concat: "input_count" }), + createCumulativeSeries({ + concat: "input_count", + }), ...createMinMaxPercentilesSeries({ concat: "input_count", }), @@ -3312,7 +3380,9 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { title: "Transaction Output Count", bottom: [ createAverageSeries({ concat: "output_count" }), - ...createSumCumulativeSeries({ concat: "output_count" }), + createCumulativeSeries({ + concat: "input_count", + }), ...createMinMaxPercentilesSeries({ concat: "output_count", }), diff --git a/websites/default/scripts/simulation.js b/websites/default/scripts/simulation.js index 4f6864f27..2a1f915da 100644 --- a/websites/default/scripts/simulation.js +++ b/websites/default/scripts/simulation.js @@ -770,7 +770,7 @@ export function init({ data: bitcoinPriceData, }, { - title: "Average Price Paid", + title: "Average Cost Basis", type: "Line", color: colors.lime, data: averagePricePaidData,