global: snapshot

This commit is contained in:
nym21
2026-01-18 16:04:24 +01:00
parent 4031bf3e79
commit c90953adbe
26 changed files with 1065 additions and 828 deletions

1
.gitignore vendored
View File

@@ -20,6 +20,7 @@ _*
/*.html
/research
/filter_*
/heatmaps
# Logs
*.log*

33
Cargo.lock generated
View File

@@ -463,6 +463,7 @@ dependencies = [
"color-eyre",
"derive_more",
"pco",
"plotters",
"rayon",
"rustc-hash",
"schemars",
@@ -562,6 +563,21 @@ dependencies = [
"tracing",
]
[[package]]
name = "brk_playground"
version = "0.1.0-alpha.6"
dependencies = [
"brk_computer",
"brk_error",
"brk_fetcher",
"brk_indexer",
"brk_logger",
"brk_types",
"plotters",
"tracing",
"vecdb",
]
[[package]]
name = "brk_query"
version = "0.1.0-alpha.6"
@@ -628,9 +644,8 @@ dependencies = [
"brk_rpc",
"brk_traversable",
"brk_types",
"brk_website",
"derive_more",
"importmap",
"include_dir",
"jiff",
"quick_cache",
"schemars",
@@ -695,6 +710,20 @@ dependencies = [
"vecdb",
]
[[package]]
name = "brk_website"
version = "0.1.0-alpha.6"
dependencies = [
"axum",
"brk_logger",
"importmap",
"include_dir",
"tokio",
"tower-http",
"tower-layer",
"tracing",
]
[[package]]
name = "brotli"
version = "8.0.2"

View File

@@ -61,6 +61,7 @@ brk_store = { version = "0.1.0-alpha.6", path = "crates/brk_store" }
brk_traversable = { version = "0.1.0-alpha.6", path = "crates/brk_traversable", features = ["pco", "derive"] }
brk_traversable_derive = { version = "0.1.0-alpha.6", path = "crates/brk_traversable_derive" }
brk_types = { version = "0.1.0-alpha.6", path = "crates/brk_types" }
brk_website = { version = "0.1.0-alpha.6", path = "crates/brk_website" }
byteview = "0.10.0"
color-eyre = "0.6.5"
derive_more = { version = "2.1.1", features = ["deref", "deref_mut"] }
@@ -78,6 +79,8 @@ serde_json = { version = "1.0.149", features = ["float_roundtrip", "preserve_ord
smallvec = "1.15.1"
tokio = { version = "1.49.0", features = ["rt-multi-thread"] }
tracing = { version = "0.1", default-features = false, features = ["std"] }
tower-http = { version = "0.6.8", features = ["catch-panic", "compression-br", "compression-gzip", "compression-zstd", "cors", "normalize-path", "timeout", "trace"] }
tower-layer = "0.3"
vecdb = { version = "0.5.11", features = ["derive", "serde_json", "pco", "schemars"] }
# vecdb = { path = "../anydb/crates/vecdb", features = ["derive", "serde_json", "pco", "schemars"] }

View File

@@ -2689,56 +2689,6 @@ impl Price111dSmaPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct PercentilesPattern {
pub pct05: MetricPattern4<Dollars>,
pub pct10: MetricPattern4<Dollars>,
pub pct15: MetricPattern4<Dollars>,
pub pct20: MetricPattern4<Dollars>,
pub pct25: MetricPattern4<Dollars>,
pub pct30: MetricPattern4<Dollars>,
pub pct35: MetricPattern4<Dollars>,
pub pct40: MetricPattern4<Dollars>,
pub pct45: MetricPattern4<Dollars>,
pub pct50: MetricPattern4<Dollars>,
pub pct55: MetricPattern4<Dollars>,
pub pct60: MetricPattern4<Dollars>,
pub pct65: MetricPattern4<Dollars>,
pub pct70: MetricPattern4<Dollars>,
pub pct75: MetricPattern4<Dollars>,
pub pct80: MetricPattern4<Dollars>,
pub pct85: MetricPattern4<Dollars>,
pub pct90: MetricPattern4<Dollars>,
pub pct95: MetricPattern4<Dollars>,
}
impl PercentilesPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
pct05: MetricPattern4::new(client.clone(), _m(&acc, "pct05")),
pct10: MetricPattern4::new(client.clone(), _m(&acc, "pct10")),
pct15: MetricPattern4::new(client.clone(), _m(&acc, "pct15")),
pct20: MetricPattern4::new(client.clone(), _m(&acc, "pct20")),
pct25: MetricPattern4::new(client.clone(), _m(&acc, "pct25")),
pct30: MetricPattern4::new(client.clone(), _m(&acc, "pct30")),
pct35: MetricPattern4::new(client.clone(), _m(&acc, "pct35")),
pct40: MetricPattern4::new(client.clone(), _m(&acc, "pct40")),
pct45: MetricPattern4::new(client.clone(), _m(&acc, "pct45")),
pct50: MetricPattern4::new(client.clone(), _m(&acc, "pct50")),
pct55: MetricPattern4::new(client.clone(), _m(&acc, "pct55")),
pct60: MetricPattern4::new(client.clone(), _m(&acc, "pct60")),
pct65: MetricPattern4::new(client.clone(), _m(&acc, "pct65")),
pct70: MetricPattern4::new(client.clone(), _m(&acc, "pct70")),
pct75: MetricPattern4::new(client.clone(), _m(&acc, "pct75")),
pct80: MetricPattern4::new(client.clone(), _m(&acc, "pct80")),
pct85: MetricPattern4::new(client.clone(), _m(&acc, "pct85")),
pct90: MetricPattern4::new(client.clone(), _m(&acc, "pct90")),
pct95: MetricPattern4::new(client.clone(), _m(&acc, "pct95")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct ActivePriceRatioPattern {
pub ratio: MetricPattern4<StoredF32>,
@@ -2789,6 +2739,56 @@ impl ActivePriceRatioPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct PercentilesPattern {
pub pct05: MetricPattern4<Dollars>,
pub pct10: MetricPattern4<Dollars>,
pub pct15: MetricPattern4<Dollars>,
pub pct20: MetricPattern4<Dollars>,
pub pct25: MetricPattern4<Dollars>,
pub pct30: MetricPattern4<Dollars>,
pub pct35: MetricPattern4<Dollars>,
pub pct40: MetricPattern4<Dollars>,
pub pct45: MetricPattern4<Dollars>,
pub pct50: MetricPattern4<Dollars>,
pub pct55: MetricPattern4<Dollars>,
pub pct60: MetricPattern4<Dollars>,
pub pct65: MetricPattern4<Dollars>,
pub pct70: MetricPattern4<Dollars>,
pub pct75: MetricPattern4<Dollars>,
pub pct80: MetricPattern4<Dollars>,
pub pct85: MetricPattern4<Dollars>,
pub pct90: MetricPattern4<Dollars>,
pub pct95: MetricPattern4<Dollars>,
}
impl PercentilesPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
pct05: MetricPattern4::new(client.clone(), _m(&acc, "pct05")),
pct10: MetricPattern4::new(client.clone(), _m(&acc, "pct10")),
pct15: MetricPattern4::new(client.clone(), _m(&acc, "pct15")),
pct20: MetricPattern4::new(client.clone(), _m(&acc, "pct20")),
pct25: MetricPattern4::new(client.clone(), _m(&acc, "pct25")),
pct30: MetricPattern4::new(client.clone(), _m(&acc, "pct30")),
pct35: MetricPattern4::new(client.clone(), _m(&acc, "pct35")),
pct40: MetricPattern4::new(client.clone(), _m(&acc, "pct40")),
pct45: MetricPattern4::new(client.clone(), _m(&acc, "pct45")),
pct50: MetricPattern4::new(client.clone(), _m(&acc, "pct50")),
pct55: MetricPattern4::new(client.clone(), _m(&acc, "pct55")),
pct60: MetricPattern4::new(client.clone(), _m(&acc, "pct60")),
pct65: MetricPattern4::new(client.clone(), _m(&acc, "pct65")),
pct70: MetricPattern4::new(client.clone(), _m(&acc, "pct70")),
pct75: MetricPattern4::new(client.clone(), _m(&acc, "pct75")),
pct80: MetricPattern4::new(client.clone(), _m(&acc, "pct80")),
pct85: MetricPattern4::new(client.clone(), _m(&acc, "pct85")),
pct90: MetricPattern4::new(client.clone(), _m(&acc, "pct90")),
pct95: MetricPattern4::new(client.clone(), _m(&acc, "pct95")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern5 {
pub neg_unrealized_loss_rel_to_market_cap: MetricPattern1<StoredF32>,
@@ -3072,6 +3072,40 @@ impl BitcoinPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct ClassAveragePricePattern<T> {
pub _2015: MetricPattern4<T>,
pub _2016: MetricPattern4<T>,
pub _2017: MetricPattern4<T>,
pub _2018: MetricPattern4<T>,
pub _2019: MetricPattern4<T>,
pub _2020: MetricPattern4<T>,
pub _2021: MetricPattern4<T>,
pub _2022: MetricPattern4<T>,
pub _2023: MetricPattern4<T>,
pub _2024: MetricPattern4<T>,
pub _2025: MetricPattern4<T>,
}
impl<T: DeserializeOwned> ClassAveragePricePattern<T> {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_average_price")),
_2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_average_price")),
_2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_average_price")),
_2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_average_price")),
_2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_average_price")),
_2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_average_price")),
_2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_average_price")),
_2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_average_price")),
_2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_average_price")),
_2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_average_price")),
_2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_average_price")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct DollarsPattern<T> {
pub average: MetricPattern2<T>,
@@ -3106,99 +3140,6 @@ impl<T: DeserializeOwned> DollarsPattern<T> {
}
}
/// Pattern struct for repeated tree structure.
pub struct ClassAveragePricePattern<T> {
pub _2015: MetricPattern4<T>,
pub _2016: MetricPattern4<T>,
pub _2017: MetricPattern4<T>,
pub _2018: MetricPattern4<T>,
pub _2019: MetricPattern4<T>,
pub _2020: MetricPattern4<T>,
pub _2021: MetricPattern4<T>,
pub _2022: MetricPattern4<T>,
pub _2023: MetricPattern4<T>,
pub _2024: MetricPattern4<T>,
pub _2025: MetricPattern4<T>,
}
impl<T: DeserializeOwned> ClassAveragePricePattern<T> {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_returns")),
_2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_returns")),
_2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_returns")),
_2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_returns")),
_2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_returns")),
_2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_returns")),
_2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_returns")),
_2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_returns")),
_2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_returns")),
_2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_returns")),
_2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_returns")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern {
pub neg_unrealized_loss_rel_to_market_cap: MetricPattern1<StoredF32>,
pub net_unrealized_pnl_rel_to_market_cap: MetricPattern1<StoredF32>,
pub nupl: MetricPattern1<StoredF32>,
pub supply_in_loss_rel_to_circulating_supply: MetricPattern1<StoredF64>,
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_circulating_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_rel_to_circulating_supply: MetricPattern4<StoredF64>,
pub unrealized_loss_rel_to_market_cap: MetricPattern1<StoredF32>,
pub unrealized_profit_rel_to_market_cap: MetricPattern1<StoredF32>,
}
impl RelativePattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
neg_unrealized_loss_rel_to_market_cap: MetricPattern1::new(
client.clone(),
_m(&acc, "neg_unrealized_loss_rel_to_market_cap"),
),
net_unrealized_pnl_rel_to_market_cap: MetricPattern1::new(
client.clone(),
_m(&acc, "net_unrealized_pnl_rel_to_market_cap"),
),
nupl: MetricPattern1::new(client.clone(), _m(&acc, "nupl")),
supply_in_loss_rel_to_circulating_supply: MetricPattern1::new(
client.clone(),
_m(&acc, "supply_in_loss_rel_to_circulating_supply"),
),
supply_in_loss_rel_to_own_supply: MetricPattern1::new(
client.clone(),
_m(&acc, "supply_in_loss_rel_to_own_supply"),
),
supply_in_profit_rel_to_circulating_supply: MetricPattern1::new(
client.clone(),
_m(&acc, "supply_in_profit_rel_to_circulating_supply"),
),
supply_in_profit_rel_to_own_supply: MetricPattern1::new(
client.clone(),
_m(&acc, "supply_in_profit_rel_to_own_supply"),
),
supply_rel_to_circulating_supply: MetricPattern4::new(
client.clone(),
_m(&acc, "supply_rel_to_circulating_supply"),
),
unrealized_loss_rel_to_market_cap: MetricPattern1::new(
client.clone(),
_m(&acc, "unrealized_loss_rel_to_market_cap"),
),
unrealized_profit_rel_to_market_cap: MetricPattern1::new(
client.clone(),
_m(&acc, "unrealized_profit_rel_to_market_cap"),
),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern2 {
pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1<StoredF32>,
@@ -3261,6 +3202,65 @@ impl RelativePattern2 {
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern {
pub neg_unrealized_loss_rel_to_market_cap: MetricPattern1<StoredF32>,
pub net_unrealized_pnl_rel_to_market_cap: MetricPattern1<StoredF32>,
pub nupl: MetricPattern1<StoredF32>,
pub supply_in_loss_rel_to_circulating_supply: MetricPattern1<StoredF64>,
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_circulating_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_rel_to_circulating_supply: MetricPattern4<StoredF64>,
pub unrealized_loss_rel_to_market_cap: MetricPattern1<StoredF32>,
pub unrealized_profit_rel_to_market_cap: MetricPattern1<StoredF32>,
}
impl RelativePattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
neg_unrealized_loss_rel_to_market_cap: MetricPattern1::new(
client.clone(),
_m(&acc, "neg_unrealized_loss_rel_to_market_cap"),
),
net_unrealized_pnl_rel_to_market_cap: MetricPattern1::new(
client.clone(),
_m(&acc, "net_unrealized_pnl_rel_to_market_cap"),
),
nupl: MetricPattern1::new(client.clone(), _m(&acc, "nupl")),
supply_in_loss_rel_to_circulating_supply: MetricPattern1::new(
client.clone(),
_m(&acc, "supply_in_loss_rel_to_circulating_supply"),
),
supply_in_loss_rel_to_own_supply: MetricPattern1::new(
client.clone(),
_m(&acc, "supply_in_loss_rel_to_own_supply"),
),
supply_in_profit_rel_to_circulating_supply: MetricPattern1::new(
client.clone(),
_m(&acc, "supply_in_profit_rel_to_circulating_supply"),
),
supply_in_profit_rel_to_own_supply: MetricPattern1::new(
client.clone(),
_m(&acc, "supply_in_profit_rel_to_own_supply"),
),
supply_rel_to_circulating_supply: MetricPattern4::new(
client.clone(),
_m(&acc, "supply_rel_to_circulating_supply"),
),
unrealized_loss_rel_to_market_cap: MetricPattern1::new(
client.clone(),
_m(&acc, "unrealized_loss_rel_to_market_cap"),
),
unrealized_profit_rel_to_market_cap: MetricPattern1::new(
client.clone(),
_m(&acc, "unrealized_profit_rel_to_market_cap"),
),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CountPattern2<T> {
pub average: MetricPattern1<T>,
@@ -3466,25 +3466,25 @@ impl PeriodCagrPattern {
}
/// Pattern struct for repeated tree structure.
pub struct _0satsPattern2 {
pub struct _10yTo12yPattern {
pub activity: ActivityPattern2,
pub cost_basis: CostBasisPattern,
pub cost_basis: CostBasisPattern2,
pub outputs: OutputsPattern,
pub realized: RealizedPattern,
pub relative: RelativePattern4,
pub realized: RealizedPattern2,
pub relative: RelativePattern2,
pub supply: SupplyPattern2,
pub unrealized: UnrealizedPattern,
}
impl _0satsPattern2 {
impl _10yTo12yPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
activity: ActivityPattern2::new(client.clone(), acc.clone()),
cost_basis: CostBasisPattern::new(client.clone(), acc.clone()),
cost_basis: CostBasisPattern2::new(client.clone(), acc.clone()),
outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")),
realized: RealizedPattern::new(client.clone(), acc.clone()),
relative: RelativePattern4::new(client.clone(), _m(&acc, "supply_in")),
realized: RealizedPattern2::new(client.clone(), acc.clone()),
relative: RelativePattern2::new(client.clone(), acc.clone()),
supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")),
unrealized: UnrealizedPattern::new(client.clone(), acc.clone()),
}
@@ -3518,25 +3518,25 @@ impl _10yPattern {
}
/// Pattern struct for repeated tree structure.
pub struct _10yTo12yPattern {
pub struct _0satsPattern2 {
pub activity: ActivityPattern2,
pub cost_basis: CostBasisPattern2,
pub cost_basis: CostBasisPattern,
pub outputs: OutputsPattern,
pub realized: RealizedPattern2,
pub relative: RelativePattern2,
pub realized: RealizedPattern,
pub relative: RelativePattern4,
pub supply: SupplyPattern2,
pub unrealized: UnrealizedPattern,
}
impl _10yTo12yPattern {
impl _0satsPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
activity: ActivityPattern2::new(client.clone(), acc.clone()),
cost_basis: CostBasisPattern2::new(client.clone(), acc.clone()),
cost_basis: CostBasisPattern::new(client.clone(), acc.clone()),
outputs: OutputsPattern::new(client.clone(), _m(&acc, "utxo_count")),
realized: RealizedPattern2::new(client.clone(), acc.clone()),
relative: RelativePattern2::new(client.clone(), acc.clone()),
realized: RealizedPattern::new(client.clone(), acc.clone()),
relative: RelativePattern4::new(client.clone(), _m(&acc, "supply_in")),
supply: SupplyPattern2::new(client.clone(), _m(&acc, "supply")),
unrealized: UnrealizedPattern::new(client.clone(), acc.clone()),
}
@@ -3655,24 +3655,6 @@ impl<T: DeserializeOwned> SplitPattern2<T> {
}
}
/// Pattern struct for repeated tree structure.
pub struct CostBasisPattern2 {
pub max: MetricPattern1<Dollars>,
pub min: MetricPattern1<Dollars>,
pub percentiles: PercentilesPattern,
}
impl CostBasisPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
max: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")),
min: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")),
percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CoinbasePattern {
pub bitcoin: BitcoinPattern,
@@ -3692,19 +3674,55 @@ impl CoinbasePattern {
}
/// Pattern struct for repeated tree structure.
pub struct ActiveSupplyPattern {
pub bitcoin: MetricPattern1<Bitcoin>,
pub dollars: MetricPattern1<Dollars>,
pub sats: MetricPattern1<Sats>,
pub struct CoinbasePattern2 {
pub bitcoin: BlockCountPattern<Bitcoin>,
pub dollars: BlockCountPattern<Dollars>,
pub sats: BlockCountPattern<Sats>,
}
impl ActiveSupplyPattern {
impl CoinbasePattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
bitcoin: MetricPattern1::new(client.clone(), _m(&acc, "btc")),
dollars: MetricPattern1::new(client.clone(), _m(&acc, "usd")),
sats: MetricPattern1::new(client.clone(), acc.clone()),
bitcoin: BlockCountPattern::new(client.clone(), _m(&acc, "btc")),
dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")),
sats: BlockCountPattern::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct SegwitAdoptionPattern {
pub base: MetricPattern11<StoredF32>,
pub cumulative: MetricPattern2<StoredF32>,
pub sum: MetricPattern2<StoredF32>,
}
impl SegwitAdoptionPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
base: MetricPattern11::new(client.clone(), acc.clone()),
cumulative: MetricPattern2::new(client.clone(), _m(&acc, "cumulative")),
sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CostBasisPattern2 {
pub max: MetricPattern1<Dollars>,
pub min: MetricPattern1<Dollars>,
pub percentiles: PercentilesPattern,
}
impl CostBasisPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
max: MetricPattern1::new(client.clone(), _m(&acc, "max_cost_basis")),
min: MetricPattern1::new(client.clone(), _m(&acc, "min_cost_basis")),
percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")),
}
}
}
@@ -3727,24 +3745,6 @@ impl UnclaimedRewardsPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct CoinbasePattern2 {
pub bitcoin: BlockCountPattern<Bitcoin>,
pub dollars: BlockCountPattern<Dollars>,
pub sats: BlockCountPattern<Sats>,
}
impl CoinbasePattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
bitcoin: BlockCountPattern::new(client.clone(), _m(&acc, "btc")),
dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")),
sats: BlockCountPattern::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct _2015Pattern {
pub bitcoin: MetricPattern4<Bitcoin>,
@@ -3764,19 +3764,19 @@ impl _2015Pattern {
}
/// Pattern struct for repeated tree structure.
pub struct SegwitAdoptionPattern {
pub base: MetricPattern11<StoredF32>,
pub cumulative: MetricPattern2<StoredF32>,
pub sum: MetricPattern2<StoredF32>,
pub struct ActiveSupplyPattern {
pub bitcoin: MetricPattern1<Bitcoin>,
pub dollars: MetricPattern1<Dollars>,
pub sats: MetricPattern1<Sats>,
}
impl SegwitAdoptionPattern {
impl ActiveSupplyPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
base: MetricPattern11::new(client.clone(), acc.clone()),
cumulative: MetricPattern2::new(client.clone(), _m(&acc, "cumulative")),
sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")),
bitcoin: MetricPattern1::new(client.clone(), _m(&acc, "btc")),
dollars: MetricPattern1::new(client.clone(), _m(&acc, "usd")),
sats: MetricPattern1::new(client.clone(), acc.clone()),
}
}
}
@@ -3797,6 +3797,22 @@ impl _1dReturns1mSdPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct SupplyPattern2 {
pub halved: ActiveSupplyPattern,
pub total: ActiveSupplyPattern,
}
impl SupplyPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
halved: ActiveSupplyPattern::new(client.clone(), _m(&acc, "halved")),
total: ActiveSupplyPattern::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CostBasisPattern {
pub max: MetricPattern1<Dollars>,
@@ -3835,22 +3851,6 @@ impl RelativePattern4 {
}
}
/// Pattern struct for repeated tree structure.
pub struct SupplyPattern2 {
pub halved: ActiveSupplyPattern,
pub total: ActiveSupplyPattern,
}
impl SupplyPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
halved: ActiveSupplyPattern::new(client.clone(), _m(&acc, "halved")),
total: ActiveSupplyPattern::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct BitcoinPattern2<T> {
pub cumulative: MetricPattern2<T>,
@@ -3899,20 +3899,6 @@ impl<T: DeserializeOwned> BlockCountPattern<T> {
}
}
/// Pattern struct for repeated tree structure.
pub struct OutputsPattern {
pub utxo_count: MetricPattern1<StoredU64>,
}
impl OutputsPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
utxo_count: MetricPattern1::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct RealizedPriceExtraPattern {
pub ratio: MetricPattern4<StoredF32>,
@@ -3927,6 +3913,20 @@ impl RealizedPriceExtraPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct OutputsPattern {
pub utxo_count: MetricPattern1<StoredU64>,
}
impl OutputsPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
utxo_count: MetricPattern1::new(client.clone(), acc.clone()),
}
}
}
// Metrics tree
/// Metrics tree node.
@@ -6191,8 +6191,8 @@ impl MetricsTree_Market_Ath {
/// Metrics tree node.
pub struct MetricsTree_Market_Dca {
pub class_average_price: MetricsTree_Market_Dca_ClassAveragePrice,
pub class_returns: ClassAveragePricePattern<StoredF32>,
pub class_average_price: ClassAveragePricePattern<Dollars>,
pub class_returns: MetricsTree_Market_Dca_ClassReturns,
pub class_stack: MetricsTree_Market_Dca_ClassStack,
pub period_average_price: PeriodAveragePricePattern<Dollars>,
pub period_cagr: PeriodCagrPattern,
@@ -6204,11 +6204,14 @@ pub struct MetricsTree_Market_Dca {
impl MetricsTree_Market_Dca {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
class_average_price: MetricsTree_Market_Dca_ClassAveragePrice::new(
class_average_price: ClassAveragePricePattern::new(
client.clone(),
format!("{base_path}_class_average_price"),
"dca_class".to_string(),
),
class_returns: MetricsTree_Market_Dca_ClassReturns::new(
client.clone(),
format!("{base_path}_class_returns"),
),
class_returns: ClassAveragePricePattern::new(client.clone(), "dca_class".to_string()),
class_stack: MetricsTree_Market_Dca_ClassStack::new(
client.clone(),
format!("{base_path}_class_stack"),
@@ -6232,34 +6235,34 @@ impl MetricsTree_Market_Dca {
}
/// Metrics tree node.
pub struct MetricsTree_Market_Dca_ClassAveragePrice {
pub _2015: MetricPattern4<Dollars>,
pub _2016: MetricPattern4<Dollars>,
pub _2017: MetricPattern4<Dollars>,
pub _2018: MetricPattern4<Dollars>,
pub _2019: MetricPattern4<Dollars>,
pub _2020: MetricPattern4<Dollars>,
pub _2021: MetricPattern4<Dollars>,
pub _2022: MetricPattern4<Dollars>,
pub _2023: MetricPattern4<Dollars>,
pub _2024: MetricPattern4<Dollars>,
pub _2025: MetricPattern4<Dollars>,
pub struct MetricsTree_Market_Dca_ClassReturns {
pub _2015: MetricPattern4<StoredF32>,
pub _2016: MetricPattern4<StoredF32>,
pub _2017: MetricPattern4<StoredF32>,
pub _2018: MetricPattern4<StoredF32>,
pub _2019: MetricPattern4<StoredF32>,
pub _2020: MetricPattern4<StoredF32>,
pub _2021: MetricPattern4<StoredF32>,
pub _2022: MetricPattern4<StoredF32>,
pub _2023: MetricPattern4<StoredF32>,
pub _2024: MetricPattern4<StoredF32>,
pub _2025: MetricPattern4<StoredF32>,
}
impl MetricsTree_Market_Dca_ClassAveragePrice {
impl MetricsTree_Market_Dca_ClassReturns {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
_2015: MetricPattern4::new(client.clone(), "dca_class_2015_average_price".to_string()),
_2016: MetricPattern4::new(client.clone(), "dca_class_2016_average_price".to_string()),
_2017: MetricPattern4::new(client.clone(), "dca_class_2017_average_price".to_string()),
_2018: MetricPattern4::new(client.clone(), "dca_class_2018_average_price".to_string()),
_2019: MetricPattern4::new(client.clone(), "dca_class_2019_average_price".to_string()),
_2020: MetricPattern4::new(client.clone(), "dca_class_2020_average_price".to_string()),
_2021: MetricPattern4::new(client.clone(), "dca_class_2021_average_price".to_string()),
_2022: MetricPattern4::new(client.clone(), "dca_class_2022_average_price".to_string()),
_2023: MetricPattern4::new(client.clone(), "dca_class_2023_average_price".to_string()),
_2024: MetricPattern4::new(client.clone(), "dca_class_2024_average_price".to_string()),
_2025: MetricPattern4::new(client.clone(), "dca_class_2025_average_price".to_string()),
_2015: MetricPattern4::new(client.clone(), "dca_class_2015_returns".to_string()),
_2016: MetricPattern4::new(client.clone(), "dca_class_2016_returns".to_string()),
_2017: MetricPattern4::new(client.clone(), "dca_class_2017_returns".to_string()),
_2018: MetricPattern4::new(client.clone(), "dca_class_2018_returns".to_string()),
_2019: MetricPattern4::new(client.clone(), "dca_class_2019_returns".to_string()),
_2020: MetricPattern4::new(client.clone(), "dca_class_2020_returns".to_string()),
_2021: MetricPattern4::new(client.clone(), "dca_class_2021_returns".to_string()),
_2022: MetricPattern4::new(client.clone(), "dca_class_2022_returns".to_string()),
_2023: MetricPattern4::new(client.clone(), "dca_class_2023_returns".to_string()),
_2024: MetricPattern4::new(client.clone(), "dca_class_2024_returns".to_string()),
_2025: MetricPattern4::new(client.clone(), "dca_class_2025_returns".to_string()),
}
}
}
@@ -7599,7 +7602,7 @@ pub struct BrkClient {
impl BrkClient {
/// Client version.
pub const VERSION: &'static str = "v0.1.0-alpha.3";
pub const VERSION: &'static str = "v0.1.0-alpha.6";
/// Create a new client with the given base URL.
pub fn new(base_url: impl Into<String>) -> Self {

View File

@@ -32,5 +32,6 @@ vecdb = { workspace = true }
[dev-dependencies]
brk_alloc = { workspace = true }
plotters = "0.3"
brk_bencher = { workspace = true }
color-eyre = { workspace = true }

View File

@@ -4,7 +4,7 @@ use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{
EmptyAddressData, EmptyAddressIndex, Height, LoadedAddressData, LoadedAddressIndex,
DateIndex, EmptyAddressData, EmptyAddressIndex, Height, LoadedAddressData, LoadedAddressIndex,
SupplyState, Version,
};
use tracing::info;
@@ -242,6 +242,21 @@ impl Vecs {
(recovered_height, chain_state)
};
// Update starting_indexes if we need to recompute from an earlier point
if starting_height < starting_indexes.height {
starting_indexes.height = starting_height;
// Also update dateindex to match
if starting_height.is_zero() {
starting_indexes.dateindex = DateIndex::from(0);
} else {
starting_indexes.dateindex = indexes
.height
.dateindex
.read_once(starting_height.decremented().unwrap())?
.into();
}
}
// 2b. Validate computed versions
let base_version = VERSION;
self.utxo_cohorts.validate_computed_versions(base_version)?;

View File

@@ -15,14 +15,14 @@ mod blocks;
mod cointime;
mod constants;
mod distribution;
mod indexes;
pub mod indexes;
mod inputs;
mod internal;
mod market;
mod outputs;
mod pools;
mod positions;
mod price;
pub mod price;
mod scripts;
mod supply;
mod traits;

7
crates/brk_playground/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
# Ignore everything in playground except essential files
*
!.gitignore
!Cargo.toml
!src/
!src/lib.rs
!README.md

View File

@@ -0,0 +1,20 @@
[package]
name = "brk_playground"
description = "Experimental playground for brk development"
version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
publish = false
[dependencies]
brk_computer = { workspace = true }
brk_error = { workspace = true }
brk_fetcher = { workspace = true }
brk_indexer = { workspace = true }
brk_logger = { workspace = true }
brk_types = { workspace = true }
plotters = "0.3"
tracing = { workspace = true }
vecdb = { workspace = true }

View File

@@ -0,0 +1,4 @@
//! Experimental playground for brk development.
//!
//! This crate is for experiments and prototypes.
//! Most contents are git-ignored.

View File

@@ -6,7 +6,6 @@ edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
include = ["src/**/*", "website/**/*", "examples/**/*", "Cargo.toml", "README.md"]
[dependencies]
aide = { workspace = true }
@@ -22,10 +21,8 @@ brk_reader = { workspace = true }
brk_rpc = { workspace = true }
brk_types = { workspace = true }
brk_traversable = { workspace = true }
brk_website = { workspace = true }
derive_more = { workspace = true }
include_dir = "0.7"
# importmap = { path = "../../../importmap", features = ["embedded"] }
importmap = { version = "0.3.0", features = ["embedded"] }
vecdb = { workspace = true }
jiff = { workspace = true }
quick_cache = "0.6.18"
@@ -34,8 +31,8 @@ serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
tower-http = { version = "0.6.8", features = ["catch-panic", "compression-br", "compression-gzip", "compression-zstd", "cors", "normalize-path", "timeout", "trace"] }
tower-layer = "0.3"
tower-http = { workspace = true }
tower-layer = { workspace = true }
[dev-dependencies]
brk_mempool = { workspace = true }

View File

@@ -1,5 +1,3 @@
use std::path::Path;
use axum::http::{
HeaderMap,
header::{self, IF_NONE_MATCH},
@@ -7,31 +5,29 @@ use axum::http::{
pub trait HeaderMapExtended {
fn has_etag(&self, etag: &str) -> bool;
fn insert_etag(&mut self, etag: &str);
fn insert_cache_control(&mut self, value: &str);
fn insert_cache_control_must_revalidate(&mut self);
fn insert_cache_control_immutable(&mut self);
fn insert_etag(&mut self, etag: &str);
fn insert_content_disposition_attachment(&mut self);
fn insert_content_type(&mut self, path: &Path);
fn insert_content_type_image_icon(&mut self);
fn insert_content_type_image_jpeg(&mut self);
fn insert_content_type_image_png(&mut self);
fn insert_content_type_application_javascript(&mut self);
fn insert_content_type_application_json(&mut self);
fn insert_content_type_application_manifest_json(&mut self);
fn insert_content_type_application_pdf(&mut self);
fn insert_content_type_text_css(&mut self);
fn insert_content_type_text_csv(&mut self);
fn insert_content_type_text_html(&mut self);
fn insert_content_type_text_plain(&mut self);
fn insert_content_type_font_woff2(&mut self);
fn insert_content_type_octet_stream(&mut self);
}
impl HeaderMapExtended for HeaderMap {
fn has_etag(&self, etag: &str) -> bool {
self.get(IF_NONE_MATCH)
.is_some_and(|prev_etag| etag == prev_etag)
}
fn insert_etag(&mut self, etag: &str) {
self.insert(header::ETAG, etag.parse().unwrap());
}
fn insert_cache_control(&mut self, value: &str) {
self.insert(header::CACHE_CONTROL, value.parse().unwrap());
}
@@ -40,99 +36,22 @@ impl HeaderMapExtended for HeaderMap {
self.insert_cache_control("public, max-age=1, must-revalidate");
}
fn insert_cache_control_immutable(&mut self) {
self.insert_cache_control("public, max-age=31536000, immutable");
}
fn insert_content_disposition_attachment(&mut self) {
self.insert(header::CONTENT_DISPOSITION, "attachment".parse().unwrap());
}
fn insert_etag(&mut self, etag: &str) {
self.insert(header::ETAG, etag.parse().unwrap());
}
fn has_etag(&self, etag: &str) -> bool {
self.get(IF_NONE_MATCH)
.is_some_and(|prev_etag| etag == prev_etag)
}
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
fn insert_content_type(&mut self, path: &Path) {
match path
.extension()
.map(|s| s.to_str().unwrap_or_default())
.unwrap_or_default()
{
"js" | "mjs" => self.insert_content_type_application_javascript(),
"json" | "map" => self.insert_content_type_application_json(),
"html" => self.insert_content_type_text_html(),
"css" => self.insert_content_type_text_css(),
"toml" | "txt" => self.insert_content_type_text_plain(),
"pdf" => self.insert_content_type_application_pdf(),
"woff2" => self.insert_content_type_font_woff2(),
"ico" => self.insert_content_type_image_icon(),
"jpg" | "jpeg" => self.insert_content_type_image_jpeg(),
"png" => self.insert_content_type_image_png(),
"webmanifest" => self.insert_content_type_application_manifest_json(),
_ => {}
}
}
fn insert_content_type_image_icon(&mut self) {
self.insert(header::CONTENT_TYPE, "image/x-icon".parse().unwrap());
}
fn insert_content_type_image_jpeg(&mut self) {
self.insert(header::CONTENT_TYPE, "image/jpeg".parse().unwrap());
}
fn insert_content_type_image_png(&mut self) {
self.insert(header::CONTENT_TYPE, "image/png".parse().unwrap());
}
fn insert_content_type_application_javascript(&mut self) {
self.insert(
header::CONTENT_TYPE,
"application/javascript".parse().unwrap(),
);
}
fn insert_content_type_application_json(&mut self) {
self.insert(header::CONTENT_TYPE, "application/json".parse().unwrap());
}
fn insert_content_type_application_manifest_json(&mut self) {
self.insert(
header::CONTENT_TYPE,
"application/manifest+json".parse().unwrap(),
);
}
fn insert_content_type_application_pdf(&mut self) {
self.insert(header::CONTENT_TYPE, "application/pdf".parse().unwrap());
}
fn insert_content_type_text_css(&mut self) {
self.insert(header::CONTENT_TYPE, "text/css".parse().unwrap());
}
fn insert_content_type_text_csv(&mut self) {
self.insert(header::CONTENT_TYPE, "text/csv".parse().unwrap());
}
fn insert_content_type_text_html(&mut self) {
self.insert(header::CONTENT_TYPE, "text/html".parse().unwrap());
}
fn insert_content_type_text_plain(&mut self) {
self.insert(header::CONTENT_TYPE, "text/plain".parse().unwrap());
}
fn insert_content_type_font_woff2(&mut self) {
self.insert(header::CONTENT_TYPE, "font/woff2".parse().unwrap());
}
fn insert_content_type_octet_stream(&mut self) {
self.insert(
header::CONTENT_TYPE,

View File

@@ -1,25 +0,0 @@
use aide::axum::ApiRouter;
use axum::{response::Redirect, routing::get};
use super::AppState;
mod file;
mod website;
use file::{file_handler, index_handler};
pub use website::*;
pub trait FilesRoutes {
fn add_files_routes(self, website: &Website) -> Self;
}
impl FilesRoutes for ApiRouter<AppState> {
fn add_files_routes(self, website: &Website) -> Self {
if website.is_enabled() {
self.route("/{*path}", get(file_handler))
.route("/", get(index_handler))
} else {
self.route("/", get(Redirect::temporary("/api")))
}
}
}

View File

@@ -18,7 +18,6 @@ use axum::{
serve,
};
use brk_query::AsyncQuery;
use include_dir::{Dir, include_dir};
use quick_cache::sync::Cache;
use tokio::net::TcpListener;
use tower_http::{
@@ -29,23 +28,17 @@ use tower_http::{
use tower_layer::Layer;
use tracing::{error, info};
/// Embedded website assets
pub static EMBEDDED_WEBSITE: Dir = include_dir!("$CARGO_MANIFEST_DIR/website");
mod api;
pub mod cache;
mod error;
mod extended;
mod files;
mod state;
use api::*;
pub use brk_types::Port;
pub use brk_website::Website;
pub use cache::{CacheParams, CacheStrategy};
pub use error::{Error, Result};
use extended::*;
use files::FilesRoutes;
pub use files::Website;
use state::*;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
@@ -69,10 +62,7 @@ impl Server {
pub async fn serve(self, port: Option<Port>) -> brk_error::Result<()> {
let state = self.0;
let compression_layer = CompressionLayer::new()
.br(true)
.gzip(true)
.zstd(true);
let compression_layer = CompressionLayer::new().br(true).gzip(true).zstd(true);
let response_uri_layer = axum::middleware::from_fn(
async |request: Request<Body>, next: Next| -> Response<Body> {
@@ -107,35 +97,23 @@ impl Server {
.on_eos(());
let vecs = state.query.inner().vecs();
let router = ApiRouter::new()
.add_api_routes()
.add_files_routes(&state.website)
.route(
"/discord",
get(Redirect::temporary("https://discord.gg/WACpShCB7M")),
)
.route("/crate", get(Redirect::temporary("https://crates.io/crates/brk")))
.route(
"/status",
get(Redirect::temporary("https://status.bitview.space")),
)
.route("/github", get(Redirect::temporary("https://github.com/bitcoinresearchkit/brk")))
.route("/changelog", get(Redirect::temporary("https://github.com/bitcoinresearchkit/brk/blob/main/docs/CHANGELOG.md")))
.route(
"/install",
get(Redirect::temporary("https://github.com/bitcoinresearchkit/brk/blob/main/crates/brk_cli/README.md#brk_cli")),
)
.route(
"/service",
get(Redirect::temporary("https://github.com/bitcoinresearchkit/brk?tab=readme-ov-file#professional-hosting")),
)
.route("/nostr", get(Redirect::temporary("https://primal.net/p/npub1jagmm3x39lmwfnrtvxcs9ac7g300y3dusv9lgzhk2e4x5frpxlrqa73v44")))
let website_router = brk_website::router(state.website.clone());
let mut router = ApiRouter::new().add_api_routes();
if !state.website.is_enabled() {
router = router.route("/", get(Redirect::temporary("/api")));
}
let router = router
.with_state(state)
.merge(website_router)
.layer(CatchPanicLayer::new())
.layer(compression_layer)
.layer(response_uri_layer)
.layer(trace_layer)
.layer(TimeoutLayer::with_status_code(StatusCode::GATEWAY_TIMEOUT, Duration::from_secs(5)))
.layer(TimeoutLayer::with_status_code(
StatusCode::GATEWAY_TIMEOUT,
Duration::from_secs(5),
))
.layer(CorsLayer::permissive());
let (listener, port) = match port {

View File

@@ -0,0 +1,21 @@
[package]
name = "brk_website"
description = "Standalone website server for BRK"
version.workspace = true
edition.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
include = ["src/**/*", "website/**/*", "examples/**/*", "Cargo.toml", "README.md"]
[dependencies]
axum = { workspace = true }
include_dir = "0.7"
importmap = { version = "0.3.0", features = ["embedded"] }
tracing = { workspace = true }
[dev-dependencies]
brk_logger = { workspace = true }
tokio = { workspace = true }
tower-http = { workspace = true }
tower-layer = { workspace = true }

View File

@@ -0,0 +1,44 @@
# brk_website
Website serving for BRK with minimal dependencies.
## Features
- **Embedded assets**: Website files compiled into binary
- **Filesystem mode**: Serve from custom path for development
- **SPA support**: Routes without extensions fallback to index.html
- **ImportMap**: Auto-generates import maps for hashed assets
## Usage
```rust,ignore
use brk_website::{Website, router};
// Create router for website
let website_router = router(Website::Default);
// Merge with your app
let app = your_api_router.merge(website_router);
```
## Website Enum
| Variant | Description |
|---------|-------------|
| `Default` | Filesystem in debug, embedded in release |
| `Filesystem(path)` | Always serve from specified path |
| `Disabled` | No routes registered |
## Standalone Server
See the `website` example for a complete standalone server with compression, tracing, and other middleware.
```sh
cargo run -p brk_website --example website
```
## Dependencies
- `axum` - HTTP routing
- `include_dir` - embedded assets
- `importmap` - asset hashing

View File

@@ -0,0 +1,100 @@
use std::time::Duration;
use axum::{
ServiceExt,
body::Body,
http::{Request, Response, StatusCode, Uri},
middleware::Next,
};
use brk_website::{Website, router};
use tokio::net::TcpListener;
use tower_http::{
catch_panic::CatchPanicLayer,
classify::ServerErrorsFailureClass,
compression::CompressionLayer,
cors::CorsLayer,
normalize_path::NormalizePathLayer,
timeout::TimeoutLayer,
trace::TraceLayer,
};
use tower_layer::Layer;
use tracing::{error, info};
#[tokio::main]
async fn main() -> std::io::Result<()> {
let _ = brk_logger::init(None);
// Use the embedded website (default in release mode)
// Or use Website::Filesystem(path) to serve from a custom path
let website = Website::Default;
if !website.is_enabled() {
eprintln!("Website is disabled");
return Ok(());
}
website.log();
let compression_layer = CompressionLayer::new()
.br(true)
.gzip(true)
.zstd(true);
let response_uri_layer = axum::middleware::from_fn(
async |request: Request<Body>, next: Next| -> Response<Body> {
let uri = request.uri().clone();
let mut response = next.run(request).await;
response.extensions_mut().insert(uri);
response
},
);
let trace_layer = TraceLayer::new_for_http()
.on_request(())
.on_response(
|response: &Response<Body>, latency: Duration, _: &tracing::Span| {
let status = response.status().as_u16();
let Some(uri) = response.extensions().get::<Uri>() else {
return;
};
match response.status() {
StatusCode::OK
| StatusCode::NOT_MODIFIED
| StatusCode::TEMPORARY_REDIRECT
| StatusCode::PERMANENT_REDIRECT => info!(status, %uri, ?latency),
_ => error!(status, %uri, ?latency),
}
},
)
.on_body_chunk(())
.on_failure(
|error: ServerErrorsFailureClass, latency: Duration, _: &tracing::Span| {
error!(?error, ?latency, "request failed");
},
)
.on_eos(());
let app = router(website)
.layer(CatchPanicLayer::new())
.layer(compression_layer)
.layer(response_uri_layer)
.layer(trace_layer)
.layer(TimeoutLayer::with_status_code(
StatusCode::GATEWAY_TIMEOUT,
Duration::from_secs(5),
))
.layer(CorsLayer::permissive());
let port = 3110;
let listener = TcpListener::bind(format!("0.0.0.0:{port}")).await?;
info!("website server listening on port {port}");
let service = NormalizePathLayer::trim_trailing_slash().layer(app);
axum::serve(
listener,
ServiceExt::<Request<Body>>::into_make_service(service),
)
.await
}

View File

@@ -0,0 +1,23 @@
use axum::{
body::Body,
http::{Response, StatusCode},
response::IntoResponse,
};
/// Website result type.
pub type Result<T> = std::result::Result<T, Error>;
/// Website error type that maps to HTTP status codes.
pub struct Error(StatusCode, String);
impl Error {
pub fn not_found(msg: impl Into<String>) -> Self {
Self(StatusCode::NOT_FOUND, msg.into())
}
}
impl IntoResponse for Error {
fn into_response(self) -> Response<Body> {
(self.0, self.1).into_response()
}
}

View File

@@ -1,23 +1,23 @@
use std::path::Path;
use axum::{body::Body, extract::State, response::Response};
use axum::{body::Body, extract::State, http::Response};
use crate::{AppState, HeaderMapExtended, Result};
use crate::{HeaderMapExtended, Result, Website};
pub async fn file_handler(
State(state): State<AppState>,
State(website): State<Website>,
path: axum::extract::Path<String>,
) -> Result<Response> {
serve(&state, &path.0)
) -> Result<Response<Body>> {
serve(&website, &path.0)
}
pub async fn index_handler(State(state): State<AppState>) -> Result<Response> {
serve(&state, "")
pub async fn index_handler(State(website): State<Website>) -> Result<Response<Body>> {
serve(&website, "")
}
fn serve(state: &AppState, path: &str) -> Result<Response> {
fn serve(website: &Website, path: &str) -> Result<Response<Body>> {
let path = sanitize(path);
let content = state.website.get_file(&path)?;
let content = website.get_file(&path)?;
let mut response = Response::new(Body::from(content));
let headers = response.headers_mut();

View File

@@ -0,0 +1,53 @@
use std::path::Path;
use axum::http::{HeaderMap, header};
pub trait HeaderMapExtended {
fn insert_cache_control_must_revalidate(&mut self);
fn insert_cache_control_immutable(&mut self);
fn insert_content_type(&mut self, path: &Path);
fn insert_content_type_text_html(&mut self);
}
impl HeaderMapExtended for HeaderMap {
fn insert_cache_control_must_revalidate(&mut self) {
self.insert(
header::CACHE_CONTROL,
"public, max-age=1, must-revalidate".parse().unwrap(),
);
}
fn insert_cache_control_immutable(&mut self) {
self.insert(
header::CACHE_CONTROL,
"public, max-age=31536000, immutable".parse().unwrap(),
);
}
fn insert_content_type(&mut self, path: &Path) {
let content_type = match path
.extension()
.map(|s| s.to_str().unwrap_or_default())
.unwrap_or_default()
{
"js" | "mjs" => "application/javascript",
"json" | "map" => "application/json",
"html" => "text/html",
"css" => "text/css",
"toml" | "txt" => "text/plain",
"pdf" => "application/pdf",
"woff2" => "font/woff2",
"ico" => "image/x-icon",
"jpg" | "jpeg" => "image/jpeg",
"png" => "image/png",
"svg" => "image/svg+xml",
"webmanifest" => "application/manifest+json",
_ => return,
};
self.insert(header::CONTENT_TYPE, content_type.parse().unwrap());
}
fn insert_content_type_text_html(&mut self) {
self.insert(header::CONTENT_TYPE, "text/html".parse().unwrap());
}
}

View File

@@ -0,0 +1,17 @@
//! Standalone website serving for BRK.
//!
//! This crate provides website serving without any BRK data layer dependencies.
//! It can serve the embedded website or from a filesystem path.
//!
//! See the `website` example for how to run a standalone server.
mod error;
mod handlers;
mod headers;
mod router;
mod website;
pub use error::{Error, Result};
pub use headers::HeaderMapExtended;
pub use router::router;
pub use website::{EMBEDDED_WEBSITE, Website};

View File

@@ -0,0 +1,17 @@
use axum::{Router, routing::get};
use crate::{Website, handlers::{file_handler, index_handler}};
/// Create a router for serving the website.
///
/// Returns an empty router if the website is disabled.
pub fn router(website: Website) -> Router {
if website.is_enabled() {
Router::new()
.route("/{*path}", get(file_handler))
.route("/", get(index_handler))
.with_state(website)
} else {
Router::new()
}
}

View File

@@ -5,17 +5,22 @@ use std::{
};
use importmap::ImportMap;
use include_dir::{Dir, include_dir};
use tracing::{error, info};
use crate::{EMBEDDED_WEBSITE, Error, Result};
use crate::{Error, Result};
/// Embedded website assets
pub static EMBEDDED_WEBSITE: Dir = include_dir!("$CARGO_MANIFEST_DIR/website");
/// Cached index.html with importmap injected
static INDEX_HTML: OnceLock<String> = OnceLock::new();
/// Source for serving the website
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Default)]
pub enum Website {
Disabled,
#[default]
Default,
Filesystem(PathBuf),
}
@@ -42,7 +47,12 @@ impl Website {
}
/// Get file content by path (handles hash-stripping, SPA fallback, importmap)
///
/// Returns an error if the website is disabled.
pub fn get_file(&self, path: &str) -> Result<Vec<u8>> {
if !self.is_enabled() {
return Err(Error::not_found("Website is disabled"));
}
match self.filesystem_path() {
None => self.get_embedded(path),
Some(base) => self.get_filesystem(&base, path),
@@ -52,15 +62,15 @@ impl Website {
/// Log which website source is being used (call once at startup)
pub fn log(&self) {
match self {
Self::Disabled => info!("Website: disabled"),
Self::Disabled => info!("website: disabled"),
Self::Default => {
if let Some(p) = self.filesystem_path() {
info!("Website: filesystem ({})", p.display());
info!("website: filesystem ({})", p.display());
} else {
info!("Website: embedded");
info!("website: embedded");
}
}
Self::Filesystem(p) => info!("Website: filesystem ({})", p.display()),
Self::Filesystem(p) => info!("website: filesystem ({})", p.display()),
}
}

View File

@@ -1645,59 +1645,6 @@ function createPrice111dSmaPattern(client, acc) {
};
}
/**
* @typedef {Object} PercentilesPattern
* @property {MetricPattern4<Dollars>} pct05
* @property {MetricPattern4<Dollars>} pct10
* @property {MetricPattern4<Dollars>} pct15
* @property {MetricPattern4<Dollars>} pct20
* @property {MetricPattern4<Dollars>} pct25
* @property {MetricPattern4<Dollars>} pct30
* @property {MetricPattern4<Dollars>} pct35
* @property {MetricPattern4<Dollars>} pct40
* @property {MetricPattern4<Dollars>} pct45
* @property {MetricPattern4<Dollars>} pct50
* @property {MetricPattern4<Dollars>} pct55
* @property {MetricPattern4<Dollars>} pct60
* @property {MetricPattern4<Dollars>} pct65
* @property {MetricPattern4<Dollars>} pct70
* @property {MetricPattern4<Dollars>} pct75
* @property {MetricPattern4<Dollars>} pct80
* @property {MetricPattern4<Dollars>} pct85
* @property {MetricPattern4<Dollars>} pct90
* @property {MetricPattern4<Dollars>} pct95
*/
/**
* Create a PercentilesPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {PercentilesPattern}
*/
function createPercentilesPattern(client, acc) {
return {
pct05: createMetricPattern4(client, _m(acc, 'pct05')),
pct10: createMetricPattern4(client, _m(acc, 'pct10')),
pct15: createMetricPattern4(client, _m(acc, 'pct15')),
pct20: createMetricPattern4(client, _m(acc, 'pct20')),
pct25: createMetricPattern4(client, _m(acc, 'pct25')),
pct30: createMetricPattern4(client, _m(acc, 'pct30')),
pct35: createMetricPattern4(client, _m(acc, 'pct35')),
pct40: createMetricPattern4(client, _m(acc, 'pct40')),
pct45: createMetricPattern4(client, _m(acc, 'pct45')),
pct50: createMetricPattern4(client, _m(acc, 'pct50')),
pct55: createMetricPattern4(client, _m(acc, 'pct55')),
pct60: createMetricPattern4(client, _m(acc, 'pct60')),
pct65: createMetricPattern4(client, _m(acc, 'pct65')),
pct70: createMetricPattern4(client, _m(acc, 'pct70')),
pct75: createMetricPattern4(client, _m(acc, 'pct75')),
pct80: createMetricPattern4(client, _m(acc, 'pct80')),
pct85: createMetricPattern4(client, _m(acc, 'pct85')),
pct90: createMetricPattern4(client, _m(acc, 'pct90')),
pct95: createMetricPattern4(client, _m(acc, 'pct95')),
};
}
/**
* @typedef {Object} ActivePriceRatioPattern
* @property {MetricPattern4<StoredF32>} ratio
@@ -1751,6 +1698,59 @@ function createActivePriceRatioPattern(client, acc) {
};
}
/**
* @typedef {Object} PercentilesPattern
* @property {MetricPattern4<Dollars>} pct05
* @property {MetricPattern4<Dollars>} pct10
* @property {MetricPattern4<Dollars>} pct15
* @property {MetricPattern4<Dollars>} pct20
* @property {MetricPattern4<Dollars>} pct25
* @property {MetricPattern4<Dollars>} pct30
* @property {MetricPattern4<Dollars>} pct35
* @property {MetricPattern4<Dollars>} pct40
* @property {MetricPattern4<Dollars>} pct45
* @property {MetricPattern4<Dollars>} pct50
* @property {MetricPattern4<Dollars>} pct55
* @property {MetricPattern4<Dollars>} pct60
* @property {MetricPattern4<Dollars>} pct65
* @property {MetricPattern4<Dollars>} pct70
* @property {MetricPattern4<Dollars>} pct75
* @property {MetricPattern4<Dollars>} pct80
* @property {MetricPattern4<Dollars>} pct85
* @property {MetricPattern4<Dollars>} pct90
* @property {MetricPattern4<Dollars>} pct95
*/
/**
* Create a PercentilesPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {PercentilesPattern}
*/
function createPercentilesPattern(client, acc) {
return {
pct05: createMetricPattern4(client, _m(acc, 'pct05')),
pct10: createMetricPattern4(client, _m(acc, 'pct10')),
pct15: createMetricPattern4(client, _m(acc, 'pct15')),
pct20: createMetricPattern4(client, _m(acc, 'pct20')),
pct25: createMetricPattern4(client, _m(acc, 'pct25')),
pct30: createMetricPattern4(client, _m(acc, 'pct30')),
pct35: createMetricPattern4(client, _m(acc, 'pct35')),
pct40: createMetricPattern4(client, _m(acc, 'pct40')),
pct45: createMetricPattern4(client, _m(acc, 'pct45')),
pct50: createMetricPattern4(client, _m(acc, 'pct50')),
pct55: createMetricPattern4(client, _m(acc, 'pct55')),
pct60: createMetricPattern4(client, _m(acc, 'pct60')),
pct65: createMetricPattern4(client, _m(acc, 'pct65')),
pct70: createMetricPattern4(client, _m(acc, 'pct70')),
pct75: createMetricPattern4(client, _m(acc, 'pct75')),
pct80: createMetricPattern4(client, _m(acc, 'pct80')),
pct85: createMetricPattern4(client, _m(acc, 'pct85')),
pct90: createMetricPattern4(client, _m(acc, 'pct90')),
pct95: createMetricPattern4(client, _m(acc, 'pct95')),
};
}
/**
* @typedef {Object} RelativePattern5
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToMarketCap
@@ -2005,6 +2005,45 @@ function createBitcoinPattern(client, acc) {
};
}
/**
* @template T
* @typedef {Object} ClassAveragePricePattern
* @property {MetricPattern4<T>} _2015
* @property {MetricPattern4<T>} _2016
* @property {MetricPattern4<T>} _2017
* @property {MetricPattern4<T>} _2018
* @property {MetricPattern4<T>} _2019
* @property {MetricPattern4<T>} _2020
* @property {MetricPattern4<T>} _2021
* @property {MetricPattern4<T>} _2022
* @property {MetricPattern4<T>} _2023
* @property {MetricPattern4<T>} _2024
* @property {MetricPattern4<T>} _2025
*/
/**
* Create a ClassAveragePricePattern pattern node
* @template T
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {ClassAveragePricePattern<T>}
*/
function createClassAveragePricePattern(client, acc) {
return {
_2015: createMetricPattern4(client, _m(acc, '2015_average_price')),
_2016: createMetricPattern4(client, _m(acc, '2016_average_price')),
_2017: createMetricPattern4(client, _m(acc, '2017_average_price')),
_2018: createMetricPattern4(client, _m(acc, '2018_average_price')),
_2019: createMetricPattern4(client, _m(acc, '2019_average_price')),
_2020: createMetricPattern4(client, _m(acc, '2020_average_price')),
_2021: createMetricPattern4(client, _m(acc, '2021_average_price')),
_2022: createMetricPattern4(client, _m(acc, '2022_average_price')),
_2023: createMetricPattern4(client, _m(acc, '2023_average_price')),
_2024: createMetricPattern4(client, _m(acc, '2024_average_price')),
_2025: createMetricPattern4(client, _m(acc, '2025_average_price')),
};
}
/**
* @template T
* @typedef {Object} DollarsPattern
@@ -2045,41 +2084,37 @@ function createDollarsPattern(client, acc) {
}
/**
* @template T
* @typedef {Object} ClassAveragePricePattern
* @property {MetricPattern4<T>} _2015
* @property {MetricPattern4<T>} _2016
* @property {MetricPattern4<T>} _2017
* @property {MetricPattern4<T>} _2018
* @property {MetricPattern4<T>} _2019
* @property {MetricPattern4<T>} _2020
* @property {MetricPattern4<T>} _2021
* @property {MetricPattern4<T>} _2022
* @property {MetricPattern4<T>} _2023
* @property {MetricPattern4<T>} _2024
* @property {MetricPattern4<T>} _2025
* @typedef {Object} RelativePattern2
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF32>} netUnrealizedPnlRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} netUnrealizedPnlRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF64>} supplyInLossRelToOwnSupply
* @property {MetricPattern1<StoredF64>} supplyInProfitRelToOwnSupply
* @property {MetricPattern1<StoredF32>} unrealizedLossRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} unrealizedLossRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF32>} unrealizedProfitRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} unrealizedProfitRelToOwnTotalUnrealizedPnl
*/
/**
* Create a ClassAveragePricePattern pattern node
* @template T
* Create a RelativePattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {ClassAveragePricePattern<T>}
* @returns {RelativePattern2}
*/
function createClassAveragePricePattern(client, acc) {
function createRelativePattern2(client, acc) {
return {
_2015: createMetricPattern4(client, _m(acc, '2015_returns')),
_2016: createMetricPattern4(client, _m(acc, '2016_returns')),
_2017: createMetricPattern4(client, _m(acc, '2017_returns')),
_2018: createMetricPattern4(client, _m(acc, '2018_returns')),
_2019: createMetricPattern4(client, _m(acc, '2019_returns')),
_2020: createMetricPattern4(client, _m(acc, '2020_returns')),
_2021: createMetricPattern4(client, _m(acc, '2021_returns')),
_2022: createMetricPattern4(client, _m(acc, '2022_returns')),
_2023: createMetricPattern4(client, _m(acc, '2023_returns')),
_2024: createMetricPattern4(client, _m(acc, '2024_returns')),
_2025: createMetricPattern4(client, _m(acc, '2025_returns')),
negUnrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')),
negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')),
netUnrealizedPnlRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')),
netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')),
supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')),
supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')),
unrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')),
unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')),
unrealizedProfitRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')),
unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')),
};
}
@@ -2118,41 +2153,6 @@ function createRelativePattern(client, acc) {
};
}
/**
* @typedef {Object} RelativePattern2
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF32>} netUnrealizedPnlRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} netUnrealizedPnlRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF64>} supplyInLossRelToOwnSupply
* @property {MetricPattern1<StoredF64>} supplyInProfitRelToOwnSupply
* @property {MetricPattern1<StoredF32>} unrealizedLossRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} unrealizedLossRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF32>} unrealizedProfitRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} unrealizedProfitRelToOwnTotalUnrealizedPnl
*/
/**
* Create a RelativePattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {RelativePattern2}
*/
function createRelativePattern2(client, acc) {
return {
negUnrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')),
negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')),
netUnrealizedPnlRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')),
netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')),
supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')),
supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')),
unrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')),
unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')),
unrealizedProfitRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')),
unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')),
};
}
/**
* @template T
* @typedef {Object} CountPattern2
@@ -2387,29 +2387,29 @@ function createPeriodCagrPattern(client, acc) {
}
/**
* @typedef {Object} _0satsPattern2
* @typedef {Object} _10yTo12yPattern
* @property {ActivityPattern2} activity
* @property {CostBasisPattern} costBasis
* @property {CostBasisPattern2} costBasis
* @property {OutputsPattern} outputs
* @property {RealizedPattern} realized
* @property {RelativePattern4} relative
* @property {RealizedPattern2} realized
* @property {RelativePattern2} relative
* @property {SupplyPattern2} supply
* @property {UnrealizedPattern} unrealized
*/
/**
* Create a _0satsPattern2 pattern node
* Create a _10yTo12yPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {_0satsPattern2}
* @returns {_10yTo12yPattern}
*/
function create_0satsPattern2(client, acc) {
function create_10yTo12yPattern(client, acc) {
return {
activity: createActivityPattern2(client, acc),
costBasis: createCostBasisPattern(client, acc),
costBasis: createCostBasisPattern2(client, acc),
outputs: createOutputsPattern(client, _m(acc, 'utxo_count')),
realized: createRealizedPattern(client, acc),
relative: createRelativePattern4(client, _m(acc, 'supply_in')),
realized: createRealizedPattern2(client, acc),
relative: createRelativePattern2(client, acc),
supply: createSupplyPattern2(client, _m(acc, 'supply')),
unrealized: createUnrealizedPattern(client, acc),
};
@@ -2445,29 +2445,29 @@ function create_10yPattern(client, acc) {
}
/**
* @typedef {Object} _10yTo12yPattern
* @typedef {Object} _0satsPattern2
* @property {ActivityPattern2} activity
* @property {CostBasisPattern2} costBasis
* @property {CostBasisPattern} costBasis
* @property {OutputsPattern} outputs
* @property {RealizedPattern2} realized
* @property {RelativePattern2} relative
* @property {RealizedPattern} realized
* @property {RelativePattern4} relative
* @property {SupplyPattern2} supply
* @property {UnrealizedPattern} unrealized
*/
/**
* Create a _10yTo12yPattern pattern node
* Create a _0satsPattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {_10yTo12yPattern}
* @returns {_0satsPattern2}
*/
function create_10yTo12yPattern(client, acc) {
function create_0satsPattern2(client, acc) {
return {
activity: createActivityPattern2(client, acc),
costBasis: createCostBasisPattern2(client, acc),
costBasis: createCostBasisPattern(client, acc),
outputs: createOutputsPattern(client, _m(acc, 'utxo_count')),
realized: createRealizedPattern2(client, acc),
relative: createRelativePattern2(client, acc),
realized: createRealizedPattern(client, acc),
relative: createRelativePattern4(client, _m(acc, 'supply_in')),
supply: createSupplyPattern2(client, _m(acc, 'supply')),
unrealized: createUnrealizedPattern(client, acc),
};
@@ -2581,27 +2581,6 @@ function createSplitPattern2(client, acc) {
};
}
/**
* @typedef {Object} CostBasisPattern2
* @property {MetricPattern1<Dollars>} max
* @property {MetricPattern1<Dollars>} min
* @property {PercentilesPattern} percentiles
*/
/**
* Create a CostBasisPattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {CostBasisPattern2}
*/
function createCostBasisPattern2(client, acc) {
return {
max: createMetricPattern1(client, _m(acc, 'max_cost_basis')),
min: createMetricPattern1(client, _m(acc, 'min_cost_basis')),
percentiles: createPercentilesPattern(client, _m(acc, 'cost_basis')),
};
}
/**
* @typedef {Object} CoinbasePattern
* @property {BitcoinPattern} bitcoin
@@ -2624,23 +2603,65 @@ function createCoinbasePattern(client, acc) {
}
/**
* @typedef {Object} ActiveSupplyPattern
* @property {MetricPattern1<Bitcoin>} bitcoin
* @property {MetricPattern1<Dollars>} dollars
* @property {MetricPattern1<Sats>} sats
* @typedef {Object} CoinbasePattern2
* @property {BlockCountPattern<Bitcoin>} bitcoin
* @property {BlockCountPattern<Dollars>} dollars
* @property {BlockCountPattern<Sats>} sats
*/
/**
* Create a ActiveSupplyPattern pattern node
* Create a CoinbasePattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {ActiveSupplyPattern}
* @returns {CoinbasePattern2}
*/
function createActiveSupplyPattern(client, acc) {
function createCoinbasePattern2(client, acc) {
return {
bitcoin: createMetricPattern1(client, _m(acc, 'btc')),
dollars: createMetricPattern1(client, _m(acc, 'usd')),
sats: createMetricPattern1(client, acc),
bitcoin: createBlockCountPattern(client, _m(acc, 'btc')),
dollars: createBlockCountPattern(client, _m(acc, 'usd')),
sats: createBlockCountPattern(client, acc),
};
}
/**
* @typedef {Object} SegwitAdoptionPattern
* @property {MetricPattern11<StoredF32>} base
* @property {MetricPattern2<StoredF32>} cumulative
* @property {MetricPattern2<StoredF32>} sum
*/
/**
* Create a SegwitAdoptionPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {SegwitAdoptionPattern}
*/
function createSegwitAdoptionPattern(client, acc) {
return {
base: createMetricPattern11(client, acc),
cumulative: createMetricPattern2(client, _m(acc, 'cumulative')),
sum: createMetricPattern2(client, _m(acc, 'sum')),
};
}
/**
* @typedef {Object} CostBasisPattern2
* @property {MetricPattern1<Dollars>} max
* @property {MetricPattern1<Dollars>} min
* @property {PercentilesPattern} percentiles
*/
/**
* Create a CostBasisPattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {CostBasisPattern2}
*/
function createCostBasisPattern2(client, acc) {
return {
max: createMetricPattern1(client, _m(acc, 'max_cost_basis')),
min: createMetricPattern1(client, _m(acc, 'min_cost_basis')),
percentiles: createPercentilesPattern(client, _m(acc, 'cost_basis')),
};
}
@@ -2665,27 +2686,6 @@ function createUnclaimedRewardsPattern(client, acc) {
};
}
/**
* @typedef {Object} CoinbasePattern2
* @property {BlockCountPattern<Bitcoin>} bitcoin
* @property {BlockCountPattern<Dollars>} dollars
* @property {BlockCountPattern<Sats>} sats
*/
/**
* Create a CoinbasePattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {CoinbasePattern2}
*/
function createCoinbasePattern2(client, acc) {
return {
bitcoin: createBlockCountPattern(client, _m(acc, 'btc')),
dollars: createBlockCountPattern(client, _m(acc, 'usd')),
sats: createBlockCountPattern(client, acc),
};
}
/**
* @typedef {Object} _2015Pattern
* @property {MetricPattern4<Bitcoin>} bitcoin
@@ -2708,23 +2708,23 @@ function create_2015Pattern(client, acc) {
}
/**
* @typedef {Object} SegwitAdoptionPattern
* @property {MetricPattern11<StoredF32>} base
* @property {MetricPattern2<StoredF32>} cumulative
* @property {MetricPattern2<StoredF32>} sum
* @typedef {Object} ActiveSupplyPattern
* @property {MetricPattern1<Bitcoin>} bitcoin
* @property {MetricPattern1<Dollars>} dollars
* @property {MetricPattern1<Sats>} sats
*/
/**
* Create a SegwitAdoptionPattern pattern node
* Create a ActiveSupplyPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {SegwitAdoptionPattern}
* @returns {ActiveSupplyPattern}
*/
function createSegwitAdoptionPattern(client, acc) {
function createActiveSupplyPattern(client, acc) {
return {
base: createMetricPattern11(client, acc),
cumulative: createMetricPattern2(client, _m(acc, 'cumulative')),
sum: createMetricPattern2(client, _m(acc, 'sum')),
bitcoin: createMetricPattern1(client, _m(acc, 'btc')),
dollars: createMetricPattern1(client, _m(acc, 'usd')),
sats: createMetricPattern1(client, acc),
};
}
@@ -2747,6 +2747,25 @@ function create_1dReturns1mSdPattern(client, acc) {
};
}
/**
* @typedef {Object} SupplyPattern2
* @property {ActiveSupplyPattern} halved
* @property {ActiveSupplyPattern} total
*/
/**
* Create a SupplyPattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {SupplyPattern2}
*/
function createSupplyPattern2(client, acc) {
return {
halved: createActiveSupplyPattern(client, _m(acc, 'halved')),
total: createActiveSupplyPattern(client, acc),
};
}
/**
* @typedef {Object} CostBasisPattern
* @property {MetricPattern1<Dollars>} max
@@ -2785,25 +2804,6 @@ function createRelativePattern4(client, acc) {
};
}
/**
* @typedef {Object} SupplyPattern2
* @property {ActiveSupplyPattern} halved
* @property {ActiveSupplyPattern} total
*/
/**
* Create a SupplyPattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {SupplyPattern2}
*/
function createSupplyPattern2(client, acc) {
return {
halved: createActiveSupplyPattern(client, _m(acc, 'halved')),
total: createActiveSupplyPattern(client, acc),
};
}
/**
* @template T
* @typedef {Object} BitcoinPattern2
@@ -2867,23 +2867,6 @@ function createBlockCountPattern(client, acc) {
};
}
/**
* @typedef {Object} OutputsPattern
* @property {MetricPattern1<StoredU64>} utxoCount
*/
/**
* Create a OutputsPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {OutputsPattern}
*/
function createOutputsPattern(client, acc) {
return {
utxoCount: createMetricPattern1(client, acc),
};
}
/**
* @typedef {Object} RealizedPriceExtraPattern
* @property {MetricPattern4<StoredF32>} ratio
@@ -2901,6 +2884,23 @@ function createRealizedPriceExtraPattern(client, acc) {
};
}
/**
* @typedef {Object} OutputsPattern
* @property {MetricPattern1<StoredU64>} utxoCount
*/
/**
* Create a OutputsPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {OutputsPattern}
*/
function createOutputsPattern(client, acc) {
return {
utxoCount: createMetricPattern1(client, acc),
};
}
// Catalog tree typedefs
/**
@@ -3696,8 +3696,8 @@ function createRealizedPriceExtraPattern(client, acc) {
/**
* @typedef {Object} MetricsTree_Market_Dca
* @property {MetricsTree_Market_Dca_ClassAveragePrice} classAveragePrice
* @property {ClassAveragePricePattern<StoredF32>} classReturns
* @property {ClassAveragePricePattern<Dollars>} classAveragePrice
* @property {MetricsTree_Market_Dca_ClassReturns} classReturns
* @property {MetricsTree_Market_Dca_ClassStack} classStack
* @property {PeriodAveragePricePattern<Dollars>} periodAveragePrice
* @property {PeriodCagrPattern} periodCagr
@@ -3707,18 +3707,18 @@ function createRealizedPriceExtraPattern(client, acc) {
*/
/**
* @typedef {Object} MetricsTree_Market_Dca_ClassAveragePrice
* @property {MetricPattern4<Dollars>} _2015
* @property {MetricPattern4<Dollars>} _2016
* @property {MetricPattern4<Dollars>} _2017
* @property {MetricPattern4<Dollars>} _2018
* @property {MetricPattern4<Dollars>} _2019
* @property {MetricPattern4<Dollars>} _2020
* @property {MetricPattern4<Dollars>} _2021
* @property {MetricPattern4<Dollars>} _2022
* @property {MetricPattern4<Dollars>} _2023
* @property {MetricPattern4<Dollars>} _2024
* @property {MetricPattern4<Dollars>} _2025
* @typedef {Object} MetricsTree_Market_Dca_ClassReturns
* @property {MetricPattern4<StoredF32>} _2015
* @property {MetricPattern4<StoredF32>} _2016
* @property {MetricPattern4<StoredF32>} _2017
* @property {MetricPattern4<StoredF32>} _2018
* @property {MetricPattern4<StoredF32>} _2019
* @property {MetricPattern4<StoredF32>} _2020
* @property {MetricPattern4<StoredF32>} _2021
* @property {MetricPattern4<StoredF32>} _2022
* @property {MetricPattern4<StoredF32>} _2023
* @property {MetricPattern4<StoredF32>} _2024
* @property {MetricPattern4<StoredF32>} _2025
*/
/**
@@ -4259,7 +4259,7 @@ function createRealizedPriceExtraPattern(client, acc) {
* @extends BrkClientBase
*/
class BrkClient extends BrkClientBase {
VERSION = "v0.1.0-alpha.3";
VERSION = "v0.1.0-alpha.6";
INDEXES = /** @type {const} */ ([
"dateindex",
@@ -5726,20 +5726,20 @@ class BrkClient extends BrkClientBase {
yearsSincePriceAth: createMetricPattern4(this, 'years_since_price_ath'),
},
dca: {
classAveragePrice: {
_2015: createMetricPattern4(this, 'dca_class_2015_average_price'),
_2016: createMetricPattern4(this, 'dca_class_2016_average_price'),
_2017: createMetricPattern4(this, 'dca_class_2017_average_price'),
_2018: createMetricPattern4(this, 'dca_class_2018_average_price'),
_2019: createMetricPattern4(this, 'dca_class_2019_average_price'),
_2020: createMetricPattern4(this, 'dca_class_2020_average_price'),
_2021: createMetricPattern4(this, 'dca_class_2021_average_price'),
_2022: createMetricPattern4(this, 'dca_class_2022_average_price'),
_2023: createMetricPattern4(this, 'dca_class_2023_average_price'),
_2024: createMetricPattern4(this, 'dca_class_2024_average_price'),
_2025: createMetricPattern4(this, 'dca_class_2025_average_price'),
classAveragePrice: createClassAveragePricePattern(this, 'dca_class'),
classReturns: {
_2015: createMetricPattern4(this, 'dca_class_2015_returns'),
_2016: createMetricPattern4(this, 'dca_class_2016_returns'),
_2017: createMetricPattern4(this, 'dca_class_2017_returns'),
_2018: createMetricPattern4(this, 'dca_class_2018_returns'),
_2019: createMetricPattern4(this, 'dca_class_2019_returns'),
_2020: createMetricPattern4(this, 'dca_class_2020_returns'),
_2021: createMetricPattern4(this, 'dca_class_2021_returns'),
_2022: createMetricPattern4(this, 'dca_class_2022_returns'),
_2023: createMetricPattern4(this, 'dca_class_2023_returns'),
_2024: createMetricPattern4(this, 'dca_class_2024_returns'),
_2025: createMetricPattern4(this, 'dca_class_2025_returns'),
},
classReturns: createClassAveragePricePattern(this, 'dca_class'),
classStack: {
_2015: create_2015Pattern(this, 'dca_class_2015_stack'),
_2016: create_2015Pattern(this, 'dca_class_2016_stack'),

View File

@@ -1883,31 +1883,6 @@ class Price111dSmaPattern:
self.ratio_pct99_usd: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'ratio_pct99_usd'))
self.ratio_sd: Ratio1ySdPattern = Ratio1ySdPattern(client, _m(acc, 'ratio'))
class PercentilesPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.pct05: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct05'))
self.pct10: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct10'))
self.pct15: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct15'))
self.pct20: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct20'))
self.pct25: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct25'))
self.pct30: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct30'))
self.pct35: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct35'))
self.pct40: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct40'))
self.pct45: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct45'))
self.pct50: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct50'))
self.pct55: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct55'))
self.pct60: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct60'))
self.pct65: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct65'))
self.pct70: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct70'))
self.pct75: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct75'))
self.pct80: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct80'))
self.pct85: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct85'))
self.pct90: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct90'))
self.pct95: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct95'))
class ActivePriceRatioPattern:
"""Pattern struct for repeated tree structure."""
@@ -1933,6 +1908,31 @@ class ActivePriceRatioPattern:
self.ratio_pct99_usd: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct99_usd'))
self.ratio_sd: Ratio1ySdPattern = Ratio1ySdPattern(client, acc)
class PercentilesPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.pct05: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct05'))
self.pct10: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct10'))
self.pct15: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct15'))
self.pct20: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct20'))
self.pct25: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct25'))
self.pct30: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct30'))
self.pct35: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct35'))
self.pct40: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct40'))
self.pct45: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct45'))
self.pct50: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct50'))
self.pct55: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct55'))
self.pct60: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct60'))
self.pct65: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct65'))
self.pct70: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct70'))
self.pct75: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct75'))
self.pct80: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct80'))
self.pct85: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct85'))
self.pct90: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct90'))
self.pct95: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'pct95'))
class RelativePattern5:
"""Pattern struct for repeated tree structure."""
@@ -2049,6 +2049,23 @@ class BitcoinPattern:
self.pct90: MetricPattern6[Bitcoin] = MetricPattern6(client, _m(acc, 'pct90'))
self.sum: MetricPattern2[Bitcoin] = MetricPattern2(client, _m(acc, 'sum'))
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'))
class DollarsPattern(Generic[T]):
"""Pattern struct for repeated tree structure."""
@@ -2066,22 +2083,21 @@ class DollarsPattern(Generic[T]):
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum'))
class ClassAveragePricePattern(Generic[T]):
class RelativePattern2:
"""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.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 RelativePattern:
"""Pattern struct for repeated tree structure."""
@@ -2099,22 +2115,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."""
@@ -2217,16 +2217,16 @@ class PeriodCagrPattern:
self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc))
self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc))
class _0satsPattern2:
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: CostBasisPattern = CostBasisPattern(client, acc)
self.cost_basis: CostBasisPattern2 = CostBasisPattern2(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.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)
@@ -2243,16 +2243,16 @@ class _10yPattern:
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
class _10yTo12yPattern:
class _0satsPattern2:
"""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.cost_basis: CostBasisPattern = CostBasisPattern(client, acc)
self.outputs: OutputsPattern = OutputsPattern(client, _m(acc, 'utxo_count'))
self.realized: RealizedPattern2 = RealizedPattern2(client, acc)
self.relative: RelativePattern2 = RelativePattern2(client, acc)
self.realized: RealizedPattern = RealizedPattern(client, acc)
self.relative: RelativePattern4 = RelativePattern4(client, _m(acc, 'supply_in'))
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
@@ -2303,15 +2303,6 @@ class SplitPattern2(Generic[T]):
self.low: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'low'))
self.open: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'open'))
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 CoinbasePattern:
"""Pattern struct for repeated tree structure."""
@@ -2321,14 +2312,32 @@ class CoinbasePattern:
self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, 'usd'))
self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc)
class ActiveSupplyPattern:
class CoinbasePattern2:
"""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)
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 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 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 UnclaimedRewardsPattern:
"""Pattern struct for repeated tree structure."""
@@ -2339,15 +2348,6 @@ class UnclaimedRewardsPattern:
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
self.sats: BlockCountPattern[Sats] = BlockCountPattern(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 _2015Pattern:
"""Pattern struct for repeated tree structure."""
@@ -2357,14 +2357,14 @@ class _2015Pattern:
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd'))
self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc)
class SegwitAdoptionPattern:
class ActiveSupplyPattern:
"""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'))
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 _1dReturns1mSdPattern:
"""Pattern struct for repeated tree structure."""
@@ -2374,6 +2374,14 @@ class _1dReturns1mSdPattern:
self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd'))
self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma'))
class SupplyPattern2:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved'))
self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc)
class CostBasisPattern:
"""Pattern struct for repeated tree structure."""
@@ -2390,14 +2398,6 @@ class RelativePattern4:
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 SupplyPattern2:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved'))
self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc)
class BitcoinPattern2(Generic[T]):
"""Pattern struct for repeated tree structure."""
@@ -2422,13 +2422,6 @@ class BlockCountPattern(Generic[T]):
self.cumulative: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'cumulative'))
self.sum: MetricPattern1[T] = MetricPattern1(client, acc)
class OutputsPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, acc)
class RealizedPriceExtraPattern:
"""Pattern struct for repeated tree structure."""
@@ -2436,6 +2429,13 @@ class RealizedPriceExtraPattern:
"""Create pattern node with accumulated metric name."""
self.ratio: MetricPattern4[StoredF32] = MetricPattern4(client, acc)
class OutputsPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, acc)
# Metrics tree classes
class MetricsTree_Addresses:
@@ -3269,21 +3269,21 @@ 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._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')
class MetricsTree_Market_Dca_ClassStack:
"""Metrics tree node."""
@@ -3305,8 +3305,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')
@@ -3900,7 +3900,7 @@ class MetricsTree:
class BrkClient(BrkClientBase):
"""Main BRK client with metrics tree and API methods."""
VERSION = "v0.1.0-alpha.3"
VERSION = "v0.1.0-alpha.6"
INDEXES = [
"dateindex",