mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-02 02:20:00 -07:00
website: snapshot
This commit is contained in:
@@ -131,7 +131,8 @@ def _p(prefix: str, acc: str) -> str:
|
||||
pub fn generate_endpoint_class(output: &mut String) {
|
||||
writeln!(
|
||||
output,
|
||||
r#"class MetricData(TypedDict, Generic[T]):
|
||||
r#"@dataclass
|
||||
class MetricData(Generic[T]):
|
||||
"""Metric data with range information."""
|
||||
version: int
|
||||
total: int
|
||||
@@ -176,8 +177,9 @@ class _EndpointConfig:
|
||||
p = self.path()
|
||||
return f"{{p}}?{{query}}" if query else p
|
||||
|
||||
def get_json(self) -> Any:
|
||||
return self.client.get_json(self._build_path())
|
||||
def get_json(self) -> MetricData:
|
||||
data = self.client.get_json(self._build_path())
|
||||
return MetricData(**data)
|
||||
|
||||
def get_csv(self) -> str:
|
||||
return self.client.get_text(self._build_path(format='csv'))
|
||||
@@ -376,7 +378,7 @@ pub fn generate_index_accessors(output: &mut String, patterns: &[IndexSetPattern
|
||||
// Generate helper function
|
||||
writeln!(
|
||||
output,
|
||||
r#"def _ep(c: BrkClientBase, n: str, i: Index) -> MetricEndpointBuilder:
|
||||
r#"def _ep(c: BrkClientBase, n: str, i: Index) -> MetricEndpointBuilder[Any]:
|
||||
return MetricEndpointBuilder(c, n, i)
|
||||
"#
|
||||
)
|
||||
@@ -409,6 +411,7 @@ pub fn generate_index_accessors(output: &mut String, patterns: &[IndexSetPattern
|
||||
|
||||
// Generate the main accessor class
|
||||
writeln!(output, "class {}(Generic[T]):", pattern.name).unwrap();
|
||||
writeln!(output, " by: {}[T]", by_class_name).unwrap();
|
||||
writeln!(
|
||||
output,
|
||||
" def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, {}(c, n)",
|
||||
|
||||
@@ -24,12 +24,18 @@ pub fn generate_python_client(
|
||||
|
||||
writeln!(output, "# Auto-generated BRK Python client").unwrap();
|
||||
writeln!(output, "# Do not edit manually\n").unwrap();
|
||||
writeln!(output, "from __future__ import annotations").unwrap();
|
||||
writeln!(output, "from dataclasses import dataclass").unwrap();
|
||||
writeln!(
|
||||
output,
|
||||
"from typing import TypeVar, Generic, Any, Optional, List, Literal, TypedDict, Union, Protocol, overload"
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, "from http.client import HTTPSConnection, HTTPConnection").unwrap();
|
||||
writeln!(
|
||||
output,
|
||||
"from http.client import HTTPSConnection, HTTPConnection"
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(output, "from urllib.parse import urlparse").unwrap();
|
||||
writeln!(output, "import json\n").unwrap();
|
||||
writeln!(output, "T = TypeVar('T')\n").unwrap();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,8 +38,8 @@ impl UTXOCohorts {
|
||||
) -> Result<Self> {
|
||||
let v = version + VERSION;
|
||||
|
||||
// Phase 1: Import base cohorts that don't need adjusted (age_range, amount_range, etc.)
|
||||
// These are the source cohorts for overlapping computations.
|
||||
// Phase 1: Import base cohorts for overlapping computations (age_range, amount_range).
|
||||
// These are the source cohorts and must be imported before "all" to provide up_to_1h.
|
||||
let base = |f: Filter, name: &'static str| {
|
||||
UTXOCohortVecs::forced_import(
|
||||
db,
|
||||
@@ -57,9 +57,6 @@ impl UTXOCohorts {
|
||||
|
||||
let age_range = ByAgeRange::try_new(&base)?;
|
||||
let amount_range = ByAmountRange::try_new(&base)?;
|
||||
let epoch = ByEpoch::try_new(&base)?;
|
||||
let year = ByYear::try_new(&base)?;
|
||||
let type_ = BySpendableType::try_new(&base)?;
|
||||
|
||||
// Get up_to_1h realized for adjusted computation (cohort - up_to_1h)
|
||||
let up_to_1h_realized = age_range.up_to_1h.metrics.realized.as_ref();
|
||||
@@ -80,7 +77,27 @@ impl UTXOCohorts {
|
||||
|
||||
let all_supply = Some(&all.metrics.supply);
|
||||
|
||||
// Phase 3: Import cohorts that need adjusted and/or all_supply
|
||||
// Phase 3: Import cohorts that need all_supply but not adjusted (epoch, year, type)
|
||||
let base_with_all_supply = |f: Filter, name: &'static str| {
|
||||
UTXOCohortVecs::forced_import(
|
||||
db,
|
||||
f,
|
||||
name,
|
||||
v,
|
||||
indexes,
|
||||
price,
|
||||
states_path,
|
||||
StateLevel::Full,
|
||||
all_supply,
|
||||
None,
|
||||
)
|
||||
};
|
||||
|
||||
let epoch = ByEpoch::try_new(&base_with_all_supply)?;
|
||||
let year = ByYear::try_new(&base_with_all_supply)?;
|
||||
let type_ = BySpendableType::try_new(&base_with_all_supply)?;
|
||||
|
||||
// Phase 4: Import cohorts that need all_supply and up_to_1h for adjusted
|
||||
let price_only_adjusted = |f: Filter, name: &'static str| {
|
||||
UTXOCohortVecs::forced_import(
|
||||
db,
|
||||
@@ -115,7 +132,17 @@ impl UTXOCohorts {
|
||||
|
||||
let max_age = ByMaxAge::try_new(&none_adjusted)?;
|
||||
|
||||
// Phase 4: Import remaining cohorts (no adjusted needed)
|
||||
// Phase 5: Add rel_to_circulating metrics to base cohorts now that up_to_1h_realized is no longer borrowed
|
||||
let mut age_range = age_range;
|
||||
let mut amount_range = amount_range;
|
||||
for (vecs, name) in age_range.iter_mut().zip(ByAgeRange::names().iter()) {
|
||||
vecs.add_rel_to_circulating(name.id, v, all_supply.unwrap());
|
||||
}
|
||||
for (vecs, name) in amount_range.iter_mut().zip(ByAmountRange::names().iter()) {
|
||||
vecs.add_rel_to_circulating(name.id, v, all_supply.unwrap());
|
||||
}
|
||||
|
||||
// Phase 6: Import remaining cohorts (no adjusted needed)
|
||||
let none = |f: Filter, name: &'static str| {
|
||||
UTXOCohortVecs::forced_import(
|
||||
db,
|
||||
|
||||
@@ -80,6 +80,19 @@ impl UTXOCohortVecs {
|
||||
})
|
||||
}
|
||||
|
||||
/// Add relative-to-circulating-supply metrics in a second step.
|
||||
/// Called after the "all" cohort is available.
|
||||
pub fn add_rel_to_circulating(
|
||||
&mut self,
|
||||
name: &str,
|
||||
version: Version,
|
||||
all_supply: &SupplyMetrics,
|
||||
) {
|
||||
let full_name = CohortContext::Utxo.full_name(self.filter(), name);
|
||||
self.metrics
|
||||
.add_rel_to_circulating(&full_name, version, all_supply);
|
||||
}
|
||||
|
||||
/// Get the starting height when state was imported.
|
||||
pub fn state_starting_height(&self) -> Option<Height> {
|
||||
self.state_starting_height
|
||||
|
||||
@@ -333,6 +333,28 @@ impl CohortMetrics {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add relative-to-circulating-supply metrics in a second step.
|
||||
/// Called after the "all" cohort is available.
|
||||
pub fn add_rel_to_circulating(
|
||||
&mut self,
|
||||
full_name: &str,
|
||||
version: Version,
|
||||
all_supply: &SupplyMetrics,
|
||||
) {
|
||||
if let (Some(relative), Some(unrealized)) =
|
||||
(self.relative.as_mut(), self.unrealized.as_ref())
|
||||
{
|
||||
relative.add_rel_to_circulating(
|
||||
&self.filter,
|
||||
full_name,
|
||||
version,
|
||||
unrealized,
|
||||
&self.supply,
|
||||
all_supply,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Second phase of computed metrics (ratios, relative values).
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn compute_rest_part2(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use brk_cohort::Filter;
|
||||
use brk_error::Result;
|
||||
use brk_traversable::Traversable;
|
||||
use brk_types::{Dollars, Sats, StoredF32, StoredF64, Version};
|
||||
@@ -352,4 +353,95 @@ impl RelativeMetrics {
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
/// Add relative-to-circulating-supply metrics in a second step.
|
||||
/// Called after the "all" cohort is available to provide global supply sources.
|
||||
pub fn add_rel_to_circulating(
|
||||
&mut self,
|
||||
filter: &Filter,
|
||||
full_name: &str,
|
||||
version: Version,
|
||||
unrealized: &UnrealizedMetrics,
|
||||
supply: &SupplyMetrics,
|
||||
all_supply: &SupplyMetrics,
|
||||
) {
|
||||
let v1 = Version::ONE;
|
||||
|
||||
// Skip if this is the "all" cohort itself
|
||||
if !filter.compute_rel_to_all() {
|
||||
return;
|
||||
}
|
||||
|
||||
let name = |suffix: &str| {
|
||||
if full_name.is_empty() {
|
||||
suffix.to_string()
|
||||
} else {
|
||||
format!("{full_name}_{suffix}")
|
||||
}
|
||||
};
|
||||
|
||||
// Global sources from "all" cohort
|
||||
let global_supply_sats_height = &all_supply.total.sats.height;
|
||||
let global_supply_sats_difficultyepoch = &all_supply.total.sats.difficultyepoch;
|
||||
let global_supply_sats_dates = &all_supply.total.sats.rest.dates;
|
||||
let global_supply_sats_dateindex = &all_supply.total.sats.rest.dateindex;
|
||||
|
||||
// Fill in supply_rel_to_circulating_supply if not already set
|
||||
if self.supply_rel_to_circulating_supply.is_none() {
|
||||
self.supply_rel_to_circulating_supply = Some(
|
||||
LazyBinaryFromDateLast::from_both_derived_last::<PercentageSatsF64>(
|
||||
&name("supply_rel_to_circulating_supply"),
|
||||
version + v1,
|
||||
supply.total.sats.rest.dateindex.boxed_clone(),
|
||||
&supply.total.sats.rest.dates,
|
||||
global_supply_sats_dateindex.boxed_clone(),
|
||||
global_supply_sats_dates,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Fill in supply_in_profit_rel_to_circulating_supply if not already set
|
||||
if self.supply_in_profit_rel_to_circulating_supply.is_none() {
|
||||
self.supply_in_profit_rel_to_circulating_supply = Some(
|
||||
LazyBinaryFromHeightLast::from_height_difficultyepoch_dates::<PercentageSatsF64>(
|
||||
&name("supply_in_profit_rel_to_circulating_supply"),
|
||||
version + v1,
|
||||
unrealized.supply_in_profit.height.boxed_clone(),
|
||||
global_supply_sats_height.boxed_clone(),
|
||||
unrealized.supply_in_profit.difficultyepoch.sats.boxed_clone(),
|
||||
global_supply_sats_difficultyepoch.boxed_clone(),
|
||||
unrealized
|
||||
.supply_in_profit
|
||||
.indexes
|
||||
.sats_dateindex
|
||||
.boxed_clone(),
|
||||
&unrealized.supply_in_profit.indexes.sats,
|
||||
global_supply_sats_dateindex.boxed_clone(),
|
||||
global_supply_sats_dates,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Fill in supply_in_loss_rel_to_circulating_supply if not already set
|
||||
if self.supply_in_loss_rel_to_circulating_supply.is_none() {
|
||||
self.supply_in_loss_rel_to_circulating_supply = Some(
|
||||
LazyBinaryFromHeightLast::from_height_difficultyepoch_dates::<PercentageSatsF64>(
|
||||
&name("supply_in_loss_rel_to_circulating_supply"),
|
||||
version + v1,
|
||||
unrealized.supply_in_loss.height.boxed_clone(),
|
||||
global_supply_sats_height.boxed_clone(),
|
||||
unrealized.supply_in_loss.difficultyepoch.sats.boxed_clone(),
|
||||
global_supply_sats_difficultyepoch.boxed_clone(),
|
||||
unrealized
|
||||
.supply_in_loss
|
||||
.indexes
|
||||
.sats_dateindex
|
||||
.boxed_clone(),
|
||||
&unrealized.supply_in_loss.indexes.sats,
|
||||
global_supply_sats_dateindex.boxed_clone(),
|
||||
global_supply_sats_dates,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ pub struct Vecs {
|
||||
pub _1w_dominance: LazyBinaryFromHeightLast<StoredF32, StoredU32, StoredU32>,
|
||||
pub _1m_dominance: LazyBinaryFromHeightLast<StoredF32, StoredU32, StoredU32>,
|
||||
pub _1y_dominance: LazyBinaryFromHeightLast<StoredF32, StoredU32, StoredU32>,
|
||||
pub blocks_since_block: ComputedFromHeightLast<StoredU32>,
|
||||
pub days_since_block: ComputedFromDateLast<StoredU16>,
|
||||
}
|
||||
|
||||
@@ -128,6 +129,12 @@ impl Vecs {
|
||||
>(&suffix("coinbase"), version, &subsidy, &fee),
|
||||
subsidy,
|
||||
fee,
|
||||
blocks_since_block: ComputedFromHeightLast::forced_import(
|
||||
db,
|
||||
&suffix("blocks_since_block"),
|
||||
version,
|
||||
indexes,
|
||||
)?,
|
||||
days_since_block: ComputedFromDateLast::forced_import(
|
||||
db,
|
||||
&suffix("days_since_block"),
|
||||
@@ -211,6 +218,26 @@ impl Vecs {
|
||||
|
||||
self.fee.derive_from(indexes, starting_indexes, exit)?;
|
||||
|
||||
self.blocks_since_block
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
let mut prev = StoredU32::ZERO;
|
||||
v.compute_transform(
|
||||
starting_indexes.height,
|
||||
blocks_mined_height,
|
||||
|(h, mined, ..)| {
|
||||
let blocks = if mined.is_zero() {
|
||||
prev + StoredU32::ONE
|
||||
} else {
|
||||
StoredU32::ZERO
|
||||
};
|
||||
prev = blocks;
|
||||
(h, blocks)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.days_since_block
|
||||
.compute_all(starting_indexes, exit, |v| {
|
||||
let mut prev = None;
|
||||
|
||||
@@ -40,3 +40,15 @@ path = "examples/tune_smooth.rs"
|
||||
[[example]]
|
||||
name = "debug_oracle"
|
||||
path = "examples/debug_oracle.rs"
|
||||
|
||||
[[example]]
|
||||
name = "filters"
|
||||
path = "examples/filters.rs"
|
||||
|
||||
[[example]]
|
||||
name = "stencil"
|
||||
path = "examples/stencil.rs"
|
||||
|
||||
[[example]]
|
||||
name = "epoch5_test"
|
||||
path = "examples/epoch5_test.rs"
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
JavaScript/TypeScript client for the [Bitcoin Research Kit](https://github.com/bitcoinresearchkit/brk) API.
|
||||
|
||||
Zero dependencies.
|
||||
|
||||
[npm](https://www.npmjs.com/package/brk-client) | [API Reference](https://github.com/bitcoinresearchkit/brk/blob/main/modules/brk-client/docs/globals.md)
|
||||
|
||||
## Installation
|
||||
@@ -10,6 +12,8 @@ JavaScript/TypeScript client for the [Bitcoin Research Kit](https://github.com/b
|
||||
npm install brk-client
|
||||
```
|
||||
|
||||
Or just copy [`index.js`](./index.js) into your project - it's a single file with no dependencies.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```javascript
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
3.12
|
||||
3.9
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
Python client for the [Bitcoin Research Kit](https://github.com/bitcoinresearchkit/brk) API.
|
||||
|
||||
Requires Python 3.9+. Zero dependencies.
|
||||
|
||||
[PyPI](https://pypi.org/project/brk-client/) | [API Reference](https://github.com/bitcoinresearchkit/brk/blob/main/packages/brk_client/DOCS.md)
|
||||
|
||||
## Installation
|
||||
@@ -12,6 +14,8 @@ pip install brk-client
|
||||
uv add brk-client
|
||||
```
|
||||
|
||||
Or just copy [`brk_client/__init__.py`](./brk_client/__init__.py) into your project - it's a single file with no dependencies.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Auto-generated BRK Python client
|
||||
# Do not edit manually
|
||||
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from typing import TypeVar, Generic, Any, Optional, List, Literal, TypedDict, Union, Protocol, overload
|
||||
from http.client import HTTPSConnection, HTTPConnection
|
||||
from urllib.parse import urlparse
|
||||
@@ -1039,7 +1041,8 @@ def _p(prefix: str, acc: str) -> str:
|
||||
return f"{prefix}_{acc}" if acc else prefix
|
||||
|
||||
|
||||
class MetricData(TypedDict, Generic[T]):
|
||||
@dataclass
|
||||
class MetricData(Generic[T]):
|
||||
"""Metric data with range information."""
|
||||
version: int
|
||||
total: int
|
||||
@@ -1084,8 +1087,9 @@ class _EndpointConfig:
|
||||
p = self.path()
|
||||
return f"{p}?{query}" if query else p
|
||||
|
||||
def get_json(self) -> Any:
|
||||
return self.client.get_json(self._build_path())
|
||||
def get_json(self) -> MetricData:
|
||||
data = self.client.get_json(self._build_path())
|
||||
return MetricData(**data)
|
||||
|
||||
def get_csv(self) -> str:
|
||||
return self.client.get_text(self._build_path(format='csv'))
|
||||
@@ -1288,7 +1292,7 @@ _i31 = ('loadedaddressindex',)
|
||||
_i32 = ('emptyaddressindex',)
|
||||
_i33 = ('pairoutputindex',)
|
||||
|
||||
def _ep(c: BrkClientBase, n: str, i: Index) -> MetricEndpointBuilder:
|
||||
def _ep(c: BrkClientBase, n: str, i: Index) -> MetricEndpointBuilder[Any]:
|
||||
return MetricEndpointBuilder(c, n, i)
|
||||
|
||||
# Index accessor classes
|
||||
@@ -1306,6 +1310,7 @@ class _MetricPattern1By(Generic[T]):
|
||||
def yearindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'yearindex')
|
||||
|
||||
class MetricPattern1(Generic[T]):
|
||||
by: _MetricPattern1By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern1By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1324,6 +1329,7 @@ class _MetricPattern2By(Generic[T]):
|
||||
def yearindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'yearindex')
|
||||
|
||||
class MetricPattern2(Generic[T]):
|
||||
by: _MetricPattern2By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern2By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1342,6 +1348,7 @@ class _MetricPattern3By(Generic[T]):
|
||||
def yearindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'yearindex')
|
||||
|
||||
class MetricPattern3(Generic[T]):
|
||||
by: _MetricPattern3By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern3By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1359,6 +1366,7 @@ class _MetricPattern4By(Generic[T]):
|
||||
def yearindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'yearindex')
|
||||
|
||||
class MetricPattern4(Generic[T]):
|
||||
by: _MetricPattern4By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern4By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1371,6 +1379,7 @@ class _MetricPattern5By(Generic[T]):
|
||||
def height(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'height')
|
||||
|
||||
class MetricPattern5(Generic[T]):
|
||||
by: _MetricPattern5By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern5By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1382,6 +1391,7 @@ class _MetricPattern6By(Generic[T]):
|
||||
def dateindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'dateindex')
|
||||
|
||||
class MetricPattern6(Generic[T]):
|
||||
by: _MetricPattern6By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern6By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1393,6 +1403,7 @@ class _MetricPattern7By(Generic[T]):
|
||||
def decadeindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'decadeindex')
|
||||
|
||||
class MetricPattern7(Generic[T]):
|
||||
by: _MetricPattern7By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern7By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1404,6 +1415,7 @@ class _MetricPattern8By(Generic[T]):
|
||||
def difficultyepoch(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'difficultyepoch')
|
||||
|
||||
class MetricPattern8(Generic[T]):
|
||||
by: _MetricPattern8By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern8By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1415,6 +1427,7 @@ class _MetricPattern9By(Generic[T]):
|
||||
def emptyoutputindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'emptyoutputindex')
|
||||
|
||||
class MetricPattern9(Generic[T]):
|
||||
by: _MetricPattern9By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern9By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1426,6 +1439,7 @@ class _MetricPattern10By(Generic[T]):
|
||||
def halvingepoch(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'halvingepoch')
|
||||
|
||||
class MetricPattern10(Generic[T]):
|
||||
by: _MetricPattern10By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern10By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1437,6 +1451,7 @@ class _MetricPattern11By(Generic[T]):
|
||||
def height(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'height')
|
||||
|
||||
class MetricPattern11(Generic[T]):
|
||||
by: _MetricPattern11By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern11By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1448,6 +1463,7 @@ class _MetricPattern12By(Generic[T]):
|
||||
def txinindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'txinindex')
|
||||
|
||||
class MetricPattern12(Generic[T]):
|
||||
by: _MetricPattern12By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern12By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1459,6 +1475,7 @@ class _MetricPattern13By(Generic[T]):
|
||||
def monthindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'monthindex')
|
||||
|
||||
class MetricPattern13(Generic[T]):
|
||||
by: _MetricPattern13By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern13By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1470,6 +1487,7 @@ class _MetricPattern14By(Generic[T]):
|
||||
def opreturnindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'opreturnindex')
|
||||
|
||||
class MetricPattern14(Generic[T]):
|
||||
by: _MetricPattern14By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern14By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1481,6 +1499,7 @@ class _MetricPattern15By(Generic[T]):
|
||||
def txoutindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'txoutindex')
|
||||
|
||||
class MetricPattern15(Generic[T]):
|
||||
by: _MetricPattern15By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern15By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1492,6 +1511,7 @@ class _MetricPattern16By(Generic[T]):
|
||||
def p2aaddressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2aaddressindex')
|
||||
|
||||
class MetricPattern16(Generic[T]):
|
||||
by: _MetricPattern16By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern16By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1503,6 +1523,7 @@ class _MetricPattern17By(Generic[T]):
|
||||
def p2msoutputindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2msoutputindex')
|
||||
|
||||
class MetricPattern17(Generic[T]):
|
||||
by: _MetricPattern17By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern17By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1514,6 +1535,7 @@ class _MetricPattern18By(Generic[T]):
|
||||
def p2pk33addressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2pk33addressindex')
|
||||
|
||||
class MetricPattern18(Generic[T]):
|
||||
by: _MetricPattern18By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern18By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1525,6 +1547,7 @@ class _MetricPattern19By(Generic[T]):
|
||||
def p2pk65addressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2pk65addressindex')
|
||||
|
||||
class MetricPattern19(Generic[T]):
|
||||
by: _MetricPattern19By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern19By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1536,6 +1559,7 @@ class _MetricPattern20By(Generic[T]):
|
||||
def p2pkhaddressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2pkhaddressindex')
|
||||
|
||||
class MetricPattern20(Generic[T]):
|
||||
by: _MetricPattern20By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern20By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1547,6 +1571,7 @@ class _MetricPattern21By(Generic[T]):
|
||||
def p2shaddressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2shaddressindex')
|
||||
|
||||
class MetricPattern21(Generic[T]):
|
||||
by: _MetricPattern21By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern21By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1558,6 +1583,7 @@ class _MetricPattern22By(Generic[T]):
|
||||
def p2traddressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2traddressindex')
|
||||
|
||||
class MetricPattern22(Generic[T]):
|
||||
by: _MetricPattern22By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern22By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1569,6 +1595,7 @@ class _MetricPattern23By(Generic[T]):
|
||||
def p2wpkhaddressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2wpkhaddressindex')
|
||||
|
||||
class MetricPattern23(Generic[T]):
|
||||
by: _MetricPattern23By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern23By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1580,6 +1607,7 @@ class _MetricPattern24By(Generic[T]):
|
||||
def p2wshaddressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'p2wshaddressindex')
|
||||
|
||||
class MetricPattern24(Generic[T]):
|
||||
by: _MetricPattern24By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern24By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1591,6 +1619,7 @@ class _MetricPattern25By(Generic[T]):
|
||||
def quarterindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'quarterindex')
|
||||
|
||||
class MetricPattern25(Generic[T]):
|
||||
by: _MetricPattern25By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern25By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1602,6 +1631,7 @@ class _MetricPattern26By(Generic[T]):
|
||||
def semesterindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'semesterindex')
|
||||
|
||||
class MetricPattern26(Generic[T]):
|
||||
by: _MetricPattern26By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern26By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1613,6 +1643,7 @@ class _MetricPattern27By(Generic[T]):
|
||||
def txindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'txindex')
|
||||
|
||||
class MetricPattern27(Generic[T]):
|
||||
by: _MetricPattern27By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern27By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1624,6 +1655,7 @@ class _MetricPattern28By(Generic[T]):
|
||||
def unknownoutputindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'unknownoutputindex')
|
||||
|
||||
class MetricPattern28(Generic[T]):
|
||||
by: _MetricPattern28By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern28By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1635,6 +1667,7 @@ class _MetricPattern29By(Generic[T]):
|
||||
def weekindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'weekindex')
|
||||
|
||||
class MetricPattern29(Generic[T]):
|
||||
by: _MetricPattern29By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern29By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1646,6 +1679,7 @@ class _MetricPattern30By(Generic[T]):
|
||||
def yearindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'yearindex')
|
||||
|
||||
class MetricPattern30(Generic[T]):
|
||||
by: _MetricPattern30By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern30By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1657,6 +1691,7 @@ class _MetricPattern31By(Generic[T]):
|
||||
def loadedaddressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'loadedaddressindex')
|
||||
|
||||
class MetricPattern31(Generic[T]):
|
||||
by: _MetricPattern31By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern31By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1668,6 +1703,7 @@ class _MetricPattern32By(Generic[T]):
|
||||
def emptyaddressindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'emptyaddressindex')
|
||||
|
||||
class MetricPattern32(Generic[T]):
|
||||
by: _MetricPattern32By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern32By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1679,6 +1715,7 @@ class _MetricPattern33By(Generic[T]):
|
||||
def pairoutputindex(self) -> MetricEndpointBuilder[T]: return _ep(self._c, self._n, 'pairoutputindex')
|
||||
|
||||
class MetricPattern33(Generic[T]):
|
||||
by: _MetricPattern33By[T]
|
||||
def __init__(self, c: BrkClientBase, n: str): self._n, self.by = n, _MetricPattern33By(c, n)
|
||||
@property
|
||||
def name(self) -> str: return self._n
|
||||
@@ -1973,12 +2010,32 @@ class AaopoolPattern:
|
||||
self._24h_blocks_mined: MetricPattern1[StoredU32] = MetricPattern1(client, _m(acc, '24h_blocks_mined'))
|
||||
self._24h_dominance: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, '24h_dominance'))
|
||||
self.blocks_mined: BlockCountPattern[StoredU32] = BlockCountPattern(client, _m(acc, 'blocks_mined'))
|
||||
self.blocks_since_block: MetricPattern1[StoredU32] = MetricPattern1(client, _m(acc, 'blocks_since_block'))
|
||||
self.coinbase: CoinbasePattern2 = CoinbasePattern2(client, _m(acc, 'coinbase'))
|
||||
self.days_since_block: MetricPattern4[StoredU16] = MetricPattern4(client, _m(acc, 'days_since_block'))
|
||||
self.dominance: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'dominance'))
|
||||
self.fee: UnclaimedRewardsPattern = UnclaimedRewardsPattern(client, _m(acc, 'fee'))
|
||||
self.subsidy: UnclaimedRewardsPattern = UnclaimedRewardsPattern(client, _m(acc, 'subsidy'))
|
||||
|
||||
class RelativePattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap'))
|
||||
self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl'))
|
||||
self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap'))
|
||||
self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl'))
|
||||
self.supply_in_loss_rel_to_circulating_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_circulating_supply'))
|
||||
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply'))
|
||||
self.supply_in_profit_rel_to_circulating_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_circulating_supply'))
|
||||
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply'))
|
||||
self.supply_rel_to_circulating_supply: MetricPattern4[StoredF64] = MetricPattern4(client, _m(acc, 'supply_rel_to_circulating_supply'))
|
||||
self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap'))
|
||||
self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl'))
|
||||
self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap'))
|
||||
self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl'))
|
||||
|
||||
class LookbackPattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2016,6 +2073,24 @@ class PeriodLumpSumStackPattern:
|
||||
self._6y: _2015Pattern = _2015Pattern(client, _p('6y', acc))
|
||||
self._8y: _2015Pattern = _2015Pattern(client, _p('8y', acc))
|
||||
|
||||
class ClassAveragePricePattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_average_price'))
|
||||
self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_average_price'))
|
||||
self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_average_price'))
|
||||
self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_average_price'))
|
||||
self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_average_price'))
|
||||
self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_average_price'))
|
||||
self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_average_price'))
|
||||
self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_average_price'))
|
||||
self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_average_price'))
|
||||
self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_average_price'))
|
||||
self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_average_price'))
|
||||
self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2026_average_price'))
|
||||
|
||||
class PeriodAveragePricePattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2034,24 +2109,6 @@ class PeriodAveragePricePattern(Generic[T]):
|
||||
self._6y: MetricPattern4[T] = MetricPattern4(client, _p('6y', acc))
|
||||
self._8y: MetricPattern4[T] = MetricPattern4(client, _p('8y', acc))
|
||||
|
||||
class ClassAveragePricePattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_returns'))
|
||||
self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_returns'))
|
||||
self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_returns'))
|
||||
self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_returns'))
|
||||
self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_returns'))
|
||||
self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_returns'))
|
||||
self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_returns'))
|
||||
self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_returns'))
|
||||
self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_returns'))
|
||||
self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_returns'))
|
||||
self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_returns'))
|
||||
self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2026_returns'))
|
||||
|
||||
class BitcoinPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2102,22 +2159,6 @@ class RelativePattern:
|
||||
self.unrealized_loss_rel_to_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_market_cap'))
|
||||
self.unrealized_profit_rel_to_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_market_cap'))
|
||||
|
||||
class RelativePattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap'))
|
||||
self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl'))
|
||||
self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap'))
|
||||
self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl'))
|
||||
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply'))
|
||||
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply'))
|
||||
self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap'))
|
||||
self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl'))
|
||||
self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap'))
|
||||
self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl'))
|
||||
|
||||
class CountPattern2(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2149,21 +2190,6 @@ class AddrCountPattern:
|
||||
self.p2wpkh: MetricPattern1[StoredU64] = MetricPattern1(client, _p('p2wpkh', acc))
|
||||
self.p2wsh: MetricPattern1[StoredU64] = MetricPattern1(client, _p('p2wsh', acc))
|
||||
|
||||
class FullnessPattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'average'))
|
||||
self.base: MetricPattern11[T] = MetricPattern11(client, acc)
|
||||
self.max: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'max'))
|
||||
self.median: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'median'))
|
||||
self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min'))
|
||||
self.pct10: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct10'))
|
||||
self.pct25: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct25'))
|
||||
self.pct75: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct75'))
|
||||
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
|
||||
|
||||
class FeeRatePattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2179,6 +2205,21 @@ class FeeRatePattern(Generic[T]):
|
||||
self.pct90: MetricPattern11[T] = MetricPattern11(client, _m(acc, 'pct90'))
|
||||
self.txindex: MetricPattern27[T] = MetricPattern27(client, acc)
|
||||
|
||||
class FullnessPattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.average: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'average'))
|
||||
self.base: MetricPattern11[T] = MetricPattern11(client, acc)
|
||||
self.max: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'max'))
|
||||
self.median: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'median'))
|
||||
self.min: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'min'))
|
||||
self.pct10: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct10'))
|
||||
self.pct25: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct25'))
|
||||
self.pct75: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct75'))
|
||||
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
|
||||
|
||||
class _0satsPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2207,18 +2248,18 @@ class PhaseDailyCentsPattern(Generic[T]):
|
||||
self.pct75: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct75'))
|
||||
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
|
||||
|
||||
class _10yTo12yPattern:
|
||||
class PeriodCagrPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: ActivityPattern2 = ActivityPattern2(client, acc)
|
||||
self.cost_basis: CostBasisPattern2 = CostBasisPattern2(client, acc)
|
||||
self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: RealizedPattern2 = RealizedPattern2(client, acc)
|
||||
self.relative: RelativePattern2 = RelativePattern2(client, acc)
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
self._10y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('10y', acc))
|
||||
self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('2y', acc))
|
||||
self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('3y', acc))
|
||||
self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('4y', acc))
|
||||
self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('5y', acc))
|
||||
self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc))
|
||||
self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc))
|
||||
|
||||
class UnrealizedPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2242,11 +2283,11 @@ class _0satsPattern2:
|
||||
self.cost_basis: CostBasisPattern = CostBasisPattern(client, acc)
|
||||
self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: RealizedPattern = RealizedPattern(client, acc)
|
||||
self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply_in'))
|
||||
self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply'))
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class _100btcPattern:
|
||||
class _0Pattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
@@ -2259,19 +2300,6 @@ class _100btcPattern:
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class PeriodCagrPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self._10y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('10y', acc))
|
||||
self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('2y', acc))
|
||||
self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('3y', acc))
|
||||
self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('4y', acc))
|
||||
self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('5y', acc))
|
||||
self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc))
|
||||
self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc))
|
||||
|
||||
class _10yPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2285,6 +2313,30 @@ class _10yPattern:
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class _10yTo12yPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.activity: ActivityPattern2 = ActivityPattern2(client, acc)
|
||||
self.cost_basis: CostBasisPattern2 = CostBasisPattern2(client, acc)
|
||||
self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count'))
|
||||
self.realized: RealizedPattern2 = RealizedPattern2(client, acc)
|
||||
self.relative: RelativePattern2 = RelativePattern2(client, acc)
|
||||
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
|
||||
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
|
||||
|
||||
class RelativePattern4:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.supply_in_loss_rel_to_circulating_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'in_loss_rel_to_circulating_supply'))
|
||||
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'in_loss_rel_to_own_supply'))
|
||||
self.supply_in_profit_rel_to_circulating_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'in_profit_rel_to_circulating_supply'))
|
||||
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'in_profit_rel_to_own_supply'))
|
||||
self.supply_rel_to_circulating_supply: MetricPattern4[StoredF64] = MetricPattern4(client, _m(acc, 'rel_to_circulating_supply'))
|
||||
|
||||
class ActivityPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2306,15 +2358,6 @@ class SplitPattern2(Generic[T]):
|
||||
self.low: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'low'))
|
||||
self.open: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'open'))
|
||||
|
||||
class SegwitAdoptionPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc)
|
||||
self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative'))
|
||||
self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum'))
|
||||
|
||||
class UnclaimedRewardsPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2324,42 +2367,6 @@ class UnclaimedRewardsPattern:
|
||||
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
||||
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
||||
|
||||
class ActiveSupplyPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: MetricPattern1[Bitcoin] = MetricPattern1(client, _m(acc, 'btc'))
|
||||
self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'usd'))
|
||||
self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc)
|
||||
|
||||
class CoinbasePattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: BlockCountPattern[Bitcoin] = BlockCountPattern(client, _m(acc, 'btc'))
|
||||
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
||||
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
||||
|
||||
class CostBasisPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.max: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis'))
|
||||
self.min: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis'))
|
||||
self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis'))
|
||||
|
||||
class _2015Pattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: MetricPattern4[Bitcoin] = MetricPattern4(client, _m(acc, 'btc'))
|
||||
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd'))
|
||||
self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc)
|
||||
|
||||
class CoinbasePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2369,29 +2376,50 @@ class CoinbasePattern:
|
||||
self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, 'usd'))
|
||||
self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc)
|
||||
|
||||
class RelativePattern4:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'loss_rel_to_own_supply'))
|
||||
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'profit_rel_to_own_supply'))
|
||||
|
||||
class _1dReturns1mSdPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd'))
|
||||
self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma'))
|
||||
|
||||
class CostBasisPattern:
|
||||
class CostBasisPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.max: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis'))
|
||||
self.min: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis'))
|
||||
self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis'))
|
||||
|
||||
class ActiveSupplyPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: MetricPattern1[Bitcoin] = MetricPattern1(client, _m(acc, 'btc'))
|
||||
self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'usd'))
|
||||
self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc)
|
||||
|
||||
class _2015Pattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: MetricPattern4[Bitcoin] = MetricPattern4(client, _m(acc, 'btc'))
|
||||
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd'))
|
||||
self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc)
|
||||
|
||||
class SegwitAdoptionPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc)
|
||||
self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative'))
|
||||
self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum'))
|
||||
|
||||
class CoinbasePattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.bitcoin: BlockCountPattern[Bitcoin] = BlockCountPattern(client, _m(acc, 'btc'))
|
||||
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
|
||||
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
|
||||
|
||||
class SupplyPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2401,6 +2429,22 @@ class SupplyPattern2:
|
||||
self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved'))
|
||||
self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc)
|
||||
|
||||
class CostBasisPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.max: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'max_cost_basis'))
|
||||
self.min: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'min_cost_basis'))
|
||||
|
||||
class _1dReturns1mSdPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd'))
|
||||
self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma'))
|
||||
|
||||
class SatsPattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2409,14 +2453,6 @@ class SatsPattern(Generic[T]):
|
||||
self.ohlc: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'ohlc_sats'))
|
||||
self.split: SplitPattern2[T] = SplitPattern2(client, _m(acc, 'sats'))
|
||||
|
||||
class BitcoinPattern2(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.cumulative: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'cumulative'))
|
||||
self.sum: MetricPattern1[T] = MetricPattern1(client, acc)
|
||||
|
||||
class BlockCountPattern(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2425,6 +2461,14 @@ class BlockCountPattern(Generic[T]):
|
||||
self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative'))
|
||||
self.sum: MetricPattern1[T] = MetricPattern1(client, acc)
|
||||
|
||||
class BitcoinPattern2(Generic[T]):
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.cumulative: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'cumulative'))
|
||||
self.sum: MetricPattern1[T] = MetricPattern1(client, acc)
|
||||
|
||||
class OutputsPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
@@ -2842,47 +2886,47 @@ class MetricsTree_Distribution_UtxoCohorts_Epoch:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._0: _0satsPattern2 = _0satsPattern2(client, 'epoch_0')
|
||||
self._1: _0satsPattern2 = _0satsPattern2(client, 'epoch_1')
|
||||
self._2: _0satsPattern2 = _0satsPattern2(client, 'epoch_2')
|
||||
self._3: _0satsPattern2 = _0satsPattern2(client, 'epoch_3')
|
||||
self._4: _0satsPattern2 = _0satsPattern2(client, 'epoch_4')
|
||||
self._0: _0Pattern = _0Pattern(client, 'epoch_0')
|
||||
self._1: _0Pattern = _0Pattern(client, 'epoch_1')
|
||||
self._2: _0Pattern = _0Pattern(client, 'epoch_2')
|
||||
self._3: _0Pattern = _0Pattern(client, 'epoch_3')
|
||||
self._4: _0Pattern = _0Pattern(client, 'epoch_4')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_GeAmount:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._100btc: _100btcPattern = _100btcPattern(client, 'utxos_above_100btc')
|
||||
self._100k_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_100k_sats')
|
||||
self._100sats: _100btcPattern = _100btcPattern(client, 'utxos_above_100sats')
|
||||
self._10btc: _100btcPattern = _100btcPattern(client, 'utxos_above_10btc')
|
||||
self._10k_btc: _100btcPattern = _100btcPattern(client, 'utxos_above_10k_btc')
|
||||
self._10k_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_10k_sats')
|
||||
self._10m_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_10m_sats')
|
||||
self._10sats: _100btcPattern = _100btcPattern(client, 'utxos_above_10sats')
|
||||
self._1btc: _100btcPattern = _100btcPattern(client, 'utxos_above_1btc')
|
||||
self._1k_btc: _100btcPattern = _100btcPattern(client, 'utxos_above_1k_btc')
|
||||
self._1k_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_1k_sats')
|
||||
self._1m_sats: _100btcPattern = _100btcPattern(client, 'utxos_above_1m_sats')
|
||||
self._1sat: _100btcPattern = _100btcPattern(client, 'utxos_above_1sat')
|
||||
self._100btc: _0Pattern = _0Pattern(client, 'utxos_above_100btc')
|
||||
self._100k_sats: _0Pattern = _0Pattern(client, 'utxos_above_100k_sats')
|
||||
self._100sats: _0Pattern = _0Pattern(client, 'utxos_above_100sats')
|
||||
self._10btc: _0Pattern = _0Pattern(client, 'utxos_above_10btc')
|
||||
self._10k_btc: _0Pattern = _0Pattern(client, 'utxos_above_10k_btc')
|
||||
self._10k_sats: _0Pattern = _0Pattern(client, 'utxos_above_10k_sats')
|
||||
self._10m_sats: _0Pattern = _0Pattern(client, 'utxos_above_10m_sats')
|
||||
self._10sats: _0Pattern = _0Pattern(client, 'utxos_above_10sats')
|
||||
self._1btc: _0Pattern = _0Pattern(client, 'utxos_above_1btc')
|
||||
self._1k_btc: _0Pattern = _0Pattern(client, 'utxos_above_1k_btc')
|
||||
self._1k_sats: _0Pattern = _0Pattern(client, 'utxos_above_1k_sats')
|
||||
self._1m_sats: _0Pattern = _0Pattern(client, 'utxos_above_1m_sats')
|
||||
self._1sat: _0Pattern = _0Pattern(client, 'utxos_above_1sat')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_LtAmount:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._100btc: _100btcPattern = _100btcPattern(client, 'utxos_under_100btc')
|
||||
self._100k_btc: _100btcPattern = _100btcPattern(client, 'utxos_under_100k_btc')
|
||||
self._100k_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_100k_sats')
|
||||
self._100sats: _100btcPattern = _100btcPattern(client, 'utxos_under_100sats')
|
||||
self._10btc: _100btcPattern = _100btcPattern(client, 'utxos_under_10btc')
|
||||
self._10k_btc: _100btcPattern = _100btcPattern(client, 'utxos_under_10k_btc')
|
||||
self._10k_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_10k_sats')
|
||||
self._10m_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_10m_sats')
|
||||
self._10sats: _100btcPattern = _100btcPattern(client, 'utxos_under_10sats')
|
||||
self._1btc: _100btcPattern = _100btcPattern(client, 'utxos_under_1btc')
|
||||
self._1k_btc: _100btcPattern = _100btcPattern(client, 'utxos_under_1k_btc')
|
||||
self._1k_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_1k_sats')
|
||||
self._1m_sats: _100btcPattern = _100btcPattern(client, 'utxos_under_1m_sats')
|
||||
self._100btc: _0Pattern = _0Pattern(client, 'utxos_under_100btc')
|
||||
self._100k_btc: _0Pattern = _0Pattern(client, 'utxos_under_100k_btc')
|
||||
self._100k_sats: _0Pattern = _0Pattern(client, 'utxos_under_100k_sats')
|
||||
self._100sats: _0Pattern = _0Pattern(client, 'utxos_under_100sats')
|
||||
self._10btc: _0Pattern = _0Pattern(client, 'utxos_under_10btc')
|
||||
self._10k_btc: _0Pattern = _0Pattern(client, 'utxos_under_10k_btc')
|
||||
self._10k_sats: _0Pattern = _0Pattern(client, 'utxos_under_10k_sats')
|
||||
self._10m_sats: _0Pattern = _0Pattern(client, 'utxos_under_10m_sats')
|
||||
self._10sats: _0Pattern = _0Pattern(client, 'utxos_under_10sats')
|
||||
self._1btc: _0Pattern = _0Pattern(client, 'utxos_under_1btc')
|
||||
self._1k_btc: _0Pattern = _0Pattern(client, 'utxos_under_1k_btc')
|
||||
self._1k_sats: _0Pattern = _0Pattern(client, 'utxos_under_1k_sats')
|
||||
self._1m_sats: _0Pattern = _0Pattern(client, 'utxos_under_1m_sats')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_MaxAge:
|
||||
"""Metrics tree node."""
|
||||
@@ -2911,24 +2955,24 @@ class MetricsTree_Distribution_UtxoCohorts_MinAge:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._10y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_10y_old')
|
||||
self._12y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_12y_old')
|
||||
self._1d: _100btcPattern = _100btcPattern(client, 'utxos_at_least_1d_old')
|
||||
self._1m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_1m_old')
|
||||
self._1w: _100btcPattern = _100btcPattern(client, 'utxos_at_least_1w_old')
|
||||
self._1y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_1y_old')
|
||||
self._2m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_2m_old')
|
||||
self._2y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_2y_old')
|
||||
self._3m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_3m_old')
|
||||
self._3y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_3y_old')
|
||||
self._4m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_4m_old')
|
||||
self._4y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_4y_old')
|
||||
self._5m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_5m_old')
|
||||
self._5y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_5y_old')
|
||||
self._6m: _100btcPattern = _100btcPattern(client, 'utxos_at_least_6m_old')
|
||||
self._6y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_6y_old')
|
||||
self._7y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_7y_old')
|
||||
self._8y: _100btcPattern = _100btcPattern(client, 'utxos_at_least_8y_old')
|
||||
self._10y: _0Pattern = _0Pattern(client, 'utxos_at_least_10y_old')
|
||||
self._12y: _0Pattern = _0Pattern(client, 'utxos_at_least_12y_old')
|
||||
self._1d: _0Pattern = _0Pattern(client, 'utxos_at_least_1d_old')
|
||||
self._1m: _0Pattern = _0Pattern(client, 'utxos_at_least_1m_old')
|
||||
self._1w: _0Pattern = _0Pattern(client, 'utxos_at_least_1w_old')
|
||||
self._1y: _0Pattern = _0Pattern(client, 'utxos_at_least_1y_old')
|
||||
self._2m: _0Pattern = _0Pattern(client, 'utxos_at_least_2m_old')
|
||||
self._2y: _0Pattern = _0Pattern(client, 'utxos_at_least_2y_old')
|
||||
self._3m: _0Pattern = _0Pattern(client, 'utxos_at_least_3m_old')
|
||||
self._3y: _0Pattern = _0Pattern(client, 'utxos_at_least_3y_old')
|
||||
self._4m: _0Pattern = _0Pattern(client, 'utxos_at_least_4m_old')
|
||||
self._4y: _0Pattern = _0Pattern(client, 'utxos_at_least_4y_old')
|
||||
self._5m: _0Pattern = _0Pattern(client, 'utxos_at_least_5m_old')
|
||||
self._5y: _0Pattern = _0Pattern(client, 'utxos_at_least_5y_old')
|
||||
self._6m: _0Pattern = _0Pattern(client, 'utxos_at_least_6m_old')
|
||||
self._6y: _0Pattern = _0Pattern(client, 'utxos_at_least_6y_old')
|
||||
self._7y: _0Pattern = _0Pattern(client, 'utxos_at_least_7y_old')
|
||||
self._8y: _0Pattern = _0Pattern(client, 'utxos_at_least_8y_old')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Term_Long:
|
||||
"""Metrics tree node."""
|
||||
@@ -2965,40 +3009,40 @@ class MetricsTree_Distribution_UtxoCohorts_Type:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.empty: _0satsPattern2 = _0satsPattern2(client, 'empty_outputs')
|
||||
self.p2a: _0satsPattern2 = _0satsPattern2(client, 'p2a')
|
||||
self.p2ms: _0satsPattern2 = _0satsPattern2(client, 'p2ms')
|
||||
self.p2pk33: _0satsPattern2 = _0satsPattern2(client, 'p2pk33')
|
||||
self.p2pk65: _0satsPattern2 = _0satsPattern2(client, 'p2pk65')
|
||||
self.p2pkh: _0satsPattern2 = _0satsPattern2(client, 'p2pkh')
|
||||
self.p2sh: _0satsPattern2 = _0satsPattern2(client, 'p2sh')
|
||||
self.p2tr: _0satsPattern2 = _0satsPattern2(client, 'p2tr')
|
||||
self.p2wpkh: _0satsPattern2 = _0satsPattern2(client, 'p2wpkh')
|
||||
self.p2wsh: _0satsPattern2 = _0satsPattern2(client, 'p2wsh')
|
||||
self.unknown: _0satsPattern2 = _0satsPattern2(client, 'unknown_outputs')
|
||||
self.empty: _0Pattern = _0Pattern(client, 'empty_outputs')
|
||||
self.p2a: _0Pattern = _0Pattern(client, 'p2a')
|
||||
self.p2ms: _0Pattern = _0Pattern(client, 'p2ms')
|
||||
self.p2pk33: _0Pattern = _0Pattern(client, 'p2pk33')
|
||||
self.p2pk65: _0Pattern = _0Pattern(client, 'p2pk65')
|
||||
self.p2pkh: _0Pattern = _0Pattern(client, 'p2pkh')
|
||||
self.p2sh: _0Pattern = _0Pattern(client, 'p2sh')
|
||||
self.p2tr: _0Pattern = _0Pattern(client, 'p2tr')
|
||||
self.p2wpkh: _0Pattern = _0Pattern(client, 'p2wpkh')
|
||||
self.p2wsh: _0Pattern = _0Pattern(client, 'p2wsh')
|
||||
self.unknown: _0Pattern = _0Pattern(client, 'unknown_outputs')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts_Year:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._2009: _0satsPattern2 = _0satsPattern2(client, 'year_2009')
|
||||
self._2010: _0satsPattern2 = _0satsPattern2(client, 'year_2010')
|
||||
self._2011: _0satsPattern2 = _0satsPattern2(client, 'year_2011')
|
||||
self._2012: _0satsPattern2 = _0satsPattern2(client, 'year_2012')
|
||||
self._2013: _0satsPattern2 = _0satsPattern2(client, 'year_2013')
|
||||
self._2014: _0satsPattern2 = _0satsPattern2(client, 'year_2014')
|
||||
self._2015: _0satsPattern2 = _0satsPattern2(client, 'year_2015')
|
||||
self._2016: _0satsPattern2 = _0satsPattern2(client, 'year_2016')
|
||||
self._2017: _0satsPattern2 = _0satsPattern2(client, 'year_2017')
|
||||
self._2018: _0satsPattern2 = _0satsPattern2(client, 'year_2018')
|
||||
self._2019: _0satsPattern2 = _0satsPattern2(client, 'year_2019')
|
||||
self._2020: _0satsPattern2 = _0satsPattern2(client, 'year_2020')
|
||||
self._2021: _0satsPattern2 = _0satsPattern2(client, 'year_2021')
|
||||
self._2022: _0satsPattern2 = _0satsPattern2(client, 'year_2022')
|
||||
self._2023: _0satsPattern2 = _0satsPattern2(client, 'year_2023')
|
||||
self._2024: _0satsPattern2 = _0satsPattern2(client, 'year_2024')
|
||||
self._2025: _0satsPattern2 = _0satsPattern2(client, 'year_2025')
|
||||
self._2026: _0satsPattern2 = _0satsPattern2(client, 'year_2026')
|
||||
self._2009: _0Pattern = _0Pattern(client, 'year_2009')
|
||||
self._2010: _0Pattern = _0Pattern(client, 'year_2010')
|
||||
self._2011: _0Pattern = _0Pattern(client, 'year_2011')
|
||||
self._2012: _0Pattern = _0Pattern(client, 'year_2012')
|
||||
self._2013: _0Pattern = _0Pattern(client, 'year_2013')
|
||||
self._2014: _0Pattern = _0Pattern(client, 'year_2014')
|
||||
self._2015: _0Pattern = _0Pattern(client, 'year_2015')
|
||||
self._2016: _0Pattern = _0Pattern(client, 'year_2016')
|
||||
self._2017: _0Pattern = _0Pattern(client, 'year_2017')
|
||||
self._2018: _0Pattern = _0Pattern(client, 'year_2018')
|
||||
self._2019: _0Pattern = _0Pattern(client, 'year_2019')
|
||||
self._2020: _0Pattern = _0Pattern(client, 'year_2020')
|
||||
self._2021: _0Pattern = _0Pattern(client, 'year_2021')
|
||||
self._2022: _0Pattern = _0Pattern(client, 'year_2022')
|
||||
self._2023: _0Pattern = _0Pattern(client, 'year_2023')
|
||||
self._2024: _0Pattern = _0Pattern(client, 'year_2024')
|
||||
self._2025: _0Pattern = _0Pattern(client, 'year_2025')
|
||||
self._2026: _0Pattern = _0Pattern(client, 'year_2026')
|
||||
|
||||
class MetricsTree_Distribution_UtxoCohorts:
|
||||
"""Metrics tree node."""
|
||||
@@ -3282,22 +3326,22 @@ class MetricsTree_Market_Ath:
|
||||
self.price_drawdown: MetricPattern3[StoredF32] = MetricPattern3(client, 'price_drawdown')
|
||||
self.years_since_price_ath: MetricPattern4[StoredF32] = MetricPattern4(client, 'years_since_price_ath')
|
||||
|
||||
class MetricsTree_Market_Dca_ClassAveragePrice:
|
||||
class MetricsTree_Market_Dca_ClassReturns:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self._2015: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2015_average_price')
|
||||
self._2016: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2016_average_price')
|
||||
self._2017: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2017_average_price')
|
||||
self._2018: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2018_average_price')
|
||||
self._2019: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2019_average_price')
|
||||
self._2020: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2020_average_price')
|
||||
self._2021: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2021_average_price')
|
||||
self._2022: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2022_average_price')
|
||||
self._2023: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2023_average_price')
|
||||
self._2024: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2024_average_price')
|
||||
self._2025: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2025_average_price')
|
||||
self._2026: MetricPattern4[Dollars] = MetricPattern4(client, 'dca_class_2026_average_price')
|
||||
self._2015: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2015_returns')
|
||||
self._2016: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2016_returns')
|
||||
self._2017: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2017_returns')
|
||||
self._2018: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2018_returns')
|
||||
self._2019: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2019_returns')
|
||||
self._2020: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2020_returns')
|
||||
self._2021: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2021_returns')
|
||||
self._2022: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2022_returns')
|
||||
self._2023: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2023_returns')
|
||||
self._2024: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2024_returns')
|
||||
self._2025: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2025_returns')
|
||||
self._2026: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2026_returns')
|
||||
|
||||
class MetricsTree_Market_Dca_ClassStack:
|
||||
"""Metrics tree node."""
|
||||
@@ -3320,8 +3364,8 @@ class MetricsTree_Market_Dca:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.class_average_price: MetricsTree_Market_Dca_ClassAveragePrice = MetricsTree_Market_Dca_ClassAveragePrice(client)
|
||||
self.class_returns: ClassAveragePricePattern[StoredF32] = ClassAveragePricePattern(client, 'dca_class')
|
||||
self.class_average_price: ClassAveragePricePattern[Dollars] = ClassAveragePricePattern(client, 'dca_class')
|
||||
self.class_returns: MetricsTree_Market_Dca_ClassReturns = MetricsTree_Market_Dca_ClassReturns(client)
|
||||
self.class_stack: MetricsTree_Market_Dca_ClassStack = MetricsTree_Market_Dca_ClassStack(client)
|
||||
self.period_average_price: PeriodAveragePricePattern[Dollars] = PeriodAveragePricePattern(client, 'dca_average_price')
|
||||
self.period_cagr: PeriodCagrPattern = PeriodCagrPattern(client, 'dca_cagr')
|
||||
|
||||
@@ -3,7 +3,7 @@ name = "brk-client"
|
||||
version = "0.1.0-alpha.6"
|
||||
description = "Python client for the Bitcoin Research Kit"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
requires-python = ">=3.9"
|
||||
license = "MIT"
|
||||
keywords = ["bitcoin", "blockchain", "analytics", "on-chain"]
|
||||
classifiers = [
|
||||
@@ -11,6 +11,8 @@ classifiers = [
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
|
||||
@@ -67,32 +67,65 @@ function getLightDarkValue(property) {
|
||||
return dark ? _dark : light;
|
||||
}
|
||||
|
||||
const red = createColor(() => getColor("red"));
|
||||
const orange = createColor(() => getColor("orange"));
|
||||
const amber = createColor(() => getColor("amber"));
|
||||
const yellow = createColor(() => getColor("yellow"));
|
||||
const avocado = createColor(() => getColor("avocado"));
|
||||
const lime = createColor(() => getColor("lime"));
|
||||
const green = createColor(() => getColor("green"));
|
||||
const emerald = createColor(() => getColor("emerald"));
|
||||
const teal = createColor(() => getColor("teal"));
|
||||
const cyan = createColor(() => getColor("cyan"));
|
||||
const sky = createColor(() => getColor("sky"));
|
||||
const blue = createColor(() => getColor("blue"));
|
||||
const indigo = createColor(() => getColor("indigo"));
|
||||
const violet = createColor(() => getColor("violet"));
|
||||
const purple = createColor(() => getColor("purple"));
|
||||
const fuchsia = createColor(() => getColor("fuchsia"));
|
||||
const pink = createColor(() => getColor("pink"));
|
||||
const rose = createColor(() => getColor("rose"));
|
||||
|
||||
export const colors = {
|
||||
default: createColor(() => getLightDarkValue("--color")),
|
||||
gray: createColor(() => getColor("gray")),
|
||||
border: createColor(() => getLightDarkValue("--border-color")),
|
||||
|
||||
red: createColor(() => getColor("red")),
|
||||
orange: createColor(() => getColor("orange")),
|
||||
amber: createColor(() => getColor("amber")),
|
||||
yellow: createColor(() => getColor("yellow")),
|
||||
avocado: createColor(() => getColor("avocado")),
|
||||
lime: createColor(() => getColor("lime")),
|
||||
green: createColor(() => getColor("green")),
|
||||
emerald: createColor(() => getColor("emerald")),
|
||||
teal: createColor(() => getColor("teal")),
|
||||
cyan: createColor(() => getColor("cyan")),
|
||||
sky: createColor(() => getColor("sky")),
|
||||
blue: createColor(() => getColor("blue")),
|
||||
indigo: createColor(() => getColor("indigo")),
|
||||
violet: createColor(() => getColor("violet")),
|
||||
purple: createColor(() => getColor("purple")),
|
||||
fuchsia: createColor(() => getColor("fuchsia")),
|
||||
pink: createColor(() => getColor("pink")),
|
||||
rose: createColor(() => getColor("rose")),
|
||||
red,
|
||||
orange,
|
||||
amber,
|
||||
yellow,
|
||||
avocado,
|
||||
lime,
|
||||
green,
|
||||
emerald,
|
||||
teal,
|
||||
cyan,
|
||||
sky,
|
||||
blue,
|
||||
indigo,
|
||||
violet,
|
||||
purple,
|
||||
fuchsia,
|
||||
pink,
|
||||
rose,
|
||||
|
||||
/** Semantic stat colors for pattern helpers */
|
||||
stat: {
|
||||
sum: blue,
|
||||
cumulative: indigo,
|
||||
avg: orange,
|
||||
max: green,
|
||||
pct90: cyan,
|
||||
pct75: blue,
|
||||
median: yellow,
|
||||
pct25: violet,
|
||||
pct10: fuchsia,
|
||||
min: red,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {typeof colors} Colors
|
||||
* @typedef {keyof Colors} ColorName
|
||||
* @typedef {Exclude<keyof Colors, "stat">} ColorName
|
||||
*/
|
||||
|
||||
@@ -219,6 +219,10 @@ export function createChart({ parent, id: chartId, brk, fitContent }) {
|
||||
? initialRange.to - initialRange.from
|
||||
: Infinity;
|
||||
|
||||
/** @param {number} count */
|
||||
const getDotsRadius = (count) =>
|
||||
count > 1000 ? 1 : count > 200 ? 1.5 : count > 100 ? 2 : 3;
|
||||
|
||||
/** @type {Set<ZoomChangeCallback>} */
|
||||
const onZoomChange = new Set();
|
||||
|
||||
@@ -1023,11 +1027,12 @@ export function createChart({ parent, id: chartId, brk, fitContent }) {
|
||||
|
||||
let active = defaultActive !== false;
|
||||
let highlighted = true;
|
||||
const showLastValue = options?.lastValueVisible !== false;
|
||||
|
||||
function update() {
|
||||
iseries.applyOptions({
|
||||
visible: active,
|
||||
lastValueVisible: highlighted,
|
||||
lastValueVisible: showLastValue && highlighted,
|
||||
color: color.highlight(highlighted),
|
||||
});
|
||||
}
|
||||
@@ -1117,21 +1122,21 @@ export function createChart({ parent, id: chartId, brk, fitContent }) {
|
||||
|
||||
let active = defaultActive !== false;
|
||||
let highlighted = true;
|
||||
let radius =
|
||||
visibleBarsCount > 1000 ? 1 : visibleBarsCount > 200 ? 1.5 : 2;
|
||||
let radius = getDotsRadius(visibleBarsCount);
|
||||
|
||||
function update() {
|
||||
iseries.applyOptions({
|
||||
visible: active,
|
||||
lastValueVisible: highlighted,
|
||||
color: color.highlight(highlighted),
|
||||
pointMarkersRadius: radius,
|
||||
});
|
||||
}
|
||||
update();
|
||||
|
||||
/** @type {ZoomChangeCallback} */
|
||||
function handleZoom(count) {
|
||||
const newRadius = count > 1000 ? 1 : count > 200 ? 1.5 : 2;
|
||||
const newRadius = getDotsRadius(count);
|
||||
if (newRadius === radius) return;
|
||||
radius = newRadius;
|
||||
iseries.applyOptions({ pointMarkersRadius: radius });
|
||||
@@ -1507,8 +1512,13 @@ export function createChart({ parent, id: chartId, brk, fitContent }) {
|
||||
}
|
||||
|
||||
const defaultUnit = units[0];
|
||||
const sortedUnitIds = units
|
||||
.map((u) => u.id)
|
||||
.sort()
|
||||
.join(",");
|
||||
const persistedUnit = createPersistedValue({
|
||||
defaultValue: /** @type {string} */ (defaultUnit.id),
|
||||
storageKey: `unit-${sortedUnitIds}`,
|
||||
urlKey: paneIndex === 0 ? "u0" : "u1",
|
||||
serialize: (v) => v,
|
||||
deserialize: (s) => s,
|
||||
|
||||
@@ -33,6 +33,7 @@ export function createChainSection(ctx) {
|
||||
market,
|
||||
scripts,
|
||||
supply,
|
||||
distribution,
|
||||
} = brk.metrics;
|
||||
|
||||
// Build pools tree dynamically
|
||||
@@ -49,10 +50,10 @@ export function createChainSection(ctx) {
|
||||
name: "Dominance",
|
||||
title: `${poolName} Dominance`,
|
||||
bottom: [
|
||||
line({
|
||||
dots({
|
||||
metric: pool._24hDominance,
|
||||
name: "24h",
|
||||
color: colors.orange,
|
||||
color: colors.pink,
|
||||
unit: Unit.percentage,
|
||||
defaultActive: false,
|
||||
}),
|
||||
@@ -88,7 +89,7 @@ export function createChainSection(ctx) {
|
||||
name: "Blocks mined",
|
||||
title: `${poolName} Blocks`,
|
||||
bottom: [
|
||||
line({
|
||||
dots({
|
||||
metric: pool.blocksMined.sum,
|
||||
name: "Sum",
|
||||
unit: Unit.count,
|
||||
@@ -98,6 +99,14 @@ export function createChainSection(ctx) {
|
||||
name: "Cumulative",
|
||||
color: colors.blue,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: pool._24hBlocksMined,
|
||||
name: "24h Sum",
|
||||
color: colors.pink,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: pool._1wBlocksMined,
|
||||
@@ -142,12 +151,17 @@ export function createChainSection(ctx) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Days since block",
|
||||
title: `${poolName} Last Block`,
|
||||
name: "Since last block",
|
||||
title: `${poolName} Since Last Block`,
|
||||
bottom: [
|
||||
line({
|
||||
metric: pool.blocksSinceBlock,
|
||||
name: "Blocks",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: pool.daysSinceBlock,
|
||||
name: "Since block",
|
||||
name: "Days",
|
||||
unit: Unit.days,
|
||||
}),
|
||||
],
|
||||
@@ -227,12 +241,35 @@ export function createChainSection(ctx) {
|
||||
title: "Transaction Count",
|
||||
bottom: fromDollarsPattern(transactions.count.txCount, Unit.count),
|
||||
},
|
||||
{
|
||||
name: "Speed",
|
||||
title: "Transactions Per Second",
|
||||
bottom: [
|
||||
dots({
|
||||
metric: transactions.volume.txPerSec,
|
||||
name: "Transactions",
|
||||
unit: Unit.perSec,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Volume",
|
||||
title: "Transaction Volume",
|
||||
bottom: [
|
||||
...satsBtcUsd(transactions.volume.sentSum, "Sent"),
|
||||
...satsBtcUsd(transactions.volume.receivedSum, "Received", colors.cyan, {
|
||||
...satsBtcUsd(
|
||||
transactions.volume.receivedSum,
|
||||
"Received",
|
||||
colors.cyan,
|
||||
{
|
||||
defaultActive: false,
|
||||
},
|
||||
),
|
||||
line({
|
||||
metric: transactions.volume.annualizedVolume.bitcoin,
|
||||
name: "annualized",
|
||||
color: colors.red,
|
||||
unit: Unit.btc,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
@@ -242,13 +279,6 @@ export function createChainSection(ctx) {
|
||||
unit: Unit.sats,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.volume.annualizedVolume.bitcoin,
|
||||
name: "annualized",
|
||||
color: colors.red,
|
||||
unit: Unit.btc,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.volume.annualizedVolume.dollars,
|
||||
name: "annualized",
|
||||
@@ -266,6 +296,11 @@ export function createChainSection(ctx) {
|
||||
...fromFeeRatePattern(transactions.size.vsize, Unit.vb),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Fee Rate",
|
||||
title: "Fee Rate",
|
||||
bottom: fromFeeRatePattern(transactions.fees.feeRate, Unit.feeRate),
|
||||
},
|
||||
{
|
||||
name: "Versions",
|
||||
title: "Transaction Versions",
|
||||
@@ -310,17 +345,6 @@ export function createChainSection(ctx) {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Speed",
|
||||
title: "Transactions Per Second",
|
||||
bottom: [
|
||||
dots({
|
||||
metric: transactions.volume.txPerSec,
|
||||
name: "Transactions",
|
||||
unit: Unit.perSec,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -356,6 +380,11 @@ export function createChainSection(ctx) {
|
||||
title: "Output Count",
|
||||
bottom: [...fromSizePattern(outputs.count.totalCount, Unit.count)],
|
||||
},
|
||||
{
|
||||
name: "OP_RETURN",
|
||||
title: "OP_RETURN Outputs",
|
||||
bottom: fromFullnessPattern(scripts.count.opreturn, Unit.count),
|
||||
},
|
||||
{
|
||||
name: "Speed",
|
||||
title: "Outputs Per Second",
|
||||
@@ -387,70 +416,99 @@ export function createChainSection(ctx) {
|
||||
],
|
||||
},
|
||||
|
||||
// Coinbase
|
||||
// Supply
|
||||
{
|
||||
name: "Coinbase",
|
||||
title: "Coinbase Rewards",
|
||||
bottom: fromCoinbasePattern(blocks.rewards.coinbase, "Coinbase"),
|
||||
},
|
||||
|
||||
// Subsidy
|
||||
{
|
||||
name: "Subsidy",
|
||||
title: "Block Subsidy",
|
||||
bottom: [
|
||||
...fromCoinbasePattern(blocks.rewards.subsidy, "Subsidy"),
|
||||
line({
|
||||
metric: blocks.rewards.subsidyDominance,
|
||||
name: "Dominance",
|
||||
color: colors.purple,
|
||||
unit: Unit.percentage,
|
||||
defaultActive: false,
|
||||
}),
|
||||
name: "Supply",
|
||||
tree: [
|
||||
{
|
||||
name: "Circulating",
|
||||
title: "Circulating Supply",
|
||||
bottom: fromSupplyPattern(supply.circulating, "Supply"),
|
||||
},
|
||||
{
|
||||
name: "Inflation",
|
||||
title: "Inflation Rate",
|
||||
bottom: [
|
||||
dots({
|
||||
metric: supply.inflation,
|
||||
name: "Rate",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Unspendable",
|
||||
title: "Unspendable Supply",
|
||||
bottom: fromValuePattern(supply.burned.unspendable),
|
||||
},
|
||||
{
|
||||
name: "OP_RETURN",
|
||||
title: "OP_RETURN Supply",
|
||||
bottom: fromValuePattern(supply.burned.opreturn),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Fee
|
||||
// Rewards
|
||||
{
|
||||
name: "Fee",
|
||||
name: "Rewards",
|
||||
tree: [
|
||||
{
|
||||
name: "Total",
|
||||
name: "Coinbase",
|
||||
title: "Coinbase Rewards",
|
||||
bottom: fromCoinbasePattern(blocks.rewards.coinbase),
|
||||
},
|
||||
{
|
||||
name: "Subsidy",
|
||||
title: "Block Subsidy",
|
||||
bottom: [
|
||||
...fromCoinbasePattern(blocks.rewards.subsidy),
|
||||
line({
|
||||
metric: blocks.rewards.subsidyDominance,
|
||||
name: "Dominance",
|
||||
color: colors.purple,
|
||||
unit: Unit.percentage,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Fee",
|
||||
title: "Transaction Fees",
|
||||
bottom: [
|
||||
line({
|
||||
metric: transactions.fees.fee.sats.sum,
|
||||
name: "Sum",
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.fee.sats.cumulative,
|
||||
name: "Cumulative",
|
||||
color: colors.blue,
|
||||
unit: Unit.sats,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.fee.bitcoin.sum,
|
||||
name: "Sum",
|
||||
name: "sum",
|
||||
unit: Unit.btc,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.fee.bitcoin.cumulative,
|
||||
name: "Cumulative",
|
||||
color: colors.blue,
|
||||
name: "cumulative",
|
||||
color: colors.stat.cumulative,
|
||||
unit: Unit.btc,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.fee.sats.sum,
|
||||
name: "sum",
|
||||
unit: Unit.sats,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.fee.sats.cumulative,
|
||||
name: "cumulative",
|
||||
color: colors.stat.cumulative,
|
||||
unit: Unit.sats,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.fee.dollars.sum,
|
||||
name: "Sum",
|
||||
name: "sum",
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.fee.dollars.cumulative,
|
||||
name: "Cumulative",
|
||||
color: colors.blue,
|
||||
name: "cumulative",
|
||||
color: colors.stat.cumulative,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
@@ -464,64 +522,98 @@ export function createChainSection(ctx) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Rate",
|
||||
title: "Fee Rate",
|
||||
bottom: [
|
||||
line({
|
||||
metric: transactions.fees.feeRate.median,
|
||||
name: "Median",
|
||||
color: colors.purple,
|
||||
unit: Unit.feeRate,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.feeRate.average,
|
||||
name: "Average",
|
||||
color: colors.blue,
|
||||
unit: Unit.feeRate,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.feeRate.min,
|
||||
name: "Min",
|
||||
color: colors.red,
|
||||
unit: Unit.feeRate,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.feeRate.max,
|
||||
name: "Max",
|
||||
color: colors.green,
|
||||
unit: Unit.feeRate,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.feeRate.pct10,
|
||||
name: "pct10",
|
||||
color: colors.rose,
|
||||
unit: Unit.feeRate,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.feeRate.pct25,
|
||||
name: "pct25",
|
||||
color: colors.pink,
|
||||
unit: Unit.feeRate,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.feeRate.pct75,
|
||||
name: "pct75",
|
||||
color: colors.violet,
|
||||
unit: Unit.feeRate,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: transactions.fees.feeRate.pct90,
|
||||
name: "pct90",
|
||||
color: colors.fuchsia,
|
||||
unit: Unit.feeRate,
|
||||
defaultActive: false,
|
||||
}),
|
||||
name: "Unclaimed",
|
||||
title: "Unclaimed Rewards",
|
||||
bottom: fromValuePattern(
|
||||
blocks.rewards.unclaimedRewards,
|
||||
"Unclaimed",
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Addresses
|
||||
{
|
||||
name: "Addresses",
|
||||
tree: [
|
||||
{
|
||||
name: "Count",
|
||||
tree: [
|
||||
{
|
||||
name: "All",
|
||||
title: "Total Address Count",
|
||||
bottom: [
|
||||
line({
|
||||
metric: distribution.addrCount.all,
|
||||
name: "Loaded",
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.emptyAddrCount.all,
|
||||
name: "Empty",
|
||||
color: colors.gray,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "By Type",
|
||||
title: "Address Count by Type",
|
||||
bottom: [
|
||||
line({
|
||||
metric: distribution.addrCount.p2pkh,
|
||||
name: "P2PKH",
|
||||
color: colors.orange,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addrCount.p2sh,
|
||||
name: "P2SH",
|
||||
color: colors.yellow,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addrCount.p2wpkh,
|
||||
name: "P2WPKH",
|
||||
color: colors.green,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addrCount.p2wsh,
|
||||
name: "P2WSH",
|
||||
color: colors.teal,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addrCount.p2tr,
|
||||
name: "P2TR",
|
||||
color: colors.purple,
|
||||
unit: Unit.count,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addrCount.p2pk65,
|
||||
name: "P2PK65",
|
||||
color: colors.pink,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addrCount.p2pk33,
|
||||
name: "P2PK33",
|
||||
color: colors.red,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: distribution.addrCount.p2a,
|
||||
name: "P2A",
|
||||
color: colors.blue,
|
||||
unit: Unit.count,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -568,6 +660,13 @@ export function createChainSection(ctx) {
|
||||
unit: Unit.hashRate,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.difficulty.asHash,
|
||||
name: "Difficulty",
|
||||
color: colors.default,
|
||||
unit: Unit.hashRate,
|
||||
options: { lineStyle: 1 },
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -579,34 +678,17 @@ export function createChainSection(ctx) {
|
||||
name: "Difficulty",
|
||||
unit: Unit.difficulty,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.difficulty.adjustment,
|
||||
name: "Adjustment",
|
||||
color: colors.orange,
|
||||
unit: Unit.percentage,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.difficulty.asHash,
|
||||
name: "As hash",
|
||||
color: colors.default,
|
||||
unit: Unit.hashRate,
|
||||
defaultActive: false,
|
||||
options: { lineStyle: 1 },
|
||||
}),
|
||||
line({
|
||||
metric: blocks.difficulty.blocksBeforeNextAdjustment,
|
||||
name: "Blocks until adj.",
|
||||
name: "before next",
|
||||
color: colors.indigo,
|
||||
unit: Unit.blocks,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.difficulty.daysBeforeNextAdjustment,
|
||||
name: "Days until adj.",
|
||||
name: "before next",
|
||||
color: colors.purple,
|
||||
unit: Unit.days,
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
@@ -619,6 +701,7 @@ export function createChainSection(ctx) {
|
||||
name: "Difficulty Change",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
priceLine({ ctx, number: 0, unit: Unit.percentage }),
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -701,23 +784,22 @@ export function createChainSection(ctx) {
|
||||
name: "Halving",
|
||||
title: "Halving",
|
||||
bottom: [
|
||||
line({
|
||||
metric: blocks.halving.blocksBeforeNextHalving,
|
||||
name: "Blocks before next",
|
||||
unit: Unit.blocks,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.halving.daysBeforeNextHalving,
|
||||
name: "Days before next",
|
||||
color: colors.orange,
|
||||
unit: Unit.days,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.halving.epoch,
|
||||
name: "Epoch",
|
||||
color: colors.purple,
|
||||
unit: Unit.epoch,
|
||||
defaultActive: false,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.halving.blocksBeforeNextHalving,
|
||||
name: "before next",
|
||||
unit: Unit.blocks,
|
||||
}),
|
||||
line({
|
||||
metric: blocks.halving.daysBeforeNextHalving,
|
||||
name: "before next",
|
||||
color: colors.blue,
|
||||
unit: Unit.days,
|
||||
}),
|
||||
],
|
||||
},
|
||||
@@ -725,10 +807,11 @@ export function createChainSection(ctx) {
|
||||
name: "Puell Multiple",
|
||||
title: "Puell Multiple",
|
||||
bottom: [
|
||||
line({
|
||||
baseline({
|
||||
metric: market.indicators.puellMultiple,
|
||||
name: "Puell Multiple",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
priceLine({ ctx, unit: Unit.ratio, number: 1 }),
|
||||
],
|
||||
@@ -741,60 +824,6 @@ export function createChainSection(ctx) {
|
||||
name: "Pools",
|
||||
tree: poolsTree,
|
||||
},
|
||||
|
||||
// Unspendable
|
||||
{
|
||||
name: "Unspendable",
|
||||
tree: [
|
||||
{
|
||||
name: "Supply",
|
||||
title: "Unspendable Supply",
|
||||
bottom: fromValuePattern(supply.burned.unspendable, "Supply"),
|
||||
},
|
||||
{
|
||||
name: "OP_RETURN",
|
||||
tree: [
|
||||
{
|
||||
name: "Outputs",
|
||||
title: "OP_RETURN Outputs",
|
||||
bottom: fromFullnessPattern(scripts.count.opreturn, Unit.count),
|
||||
},
|
||||
{
|
||||
name: "Supply",
|
||||
title: "OP_RETURN Supply",
|
||||
bottom: fromValuePattern(supply.burned.opreturn, "Supply"),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Supply
|
||||
{
|
||||
name: "Supply",
|
||||
title: "Circulating Supply",
|
||||
bottom: fromSupplyPattern(supply.circulating, "Supply"),
|
||||
},
|
||||
|
||||
// Inflation
|
||||
{
|
||||
name: "Inflation",
|
||||
title: "Inflation Rate",
|
||||
bottom: [
|
||||
line({
|
||||
metric: supply.inflation,
|
||||
name: "Rate",
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
||||
// Unclaimed Rewards
|
||||
{
|
||||
name: "Unclaimed Rewards",
|
||||
title: "Unclaimed Rewards",
|
||||
bottom: fromValuePattern(blocks.rewards.unclaimedRewards, "Unclaimed"),
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
percentileUsdMap,
|
||||
percentileMap,
|
||||
sdPatterns,
|
||||
sdBands,
|
||||
sdBandsUsd,
|
||||
sdBandsRatio,
|
||||
} from "./shared.js";
|
||||
|
||||
/**
|
||||
@@ -56,8 +57,8 @@ function createCointimePriceWithRatioOptions(
|
||||
baseline({
|
||||
metric: ratio.ratio,
|
||||
name: "Ratio",
|
||||
color,
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
line({
|
||||
metric: ratio.ratio1wSma,
|
||||
@@ -191,7 +192,7 @@ function createCointimePriceWithRatioOptions(
|
||||
title: `${title} ${titleAddon} Z-Score`,
|
||||
top: [
|
||||
line({ metric: price, name: legend, color, unit: Unit.usd }),
|
||||
...sdBands(colors, sd).map(
|
||||
...sdBandsUsd(colors, sd).map(
|
||||
({ name: bandName, prop, color: bandColor }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
@@ -203,7 +204,33 @@ function createCointimePriceWithRatioOptions(
|
||||
),
|
||||
],
|
||||
bottom: [
|
||||
line({ metric: sd.zscore, name: "Z-Score", color, unit: Unit.sd }),
|
||||
baseline({
|
||||
metric: sd.zscore,
|
||||
name: "Z-Score",
|
||||
unit: Unit.sd,
|
||||
}),
|
||||
baseline({
|
||||
metric: ratio.ratio,
|
||||
name: "Ratio",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
line({
|
||||
metric: sd.sd,
|
||||
name: "Volatility",
|
||||
color: colors.gray,
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
...sdBandsRatio(colors, sd).map(
|
||||
({ name: bandName, prop, color: bandColor }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
name: bandName,
|
||||
color: bandColor,
|
||||
unit: Unit.ratio,
|
||||
defaultActive: false,
|
||||
}),
|
||||
),
|
||||
...priceLines({
|
||||
ctx,
|
||||
unit: Unit.sd,
|
||||
|
||||
@@ -15,35 +15,51 @@ import {
|
||||
} from "./series.js";
|
||||
import { colors } from "../chart/colors.js";
|
||||
|
||||
/**
|
||||
* @template {(arg: any, ...args: any[]) => any} F
|
||||
* @typedef {F extends (arg: any, ...args: infer P) => infer R ? (...args: P) => R : never} OmitFirstArg
|
||||
*/
|
||||
|
||||
/** @typedef {ReturnType<typeof createContext>} PartialContext */
|
||||
|
||||
/**
|
||||
* Create a context object with all dependencies for building partial options
|
||||
* @param {Object} args
|
||||
* @param {BrkClient} args.brk
|
||||
* @returns {PartialContext}
|
||||
*/
|
||||
export function createContext({ brk }) {
|
||||
return {
|
||||
colors,
|
||||
brk,
|
||||
|
||||
/** @type {OmitFirstArg<typeof fromBlockCount>} */
|
||||
fromBlockCount: (pattern, title, color) =>
|
||||
fromBlockCount(colors, pattern, title, color),
|
||||
/** @type {OmitFirstArg<typeof fromBitcoin>} */
|
||||
fromBitcoin: (pattern, title, color) =>
|
||||
fromBitcoin(colors, pattern, title, color),
|
||||
/** @type {OmitFirstArg<typeof fromBlockSize>} */
|
||||
fromBlockSize: (pattern, title, color) =>
|
||||
fromBlockSize(colors, pattern, title, color),
|
||||
/** @type {OmitFirstArg<typeof fromSizePattern>} */
|
||||
fromSizePattern: (pattern, unit, title) =>
|
||||
fromSizePattern(colors, pattern, unit, title),
|
||||
/** @type {OmitFirstArg<typeof fromFullnessPattern>} */
|
||||
fromFullnessPattern: (pattern, unit, title) =>
|
||||
fromFullnessPattern(colors, pattern, unit, title),
|
||||
/** @type {OmitFirstArg<typeof fromDollarsPattern>} */
|
||||
fromDollarsPattern: (pattern, unit, title) =>
|
||||
fromDollarsPattern(colors, pattern, unit, title),
|
||||
/** @type {OmitFirstArg<typeof fromFeeRatePattern>} */
|
||||
fromFeeRatePattern: (pattern, unit, title) =>
|
||||
fromFeeRatePattern(colors, pattern, unit, title),
|
||||
/** @type {OmitFirstArg<typeof fromCoinbasePattern>} */
|
||||
fromCoinbasePattern: (pattern, title) =>
|
||||
fromCoinbasePattern(colors, pattern, title),
|
||||
/** @type {OmitFirstArg<typeof fromValuePattern>} */
|
||||
fromValuePattern: (pattern, title, sumColor, cumulativeColor) =>
|
||||
fromValuePattern(colors, pattern, title, sumColor, cumulativeColor),
|
||||
/** @type {OmitFirstArg<typeof fromBitcoinPatternWithUnit>} */
|
||||
fromBitcoinPatternWithUnit: (
|
||||
pattern,
|
||||
title,
|
||||
@@ -59,6 +75,7 @@ export function createContext({ brk }) {
|
||||
sumColor,
|
||||
cumulativeColor,
|
||||
),
|
||||
/** @type {OmitFirstArg<typeof fromBlockCountWithUnit>} */
|
||||
fromBlockCountWithUnit: (pattern, unit, title, sumColor, cumulativeColor) =>
|
||||
fromBlockCountWithUnit(
|
||||
colors,
|
||||
@@ -68,9 +85,11 @@ export function createContext({ brk }) {
|
||||
sumColor,
|
||||
cumulativeColor,
|
||||
),
|
||||
/** @type {OmitFirstArg<typeof fromIntervalPattern>} */
|
||||
fromIntervalPattern: (pattern, unit, title, color) =>
|
||||
fromIntervalPattern(colors, pattern, unit, title, color),
|
||||
/** @type {fromSupplyPattern} */
|
||||
fromSupplyPattern: (pattern, title, color) =>
|
||||
fromSupplyPattern(colors, pattern, title, color),
|
||||
fromSupplyPattern(pattern, title, color),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ export function createAddressCohortFolder(ctx, args) {
|
||||
{
|
||||
name: "total",
|
||||
title: `Supply ${title}`,
|
||||
bottom: createGroupedSupplyTotalSeries(ctx, list),
|
||||
bottom: createGroupedSupplyTotalSeries(list),
|
||||
},
|
||||
{
|
||||
name: "in profit",
|
||||
@@ -23,6 +23,12 @@ const entries = (obj) =>
|
||||
Object.entries(obj)
|
||||
);
|
||||
|
||||
/** @type {readonly AddressableType[]} */
|
||||
const ADDRESSABLE_TYPES = ["p2pk65", "p2pk33", "p2pkh", "p2sh", "p2wpkh", "p2wsh", "p2tr", "p2a"];
|
||||
|
||||
/** @type {(key: SpendableType) => key is AddressableType} */
|
||||
const isAddressable = (key) => ADDRESSABLE_TYPES.includes(/** @type {any} */ (key));
|
||||
|
||||
/**
|
||||
* Build all cohort data from brk tree
|
||||
* @param {Colors} colors
|
||||
@@ -31,6 +37,7 @@ const entries = (obj) =>
|
||||
export function buildCohortData(colors, brk) {
|
||||
const utxoCohorts = brk.metrics.distribution.utxoCohorts;
|
||||
const addressCohorts = brk.metrics.distribution.addressCohorts;
|
||||
const { addrCount } = brk.metrics.distribution;
|
||||
const {
|
||||
TERM_NAMES,
|
||||
EPOCH_NAMES,
|
||||
@@ -51,6 +58,7 @@ export function buildCohortData(colors, brk) {
|
||||
title: "",
|
||||
color: colors.orange,
|
||||
tree: utxoCohorts.all,
|
||||
addrCount: addrCount.all,
|
||||
};
|
||||
|
||||
// Term cohorts - split because short is CohortFull, long is CohortWithPercentiles
|
||||
@@ -200,18 +208,32 @@ export function buildCohortData(colors, brk) {
|
||||
},
|
||||
);
|
||||
|
||||
// Spendable type cohorts - CohortBasic (neither adjustedSopr nor percentiles)
|
||||
/** @type {readonly CohortBasic[]} */
|
||||
const type = entries(utxoCohorts.type).map(([key, tree]) => {
|
||||
// Spendable type cohorts - split by addressability
|
||||
/** @type {readonly CohortAddress[]} */
|
||||
const typeAddressable = ADDRESSABLE_TYPES.map((key) => {
|
||||
const names = SPENDABLE_TYPE_NAMES[key];
|
||||
return {
|
||||
name: names.short,
|
||||
title: names.long,
|
||||
color: colors[spendableTypeColors[key]],
|
||||
tree,
|
||||
tree: utxoCohorts.type[key],
|
||||
addrCount: addrCount[key],
|
||||
};
|
||||
});
|
||||
|
||||
/** @type {readonly CohortBasic[]} */
|
||||
const typeOther = entries(utxoCohorts.type)
|
||||
.filter(([key]) => !isAddressable(key))
|
||||
.map(([key, tree]) => {
|
||||
const names = SPENDABLE_TYPE_NAMES[key];
|
||||
return {
|
||||
name: names.short,
|
||||
title: names.long,
|
||||
color: colors[spendableTypeColors[key]],
|
||||
tree,
|
||||
};
|
||||
});
|
||||
|
||||
// Year cohorts - CohortBasic (neither adjustedSopr nor percentiles)
|
||||
/** @type {readonly CohortBasic[]} */
|
||||
const year = entries(utxoCohorts.year).map(([key, tree]) => {
|
||||
@@ -238,7 +260,8 @@ export function buildCohortData(colors, brk) {
|
||||
addressesUnderAmount,
|
||||
utxosAmountRanges,
|
||||
addressesAmountRanges,
|
||||
type,
|
||||
typeAddressable,
|
||||
typeOther,
|
||||
year,
|
||||
};
|
||||
}
|
||||
@@ -12,6 +12,7 @@ export {
|
||||
createCohortFolderWithAdjusted,
|
||||
createCohortFolderWithPercentiles,
|
||||
createCohortFolderBasic,
|
||||
createCohortFolderAddress,
|
||||
} from "./utxo.js";
|
||||
export { createAddressCohortFolder } from "./address.js";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { Unit } from "../../utils/units.js";
|
||||
import { priceLine } from "../constants.js";
|
||||
import { line } from "../series.js";
|
||||
import { baseline, line } from "../series.js";
|
||||
import { satsBtcUsd } from "../shared.js";
|
||||
|
||||
/**
|
||||
@@ -74,25 +74,22 @@ export function createSingleSupplySeries(ctx, cohort) {
|
||||
|
||||
/**
|
||||
* Create supply total series for grouped cohorts
|
||||
* @param {PartialContext} ctx
|
||||
* @param {readonly CohortObject[]} list
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function createGroupedSupplyTotalSeries(ctx, list) {
|
||||
const { brk } = ctx;
|
||||
const constant100 = brk.metrics.constants.constant100;
|
||||
|
||||
export function createGroupedSupplyTotalSeries(list) {
|
||||
return list.flatMap(({ color, name, tree }) => [
|
||||
...satsBtcUsd(tree.supply.total, name, color),
|
||||
line({
|
||||
metric:
|
||||
"supplyRelToCirculatingSupply" in tree.relative
|
||||
? tree.relative.supplyRelToCirculatingSupply
|
||||
: constant100,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.pctSupply,
|
||||
}),
|
||||
...("supplyRelToCirculatingSupply" in tree.relative
|
||||
? [
|
||||
line({
|
||||
metric: tree.relative.supplyRelToCirculatingSupply,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.pctSupply,
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -194,12 +191,12 @@ export function createRealizedPriceSeries(list) {
|
||||
*/
|
||||
export function createRealizedPriceRatioSeries(ctx, list) {
|
||||
return [
|
||||
...list.map(({ color, name, tree }) =>
|
||||
line({
|
||||
...list.map(({ name, tree }) =>
|
||||
baseline({
|
||||
metric: tree.realized.realizedPriceExtra.ratio,
|
||||
name,
|
||||
color,
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
),
|
||||
priceLine({ ctx, unit: Unit.ratio, number: 1 }),
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,8 @@ import {
|
||||
percentileUsdMap,
|
||||
percentileMap,
|
||||
sdPatterns,
|
||||
sdBands,
|
||||
sdBandsUsd,
|
||||
sdBandsRatio,
|
||||
} from "../shared.js";
|
||||
import { periodIdToName } from "./utils.js";
|
||||
|
||||
@@ -90,7 +91,6 @@ export function createPriceWithRatioOptions(
|
||||
metric: ratio.ratio,
|
||||
name: "Ratio",
|
||||
base: 1,
|
||||
color,
|
||||
unit: Unit.ratio,
|
||||
}),
|
||||
.../** @type {const} */ ([
|
||||
@@ -222,7 +222,7 @@ export function createPriceWithRatioOptions(
|
||||
title: `${title} ${titleAddon} Z-Score`,
|
||||
top: [
|
||||
line({ metric: priceMetric, name: legend, color, unit: Unit.usd }),
|
||||
...sdBands(colors, sd).map(
|
||||
...sdBandsUsd(colors, sd).map(
|
||||
({ name: bandName, prop, color: bandColor }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
@@ -237,9 +237,31 @@ export function createPriceWithRatioOptions(
|
||||
baseline({
|
||||
metric: sd.zscore,
|
||||
name: "Z-Score",
|
||||
color,
|
||||
unit: Unit.sd,
|
||||
}),
|
||||
baseline({
|
||||
metric: ratio.ratio,
|
||||
name: "Ratio",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
line({
|
||||
metric: sd.sd,
|
||||
name: "Volatility",
|
||||
color: colors.gray,
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
...sdBandsRatio(colors, sd).map(
|
||||
({ name: bandName, prop, color: bandColor }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
name: bandName,
|
||||
color: bandColor,
|
||||
unit: Unit.ratio,
|
||||
defaultActive: false,
|
||||
}),
|
||||
),
|
||||
priceLine({ ctx, unit: Unit.ratio, number: 1 }),
|
||||
priceLine({
|
||||
ctx,
|
||||
unit: Unit.sd,
|
||||
|
||||
@@ -8,8 +8,9 @@ import {
|
||||
createCohortFolderWithAdjusted,
|
||||
createCohortFolderWithPercentiles,
|
||||
createCohortFolderBasic,
|
||||
createCohortFolderAddress,
|
||||
createAddressCohortFolder,
|
||||
} from "./cohorts/index.js";
|
||||
} from "./distribution/index.js";
|
||||
import { createMarketSection } from "./market/index.js";
|
||||
import { createChainSection } from "./chain.js";
|
||||
import { createCointimeSection } from "./cointime.js";
|
||||
@@ -17,6 +18,7 @@ import { colors } from "../chart/colors.js";
|
||||
|
||||
// Re-export types for external consumers
|
||||
export * from "./types.js";
|
||||
export * from "./context.js";
|
||||
|
||||
/**
|
||||
* Create partial options tree
|
||||
@@ -43,17 +45,22 @@ export function createPartialOptions({ brk }) {
|
||||
addressesUnderAmount,
|
||||
utxosAmountRanges,
|
||||
addressesAmountRanges,
|
||||
type,
|
||||
typeAddressable,
|
||||
typeOther,
|
||||
year,
|
||||
} = buildCohortData(colors, brk);
|
||||
|
||||
// Helpers to map cohorts by capability type
|
||||
/** @param {CohortWithAdjusted} cohort */
|
||||
const mapWithAdjusted = (cohort) => createCohortFolderWithAdjusted(ctx, cohort);
|
||||
const mapWithAdjusted = (cohort) =>
|
||||
createCohortFolderWithAdjusted(ctx, cohort);
|
||||
/** @param {CohortWithPercentiles} cohort */
|
||||
const mapWithPercentiles = (cohort) => createCohortFolderWithPercentiles(ctx, cohort);
|
||||
const mapWithPercentiles = (cohort) =>
|
||||
createCohortFolderWithPercentiles(ctx, cohort);
|
||||
/** @param {CohortBasic} cohort */
|
||||
const mapBasic = (cohort) => createCohortFolderBasic(ctx, cohort);
|
||||
/** @param {CohortAddress} cohort */
|
||||
const mapAddress = (cohort) => createCohortFolderAddress(ctx, cohort);
|
||||
/** @param {AddressCohortObject} cohort */
|
||||
const mapAddressCohorts = (cohort) => createAddressCohortFolder(ctx, cohort);
|
||||
|
||||
@@ -81,7 +88,7 @@ export function createPartialOptions({ brk }) {
|
||||
|
||||
// Cohorts section
|
||||
{
|
||||
name: "Cohorts",
|
||||
name: "Distribution",
|
||||
tree: [
|
||||
// All UTXOs - CohortAll (adjustedSopr + percentiles but no RelToMarketCap)
|
||||
createCohortFolderAll(ctx, cohortAll),
|
||||
@@ -90,22 +97,29 @@ export function createPartialOptions({ brk }) {
|
||||
{
|
||||
name: "Terms",
|
||||
tree: [
|
||||
// Compare folder uses WithPercentiles (common capabilities)
|
||||
createCohortFolderWithPercentiles(ctx, {
|
||||
name: "Compare",
|
||||
title: "Term",
|
||||
list: [termShort, termLong],
|
||||
}),
|
||||
// Individual cohorts with their specific capabilities
|
||||
createCohortFolderFull(ctx, termShort),
|
||||
createCohortFolderWithPercentiles(ctx, termLong),
|
||||
],
|
||||
},
|
||||
|
||||
// Types - CohortBasic
|
||||
// Types - addressable types have addrCount, others don't
|
||||
{
|
||||
name: "Types",
|
||||
tree: [
|
||||
createCohortFolderBasic(ctx, {
|
||||
createCohortFolderAddress(ctx, {
|
||||
name: "Compare",
|
||||
title: "Type",
|
||||
list: type,
|
||||
list: typeAddressable,
|
||||
}),
|
||||
...type.map(mapBasic),
|
||||
...typeAddressable.map(mapAddress),
|
||||
...typeOther.map(mapBasic),
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
@@ -193,8 +193,8 @@ export function fromBlockCount(colors, pattern, title, color) {
|
||||
{ metric: pattern.sum, title, color: color ?? colors.default },
|
||||
{
|
||||
metric: pattern.cumulative,
|
||||
title: `${title} (cum.)`,
|
||||
color: colors.cyan,
|
||||
title: `${title} cumulative`,
|
||||
color: colors.stat.cumulative,
|
||||
defaultActive: false,
|
||||
},
|
||||
];
|
||||
@@ -209,49 +209,55 @@ export function fromBlockCount(colors, pattern, title, color) {
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromBitcoin(colors, pattern, title, color) {
|
||||
const { stat } = colors;
|
||||
return [
|
||||
{ metric: pattern.base, title, color: color ?? colors.default },
|
||||
{ metric: pattern.average, title: "Average", defaultActive: false },
|
||||
{
|
||||
metric: pattern.average,
|
||||
title: `${title} avg`,
|
||||
color: stat.avg,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.max,
|
||||
title: "Max",
|
||||
color: colors.pink,
|
||||
title: `${title} max`,
|
||||
color: stat.max,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.min,
|
||||
title: "Min",
|
||||
color: colors.green,
|
||||
title: `${title} min`,
|
||||
color: stat.min,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.median,
|
||||
title: "Median",
|
||||
color: colors.amber,
|
||||
title: `${title} median`,
|
||||
color: stat.median,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct75,
|
||||
title: "pct75",
|
||||
color: colors.red,
|
||||
title: `${title} pct75`,
|
||||
color: stat.pct75,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: "pct25",
|
||||
color: colors.yellow,
|
||||
title: `${title} pct25`,
|
||||
color: stat.pct25,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct90,
|
||||
title: "pct90",
|
||||
color: colors.rose,
|
||||
title: `${title} pct90`,
|
||||
color: stat.pct90,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: "pct10",
|
||||
color: colors.lime,
|
||||
title: `${title} pct10`,
|
||||
color: stat.pct10,
|
||||
defaultActive: false,
|
||||
},
|
||||
];
|
||||
@@ -266,55 +272,61 @@ export function fromBitcoin(colors, pattern, title, color) {
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromBlockSize(colors, pattern, title, color) {
|
||||
const { stat } = colors;
|
||||
return [
|
||||
{ metric: pattern.sum, title, color: color ?? colors.default },
|
||||
{ metric: pattern.average, title: "Average", defaultActive: false },
|
||||
{
|
||||
metric: pattern.average,
|
||||
title: `${title} avg`,
|
||||
color: stat.avg,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.cumulative,
|
||||
title: `Cumulative`,
|
||||
color: colors.cyan,
|
||||
title: `${title} cumulative`,
|
||||
color: stat.cumulative,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.max,
|
||||
title: "Max",
|
||||
color: colors.pink,
|
||||
title: `${title} max`,
|
||||
color: stat.max,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.min,
|
||||
title: "Min",
|
||||
color: colors.green,
|
||||
title: `${title} min`,
|
||||
color: stat.min,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.median,
|
||||
title: "Median",
|
||||
color: colors.amber,
|
||||
title: `${title} median`,
|
||||
color: stat.median,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct75,
|
||||
title: "pct75",
|
||||
color: colors.red,
|
||||
title: `${title} pct75`,
|
||||
color: stat.pct75,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: "pct25",
|
||||
color: colors.yellow,
|
||||
title: `${title} pct25`,
|
||||
color: stat.pct25,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct90,
|
||||
title: "pct90",
|
||||
color: colors.rose,
|
||||
title: `${title} pct90`,
|
||||
color: stat.pct90,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: "pct10",
|
||||
color: colors.lime,
|
||||
title: `${title} pct10`,
|
||||
color: stat.pct10,
|
||||
defaultActive: false,
|
||||
},
|
||||
];
|
||||
@@ -329,68 +341,69 @@ export function fromBlockSize(colors, pattern, title, color) {
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromSizePattern(colors, pattern, unit, title = "") {
|
||||
const { stat } = colors;
|
||||
return [
|
||||
{ metric: pattern.average, title: `${title} avg`.trim(), unit },
|
||||
{
|
||||
metric: pattern.sum,
|
||||
title: `${title} sum`.trim(),
|
||||
color: colors.blue,
|
||||
color: stat.sum,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.cumulative,
|
||||
title: `${title} cumulative`.trim(),
|
||||
color: colors.indigo,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: colors.red,
|
||||
color: stat.cumulative,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.max,
|
||||
title: `${title} max`.trim(),
|
||||
color: colors.green,
|
||||
color: stat.max,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: colors.rose,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: colors.pink,
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: stat.min,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.median,
|
||||
title: `${title} median`.trim(),
|
||||
color: colors.purple,
|
||||
color: stat.median,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct75,
|
||||
title: `${title} pct75`.trim(),
|
||||
color: colors.violet,
|
||||
color: stat.pct75,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: stat.pct25,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct90,
|
||||
title: `${title} pct90`.trim(),
|
||||
color: colors.fuchsia,
|
||||
color: stat.pct90,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: stat.pct10,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -406,61 +419,61 @@ export function fromSizePattern(colors, pattern, unit, title = "") {
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromFullnessPattern(colors, pattern, unit, title = "") {
|
||||
const { stat } = colors;
|
||||
return [
|
||||
{ metric: pattern.base, title: title || "base", unit },
|
||||
{
|
||||
metric: pattern.average,
|
||||
title: `${title} avg`.trim(),
|
||||
color: colors.purple,
|
||||
color: stat.avg,
|
||||
unit,
|
||||
},
|
||||
{
|
||||
metric: pattern.max,
|
||||
title: `${title} max`.trim(),
|
||||
color: stat.max,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: colors.red,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.max,
|
||||
title: `${title} max`.trim(),
|
||||
color: colors.green,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: colors.rose,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: colors.pink,
|
||||
color: stat.min,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.median,
|
||||
title: `${title} median`.trim(),
|
||||
color: colors.violet,
|
||||
color: stat.median,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct75,
|
||||
title: `${title} pct75`.trim(),
|
||||
color: colors.fuchsia,
|
||||
color: stat.pct75,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: stat.pct25,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct90,
|
||||
title: `${title} pct90`.trim(),
|
||||
color: colors.amber,
|
||||
color: stat.pct90,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: stat.pct10,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -476,74 +489,75 @@ export function fromFullnessPattern(colors, pattern, unit, title = "") {
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromDollarsPattern(colors, pattern, unit, title = "") {
|
||||
const { stat } = colors;
|
||||
return [
|
||||
{ metric: pattern.base, title: title || "base", unit },
|
||||
{
|
||||
metric: pattern.sum,
|
||||
title: `${title} sum`.trim(),
|
||||
color: colors.blue,
|
||||
color: stat.sum,
|
||||
unit,
|
||||
},
|
||||
{
|
||||
metric: pattern.cumulative,
|
||||
title: `${title} cumulative`.trim(),
|
||||
color: colors.cyan,
|
||||
color: stat.cumulative,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.average,
|
||||
title: `${title} avg`.trim(),
|
||||
color: colors.purple,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: colors.red,
|
||||
color: stat.avg,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.max,
|
||||
title: `${title} max`.trim(),
|
||||
color: colors.green,
|
||||
color: stat.max,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: colors.rose,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: colors.pink,
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: stat.min,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.median,
|
||||
title: `${title} median`.trim(),
|
||||
color: colors.violet,
|
||||
color: stat.median,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct75,
|
||||
title: `${title} pct75`.trim(),
|
||||
color: colors.fuchsia,
|
||||
color: stat.pct75,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: stat.pct25,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct90,
|
||||
title: `${title} pct90`.trim(),
|
||||
color: colors.amber,
|
||||
color: stat.pct90,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: stat.pct10,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -559,54 +573,67 @@ export function fromDollarsPattern(colors, pattern, unit, title = "") {
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromFeeRatePattern(colors, pattern, unit, title = "") {
|
||||
const { stat } = colors;
|
||||
return [
|
||||
{ metric: pattern.average, title: `${title} avg`.trim(), unit },
|
||||
{
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: colors.red,
|
||||
type: "Dots",
|
||||
metric: pattern.average,
|
||||
title: `${title} avg`.trim(),
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
type: "Dots",
|
||||
metric: pattern.max,
|
||||
title: `${title} max`.trim(),
|
||||
color: colors.green,
|
||||
color: stat.max,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: colors.rose,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: colors.pink,
|
||||
type: "Dots",
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: stat.min,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
type: "Dots",
|
||||
metric: pattern.median,
|
||||
title: `${title} median`.trim(),
|
||||
color: colors.purple,
|
||||
color: stat.median,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
type: "Dots",
|
||||
metric: pattern.pct75,
|
||||
title: `${title} pct75`.trim(),
|
||||
color: colors.violet,
|
||||
color: stat.pct75,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
type: "Dots",
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: stat.pct25,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
type: "Dots",
|
||||
metric: pattern.pct90,
|
||||
title: `${title} pct90`.trim(),
|
||||
color: colors.fuchsia,
|
||||
color: stat.pct90,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
type: "Dots",
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: stat.pct10,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -617,13 +644,13 @@ export function fromFeeRatePattern(colors, pattern, unit, title = "") {
|
||||
* Create series from a CoinbasePattern ({ sats, bitcoin, dollars } each as FullnessPattern)
|
||||
* @param {Colors} colors
|
||||
* @param {CoinbasePattern} pattern
|
||||
* @param {string} title
|
||||
* @param {string} [title]
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromCoinbasePattern(colors, pattern, title) {
|
||||
return [
|
||||
...fromFullnessPattern(colors, pattern.sats, Unit.sats, title),
|
||||
...fromFullnessPattern(colors, pattern.bitcoin, Unit.btc, title),
|
||||
...fromFullnessPattern(colors, pattern.sats, Unit.sats, title),
|
||||
...fromFullnessPattern(colors, pattern.dollars, Unit.usd, title),
|
||||
];
|
||||
}
|
||||
@@ -632,7 +659,7 @@ export function fromCoinbasePattern(colors, pattern, title) {
|
||||
* Create series from a ValuePattern ({ sats, bitcoin, dollars } each as BlockCountPattern with sum + cumulative)
|
||||
* @param {Colors} colors
|
||||
* @param {ValuePattern} pattern
|
||||
* @param {string} title
|
||||
* @param {string} [title]
|
||||
* @param {Color} [sumColor]
|
||||
* @param {Color} [cumulativeColor]
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
@@ -640,47 +667,47 @@ export function fromCoinbasePattern(colors, pattern, title) {
|
||||
export function fromValuePattern(
|
||||
colors,
|
||||
pattern,
|
||||
title,
|
||||
title = "",
|
||||
sumColor,
|
||||
cumulativeColor,
|
||||
) {
|
||||
return [
|
||||
{
|
||||
metric: pattern.sats.sum,
|
||||
title,
|
||||
color: sumColor,
|
||||
unit: Unit.sats,
|
||||
},
|
||||
{
|
||||
metric: pattern.sats.cumulative,
|
||||
title: `${title} cumulative`,
|
||||
color: cumulativeColor ?? colors.blue,
|
||||
unit: Unit.sats,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.bitcoin.sum,
|
||||
title,
|
||||
title: title || "sum",
|
||||
color: sumColor,
|
||||
unit: Unit.btc,
|
||||
},
|
||||
{
|
||||
metric: pattern.bitcoin.cumulative,
|
||||
title: `${title} cumulative`,
|
||||
color: cumulativeColor ?? colors.blue,
|
||||
title: `${title} cumulative`.trim(),
|
||||
color: cumulativeColor ?? colors.stat.cumulative,
|
||||
unit: Unit.btc,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.sats.sum,
|
||||
title: title || "sum",
|
||||
color: sumColor,
|
||||
unit: Unit.sats,
|
||||
},
|
||||
{
|
||||
metric: pattern.sats.cumulative,
|
||||
title: `${title} cumulative`.trim(),
|
||||
color: cumulativeColor ?? colors.stat.cumulative,
|
||||
unit: Unit.sats,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.dollars.sum,
|
||||
title,
|
||||
title: title || "sum",
|
||||
color: sumColor,
|
||||
unit: Unit.usd,
|
||||
},
|
||||
{
|
||||
metric: pattern.dollars.cumulative,
|
||||
title: `${title} cumulative`,
|
||||
color: cumulativeColor ?? colors.blue,
|
||||
title: `${title} cumulative`.trim(),
|
||||
color: cumulativeColor ?? colors.stat.cumulative,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -715,7 +742,7 @@ export function fromBitcoinPatternWithUnit(
|
||||
{
|
||||
metric: pattern.cumulative,
|
||||
title: `${title} cumulative`,
|
||||
color: cumulativeColor ?? colors.blue,
|
||||
color: cumulativeColor ?? colors.stat.cumulative,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -750,7 +777,7 @@ export function fromBlockCountWithUnit(
|
||||
{
|
||||
metric: pattern.cumulative,
|
||||
title: `${title} cumulative`.trim(),
|
||||
color: cumulativeColor ?? colors.blue,
|
||||
color: cumulativeColor ?? colors.stat.cumulative,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -767,61 +794,62 @@ export function fromBlockCountWithUnit(
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromIntervalPattern(colors, pattern, unit, title = "", color) {
|
||||
const { stat } = colors;
|
||||
return [
|
||||
{ metric: pattern.base, title: title ?? "base", color, unit },
|
||||
{
|
||||
metric: pattern.average,
|
||||
title: `${title} avg`.trim(),
|
||||
color: colors.cyan,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: colors.red,
|
||||
color: stat.avg,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.max,
|
||||
title: `${title} max`.trim(),
|
||||
color: colors.green,
|
||||
color: stat.max,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.min,
|
||||
title: `${title} min`.trim(),
|
||||
color: stat.min,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.median,
|
||||
title: `${title} median`.trim(),
|
||||
color: colors.violet,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: colors.rose,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: colors.pink,
|
||||
color: stat.median,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct75,
|
||||
title: `${title} pct75`.trim(),
|
||||
color: colors.fuchsia,
|
||||
color: stat.pct75,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct25,
|
||||
title: `${title} pct25`.trim(),
|
||||
color: stat.pct25,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct90,
|
||||
title: `${title} pct90`.trim(),
|
||||
color: colors.amber,
|
||||
color: stat.pct90,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
metric: pattern.pct10,
|
||||
title: `${title} pct10`.trim(),
|
||||
color: stat.pct10,
|
||||
unit,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -830,30 +858,29 @@ export function fromIntervalPattern(colors, pattern, unit, title = "", color) {
|
||||
|
||||
/**
|
||||
* Create series from a SupplyPattern (sats/bitcoin/dollars, no sum/cumulative)
|
||||
* @param {Colors} colors
|
||||
* @param {SupplyPattern} pattern
|
||||
* @param {string} title
|
||||
* @param {Color} [color]
|
||||
* @returns {AnyFetchedSeriesBlueprint[]}
|
||||
*/
|
||||
export function fromSupplyPattern(colors, pattern, title, color) {
|
||||
export function fromSupplyPattern(pattern, title, color) {
|
||||
return [
|
||||
{
|
||||
metric: pattern.sats,
|
||||
title,
|
||||
color: color ?? colors.default,
|
||||
unit: Unit.sats,
|
||||
},
|
||||
{
|
||||
metric: pattern.bitcoin,
|
||||
title,
|
||||
color: color ?? colors.default,
|
||||
color,
|
||||
unit: Unit.btc,
|
||||
},
|
||||
{
|
||||
metric: pattern.sats,
|
||||
title,
|
||||
color,
|
||||
unit: Unit.sats,
|
||||
},
|
||||
{
|
||||
metric: pattern.dollars,
|
||||
title,
|
||||
color: color ?? colors.default,
|
||||
color,
|
||||
unit: Unit.usd,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/** Shared helpers for options */
|
||||
|
||||
import { Unit } from "../utils/units.js";
|
||||
import { line } from "./series.js";
|
||||
import { line, baseline } from "./series.js";
|
||||
import { priceLine, priceLines } from "./constants.js";
|
||||
|
||||
/**
|
||||
* Create sats/btc/usd line series from a pattern with .sats/.bitcoin/.dollars
|
||||
@@ -14,7 +15,6 @@ import { line } from "./series.js";
|
||||
export function satsBtcUsd(pattern, name, color, options) {
|
||||
const { defaultActive } = options || {};
|
||||
return [
|
||||
line({ metric: pattern.sats, name, color, unit: Unit.sats, defaultActive }),
|
||||
line({
|
||||
metric: pattern.bitcoin,
|
||||
name,
|
||||
@@ -22,6 +22,7 @@ export function satsBtcUsd(pattern, name, color, options) {
|
||||
unit: Unit.btc,
|
||||
defaultActive,
|
||||
}),
|
||||
line({ metric: pattern.sats, name, color, unit: Unit.sats, defaultActive }),
|
||||
line({
|
||||
metric: pattern.dollars,
|
||||
name,
|
||||
@@ -82,7 +83,7 @@ export function sdPatterns(ratio) {
|
||||
* @param {Colors} colors
|
||||
* @param {Ratio1ySdPattern} sd
|
||||
*/
|
||||
export function sdBands(colors, sd) {
|
||||
export function sdBandsUsd(colors, sd) {
|
||||
return /** @type {const} */ ([
|
||||
{ name: "0σ", prop: sd._0sdUsd, color: colors.lime },
|
||||
{ name: "+0.5σ", prop: sd.p05sdUsd, color: colors.yellow },
|
||||
@@ -95,7 +96,249 @@ export function sdBands(colors, sd) {
|
||||
{ name: "−2σ", prop: sd.m2sdUsd, color: colors.blue },
|
||||
{ name: "+2.5σ", prop: sd.p25sdUsd, color: colors.rose },
|
||||
{ name: "−2.5σ", prop: sd.m25sdUsd, color: colors.indigo },
|
||||
{ name: "+3σ", prop: sd.p3sdUsd, color: colors.pink },
|
||||
{ name: "−3σ", prop: sd.m3sdUsd, color: colors.violet },
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build SD band mappings (ratio) from an SD pattern
|
||||
* @param {Colors} colors
|
||||
* @param {Ratio1ySdPattern} sd
|
||||
*/
|
||||
export function sdBandsRatio(colors, sd) {
|
||||
return /** @type {const} */ ([
|
||||
{ name: "0σ", prop: sd.sma, color: colors.lime },
|
||||
{ name: "+0.5σ", prop: sd.p05sd, color: colors.yellow },
|
||||
{ name: "−0.5σ", prop: sd.m05sd, color: colors.teal },
|
||||
{ name: "+1σ", prop: sd.p1sd, color: colors.amber },
|
||||
{ name: "−1σ", prop: sd.m1sd, color: colors.cyan },
|
||||
{ name: "+1.5σ", prop: sd.p15sd, color: colors.orange },
|
||||
{ name: "−1.5σ", prop: sd.m15sd, color: colors.sky },
|
||||
{ name: "+2σ", prop: sd.p2sd, color: colors.red },
|
||||
{ name: "−2σ", prop: sd.m2sd, color: colors.blue },
|
||||
{ name: "+2.5σ", prop: sd.p25sd, color: colors.rose },
|
||||
{ name: "−2.5σ", prop: sd.m25sd, color: colors.indigo },
|
||||
{ name: "+3σ", prop: sd.p3sd, color: colors.pink },
|
||||
{ name: "−3σ", prop: sd.m3sd, color: colors.violet },
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build ratio SMA series from a ratio pattern
|
||||
* @param {Colors} colors
|
||||
* @param {ActivePriceRatioPattern} ratio
|
||||
*/
|
||||
export function ratioSmas(colors, ratio) {
|
||||
return /** @type {const} */ ([
|
||||
{ name: "1w SMA", metric: ratio.ratio1wSma, color: colors.lime },
|
||||
{ name: "1m SMA", metric: ratio.ratio1mSma, color: colors.teal },
|
||||
{ name: "1y SMA", metric: ratio.ratio1ySd.sma, color: colors.sky },
|
||||
{ name: "2y SMA", metric: ratio.ratio2ySd.sma, color: colors.indigo },
|
||||
{ name: "4y SMA", metric: ratio.ratio4ySd.sma, color: colors.purple },
|
||||
{ name: "All SMA", metric: ratio.ratioSd.sma, color: colors.rose },
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ratio chart from ActivePriceRatioPattern
|
||||
* @param {PartialContext} ctx
|
||||
* @param {Object} args
|
||||
* @param {string} args.title
|
||||
* @param {AnyMetricPattern} args.price - The price metric to show in top pane
|
||||
* @param {ActivePriceRatioPattern} args.ratio - The ratio pattern
|
||||
* @param {Color} args.color
|
||||
* @returns {PartialChartOption}
|
||||
*/
|
||||
export function createRatioChart(ctx, { title, price, ratio, color }) {
|
||||
const { colors } = ctx;
|
||||
|
||||
return {
|
||||
name: "ratio",
|
||||
title: `${title} Ratio`,
|
||||
top: [
|
||||
line({ metric: price, name: "price", color, unit: Unit.usd }),
|
||||
...percentileUsdMap(colors, ratio).map(({ name, prop, color }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
name,
|
||||
color,
|
||||
defaultActive: false,
|
||||
unit: Unit.usd,
|
||||
options: { lineStyle: 1 },
|
||||
}),
|
||||
),
|
||||
],
|
||||
bottom: [
|
||||
baseline({
|
||||
metric: ratio.ratio,
|
||||
name: "Ratio",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
...ratioSmas(colors, ratio).map(({ name, metric, color }) =>
|
||||
line({ metric, name, color, unit: Unit.ratio, defaultActive: false }),
|
||||
),
|
||||
...percentileMap(colors, ratio).map(({ name, prop, color }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
name,
|
||||
color,
|
||||
defaultActive: false,
|
||||
unit: Unit.ratio,
|
||||
options: { lineStyle: 1 },
|
||||
}),
|
||||
),
|
||||
priceLine({ ctx, unit: Unit.ratio, number: 1 }),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ZScores folder from ActivePriceRatioPattern
|
||||
* @param {PartialContext} ctx
|
||||
* @param {Object} args
|
||||
* @param {string} args.title
|
||||
* @param {string} args.legend
|
||||
* @param {AnyMetricPattern} args.price - The price metric to show in top pane
|
||||
* @param {ActivePriceRatioPattern} args.ratio - The ratio pattern
|
||||
* @param {Color} args.color
|
||||
* @returns {PartialOptionsGroup}
|
||||
*/
|
||||
export function createZScoresFolder(
|
||||
ctx,
|
||||
{ title, legend, price, ratio, color },
|
||||
) {
|
||||
const { colors } = ctx;
|
||||
const sdPats = sdPatterns(ratio);
|
||||
|
||||
return {
|
||||
name: "ZScores",
|
||||
tree: [
|
||||
{
|
||||
name: "Compare",
|
||||
title: `${title} Z-Scores`,
|
||||
top: [
|
||||
line({ metric: price, name: legend, color, unit: Unit.usd }),
|
||||
line({
|
||||
metric: ratio.ratio1ySd._0sdUsd,
|
||||
name: "1y 0σ",
|
||||
color: colors.orange,
|
||||
defaultActive: false,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
metric: ratio.ratio2ySd._0sdUsd,
|
||||
name: "2y 0σ",
|
||||
color: colors.yellow,
|
||||
defaultActive: false,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
metric: ratio.ratio4ySd._0sdUsd,
|
||||
name: "4y 0σ",
|
||||
color: colors.lime,
|
||||
defaultActive: false,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
line({
|
||||
metric: ratio.ratioSd._0sdUsd,
|
||||
name: "all 0σ",
|
||||
color: colors.blue,
|
||||
defaultActive: false,
|
||||
unit: Unit.usd,
|
||||
}),
|
||||
],
|
||||
bottom: [
|
||||
line({
|
||||
metric: ratio.ratioSd.zscore,
|
||||
name: "all",
|
||||
color: colors.blue,
|
||||
unit: Unit.sd,
|
||||
}),
|
||||
line({
|
||||
metric: ratio.ratio4ySd.zscore,
|
||||
name: "4y",
|
||||
color: colors.lime,
|
||||
unit: Unit.sd,
|
||||
}),
|
||||
line({
|
||||
metric: ratio.ratio2ySd.zscore,
|
||||
name: "2y",
|
||||
color: colors.yellow,
|
||||
unit: Unit.sd,
|
||||
}),
|
||||
line({
|
||||
metric: ratio.ratio1ySd.zscore,
|
||||
name: "1y",
|
||||
color: colors.orange,
|
||||
unit: Unit.sd,
|
||||
}),
|
||||
...priceLines({
|
||||
ctx,
|
||||
unit: Unit.sd,
|
||||
numbers: [0, 1, -1, 2, -2, 3, -3],
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
...sdPats.map(({ nameAddon, titleAddon, sd }) => ({
|
||||
name: nameAddon,
|
||||
title: `${title} ${titleAddon} Z-Score`,
|
||||
top: [
|
||||
line({ metric: price, name: legend, color, unit: Unit.usd }),
|
||||
...sdBandsUsd(colors, sd).map(
|
||||
({ name: bandName, prop, color: bandColor }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
name: bandName,
|
||||
color: bandColor,
|
||||
unit: Unit.usd,
|
||||
defaultActive: false,
|
||||
}),
|
||||
),
|
||||
],
|
||||
bottom: [
|
||||
baseline({
|
||||
metric: sd.zscore,
|
||||
name: "Z-Score",
|
||||
unit: Unit.sd,
|
||||
}),
|
||||
baseline({
|
||||
metric: ratio.ratio,
|
||||
name: "Ratio",
|
||||
unit: Unit.ratio,
|
||||
base: 1,
|
||||
}),
|
||||
line({
|
||||
metric: sd.sd,
|
||||
name: "Volatility",
|
||||
color: colors.gray,
|
||||
unit: Unit.percentage,
|
||||
}),
|
||||
...sdBandsRatio(colors, sd).map(
|
||||
({ name: bandName, prop, color: bandColor }) =>
|
||||
line({
|
||||
metric: prop,
|
||||
name: bandName,
|
||||
color: bandColor,
|
||||
unit: Unit.ratio,
|
||||
defaultActive: false,
|
||||
}),
|
||||
),
|
||||
priceLine({ ctx, unit: Unit.ratio, number: 1 }),
|
||||
priceLine({
|
||||
ctx,
|
||||
unit: Unit.sd,
|
||||
}),
|
||||
...priceLines({
|
||||
ctx,
|
||||
unit: Unit.sd,
|
||||
numbers: [1, -1, 2, -2, 3, -3],
|
||||
defaultActive: false,
|
||||
}),
|
||||
],
|
||||
})),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
* @property {string} title
|
||||
* @property {Color} color
|
||||
* @property {PatternAll} tree
|
||||
* @property {Brk.MetricPattern1<Brk.StoredU64>} addrCount
|
||||
*
|
||||
* Full cohort: adjustedSopr + percentiles + RelToMarketCap (term.short)
|
||||
* @typedef {Object} CohortFull
|
||||
@@ -190,6 +191,13 @@
|
||||
* @property {PatternBasic} tree
|
||||
*
|
||||
* ============================================================================
|
||||
* Extended Cohort Types (with address count)
|
||||
* ============================================================================
|
||||
*
|
||||
* Basic cohort with address count (for "type" cohorts)
|
||||
* @typedef {CohortBasic & { addrCount: Brk.MetricPattern1<Brk.StoredU64> }} CohortAddress
|
||||
*
|
||||
* ============================================================================
|
||||
* Cohort Group Types (by capability)
|
||||
* ============================================================================
|
||||
*
|
||||
@@ -233,23 +241,6 @@
|
||||
* @property {readonly AddressCohortObject[]} list
|
||||
*
|
||||
* @typedef {UtxoCohortGroupObject | AddressCohortGroupObject} CohortGroupObject
|
||||
*
|
||||
* @typedef {Object} PartialContext
|
||||
* @property {Colors} colors
|
||||
* @property {BrkClient} brk
|
||||
* @property {(pattern: BlockCountPattern<any>, title: string, color?: Color) => AnyFetchedSeriesBlueprint[]} fromBlockCount
|
||||
* @property {(pattern: FullnessPattern<any>, title: string, color?: Color) => AnyFetchedSeriesBlueprint[]} fromBitcoin
|
||||
* @property {(pattern: AnyStatsPattern, title: string, color?: Color) => AnyFetchedSeriesBlueprint[]} fromBlockSize
|
||||
* @property {(pattern: AnyStatsPattern, unit: Unit, title?: string) => AnyFetchedSeriesBlueprint[]} fromSizePattern
|
||||
* @property {(pattern: FullnessPattern<any>, unit: Unit, title?: string) => AnyFetchedSeriesBlueprint[]} fromFullnessPattern
|
||||
* @property {(pattern: DollarsPattern<any>, unit: Unit, title?: string) => AnyFetchedSeriesBlueprint[]} fromDollarsPattern
|
||||
* @property {(pattern: FeeRatePattern<any>, unit: Unit, title?: string) => AnyFetchedSeriesBlueprint[]} fromFeeRatePattern
|
||||
* @property {(pattern: CoinbasePattern, title: string) => AnyFetchedSeriesBlueprint[]} fromCoinbasePattern
|
||||
* @property {(pattern: ValuePattern, title: string, sumColor?: Color, cumulativeColor?: Color) => AnyFetchedSeriesBlueprint[]} fromValuePattern
|
||||
* @property {(pattern: { sum: AnyMetricPattern, cumulative: AnyMetricPattern }, title: string, unit: Unit, sumColor?: Color, cumulativeColor?: Color) => AnyFetchedSeriesBlueprint[]} fromBitcoinPatternWithUnit
|
||||
* @property {(pattern: BlockCountPattern<any>, unit: Unit, title?: string, sumColor?: Color, cumulativeColor?: Color) => AnyFetchedSeriesBlueprint[]} fromBlockCountWithUnit
|
||||
* @property {(pattern: IntervalPattern, unit: Unit, title?: string, color?: Color) => AnyFetchedSeriesBlueprint[]} fromIntervalPattern
|
||||
* @property {(pattern: SupplyPattern, title: string, color?: Color) => AnyFetchedSeriesBlueprint[]} fromSupplyPattern
|
||||
*/
|
||||
|
||||
// Re-export for type consumers
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* @import { WebSockets } from "./utils/ws.js"
|
||||
*
|
||||
* @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, SeriesType, AnyFetchedSeriesBlueprint, TableOption, ExplorerOption, UrlOption, PartialOptionsGroup, OptionsGroup, PartialOptionsTree, UtxoCohortObject, AddressCohortObject, CohortObject, CohortGroupObject, FetchedLineSeriesBlueprint, FetchedBaselineSeriesBlueprint, FetchedHistogramSeriesBlueprint, PartialContext, PatternAll, PatternFull, PatternWithAdjusted, PatternWithPercentiles, PatternBasic, CohortAll, CohortFull, CohortWithAdjusted, CohortWithPercentiles, CohortBasic, CohortGroupFull, CohortGroupWithAdjusted, CohortGroupWithPercentiles, CohortGroupBasic, UtxoCohortGroupObject, AddressCohortGroupObject, FetchedDotsSeriesBlueprint, FetchedCandlestickSeriesBlueprint } from "./options/partial.js"
|
||||
* @import { Option, PartialChartOption, ChartOption, AnyPartialOption, ProcessedOptionAddons, OptionsTree, SimulationOption, AnySeriesBlueprint, SeriesType, AnyFetchedSeriesBlueprint, TableOption, ExplorerOption, UrlOption, PartialOptionsGroup, OptionsGroup, PartialOptionsTree, UtxoCohortObject, AddressCohortObject, CohortObject, CohortGroupObject, FetchedLineSeriesBlueprint, FetchedBaselineSeriesBlueprint, FetchedHistogramSeriesBlueprint, PartialContext, PatternAll, PatternFull, PatternWithAdjusted, PatternWithPercentiles, PatternBasic, CohortAll, CohortFull, CohortWithAdjusted, CohortWithPercentiles, CohortBasic, CohortAddress, CohortGroupFull, CohortGroupWithAdjusted, CohortGroupWithPercentiles, CohortGroupBasic, UtxoCohortGroupObject, AddressCohortGroupObject, FetchedDotsSeriesBlueprint, FetchedCandlestickSeriesBlueprint } from "./options/partial.js"
|
||||
*
|
||||
*
|
||||
* @import { UnitObject as Unit } from "./utils/units.js"
|
||||
@@ -41,7 +41,7 @@
|
||||
* @typedef {Brk._10yTo12yPattern} AgeRangePattern
|
||||
* @typedef {Brk._0satsPattern2} UtxoAmountPattern
|
||||
* @typedef {Brk._0satsPattern} AddressAmountPattern
|
||||
* @typedef {Brk._100btcPattern} BasicUtxoPattern
|
||||
* @typedef {Brk._0Pattern} BasicUtxoPattern
|
||||
* @typedef {Brk._0satsPattern2} EpochPattern
|
||||
* @typedef {Brk.Ratio1ySdPattern} Ratio1ySdPattern
|
||||
* @typedef {Brk.Dollars} Dollars
|
||||
@@ -53,6 +53,8 @@
|
||||
* @typedef {Brk.AnyMetricEndpointBuilder} AnyMetricEndpoint
|
||||
* @typedef {Brk.AnyMetricData} AnyMetricData
|
||||
* @typedef {Brk.AddrCountPattern} AddrCountPattern
|
||||
* @typedef {keyof Brk.MetricsTree_Distribution_UtxoCohorts_Type} SpendableType
|
||||
* @typedef {keyof Brk.MetricsTree_Distribution_AnyAddressIndexes} AddressableType
|
||||
* @typedef {FullnessPattern<any>} IntervalPattern
|
||||
* @typedef {Brk.MetricsTree_Supply_Circulating} SupplyPattern
|
||||
* @typedef {Brk.RelativePattern} GlobalRelativePattern
|
||||
|
||||
@@ -31,7 +31,7 @@ export const numberToPercentage = new Intl.NumberFormat("en-US", {
|
||||
export function numberToShortUSFormat(value, digits) {
|
||||
const absoluteValue = Math.abs(value);
|
||||
|
||||
if (isNaN(value)) {
|
||||
if (isNaN(value) || !isFinite(value)) {
|
||||
return "";
|
||||
} else if (absoluteValue < 10) {
|
||||
return numberToUSNumber(value, Math.min(3, digits || 10));
|
||||
@@ -41,13 +41,13 @@ export function numberToShortUSFormat(value, digits) {
|
||||
return numberToUSNumber(value, Math.min(1, digits || 10));
|
||||
} else if (absoluteValue < 1_000_000) {
|
||||
return numberToUSNumber(value, 0);
|
||||
} else if (absoluteValue >= 1_000_000_000_000_000_000_000) {
|
||||
} else if (absoluteValue >= 1e27) {
|
||||
return "Inf.";
|
||||
}
|
||||
|
||||
const log = Math.floor(Math.log10(absoluteValue) - 6);
|
||||
|
||||
const suffices = ["M", "B", "T", "P", "E", "Z"];
|
||||
const suffices = ["M", "B", "T", "P", "E", "Z", "Y"];
|
||||
const letterIndex = Math.floor(log / 3);
|
||||
const letter = suffices[letterIndex];
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export const Unit = /** @type {const} */ ({
|
||||
sd: { id: "sd", name: "Std Dev" },
|
||||
|
||||
// Relative percentages
|
||||
pctSupply: { id: "pct-supply", name: "% of Supply" },
|
||||
pctSupply: { id: "pct-supply", name: "% of circulating Supply" },
|
||||
pctOwn: { id: "pct-own", name: "% of Own Supply" },
|
||||
pctMcap: { id: "pct-mcap", name: "% of Market Cap" },
|
||||
pctRcap: { id: "pct-rcap", name: "% of Realized Cap" },
|
||||
|
||||
Reference in New Issue
Block a user