mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-25 05:34:29 -07:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e3431c2fa3 | |||
| 5979b9771e | |||
| aa61832fb2 | |||
| 2ac6e982b1 | |||
| 3204ddcf07 | |||
| c87b1c133c | |||
| 9b275ecdae | |||
| d6fd7de361 | |||
| 49d66a133e | |||
| c559f26d0e | |||
| bbe9f1bad2 |
Generated
+15
-15
@@ -443,7 +443,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"brk_bundler",
|
||||
"brk_cli",
|
||||
@@ -463,7 +463,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_bundler"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"brk_rolldown",
|
||||
"log",
|
||||
@@ -474,7 +474,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_cli"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"bitcoincore-rpc",
|
||||
"brk_computer",
|
||||
@@ -499,7 +499,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_computer"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -520,7 +520,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_core"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitcoin",
|
||||
@@ -541,7 +541,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_exit"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"brk_logger",
|
||||
"ctrlc",
|
||||
@@ -550,7 +550,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_fetcher"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"brk_core",
|
||||
"brk_logger",
|
||||
@@ -563,7 +563,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_indexer"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -581,7 +581,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_logger"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"env_logger",
|
||||
@@ -591,7 +591,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_parser"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
@@ -606,7 +606,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_query"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"brk_computer",
|
||||
"brk_core",
|
||||
@@ -929,7 +929,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_server"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"bitcoincore-rpc",
|
||||
@@ -959,7 +959,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_state"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"brk_core",
|
||||
@@ -973,7 +973,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_store"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"brk_core",
|
||||
@@ -995,7 +995,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "brk_vec"
|
||||
version = "0.0.63"
|
||||
version = "0.0.66"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"brk_core",
|
||||
|
||||
+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.63"
|
||||
package.version = "0.0.66"
|
||||
package.homepage = "https://bitcoinresearchkit.org"
|
||||
package.repository = "https://github.com/bitcoinresearchkit/brk"
|
||||
|
||||
@@ -22,20 +22,20 @@ 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.63", path = "crates/brk_bundler" }
|
||||
brk_cli = { version = "0.0.63", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0.0.63", path = "crates/brk_computer" }
|
||||
brk_core = { version = "0.0.63", path = "crates/brk_core" }
|
||||
brk_exit = { version = "0.0.63", path = "crates/brk_exit" }
|
||||
brk_fetcher = { version = "0.0.63", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.0.63", path = "crates/brk_indexer" }
|
||||
brk_logger = { version = "0.0.63", path = "crates/brk_logger" }
|
||||
brk_parser = { version = "0.0.63", path = "crates/brk_parser" }
|
||||
brk_query = { version = "0.0.63", path = "crates/brk_query" }
|
||||
brk_server = { version = "0.0.63", path = "crates/brk_server" }
|
||||
brk_state = { version = "0.0.63", path = "crates/brk_state" }
|
||||
brk_store = { version = "0.0.63", path = "crates/brk_store" }
|
||||
brk_vec = { version = "0.0.63", path = "crates/brk_vec" }
|
||||
brk_bundler = { version = "0.0.66", path = "crates/brk_bundler" }
|
||||
brk_cli = { version = "0.0.66", path = "crates/brk_cli" }
|
||||
brk_computer = { version = "0.0.66", path = "crates/brk_computer" }
|
||||
brk_core = { version = "0.0.66", path = "crates/brk_core" }
|
||||
brk_exit = { version = "0.0.66", path = "crates/brk_exit" }
|
||||
brk_fetcher = { version = "0.0.66", path = "crates/brk_fetcher" }
|
||||
brk_indexer = { version = "0.0.66", path = "crates/brk_indexer" }
|
||||
brk_logger = { version = "0.0.66", path = "crates/brk_logger" }
|
||||
brk_parser = { version = "0.0.66", path = "crates/brk_parser" }
|
||||
brk_query = { version = "0.0.66", path = "crates/brk_query" }
|
||||
brk_server = { version = "0.0.66", path = "crates/brk_server" }
|
||||
brk_state = { version = "0.0.66", path = "crates/brk_state" }
|
||||
brk_store = { version = "0.0.66", path = "crates/brk_store" }
|
||||
brk_vec = { version = "0.0.66", path = "crates/brk_vec" }
|
||||
byteview = "=0.6.1"
|
||||
clap = { version = "4.5.40", features = ["string"] }
|
||||
clap_derive = "4.5.40"
|
||||
|
||||
@@ -52,7 +52,8 @@ pub async fn bundle(websites_path: &Path, source_folder: &str, watch: bool) -> i
|
||||
if let Some(start) = entry.find("main") {
|
||||
if let Some(end) = entry.find(".js") {
|
||||
let main_hashed = &entry[start..end];
|
||||
contents = contents.replace("/scripts/main.js", &format!("/scripts/{main_hashed}.js"));
|
||||
contents =
|
||||
contents.replace("/scripts/main.js", &format!("/scripts/{main_hashed}.js"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
A command line interface to interact with the full Bitcoin Research Kit. It's built on top of every other create and gives the possility to use BRK using the terminal instead of Rust.
|
||||
|
||||
It has 2 commandes for now (other than `help` and `version`) which are `run` and `query`. The former is used to run the processing (indexer + computer) and/or the server. The latter uses `brk_query` as its backend just like to server to be able to get datasets via the terminal instead of the API. Both commands are very costumizable by having all the parameters of their Rust counterparts ([`run`](https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_cli/src/run.rs#L91-L147), [`query`](https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_query/src/params.rs)).
|
||||
It has 2 commands (other than `help` and `version`) which are `run` and `query`. The former is used to run the processing (indexer + computer) and/or the server. The latter uses `brk_query` as its backend just like to server to be able to get datasets via the terminal instead of the API. Both commands are custumizable by supporting all the parameters of their Rust counterparts ([`run`](https://github.com/bitcoinresearchkit/brk/blob/c9c6b583338203b2b11bdf31e961b1c306f5d82b/crates/brk_cli/src/run.rs#L110-L191), and [`query`](https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_query/src/params.rs)).
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -54,13 +54,16 @@ To be determined
|
||||
- [Bitcoin](https://bitcoin.org/en/full-node)
|
||||
- [Rust](https://www.rust-lang.org/tools/install)
|
||||
- Unix based operating system (Mac OS or Linux)
|
||||
- Ubuntu users need to install `open-ssl` via `sudo apt install libssl-dev pkg-config`
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Ubuntu users need to install `open-ssl` via `sudo apt install libssl-dev pkg-config`
|
||||
|
||||
|
||||
## Download
|
||||
|
||||
### Binaries
|
||||
|
||||
You can find a pre-built binary for your operating system on the releases page ([link](https://github.com/bitcoinresearchkit/brk/releases/latest)).
|
||||
You can find a pre-built binary for your operating system in the [releases page](https://github.com/bitcoinresearchkit/brk/releases/latest).
|
||||
|
||||
### Cargo
|
||||
|
||||
@@ -84,8 +87,10 @@ cargo run -r
|
||||
|
||||
Run `brk -h` to view each available command and their respective description.
|
||||
|
||||
`-h` works also for commands, which mean that `brk run -h` will explain all the parameters of `brk run` for example.
|
||||
`-h` works also for commands, so `brk run -h` will enumerate all the parameters of `brk run`.
|
||||
|
||||
Every parameter set for `brk run` will be saved at `~/.brk/config.toml`, which will allow you to simply run `brk run` next time.
|
||||
> [!TIP]
|
||||
> Every parameter set for `brk run` will be saved at `~/.brk/config.toml`, which allows you to simply run `brk run` next time.
|
||||
|
||||
Then the easiest to let others access your server is to use `cloudflared` which will also cache requests. For more information go to: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
|
||||
|
||||
The easiest way to let others access your server is to use `cloudflared` which will also cache requests. For more information see [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) documentation.
|
||||
|
||||
@@ -0,0 +1,681 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use brk_core::{Bitcoin, CheckedSub, Dollars, StoredF64, Version};
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, Computation, Format, VecIterator};
|
||||
|
||||
use crate::vecs::{
|
||||
fetched,
|
||||
grouped::{ComputedRatioVecsFromDateIndex, ComputedValueVecsFromHeight},
|
||||
stateful, transactions,
|
||||
};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromHeight, StorableVecGeneatorOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
pub indexes_to_coinblocks_created: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_coinblocks_stored: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_liveliness: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_vaultedness: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_activity_to_vaultedness_ratio: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_vaulted_supply: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_active_supply: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_thermo_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_investor_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_vaulted_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_active_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_vaulted_price: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_vaulted_price_ratio: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_active_price: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_active_price_ratio: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_true_market_mean: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_true_market_mean_ratio: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_cointime_value_destroyed: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_cointime_value_created: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_cointime_value_stored: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_cointime_price: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_cointime_cap: ComputedVecsFromHeight<Dollars>,
|
||||
pub indexes_to_cointime_price_ratio: ComputedRatioVecsFromDateIndex,
|
||||
// pub indexes_to_thermo_cap_relative_to_investor_cap: ComputedValueVecsFromHeight,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(
|
||||
path: &Path,
|
||||
version: Version,
|
||||
_computation: Computation,
|
||||
format: Format,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let compute_dollars = fetched.is_some();
|
||||
|
||||
fs::create_dir_all(path)?;
|
||||
|
||||
Ok(Self {
|
||||
indexes_to_coinblocks_created: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"coinblocks_created",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_coinblocks_stored: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"coinblocks_stored",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_liveliness: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"liveliness",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaultedness: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"vaultedness",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_activity_to_vaultedness_ratio: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"activity_to_vaultedness_ratio",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaulted_supply: ComputedValueVecsFromHeight::forced_import(
|
||||
path,
|
||||
"vaulted_supply",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
indexes_to_active_supply: ComputedValueVecsFromHeight::forced_import(
|
||||
path,
|
||||
"active_supply",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
compute_dollars,
|
||||
)?,
|
||||
indexes_to_thermo_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"thermo_cap",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_investor_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"investor_cap",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaulted_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"vaulted_cap",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_active_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"active_cap",
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaulted_price: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"vaulted_price",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_vaulted_price_ratio: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"vaulted_price",
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_active_price: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"active_price",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_active_price_ratio: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"active_price",
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_true_market_mean: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"true_market_mean",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_true_market_mean_ratio: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"true_market_mean",
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_cointime_value_destroyed: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_value_destroyed",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_cointime_value_created: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_value_created",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_cointime_value_stored: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_value_stored",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_cointime_price: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_price",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_cointime_cap: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
"cointime_cap",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_cointime_price_ratio: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"cointime_price",
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
transactions: &transactions::Vecs,
|
||||
stateful: &stateful::Vecs,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
let circulating_supply = &stateful.utxos_vecs.all.1.height_to_supply;
|
||||
|
||||
self.indexes_to_coinblocks_created.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
circulating_supply,
|
||||
|(i, v, ..)| (i, StoredF64::from(Bitcoin::from(v))),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
let indexes_to_coinblocks_destroyed =
|
||||
&stateful.utxos_vecs.all.1.indexes_to_coinblocks_destroyed;
|
||||
|
||||
self.indexes_to_coinblocks_stored.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut coinblocks_destroyed_iter = indexes_to_coinblocks_destroyed
|
||||
.height
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_coinblocks_created.height.as_ref().unwrap(),
|
||||
|(i, created, ..)| {
|
||||
let destroyed = coinblocks_destroyed_iter.unwrap_get_inner(i);
|
||||
(i, created.checked_sub(destroyed).unwrap())
|
||||
},
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_liveliness.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
indexes_to_coinblocks_destroyed
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
self.indexes_to_coinblocks_created
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
let liveliness = &self.indexes_to_liveliness;
|
||||
|
||||
self.indexes_to_vaultedness.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
liveliness.height.as_ref().unwrap(),
|
||||
|(i, v, ..)| (i, StoredF64::from(1.0).checked_sub(v).unwrap()),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
let vaultedness = &self.indexes_to_vaultedness;
|
||||
|
||||
self.indexes_to_activity_to_vaultedness_ratio.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
liveliness.height.as_ref().unwrap(),
|
||||
vaultedness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_vaulted_supply.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
circulating_supply,
|
||||
vaultedness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_active_supply.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
circulating_supply,
|
||||
liveliness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
if let Some(fetched) = fetched {
|
||||
let realized_cap = stateful
|
||||
.utxos_vecs
|
||||
.all
|
||||
.1
|
||||
.height_to_realized_cap
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
|
||||
let realized_price = stateful
|
||||
.utxos_vecs
|
||||
.all
|
||||
.1
|
||||
.indexes_to_realized_price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.height
|
||||
.as_ref()
|
||||
.unwrap();
|
||||
|
||||
self.indexes_to_thermo_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
transactions
|
||||
.indexes_to_subsidy
|
||||
.dollars
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
|(i, v, ..)| (i, v),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_investor_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_subtract(
|
||||
starting_indexes.height,
|
||||
realized_cap,
|
||||
self.indexes_to_thermo_cap.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_vaulted_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
realized_cap,
|
||||
self.indexes_to_vaultedness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_active_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
realized_cap,
|
||||
self.indexes_to_liveliness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_vaulted_price.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
realized_price,
|
||||
self.indexes_to_vaultedness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_vaulted_price_ratio.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.indexes_to_vaulted_price.dateindex.unwrap_last()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_active_price.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
realized_price,
|
||||
self.indexes_to_liveliness.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_active_price_ratio.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.indexes_to_active_price.dateindex.unwrap_last()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_true_market_mean.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_investor_cap.height.as_ref().unwrap(),
|
||||
self.indexes_to_active_supply
|
||||
.bitcoin
|
||||
.height
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_true_market_mean_ratio.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.indexes_to_true_market_mean.dateindex.unwrap_last()),
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_value_destroyed.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
// TODO: Another example when the callback should be applied to each index, instead of to base then merging from more granular to less
|
||||
// The price taken won't be correct for time based indexes
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&fetched.chainindexes_to_close.height,
|
||||
indexes_to_coinblocks_destroyed.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_value_created.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&fetched.chainindexes_to_close.height,
|
||||
self.indexes_to_coinblocks_created.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_value_stored.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&fetched.chainindexes_to_close.height,
|
||||
self.indexes_to_coinblocks_stored.height.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_price.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_divide(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_cointime_value_destroyed
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
self.indexes_to_coinblocks_stored
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_multiply(
|
||||
starting_indexes.height,
|
||||
self.indexes_to_cointime_price.height.as_ref().unwrap(),
|
||||
circulating_supply,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cointime_price_ratio.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(self.indexes_to_cointime_price.dateindex.unwrap_last()),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.indexes_to_coinblocks_created.vecs(),
|
||||
self.indexes_to_coinblocks_stored.vecs(),
|
||||
self.indexes_to_liveliness.vecs(),
|
||||
self.indexes_to_vaultedness.vecs(),
|
||||
self.indexes_to_activity_to_vaultedness_ratio.vecs(),
|
||||
self.indexes_to_vaulted_supply.vecs(),
|
||||
self.indexes_to_active_supply.vecs(),
|
||||
self.indexes_to_thermo_cap.vecs(),
|
||||
self.indexes_to_investor_cap.vecs(),
|
||||
self.indexes_to_vaulted_cap.vecs(),
|
||||
self.indexes_to_active_cap.vecs(),
|
||||
self.indexes_to_vaulted_price.vecs(),
|
||||
self.indexes_to_vaulted_price_ratio.vecs(),
|
||||
self.indexes_to_active_price.vecs(),
|
||||
self.indexes_to_active_price_ratio.vecs(),
|
||||
self.indexes_to_true_market_mean.vecs(),
|
||||
self.indexes_to_true_market_mean_ratio.vecs(),
|
||||
self.indexes_to_cointime_price.vecs(),
|
||||
self.indexes_to_cointime_cap.vecs(),
|
||||
self.indexes_to_cointime_price_ratio.vecs(),
|
||||
self.indexes_to_cointime_value_destroyed.vecs(),
|
||||
self.indexes_to_cointime_value_created.vecs(),
|
||||
self.indexes_to_cointime_value_stored.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -130,7 +130,11 @@ where
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
path,
|
||||
&maybe_suffix("sum"),
|
||||
&(if !options.last {
|
||||
name.to_string()
|
||||
} else {
|
||||
maybe_suffix("sum")
|
||||
}),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
|
||||
@@ -24,8 +24,10 @@ pub struct ComputedRatioVecsFromDateIndex {
|
||||
pub ratio_1w_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_4y_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_1y_sma_momentum_oscillator: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_standard_deviation: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_4y_sd: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99_9: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99_5: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_p99: ComputedVecsFromDateIndex<StoredF32>,
|
||||
@@ -51,6 +53,7 @@ pub struct ComputedRatioVecsFromDateIndex {
|
||||
pub ratio_m2sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_m3sd_as_price: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub ratio_zscore: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub ratio_4y_zscore: ComputedVecsFromDateIndex<StoredF32>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -62,8 +65,9 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
compute_source: bool,
|
||||
version: Version,
|
||||
format: Format,
|
||||
options: StorableVecGeneatorOptions,
|
||||
) -> color_eyre::Result<Self> {
|
||||
let options = StorableVecGeneatorOptions::default().add_last();
|
||||
|
||||
Ok(Self {
|
||||
price: compute_source.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
@@ -116,6 +120,14 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_4y_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_4y_sma"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_1y_sma_momentum_oscillator: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_1y_sma_momentum_oscillator"),
|
||||
@@ -124,9 +136,17 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_standard_deviation: ComputedVecsFromDateIndex::forced_import(
|
||||
ratio_sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_standard_deviation"),
|
||||
&format!("{name}_ratio_sd"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_4y_sd: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_4y_sd"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
@@ -332,6 +352,14 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
ratio_4y_zscore: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("{name}_ratio_4y_zscore"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
options,
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -476,6 +504,22 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_4y_sma.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),
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_1y_sma_momentum_oscillator.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
@@ -528,6 +572,8 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
|
||||
let mut sma_iter = self.ratio_sma.dateindex.as_ref().unwrap().into_iter();
|
||||
|
||||
let mut _4y_sma_iter = self.ratio_4y_sma.dateindex.as_ref().unwrap().into_iter();
|
||||
|
||||
let nan = StoredF32::from(f32::NAN);
|
||||
self.ratio
|
||||
.dateindex
|
||||
@@ -566,7 +612,12 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_standard_deviation
|
||||
self.ratio_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, nan, exit)?;
|
||||
self.ratio_4y_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
@@ -645,12 +696,26 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
.sqrt(),
|
||||
);
|
||||
|
||||
self.ratio_standard_deviation
|
||||
self.ratio_sd
|
||||
.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::<f32>()
|
||||
/ (index.unwrap_to_usize() + 1) as f32)
|
||||
.sqrt(),
|
||||
);
|
||||
|
||||
self.ratio_4y_sd
|
||||
.dateindex
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.forced_push_at(index, _4y_sd, exit)?;
|
||||
|
||||
self.ratio_p1sd.dateindex.as_mut().unwrap().forced_push_at(
|
||||
index,
|
||||
avg + sd,
|
||||
@@ -726,7 +791,13 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
exit,
|
||||
None as Option<&EagerVec<_, _>>,
|
||||
)?;
|
||||
self.ratio_standard_deviation.compute_rest(
|
||||
self.ratio_sd.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
None as Option<&EagerVec<_, _>>,
|
||||
)?;
|
||||
self.ratio_4y_sd.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
@@ -1007,21 +1078,27 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
let mut sma_iter = self.ratio_sma.dateindex.as_ref().unwrap().into_iter();
|
||||
let mut sd_iter = self
|
||||
.ratio_standard_deviation
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.into_iter();
|
||||
vec.compute_transform(
|
||||
vec.compute_zscore(
|
||||
starting_indexes.dateindex,
|
||||
self.ratio.dateindex.as_ref().unwrap(),
|
||||
|(i, ratio, ..)| {
|
||||
let sma = sma_iter.unwrap_get_inner(i);
|
||||
let sd = sd_iter.unwrap_get_inner(i);
|
||||
(i, (ratio - sma) / sd)
|
||||
},
|
||||
self.ratio_sma.dateindex.as_ref().unwrap(),
|
||||
self.ratio_sd.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.ratio_4y_zscore.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.dateindex.as_ref().unwrap(),
|
||||
self.ratio_4y_sd.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
@@ -1032,7 +1109,8 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
|
||||
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<DateIndex, StoredF32>> {
|
||||
vec![
|
||||
self.ratio_standard_deviation.dateindex.as_mut().unwrap(),
|
||||
self.ratio_sd.dateindex.as_mut().unwrap(),
|
||||
self.ratio_4y_sd.dateindex.as_mut().unwrap(),
|
||||
self.ratio_p99_9.dateindex.as_mut().unwrap(),
|
||||
self.ratio_p99_5.dateindex.as_mut().unwrap(),
|
||||
self.ratio_p99.dateindex.as_mut().unwrap(),
|
||||
@@ -1056,8 +1134,10 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
self.ratio_1w_sma.vecs(),
|
||||
self.ratio_1m_sma.vecs(),
|
||||
self.ratio_1y_sma.vecs(),
|
||||
self.ratio_4y_sma.vecs(),
|
||||
self.ratio_1y_sma_momentum_oscillator.vecs(),
|
||||
self.ratio_standard_deviation.vecs(),
|
||||
self.ratio_sd.vecs(),
|
||||
self.ratio_4y_sd.vecs(),
|
||||
self.ratio_p99_9.vecs(),
|
||||
self.ratio_p99_5.vecs(),
|
||||
self.ratio_p99.vecs(),
|
||||
@@ -1083,6 +1163,7 @@ impl ComputedRatioVecsFromDateIndex {
|
||||
self.ratio_m2sd_as_price.vecs(),
|
||||
self.ratio_m3sd_as_price.vecs(),
|
||||
self.ratio_zscore.vecs(),
|
||||
self.ratio_4y_zscore.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
||||
@@ -36,11 +36,15 @@ pub struct Vecs {
|
||||
pub indexes_to_55d_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_89d_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_144d_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_200d_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_1y_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_2y_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_200w_sma: ComputedRatioVecsFromDateIndex,
|
||||
pub indexes_to_4y_sma: ComputedRatioVecsFromDateIndex,
|
||||
|
||||
pub indexes_to_200d_sma_x2_4: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub indexes_to_200d_sma_x0_8: ComputedVecsFromDateIndex<Dollars>,
|
||||
|
||||
pub price_1d_ago: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub price_1w_ago: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub price_1m_ago: ComputedVecsFromDateIndex<Dollars>,
|
||||
@@ -240,7 +244,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_8d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -248,7 +251,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_13d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -256,7 +258,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_21d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -264,7 +265,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_1m_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -272,7 +272,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_34d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -280,7 +279,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_55d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -288,7 +286,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_89d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -296,7 +293,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_144d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -304,7 +300,13 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_200d_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"200d_sma",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)?,
|
||||
indexes_to_1y_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -312,7 +314,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_2y_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -320,7 +321,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_200w_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -328,7 +328,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_4y_sma: ComputedRatioVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
@@ -336,7 +335,6 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
|
||||
_1d_returns: ComputedVecsFromDateIndex::forced_import(
|
||||
@@ -1215,6 +1213,23 @@ impl Vecs {
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
|
||||
indexes_to_200d_sma_x2_4: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"200d_sma_x2_4",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_200d_sma_x0_8: ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
"200d_sma_x0_8",
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1771,6 +1786,7 @@ impl Vecs {
|
||||
(&mut self.indexes_to_55d_sma, 55),
|
||||
(&mut self.indexes_to_89d_sma, 89),
|
||||
(&mut self.indexes_to_144d_sma, 144),
|
||||
(&mut self.indexes_to_200d_sma, 200),
|
||||
(&mut self.indexes_to_1y_sma, 365),
|
||||
(&mut self.indexes_to_2y_sma, 2 * 365),
|
||||
(&mut self.indexes_to_200w_sma, 200 * 7),
|
||||
@@ -1797,7 +1813,51 @@ impl Vecs {
|
||||
});
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
})?;
|
||||
|
||||
self.indexes_to_200d_sma_x0_8.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_200d_sma
|
||||
.price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
|(i, v, ..)| (i, v * 0.8),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_200d_sma_x2_4.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_200d_sma
|
||||
.price
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
|(i, v, ..)| (i, v * 2.4),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
@@ -1817,10 +1877,13 @@ impl Vecs {
|
||||
self.indexes_to_55d_sma.vecs(),
|
||||
self.indexes_to_89d_sma.vecs(),
|
||||
self.indexes_to_144d_sma.vecs(),
|
||||
self.indexes_to_200d_sma.vecs(),
|
||||
self.indexes_to_1y_sma.vecs(),
|
||||
self.indexes_to_2y_sma.vecs(),
|
||||
self.indexes_to_200w_sma.vecs(),
|
||||
self.indexes_to_4y_sma.vecs(),
|
||||
self.indexes_to_200d_sma_x0_8.vecs(),
|
||||
self.indexes_to_200d_sma_x2_4.vecs(),
|
||||
self.price_1d_ago.vecs(),
|
||||
self.price_1w_ago.vecs(),
|
||||
self.price_1m_ago.vecs(),
|
||||
|
||||
@@ -7,6 +7,7 @@ use brk_indexer::Indexer;
|
||||
use brk_vec::{AnyCollectableVec, Computation, Format};
|
||||
|
||||
pub mod blocks;
|
||||
pub mod cointime;
|
||||
pub mod constants;
|
||||
pub mod fetched;
|
||||
pub mod grouped;
|
||||
@@ -31,6 +32,7 @@ pub struct Vecs {
|
||||
pub transactions: transactions::Vecs,
|
||||
pub stateful: stateful::Vecs,
|
||||
pub fetched: Option<fetched::Vecs>,
|
||||
pub cointime: cointime::Vecs,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -112,6 +114,13 @@ impl Vecs {
|
||||
format,
|
||||
fetched.as_ref(),
|
||||
)?,
|
||||
cointime: cointime::Vecs::forced_import(
|
||||
path,
|
||||
version + VERSION + Version::ZERO,
|
||||
computation,
|
||||
format,
|
||||
fetched.as_ref(),
|
||||
)?,
|
||||
indexes,
|
||||
fetched,
|
||||
})
|
||||
@@ -125,7 +134,7 @@ impl Vecs {
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
info!("Computing indexes...");
|
||||
let starting_indexes = self.indexes.compute(indexer, starting_indexes, exit)?;
|
||||
let mut starting_indexes = self.indexes.compute(indexer, starting_indexes, exit)?;
|
||||
|
||||
info!("Computing constants...");
|
||||
self.constants
|
||||
@@ -178,7 +187,17 @@ impl Vecs {
|
||||
&self.transactions,
|
||||
self.fetched.as_ref(),
|
||||
&self.market,
|
||||
starting_indexes,
|
||||
&mut starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.cointime.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
self.fetched.as_ref(),
|
||||
&self.transactions,
|
||||
&self.stateful,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -194,6 +213,7 @@ impl Vecs {
|
||||
self.market.vecs(),
|
||||
self.transactions.vecs(),
|
||||
self.stateful.vecs(),
|
||||
self.cointime.vecs(),
|
||||
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.into_iter()
|
||||
|
||||
@@ -57,7 +57,7 @@ pub struct Vecs {
|
||||
pub indexes_to_coinblocks_destroyed: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_coindays_destroyed: ComputedVecsFromHeight<StoredF64>,
|
||||
pub dateindex_to_adjusted_spent_output_profit_ratio: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_realized_cap_30d_change: Option<EagerVec<DateIndex, Dollars>>,
|
||||
pub indexes_to_realized_cap_30d_change: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub dateindex_to_sell_side_risk_ratio: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub dateindex_to_spent_output_profit_ratio: Option<EagerVec<DateIndex, StoredF32>>,
|
||||
pub indexes_to_adjusted_value_created: Option<ComputedVecsFromHeight<Dollars>>,
|
||||
@@ -89,6 +89,10 @@ pub struct Vecs {
|
||||
Option<EagerVec<Height, StoredF32>>,
|
||||
pub indexes_to_net_unrealized_profit_and_loss_relative_to_market_cap:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_realized_profit_relative_to_realized_cap:
|
||||
Option<ComputedVecsFromHeight<StoredF32>>,
|
||||
pub indexes_to_realized_loss_relative_to_realized_cap:
|
||||
Option<ComputedVecsFromHeight<StoredF32>>,
|
||||
pub indexes_to_net_realized_profit_and_loss_relative_to_realized_cap:
|
||||
Option<ComputedVecsFromHeight<StoredF32>>,
|
||||
pub height_to_supply_even_value: Option<ComputedHeightValueVecs>,
|
||||
@@ -117,6 +121,12 @@ pub struct Vecs {
|
||||
Option<ComputedVecsFromDateIndex<StoredF64>>,
|
||||
pub indexes_to_supply_in_profit_relative_to_circulating_supply:
|
||||
Option<ComputedVecsFromDateIndex<StoredF64>>,
|
||||
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change:
|
||||
Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap:
|
||||
Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -412,7 +422,6 @@ impl Vecs {
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -432,7 +441,9 @@ impl Vecs {
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -452,7 +463,9 @@ impl Vecs {
|
||||
false,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -463,7 +476,7 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default().add_sum().add_cumulative(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -558,12 +571,14 @@ impl Vecs {
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
dateindex_to_realized_cap_30d_change: compute_dollars.then(|| {
|
||||
EagerVec::forced_import(
|
||||
indexes_to_realized_cap_30d_change: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&suffix("realized_cap_30d_change"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -574,7 +589,9 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default()
|
||||
.add_sum()
|
||||
.add_cumulative(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
@@ -686,15 +703,37 @@ impl Vecs {
|
||||
.unwrap()
|
||||
},
|
||||
),
|
||||
indexes_to_realized_profit_relative_to_realized_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("realized_profit_relative_to_realized_cap"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_realized_loss_relative_to_realized_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("realized_loss_relative_to_realized_cap"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_net_realized_profit_and_loss_relative_to_realized_cap: compute_dollars.then(
|
||||
|| {
|
||||
ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
&suffix("net_realized_profit_and_loss_relative_to_realized_cap"),
|
||||
true,
|
||||
version + VERSION + Version::ZERO,
|
||||
version + VERSION + Version::ONE,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last(),
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
)
|
||||
.unwrap()
|
||||
},
|
||||
@@ -893,7 +932,7 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::TWO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default().add_sum().add_cumulative(),
|
||||
)?,
|
||||
indexes_to_coindays_destroyed: ComputedVecsFromHeight::forced_import(
|
||||
path,
|
||||
@@ -901,8 +940,41 @@ impl Vecs {
|
||||
true,
|
||||
version + VERSION + Version::TWO,
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_sum(),
|
||||
StorableVecGeneatorOptions::default().add_sum().add_cumulative(),
|
||||
)?,
|
||||
indexes_to_cumulative_net_realized_profit_and_loss_30d_change: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change")),
|
||||
true,
|
||||
version + VERSION + Version::new(3),
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last()
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change_relative_to_realized_cap")),
|
||||
true,
|
||||
version + VERSION + Version::new(3),
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last()
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
path,
|
||||
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change_relative_to_market_cap")),
|
||||
true,
|
||||
version + VERSION + Version::new(3),
|
||||
format,
|
||||
StorableVecGeneatorOptions::default().add_last()
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1877,6 +1949,7 @@ impl Vecs {
|
||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
if let Some(v) = self
|
||||
@@ -2021,18 +2094,26 @@ impl Vecs {
|
||||
Some(self.height_to_adjusted_value_destroyed.as_ref().unwrap()),
|
||||
)?;
|
||||
|
||||
self.dateindex_to_realized_cap_30d_change
|
||||
self.indexes_to_realized_cap_30d_change
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_change(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_realized_cap
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_last(),
|
||||
30,
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_change(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_realized_cap
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_last(),
|
||||
30,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_net_realized_profit_and_loss
|
||||
@@ -2280,6 +2361,42 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_realized_profit_relative_to_realized_cap
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_realized_profit.as_ref().unwrap(),
|
||||
*height_to_realized_cap.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_realized_loss_relative_to_realized_cap
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_realized_loss.as_ref().unwrap(),
|
||||
*height_to_realized_cap.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_net_realized_profit_and_loss_relative_to_realized_cap
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
@@ -2435,6 +2552,64 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_change(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_net_realized_profit_and_loss
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_cumulative(),
|
||||
30,
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap.
|
||||
as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref().unwrap().dateindex.as_ref().unwrap(),
|
||||
*dateindex_to_realized_cap.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap.
|
||||
as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref().unwrap().dateindex.as_ref().unwrap(),
|
||||
market.indexes_to_marketcap.dateindex.as_ref().unwrap(),
|
||||
exit,
|
||||
)
|
||||
},
|
||||
)?;
|
||||
|
||||
if let Some(height_to_supply_even_relative_to_circulating_supply) = self
|
||||
.height_to_supply_even_relative_to_circulating_supply
|
||||
.as_mut()
|
||||
@@ -2618,9 +2793,9 @@ impl Vecs {
|
||||
self.indexes_to_adjusted_value_destroyed
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.dateindex_to_realized_cap_30d_change
|
||||
self.indexes_to_realized_cap_30d_change
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_net_realized_profit_and_loss
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
@@ -2703,6 +2878,12 @@ impl Vecs {
|
||||
self.indexes_to_net_unrealized_profit_and_loss_relative_to_market_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_realized_profit_relative_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_realized_loss_relative_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_net_realized_profit_and_loss_relative_to_realized_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
@@ -2756,6 +2937,12 @@ impl Vecs {
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_coinblocks_destroyed.vecs(),
|
||||
self.indexes_to_coindays_destroyed.vecs(),
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
||||
@@ -4,8 +4,8 @@ use brk_core::{DateIndex, Height, InputIndex, OutputIndex, OutputType, Result, S
|
||||
use brk_exit::Exit;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_vec::{
|
||||
AnyCollectableVec, AnyVec, BaseVecIterator, CollectableVec, Computation, EagerVec, Format,
|
||||
GenericStoredVec, StoredIndex, StoredVec, UnsafeSlice, VecIterator,
|
||||
AnyCollectableVec, AnyVec, CollectableVec, Computation, EagerVec, Format, GenericStoredVec,
|
||||
StoredIndex, StoredVec, UnsafeSlice, VecIterator,
|
||||
};
|
||||
use log::info;
|
||||
use outputs::OutputCohorts;
|
||||
@@ -39,7 +39,7 @@ pub struct Vecs {
|
||||
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
|
||||
pub height_to_opreturn_supply: EagerVec<Height, Sats>,
|
||||
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
|
||||
utxos_vecs: Outputs<(OutputFilter, cohort::Vecs)>,
|
||||
pub utxos_vecs: Outputs<(OutputFilter, cohort::Vecs)>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -1202,7 +1202,7 @@ impl Vecs {
|
||||
fetched: Option<&fetched::Vecs>,
|
||||
market: &market::Vecs,
|
||||
// Must take ownership as its indexes will be updated for this specific function
|
||||
mut starting_indexes: Indexes,
|
||||
starting_indexes: &mut Indexes,
|
||||
exit: &Exit,
|
||||
) -> color_eyre::Result<()> {
|
||||
let indexer_vecs = indexer.vecs();
|
||||
@@ -1343,268 +1343,265 @@ impl Vecs {
|
||||
.try_for_each(|(_, v)| v.state.price_to_amount.reset())?;
|
||||
}
|
||||
|
||||
if starting_height == Height::from(height_to_date_fixed.len()) {
|
||||
return Ok(());
|
||||
}
|
||||
if starting_height < Height::from(height_to_date_fixed.len()) {
|
||||
starting_indexes.update_from_height(starting_height, indexes);
|
||||
|
||||
// ---
|
||||
// INIT
|
||||
// ---
|
||||
separate_utxo_vecs
|
||||
.par_iter_mut()
|
||||
.for_each(|(_, v)| v.init(starting_height));
|
||||
|
||||
separate_utxo_vecs
|
||||
.par_iter_mut()
|
||||
.for_each(|(_, v)| v.init(starting_height));
|
||||
|
||||
let mut unspendable_supply = if let Some(prev_height) = starting_height.decremented() {
|
||||
self.height_to_unspendable_supply
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height)
|
||||
} else {
|
||||
Sats::ZERO
|
||||
};
|
||||
let mut opreturn_supply = if let Some(prev_height) = starting_height.decremented() {
|
||||
self.height_to_opreturn_supply
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height)
|
||||
} else {
|
||||
Sats::ZERO
|
||||
};
|
||||
|
||||
let mut height = starting_height;
|
||||
starting_indexes.update_from_height(height, indexes);
|
||||
|
||||
(height.unwrap_to_usize()..height_to_first_outputindex_iter.len())
|
||||
.map(Height::from)
|
||||
.try_for_each(|_height| -> color_eyre::Result<()> {
|
||||
height = _height;
|
||||
|
||||
self.utxos_vecs
|
||||
.as_mut_separate_vecs()
|
||||
.iter_mut()
|
||||
.for_each(|(_, v)| v.state.reset_single_iteration_values());
|
||||
|
||||
info!("Processing chain at {height}...");
|
||||
|
||||
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
|
||||
let price = height_to_close_iter
|
||||
.as_mut()
|
||||
.map(|i| *i.unwrap_get_inner(height));
|
||||
let first_outputindex = height_to_first_outputindex_iter
|
||||
.unwrap_get_inner(height)
|
||||
.unwrap_to_usize();
|
||||
let first_inputindex = height_to_first_inputindex_iter
|
||||
.unwrap_get_inner(height)
|
||||
.unwrap_to_usize();
|
||||
let output_count = height_to_output_count_iter.unwrap_get_inner(height);
|
||||
let input_count = height_to_input_count_iter.unwrap_get_inner(height);
|
||||
|
||||
let (mut height_to_sent, mut received) = thread::scope(|s| {
|
||||
if chain_state_starting_height <= height {
|
||||
s.spawn(|| {
|
||||
self.utxos_vecs
|
||||
.tick_tock_next_block(&chain_state, timestamp);
|
||||
});
|
||||
}
|
||||
|
||||
let sent_handle = s.spawn(|| {
|
||||
// Skip coinbase
|
||||
(first_inputindex + 1..first_inputindex + *input_count)
|
||||
.into_par_iter()
|
||||
.map(InputIndex::from)
|
||||
.map(|inputindex| {
|
||||
let outputindex = inputindex_to_outputindex
|
||||
.get_or_read(inputindex, &inputindex_to_outputindex_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let value = outputindex_to_value
|
||||
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let input_type = outputindex_to_outputtype
|
||||
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
// dbg!(input_type);
|
||||
|
||||
if input_type.is_unspendable() {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
let input_txindex = outputindex_to_txindex
|
||||
.get_or_read(outputindex, &outputindex_to_txindex_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let height = txindex_to_height
|
||||
.get_or_read(input_txindex, &txindex_to_height_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
(height, value, input_type)
|
||||
})
|
||||
.fold(
|
||||
BTreeMap::<Height, Transacted>::default,
|
||||
|mut tree, (height, value, input_type)| {
|
||||
tree.entry(height).or_default().iterate(value, input_type);
|
||||
tree
|
||||
},
|
||||
)
|
||||
.reduce(BTreeMap::<Height, Transacted>::default, |first, second| {
|
||||
let (mut source, to_consume) = if first.len() > second.len() {
|
||||
(first, second)
|
||||
} else {
|
||||
(second, first)
|
||||
};
|
||||
to_consume.into_iter().for_each(|(k, v)| {
|
||||
*source.entry(k).or_default() += v;
|
||||
});
|
||||
source
|
||||
})
|
||||
});
|
||||
|
||||
let received_handle = s.spawn(|| {
|
||||
(first_outputindex..first_outputindex + *output_count)
|
||||
.into_par_iter()
|
||||
.map(OutputIndex::from)
|
||||
.map(|outputindex| {
|
||||
let value = outputindex_to_value
|
||||
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let output_type = outputindex_to_outputtype
|
||||
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
(value, output_type)
|
||||
})
|
||||
.fold(
|
||||
Transacted::default,
|
||||
|mut transacted, (value, output_type)| {
|
||||
transacted.iterate(value, output_type);
|
||||
transacted
|
||||
},
|
||||
)
|
||||
.reduce(Transacted::default, |acc, transacted| acc + transacted)
|
||||
});
|
||||
|
||||
(sent_handle.join().unwrap(), received_handle.join().unwrap())
|
||||
});
|
||||
|
||||
unspendable_supply += received
|
||||
.by_type
|
||||
.unspendable
|
||||
.as_vec()
|
||||
let mut unspendable_supply = if let Some(prev_height) = starting_height.decremented() {
|
||||
self.height_to_unspendable_supply
|
||||
.into_iter()
|
||||
.map(|state| state.value)
|
||||
.sum::<Sats>()
|
||||
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
|
||||
|
||||
opreturn_supply += received.by_type.unspendable.opreturn.value;
|
||||
|
||||
if height == Height::new(0) {
|
||||
received = Transacted::default();
|
||||
unspendable_supply += Sats::FIFTY_BTC;
|
||||
} else if height == Height::new(91_842) || height == Height::new(91_880) {
|
||||
// Need to destroy invalid coinbases due to duplicate txids
|
||||
if height == Height::new(91_842) {
|
||||
height_to_sent.entry(Height::new(91_812)).or_default()
|
||||
} else {
|
||||
height_to_sent.entry(Height::new(91_722)).or_default()
|
||||
}
|
||||
.iterate(Sats::FIFTY_BTC, OutputType::P2PK65);
|
||||
};
|
||||
|
||||
if chain_state_starting_height <= height {
|
||||
// Push current block state before processing sends and receives
|
||||
chain_state.push(BlockState {
|
||||
supply: received.spendable_supply.clone(),
|
||||
price,
|
||||
timestamp,
|
||||
});
|
||||
|
||||
self.utxos_vecs.receive(received, height, price);
|
||||
|
||||
let unsafe_chain_state = UnsafeSlice::new(&mut chain_state);
|
||||
|
||||
height_to_sent.par_iter().for_each(|(height, sent)| unsafe {
|
||||
(*unsafe_chain_state.get(height.unwrap_to_usize())).supply -=
|
||||
&sent.spendable_supply;
|
||||
});
|
||||
|
||||
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
|
||||
} else {
|
||||
dbg!(chain_state_starting_height, height);
|
||||
panic!("temp, just making sure")
|
||||
}
|
||||
|
||||
let mut separate_utxo_vecs = self.utxos_vecs.as_mut_separate_vecs();
|
||||
|
||||
separate_utxo_vecs
|
||||
.iter_mut()
|
||||
.try_for_each(|(_, v)| v.forced_pushed_at(height, exit))?;
|
||||
|
||||
self.height_to_unspendable_supply.forced_push_at(
|
||||
height,
|
||||
unspendable_supply,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
.unwrap_get_inner(prev_height)
|
||||
} else {
|
||||
Sats::ZERO
|
||||
};
|
||||
let mut opreturn_supply = if let Some(prev_height) = starting_height.decremented() {
|
||||
self.height_to_opreturn_supply
|
||||
.forced_push_at(height, opreturn_supply, exit)?;
|
||||
.into_iter()
|
||||
.unwrap_get_inner(prev_height)
|
||||
} else {
|
||||
Sats::ZERO
|
||||
};
|
||||
|
||||
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
|
||||
let dateindex = DateIndex::try_from(date).unwrap();
|
||||
let date_first_height = dateindex_to_first_height_iter.unwrap_get_inner(dateindex);
|
||||
let date_height_count = dateindex_to_height_count_iter.unwrap_get_inner(dateindex);
|
||||
let is_date_last_height = date_first_height
|
||||
+ Height::from(date_height_count).decremented().unwrap()
|
||||
== height;
|
||||
let date_price = dateindex_to_close_iter
|
||||
.as_mut()
|
||||
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
|
||||
let mut height = starting_height;
|
||||
|
||||
separate_utxo_vecs.par_iter_mut().try_for_each(|(_, v)| {
|
||||
v.compute_then_force_push_unrealized_states(
|
||||
(height.unwrap_to_usize()..height_to_date_fixed.len())
|
||||
.map(Height::from)
|
||||
.try_for_each(|_height| -> color_eyre::Result<()> {
|
||||
height = _height;
|
||||
|
||||
self.utxos_vecs
|
||||
.as_mut_separate_vecs()
|
||||
.iter_mut()
|
||||
.for_each(|(_, v)| v.state.reset_single_iteration_values());
|
||||
|
||||
info!("Processing chain at {height}...");
|
||||
|
||||
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
|
||||
let price = height_to_close_iter
|
||||
.as_mut()
|
||||
.map(|i| *i.unwrap_get_inner(height));
|
||||
let first_outputindex = height_to_first_outputindex_iter
|
||||
.unwrap_get_inner(height)
|
||||
.unwrap_to_usize();
|
||||
let first_inputindex = height_to_first_inputindex_iter
|
||||
.unwrap_get_inner(height)
|
||||
.unwrap_to_usize();
|
||||
let output_count = height_to_output_count_iter.unwrap_get_inner(height);
|
||||
let input_count = height_to_input_count_iter.unwrap_get_inner(height);
|
||||
|
||||
let (mut height_to_sent, mut received) = thread::scope(|s| {
|
||||
if chain_state_starting_height <= height {
|
||||
s.spawn(|| {
|
||||
self.utxos_vecs
|
||||
.tick_tock_next_block(&chain_state, timestamp);
|
||||
});
|
||||
}
|
||||
|
||||
let sent_handle = s.spawn(|| {
|
||||
// Skip coinbase
|
||||
(first_inputindex + 1..first_inputindex + *input_count)
|
||||
.into_par_iter()
|
||||
.map(InputIndex::from)
|
||||
.map(|inputindex| {
|
||||
let outputindex = inputindex_to_outputindex
|
||||
.get_or_read(inputindex, &inputindex_to_outputindex_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let value = outputindex_to_value
|
||||
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let input_type = outputindex_to_outputtype
|
||||
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
// dbg!(input_type);
|
||||
|
||||
if input_type.is_unspendable() {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
let input_txindex = outputindex_to_txindex
|
||||
.get_or_read(outputindex, &outputindex_to_txindex_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let height = txindex_to_height
|
||||
.get_or_read(input_txindex, &txindex_to_height_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
(height, value, input_type)
|
||||
})
|
||||
.fold(
|
||||
BTreeMap::<Height, Transacted>::default,
|
||||
|mut tree, (height, value, input_type)| {
|
||||
tree.entry(height).or_default().iterate(value, input_type);
|
||||
tree
|
||||
},
|
||||
)
|
||||
.reduce(BTreeMap::<Height, Transacted>::default, |first, second| {
|
||||
let (mut source, to_consume) = if first.len() > second.len() {
|
||||
(first, second)
|
||||
} else {
|
||||
(second, first)
|
||||
};
|
||||
to_consume.into_iter().for_each(|(k, v)| {
|
||||
*source.entry(k).or_default() += v;
|
||||
});
|
||||
source
|
||||
})
|
||||
});
|
||||
|
||||
let received_handle = s.spawn(|| {
|
||||
(first_outputindex..first_outputindex + *output_count)
|
||||
.into_par_iter()
|
||||
.map(OutputIndex::from)
|
||||
.map(|outputindex| {
|
||||
let value = outputindex_to_value
|
||||
.get_or_read(outputindex, &outputindex_to_value_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
let output_type = outputindex_to_outputtype
|
||||
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.into_inner();
|
||||
|
||||
(value, output_type)
|
||||
})
|
||||
.fold(
|
||||
Transacted::default,
|
||||
|mut transacted, (value, output_type)| {
|
||||
transacted.iterate(value, output_type);
|
||||
transacted
|
||||
},
|
||||
)
|
||||
.reduce(Transacted::default, |acc, transacted| acc + transacted)
|
||||
});
|
||||
|
||||
(sent_handle.join().unwrap(), received_handle.join().unwrap())
|
||||
});
|
||||
|
||||
unspendable_supply += received
|
||||
.by_type
|
||||
.unspendable
|
||||
.as_vec()
|
||||
.into_iter()
|
||||
.map(|state| state.value)
|
||||
.sum::<Sats>()
|
||||
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
|
||||
|
||||
opreturn_supply += received.by_type.unspendable.opreturn.value;
|
||||
|
||||
if height == Height::new(0) {
|
||||
received = Transacted::default();
|
||||
unspendable_supply += Sats::FIFTY_BTC;
|
||||
} else if height == Height::new(91_842) || height == Height::new(91_880) {
|
||||
// Need to destroy invalid coinbases due to duplicate txids
|
||||
if height == Height::new(91_842) {
|
||||
height_to_sent.entry(Height::new(91_812)).or_default()
|
||||
} else {
|
||||
height_to_sent.entry(Height::new(91_722)).or_default()
|
||||
}
|
||||
.iterate(Sats::FIFTY_BTC, OutputType::P2PK65);
|
||||
};
|
||||
|
||||
if chain_state_starting_height <= height {
|
||||
// Push current block state before processing sends and receives
|
||||
chain_state.push(BlockState {
|
||||
supply: received.spendable_supply.clone(),
|
||||
price,
|
||||
timestamp,
|
||||
});
|
||||
|
||||
self.utxos_vecs.receive(received, height, price);
|
||||
|
||||
let unsafe_chain_state = UnsafeSlice::new(&mut chain_state);
|
||||
|
||||
height_to_sent.par_iter().for_each(|(height, sent)| unsafe {
|
||||
(*unsafe_chain_state.get(height.unwrap_to_usize())).supply -=
|
||||
&sent.spendable_supply;
|
||||
});
|
||||
|
||||
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
|
||||
} else {
|
||||
dbg!(chain_state_starting_height, height);
|
||||
panic!("temp, just making sure")
|
||||
}
|
||||
|
||||
let mut separate_utxo_vecs = self.utxos_vecs.as_mut_separate_vecs();
|
||||
|
||||
separate_utxo_vecs
|
||||
.iter_mut()
|
||||
.try_for_each(|(_, v)| v.forced_pushed_at(height, exit))?;
|
||||
|
||||
self.height_to_unspendable_supply.forced_push_at(
|
||||
height,
|
||||
price,
|
||||
is_date_last_height.then_some(dateindex),
|
||||
date_price,
|
||||
unspendable_supply,
|
||||
exit,
|
||||
)
|
||||
)?;
|
||||
|
||||
self.height_to_opreturn_supply
|
||||
.forced_push_at(height, opreturn_supply, exit)?;
|
||||
|
||||
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
|
||||
let dateindex = DateIndex::try_from(date).unwrap();
|
||||
let date_first_height =
|
||||
dateindex_to_first_height_iter.unwrap_get_inner(dateindex);
|
||||
let date_height_count =
|
||||
dateindex_to_height_count_iter.unwrap_get_inner(dateindex);
|
||||
let is_date_last_height = date_first_height
|
||||
+ Height::from(date_height_count).decremented().unwrap()
|
||||
== height;
|
||||
let date_price = dateindex_to_close_iter
|
||||
.as_mut()
|
||||
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
|
||||
|
||||
separate_utxo_vecs.par_iter_mut().try_for_each(|(_, v)| {
|
||||
v.compute_then_force_push_unrealized_states(
|
||||
height,
|
||||
price,
|
||||
is_date_last_height.then_some(dateindex),
|
||||
date_price,
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
|
||||
if height != Height::ZERO && height.unwrap_to_usize() % 20_000 == 0 {
|
||||
info!("Flushing...");
|
||||
exit.block();
|
||||
self.flush_states(height, &chain_state, exit)?;
|
||||
exit.release();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
if height != Height::ZERO && height.unwrap_to_usize() % 20_000 == 0 {
|
||||
info!("Flushing...");
|
||||
exit.block();
|
||||
self.flush_states(height, &chain_state, exit)?;
|
||||
exit.release();
|
||||
}
|
||||
exit.block();
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
info!("Flushing...");
|
||||
|
||||
exit.block();
|
||||
self.flush_states(height, &chain_state, exit)?;
|
||||
}
|
||||
|
||||
info!("Flushing...");
|
||||
|
||||
self.flush_states(height, &chain_state, exit)?;
|
||||
|
||||
info!("Computing overlaping...");
|
||||
info!("Computing overlapping...");
|
||||
|
||||
self.utxos_vecs
|
||||
.compute_overlaping_vecs(&starting_indexes, exit)?;
|
||||
.compute_overlapping_vecs(starting_indexes, exit)?;
|
||||
|
||||
info!("Computing rest part 1...");
|
||||
|
||||
@@ -1612,7 +1609,7 @@ impl Vecs {
|
||||
.as_mut_vecs()
|
||||
.par_iter_mut()
|
||||
.try_for_each(|(_, v)| {
|
||||
v.compute_rest_part1(indexer, indexes, fetched, &starting_indexes, exit)
|
||||
v.compute_rest_part1(indexer, indexes, fetched, starting_indexes, exit)
|
||||
})?;
|
||||
|
||||
info!("Computing rest part 2...");
|
||||
@@ -1627,6 +1624,13 @@ impl Vecs {
|
||||
.dateindex
|
||||
.clone();
|
||||
let height_to_realized_cap = self.utxos_vecs.all.1.height_to_realized_cap.clone();
|
||||
let dateindex_to_realized_cap = self
|
||||
.utxos_vecs
|
||||
.all
|
||||
.1
|
||||
.indexes_to_realized_cap
|
||||
.as_ref()
|
||||
.map(|v| v.dateindex.unwrap_last().clone());
|
||||
|
||||
self.utxos_vecs
|
||||
.as_mut_vecs()
|
||||
@@ -1636,11 +1640,12 @@ impl Vecs {
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
&starting_indexes,
|
||||
starting_indexes,
|
||||
market,
|
||||
&height_to_supply,
|
||||
dateindex_to_supply.as_ref().unwrap(),
|
||||
height_to_realized_cap.as_ref(),
|
||||
dateindex_to_realized_cap.as_ref(),
|
||||
exit,
|
||||
)
|
||||
})?;
|
||||
@@ -1648,7 +1653,7 @@ impl Vecs {
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
&starting_indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_unspendable_supply),
|
||||
)?;
|
||||
@@ -1656,7 +1661,7 @@ impl Vecs {
|
||||
indexer,
|
||||
indexes,
|
||||
fetched,
|
||||
&starting_indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_opreturn_supply),
|
||||
)?;
|
||||
|
||||
@@ -14,7 +14,7 @@ pub trait OutputCohorts {
|
||||
fn tick_tock_next_block(&mut self, chain_state: &[BlockState], timestamp: Timestamp);
|
||||
fn send(&mut self, height_to_sent: BTreeMap<Height, Transacted>, chain_state: &[BlockState]);
|
||||
fn receive(&mut self, received: Transacted, height: Height, price: Option<Dollars>);
|
||||
fn compute_overlaping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
fn compute_overlapping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
|
||||
}
|
||||
|
||||
impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
|
||||
@@ -172,7 +172,7 @@ impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
|
||||
});
|
||||
}
|
||||
|
||||
fn compute_overlaping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
fn compute_overlapping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
|
||||
let by_date_range = self.by_date_range.as_vec();
|
||||
let by_size_range = self.by_size_range.as_vec();
|
||||
|
||||
|
||||
@@ -139,6 +139,24 @@ impl Div<usize> for Dollars {
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<StoredF64> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: StoredF64) -> Self::Output {
|
||||
self / f64::from(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f64> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: f64) -> Self::Output {
|
||||
if self.is_nan() || rhs == 0.0 {
|
||||
Dollars::NAN
|
||||
} else {
|
||||
Dollars::from(Cents::from(Self::from(self.0 / rhs)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<Bitcoin> for Dollars {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Bitcoin) -> Self::Output {
|
||||
@@ -178,6 +196,24 @@ impl Mul<usize> for Close<Dollars> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<StoredF64> for Close<Dollars> {
|
||||
type Output = Dollars;
|
||||
fn mul(self, rhs: StoredF64) -> Self::Output {
|
||||
*self * rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<f64> for Dollars {
|
||||
type Output = Dollars;
|
||||
fn mul(self, rhs: f64) -> Self::Output {
|
||||
if rhs.fract() != 0.0 {
|
||||
Self::from(self.0 * rhs)
|
||||
} else {
|
||||
self * rhs as i64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Bitcoin> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: Bitcoin) -> Self::Output {
|
||||
@@ -208,11 +244,14 @@ impl Mul<Sats> for Dollars {
|
||||
impl Mul<StoredF32> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: StoredF32) -> Self::Output {
|
||||
if rhs.fract() != 0.0 {
|
||||
Self::from(self.0 * *rhs as f64)
|
||||
} else {
|
||||
self * *rhs as i64
|
||||
}
|
||||
self * *rhs as f64
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<StoredF64> for Dollars {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: StoredF64) -> Self::Output {
|
||||
self * *rhs
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -524,3 +524,13 @@ where
|
||||
Self(self.0 / rhs)
|
||||
}
|
||||
}
|
||||
|
||||
// impl<T> Mul<usize> for Close<T>
|
||||
// where
|
||||
// T: Mul<usize, Output = T>,
|
||||
// {
|
||||
// type Output = Self;
|
||||
// fn mul(self, rhs: usize) -> Self::Output {
|
||||
// Self(self.0 * rhs)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -9,7 +9,7 @@ use byteview::ByteView;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
|
||||
|
||||
use crate::{CheckedSub, copy_first_8bytes};
|
||||
use crate::{CheckedSub, StoredF64, copy_first_8bytes};
|
||||
|
||||
use super::{Bitcoin, Cents, Dollars, Height};
|
||||
|
||||
@@ -112,6 +112,13 @@ impl Mul<Height> for Sats {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<StoredF64> for Sats {
|
||||
type Output = Self;
|
||||
fn mul(self, rhs: StoredF64) -> Self::Output {
|
||||
Sats::from((self.0 as f64 * f64::from(rhs)) as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sum for Sats {
|
||||
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
|
||||
let sats: u64 = iter.map(|sats| sats.0).sum();
|
||||
|
||||
@@ -51,6 +51,13 @@ impl Div<usize> for StoredF64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<StoredF64> for StoredF64 {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 / rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for StoredF64 {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
|
||||
@@ -3,5 +3,7 @@ use log::info;
|
||||
pub fn pause() {
|
||||
info!("Press enter to continue...");
|
||||
let mut buffer = String::new();
|
||||
std::io::stdin().read_line(&mut buffer).expect("Failed to read line");
|
||||
std::io::stdin()
|
||||
.read_line(&mut buffer)
|
||||
.expect("Failed to read line");
|
||||
}
|
||||
|
||||
@@ -26,11 +26,17 @@ impl<'a> VecTrees<'a> {
|
||||
|| s == &"cumulative_up"
|
||||
|| s.starts_with("cumulative_start")
|
||||
|| s.starts_with("cumulative_from")
|
||||
|| s == &"activity"
|
||||
}))
|
||||
&& !(split.len() == 4
|
||||
&& split
|
||||
.get(1)
|
||||
.is_some_and(|s| s == &"up" || s == &"start" || s.starts_with("from"))
|
||||
&& split.get(1).is_some_and(|s| {
|
||||
s == &"up"
|
||||
|| s == &"start"
|
||||
|| s.starts_with("from")
|
||||
|| s == &"cumulative_up"
|
||||
|| s == &"cumulative_start"
|
||||
|| s.starts_with("cumulative_from")
|
||||
})
|
||||
&& split.get(2).is_some_and(|s| s.ends_with("relative")))
|
||||
{
|
||||
dbg!(&name, &split);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ impl<T> Outputs<T> {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub fn as_mut_overlaping_vecs(&mut self) -> Vec<&mut T> {
|
||||
pub fn as_mut_overlapping_vecs(&mut self) -> Vec<&mut T> {
|
||||
[&mut self.all]
|
||||
.into_iter()
|
||||
.chain(self.by_term.as_mut_vec())
|
||||
|
||||
@@ -1015,6 +1015,32 @@ where
|
||||
|
||||
self.safe_flush(exit)
|
||||
}
|
||||
|
||||
pub fn compute_zscore(
|
||||
&mut self,
|
||||
max_from: I,
|
||||
ratio: &impl AnyIterableVec<I, StoredF32>,
|
||||
sma: &impl AnyIterableVec<I, StoredF32>,
|
||||
sd: &impl AnyIterableVec<I, StoredF32>,
|
||||
exit: &Exit,
|
||||
) -> Result<()>
|
||||
where
|
||||
T: From<StoredF32>,
|
||||
{
|
||||
let mut sma_iter = sma.iter();
|
||||
let mut sd_iter = sd.iter();
|
||||
|
||||
self.compute_transform(
|
||||
max_from,
|
||||
ratio,
|
||||
|(i, ratio, ..)| {
|
||||
let sma = sma_iter.unwrap_get_inner(i);
|
||||
let sd = sd_iter.unwrap_get_inner(i);
|
||||
(i, T::from((ratio - sma) / sd))
|
||||
},
|
||||
exit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl EagerVec<DateIndex, Sats> {
|
||||
|
||||
@@ -400,13 +400,17 @@ function createChartElement({
|
||||
({ _indexes, values }) => {
|
||||
if (!_indexes?.length || !values?.length) return;
|
||||
|
||||
const consoleTimeLabel = `${vecId}-time`;
|
||||
console.time(consoleTimeLabel);
|
||||
|
||||
const indexes = /** @type {number[]} */ (_indexes);
|
||||
|
||||
let length = Math.min(indexes.length, values.length);
|
||||
|
||||
// TODO: Don't create new Array if data already present, update instead
|
||||
/** @type {LineData[] | CandlestickData[]} */
|
||||
const data = new Array(length);
|
||||
const data = /** @type {LineData[] | CandlestickData[]} */ (
|
||||
Array.from({ length })
|
||||
);
|
||||
|
||||
let prevTime = null;
|
||||
let timeOffset = 0;
|
||||
@@ -433,16 +437,18 @@ function createChartElement({
|
||||
if (sameTime) {
|
||||
console.log(data[offsetedI]);
|
||||
}
|
||||
const candles = /** @type {CandlestickData[]} */ (data);
|
||||
let [open, high, low, close] = v;
|
||||
candles[offsetedI] = {
|
||||
data[offsetedI] = {
|
||||
time,
|
||||
open: sameTime ? candles[offsetedI].open : open,
|
||||
// @ts-ignore
|
||||
open: sameTime ? data[offsetedI].open : open,
|
||||
high: sameTime
|
||||
? Math.max(candles[offsetedI].high, high)
|
||||
? // @ts-ignore
|
||||
Math.max(data[offsetedI].high, high)
|
||||
: high,
|
||||
low: sameTime
|
||||
? Math.min(candles[offsetedI].low, low)
|
||||
? // @ts-ignore
|
||||
Math.min(data[offsetedI].low, low)
|
||||
: low,
|
||||
close,
|
||||
};
|
||||
@@ -474,69 +480,12 @@ function createChartElement({
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (data.length) {
|
||||
let i = 0;
|
||||
// console.log(seriesData);
|
||||
const first = seriesData[0];
|
||||
} else {
|
||||
const last = seriesData.at(-1);
|
||||
if (!last) throw Error("Unreachable");
|
||||
while (data[i].time < first.time) {
|
||||
iseries.update(data[i], true);
|
||||
i++;
|
||||
}
|
||||
// console.log(i);
|
||||
let j = 0;
|
||||
while (i < data.length) {
|
||||
const dataI = data[i];
|
||||
const iTime = dataI.time;
|
||||
const seriesDataJ = /** @type {typeof dataI} */ (
|
||||
seriesData[j]
|
||||
);
|
||||
const jTime = seriesDataJ.time;
|
||||
if (iTime === jTime) {
|
||||
const historicalUpdate = iTime < last.time;
|
||||
|
||||
if ("value" in dataI) {
|
||||
if (
|
||||
// @ts-ignore
|
||||
dataI.value !== seriesDataJ.value &&
|
||||
// @ts-ignore
|
||||
(!isNaN(dataI.value) || !isNaN(seriesDataJ.value))
|
||||
) {
|
||||
// console.log(vecId);
|
||||
iseries.update(dataI, historicalUpdate);
|
||||
}
|
||||
} else if (
|
||||
// @ts-ignore
|
||||
dataI.open !== seriesDataJ.open ||
|
||||
// @ts-ignore
|
||||
dataI.high !== seriesDataJ.high ||
|
||||
// @ts-ignore
|
||||
dataI.low !== seriesDataJ.low ||
|
||||
// @ts-ignore
|
||||
dataI.close !== seriesDataJ.close
|
||||
) {
|
||||
// console.log({
|
||||
// vecId,
|
||||
// dataI,
|
||||
// i,
|
||||
// data,
|
||||
// j,
|
||||
// seriesDataJ,
|
||||
// seriesData,
|
||||
// });
|
||||
iseries.update(dataI, historicalUpdate);
|
||||
}
|
||||
i++;
|
||||
j++;
|
||||
} else if (iTime < jTime) {
|
||||
iseries.update(dataI, true);
|
||||
i++;
|
||||
} else if (iTime > last.time) {
|
||||
iseries.update(dataI);
|
||||
i++;
|
||||
} else if (iTime > jTime) {
|
||||
j++;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].time >= last.time) {
|
||||
iseries.update(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -546,6 +495,8 @@ function createChartElement({
|
||||
index,
|
||||
unit,
|
||||
});
|
||||
|
||||
console.timeEnd(consoleTimeLabel);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -396,6 +396,7 @@ export function init({
|
||||
blueprints[unit]?.forEach((blueprint, order) => {
|
||||
order += orderStart;
|
||||
|
||||
console.log(blueprint.key);
|
||||
const indexes = /** @type {readonly number[]} */ (
|
||||
vecIdToIndexes[blueprint.key]
|
||||
);
|
||||
|
||||
@@ -744,15 +744,18 @@ function createUtils() {
|
||||
id === "open" ||
|
||||
id === "marketcap" ||
|
||||
id.includes("in-usd") ||
|
||||
id.includes("cointime-value") ||
|
||||
id.startsWith("price") ||
|
||||
id.endsWith("price-paid") ||
|
||||
id.endsWith("price") ||
|
||||
(id.endsWith("-cap") && !id.includes("relative-to")) ||
|
||||
id.endsWith("value-created") ||
|
||||
id.endsWith("value-destroyed") ||
|
||||
(id.includes("realized") &&
|
||||
((id.includes("realized") || id.includes("true-market-mean")) &&
|
||||
!id.includes("ratio") &&
|
||||
!id.includes("relative-to")) ||
|
||||
(id.endsWith("sma") && !id.includes("ratio")) ||
|
||||
((id.endsWith("sma") || id.includes("sma-x")) &&
|
||||
!id.includes("ratio")) ||
|
||||
id === "ath")
|
||||
) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
@@ -763,18 +766,20 @@ function createUtils() {
|
||||
unit = "Cents";
|
||||
}
|
||||
if (
|
||||
(!unit || thoroughUnitCheck) &&
|
||||
(id.endsWith("ratio") ||
|
||||
(id.includes("ratio") && id.endsWith("sma")) ||
|
||||
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"))
|
||||
((!unit || thoroughUnitCheck) &&
|
||||
(id.endsWith("ratio") ||
|
||||
(id.includes("ratio") && id.endsWith("sma")) ||
|
||||
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.includes("liveliness") ||
|
||||
id.includes("vaultedness")
|
||||
) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
unit = "Ratio";
|
||||
@@ -838,7 +843,7 @@ function createUtils() {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
unit = "Bytes";
|
||||
}
|
||||
if ((!unit || thoroughUnitCheck) && id.endsWith("standard-deviation")) {
|
||||
if ((!unit || thoroughUnitCheck) && id.endsWith("-sd")) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
unit = "sd";
|
||||
}
|
||||
@@ -1264,12 +1269,6 @@ function createUtils() {
|
||||
return 0;
|
||||
return this.differenceBetween(date, new Date("2009-01-09"));
|
||||
},
|
||||
/**
|
||||
* @param {Date} start
|
||||
*/
|
||||
getRangeUpToToday(start) {
|
||||
return this.getRange(start, new Date());
|
||||
},
|
||||
/**
|
||||
* @param {Date} start
|
||||
* @param {Date} end
|
||||
@@ -1578,7 +1577,9 @@ function createVecsResources(signals, utils) {
|
||||
map.set(fetchedKey, {
|
||||
loading: false,
|
||||
at: null,
|
||||
vec: signals.createSignal(/** @type {T[] | null} */ (null)),
|
||||
vec: signals.createSignal(/** @type {T[] | null} */ (null), {
|
||||
equals: false,
|
||||
}),
|
||||
});
|
||||
return map;
|
||||
});
|
||||
@@ -2289,36 +2290,36 @@ function main() {
|
||||
initSelected();
|
||||
|
||||
function initFolders() {
|
||||
// async function scrollToSelected() {
|
||||
// if (!options.selected()) throw "Selected should be set by now";
|
||||
// const selectedId = options.selected().id;
|
||||
async function scrollToSelected() {
|
||||
if (!options.selected()) throw "Selected should be set by now";
|
||||
const selectedId = options.selected().id;
|
||||
|
||||
// const path = options.selected().path;
|
||||
const path = options.selected().path;
|
||||
|
||||
// let i = 0;
|
||||
// while (i !== path.length) {
|
||||
// try {
|
||||
// const id = path[i];
|
||||
// const details = /** @type {HTMLDetailsElement} */ (
|
||||
// utils.dom.getElementById(id)
|
||||
// );
|
||||
// details.open = true;
|
||||
// i++;
|
||||
// } catch {
|
||||
// await utils.next();
|
||||
// }
|
||||
// }
|
||||
let i = 0;
|
||||
while (i !== path.length) {
|
||||
try {
|
||||
const id = path[i];
|
||||
const details = /** @type {HTMLDetailsElement} */ (
|
||||
utils.dom.getElementById(id)
|
||||
);
|
||||
details.open = true;
|
||||
i++;
|
||||
} catch {
|
||||
await utils.next();
|
||||
}
|
||||
}
|
||||
|
||||
// await utils.next();
|
||||
// await utils.next();
|
||||
await utils.next();
|
||||
await utils.next();
|
||||
|
||||
// utils.dom
|
||||
// .getElementById(`${selectedId}-nav-selector`)
|
||||
// .scrollIntoView({
|
||||
// behavior: "instant",
|
||||
// block: "center",
|
||||
// });
|
||||
// }
|
||||
utils.dom
|
||||
.getElementById(`${selectedId}-nav-selector`)
|
||||
.scrollIntoView({
|
||||
behavior: "instant",
|
||||
block: "center",
|
||||
});
|
||||
}
|
||||
|
||||
utils.dom.onFirstIntersection(elements.nav, () => {
|
||||
options.treeElement.set(() => {
|
||||
@@ -2328,7 +2329,9 @@ function main() {
|
||||
return treeElement;
|
||||
});
|
||||
|
||||
// setTimeout(scrollToSelected, 10);
|
||||
if (localhost) {
|
||||
setTimeout(scrollToSelected, 10);
|
||||
}
|
||||
});
|
||||
}
|
||||
initFolders();
|
||||
|
||||
@@ -127,14 +127,17 @@ function createPartialOptions(colors) {
|
||||
* @template {string} S
|
||||
* @typedef {K extends `${infer Rest}${S}` ? Rest : never} WithoutSuffix
|
||||
*/
|
||||
/**
|
||||
* @template {string} K
|
||||
* @template {string} S
|
||||
* @typedef {K extends `${infer _Prefix}${S}${infer _Suffix}` ? never : K} ExcludeSubstring
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {"cumulative-"} CumulativePrefix
|
||||
* @typedef {"-30d-change"} _30DChageSubString
|
||||
* @typedef {StartsWith<CumulativePrefix>} CumulativeVecId
|
||||
* @typedef {WithoutPrefix<CumulativeVecId, CumulativePrefix>} CumulativeVecIdBase
|
||||
* @typedef {"-sum"} SumSuffix
|
||||
* @typedef {EndsWith<SumSuffix>} VecIdSum
|
||||
* @typedef {WithoutSuffix<VecIdSum, SumSuffix>} VecIdSumBase
|
||||
* @typedef {ExcludeSubstring<WithoutPrefix<CumulativeVecId, CumulativePrefix>, _30DChageSubString>} CumulativeVecIdBase
|
||||
* @typedef {"-average"} AverageSuffix
|
||||
* @typedef {EndsWith<AverageSuffix>} VecIdAverage
|
||||
* @typedef {WithoutSuffix<VecIdAverage, AverageSuffix>} VecIdAverageBase
|
||||
@@ -162,15 +165,16 @@ function createPartialOptions(colors) {
|
||||
*/
|
||||
|
||||
const averages = /** @type {const} */ ([
|
||||
{ name: "1 Week", key: "1w", days: 7, color: colors.orange },
|
||||
{ name: "8 Day", key: "8d", days: 8, color: colors.amber },
|
||||
{ name: "13 Day", key: "13d", days: 13, color: colors.yellow },
|
||||
{ name: "21 Day", key: "21d", days: 21, color: colors.lime },
|
||||
{ name: "1 Month", key: "1m", days: 30, color: colors.green },
|
||||
{ name: "34 Day", key: "34d", days: 34, color: colors.emerald },
|
||||
{ name: "55 Day", key: "55d", days: 55, color: colors.teal },
|
||||
{ name: "89 Day", key: "89d", days: 89, color: colors.cyan },
|
||||
{ name: "144 Day", key: "144d", days: 144, color: colors.sky },
|
||||
{ name: "1 Week", key: "1w", days: 7, color: colors.red },
|
||||
{ name: "8 Day", key: "8d", days: 8, color: colors.orange },
|
||||
{ name: "13 Day", key: "13d", days: 13, color: colors.amber },
|
||||
{ name: "21 Day", key: "21d", days: 21, color: colors.yellow },
|
||||
{ name: "1 Month", key: "1m", days: 30, color: colors.lime },
|
||||
{ name: "34 Day", key: "34d", days: 34, color: colors.green },
|
||||
{ name: "55 Day", key: "55d", days: 55, color: colors.emerald },
|
||||
{ name: "89 Day", key: "89d", days: 89, color: colors.teal },
|
||||
{ name: "144 Day", key: "144d", days: 144, color: colors.cyan },
|
||||
{ name: "200 Day", key: "200d", days: 200, color: colors.sky },
|
||||
{ name: "1 Year", key: "1y", days: 365, color: colors.blue },
|
||||
{ name: "2 Year", key: "2y", days: 2 * 365, color: colors.indigo },
|
||||
{ name: "200 Week", key: "200w", days: 200 * 7, color: colors.violet },
|
||||
@@ -206,7 +210,7 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
]);
|
||||
|
||||
const upTo = /** @type {const} */ ([
|
||||
const upToDate = /** @type {const} */ ([
|
||||
{
|
||||
key: "up-to-1d",
|
||||
name: "1d",
|
||||
@@ -317,7 +321,7 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
]);
|
||||
|
||||
const from = /** @type {const} */ ([
|
||||
const fromDate = /** @type {const} */ ([
|
||||
{
|
||||
key: "from-1d",
|
||||
name: "1d",
|
||||
@@ -428,7 +432,7 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
]);
|
||||
|
||||
const range = /** @type {const} */ ([
|
||||
const dateRange = /** @type {const} */ ([
|
||||
{
|
||||
key: "start-to-1d",
|
||||
name: "24h",
|
||||
@@ -800,6 +804,66 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
]);
|
||||
|
||||
const cointimePrices = /** @type {const} */ ([
|
||||
{
|
||||
key: `vaulted-price`,
|
||||
name: "Vaulted",
|
||||
title: "Vaulted Price",
|
||||
color: colors.lime,
|
||||
},
|
||||
{
|
||||
key: `active-price`,
|
||||
name: "Active",
|
||||
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",
|
||||
title: "Cointime Price",
|
||||
color: colors.yellow,
|
||||
},
|
||||
]);
|
||||
|
||||
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: `active-cap`,
|
||||
name: "Active",
|
||||
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,
|
||||
},
|
||||
]);
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {VecId} args.key
|
||||
@@ -831,13 +895,13 @@ function createPartialOptions(colors) {
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {VecIdSumBase & CumulativeVecIdBase} args.concat
|
||||
* @param {CumulativeVecIdBase} args.concat
|
||||
* @param {string} [args.name]
|
||||
*/
|
||||
function createSumCumulativeSeries({ concat, name }) {
|
||||
return /** @satisfies {AnyFetchedSeriesBlueprint[]} */ ([
|
||||
{
|
||||
key: `${concat}-sum`,
|
||||
key: concat,
|
||||
title: name ? `${name} Sum` : "Sum",
|
||||
color: colors.orange,
|
||||
},
|
||||
@@ -902,7 +966,7 @@ function createPartialOptions(colors) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VecIdAverageBase & VecIdSumBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} key
|
||||
* @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} key
|
||||
*/
|
||||
function createAverageSumCumulativeMinMaxPercentilesSeries(key) {
|
||||
return [
|
||||
@@ -914,7 +978,7 @@ function createPartialOptions(colors) {
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {VecId & VecIdAverageBase & VecIdSumBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.key
|
||||
* @param {VecId & VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.key
|
||||
* @param {string} args.name
|
||||
*/
|
||||
function createBaseAverageSumCumulativeMinMaxPercentilesSeries({
|
||||
@@ -932,7 +996,7 @@ function createPartialOptions(colors) {
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {VecId & VecIdSumBase & CumulativeVecIdBase} args.key
|
||||
* @param {VecId & CumulativeVecIdBase} args.key
|
||||
* @param {string} args.name
|
||||
*/
|
||||
function createBaseSumCumulativeSeries({ key, name }) {
|
||||
@@ -1057,12 +1121,6 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
},
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}-ratio-sma`,
|
||||
name: "sma",
|
||||
color: colors.yellow,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}-ratio-p1sd`,
|
||||
name: "+1σ",
|
||||
@@ -1153,6 +1211,18 @@ function createPartialOptions(colors) {
|
||||
color: colors.rose,
|
||||
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.yellow,
|
||||
defaultActive: false,
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}-ratio-1y-sma-momentum-oscillator`,
|
||||
title: "1Y Momentum",
|
||||
@@ -1165,7 +1235,7 @@ function createPartialOptions(colors) {
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}-ratio-zscore`,
|
||||
title: "Score",
|
||||
title: "All time",
|
||||
type: "Baseline",
|
||||
options: {
|
||||
createPriceLine: {
|
||||
@@ -1173,6 +1243,17 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
key: `${key}-ratio-4y-zscore`,
|
||||
title: "4y",
|
||||
type: "Baseline",
|
||||
colors: [colors.yellow, colors.pink],
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
}
|
||||
@@ -1434,19 +1515,170 @@ function createPartialOptions(colors) {
|
||||
name: "Profit",
|
||||
color: colors.green,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `cumulative-${fixKey(args.key)}realized-profit`,
|
||||
name: "Cumulative Profit",
|
||||
color: colors.green,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${fixKey(args.key)}realized-loss`,
|
||||
name: "Loss",
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `cumulative-${fixKey(args.key)}realized-loss`,
|
||||
name: "Cumulative Loss",
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${fixKey(args.key)}negative-realized-loss`,
|
||||
name: "Negative Loss",
|
||||
color: colors.red,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `cumulative-${fixKey(
|
||||
args.key
|
||||
)}negative-realized-loss`,
|
||||
name: "Cumulative Negative Loss",
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(
|
||||
args.key
|
||||
)}realized-profit-relative-to-realized-cap`,
|
||||
title: "Profit",
|
||||
color: colors.green,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(
|
||||
args.key
|
||||
)}realized-loss-relative-to-realized-cap`,
|
||||
title: "Loss",
|
||||
color: colors.red,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Net pnl",
|
||||
title: `${args.title} Net Realized Profit And Loss`,
|
||||
bottom: list.flatMap(({ color, name, key }) => [
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(key)}net-realized-profit-and-loss`,
|
||||
title: "Net",
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `cumulative-${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss`,
|
||||
title: "Cumulative net",
|
||||
defaultActive: false,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `cumulative-${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss-30d-change`,
|
||||
title: "cum net 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,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `cumulative-${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss-30d-change-relative-to-realized-cap`,
|
||||
title: "cum net 30d change",
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `cumulative-${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss-30d-change-relative-to-market-cap`,
|
||||
title: "cum net 30d change",
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "sopr",
|
||||
title: `${args.title} Spent Output Profit Ratio`,
|
||||
bottom: list.flatMap(({ color, name, key }) => [
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(key)}spent-output-profit-ratio`,
|
||||
title: "sopr",
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(key)}adjusted-spent-output-profit-ratio`,
|
||||
title: "asopr",
|
||||
colors: [colors.yellow, colors.pink],
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 1,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]),
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
@@ -1457,8 +1689,19 @@ function createPartialOptions(colors) {
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
key: `${key}realized-profit`,
|
||||
name: useGroupName ? name : "Profit",
|
||||
color: useGroupName ? color : colors.green,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${key}realized-profit-relative-to-realized-cap`,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
@@ -1471,75 +1714,151 @@ function createPartialOptions(colors) {
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
key: `${key}realized-loss`,
|
||||
name: useGroupName ? name : "Loss",
|
||||
color: useGroupName ? color : colors.red,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${key}realized-loss-relative-to-realized-cap`,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
},
|
||||
]),
|
||||
{
|
||||
name: "Net pnl",
|
||||
title: `${args.title} Net Realized Profit And Loss`,
|
||||
bottom: list.flatMap(({ color, name, key }) => [
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(key)}net-realized-profit-and-loss`,
|
||||
title: useGroupName ? name : "Net",
|
||||
color: useGroupName ? color : undefined,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss-relative-to-realized-cap`,
|
||||
title: useGroupName ? name : "Net",
|
||||
color: useGroupName ? color : undefined,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]),
|
||||
},
|
||||
...(!("list" in args)
|
||||
? [
|
||||
{
|
||||
name: "sopr",
|
||||
title: `${args.title} Spent Output Profit Ratio`,
|
||||
name: "Net pnl",
|
||||
title: `${args.title} Net Realized Profit And Loss`,
|
||||
bottom: list.flatMap(({ color, name, key }) => [
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(key)}spent-output-profit-ratio`,
|
||||
title: useGroupName ? name : "sopr",
|
||||
color: useGroupName ? color : undefined,
|
||||
key: `${fixKey(key)}net-realized-profit-and-loss`,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 1,
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(key)}adjusted-spent-output-profit-ratio`,
|
||||
title: useGroupName ? name : "asopr",
|
||||
color: useGroupName ? color : undefined,
|
||||
key: `${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss-relative-to-realized-cap`,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 1,
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]),
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
name: "cumulative",
|
||||
tree: [
|
||||
{
|
||||
name: "profit",
|
||||
title: `Cumulative ${args.title} Realized Profit`,
|
||||
bottom: list.flatMap(({ color, name, key: _key }) => {
|
||||
const key = fixKey(_key);
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
key: `cumulative-${key}realized-profit`,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "loss",
|
||||
title: `Cumulative ${args.title} Realized Loss`,
|
||||
bottom: list.flatMap(({ color, name, key: _key }) => {
|
||||
const key = fixKey(_key);
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
key: `cumulative-${key}realized-loss`,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "Net pnl",
|
||||
title: `Cumulative ${args.title} Net Realized Profit And Loss`,
|
||||
bottom: list.flatMap(({ color, name, key }) => [
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `cumulative-${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss`,
|
||||
title: name,
|
||||
color,
|
||||
defaultActive: false,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]),
|
||||
},
|
||||
{
|
||||
name: "Net pnl 30d change",
|
||||
title: `Cumulative ${args.title} Net Realized Profit And Loss 30 Day Change`,
|
||||
bottom: list.flatMap(({ color, name, key }) => [
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `cumulative-${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss-30d-change`,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `cumulative-${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss-30d-change-relative-to-realized-cap`,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `cumulative-${fixKey(
|
||||
key
|
||||
)}net-realized-profit-and-loss-30d-change-relative-to-market-cap`,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
}),
|
||||
]),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "sopr",
|
||||
tree: [
|
||||
@@ -1550,8 +1869,8 @@ function createPartialOptions(colors) {
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(key)}spent-output-profit-ratio`,
|
||||
title: useGroupName ? name : "sopr",
|
||||
color: useGroupName ? color : undefined,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 1,
|
||||
@@ -1569,8 +1888,8 @@ function createPartialOptions(colors) {
|
||||
key: `${fixKey(
|
||||
key
|
||||
)}adjusted-spent-output-profit-ratio`,
|
||||
title: useGroupName ? name : "asopr",
|
||||
color: useGroupName ? color : undefined,
|
||||
title: name,
|
||||
color,
|
||||
options: {
|
||||
createPriceLine: {
|
||||
value: 1,
|
||||
@@ -1776,13 +2095,25 @@ function createPartialOptions(colors) {
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
key: `${key}coinblocks-destroyed`,
|
||||
name: useGroupName ? name : "destroyed",
|
||||
name: useGroupName ? name : "sum",
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}coindays-destroyed`,
|
||||
name: useGroupName ? name : "destroyed",
|
||||
key: `cumulative-${key}coinblocks-destroyed`,
|
||||
name: useGroupName ? name : "cumulative",
|
||||
color,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}coindays-destroyed`,
|
||||
name: useGroupName ? name : "sum",
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `cumulative-${key}coindays-destroyed`,
|
||||
name: useGroupName ? name : "cumulative",
|
||||
color,
|
||||
defaultActive: false,
|
||||
}),
|
||||
]);
|
||||
}),
|
||||
@@ -1904,6 +2235,32 @@ function createPartialOptions(colors) {
|
||||
],
|
||||
})),
|
||||
},
|
||||
{
|
||||
name: "Indicators",
|
||||
tree: [
|
||||
{
|
||||
name: "Mayer multiple",
|
||||
title: "Mayer multiple",
|
||||
top: [
|
||||
createBaseSeries({
|
||||
key: `200d-sma`,
|
||||
name: "200d sma",
|
||||
color: colors.yellow,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `200d-sma-x2-4`,
|
||||
name: "200d sma x2.4",
|
||||
color: colors.green,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `200d-sma-x0-8`,
|
||||
name: "200d sma x0.8",
|
||||
color: colors.red,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -2618,9 +2975,9 @@ function createPartialOptions(colors) {
|
||||
createUTXOGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Up To",
|
||||
list: upTo,
|
||||
list: upToDate,
|
||||
}),
|
||||
...upTo.map(createUTXOGroupFolder),
|
||||
...upToDate.map(createUTXOGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -2629,9 +2986,9 @@ function createPartialOptions(colors) {
|
||||
createUTXOGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By From",
|
||||
list: from,
|
||||
list: fromDate,
|
||||
}),
|
||||
...from.map(createUTXOGroupFolder),
|
||||
...fromDate.map(createUTXOGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -2640,9 +2997,9 @@ function createPartialOptions(colors) {
|
||||
createUTXOGroupFolder({
|
||||
name: "Compare",
|
||||
title: "Compare By Range",
|
||||
list: range,
|
||||
list: dateRange,
|
||||
}),
|
||||
...range.map(createUTXOGroupFolder),
|
||||
...dateRange.map(createUTXOGroupFolder),
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -2732,7 +3089,7 @@ function createPartialOptions(colors) {
|
||||
bottom: [
|
||||
createBaseSeries({ key: "opreturn-count", name: "Count" }),
|
||||
createBaseSeries({
|
||||
key: "opreturn-count-sum",
|
||||
key: "opreturn-count",
|
||||
name: "sum",
|
||||
}),
|
||||
createBaseSeries({
|
||||
@@ -2764,6 +3121,182 @@ function createPartialOptions(colors) {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Cointime",
|
||||
tree: [
|
||||
{
|
||||
name: "Coinblocks",
|
||||
title: "Coinblocks",
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key: "coinblocks-destroyed",
|
||||
name: "Destroyed",
|
||||
color: colors.red,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "cumulative-coinblocks-destroyed",
|
||||
name: "Cumulative Destroyed",
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "coinblocks-created",
|
||||
name: "created",
|
||||
color: colors.orange,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "cumulative-coinblocks-created",
|
||||
name: "Cumulative created",
|
||||
color: colors.orange,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "coinblocks-stored",
|
||||
name: "stored",
|
||||
color: colors.green,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "cumulative-coinblocks-stored",
|
||||
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: "all",
|
||||
color: colors.orange,
|
||||
},
|
||||
{
|
||||
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,
|
||||
}),
|
||||
])
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Capitalization",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Compare Cointime Capitalizations",
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key: `marketcap`,
|
||||
name: "Market",
|
||||
color: colors.default,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `realized-cap`,
|
||||
name: "Realized",
|
||||
color: colors.orange,
|
||||
}),
|
||||
...cointimeCapitalizations.map(({ key, name, color }) =>
|
||||
createBaseSeries({
|
||||
key,
|
||||
name,
|
||||
color,
|
||||
})
|
||||
),
|
||||
],
|
||||
},
|
||||
...cointimeCapitalizations.map(
|
||||
({ key, name, color, title }) => ({
|
||||
name,
|
||||
title,
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `marketcap`,
|
||||
name: "Market",
|
||||
color: colors.default,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `realized-cap`,
|
||||
name: "Realized",
|
||||
color: colors.orange,
|
||||
}),
|
||||
],
|
||||
})
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Prices",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: "Compare Cointime Prices",
|
||||
top: cointimePrices.map(({ key, name, color }) =>
|
||||
createBaseSeries({
|
||||
key,
|
||||
name,
|
||||
color,
|
||||
})
|
||||
),
|
||||
},
|
||||
...cointimePrices.map(({ key, name, color, title }) =>
|
||||
createPriceWithRatio({
|
||||
key,
|
||||
legend: name,
|
||||
color,
|
||||
name,
|
||||
title,
|
||||
})
|
||||
),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user