diff --git a/crates/brk_computer/src/storage/vecs/marketprice.rs b/crates/brk_computer/src/storage/vecs/marketprice.rs index 341cd99de..fea826bc6 100644 --- a/crates/brk_computer/src/storage/vecs/marketprice.rs +++ b/crates/brk_computer/src/storage/vecs/marketprice.rs @@ -2,7 +2,7 @@ use std::{fs, path::Path}; use brk_core::{ Cents, Close, Dateindex, Decadeindex, Difficultyepoch, Dollars, Height, High, Low, Monthindex, - OHLCCents, OHLCDollars, Open, Quarterindex, Sats, Weekindex, Yearindex, + OHLCCents, OHLCDollars, OHLCSats, Open, Quarterindex, Sats, Weekindex, Yearindex, }; use brk_exit::Exit; use brk_fetcher::Fetcher; @@ -23,31 +23,46 @@ pub struct Vecs { pub dateindex_to_high_in_cents: ComputedVec>, pub dateindex_to_low_in_cents: ComputedVec>, pub dateindex_to_ohlc: ComputedVec, + pub dateindex_to_ohlc_in_sats: ComputedVec, pub dateindex_to_ohlc_in_cents: ComputedVec, pub dateindex_to_open_in_cents: ComputedVec>, pub height_to_close_in_cents: ComputedVec>, pub height_to_high_in_cents: ComputedVec>, pub height_to_low_in_cents: ComputedVec>, pub height_to_ohlc: ComputedVec, + pub height_to_ohlc_in_sats: ComputedVec, pub height_to_ohlc_in_cents: ComputedVec, pub height_to_open_in_cents: ComputedVec>, pub timeindexes_to_close: ComputedVecsFromDateindex>, pub timeindexes_to_high: ComputedVecsFromDateindex>, pub timeindexes_to_low: ComputedVecsFromDateindex>, pub timeindexes_to_open: ComputedVecsFromDateindex>, - pub timeindexes_to_sats_per_dollar: ComputedVecsFromDateindex>, + pub timeindexes_to_open_in_sats: ComputedVecsFromDateindex>, + pub timeindexes_to_high_in_sats: ComputedVecsFromDateindex>, + pub timeindexes_to_low_in_sats: ComputedVecsFromDateindex>, + pub timeindexes_to_close_in_sats: ComputedVecsFromDateindex>, pub chainindexes_to_close: ComputedVecsFromHeightStrict>, pub chainindexes_to_high: ComputedVecsFromHeightStrict>, pub chainindexes_to_low: ComputedVecsFromHeightStrict>, pub chainindexes_to_open: ComputedVecsFromHeightStrict>, - pub chainindexes_to_sats_per_dollar: ComputedVecsFromHeightStrict>, + pub chainindexes_to_open_in_sats: ComputedVecsFromHeightStrict>, + pub chainindexes_to_high_in_sats: ComputedVecsFromHeightStrict>, + pub chainindexes_to_low_in_sats: ComputedVecsFromHeightStrict>, + pub chainindexes_to_close_in_sats: ComputedVecsFromHeightStrict>, pub weekindex_to_ohlc: ComputedVec, + pub weekindex_to_ohlc_in_sats: ComputedVec, pub difficultyepoch_to_ohlc: ComputedVec, + pub difficultyepoch_to_ohlc_in_sats: ComputedVec, pub monthindex_to_ohlc: ComputedVec, + pub monthindex_to_ohlc_in_sats: ComputedVec, pub quarterindex_to_ohlc: ComputedVec, + pub quarterindex_to_ohlc_in_sats: ComputedVec, pub yearindex_to_ohlc: ComputedVec, + pub yearindex_to_ohlc_in_sats: ComputedVec, // pub halvingepoch_to_ohlc: StorableVec, + // pub halvingepoch_to_ohlc_in_sats: StorableVec, pub decadeindex_to_ohlc: ComputedVec, + pub decadeindex_to_ohlc_in_sats: ComputedVec, } impl Vecs { @@ -70,6 +85,11 @@ impl Vecs { Version::ZERO, compressed, )?, + dateindex_to_ohlc_in_sats: ComputedVec::forced_import( + &path.join("dateindex_to_ohlc_in_sats"), + Version::ZERO, + compressed, + )?, dateindex_to_close_in_cents: ComputedVec::forced_import( &path.join("dateindex_to_close_in_cents"), Version::ZERO, @@ -100,6 +120,11 @@ impl Vecs { Version::ZERO, compressed, )?, + height_to_ohlc_in_sats: ComputedVec::forced_import( + &path.join("height_to_ohlc_in_sats"), + Version::ZERO, + compressed, + )?, height_to_close_in_cents: ComputedVec::forced_import( &path.join("height_to_close_in_cents"), Version::ZERO, @@ -148,9 +173,30 @@ impl Vecs { compressed, StorableVecGeneatorOptions::default().add_last(), )?, - timeindexes_to_sats_per_dollar: ComputedVecsFromDateindex::forced_import( + timeindexes_to_open_in_sats: ComputedVecsFromDateindex::forced_import( path, - "sats_per_dollar", + "open_in_sats", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_first(), + )?, + timeindexes_to_high_in_sats: ComputedVecsFromDateindex::forced_import( + path, + "high_in_sats", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_max(), + )?, + timeindexes_to_low_in_sats: ComputedVecsFromDateindex::forced_import( + path, + "low_in_sats", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_min(), + )?, + timeindexes_to_close_in_sats: ComputedVecsFromDateindex::forced_import( + path, + "close_in_sats", Version::ZERO, compressed, StorableVecGeneatorOptions::default().add_last(), @@ -183,9 +229,30 @@ impl Vecs { compressed, StorableVecGeneatorOptions::default().add_last(), )?, - chainindexes_to_sats_per_dollar: ComputedVecsFromHeightStrict::forced_import( + chainindexes_to_open_in_sats: ComputedVecsFromHeightStrict::forced_import( path, - "sats_per_dollar", + "open_in_sats", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_first(), + )?, + chainindexes_to_high_in_sats: ComputedVecsFromHeightStrict::forced_import( + path, + "high_in_sats", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_max(), + )?, + chainindexes_to_low_in_sats: ComputedVecsFromHeightStrict::forced_import( + path, + "low_in_sats", + Version::ZERO, + compressed, + StorableVecGeneatorOptions::default().add_min(), + )?, + chainindexes_to_close_in_sats: ComputedVecsFromHeightStrict::forced_import( + path, + "close_in_sats", Version::ZERO, compressed, StorableVecGeneatorOptions::default().add_last(), @@ -195,32 +262,62 @@ impl Vecs { Version::ZERO, compressed, )?, + weekindex_to_ohlc_in_sats: ComputedVec::forced_import( + &path.join("weekindex_to_ohlc_in_sats"), + Version::ZERO, + compressed, + )?, difficultyepoch_to_ohlc: ComputedVec::forced_import( &path.join("difficultyepoch_to_ohlc"), Version::ZERO, compressed, )?, + difficultyepoch_to_ohlc_in_sats: ComputedVec::forced_import( + &path.join("difficultyepoch_to_ohlc_in_sats"), + Version::ZERO, + compressed, + )?, monthindex_to_ohlc: ComputedVec::forced_import( &path.join("monthindex_to_ohlc"), Version::ZERO, compressed, )?, + monthindex_to_ohlc_in_sats: ComputedVec::forced_import( + &path.join("monthindex_to_ohlc_in_sats"), + Version::ZERO, + compressed, + )?, quarterindex_to_ohlc: ComputedVec::forced_import( &path.join("quarterindex_to_ohlc"), Version::ZERO, compressed, )?, + quarterindex_to_ohlc_in_sats: ComputedVec::forced_import( + &path.join("quarterindex_to_ohlc_in_sats"), + Version::ZERO, + compressed, + )?, yearindex_to_ohlc: ComputedVec::forced_import( &path.join("yearindex_to_ohlc"), Version::ZERO, compressed, )?, + yearindex_to_ohlc_in_sats: ComputedVec::forced_import( + &path.join("yearindex_to_ohlc_in_sats"), + Version::ZERO, + compressed, + )?, // halvingepoch_to_ohlc: StorableVec::forced_import(&path.join("halvingepoch_to_ohlc"), Version::ZERO, compressed)?, decadeindex_to_ohlc: ComputedVec::forced_import( &path.join("decadeindex_to_ohlc"), Version::ZERO, compressed, )?, + decadeindex_to_ohlc_in_sats: ComputedVec::forced_import( + &path.join("decadeindex_to_ohlc_in_sats"), + Version::ZERO, + compressed, + )?, }) } @@ -637,7 +734,52 @@ impl Vecs { exit, )?; - self.chainindexes_to_sats_per_dollar.compute( + self.chainindexes_to_open_in_sats.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_transform( + starting_indexes.height, + self.chainindexes_to_open.height.mut_vec(), + |(i, open, ..)| (i, Open::new(Sats::ONE_BTC / *open)), + exit, + ) + }, + )?; + + self.chainindexes_to_high_in_sats.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_transform( + starting_indexes.height, + self.chainindexes_to_low.height.mut_vec(), + |(i, low, ..)| (i, High::new(Sats::ONE_BTC / *low)), + exit, + ) + }, + )?; + + self.chainindexes_to_low_in_sats.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_transform( + starting_indexes.height, + self.chainindexes_to_high.height.mut_vec(), + |(i, high, ..)| (i, Low::new(Sats::ONE_BTC / *high)), + exit, + ) + }, + )?; + + self.chainindexes_to_close_in_sats.compute( indexer, indexes, starting_indexes, @@ -646,13 +788,58 @@ impl Vecs { v.compute_transform( starting_indexes.height, self.chainindexes_to_close.height.mut_vec(), - |(i, close, ..)| (i, Close::from(Sats::ONE_BTC / *close)), + |(i, close, ..)| (i, Close::new(Sats::ONE_BTC / *close)), exit, ) }, )?; - self.timeindexes_to_sats_per_dollar.compute( + self.timeindexes_to_open_in_sats.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_transform( + starting_indexes.dateindex, + self.timeindexes_to_open.dateindex.mut_vec(), + |(i, open, ..)| (i, Open::new(Sats::ONE_BTC / *open)), + exit, + ) + }, + )?; + + self.timeindexes_to_high_in_sats.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_transform( + starting_indexes.dateindex, + self.timeindexes_to_low.dateindex.mut_vec(), + |(i, low, ..)| (i, High::new(Sats::ONE_BTC / *low)), + exit, + ) + }, + )?; + + self.timeindexes_to_low_in_sats.compute( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_transform( + starting_indexes.dateindex, + self.timeindexes_to_high.dateindex.mut_vec(), + |(i, high, ..)| (i, Low::new(Sats::ONE_BTC / *high)), + exit, + ) + }, + )?; + + self.timeindexes_to_close_in_sats.compute( indexer, indexes, starting_indexes, @@ -661,12 +848,259 @@ impl Vecs { v.compute_transform( starting_indexes.dateindex, self.timeindexes_to_close.dateindex.mut_vec(), - |(i, close, ..)| (i, Close::from(Sats::ONE_BTC / *close)), + |(i, close, ..)| (i, Close::new(Sats::ONE_BTC / *close)), exit, ) }, )?; + self.height_to_ohlc_in_sats.compute_transform( + starting_indexes.height, + self.chainindexes_to_close_in_sats.height.mut_vec(), + |(i, close, ..)| { + ( + i, + OHLCSats { + open: self + .chainindexes_to_open_in_sats + .height + .double_unwrap_cached_get(i), + high: self + .chainindexes_to_high_in_sats + .height + .double_unwrap_cached_get(i), + low: self + .chainindexes_to_low_in_sats + .height + .double_unwrap_cached_get(i), + close, + }, + ) + }, + exit, + )?; + + self.dateindex_to_ohlc_in_sats.compute_transform( + starting_indexes.dateindex, + self.timeindexes_to_close_in_sats.dateindex.mut_vec(), + |(i, close, ..)| { + ( + i, + OHLCSats { + open: self + .timeindexes_to_open_in_sats + .dateindex + .double_unwrap_cached_get(i), + high: self + .timeindexes_to_high_in_sats + .dateindex + .double_unwrap_cached_get(i), + low: self + .timeindexes_to_low_in_sats + .dateindex + .double_unwrap_cached_get(i), + close, + }, + ) + }, + exit, + )?; + + self.weekindex_to_ohlc_in_sats.compute_transform( + starting_indexes.weekindex, + self.timeindexes_to_close_in_sats + .weekindex + .unwrap_last() + .mut_vec(), + |(i, close, ..)| { + ( + i, + OHLCSats { + open: self + .timeindexes_to_open_in_sats + .weekindex + .unwrap_first() + .double_unwrap_cached_get(i), + high: self + .timeindexes_to_high_in_sats + .weekindex + .unwrap_max() + .double_unwrap_cached_get(i), + low: self + .timeindexes_to_low_in_sats + .weekindex + .unwrap_min() + .double_unwrap_cached_get(i), + close, + }, + ) + }, + exit, + )?; + + self.difficultyepoch_to_ohlc_in_sats.compute_transform( + starting_indexes.difficultyepoch, + self.chainindexes_to_close_in_sats + .difficultyepoch + .unwrap_last() + .mut_vec(), + |(i, close, ..)| { + ( + i, + OHLCSats { + open: self + .chainindexes_to_open_in_sats + .difficultyepoch + .unwrap_first() + .double_unwrap_cached_get(i), + high: self + .chainindexes_to_high_in_sats + .difficultyepoch + .unwrap_max() + .double_unwrap_cached_get(i), + low: self + .chainindexes_to_low_in_sats + .difficultyepoch + .unwrap_min() + .double_unwrap_cached_get(i), + close, + }, + ) + }, + exit, + )?; + + self.monthindex_to_ohlc_in_sats.compute_transform( + starting_indexes.monthindex, + self.timeindexes_to_close_in_sats + .monthindex + .unwrap_last() + .mut_vec(), + |(i, close, ..)| { + ( + i, + OHLCSats { + open: self + .timeindexes_to_open_in_sats + .monthindex + .unwrap_first() + .double_unwrap_cached_get(i), + high: self + .timeindexes_to_high_in_sats + .monthindex + .unwrap_max() + .double_unwrap_cached_get(i), + low: self + .timeindexes_to_low_in_sats + .monthindex + .unwrap_min() + .double_unwrap_cached_get(i), + close, + }, + ) + }, + exit, + )?; + + self.quarterindex_to_ohlc_in_sats.compute_transform( + starting_indexes.quarterindex, + self.timeindexes_to_close_in_sats + .quarterindex + .unwrap_last() + .mut_vec(), + |(i, close, ..)| { + ( + i, + OHLCSats { + open: self + .timeindexes_to_open_in_sats + .quarterindex + .unwrap_first() + .double_unwrap_cached_get(i), + high: self + .timeindexes_to_high_in_sats + .quarterindex + .unwrap_max() + .double_unwrap_cached_get(i), + low: self + .timeindexes_to_low_in_sats + .quarterindex + .unwrap_min() + .double_unwrap_cached_get(i), + close, + }, + ) + }, + exit, + )?; + + self.yearindex_to_ohlc_in_sats.compute_transform( + starting_indexes.yearindex, + self.timeindexes_to_close_in_sats + .yearindex + .unwrap_last() + .mut_vec(), + |(i, close, ..)| { + ( + i, + OHLCSats { + open: self + .timeindexes_to_open_in_sats + .yearindex + .unwrap_first() + .double_unwrap_cached_get(i), + high: self + .timeindexes_to_high_in_sats + .yearindex + .unwrap_max() + .double_unwrap_cached_get(i), + low: self + .timeindexes_to_low_in_sats + .yearindex + .unwrap_min() + .double_unwrap_cached_get(i), + close, + }, + ) + }, + exit, + )?; + + // self.halvingepoch_to_ohlc + // _in_sats.compute_transform(starting_indexes.halvingepoch, other, t, exit)?; + + self.decadeindex_to_ohlc_in_sats.compute_transform( + starting_indexes.decadeindex, + self.timeindexes_to_close_in_sats + .decadeindex + .unwrap_last() + .mut_vec(), + |(i, close, ..)| { + ( + i, + OHLCSats { + open: self + .timeindexes_to_open_in_sats + .decadeindex + .unwrap_first() + .double_unwrap_cached_get(i), + high: self + .timeindexes_to_high_in_sats + .decadeindex + .unwrap_max() + .double_unwrap_cached_get(i), + low: self + .timeindexes_to_low_in_sats + .decadeindex + .unwrap_min() + .double_unwrap_cached_get(i), + close, + }, + ) + }, + exit, + )?; + Ok(()) } @@ -692,9 +1126,16 @@ impl Vecs { self.yearindex_to_ohlc.any_vec(), // self.halvingepoch_to_ohlc.any_vec(), self.decadeindex_to_ohlc.any_vec(), + self.height_to_ohlc_in_sats.any_vec(), + self.dateindex_to_ohlc_in_sats.any_vec(), + self.weekindex_to_ohlc_in_sats.any_vec(), + self.difficultyepoch_to_ohlc_in_sats.any_vec(), + self.monthindex_to_ohlc_in_sats.any_vec(), + self.quarterindex_to_ohlc_in_sats.any_vec(), + self.yearindex_to_ohlc_in_sats.any_vec(), + // self.halvingepoch_to_ohlc_in_sats.any_vec(), + self.decadeindex_to_ohlc_in_sats.any_vec(), ], - self.chainindexes_to_sats_per_dollar.any_vecs(), - self.timeindexes_to_sats_per_dollar.any_vecs(), self.timeindexes_to_close.any_vecs(), self.timeindexes_to_high.any_vecs(), self.timeindexes_to_low.any_vecs(), @@ -703,6 +1144,14 @@ impl Vecs { self.chainindexes_to_high.any_vecs(), self.chainindexes_to_low.any_vecs(), self.chainindexes_to_open.any_vecs(), + self.timeindexes_to_close_in_sats.any_vecs(), + self.timeindexes_to_high_in_sats.any_vecs(), + self.timeindexes_to_low_in_sats.any_vecs(), + self.timeindexes_to_open_in_sats.any_vecs(), + self.chainindexes_to_close_in_sats.any_vecs(), + self.chainindexes_to_high_in_sats.any_vecs(), + self.chainindexes_to_low_in_sats.any_vecs(), + self.chainindexes_to_open_in_sats.any_vecs(), ] .concat() } diff --git a/crates/brk_core/src/structs/ohlc.rs b/crates/brk_core/src/structs/ohlc.rs index 7e780c2da..bb14126c6 100644 --- a/crates/brk_core/src/structs/ohlc.rs +++ b/crates/brk_core/src/structs/ohlc.rs @@ -99,6 +99,51 @@ impl From<&OHLCCents> for OHLCDollars { } } +#[derive(Debug, Default, Clone, FromBytes, Immutable, IntoBytes, KnownLayout)] +#[repr(C)] +pub struct OHLCSats { + pub open: Open, + pub high: High, + pub low: Low, + pub close: Close, +} + +impl Serialize for OHLCSats { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut tup = serializer.serialize_tuple(4)?; + tup.serialize_element(&self.open)?; + tup.serialize_element(&self.high)?; + tup.serialize_element(&self.low)?; + tup.serialize_element(&self.close)?; + tup.end() + } +} + +impl From<(Open, High, Low, Close)> for OHLCSats { + fn from(value: (Open, High, Low, Close)) -> Self { + Self { + open: value.0, + high: value.1, + low: value.2, + close: value.3, + } + } +} + +impl From> for OHLCSats { + fn from(value: Close) -> Self { + Self { + open: Open::from(value), + high: High::from(value), + low: Low::from(value), + close: value, + } + } +} + #[derive( Debug, Default, @@ -117,12 +162,40 @@ impl From<&OHLCCents> for OHLCDollars { )] #[repr(C)] pub struct Open(T); -impl From for Open { - fn from(value: T) -> Self { + +impl Open { + pub fn new(value: T) -> Self { Self(value) } } +impl From for Open +where + T: From, +{ + fn from(value: usize) -> Self { + Self(T::from(value)) + } +} + +impl From for Open +where + T: From, +{ + fn from(value: f64) -> Self { + Self(T::from(value)) + } +} + +impl From> for f64 +where + f64: From, +{ + fn from(value: Open) -> Self { + Self::from(value.0) + } +} + impl From> for Open where T: Copy, @@ -138,24 +211,6 @@ impl From> for Open { } } -impl From for Open { - fn from(value: usize) -> Self { - Self(Dollars::from(value)) - } -} - -impl From for Open { - fn from(value: f64) -> Self { - Self(Dollars::from(value)) - } -} - -impl From> for f64 { - fn from(value: Open) -> Self { - Self::from(value.0) - } -} - impl Add for Open where T: Add, @@ -194,12 +249,40 @@ where )] #[repr(C)] pub struct High(T); -impl From for High { - fn from(value: T) -> Self { + +impl High { + pub fn new(value: T) -> Self { Self(value) } } +impl From for High +where + T: From, +{ + fn from(value: usize) -> Self { + Self(T::from(value)) + } +} + +impl From for High +where + T: From, +{ + fn from(value: f64) -> Self { + Self(T::from(value)) + } +} + +impl From> for f64 +where + f64: From, +{ + fn from(value: High) -> Self { + Self::from(value.0) + } +} + impl From> for High where T: Copy, @@ -215,24 +298,6 @@ impl From> for High { } } -impl From for High { - fn from(value: usize) -> Self { - Self(Dollars::from(value)) - } -} - -impl From for High { - fn from(value: f64) -> Self { - Self(Dollars::from(value)) - } -} - -impl From> for f64 { - fn from(value: High) -> Self { - Self::from(value.0) - } -} - impl Add for High where T: Add, @@ -271,12 +336,40 @@ where )] #[repr(C)] pub struct Low(T); -impl From for Low { - fn from(value: T) -> Self { + +impl Low { + pub fn new(value: T) -> Self { Self(value) } } +impl From for Low +where + T: From, +{ + fn from(value: usize) -> Self { + Self(T::from(value)) + } +} + +impl From for Low +where + T: From, +{ + fn from(value: f64) -> Self { + Self(T::from(value)) + } +} + +impl From> for f64 +where + f64: From, +{ + fn from(value: Low) -> Self { + Self::from(value.0) + } +} + impl From> for Low where T: Copy, @@ -292,24 +385,6 @@ impl From> for Low { } } -impl From for Low { - fn from(value: usize) -> Self { - Self(Dollars::from(value)) - } -} - -impl From for Low { - fn from(value: f64) -> Self { - Self(Dollars::from(value)) - } -} - -impl From> for f64 { - fn from(value: Low) -> Self { - Self::from(value.0) - } -} - impl Add for Low where T: Add, @@ -348,54 +423,52 @@ where )] #[repr(C)] pub struct Close(T); -impl From for Close { - fn from(value: T) -> Self { + +impl Close { + pub fn new(value: T) -> Self { Self(value) } } +impl From for Close +where + T: From, +{ + fn from(value: usize) -> Self { + Self(T::from(value)) + } +} + +impl From for Close +where + T: From, +{ + fn from(value: f64) -> Self { + Self(T::from(value)) + } +} + +impl From> for f64 +where + f64: From, +{ + fn from(value: Close) -> Self { + Self::from(value.0) + } +} + +// impl From> for Close +// where +// B: From, +// { +// fn from(value: Close) -> Self { +// Self(B::from(*value)) impl From> for Close { fn from(value: Close) -> Self { Self(Dollars::from(*value)) } } -impl From for Close { - fn from(value: usize) -> Self { - Self(Dollars::from(value)) - } -} - -impl From for Close { - fn from(value: usize) -> Self { - Self(Sats::from(value)) - } -} - -impl From for Close { - fn from(value: f64) -> Self { - Self(Dollars::from(value)) - } -} - -impl From for Close { - fn from(value: f64) -> Self { - Self(Sats::from(value)) - } -} - -impl From> for f64 { - fn from(value: Close) -> Self { - Self::from(value.0) - } -} - -impl From> for f64 { - fn from(value: Close) -> Self { - Self::from(value.0) - } -} - impl Add for Close where T: Add, diff --git a/crates/brk_fetcher/src/fetchers/binance.rs b/crates/brk_fetcher/src/fetchers/binance.rs index b76be66d1..b8ef27c55 100644 --- a/crates/brk_fetcher/src/fetchers/binance.rs +++ b/crates/brk_fetcher/src/fetchers/binance.rs @@ -223,10 +223,10 @@ impl Binance { Ok(( timestamp, OHLCCents::from(( - Open::from(get_cents(1)), - High::from(get_cents(2)), - Low::from(get_cents(3)), - Close::from(get_cents(4)), + Open::new(get_cents(1)), + High::new(get_cents(2)), + Low::new(get_cents(3)), + Close::new(get_cents(4)), )), )) } diff --git a/crates/brk_fetcher/src/fetchers/kibo.rs b/crates/brk_fetcher/src/fetchers/kibo.rs index 9408b0143..dab6dd40f 100644 --- a/crates/brk_fetcher/src/fetchers/kibo.rs +++ b/crates/brk_fetcher/src/fetchers/kibo.rs @@ -141,10 +141,10 @@ impl Kibo { }; Ok(OHLCCents::from(( - Open::from(get_value("open")?), - High::from(get_value("high")?), - Low::from(get_value("low")?), - Close::from(get_value("close")?), + Open::new(get_value("open")?), + High::new(get_value("high")?), + Low::new(get_value("low")?), + Close::new(get_value("close")?), ))) } } diff --git a/crates/brk_fetcher/src/fetchers/kraken.rs b/crates/brk_fetcher/src/fetchers/kraken.rs index b1e2eef1c..1efdfaa58 100644 --- a/crates/brk_fetcher/src/fetchers/kraken.rs +++ b/crates/brk_fetcher/src/fetchers/kraken.rs @@ -114,10 +114,10 @@ impl Kraken { Ok(( timestamp, OHLCCents::from(( - Open::from(get_cents(1)), - High::from(get_cents(2)), - Low::from(get_cents(3)), - Close::from(get_cents(4)), + Open::new(get_cents(1)), + High::new(get_cents(2)), + Low::new(get_cents(3)), + Close::new(get_cents(4)), )), )) } diff --git a/crates/brk_fetcher/src/lib.rs b/crates/brk_fetcher/src/lib.rs index ebb2612af..3b631108f 100644 --- a/crates/brk_fetcher/src/lib.rs +++ b/crates/brk_fetcher/src/lib.rs @@ -60,9 +60,9 @@ impl Fetcher { self.binance .get_from_1mn(timestamp, previous_timestamp) .unwrap_or_else(|_| { - self.kibo.get_from_height(height).unwrap_or_else(|_| { + self.kibo.get_from_height(height).unwrap_or_else(|e| { let date = Date::from(timestamp); - + eprintln!("{e}"); panic!( " Can't find the price for: height: {height} - date: {date} diff --git a/websites/kibo.money/index.html b/websites/kibo.money/index.html index da326a15d..6673ba1cf 100644 --- a/websites/kibo.money/index.html +++ b/websites/kibo.money/index.html @@ -1051,12 +1051,32 @@ margin-left: var(--negative-main-padding); fieldset { - padding-left: var(--main-padding); - padding-top: 0.5rem; + padding: 0.5rem; z-index: 10; position: absolute; - left: 0; - top: 0; + + &[data-position="nw"] { + padding-left: var(--main-padding); + top: 0; + left: 0; + } + + &[data-position="ne"] { + top: 0; + right: 0; + } + + &[data-position="se"] { + bottom: 0; + right: 0; + } + + &[data-position="sw"] { + padding-left: var(--main-padding); + bottom: 0; + left: 0; + } + gap: 0; } } diff --git a/websites/kibo.money/packages/lightweight-charts/wrapper.js b/websites/kibo.money/packages/lightweight-charts/wrapper.js index e9e1b9df3..86b367bda 100644 --- a/websites/kibo.money/packages/lightweight-charts/wrapper.js +++ b/websites/kibo.money/packages/lightweight-charts/wrapper.js @@ -1,6 +1,6 @@ // @ts-check -/** @import {IChartApi, ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData, SeriesType} from './v5.0.5-treeshaked/types' */ +/** @import {IChartApi, ISeriesApi, SeriesDefinition, SingleValueData as _SingleValueData, CandlestickData as _CandlestickData, BaselineData, SeriesType, IPaneApi, LineSeriesOptions} from './v5.0.5-treeshaked/types' */ /** * @typedef {[number, number, number, number]} OHLCTuple @@ -47,7 +47,7 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { autoSize: true, layout: { fontFamily: "Geist mono", - fontSize: 13, + // fontSize: 13, background: { color: "transparent" }, attributionLogo: false, colorSpace: "display-p3", @@ -98,6 +98,16 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { index === /** @satisfies {Height} */ (0) || index === /** @satisfies {Difficultyepoch} */ (3) || index === /** @satisfies {Halvingepoch} */ (8), + minBarSpacing: + index === /** @satisfies {Monthindex} */ (4) + ? 1 + : index === /** @satisfies {Quarterindex} */ (5) + ? 3 + : index === /** @satisfies {Yearindex} */ (6) + ? 12 + : index === /** @satisfies {Decadeindex} */ (7) + ? 120 + : undefined, }, crosshair: { horzLine: { @@ -291,6 +301,7 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { * @param {Accessor} [args.data] * @param {number} [args.paneIndex] * @param {boolean} [args.defaultActive] + * @param {boolean} [args.inverse] */ addCandlestickSeries({ vecId, @@ -299,13 +310,14 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { paneIndex: _paneIndex, defaultActive, data, + inverse, }) { const paneIndex = _paneIndex ?? 0; if (!ichart || !timeResource) throw Error("Chart not fully set"); - const green = colors.green(); - const red = colors.red(); + const green = inverse ? colors.red() : colors.green(); + const red = inverse ? colors.green() : colors.red(); const series = ichart.addSeries( /** @type {SeriesDefinition<'Candlestick'>} */ (lc.CandlestickSeries), { @@ -351,14 +363,11 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { utils, }); - createPriceScaleSelectorIfNeeded({ - ichart, + this.addPriceScaleSelectorIfNeeded({ paneIndex, seriesType: "Candlestick", - signals, id, unit, - utils, }); return series; @@ -372,6 +381,7 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { * @param {Color} [args.color] * @param {number} [args.paneIndex] * @param {boolean} [args.defaultActive] + * @param {DeepPartial} [args.options] */ addLineSeries({ vecId, @@ -381,12 +391,13 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { paneIndex: _paneIndex, defaultActive, data, + options, }) { if (!ichart || !timeResource) throw Error("Chart not fully set"); const paneIndex = _paneIndex ?? 0; - color ||= colors.orange; + color ||= unit === "USD" ? colors.dollars : colors.bitcoin; const series = ichart.addSeries( /** @type {SeriesDefinition<'Line'>} */ (lc.LineSeries), @@ -395,6 +406,7 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { visible: defaultActive !== false, priceLineVisible: false, color: color(), + ...options, }, paneIndex, ); @@ -434,14 +446,11 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { utils, }); - createPriceScaleSelectorIfNeeded({ - ichart, + this.addPriceScaleSelectorIfNeeded({ paneIndex, - signals, seriesType: "Line", id, unit, - utils, }); return series; @@ -520,18 +529,99 @@ export default import("./v5.0.5-treeshaked/script.js").then((lc) => { utils, }); - createPriceScaleSelectorIfNeeded({ - ichart, + this.addPriceScaleSelectorIfNeeded({ paneIndex, - signals, seriesType: "Baseline", id, unit, - utils, }); return series; }, + /** + * @param {Object} args + * @param {Unit} args.unit + * @param {string} args.id + * @param {SeriesType} args.seriesType + * @param {number} args.paneIndex + */ + addPriceScaleSelectorIfNeeded({ unit, paneIndex, id, seriesType }) { + id = `${id}-scale`; + + this.addFieldsetIfNeeded({ + id, + paneIndex, + position: "sw", + createChild({ owner, pane }) { + const { field, selected } = utils.dom.createHorizontalChoiceField({ + choices: /** @type {const} */ (["lin", "log"]), + id: utils.stringToId(`${id} ${unit}`), + defaultValue: + unit === "USD" && seriesType !== "Baseline" ? "log" : "lin", + key: `${id}-price-scale-${paneIndex}`, + signals, + }); + + signals.runWithOwner(owner, () => { + signals.createEffect(selected, (selected) => { + try { + pane.priceScale("right").applyOptions({ + mode: selected === "lin" ? 0 : 1, + }); + } catch {} + }); + }); + + return field; + }, + }); + }, + /** + * @param {Object} args + * @param {string} args.id + * @param {number} args.paneIndex + * @param {"nw" | "ne" | "se" | "sw"} args.position + * @param {number} [args.timeout] + * @param {(args: {owner: Owner | null, pane: IPaneApi