bindgen: snapshot

This commit is contained in:
nym21
2026-03-15 21:26:05 +01:00
parent 6e5b2c0e63
commit fdf8661a4b
23 changed files with 1151 additions and 810 deletions
+216 -50
View File
@@ -8,7 +8,10 @@ use std::collections::BTreeMap;
use brk_types::TreeNode;
use super::{find_common_prefix, find_common_suffix, get_node_fields, normalize_prefix};
use super::{
find_common_prefix, find_common_suffix, get_node_fields, get_shortest_leaf_name,
normalize_prefix,
};
use crate::{PatternBaseResult, PatternField, PatternMode, StructuralPattern, build_child_path};
/// Result of analyzing a single pattern instance.
@@ -91,7 +94,47 @@ fn collect_instance_analyses(
}
// Analyze this instance
let analysis = analyze_instance(&child_bases);
let mut analysis = analyze_instance(&child_bases);
// When some field_parts are empty (children returned the same base),
// replace empty parts with discriminators derived from shortest leaf names.
let has_empty = analysis.field_parts.values().any(|v| v.is_empty());
let has_nonempty = analysis.field_parts.values().any(|v| !v.is_empty());
if has_empty && has_nonempty {
// Mixed case: some fields have parts, some don't.
// Use shortest leaf to derive discriminators for empty fields.
let prefix = format!("{}_", analysis.base);
for (field_name, child_node) in children {
if let Some(part) = analysis.field_parts.get(field_name)
&& part.is_empty()
&& let Some(leaf) = get_shortest_leaf_name(child_node)
&& let Some(suffix) = leaf.strip_prefix(&prefix)
&& !suffix.is_empty()
// Only use if the suffix starts with the field key,
// avoiding internal sub-field names like "0sd" from a Price child
&& suffix.starts_with(field_name.trim_start_matches('_'))
{
analysis
.field_parts
.insert(field_name.clone(), suffix.to_string());
}
}
} else if has_empty && analysis.field_parts.len() > 1 {
// All-empty case: all children returned the same base.
// Re-analyze using shortest leaf names which may differentiate.
let mut leaf_bases: BTreeMap<String, String> = BTreeMap::new();
for (field_name, child_node) in children {
if let Some(leaf) = get_shortest_leaf_name(child_node) {
leaf_bases.insert(field_name.clone(), leaf);
}
}
if leaf_bases.len() == child_bases.len() {
let leaf_analysis = analyze_instance(&leaf_bases);
if !leaf_analysis.field_parts.values().all(|v| v.is_empty()) {
analysis.field_parts = leaf_analysis.field_parts;
}
}
}
// Store the base result for this node
// Note: has_outlier is false because we use recursive base computation
@@ -121,6 +164,126 @@ fn collect_instance_analyses(
}
}
/// Try to detect a template pattern when instances have different field_parts.
///
/// Supports two cases:
/// 1. **Embedded discriminator**: a substring varies per instance within field_parts.
/// E.g., `ratio_pct99_bps` vs `ratio_pct1_bps` → template `ratio_{disc}_bps`
/// 2. **Suffix discriminator**: a common suffix is appended to all field_parts.
/// E.g., `ratio_sd` vs `ratio_sd_4y` → template `ratio_sd{disc}`
fn try_detect_template(
majority: &[&InstanceAnalysis],
fields: &[PatternField],
) -> Option<PatternMode> {
if majority.len() < 2 {
return None;
}
// Strategy 1: Find an embedded discriminator (shortest non-empty field_part
// that differs between instances and appears as substring in other parts)
if let Some(mode) = try_embedded_disc(majority, fields) {
return Some(mode);
}
// Strategy 2: Find a common suffix difference across ALL field_parts
try_suffix_disc(majority, fields)
}
/// Strategy 1: embedded discriminator (e.g., pct99 inside ratio_pct99_bps)
fn try_embedded_disc(
majority: &[&InstanceAnalysis],
fields: &[PatternField],
) -> Option<PatternMode> {
let first = &majority[0];
let second = &majority[1];
// Find the discriminator: shortest non-empty field_part that differs
let disc_field = fields
.iter()
.filter_map(|f| first.field_parts.get(&f.name).map(|v| (&f.name, v)))
.filter(|(_, v)| !v.is_empty())
.min_by_key(|(_, v)| v.len())?;
let disc_first = disc_field.1;
let disc_second = second.field_parts.get(disc_field.0)?;
if disc_first == disc_second || disc_first.is_empty() || disc_second.is_empty() {
return None;
}
// Build templates by replacing the discriminator with {disc}
let mut templates = BTreeMap::new();
for field in fields {
let part = first.field_parts.get(&field.name)?;
let template = part.replacen(disc_first, "{disc}", 1);
templates.insert(field.name.clone(), template);
}
// Verify ALL instances match
for analysis in majority {
let inst_disc = analysis.field_parts.get(disc_field.0)?;
for field in fields {
let part = analysis.field_parts.get(&field.name)?;
let expected = templates.get(&field.name)?.replace("{disc}", inst_disc);
if part != &expected {
return None;
}
}
}
Some(PatternMode::Templated { templates })
}
/// Strategy 2: suffix discriminator (e.g., all field_parts differ by `_4y` suffix)
fn try_suffix_disc(
majority: &[&InstanceAnalysis],
fields: &[PatternField],
) -> Option<PatternMode> {
let first = &majority[0];
// For each other instance, check if ALL field_parts differ from the first
// by the same suffix. Use the first field to detect the suffix.
let ref_field = &fields[0].name;
let ref_first = first.field_parts.get(ref_field)?;
// Build templates from the first instance
// Non-empty parts get {disc} appended; empty parts (identity) stay empty
let mut templates = BTreeMap::new();
for field in fields {
let part = first.field_parts.get(&field.name)?;
if part.is_empty() {
templates.insert(field.name.clone(), String::new());
} else {
templates.insert(field.name.clone(), format!("{part}{{disc}}"));
}
}
// Verify ALL other instances: non-empty parts differ by the same suffix
for analysis in &majority[1..] {
let ref_other = analysis.field_parts.get(ref_field)?;
let suffix = ref_other.strip_prefix(ref_first)?;
for field in fields {
let first_part = first.field_parts.get(&field.name)?;
let other_part = analysis.field_parts.get(&field.name)?;
if first_part.is_empty() {
// Identity field — must stay empty in all instances
if !other_part.is_empty() {
return None;
}
} else {
let expected = format!("{first_part}{suffix}");
if other_part != &expected {
return None;
}
}
}
}
Some(PatternMode::Templated { templates })
}
/// Analyze a single pattern instance from its child bases.
fn analyze_instance(child_bases: &BTreeMap<String, String>) -> InstanceAnalysis {
let bases: Vec<&str> = child_bases.values().map(|s| s.as_str()).collect();
@@ -144,6 +307,19 @@ fn analyze_instance(child_bases: &BTreeMap<String, String>) -> InstanceAnalysis
field_parts.insert(field_name.clone(), relative);
}
// If all field_parts are empty (all children returned the same base),
// use the field keys as suffix discriminators. This handles patterns like
// period windows (all/_4y/_2y/_1y) where children differ by a suffix
// that corresponds to the tree key.
if field_parts.len() > 1 && field_parts.values().all(|v| v.is_empty()) {
// Can't differentiate — this pattern is non-parameterizable
return InstanceAnalysis {
base,
field_parts,
is_suffix_mode: true,
};
}
return InstanceAnalysis {
base,
field_parts,
@@ -188,64 +364,56 @@ fn analyze_instance(child_bases: &BTreeMap<String, String>) -> InstanceAnalysis
}
/// Determine the consistent mode for a pattern from all its instances.
/// Uses majority voting: if most instances agree on mode and field_parts,
/// use those. Minority instances will be inlined at usage sites.
/// Picks the majority mode (suffix vs prefix), then requires all instances
/// in that mode to agree on field_parts. Minority-mode instances get inlined.
fn determine_pattern_mode(
analyses: &[InstanceAnalysis],
fields: &[PatternField],
) -> Option<PatternMode> {
if analyses.is_empty() {
return None;
}
analyses.first()?;
// Group instances by (mode, field_parts) signature
let suffix_instances: Vec<_> = analyses.iter().filter(|a| a.is_suffix_mode).collect();
let prefix_instances: Vec<_> = analyses.iter().filter(|a| !a.is_suffix_mode).collect();
// Pick the majority mode
let suffix_count = analyses.iter().filter(|a| a.is_suffix_mode).count();
let is_suffix = suffix_count * 2 >= analyses.len();
// Pick the majority mode group
let (majority_instances, is_suffix) = if suffix_instances.len() >= prefix_instances.len() {
(suffix_instances, true)
} else {
(prefix_instances, false)
};
if majority_instances.is_empty() {
return None;
}
// Find the most common field_parts within the majority group
// Convert to sorted Vec for comparison since BTreeMap isn't hashable
let mut parts_counts: BTreeMap<Vec<(String, String)>, usize> = BTreeMap::new();
for analysis in &majority_instances {
let mut sorted: Vec<_> = analysis
.field_parts
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
sorted.sort();
*parts_counts.entry(sorted).or_insert(0) += 1;
}
let (best_parts_vec, _count) = parts_counts.into_iter().max_by_key(|(_, count)| *count)?;
let best_parts: BTreeMap<String, String> = best_parts_vec.into_iter().collect();
// All instances of the majority mode must agree on field_parts
let majority: Vec<_> = analyses
.iter()
.filter(|a| a.is_suffix_mode == is_suffix)
.collect();
let first_majority = majority.first()?;
// Verify all required fields have parts
for field in fields {
if !best_parts.contains_key(&field.name) {
if !first_majority.field_parts.contains_key(&field.name) {
return None;
}
}
let field_parts = best_parts;
if majority
.iter()
.all(|a| a.field_parts == first_majority.field_parts)
{
let field_parts = first_majority.field_parts.clone();
return if is_suffix {
Some(PatternMode::Suffix {
relatives: field_parts,
})
} else {
Some(PatternMode::Prefix {
prefixes: field_parts,
})
};
}
// Instances disagree on field_parts. Try to detect a template pattern:
// if each field's value varies by exactly one substring that's different
// per instance, we can use a Templated mode with {disc} placeholder.
if is_suffix {
Some(PatternMode::Suffix {
relatives: field_parts,
})
try_detect_template(&majority, fields)
} else {
Some(PatternMode::Prefix {
prefixes: field_parts,
})
None
}
}
@@ -402,9 +570,8 @@ mod tests {
assert_eq!(relatives.get("min"), Some(&"min".to_string()));
assert_eq!(relatives.get("percentiles"), Some(&"".to_string()));
}
PatternMode::Prefix { .. } => {
panic!("Expected suffix mode, got prefix mode");
}
PatternMode::Prefix { .. } => panic!("Expected suffix mode, got prefix mode"),
PatternMode::Templated { .. } => panic!("Expected suffix mode, got templated mode"),
}
}
@@ -460,9 +627,8 @@ mod tests {
assert_eq!(relatives.get("max"), Some(&"max".to_string()));
assert_eq!(relatives.get("min"), Some(&"min".to_string()));
}
PatternMode::Prefix { .. } => {
panic!("Expected suffix mode");
}
PatternMode::Prefix { .. } => panic!("Expected suffix mode"),
PatternMode::Templated { .. } => panic!("Expected suffix mode, got templated"),
}
}
}
+1 -1
View File
@@ -16,7 +16,7 @@ use super::{find_common_prefix, find_common_suffix, normalize_prefix};
///
/// This is useful for pattern base analysis where we want the "base" case
/// (e.g., the leaf without suffix like `_btc` or `_usd`).
fn get_shortest_leaf_name(node: &TreeNode) -> Option<String> {
pub(super) fn get_shortest_leaf_name(node: &TreeNode) -> Option<String> {
match node {
TreeNode::Leaf(leaf) => Some(leaf.name().to_string()),
TreeNode::Branch(children) => children
@@ -59,4 +59,52 @@ impl LanguageSyntax for JavaScriptSyntax {
fn constructor_name(&self, type_name: &str) -> String {
format!("create{}", type_name)
}
fn disc_arg_expr(&self, template: &str) -> String {
if template == "{disc}" {
"disc".to_string()
} else if template.is_empty() {
"''".to_string()
} else if !template.contains("{disc}") {
format!("'{}'", template)
} else if template.ends_with("{disc}") {
let static_part = template.trim_end_matches("{disc}").trim_end_matches('_');
format!("_m('{}', disc)", static_part)
} else {
let js_template = template.replace("{disc}", "${disc}");
format!("`{}`", js_template)
}
}
fn template_expr(&self, acc_var: &str, template: &str) -> String {
let var_name = to_camel_case(acc_var);
if template.is_empty() {
// Identity — just pass disc
format!("_m({}, disc)", var_name)
} else if template == "{disc}" {
// Template IS the discriminator
format!("_m({}, disc)", var_name)
} else if !template.contains("{disc}") {
// Static suffix — no disc involved
format!("_m({}, '{}')", var_name, template)
} else {
// Template with {disc}: use nested _m for proper separator handling
// "ratio_{disc}_bps" → split on {disc} → _m(_m(acc, 'ratio'), disc) then _bps
// But this is complex. For embedded disc, use string interpolation.
// For suffix disc (ends with {disc}), use _m composition.
if template.ends_with("{disc}") {
let static_part = &template[..template.len() - "{disc}".len()];
if static_part.is_empty() {
format!("_m({}, disc)", var_name)
} else {
let static_part = static_part.trim_end_matches('_');
format!("_m(_m({}, '{}'), disc)", var_name, static_part)
}
} else {
// Embedded disc — use template literal
let js_template = template.replace("{disc}", "${disc}");
format!("_m({}, `{}`)", var_name, js_template)
}
}
}
}
+25
View File
@@ -54,4 +54,29 @@ impl LanguageSyntax for PythonSyntax {
fn constructor_name(&self, type_name: &str) -> String {
type_name.to_string()
}
fn disc_arg_expr(&self, template: &str) -> String {
if template == "{disc}" {
"disc".to_string()
} else if template.is_empty() {
"''".to_string()
} else if !template.contains("{disc}") {
format!("'{}'", template)
} else if template.ends_with("{disc}") {
let static_part = template.trim_end_matches("{disc}").trim_end_matches('_');
format!("_m('{}', disc)", static_part)
} else {
format!("f'{}'", template)
}
}
fn template_expr(&self, acc_var: &str, template: &str) -> String {
if template == "{disc}" {
format!("_m({}, disc)", acc_var)
} else if !template.contains("{disc}") {
format!("_m({}, '{}')", acc_var, template)
} else {
format!("_m({}, f'{}')", acc_var, template)
}
}
}
+44
View File
@@ -55,4 +55,48 @@ impl LanguageSyntax for RustSyntax {
fn constructor_name(&self, type_name: &str) -> String {
format!("{}::new", type_name)
}
fn disc_arg_expr(&self, template: &str) -> String {
if template == "{disc}" {
"disc.clone()".to_string()
} else if template.is_empty() {
"String::new()".to_string()
} else if !template.contains("{disc}") {
format!("\"{}\".to_string()", template)
} else if template.ends_with("{disc}") {
let static_part = template.trim_end_matches("{disc}").trim_end_matches('_');
format!("_m(\"{}\", &disc)", static_part)
} else {
let rust_template = template
.replace("{disc}", "{disc}")
.replace('{', "{{")
.replace('}', "}}")
.replace("{{disc}}", "{disc}");
format!("format!(\"{}\")", rust_template)
}
}
fn template_expr(&self, acc_var: &str, template: &str) -> String {
if template == "{disc}" {
// _m(acc, disc) in Rust
format!("_m(&{}, &disc)", acc_var)
} else if template.is_empty() {
// Identity
acc_var.to_string()
} else if !template.contains("{disc}") {
// Static suffix
format!("_m(&{}, \"{}\")", acc_var, template)
} else {
// Template with disc: _m(&acc, &format!("ratio_{disc}_bps", disc=disc))
let rust_template = template
.replace("{disc}", "{disc}")
.replace('{', "{{")
.replace('}', "}}")
.replace("{{disc}}", "{disc}");
format!(
"_m(&{}, &format!(\"{}\", disc=disc))",
acc_var, rust_template
)
}
}
}
+18 -2
View File
@@ -29,7 +29,10 @@ fn compute_path_expr<S: LanguageSyntax>(
) -> String {
match pattern.get_field_part(&field.name) {
Some(part) => {
if pattern.is_suffix_mode() {
if pattern.is_templated() {
// Templated: replace {disc} with disc variable at runtime
syntax.template_expr(base_var, part)
} else if pattern.is_suffix_mode() {
syntax.suffix_expr(base_var, part)
} else {
syntax.prefix_expr(part, base_var)
@@ -76,7 +79,20 @@ pub fn generate_parameterized_field<S: LanguageSyntax>(
let type_ann =
metadata.field_type_annotation(field, pattern.is_generic, None, syntax.generic_syntax());
let path_expr = compute_path_expr(syntax, pattern, field, "acc");
let value = compute_field_value(syntax, field, metadata, &path_expr);
// When calling a templated child pattern, pass acc and disc separately
let value = if let Some(child_pattern) = metadata.find_pattern(&field.rust_type)
&& child_pattern.is_templated()
{
let disc_template = pattern
.get_field_part(&field.name)
.unwrap_or(&field.name);
let disc_arg = syntax.disc_arg_expr(disc_template);
let acc_arg = syntax.suffix_expr("acc", ""); // identity — returns acc or acc.clone()
syntax.constructor(&field.rust_type, &format!("{acc_arg}, {disc_arg}"))
} else {
compute_field_value(syntax, field, metadata, &path_expr)
};
writeln!(
output,
@@ -701,7 +701,7 @@ pub fn generate_structural_patterns(
}
writeln!(output, " */\n").unwrap();
// Generate factory function for ALL patterns
writeln!(output, "/**").unwrap();
writeln!(output, " * Create a {} pattern node", pattern.name).unwrap();
if pattern.is_generic {
@@ -709,6 +709,9 @@ pub fn generate_structural_patterns(
}
writeln!(output, " * @param {{BrkClientBase}} client").unwrap();
writeln!(output, " * @param {{string}} acc - Accumulated metric name").unwrap();
if pattern.is_templated() {
writeln!(output, " * @param {{string}} disc - Discriminator suffix").unwrap();
}
let return_type = if pattern.is_generic {
format!("{}<T>", pattern.name)
} else {
@@ -717,7 +720,11 @@ pub fn generate_structural_patterns(
writeln!(output, " * @returns {{{}}}", return_type).unwrap();
writeln!(output, " */").unwrap();
writeln!(output, "function create{}(client, acc) {{", pattern.name).unwrap();
if pattern.is_templated() {
writeln!(output, "function create{}(client, acc, disc) {{", pattern.name).unwrap();
} else {
writeln!(output, "function create{}(client, acc) {{", pattern.name).unwrap();
}
writeln!(output, " return {{").unwrap();
let syntax = JavaScriptSyntax;
@@ -221,12 +221,31 @@ fn generate_tree_initializer(
writeln!(output, "{}}},", indent_str).unwrap();
} else {
// Use pattern factory
writeln!(
output,
"{}{}: create{}(this, '{}'),",
indent_str, field_name, child.field.rust_type, child.base_result.base
)
.unwrap();
let pattern = metadata.find_pattern(&child.field.rust_type);
if pattern.is_some_and(|p| p.is_templated()) {
// Templated: extract discriminator from field_parts
let disc = child
.base_result
.field_parts
.values()
.filter(|v| !v.is_empty())
.min_by_key(|v| v.len())
.cloned()
.unwrap_or_default();
writeln!(
output,
"{}{}: create{}(this, '{}', '{}'),",
indent_str, field_name, child.field.rust_type, child.base_result.base, disc
)
.unwrap();
} else {
writeln!(
output,
"{}{}: create{}(this, '{}'),",
indent_str, field_name, child.field.rust_type, child.base_result.base
)
.unwrap();
}
}
}
}
@@ -683,6 +683,7 @@ pub fn generate_structural_patterns(
writeln!(output, "# Reusable structural pattern classes\n").unwrap();
for pattern in patterns {
// Generate class
if pattern.is_generic {
writeln!(output, "class {}(Generic[T]):", pattern.name).unwrap();
@@ -552,11 +552,19 @@ pub fn generate_pattern_structs(
" /// Create a new pattern node with accumulated metric name."
)
.unwrap();
writeln!(
output,
" pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {{"
)
.unwrap();
if pattern.is_templated() {
writeln!(
output,
" pub fn new(client: Arc<BrkClientBase>, acc: String, disc: String) -> Self {{"
)
.unwrap();
} else {
writeln!(
output,
" pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {{"
)
.unwrap();
}
writeln!(output, " Self {{").unwrap();
let syntax = RustSyntax;
+31 -11
View File
@@ -98,17 +98,37 @@ fn generate_tree_node(
.unwrap();
} else {
// Pattern type - use ::new() constructor
// All patterns have ::new(), parameterizable ones use detected mode,
// non-parameterizable ones use field name fallback
generate_tree_node_field(
output,
&syntax,
&child.field,
metadata,
" ",
child.name,
Some(&child.base_result.base),
);
let pattern = metadata.find_pattern(&child.field.rust_type);
if pattern.is_some_and(|p| p.is_templated()) {
// Templated pattern: pass base and disc
let disc = child
.base_result
.field_parts
.values()
.filter(|v| !v.is_empty())
.min_by_key(|v| v.len())
.cloned()
.unwrap_or_default();
writeln!(
output,
" {}: {}::new(client.clone(), {}, {}.to_string()),",
field_name,
child.field.rust_type,
syntax.string_literal(&child.base_result.base),
syntax.string_literal(&disc),
)
.unwrap();
} else {
generate_tree_node_field(
output,
&syntax,
&child.field,
metadata,
" ",
child.name,
Some(&child.base_result.base),
);
}
}
}
+19
View File
@@ -92,4 +92,23 @@ pub trait LanguageSyntax {
/// - JavaScript: `createTypeName`
/// - Rust: `TypeName::new`
fn constructor_name(&self, type_name: &str) -> String;
/// Format a discriminator argument for passing to a templated child.
///
/// Returns an expression computing the disc value from a template.
/// - `"pct99"` (static) → `'pct99'` (JS) / `"pct99".to_string()` (Rust)
/// - `""` (empty) → `disc` (pass parent's disc through)
/// - `"p1sd{disc}"` (suffix) → `_m('p1sd', disc)` (composed)
/// - `"ratio_{disc}_bps"` (embedded) → `` `ratio_${disc}_bps` `` (template literal)
fn disc_arg_expr(&self, template: &str) -> String;
/// Format a templated mode expression: substitute `{disc}` at runtime.
///
/// The template contains `{disc}` placeholder. The generated code should
/// construct `_m(acc, template_with_disc_substituted)` at runtime.
///
/// # Arguments
/// * `acc_var` - The accumulator variable (e.g., "acc")
/// * `template` - Template like `"ratio_{disc}_bps"` or `"{disc}"`
fn template_expr(&self, acc_var: &str, template: &str) -> String;
}
+3 -19
View File
@@ -69,26 +69,10 @@ impl ClientMetadata {
self.find_pattern(name).is_some_and(|p| p.is_generic)
}
/// Check if a pattern by name is fully parameterizable.
/// A pattern is parameterizable if it has a mode AND all its branch fields
/// are also parameterizable (or not patterns at all).
/// Check if a pattern by name is parameterizable (has a mode).
pub fn is_parameterizable(&self, name: &str) -> bool {
self.find_pattern(name).is_some_and(|p| {
if !p.is_parameterizable() {
return false;
}
// Check all branch fields have parameterizable types (or are not patterns)
p.fields.iter().all(|f| {
if f.is_branch() {
self.structural_patterns
.iter()
.find(|pat| pat.name == f.rust_type)
.is_none_or(|pat| pat.is_parameterizable())
} else {
true
}
})
})
self.find_pattern(name)
.is_some_and(|p| p.is_parameterizable())
}
/// Check if child fields match ANY pattern (parameterizable or not).
@@ -23,4 +23,12 @@ pub enum PatternMode {
/// Maps field name to its prefix (empty string for identity)
prefixes: BTreeMap<String, String>,
},
/// Fields construct metric names using a template with a discriminator placeholder.
/// Factory takes two params: `acc` (base) and `disc` (discriminator).
/// Formula: `_m(acc, template.replace("{disc}", disc))`
/// Example: template `"ratio_{disc}_bps"` with disc `"pct99"` → `_m(acc, "ratio_pct99_bps")`
Templated {
/// Maps field name to its template string containing `{disc}` placeholder
templates: BTreeMap<String, String>,
},
}
+52 -5
View File
@@ -41,21 +41,30 @@ impl StructuralPattern {
relatives.get(field_name).map(|s| s.as_str())
}
Some(PatternMode::Prefix { prefixes }) => prefixes.get(field_name).map(|s| s.as_str()),
Some(PatternMode::Templated { templates }) => {
templates.get(field_name).map(|s| s.as_str())
}
None => None,
}
}
/// Returns true if this pattern is in suffix mode.
pub fn is_suffix_mode(&self) -> bool {
matches!(&self.mode, Some(PatternMode::Suffix { .. }))
matches!(
&self.mode,
Some(PatternMode::Suffix { .. } | PatternMode::Templated { .. })
)
}
/// Returns true if this pattern uses templated mode with a discriminator.
pub fn is_templated(&self) -> bool {
matches!(&self.mode, Some(PatternMode::Templated { .. }))
}
/// Check if the given instance field parts match this pattern's field parts.
/// Returns true if all field parts in the pattern match the instance's field parts.
pub fn field_parts_match(&self, instance_field_parts: &BTreeMap<String, String>) -> bool {
match &self.mode {
Some(PatternMode::Suffix { relatives }) => {
// For each field in the pattern, check if the instance has the same suffix
relatives.iter().all(|(field_name, pattern_suffix)| {
instance_field_parts
.get(field_name)
@@ -63,18 +72,56 @@ impl StructuralPattern {
})
}
Some(PatternMode::Prefix { prefixes }) => {
// For each field in the pattern, check if the instance has the same prefix
prefixes.iter().all(|(field_name, pattern_prefix)| {
instance_field_parts
.get(field_name)
.is_some_and(|instance_prefix| instance_prefix == pattern_prefix)
})
}
None => false, // Non-parameterizable patterns don't use field parts
Some(PatternMode::Templated { templates }) => {
// For templated patterns, check if the instance's field_parts
// can be produced by substituting some discriminator into the templates
let first_template_field = templates.iter().next();
let Some((ref_field, ref_template)) = first_template_field else {
return false;
};
let Some(ref_value) = instance_field_parts.get(ref_field) else {
return false;
};
// Extract discriminator from the reference field
let Some(disc) = extract_disc(ref_template, ref_value) else {
return false;
};
// Verify all fields match with this discriminator
templates.iter().all(|(field_name, template)| {
instance_field_parts
.get(field_name)
.is_some_and(|value| *value == template.replace("{disc}", &disc))
})
}
None => false,
}
}
}
/// Extract the discriminator value by matching a template against a concrete string.
/// E.g., template `"ratio_{disc}_bps"` matched against `"ratio_pct99_bps"` yields `"pct99"`.
fn extract_disc(template: &str, value: &str) -> Option<String> {
let parts: Vec<&str> = template.split("{disc}").collect();
if parts.len() != 2 {
return None;
}
let prefix = parts[0];
let suffix = parts[1];
if value.starts_with(prefix) && value.ends_with(suffix) {
let disc = &value[prefix.len()..value.len() - suffix.len()];
if !disc.is_empty() {
return Some(disc.to_string());
}
}
None
}
/// A field in a structural pattern.
#[derive(Debug, Clone, PartialOrd, Ord)]
pub struct PatternField {
+222 -260
View File
@@ -992,41 +992,41 @@ impl Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75
/// Pattern struct for repeated tree structure.
pub struct _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern {
pub _0sd: CentsSatsUsdPattern,
pub m0_5sd: PriceValuePattern,
pub m1_5sd: PriceValuePattern,
pub m1sd: PriceValuePattern,
pub m2_5sd: PriceValuePattern,
pub m2sd: PriceValuePattern,
pub m3sd: PriceValuePattern,
pub p0_5sd: PriceValuePattern,
pub p1_5sd: PriceValuePattern,
pub p1sd: PriceValuePattern,
pub p2_5sd: PriceValuePattern,
pub p2sd: PriceValuePattern,
pub p3sd: PriceValuePattern,
pub m0_5sd: PriceRatioPattern,
pub m1_5sd: PriceRatioPattern,
pub m1sd: PriceRatioPattern,
pub m2_5sd: PriceRatioPattern,
pub m2sd: PriceRatioPattern,
pub m3sd: PriceRatioPattern,
pub p0_5sd: PriceRatioPattern,
pub p1_5sd: PriceRatioPattern,
pub p1sd: PriceRatioPattern,
pub p2_5sd: PriceRatioPattern,
pub p2sd: PriceRatioPattern,
pub p3sd: PriceRatioPattern,
pub sd: MetricPattern1<StoredF32>,
pub zscore: MetricPattern1<StoredF32>,
}
impl _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
pub fn new(client: Arc<BrkClientBase>, acc: String, disc: String) -> Self {
Self {
_0sd: CentsSatsUsdPattern::new(client.clone(), _m(&acc, "0sd_4y")),
m0_5sd: PriceValuePattern::new(client.clone(), acc.clone()),
m1_5sd: PriceValuePattern::new(client.clone(), acc.clone()),
m1sd: PriceValuePattern::new(client.clone(), acc.clone()),
m2_5sd: PriceValuePattern::new(client.clone(), acc.clone()),
m2sd: PriceValuePattern::new(client.clone(), acc.clone()),
m3sd: PriceValuePattern::new(client.clone(), acc.clone()),
p0_5sd: PriceValuePattern::new(client.clone(), acc.clone()),
p1_5sd: PriceValuePattern::new(client.clone(), acc.clone()),
p1sd: PriceValuePattern::new(client.clone(), acc.clone()),
p2_5sd: PriceValuePattern::new(client.clone(), acc.clone()),
p2sd: PriceValuePattern::new(client.clone(), acc.clone()),
p3sd: PriceValuePattern::new(client.clone(), acc.clone()),
sd: MetricPattern1::new(client.clone(), _m(&acc, "sd_4y")),
zscore: MetricPattern1::new(client.clone(), _m(&acc, "zscore_4y")),
_0sd: CentsSatsUsdPattern::new(client.clone(), _m(&acc, &format!("0sd{disc}", disc=disc))),
m0_5sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("m0_5sd", &disc)),
m1_5sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("m1_5sd", &disc)),
m1sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("m1sd", &disc)),
m2_5sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("m2_5sd", &disc)),
m2sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("m2sd", &disc)),
m3sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("m3sd", &disc)),
p0_5sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("p0_5sd", &disc)),
p1_5sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("p1_5sd", &disc)),
p1sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("p1sd", &disc)),
p2_5sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("p2_5sd", &disc)),
p2sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("p2sd", &disc)),
p3sd: PriceRatioPattern::new(client.clone(), acc.clone(), _m("p3sd", &disc)),
sd: MetricPattern1::new(client.clone(), _m(&acc, &format!("ratio_sd{disc}", disc=disc))),
zscore: MetricPattern1::new(client.clone(), _m(&acc, &format!("ratio_zscore{disc}", disc=disc))),
}
}
}
@@ -1123,18 +1123,18 @@ impl CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
cap: CentsDeltaRelUsdPattern::new(client.clone(), _m(&acc, "realized_cap")),
gross_pnl: BaseCumulativeSumPattern3::new(client.clone(), _m(&acc, "realized_gross_pnl")),
investor: LowerPriceUpperPattern::new(client.clone(), acc.clone()),
loss: BaseCapitulationCumulativeNegativeRelSumValuePattern::new(client.clone(), acc.clone()),
mvrv: MetricPattern1::new(client.clone(), _m(&acc, "mvrv")),
net_pnl: BaseChangeCumulativeDeltaRelSumPattern::new(client.clone(), _m(&acc, "net")),
peak_regret: BaseCumulativeRelPattern::new(client.clone(), _m(&acc, "realized_peak_regret")),
price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern::new(client.clone(), _m(&acc, "realized_price")),
profit: BaseCumulativeDistributionRelSumValuePattern::new(client.clone(), acc.clone()),
profit_to_loss_ratio: _1m1w1y24hPattern::new(client.clone(), _m(&acc, "realized_profit_to_loss_ratio")),
sell_side_risk_ratio: _1m1w1y24hPattern6::new(client.clone(), _m(&acc, "sell_side_risk_ratio")),
sopr: AdjustedRatioValuePattern::new(client.clone(), acc.clone()),
cap: CentsDeltaRelUsdPattern::new(client.clone(), format!("{acc}_cap")),
gross_pnl: BaseCumulativeSumPattern3::new(client.clone(), format!("{acc}_gross_pnl")),
investor: LowerPriceUpperPattern::new(client.clone(), format!("{acc}_investor")),
loss: BaseCapitulationCumulativeNegativeRelSumValuePattern::new(client.clone(), format!("{acc}_loss")),
mvrv: MetricPattern1::new(client.clone(), format!("{acc}_mvrv")),
net_pnl: BaseChangeCumulativeDeltaRelSumPattern::new(client.clone(), format!("{acc}_net_pnl")),
peak_regret: BaseCumulativeRelPattern::new(client.clone(), format!("{acc}_peak_regret")),
price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern::new(client.clone(), format!("{acc}_price")),
profit: BaseCumulativeDistributionRelSumValuePattern::new(client.clone(), format!("{acc}_profit")),
profit_to_loss_ratio: _1m1w1y24hPattern::new(client.clone(), format!("{acc}_profit_to_loss_ratio")),
sell_side_risk_ratio: _1m1w1y24hPattern6::new(client.clone(), format!("{acc}_sell_side_risk_ratio")),
sopr: AdjustedRatioValuePattern::new(client.clone(), format!("{acc}_sopr")),
}
}
}
@@ -1223,18 +1223,18 @@ pub struct AverageGainsLossesRsiStochPattern {
impl AverageGainsLossesRsiStochPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
pub fn new(client: Arc<BrkClientBase>, acc: String, disc: String) -> Self {
Self {
average_gain: MetricPattern1::new(client.clone(), _m(&acc, "average_gain_24h")),
average_loss: MetricPattern1::new(client.clone(), _m(&acc, "average_loss_24h")),
gains: MetricPattern1::new(client.clone(), _m(&acc, "gains_24h")),
losses: MetricPattern1::new(client.clone(), _m(&acc, "losses_24h")),
rsi: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "24h")),
rsi_max: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "max_24h")),
rsi_min: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "min_24h")),
stoch_rsi: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "stoch_24h")),
stoch_rsi_d: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "stoch_d_24h")),
stoch_rsi_k: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, "stoch_k_24h")),
average_gain: MetricPattern1::new(client.clone(), _m(&acc, &format!("average_gain_{disc}", disc=disc))),
average_loss: MetricPattern1::new(client.clone(), _m(&acc, &format!("average_loss_{disc}", disc=disc))),
gains: MetricPattern1::new(client.clone(), _m(&acc, &format!("gains_{disc}", disc=disc))),
losses: MetricPattern1::new(client.clone(), _m(&acc, &format!("losses_{disc}", disc=disc))),
rsi: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &disc)),
rsi_max: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("max_{disc}", disc=disc))),
rsi_min: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("min_{disc}", disc=disc))),
stoch_rsi: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("stoch_{disc}", disc=disc))),
stoch_rsi_d: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("stoch_d_{disc}", disc=disc))),
stoch_rsi_k: BpsPercentRatioPattern3::new(client.clone(), _m(&acc, &format!("stoch_k_{disc}", disc=disc))),
}
}
}
@@ -1377,7 +1377,7 @@ impl BpsCentsPercentilesRatioSatsSmaStdUsdPattern {
ratio: MetricPattern1::new(client.clone(), _m(&acc, "ratio")),
sats: MetricPattern1::new(client.clone(), _m(&acc, "sats")),
sma: _1m1w1y2y4yAllPattern::new(client.clone(), _m(&acc, "ratio_sma")),
std_dev: _1y2y4yAllPattern::new(client.clone(), _m(&acc, "ratio")),
std_dev: _1y2y4yAllPattern::new(client.clone(), acc.clone()),
usd: MetricPattern1::new(client.clone(), acc.clone()),
}
}
@@ -1531,12 +1531,12 @@ impl CapLossMvrvNetPriceProfitSoprPattern {
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
cap: CentsDeltaUsdPattern::new(client.clone(), _m(&acc, "realized_cap")),
loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone()),
loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone(), String::new()),
mvrv: MetricPattern1::new(client.clone(), _m(&acc, "mvrv")),
net_pnl: BaseCumulativeDeltaSumPattern::new(client.clone(), _m(&acc, "net_realized_pnl")),
price: BpsCentsRatioSatsUsdPattern::new(client.clone(), _m(&acc, "realized_price")),
profit: BaseCumulativeSumPattern3::new(client.clone(), _m(&acc, "realized_profit")),
sopr: RatioValuePattern::new(client.clone(), acc.clone()),
sopr: RatioValuePattern::new(client.clone(), _m(&acc, "sopr_24h")),
}
}
}
@@ -1773,12 +1773,12 @@ impl Pct1Pct2Pct5Pct95Pct98Pct99Pattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
pct1: BpsPriceRatioPattern::new(client.clone(), acc.clone()),
pct2: BpsPriceRatioPattern::new(client.clone(), acc.clone()),
pct5: BpsPriceRatioPattern::new(client.clone(), acc.clone()),
pct95: BpsPriceRatioPattern::new(client.clone(), acc.clone()),
pct98: BpsPriceRatioPattern::new(client.clone(), acc.clone()),
pct99: BpsPriceRatioPattern::new(client.clone(), acc.clone()),
pct1: BpsPriceRatioPattern::new(client.clone(), acc.clone(), "pct1".to_string()),
pct2: BpsPriceRatioPattern::new(client.clone(), acc.clone(), "pct2".to_string()),
pct5: BpsPriceRatioPattern::new(client.clone(), acc.clone(), "pct5".to_string()),
pct95: BpsPriceRatioPattern::new(client.clone(), acc.clone(), "pct95".to_string()),
pct98: BpsPriceRatioPattern::new(client.clone(), acc.clone(), "pct98".to_string()),
pct99: BpsPriceRatioPattern::new(client.clone(), acc.clone(), "pct99".to_string()),
}
}
}
@@ -1972,11 +1972,11 @@ impl EmaHistogramLineSignalPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
ema_fast: MetricPattern1::new(client.clone(), _m(&acc, "ema_fast_24h")),
ema_slow: MetricPattern1::new(client.clone(), _m(&acc, "ema_slow_24h")),
histogram: MetricPattern1::new(client.clone(), _m(&acc, "histogram_24h")),
line: MetricPattern1::new(client.clone(), _m(&acc, "line_24h")),
signal: MetricPattern1::new(client.clone(), _m(&acc, "signal_24h")),
ema_fast: MetricPattern1::new(client.clone(), format!("{acc}_ema_fast")),
ema_slow: MetricPattern1::new(client.clone(), format!("{acc}_ema_slow")),
histogram: MetricPattern1::new(client.clone(), format!("{acc}_histogram")),
line: MetricPattern1::new(client.clone(), format!("{acc}_line")),
signal: MetricPattern1::new(client.clone(), format!("{acc}_signal")),
}
}
}
@@ -2018,9 +2018,9 @@ impl MvrvNuplRealizedSupplyPattern {
Self {
mvrv: MetricPattern1::new(client.clone(), _m(&acc, "mvrv")),
nupl: BpsRatioPattern::new(client.clone(), _m(&acc, "nupl")),
realized_cap: AllSthPattern::new(client.clone(), acc.clone()),
realized_cap: AllSthPattern::new(client.clone(), _m(&acc, "realized_cap")),
realized_price: BpsCentsRatioSatsUsdPattern::new(client.clone(), _m(&acc, "realized_price")),
supply: AllSthPattern2::new(client.clone(), acc.clone()),
supply: AllSthPattern2::new(client.clone(), _m(&acc, "supply")),
}
}
}
@@ -2201,10 +2201,10 @@ impl _1y2y4yAllPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_1y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern::new(client.clone(), acc.clone()),
_2y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern::new(client.clone(), acc.clone()),
_4y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern::new(client.clone(), acc.clone()),
all: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern::new(client.clone(), acc.clone()),
_1y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern::new(client.clone(), acc.clone(), "1y".to_string()),
_2y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern::new(client.clone(), acc.clone(), "2y".to_string()),
_4y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern::new(client.clone(), acc.clone(), "4y".to_string()),
all: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern::new(client.clone(), acc.clone(), String::new()),
}
}
}
@@ -2259,12 +2259,12 @@ pub struct BaseCumulativeNegativeSumPattern {
impl BaseCumulativeNegativeSumPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
pub fn new(client: Arc<BrkClientBase>, acc: String, disc: String) -> Self {
Self {
base: CentsUsdPattern2::new(client.clone(), _m(&acc, "unrealized_loss")),
cumulative: CentsUsdPattern2::new(client.clone(), _m(&acc, "unrealized_loss_cumulative")),
negative: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")),
sum: _1m1w1y24hPattern4::new(client.clone(), _m(&acc, "unrealized_loss_sum")),
base: CentsUsdPattern2::new(client.clone(), _m(&acc, &disc)),
cumulative: CentsUsdPattern2::new(client.clone(), _m(&acc, &format!("{disc}_cumulative", disc=disc))),
negative: MetricPattern1::new(client.clone(), _m(&acc, &format!("neg_{disc}", disc=disc))),
sum: _1m1w1y24hPattern4::new(client.clone(), _m(&acc, &format!("{disc}_sum", disc=disc))),
}
}
}
@@ -2381,7 +2381,7 @@ impl LossNetNuplProfitPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone()),
loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone(), String::new()),
net_pnl: CentsUsdPattern::new(client.clone(), _m(&acc, "net_unrealized_pnl")),
nupl: BpsRatioPattern::new(client.clone(), _m(&acc, "nupl")),
profit: BaseCumulativeSumPattern3::new(client.clone(), _m(&acc, "unrealized_profit")),
@@ -2584,11 +2584,11 @@ pub struct BpsPriceRatioPattern {
impl BpsPriceRatioPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
pub fn new(client: Arc<BrkClientBase>, acc: String, disc: String) -> Self {
Self {
bps: MetricPattern1::new(client.clone(), _m(&acc, "ratio_pct99_bps")),
price: CentsSatsUsdPattern::new(client.clone(), _m(&acc, "pct99")),
ratio: MetricPattern1::new(client.clone(), _m(&acc, "ratio_pct99")),
bps: MetricPattern1::new(client.clone(), _m(&acc, &format!("ratio_{disc}_bps", disc=disc))),
price: CentsSatsUsdPattern::new(client.clone(), _m(&acc, &disc)),
ratio: MetricPattern1::new(client.clone(), _m(&acc, &format!("ratio_{disc}", disc=disc))),
}
}
}
@@ -2730,7 +2730,7 @@ impl LossNuplProfitPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone()),
loss: BaseCumulativeNegativeSumPattern::new(client.clone(), acc.clone(), String::new()),
nupl: BpsRatioPattern::new(client.clone(), _m(&acc, "nupl")),
profit: BaseCumulativeSumPattern3::new(client.clone(), _m(&acc, "unrealized_profit")),
}
@@ -2766,9 +2766,9 @@ impl RatioValuePattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
ratio: _1m1w1y24hPattern::new(client.clone(), _m(&acc, "asopr")),
value_created: BaseCumulativeSumPattern::new(client.clone(), _m(&acc, "adj_value_created")),
value_destroyed: BaseCumulativeSumPattern::new(client.clone(), _m(&acc, "adj_value_destroyed")),
ratio: _1m1w1y24hPattern::new(client.clone(), format!("{acc}_ratio")),
value_created: BaseCumulativeSumPattern::new(client.clone(), format!("{acc}_value_created")),
value_destroyed: BaseCumulativeSumPattern::new(client.clone(), format!("{acc}_value_destroyed")),
}
}
}
@@ -2838,7 +2838,7 @@ impl AbsoluteRatePattern {
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
absolute: _1m1w1y24hPattern::new(client.clone(), acc.clone()),
rate: _1m1w1y24hPattern2::new(client.clone(), acc.clone()),
rate: _1m1w1y24hPattern2::new(client.clone(), _m(&acc, "rate")),
}
}
}
@@ -2854,7 +2854,7 @@ impl AbsoluteRatePattern2 {
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
absolute: _1m1w1y24hPattern3::new(client.clone(), acc.clone()),
rate: _1m1w1y24hPattern2::new(client.clone(), acc.clone()),
rate: _1m1w1y24hPattern2::new(client.clone(), _m(&acc, "rate")),
}
}
}
@@ -3020,17 +3020,17 @@ impl InPattern {
}
/// Pattern struct for repeated tree structure.
pub struct PriceValuePattern {
pub struct PriceRatioPattern {
pub price: CentsSatsUsdPattern,
pub value: MetricPattern1<StoredF32>,
pub ratio: MetricPattern1<StoredF32>,
}
impl PriceValuePattern {
impl PriceRatioPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
pub fn new(client: Arc<BrkClientBase>, acc: String, disc: String) -> Self {
Self {
price: CentsSatsUsdPattern::new(client.clone(), _m(&acc, "p3sd_4y")),
value: MetricPattern1::new(client.clone(), _m(&acc, "ratio_p3sd_4y")),
price: CentsSatsUsdPattern::new(client.clone(), _m(&acc, &disc)),
ratio: MetricPattern1::new(client.clone(), _m(&acc, &format!("ratio_{disc}", disc=disc))),
}
}
}
@@ -3061,8 +3061,8 @@ impl SdSmaPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
sd: MetricPattern1::new(client.clone(), _m(&acc, "sd_1y")),
sma: MetricPattern1::new(client.clone(), _m(&acc, "sma_1y")),
sd: MetricPattern1::new(client.clone(), format!("{acc}_sd")),
sma: MetricPattern1::new(client.clone(), format!("{acc}_sma")),
}
}
}
@@ -5338,7 +5338,7 @@ impl MetricsTree_Market_Returns_Periods {
pub struct MetricsTree_Market_Returns_Sd24h {
pub _1w: MetricsTree_Market_Returns_Sd24h_1w,
pub _1m: MetricsTree_Market_Returns_Sd24h_1m,
pub _1y: SdSmaPattern,
pub _1y: MetricsTree_Market_Returns_Sd24h_1y,
}
impl MetricsTree_Market_Returns_Sd24h {
@@ -5346,7 +5346,7 @@ impl MetricsTree_Market_Returns_Sd24h {
Self {
_1w: MetricsTree_Market_Returns_Sd24h_1w::new(client.clone(), format!("{base_path}_1w")),
_1m: MetricsTree_Market_Returns_Sd24h_1m::new(client.clone(), format!("{base_path}_1m")),
_1y: SdSmaPattern::new(client.clone(), "price_return_24h".to_string()),
_1y: MetricsTree_Market_Returns_Sd24h_1y::new(client.clone(), format!("{base_path}_1y")),
}
}
}
@@ -5381,6 +5381,21 @@ impl MetricsTree_Market_Returns_Sd24h_1m {
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Returns_Sd24h_1y {
pub sma: MetricPattern1<StoredF32>,
pub sd: MetricPattern1<StoredF32>,
}
impl MetricsTree_Market_Returns_Sd24h_1y {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
sma: MetricPattern1::new(client.clone(), "price_return_24h_sma_1y".to_string()),
sd: MetricPattern1::new(client.clone(), "price_return_24h_sd_1y".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Volatility {
pub _1w: MetricPattern1<StoredF32>,
@@ -5484,8 +5499,8 @@ pub struct MetricsTree_Market_MovingAverage_Sma_200d {
pub sats: MetricPattern1<SatsFract>,
pub bps: MetricPattern1<BasisPoints32>,
pub ratio: MetricPattern1<StoredF32>,
pub x2_4: MetricsTree_Market_MovingAverage_Sma_200d_X24,
pub x0_8: MetricsTree_Market_MovingAverage_Sma_200d_X08,
pub x2_4: CentsSatsUsdPattern,
pub x0_8: CentsSatsUsdPattern,
}
impl MetricsTree_Market_MovingAverage_Sma_200d {
@@ -5496,42 +5511,8 @@ impl MetricsTree_Market_MovingAverage_Sma_200d {
sats: MetricPattern1::new(client.clone(), "price_sma_200d_sats".to_string()),
bps: MetricPattern1::new(client.clone(), "price_sma_200d_ratio_bps".to_string()),
ratio: MetricPattern1::new(client.clone(), "price_sma_200d_ratio".to_string()),
x2_4: MetricsTree_Market_MovingAverage_Sma_200d_X24::new(client.clone(), format!("{base_path}_x2_4")),
x0_8: MetricsTree_Market_MovingAverage_Sma_200d_X08::new(client.clone(), format!("{base_path}_x0_8")),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_MovingAverage_Sma_200d_X24 {
pub usd: MetricPattern1<Dollars>,
pub cents: MetricPattern1<Cents>,
pub sats: MetricPattern1<SatsFract>,
}
impl MetricsTree_Market_MovingAverage_Sma_200d_X24 {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
usd: MetricPattern1::new(client.clone(), "price_sma_200d_x2_4_usd".to_string()),
cents: MetricPattern1::new(client.clone(), "price_sma_200d_x2_4_cents".to_string()),
sats: MetricPattern1::new(client.clone(), "price_sma_200d_x2_4_sats".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_MovingAverage_Sma_200d_X08 {
pub usd: MetricPattern1<Dollars>,
pub cents: MetricPattern1<Cents>,
pub sats: MetricPattern1<SatsFract>,
}
impl MetricsTree_Market_MovingAverage_Sma_200d_X08 {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
usd: MetricPattern1::new(client.clone(), "price_sma_200d_x0_8_usd".to_string()),
cents: MetricPattern1::new(client.clone(), "price_sma_200d_x0_8_cents".to_string()),
sats: MetricPattern1::new(client.clone(), "price_sma_200d_x0_8_sats".to_string()),
x2_4: CentsSatsUsdPattern::new(client.clone(), "price_sma_200d_x2_4".to_string()),
x0_8: CentsSatsUsdPattern::new(client.clone(), "price_sma_200d_x0_8".to_string()),
}
}
}
@@ -5543,7 +5524,7 @@ pub struct MetricsTree_Market_MovingAverage_Sma_350d {
pub sats: MetricPattern1<SatsFract>,
pub bps: MetricPattern1<BasisPoints32>,
pub ratio: MetricPattern1<StoredF32>,
pub x2: MetricsTree_Market_MovingAverage_Sma_350d_X2,
pub x2: CentsSatsUsdPattern,
}
impl MetricsTree_Market_MovingAverage_Sma_350d {
@@ -5554,24 +5535,7 @@ impl MetricsTree_Market_MovingAverage_Sma_350d {
sats: MetricPattern1::new(client.clone(), "price_sma_350d_sats".to_string()),
bps: MetricPattern1::new(client.clone(), "price_sma_350d_ratio_bps".to_string()),
ratio: MetricPattern1::new(client.clone(), "price_sma_350d_ratio".to_string()),
x2: MetricsTree_Market_MovingAverage_Sma_350d_X2::new(client.clone(), format!("{base_path}_x2")),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_MovingAverage_Sma_350d_X2 {
pub usd: MetricPattern1<Dollars>,
pub cents: MetricPattern1<Cents>,
pub sats: MetricPattern1<SatsFract>,
}
impl MetricsTree_Market_MovingAverage_Sma_350d_X2 {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
usd: MetricPattern1::new(client.clone(), "price_sma_350d_x2_usd".to_string()),
cents: MetricPattern1::new(client.clone(), "price_sma_350d_x2_cents".to_string()),
sats: MetricPattern1::new(client.clone(), "price_sma_350d_x2_sats".to_string()),
x2: CentsSatsUsdPattern::new(client.clone(), "price_sma_350d_x2".to_string()),
}
}
}
@@ -5840,118 +5804,25 @@ impl MetricsTree_Market_Technical {
/// Metrics tree node.
pub struct MetricsTree_Market_Technical_Rsi {
pub _24h: AverageGainsLossesRsiStochPattern,
pub _1w: MetricsTree_Market_Technical_Rsi_1w,
pub _1m: MetricsTree_Market_Technical_Rsi_1m,
pub _1y: MetricsTree_Market_Technical_Rsi_1y,
pub _1w: AverageGainsLossesRsiStochPattern,
pub _1m: AverageGainsLossesRsiStochPattern,
pub _1y: AverageGainsLossesRsiStochPattern,
}
impl MetricsTree_Market_Technical_Rsi {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
_24h: AverageGainsLossesRsiStochPattern::new(client.clone(), "rsi".to_string()),
_1w: MetricsTree_Market_Technical_Rsi_1w::new(client.clone(), format!("{base_path}_1w")),
_1m: MetricsTree_Market_Technical_Rsi_1m::new(client.clone(), format!("{base_path}_1m")),
_1y: MetricsTree_Market_Technical_Rsi_1y::new(client.clone(), format!("{base_path}_1y")),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Technical_Rsi_1w {
pub gains: MetricPattern1<StoredF32>,
pub losses: MetricPattern1<StoredF32>,
pub average_gain: MetricPattern1<StoredF32>,
pub average_loss: MetricPattern1<StoredF32>,
pub rsi: BpsPercentRatioPattern3,
pub rsi_min: BpsPercentRatioPattern3,
pub rsi_max: BpsPercentRatioPattern3,
pub stoch_rsi: BpsPercentRatioPattern3,
pub stoch_rsi_k: BpsPercentRatioPattern3,
pub stoch_rsi_d: BpsPercentRatioPattern3,
}
impl MetricsTree_Market_Technical_Rsi_1w {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
gains: MetricPattern1::new(client.clone(), "rsi_gains_1w".to_string()),
losses: MetricPattern1::new(client.clone(), "rsi_losses_1w".to_string()),
average_gain: MetricPattern1::new(client.clone(), "rsi_average_gain_1w".to_string()),
average_loss: MetricPattern1::new(client.clone(), "rsi_average_loss_1w".to_string()),
rsi: BpsPercentRatioPattern3::new(client.clone(), "rsi_1w".to_string()),
rsi_min: BpsPercentRatioPattern3::new(client.clone(), "rsi_min_1w".to_string()),
rsi_max: BpsPercentRatioPattern3::new(client.clone(), "rsi_max_1w".to_string()),
stoch_rsi: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_1w".to_string()),
stoch_rsi_k: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_k_1w".to_string()),
stoch_rsi_d: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_d_1w".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Technical_Rsi_1m {
pub gains: MetricPattern1<StoredF32>,
pub losses: MetricPattern1<StoredF32>,
pub average_gain: MetricPattern1<StoredF32>,
pub average_loss: MetricPattern1<StoredF32>,
pub rsi: BpsPercentRatioPattern3,
pub rsi_min: BpsPercentRatioPattern3,
pub rsi_max: BpsPercentRatioPattern3,
pub stoch_rsi: BpsPercentRatioPattern3,
pub stoch_rsi_k: BpsPercentRatioPattern3,
pub stoch_rsi_d: BpsPercentRatioPattern3,
}
impl MetricsTree_Market_Technical_Rsi_1m {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
gains: MetricPattern1::new(client.clone(), "rsi_gains_1m".to_string()),
losses: MetricPattern1::new(client.clone(), "rsi_losses_1m".to_string()),
average_gain: MetricPattern1::new(client.clone(), "rsi_average_gain_1m".to_string()),
average_loss: MetricPattern1::new(client.clone(), "rsi_average_loss_1m".to_string()),
rsi: BpsPercentRatioPattern3::new(client.clone(), "rsi_1m".to_string()),
rsi_min: BpsPercentRatioPattern3::new(client.clone(), "rsi_min_1m".to_string()),
rsi_max: BpsPercentRatioPattern3::new(client.clone(), "rsi_max_1m".to_string()),
stoch_rsi: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_1m".to_string()),
stoch_rsi_k: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_k_1m".to_string()),
stoch_rsi_d: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_d_1m".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Technical_Rsi_1y {
pub gains: MetricPattern1<StoredF32>,
pub losses: MetricPattern1<StoredF32>,
pub average_gain: MetricPattern1<StoredF32>,
pub average_loss: MetricPattern1<StoredF32>,
pub rsi: BpsPercentRatioPattern3,
pub rsi_min: BpsPercentRatioPattern3,
pub rsi_max: BpsPercentRatioPattern3,
pub stoch_rsi: BpsPercentRatioPattern3,
pub stoch_rsi_k: BpsPercentRatioPattern3,
pub stoch_rsi_d: BpsPercentRatioPattern3,
}
impl MetricsTree_Market_Technical_Rsi_1y {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
gains: MetricPattern1::new(client.clone(), "rsi_gains_1y".to_string()),
losses: MetricPattern1::new(client.clone(), "rsi_losses_1y".to_string()),
average_gain: MetricPattern1::new(client.clone(), "rsi_average_gain_1y".to_string()),
average_loss: MetricPattern1::new(client.clone(), "rsi_average_loss_1y".to_string()),
rsi: BpsPercentRatioPattern3::new(client.clone(), "rsi_1y".to_string()),
rsi_min: BpsPercentRatioPattern3::new(client.clone(), "rsi_min_1y".to_string()),
rsi_max: BpsPercentRatioPattern3::new(client.clone(), "rsi_max_1y".to_string()),
stoch_rsi: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_1y".to_string()),
stoch_rsi_k: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_k_1y".to_string()),
stoch_rsi_d: BpsPercentRatioPattern3::new(client.clone(), "rsi_stoch_d_1y".to_string()),
_24h: AverageGainsLossesRsiStochPattern::new(client.clone(), "rsi".to_string(), "24h".to_string().to_string()),
_1w: AverageGainsLossesRsiStochPattern::new(client.clone(), "rsi".to_string(), "1w".to_string().to_string()),
_1m: AverageGainsLossesRsiStochPattern::new(client.clone(), "rsi".to_string(), "1m".to_string().to_string()),
_1y: AverageGainsLossesRsiStochPattern::new(client.clone(), "rsi".to_string(), "1y".to_string().to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Technical_Macd {
pub _24h: EmaHistogramLineSignalPattern,
pub _24h: MetricsTree_Market_Technical_Macd_24h,
pub _1w: MetricsTree_Market_Technical_Macd_1w,
pub _1m: MetricsTree_Market_Technical_Macd_1m,
pub _1y: MetricsTree_Market_Technical_Macd_1y,
@@ -5960,7 +5831,7 @@ pub struct MetricsTree_Market_Technical_Macd {
impl MetricsTree_Market_Technical_Macd {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
_24h: EmaHistogramLineSignalPattern::new(client.clone(), "macd".to_string()),
_24h: MetricsTree_Market_Technical_Macd_24h::new(client.clone(), format!("{base_path}_24h")),
_1w: MetricsTree_Market_Technical_Macd_1w::new(client.clone(), format!("{base_path}_1w")),
_1m: MetricsTree_Market_Technical_Macd_1m::new(client.clone(), format!("{base_path}_1m")),
_1y: MetricsTree_Market_Technical_Macd_1y::new(client.clone(), format!("{base_path}_1y")),
@@ -5968,6 +5839,27 @@ impl MetricsTree_Market_Technical_Macd {
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Technical_Macd_24h {
pub ema_fast: MetricPattern1<StoredF32>,
pub ema_slow: MetricPattern1<StoredF32>,
pub line: MetricPattern1<StoredF32>,
pub signal: MetricPattern1<StoredF32>,
pub histogram: MetricPattern1<StoredF32>,
}
impl MetricsTree_Market_Technical_Macd_24h {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
ema_fast: MetricPattern1::new(client.clone(), "macd_ema_fast_24h".to_string()),
ema_slow: MetricPattern1::new(client.clone(), "macd_ema_slow_24h".to_string()),
line: MetricPattern1::new(client.clone(), "macd_line_24h".to_string()),
signal: MetricPattern1::new(client.clone(), "macd_signal_24h".to_string()),
histogram: MetricPattern1::new(client.clone(), "macd_histogram_24h".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Technical_Macd_1w {
pub ema_fast: MetricPattern1<StoredF32>,
@@ -6578,7 +6470,7 @@ pub struct MetricsTree_Cohorts_Utxo_All {
pub supply: MetricsTree_Cohorts_Utxo_All_Supply,
pub outputs: UnspentPattern,
pub activity: CoindaysCoinyearsDormancySentPattern,
pub realized: CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern,
pub realized: MetricsTree_Cohorts_Utxo_All_Realized,
pub cost_basis: InvestedMaxMinPercentilesSupplyPattern,
pub unrealized: MetricsTree_Cohorts_Utxo_All_Unrealized,
}
@@ -6589,7 +6481,7 @@ impl MetricsTree_Cohorts_Utxo_All {
supply: MetricsTree_Cohorts_Utxo_All_Supply::new(client.clone(), format!("{base_path}_supply")),
outputs: UnspentPattern::new(client.clone(), "utxo_count".to_string()),
activity: CoindaysCoinyearsDormancySentPattern::new(client.clone(), "".to_string()),
realized: CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern::new(client.clone(), "".to_string()),
realized: MetricsTree_Cohorts_Utxo_All_Realized::new(client.clone(), format!("{base_path}_realized")),
cost_basis: InvestedMaxMinPercentilesSupplyPattern::new(client.clone(), "".to_string()),
unrealized: MetricsTree_Cohorts_Utxo_All_Unrealized::new(client.clone(), format!("{base_path}_unrealized")),
}
@@ -6617,6 +6509,41 @@ impl MetricsTree_Cohorts_Utxo_All_Supply {
}
}
/// Metrics tree node.
pub struct MetricsTree_Cohorts_Utxo_All_Realized {
pub cap: CentsDeltaRelUsdPattern,
pub profit: BaseCumulativeDistributionRelSumValuePattern,
pub loss: BaseCapitulationCumulativeNegativeRelSumValuePattern,
pub price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern,
pub mvrv: MetricPattern1<StoredF32>,
pub sopr: AdjustedRatioValuePattern,
pub net_pnl: BaseChangeCumulativeDeltaRelSumPattern,
pub gross_pnl: BaseCumulativeSumPattern3,
pub sell_side_risk_ratio: _1m1w1y24hPattern6,
pub peak_regret: BaseCumulativeRelPattern,
pub investor: LowerPriceUpperPattern,
pub profit_to_loss_ratio: _1m1w1y24hPattern<StoredF64>,
}
impl MetricsTree_Cohorts_Utxo_All_Realized {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
cap: CentsDeltaRelUsdPattern::new(client.clone(), "realized_cap".to_string()),
profit: BaseCumulativeDistributionRelSumValuePattern::new(client.clone(), "".to_string()),
loss: BaseCapitulationCumulativeNegativeRelSumValuePattern::new(client.clone(), "".to_string()),
price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern::new(client.clone(), "realized_price".to_string()),
mvrv: MetricPattern1::new(client.clone(), "mvrv".to_string()),
sopr: AdjustedRatioValuePattern::new(client.clone(), "".to_string()),
net_pnl: BaseChangeCumulativeDeltaRelSumPattern::new(client.clone(), "net".to_string()),
gross_pnl: BaseCumulativeSumPattern3::new(client.clone(), "realized_gross_pnl".to_string()),
sell_side_risk_ratio: _1m1w1y24hPattern6::new(client.clone(), "sell_side_risk_ratio".to_string()),
peak_regret: BaseCumulativeRelPattern::new(client.clone(), "realized_peak_regret".to_string()),
investor: LowerPriceUpperPattern::new(client.clone(), "".to_string()),
profit_to_loss_ratio: _1m1w1y24hPattern::new(client.clone(), "realized_profit_to_loss_ratio".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Cohorts_Utxo_All_Unrealized {
pub nupl: BpsRatioPattern,
@@ -6708,7 +6635,7 @@ pub struct MetricsTree_Cohorts_Utxo_Sth {
pub supply: DeltaHalfInRelTotalPattern2,
pub outputs: UnspentPattern,
pub activity: CoindaysCoinyearsDormancySentPattern,
pub realized: CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern,
pub realized: MetricsTree_Cohorts_Utxo_Sth_Realized,
pub cost_basis: InvestedMaxMinPercentilesSupplyPattern,
pub unrealized: GrossInvestedLossNetNuplProfitSentimentPattern2,
}
@@ -6719,13 +6646,48 @@ impl MetricsTree_Cohorts_Utxo_Sth {
supply: DeltaHalfInRelTotalPattern2::new(client.clone(), "sth_supply".to_string()),
outputs: UnspentPattern::new(client.clone(), "sth_utxo_count".to_string()),
activity: CoindaysCoinyearsDormancySentPattern::new(client.clone(), "sth".to_string()),
realized: CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern::new(client.clone(), "sth".to_string()),
realized: MetricsTree_Cohorts_Utxo_Sth_Realized::new(client.clone(), format!("{base_path}_realized")),
cost_basis: InvestedMaxMinPercentilesSupplyPattern::new(client.clone(), "sth".to_string()),
unrealized: GrossInvestedLossNetNuplProfitSentimentPattern2::new(client.clone(), "sth".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Cohorts_Utxo_Sth_Realized {
pub cap: CentsDeltaRelUsdPattern,
pub profit: BaseCumulativeDistributionRelSumValuePattern,
pub loss: BaseCapitulationCumulativeNegativeRelSumValuePattern,
pub price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern,
pub mvrv: MetricPattern1<StoredF32>,
pub sopr: AdjustedRatioValuePattern,
pub net_pnl: BaseChangeCumulativeDeltaRelSumPattern,
pub gross_pnl: BaseCumulativeSumPattern3,
pub sell_side_risk_ratio: _1m1w1y24hPattern6,
pub peak_regret: BaseCumulativeRelPattern,
pub investor: LowerPriceUpperPattern,
pub profit_to_loss_ratio: _1m1w1y24hPattern<StoredF64>,
}
impl MetricsTree_Cohorts_Utxo_Sth_Realized {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
cap: CentsDeltaRelUsdPattern::new(client.clone(), "sth_realized_cap".to_string()),
profit: BaseCumulativeDistributionRelSumValuePattern::new(client.clone(), "sth".to_string()),
loss: BaseCapitulationCumulativeNegativeRelSumValuePattern::new(client.clone(), "sth".to_string()),
price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern::new(client.clone(), "sth_realized_price".to_string()),
mvrv: MetricPattern1::new(client.clone(), "sth_mvrv".to_string()),
sopr: AdjustedRatioValuePattern::new(client.clone(), "sth".to_string()),
net_pnl: BaseChangeCumulativeDeltaRelSumPattern::new(client.clone(), "sth_net".to_string()),
gross_pnl: BaseCumulativeSumPattern3::new(client.clone(), "sth_realized_gross_pnl".to_string()),
sell_side_risk_ratio: _1m1w1y24hPattern6::new(client.clone(), "sth_sell_side_risk_ratio".to_string()),
peak_regret: BaseCumulativeRelPattern::new(client.clone(), "sth_realized_peak_regret".to_string()),
investor: LowerPriceUpperPattern::new(client.clone(), "sth".to_string()),
profit_to_loss_ratio: _1m1w1y24hPattern::new(client.clone(), "sth_realized_profit_to_loss_ratio".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Cohorts_Utxo_Lth {
pub supply: DeltaHalfInRelTotalPattern2,
@@ -10,7 +10,7 @@ use brk_types::{Cents, Dollars, SatsFract, Version};
use schemars::JsonSchema;
use vecdb::{Database, ReadableCloneableVec, UnaryTransform};
use super::{PerBlock, LazyPerBlock};
use super::{LazyPerBlock, PerBlock};
use crate::{
indexes,
internal::{CentsUnsignedToDollars, ComputedVecValue, DollarsToSatsFract, NumericValue},
@@ -32,8 +32,7 @@ impl Price<PerBlock<Cents>> {
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let cents =
PerBlock::forced_import(db, &format!("{name}_cents"), version, indexes)?;
let cents = PerBlock::forced_import(db, &format!("{name}_cents"), version, indexes)?;
let usd = LazyPerBlock::from_computed::<CentsUnsignedToDollars>(
name,
version,
@@ -65,11 +64,7 @@ where
source.height.read_only_boxed_clone(),
source,
);
let usd = LazyPerBlock::from_lazy::<CentsUnsignedToDollars, ST>(
&format!("{name}_usd"),
version,
&cents,
);
let usd = LazyPerBlock::from_lazy::<CentsUnsignedToDollars, ST>(name, version, &cents);
let sats = LazyPerBlock::from_lazy::<DollarsToSatsFract, Cents>(
&format!("{name}_sats"),
version,
@@ -27,10 +27,10 @@ impl RatioPerBlockStdDevBands {
let v = version + VERSION;
macro_rules! import_sd {
($suffix:expr, $period:expr, $days:expr) => {
($period:expr, $days:expr) => {
StdDevPerBlockExtended::forced_import(
db,
&format!("{name}_{}", $suffix),
name,
$period,
$days,
v,
@@ -40,10 +40,10 @@ impl RatioPerBlockStdDevBands {
}
Ok(Self {
all: import_sd!("ratio", "", usize::MAX),
_1y: import_sd!("ratio", "1y", 365),
_2y: import_sd!("ratio", "2y", 2 * 365),
_4y: import_sd!("ratio", "4y", 4 * 365),
all: import_sd!("", usize::MAX),
_1y: import_sd!("1y", 365),
_2y: import_sd!("2y", 2 * 365),
_4y: import_sd!("4y", 4 * 365),
})
}
@@ -8,13 +8,13 @@ use vecdb::{
use crate::{
blocks, indexes,
internal::{PerBlock, Price, PriceTimesRatioCents},
internal::{PerBlock, Price, PriceTimesRatioCents, per_block::stddev::period_suffix},
};
#[derive(Traversable)]
pub struct StdDevBand<M: StorageMode = Rw> {
#[traversable(flatten)]
pub value: PerBlock<StoredF32, M>,
pub ratio: PerBlock<StoredF32, M>,
pub price: Price<PerBlock<Cents, M>>,
}
@@ -49,16 +49,11 @@ impl StdDevPerBlockExtended {
indexes: &indexes::Vecs,
) -> Result<Self> {
let version = parent_version + Version::TWO;
let p = super::period_suffix(period);
let p = period_suffix(period);
macro_rules! import {
($suffix:expr) => {
PerBlock::forced_import(
db,
&format!("{name}_{}{p}", $suffix),
version,
indexes,
)?
PerBlock::forced_import(db, &format!("{name}_{}{p}", $suffix), version, indexes)?
};
}
@@ -69,18 +64,18 @@ impl StdDevPerBlockExtended {
}
macro_rules! import_band {
($suffix:expr) => {
($suffix:expr) => {{
StdDevBand {
value: import!(concat!("ratio_", $suffix)),
ratio: import!(concat!("ratio_", $suffix)),
price: import_price!($suffix),
}
};
}};
}
Ok(Self {
days,
sd: import!("sd"),
zscore: import!("zscore"),
sd: import!("ratio_sd"),
zscore: import!("ratio_zscore"),
_0sd: import_price!("0sd"),
p0_5sd: import_band!("p0_5sd"),
p1sd: import_band!("p1sd"),
@@ -106,12 +101,9 @@ impl StdDevPerBlockExtended {
sma: &impl ReadableVec<Height, StoredF32>,
) -> Result<()> {
if self.days == usize::MAX {
self.sd.height.compute_expanding_sd(
starting_indexes.height,
source,
sma,
exit,
)?;
self.sd
.height
.compute_expanding_sd(starting_indexes.height, source, sma, exit)?;
} else {
let window_starts = blocks.lookback.start_vec(self.days);
self.sd.height.compute_rolling_sd(
@@ -154,10 +146,7 @@ impl StdDevPerBlockExtended {
let source_data = source.collect_range_at(start, source_len);
let sma_data = sma.collect_range_at(start, sma.len());
let sd_data = self
.sd
.height
.collect_range_at(start, self.sd.height.len());
let sd_data = self.sd.height.collect_range_at(start, self.sd.height.len());
const MULTIPLIERS: [f32; 12] = [
0.5, 1.0, 1.5, 2.0, 2.5, 3.0, -0.5, -1.0, -1.5, -2.0, -2.5, -3.0,
@@ -208,18 +197,18 @@ impl StdDevPerBlockExtended {
}
compute_band_price!(&mut self._0sd, sma);
compute_band_price!(&mut self.p0_5sd.price, &self.p0_5sd.value.height);
compute_band_price!(&mut self.p1sd.price, &self.p1sd.value.height);
compute_band_price!(&mut self.p1_5sd.price, &self.p1_5sd.value.height);
compute_band_price!(&mut self.p2sd.price, &self.p2sd.value.height);
compute_band_price!(&mut self.p2_5sd.price, &self.p2_5sd.value.height);
compute_band_price!(&mut self.p3sd.price, &self.p3sd.value.height);
compute_band_price!(&mut self.m0_5sd.price, &self.m0_5sd.value.height);
compute_band_price!(&mut self.m1sd.price, &self.m1sd.value.height);
compute_band_price!(&mut self.m1_5sd.price, &self.m1_5sd.value.height);
compute_band_price!(&mut self.m2sd.price, &self.m2sd.value.height);
compute_band_price!(&mut self.m2_5sd.price, &self.m2_5sd.value.height);
compute_band_price!(&mut self.m3sd.price, &self.m3sd.value.height);
compute_band_price!(&mut self.p0_5sd.price, &self.p0_5sd.ratio.height);
compute_band_price!(&mut self.p1sd.price, &self.p1sd.ratio.height);
compute_band_price!(&mut self.p1_5sd.price, &self.p1_5sd.ratio.height);
compute_band_price!(&mut self.p2sd.price, &self.p2sd.ratio.height);
compute_band_price!(&mut self.p2_5sd.price, &self.p2_5sd.ratio.height);
compute_band_price!(&mut self.p3sd.price, &self.p3sd.ratio.height);
compute_band_price!(&mut self.m0_5sd.price, &self.m0_5sd.ratio.height);
compute_band_price!(&mut self.m1sd.price, &self.m1sd.ratio.height);
compute_band_price!(&mut self.m1_5sd.price, &self.m1_5sd.ratio.height);
compute_band_price!(&mut self.m2sd.price, &self.m2sd.ratio.height);
compute_band_price!(&mut self.m2_5sd.price, &self.m2_5sd.ratio.height);
compute_band_price!(&mut self.m3sd.price, &self.m3sd.ratio.height);
Ok(())
}
@@ -228,18 +217,18 @@ impl StdDevPerBlockExtended {
&mut self,
) -> impl Iterator<Item = &mut EagerVec<PcoVec<Height, StoredF32>>> {
[
&mut self.p0_5sd.value.height,
&mut self.p1sd.value.height,
&mut self.p1_5sd.value.height,
&mut self.p2sd.value.height,
&mut self.p2_5sd.value.height,
&mut self.p3sd.value.height,
&mut self.m0_5sd.value.height,
&mut self.m1sd.value.height,
&mut self.m1_5sd.value.height,
&mut self.m2sd.value.height,
&mut self.m2_5sd.value.height,
&mut self.m3sd.value.height,
&mut self.p0_5sd.ratio.height,
&mut self.p1sd.ratio.height,
&mut self.p1_5sd.ratio.height,
&mut self.p2sd.ratio.height,
&mut self.p2_5sd.ratio.height,
&mut self.p3sd.ratio.height,
&mut self.m0_5sd.ratio.height,
&mut self.m1sd.ratio.height,
&mut self.m1_5sd.ratio.height,
&mut self.m2sd.ratio.height,
&mut self.m2_5sd.ratio.height,
&mut self.m3sd.ratio.height,
]
.into_iter()
}
+1
View File
@@ -25,6 +25,7 @@ pub fn main() -> color_eyre::Result<()> {
.to_path_buf();
let output_paths = brk_bindgen::ClientOutputPaths::new()
.rust(workspace_root.join("crates/brk_client/src/lib.rs"))
.javascript(workspace_root.join("website/scripts/modules/brk-client/index.js"));
generate_bindings(&vecs, &openapi, &output_paths)?;
+125 -204
View File
@@ -1656,18 +1656,18 @@ function createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65
/**
* @typedef {Object} _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern
* @property {CentsSatsUsdPattern} _0sd
* @property {PriceValuePattern} m05sd
* @property {PriceValuePattern} m15sd
* @property {PriceValuePattern} m1sd
* @property {PriceValuePattern} m25sd
* @property {PriceValuePattern} m2sd
* @property {PriceValuePattern} m3sd
* @property {PriceValuePattern} p05sd
* @property {PriceValuePattern} p15sd
* @property {PriceValuePattern} p1sd
* @property {PriceValuePattern} p25sd
* @property {PriceValuePattern} p2sd
* @property {PriceValuePattern} p3sd
* @property {PriceRatioPattern} m05sd
* @property {PriceRatioPattern} m15sd
* @property {PriceRatioPattern} m1sd
* @property {PriceRatioPattern} m25sd
* @property {PriceRatioPattern} m2sd
* @property {PriceRatioPattern} m3sd
* @property {PriceRatioPattern} p05sd
* @property {PriceRatioPattern} p15sd
* @property {PriceRatioPattern} p1sd
* @property {PriceRatioPattern} p25sd
* @property {PriceRatioPattern} p2sd
* @property {PriceRatioPattern} p3sd
* @property {MetricPattern1<StoredF32>} sd
* @property {MetricPattern1<StoredF32>} zscore
*/
@@ -1676,25 +1676,26 @@ function createPct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65
* Create a _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @param {string} disc - Discriminator suffix
* @returns {_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern}
*/
function create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc) {
function create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, disc) {
return {
_0sd: createCentsSatsUsdPattern(client, _m(acc, '0sd_4y')),
m05sd: createPriceValuePattern(client, acc),
m15sd: createPriceValuePattern(client, acc),
m1sd: createPriceValuePattern(client, acc),
m25sd: createPriceValuePattern(client, acc),
m2sd: createPriceValuePattern(client, acc),
m3sd: createPriceValuePattern(client, acc),
p05sd: createPriceValuePattern(client, acc),
p15sd: createPriceValuePattern(client, acc),
p1sd: createPriceValuePattern(client, acc),
p25sd: createPriceValuePattern(client, acc),
p2sd: createPriceValuePattern(client, acc),
p3sd: createPriceValuePattern(client, acc),
sd: createMetricPattern1(client, _m(acc, 'sd_4y')),
zscore: createMetricPattern1(client, _m(acc, 'zscore_4y')),
_0sd: createCentsSatsUsdPattern(client, _m(_m(acc, '0sd'), disc)),
m05sd: createPriceRatioPattern(client, acc, _m('m0_5sd', disc)),
m15sd: createPriceRatioPattern(client, acc, _m('m1_5sd', disc)),
m1sd: createPriceRatioPattern(client, acc, _m('m1sd', disc)),
m25sd: createPriceRatioPattern(client, acc, _m('m2_5sd', disc)),
m2sd: createPriceRatioPattern(client, acc, _m('m2sd', disc)),
m3sd: createPriceRatioPattern(client, acc, _m('m3sd', disc)),
p05sd: createPriceRatioPattern(client, acc, _m('p0_5sd', disc)),
p15sd: createPriceRatioPattern(client, acc, _m('p1_5sd', disc)),
p1sd: createPriceRatioPattern(client, acc, _m('p1sd', disc)),
p25sd: createPriceRatioPattern(client, acc, _m('p2_5sd', disc)),
p2sd: createPriceRatioPattern(client, acc, _m('p2sd', disc)),
p3sd: createPriceRatioPattern(client, acc, _m('p3sd', disc)),
sd: createMetricPattern1(client, _m(_m(acc, 'ratio_sd'), disc)),
zscore: createMetricPattern1(client, _m(_m(acc, 'ratio_zscore'), disc)),
};
}
@@ -1907,20 +1908,21 @@ function createAverageBaseCumulativeMaxMedianMinPct10Pct25Pct75Pct90SumPattern(c
* Create a AverageGainsLossesRsiStochPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @param {string} disc - Discriminator suffix
* @returns {AverageGainsLossesRsiStochPattern}
*/
function createAverageGainsLossesRsiStochPattern(client, acc) {
function createAverageGainsLossesRsiStochPattern(client, acc, disc) {
return {
averageGain: createMetricPattern1(client, _m(acc, 'average_gain_24h')),
averageLoss: createMetricPattern1(client, _m(acc, 'average_loss_24h')),
gains: createMetricPattern1(client, _m(acc, 'gains_24h')),
losses: createMetricPattern1(client, _m(acc, 'losses_24h')),
rsi: createBpsPercentRatioPattern3(client, _m(acc, '24h')),
rsiMax: createBpsPercentRatioPattern3(client, _m(acc, 'max_24h')),
rsiMin: createBpsPercentRatioPattern3(client, _m(acc, 'min_24h')),
stochRsi: createBpsPercentRatioPattern3(client, _m(acc, 'stoch_24h')),
stochRsiD: createBpsPercentRatioPattern3(client, _m(acc, 'stoch_d_24h')),
stochRsiK: createBpsPercentRatioPattern3(client, _m(acc, 'stoch_k_24h')),
averageGain: createMetricPattern1(client, _m(_m(acc, 'average_gain'), disc)),
averageLoss: createMetricPattern1(client, _m(_m(acc, 'average_loss'), disc)),
gains: createMetricPattern1(client, _m(_m(acc, 'gains'), disc)),
losses: createMetricPattern1(client, _m(_m(acc, 'losses'), disc)),
rsi: createBpsPercentRatioPattern3(client, _m(acc, disc)),
rsiMax: createBpsPercentRatioPattern3(client, _m(_m(acc, 'max'), disc)),
rsiMin: createBpsPercentRatioPattern3(client, _m(_m(acc, 'min'), disc)),
stochRsi: createBpsPercentRatioPattern3(client, _m(_m(acc, 'stoch'), disc)),
stochRsiD: createBpsPercentRatioPattern3(client, _m(_m(acc, 'stoch_d'), disc)),
stochRsiK: createBpsPercentRatioPattern3(client, _m(_m(acc, 'stoch_k'), disc)),
};
}
@@ -2078,7 +2080,7 @@ function createBpsCentsPercentilesRatioSatsSmaStdUsdPattern(client, acc) {
ratio: createMetricPattern1(client, _m(acc, 'ratio')),
sats: createMetricPattern1(client, _m(acc, 'sats')),
sma: create_1m1w1y2y4yAllPattern(client, _m(acc, 'ratio_sma')),
stdDev: create_1y2y4yAllPattern(client, _m(acc, 'ratio')),
stdDev: create_1y2y4yAllPattern(client, acc),
usd: createMetricPattern1(client, acc),
};
}
@@ -2252,7 +2254,7 @@ function createBaseCumulativeNegativeRelSumPattern2(client, acc) {
function createCapLossMvrvNetPriceProfitSoprPattern(client, acc) {
return {
cap: createCentsDeltaUsdPattern(client, _m(acc, 'realized_cap')),
loss: createBaseCumulativeNegativeSumPattern(client, acc),
loss: createBaseCumulativeNegativeSumPattern(client, acc, ''),
mvrv: createMetricPattern1(client, _m(acc, 'mvrv')),
netPnl: createBaseCumulativeDeltaSumPattern(client, _m(acc, 'net_realized_pnl')),
price: createBpsCentsRatioSatsUsdPattern(client, _m(acc, 'realized_price')),
@@ -2524,12 +2526,12 @@ function createDeltaHalfInRelTotalPattern2(client, acc) {
*/
function createPct1Pct2Pct5Pct95Pct98Pct99Pattern(client, acc) {
return {
pct1: createBpsPriceRatioPattern(client, acc),
pct2: createBpsPriceRatioPattern(client, acc),
pct5: createBpsPriceRatioPattern(client, acc),
pct95: createBpsPriceRatioPattern(client, acc),
pct98: createBpsPriceRatioPattern(client, acc),
pct99: createBpsPriceRatioPattern(client, acc),
pct1: createBpsPriceRatioPattern(client, acc, 'pct1'),
pct2: createBpsPriceRatioPattern(client, acc, 'pct2'),
pct5: createBpsPriceRatioPattern(client, acc, 'pct5'),
pct95: createBpsPriceRatioPattern(client, acc, 'pct95'),
pct98: createBpsPriceRatioPattern(client, acc, 'pct98'),
pct99: createBpsPriceRatioPattern(client, acc, 'pct99'),
};
}
@@ -2750,11 +2752,11 @@ function createDeltaHalfInTotalPattern2(client, acc) {
*/
function createEmaHistogramLineSignalPattern(client, acc) {
return {
emaFast: createMetricPattern1(client, _m(acc, 'ema_fast_24h')),
emaSlow: createMetricPattern1(client, _m(acc, 'ema_slow_24h')),
histogram: createMetricPattern1(client, _m(acc, 'histogram_24h')),
line: createMetricPattern1(client, _m(acc, 'line_24h')),
signal: createMetricPattern1(client, _m(acc, 'signal_24h')),
emaFast: createMetricPattern1(client, `${acc}_ema_fast`),
emaSlow: createMetricPattern1(client, `${acc}_ema_slow`),
histogram: createMetricPattern1(client, `${acc}_histogram`),
line: createMetricPattern1(client, `${acc}_line`),
signal: createMetricPattern1(client, `${acc}_signal`),
};
}
@@ -3014,10 +3016,10 @@ function create_1m1w1y24hPattern4(client, acc) {
*/
function create_1y2y4yAllPattern(client, acc) {
return {
_1y: create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc),
_2y: create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc),
_4y: create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc),
all: create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc),
_1y: create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, ''),
_2y: create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, ''),
_4y: create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, ''),
all: create_0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, ''),
};
}
@@ -3079,14 +3081,15 @@ function createBaseCumulativeDeltaSumPattern(client, acc) {
* Create a BaseCumulativeNegativeSumPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @param {string} disc - Discriminator suffix
* @returns {BaseCumulativeNegativeSumPattern}
*/
function createBaseCumulativeNegativeSumPattern(client, acc) {
function createBaseCumulativeNegativeSumPattern(client, acc, disc) {
return {
base: createCentsUsdPattern2(client, _m(acc, 'unrealized_loss')),
cumulative: createCentsUsdPattern2(client, _m(acc, 'unrealized_loss_cumulative')),
negative: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss')),
sum: create_1m1w1y24hPattern4(client, _m(acc, 'unrealized_loss_sum')),
base: createCentsUsdPattern2(client, _m(acc, disc)),
cumulative: createCentsUsdPattern2(client, _m(acc, `${disc}_cumulative`)),
negative: createMetricPattern1(client, _m(_m(acc, 'neg'), disc)),
sum: create_1m1w1y24hPattern4(client, _m(acc, `${disc}_sum`)),
};
}
@@ -3221,7 +3224,7 @@ function createCoindaysCoinyearsDormancySentPattern(client, acc) {
*/
function createLossNetNuplProfitPattern(client, acc) {
return {
loss: createBaseCumulativeNegativeSumPattern(client, acc),
loss: createBaseCumulativeNegativeSumPattern(client, acc, ''),
netPnl: createCentsUsdPattern(client, _m(acc, 'net_unrealized_pnl')),
nupl: createBpsRatioPattern(client, _m(acc, 'nupl')),
profit: createBaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit')),
@@ -3457,13 +3460,14 @@ function createBpsPercentRatioPattern4(client, acc) {
* Create a BpsPriceRatioPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @param {string} disc - Discriminator suffix
* @returns {BpsPriceRatioPattern}
*/
function createBpsPriceRatioPattern(client, acc) {
function createBpsPriceRatioPattern(client, acc, disc) {
return {
bps: createMetricPattern1(client, _m(acc, 'ratio_pct99_bps')),
price: createCentsSatsUsdPattern(client, _m(acc, 'pct99')),
ratio: createMetricPattern1(client, _m(acc, 'ratio_pct99')),
bps: createMetricPattern1(client, _m(acc, `ratio_${disc}_bps`)),
price: createCentsSatsUsdPattern(client, _m(acc, disc)),
ratio: createMetricPattern1(client, _m(_m(acc, 'ratio'), disc)),
};
}
@@ -3629,7 +3633,7 @@ function createGreedNetPainPattern(client, acc) {
*/
function createLossNuplProfitPattern(client, acc) {
return {
loss: createBaseCumulativeNegativeSumPattern(client, acc),
loss: createBaseCumulativeNegativeSumPattern(client, acc, ''),
nupl: createBpsRatioPattern(client, _m(acc, 'nupl')),
profit: createBaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit')),
};
@@ -3671,9 +3675,9 @@ function createLowerPriceUpperPattern(client, acc) {
*/
function createRatioValuePattern2(client, acc) {
return {
ratio: create_1m1w1y24hPattern(client, _m(acc, 'asopr')),
valueCreated: createBaseCumulativeSumPattern(client, _m(acc, 'adj_value_created')),
valueDestroyed: createBaseCumulativeSumPattern(client, _m(acc, 'adj_value_destroyed')),
ratio: create_1m1w1y24hPattern(client, `${acc}_ratio`),
valueCreated: createBaseCumulativeSumPattern(client, `${acc}_value_created`),
valueDestroyed: createBaseCumulativeSumPattern(client, `${acc}_value_destroyed`),
};
}
@@ -3973,21 +3977,22 @@ function createInPattern(client, acc) {
}
/**
* @typedef {Object} PriceValuePattern
* @typedef {Object} PriceRatioPattern
* @property {CentsSatsUsdPattern} price
* @property {MetricPattern1<StoredF32>} value
* @property {MetricPattern1<StoredF32>} ratio
*/
/**
* Create a PriceValuePattern pattern node
* Create a PriceRatioPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {PriceValuePattern}
* @param {string} disc - Discriminator suffix
* @returns {PriceRatioPattern}
*/
function createPriceValuePattern(client, acc) {
function createPriceRatioPattern(client, acc, disc) {
return {
price: createCentsSatsUsdPattern(client, _m(acc, 'p3sd_4y')),
value: createMetricPattern1(client, _m(acc, 'ratio_p3sd_4y')),
price: createCentsSatsUsdPattern(client, _m(acc, disc)),
ratio: createMetricPattern1(client, _m(_m(acc, 'ratio'), disc)),
};
}
@@ -4024,8 +4029,8 @@ function createRelPattern(client, acc) {
*/
function createSdSmaPattern(client, acc) {
return {
sd: createMetricPattern1(client, _m(acc, 'sd_1y')),
sma: createMetricPattern1(client, _m(acc, 'sma_1y')),
sd: createMetricPattern1(client, `${acc}_sd`),
sma: createMetricPattern1(client, `${acc}_sma`),
};
}
@@ -5051,7 +5056,7 @@ function createUnspentPattern(client, acc) {
* @typedef {Object} MetricsTree_Market_Returns_Sd24h
* @property {MetricsTree_Market_Returns_Sd24h_1w} _1w
* @property {MetricsTree_Market_Returns_Sd24h_1m} _1m
* @property {SdSmaPattern} _1y
* @property {MetricsTree_Market_Returns_Sd24h_1y} _1y
*/
/**
@@ -5066,6 +5071,12 @@ function createUnspentPattern(client, acc) {
* @property {MetricPattern1<StoredF32>} sd
*/
/**
* @typedef {Object} MetricsTree_Market_Returns_Sd24h_1y
* @property {MetricPattern1<StoredF32>} sma
* @property {MetricPattern1<StoredF32>} sd
*/
/**
* @typedef {Object} MetricsTree_Market_Volatility
* @property {MetricPattern1<StoredF32>} _1w
@@ -5115,22 +5126,8 @@ function createUnspentPattern(client, acc) {
* @property {MetricPattern1<SatsFract>} sats
* @property {MetricPattern1<BasisPoints32>} bps
* @property {MetricPattern1<StoredF32>} ratio
* @property {MetricsTree_Market_MovingAverage_Sma_200d_X24} x24
* @property {MetricsTree_Market_MovingAverage_Sma_200d_X08} x08
*/
/**
* @typedef {Object} MetricsTree_Market_MovingAverage_Sma_200d_X24
* @property {MetricPattern1<Dollars>} usd
* @property {MetricPattern1<Cents>} cents
* @property {MetricPattern1<SatsFract>} sats
*/
/**
* @typedef {Object} MetricsTree_Market_MovingAverage_Sma_200d_X08
* @property {MetricPattern1<Dollars>} usd
* @property {MetricPattern1<Cents>} cents
* @property {MetricPattern1<SatsFract>} sats
* @property {CentsSatsUsdPattern} x24
* @property {CentsSatsUsdPattern} x08
*/
/**
@@ -5140,14 +5137,7 @@ function createUnspentPattern(client, acc) {
* @property {MetricPattern1<SatsFract>} sats
* @property {MetricPattern1<BasisPoints32>} bps
* @property {MetricPattern1<StoredF32>} ratio
* @property {MetricsTree_Market_MovingAverage_Sma_350d_X2} x2
*/
/**
* @typedef {Object} MetricsTree_Market_MovingAverage_Sma_350d_X2
* @property {MetricPattern1<Dollars>} usd
* @property {MetricPattern1<Cents>} cents
* @property {MetricPattern1<SatsFract>} sats
* @property {CentsSatsUsdPattern} x2
*/
/**
@@ -5270,61 +5260,28 @@ function createUnspentPattern(client, acc) {
/**
* @typedef {Object} MetricsTree_Market_Technical_Rsi
* @property {AverageGainsLossesRsiStochPattern} _24h
* @property {MetricsTree_Market_Technical_Rsi_1w} _1w
* @property {MetricsTree_Market_Technical_Rsi_1m} _1m
* @property {MetricsTree_Market_Technical_Rsi_1y} _1y
*/
/**
* @typedef {Object} MetricsTree_Market_Technical_Rsi_1w
* @property {MetricPattern1<StoredF32>} gains
* @property {MetricPattern1<StoredF32>} losses
* @property {MetricPattern1<StoredF32>} averageGain
* @property {MetricPattern1<StoredF32>} averageLoss
* @property {BpsPercentRatioPattern3} rsi
* @property {BpsPercentRatioPattern3} rsiMin
* @property {BpsPercentRatioPattern3} rsiMax
* @property {BpsPercentRatioPattern3} stochRsi
* @property {BpsPercentRatioPattern3} stochRsiK
* @property {BpsPercentRatioPattern3} stochRsiD
*/
/**
* @typedef {Object} MetricsTree_Market_Technical_Rsi_1m
* @property {MetricPattern1<StoredF32>} gains
* @property {MetricPattern1<StoredF32>} losses
* @property {MetricPattern1<StoredF32>} averageGain
* @property {MetricPattern1<StoredF32>} averageLoss
* @property {BpsPercentRatioPattern3} rsi
* @property {BpsPercentRatioPattern3} rsiMin
* @property {BpsPercentRatioPattern3} rsiMax
* @property {BpsPercentRatioPattern3} stochRsi
* @property {BpsPercentRatioPattern3} stochRsiK
* @property {BpsPercentRatioPattern3} stochRsiD
*/
/**
* @typedef {Object} MetricsTree_Market_Technical_Rsi_1y
* @property {MetricPattern1<StoredF32>} gains
* @property {MetricPattern1<StoredF32>} losses
* @property {MetricPattern1<StoredF32>} averageGain
* @property {MetricPattern1<StoredF32>} averageLoss
* @property {BpsPercentRatioPattern3} rsi
* @property {BpsPercentRatioPattern3} rsiMin
* @property {BpsPercentRatioPattern3} rsiMax
* @property {BpsPercentRatioPattern3} stochRsi
* @property {BpsPercentRatioPattern3} stochRsiK
* @property {BpsPercentRatioPattern3} stochRsiD
* @property {AverageGainsLossesRsiStochPattern} _1w
* @property {AverageGainsLossesRsiStochPattern} _1m
* @property {AverageGainsLossesRsiStochPattern} _1y
*/
/**
* @typedef {Object} MetricsTree_Market_Technical_Macd
* @property {EmaHistogramLineSignalPattern} _24h
* @property {MetricsTree_Market_Technical_Macd_24h} _24h
* @property {MetricsTree_Market_Technical_Macd_1w} _1w
* @property {MetricsTree_Market_Technical_Macd_1m} _1m
* @property {MetricsTree_Market_Technical_Macd_1y} _1y
*/
/**
* @typedef {Object} MetricsTree_Market_Technical_Macd_24h
* @property {MetricPattern1<StoredF32>} emaFast
* @property {MetricPattern1<StoredF32>} emaSlow
* @property {MetricPattern1<StoredF32>} line
* @property {MetricPattern1<StoredF32>} signal
* @property {MetricPattern1<StoredF32>} histogram
*/
/**
* @typedef {Object} MetricsTree_Market_Technical_Macd_1w
* @property {MetricPattern1<StoredF32>} emaFast
@@ -7845,7 +7802,10 @@ class BrkClient extends BrkClientBase {
sma: createMetricPattern1(this, 'price_return_24h_sma_1m'),
sd: createMetricPattern1(this, 'price_return_24h_sd_1m'),
},
_1y: createSdSmaPattern(this, 'price_return_24h'),
_1y: {
sma: createMetricPattern1(this, 'price_return_24h_sma_1y'),
sd: createMetricPattern1(this, 'price_return_24h_sd_1y'),
},
},
},
volatility: {
@@ -7878,16 +7838,8 @@ class BrkClient extends BrkClientBase {
sats: createMetricPattern1(this, 'price_sma_200d_sats'),
bps: createMetricPattern1(this, 'price_sma_200d_ratio_bps'),
ratio: createMetricPattern1(this, 'price_sma_200d_ratio'),
x24: {
usd: createMetricPattern1(this, 'price_sma_200d_x2_4_usd'),
cents: createMetricPattern1(this, 'price_sma_200d_x2_4_cents'),
sats: createMetricPattern1(this, 'price_sma_200d_x2_4_sats'),
},
x08: {
usd: createMetricPattern1(this, 'price_sma_200d_x0_8_usd'),
cents: createMetricPattern1(this, 'price_sma_200d_x0_8_cents'),
sats: createMetricPattern1(this, 'price_sma_200d_x0_8_sats'),
},
x24: createCentsSatsUsdPattern(this, 'price_sma_200d_x2_4'),
x08: createCentsSatsUsdPattern(this, 'price_sma_200d_x0_8'),
},
_350d: {
usd: createMetricPattern1(this, 'price_sma_350d'),
@@ -7895,11 +7847,7 @@ class BrkClient extends BrkClientBase {
sats: createMetricPattern1(this, 'price_sma_350d_sats'),
bps: createMetricPattern1(this, 'price_sma_350d_ratio_bps'),
ratio: createMetricPattern1(this, 'price_sma_350d_ratio'),
x2: {
usd: createMetricPattern1(this, 'price_sma_350d_x2_usd'),
cents: createMetricPattern1(this, 'price_sma_350d_x2_cents'),
sats: createMetricPattern1(this, 'price_sma_350d_x2_sats'),
},
x2: createCentsSatsUsdPattern(this, 'price_sma_350d_x2'),
},
_1y: createBpsCentsRatioSatsUsdPattern(this, 'price_sma_1y'),
_2y: createBpsCentsRatioSatsUsdPattern(this, 'price_sma_2y'),
@@ -7995,49 +7943,22 @@ class BrkClient extends BrkClientBase {
},
technical: {
rsi: {
_24h: createAverageGainsLossesRsiStochPattern(this, 'rsi'),
_1w: {
gains: createMetricPattern1(this, 'rsi_gains_1w'),
losses: createMetricPattern1(this, 'rsi_losses_1w'),
averageGain: createMetricPattern1(this, 'rsi_average_gain_1w'),
averageLoss: createMetricPattern1(this, 'rsi_average_loss_1w'),
rsi: createBpsPercentRatioPattern3(this, 'rsi_1w'),
rsiMin: createBpsPercentRatioPattern3(this, 'rsi_min_1w'),
rsiMax: createBpsPercentRatioPattern3(this, 'rsi_max_1w'),
stochRsi: createBpsPercentRatioPattern3(this, 'rsi_stoch_1w'),
stochRsiK: createBpsPercentRatioPattern3(this, 'rsi_stoch_k_1w'),
stochRsiD: createBpsPercentRatioPattern3(this, 'rsi_stoch_d_1w'),
},
_1m: {
gains: createMetricPattern1(this, 'rsi_gains_1m'),
losses: createMetricPattern1(this, 'rsi_losses_1m'),
averageGain: createMetricPattern1(this, 'rsi_average_gain_1m'),
averageLoss: createMetricPattern1(this, 'rsi_average_loss_1m'),
rsi: createBpsPercentRatioPattern3(this, 'rsi_1m'),
rsiMin: createBpsPercentRatioPattern3(this, 'rsi_min_1m'),
rsiMax: createBpsPercentRatioPattern3(this, 'rsi_max_1m'),
stochRsi: createBpsPercentRatioPattern3(this, 'rsi_stoch_1m'),
stochRsiK: createBpsPercentRatioPattern3(this, 'rsi_stoch_k_1m'),
stochRsiD: createBpsPercentRatioPattern3(this, 'rsi_stoch_d_1m'),
},
_1y: {
gains: createMetricPattern1(this, 'rsi_gains_1y'),
losses: createMetricPattern1(this, 'rsi_losses_1y'),
averageGain: createMetricPattern1(this, 'rsi_average_gain_1y'),
averageLoss: createMetricPattern1(this, 'rsi_average_loss_1y'),
rsi: createBpsPercentRatioPattern3(this, 'rsi_1y'),
rsiMin: createBpsPercentRatioPattern3(this, 'rsi_min_1y'),
rsiMax: createBpsPercentRatioPattern3(this, 'rsi_max_1y'),
stochRsi: createBpsPercentRatioPattern3(this, 'rsi_stoch_1y'),
stochRsiK: createBpsPercentRatioPattern3(this, 'rsi_stoch_k_1y'),
stochRsiD: createBpsPercentRatioPattern3(this, 'rsi_stoch_d_1y'),
},
_24h: createAverageGainsLossesRsiStochPattern(this, 'rsi', '24h'),
_1w: createAverageGainsLossesRsiStochPattern(this, 'rsi', '1w'),
_1m: createAverageGainsLossesRsiStochPattern(this, 'rsi', '1m'),
_1y: createAverageGainsLossesRsiStochPattern(this, 'rsi', '1y'),
},
stochK: createBpsPercentRatioPattern3(this, 'stoch_k'),
stochD: createBpsPercentRatioPattern3(this, 'stoch_d'),
piCycle: createBpsRatioPattern2(this, 'pi_cycle'),
macd: {
_24h: createEmaHistogramLineSignalPattern(this, 'macd'),
_24h: {
emaFast: createMetricPattern1(this, 'macd_ema_fast_24h'),
emaSlow: createMetricPattern1(this, 'macd_ema_slow_24h'),
line: createMetricPattern1(this, 'macd_line_24h'),
signal: createMetricPattern1(this, 'macd_signal_24h'),
histogram: createMetricPattern1(this, 'macd_histogram_24h'),
},
_1w: {
emaFast: createMetricPattern1(this, 'macd_ema_fast_1w'),
emaSlow: createMetricPattern1(this, 'macd_ema_slow_1w'),
+137 -155
View File
@@ -2149,21 +2149,21 @@ class _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, '0sd_4y'))
self.m0_5sd: PriceValuePattern = PriceValuePattern(client, acc)
self.m1_5sd: PriceValuePattern = PriceValuePattern(client, acc)
self.m1sd: PriceValuePattern = PriceValuePattern(client, acc)
self.m2_5sd: PriceValuePattern = PriceValuePattern(client, acc)
self.m2sd: PriceValuePattern = PriceValuePattern(client, acc)
self.m3sd: PriceValuePattern = PriceValuePattern(client, acc)
self.p0_5sd: PriceValuePattern = PriceValuePattern(client, acc)
self.p1_5sd: PriceValuePattern = PriceValuePattern(client, acc)
self.p1sd: PriceValuePattern = PriceValuePattern(client, acc)
self.p2_5sd: PriceValuePattern = PriceValuePattern(client, acc)
self.p2sd: PriceValuePattern = PriceValuePattern(client, acc)
self.p3sd: PriceValuePattern = PriceValuePattern(client, acc)
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'sd_4y'))
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'zscore_4y'))
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, f'0sd{disc}'))
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('m0_5sd', disc))
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('m1_5sd', disc))
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('m1sd', disc))
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('m2_5sd', disc))
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('m2sd', disc))
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('m3sd', disc))
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('p0_5sd', disc))
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('p1_5sd', disc))
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('p1sd', disc))
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('p2_5sd', disc))
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('p2sd', disc))
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, acc, _m('p3sd', disc))
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, f'ratio_sd{disc}'))
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, f'ratio_zscore{disc}'))
class _10y1m1w1y2y3m3y4y5y6m6y8yPattern2:
"""Pattern struct for repeated tree structure."""
@@ -2206,18 +2206,18 @@ class CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.cap: CentsDeltaRelUsdPattern = CentsDeltaRelUsdPattern(client, _m(acc, 'realized_cap'))
self.gross_pnl: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, _m(acc, 'realized_gross_pnl'))
self.investor: LowerPriceUpperPattern = LowerPriceUpperPattern(client, acc)
self.loss: BaseCapitulationCumulativeNegativeRelSumValuePattern = BaseCapitulationCumulativeNegativeRelSumValuePattern(client, acc)
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
self.net_pnl: BaseChangeCumulativeDeltaRelSumPattern = BaseChangeCumulativeDeltaRelSumPattern(client, _m(acc, 'net'))
self.peak_regret: BaseCumulativeRelPattern = BaseCumulativeRelPattern(client, _m(acc, 'realized_peak_regret'))
self.price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern = BpsCentsPercentilesRatioSatsSmaStdUsdPattern(client, _m(acc, 'realized_price'))
self.profit: BaseCumulativeDistributionRelSumValuePattern = BaseCumulativeDistributionRelSumValuePattern(client, acc)
self.profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'realized_profit_to_loss_ratio'))
self.sell_side_risk_ratio: _1m1w1y24hPattern6 = _1m1w1y24hPattern6(client, _m(acc, 'sell_side_risk_ratio'))
self.sopr: AdjustedRatioValuePattern = AdjustedRatioValuePattern(client, acc)
self.cap: CentsDeltaRelUsdPattern = CentsDeltaRelUsdPattern(client, f'{acc}_cap')
self.gross_pnl: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, f'{acc}_gross_pnl')
self.investor: LowerPriceUpperPattern = LowerPriceUpperPattern(client, f'{acc}_investor')
self.loss: BaseCapitulationCumulativeNegativeRelSumValuePattern = BaseCapitulationCumulativeNegativeRelSumValuePattern(client, f'{acc}_loss')
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_mvrv')
self.net_pnl: BaseChangeCumulativeDeltaRelSumPattern = BaseChangeCumulativeDeltaRelSumPattern(client, f'{acc}_net_pnl')
self.peak_regret: BaseCumulativeRelPattern = BaseCumulativeRelPattern(client, f'{acc}_peak_regret')
self.price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern = BpsCentsPercentilesRatioSatsSmaStdUsdPattern(client, f'{acc}_price')
self.profit: BaseCumulativeDistributionRelSumValuePattern = BaseCumulativeDistributionRelSumValuePattern(client, f'{acc}_profit')
self.profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, f'{acc}_profit_to_loss_ratio')
self.sell_side_risk_ratio: _1m1w1y24hPattern6 = _1m1w1y24hPattern6(client, f'{acc}_sell_side_risk_ratio')
self.sopr: AdjustedRatioValuePattern = AdjustedRatioValuePattern(client, f'{acc}_sopr')
class AverageCumulativeMaxMedianMinPct10Pct25Pct75Pct90RollingSumPattern:
"""Pattern struct for repeated tree structure."""
@@ -2258,16 +2258,16 @@ class AverageGainsLossesRsiStochPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.average_gain: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'average_gain_24h'))
self.average_loss: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'average_loss_24h'))
self.gains: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'gains_24h'))
self.losses: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'losses_24h'))
self.rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, '24h'))
self.rsi_max: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'max_24h'))
self.rsi_min: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'min_24h'))
self.stoch_rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'stoch_24h'))
self.stoch_rsi_d: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'stoch_d_24h'))
self.stoch_rsi_k: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'stoch_k_24h'))
self.average_gain: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, f'average_gain_{disc}'))
self.average_loss: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, f'average_loss_{disc}'))
self.gains: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, f'gains_{disc}'))
self.losses: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, f'losses_{disc}'))
self.rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, disc))
self.rsi_max: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'max_{disc}'))
self.rsi_min: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'min_{disc}'))
self.stoch_rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'stoch_{disc}'))
self.stoch_rsi_d: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'stoch_d_{disc}'))
self.stoch_rsi_k: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, f'stoch_k_{disc}'))
class AllP2aP2pk33P2pk65P2pkhP2shP2trP2wpkhP2wshPattern3:
"""Pattern struct for repeated tree structure."""
@@ -2338,7 +2338,7 @@ class BpsCentsPercentilesRatioSatsSmaStdUsdPattern:
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'ratio'))
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, _m(acc, 'sats'))
self.sma: _1m1w1y2y4yAllPattern = _1m1w1y2y4yAllPattern(client, _m(acc, 'ratio_sma'))
self.std_dev: _1y2y4yAllPattern = _1y2y4yAllPattern(client, _m(acc, 'ratio'))
self.std_dev: _1y2y4yAllPattern = _1y2y4yAllPattern(client, acc)
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, acc)
class AverageMaxMedianMinPct10Pct25Pct75Pct90Pattern2(Generic[T]):
@@ -2413,12 +2413,12 @@ class CapLossMvrvNetPriceProfitSoprPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.cap: CentsDeltaUsdPattern = CentsDeltaUsdPattern(client, _m(acc, 'realized_cap'))
self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc)
self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc, '')
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
self.net_pnl: BaseCumulativeDeltaSumPattern = BaseCumulativeDeltaSumPattern(client, _m(acc, 'net_realized_pnl'))
self.price: BpsCentsRatioSatsUsdPattern = BpsCentsRatioSatsUsdPattern(client, _m(acc, 'realized_price'))
self.profit: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, _m(acc, 'realized_profit'))
self.sopr: RatioValuePattern = RatioValuePattern(client, acc)
self.sopr: RatioValuePattern = RatioValuePattern(client, _m(acc, 'sopr_24h'))
class GrossInvestedLossNetNuplProfitSentimentPattern2:
"""Pattern struct for repeated tree structure."""
@@ -2534,12 +2534,12 @@ class Pct1Pct2Pct5Pct95Pct98Pct99Pattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.pct1: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc)
self.pct2: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc)
self.pct5: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc)
self.pct95: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc)
self.pct98: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc)
self.pct99: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc)
self.pct1: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc, 'pct1')
self.pct2: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc, 'pct2')
self.pct5: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc, 'pct5')
self.pct95: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc, 'pct95')
self.pct98: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc, 'pct98')
self.pct99: BpsPriceRatioPattern = BpsPriceRatioPattern(client, acc, 'pct99')
class ActivityOutputsRealizedSupplyUnrealizedPattern:
"""Pattern struct for repeated tree structure."""
@@ -2634,11 +2634,11 @@ class EmaHistogramLineSignalPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.ema_fast: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'ema_fast_24h'))
self.ema_slow: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'ema_slow_24h'))
self.histogram: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'histogram_24h'))
self.line: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'line_24h'))
self.signal: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'signal_24h'))
self.ema_fast: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_ema_fast')
self.ema_slow: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_ema_slow')
self.histogram: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_histogram')
self.line: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_line')
self.signal: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_signal')
class InvestedMaxMinPercentilesSupplyPattern:
"""Pattern struct for repeated tree structure."""
@@ -2658,9 +2658,9 @@ class MvrvNuplRealizedSupplyPattern:
"""Create pattern node with accumulated metric name."""
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'mvrv'))
self.nupl: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'nupl'))
self.realized_cap: AllSthPattern = AllSthPattern(client, acc)
self.realized_cap: AllSthPattern = AllSthPattern(client, _m(acc, 'realized_cap'))
self.realized_price: BpsCentsRatioSatsUsdPattern = BpsCentsRatioSatsUsdPattern(client, _m(acc, 'realized_price'))
self.supply: AllSthPattern2 = AllSthPattern2(client, acc)
self.supply: AllSthPattern2 = AllSthPattern2(client, _m(acc, 'supply'))
class PhsReboundThsPattern:
"""Pattern struct for repeated tree structure."""
@@ -2749,10 +2749,10 @@ class _1y2y4yAllPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self._1y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc)
self._2y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc)
self._4y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc)
self.all: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc)
self._1y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, '1y')
self._2y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, '2y')
self._4y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, '4y')
self.all: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, acc, '')
class AdjustedRatioValuePattern:
"""Pattern struct for repeated tree structure."""
@@ -2779,10 +2779,10 @@ class BaseCumulativeNegativeSumPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'unrealized_loss'))
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'unrealized_loss_cumulative'))
self.negative: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss'))
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, _m(acc, 'unrealized_loss_sum'))
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, disc))
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, f'{disc}_cumulative'))
self.negative: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, f'neg_{disc}'))
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, _m(acc, f'{disc}_sum'))
class BothReactivatedReceivingSendingPattern:
"""Pattern struct for repeated tree structure."""
@@ -2839,7 +2839,7 @@ class LossNetNuplProfitPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc)
self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc, '')
self.net_pnl: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'net_unrealized_pnl'))
self.nupl: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'nupl'))
self.profit: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit'))
@@ -2942,9 +2942,9 @@ class BpsPriceRatioPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.bps: MetricPattern1[BasisPoints32] = MetricPattern1(client, _m(acc, 'ratio_pct99_bps'))
self.price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'pct99'))
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'ratio_pct99'))
self.bps: MetricPattern1[BasisPoints32] = MetricPattern1(client, _m(acc, f'ratio_{disc}_bps'))
self.price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, disc))
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, f'ratio_{disc}'))
class BpsPercentRatioPattern5:
"""Pattern struct for repeated tree structure."""
@@ -3014,7 +3014,7 @@ class LossNuplProfitPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc)
self.loss: BaseCumulativeNegativeSumPattern = BaseCumulativeNegativeSumPattern(client, acc, '')
self.nupl: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'nupl'))
self.profit: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit'))
@@ -3032,9 +3032,9 @@ class RatioValuePattern2:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'asopr'))
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, _m(acc, 'adj_value_created'))
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, _m(acc, 'adj_value_destroyed'))
self.ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, f'{acc}_ratio')
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, f'{acc}_value_created')
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, f'{acc}_value_destroyed')
class RatioValuePattern:
"""Pattern struct for repeated tree structure."""
@@ -3069,7 +3069,7 @@ class AbsoluteRatePattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.absolute: _1m1w1y24hPattern[StoredI64] = _1m1w1y24hPattern(client, acc)
self.rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, acc)
self.rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, _m(acc, 'rate'))
class AbsoluteRatePattern2:
"""Pattern struct for repeated tree structure."""
@@ -3077,7 +3077,7 @@ class AbsoluteRatePattern2:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.absolute: _1m1w1y24hPattern3 = _1m1w1y24hPattern3(client, acc)
self.rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, acc)
self.rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, _m(acc, 'rate'))
class AllSthPattern2:
"""Pattern struct for repeated tree structure."""
@@ -3159,13 +3159,13 @@ class InPattern:
self.in_loss: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'loss'))
self.in_profit: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'profit'))
class PriceValuePattern:
class PriceRatioPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'p3sd_4y'))
self.value: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'ratio_p3sd_4y'))
self.price: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, disc))
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, f'ratio_{disc}'))
class RelPattern:
"""Pattern struct for repeated tree structure."""
@@ -3180,8 +3180,8 @@ class SdSmaPattern:
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'sd_1y'))
self.sma: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'sma_1y'))
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_sd')
self.sma: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_sma')
class ValuePattern:
"""Pattern struct for repeated tree structure."""
@@ -4237,13 +4237,20 @@ class MetricsTree_Market_Returns_Sd24h_1m:
self.sma: MetricPattern1[StoredF32] = MetricPattern1(client, 'price_return_24h_sma_1m')
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'price_return_24h_sd_1m')
class MetricsTree_Market_Returns_Sd24h_1y:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.sma: MetricPattern1[StoredF32] = MetricPattern1(client, 'price_return_24h_sma_1y')
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'price_return_24h_sd_1y')
class MetricsTree_Market_Returns_Sd24h:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self._1w: MetricsTree_Market_Returns_Sd24h_1w = MetricsTree_Market_Returns_Sd24h_1w(client)
self._1m: MetricsTree_Market_Returns_Sd24h_1m = MetricsTree_Market_Returns_Sd24h_1m(client)
self._1y: SdSmaPattern = SdSmaPattern(client, 'price_return_24h')
self._1y: MetricsTree_Market_Returns_Sd24h_1y = MetricsTree_Market_Returns_Sd24h_1y(client)
class MetricsTree_Market_Returns:
"""Metrics tree node."""
@@ -4271,22 +4278,6 @@ class MetricsTree_Market_Range:
self.true_range_sum_2w: MetricPattern1[StoredF32] = MetricPattern1(client, 'price_true_range_sum_2w')
self.choppiness_index_2w: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'price_choppiness_index_2w')
class MetricsTree_Market_MovingAverage_Sma_200d_X24:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, 'price_sma_200d_x2_4_usd')
self.cents: MetricPattern1[Cents] = MetricPattern1(client, 'price_sma_200d_x2_4_cents')
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, 'price_sma_200d_x2_4_sats')
class MetricsTree_Market_MovingAverage_Sma_200d_X08:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, 'price_sma_200d_x0_8_usd')
self.cents: MetricPattern1[Cents] = MetricPattern1(client, 'price_sma_200d_x0_8_cents')
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, 'price_sma_200d_x0_8_sats')
class MetricsTree_Market_MovingAverage_Sma_200d:
"""Metrics tree node."""
@@ -4296,16 +4287,8 @@ class MetricsTree_Market_MovingAverage_Sma_200d:
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, 'price_sma_200d_sats')
self.bps: MetricPattern1[BasisPoints32] = MetricPattern1(client, 'price_sma_200d_ratio_bps')
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, 'price_sma_200d_ratio')
self.x2_4: MetricsTree_Market_MovingAverage_Sma_200d_X24 = MetricsTree_Market_MovingAverage_Sma_200d_X24(client)
self.x0_8: MetricsTree_Market_MovingAverage_Sma_200d_X08 = MetricsTree_Market_MovingAverage_Sma_200d_X08(client)
class MetricsTree_Market_MovingAverage_Sma_350d_X2:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, 'price_sma_350d_x2_usd')
self.cents: MetricPattern1[Cents] = MetricPattern1(client, 'price_sma_350d_x2_cents')
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, 'price_sma_350d_x2_sats')
self.x2_4: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'price_sma_200d_x2_4')
self.x0_8: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'price_sma_200d_x0_8')
class MetricsTree_Market_MovingAverage_Sma_350d:
"""Metrics tree node."""
@@ -4316,7 +4299,7 @@ class MetricsTree_Market_MovingAverage_Sma_350d:
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, 'price_sma_350d_sats')
self.bps: MetricPattern1[BasisPoints32] = MetricPattern1(client, 'price_sma_350d_ratio_bps')
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, 'price_sma_350d_ratio')
self.x2: MetricsTree_Market_MovingAverage_Sma_350d_X2 = MetricsTree_Market_MovingAverage_Sma_350d_X2(client)
self.x2: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'price_sma_350d_x2')
class MetricsTree_Market_MovingAverage_Sma:
"""Metrics tree node."""
@@ -4462,59 +4445,24 @@ class MetricsTree_Market_Dca:
self.period: MetricsTree_Market_Dca_Period = MetricsTree_Market_Dca_Period(client)
self.class_: MetricsTree_Market_Dca_Class = MetricsTree_Market_Dca_Class(client)
class MetricsTree_Market_Technical_Rsi_1w:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.gains: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_gains_1w')
self.losses: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_losses_1w')
self.average_gain: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_average_gain_1w')
self.average_loss: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_average_loss_1w')
self.rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_1w')
self.rsi_min: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_min_1w')
self.rsi_max: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_max_1w')
self.stoch_rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_1w')
self.stoch_rsi_k: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_k_1w')
self.stoch_rsi_d: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_d_1w')
class MetricsTree_Market_Technical_Rsi_1m:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.gains: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_gains_1m')
self.losses: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_losses_1m')
self.average_gain: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_average_gain_1m')
self.average_loss: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_average_loss_1m')
self.rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_1m')
self.rsi_min: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_min_1m')
self.rsi_max: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_max_1m')
self.stoch_rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_1m')
self.stoch_rsi_k: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_k_1m')
self.stoch_rsi_d: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_d_1m')
class MetricsTree_Market_Technical_Rsi_1y:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.gains: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_gains_1y')
self.losses: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_losses_1y')
self.average_gain: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_average_gain_1y')
self.average_loss: MetricPattern1[StoredF32] = MetricPattern1(client, 'rsi_average_loss_1y')
self.rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_1y')
self.rsi_min: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_min_1y')
self.rsi_max: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_max_1y')
self.stoch_rsi: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_1y')
self.stoch_rsi_k: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_k_1y')
self.stoch_rsi_d: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'rsi_stoch_d_1y')
class MetricsTree_Market_Technical_Rsi:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self._24h: AverageGainsLossesRsiStochPattern = AverageGainsLossesRsiStochPattern(client, 'rsi')
self._1w: MetricsTree_Market_Technical_Rsi_1w = MetricsTree_Market_Technical_Rsi_1w(client)
self._1m: MetricsTree_Market_Technical_Rsi_1m = MetricsTree_Market_Technical_Rsi_1m(client)
self._1y: MetricsTree_Market_Technical_Rsi_1y = MetricsTree_Market_Technical_Rsi_1y(client)
self._1w: AverageGainsLossesRsiStochPattern = AverageGainsLossesRsiStochPattern(client, 'rsi')
self._1m: AverageGainsLossesRsiStochPattern = AverageGainsLossesRsiStochPattern(client, 'rsi')
self._1y: AverageGainsLossesRsiStochPattern = AverageGainsLossesRsiStochPattern(client, 'rsi')
class MetricsTree_Market_Technical_Macd_24h:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.ema_fast: MetricPattern1[StoredF32] = MetricPattern1(client, 'macd_ema_fast_24h')
self.ema_slow: MetricPattern1[StoredF32] = MetricPattern1(client, 'macd_ema_slow_24h')
self.line: MetricPattern1[StoredF32] = MetricPattern1(client, 'macd_line_24h')
self.signal: MetricPattern1[StoredF32] = MetricPattern1(client, 'macd_signal_24h')
self.histogram: MetricPattern1[StoredF32] = MetricPattern1(client, 'macd_histogram_24h')
class MetricsTree_Market_Technical_Macd_1w:
"""Metrics tree node."""
@@ -4550,7 +4498,7 @@ class MetricsTree_Market_Technical_Macd:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self._24h: EmaHistogramLineSignalPattern = EmaHistogramLineSignalPattern(client, 'macd')
self._24h: MetricsTree_Market_Technical_Macd_24h = MetricsTree_Market_Technical_Macd_24h(client)
self._1w: MetricsTree_Market_Technical_Macd_1w = MetricsTree_Market_Technical_Macd_1w(client)
self._1m: MetricsTree_Market_Technical_Macd_1m = MetricsTree_Market_Technical_Macd_1m(client)
self._1y: MetricsTree_Market_Technical_Macd_1y = MetricsTree_Market_Technical_Macd_1y(client)
@@ -4827,6 +4775,23 @@ class MetricsTree_Cohorts_Utxo_All_Supply:
self.in_profit: BtcCentsRelSatsUsdPattern2 = BtcCentsRelSatsUsdPattern2(client, 'supply_in_profit')
self.in_loss: BtcCentsRelSatsUsdPattern2 = BtcCentsRelSatsUsdPattern2(client, 'supply_in_loss')
class MetricsTree_Cohorts_Utxo_All_Realized:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.cap: CentsDeltaRelUsdPattern = CentsDeltaRelUsdPattern(client, 'realized_cap')
self.profit: BaseCumulativeDistributionRelSumValuePattern = BaseCumulativeDistributionRelSumValuePattern(client, '')
self.loss: BaseCapitulationCumulativeNegativeRelSumValuePattern = BaseCapitulationCumulativeNegativeRelSumValuePattern(client, '')
self.price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern = BpsCentsPercentilesRatioSatsSmaStdUsdPattern(client, 'realized_price')
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, 'mvrv')
self.sopr: AdjustedRatioValuePattern = AdjustedRatioValuePattern(client, '')
self.net_pnl: BaseChangeCumulativeDeltaRelSumPattern = BaseChangeCumulativeDeltaRelSumPattern(client, 'net')
self.gross_pnl: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, 'realized_gross_pnl')
self.sell_side_risk_ratio: _1m1w1y24hPattern6 = _1m1w1y24hPattern6(client, 'sell_side_risk_ratio')
self.peak_regret: BaseCumulativeRelPattern = BaseCumulativeRelPattern(client, 'realized_peak_regret')
self.investor: LowerPriceUpperPattern = LowerPriceUpperPattern(client, '')
self.profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'realized_profit_to_loss_ratio')
class MetricsTree_Cohorts_Utxo_All_Unrealized_Profit:
"""Metrics tree node."""
@@ -4875,10 +4840,27 @@ class MetricsTree_Cohorts_Utxo_All:
self.supply: MetricsTree_Cohorts_Utxo_All_Supply = MetricsTree_Cohorts_Utxo_All_Supply(client)
self.outputs: UnspentPattern = UnspentPattern(client, 'utxo_count')
self.activity: CoindaysCoinyearsDormancySentPattern = CoindaysCoinyearsDormancySentPattern(client, '')
self.realized: CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern = CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern(client, '')
self.realized: MetricsTree_Cohorts_Utxo_All_Realized = MetricsTree_Cohorts_Utxo_All_Realized(client)
self.cost_basis: InvestedMaxMinPercentilesSupplyPattern = InvestedMaxMinPercentilesSupplyPattern(client, '')
self.unrealized: MetricsTree_Cohorts_Utxo_All_Unrealized = MetricsTree_Cohorts_Utxo_All_Unrealized(client)
class MetricsTree_Cohorts_Utxo_Sth_Realized:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.cap: CentsDeltaRelUsdPattern = CentsDeltaRelUsdPattern(client, 'sth_realized_cap')
self.profit: BaseCumulativeDistributionRelSumValuePattern = BaseCumulativeDistributionRelSumValuePattern(client, 'sth')
self.loss: BaseCapitulationCumulativeNegativeRelSumValuePattern = BaseCapitulationCumulativeNegativeRelSumValuePattern(client, 'sth')
self.price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern = BpsCentsPercentilesRatioSatsSmaStdUsdPattern(client, 'sth_realized_price')
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_mvrv')
self.sopr: AdjustedRatioValuePattern = AdjustedRatioValuePattern(client, 'sth')
self.net_pnl: BaseChangeCumulativeDeltaRelSumPattern = BaseChangeCumulativeDeltaRelSumPattern(client, 'sth_net')
self.gross_pnl: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, 'sth_realized_gross_pnl')
self.sell_side_risk_ratio: _1m1w1y24hPattern6 = _1m1w1y24hPattern6(client, 'sth_sell_side_risk_ratio')
self.peak_regret: BaseCumulativeRelPattern = BaseCumulativeRelPattern(client, 'sth_realized_peak_regret')
self.investor: LowerPriceUpperPattern = LowerPriceUpperPattern(client, 'sth')
self.profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'sth_realized_profit_to_loss_ratio')
class MetricsTree_Cohorts_Utxo_Sth:
"""Metrics tree node."""
@@ -4886,7 +4868,7 @@ class MetricsTree_Cohorts_Utxo_Sth:
self.supply: DeltaHalfInRelTotalPattern2 = DeltaHalfInRelTotalPattern2(client, 'sth_supply')
self.outputs: UnspentPattern = UnspentPattern(client, 'sth_utxo_count')
self.activity: CoindaysCoinyearsDormancySentPattern = CoindaysCoinyearsDormancySentPattern(client, 'sth')
self.realized: CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern = CapGrossInvestorLossMvrvNetPeakPriceProfitSellSoprPattern(client, 'sth')
self.realized: MetricsTree_Cohorts_Utxo_Sth_Realized = MetricsTree_Cohorts_Utxo_Sth_Realized(client)
self.cost_basis: InvestedMaxMinPercentilesSupplyPattern = InvestedMaxMinPercentilesSupplyPattern(client, 'sth')
self.unrealized: GrossInvestedLossNetNuplProfitSentimentPattern2 = GrossInvestedLossNetNuplProfitSentimentPattern2(client, 'sth')
+107 -28
View File
@@ -46,7 +46,10 @@ export function flatMapCohorts(list, fn) {
* @returns {R[]}
*/
export function mapCohortsWithAll(list, all, fn) {
return [...list.map(fn), { ...fn({ ...all, name: "All" }), defaultActive: false }];
return [
...list.map(fn),
{ ...fn({ ...all, name: "All" }), defaultActive: false },
];
}
/**
@@ -60,7 +63,10 @@ export function mapCohortsWithAll(list, all, fn) {
* @returns {R[]}
*/
export function flatMapCohortsWithAll(list, all, fn) {
return [...list.flatMap(fn), ...fn({ ...all, name: "All" }).map((s) => ({ ...s, defaultActive: false }))];
return [
...list.flatMap(fn),
...fn({ ...all, name: "All" }).map((s) => ({ ...s, defaultActive: false })),
];
}
/**
@@ -257,20 +263,32 @@ export function satsBtcUsdFullTree({ pattern, name, title, color }) {
name: "Compare",
title: `${title} Rolling Sum`,
bottom: ROLLING_WINDOWS.flatMap((w) =>
satsBtcUsd({ pattern: pattern.sum[w.key], name: w.name, color: w.color }),
satsBtcUsd({
pattern: pattern.sum[w.key],
name: w.name,
color: w.color,
}),
),
},
...ROLLING_WINDOWS.map((w) => ({
name: w.name,
title: `${title} ${w.name} Rolling Sum`,
bottom: satsBtcUsd({ pattern: pattern.sum[w.key], name: w.name, color: w.color }),
bottom: satsBtcUsd({
pattern: pattern.sum[w.key],
name: w.name,
color: w.color,
}),
})),
],
},
{
name: "Cumulative",
title: `${title} (Total)`,
bottom: satsBtcUsd({ pattern: pattern.cumulative, name: "all-time", color }),
bottom: satsBtcUsd({
pattern: pattern.cumulative,
name: "all-time",
color,
}),
},
];
}
@@ -296,7 +314,12 @@ export function simplePriceRatioTree({ pattern, title, legend, color }) {
title: `${title} Ratio`,
top: [price({ metric: pattern, name: legend, color })],
bottom: [
baseline({ metric: pattern.ratio, name: "Ratio", unit: Unit.ratio, base: 1 }),
baseline({
metric: pattern.ratio,
name: "Ratio",
unit: Unit.ratio,
base: 1,
}),
],
},
];
@@ -312,7 +335,13 @@ export function simplePriceRatioTree({ pattern, title, legend, color }) {
* @param {FetchedPriceSeriesBlueprint[]} [args.priceReferences]
* @returns {PartialOptionsTree}
*/
export function priceRatioPercentilesTree({ pattern, title, legend, color, priceReferences }) {
export function priceRatioPercentilesTree({
pattern,
title,
legend,
color,
priceReferences,
}) {
const p = pattern.percentiles;
const pctUsd = [
{ name: "pct95", prop: p.pct95.price, color: colors.ratioPct._95 },
@@ -338,7 +367,13 @@ export function priceRatioPercentilesTree({ pattern, title, legend, color, price
price({ metric: pattern, name: legend, color }),
...(priceReferences ?? []),
...pctUsd.map(({ name, prop, color }) =>
price({ metric: prop, name, color, defaultActive: false, options: { lineStyle: 1 } }),
price({
metric: prop,
name,
color,
defaultActive: false,
options: { lineStyle: 1 },
}),
),
],
},
@@ -348,13 +383,31 @@ export function priceRatioPercentilesTree({ pattern, title, legend, color, price
top: [
price({ metric: pattern, name: legend, color }),
...pctUsd.map(({ name, prop, color }) =>
price({ metric: prop, name, color, defaultActive: false, options: { lineStyle: 1 } }),
price({
metric: prop,
name,
color,
defaultActive: false,
options: { lineStyle: 1 },
}),
),
],
bottom: [
baseline({ metric: pattern.ratio, name: "Ratio", unit: Unit.ratio, base: 1 }),
baseline({
metric: pattern.ratio,
name: "Ratio",
unit: Unit.ratio,
base: 1,
}),
...pctRatio.map(({ name, prop, color }) =>
line({ metric: prop, name, color, defaultActive: false, unit: Unit.ratio, options: { lineStyle: 1 } }),
line({
metric: prop,
name,
color,
defaultActive: false,
unit: Unit.ratio,
options: { lineStyle: 1 },
}),
),
],
},
@@ -381,7 +434,13 @@ export function groupedSimplePriceRatioTree({ list, title }) {
name: "Ratio",
title: `${title} Ratio`,
bottom: list.map(({ name, color, pattern }) =>
baseline({ metric: pattern.ratio, name, color, unit: Unit.ratio, base: 1 }),
baseline({
metric: pattern.ratio,
name,
color,
unit: Unit.ratio,
base: 1,
}),
),
},
];
@@ -453,10 +512,30 @@ export function percentileMap(ratio) {
*/
export function sdPatterns(ratio) {
return /** @type {const} */ ([
{ nameAddon: "All Time", titleAddon: "", sd: ratio.stdDev.all, smaRatio: ratio.sma.all.ratio },
{ nameAddon: "4y", titleAddon: "4y", sd: ratio.stdDev._4y, smaRatio: ratio.sma._4y.ratio },
{ nameAddon: "2y", titleAddon: "2y", sd: ratio.stdDev._2y, smaRatio: ratio.sma._2y.ratio },
{ nameAddon: "1y", titleAddon: "1y", sd: ratio.stdDev._1y, smaRatio: ratio.sma._1y.ratio },
{
nameAddon: "All Time",
titleAddon: "",
sd: ratio.stdDev.all,
smaRatio: ratio.sma.all.ratio,
},
{
nameAddon: "4y",
titleAddon: "4y",
sd: ratio.stdDev._4y,
smaRatio: ratio.sma._4y.ratio,
},
{
nameAddon: "2y",
titleAddon: "2y",
sd: ratio.stdDev._2y,
smaRatio: ratio.sma._2y.ratio,
},
{
nameAddon: "1y",
titleAddon: "1y",
sd: ratio.stdDev._1y,
smaRatio: ratio.sma._1y.ratio,
},
]);
}
@@ -490,18 +569,18 @@ export function sdBandsUsd(sd) {
export function sdBandsRatio(sd, smaRatio) {
return /** @type {const} */ ([
{ name: "0σ", prop: smaRatio, color: colors.sd._0 },
{ name: "+0.5σ", prop: sd.p05sd.value, color: colors.sd.p05 },
{ name: "0.5σ", prop: sd.m05sd.value, color: colors.sd.m05 },
{ name: "+1σ", prop: sd.p1sd.value, color: colors.sd.p1 },
{ name: "1σ", prop: sd.m1sd.value, color: colors.sd.m1 },
{ name: "+1.5σ", prop: sd.p15sd.value, color: colors.sd.p15 },
{ name: "1.5σ", prop: sd.m15sd.value, color: colors.sd.m15 },
{ name: "+2σ", prop: sd.p2sd.value, color: colors.sd.p2 },
{ name: "2σ", prop: sd.m2sd.value, color: colors.sd.m2 },
{ name: "+2.5σ", prop: sd.p25sd.value, color: colors.sd.p25 },
{ name: "2.5σ", prop: sd.m25sd.value, color: colors.sd.m25 },
{ name: "+3σ", prop: sd.p3sd.value, color: colors.sd.p3 },
{ name: "3σ", prop: sd.m3sd.value, color: colors.sd.m3 },
{ name: "+0.5σ", prop: sd.p05sd.ratio, color: colors.sd.p05 },
{ name: "0.5σ", prop: sd.m05sd.ratio, color: colors.sd.m05 },
{ name: "+1σ", prop: sd.p1sd.ratio, color: colors.sd.p1 },
{ name: "1σ", prop: sd.m1sd.ratio, color: colors.sd.m1 },
{ name: "+1.5σ", prop: sd.p15sd.ratio, color: colors.sd.p15 },
{ name: "1.5σ", prop: sd.m15sd.ratio, color: colors.sd.m15 },
{ name: "+2σ", prop: sd.p2sd.ratio, color: colors.sd.p2 },
{ name: "2σ", prop: sd.m2sd.ratio, color: colors.sd.m2 },
{ name: "+2.5σ", prop: sd.p25sd.ratio, color: colors.sd.p25 },
{ name: "2.5σ", prop: sd.m25sd.ratio, color: colors.sd.m25 },
{ name: "+3σ", prop: sd.p3sd.ratio, color: colors.sd.p3 },
{ name: "3σ", prop: sd.m3sd.ratio, color: colors.sd.m3 },
]);
}