mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-25 21:54:30 -07:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ec960bfefa | |||
| 79f689dde1 | |||
| 3b3654df56 | |||
| c66f008f07 | |||
| 37d9498d90 | |||
| 1ff67093db | |||
| daed37ccb8 | |||
| d41d807b4f | |||
| d6fa5c8a55 | |||
| 2dd608dfed |
Generated
+35
-36
@@ -170,9 +170,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.4.25"
|
||||
version = "0.4.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40f6024f3f856663b45fd0c9b6f2024034a702f453549449e0d84a305900dad4"
|
||||
checksum = "937f41778d8baa0b8984a101f48ec5d2e5b0d23a3f9235b2066eef29c3472bb9"
|
||||
dependencies = [
|
||||
"brotli",
|
||||
"flate2",
|
||||
@@ -477,7 +477,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"brk_bundler",
|
||||
"brk_cli",
|
||||
@@ -497,7 +497,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_bundler"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"brk_rolldown",
|
||||
"log",
|
||||
@@ -508,7 +508,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_cli"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"bitcoincore-rpc",
|
||||
"brk_computer",
|
||||
@@ -531,7 +531,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_computer"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitcoin",
|
||||
@@ -548,7 +548,6 @@ dependencies = [
|
||||
"derive_deref",
|
||||
"either",
|
||||
"fjall",
|
||||
"jiff",
|
||||
"log",
|
||||
"rayon",
|
||||
"serde",
|
||||
@@ -558,7 +557,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_core"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitcoin",
|
||||
@@ -579,7 +578,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_exit"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"brk_logger",
|
||||
"ctrlc",
|
||||
@@ -588,7 +587,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_fetcher"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"brk_core",
|
||||
"brk_logger",
|
||||
@@ -600,7 +599,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_indexer"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -618,7 +617,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_interface"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"brk_computer",
|
||||
"brk_core",
|
||||
@@ -636,7 +635,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_logger"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"env_logger",
|
||||
@@ -646,7 +645,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_mcp"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"brk_interface",
|
||||
@@ -656,7 +655,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_parser"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -1025,7 +1024,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_server"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"bitcoincore-rpc",
|
||||
@@ -1055,7 +1054,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_store"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"brk_core",
|
||||
"byteview",
|
||||
@@ -1077,7 +1076,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_vec"
|
||||
version = "0.0.78"
|
||||
version = "0.0.80"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"brk_core",
|
||||
@@ -1159,9 +1158,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "castaway"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
|
||||
checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
@@ -1371,9 +1370,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
@@ -2431,9 +2430,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.5"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
|
||||
checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -3553,9 +3552,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "regress"
|
||||
version = "0.10.3"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ef7fa9ed0256d64a688a3747d0fef7a88851c18a5e1d57f115f38ec2e09366"
|
||||
checksum = "145bb27393fe455dd64d6cbc8d059adfa392590a45eadf079c01b11857e7b010"
|
||||
dependencies = [
|
||||
"hashbrown 0.15.4",
|
||||
"memchr",
|
||||
@@ -4240,9 +4239,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.1"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0207d6ed1852c2a124c1fbec61621acb8330d2bf969a5d0643131e9affd985a5"
|
||||
checksum = "ed0aee96c12fa71097902e0bb061a5e1ebd766a6636bb605ba401c45c1650eac"
|
||||
dependencies = [
|
||||
"indexmap 2.10.0",
|
||||
"serde",
|
||||
@@ -4264,18 +4263,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5c1c469eda89749d2230d8156a5969a69ffe0d6d01200581cdc6110674d293e"
|
||||
checksum = "97200572db069e74c512a14117b296ba0a80a30123fbbb5aa1f4a348f639ca30"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.0.0"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b679217f2848de74cabd3e8fc5e6d66f40b7da40f8e1954d92054d9010690fd5"
|
||||
checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64"
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
@@ -4574,9 +4573,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "vfs"
|
||||
version = "0.12.1"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ec343ec20aa715908fd028a4b8e7c99a349d13143224222e4d61c316d1e7f0a"
|
||||
checksum = "9e723b9e1c02a3cf9f9d0de6a4ddb8cdc1df859078902fe0ae0589d615711ae6"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
]
|
||||
@@ -4929,9 +4928,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.11"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
|
||||
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
|
||||
+15
-15
@@ -4,7 +4,7 @@ members = ["crates/*"]
|
||||
package.description = "The Bitcoin Research Kit is a suite of tools designed to extract, compute and display data stored on a Bitcoin Core node"
|
||||
package.license = "MIT"
|
||||
package.edition = "2024"
|
||||
package.version = "0.0.78"
|
||||
package.version = "0.0.80"
|
||||
package.homepage = "https://bitcoinresearchkit.org"
|
||||
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
||||
|
||||
@@ -26,22 +26,22 @@ axum = "0.8.4"
|
||||
bincode = { version = "2.0.1", features = ["serde"] }
|
||||
bitcoin = { version = "0.32.6", features = ["serde"] }
|
||||
bitcoincore-rpc = "0.19.0"
|
||||
brk_bundler = { version = "0.0.78", path = "crates/brk_bundler" }
|
||||
brk_cli = { version = "0.0.78", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0.0.78", path = "crates/brk_computer" }
|
||||
brk_core = { version = "0.0.78", path = "crates/brk_core" }
|
||||
brk_exit = { version = "0.0.78", path = "crates/brk_exit" }
|
||||
brk_fetcher = { version = "0.0.78", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.0.78", path = "crates/brk_indexer" }
|
||||
brk_interface = { version = "0.0.78", path = "crates/brk_interface" }
|
||||
brk_logger = { version = "0.0.78", path = "crates/brk_logger" }
|
||||
brk_mcp = { version = "0.0.78", path = "crates/brk_mcp" }
|
||||
brk_parser = { version = "0.0.78", path = "crates/brk_parser" }
|
||||
brk_bundler = { version = "0.0.80", path = "crates/brk_bundler" }
|
||||
brk_cli = { version = "0.0.80", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0.0.80", path = "crates/brk_computer" }
|
||||
brk_core = { version = "0.0.80", path = "crates/brk_core" }
|
||||
brk_exit = { version = "0.0.80", path = "crates/brk_exit" }
|
||||
brk_fetcher = { version = "0.0.80", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.0.80", path = "crates/brk_indexer" }
|
||||
brk_interface = { version = "0.0.80", path = "crates/brk_interface" }
|
||||
brk_logger = { version = "0.0.80", path = "crates/brk_logger" }
|
||||
brk_mcp = { version = "0.0.80", path = "crates/brk_mcp" }
|
||||
brk_parser = { version = "0.0.80", path = "crates/brk_parser" }
|
||||
brk_rmcp = { version = "0.2.1", features = ["transport-streamable-http-server", "transport-worker"]}
|
||||
# brk_rmcp = { path = "../rust-sdk/crates/rmcp", features = ["transport-streamable-http-server", "transport-worker"]}
|
||||
brk_server = { version = "0.0.78", path = "crates/brk_server" }
|
||||
brk_store = { version = "0.0.78", path = "crates/brk_store" }
|
||||
brk_vec = { version = "0.0.78", path = "crates/brk_vec" }
|
||||
brk_server = { version = "0.0.80", path = "crates/brk_server" }
|
||||
brk_store = { version = "0.0.80", path = "crates/brk_store" }
|
||||
brk_vec = { version = "0.0.80", path = "crates/brk_vec" }
|
||||
byteview = "=0.6.1"
|
||||
clap = { version = "4.5.41", features = ["string"] }
|
||||
clap_derive = "4.5.41"
|
||||
|
||||
@@ -46,8 +46,7 @@ The toolkit can be used in various ways to accommodate as many needs as possible
|
||||
Just like the website, it's entirely free, with no authentication or rate-limiting.
|
||||
- **[AI](https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_mcp/README.md#brk-mcp)** \
|
||||
LLMs have to possibility to connect to BRK's backend through a [MCP](https://modelcontextprotocol.io/introduction). \
|
||||
It will give them access to the same tools as the API, with no restrictions, and allow you to have your very own data analysts. \
|
||||
One-shot output examples: [Document](https://claude.ai/public/artifacts/71194d29-f965-417c-ba09-fdf0e4ecb1d5) // [Dashboard](https://claude.ai/public/artifacts/beef143f-399a-4ed4-b8bf-c986b776de42) // [Dashboard 2](https://claude.ai/public/artifacts/5430ae49-bb3d-4fc1-ab24-f1e33deb40dc)
|
||||
It will give them access to the same tools as the API, with no restrictions, and allow you to have your very own data analysts.
|
||||
- **[CLI](https://crates.io/crates/brk_cli)** \
|
||||
Node runners are strongly encouraged to try out and self-host their own instance using BRK's command line interface. \
|
||||
The CLI has multiple cogs available for users to tweak to adapt to all situations with even the possibility for web developers to create their own custom website which could later on be added as an alternative front-end.
|
||||
|
||||
@@ -24,7 +24,7 @@ color-eyre = { workspace = true }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
toml = "0.9.1"
|
||||
toml = "0.9.2"
|
||||
|
||||
[[bin]]
|
||||
name = "brk"
|
||||
|
||||
@@ -23,7 +23,6 @@ color-eyre = { workspace = true }
|
||||
derive_deref = { workspace = true }
|
||||
either = "1.15.0"
|
||||
fjall = { workspace = true }
|
||||
jiff = { workspace = true }
|
||||
log = { workspace = true }
|
||||
rayon = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
|
||||
@@ -10,6 +10,7 @@ use brk_fetcher::Fetcher;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, AnyIterableVec, AnyVec, Computation, EagerVec, Format, StoredIndex,
|
||||
VecIterator,
|
||||
};
|
||||
|
||||
use crate::vecs::grouped::Source;
|
||||
@@ -456,33 +457,34 @@ impl Vecs {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let mut prev = None;
|
||||
self.dateindex_to_ohlc_in_cents.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex_to_date,
|
||||
|(di, d, this)| {
|
||||
let get_prev = || {
|
||||
this.get_or_read(di, &this.mmap().load())
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_owned()
|
||||
};
|
||||
if prev.is_none() {
|
||||
let i = di.unwrap_to_usize();
|
||||
prev.replace(if i > 0 {
|
||||
this.into_iter().unwrap_get_inner_(i - 1)
|
||||
} else {
|
||||
OHLCCents::default()
|
||||
});
|
||||
}
|
||||
|
||||
let mut ohlc = if di.unwrap_to_usize() + 100 >= this.len() {
|
||||
fetcher.get_date(d).unwrap_or_else(|_| get_prev())
|
||||
} else {
|
||||
get_prev()
|
||||
};
|
||||
|
||||
if let Some(prev) = di.decremented() {
|
||||
let prev_open = *this
|
||||
.get_or_read(prev, &this.mmap().load())
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.close;
|
||||
let ohlc = if di.unwrap_to_usize() + 100 >= this.len()
|
||||
&& let Ok(mut ohlc) = fetcher.get_date(d)
|
||||
{
|
||||
let prev_open = *prev.as_ref().unwrap().close;
|
||||
*ohlc.open = prev_open;
|
||||
*ohlc.high = (*ohlc.high).max(prev_open);
|
||||
*ohlc.low = (*ohlc.low).min(prev_open);
|
||||
}
|
||||
ohlc
|
||||
} else {
|
||||
prev.clone().unwrap()
|
||||
};
|
||||
|
||||
prev.replace(ohlc.clone());
|
||||
|
||||
(di, ohlc)
|
||||
},
|
||||
exit,
|
||||
|
||||
@@ -498,9 +498,9 @@ impl Vecs {
|
||||
let dateindex_to_first_height = &indexes.dateindex_to_first_height;
|
||||
let dateindex_to_height_count = &indexes.dateindex_to_height_count;
|
||||
|
||||
let outputindex_to_value_mmap = outputindex_to_value.mmap().load();
|
||||
let outputindex_to_outputtype_mmap = outputindex_to_outputtype.mmap().load();
|
||||
let outputindex_to_typeindex_mmap = outputindex_to_typeindex.mmap().load();
|
||||
let outputindex_to_value_mmap = outputindex_to_value.create_mmap()?;
|
||||
let outputindex_to_outputtype_mmap = outputindex_to_outputtype.create_mmap()?;
|
||||
let outputindex_to_typeindex_mmap = outputindex_to_typeindex.create_mmap()?;
|
||||
|
||||
let mut inputindex_to_outputindex_iter = inputindex_to_outputindex.into_iter();
|
||||
let mut height_to_first_outputindex_iter = height_to_first_outputindex.into_iter();
|
||||
|
||||
@@ -7,7 +7,7 @@ pub fn setrlimit() -> io::Result<()> {
|
||||
|
||||
rlimit::setrlimit(
|
||||
Resource::NOFILE,
|
||||
no_file_limit.0.max(250_000),
|
||||
no_file_limit.0.max(10_000),
|
||||
no_file_limit.1,
|
||||
)?;
|
||||
|
||||
|
||||
+103
-27
@@ -15,7 +15,7 @@ use bitcoin::{Transaction, TxIn, TxOut};
|
||||
use brk_exit::Exit;
|
||||
use brk_parser::Parser;
|
||||
use brk_store::AnyStore;
|
||||
use brk_vec::{AnyVec, VecIterator};
|
||||
use brk_vec::{AnyVec, Mmap, VecIterator};
|
||||
use color_eyre::eyre::{ContextCompat, eyre};
|
||||
use log::{error, info};
|
||||
use rayon::prelude::*;
|
||||
@@ -40,6 +40,7 @@ pub struct Indexer {
|
||||
impl Indexer {
|
||||
pub fn forced_import(outputs_dir: &Path) -> color_eyre::Result<Self> {
|
||||
setrlimit()?;
|
||||
|
||||
Ok(Self {
|
||||
vecs: Vecs::forced_import(&outputs_dir.join("vecs/indexed"), VERSION + Version::ZERO)?,
|
||||
stores: Stores::forced_import(&outputs_dir.join("stores"), VERSION + Version::ZERO)?,
|
||||
@@ -88,9 +89,9 @@ impl Indexer {
|
||||
height: Height,
|
||||
rem: bool,
|
||||
exit: &Exit|
|
||||
-> color_eyre::Result<()> {
|
||||
-> color_eyre::Result<bool> {
|
||||
if height == 0 || (height % SNAPSHOT_BLOCK_RANGE != 0) != rem || exit.triggered() {
|
||||
return Ok(());
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
info!("Exporting...");
|
||||
@@ -98,15 +99,88 @@ impl Indexer {
|
||||
stores.commit(height)?;
|
||||
vecs.flush(height)?;
|
||||
exit.release();
|
||||
Ok(())
|
||||
Ok(true)
|
||||
};
|
||||
|
||||
let mut txindex_to_first_outputindex_mmap_opt = None;
|
||||
let mut p2pk65addressindex_to_p2pk65bytes_mmap_opt = None;
|
||||
let mut p2pk33addressindex_to_p2pk33bytes_mmap_opt = None;
|
||||
let mut p2pkhaddressindex_to_p2pkhbytes_mmap_opt = None;
|
||||
let mut p2shaddressindex_to_p2shbytes_mmap_opt = None;
|
||||
let mut p2wpkhaddressindex_to_p2wpkhbytes_mmap_opt = None;
|
||||
let mut p2wshaddressindex_to_p2wshbytes_mmap_opt = None;
|
||||
let mut p2traddressindex_to_p2trbytes_mmap_opt = None;
|
||||
let mut p2aaddressindex_to_p2abytes_mmap_opt = None;
|
||||
|
||||
let reset_mmaps_options =
|
||||
|vecs: &mut Vecs,
|
||||
txindex_to_first_outputindex_mmap_opt: &mut Option<Mmap>,
|
||||
p2pk65addressindex_to_p2pk65bytes_mmap_opt: &mut Option<Mmap>,
|
||||
p2pk33addressindex_to_p2pk33bytes_mmap_opt: &mut Option<Mmap>,
|
||||
p2pkhaddressindex_to_p2pkhbytes_mmap_opt: &mut Option<Mmap>,
|
||||
p2shaddressindex_to_p2shbytes_mmap_opt: &mut Option<Mmap>,
|
||||
p2wpkhaddressindex_to_p2wpkhbytes_mmap_opt: &mut Option<Mmap>,
|
||||
p2wshaddressindex_to_p2wshbytes_mmap_opt: &mut Option<Mmap>,
|
||||
p2traddressindex_to_p2trbytes_mmap_opt: &mut Option<Mmap>,
|
||||
p2aaddressindex_to_p2abytes_mmap_opt: &mut Option<Mmap>| {
|
||||
txindex_to_first_outputindex_mmap_opt
|
||||
.replace(vecs.txindex_to_first_outputindex.create_mmap().unwrap());
|
||||
p2pk65addressindex_to_p2pk65bytes_mmap_opt.replace(
|
||||
vecs.p2pk65addressindex_to_p2pk65bytes
|
||||
.create_mmap()
|
||||
.unwrap(),
|
||||
);
|
||||
p2pk33addressindex_to_p2pk33bytes_mmap_opt.replace(
|
||||
vecs.p2pk33addressindex_to_p2pk33bytes
|
||||
.create_mmap()
|
||||
.unwrap(),
|
||||
);
|
||||
p2pkhaddressindex_to_p2pkhbytes_mmap_opt
|
||||
.replace(vecs.p2pkhaddressindex_to_p2pkhbytes.create_mmap().unwrap());
|
||||
p2shaddressindex_to_p2shbytes_mmap_opt
|
||||
.replace(vecs.p2shaddressindex_to_p2shbytes.create_mmap().unwrap());
|
||||
p2wpkhaddressindex_to_p2wpkhbytes_mmap_opt.replace(
|
||||
vecs.p2wpkhaddressindex_to_p2wpkhbytes
|
||||
.create_mmap()
|
||||
.unwrap(),
|
||||
);
|
||||
p2wshaddressindex_to_p2wshbytes_mmap_opt
|
||||
.replace(vecs.p2wshaddressindex_to_p2wshbytes.create_mmap().unwrap());
|
||||
p2traddressindex_to_p2trbytes_mmap_opt
|
||||
.replace(vecs.p2traddressindex_to_p2trbytes.create_mmap().unwrap());
|
||||
p2aaddressindex_to_p2abytes_mmap_opt
|
||||
.replace(vecs.p2aaddressindex_to_p2abytes.create_mmap().unwrap());
|
||||
};
|
||||
|
||||
reset_mmaps_options(
|
||||
vecs,
|
||||
&mut txindex_to_first_outputindex_mmap_opt,
|
||||
&mut p2pk65addressindex_to_p2pk65bytes_mmap_opt,
|
||||
&mut p2pk33addressindex_to_p2pk33bytes_mmap_opt,
|
||||
&mut p2pkhaddressindex_to_p2pkhbytes_mmap_opt,
|
||||
&mut p2shaddressindex_to_p2shbytes_mmap_opt,
|
||||
&mut p2wpkhaddressindex_to_p2wpkhbytes_mmap_opt,
|
||||
&mut p2wshaddressindex_to_p2wshbytes_mmap_opt,
|
||||
&mut p2traddressindex_to_p2trbytes_mmap_opt,
|
||||
&mut p2aaddressindex_to_p2abytes_mmap_opt,
|
||||
);
|
||||
|
||||
parser.parse(start, end).iter().try_for_each(
|
||||
|(height, block, blockhash)| -> color_eyre::Result<()> {
|
||||
info!("Indexing block {height}...");
|
||||
|
||||
idxs.height = height;
|
||||
|
||||
let txindex_to_first_outputindex_mmap = txindex_to_first_outputindex_mmap_opt.as_ref().unwrap();
|
||||
let p2pk65addressindex_to_p2pk65bytes_mmap = p2pk65addressindex_to_p2pk65bytes_mmap_opt.as_ref().unwrap();
|
||||
let p2pk33addressindex_to_p2pk33bytes_mmap = p2pk33addressindex_to_p2pk33bytes_mmap_opt.as_ref().unwrap();
|
||||
let p2pkhaddressindex_to_p2pkhbytes_mmap = p2pkhaddressindex_to_p2pkhbytes_mmap_opt.as_ref().unwrap();
|
||||
let p2shaddressindex_to_p2shbytes_mmap = p2shaddressindex_to_p2shbytes_mmap_opt.as_ref().unwrap();
|
||||
let p2wpkhaddressindex_to_p2wpkhbytes_mmap = p2wpkhaddressindex_to_p2wpkhbytes_mmap_opt.as_ref().unwrap();
|
||||
let p2wshaddressindex_to_p2wshbytes_mmap = p2wshaddressindex_to_p2wshbytes_mmap_opt.as_ref().unwrap();
|
||||
let p2traddressindex_to_p2trbytes_mmap = p2traddressindex_to_p2trbytes_mmap_opt.as_ref().unwrap();
|
||||
let p2aaddressindex_to_p2abytes_mmap = p2aaddressindex_to_p2abytes_mmap_opt.as_ref().unwrap();
|
||||
|
||||
// Used to check rapidhash collisions
|
||||
let check_collisions = check_collisions && height > Height::new(COLLISIONS_CHECKED_UP_TO);
|
||||
|
||||
@@ -166,9 +240,6 @@ impl Indexer {
|
||||
});
|
||||
|
||||
let input_source_vec_handle = scope.spawn(|| {
|
||||
let txindex_to_first_outputindex_mmap = vecs
|
||||
.txindex_to_first_outputindex.mmap().load();
|
||||
|
||||
let inputs = block
|
||||
.txdata
|
||||
.iter()
|
||||
@@ -211,7 +282,7 @@ impl Indexer {
|
||||
|
||||
let vout = Vout::from(outpoint.vout);
|
||||
|
||||
let outputindex = vecs.txindex_to_first_outputindex.get_or_read(prev_txindex, &txindex_to_first_outputindex_mmap)?
|
||||
let outputindex = vecs.txindex_to_first_outputindex.get_or_read(prev_txindex, txindex_to_first_outputindex_mmap)?
|
||||
.context("Expect outputindex to not be none")
|
||||
.inspect_err(|_| {
|
||||
dbg!(outpoint.txid, prev_txindex, vout);
|
||||
@@ -240,16 +311,6 @@ impl Indexer {
|
||||
})
|
||||
});
|
||||
|
||||
let p2pk65addressindex_to_p2pk65bytes_mmap = vecs
|
||||
.p2pk65addressindex_to_p2pk65bytes.mmap().load();
|
||||
let p2pk33addressindex_to_p2pk33bytes_mmap = vecs.p2pk33addressindex_to_p2pk33bytes.mmap().load();
|
||||
let p2pkhaddressindex_to_p2pkhbytes_mmap = vecs.p2pkhaddressindex_to_p2pkhbytes.mmap().load();
|
||||
let p2shaddressindex_to_p2shbytes_mmap = vecs.p2shaddressindex_to_p2shbytes.mmap().load();
|
||||
let p2wpkhaddressindex_to_p2wpkhbytes_mmap = vecs.p2wpkhaddressindex_to_p2wpkhbytes.mmap().load();
|
||||
let p2wshaddressindex_to_p2wshbytes_mmap = vecs.p2wshaddressindex_to_p2wshbytes.mmap().load();
|
||||
let p2traddressindex_to_p2trbytes_mmap = vecs.p2traddressindex_to_p2trbytes.mmap().load();
|
||||
let p2aaddressindex_to_p2abytes_mmap = vecs.p2aaddressindex_to_p2abytes.mmap().load();
|
||||
|
||||
let outputs = block
|
||||
.txdata
|
||||
.iter()
|
||||
@@ -307,35 +368,35 @@ impl Indexer {
|
||||
let prev_addressbytes_opt = match outputtype {
|
||||
OutputType::P2PK65 => vecs
|
||||
.p2pk65addressindex_to_p2pk65bytes
|
||||
.get_or_read(typeindex.into(), &p2pk65addressindex_to_p2pk65bytes_mmap)?
|
||||
.get_or_read(typeindex.into(), p2pk65addressindex_to_p2pk65bytes_mmap)?
|
||||
.map(|v| AddressBytes::from(v.into_owned())),
|
||||
OutputType::P2PK33 => vecs
|
||||
.p2pk33addressindex_to_p2pk33bytes
|
||||
.get_or_read(typeindex.into(), &p2pk33addressindex_to_p2pk33bytes_mmap)?
|
||||
.get_or_read(typeindex.into(), p2pk33addressindex_to_p2pk33bytes_mmap)?
|
||||
.map(|v| AddressBytes::from(v.into_owned())),
|
||||
OutputType::P2PKH => vecs
|
||||
.p2pkhaddressindex_to_p2pkhbytes
|
||||
.get_or_read(typeindex.into(), &p2pkhaddressindex_to_p2pkhbytes_mmap)?
|
||||
.get_or_read(typeindex.into(), p2pkhaddressindex_to_p2pkhbytes_mmap)?
|
||||
.map(|v| AddressBytes::from(v.into_owned())),
|
||||
OutputType::P2SH => vecs
|
||||
.p2shaddressindex_to_p2shbytes
|
||||
.get_or_read(typeindex.into(), &p2shaddressindex_to_p2shbytes_mmap)?
|
||||
.get_or_read(typeindex.into(), p2shaddressindex_to_p2shbytes_mmap)?
|
||||
.map(|v| AddressBytes::from(v.into_owned())),
|
||||
OutputType::P2WPKH => vecs
|
||||
.p2wpkhaddressindex_to_p2wpkhbytes
|
||||
.get_or_read(typeindex.into(), &p2wpkhaddressindex_to_p2wpkhbytes_mmap)?
|
||||
.get_or_read(typeindex.into(), p2wpkhaddressindex_to_p2wpkhbytes_mmap)?
|
||||
.map(|v| AddressBytes::from(v.into_owned())),
|
||||
OutputType::P2WSH => vecs
|
||||
.p2wshaddressindex_to_p2wshbytes
|
||||
.get_or_read(typeindex.into(), &p2wshaddressindex_to_p2wshbytes_mmap)?
|
||||
.get_or_read(typeindex.into(), p2wshaddressindex_to_p2wshbytes_mmap)?
|
||||
.map(|v| AddressBytes::from(v.into_owned())),
|
||||
OutputType::P2TR => vecs
|
||||
.p2traddressindex_to_p2trbytes
|
||||
.get_or_read(typeindex.into(), &p2traddressindex_to_p2trbytes_mmap)?
|
||||
.get_or_read(typeindex.into(), p2traddressindex_to_p2trbytes_mmap)?
|
||||
.map(|v| AddressBytes::from(v.into_owned())),
|
||||
OutputType::P2A => vecs
|
||||
.p2aaddressindex_to_p2abytes
|
||||
.get_or_read(typeindex.into(), &p2aaddressindex_to_p2abytes_mmap)?
|
||||
.get_or_read(typeindex.into(), p2aaddressindex_to_p2abytes_mmap)?
|
||||
.map(|v| AddressBytes::from(v.into_owned())),
|
||||
OutputType::Empty | OutputType::OpReturn | OutputType::P2MS | OutputType::Unknown => {
|
||||
unreachable!()
|
||||
@@ -677,7 +738,22 @@ impl Indexer {
|
||||
idxs.inputindex += InputIndex::from(inputs_len);
|
||||
idxs.outputindex += OutputIndex::from(outputs_len);
|
||||
|
||||
export_if_needed(stores, vecs, height, false, exit)?;
|
||||
let exported = export_if_needed(stores, vecs, height, false, exit)?;
|
||||
|
||||
if exported {
|
||||
reset_mmaps_options(
|
||||
vecs,
|
||||
&mut txindex_to_first_outputindex_mmap_opt,
|
||||
&mut p2pk65addressindex_to_p2pk65bytes_mmap_opt,
|
||||
&mut p2pk33addressindex_to_p2pk33bytes_mmap_opt,
|
||||
&mut p2pkhaddressindex_to_p2pkhbytes_mmap_opt,
|
||||
&mut p2shaddressindex_to_p2shbytes_mmap_opt,
|
||||
&mut p2wpkhaddressindex_to_p2wpkhbytes_mmap_opt,
|
||||
&mut p2wshaddressindex_to_p2wshbytes_mmap_opt,
|
||||
&mut p2traddressindex_to_p2trbytes_mmap_opt,
|
||||
&mut p2aaddressindex_to_p2abytes_mmap_opt,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
@@ -72,7 +72,7 @@ impl Stores {
|
||||
path,
|
||||
"p2aaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
Some(None),
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
let p2pk33addressindex_with_outputindex = scope.spawn(|| {
|
||||
@@ -81,7 +81,7 @@ impl Stores {
|
||||
path,
|
||||
"p2pk33addressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
Some(None),
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
let p2pk65addressindex_with_outputindex = scope.spawn(|| {
|
||||
@@ -90,7 +90,7 @@ impl Stores {
|
||||
path,
|
||||
"p2pk65addressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
Some(None),
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
let p2pkhaddressindex_with_outputindex = scope.spawn(|| {
|
||||
@@ -99,7 +99,7 @@ impl Stores {
|
||||
path,
|
||||
"p2pkhaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
Some(None),
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
let p2shaddressindex_with_outputindex = scope.spawn(|| {
|
||||
@@ -108,7 +108,7 @@ impl Stores {
|
||||
path,
|
||||
"p2shaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
Some(None),
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
let p2traddressindex_with_outputindex = scope.spawn(|| {
|
||||
@@ -117,7 +117,7 @@ impl Stores {
|
||||
path,
|
||||
"p2traddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
Some(None),
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
let p2wpkhaddressindex_with_outputindex = scope.spawn(|| {
|
||||
@@ -126,7 +126,7 @@ impl Stores {
|
||||
path,
|
||||
"p2wpkhaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
Some(None),
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
let p2wshaddressindex_with_outputindex = scope.spawn(|| {
|
||||
@@ -135,7 +135,7 @@ impl Stores {
|
||||
path,
|
||||
"p2wshaddressindex_with_outputindex",
|
||||
version + VERSION + Version::ZERO,
|
||||
Some(None),
|
||||
Some(false),
|
||||
)
|
||||
});
|
||||
|
||||
|
||||
@@ -47,11 +47,3 @@ Verify that it has access to BRK's tools.
|
||||
Optionally and highly recommended, giving it unsupervised access gives a more fluid experience and prevents possible issues and errors.
|
||||
|
||||

|
||||
|
||||
#### Results
|
||||
|
||||
Some examples of dashboard and documents generated by Claude using BRK's tools:
|
||||
|
||||
- [Document](https://claude.ai/public/artifacts/71194d29-f965-417c-ba09-fdf0e4ecb1d5)
|
||||
- [Dashboard](https://claude.ai/public/artifacts/beef143f-399a-4ed4-b8bf-c986b776de42)
|
||||
- [Dashboard2](https://claude.ai/public/artifacts/5430ae49-bb3d-4fc1-ab24-f1e33deb40dc)
|
||||
|
||||
+16
-19
@@ -34,11 +34,9 @@ pub struct Store<Key, Value> {
|
||||
rtx: ReadTransaction,
|
||||
puts: BTreeMap<Key, Value>,
|
||||
dels: BTreeSet<Key>,
|
||||
bloom_filter_bits: Option<Option<u8>>,
|
||||
bloom_filters: Option<bool>,
|
||||
}
|
||||
|
||||
/// Use default if will read
|
||||
const DEFAULT_BLOOM_FILTER_BITS: Option<u8> = Some(5);
|
||||
// const CHECK_COLLISIONS: bool = true;
|
||||
const MAJOR_FJALL_VERSION: Version = Version::TWO;
|
||||
|
||||
@@ -59,7 +57,7 @@ where
|
||||
path: &Path,
|
||||
name: &str,
|
||||
version: Version,
|
||||
bloom_filter_bits: Option<Option<u8>>,
|
||||
bloom_filters: Option<bool>,
|
||||
) -> Result<Self> {
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
@@ -68,7 +66,7 @@ where
|
||||
&path.join(format!("meta/{name}")),
|
||||
MAJOR_FJALL_VERSION + version,
|
||||
|| {
|
||||
Self::open_partition_handle(keyspace, name, bloom_filter_bits).inspect_err(|e| {
|
||||
Self::open_partition_handle(keyspace, name, bloom_filters).inspect_err(|e| {
|
||||
eprintln!("{e}");
|
||||
eprintln!("Delete {path:?} and try again");
|
||||
})
|
||||
@@ -85,7 +83,7 @@ where
|
||||
rtx,
|
||||
puts: BTreeMap::new(),
|
||||
dels: BTreeSet::new(),
|
||||
bloom_filter_bits,
|
||||
bloom_filters,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -180,17 +178,17 @@ where
|
||||
fn open_partition_handle(
|
||||
keyspace: &TransactionalKeyspace,
|
||||
name: &str,
|
||||
bloom_filter_bits: Option<Option<u8>>,
|
||||
bloom_filters: Option<bool>,
|
||||
) -> Result<TransactionalPartitionHandle> {
|
||||
keyspace
|
||||
.open_partition(
|
||||
name,
|
||||
PartitionCreateOptions::default()
|
||||
.bloom_filter_bits(bloom_filter_bits.unwrap_or(DEFAULT_BLOOM_FILTER_BITS))
|
||||
.max_memtable_size(8 * 1024 * 1024)
|
||||
.manual_journal_persist(true),
|
||||
)
|
||||
.map_err(|e| e.into())
|
||||
let mut options = PartitionCreateOptions::default()
|
||||
.max_memtable_size(8 * 1024 * 1024)
|
||||
.manual_journal_persist(true);
|
||||
|
||||
if bloom_filters.is_some_and(|b| !b) {
|
||||
options = options.bloom_filter_bits(None);
|
||||
}
|
||||
|
||||
keyspace.open_partition(name, options).map_err(|e| e.into())
|
||||
}
|
||||
|
||||
pub fn commit_(
|
||||
@@ -272,8 +270,7 @@ where
|
||||
|
||||
self.meta.reset();
|
||||
|
||||
let partition =
|
||||
Self::open_partition_handle(&self.keyspace, self.name, self.bloom_filter_bits)?;
|
||||
let partition = Self::open_partition_handle(&self.keyspace, self.name, self.bloom_filters)?;
|
||||
|
||||
self.partition.replace(partition);
|
||||
|
||||
@@ -314,7 +311,7 @@ where
|
||||
rtx: self.keyspace.read_tx(),
|
||||
puts: self.puts.clone(),
|
||||
dels: self.dels.clone(),
|
||||
bloom_filter_bits: self.bloom_filter_bits,
|
||||
bloom_filters: self.bloom_filters,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ brk_exit = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
clap_derive = { workspace = true }
|
||||
log = { workspace = true }
|
||||
memmap2 = "0.9.5"
|
||||
memmap2 = "0.9.7"
|
||||
rayon = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::{DateIndex, Height, Version};
|
||||
use brk_core::{DateIndex, Height, Printable, Version};
|
||||
use brk_vec::{AnyVec, CollectableVec, Format, GenericStoredVec, StoredVec, VecIterator};
|
||||
|
||||
type I = DateIndex;
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
type VEC = StoredVec<DateIndex, u32>;
|
||||
type VEC = StoredVec<I, u32>;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let _ = fs::remove_dir_all("./vec");
|
||||
let _ = fs::remove_file("./vec");
|
||||
|
||||
let version = Version::TWO;
|
||||
let format = Format::Compressed;
|
||||
let format = Format::Raw;
|
||||
|
||||
{
|
||||
let mut vec: VEC = StoredVec::forced_import(Path::new("."), "vec", version, format)?;
|
||||
@@ -21,6 +23,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let mut iter = vec.into_iter();
|
||||
dbg!(iter.get(0.into()));
|
||||
dbg!(iter.get(1.into()));
|
||||
dbg!(iter.get(2.into()));
|
||||
dbg!(iter.get(20.into()));
|
||||
dbg!(iter.get(21.into()));
|
||||
|
||||
@@ -38,6 +42,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
dbg!(iter.get(0.into()));
|
||||
dbg!(iter.get(1.into()));
|
||||
dbg!(iter.get(2.into()));
|
||||
dbg!(iter.get(3.into()));
|
||||
dbg!(iter.get(4.into()));
|
||||
dbg!(iter.get(5.into()));
|
||||
dbg!(iter.get(20.into()));
|
||||
dbg!(iter.get(20.into()));
|
||||
dbg!(iter.get(0.into()));
|
||||
|
||||
@@ -7,7 +7,6 @@ use std::{
|
||||
|
||||
use arc_swap::ArcSwap;
|
||||
use brk_core::{Error, Height, Result, Version};
|
||||
use memmap2::Mmap;
|
||||
use zerocopy::{FromBytes, IntoBytes};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
@@ -31,8 +30,12 @@ impl Header {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn import_and_verify(mmap: &Mmap, vec_version: Version, format: Format) -> Result<Self> {
|
||||
let inner = HeaderInner::import_and_verify(mmap, vec_version, format)?;
|
||||
pub fn import_and_verify(
|
||||
file: &mut File,
|
||||
vec_version: Version,
|
||||
format: Format,
|
||||
) -> Result<Self> {
|
||||
let inner = HeaderInner::import_and_verify(file, vec_version, format)?;
|
||||
Ok(Self {
|
||||
inner: Arc::new(ArcSwap::from_pointee(inner)),
|
||||
modified: false,
|
||||
@@ -100,7 +103,6 @@ impl HeaderInner {
|
||||
compressed: ZeroCopyBool::from(format),
|
||||
};
|
||||
header.write(file)?;
|
||||
// dbg!(file.bytes().map(|b| b.unwrap()).collect::<Vec<_>>());
|
||||
file.seek(SeekFrom::End(0))?;
|
||||
Ok(header)
|
||||
}
|
||||
@@ -109,13 +111,22 @@ impl HeaderInner {
|
||||
file.write_all_at(self.as_bytes(), 0)
|
||||
}
|
||||
|
||||
pub fn import_and_verify(mmap: &Mmap, vec_version: Version, format: Format) -> Result<Self> {
|
||||
if mmap.len() < HEADER_OFFSET {
|
||||
pub fn import_and_verify(
|
||||
file: &mut File,
|
||||
vec_version: Version,
|
||||
format: Format,
|
||||
) -> Result<Self> {
|
||||
let len = file.metadata()?.len();
|
||||
|
||||
if len < HEADER_OFFSET as u64 {
|
||||
return Err(Error::WrongLength);
|
||||
}
|
||||
// dbg!(mmap.len());
|
||||
let header = HeaderInner::read_from_bytes(&mmap[..HEADER_OFFSET])?;
|
||||
// dbg!(&header);
|
||||
|
||||
let mut buf = [0; HEADER_OFFSET];
|
||||
file.read_exact_at(&mut buf, 0)?;
|
||||
|
||||
let header = HeaderInner::read_from_bytes(&buf)?;
|
||||
|
||||
if header.header_version != HEADER_VERSION {
|
||||
return Err(Error::DifferentVersion {
|
||||
found: header.header_version,
|
||||
@@ -136,6 +147,7 @@ impl HeaderInner {
|
||||
{
|
||||
return Err(Error::DifferentCompressionMode);
|
||||
}
|
||||
|
||||
Ok(header)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,8 @@ use std::{
|
||||
fs::{File, OpenOptions},
|
||||
io::{self, Seek, SeekFrom, Write},
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use arc_swap::ArcSwap;
|
||||
use brk_core::Result;
|
||||
use memmap2::Mmap;
|
||||
|
||||
@@ -38,7 +36,7 @@ where
|
||||
}
|
||||
#[inline]
|
||||
fn get_or_read_(&self, index: usize, mmap: &Mmap) -> Result<Option<Cow<T>>> {
|
||||
let stored_len = self.stored_len_(mmap);
|
||||
let stored_len = self.stored_len();
|
||||
|
||||
if index >= stored_len {
|
||||
let pushed = self.pushed();
|
||||
@@ -61,10 +59,7 @@ where
|
||||
format!("{}_to_{}", I::to_string(), self.name())
|
||||
}
|
||||
|
||||
fn mmap(&self) -> &ArcSwap<Mmap>;
|
||||
|
||||
fn stored_len(&self) -> usize;
|
||||
fn stored_len_(&self, mmap: &Mmap) -> usize;
|
||||
|
||||
fn pushed(&self) -> &[T];
|
||||
#[inline]
|
||||
@@ -116,7 +111,7 @@ where
|
||||
|
||||
fn file_set_len(&mut self, file: &mut File, len: u64) -> Result<()> {
|
||||
Self::file_set_len_(file, len)?;
|
||||
self.update_mmap(file)
|
||||
Ok(())
|
||||
}
|
||||
fn file_set_len_(file: &mut File, len: u64) -> Result<()> {
|
||||
file.set_len(len)?;
|
||||
@@ -127,7 +122,7 @@ where
|
||||
fn file_write_all(&mut self, file: &mut File, buf: &[u8]) -> Result<()> {
|
||||
file.write_all(buf)?;
|
||||
file.flush()?;
|
||||
self.update_mmap(file)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn file_truncate_and_write_all(&mut self, file: &mut File, len: u64, buf: &[u8]) -> Result<()> {
|
||||
@@ -143,14 +138,10 @@ where
|
||||
self.file_truncate_and_write_all(&mut file, HEADER_OFFSET as u64, &[])
|
||||
}
|
||||
|
||||
fn new_mmap(file: &File) -> Result<Arc<Mmap>> {
|
||||
Ok(Arc::new(unsafe { Mmap::map(file)? }))
|
||||
}
|
||||
|
||||
fn update_mmap(&mut self, file: &File) -> Result<()> {
|
||||
let mmap = Self::new_mmap(file)?;
|
||||
self.mmap().store(mmap);
|
||||
Ok(())
|
||||
#[inline]
|
||||
fn create_mmap(&self) -> Result<Mmap> {
|
||||
let file = self.open_file()?;
|
||||
unsafe { Mmap::map(&file).map_err(|e| e.into()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -57,7 +57,7 @@ where
|
||||
}
|
||||
|
||||
pub fn import(parent: &Path, name: &str, version: Version) -> Result<Self> {
|
||||
let inner = RawVec::import(parent, name, version)?;
|
||||
let mut inner = RawVec::import(parent, name, version)?;
|
||||
|
||||
let pages_meta = {
|
||||
let path = inner
|
||||
@@ -66,12 +66,19 @@ where
|
||||
if inner.is_empty() {
|
||||
let _ = fs::remove_file(&path);
|
||||
}
|
||||
Arc::new(ArcSwap::new(Arc::new(CompressedPagesMetadata::read(
|
||||
&path,
|
||||
)?)))
|
||||
CompressedPagesMetadata::read(&path)?
|
||||
};
|
||||
|
||||
Ok(Self { inner, pages_meta })
|
||||
inner.set_stored_len(if let Some(last) = pages_meta.last() {
|
||||
(pages_meta.len() - 1) * Self::PER_PAGE + last.values_len as usize
|
||||
} else {
|
||||
0
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
inner,
|
||||
pages_meta: Arc::new(ArcSwap::new(Arc::new(pages_meta))),
|
||||
})
|
||||
}
|
||||
|
||||
fn decode_page(&self, page_index: usize, mmap: &Mmap) -> Result<Vec<T>> {
|
||||
@@ -130,14 +137,6 @@ where
|
||||
page_index * Self::PER_PAGE
|
||||
}
|
||||
|
||||
fn stored_len__(pages_meta: &Guard<Arc<CompressedPagesMetadata>>) -> usize {
|
||||
if let Some(last) = pages_meta.last() {
|
||||
(pages_meta.len() - 1) * Self::PER_PAGE + last.values_len as usize
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter(&self) -> CompressedVecIterator<'_, I, T> {
|
||||
self.into_iter()
|
||||
@@ -180,22 +179,13 @@ where
|
||||
self.inner.mut_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mmap(&self) -> &ArcSwap<Mmap> {
|
||||
self.inner.mmap()
|
||||
}
|
||||
|
||||
fn parent(&self) -> &Path {
|
||||
self.inner.parent()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn stored_len(&self) -> usize {
|
||||
Self::stored_len__(&self.pages_meta.load())
|
||||
}
|
||||
#[inline]
|
||||
fn stored_len_(&self, _: &Mmap) -> usize {
|
||||
self.stored_len()
|
||||
self.inner.stored_len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -223,6 +213,8 @@ where
|
||||
|
||||
let stored_len = self.stored_len();
|
||||
|
||||
let mut file = file_opt.unwrap_or(self.open_file()?);
|
||||
|
||||
let mut pages_meta = (**self.pages_meta.load()).clone();
|
||||
|
||||
let mut starting_page_index = pages_meta.len();
|
||||
@@ -236,16 +228,13 @@ where
|
||||
|
||||
let last_page_index = pages_meta.len() - 1;
|
||||
|
||||
values = Self::decode_page_(
|
||||
stored_len,
|
||||
last_page_index,
|
||||
&self.mmap().load(),
|
||||
&pages_meta,
|
||||
)
|
||||
.inspect_err(|_| {
|
||||
dbg!(last_page_index, &pages_meta);
|
||||
})
|
||||
.unwrap();
|
||||
let mmap = unsafe { Mmap::map(&file)? };
|
||||
|
||||
values = Self::decode_page_(stored_len, last_page_index, &mmap, &pages_meta)
|
||||
.inspect_err(|_| {
|
||||
dbg!(last_page_index, &pages_meta);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
truncate_at.replace(pages_meta.pop().unwrap().start);
|
||||
starting_page_index = last_page_index;
|
||||
@@ -287,8 +276,6 @@ where
|
||||
|
||||
pages_meta.write()?;
|
||||
|
||||
let mut file = file_opt.unwrap_or(self.open_file()?);
|
||||
|
||||
if let Some(truncate_at) = truncate_at {
|
||||
self.file_set_len(&mut file, truncate_at)?;
|
||||
}
|
||||
@@ -324,7 +311,11 @@ where
|
||||
|
||||
let page_index = Self::index_to_page_index(index);
|
||||
|
||||
let values = self.decode_page(page_index, &self.mmap().load())?;
|
||||
let mut file = self.open_file()?;
|
||||
|
||||
let mmap = unsafe { Mmap::map(&file)? };
|
||||
|
||||
let values = self.decode_page(page_index, &mmap)?;
|
||||
let mut buf = vec![];
|
||||
|
||||
let mut page = pages_meta.truncate(page_index).unwrap();
|
||||
@@ -348,8 +339,6 @@ where
|
||||
|
||||
self.pages_meta.store(Arc::new(pages_meta));
|
||||
|
||||
let mut file = self.open_file()?;
|
||||
|
||||
self.file_truncate_and_write_all(&mut file, len, &buf)?;
|
||||
|
||||
Ok(())
|
||||
@@ -399,7 +388,7 @@ impl<I, T> Clone for CompressedVec<I, T> {
|
||||
#[derive(Debug)]
|
||||
pub struct CompressedVecIterator<'a, I, T> {
|
||||
vec: &'a CompressedVec<I, T>,
|
||||
guard: Guard<Arc<Mmap>>,
|
||||
mmap: Mmap,
|
||||
decoded_page: Option<(usize, Vec<T>)>,
|
||||
// second_decoded_page?: Option<(usize, Vec<T>)>,
|
||||
pages_meta: Guard<Arc<CompressedPagesMetadata>>,
|
||||
@@ -445,7 +434,7 @@ where
|
||||
type Item = (I, Cow<'a, T>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mmap = &self.guard;
|
||||
let mmap = &self.mmap;
|
||||
let i = self.index;
|
||||
let stored_len = self.stored_len;
|
||||
|
||||
@@ -496,14 +485,15 @@ where
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
let pages_meta = self.pages_meta.load();
|
||||
let stored_len = CompressedVec::<I, T>::stored_len__(&pages_meta);
|
||||
let stored_len = self.stored_len();
|
||||
|
||||
CompressedVecIterator {
|
||||
vec: self,
|
||||
guard: self.mmap().load(),
|
||||
mmap: self.create_mmap().unwrap(),
|
||||
decoded_page: None,
|
||||
pages_meta,
|
||||
stored_len,
|
||||
index: 0,
|
||||
stored_len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use arc_swap::ArcSwap;
|
||||
use brk_core::{
|
||||
Bitcoin, CheckedSub, Close, Date, DateIndex, Dollars, Error, Result, Sats, StoredF32,
|
||||
StoredUsize, Version,
|
||||
@@ -108,10 +107,6 @@ where
|
||||
self.0.get_or_read(index, mmap)
|
||||
}
|
||||
|
||||
pub fn mmap(&self) -> &ArcSwap<Mmap> {
|
||||
self.0.mmap()
|
||||
}
|
||||
|
||||
pub fn inner_version(&self) -> Version {
|
||||
self.0.version()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::{borrow::Cow, cmp::Ordering, fmt::Debug, path::Path};
|
||||
|
||||
use arc_swap::ArcSwap;
|
||||
use brk_core::{Error, Height, Result, Version};
|
||||
|
||||
use crate::{
|
||||
@@ -78,8 +77,8 @@ where
|
||||
self.0.header()
|
||||
}
|
||||
|
||||
pub fn mmap(&self) -> &ArcSwap<Mmap> {
|
||||
self.0.mmap()
|
||||
pub fn create_mmap(&self) -> Result<Mmap> {
|
||||
self.0.create_mmap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
||||
@@ -5,10 +5,12 @@ use std::{
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
},
|
||||
};
|
||||
|
||||
use arc_swap::{ArcSwap, Guard};
|
||||
use brk_core::{Error, Result, Version};
|
||||
use memmap2::Mmap;
|
||||
use rayon::prelude::*;
|
||||
@@ -25,9 +27,9 @@ pub struct RawVec<I, T> {
|
||||
header: Header,
|
||||
parent: PathBuf,
|
||||
name: &'static str,
|
||||
// Consider Arc<ArcSwap<Option<Mmap>>> for dataraces when reorg ?
|
||||
mmap: Arc<ArcSwap<Mmap>>,
|
||||
pushed: Vec<T>,
|
||||
local_stored_len: Option<usize>,
|
||||
shared_stored_len: Arc<AtomicUsize>,
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
@@ -55,16 +57,18 @@ where
|
||||
|
||||
pub fn import(parent: &Path, name: &str, version: Version) -> Result<Self> {
|
||||
let path = Self::path_(parent, name);
|
||||
let (mmap, header) = match Self::open_file_(&path) {
|
||||
let (header, file) = match Self::open_file_(&path) {
|
||||
Ok(mut file) => {
|
||||
if file.metadata()?.len() == 0 {
|
||||
let header = Header::create_and_write(&mut file, version, Format::Raw)?;
|
||||
let mmap = Self::new_mmap(&file)?;
|
||||
(mmap, header)
|
||||
(
|
||||
Header::create_and_write(&mut file, version, Format::Raw)?,
|
||||
Some(file),
|
||||
)
|
||||
} else {
|
||||
let mmap = Self::new_mmap(&file)?;
|
||||
let header = Header::import_and_verify(&mmap, version, Format::Raw)?;
|
||||
(mmap, header)
|
||||
(
|
||||
Header::import_and_verify(&mut file, version, Format::Raw)?,
|
||||
Some(file),
|
||||
)
|
||||
}
|
||||
}
|
||||
Err(e) => match e.kind() {
|
||||
@@ -72,25 +76,36 @@ where
|
||||
fs::create_dir_all(Self::folder_(parent, name))?;
|
||||
let mut file = Self::open_file_(&path)?;
|
||||
let header = Header::create_and_write(&mut file, version, Format::Raw)?;
|
||||
let mmap = Self::new_mmap(&file)?;
|
||||
(mmap, header)
|
||||
(header, None)
|
||||
}
|
||||
_ => {
|
||||
return Err(e.into());
|
||||
}
|
||||
_ => return Err(e.into()),
|
||||
},
|
||||
};
|
||||
|
||||
let mmap = Arc::new(ArcSwap::new(mmap));
|
||||
let stored_len = if let Some(file) = file {
|
||||
(file.metadata()?.len() as usize - HEADER_OFFSET) / Self::SIZE_OF_T
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
mmap,
|
||||
header,
|
||||
name: Box::leak(Box::new(name.to_string())),
|
||||
parent: parent.to_owned(),
|
||||
pushed: vec![],
|
||||
local_stored_len: Some(stored_len),
|
||||
shared_stored_len: Arc::new(AtomicUsize::new(stored_len)),
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_stored_len(&mut self, len: usize) {
|
||||
self.local_stored_len.replace(len);
|
||||
self.shared_stored_len.store(len, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter(&self) -> RawVecIterator<'_, I, T> {
|
||||
self.into_iter()
|
||||
@@ -141,18 +156,10 @@ where
|
||||
&mut self.header
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mmap(&self) -> &ArcSwap<Mmap> {
|
||||
&self.mmap
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn stored_len(&self) -> usize {
|
||||
self.stored_len_(&self.mmap.load())
|
||||
}
|
||||
#[inline]
|
||||
fn stored_len_(&self, mmap: &Mmap) -> usize {
|
||||
(mmap.len() - HEADER_OFFSET) / Self::SIZE_OF_T
|
||||
self.local_stored_len
|
||||
.unwrap_or_else(|| self.shared_stored_len.load(Ordering::Relaxed))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -194,9 +201,14 @@ where
|
||||
};
|
||||
|
||||
let mut file = file_opt.unwrap_or(self.open_file()?);
|
||||
|
||||
self.file_write_all(&mut file, &bytes)?;
|
||||
|
||||
if let Some(local_stored_len) = self.local_stored_len.as_mut() {
|
||||
*local_stored_len += pushed_len;
|
||||
}
|
||||
self.shared_stored_len
|
||||
.fetch_add(pushed_len, Ordering::Relaxed);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -212,6 +224,8 @@ where
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.set_stored_len(index);
|
||||
|
||||
let len = index * Self::SIZE_OF_T + HEADER_OFFSET;
|
||||
|
||||
let mut file = self.open_file()?;
|
||||
@@ -221,6 +235,7 @@ where
|
||||
}
|
||||
|
||||
fn reset(&mut self) -> Result<()> {
|
||||
self.set_stored_len(0);
|
||||
self.reset_()
|
||||
}
|
||||
}
|
||||
@@ -262,9 +277,10 @@ impl<I, T> Clone for RawVec<I, T> {
|
||||
header: self.header.clone(),
|
||||
parent: self.parent.clone(),
|
||||
name: self.name,
|
||||
mmap: self.mmap.clone(),
|
||||
pushed: vec![],
|
||||
phantom: PhantomData,
|
||||
local_stored_len: None,
|
||||
shared_stored_len: self.shared_stored_len.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -272,7 +288,7 @@ impl<I, T> Clone for RawVec<I, T> {
|
||||
#[derive(Debug)]
|
||||
pub struct RawVecIterator<'a, I, T> {
|
||||
vec: &'a RawVec<I, T>,
|
||||
guard: Guard<Arc<Mmap>>,
|
||||
mmap: Mmap,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
@@ -305,12 +321,11 @@ where
|
||||
type Item = (I, Cow<'a, T>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mmap = &self.guard;
|
||||
let index = self.index;
|
||||
|
||||
let opt = self
|
||||
.vec
|
||||
.get_or_read_(index, mmap)
|
||||
.get_or_read_(index, &self.mmap)
|
||||
.unwrap()
|
||||
.map(|v| (I::from(index), v));
|
||||
|
||||
@@ -333,7 +348,7 @@ where
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
RawVecIterator {
|
||||
vec: self,
|
||||
guard: self.mmap.load(),
|
||||
mmap: self.create_mmap().unwrap(),
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use arc_swap::ArcSwap;
|
||||
use brk_core::{Result, Version};
|
||||
use memmap2::Mmap;
|
||||
|
||||
@@ -75,14 +74,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mmap(&self) -> &ArcSwap<Mmap> {
|
||||
match self {
|
||||
StoredVec::Raw(v) => v.mmap(),
|
||||
StoredVec::Compressed(v) => v.mmap(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn parent(&self) -> &Path {
|
||||
match self {
|
||||
@@ -98,13 +89,6 @@ where
|
||||
StoredVec::Compressed(v) => v.stored_len(),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn stored_len_(&self, mmap: &Mmap) -> usize {
|
||||
match self {
|
||||
StoredVec::Raw(v) => v.stored_len_(mmap),
|
||||
StoredVec::Compressed(v) => v.stored_len_(mmap),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pushed(&self) -> &[T] {
|
||||
|
||||
+224
-216
@@ -1227,78 +1227,82 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
name: legend,
|
||||
color,
|
||||
}),
|
||||
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,
|
||||
}),
|
||||
...(`${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} */ ({
|
||||
@@ -1312,150 +1316,154 @@ function createPartialOptions({ env, colors, 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,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}_ratio_zscore`,
|
||||
title: "All time",
|
||||
type: "Baseline",
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}_ratio_4y_zscore`,
|
||||
title: "4y",
|
||||
type: "Baseline",
|
||||
colors: [colors.yellow, colors.pink],
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}_ratio_1y_zscore`,
|
||||
title: "1y",
|
||||
type: "Baseline",
|
||||
colors: [colors.orange, colors.purple],
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
...(`${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,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}_ratio_zscore`,
|
||||
title: "All time",
|
||||
type: "Baseline",
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}_ratio_4y_zscore`,
|
||||
title: "4y",
|
||||
type: "Baseline",
|
||||
colors: [colors.yellow, colors.pink],
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}_ratio_1y_zscore`,
|
||||
title: "1y",
|
||||
type: "Baseline",
|
||||
colors: [colors.orange, colors.purple],
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user