diff --git a/Cargo.lock b/Cargo.lock index dbe0f71d1..ef34398ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,11 +166,13 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-compression" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddb939d66e4ae03cee6091612804ba446b12878410cfa17f785f4dd67d4014e8" +checksum = "6448dfb3960f0b038e88c781ead1e7eb7929dfc3a71a1336ec9086c00f6d1e75" dependencies = [ "brotli", + "compression-codecs", + "compression-core", "flate2", "futures-core", "memchr", @@ -454,9 +456,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" dependencies = [ "serde", ] @@ -675,7 +677,7 @@ dependencies = [ "serde", "serde_json", "sse-stream", - "thiserror 2.0.15", + "thiserror 2.0.16", "tokio", "tokio-stream", "tokio-util", @@ -690,7 +692,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b49ac541e14b18e43696144176faeabc547ce198cb10d575c13fcc6245d337c" dependencies = [ - "darling 0.21.2", + "darling 0.21.3", "proc-macro2", "quote", "serde_json", @@ -706,7 +708,7 @@ dependencies = [ "anyhow", "append-only-vec", "arcstr", - "bitflags 2.9.2", + "bitflags 2.9.3", "brk_rolldown_common", "brk_rolldown_debug", "brk_rolldown_ecmascript", @@ -727,7 +729,7 @@ dependencies = [ "css-module-lexer", "dunce", "futures", - "indexmap 2.10.0", + "indexmap 2.11.0", "itertools", "itoa", "memchr", @@ -755,7 +757,7 @@ checksum = "23cd66173b33436aaec126f64e8f1d0938539d2eb934e88c633cf6181f7e4c53" dependencies = [ "anyhow", "arcstr", - "bitflags 2.9.2", + "bitflags 2.9.3", "brk_rolldown_ecmascript", "brk_rolldown_error", "brk_rolldown_fs", @@ -837,7 +839,7 @@ checksum = "9fd007c612609bcf46e3dca4f9f3c79d16dc1f0bdf7cd0047bfe752fbc6fbecc" dependencies = [ "anyhow", "arcstr", - "bitflags 2.9.2", + "bitflags 2.9.3", "brk_rolldown_utils", "derive_more", "heck", @@ -868,7 +870,7 @@ dependencies = [ "anyhow", "arcstr", "async-trait", - "bitflags 2.9.2", + "bitflags 2.9.3", "brk_rolldown_common", "brk_rolldown_debug", "brk_rolldown_ecmascript", @@ -996,7 +998,7 @@ dependencies = [ "fast-glob", "form_urlencoded", "futures", - "indexmap 2.10.0", + "indexmap 2.11.0", "infer", "itoa", "memchr", @@ -1147,9 +1149,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.33" +version = "1.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" dependencies = [ "jobserver", "libc", @@ -1169,9 +1171,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "cfg_aliases" @@ -1302,6 +1304,28 @@ version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0095f6103c2a8b44acd6fd15960c801dafebf02e21940360833e0673f48ba7" +[[package]] +name = "compression-codecs" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46cc6539bf1c592cff488b9f253b30bc0ec50d15407c2cf45e27bd8f308d5905" +dependencies = [ + "brotli", + "compression-core", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "zstd", + "zstd-safe", +] + +[[package]] +name = "compression-core" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2957e823c15bde7ecf1e8b64e537aa03a6be5fda0e2334e99887669e75b12e01" + [[package]] name = "concurrent_lru" version = "0.2.0" @@ -1460,12 +1484,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08440b3dd222c3d0433e63e097463969485f112baff337dfdaca043a0d760570" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core 0.21.2", - "darling_macro 0.21.2", + "darling_core 0.21.3", + "darling_macro 0.21.3", ] [[package]] @@ -1484,9 +1508,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25b7912bc28a04ab1b7715a68ea03aaa15662b43a1a4b2c480531fd19f8bf7e" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ "fnv", "ident_case", @@ -1509,11 +1533,11 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce154b9bea7fb0c8e8326e62d00354000c36e79770ff21b8c84e3aa267d9d531" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core 0.21.2", + "darling_core 0.21.3", "quote", "syn 2.0.106", ] @@ -1737,14 +1761,14 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "filetime" -version = "0.2.25" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1795,9 +1819,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] @@ -2206,9 +2230,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -2244,9 +2268,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" dependencies = [ "equivalent", "hashbrown 0.15.5", @@ -2268,7 +2292,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "inotify-sys", "libc", ] @@ -2293,11 +2317,11 @@ dependencies = [ [[package]] name = "io-uring" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "cfg-if", "libc", ] @@ -2443,7 +2467,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "libc", "redox_syscall", ] @@ -2529,9 +2553,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" +checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" dependencies = [ "libc", ] @@ -2592,7 +2616,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "cfg-if", "cfg_aliases", "libc", @@ -2619,7 +2643,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "fsevent-sys", "inotify", "kqueue", @@ -2756,7 +2780,7 @@ dependencies = [ "rustc-hash", "serde", "serde_json", - "thiserror 2.0.15", + "thiserror 2.0.16", "time", ] @@ -2770,7 +2794,7 @@ dependencies = [ "owo-colors", "oxc-miette-derive", "textwrap", - "thiserror 2.0.15", + "thiserror 2.0.16", "unicode-width", ] @@ -2806,7 +2830,7 @@ version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "989b81258ce151e23adee6f1393f7c0fb7e10e3a6c6c001f71bbaff4081c72a4" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "oxc_allocator", "oxc_ast_macros", "oxc_data_structures", @@ -2847,7 +2871,7 @@ version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5361ef66f38635d9671596d83abf44bcdbc3e39dbff303f3517828b86ad60e8f" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "itertools", "nonmax", "oxc_index", @@ -2862,7 +2886,7 @@ version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde8fc6f7337632fce3e9e51c150f57fb0ef234524c6947f63e8009e1ea613cf" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "cow-utils", "dragonbox_ecma", "nonmax", @@ -2940,7 +2964,7 @@ version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83d8c311d64fa0bf8cab1bde3f7760cd828e71ed483ca0878799f1f72542cb4d" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "oxc_allocator", "oxc_ast", "oxc_ast_visit", @@ -2995,7 +3019,7 @@ version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70253728183a5a92d1ba964d9952201e0269ebd07c4917c4553283d564225bab" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "cow-utils", "memchr", "num-bigint", @@ -3018,7 +3042,7 @@ version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de5bb2ed6646bb7815126e0f36787c349e13561fed2c05f95b27a1f82dd066c4" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "oxc_allocator", "oxc_ast_macros", "oxc_diagnostics", @@ -3030,12 +3054,12 @@ dependencies = [ [[package]] name = "oxc_resolver" -version = "11.6.1" +version = "11.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b0efb2038cc4e9d12f0fd32aedcfd594f8879866b38bd4becf5e87fa283cc0" +checksum = "3d84cdcd778d15db5b21cc61baf79ac55cee97e7feb725b2664453979ba3cd76" dependencies = [ "cfg-if", - "indexmap 2.10.0", + "indexmap 2.11.0", "json-strip-comments", "once_cell", "papaya", @@ -3044,7 +3068,7 @@ dependencies = [ "serde", "serde_json", "simdutf8", - "thiserror 2.0.15", + "thiserror 2.0.16", "tracing", "url", ] @@ -3103,7 +3127,7 @@ version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72d9d80d47d2eee5c1e6dbcdf1841b42afc4f1cd1f63701fc346162616dac52f" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "cow-utils", "dragonbox_ecma", "nonmax", @@ -3128,7 +3152,7 @@ dependencies = [ "base64 0.22.1", "compact_str", "cow-utils", - "indexmap 2.10.0", + "indexmap 2.11.0", "itoa", "memchr", "oxc-browserslist", @@ -3284,9 +3308,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" @@ -3296,7 +3320,7 @@ checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" dependencies = [ "fixedbitset", "hashbrown 0.15.5", - "indexmap 2.10.0", + "indexmap 2.11.0", "serde", ] @@ -3398,7 +3422,7 @@ dependencies = [ "rustc-hash", "serde", "serde_json", - "thiserror 2.0.15", + "thiserror 2.0.16", ] [[package]] @@ -3608,7 +3632,7 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", ] [[package]] @@ -3686,9 +3710,9 @@ dependencies = [ [[package]] name = "rolldown-ariadne" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324d1b9754f0cb535f4032a6a654d3a56047a500f557c16060f12f70b0089c57" +checksum = "77dff57c9de498bb1eb5b1ce682c2e3a0ae956b266fa0933c3e151b87b078967" dependencies = [ "unicode-width", "yansi", @@ -3722,7 +3746,7 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "errno", "libc", "linux-raw-sys", @@ -3926,11 +3950,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ - "indexmap 2.10.0", + "indexmap 2.11.0", "itoa", "memchr", "ryu", @@ -3978,7 +4002,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.10.0", + "indexmap 2.11.0", "schemars 0.9.0", "schemars 1.0.4", "serde", @@ -4186,15 +4210,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -4237,11 +4261,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.15" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ - "thiserror-impl 2.0.15", + "thiserror-impl 2.0.16", ] [[package]] @@ -4257,9 +4281,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.15" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", @@ -4375,7 +4399,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" dependencies = [ - "indexmap 2.10.0", + "indexmap 2.11.0", "serde", "serde_spanned", "toml_datetime", @@ -4431,7 +4455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ "async-compression", - "bitflags 2.9.2", + "bitflags 2.9.3", "bytes", "futures-core", "http", @@ -4554,7 +4578,7 @@ version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ef1b7a6d914a34127ed8e1fa927eb7088903787bcded4fa3eef8f85ee1568be" dependencies = [ - "thiserror 2.0.15", + "thiserror 2.0.16", "ts-rs-macros", ] @@ -4629,13 +4653,14 @@ checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" [[package]] name = "url" -version = "2.5.4" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -4860,11 +4885,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -5090,9 +5115,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" [[package]] name = "wit-bindgen-rt" @@ -5100,7 +5125,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", ] [[package]] @@ -5221,14 +5246,14 @@ dependencies = [ [[package]] name = "zip" -version = "4.3.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aed4ac33e8eb078c89e6cbb1d5c4c7703ec6d299fc3e7c3695af8f8b423468b" +checksum = "8835eb39822904d39cb19465de1159e05d371973f0c6df3a365ad50565ddc8b9" dependencies = [ "arbitrary", "crc32fast", "flate2", - "indexmap 2.10.0", + "indexmap 2.11.0", "memchr", "zopfli", ] diff --git a/Cargo.toml b/Cargo.toml index 98845f42d..c03da6692 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ rayon = "1.11.0" serde = "1.0.219" serde_bytes = "0.11.17" serde_derive = "1.0.219" -serde_json = { version = "1.0.142", features = ["float_roundtrip"] } +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"]} diff --git a/crates/brk_cli/Cargo.toml b/crates/brk_cli/Cargo.toml index 45857e79f..b59c67068 100644 --- a/crates/brk_cli/Cargo.toml +++ b/crates/brk_cli/Cargo.toml @@ -28,7 +28,7 @@ minreq = { workspace = true } serde = { workspace = true } tokio = { workspace = true } toml = "0.9.5" -zip = { version = "4.3.0", default-features = false, features = ["deflate"] } +zip = { version = "4.5.0", default-features = false, features = ["deflate"] } [[bin]] name = "brk" diff --git a/crates/brk_computer/src/constants.rs b/crates/brk_computer/src/constants.rs index cbf2653ba..1612762c2 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::{StoredU16, Version}; +use brk_structs::{StoredI16, StoredU16, Version}; use vecdb::{AnyCollectableVec, AnyVec, Database, Exit}; use crate::grouped::Source; @@ -21,8 +21,15 @@ pub struct Vecs { pub constant_0: ComputedVecsFromHeight, pub constant_1: ComputedVecsFromHeight, + pub constant_2: ComputedVecsFromHeight, + pub constant_3: ComputedVecsFromHeight, + pub constant_4: ComputedVecsFromHeight, pub constant_50: ComputedVecsFromHeight, pub constant_100: ComputedVecsFromHeight, + pub constant_minus_1: ComputedVecsFromHeight, + pub constant_minus_2: ComputedVecsFromHeight, + pub constant_minus_3: ComputedVecsFromHeight, + pub constant_minus_4: ComputedVecsFromHeight, } impl Vecs { @@ -46,6 +53,30 @@ impl Vecs { indexes, VecBuilderOptions::default().add_last(), )?, + constant_2: ComputedVecsFromHeight::forced_import( + &db, + "constant_2", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, + constant_3: ComputedVecsFromHeight::forced_import( + &db, + "constant_3", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, + constant_4: ComputedVecsFromHeight::forced_import( + &db, + "constant_4", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, constant_50: ComputedVecsFromHeight::forced_import( &db, "constant_50", @@ -62,6 +93,38 @@ impl Vecs { indexes, VecBuilderOptions::default().add_last(), )?, + constant_minus_1: ComputedVecsFromHeight::forced_import( + &db, + "constant_minus_1", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, + constant_minus_2: ComputedVecsFromHeight::forced_import( + &db, + "constant_minus_2", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, + constant_minus_3: ComputedVecsFromHeight::forced_import( + &db, + "constant_minus_3", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, + constant_minus_4: ComputedVecsFromHeight::forced_import( + &db, + "constant_minus_4", + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + VecBuilderOptions::default().add_last(), + )?, db, }) @@ -120,6 +183,57 @@ impl Vecs { }, )?; + 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, @@ -154,6 +268,74 @@ impl Vecs { }, )?; + 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(()) + }, + )?; + Ok(()) } @@ -161,8 +343,15 @@ impl Vecs { [ self.constant_0.vecs(), self.constant_1.vecs(), + self.constant_2.vecs(), + self.constant_3.vecs(), + self.constant_4.vecs(), self.constant_50.vecs(), self.constant_100.vecs(), + self.constant_minus_1.vecs(), + self.constant_minus_2.vecs(), + self.constant_minus_3.vecs(), + self.constant_minus_4.vecs(), ] .into_iter() .flatten() diff --git a/crates/brk_computer/src/grouped/mod.rs b/crates/brk_computer/src/grouped/mod.rs index 5dd681a5f..d54cc902b 100644 --- a/crates/brk_computer/src/grouped/mod.rs +++ b/crates/brk_computer/src/grouped/mod.rs @@ -6,6 +6,7 @@ mod from_height; mod from_height_strict; mod from_txindex; mod ratio_from_dateindex; +mod sd_from_dateindex; mod source; mod value_from_dateindex; mod value_from_height; @@ -20,6 +21,7 @@ pub use from_height::*; pub use from_height_strict::*; pub use from_txindex::*; pub use ratio_from_dateindex::*; +pub use sd_from_dateindex::*; pub use source::*; pub use value_from_dateindex::*; pub use value_from_height::*; diff --git a/crates/brk_computer/src/grouped/ratio_from_dateindex.rs b/crates/brk_computer/src/grouped/ratio_from_dateindex.rs index e8a76e203..911f61387 100644 --- a/crates/brk_computer/src/grouped/ratio_from_dateindex.rs +++ b/crates/brk_computer/src/grouped/ratio_from_dateindex.rs @@ -6,7 +6,12 @@ use vecdb::{ Exit, GenericStoredVec, StoredIndex, VecIterator, }; -use crate::{Indexes, grouped::source::Source, indexes, price, utils::get_percentile}; +use crate::{ + Indexes, + grouped::{ComputedStandardDeviationVecsFromDateIndex, source::Source}, + indexes, price, + utils::get_percentile, +}; use super::{ComputedVecsFromDateIndex, VecBuilderOptions}; @@ -15,45 +20,28 @@ pub struct ComputedRatioVecsFromDateIndex { pub price: Option>, pub ratio: ComputedVecsFromDateIndex, - pub ratio_sma: Option>, pub ratio_1w_sma: Option>, pub ratio_1m_sma: Option>, - pub ratio_1y_sma: Option>, - pub ratio_4y_sma: Option>, - pub ratio_1y_sma_momentum_oscillator: Option>, - pub ratio_sd: Option>, - pub ratio_4y_sd: Option>, - pub ratio_1y_sd: Option>, - pub ratio_p99_9: Option>, - pub ratio_p99_5: Option>, pub ratio_p99: Option>, + pub ratio_p98: Option>, + pub ratio_p95: Option>, + pub ratio_p5: Option>, + pub ratio_p2: Option>, pub ratio_p1: Option>, - pub ratio_p0_5: Option>, - pub ratio_p0_1: Option>, - pub ratio_p1sd: Option>, - pub ratio_p2sd: Option>, - pub ratio_p3sd: Option>, - pub ratio_m1sd: Option>, - pub ratio_m2sd: Option>, - pub ratio_m3sd: Option>, - pub ratio_p99_9_as_price: Option>, - pub ratio_p99_5_as_price: Option>, pub ratio_p99_as_price: Option>, + pub ratio_p98_as_price: Option>, + pub ratio_p95_as_price: Option>, + pub ratio_p5_as_price: Option>, + pub ratio_p2_as_price: Option>, pub ratio_p1_as_price: Option>, - pub ratio_p0_5_as_price: Option>, - pub ratio_p0_1_as_price: Option>, - pub ratio_p1sd_as_price: Option>, - pub ratio_p2sd_as_price: Option>, - pub ratio_p3sd_as_price: Option>, - pub ratio_m1sd_as_price: Option>, - pub ratio_m2sd_as_price: Option>, - pub ratio_m3sd_as_price: Option>, - pub ratio_zscore: Option>, - pub ratio_4y_zscore: Option>, - pub ratio_1y_zscore: Option>, + + pub ratio_sd: Option, + pub ratio_4y_sd: Option, + pub ratio_2y_sd: Option, + pub ratio_1y_sd: Option, } -const VERSION: Version = Version::ZERO; +const VERSION: Version = Version::TWO; impl ComputedRatioVecsFromDateIndex { #[allow(clippy::too_many_arguments)] @@ -87,17 +75,6 @@ impl ComputedRatioVecsFromDateIndex { indexes, options, )?, - ratio_sma: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_sma"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), ratio_1w_sma: extended.then(|| { ComputedVecsFromDateIndex::forced_import( db, @@ -120,91 +97,47 @@ impl ComputedRatioVecsFromDateIndex { ) .unwrap() }), - ratio_1y_sma: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_1y_sma"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_4y_sma: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_4y_sma"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_1y_sma_momentum_oscillator: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_1y_sma_momentum_oscillator"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), ratio_sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( + ComputedStandardDeviationVecsFromDateIndex::forced_import( db, - &format!("{name}_ratio_sd"), + &format!("{name}_ratio"), + usize::MAX, Source::Compute, version + VERSION + Version::ZERO, indexes, - options, - ) - .unwrap() - }), - ratio_4y_sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_4y_sd"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, ) .unwrap() }), ratio_1y_sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( + ComputedStandardDeviationVecsFromDateIndex::forced_import( db, - &format!("{name}_ratio_1y_sd"), + &format!("{name}_ratio_1y"), + 365, Source::Compute, version + VERSION + Version::ZERO, indexes, - options, ) .unwrap() }), - ratio_p99_9: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( + ratio_2y_sd: extended.then(|| { + ComputedStandardDeviationVecsFromDateIndex::forced_import( db, - &format!("{name}_ratio_p99_9"), + &format!("{name}_ratio_2y"), + 2 * 365, Source::Compute, version + VERSION + Version::ZERO, indexes, - options, ) .unwrap() }), - ratio_p99_5: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( + ratio_4y_sd: extended.then(|| { + ComputedStandardDeviationVecsFromDateIndex::forced_import( db, - &format!("{name}_ratio_p99_5"), + &format!("{name}_ratio_4y"), + 4 * 365, Source::Compute, version + VERSION + Version::ZERO, indexes, - options, ) .unwrap() }), @@ -219,6 +152,50 @@ impl ComputedRatioVecsFromDateIndex { ) .unwrap() }), + ratio_p98: extended.then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_ratio_p98"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), + ratio_p95: extended.then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_ratio_p95"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), + ratio_p5: extended.then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_ratio_p5"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), + ratio_p2: extended.then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_ratio_p2"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), ratio_p1: extended.then(|| { ComputedVecsFromDateIndex::forced_import( db, @@ -230,116 +207,6 @@ impl ComputedRatioVecsFromDateIndex { ) .unwrap() }), - ratio_p0_5: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p0_5"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p0_1: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p0_1"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p1sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p1sd"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p2sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p2sd"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p3sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p3sd"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_m1sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_m1sd"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_m2sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_m2sd"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_m3sd: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_m3sd"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p99_9_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p99_9_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p99_5_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p99_5_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), ratio_p99_as_price: extended.then(|| { ComputedVecsFromDateIndex::forced_import( db, @@ -351,6 +218,50 @@ impl ComputedRatioVecsFromDateIndex { ) .unwrap() }), + ratio_p98_as_price: extended.then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_ratio_p98_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), + ratio_p95_as_price: extended.then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_ratio_p95_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), + ratio_p5_as_price: extended.then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_ratio_p5_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), + ratio_p2_as_price: extended.then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_ratio_p2_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), ratio_p1_as_price: extended.then(|| { ComputedVecsFromDateIndex::forced_import( db, @@ -362,127 +273,6 @@ impl ComputedRatioVecsFromDateIndex { ) .unwrap() }), - ratio_p0_5_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p0_5_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p0_1_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p0_1_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p1sd_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p1sd_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p2sd_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p2sd_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_p3sd_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_p3sd_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_m1sd_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_m1sd_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_m2sd_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_m2sd_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_m3sd_as_price: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_m3sd_as_price"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_zscore: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_zscore"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_4y_zscore: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_4y_zscore"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), - ratio_1y_zscore: extended.then(|| { - ComputedVecsFromDateIndex::forced_import( - db, - &format!("{name}_ratio_1y_zscore"), - Source::Compute, - version + VERSION + Version::ZERO, - indexes, - options, - ) - .unwrap() - }), }) } @@ -562,29 +352,12 @@ impl ComputedRatioVecsFromDateIndex { }, )?; - if self.ratio_sma.is_none() { + if self.ratio_1w_sma.is_none() { return Ok(()); } let min_ratio_date = DateIndex::try_from(Date::MIN_RATIO).unwrap(); - self.ratio_sma.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |v, _, _, starting_indexes, exit| { - v.compute_sma_( - starting_indexes.dateindex, - self.ratio.dateindex.as_ref().unwrap(), - usize::MAX, - exit, - Some(min_ratio_date), - )?; - Ok(()) - }, - )?; - self.ratio_1w_sma.as_mut().unwrap().compute_all( indexer, indexes, @@ -619,74 +392,6 @@ impl ComputedRatioVecsFromDateIndex { }, )?; - self.ratio_1y_sma.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |v, _, _, starting_indexes, exit| { - v.compute_sma_( - starting_indexes.dateindex, - self.ratio.dateindex.as_ref().unwrap(), - 365, - exit, - Some(min_ratio_date), - )?; - Ok(()) - }, - )?; - - self.ratio_4y_sma.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |v, _, _, starting_indexes, exit| { - v.compute_sma_( - starting_indexes.dateindex, - self.ratio.dateindex.as_ref().unwrap(), - 4 * 365, - exit, - Some(min_ratio_date), - )?; - Ok(()) - }, - )?; - - self.ratio_1y_sma_momentum_oscillator - .as_mut() - .unwrap() - .compute_all( - indexer, - indexes, - starting_indexes, - exit, - |v, _, _, starting_indexes, exit| { - let mut ratio_1y_sma_iter = self - .ratio_1y_sma - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - v.compute_transform( - starting_indexes.dateindex, - self.ratio.dateindex.as_ref().unwrap(), - |(i, ratio, ..)| { - ( - i, - StoredF32::from( - *ratio / *ratio_1y_sma_iter.unwrap_get_inner(i) - 1.0, - ), - ) - }, - exit, - )?; - Ok(()) - }, - )?; - let ratio_version = self.ratio.dateindex.as_ref().unwrap().version(); self.mut_ratio_vecs() .iter_mut() @@ -712,36 +417,6 @@ impl ComputedRatioVecsFromDateIndex { sorted.sort_unstable(); - // if sorted.len() != starting_dateindex.unwrap_to_usize() - min_ratio_date.unwrap_to_usize() { - // unreachable!(); - // } - - let mut sma_iter = self - .ratio_sma - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - let mut _4y_sma_iter = self - .ratio_4y_sma - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - let mut _1y_sma_iter = self - .ratio_1y_sma - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - - let nan = StoredF32::from(f32::NAN); self.ratio .dateindex .as_ref() @@ -749,130 +424,53 @@ impl ComputedRatioVecsFromDateIndex { .iter_at(starting_dateindex) .try_for_each(|(index, ratio)| -> Result<()> { if index < min_ratio_date { - self.ratio_p0_1 + self.ratio_p5 .as_mut() .unwrap() .dateindex .as_mut() .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_p0_5 + .forced_push_at(index, StoredF32::NAN, exit)?; + self.ratio_p2 .as_mut() .unwrap() .dateindex .as_mut() .unwrap() - .forced_push_at(index, nan, exit)?; + .forced_push_at(index, StoredF32::NAN, exit)?; self.ratio_p1 .as_mut() .unwrap() .dateindex .as_mut() .unwrap() - .forced_push_at(index, nan, exit)?; + .forced_push_at(index, StoredF32::NAN, exit)?; + self.ratio_p95 + .as_mut() + .unwrap() + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, StoredF32::NAN, exit)?; + self.ratio_p98 + .as_mut() + .unwrap() + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, StoredF32::NAN, exit)?; self.ratio_p99 .as_mut() .unwrap() .dateindex .as_mut() .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_p99_5 - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_p99_9 - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_4y_sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_1y_sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - - self.ratio_p1sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_p2sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_p3sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_m1sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_m2sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; - self.ratio_m3sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, nan, exit)?; + .forced_push_at(index, StoredF32::NAN, exit)?; } else { let ratio = ratio.into_owned(); let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos); sorted.insert(pos, ratio); - self.ratio_p0_1 - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, get_percentile(&sorted, 0.001), exit)?; - self.ratio_p0_5 - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, get_percentile(&sorted, 0.005), exit)?; + self.ratio_p1 .as_mut() .unwrap() @@ -880,6 +478,34 @@ impl ComputedRatioVecsFromDateIndex { .as_mut() .unwrap() .forced_push_at(index, get_percentile(&sorted, 0.01), exit)?; + self.ratio_p2 + .as_mut() + .unwrap() + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, get_percentile(&sorted, 0.02), exit)?; + self.ratio_p5 + .as_mut() + .unwrap() + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, get_percentile(&sorted, 0.05), exit)?; + self.ratio_p95 + .as_mut() + .unwrap() + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, get_percentile(&sorted, 0.95), exit)?; + self.ratio_p98 + .as_mut() + .unwrap() + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, get_percentile(&sorted, 0.98), exit)?; self.ratio_p99 .as_mut() .unwrap() @@ -887,195 +513,41 @@ impl ComputedRatioVecsFromDateIndex { .as_mut() .unwrap() .forced_push_at(index, get_percentile(&sorted, 0.99), exit)?; - self.ratio_p99_5 - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, get_percentile(&sorted, 0.995), exit)?; - self.ratio_p99_9 - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, get_percentile(&sorted, 0.999), exit)?; - - let avg = sma_iter.unwrap_get_inner(index); - - let sd = StoredF32::from( - (sorted.iter().map(|v| (**v - *avg).powi(2)).sum::() - / (index.unwrap_to_usize() + 1) as f32) - .sqrt(), - ); - - self.ratio_sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, sd, exit)?; - - let _4y_avg = _4y_sma_iter.unwrap_get_inner(index); - - let _4y_sd = StoredF32::from( - (sorted.iter().map(|v| (**v - *_4y_avg).powi(2)).sum::() - / (index.unwrap_to_usize() + 1) as f32) - .sqrt(), - ); - - self.ratio_4y_sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, _4y_sd, exit)?; - - let _1y_avg = _1y_sma_iter.unwrap_get_inner(index); - - let _1y_sd = StoredF32::from( - (sorted.iter().map(|v| (**v - *_1y_avg).powi(2)).sum::() - / (index.unwrap_to_usize() + 1) as f32) - .sqrt(), - ); - - self.ratio_1y_sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, _1y_sd, exit)?; - - self.ratio_p1sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, avg + sd, exit)?; - self.ratio_p2sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, avg + 2 * sd, exit)?; - self.ratio_p3sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, avg + 3 * sd, exit)?; - self.ratio_m1sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, avg - sd, exit)?; - self.ratio_m2sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, avg - 2 * sd, exit)?; - self.ratio_m3sd - .as_mut() - .unwrap() - .dateindex - .as_mut() - .unwrap() - .forced_push_at(index, avg - 3 * sd, exit)?; } Ok(()) })?; - drop(sma_iter); - drop(_4y_sma_iter); - drop(_1y_sma_iter); - self.mut_ratio_vecs() .into_iter() .try_for_each(|v| v.safe_flush(exit))?; - self.ratio_p99_9.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; - self.ratio_p99_5.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; - self.ratio_p99.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; self.ratio_p1.as_mut().unwrap().compute_rest( starting_indexes, exit, None as Option<&EagerVec<_, _>>, )?; - self.ratio_p0_5.as_mut().unwrap().compute_rest( + self.ratio_p2.as_mut().unwrap().compute_rest( starting_indexes, exit, None as Option<&EagerVec<_, _>>, )?; - self.ratio_p0_1.as_mut().unwrap().compute_rest( + self.ratio_p5.as_mut().unwrap().compute_rest( starting_indexes, exit, None as Option<&EagerVec<_, _>>, )?; - self.ratio_sd.as_mut().unwrap().compute_rest( + self.ratio_p95.as_mut().unwrap().compute_rest( starting_indexes, exit, None as Option<&EagerVec<_, _>>, )?; - self.ratio_4y_sd.as_mut().unwrap().compute_rest( + self.ratio_p98.as_mut().unwrap().compute_rest( starting_indexes, exit, None as Option<&EagerVec<_, _>>, )?; - self.ratio_1y_sd.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; - self.ratio_p1sd.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; - self.ratio_p2sd.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; - self.ratio_p3sd.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; - self.ratio_m1sd.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; - self.ratio_m2sd.as_mut().unwrap().compute_rest( - starting_indexes, - exit, - None as Option<&EagerVec<_, _>>, - )?; - self.ratio_m3sd.as_mut().unwrap().compute_rest( + self.ratio_p99.as_mut().unwrap().compute_rest( starting_indexes, exit, None as Option<&EagerVec<_, _>>, @@ -1112,372 +584,68 @@ impl ComputedRatioVecsFromDateIndex { }, )?; - self.ratio_p99_5_as_price.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_p99_5 - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) + let compute_as_price = + |as_price: Option<&mut ComputedVecsFromDateIndex>, + source: Option<&ComputedVecsFromDateIndex>| { + as_price.unwrap().compute_all( + indexer, + indexes, + starting_indexes, + exit, + |vec, _, _, starting_indexes, exit| { + let mut iter = source.unwrap().dateindex.as_ref().unwrap().into_iter(); + vec.compute_transform( + starting_indexes.dateindex, + date_to_price, + |(i, price, ..)| { + let multiplier = iter.unwrap_get_inner(i); + (i, price * multiplier) + }, + exit, + )?; + Ok(()) }, - exit, - )?; - Ok(()) - }, - )?; + ) + }; - self.ratio_p99_9_as_price.as_mut().unwrap().compute_all( + compute_as_price(self.ratio_p1_as_price.as_mut(), self.ratio_p1.as_ref())?; + compute_as_price(self.ratio_p2_as_price.as_mut(), self.ratio_p2.as_ref())?; + compute_as_price(self.ratio_p5_as_price.as_mut(), self.ratio_p5.as_ref())?; + compute_as_price(self.ratio_p95_as_price.as_mut(), self.ratio_p95.as_ref())?; + compute_as_price(self.ratio_p98_as_price.as_mut(), self.ratio_p98.as_ref())?; + compute_as_price(self.ratio_p99_as_price.as_mut(), self.ratio_p99.as_ref())?; + + self.ratio_sd.as_mut().unwrap().compute_all( indexer, indexes, starting_indexes, exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_p99_9 - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, + self.ratio.dateindex.as_ref().unwrap(), + Some(date_to_price), )?; - - self.ratio_p1_as_price.as_mut().unwrap().compute_all( + self.ratio_4y_sd.as_mut().unwrap().compute_all( indexer, indexes, starting_indexes, exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_p1 - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, + self.ratio.dateindex.as_ref().unwrap(), + Some(date_to_price), )?; - - self.ratio_p0_5_as_price.as_mut().unwrap().compute_all( + self.ratio_2y_sd.as_mut().unwrap().compute_all( indexer, indexes, starting_indexes, exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_p0_5 - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, + self.ratio.dateindex.as_ref().unwrap(), + Some(date_to_price), )?; - - self.ratio_p0_1_as_price.as_mut().unwrap().compute_all( + self.ratio_1y_sd.as_mut().unwrap().compute_all( indexer, indexes, starting_indexes, exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_p0_1 - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_p1sd_as_price.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_p1sd - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_p2sd_as_price.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_p2sd - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_p3sd_as_price.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_p3sd - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_m1sd_as_price.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_m1sd - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_m2sd_as_price.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_m2sd - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_m3sd_as_price.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - let mut iter = self - .ratio_m3sd - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap() - .into_iter(); - vec.compute_transform( - starting_indexes.dateindex, - date_to_price, - |(i, price, ..)| { - let multiplier = iter.unwrap_get_inner(i); - (i, price * multiplier) - }, - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_zscore.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - vec.compute_zscore( - starting_indexes.dateindex, - self.ratio.dateindex.as_ref().unwrap(), - self.ratio_sma.as_ref().unwrap().dateindex.as_ref().unwrap(), - self.ratio_sd.as_ref().unwrap().dateindex.as_ref().unwrap(), - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_4y_zscore.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - vec.compute_zscore( - starting_indexes.dateindex, - self.ratio.dateindex.as_ref().unwrap(), - self.ratio_4y_sma - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap(), - self.ratio_4y_sd - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap(), - exit, - )?; - Ok(()) - }, - )?; - - self.ratio_1y_zscore.as_mut().unwrap().compute_all( - indexer, - indexes, - starting_indexes, - exit, - |vec, _, _, starting_indexes, exit| { - vec.compute_zscore( - starting_indexes.dateindex, - self.ratio.dateindex.as_ref().unwrap(), - self.ratio_1y_sma - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap(), - self.ratio_1y_sd - .as_ref() - .unwrap() - .dateindex - .as_ref() - .unwrap(), - exit, - )?; - Ok(()) - }, + self.ratio.dateindex.as_ref().unwrap(), + Some(date_to_price), )?; Ok(()) @@ -1485,49 +653,22 @@ impl ComputedRatioVecsFromDateIndex { fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec> { [ - self.ratio_sd - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_4y_sd - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_1y_sd - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_p99_9 - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_p99_5 - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_p99 - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), self.ratio_p1 .as_mut() .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_p0_5 + self.ratio_p2 .as_mut() .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_p0_1 + self.ratio_p5 .as_mut() .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_p1sd + self.ratio_p95 .as_mut() .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_p2sd + self.ratio_p98 .as_mut() .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_p3sd - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_m1sd - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_m2sd - .as_mut() - .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), - self.ratio_m3sd + self.ratio_p99 .as_mut() .map_or(vec![], |v| vec![v.dateindex.as_mut().unwrap()]), ] @@ -1540,66 +681,30 @@ impl ComputedRatioVecsFromDateIndex { [ self.price.as_ref().map_or(vec![], |v| v.vecs()), self.ratio.vecs(), - self.ratio_sma.as_ref().map_or(vec![], |v| v.vecs()), self.ratio_1w_sma.as_ref().map_or(vec![], |v| v.vecs()), self.ratio_1m_sma.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_1y_sma.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_4y_sma.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_1y_sma_momentum_oscillator - .as_ref() - .map_or(vec![], |v| v.vecs()), self.ratio_sd.as_ref().map_or(vec![], |v| v.vecs()), self.ratio_1y_sd.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_2y_sd.as_ref().map_or(vec![], |v| v.vecs()), self.ratio_4y_sd.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p99_9.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p99_5.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p99.as_ref().map_or(vec![], |v| v.vecs()), self.ratio_p1.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p0_5.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p0_1.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p1sd.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p2sd.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p3sd.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_m1sd.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_m2sd.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_m3sd.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p99_9_as_price + self.ratio_p2.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_p5.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_p95.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_p98.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_p99.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_p1_as_price.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_p2_as_price.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_p5_as_price.as_ref().map_or(vec![], |v| v.vecs()), + self.ratio_p95_as_price .as_ref() .map_or(vec![], |v| v.vecs()), - self.ratio_p99_5_as_price + self.ratio_p98_as_price .as_ref() .map_or(vec![], |v| v.vecs()), self.ratio_p99_as_price .as_ref() .map_or(vec![], |v| v.vecs()), - self.ratio_p1_as_price.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_p0_5_as_price - .as_ref() - .map_or(vec![], |v| v.vecs()), - self.ratio_p0_1_as_price - .as_ref() - .map_or(vec![], |v| v.vecs()), - self.ratio_p1sd_as_price - .as_ref() - .map_or(vec![], |v| v.vecs()), - self.ratio_p2sd_as_price - .as_ref() - .map_or(vec![], |v| v.vecs()), - self.ratio_p3sd_as_price - .as_ref() - .map_or(vec![], |v| v.vecs()), - self.ratio_m1sd_as_price - .as_ref() - .map_or(vec![], |v| v.vecs()), - self.ratio_m2sd_as_price - .as_ref() - .map_or(vec![], |v| v.vecs()), - self.ratio_m3sd_as_price - .as_ref() - .map_or(vec![], |v| v.vecs()), - self.ratio_zscore.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_1y_zscore.as_ref().map_or(vec![], |v| v.vecs()), - self.ratio_4y_zscore.as_ref().map_or(vec![], |v| v.vecs()), ] .into_iter() .flatten() diff --git a/crates/brk_computer/src/grouped/sd_from_dateindex.rs b/crates/brk_computer/src/grouped/sd_from_dateindex.rs new file mode 100644 index 000000000..1e957d147 --- /dev/null +++ b/crates/brk_computer/src/grouped/sd_from_dateindex.rs @@ -0,0 +1,707 @@ +use brk_error::Result; +use brk_indexer::Indexer; +use brk_structs::{CheckedSub, Date, DateIndex, Dollars, StoredF32, Version}; +use vecdb::{ + AnyCollectableVec, AnyIterableVec, AnyStoredVec, AnyVec, BoxedVecIterator, CollectableVec, + Database, EagerVec, Exit, GenericStoredVec, StoredIndex, +}; + +use crate::{Indexes, grouped::source::Source, indexes}; + +use super::{ComputedVecsFromDateIndex, VecBuilderOptions}; + +#[derive(Clone)] +pub struct ComputedStandardDeviationVecsFromDateIndex { + days: usize, + + pub sma: Option>, + pub sd: ComputedVecsFromDateIndex, + pub _0sd_as_price: ComputedVecsFromDateIndex, + pub p0_5sd: ComputedVecsFromDateIndex, + pub p1sd: ComputedVecsFromDateIndex, + pub p1_5sd: ComputedVecsFromDateIndex, + pub p2sd: ComputedVecsFromDateIndex, + pub p2_5sd: ComputedVecsFromDateIndex, + pub p3sd: ComputedVecsFromDateIndex, + pub m0_5sd: ComputedVecsFromDateIndex, + pub m1sd: ComputedVecsFromDateIndex, + pub m1_5sd: ComputedVecsFromDateIndex, + pub m2sd: ComputedVecsFromDateIndex, + pub m2_5sd: ComputedVecsFromDateIndex, + pub m3sd: ComputedVecsFromDateIndex, + pub p0_5sd_as_price: ComputedVecsFromDateIndex, + pub p1sd_as_price: ComputedVecsFromDateIndex, + pub p1_5sd_as_price: ComputedVecsFromDateIndex, + pub p2sd_as_price: ComputedVecsFromDateIndex, + pub p2_5sd_as_price: ComputedVecsFromDateIndex, + pub p3sd_as_price: ComputedVecsFromDateIndex, + pub m0_5sd_as_price: ComputedVecsFromDateIndex, + pub m1sd_as_price: ComputedVecsFromDateIndex, + pub m1_5sd_as_price: ComputedVecsFromDateIndex, + pub m2sd_as_price: ComputedVecsFromDateIndex, + pub m2_5sd_as_price: ComputedVecsFromDateIndex, + pub m3sd_as_price: ComputedVecsFromDateIndex, + pub zscore: ComputedVecsFromDateIndex, +} + +const VERSION: Version = Version::ONE; + +impl ComputedStandardDeviationVecsFromDateIndex { + #[allow(clippy::too_many_arguments)] + pub fn forced_import( + db: &Database, + name: &str, + days: usize, + source: Source, + version: Version, + indexes: &indexes::Vecs, + ) -> Result { + let options = VecBuilderOptions::default().add_last(); + + Ok(Self { + days, + sma: source.is_compute().then(|| { + ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_sma"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + ) + .unwrap() + }), + sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p0_5sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p0_5sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p1sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p1sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p1_5sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p1_5sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p2sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p2sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p2_5sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p2_5sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p3sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p3sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m0_5sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m0_5sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m1sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m1sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m1_5sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m1_5sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m2sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m2sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m2_5sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m2_5sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m3sd: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m3sd"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + _0sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_0sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p0_5sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p0_5sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p1sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p1sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p1_5sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p1_5sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p2sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p2sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p2_5sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p2_5sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + p3sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_p3sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m0_5sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m0_5sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m1sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m1sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m1_5sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m1_5sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m2sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m2sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m2_5sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m2_5sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + m3sd_as_price: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_m3sd_as_price"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + zscore: ComputedVecsFromDateIndex::forced_import( + db, + &format!("{name}_zscore"), + Source::Compute, + version + VERSION + Version::ZERO, + indexes, + options, + )?, + }) + } + + pub fn compute_all( + &mut self, + indexer: &Indexer, + indexes: &indexes::Vecs, + starting_indexes: &Indexes, + exit: &Exit, + source: &impl CollectableVec, + source_as_price: Option<&impl AnyIterableVec>, + ) -> Result<()> { + let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap(); + + self.sma.as_mut().unwrap().compute_all( + indexer, + indexes, + starting_indexes, + exit, + |v, _, _, starting_indexes, exit| { + v.compute_sma_( + starting_indexes.dateindex, + source, + self.days, + exit, + Some(min_date), + )?; + Ok(()) + }, + )?; + + let sma_opt: Option<&EagerVec> = None; + self.compute_rest( + indexer, + indexes, + starting_indexes, + exit, + sma_opt, + source, + source_as_price, + ) + } + + #[allow(clippy::too_many_arguments)] + pub fn compute_rest( + &mut self, + indexer: &Indexer, + indexes: &indexes::Vecs, + starting_indexes: &Indexes, + exit: &Exit, + sma_opt: Option<&impl AnyIterableVec>, + source: &impl CollectableVec, + source_as_price: Option<&impl AnyIterableVec>, + ) -> Result<()> { + let sma = sma_opt.unwrap_or_else(|| unsafe { + std::mem::transmute(&self.sma.as_ref().unwrap().dateindex) + }); + + let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap(); + + let source_version = source.version(); + + self.mut_vecs().iter_mut().try_for_each(|v| -> Result<()> { + v.validate_computed_version_or_reset( + Version::ZERO + v.inner_version() + source_version, + )?; + Ok(()) + })?; + + let starting_dateindex = self + .mut_vecs() + .iter() + .map(|v| DateIndex::from(v.len())) + .min() + .unwrap() + .min(starting_indexes.dateindex); + + let mut sorted = source.collect_range( + Some(min_date.unwrap_to_usize()), + Some(starting_dateindex.unwrap_to_usize()), + )?; + + sorted.sort_unstable(); + + let mut sma_iter = sma.iter(); + + source + .iter_at(starting_dateindex) + .try_for_each(|(index, ratio)| -> Result<()> { + if index < min_date { + self.sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + + self.p0_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.p1sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.p1_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.p2sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.p2_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.p3sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.m0_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.m1sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.m1_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.m2sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.m2_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + self.m3sd.dateindex.as_mut().unwrap().forced_push_at( + index, + StoredF32::NAN, + exit, + )?; + } else { + let ratio = ratio.into_owned(); + let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos); + sorted.insert(pos, ratio); + + let avg = sma_iter.unwrap_get_inner(index); + + let population = + index.checked_sub(min_date).unwrap().unwrap_to_usize() as f32 + 1.0; + + let sd = StoredF32::from( + (sorted.iter().map(|v| (**v - *avg).powi(2)).sum::() / population) + .sqrt(), + ); + + self.sd + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, sd, exit)?; + self.p0_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg + StoredF32::from(0.5 * *sd), + exit, + )?; + self.p1sd + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, avg + sd, exit)?; + self.p1_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg + StoredF32::from(1.5 * *sd), + exit, + )?; + self.p2sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg + 2 * sd, + exit, + )?; + self.p2_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg + StoredF32::from(2.5 * *sd), + exit, + )?; + self.p3sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg + 3 * sd, + exit, + )?; + self.m0_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg - StoredF32::from(0.5 * *sd), + exit, + )?; + self.m1sd + .dateindex + .as_mut() + .unwrap() + .forced_push_at(index, avg - sd, exit)?; + self.m1_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg - StoredF32::from(1.5 * *sd), + exit, + )?; + self.m2sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg - 2 * sd, + exit, + )?; + self.m2_5sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg - StoredF32::from(2.5 * *sd), + exit, + )?; + self.m3sd.dateindex.as_mut().unwrap().forced_push_at( + index, + avg - 3 * sd, + exit, + )?; + } + + Ok(()) + })?; + + drop(sma_iter); + + self.mut_vecs() + .into_iter() + .try_for_each(|v| v.safe_flush(exit))?; + + [ + &mut self.sd, + &mut self.p0_5sd, + &mut self.p1sd, + &mut self.p1_5sd, + &mut self.p2sd, + &mut self.p2_5sd, + &mut self.p3sd, + &mut self.m0_5sd, + &mut self.m1sd, + &mut self.m1_5sd, + &mut self.m2sd, + &mut self.m2_5sd, + &mut self.m3sd, + ] + .into_iter() + .try_for_each(|v| { + v.compute_rest(starting_indexes, exit, None as Option<&EagerVec<_, _>>) + })?; + + self.zscore.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |vec, _, _, starting_indexes, exit| { + vec.compute_zscore( + starting_indexes.dateindex, + source, + sma, + self.sd.dateindex.as_ref().unwrap(), + exit, + )?; + Ok(()) + }, + )?; + + let Some(price) = source_as_price else { + return Ok(()); + }; + + let compute_as_price = + |as_price: &mut ComputedVecsFromDateIndex, + mut iter: BoxedVecIterator| { + as_price.compute_all( + indexer, + indexes, + starting_indexes, + exit, + |vec, _, _, starting_indexes, exit| { + vec.compute_transform( + starting_indexes.dateindex, + price, + |(i, price, ..)| { + let multiplier = iter.unwrap_get_inner(i); + (i, price * multiplier) + }, + exit, + )?; + Ok(()) + }, + ) + }; + + compute_as_price(&mut self._0sd_as_price, sma.iter())?; + compute_as_price( + &mut self.p0_5sd_as_price, + self.p0_5sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.p1sd_as_price, + self.p1sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.p1_5sd_as_price, + self.p1_5sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.p2sd_as_price, + self.p2sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.p2_5sd_as_price, + self.p2_5sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.p3sd_as_price, + self.p3sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.m0_5sd_as_price, + self.m0_5sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.m1sd_as_price, + self.m1sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.m1_5sd_as_price, + self.m1_5sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.m2sd_as_price, + self.m2sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.m2_5sd_as_price, + self.m2_5sd.dateindex.as_ref().unwrap().iter(), + )?; + compute_as_price( + &mut self.m3sd_as_price, + self.m3sd.dateindex.as_ref().unwrap().iter(), + )?; + + Ok(()) + } + + fn mut_vecs(&mut self) -> [&mut EagerVec; 13] { + [ + self.sd.dateindex.as_mut().unwrap(), + self.p0_5sd.dateindex.as_mut().unwrap(), + self.p1sd.dateindex.as_mut().unwrap(), + self.p1_5sd.dateindex.as_mut().unwrap(), + self.p2sd.dateindex.as_mut().unwrap(), + self.p2_5sd.dateindex.as_mut().unwrap(), + self.p3sd.dateindex.as_mut().unwrap(), + self.m0_5sd.dateindex.as_mut().unwrap(), + self.m1sd.dateindex.as_mut().unwrap(), + self.m1_5sd.dateindex.as_mut().unwrap(), + self.m2sd.dateindex.as_mut().unwrap(), + self.m2_5sd.dateindex.as_mut().unwrap(), + self.m3sd.dateindex.as_mut().unwrap(), + ] + } + + pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> { + [ + self.sma.as_ref().map_or(vec![], |v| v.vecs()), + self.sd.vecs(), + self.p0_5sd.vecs(), + self.p1sd.vecs(), + self.p1_5sd.vecs(), + self.p2sd.vecs(), + self.p2_5sd.vecs(), + self.p3sd.vecs(), + self.m0_5sd.vecs(), + self.m1sd.vecs(), + self.m1_5sd.vecs(), + self.m2sd.vecs(), + self.m2_5sd.vecs(), + self.m3sd.vecs(), + self._0sd_as_price.vecs(), + self.p0_5sd_as_price.vecs(), + self.p1sd_as_price.vecs(), + self.p1_5sd_as_price.vecs(), + self.p2sd_as_price.vecs(), + self.p2_5sd_as_price.vecs(), + self.p3sd_as_price.vecs(), + self.m0_5sd_as_price.vecs(), + self.m1sd_as_price.vecs(), + self.m1_5sd_as_price.vecs(), + self.m2sd_as_price.vecs(), + self.m2_5sd_as_price.vecs(), + self.m3sd_as_price.vecs(), + self.zscore.vecs(), + ] + .into_iter() + .flatten() + .collect::>() + } +} diff --git a/crates/brk_computer/src/stateful/mod.rs b/crates/brk_computer/src/stateful/mod.rs index 968bacc7a..59900a3b5 100644 --- a/crates/brk_computer/src/stateful/mod.rs +++ b/crates/brk_computer/src/stateful/mod.rs @@ -597,24 +597,52 @@ impl Vecs { Ordering::Less => Height::ZERO, }; - // dbg!(stateful_starting_height); + // info!("stateful_starting_height = {stateful_starting_height}"); // let stateful_starting_height = stateful_starting_height // .checked_sub(Height::new(1)) // .unwrap_or_default(); - // dbg!(stateful_starting_height); + // info!("stateful_starting_height = {stateful_starting_height}"); let starting_height = starting_indexes.height.min(stateful_starting_height); - // dbg!(starting_height); + info!("starting_height = {starting_height}"); let last_height = Height::from(indexer.vecs.height_to_blockhash.stamp()); - // dbg!(last_height); + info!("last_height = {last_height}"); if starting_height <= last_height { - // dbg!(starting_height); + info!("starting_height = {starting_height}"); let starting_height = if starting_height.is_not_zero() { - let mut set = separate_utxo_vecs - .iter_mut() - .map(|(_, v)| v.import_state(starting_height).unwrap_or_default()) - .collect::>(); + let mut set = [ + self.chain_state.rollback_before(starting_height.into())?, + self.p2pk33addressindex_to_anyaddressindex + .rollback_before(starting_height.into())?, + self.p2pk65addressindex_to_anyaddressindex + .rollback_before(starting_height.into())?, + self.p2pkhaddressindex_to_anyaddressindex + .rollback_before(starting_height.into())?, + self.p2shaddressindex_to_anyaddressindex + .rollback_before(starting_height.into())?, + self.p2traddressindex_to_anyaddressindex + .rollback_before(starting_height.into())?, + self.p2wpkhaddressindex_to_anyaddressindex + .rollback_before(starting_height.into())?, + self.p2wshaddressindex_to_anyaddressindex + .rollback_before(starting_height.into())?, + self.p2aaddressindex_to_anyaddressindex + .rollback_before(starting_height.into())?, + self.loadedaddressindex_to_loadedaddressdata + .rollback_before(starting_height.into())?, + self.emptyaddressindex_to_emptyaddressdata + .rollback_before(starting_height.into())?, + ] + .into_iter() + .enumerate() + .map(|(i, s)| { + let h = Height::from(s).incremented(); + dbg!((i, s, h)); + h + }) + .collect::>(); + if set.len() == 1 { set.pop_first().unwrap() } else { @@ -623,40 +651,23 @@ impl Vecs { } else { Height::ZERO }; - // dbg!(starting_height); + + let starting_height = if starting_height.is_not_zero() + && separate_utxo_vecs + .iter_mut() + .map(|(_, v)| v.import_state(starting_height).unwrap_or_default()) + .all(|h| h == starting_height) + { + starting_height + } else { + Height::ZERO + }; + info!("starting_height = {starting_height}"); let starting_height = if starting_height.is_not_zero() && separate_address_vecs .iter_mut() .map(|(_, v)| v.import_state(starting_height).unwrap_or_default()) - .chain( - [ - self.chain_state.rollback_before(starting_height.into())?, - self.p2pk33addressindex_to_anyaddressindex - .rollback_before(starting_height.into())?, - self.p2pk65addressindex_to_anyaddressindex - .rollback_before(starting_height.into())?, - self.p2pkhaddressindex_to_anyaddressindex - .rollback_before(starting_height.into())?, - self.p2shaddressindex_to_anyaddressindex - .rollback_before(starting_height.into())?, - self.p2traddressindex_to_anyaddressindex - .rollback_before(starting_height.into())?, - self.p2wpkhaddressindex_to_anyaddressindex - .rollback_before(starting_height.into())?, - self.p2wshaddressindex_to_anyaddressindex - .rollback_before(starting_height.into())?, - self.p2aaddressindex_to_anyaddressindex - .rollback_before(starting_height.into())?, - self.loadedaddressindex_to_loadedaddressdata - .rollback_before(starting_height.into())?, - self.emptyaddressindex_to_emptyaddressdata - .rollback_before(starting_height.into())?, - ] - .into_iter() - .map(Height::from) - .map(Height::incremented), - ) .all(|h| h == starting_height) { starting_height @@ -664,8 +675,7 @@ impl Vecs { Height::ZERO }; - // dbg!(starting_height); - // std::process::exit(0); + info!("starting_height = {starting_height}"); let mut chain_state: Vec; if starting_height.is_not_zero() { @@ -690,6 +700,8 @@ impl Vecs { } else { info!("Starting processing utxos from the start"); + // std::process::exit(0); + chain_state = vec![]; self.p2pk33addressindex_to_anyaddressindex.reset()?; diff --git a/crates/brk_computer/src/states/price_to_amount.rs b/crates/brk_computer/src/states/price_to_amount.rs index 49f44106d..cf198f978 100644 --- a/crates/brk_computer/src/states/price_to_amount.rs +++ b/crates/brk_computer/src/states/price_to_amount.rs @@ -67,7 +67,7 @@ impl PriceToAmount { self.state.as_mut().unwrap().remove(&price); } } else { - dbg!(&self.state, price, &self.pathbuf); + dbg!(price, &self.pathbuf); unreachable!(); } } diff --git a/crates/brk_structs/src/structs/mod.rs b/crates/brk_structs/src/structs/mod.rs index f19493995..155563604 100644 --- a/crates/brk_structs/src/structs/mod.rs +++ b/crates/brk_structs/src/structs/mod.rs @@ -42,6 +42,7 @@ mod semesterindex; mod stored_bool; mod stored_f32; mod stored_f64; +mod stored_i16; mod stored_u16; mod stored_u32; mod stored_u64; @@ -103,6 +104,7 @@ pub use semesterindex::*; pub use stored_bool::*; pub use stored_f32::*; pub use stored_f64::*; +pub use stored_i16::*; pub use stored_u8::*; pub use stored_u16::*; pub use stored_u32::*; diff --git a/crates/brk_structs/src/structs/stored_f32.rs b/crates/brk_structs/src/structs/stored_f32.rs index 7dcead77e..1d68e03b8 100644 --- a/crates/brk_structs/src/structs/stored_f32.rs +++ b/crates/brk_structs/src/structs/stored_f32.rs @@ -1,6 +1,7 @@ use core::panic; use std::{ cmp::Ordering, + f32, ops::{Add, AddAssign, Div, Mul, Sub}, }; @@ -26,6 +27,10 @@ use super::{Dollars, StoredF64}; )] pub struct StoredF32(f32); +impl StoredF32 { + pub const NAN: Self = StoredF32(f32::NAN); +} + impl From for StoredF32 { fn from(value: f32) -> Self { Self(value) diff --git a/crates/brk_structs/src/structs/stored_i16.rs b/crates/brk_structs/src/structs/stored_i16.rs new file mode 100644 index 000000000..e249b9681 --- /dev/null +++ b/crates/brk_structs/src/structs/stored_i16.rs @@ -0,0 +1,105 @@ +use std::ops::{Add, AddAssign, Div}; + +use derive_deref::Deref; +use serde::Serialize; +use vecdb::{CheckedSub, Printable, StoredCompressed}; +use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; + +#[derive( + Debug, + Deref, + Clone, + Default, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + FromBytes, + Immutable, + IntoBytes, + KnownLayout, + Serialize, + StoredCompressed, +)] +pub struct StoredI16(i16); + +impl StoredI16 { + pub const ZERO: Self = Self(0); + + pub fn new(v: i16) -> Self { + Self(v) + } +} + +impl From for StoredI16 { + fn from(value: i16) -> Self { + Self(value) + } +} + +impl From for StoredI16 { + fn from(value: usize) -> Self { + if value > i16::MAX as usize { + panic!("usize too big (value = {value})") + } + Self(value as i16) + } +} + +impl CheckedSub for StoredI16 { + fn checked_sub(self, rhs: Self) -> Option { + self.0.checked_sub(rhs.0).map(Self) + } +} + +impl Div for StoredI16 { + type Output = Self; + fn div(self, rhs: usize) -> Self::Output { + Self(self.0 / rhs as i16) + } +} + +impl Add for StoredI16 { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } +} + +impl AddAssign for StoredI16 { + fn add_assign(&mut self, rhs: Self) { + *self = *self + rhs + } +} + +impl From for StoredI16 { + fn from(value: f64) -> Self { + if value < 0.0 || value > i16::MAX as f64 { + panic!() + } + Self(value as i16) + } +} + +impl From for f64 { + fn from(value: StoredI16) -> Self { + value.0 as f64 + } +} + +impl From for usize { + fn from(value: StoredI16) -> Self { + value.0 as usize + } +} + +impl Printable for StoredI16 { + fn to_string() -> &'static str { + "i16" + } + + fn to_possible_strings() -> &'static [&'static str] { + &["i16"] + } +} diff --git a/crates/brk_structs/src/structs/stored_u16.rs b/crates/brk_structs/src/structs/stored_u16.rs index a51fc823e..3290395da 100644 --- a/crates/brk_structs/src/structs/stored_u16.rs +++ b/crates/brk_structs/src/structs/stored_u16.rs @@ -1,8 +1,8 @@ use std::ops::{Add, AddAssign, Div}; -use vecdb::{CheckedSub, Printable, StoredCompressed}; use derive_deref::Deref; use serde::Serialize; +use vecdb::{CheckedSub, Printable, StoredCompressed}; use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout}; use super::{ @@ -33,8 +33,8 @@ pub struct StoredU16(u16); impl StoredU16 { pub const ZERO: Self = Self(0); - pub fn new(counter: u16) -> Self { - Self(counter) + pub fn new(v: u16) -> Self { + Self(v) } } diff --git a/websites/custom/index.html b/websites/custom/index.html index b893898f6..a0ba6afbd 100644 --- a/websites/custom/index.html +++ b/websites/custom/index.html @@ -1,31 +1,236 @@ - + Custom - -

Infinite Code: A Digital Symphony

- -

- Unleash the inner coder within you and weave a tapestry of innovation in a - digital realm where every line of code becomes your palette. Picture an - endless HTML canvas, each tag an invitation to dream, every element a - window to possibilities. Let your JavaScript spirit soar like a dynamic - function—fluid yet unforgivingly creative—transforming mere logic into - animated expressions of art. And as you style your thoughts with CSS, each - hex color shines like a beacon of brilliance, every property a stroke of - imaginative genius. -

- -

- In this universe of web development, the DOM is your poetic playground, - where algorithms dance with beauty and creativity is written in the syntax - of tomorrow. Create without boundaries, let your code be as rich and - expansive as an infinite loop of passion, where every variable holds the - whisper of your inspiration, and every function unveils a new horizon of - digital artistry. The web is your canvas; the sky, a limitless expanse of - code. -

+ +
+ diff --git a/websites/default/index.html b/websites/default/index.html index 666c1b12a..15ae556e0 100644 --- a/websites/default/index.html +++ b/websites/default/index.html @@ -2,10 +2,7 @@ - + } ISeries * @typedef {_ISeriesApi<'Candlestick', number>} CandlestickISeries + * @typedef {_ISeriesApi<'Histogram', number>} HistogramISeries * @typedef {_ISeriesApi<'Line', number>} LineISeries * @typedef {_ISeriesApi<'Baseline', number>} BaselineISeries * + * @typedef {_LineSeriesPartialOptions} LineSeriesPartialOptions + * @typedef {_HistogramSeriesPartialOptions} HistogramSeriesPartialOptions + * @typedef {_BaselineSeriesPartialOptions} BaselineSeriesPartialOptions + * @typedef {_CandlestickSeriesPartialOptions} CandlestickSeriesPartialOptions + * * @typedef {Object} Series * @property {ISeries} inner * @property {string} id @@ -28,27 +34,18 @@ * @typedef {_CandlestickData} CandlestickData * @typedef {_LineData} LineData * @typedef {_BaselineData} BaselineData + * @typedef {_HistogramData} HistogramData * * @typedef {function({ iseries: ISeries; unit: Unit; index: Index }): void} SetDataCallback - * - * @typedef {Object} CreatePriceLine - * @property {number} value - * - * @typedef {Object} CreatePriceLineOptions - * @property {CreatePriceLine} createPriceLine - * - * @typedef {Partial} PartialCreatePriceLineOptions - * - * @typedef {LineSeriesPartialOptions & PartialCreatePriceLineOptions} PartialLineStyleOptions - * @typedef {CandlestickSeriesPartialOptions & PartialCreatePriceLineOptions} PartialCandlestickStyleOptions - * @typedef {BaselineSeriesPartialOptions & PartialCreatePriceLineOptions} PartialBaselineStyleOptions */ import { createChart, CandlestickSeries, + HistogramSeries, LineSeries, BaselineSeries, + // } from "./5.0.8/dist/lightweight-charts.standalone.development.mjs"; } from "./5.0.8/dist/lightweight-charts.standalone.production.mjs"; const oklchToRGBA = createOklchToRGBA(); @@ -561,7 +558,7 @@ function createChartElement({ * @param {boolean} [args.defaultActive] * @param {boolean} [args.inverse] * @param {SetDataCallback} [args.setDataCallback] - * @param {PartialCandlestickStyleOptions} [args.options] + * @param {CandlestickSeriesPartialOptions} [args.options] */ addCandlestickSeries({ vecId, @@ -573,6 +570,7 @@ function createChartElement({ setDataCallback, data, inverse, + options, }) { const green = inverse ? colors.red : colors.green; const red = inverse ? colors.green : colors.red; @@ -588,6 +586,7 @@ function createChartElement({ wickDownColor: red(), borderVisible: false, visible: defaultActive !== false, + ...options, }, paneIndex, ) @@ -607,6 +606,58 @@ function createChartElement({ vecId, }); }, + /** + * @param {Object} args + * @param {string} args.name + * @param {Unit} args.unit + * @param {number} args.order + * @param {Color} args.color + * @param {VecId} [args.vecId] + * @param {Accessor} [args.data] + * @param {number} [args.paneIndex] + * @param {boolean} [args.defaultActive] + * @param {SetDataCallback} [args.setDataCallback] + * @param {HistogramSeriesPartialOptions} [args.options] + */ + addHistogramSeries({ + vecId, + name, + unit, + color, + order, + paneIndex = 0, + defaultActive, + setDataCallback, + data, + options, + }) { + /** @type {HistogramISeries} */ + const iseries = /** @type {any} */ ( + ichart.addSeries( + /** @type {SeriesDefinition<'Histogram'>} */ (HistogramSeries), + { + color: color(), + visible: defaultActive !== false, + priceLineVisible: false, + }, + paneIndex, + ) + ); + + return addSeries({ + colors: [color], + iseries, + name, + order, + paneIndex, + seriesType: "Bar", + unit, + data, + setDataCallback, + defaultActive, + vecId, + }); + }, /** * @param {Object} args * @param {string} args.name @@ -618,7 +669,7 @@ function createChartElement({ * @param {SetDataCallback} [args.setDataCallback] * @param {number} [args.paneIndex] * @param {boolean} [args.defaultActive] - * @param {PartialLineStyleOptions} [args.options] + * @param {LineSeriesPartialOptions} [args.options] */ addLineSeries({ vecId, @@ -649,11 +700,6 @@ function createChartElement({ ) ); - const priceLineOptions = options?.createPriceLine; - if (priceLineOptions) { - createPriceLine(iseries, priceLineOptions, colors); - } - return addSeries({ colors: [color], iseries, @@ -678,7 +724,7 @@ function createChartElement({ * @param {SetDataCallback} [args.setDataCallback] * @param {number} [args.paneIndex] * @param {boolean} [args.defaultActive] - * @param {PartialBaselineStyleOptions} [args.options] + * @param {BaselineSeriesPartialOptions} [args.options] */ addBaselineSeries({ vecId, @@ -701,7 +747,7 @@ function createChartElement({ lineWidth: /** @type {any} */ (1.5), visible: defaultActive !== false, baseValue: { - price: options?.createPriceLine?.value ?? 0, + price: options?.baseValue?.price ?? 0, }, ...options, topLineColor: options?.topLineColor ?? colors.green(), @@ -717,11 +763,6 @@ function createChartElement({ ) ); - const priceLineOptions = options?.createPriceLine; - if (priceLineOptions) { - createPriceLine(iseries, priceLineOptions, colors); - } - return addSeries({ colors: [ () => options?.topLineColor ?? colors.green(), @@ -761,6 +802,16 @@ function createChartElement({ paneIndex, order, }); + } else if (blueprint.type === "Histogram") { + chart.addHistogramSeries({ + name: blueprint.title, + unit, + color: blueprint.color, + data: blueprint.data, + defaultActive: blueprint.defaultActive, + paneIndex, + order, + }); } else { chart.addLineSeries({ name: blueprint.title, @@ -927,21 +978,6 @@ function createLegend({ signals, utils }) { }; } -/** - * @param {ISeries} series - * @param {DeepPartial} options - * @param {Colors} colors - */ -function createPriceLine(series, options, colors) { - series.createPriceLine({ - price: options.value || 0, - color: colors.gray(), - axisLabelVisible: false, - lineWidth: 1, - lineStyle: 4, - }); -} - /** * @param {number} value * @param {0 | 2} [digits] diff --git a/websites/default/scripts/chart.js b/websites/default/scripts/chart.js index afe0b2682..14ae5b51b 100644 --- a/websites/default/scripts/chart.js +++ b/websites/default/scripts/chart.js @@ -425,10 +425,26 @@ export function init({ ); break; } + case "Histogram": { + seriesList.push( + chart.addHistogramSeries({ + vecId: blueprint.key, + name: blueprint.title, + unit, + color: blueprint.color, + defaultActive: blueprint.defaultActive, + paneIndex, + options: blueprint.options, + order, + }), + ); + break; + } case "Candlestick": { throw Error("TODO"); } - default: + case "Line": + case undefined: seriesList.push( chart.addLineSeries({ vecId: blueprint.key, diff --git a/websites/default/scripts/main.js b/websites/default/scripts/main.js index de8e17248..c63b21c97 100644 --- a/websites/default/scripts/main.js +++ b/websites/default/scripts/main.js @@ -2,7 +2,7 @@ /** * @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, SeriesType } from "./options" - * @import { Valued, SingleValueData, CandlestickData, OHLCTuple, Series, ISeries, LineData, BaselineData, PartialLineStyleOptions, PartialBaselineStyleOptions, PartialCandlestickStyleOptions } from "../packages/lightweight-charts/wrapper" + * @import { Valued, SingleValueData, CandlestickData, OHLCTuple, Series, ISeries, HistogramData, LineData, BaselineData, LineSeriesPartialOptions, BaselineSeriesPartialOptions, HistogramSeriesPartialOptions, CandlestickSeriesPartialOptions } from "../packages/lightweight-charts/wrapper" * @import * as _ from "../packages/leeoniya-ufuzzy/1.0.18/dist/uFuzzy.d.ts" * @import { SerializedChartableIndex } from "./chart"; * @import { Signal, Signals, Accessor } from "../packages/solidjs-signals/wrapper"; @@ -45,6 +45,7 @@ * "Years" | * "Locktime" | * "sat/vB" | + * "%pnl" | * "constant" | * "cagr" | * "vB" | @@ -53,7 +54,6 @@ * "Epoch" | * "Height" | * "Type" | - * "zscore" | * "Bytes" * } Unit */ @@ -196,12 +196,12 @@ function createUtils() { createSpanName(name) { const spanName = window.document.createElement("span"); spanName.classList.add("name"); - const [first, second, third] = name.split("-"); + const [first, second, third] = name.split(" - "); spanName.innerHTML = first; if (second) { const smallRest = window.document.createElement("small"); - smallRest.innerHTML = `— ${second}`; + smallRest.innerHTML = ` — ${second}`; spanName.append(smallRest); if (third) { @@ -776,16 +776,18 @@ function createUtils() { if ( ((!unit || thoroughUnitCheck) && (id.endsWith("ratio") || - (id.includes("ratio") && id.endsWith("sma")) || + (id.includes("ratio") && + (id.endsWith("sma") || id.endsWith("zscore"))) || + id.endsWith("_5sd") || id.endsWith("1sd") || id.endsWith("2sd") || id.endsWith("3sd") || - id.endsWith("p0_1") || - id.endsWith("p0_5") || id.endsWith("p1") || - id.endsWith("p99") || - id.endsWith("p99_5") || - id.endsWith("p99_9"))) || + id.endsWith("p2") || + id.endsWith("p5") || + id.endsWith("p95") || + id.endsWith("p98") || + id.endsWith("p99"))) || id.includes("liveliness") || id.includes("vaultedness") ) { @@ -828,10 +830,6 @@ function createUtils() { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "performance"; } - if ((!unit || thoroughUnitCheck) && id.endsWith("zscore")) { - if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); - unit = "zscore"; - } if ((!unit || thoroughUnitCheck) && id.endsWith("locktime")) { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "Locktime"; @@ -934,6 +932,14 @@ function createUtils() { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "%all"; } + if ( + (!unit || thoroughUnitCheck) && + (id.includes("relative_to_realized_profit") || + id.includes("relative_to_realized_loss")) + ) { + if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); + unit = "%pnl"; + } if ((!unit || thoroughUnitCheck) && id.endsWith("relative_to_own_supply")) { if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`); unit = "%self"; diff --git a/websites/default/scripts/options.js b/websites/default/scripts/options.js index 9ba53690d..0d00c1d8c 100644 --- a/websites/default/scripts/options.js +++ b/websites/default/scripts/options.js @@ -9,33 +9,41 @@ * @property {"Baseline"} type * @property {Color} [color] * @property {[Color, Color]} [colors] - * @property {PartialBaselineStyleOptions} [options] + * @property {BaselineSeriesPartialOptions} [options] * @property {Accessor} [data] * @typedef {BaseSeriesBlueprint & BaselineSeriesBlueprintSpecific} BaselineSeriesBlueprint * * @typedef {Object} CandlestickSeriesBlueprintSpecific * @property {"Candlestick"} type * @property {Color} [color] - * @property {PartialCandlestickStyleOptions} [options] + * @property {CandlestickSeriesPartialOptions} [options] * @property {Accessor} [data] * @typedef {BaseSeriesBlueprint & CandlestickSeriesBlueprintSpecific} CandlestickSeriesBlueprint * * @typedef {Object} LineSeriesBlueprintSpecific * @property {"Line"} [type] * @property {Color} [color] - * @property {PartialLineStyleOptions} [options] + * @property {LineSeriesPartialOptions} [options] * @property {Accessor} [data] * @typedef {BaseSeriesBlueprint & LineSeriesBlueprintSpecific} LineSeriesBlueprint * - * @typedef {BaselineSeriesBlueprint | CandlestickSeriesBlueprint | LineSeriesBlueprint} AnySeriesBlueprint + * @typedef {Object} HistogramSeriesBlueprintSpecific + * @property {"Histogram"} type + * @property {Color} color + * @property {HistogramSeriesPartialOptions} [options] + * @property {Accessor} [data] + * @typedef {BaseSeriesBlueprint & HistogramSeriesBlueprintSpecific} HistogramSeriesBlueprint + * + * @typedef {BaselineSeriesBlueprint | CandlestickSeriesBlueprint | LineSeriesBlueprint | HistogramSeriesBlueprint} AnySeriesBlueprint * * @typedef {AnySeriesBlueprint["type"]} SeriesType * - * @typedef {{ key: VecId, unit?: Unit | Unit[] }} FetchedAnySeriesOptions + * @typedef {{ key: VecId, unit?: Unit }} FetchedAnySeriesOptions * * @typedef {BaselineSeriesBlueprint & FetchedAnySeriesOptions} FetchedBaselineSeriesBlueprint * @typedef {CandlestickSeriesBlueprint & FetchedAnySeriesOptions} FetchedCandlestickSeriesBlueprint * @typedef {LineSeriesBlueprint & FetchedAnySeriesOptions} FetchedLineSeriesBlueprint + * @typedef {HistogramSeriesBlueprint & FetchedAnySeriesOptions} FetchedHistogramSeriesBlueprint * @typedef {AnySeriesBlueprint & FetchedAnySeriesOptions} AnyFetchedSeriesBlueprint * * @typedef {Object} PartialOption @@ -996,6 +1004,12 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { ]); const cointimePrices = /** @type {const} */ ([ + { + key: `true_market_mean`, + name: "True market mean", + title: "True market mean", + color: colors.blue, + }, { key: `vaulted_price`, name: "Vaulted", @@ -1008,12 +1022,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { title: "Active Price", color: colors.rose, }, - { - key: `true_market_mean`, - name: "True market mean", - title: "True market mean", - color: colors.blue, - }, { key: `cointime_price`, name: "cointime", @@ -1024,16 +1032,10 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { const cointimeCapitalizations = /** @type {const} */ ([ { - key: `thermo_cap`, - name: "Thermo", - title: "Thermo Capitalization", - color: colors.emerald, - }, - { - key: `investor_cap`, - name: "Investor", - title: "Investor Capitalization", - color: colors.fuchsia, + key: `vaulted_cap`, + name: "Vaulted", + title: "Vaulted Capitalization", + color: colors.lime, }, { key: `active_cap`, @@ -1041,33 +1043,93 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { title: "Active Capitalization", color: colors.rose, }, - { - key: `vaulted_cap`, - name: "Vaulted", - title: "Vaulted Capitalization", - color: colors.lime, - }, { key: `cointime_cap`, name: "Cointime", title: "Cointime Capitalization", color: colors.yellow, }, + { + key: `investor_cap`, + name: "Investor", + title: "Investor Capitalization", + color: colors.fuchsia, + }, + { + key: `thermo_cap`, + name: "Thermo", + title: "Thermo Capitalization", + color: colors.emerald, + }, ]); + /** + * @param {Object} args + * @param {number} [args.number] + * @param {boolean} [args.defaultActive] + * @param {Unit} args.unit + */ + function createPriceLine({ number = 0, unit, defaultActive }) { + return /** @satisfies {FetchedLineSeriesBlueprint} */ ({ + key: `constant_${number >= 0 ? number : `minus_${Math.abs(number)}`}`, + title: `${number}`, + unit, + defaultActive, + color: colors.gray, + options: { + lineStyle: 4, + lastValueVisible: false, + crosshairMarkerVisible: false, + }, + }); + } + + /** + * @param {Object} args + * @param {number[]} args.numbers + * @param {boolean} [args.defaultActive] + * @param {Unit} args.unit + */ + function createPriceLines({ numbers, unit }) { + return numbers.map( + (number) => + /** @satisfies {FetchedLineSeriesBlueprint} */ ({ + key: `constant_${number >= 0 ? number : `minus_${Math.abs(number)}`}`, + title: `${number}`, + unit, + defaultActive: !number, + color: colors.gray, + options: { + lineStyle: 4, + lastValueVisible: false, + crosshairMarkerVisible: false, + }, + }), + ); + } + /** * @param {Object} args * @param {VecId} args.key * @param {string} args.name * @param {Color} [args.color] + * @param {Unit} [args.unit] * @param {boolean} [args.defaultActive] - * @param {PartialLineStyleOptions} [args.options] + * @param {LineSeriesPartialOptions} [args.options] */ - function createBaseSeries({ key, name, color, defaultActive, options }) { + function createBaseSeries({ + key, + name, + color, + defaultActive, + unit, + options, + }) { return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({ key, title: name, color, + unit, defaultActive, options, }); @@ -1217,255 +1279,355 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { * @param {VecIdRatioZScoreCapBase} args.key * @param {Color} [args.color] */ - function createPriceWithRatio({ name, title, legend, key, color }) { - return { - name, - title, - top: [ - createBaseSeries({ - key, - name: legend, - color, - }), - ...(`${key}_ratio_p1sd_as_price` in vecIdToIndexes - ? [ - createBaseSeries({ - key: `${key}_ratio_p1sd_as_price`, - name: "+1σ", - color: colors.orange, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p2sd_as_price`, - name: "+2σ", - color: colors.red, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p3sd_as_price`, - name: "+3σ", - color: colors.pink, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_m1sd_as_price`, - name: "−1σ", - color: colors.cyan, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_m2sd_as_price`, - name: "−2σ", - color: colors.blue, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_m3sd_as_price`, - name: "−3σ", - color: colors.violet, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p99_as_price`, - name: "p99", - color: colors.orange, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p99_5_as_price`, - name: "p99.5", - color: colors.red, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p99_9_as_price`, - name: "p99.9", - color: colors.pink, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p1_as_price`, - name: "p1", - color: colors.cyan, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p0_5_as_price`, - name: "p0.5", - color: colors.blue, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p0_1_as_price`, - name: "p0.1", - color: colors.violet, - defaultActive: false, - }), - ] - : []), - ], - bottom: [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - key: `${key}_ratio`, - title: "Ratio", - type: "Baseline", - options: { - baseValue: { price: 1 }, - createPriceLine: { - value: 1, + function createPriceWithRatioOptions({ name, title, legend, key, color }) { + return [ + { + name: "price", + title, + top: [ + createBaseSeries({ + key, + name: legend, + color, + }), + ], + }, + { + name: "Ratio", + title: `${title} Ratio`, + top: [ + createBaseSeries({ + key, + name: legend, + color, + }), + ...(`${key}_ratio_p1sd_as_price` in vecIdToIndexes + ? [ + createBaseSeries({ + key: `${key}_ratio_p1_as_price`, + name: "p1", + color: colors.indigo, + defaultActive: false, + }), + 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: [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + key: `${key}_ratio`, + title: "Ratio", + type: "Baseline", + options: { + baseValue: { price: 1 }, }, - }, - }), - ...(`${key}_ratio_p1sd` in vecIdToIndexes - ? [ - createBaseSeries({ - key: `${key}_ratio_p1sd`, - name: "+1σ", - color: colors.orange, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p2sd`, - name: "+2σ", - color: colors.red, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p3sd`, - name: "+3σ", - color: colors.pink, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_m1sd`, - name: "−1σ", - color: colors.cyan, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_m2sd`, - name: "−2σ", - color: colors.blue, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_m3sd`, - name: "−3σ", - color: colors.violet, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p99`, - name: "p99", - color: colors.orange, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p99_5`, - name: "p99.5", - color: colors.red, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p99_9`, - name: "p99.9", - color: colors.pink, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p1`, - name: "p1", - color: colors.cyan, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p0_5`, - name: "p0.5", - color: colors.blue, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_p0_1`, - name: "p0.1", - color: colors.violet, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_1w_sma`, - name: "1w sma", - color: colors.fuchsia, - 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.rose, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_4y_sma`, - name: "4y_sma", - color: colors.purple, - defaultActive: false, - }), - createBaseSeries({ - key: `${key}_ratio_sma`, - name: "sma", - color: colors.yellow, - defaultActive: false, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - key: `${key}_ratio_1y_sma_momentum_oscillator`, - title: "1Y Momentum", - type: "Baseline", - options: { - createPriceLine: { - value: 0, - }, + }), + ...(`${key}_ratio_p1sd` in vecIdToIndexes + ? [ + createBaseSeries({ + key: `${key}_ratio_p1`, + name: "p1", + color: colors.indigo, + defaultActive: false, + }), + createBaseSeries({ + key: `${key}_ratio_p2`, + name: "p2", + color: colors.violet, + defaultActive: false, + }), + 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, + unit: "Ratio", + }), + ], + }, + ...(`${key}_ratio_zscore` in vecIdToIndexes + ? [ + { + name: "ZScores", + tree: [ + { + name: "compare", + title: `Compare ${title} ZScores`, + top: [ + createBaseSeries({ + key, + name: legend, + color, + }), + createBaseSeries({ + key: `${key}_ratio_1y_0sd_as_price`, + name: "1y 0sd", + color: colors.fuchsia, + defaultActive: false, + }), + createBaseSeries({ + key: `${key}_ratio_2y_0sd_as_price`, + name: "2y 0sd", + color: colors.purple, + defaultActive: false, + }), + createBaseSeries({ + key: `${key}_ratio_4y_0sd_as_price`, + name: "4y 0sd", + color: colors.violet, + defaultActive: false, + }), + createBaseSeries({ + key: `${key}_ratio_0sd_as_price`, + name: "0sd", + color: colors.indigo, + defaultActive: false, + }), + ], + bottom: [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + key: `${key}_ratio_zscore`, + title: "All", + type: "Baseline", + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + key: `${key}_ratio_4y_zscore`, + colors: [colors.lime, colors.rose], + title: "4y", + type: "Baseline", + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + key: `${key}_ratio_2y_zscore`, + colors: [colors.avocado, colors.pink], + title: "2y", + type: "Baseline", + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + key: `${key}_ratio_1y_zscore`, + colors: [colors.yellow, colors.fuchsia], + title: "1Y", + type: "Baseline", + }), + ...createPriceLines({ + numbers: [0, 1, 2, 3, 4, -1, -2, -3, -4], + unit: "Ratio", + }), + ], }, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - key: `${key}_ratio_zscore`, - title: "All time", - type: "Baseline", - options: { - createPriceLine: { - value: 0, + ...[ + { + nameAddon: "all", + titleAddon: "", + keyAddon: "", }, - }, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - key: `${key}_ratio_4y_zscore`, - title: "4y", - type: "Baseline", - colors: [colors.yellow, colors.pink], - options: { - createPriceLine: { - value: 0, + { + nameAddon: "4y", + titleAddon: "4y", + keyAddon: "4y_", }, - }, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - key: `${key}_ratio_1y_zscore`, - title: "1y", - type: "Baseline", - colors: [colors.orange, colors.purple], - options: { - createPriceLine: { - value: 0, + { + nameAddon: "2y", + titleAddon: "2y", + keyAddon: "2y_", }, - }, - }), - ] - : []), - ], - }; + { + nameAddon: "1y", + titleAddon: "1y", + keyAddon: "1y_", + }, + ].flatMap(({ nameAddon, titleAddon, keyAddon }) => ({ + name: nameAddon, + title: `${title} ${titleAddon} ZScore`, + top: [ + createBaseSeries({ + key, + 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, + }), + ], + bottom: [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + key: `${key}_ratio_${keyAddon}zscore`, + title: "All time", + type: "Baseline", + }), + ...createPriceLines({ + numbers: [0, 1, 2, 3, 4, -1, -2, -3, -4], + unit: "Ratio", + }), + ], + })), + ], + }, + ] + : []), + ]; } /** @@ -1910,15 +2072,36 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { { name: "Realized", tree: [ + ...("list" in args + ? [ + { + name: "Price", + title: `Realized Price ${title}`, + top: args.list.map(({ color, name, key }) => + createBaseSeries({ + key: `${fixKey(key)}realized_price`, + name, + color, + }), + ), + }, + ] + : createPriceWithRatioOptions({ + title: `Realized Price ${title}`, + key: `${fixKey(args.key)}realized_price`, + name: "price", + legend: "realized", + color: args.color, + })), { - name: "cap", + name: "capitalization", title: `Realized Capitalization ${title}`, bottom: list.flatMap(({ color, name, key: _key }) => { const key = fixKey(_key); return /** @type {const} */ ([ createBaseSeries({ key: `${key}realized_cap`, - name: useGroupName ? name : "Cap", + name: useGroupName ? name : "Capitalization", color, }), ...(!("list" in args) @@ -1928,36 +2111,16 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { key: `${key}realized_cap_30d_change`, title: "30d change", defaultActive: false, - options: { - createPriceLine: { - value: 0, - }, - }, + }), + createPriceLine({ + unit: "USD", + defaultActive: false, }), ] : []), ]); }), }, - "list" in args - ? { - name: "Price", - title: `Realized Price ${title}`, - top: args.list.map(({ color, name, key }) => - createBaseSeries({ - key: `${fixKey(key)}realized_price`, - name, - color, - }), - ), - } - : createPriceWithRatio({ - title: `Realized Price ${title}`, - key: `${fixKey(args.key)}realized_price`, - name: "price", - legend: "realized", - color: args.color, - }), ...(!("list" in args) ? [ { @@ -2007,11 +2170,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { )}realized_profit_relative_to_realized_cap`, title: "Profit", color: colors.green, - options: { - createPriceLine: { - value: 0, - }, - }, }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", @@ -2020,11 +2178,13 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { )}realized_loss_relative_to_realized_cap`, title: "Loss", color: colors.red, - options: { - createPriceLine: { - value: 0, - }, - }, + }), + createPriceLine({ + unit: "%rcap", + }), + createPriceLine({ + unit: "USD", + defaultActive: false, }), ], }, @@ -2035,74 +2195,54 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: `${fixKey(key)}net_realized_profit_and_loss`, - title: "Net", - options: { - createPriceLine: { - value: 0, - }, - }, + title: "Raw", }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: `${fixKey( key, )}net_realized_profit_and_loss_cumulative`, - title: "Cumulative net", + title: "Cumulative", defaultActive: false, - options: { - createPriceLine: { - value: 0, - }, - }, }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: `${fixKey( key, )}net_realized_profit_and_loss_cumulative_30d_change`, - title: "cum net 30d change", + title: "cumulative 30d change", defaultActive: false, - options: { - createPriceLine: { - value: 0, - }, - }, }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: `${fixKey( key, )}net_realized_profit_and_loss_relative_to_realized_cap`, - title: "Net", - options: { - createPriceLine: { - value: 0, - }, - }, + title: "Raw", }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: `${fixKey( key, )}net_realized_profit_and_loss_cumulative_30d_change_relative_to_realized_cap`, - title: "cum net 30d change", - options: { - createPriceLine: { - value: 0, - }, - }, + title: "cumulative 30d change", + defaultActive: false, }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: `${fixKey( key, )}net_realized_profit_and_loss_cumulative_30d_change_relative_to_market_cap`, - title: "cumulative net 30d change", - options: { - createPriceLine: { - value: 0, - }, - }, + title: "cumulative 30d change", + }), + createPriceLine({ + unit: "%mcap", + }), + createPriceLine({ + unit: "%rcap", + }), + createPriceLine({ + unit: "USD", }), ]), }, @@ -2112,15 +2252,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { bottom: list.flatMap(({ color, name, key }) => { const soprKey = `${fixKey(key)}spent_output_profit_ratio`; const asoprKey = `${fixKey(key)}adjusted_spent_output_profit_ratio`; - return [ /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ type: "Baseline", key: soprKey, title: "sopr", options: { - createPriceLine: { - value: 1, + baseValue: { + price: 1, }, }, }), @@ -2132,13 +2271,17 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { title: "asopr", colors: [colors.yellow, colors.pink], options: { - createPriceLine: { - value: 1, + baseValue: { + price: 1, }, }, }), ] : []), + createPriceLine({ + number: 1, + unit: "Ratio", + }), ]; }), }, @@ -2147,82 +2290,80 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { { name: "profit", title: `Realized Profit ${title}`, - bottom: list.flatMap(({ color, name, key: _key }) => { - const key = fixKey(_key); - return /** @type {const} */ ([ - createBaseSeries({ - key: `${key}realized_profit`, - name, - color, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${key}realized_profit_relative_to_realized_cap`, - title: name, - color, - options: { - createPriceLine: { - value: 0, - }, - }, - }), - ]); - }), + bottom: [ + ...list.flatMap(({ color, name, key: _key }) => { + const key = fixKey(_key); + return /** @type {const} */ ([ + createBaseSeries({ + key: `${key}realized_profit`, + name, + color, + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${key}realized_profit_relative_to_realized_cap`, + title: name, + color, + }), + ]); + }), + createPriceLine({ + unit: "USD", + }), + ], }, { name: "loss", title: `Realized Loss ${title}`, - bottom: list.flatMap(({ color, name, key: _key }) => { - const key = fixKey(_key); - return /** @type {const} */ ([ - createBaseSeries({ - key: `${key}realized_loss`, - name, - color, - }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${key}realized_loss_relative_to_realized_cap`, - title: name, - color, - options: { - createPriceLine: { - value: 0, - }, - }, - }), - ]); - }), + bottom: [ + ...list.flatMap(({ color, name, key: _key }) => { + const key = fixKey(_key); + return /** @type {const} */ ([ + createBaseSeries({ + key: `${key}realized_loss`, + name, + color, + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${key}realized_loss_relative_to_realized_cap`, + title: name, + color, + }), + ]); + }), + createPriceLine({ + unit: "USD", + }), + ], }, { name: "Net pnl", title: `Net Realized Profit And Loss ${title}`, - bottom: list.flatMap(({ color, name, key }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey(key)}net_realized_profit_and_loss`, - title: name, - color, - options: { - createPriceLine: { - value: 0, - }, - }, + bottom: [ + ...list.flatMap(({ color, name, key }) => [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey(key)}net_realized_profit_and_loss`, + title: name, + color, + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey( + key, + )}net_realized_profit_and_loss_relative_to_realized_cap`, + title: name, + color, + }), + ]), + createPriceLine({ + unit: "USD", }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey( - key, - )}net_realized_profit_and_loss_relative_to_realized_cap`, - title: name, - color, - options: { - createPriceLine: { - value: 0, - }, - }, + createPriceLine({ + unit: "%rcap", }), - ]), + ], }, { name: "cumulative", @@ -2258,67 +2399,63 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { { name: "Net pnl", title: `Cumulative Net Realized Profit And Loss ${title}`, - bottom: list.flatMap(({ color, name, key }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey( - key, - )}net_realized_profit_and_loss_cumulative`, - title: name, - color, - defaultActive: false, - options: { - createPriceLine: { - value: 0, - }, - }, + bottom: [ + ...list.flatMap(({ color, name, key }) => [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey( + key, + )}net_realized_profit_and_loss_cumulative`, + title: name, + color, + defaultActive: false, + }), + ]), + createPriceLine({ + unit: "USD", }), - ]), + ], }, { name: "Net pnl 30d change", title: `Cumulative Net Realized Profit And Loss 30 Day Change ${title}`, - bottom: list.flatMap(({ color, name, key }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey( - key, - )}net_realized_profit_and_loss_cumulative_30d_change`, - title: name, - color, - options: { - createPriceLine: { - value: 0, - }, - }, + bottom: [ + ...list.flatMap(({ color, name, key }) => [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey( + key, + )}net_realized_profit_and_loss_cumulative_30d_change`, + title: name, + color, + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey( + key, + )}net_realized_profit_and_loss_cumulative_30d_change_relative_to_realized_cap`, + title: name, + color, + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey( + key, + )}net_realized_profit_and_loss_cumulative_30d_change_relative_to_market_cap`, + title: name, + color, + }), + ]), + createPriceLine({ + unit: "USD", }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey( - key, - )}net_realized_profit_and_loss_cumulative_30d_change_relative_to_realized_cap`, - title: name, - color, - options: { - createPriceLine: { - value: 0, - }, - }, + createPriceLine({ + unit: "%mcap", }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey( - key, - )}net_realized_profit_and_loss_cumulative_30d_change_relative_to_market_cap`, - title: name, - color, - options: { - createPriceLine: { - value: 0, - }, - }, + createPriceLine({ + unit: "%rcap", }), - ]), + ], }, ], }, @@ -2328,19 +2465,20 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { { name: "Normal", title: `Spent Output Profit Ratio ${title}`, - bottom: list.flatMap(({ color, name, key }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey(key)}spent_output_profit_ratio`, - title: name, - color, - options: { - createPriceLine: { - value: 1, - }, - }, + bottom: [ + ...list.flatMap(({ color, name, key }) => [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey(key)}spent_output_profit_ratio`, + title: name, + color, + }), + ]), + createPriceLine({ + number: 1, + unit: "Ratio", }), - ]), + ], }, ...(() => { const reducedList = list @@ -2358,21 +2496,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { { name: "Adjusted", title: `Adjusted Spent Output Profit Ratio ${title}`, - bottom: reducedList.flatMap( - ({ color, name, key }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key, - title: name, - color, - options: { - createPriceLine: { - value: 1, - }, - }, - }), - ], - ), + bottom: [ + ...reducedList.flatMap( + ({ color, name, key }) => [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key, + title: name, + color, + }), + ], + ), + createPriceLine({ + number: 1, + unit: "Ratio", + }), + ], }, ] : []; @@ -2402,14 +2541,6 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { name: "pnl", title: `Unrealized Profit And Loss ${title}`, bottom: [ - // createBaseSeries({ - // key: `0`, - // name: "Base", - // color: colors.gray, - // options: { - // lineStyle: 4, - // }, - // }), createBaseSeries({ key: `${fixKey(args.key)}unrealized_profit`, name: "Profit", @@ -2426,6 +2557,10 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { name: "Negative Loss", color: colors.red, }), + createPriceLine({ + unit: "USD", + defaultActive: false, + }), ], }, ] @@ -2462,32 +2597,30 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { { name: "Net pnl", title: `Net Unrealized Profit And Loss ${title}`, - bottom: list.flatMap(({ color, name, key }) => [ - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey(key)}net_unrealized_profit_and_loss`, - title: useGroupName ? name : "Net", - color: useGroupName ? color : undefined, - options: { - createPriceLine: { - value: 0, - }, - }, + bottom: [ + ...list.flatMap(({ color, name, key }) => [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey(key)}net_unrealized_profit_and_loss`, + title: useGroupName ? name : "Net", + color: useGroupName ? color : undefined, + }), + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + type: "Baseline", + key: `${fixKey( + key, + )}net_unrealized_profit_and_loss_relative_to_market_cap`, + title: useGroupName ? name : "Net", + color: useGroupName ? color : undefined, + }), + ]), + createPriceLine({ + unit: "USD", }), - /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ - type: "Baseline", - key: `${fixKey( - key, - )}net_unrealized_profit_and_loss_relative_to_market_cap`, - title: useGroupName ? name : "Net", - color: useGroupName ? color : undefined, - options: { - createPriceLine: { - value: 0, - }, - }, + createPriceLine({ + unit: "%mcap", }), - ]), + ], }, ], }, @@ -2679,15 +2812,16 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { }), ), }, - ...averages.map(({ key, name, color }) => - createPriceWithRatio({ + ...averages.map(({ key, name, color }) => ({ + name, + tree: createPriceWithRatioOptions({ key: `${key}_sma`, name, title: `${name} Market Price Moving Average`, legend: "average", color, }), - ), + })), ], }, { @@ -2714,12 +2848,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { key: `${key}_returns`, title: "Returns", type: "Baseline", - options: { - createPriceLine: { - value: 0, - }, - }, }), + createPriceLine({ + unit: "performance", + }), + ...(`${key}_cagr` in vecIdToIndexes + ? [ + /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ + key: `${key}_cagr`, + title: "cagr", + type: "Baseline", + }), + createPriceLine({ + unit: "cagr", + }), + ] + : []), ], })), }, @@ -2786,21 +2930,14 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { title: "dca", type: "Baseline", colors: [colors.yellow, colors.pink], - options: { - createPriceLine: { - value: 0, - }, - }, }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ key: `${key}_returns`, title: "lump sum", type: "Baseline", - options: { - createPriceLine: { - value: 0, - }, - }, + }), + createPriceLine({ + unit: "performance", }), ], }), @@ -2836,42 +2973,25 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { title: "dca", type: "Baseline", colors: [colors.yellow, colors.pink], - options: { - createPriceLine: { - value: 0, - }, - }, }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ key: `${key}_dca_cagr`, title: "dca", type: "Baseline", colors: [colors.yellow, colors.pink], - options: { - createPriceLine: { - value: 0, - }, - }, }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ key: `${key}_returns`, title: "lump sum", type: "Baseline", - options: { - createPriceLine: { - value: 0, - }, - }, }), /** @satisfies {FetchedBaselineSeriesBlueprint} */ ({ key: `${key}_cagr`, title: "lump sum", type: "Baseline", - options: { - createPriceLine: { - value: 0, - }, - }, + }), + createPriceLine({ + unit: "performance", }), ], }), @@ -2910,11 +3030,9 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { key: `dca_class_${year}_returns`, title: "dca", type: "Baseline", - options: { - createPriceLine: { - value: 0, - }, - }, + }), + createPriceLine({ + unit: "performance", }), ], }), @@ -3419,99 +3537,30 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { name: "Cointime", tree: [ { - name: "Coinblocks", - title: "Coinblocks", - bottom: [ - createBaseSeries({ - key: "coinblocks_destroyed", - name: "Destroyed", - color: colors.red, - }), - createBaseSeries({ - key: "coinblocks_destroyed_cumulative", - name: "Cumulative Destroyed", - color: colors.red, - defaultActive: false, - }), - createBaseSeries({ - key: "coinblocks_created", - name: "created", - color: colors.orange, - }), - createBaseSeries({ - key: "coinblocks_created_cumulative", - name: "Cumulative created", - color: colors.orange, - defaultActive: false, - }), - createBaseSeries({ - key: "coinblocks_stored", - name: "stored", - color: colors.green, - }), - createBaseSeries({ - key: "coinblocks_stored_cumulative", - name: "Cumulative stored", - color: colors.green, - defaultActive: false, - }), - ], - }, - { - name: "Liveliness & Vaultedness", - title: "Liveliness & Vaultedness", - bottom: [ - createBaseSeries({ - key: "liveliness", - name: "Liveliness", - color: colors.rose, - }), - createBaseSeries({ - key: "vaultedness", - name: "Vaultedness", - color: colors.lime, - }), - ], - }, - { - name: "Supply", - title: "Cointime Supply", - bottom: /** @type {const} */ ([ + name: "Prices", + tree: [ { - name: "all", - color: colors.orange, + name: "Compare", + title: "Compare Cointime Prices", + top: cointimePrices.map(({ key, name, color }) => + createBaseSeries({ + key, + name, + color, + }), + ), }, - { - name: "vaulted", - color: colors.lime, - }, - { name: "active", color: colors.rose }, - ]).flatMap( - ({ name, color }) => - /** @type {const} */ ([ - createBaseSeries({ - key: `${ - name !== "all" ? /** @type {const} */ (`${name}_`) : "" - }supply`, - name, - color, - }), - createBaseSeries({ - key: `${ - name !== "all" ? /** @type {const} */ (`${name}_`) : "" - }supply_in_btc`, - name, - color, - }), - createBaseSeries({ - key: `${ - name !== "all" ? /** @type {const} */ (`${name}_`) : "" - }supply_in_usd`, - name, - color, - }), - ]), - ), + ...cointimePrices.map(({ key, name, color, title }) => ({ + name, + tree: createPriceWithRatioOptions({ + key, + legend: name, + color, + name, + title, + }), + })), + ], }, { name: "Capitalization", @@ -3565,28 +3614,98 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) { ], }, { - name: "Prices", - tree: [ + name: "Supply", + title: "Cointime Supply", + bottom: /** @type {const} */ ([ { - name: "Compare", - title: "Compare Cointime Prices", - top: cointimePrices.map(({ key, name, color }) => + name: "all", + color: colors.orange, + }, + { + name: "vaulted", + color: colors.lime, + }, + { name: "active", color: colors.rose }, + ]).flatMap( + ({ name, color }) => + /** @type {const} */ ([ createBaseSeries({ - key, + key: `${ + name !== "all" ? /** @type {const} */ (`${name}_`) : "" + }supply`, name, color, }), - ), - }, - ...cointimePrices.map(({ key, name, color, title }) => - createPriceWithRatio({ - key, - legend: name, - color, - name, - title, - }), - ), + createBaseSeries({ + key: `${ + name !== "all" ? /** @type {const} */ (`${name}_`) : "" + }supply_in_btc`, + name, + color, + }), + createBaseSeries({ + key: `${ + name !== "all" ? /** @type {const} */ (`${name}_`) : "" + }supply_in_usd`, + name, + color, + }), + ]), + ), + }, + { + name: "Liveliness & Vaultedness", + title: "Liveliness & Vaultedness", + bottom: [ + createBaseSeries({ + key: "liveliness", + name: "Liveliness", + color: colors.rose, + }), + createBaseSeries({ + key: "vaultedness", + name: "Vaultedness", + color: colors.lime, + }), + ], + }, + { + name: "Coinblocks", + title: "Coinblocks", + bottom: [ + createBaseSeries({ + key: "coinblocks_destroyed", + name: "Destroyed", + color: colors.red, + }), + createBaseSeries({ + key: "coinblocks_destroyed_cumulative", + name: "Cumulative Destroyed", + color: colors.red, + defaultActive: false, + }), + createBaseSeries({ + key: "coinblocks_created", + name: "created", + color: colors.orange, + }), + createBaseSeries({ + key: "coinblocks_created_cumulative", + name: "Cumulative created", + color: colors.orange, + defaultActive: false, + }), + createBaseSeries({ + key: "coinblocks_stored", + name: "stored", + color: colors.green, + }), + createBaseSeries({ + key: "coinblocks_stored_cumulative", + name: "Cumulative stored", + color: colors.green, + defaultActive: false, + }), ], }, ], @@ -3743,7 +3862,7 @@ export function initOptions({ if (env.localhost && !(blueprint.key in vecIdToIndexes)) { throw Error(`${blueprint.key} not recognized`); } - const unit = utils.vecidToUnit(blueprint.key); + const unit = blueprint.unit ?? utils.vecidToUnit(blueprint.key); record[unit] ??= []; record[unit].push(blueprint); return record;