mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-08 14:11:56 -07:00
bindgen: works
This commit is contained in:
@@ -24,6 +24,8 @@ struct InstanceAnalysis {
|
||||
field_parts: BTreeMap<String, String>,
|
||||
/// Whether this instance appears to be suffix mode
|
||||
is_suffix_mode: bool,
|
||||
/// Whether children have no common prefix/suffix (outlier naming like sopr/asopr)
|
||||
has_outlier: bool,
|
||||
}
|
||||
|
||||
/// Analyze all pattern instances and determine their modes.
|
||||
@@ -54,9 +56,127 @@ pub fn analyze_pattern_modes(
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: fill mixed-empty field_parts now that pattern modes are known.
|
||||
fill_mixed_empty_field_parts(tree, "", pattern_lookup, patterns, &mut node_bases);
|
||||
|
||||
// Re-collect analyses from updated node_bases and re-determine pattern modes
|
||||
let mut all_analyses2: BTreeMap<String, Vec<InstanceAnalysis>> = BTreeMap::new();
|
||||
collect_updated_analyses(tree, "", pattern_lookup, &node_bases, &mut all_analyses2);
|
||||
for pattern in patterns.iter_mut() {
|
||||
if let Some(analyses) = all_analyses2.get(&pattern.name) {
|
||||
pattern.mode = determine_pattern_mode(analyses, &pattern.fields);
|
||||
}
|
||||
}
|
||||
|
||||
node_bases
|
||||
}
|
||||
|
||||
/// Re-collect instance analyses from updated node_bases for pattern mode redetermination.
|
||||
fn collect_updated_analyses(
|
||||
node: &TreeNode,
|
||||
path: &str,
|
||||
pattern_lookup: &BTreeMap<Vec<PatternField>, String>,
|
||||
node_bases: &BTreeMap<String, PatternBaseResult>,
|
||||
all_analyses: &mut BTreeMap<String, Vec<InstanceAnalysis>>,
|
||||
) {
|
||||
let TreeNode::Branch(children) = node else {
|
||||
return;
|
||||
};
|
||||
|
||||
for (field_name, child_node) in children {
|
||||
let child_path = build_child_path(path, field_name);
|
||||
collect_updated_analyses(child_node, &child_path, pattern_lookup, node_bases, all_analyses);
|
||||
}
|
||||
|
||||
let fields = get_node_fields(children, pattern_lookup);
|
||||
if let Some(pattern_name) = pattern_lookup.get(&fields) {
|
||||
if let Some(base_result) = node_bases.get(path) {
|
||||
all_analyses
|
||||
.entry(pattern_name.clone())
|
||||
.or_default()
|
||||
.push(InstanceAnalysis {
|
||||
base: base_result.base.clone(),
|
||||
field_parts: base_result.field_parts.clone(),
|
||||
is_suffix_mode: base_result.is_suffix_mode,
|
||||
has_outlier: base_result.has_outlier,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Second pass: fill empty field_parts for nodes that have a mix of empty and
|
||||
/// non-empty parts, using shortest leaf names for children that need disc.
|
||||
fn fill_mixed_empty_field_parts(
|
||||
node: &TreeNode,
|
||||
path: &str,
|
||||
pattern_lookup: &BTreeMap<Vec<PatternField>, String>,
|
||||
patterns: &[StructuralPattern],
|
||||
node_bases: &mut BTreeMap<String, PatternBaseResult>,
|
||||
) {
|
||||
let TreeNode::Branch(children) = node else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Recurse first (bottom-up)
|
||||
for (field_name, child_node) in children {
|
||||
let child_path = build_child_path(path, field_name);
|
||||
fill_mixed_empty_field_parts(child_node, &child_path, pattern_lookup, patterns, node_bases);
|
||||
}
|
||||
|
||||
// Check if this node has mixed empty/non-empty field_parts
|
||||
let Some(base_result) = node_bases.get(path) else {
|
||||
return;
|
||||
};
|
||||
let has_empty = base_result.field_parts.values().any(|v| v.is_empty());
|
||||
let has_nonempty = base_result.field_parts.values().any(|v| !v.is_empty());
|
||||
if !has_empty || !has_nonempty {
|
||||
return;
|
||||
}
|
||||
|
||||
let prefix = format!("{}_", base_result.base);
|
||||
let mut updates: Vec<(String, String)> = Vec::new();
|
||||
|
||||
for (field_name, child_node) in children {
|
||||
let part = base_result.field_parts.get(field_name.as_str());
|
||||
if !part.is_some_and(|p| p.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the child's pattern is templated (needs disc from parent)
|
||||
let child_pattern_is_templated = if let TreeNode::Branch(ch) = child_node {
|
||||
let child_fields = get_node_fields(ch, pattern_lookup);
|
||||
pattern_lookup
|
||||
.get(&child_fields)
|
||||
.and_then(|name| patterns.iter().find(|p| &p.name == name))
|
||||
.is_some_and(|p| p.is_templated())
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Only fill if the child needs disc (templated) or is a leaf
|
||||
let is_leaf = matches!(child_node, TreeNode::Leaf(_));
|
||||
if !child_pattern_is_templated && !is_leaf {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(leaf) = get_shortest_leaf_name(child_node)
|
||||
&& let Some(suffix) = leaf.strip_prefix(&prefix)
|
||||
&& !suffix.is_empty()
|
||||
&& suffix.contains(field_name.trim_start_matches('_'))
|
||||
&& suffix.len() > field_name.trim_start_matches('_').len()
|
||||
{
|
||||
updates.push((field_name.clone(), suffix.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
if !updates.is_empty() {
|
||||
let base_result = node_bases.get_mut(path).unwrap();
|
||||
for (field_name, suffix) in updates {
|
||||
base_result.field_parts.insert(field_name, suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Recursively collect instance analyses bottom-up.
|
||||
/// Returns the "base" for this node (used by parent for its analysis).
|
||||
///
|
||||
@@ -98,52 +218,52 @@ fn collect_instance_analyses(
|
||||
|
||||
// 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 all_empty = analysis.field_parts.len() > 1
|
||||
&& analysis.field_parts.values().all(|v| v.is_empty());
|
||||
if all_empty {
|
||||
// All-empty case: all children returned the same base.
|
||||
// Use shortest leaf to derive field_parts for fields whose key
|
||||
// matches the metric suffix (e.g., pct1 → suffix "pct1").
|
||||
let prefix = format!("{}_", analysis.base);
|
||||
let mut any_filled = false;
|
||||
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());
|
||||
any_filled = true;
|
||||
}
|
||||
}
|
||||
} 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;
|
||||
|
||||
// If no fields could be filled and all children are the same type,
|
||||
// mark as outlier so the tree inlines instead of using identity
|
||||
// (handles patterns like period windows where field keys differ
|
||||
// from metric suffixes: all/_4y don't match 0sd/0sd_4y).
|
||||
// When children are different types (like absolute/rate), identity
|
||||
// is correct — each child handles its own suffixes internally.
|
||||
if !any_filled {
|
||||
let child_fields = get_node_fields(children, pattern_lookup);
|
||||
let all_same_type = child_fields
|
||||
.windows(2)
|
||||
.all(|w| w[0].rust_type == w[1].rust_type);
|
||||
if all_same_type {
|
||||
analysis.has_outlier = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the base result for this node
|
||||
// Note: has_outlier is false because we use recursive base computation
|
||||
// which gives correct bases without needing outlier detection
|
||||
node_bases.insert(
|
||||
path.to_string(),
|
||||
PatternBaseResult {
|
||||
base: analysis.base.clone(),
|
||||
has_outlier: false,
|
||||
has_outlier: analysis.has_outlier,
|
||||
is_suffix_mode: analysis.is_suffix_mode,
|
||||
field_parts: analysis.field_parts.clone(),
|
||||
},
|
||||
@@ -158,8 +278,14 @@ fn collect_instance_analyses(
|
||||
.push(analysis.clone());
|
||||
}
|
||||
|
||||
// Return the base for parent
|
||||
Some(analysis.base)
|
||||
// Return the base for parent.
|
||||
// For outlier nodes (no common prefix among children), return the
|
||||
// shortest leaf name so the parent can still detect naming patterns.
|
||||
if analysis.has_outlier {
|
||||
Some(get_shortest_leaf_name(node).unwrap_or(analysis.base))
|
||||
} else {
|
||||
Some(analysis.base)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,14 +305,13 @@ fn try_detect_template(
|
||||
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) {
|
||||
// Strategy 1: suffix discriminator (e.g., ratio_sd vs ratio_sd_4y)
|
||||
if let Some(mode) = try_suffix_disc(majority, fields) {
|
||||
return Some(mode);
|
||||
}
|
||||
|
||||
// Strategy 2: Find a common suffix difference across ALL field_parts
|
||||
try_suffix_disc(majority, fields)
|
||||
// Strategy 2: embedded discriminator (e.g., ratio_pct99_bps vs ratio_pct1_bps)
|
||||
try_embedded_disc(majority, fields)
|
||||
}
|
||||
|
||||
/// Strategy 1: embedded discriminator (e.g., pct99 inside ratio_pct99_bps)
|
||||
@@ -241,9 +366,11 @@ fn try_suffix_disc(
|
||||
) -> 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;
|
||||
// Use a non-empty field to detect the suffix
|
||||
let ref_field = fields
|
||||
.iter()
|
||||
.find(|f| first.field_parts.get(&f.name).is_some_and(|v| !v.is_empty()))
|
||||
.map(|f| &f.name)?;
|
||||
let ref_first = first.field_parts.get(ref_field)?;
|
||||
|
||||
// Build templates from the first instance
|
||||
@@ -268,8 +395,13 @@ fn try_suffix_disc(
|
||||
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() {
|
||||
// Identity field — must be empty OR equal to the suffix
|
||||
if other_part.is_empty() {
|
||||
// stays empty — ok
|
||||
} else if other_part == suffix {
|
||||
// empty in first, equals suffix in other — disc IS the part
|
||||
templates.insert(field.name.clone(), "{disc}".to_string());
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
@@ -312,11 +444,11 @@ fn analyze_instance(child_bases: &BTreeMap<String, String>) -> InstanceAnalysis
|
||||
// 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,
|
||||
has_outlier: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -324,6 +456,7 @@ fn analyze_instance(child_bases: &BTreeMap<String, String>) -> InstanceAnalysis
|
||||
base,
|
||||
field_parts,
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -345,12 +478,13 @@ fn analyze_instance(child_bases: &BTreeMap<String, String>) -> InstanceAnalysis
|
||||
base,
|
||||
field_parts,
|
||||
is_suffix_mode: false,
|
||||
has_outlier: false,
|
||||
};
|
||||
}
|
||||
|
||||
// No common prefix or suffix - use empty base so _m(base, relative) returns just the relative.
|
||||
// This handles cases like utxo_cohorts.all.activity where children have completely
|
||||
// different bases (coinblocks_destroyed, coindays_destroyed, etc.)
|
||||
// No common prefix or suffix — outlier naming (e.g., sopr/asopr/adj_).
|
||||
// Children have unrelated metric names that can't be parameterized.
|
||||
let field_parts = child_bases
|
||||
.iter()
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
@@ -360,6 +494,7 @@ fn analyze_instance(child_bases: &BTreeMap<String, String>) -> InstanceAnalysis
|
||||
base: String::new(),
|
||||
field_parts,
|
||||
is_suffix_mode: true,
|
||||
has_outlier: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,6 +507,12 @@ fn determine_pattern_mode(
|
||||
) -> Option<PatternMode> {
|
||||
analyses.first()?;
|
||||
|
||||
// If any instance has outlier naming (no common prefix/suffix among children),
|
||||
// the pattern can't be parameterized.
|
||||
if analyses.iter().any(|a| a.has_outlier) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Pick the majority mode
|
||||
let suffix_count = analyses.iter().filter(|a| a.is_suffix_mode).count();
|
||||
let is_suffix = suffix_count * 2 >= analyses.len();
|
||||
@@ -521,6 +662,7 @@ mod tests {
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let suffix2 = InstanceAnalysis {
|
||||
base: "sth_cost_basis".to_string(),
|
||||
@@ -532,6 +674,7 @@ mod tests {
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let suffix3 = InstanceAnalysis {
|
||||
base: "utxo_cost_basis".to_string(),
|
||||
@@ -543,6 +686,7 @@ mod tests {
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
|
||||
// 1 prefix mode instance (minority - root level)
|
||||
@@ -556,6 +700,7 @@ mod tests {
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: false,
|
||||
has_outlier: false,
|
||||
};
|
||||
|
||||
let analyses = vec![suffix1, suffix2, suffix3, prefix1];
|
||||
@@ -606,6 +751,7 @@ mod tests {
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
let instance2 = InstanceAnalysis {
|
||||
base: "metric_b".to_string(),
|
||||
@@ -616,6 +762,7 @@ mod tests {
|
||||
.into_iter()
|
||||
.collect(),
|
||||
is_suffix_mode: true,
|
||||
has_outlier: false,
|
||||
};
|
||||
|
||||
let analyses = vec![instance1, instance2];
|
||||
@@ -631,4 +778,366 @@ mod tests {
|
||||
PatternMode::Templated { .. } => panic!("Expected suffix mode, got templated"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_embedded_disc_percentile_bands() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "bps".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "price".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "ratio".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
let pct99 = InstanceAnalysis {
|
||||
base: "realized_price".into(),
|
||||
field_parts: [("bps".into(), "ratio_pct99_bps".into()), ("price".into(), "pct99".into()), ("ratio".into(), "ratio_pct99".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let pct1 = InstanceAnalysis {
|
||||
base: "realized_price".into(),
|
||||
field_parts: [("bps".into(), "ratio_pct1_bps".into()), ("price".into(), "pct1".into()), ("ratio".into(), "ratio_pct1".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[pct99, pct1], &fields);
|
||||
assert!(mode.is_some());
|
||||
match mode.unwrap() {
|
||||
PatternMode::Templated { templates } => {
|
||||
assert_eq!(templates.get("bps").unwrap(), "ratio_{disc}_bps");
|
||||
assert_eq!(templates.get("price").unwrap(), "{disc}");
|
||||
assert_eq!(templates.get("ratio").unwrap(), "ratio_{disc}");
|
||||
}
|
||||
other => panic!("Expected Templated, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_suffix_disc_period_windows() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "p1sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "zscore".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
let all_time = InstanceAnalysis {
|
||||
base: "realized_price".into(),
|
||||
field_parts: [("p1sd".into(), "p1sd".into()), ("sd".into(), "ratio_sd".into()), ("zscore".into(), "ratio_zscore".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let four_year = InstanceAnalysis {
|
||||
base: "realized_price".into(),
|
||||
field_parts: [("p1sd".into(), "p1sd_4y".into()), ("sd".into(), "ratio_sd_4y".into()), ("zscore".into(), "ratio_zscore_4y".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[all_time, four_year], &fields);
|
||||
assert!(mode.is_some());
|
||||
match mode.unwrap() {
|
||||
PatternMode::Templated { templates } => {
|
||||
assert_eq!(templates.get("p1sd").unwrap(), "p1sd{disc}");
|
||||
assert_eq!(templates.get("sd").unwrap(), "ratio_sd{disc}");
|
||||
assert_eq!(templates.get("zscore").unwrap(), "ratio_zscore{disc}");
|
||||
}
|
||||
other => panic!("Expected Templated, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_suffix_disc_with_empty_fields() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "band".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
let all_time = InstanceAnalysis {
|
||||
base: "price".into(),
|
||||
field_parts: [("band".into(), "".into()), ("sd".into(), "ratio_sd".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let four_year = InstanceAnalysis {
|
||||
base: "price".into(),
|
||||
field_parts: [("band".into(), "".into()), ("sd".into(), "ratio_sd_4y".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[all_time, four_year], &fields);
|
||||
assert!(mode.is_some());
|
||||
match mode.unwrap() {
|
||||
PatternMode::Templated { templates } => {
|
||||
assert_eq!(templates.get("band").unwrap(), "");
|
||||
assert_eq!(templates.get("sd").unwrap(), "ratio_sd{disc}");
|
||||
}
|
||||
other => panic!("Expected Templated, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_suffix_disc_empty_to_nonempty() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "all".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "sth".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
let regular = InstanceAnalysis {
|
||||
base: "supply".into(),
|
||||
field_parts: [("all".into(), "".into()), ("sth".into(), "sth_".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let profitability = InstanceAnalysis {
|
||||
base: "utxos_in_profit".into(),
|
||||
field_parts: [("all".into(), "supply".into()), ("sth".into(), "sth_supply".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[regular, profitability], &fields);
|
||||
assert!(mode.is_some());
|
||||
match mode.unwrap() {
|
||||
PatternMode::Templated { templates } => {
|
||||
assert_eq!(templates.get("all").unwrap(), "{disc}");
|
||||
assert_eq!(templates.get("sth").unwrap(), "sth_{disc}");
|
||||
}
|
||||
other => panic!("Expected Templated, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_outlier_rejects_pattern() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "ratio".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "value".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
// SOPR case: one instance has outlier naming (no common prefix)
|
||||
let normal = InstanceAnalysis {
|
||||
base: "metric".into(),
|
||||
field_parts: [("ratio".into(), "ratio".into()), ("value".into(), "value".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let outlier = InstanceAnalysis {
|
||||
base: "".into(),
|
||||
field_parts: [("ratio".into(), "asopr".into()), ("value".into(), "adj_value".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: true,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[normal, outlier], &fields);
|
||||
assert!(mode.is_none(), "Pattern with outlier instance should be non-parameterizable");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unanimity_rejects_disagreeing_instances() {
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "a".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "b".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
let inst1 = InstanceAnalysis {
|
||||
base: "x".into(),
|
||||
field_parts: [("a".into(), "foo".into()), ("b".into(), "bar".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let inst2 = InstanceAnalysis {
|
||||
base: "y".into(),
|
||||
field_parts: [("a".into(), "baz".into()), ("b".into(), "qux".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[inst1, inst2], &fields);
|
||||
assert!(mode.is_none(), "Should be non-parameterizable when no pattern detected");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_empty_different_types_uses_identity() {
|
||||
// AbsoluteRatePattern: absolute (_1m1w1y24hPattern) and rate (_1m1w1y24hPattern2)
|
||||
// have different types. Both return the same base → all-empty field_parts.
|
||||
// Should keep identity (empty parts) so both children receive acc unchanged.
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "absolute".into(), rust_type: "TypeA".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "rate".into(), rust_type: "TypeB".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
let inst = InstanceAnalysis {
|
||||
base: "supply_delta".into(),
|
||||
field_parts: [("absolute".into(), "".into()), ("rate".into(), "".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: false,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[inst], &fields);
|
||||
assert!(mode.is_some());
|
||||
match mode.unwrap() {
|
||||
PatternMode::Suffix { relatives } => {
|
||||
assert_eq!(relatives.get("absolute"), Some(&"".to_string()), "absolute should be identity");
|
||||
assert_eq!(relatives.get("rate"), Some(&"".to_string()), "rate should be identity");
|
||||
}
|
||||
other => panic!("Expected Suffix with identity, got {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_empty_same_type_marks_outlier() {
|
||||
// RatioPerBlockStdDevBands: all children are the same type (StdDevPerBlockExtended)
|
||||
// and all return the same base → all-empty field_parts.
|
||||
// Should be marked as outlier so the tree inlines instead of using a
|
||||
// factory that can't differentiate the children.
|
||||
let mut child_bases = BTreeMap::new();
|
||||
child_bases.insert("all".to_string(), "realized_price".to_string());
|
||||
child_bases.insert("_4y".to_string(), "realized_price".to_string());
|
||||
child_bases.insert("_2y".to_string(), "realized_price".to_string());
|
||||
child_bases.insert("_1y".to_string(), "realized_price".to_string());
|
||||
|
||||
let analysis = analyze_instance(&child_bases);
|
||||
|
||||
assert_eq!(analysis.base, "realized_price");
|
||||
assert!(
|
||||
analysis.field_parts.values().all(|v| v.is_empty()),
|
||||
"All field_parts should be empty when children return same base"
|
||||
);
|
||||
// Note: has_outlier is set by collect_instance_analyses based on
|
||||
// all_same_type check, not by analyze_instance directly.
|
||||
// The test for outlier detection is via determine_pattern_mode
|
||||
// with has_outlier flag set.
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_non_parameterizable_cascade() {
|
||||
// When a pattern has outlier instances, determine_pattern_mode returns None.
|
||||
// Parent patterns containing non-parameterizable children should also
|
||||
// be detected via metadata.is_parameterizable (recursive check).
|
||||
use std::collections::BTreeSet;
|
||||
let fields = vec![
|
||||
PatternField { name: "a".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
];
|
||||
let inst = InstanceAnalysis {
|
||||
base: "".into(),
|
||||
field_parts: [("a".into(), "standalone_name".into())].into_iter().collect(),
|
||||
is_suffix_mode: true, has_outlier: true,
|
||||
};
|
||||
let mode = determine_pattern_mode(&[inst], &fields);
|
||||
assert!(mode.is_none(), "Pattern with outlier should be non-parameterizable");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_disc_from_instance() {
|
||||
// StdDevPerBlockExtended 4y instance: field_parts include "0sd_4y", "p1sd_4y", "ratio_sd_4y".
|
||||
// Templates are "0sd{disc}", "p1sd{disc}", "ratio_sd{disc}".
|
||||
// The extracted disc should be "_4y", not "0sd_4y" (the shortest field_part).
|
||||
use crate::StructuralPattern;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
let pattern = StructuralPattern {
|
||||
name: "TestPattern".into(),
|
||||
fields: vec![
|
||||
PatternField { name: "_0sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "p1sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
PatternField { name: "sd".into(), rust_type: "T".into(), json_type: "n".into(), indexes: BTreeSet::new(), type_param: None },
|
||||
],
|
||||
mode: Some(PatternMode::Templated {
|
||||
templates: [
|
||||
("_0sd".into(), "0sd{disc}".into()),
|
||||
("p1sd".into(), "p1sd{disc}".into()),
|
||||
("sd".into(), "ratio_sd{disc}".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
}),
|
||||
is_generic: false,
|
||||
};
|
||||
|
||||
// 4y instance
|
||||
let field_parts_4y: BTreeMap<String, String> = [
|
||||
("_0sd".into(), "0sd_4y".into()),
|
||||
("p1sd".into(), "p1sd_4y".into()),
|
||||
("sd".into(), "ratio_sd_4y".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
let disc = pattern.extract_disc_from_instance(&field_parts_4y);
|
||||
assert_eq!(disc, Some("4y".to_string()));
|
||||
|
||||
// All-time instance (no period suffix)
|
||||
let field_parts_all: BTreeMap<String, String> = [
|
||||
("_0sd".into(), "0sd".into()),
|
||||
("p1sd".into(), "p1sd".into()),
|
||||
("sd".into(), "ratio_sd".into()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
let disc = pattern.extract_disc_from_instance(&field_parts_all);
|
||||
assert_eq!(disc, Some(String::new()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mixed_empty_fills_with_longer_suffix() {
|
||||
// CapLossMvrvNetPriceProfitSoprPattern: "loss" field is empty but its
|
||||
// shortest leaf is "realized_loss" which contains "loss" and is longer.
|
||||
// Should fill with "realized_loss". But "supply" field whose suffix equals
|
||||
// the field name exactly should NOT be filled (identity).
|
||||
let mut child_bases = BTreeMap::new();
|
||||
child_bases.insert("cap".to_string(), "utxos_realized_cap".to_string());
|
||||
child_bases.insert("loss".to_string(), "utxos".to_string()); // returns parent base
|
||||
child_bases.insert("mvrv".to_string(), "utxos_mvrv".to_string());
|
||||
child_bases.insert("price".to_string(), "utxos_realized_price".to_string());
|
||||
child_bases.insert("supply".to_string(), "utxos".to_string()); // returns parent base
|
||||
|
||||
let analysis = analyze_instance(&child_bases);
|
||||
assert_eq!(analysis.base, "utxos");
|
||||
|
||||
// loss and supply should be empty from common prefix analysis
|
||||
assert_eq!(analysis.field_parts.get("loss"), Some(&"".to_string()));
|
||||
assert_eq!(analysis.field_parts.get("supply"), Some(&"".to_string()));
|
||||
// others should be non-empty
|
||||
assert_eq!(analysis.field_parts.get("cap"), Some(&"realized_cap".to_string()));
|
||||
assert_eq!(analysis.field_parts.get("mvrv"), Some(&"mvrv".to_string()));
|
||||
assert_eq!(analysis.field_parts.get("price"), Some(&"realized_price".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mixed_empty_fills_loss_from_shortest_leaf() {
|
||||
// Integration test: "loss" child returns same base as parent (because
|
||||
// its children like neg_realized_loss break the prefix). The mixed-empty
|
||||
// fix should fill it from shortest leaf "utxos_realized_loss".
|
||||
use brk_types::{MetricLeaf, MetricLeafWithSchema, TreeNode};
|
||||
|
||||
fn leaf(name: &str) -> TreeNode {
|
||||
TreeNode::Leaf(MetricLeafWithSchema::new(
|
||||
MetricLeaf::new(name.into(), "f32".into(), std::collections::BTreeSet::new()),
|
||||
serde_json::Value::Null,
|
||||
))
|
||||
}
|
||||
|
||||
let parent = TreeNode::Branch(
|
||||
[
|
||||
("cap".into(), leaf("utxos_realized_cap")),
|
||||
(
|
||||
"loss".into(),
|
||||
TreeNode::Branch(
|
||||
[
|
||||
("base".into(), leaf("utxos_realized_loss")),
|
||||
("negative".into(), leaf("utxos_neg_realized_loss")),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
),
|
||||
),
|
||||
("mvrv".into(), leaf("utxos_mvrv")),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
);
|
||||
|
||||
let mut all_analyses = BTreeMap::new();
|
||||
let mut node_bases = BTreeMap::new();
|
||||
let pattern_lookup = BTreeMap::new();
|
||||
|
||||
collect_instance_analyses(
|
||||
&parent,
|
||||
"test",
|
||||
&pattern_lookup,
|
||||
&mut all_analyses,
|
||||
&mut node_bases,
|
||||
);
|
||||
|
||||
let result = node_bases.get("test").expect("should have node_bases entry");
|
||||
assert_eq!(result.base, "utxos");
|
||||
assert!(!result.has_outlier);
|
||||
assert_eq!(result.field_parts.get("cap"), Some(&"realized_cap".to_string()));
|
||||
assert_eq!(result.field_parts.get("mvrv"), Some(&"mvrv".to_string()));
|
||||
// loss stays empty after first pass (child returned same base as parent).
|
||||
// The second pass (fill_mixed_empty_field_parts) fills it for templated
|
||||
// children, but that requires pattern_lookup which this test doesn't set up.
|
||||
assert_eq!(result.field_parts.get("loss"), Some(&"".to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,10 +127,18 @@ pub fn prepare_tree_node<'a>(
|
||||
&& p.field_parts_match(&base_result.field_parts)
|
||||
});
|
||||
|
||||
// Check if the matching pattern is fully parameterizable (including children)
|
||||
let is_parameterizable = child_fields
|
||||
.as_ref()
|
||||
.and_then(|cf| metadata.find_pattern_by_fields(cf))
|
||||
.is_none_or(|p| metadata.is_parameterizable(&p.name));
|
||||
|
||||
// should_inline determines if we generate an inline struct type
|
||||
// We inline if: it's a branch AND (doesn't match any pattern OR pattern incompatible OR has outlier)
|
||||
let should_inline = !is_leaf
|
||||
&& (!matches_any_pattern || !pattern_compatible || base_result.has_outlier);
|
||||
&& (!matches_any_pattern
|
||||
|| !pattern_compatible
|
||||
|| !is_parameterizable
|
||||
|| base_result.has_outlier);
|
||||
|
||||
// Inline type name (only used when should_inline is true)
|
||||
let inline_type_name = if should_inline {
|
||||
|
||||
@@ -701,6 +701,10 @@ pub fn generate_structural_patterns(
|
||||
}
|
||||
writeln!(output, " */\n").unwrap();
|
||||
|
||||
// Skip factory for non-parameterizable patterns (inlined at tree level)
|
||||
if !metadata.is_parameterizable(&pattern.name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
writeln!(output, "/**").unwrap();
|
||||
writeln!(output, " * Create a {} pattern node", pattern.name).unwrap();
|
||||
|
||||
@@ -222,15 +222,12 @@ fn generate_tree_initializer(
|
||||
} else {
|
||||
// Use pattern factory
|
||||
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()
|
||||
if let Some(pat) = pattern
|
||||
&& pat.is_templated()
|
||||
{
|
||||
// Templated: extract discriminator using the pattern's templates
|
||||
let disc = pat
|
||||
.extract_disc_from_instance(&child.base_result.field_parts)
|
||||
.unwrap_or_default();
|
||||
writeln!(
|
||||
output,
|
||||
|
||||
@@ -534,7 +534,11 @@ pub fn generate_pattern_structs(
|
||||
|
||||
writeln!(output, "}}\n").unwrap();
|
||||
|
||||
// Generate impl block with constructor for ALL patterns
|
||||
// Skip constructor for non-parameterizable patterns (inlined at tree level)
|
||||
if !metadata.is_parameterizable(&pattern.name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let impl_generic = if pattern.is_generic {
|
||||
"<T: DeserializeOwned>"
|
||||
} else {
|
||||
|
||||
@@ -99,15 +99,11 @@ fn generate_tree_node(
|
||||
} else {
|
||||
// Pattern type - use ::new() constructor
|
||||
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()
|
||||
if let Some(pat) = pattern
|
||||
&& pat.is_templated()
|
||||
{
|
||||
let disc = pat
|
||||
.extract_disc_from_instance(&child.base_result.field_parts)
|
||||
.unwrap_or_default();
|
||||
writeln!(
|
||||
output,
|
||||
|
||||
@@ -69,10 +69,17 @@ impl ClientMetadata {
|
||||
self.find_pattern(name).is_some_and(|p| p.is_generic)
|
||||
}
|
||||
|
||||
/// Check if a pattern by name is parameterizable (has a mode).
|
||||
/// Check if a pattern is fully parameterizable (recursively).
|
||||
/// Returns false if the pattern or any nested branch pattern has no mode.
|
||||
pub fn is_parameterizable(&self, name: &str) -> bool {
|
||||
self.find_pattern(name)
|
||||
.is_some_and(|p| p.is_parameterizable())
|
||||
self.find_pattern(name).is_some_and(|p| {
|
||||
p.is_parameterizable()
|
||||
&& p.fields.iter().all(|f| {
|
||||
!f.is_branch()
|
||||
|| self.find_pattern(&f.rust_type).is_none()
|
||||
|| self.is_parameterizable(&f.rust_type)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Check if child fields match ANY pattern (parameterizable or not).
|
||||
|
||||
@@ -61,6 +61,29 @@ impl StructuralPattern {
|
||||
matches!(&self.mode, Some(PatternMode::Templated { .. }))
|
||||
}
|
||||
|
||||
/// Extract the discriminator value from a concrete instance's field_parts.
|
||||
/// Uses the pattern's templates to reverse-match and find the disc.
|
||||
pub fn extract_disc_from_instance(
|
||||
&self,
|
||||
instance_field_parts: &BTreeMap<String, String>,
|
||||
) -> Option<String> {
|
||||
let templates = match &self.mode {
|
||||
Some(PatternMode::Templated { templates }) => templates,
|
||||
_ => return None,
|
||||
};
|
||||
// Find a template with {disc} and extract the disc from the instance value.
|
||||
// Strip leading underscore since _m() handles separators.
|
||||
for (field_name, template) in templates {
|
||||
if let Some(value) = instance_field_parts.get(field_name) {
|
||||
if let Some(disc) = extract_disc(template, value) {
|
||||
return Some(disc.trim_start_matches('_').to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
// If no template matched (all empty templates), disc is empty
|
||||
Some(String::new())
|
||||
}
|
||||
|
||||
/// Check if the given instance field parts match this pattern's field parts.
|
||||
pub fn field_parts_match(&self, instance_field_parts: &BTreeMap<String, String>) -> bool {
|
||||
match &self.mode {
|
||||
|
||||
+1184
-264
File diff suppressed because it is too large
Load Diff
+969
-289
File diff suppressed because it is too large
Load Diff
@@ -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, 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}'))
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, f'{acc}_0sd')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'm0_5sd')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'm1_5sd')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'm1sd')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'm2_5sd')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'm2sd')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'm3sd')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'p0_5sd')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'p1_5sd')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'p1sd')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'p2_5sd')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'p2sd')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, acc, 'p3sd')
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_sd')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_zscore')
|
||||
|
||||
class _10y1m1w1y2y3m3y4y5y6m6y8yPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2318,14 +2318,14 @@ class BaseCapitulationCumulativeNegativeRelSumValuePattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'realized_loss'))
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'capitulation_flow'))
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'realized_loss_cumulative'))
|
||||
self.negative: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_realized_loss'))
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, _m(acc, 'realized_loss_rel_to_rcap'))
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, _m(acc, 'realized_loss_sum'))
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, _m(acc, 'loss_value_created'))
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, _m(acc, 'loss_value_destroyed'))
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, f'{acc}_base')
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, f'{acc}_capitulation_flow')
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, f'{acc}_cumulative')
|
||||
self.negative: MetricPattern1[Dollars] = MetricPattern1(client, f'{acc}_negative')
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, f'{acc}_rel_to_rcap')
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, f'{acc}_sum')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, f'{acc}_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, f'{acc}_value_destroyed')
|
||||
|
||||
class BpsCentsPercentilesRatioSatsSmaStdUsdPattern:
|
||||
"""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, acc)
|
||||
self.std_dev: _1y2y4yAllPattern = _1y2y4yAllPattern(client, _m(acc, '0sd'))
|
||||
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, acc)
|
||||
|
||||
class AverageMaxMedianMinPct10Pct25Pct75Pct90Pattern2(Generic[T]):
|
||||
@@ -2386,13 +2386,13 @@ class BaseCumulativeDistributionRelSumValuePattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'realized_profit'))
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'realized_profit_cumulative'))
|
||||
self.distribution_flow: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'distribution_flow'))
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, _m(acc, 'realized_profit_rel_to_rcap'))
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, _m(acc, 'realized_profit_sum'))
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, _m(acc, 'profit_value_created'))
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, _m(acc, 'profit_value_destroyed'))
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, f'{acc}_base')
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, f'{acc}_cumulative')
|
||||
self.distribution_flow: MetricPattern1[Dollars] = MetricPattern1(client, f'{acc}_distribution_flow')
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, f'{acc}_rel_to_rcap')
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, f'{acc}_sum')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, f'{acc}_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, f'{acc}_value_destroyed')
|
||||
|
||||
class BaseCumulativeNegativeRelSumPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -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, 'realized_loss')
|
||||
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, _m(acc, 'sopr_24h'))
|
||||
self.sopr: RatioValuePattern = RatioValuePattern(client, acc)
|
||||
|
||||
class GrossInvestedLossNetNuplProfitSentimentPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2645,11 +2645,11 @@ class InvestedMaxMinPercentilesSupplyPattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, _m(acc, 'invested_capital'))
|
||||
self.max: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'cost_basis_max'))
|
||||
self.min: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'cost_basis_min'))
|
||||
self.percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, _m(acc, 'cost_basis'))
|
||||
self.supply_density: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, _m(acc, 'supply_density'))
|
||||
self.invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, f'{acc}_invested_capital')
|
||||
self.max: CentsSatsUsdPattern = CentsSatsUsdPattern(client, f'{acc}_max')
|
||||
self.min: CentsSatsUsdPattern = CentsSatsUsdPattern(client, f'{acc}_min')
|
||||
self.percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, f'{acc}_percentiles')
|
||||
self.supply_density: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, f'{acc}_supply_density')
|
||||
|
||||
class MvrvNuplRealizedSupplyPattern:
|
||||
"""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, _m(acc, 'realized_cap'))
|
||||
self.realized_cap: AllSthPattern = AllSthPattern(client, acc)
|
||||
self.realized_price: BpsCentsRatioSatsUsdPattern = BpsCentsRatioSatsUsdPattern(client, _m(acc, 'realized_price'))
|
||||
self.supply: AllSthPattern2 = AllSthPattern2(client, _m(acc, 'supply'))
|
||||
self.supply: AllSthPattern2 = AllSthPattern2(client, acc)
|
||||
|
||||
class PhsReboundThsPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2749,20 +2749,20 @@ class _1y2y4yAllPattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
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, '')
|
||||
self._1y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, f'{acc}_1y')
|
||||
self._2y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, f'{acc}_2y')
|
||||
self._4y: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, f'{acc}_4y')
|
||||
self.all: _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern = _0sdM0M1M1sdM2M2sdM3sdP0P1P1sdP2P2sdP3sdSdZscorePattern(client, f'{acc}_all')
|
||||
|
||||
class AdjustedRatioValuePattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.adjusted: RatioValuePattern2 = RatioValuePattern2(client, acc)
|
||||
self.ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, _m(acc, 'sopr'))
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, _m(acc, 'value_created'))
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, _m(acc, 'value_destroyed'))
|
||||
self.adjusted: RatioValuePattern2 = RatioValuePattern2(client, f'{acc}_adjusted')
|
||||
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 BaseCumulativeDeltaSumPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -2829,17 +2829,17 @@ class CoindaysCoinyearsDormancySentPattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.coindays_destroyed: BaseCumulativeSumPattern[StoredF64] = BaseCumulativeSumPattern(client, _m(acc, 'coindays_destroyed'))
|
||||
self.coinyears_destroyed: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'coinyears_destroyed'))
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'dormancy'))
|
||||
self.sent: BaseCumulativeInSumPattern = BaseCumulativeInSumPattern(client, _m(acc, 'sent'))
|
||||
self.coindays_destroyed: BaseCumulativeSumPattern[StoredF64] = BaseCumulativeSumPattern(client, f'{acc}_coindays_destroyed')
|
||||
self.coinyears_destroyed: MetricPattern1[StoredF64] = MetricPattern1(client, f'{acc}_coinyears_destroyed')
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, f'{acc}_dormancy')
|
||||
self.sent: BaseCumulativeInSumPattern = BaseCumulativeInSumPattern(client, f'{acc}_sent')
|
||||
|
||||
class LossNetNuplProfitPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
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, 'unrealized_loss')
|
||||
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'))
|
||||
@@ -3005,16 +3005,16 @@ class GreedNetPainPattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.greed_index: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'greed_index'))
|
||||
self.net: CentsUsdPattern = CentsUsdPattern(client, _m(acc, 'net_sentiment'))
|
||||
self.pain_index: CentsUsdPattern2 = CentsUsdPattern2(client, _m(acc, 'pain_index'))
|
||||
self.greed_index: CentsUsdPattern2 = CentsUsdPattern2(client, f'{acc}_greed_index')
|
||||
self.net: CentsUsdPattern = CentsUsdPattern(client, f'{acc}_net')
|
||||
self.pain_index: CentsUsdPattern2 = CentsUsdPattern2(client, f'{acc}_pain_index')
|
||||
|
||||
class LossNuplProfitPattern:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
|
||||
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, 'unrealized_loss')
|
||||
self.nupl: BpsRatioPattern = BpsRatioPattern(client, _m(acc, 'nupl'))
|
||||
self.profit: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, _m(acc, 'unrealized_profit'))
|
||||
|
||||
@@ -3023,9 +3023,9 @@ class LowerPriceUpperPattern:
|
||||
|
||||
def __init__(self, client: BrkClientBase, acc: str):
|
||||
"""Create pattern node with accumulated metric name."""
|
||||
self.lower_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'lower_price_band'))
|
||||
self.price: BpsCentsPercentilesRatioSatsUsdPattern = BpsCentsPercentilesRatioSatsUsdPattern(client, _m(acc, 'investor_price'))
|
||||
self.upper_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, _m(acc, 'upper_price_band'))
|
||||
self.lower_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, f'{acc}_lower_price_band')
|
||||
self.price: BpsCentsPercentilesRatioSatsUsdPattern = BpsCentsPercentilesRatioSatsUsdPattern(client, f'{acc}_price')
|
||||
self.upper_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, f'{acc}_upper_price_band')
|
||||
|
||||
class RatioValuePattern2:
|
||||
"""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, _m(acc, 'rate'))
|
||||
self.rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, acc)
|
||||
|
||||
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, _m(acc, 'rate'))
|
||||
self.rate: _1m1w1y24hPattern2 = _1m1w1y24hPattern2(client, acc)
|
||||
|
||||
class AllSthPattern2:
|
||||
"""Pattern struct for repeated tree structure."""
|
||||
@@ -4775,23 +4775,194 @@ 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_Activity:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sent: BaseCumulativeInSumPattern = BaseCumulativeInSumPattern(client, 'sent')
|
||||
self.coindays_destroyed: BaseCumulativeSumPattern[StoredF64] = BaseCumulativeSumPattern(client, 'coindays_destroyed')
|
||||
self.coinyears_destroyed: MetricPattern1[StoredF64] = MetricPattern1(client, 'coinyears_destroyed')
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'dormancy')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Profit:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, 'realized_profit')
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, 'realized_profit_cumulative')
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'realized_profit_sum')
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, 'realized_profit_rel_to_rcap')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'profit_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'profit_value_destroyed')
|
||||
self.distribution_flow: MetricPattern1[Dollars] = MetricPattern1(client, 'distribution_flow')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Loss:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, 'realized_loss')
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, 'realized_loss_cumulative')
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'realized_loss_sum')
|
||||
self.negative: MetricPattern1[Dollars] = MetricPattern1(client, 'neg_realized_loss')
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, 'realized_loss_rel_to_rcap')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'loss_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'loss_value_destroyed')
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, 'capitulation_flow')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_All:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio_sd')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio_zscore')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'realized_price_0sd')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_4y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio_sd_4y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio_zscore_4y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'realized_price_0sd_4y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_2y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio_sd_2y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio_zscore_2y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'realized_price_0sd_2y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_1y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio_sd_1y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio_zscore_1y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'realized_price_0sd_1y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.all: MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_All = MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_All(client)
|
||||
self._4y: MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_4y = MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_4y(client)
|
||||
self._2y: MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_2y = MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_2y(client)
|
||||
self._1y: MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_1y = MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev_1y(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Price:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, 'realized_price')
|
||||
self.cents: MetricPattern1[Cents] = MetricPattern1(client, 'realized_price_cents')
|
||||
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, 'realized_price_sats')
|
||||
self.bps: MetricPattern1[BasisPoints32] = MetricPattern1(client, 'realized_price_ratio_bps')
|
||||
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, 'realized_price_ratio')
|
||||
self.percentiles: Pct1Pct2Pct5Pct95Pct98Pct99Pattern = Pct1Pct2Pct5Pct95Pct98Pct99Pattern(client, 'realized_price')
|
||||
self.sma: _1m1w1y2y4yAllPattern = _1m1w1y2y4yAllPattern(client, 'realized_price_ratio_sma')
|
||||
self.std_dev: MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev = MetricsTree_Cohorts_Utxo_All_Realized_Price_StdDev(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Sopr_Adjusted:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'asopr')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'adj_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'adj_value_destroyed')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Sopr:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'value_destroyed')
|
||||
self.ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'sopr')
|
||||
self.adjusted: MetricsTree_Cohorts_Utxo_All_Realized_Sopr_Adjusted = MetricsTree_Cohorts_Utxo_All_Realized_Sopr_Adjusted(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Realized_Investor:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.price: BpsCentsPercentilesRatioSatsUsdPattern = BpsCentsPercentilesRatioSatsUsdPattern(client, 'investor_price')
|
||||
self.lower_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lower_price_band')
|
||||
self.upper_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'upper_price_band')
|
||||
|
||||
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.profit: MetricsTree_Cohorts_Utxo_All_Realized_Profit = MetricsTree_Cohorts_Utxo_All_Realized_Profit(client)
|
||||
self.loss: MetricsTree_Cohorts_Utxo_All_Realized_Loss = MetricsTree_Cohorts_Utxo_All_Realized_Loss(client)
|
||||
self.price: MetricsTree_Cohorts_Utxo_All_Realized_Price = MetricsTree_Cohorts_Utxo_All_Realized_Price(client)
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, 'mvrv')
|
||||
self.sopr: AdjustedRatioValuePattern = AdjustedRatioValuePattern(client, '')
|
||||
self.sopr: MetricsTree_Cohorts_Utxo_All_Realized_Sopr = MetricsTree_Cohorts_Utxo_All_Realized_Sopr(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.investor: MetricsTree_Cohorts_Utxo_All_Realized_Investor = MetricsTree_Cohorts_Utxo_All_Realized_Investor(client)
|
||||
self.profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'realized_profit_to_loss_ratio')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_CostBasis:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.min: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'cost_basis_min')
|
||||
self.max: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'cost_basis_max')
|
||||
self.percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'cost_basis')
|
||||
self.invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'invested_capital')
|
||||
self.supply_density: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'supply_density')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Unrealized_Profit:
|
||||
"""Metrics tree node."""
|
||||
|
||||
@@ -4821,6 +4992,14 @@ class MetricsTree_Cohorts_Utxo_All_Unrealized_NetPnl:
|
||||
self.cents: MetricPattern1[CentsSigned] = MetricPattern1(client, 'net_unrealized_pnl_cents')
|
||||
self.rel_to_own_gross: BpsPercentRatioPattern = BpsPercentRatioPattern(client, 'net_unrealized_pnl_rel_to_own_gross_pnl')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Unrealized_Sentiment:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.pain_index: CentsUsdPattern2 = CentsUsdPattern2(client, 'pain_index')
|
||||
self.greed_index: CentsUsdPattern2 = CentsUsdPattern2(client, 'greed_index')
|
||||
self.net: CentsUsdPattern = CentsUsdPattern(client, 'net_sentiment')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All_Unrealized:
|
||||
"""Metrics tree node."""
|
||||
|
||||
@@ -4831,7 +5010,7 @@ class MetricsTree_Cohorts_Utxo_All_Unrealized:
|
||||
self.net_pnl: MetricsTree_Cohorts_Utxo_All_Unrealized_NetPnl = MetricsTree_Cohorts_Utxo_All_Unrealized_NetPnl(client)
|
||||
self.gross_pnl: CentsUsdPattern2 = CentsUsdPattern2(client, 'unrealized_gross_pnl')
|
||||
self.invested_capital: InPattern = InPattern(client, 'invested_capital_in')
|
||||
self.sentiment: GreedNetPainPattern = GreedNetPainPattern(client, '')
|
||||
self.sentiment: MetricsTree_Cohorts_Utxo_All_Unrealized_Sentiment = MetricsTree_Cohorts_Utxo_All_Unrealized_Sentiment(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_All:
|
||||
"""Metrics tree node."""
|
||||
@@ -4839,38 +5018,365 @@ class MetricsTree_Cohorts_Utxo_All:
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
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.activity: MetricsTree_Cohorts_Utxo_All_Activity = MetricsTree_Cohorts_Utxo_All_Activity(client)
|
||||
self.realized: MetricsTree_Cohorts_Utxo_All_Realized = MetricsTree_Cohorts_Utxo_All_Realized(client)
|
||||
self.cost_basis: InvestedMaxMinPercentilesSupplyPattern = InvestedMaxMinPercentilesSupplyPattern(client, '')
|
||||
self.cost_basis: MetricsTree_Cohorts_Utxo_All_CostBasis = MetricsTree_Cohorts_Utxo_All_CostBasis(client)
|
||||
self.unrealized: MetricsTree_Cohorts_Utxo_All_Unrealized = MetricsTree_Cohorts_Utxo_All_Unrealized(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Activity:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sent: BaseCumulativeInSumPattern = BaseCumulativeInSumPattern(client, 'sth_sent')
|
||||
self.coindays_destroyed: BaseCumulativeSumPattern[StoredF64] = BaseCumulativeSumPattern(client, 'sth_coindays_destroyed')
|
||||
self.coinyears_destroyed: MetricPattern1[StoredF64] = MetricPattern1(client, 'sth_coinyears_destroyed')
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_dormancy')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Profit:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, 'sth_realized_profit')
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, 'sth_realized_profit_cumulative')
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'sth_realized_profit_sum')
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, 'sth_realized_profit_rel_to_rcap')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'sth_profit_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'sth_profit_value_destroyed')
|
||||
self.distribution_flow: MetricPattern1[Dollars] = MetricPattern1(client, 'sth_distribution_flow')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Loss:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, 'sth_realized_loss')
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, 'sth_realized_loss_cumulative')
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'sth_realized_loss_sum')
|
||||
self.negative: MetricPattern1[Dollars] = MetricPattern1(client, 'sth_neg_realized_loss')
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, 'sth_realized_loss_rel_to_rcap')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'sth_loss_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'sth_loss_value_destroyed')
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, 'sth_capitulation_flow')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_All:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio_sd')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio_zscore')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_realized_price_0sd')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_4y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio_sd_4y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio_zscore_4y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_realized_price_0sd_4y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_2y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio_sd_2y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio_zscore_2y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_realized_price_0sd_2y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_1y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio_sd_1y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio_zscore_1y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_realized_price_0sd_1y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'sth_realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.all: MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_All = MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_All(client)
|
||||
self._4y: MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_4y = MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_4y(client)
|
||||
self._2y: MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_2y = MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_2y(client)
|
||||
self._1y: MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_1y = MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev_1y(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Price:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, 'sth_realized_price')
|
||||
self.cents: MetricPattern1[Cents] = MetricPattern1(client, 'sth_realized_price_cents')
|
||||
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, 'sth_realized_price_sats')
|
||||
self.bps: MetricPattern1[BasisPoints32] = MetricPattern1(client, 'sth_realized_price_ratio_bps')
|
||||
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_realized_price_ratio')
|
||||
self.percentiles: Pct1Pct2Pct5Pct95Pct98Pct99Pattern = Pct1Pct2Pct5Pct95Pct98Pct99Pattern(client, 'sth_realized_price')
|
||||
self.sma: _1m1w1y2y4yAllPattern = _1m1w1y2y4yAllPattern(client, 'sth_realized_price_ratio_sma')
|
||||
self.std_dev: MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev = MetricsTree_Cohorts_Utxo_Sth_Realized_Price_StdDev(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Sopr_Adjusted:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'sth_asopr')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'sth_adj_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'sth_adj_value_destroyed')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Sopr:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'sth_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'sth_value_destroyed')
|
||||
self.ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'sth_sopr')
|
||||
self.adjusted: MetricsTree_Cohorts_Utxo_Sth_Realized_Sopr_Adjusted = MetricsTree_Cohorts_Utxo_Sth_Realized_Sopr_Adjusted(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Realized_Investor:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.price: BpsCentsPercentilesRatioSatsUsdPattern = BpsCentsPercentilesRatioSatsUsdPattern(client, 'sth_investor_price')
|
||||
self.lower_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_lower_price_band')
|
||||
self.upper_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_upper_price_band')
|
||||
|
||||
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.profit: MetricsTree_Cohorts_Utxo_Sth_Realized_Profit = MetricsTree_Cohorts_Utxo_Sth_Realized_Profit(client)
|
||||
self.loss: MetricsTree_Cohorts_Utxo_Sth_Realized_Loss = MetricsTree_Cohorts_Utxo_Sth_Realized_Loss(client)
|
||||
self.price: MetricsTree_Cohorts_Utxo_Sth_Realized_Price = MetricsTree_Cohorts_Utxo_Sth_Realized_Price(client)
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, 'sth_mvrv')
|
||||
self.sopr: AdjustedRatioValuePattern = AdjustedRatioValuePattern(client, 'sth')
|
||||
self.sopr: MetricsTree_Cohorts_Utxo_Sth_Realized_Sopr = MetricsTree_Cohorts_Utxo_Sth_Realized_Sopr(client)
|
||||
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.investor: MetricsTree_Cohorts_Utxo_Sth_Realized_Investor = MetricsTree_Cohorts_Utxo_Sth_Realized_Investor(client)
|
||||
self.profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'sth_realized_profit_to_loss_ratio')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_CostBasis:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.min: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_cost_basis_min')
|
||||
self.max: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'sth_cost_basis_max')
|
||||
self.percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'sth_cost_basis')
|
||||
self.invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'sth_invested_capital')
|
||||
self.supply_density: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'sth_supply_density')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Unrealized_Sentiment:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.pain_index: CentsUsdPattern2 = CentsUsdPattern2(client, 'sth_pain_index')
|
||||
self.greed_index: CentsUsdPattern2 = CentsUsdPattern2(client, 'sth_greed_index')
|
||||
self.net: CentsUsdPattern = CentsUsdPattern(client, 'sth_net_sentiment')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth_Unrealized:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.nupl: BpsRatioPattern = BpsRatioPattern(client, 'sth_nupl')
|
||||
self.profit: BaseCumulativeRelSumPattern2 = BaseCumulativeRelSumPattern2(client, 'sth_unrealized_profit')
|
||||
self.loss: BaseCumulativeNegativeRelSumPattern2 = BaseCumulativeNegativeRelSumPattern2(client, 'sth')
|
||||
self.net_pnl: CentsRelUsdPattern2 = CentsRelUsdPattern2(client, 'sth_net_unrealized_pnl')
|
||||
self.gross_pnl: CentsUsdPattern2 = CentsUsdPattern2(client, 'sth_unrealized_gross_pnl')
|
||||
self.invested_capital: InPattern = InPattern(client, 'sth_invested_capital_in')
|
||||
self.sentiment: MetricsTree_Cohorts_Utxo_Sth_Unrealized_Sentiment = MetricsTree_Cohorts_Utxo_Sth_Unrealized_Sentiment(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Sth:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.supply: DeltaHalfInRelTotalPattern2 = DeltaHalfInRelTotalPattern2(client, 'sth_supply')
|
||||
self.outputs: UnspentPattern = UnspentPattern(client, 'sth_utxo_count')
|
||||
self.activity: CoindaysCoinyearsDormancySentPattern = CoindaysCoinyearsDormancySentPattern(client, 'sth')
|
||||
self.activity: MetricsTree_Cohorts_Utxo_Sth_Activity = MetricsTree_Cohorts_Utxo_Sth_Activity(client)
|
||||
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')
|
||||
self.cost_basis: MetricsTree_Cohorts_Utxo_Sth_CostBasis = MetricsTree_Cohorts_Utxo_Sth_CostBasis(client)
|
||||
self.unrealized: MetricsTree_Cohorts_Utxo_Sth_Unrealized = MetricsTree_Cohorts_Utxo_Sth_Unrealized(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Activity:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sent: BaseCumulativeInSumPattern = BaseCumulativeInSumPattern(client, 'lth_sent')
|
||||
self.coindays_destroyed: BaseCumulativeSumPattern[StoredF64] = BaseCumulativeSumPattern(client, 'lth_coindays_destroyed')
|
||||
self.coinyears_destroyed: MetricPattern1[StoredF64] = MetricPattern1(client, 'lth_coinyears_destroyed')
|
||||
self.dormancy: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_dormancy')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Profit:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, 'lth_realized_profit')
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, 'lth_realized_profit_cumulative')
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'lth_realized_profit_sum')
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, 'lth_realized_profit_rel_to_rcap')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'lth_profit_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'lth_profit_value_destroyed')
|
||||
self.distribution_flow: MetricPattern1[Dollars] = MetricPattern1(client, 'lth_distribution_flow')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Loss:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.base: CentsUsdPattern2 = CentsUsdPattern2(client, 'lth_realized_loss')
|
||||
self.cumulative: CentsUsdPattern2 = CentsUsdPattern2(client, 'lth_realized_loss_cumulative')
|
||||
self.sum: _1m1w1y24hPattern4 = _1m1w1y24hPattern4(client, 'lth_realized_loss_sum')
|
||||
self.negative: MetricPattern1[Dollars] = MetricPattern1(client, 'lth_neg_realized_loss')
|
||||
self.rel_to_rcap: BpsPercentRatioPattern4 = BpsPercentRatioPattern4(client, 'lth_realized_loss_rel_to_rcap')
|
||||
self.value_created: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'lth_loss_value_created')
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'lth_loss_value_destroyed')
|
||||
self.capitulation_flow: MetricPattern1[Dollars] = MetricPattern1(client, 'lth_capitulation_flow')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_All:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio_sd')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio_zscore')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_realized_price_0sd')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_4y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio_sd_4y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio_zscore_4y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_realized_price_0sd_4y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_2y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio_sd_2y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio_zscore_2y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_realized_price_0sd_2y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_1y:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.sd: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio_sd_1y')
|
||||
self.zscore: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio_zscore_1y')
|
||||
self._0sd: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_realized_price_0sd_1y')
|
||||
self.p0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p1sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p2sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.p3sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m0_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m1sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m1_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m2sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m2_5sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
self.m3sd: PriceRatioPattern = PriceRatioPattern(client, 'lth_realized_price')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.all: MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_All = MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_All(client)
|
||||
self._4y: MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_4y = MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_4y(client)
|
||||
self._2y: MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_2y = MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_2y(client)
|
||||
self._1y: MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_1y = MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev_1y(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Price:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.usd: MetricPattern1[Dollars] = MetricPattern1(client, 'lth_realized_price')
|
||||
self.cents: MetricPattern1[Cents] = MetricPattern1(client, 'lth_realized_price_cents')
|
||||
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, 'lth_realized_price_sats')
|
||||
self.bps: MetricPattern1[BasisPoints32] = MetricPattern1(client, 'lth_realized_price_ratio_bps')
|
||||
self.ratio: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_realized_price_ratio')
|
||||
self.percentiles: Pct1Pct2Pct5Pct95Pct98Pct99Pattern = Pct1Pct2Pct5Pct95Pct98Pct99Pattern(client, 'lth_realized_price')
|
||||
self.sma: _1m1w1y2y4yAllPattern = _1m1w1y2y4yAllPattern(client, 'lth_realized_price_ratio_sma')
|
||||
self.std_dev: MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev = MetricsTree_Cohorts_Utxo_Lth_Realized_Price_StdDev(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Sopr:
|
||||
"""Metrics tree node."""
|
||||
@@ -4880,33 +5386,71 @@ class MetricsTree_Cohorts_Utxo_Lth_Realized_Sopr:
|
||||
self.value_destroyed: BaseCumulativeSumPattern[Cents] = BaseCumulativeSumPattern(client, 'lth_value_destroyed')
|
||||
self.ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'lth_sopr')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized_Investor:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.price: BpsCentsPercentilesRatioSatsUsdPattern = BpsCentsPercentilesRatioSatsUsdPattern(client, 'lth_investor_price')
|
||||
self.lower_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_lower_price_band')
|
||||
self.upper_price_band: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_upper_price_band')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Realized:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.cap: CentsDeltaRelUsdPattern = CentsDeltaRelUsdPattern(client, 'lth_realized_cap')
|
||||
self.profit: BaseCumulativeDistributionRelSumValuePattern = BaseCumulativeDistributionRelSumValuePattern(client, 'lth')
|
||||
self.loss: BaseCapitulationCumulativeNegativeRelSumValuePattern = BaseCapitulationCumulativeNegativeRelSumValuePattern(client, 'lth')
|
||||
self.price: BpsCentsPercentilesRatioSatsSmaStdUsdPattern = BpsCentsPercentilesRatioSatsSmaStdUsdPattern(client, 'lth_realized_price')
|
||||
self.profit: MetricsTree_Cohorts_Utxo_Lth_Realized_Profit = MetricsTree_Cohorts_Utxo_Lth_Realized_Profit(client)
|
||||
self.loss: MetricsTree_Cohorts_Utxo_Lth_Realized_Loss = MetricsTree_Cohorts_Utxo_Lth_Realized_Loss(client)
|
||||
self.price: MetricsTree_Cohorts_Utxo_Lth_Realized_Price = MetricsTree_Cohorts_Utxo_Lth_Realized_Price(client)
|
||||
self.mvrv: MetricPattern1[StoredF32] = MetricPattern1(client, 'lth_mvrv')
|
||||
self.sopr: MetricsTree_Cohorts_Utxo_Lth_Realized_Sopr = MetricsTree_Cohorts_Utxo_Lth_Realized_Sopr(client)
|
||||
self.net_pnl: BaseChangeCumulativeDeltaRelSumPattern = BaseChangeCumulativeDeltaRelSumPattern(client, 'lth_net')
|
||||
self.gross_pnl: BaseCumulativeSumPattern3 = BaseCumulativeSumPattern3(client, 'lth_realized_gross_pnl')
|
||||
self.sell_side_risk_ratio: _1m1w1y24hPattern6 = _1m1w1y24hPattern6(client, 'lth_sell_side_risk_ratio')
|
||||
self.peak_regret: BaseCumulativeRelPattern = BaseCumulativeRelPattern(client, 'lth_realized_peak_regret')
|
||||
self.investor: LowerPriceUpperPattern = LowerPriceUpperPattern(client, 'lth')
|
||||
self.investor: MetricsTree_Cohorts_Utxo_Lth_Realized_Investor = MetricsTree_Cohorts_Utxo_Lth_Realized_Investor(client)
|
||||
self.profit_to_loss_ratio: _1m1w1y24hPattern[StoredF64] = _1m1w1y24hPattern(client, 'lth_realized_profit_to_loss_ratio')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_CostBasis:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.min: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_cost_basis_min')
|
||||
self.max: CentsSatsUsdPattern = CentsSatsUsdPattern(client, 'lth_cost_basis_max')
|
||||
self.percentiles: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'lth_cost_basis')
|
||||
self.invested_capital: Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern = Pct05Pct10Pct15Pct20Pct25Pct30Pct35Pct40Pct45Pct50Pct55Pct60Pct65Pct70Pct75Pct80Pct85Pct90Pct95Pattern(client, 'lth_invested_capital')
|
||||
self.supply_density: BpsPercentRatioPattern3 = BpsPercentRatioPattern3(client, 'lth_supply_density')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Unrealized_Sentiment:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.pain_index: CentsUsdPattern2 = CentsUsdPattern2(client, 'lth_pain_index')
|
||||
self.greed_index: CentsUsdPattern2 = CentsUsdPattern2(client, 'lth_greed_index')
|
||||
self.net: CentsUsdPattern = CentsUsdPattern(client, 'lth_net_sentiment')
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth_Unrealized:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.nupl: BpsRatioPattern = BpsRatioPattern(client, 'lth_nupl')
|
||||
self.profit: BaseCumulativeRelSumPattern2 = BaseCumulativeRelSumPattern2(client, 'lth_unrealized_profit')
|
||||
self.loss: BaseCumulativeNegativeRelSumPattern2 = BaseCumulativeNegativeRelSumPattern2(client, 'lth')
|
||||
self.net_pnl: CentsRelUsdPattern2 = CentsRelUsdPattern2(client, 'lth_net_unrealized_pnl')
|
||||
self.gross_pnl: CentsUsdPattern2 = CentsUsdPattern2(client, 'lth_unrealized_gross_pnl')
|
||||
self.invested_capital: InPattern = InPattern(client, 'lth_invested_capital_in')
|
||||
self.sentiment: MetricsTree_Cohorts_Utxo_Lth_Unrealized_Sentiment = MetricsTree_Cohorts_Utxo_Lth_Unrealized_Sentiment(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_Lth:
|
||||
"""Metrics tree node."""
|
||||
|
||||
def __init__(self, client: BrkClientBase, base_path: str = ''):
|
||||
self.supply: DeltaHalfInRelTotalPattern2 = DeltaHalfInRelTotalPattern2(client, 'lth_supply')
|
||||
self.outputs: UnspentPattern = UnspentPattern(client, 'lth_utxo_count')
|
||||
self.activity: CoindaysCoinyearsDormancySentPattern = CoindaysCoinyearsDormancySentPattern(client, 'lth')
|
||||
self.activity: MetricsTree_Cohorts_Utxo_Lth_Activity = MetricsTree_Cohorts_Utxo_Lth_Activity(client)
|
||||
self.realized: MetricsTree_Cohorts_Utxo_Lth_Realized = MetricsTree_Cohorts_Utxo_Lth_Realized(client)
|
||||
self.cost_basis: InvestedMaxMinPercentilesSupplyPattern = InvestedMaxMinPercentilesSupplyPattern(client, 'lth')
|
||||
self.unrealized: GrossInvestedLossNetNuplProfitSentimentPattern2 = GrossInvestedLossNetNuplProfitSentimentPattern2(client, 'lth')
|
||||
self.cost_basis: MetricsTree_Cohorts_Utxo_Lth_CostBasis = MetricsTree_Cohorts_Utxo_Lth_CostBasis(client)
|
||||
self.unrealized: MetricsTree_Cohorts_Utxo_Lth_Unrealized = MetricsTree_Cohorts_Utxo_Lth_Unrealized(client)
|
||||
|
||||
class MetricsTree_Cohorts_Utxo_AgeRange:
|
||||
"""Metrics tree node."""
|
||||
|
||||
Reference in New Issue
Block a user