bindgen: determinism

This commit is contained in:
nym21
2026-01-27 23:48:19 +01:00
parent 730e83472a
commit fecaf0f400
21 changed files with 787 additions and 739 deletions

View File

@@ -3,7 +3,7 @@
//! This module detects repeating tree structures and analyzes them
//! using the bottom-up name deconstruction algorithm.
use std::collections::{BTreeSet, HashMap};
use std::collections::{BTreeMap, BTreeSet};
use brk_types::{TreeNode, extract_json_type};
@@ -13,25 +13,25 @@ use crate::{PatternBaseResult, PatternField, StructuralPattern, to_pascal_case};
/// Context for pattern detection, holding all intermediate state.
struct PatternContext {
/// Maps field signatures to pattern names
signature_to_pattern: HashMap<Vec<PatternField>, String>,
signature_to_pattern: BTreeMap<Vec<PatternField>, String>,
/// Counts how many times each signature appears
signature_counts: HashMap<Vec<PatternField>, usize>,
signature_counts: BTreeMap<Vec<PatternField>, usize>,
/// Maps normalized signatures to pattern names (for naming consistency)
normalized_to_name: HashMap<Vec<PatternField>, String>,
normalized_to_name: BTreeMap<Vec<PatternField>, String>,
/// Counts pattern name usage (for unique naming)
name_counts: HashMap<String, usize>,
name_counts: BTreeMap<String, usize>,
/// Maps signatures to their child field lists
signature_to_child_fields: HashMap<Vec<PatternField>, Vec<Vec<PatternField>>>,
signature_to_child_fields: BTreeMap<Vec<PatternField>, Vec<Vec<PatternField>>>,
}
impl PatternContext {
fn new() -> Self {
Self {
signature_to_pattern: HashMap::new(),
signature_counts: HashMap::new(),
normalized_to_name: HashMap::new(),
name_counts: HashMap::new(),
signature_to_child_fields: HashMap::new(),
signature_to_pattern: BTreeMap::new(),
signature_counts: BTreeMap::new(),
normalized_to_name: BTreeMap::new(),
name_counts: BTreeMap::new(),
signature_to_child_fields: BTreeMap::new(),
}
}
}
@@ -45,9 +45,9 @@ pub fn detect_structural_patterns(
tree: &TreeNode,
) -> (
Vec<StructuralPattern>,
HashMap<Vec<PatternField>, String>,
HashMap<Vec<PatternField>, String>,
HashMap<String, PatternBaseResult>,
BTreeMap<Vec<PatternField>, String>,
BTreeMap<Vec<PatternField>, String>,
BTreeMap<String, PatternBaseResult>,
) {
let mut ctx = PatternContext::new();
resolve_branch_patterns(tree, "root", &mut ctx);
@@ -90,7 +90,7 @@ pub fn detect_structural_patterns(
patterns.extend(generic_patterns);
// Build pattern lookup for mode analysis (patterns appearing 2+ times)
let mut pattern_lookup: HashMap<Vec<PatternField>, String> = HashMap::new();
let mut pattern_lookup: BTreeMap<Vec<PatternField>, String> = BTreeMap::new();
for (sig, name) in &ctx.signature_to_pattern {
if ctx.signature_counts.get(sig).copied().unwrap_or(0) >= 2 {
pattern_lookup.insert(sig.clone(), name.clone());
@@ -110,29 +110,30 @@ pub fn detect_structural_patterns(
/// Detect generic patterns by grouping signatures by their normalized form.
fn detect_generic_patterns(
signature_to_pattern: &HashMap<Vec<PatternField>, String>,
signature_to_pattern: &BTreeMap<Vec<PatternField>, String>,
) -> (
Vec<StructuralPattern>,
HashMap<Vec<PatternField>, String>,
HashMap<Vec<PatternField>, String>,
BTreeMap<Vec<PatternField>, String>,
BTreeMap<Vec<PatternField>, String>,
) {
let mut normalized_groups: HashMap<
let mut normalized_groups: BTreeMap<
Vec<PatternField>,
Vec<(Vec<PatternField>, String, String)>,
> = HashMap::new();
> = BTreeMap::new();
for (fields, name) in signature_to_pattern {
if let Some((normalized, extracted_type)) = normalize_fields_for_generic(fields) {
normalized_groups
.entry(normalized)
.or_default()
.push((fields.clone(), name.clone(), extracted_type));
normalized_groups.entry(normalized).or_default().push((
fields.clone(),
name.clone(),
extracted_type,
));
}
}
let mut patterns = Vec::new();
let mut pattern_mappings: HashMap<Vec<PatternField>, String> = HashMap::new();
let mut type_mappings: HashMap<Vec<PatternField>, String> = HashMap::new();
let mut pattern_mappings: BTreeMap<Vec<PatternField>, String> = BTreeMap::new();
let mut type_mappings: BTreeMap<Vec<PatternField>, String> = BTreeMap::new();
for (normalized_fields, group) in normalized_groups {
if group.len() >= 2 {
@@ -205,7 +206,10 @@ fn normalize_fields_for_generic(fields: &[PatternField]) -> Option<(Vec<PatternF
// Only proceed if inner types differ from originals (meaning they had wrappers)
// and all inner types are the same
if inner_types.iter().all(|t| t == first_inner)
&& inner_types.iter().zip(leaf_types.iter()).any(|(inner, orig)| inner != *orig)
&& inner_types
.iter()
.zip(leaf_types.iter())
.any(|(inner, orig)| inner != *orig)
{
let normalized = fields
.iter()
@@ -301,7 +305,8 @@ fn resolve_branch_patterns(
.entry(normalized)
.or_insert_with(|| generate_pattern_name(field_name, &mut ctx.name_counts))
.clone();
ctx.signature_to_pattern.insert(fields.clone(), name.clone());
ctx.signature_to_pattern
.insert(fields.clone(), name.clone());
name
};
@@ -329,7 +334,7 @@ fn normalize_fields_for_naming(fields: &[PatternField]) -> Vec<PatternField> {
}
/// Generate a unique pattern name.
fn generate_pattern_name(field_name: &str, name_counts: &mut HashMap<String, usize>) -> String {
fn generate_pattern_name(field_name: &str, name_counts: &mut BTreeMap<String, usize>) -> String {
let pascal = to_pascal_case(field_name);
let sanitized = if pascal.chars().next().is_some_and(|c| c.is_ascii_digit()) {
format!("_{}", pascal)

View File

@@ -4,7 +4,7 @@
//! suffix mode (fields append to acc) or prefix mode (fields prepend to acc),
//! and extracts the field parts (relatives or prefixes) for code generation.
use std::collections::HashMap;
use std::collections::BTreeMap;
use brk_types::TreeNode;
@@ -18,7 +18,7 @@ struct InstanceAnalysis {
base: String,
/// For suffix mode: field -> relative name
/// For prefix mode: field -> prefix
field_parts: HashMap<String, String>,
field_parts: BTreeMap<String, String>,
/// Whether this instance appears to be suffix mode
is_suffix_mode: bool,
}
@@ -34,12 +34,12 @@ struct InstanceAnalysis {
pub fn analyze_pattern_modes(
tree: &TreeNode,
patterns: &mut [StructuralPattern],
pattern_lookup: &HashMap<Vec<PatternField>, String>,
) -> HashMap<String, PatternBaseResult> {
pattern_lookup: &BTreeMap<Vec<PatternField>, String>,
) -> BTreeMap<String, PatternBaseResult> {
// Collect analyses from all instances, keyed by pattern name
let mut all_analyses: HashMap<String, Vec<InstanceAnalysis>> = HashMap::new();
let mut all_analyses: BTreeMap<String, Vec<InstanceAnalysis>> = BTreeMap::new();
// Also collect base results for each node, keyed by tree path
let mut node_bases: HashMap<String, PatternBaseResult> = HashMap::new();
let mut node_bases: BTreeMap<String, PatternBaseResult> = BTreeMap::new();
// Bottom-up traversal
collect_instance_analyses(tree, "", pattern_lookup, &mut all_analyses, &mut node_bases);
@@ -61,9 +61,9 @@ pub fn analyze_pattern_modes(
fn collect_instance_analyses(
node: &TreeNode,
path: &str,
pattern_lookup: &HashMap<Vec<PatternField>, String>,
all_analyses: &mut HashMap<String, Vec<InstanceAnalysis>>,
node_bases: &mut HashMap<String, PatternBaseResult>,
pattern_lookup: &BTreeMap<Vec<PatternField>, String>,
all_analyses: &mut BTreeMap<String, Vec<InstanceAnalysis>>,
node_bases: &mut BTreeMap<String, PatternBaseResult>,
) -> Option<String> {
match node {
TreeNode::Leaf(leaf) => {
@@ -72,7 +72,7 @@ fn collect_instance_analyses(
}
TreeNode::Branch(children) => {
// First, process all children recursively (bottom-up)
let mut child_bases: HashMap<String, String> = HashMap::new();
let mut child_bases: BTreeMap<String, String> = BTreeMap::new();
for (field_name, child_node) in children {
let child_path = build_child_path(path, field_name);
if let Some(base) = collect_instance_analyses(
@@ -122,13 +122,13 @@ fn collect_instance_analyses(
}
/// Analyze a single pattern instance from its child bases.
fn analyze_instance(child_bases: &HashMap<String, String>) -> InstanceAnalysis {
fn analyze_instance(child_bases: &BTreeMap<String, String>) -> InstanceAnalysis {
let bases: Vec<&str> = child_bases.values().map(|s| s.as_str()).collect();
// Try suffix mode first: look for common prefix among children
if let Some(common_prefix) = find_common_prefix(&bases) {
let base = common_prefix.trim_end_matches('_').to_string();
let mut field_parts = HashMap::new();
let mut field_parts = BTreeMap::new();
for (field_name, child_base) in child_bases {
// Relative = child_base with common prefix stripped
@@ -154,7 +154,7 @@ fn analyze_instance(child_bases: &HashMap<String, String>) -> InstanceAnalysis {
// Try prefix mode: look for common suffix among children
if let Some(common_suffix) = find_common_suffix(&bases) {
let base = common_suffix.trim_start_matches('_').to_string();
let mut field_parts = HashMap::new();
let mut field_parts = BTreeMap::new();
for (field_name, child_base) in child_bases {
// Prefix = child_base with common suffix stripped, normalized to end with _
@@ -214,8 +214,8 @@ fn determine_pattern_mode(
}
// Find the most common field_parts within the majority group
// Convert to sorted Vec for comparison since HashMap isn't hashable
let mut parts_counts: HashMap<Vec<(String, String)>, usize> = HashMap::new();
// Convert to sorted Vec for comparison since BTreeMap isn't hashable
let mut parts_counts: BTreeMap<Vec<(String, String)>, usize> = BTreeMap::new();
for analysis in &majority_instances {
let mut sorted: Vec<_> = analysis
.field_parts
@@ -227,7 +227,7 @@ fn determine_pattern_mode(
}
let (best_parts_vec, _count) = parts_counts.into_iter().max_by_key(|(_, count)| *count)?;
let best_parts: HashMap<String, String> = best_parts_vec.into_iter().collect();
let best_parts: BTreeMap<String, String> = best_parts_vec.into_iter().collect();
// Verify all required fields have parts
for field in fields {
@@ -255,7 +255,7 @@ mod tests {
#[test]
fn test_analyze_instance_suffix_mode() {
let mut child_bases = HashMap::new();
let mut child_bases = BTreeMap::new();
child_bases.insert("max".to_string(), "lth_cost_basis_max".to_string());
child_bases.insert("min".to_string(), "lth_cost_basis_min".to_string());
child_bases.insert("percentiles".to_string(), "lth_cost_basis".to_string());
@@ -276,7 +276,7 @@ mod tests {
fn test_analyze_instance_prefix_mode() {
// Period-prefixed metrics like "1y_lump_sum_stack", "1m_lump_sum_stack"
// share a common suffix "_lump_sum_stack" with different period prefixes
let mut child_bases = HashMap::new();
let mut child_bases = BTreeMap::new();
child_bases.insert("_1y".to_string(), "1y_lump_sum_stack".to_string());
child_bases.insert("_1m".to_string(), "1m_lump_sum_stack".to_string());
child_bases.insert("_1w".to_string(), "1w_lump_sum_stack".to_string());
@@ -293,7 +293,7 @@ mod tests {
#[test]
fn test_analyze_instance_root_suffix() {
// At root level with suffix naming convention
let mut child_bases = HashMap::new();
let mut child_bases = BTreeMap::new();
child_bases.insert("max".to_string(), "cost_basis_max".to_string());
child_bases.insert("min".to_string(), "cost_basis_min".to_string());
child_bases.insert("percentiles".to_string(), "cost_basis".to_string());

View File

@@ -3,7 +3,7 @@
//! This module provides utilities for working with the TreeNode structure,
//! including leaf name extraction and index pattern detection.
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::collections::{BTreeMap, BTreeSet};
use brk_types::{Index, TreeNode, extract_json_type};
@@ -28,7 +28,7 @@ fn get_shortest_leaf_name(node: &TreeNode) -> Option<String> {
/// Get the field signature for a branch node's children.
pub fn get_node_fields(
children: &BTreeMap<String, TreeNode>,
pattern_lookup: &HashMap<Vec<PatternField>, String>,
pattern_lookup: &BTreeMap<Vec<PatternField>, String>,
) -> Vec<PatternField> {
let mut fields: Vec<PatternField> = children
.iter()
@@ -117,7 +117,7 @@ pub struct PatternBaseResult {
pub is_suffix_mode: bool,
/// The field parts (suffix in suffix mode, prefix in prefix mode) for each field.
/// Used to check if instance field parts match the pattern's field parts.
pub field_parts: HashMap<String, String>,
pub field_parts: BTreeMap<String, String>,
}
impl PatternBaseResult {
@@ -128,7 +128,7 @@ impl PatternBaseResult {
base: String::new(),
has_outlier: true,
is_suffix_mode: true,
field_parts: HashMap::new(),
field_parts: BTreeMap::new(),
}
}
@@ -139,7 +139,7 @@ impl PatternBaseResult {
base: String::new(),
has_outlier: false,
is_suffix_mode: true,
field_parts: HashMap::new(),
field_parts: BTreeMap::new(),
}
}
}
@@ -200,7 +200,7 @@ struct FindBaseResult {
base: String,
has_outlier: bool,
is_suffix_mode: bool,
field_parts: HashMap<String, String>,
field_parts: BTreeMap<String, String>,
}
/// Try to find a common base from child names using prefix/suffix detection.
@@ -214,7 +214,7 @@ fn try_find_base(
// Try common prefix first (suffix mode)
if let Some(prefix) = find_common_prefix(&leaf_names) {
let base = prefix.trim_end_matches('_').to_string();
let mut field_parts = HashMap::new();
let mut field_parts = BTreeMap::new();
for (field_name, leaf_name) in child_names {
// Compute the suffix part for this field
let suffix = if leaf_name == &base {
@@ -238,7 +238,7 @@ fn try_find_base(
// Try common suffix (prefix mode)
if let Some(suffix) = find_common_suffix(&leaf_names) {
let base = suffix.trim_start_matches('_').to_string();
let mut field_parts = HashMap::new();
let mut field_parts = BTreeMap::new();
for (field_name, leaf_name) in child_names {
// Compute the prefix part for this field, normalized to end with _
let prefix_part = leaf_name
@@ -300,7 +300,7 @@ pub fn infer_accumulated_name(parent_acc: &str, field_name: &str, descendant_lea
pub fn get_fields_with_child_info(
children: &BTreeMap<String, TreeNode>,
parent_name: &str,
pattern_lookup: &HashMap<Vec<PatternField>, String>,
pattern_lookup: &BTreeMap<Vec<PatternField>, String>,
) -> Vec<(PatternField, Option<Vec<PatternField>>)> {
children
.iter()

View File

@@ -1,10 +1,12 @@
//! Shared tree generation helpers.
use std::collections::{HashMap, HashSet};
use std::collections::{BTreeMap, BTreeSet};
use brk_types::TreeNode;
use crate::{ClientMetadata, PatternBaseResult, PatternField, child_type_name, get_fields_with_child_info};
use crate::{
ClientMetadata, PatternBaseResult, PatternField, child_type_name, get_fields_with_child_info,
};
/// Build a child path by appending a child name to a parent path.
/// Uses "/" as separator. If parent is empty, returns just the child name.
@@ -53,9 +55,9 @@ pub fn prepare_tree_node<'a>(
node: &'a TreeNode,
name: &str,
path: &str,
pattern_lookup: &HashMap<Vec<PatternField>, String>,
pattern_lookup: &BTreeMap<Vec<PatternField>, String>,
metadata: &ClientMetadata,
generated: &mut HashSet<String>,
generated: &mut BTreeSet<String>,
) -> Option<TreeNodeContext<'a>> {
let TreeNode::Branch(branch_children) = node else {
return None;
@@ -127,8 +129,8 @@ pub fn prepare_tree_node<'a>(
// 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);
let should_inline = !is_leaf
&& (!matches_any_pattern || !pattern_compatible || base_result.has_outlier);
// Inline type name (only used when should_inline is true)
let inline_type_name = if should_inline {

View File

@@ -11,6 +11,7 @@ use std::{fmt::Write, fs, io, path::Path};
use serde_json::json;
use super::write_if_changed;
use crate::{ClientMetadata, Endpoint, TypeSchemas, VERSION};
/// Generate JavaScript + JSDoc client from metadata and OpenAPI endpoints.
@@ -34,7 +35,7 @@ pub fn generate_javascript_client(
tree::generate_tree_typedefs(&mut output, &metadata.catalog, metadata);
tree::generate_main_client(&mut output, &metadata.catalog, metadata, endpoints);
fs::write(output_path, output)?;
write_if_changed(output_path, &output)?;
// Update package.json version if it exists in the same directory
if let Some(parent) = output_path.parent() {
@@ -59,7 +60,7 @@ fn update_package_json_version(package_json_path: &Path) -> io::Result<()> {
let updated = serde_json::to_string_pretty(&package)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
fs::write(package_json_path, updated + "\n")?;
write_if_changed(package_json_path, &(updated + "\n"))?;
Ok(())
}

View File

@@ -1,6 +1,6 @@
//! JavaScript tree structure generation.
use std::collections::HashSet;
use std::collections::BTreeSet;
use std::fmt::Write;
use brk_types::TreeNode;
@@ -18,7 +18,7 @@ pub fn generate_tree_typedefs(output: &mut String, catalog: &TreeNode, metadata:
writeln!(output, "// Catalog tree typedefs\n").unwrap();
let pattern_lookup = metadata.pattern_lookup();
let mut generated = HashSet::new();
let mut generated = BTreeSet::new();
generate_tree_typedef(
output,
"MetricsTree",
@@ -35,9 +35,9 @@ fn generate_tree_typedef(
name: &str,
path: &str,
node: &TreeNode,
pattern_lookup: &std::collections::HashMap<Vec<PatternField>, String>,
pattern_lookup: &std::collections::BTreeMap<Vec<PatternField>, String>,
metadata: &ClientMetadata,
generated: &mut HashSet<String>,
generated: &mut BTreeSet<String>,
) {
let Some(ctx) = prepare_tree_node(node, name, path, pattern_lookup, metadata, generated) else {
return;
@@ -124,7 +124,7 @@ pub fn generate_main_client(
writeln!(output, " */").unwrap();
writeln!(output, " _buildTree(basePath) {{").unwrap();
writeln!(output, " return {{").unwrap();
let mut generated = HashSet::new();
let mut generated = BTreeSet::new();
generate_tree_initializer(
output,
catalog,
@@ -178,9 +178,9 @@ fn generate_tree_initializer(
name: &str,
path: &str,
indent: usize,
pattern_lookup: &std::collections::HashMap<Vec<PatternField>, String>,
pattern_lookup: &std::collections::BTreeMap<Vec<PatternField>, String>,
metadata: &ClientMetadata,
generated: &mut HashSet<String>,
generated: &mut BTreeSet<String>,
) {
let indent_str = " ".repeat(indent);

View File

@@ -7,7 +7,7 @@
//! - `api.rs` - API method generation
//! - `mod.rs` - Entry point
use std::fmt::Write;
use std::{fmt::Write, fs, io, path::Path};
pub mod javascript;
pub mod python;
@@ -41,3 +41,14 @@ pub fn normalize_return_type(return_type: &str) -> String {
}
result
}
/// Write content to a file only if it differs from existing content.
/// Preserves mtime when unchanged, avoiding unnecessary cargo rebuilds.
pub fn write_if_changed(path: &Path, content: &str) -> io::Result<()> {
if let Ok(existing) = fs::read_to_string(path)
&& existing == content
{
return Ok(());
}
fs::write(path, content)
}

View File

@@ -7,8 +7,9 @@ pub mod client;
pub mod tree;
pub mod types;
use std::{fmt::Write, fs, io, path::Path};
use std::{fmt::Write, io, path::Path};
use super::write_if_changed;
use crate::{ClientMetadata, Endpoint, TypeSchemas};
/// Generate Python client from metadata and OpenAPI endpoints.
@@ -48,7 +49,7 @@ pub fn generate_python_client(
tree::generate_tree_classes(&mut output, &metadata.catalog, metadata);
api::generate_main_client(&mut output, endpoints);
fs::write(output_path, output)?;
write_if_changed(output_path, &output)?;
Ok(())
}

View File

@@ -1,6 +1,6 @@
//! Python tree structure generation.
use std::collections::HashSet;
use std::collections::BTreeSet;
use std::fmt::Write;
use brk_types::TreeNode;
@@ -15,7 +15,7 @@ pub fn generate_tree_classes(output: &mut String, catalog: &TreeNode, metadata:
writeln!(output, "# Metrics tree classes\n").unwrap();
let pattern_lookup = metadata.pattern_lookup();
let mut generated = HashSet::new();
let mut generated = BTreeSet::new();
generate_tree_class(
output,
"MetricsTree",
@@ -33,9 +33,9 @@ fn generate_tree_class(
name: &str,
path: &str,
node: &TreeNode,
pattern_lookup: &std::collections::HashMap<Vec<PatternField>, String>,
pattern_lookup: &std::collections::BTreeMap<Vec<PatternField>, String>,
metadata: &ClientMetadata,
generated: &mut HashSet<String>,
generated: &mut BTreeSet<String>,
) {
let Some(ctx) = prepare_tree_node(node, name, path, pattern_lookup, metadata, generated) else {
return;
@@ -74,7 +74,9 @@ fn generate_tree_class(
if child.is_leaf {
if let TreeNode::Leaf(leaf) = child.node {
generate_leaf_field(output, &syntax, "client", child.name, leaf, metadata, " ");
generate_leaf_field(
output, &syntax, "client", child.name, leaf, metadata, " ",
);
}
} else if child.should_inline {
// Inline class

View File

@@ -1,11 +1,14 @@
//! Python type definitions generation.
use std::collections::{HashMap, HashSet};
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Write;
use serde_json::Value;
use crate::{TypeSchemas, escape_python_keyword, generators::MANUAL_GENERIC_TYPES, get_union_variants, ref_to_type_name};
use crate::{
TypeSchemas, escape_python_keyword, generators::MANUAL_GENERIC_TYPES, get_union_variants,
ref_to_type_name,
};
/// Generate type definitions from schemas.
pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
@@ -32,7 +35,7 @@ pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
// Generate simple type aliases first
// Quote references to TypedDicts since they're defined after
let typed_dict_set: HashSet<_> = typed_dicts.iter().cloned().collect();
let typed_dict_set: BTreeSet<_> = typed_dicts.iter().cloned().collect();
for name in type_aliases {
let schema = &schemas[&name];
let type_desc = schema.get("description").and_then(|d| d.as_str());
@@ -49,7 +52,10 @@ pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
for name in typed_dicts {
let schema = &schemas[&name];
let type_desc = schema.get("description").and_then(|d| d.as_str());
let props = schema.get("properties").and_then(|p| p.as_object()).unwrap();
let props = schema
.get("properties")
.and_then(|p| p.as_object())
.unwrap();
writeln!(output, "class {}(TypedDict):", name).unwrap();
@@ -100,9 +106,9 @@ pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
/// Types that reference other types (via $ref) must be defined after their dependencies.
fn topological_sort_schemas(schemas: &TypeSchemas) -> Vec<String> {
// Build dependency graph
let mut deps: HashMap<String, HashSet<String>> = HashMap::new();
let mut deps: BTreeMap<String, BTreeSet<String>> = BTreeMap::new();
for (name, schema) in schemas {
let mut type_deps = HashSet::new();
let mut type_deps = BTreeSet::new();
collect_schema_refs(schema, &mut type_deps);
// Only keep deps that are in our schemas
type_deps.retain(|d| schemas.contains_key(d));
@@ -110,7 +116,7 @@ fn topological_sort_schemas(schemas: &TypeSchemas) -> Vec<String> {
}
// Kahn's algorithm for topological sort
let mut in_degree: HashMap<String, usize> = HashMap::new();
let mut in_degree: BTreeMap<String, usize> = BTreeMap::new();
for name in schemas.keys() {
in_degree.insert(name.clone(), 0);
}
@@ -148,7 +154,7 @@ fn topological_sort_schemas(schemas: &TypeSchemas) -> Vec<String> {
result.reverse();
// Add any types that weren't processed (e.g., due to circular refs or other edge cases)
let result_set: HashSet<_> = result.iter().cloned().collect();
let result_set: BTreeSet<_> = result.iter().cloned().collect();
let mut missing: Vec<_> = schemas
.keys()
.filter(|k| !result_set.contains(*k))
@@ -161,7 +167,7 @@ fn topological_sort_schemas(schemas: &TypeSchemas) -> Vec<String> {
}
/// Collect all type references ($ref) from a schema
fn collect_schema_refs(schema: &Value, refs: &mut HashSet<String>) {
fn collect_schema_refs(schema: &Value, refs: &mut BTreeSet<String>) {
match schema {
Value::Object(map) => {
if let Some(ref_path) = map.get("$ref").and_then(|r| r.as_str())
@@ -215,7 +221,7 @@ fn json_type_to_python(ty: &str, schema: &Value, current_type: Option<&str>) ->
pub fn schema_to_python_type(
schema: &Value,
current_type: Option<&str>,
quote_types: Option<&HashSet<String>>,
quote_types: Option<&BTreeSet<String>>,
) -> String {
if let Some(all_of) = schema.get("allOf").and_then(|v| v.as_array()) {
for item in all_of {
@@ -230,8 +236,8 @@ pub fn schema_to_python_type(
if let Some(ref_path) = schema.get("$ref").and_then(|r| r.as_str()) {
let type_name = ref_to_type_name(ref_path).unwrap_or("Any");
// Quote self-references or types in quote_types set
let should_quote = current_type == Some(type_name)
|| quote_types.is_some_and(|qt| qt.contains(type_name));
let should_quote =
current_type == Some(type_name) || quote_types.is_some_and(|qt| qt.contains(type_name));
if should_quote {
return format!("\"{}\"", type_name);
}

View File

@@ -7,8 +7,9 @@ pub mod client;
pub mod tree;
mod types;
use std::{fmt::Write, fs, io, path::Path};
use std::{fmt::Write, io, path::Path};
use super::write_if_changed;
use crate::{ClientMetadata, Endpoint};
/// Generate Rust client from metadata and OpenAPI endpoints.
@@ -38,7 +39,7 @@ pub fn generate_rust_client(
tree::generate_tree(&mut output, &metadata.catalog, metadata);
api::generate_main_client(&mut output, endpoints);
fs::write(output_path, output)?;
write_if_changed(output_path, &output)?;
Ok(())
}

View File

@@ -1,6 +1,6 @@
//! Rust tree structure generation.
use std::collections::HashSet;
use std::collections::BTreeSet;
use std::fmt::Write;
use brk_types::TreeNode;
@@ -15,7 +15,7 @@ pub fn generate_tree(output: &mut String, catalog: &TreeNode, metadata: &ClientM
writeln!(output, "// Metrics tree\n").unwrap();
let pattern_lookup = metadata.pattern_lookup();
let mut generated = HashSet::new();
let mut generated = BTreeSet::new();
generate_tree_node(
output,
"MetricsTree",
@@ -32,9 +32,9 @@ fn generate_tree_node(
name: &str,
path: &str,
node: &TreeNode,
pattern_lookup: &std::collections::HashMap<Vec<PatternField>, String>,
pattern_lookup: &std::collections::BTreeMap<Vec<PatternField>, String>,
metadata: &ClientMetadata,
generated: &mut HashSet<String>,
generated: &mut BTreeSet<String>,
) {
let Some(ctx) = prepare_tree_node(node, name, path, pattern_lookup, metadata, generated) else {
return;

View File

@@ -1,6 +1,6 @@
//! Client metadata extracted from brk_query.
use std::collections::{BTreeSet, HashMap};
use std::collections::{BTreeMap, BTreeSet};
use brk_query::Vecs;
use brk_types::{Index, MetricLeafWithSchema};
@@ -18,11 +18,11 @@ pub struct ClientMetadata {
/// Index set patterns - sets of indexes that appear together on metrics
pub index_set_patterns: Vec<IndexSetPattern>,
/// Maps concrete field signatures to pattern names
concrete_to_pattern: HashMap<Vec<PatternField>, String>,
concrete_to_pattern: BTreeMap<Vec<PatternField>, String>,
/// Maps concrete field signatures to their type parameter (for generic patterns)
concrete_to_type_param: HashMap<Vec<PatternField>, String>,
concrete_to_type_param: BTreeMap<Vec<PatternField>, String>,
/// Maps tree paths to their computed PatternBaseResult
node_bases: HashMap<String, PatternBaseResult>,
node_bases: BTreeMap<String, PatternBaseResult>,
}
impl ClientMetadata {
@@ -134,7 +134,7 @@ impl ClientMetadata {
}
/// Build a lookup map from field signatures to pattern names.
pub fn pattern_lookup(&self) -> HashMap<Vec<PatternField>, String> {
pub fn pattern_lookup(&self) -> BTreeMap<Vec<PatternField>, String> {
let mut lookup = self.concrete_to_pattern.clone();
for p in &self.structural_patterns {
lookup.insert(p.fields.clone(), p.name.clone());

View File

@@ -4,7 +4,7 @@
//! - Suffix mode: `_m(acc, relative)` → `acc_relative` or just `relative` if acc empty
//! - Prefix mode: `_p(prefix, acc)` → `prefix_acc` or just `acc` if prefix empty
use std::collections::HashMap;
use std::collections::BTreeMap;
/// How a pattern constructs metric names from the accumulator.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -14,13 +14,13 @@ pub enum PatternMode {
/// Example: `_m("lth", "max_cost_basis")` → `"lth_max_cost_basis"`
Suffix {
/// Maps field name to its relative name (full metric name when acc = "")
relatives: HashMap<String, String>,
relatives: BTreeMap<String, String>,
},
/// Fields prepend their prefix to acc.
/// Formula: `_p(prefix, acc)` → `{prefix}_{acc}` or `{acc}` if prefix empty
/// Example: `_p("cumulative", "lth_realized_loss")` → `"cumulative_lth_realized_loss"`
Prefix {
/// Maps field name to its prefix (empty string for identity)
prefixes: HashMap<String, String>,
prefixes: BTreeMap<String, String>,
},
}

View File

@@ -1,6 +1,6 @@
//! Structural pattern and field types.
use std::collections::{BTreeSet, HashMap};
use std::collections::{BTreeMap, BTreeSet};
use brk_types::Index;
@@ -37,7 +37,9 @@ impl StructuralPattern {
/// Get the field part (relative name or prefix) for a given field.
pub fn get_field_part(&self, field_name: &str) -> Option<&str> {
match &self.mode {
Some(PatternMode::Suffix { relatives }) => relatives.get(field_name).map(|s| s.as_str()),
Some(PatternMode::Suffix { relatives }) => {
relatives.get(field_name).map(|s| s.as_str())
}
Some(PatternMode::Prefix { prefixes }) => prefixes.get(field_name).map(|s| s.as_str()),
None => None,
}
@@ -50,7 +52,7 @@ impl StructuralPattern {
/// Check if the given instance field parts match this pattern's field parts.
/// Returns true if all field parts in the pattern match the instance's field parts.
pub fn field_parts_match(&self, instance_field_parts: &HashMap<String, String>) -> bool {
pub fn field_parts_match(&self, instance_field_parts: &BTreeMap<String, String>) -> bool {
match &self.mode {
Some(PatternMode::Suffix { relatives }) => {
// For each field in the pattern, check if the instance has the same suffix

View File

@@ -1,6 +1,6 @@
//! Tests that verify pattern analysis using the real catalog.
use std::collections::HashSet;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Write;
use brk_bindgen::ClientMetadata;
@@ -26,7 +26,7 @@ fn load_metadata() -> ClientMetadata {
}
/// Collect all leaf metric names from a tree.
fn collect_leaf_names(node: &TreeNode, names: &mut HashSet<String>) {
fn collect_leaf_names(node: &TreeNode, names: &mut BTreeSet<String>) {
match node {
TreeNode::Leaf(leaf) => {
names.insert(leaf.name().to_string());
@@ -63,7 +63,7 @@ fn test_catalog_loads() {
#[test]
fn test_all_leaves_have_names() {
let catalog = load_catalog();
let mut names = HashSet::new();
let mut names = BTreeSet::new();
collect_leaf_names(&catalog, &mut names);
println!("Catalog has {} unique metric names", names.len());
@@ -246,11 +246,11 @@ fn test_parameterizable_patterns_have_mode() {
// Verify all parameterizable patterns have valid modes with all fields
for pattern in &parameterizable {
let mode = pattern.mode.as_ref().unwrap();
let field_names: HashSet<_> = pattern.fields.iter().map(|f| f.name.clone()).collect();
let field_names: BTreeSet<_> = pattern.fields.iter().map(|f| f.name.clone()).collect();
match mode {
brk_bindgen::PatternMode::Suffix { relatives } => {
let mode_fields: HashSet<_> = relatives.keys().cloned().collect();
let mode_fields: BTreeSet<_> = relatives.keys().cloned().collect();
assert_eq!(
field_names, mode_fields,
"Pattern {} suffix mode should have all fields",
@@ -258,7 +258,7 @@ fn test_parameterizable_patterns_have_mode() {
);
}
brk_bindgen::PatternMode::Prefix { prefixes } => {
let mode_fields: HashSet<_> = prefixes.keys().cloned().collect();
let mode_fields: BTreeSet<_> = prefixes.keys().cloned().collect();
assert_eq!(
field_names, mode_fields,
"Pattern {} prefix mode should have all fields",
@@ -333,7 +333,7 @@ fn test_generated_rust_output() {
let metadata = ClientMetadata::from_catalog(catalog.clone());
// Collect all metric names from the catalog
let mut all_metrics = HashSet::new();
let mut all_metrics = BTreeSet::new();
collect_leaf_names(&catalog, &mut all_metrics);
// Generate Rust client output
@@ -416,7 +416,7 @@ fn test_generated_javascript_output() {
let metadata = ClientMetadata::from_catalog(catalog.clone());
// Collect all metric names from the catalog
let mut all_metrics = HashSet::new();
let mut all_metrics = BTreeSet::new();
collect_leaf_names(&catalog, &mut all_metrics);
// Load schemas from OpenAPI spec only (catalog schemas require runtime data)
@@ -507,7 +507,7 @@ fn test_generated_python_output() {
let metadata = ClientMetadata::from_catalog(catalog.clone());
// Collect all metric names from the catalog
let mut all_metrics = HashSet::new();
let mut all_metrics = BTreeSet::new();
collect_leaf_names(&catalog, &mut all_metrics);
// Load schemas from OpenAPI spec only (catalog schemas require runtime data)
@@ -665,8 +665,8 @@ fn test_cost_basis_relatives() {
// For leaves (max, min), the base is the metric name
// For branches (percentiles), the base is the common prefix of its children
let mut child_bases: std::collections::HashMap<String, String> =
std::collections::HashMap::new();
let mut child_bases: std::collections::BTreeMap<String, String> =
std::collections::BTreeMap::new();
for (field, metric) in metrics {
if field.starts_with("percentiles.") {
// This is a percentile metric - compute what the percentiles branch would return
@@ -721,20 +721,20 @@ fn test_debug_cost_basis_pattern2_mode() {
#[derive(Debug, Clone)]
struct DebugInstanceAnalysis {
base: String,
field_parts: std::collections::HashMap<String, String>,
field_parts: std::collections::BTreeMap<String, String>,
is_suffix_mode: bool,
}
fn collect_debug(
node: &TreeNode,
pattern_lookup: &std::collections::HashMap<Vec<brk_bindgen::PatternField>, String>,
all_analyses: &mut std::collections::HashMap<String, Vec<DebugInstanceAnalysis>>,
pattern_lookup: &std::collections::BTreeMap<Vec<brk_bindgen::PatternField>, String>,
all_analyses: &mut std::collections::BTreeMap<String, Vec<DebugInstanceAnalysis>>,
) -> Option<String> {
match node {
TreeNode::Leaf(leaf) => Some(leaf.name().to_string()),
TreeNode::Branch(children) => {
let mut child_bases: std::collections::HashMap<String, String> =
std::collections::HashMap::new();
let mut child_bases: std::collections::BTreeMap<String, String> =
std::collections::BTreeMap::new();
for (field_name, child_node) in children {
if let Some(base) = collect_debug(child_node, pattern_lookup, all_analyses) {
child_bases.insert(field_name.clone(), base);
@@ -750,7 +750,7 @@ fn test_debug_cost_basis_pattern2_mode() {
let (base, field_parts, is_suffix_mode) =
if let Some(common_prefix) = brk_bindgen::find_common_prefix(&bases) {
let base = common_prefix.trim_end_matches('_').to_string();
let mut parts = std::collections::HashMap::new();
let mut parts = std::collections::BTreeMap::new();
for (field_name, child_base) in &child_bases {
let relative = if *child_base == base {
String::new()
@@ -792,8 +792,7 @@ fn test_debug_cost_basis_pattern2_mode() {
}
}
let mut all_analyses: std::collections::HashMap<String, Vec<DebugInstanceAnalysis>> =
std::collections::HashMap::new();
let mut all_analyses: BTreeMap<String, Vec<DebugInstanceAnalysis>> = BTreeMap::new();
collect_debug(&catalog, &pattern_lookup, &mut all_analyses);
if let Some(analyses) = all_analyses.get("CostBasisPattern2") {

View File

@@ -1535,18 +1535,18 @@ impl<T: DeserializeOwned> ClassDaysInLossPattern<T> {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_days_in_profit")),
_2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_days_in_profit")),
_2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_days_in_profit")),
_2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_days_in_profit")),
_2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_days_in_profit")),
_2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_days_in_profit")),
_2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_days_in_profit")),
_2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_days_in_profit")),
_2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_days_in_profit")),
_2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_days_in_profit")),
_2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_days_in_profit")),
_2026: MetricPattern4::new(client.clone(), _m(&acc, "2026_days_in_profit")),
_2015: MetricPattern4::new(client.clone(), _m(&acc, "2015_returns")),
_2016: MetricPattern4::new(client.clone(), _m(&acc, "2016_returns")),
_2017: MetricPattern4::new(client.clone(), _m(&acc, "2017_returns")),
_2018: MetricPattern4::new(client.clone(), _m(&acc, "2018_returns")),
_2019: MetricPattern4::new(client.clone(), _m(&acc, "2019_returns")),
_2020: MetricPattern4::new(client.clone(), _m(&acc, "2020_returns")),
_2021: MetricPattern4::new(client.clone(), _m(&acc, "2021_returns")),
_2022: MetricPattern4::new(client.clone(), _m(&acc, "2022_returns")),
_2023: MetricPattern4::new(client.clone(), _m(&acc, "2023_returns")),
_2024: MetricPattern4::new(client.clone(), _m(&acc, "2024_returns")),
_2025: MetricPattern4::new(client.clone(), _m(&acc, "2025_returns")),
_2026: MetricPattern4::new(client.clone(), _m(&acc, "2026_returns")),
}
}
}
@@ -1619,38 +1619,6 @@ impl<T: DeserializeOwned> DollarsPattern<T> {
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern2 {
pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1<StoredF32>,
pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1<StoredF32>,
pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1<StoredF32>,
pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1<StoredF32>,
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_own_supply: MetricPattern1<StoredF64>,
pub unrealized_loss_rel_to_own_market_cap: MetricPattern1<StoredF32>,
pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1<StoredF32>,
pub unrealized_profit_rel_to_own_market_cap: MetricPattern1<StoredF32>,
pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1<StoredF32>,
}
impl RelativePattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")),
neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")),
net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")),
net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")),
supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")),
supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")),
unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")),
unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")),
unrealized_profit_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")),
unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern {
pub neg_unrealized_loss_rel_to_market_cap: MetricPattern1<StoredF32>,
@@ -1683,6 +1651,38 @@ impl RelativePattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern2 {
pub neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1<StoredF32>,
pub neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1<StoredF32>,
pub net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1<StoredF32>,
pub net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1<StoredF32>,
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_own_supply: MetricPattern1<StoredF64>,
pub unrealized_loss_rel_to_own_market_cap: MetricPattern1<StoredF32>,
pub unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1<StoredF32>,
pub unrealized_profit_rel_to_own_market_cap: MetricPattern1<StoredF32>,
pub unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1<StoredF32>,
}
impl RelativePattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_market_cap")),
neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss_rel_to_own_total_unrealized_pnl")),
net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_market_cap")),
net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl_rel_to_own_total_unrealized_pnl")),
supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_loss_rel_to_own_supply")),
supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "supply_in_profit_rel_to_own_supply")),
unrealized_loss_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_market_cap")),
unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss_rel_to_own_total_unrealized_pnl")),
unrealized_profit_rel_to_own_market_cap: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_market_cap")),
unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit_rel_to_own_total_unrealized_pnl")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CountPattern2<T> {
pub average: MetricPattern1<T>,
@@ -1833,6 +1833,32 @@ impl _0satsPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct PeriodCagrPattern {
pub _10y: MetricPattern4<StoredF32>,
pub _2y: MetricPattern4<StoredF32>,
pub _3y: MetricPattern4<StoredF32>,
pub _4y: MetricPattern4<StoredF32>,
pub _5y: MetricPattern4<StoredF32>,
pub _6y: MetricPattern4<StoredF32>,
pub _8y: MetricPattern4<StoredF32>,
}
impl PeriodCagrPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_10y: MetricPattern4::new(client.clone(), _p("10y", &acc)),
_2y: MetricPattern4::new(client.clone(), _p("2y", &acc)),
_3y: MetricPattern4::new(client.clone(), _p("3y", &acc)),
_4y: MetricPattern4::new(client.clone(), _p("4y", &acc)),
_5y: MetricPattern4::new(client.clone(), _p("5y", &acc)),
_6y: MetricPattern4::new(client.clone(), _p("6y", &acc)),
_8y: MetricPattern4::new(client.clone(), _p("8y", &acc)),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct _100btcPattern {
pub activity: ActivityPattern2,
@@ -1911,58 +1937,6 @@ impl _10yPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct UnrealizedPattern {
pub neg_unrealized_loss: MetricPattern1<Dollars>,
pub net_unrealized_pnl: MetricPattern1<Dollars>,
pub supply_in_loss: ActiveSupplyPattern,
pub supply_in_profit: ActiveSupplyPattern,
pub total_unrealized_pnl: MetricPattern1<Dollars>,
pub unrealized_loss: MetricPattern1<Dollars>,
pub unrealized_profit: MetricPattern1<Dollars>,
}
impl UnrealizedPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
neg_unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")),
net_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl")),
supply_in_loss: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_loss")),
supply_in_profit: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_profit")),
total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "total_unrealized_pnl")),
unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss")),
unrealized_profit: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct PeriodCagrPattern {
pub _10y: MetricPattern4<StoredF32>,
pub _2y: MetricPattern4<StoredF32>,
pub _3y: MetricPattern4<StoredF32>,
pub _4y: MetricPattern4<StoredF32>,
pub _5y: MetricPattern4<StoredF32>,
pub _6y: MetricPattern4<StoredF32>,
pub _8y: MetricPattern4<StoredF32>,
}
impl PeriodCagrPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
_10y: MetricPattern4::new(client.clone(), _p("10y", &acc)),
_2y: MetricPattern4::new(client.clone(), _p("2y", &acc)),
_3y: MetricPattern4::new(client.clone(), _p("3y", &acc)),
_4y: MetricPattern4::new(client.clone(), _p("4y", &acc)),
_5y: MetricPattern4::new(client.clone(), _p("5y", &acc)),
_6y: MetricPattern4::new(client.clone(), _p("6y", &acc)),
_8y: MetricPattern4::new(client.clone(), _p("8y", &acc)),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct _10yTo12yPattern {
pub activity: ActivityPattern2,
@@ -1989,6 +1963,32 @@ impl _10yTo12yPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct UnrealizedPattern {
pub neg_unrealized_loss: MetricPattern1<Dollars>,
pub net_unrealized_pnl: MetricPattern1<Dollars>,
pub supply_in_loss: ActiveSupplyPattern,
pub supply_in_profit: ActiveSupplyPattern,
pub total_unrealized_pnl: MetricPattern1<Dollars>,
pub unrealized_loss: MetricPattern1<Dollars>,
pub unrealized_profit: MetricPattern1<Dollars>,
}
impl UnrealizedPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
neg_unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "neg_unrealized_loss")),
net_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "net_unrealized_pnl")),
supply_in_loss: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_loss")),
supply_in_profit: ActiveSupplyPattern::new(client.clone(), _m(&acc, "supply_in_profit")),
total_unrealized_pnl: MetricPattern1::new(client.clone(), _m(&acc, "total_unrealized_pnl")),
unrealized_loss: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_loss")),
unrealized_profit: MetricPattern1::new(client.clone(), _m(&acc, "unrealized_profit")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct AllPattern {
pub balance_decreased: FullnessPattern<StoredU32>,
@@ -2056,37 +2056,19 @@ impl<T: DeserializeOwned> SplitPattern2<T> {
}
/// Pattern struct for repeated tree structure.
pub struct UnclaimedRewardsPattern {
pub bitcoin: BitcoinPattern2<Bitcoin>,
pub dollars: BlockCountPattern<Dollars>,
pub sats: BlockCountPattern<Sats>,
pub struct SegwitAdoptionPattern {
pub base: MetricPattern11<StoredF32>,
pub cumulative: MetricPattern2<StoredF32>,
pub sum: MetricPattern2<StoredF32>,
}
impl UnclaimedRewardsPattern {
impl SegwitAdoptionPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
bitcoin: BitcoinPattern2::new(client.clone(), _m(&acc, "btc")),
dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")),
sats: BlockCountPattern::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct _2015Pattern {
pub bitcoin: MetricPattern4<Bitcoin>,
pub dollars: MetricPattern4<Dollars>,
pub sats: MetricPattern4<Sats>,
}
impl _2015Pattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
bitcoin: MetricPattern4::new(client.clone(), _m(&acc, "btc")),
dollars: MetricPattern4::new(client.clone(), _m(&acc, "usd")),
sats: MetricPattern4::new(client.clone(), acc.clone()),
base: MetricPattern11::new(client.clone(), acc.clone()),
cumulative: MetricPattern2::new(client.clone(), _m(&acc, "cumulative")),
sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")),
}
}
}
@@ -2109,6 +2091,24 @@ impl ActiveSupplyPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct _2015Pattern {
pub bitcoin: MetricPattern4<Bitcoin>,
pub dollars: MetricPattern4<Dollars>,
pub sats: MetricPattern4<Sats>,
}
impl _2015Pattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
bitcoin: MetricPattern4::new(client.clone(), _m(&acc, "btc")),
dollars: MetricPattern4::new(client.clone(), _m(&acc, "usd")),
sats: MetricPattern4::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CoinbasePattern {
pub bitcoin: BitcoinPattern,
@@ -2128,37 +2128,19 @@ impl CoinbasePattern {
}
/// Pattern struct for repeated tree structure.
pub struct SegwitAdoptionPattern {
pub base: MetricPattern11<StoredF32>,
pub cumulative: MetricPattern2<StoredF32>,
pub sum: MetricPattern2<StoredF32>,
pub struct UnclaimedRewardsPattern {
pub bitcoin: BitcoinPattern2<Bitcoin>,
pub dollars: BlockCountPattern<Dollars>,
pub sats: BlockCountPattern<Sats>,
}
impl SegwitAdoptionPattern {
impl UnclaimedRewardsPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
base: MetricPattern11::new(client.clone(), acc.clone()),
cumulative: MetricPattern2::new(client.clone(), _m(&acc, "cumulative")),
sum: MetricPattern2::new(client.clone(), _m(&acc, "sum")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CostBasisPattern2 {
pub max: ActivePricePattern,
pub min: ActivePricePattern,
pub percentiles: PercentilesPattern,
}
impl CostBasisPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
max: ActivePricePattern::new(client.clone(), _m(&acc, "max_cost_basis")),
min: ActivePricePattern::new(client.clone(), _m(&acc, "min_cost_basis")),
percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")),
bitcoin: BitcoinPattern2::new(client.clone(), _m(&acc, "btc")),
dollars: BlockCountPattern::new(client.clone(), _m(&acc, "usd")),
sats: BlockCountPattern::new(client.clone(), acc.clone()),
}
}
}
@@ -2182,17 +2164,19 @@ impl CoinbasePattern2 {
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern4 {
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_own_supply: MetricPattern1<StoredF64>,
pub struct CostBasisPattern2 {
pub max: ActivePricePattern,
pub min: ActivePricePattern,
pub percentiles: PercentilesPattern,
}
impl RelativePattern4 {
impl CostBasisPattern2 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "loss_rel_to_own_supply")),
supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "profit_rel_to_own_supply")),
max: ActivePricePattern::new(client.clone(), _m(&acc, "max_cost_basis")),
min: ActivePricePattern::new(client.clone(), _m(&acc, "min_cost_basis")),
percentiles: PercentilesPattern::new(client.clone(), _m(&acc, "cost_basis")),
}
}
}
@@ -2214,17 +2198,17 @@ impl ActivePricePattern {
}
/// Pattern struct for repeated tree structure.
pub struct _1dReturns1mSdPattern {
pub sd: MetricPattern4<StoredF32>,
pub sma: MetricPattern4<StoredF32>,
pub struct _0sdUsdPattern {
pub dollars: MetricPattern4<Dollars>,
pub sats: MetricPattern4<SatsFract>,
}
impl _1dReturns1mSdPattern {
impl _0sdUsdPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
sd: MetricPattern4::new(client.clone(), _m(&acc, "sd")),
sma: MetricPattern4::new(client.clone(), _m(&acc, "sma")),
dollars: MetricPattern4::new(client.clone(), acc.clone()),
sats: MetricPattern4::new(client.clone(), _m(&acc, "sats")),
}
}
}
@@ -2245,22 +2229,6 @@ impl SupplyPattern2 {
}
}
/// Pattern struct for repeated tree structure.
pub struct _0sdUsdPattern {
pub dollars: MetricPattern4<Dollars>,
pub sats: MetricPattern4<SatsFract>,
}
impl _0sdUsdPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
dollars: MetricPattern4::new(client.clone(), acc.clone()),
sats: MetricPattern4::new(client.clone(), _m(&acc, "sats")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct CostBasisPattern {
pub max: ActivePricePattern,
@@ -2277,6 +2245,38 @@ impl CostBasisPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct _1dReturns1mSdPattern {
pub sd: MetricPattern4<StoredF32>,
pub sma: MetricPattern4<StoredF32>,
}
impl _1dReturns1mSdPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
sd: MetricPattern4::new(client.clone(), _m(&acc, "sd")),
sma: MetricPattern4::new(client.clone(), _m(&acc, "sma")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct RelativePattern4 {
pub supply_in_loss_rel_to_own_supply: MetricPattern1<StoredF64>,
pub supply_in_profit_rel_to_own_supply: MetricPattern1<StoredF64>,
}
impl RelativePattern4 {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
supply_in_loss_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "loss_rel_to_own_supply")),
supply_in_profit_rel_to_own_supply: MetricPattern1::new(client.clone(), _m(&acc, "profit_rel_to_own_supply")),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct BlockCountPattern<T> {
pub cumulative: MetricPattern1<T>,
@@ -2325,20 +2325,6 @@ impl<T: DeserializeOwned> SatsPattern<T> {
}
}
/// Pattern struct for repeated tree structure.
pub struct OutputsPattern {
pub utxo_count: MetricPattern1<StoredU64>,
}
impl OutputsPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
utxo_count: MetricPattern1::new(client.clone(), acc.clone()),
}
}
}
/// Pattern struct for repeated tree structure.
pub struct RealizedPriceExtraPattern {
pub ratio: MetricPattern4<StoredF32>,
@@ -2353,6 +2339,20 @@ impl RealizedPriceExtraPattern {
}
}
/// Pattern struct for repeated tree structure.
pub struct OutputsPattern {
pub utxo_count: MetricPattern1<StoredU64>,
}
impl OutputsPattern {
/// Create a new pattern node with accumulated metric name.
pub fn new(client: Arc<BrkClientBase>, acc: String) -> Self {
Self {
utxo_count: MetricPattern1::new(client.clone(), acc.clone()),
}
}
}
// Metrics tree
/// Metrics tree node.
@@ -4276,10 +4276,10 @@ impl MetricsTree_Market_Ath {
pub struct MetricsTree_Market_Dca {
pub class_average_price: MetricsTree_Market_Dca_ClassAveragePrice,
pub class_days_in_loss: MetricsTree_Market_Dca_ClassDaysInLoss,
pub class_days_in_profit: ClassDaysInLossPattern<StoredU32>,
pub class_days_in_profit: MetricsTree_Market_Dca_ClassDaysInProfit,
pub class_max_drawdown: MetricsTree_Market_Dca_ClassMaxDrawdown,
pub class_max_return: MetricsTree_Market_Dca_ClassMaxReturn,
pub class_returns: MetricsTree_Market_Dca_ClassReturns,
pub class_returns: ClassDaysInLossPattern<StoredF32>,
pub class_stack: MetricsTree_Market_Dca_ClassStack,
pub period_average_price: MetricsTree_Market_Dca_PeriodAveragePrice,
pub period_cagr: PeriodCagrPattern,
@@ -4302,10 +4302,10 @@ impl MetricsTree_Market_Dca {
Self {
class_average_price: MetricsTree_Market_Dca_ClassAveragePrice::new(client.clone(), format!("{base_path}_class_average_price")),
class_days_in_loss: MetricsTree_Market_Dca_ClassDaysInLoss::new(client.clone(), format!("{base_path}_class_days_in_loss")),
class_days_in_profit: ClassDaysInLossPattern::new(client.clone(), "dca_class".to_string()),
class_days_in_profit: MetricsTree_Market_Dca_ClassDaysInProfit::new(client.clone(), format!("{base_path}_class_days_in_profit")),
class_max_drawdown: MetricsTree_Market_Dca_ClassMaxDrawdown::new(client.clone(), format!("{base_path}_class_max_drawdown")),
class_max_return: MetricsTree_Market_Dca_ClassMaxReturn::new(client.clone(), format!("{base_path}_class_max_return")),
class_returns: MetricsTree_Market_Dca_ClassReturns::new(client.clone(), format!("{base_path}_class_returns")),
class_returns: ClassDaysInLossPattern::new(client.clone(), "dca_class".to_string()),
class_stack: MetricsTree_Market_Dca_ClassStack::new(client.clone(), format!("{base_path}_class_stack")),
period_average_price: MetricsTree_Market_Dca_PeriodAveragePrice::new(client.clone(), format!("{base_path}_period_average_price")),
period_cagr: PeriodCagrPattern::new(client.clone(), "dca_cagr".to_string()),
@@ -4395,6 +4395,41 @@ impl MetricsTree_Market_Dca_ClassDaysInLoss {
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Dca_ClassDaysInProfit {
pub _2015: MetricPattern4<StoredU32>,
pub _2016: MetricPattern4<StoredU32>,
pub _2017: MetricPattern4<StoredU32>,
pub _2018: MetricPattern4<StoredU32>,
pub _2019: MetricPattern4<StoredU32>,
pub _2020: MetricPattern4<StoredU32>,
pub _2021: MetricPattern4<StoredU32>,
pub _2022: MetricPattern4<StoredU32>,
pub _2023: MetricPattern4<StoredU32>,
pub _2024: MetricPattern4<StoredU32>,
pub _2025: MetricPattern4<StoredU32>,
pub _2026: MetricPattern4<StoredU32>,
}
impl MetricsTree_Market_Dca_ClassDaysInProfit {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
_2015: MetricPattern4::new(client.clone(), "dca_class_2015_days_in_profit".to_string()),
_2016: MetricPattern4::new(client.clone(), "dca_class_2016_days_in_profit".to_string()),
_2017: MetricPattern4::new(client.clone(), "dca_class_2017_days_in_profit".to_string()),
_2018: MetricPattern4::new(client.clone(), "dca_class_2018_days_in_profit".to_string()),
_2019: MetricPattern4::new(client.clone(), "dca_class_2019_days_in_profit".to_string()),
_2020: MetricPattern4::new(client.clone(), "dca_class_2020_days_in_profit".to_string()),
_2021: MetricPattern4::new(client.clone(), "dca_class_2021_days_in_profit".to_string()),
_2022: MetricPattern4::new(client.clone(), "dca_class_2022_days_in_profit".to_string()),
_2023: MetricPattern4::new(client.clone(), "dca_class_2023_days_in_profit".to_string()),
_2024: MetricPattern4::new(client.clone(), "dca_class_2024_days_in_profit".to_string()),
_2025: MetricPattern4::new(client.clone(), "dca_class_2025_days_in_profit".to_string()),
_2026: MetricPattern4::new(client.clone(), "dca_class_2026_days_in_profit".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Dca_ClassMaxDrawdown {
pub _2015: MetricPattern4<StoredF32>,
@@ -4465,41 +4500,6 @@ impl MetricsTree_Market_Dca_ClassMaxReturn {
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Dca_ClassReturns {
pub _2015: MetricPattern4<StoredF32>,
pub _2016: MetricPattern4<StoredF32>,
pub _2017: MetricPattern4<StoredF32>,
pub _2018: MetricPattern4<StoredF32>,
pub _2019: MetricPattern4<StoredF32>,
pub _2020: MetricPattern4<StoredF32>,
pub _2021: MetricPattern4<StoredF32>,
pub _2022: MetricPattern4<StoredF32>,
pub _2023: MetricPattern4<StoredF32>,
pub _2024: MetricPattern4<StoredF32>,
pub _2025: MetricPattern4<StoredF32>,
pub _2026: MetricPattern4<StoredF32>,
}
impl MetricsTree_Market_Dca_ClassReturns {
pub fn new(client: Arc<BrkClientBase>, base_path: String) -> Self {
Self {
_2015: MetricPattern4::new(client.clone(), "dca_class_2015_returns".to_string()),
_2016: MetricPattern4::new(client.clone(), "dca_class_2016_returns".to_string()),
_2017: MetricPattern4::new(client.clone(), "dca_class_2017_returns".to_string()),
_2018: MetricPattern4::new(client.clone(), "dca_class_2018_returns".to_string()),
_2019: MetricPattern4::new(client.clone(), "dca_class_2019_returns".to_string()),
_2020: MetricPattern4::new(client.clone(), "dca_class_2020_returns".to_string()),
_2021: MetricPattern4::new(client.clone(), "dca_class_2021_returns".to_string()),
_2022: MetricPattern4::new(client.clone(), "dca_class_2022_returns".to_string()),
_2023: MetricPattern4::new(client.clone(), "dca_class_2023_returns".to_string()),
_2024: MetricPattern4::new(client.clone(), "dca_class_2024_returns".to_string()),
_2025: MetricPattern4::new(client.clone(), "dca_class_2025_returns".to_string()),
_2026: MetricPattern4::new(client.clone(), "dca_class_2026_returns".to_string()),
}
}
}
/// Metrics tree node.
pub struct MetricsTree_Market_Dca_ClassStack {
pub _2015: _2015Pattern,
@@ -5651,7 +5651,7 @@ pub struct BrkClient {
impl BrkClient {
/// Client version.
pub const VERSION: &'static str = "v0.1.0";
pub const VERSION: &'static str = "v0.1.1";
/// Create a new client with the given base URL.
pub fn new(base_url: impl Into<String>) -> Self {

View File

@@ -7,7 +7,7 @@ use brk_iterator::Blocks;
use brk_rpc::Client;
use brk_types::Height;
use tracing::{debug, info};
use vecdb::Exit;
use vecdb::{Exit, TypedVecIterator};
mod constants;
mod indexes;
mod processor;

View File

@@ -1,5 +1,7 @@
use std::{fs, path::Path, time::Instant};
use rustc_hash::FxHashSet;
use brk_cohort::ByAddressType;
use brk_error::Result;
use brk_store::{AnyStore, Kind, Mode, Store};
@@ -228,6 +230,7 @@ impl Stores {
});
// Remove address hashes for all address types starting from rollback height
// (each address only appears once in bytes vec, so no dedup needed)
for address_type in [
OutputType::P2PK65,
OutputType::P2PK33,
@@ -280,6 +283,11 @@ impl Stores {
let mut txoutindex_to_outputtype_iter = vecs.outputs.outputtype.iter()?;
let mut txoutindex_to_typeindex_iter = vecs.outputs.typeindex.iter()?;
// Collect unique (addresstype, addressindex, txindex) to avoid double deletion
// when same address receives multiple outputs in same transaction
let mut addressindex_txindex_to_remove: FxHashSet<(OutputType, TypeIndex, TxIndex)> =
FxHashSet::default();
for txoutindex in
starting_indexes.txoutindex.to_usize()..vecs.outputs.outputtype.len()
{
@@ -292,9 +300,7 @@ impl Stores {
let addressindex = txoutindex_to_typeindex_iter.get_at_unwrap(txoutindex);
let txindex = txoutindex_to_txindex_iter.get_at_unwrap(txoutindex);
self.addresstype_to_addressindex_and_txindex
.get_mut_unwrap(addresstype)
.remove(AddressIndexTxIndex::from((addressindex, txindex)));
addressindex_txindex_to_remove.insert((addresstype, addressindex, txindex));
let vout = Vout::from(
txoutindex
@@ -304,11 +310,14 @@ impl Stores {
);
let outpoint = OutPoint::new(txindex, vout);
// OutPoints are unique per output, no dedup needed
self.addresstype_to_addressindex_and_unspentoutpoint
.get_mut_unwrap(addresstype)
.remove(AddressIndexOutPoint::from((addressindex, outpoint)));
}
// Don't remove yet - merge with second loop's set first
// Collect outputs that were spent after the rollback point
// We need to: 1) reset their spend status, 2) restore address stores
let mut txindex_to_first_txoutindex_iter =
@@ -349,21 +358,30 @@ impl Stores {
.collect();
// Now process the collected outputs (iterators dropped, can mutate vecs)
// Add spending tx entries to the same set (avoid double deletion when same tx
// both creates output to address A and spends output from address A)
for (outpoint, outputtype, typeindex, spending_txindex) in outputs_to_unspend {
// Restore address stores if this is an address output
if outputtype.is_address() {
let addresstype = outputtype;
let addressindex = typeindex;
self.addresstype_to_addressindex_and_txindex
.get_mut_unwrap(addresstype)
.remove(AddressIndexTxIndex::from((addressindex, spending_txindex)));
// Add to same set as first loop
addressindex_txindex_to_remove.insert((addresstype, addressindex, spending_txindex));
// OutPoints are unique, no dedup needed for insert
self.addresstype_to_addressindex_and_unspentoutpoint
.get_mut_unwrap(addresstype)
.insert(AddressIndexOutPoint::from((addressindex, outpoint)), Unit);
}
}
// Now remove all deduplicated addressindex_txindex entries (from both loops)
for (addresstype, addressindex, txindex) in addressindex_txindex_to_remove {
self.addresstype_to_addressindex_and_txindex
.get_mut_unwrap(addresstype)
.remove(AddressIndexTxIndex::from((addressindex, txindex)));
}
} else {
unreachable!();
}

View File

@@ -1953,18 +1953,18 @@ function createPeriodDaysInLossPattern(client, acc) {
*/
function createClassDaysInLossPattern(client, acc) {
return {
_2015: createMetricPattern4(client, _m(acc, '2015_days_in_profit')),
_2016: createMetricPattern4(client, _m(acc, '2016_days_in_profit')),
_2017: createMetricPattern4(client, _m(acc, '2017_days_in_profit')),
_2018: createMetricPattern4(client, _m(acc, '2018_days_in_profit')),
_2019: createMetricPattern4(client, _m(acc, '2019_days_in_profit')),
_2020: createMetricPattern4(client, _m(acc, '2020_days_in_profit')),
_2021: createMetricPattern4(client, _m(acc, '2021_days_in_profit')),
_2022: createMetricPattern4(client, _m(acc, '2022_days_in_profit')),
_2023: createMetricPattern4(client, _m(acc, '2023_days_in_profit')),
_2024: createMetricPattern4(client, _m(acc, '2024_days_in_profit')),
_2025: createMetricPattern4(client, _m(acc, '2025_days_in_profit')),
_2026: createMetricPattern4(client, _m(acc, '2026_days_in_profit')),
_2015: createMetricPattern4(client, _m(acc, '2015_returns')),
_2016: createMetricPattern4(client, _m(acc, '2016_returns')),
_2017: createMetricPattern4(client, _m(acc, '2017_returns')),
_2018: createMetricPattern4(client, _m(acc, '2018_returns')),
_2019: createMetricPattern4(client, _m(acc, '2019_returns')),
_2020: createMetricPattern4(client, _m(acc, '2020_returns')),
_2021: createMetricPattern4(client, _m(acc, '2021_returns')),
_2022: createMetricPattern4(client, _m(acc, '2022_returns')),
_2023: createMetricPattern4(client, _m(acc, '2023_returns')),
_2024: createMetricPattern4(client, _m(acc, '2024_returns')),
_2025: createMetricPattern4(client, _m(acc, '2025_returns')),
_2026: createMetricPattern4(client, _m(acc, '2026_returns')),
};
}
@@ -2044,41 +2044,6 @@ function createDollarsPattern(client, acc) {
};
}
/**
* @typedef {Object} RelativePattern2
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF32>} netUnrealizedPnlRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} netUnrealizedPnlRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF64>} supplyInLossRelToOwnSupply
* @property {MetricPattern1<StoredF64>} supplyInProfitRelToOwnSupply
* @property {MetricPattern1<StoredF32>} unrealizedLossRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} unrealizedLossRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF32>} unrealizedProfitRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} unrealizedProfitRelToOwnTotalUnrealizedPnl
*/
/**
* Create a RelativePattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {RelativePattern2}
*/
function createRelativePattern2(client, acc) {
return {
negUnrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')),
negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')),
netUnrealizedPnlRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')),
netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')),
supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')),
supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')),
unrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')),
unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')),
unrealizedProfitRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')),
unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')),
};
}
/**
* @typedef {Object} RelativePattern
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToMarketCap
@@ -2114,6 +2079,41 @@ function createRelativePattern(client, acc) {
};
}
/**
* @typedef {Object} RelativePattern2
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} negUnrealizedLossRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF32>} netUnrealizedPnlRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} netUnrealizedPnlRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF64>} supplyInLossRelToOwnSupply
* @property {MetricPattern1<StoredF64>} supplyInProfitRelToOwnSupply
* @property {MetricPattern1<StoredF32>} unrealizedLossRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} unrealizedLossRelToOwnTotalUnrealizedPnl
* @property {MetricPattern1<StoredF32>} unrealizedProfitRelToOwnMarketCap
* @property {MetricPattern1<StoredF32>} unrealizedProfitRelToOwnTotalUnrealizedPnl
*/
/**
* Create a RelativePattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {RelativePattern2}
*/
function createRelativePattern2(client, acc) {
return {
negUnrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap')),
negUnrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl')),
netUnrealizedPnlRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap')),
netUnrealizedPnlRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl')),
supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply')),
supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply')),
unrealizedLossRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap')),
unrealizedLossRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl')),
unrealizedProfitRelToOwnMarketCap: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap')),
unrealizedProfitRelToOwnTotalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl')),
};
}
/**
* @template T
* @typedef {Object} CountPattern2
@@ -2285,6 +2285,35 @@ function create_0satsPattern(client, acc) {
};
}
/**
* @typedef {Object} PeriodCagrPattern
* @property {MetricPattern4<StoredF32>} _10y
* @property {MetricPattern4<StoredF32>} _2y
* @property {MetricPattern4<StoredF32>} _3y
* @property {MetricPattern4<StoredF32>} _4y
* @property {MetricPattern4<StoredF32>} _5y
* @property {MetricPattern4<StoredF32>} _6y
* @property {MetricPattern4<StoredF32>} _8y
*/
/**
* Create a PeriodCagrPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {PeriodCagrPattern}
*/
function createPeriodCagrPattern(client, acc) {
return {
_10y: createMetricPattern4(client, _p('10y', acc)),
_2y: createMetricPattern4(client, _p('2y', acc)),
_3y: createMetricPattern4(client, _p('3y', acc)),
_4y: createMetricPattern4(client, _p('4y', acc)),
_5y: createMetricPattern4(client, _p('5y', acc)),
_6y: createMetricPattern4(client, _p('6y', acc)),
_8y: createMetricPattern4(client, _p('8y', acc)),
};
}
/**
* @typedef {Object} _100btcPattern
* @property {ActivityPattern2} activity
@@ -2372,64 +2401,6 @@ function create_10yPattern(client, acc) {
};
}
/**
* @typedef {Object} UnrealizedPattern
* @property {MetricPattern1<Dollars>} negUnrealizedLoss
* @property {MetricPattern1<Dollars>} netUnrealizedPnl
* @property {ActiveSupplyPattern} supplyInLoss
* @property {ActiveSupplyPattern} supplyInProfit
* @property {MetricPattern1<Dollars>} totalUnrealizedPnl
* @property {MetricPattern1<Dollars>} unrealizedLoss
* @property {MetricPattern1<Dollars>} unrealizedProfit
*/
/**
* Create a UnrealizedPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {UnrealizedPattern}
*/
function createUnrealizedPattern(client, acc) {
return {
negUnrealizedLoss: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss')),
netUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl')),
supplyInLoss: createActiveSupplyPattern(client, _m(acc, 'supply_in_loss')),
supplyInProfit: createActiveSupplyPattern(client, _m(acc, 'supply_in_profit')),
totalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'total_unrealized_pnl')),
unrealizedLoss: createMetricPattern1(client, _m(acc, 'unrealized_loss')),
unrealizedProfit: createMetricPattern1(client, _m(acc, 'unrealized_profit')),
};
}
/**
* @typedef {Object} PeriodCagrPattern
* @property {MetricPattern4<StoredF32>} _10y
* @property {MetricPattern4<StoredF32>} _2y
* @property {MetricPattern4<StoredF32>} _3y
* @property {MetricPattern4<StoredF32>} _4y
* @property {MetricPattern4<StoredF32>} _5y
* @property {MetricPattern4<StoredF32>} _6y
* @property {MetricPattern4<StoredF32>} _8y
*/
/**
* Create a PeriodCagrPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {PeriodCagrPattern}
*/
function createPeriodCagrPattern(client, acc) {
return {
_10y: createMetricPattern4(client, _p('10y', acc)),
_2y: createMetricPattern4(client, _p('2y', acc)),
_3y: createMetricPattern4(client, _p('3y', acc)),
_4y: createMetricPattern4(client, _p('4y', acc)),
_5y: createMetricPattern4(client, _p('5y', acc)),
_6y: createMetricPattern4(client, _p('6y', acc)),
_8y: createMetricPattern4(client, _p('8y', acc)),
};
}
/**
* @typedef {Object} _10yTo12yPattern
* @property {ActivityPattern2} activity
@@ -2459,6 +2430,35 @@ function create_10yTo12yPattern(client, acc) {
};
}
/**
* @typedef {Object} UnrealizedPattern
* @property {MetricPattern1<Dollars>} negUnrealizedLoss
* @property {MetricPattern1<Dollars>} netUnrealizedPnl
* @property {ActiveSupplyPattern} supplyInLoss
* @property {ActiveSupplyPattern} supplyInProfit
* @property {MetricPattern1<Dollars>} totalUnrealizedPnl
* @property {MetricPattern1<Dollars>} unrealizedLoss
* @property {MetricPattern1<Dollars>} unrealizedProfit
*/
/**
* Create a UnrealizedPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {UnrealizedPattern}
*/
function createUnrealizedPattern(client, acc) {
return {
negUnrealizedLoss: createMetricPattern1(client, _m(acc, 'neg_unrealized_loss')),
netUnrealizedPnl: createMetricPattern1(client, _m(acc, 'net_unrealized_pnl')),
supplyInLoss: createActiveSupplyPattern(client, _m(acc, 'supply_in_loss')),
supplyInProfit: createActiveSupplyPattern(client, _m(acc, 'supply_in_profit')),
totalUnrealizedPnl: createMetricPattern1(client, _m(acc, 'total_unrealized_pnl')),
unrealizedLoss: createMetricPattern1(client, _m(acc, 'unrealized_loss')),
unrealizedProfit: createMetricPattern1(client, _m(acc, 'unrealized_profit')),
};
}
/**
* @typedef {Object} AllPattern
* @property {FullnessPattern<StoredU32>} balanceDecreased
@@ -2537,44 +2537,23 @@ function createSplitPattern2(client, acc) {
}
/**
* @typedef {Object} UnclaimedRewardsPattern
* @property {BitcoinPattern2<Bitcoin>} bitcoin
* @property {BlockCountPattern<Dollars>} dollars
* @property {BlockCountPattern<Sats>} sats
* @typedef {Object} SegwitAdoptionPattern
* @property {MetricPattern11<StoredF32>} base
* @property {MetricPattern2<StoredF32>} cumulative
* @property {MetricPattern2<StoredF32>} sum
*/
/**
* Create a UnclaimedRewardsPattern pattern node
* Create a SegwitAdoptionPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {UnclaimedRewardsPattern}
* @returns {SegwitAdoptionPattern}
*/
function createUnclaimedRewardsPattern(client, acc) {
function createSegwitAdoptionPattern(client, acc) {
return {
bitcoin: createBitcoinPattern2(client, _m(acc, 'btc')),
dollars: createBlockCountPattern(client, _m(acc, 'usd')),
sats: createBlockCountPattern(client, acc),
};
}
/**
* @typedef {Object} _2015Pattern
* @property {MetricPattern4<Bitcoin>} bitcoin
* @property {MetricPattern4<Dollars>} dollars
* @property {MetricPattern4<Sats>} sats
*/
/**
* Create a _2015Pattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {_2015Pattern}
*/
function create_2015Pattern(client, acc) {
return {
bitcoin: createMetricPattern4(client, _m(acc, 'btc')),
dollars: createMetricPattern4(client, _m(acc, 'usd')),
sats: createMetricPattern4(client, acc),
base: createMetricPattern11(client, acc),
cumulative: createMetricPattern2(client, _m(acc, 'cumulative')),
sum: createMetricPattern2(client, _m(acc, 'sum')),
};
}
@@ -2599,6 +2578,27 @@ function createActiveSupplyPattern(client, acc) {
};
}
/**
* @typedef {Object} _2015Pattern
* @property {MetricPattern4<Bitcoin>} bitcoin
* @property {MetricPattern4<Dollars>} dollars
* @property {MetricPattern4<Sats>} sats
*/
/**
* Create a _2015Pattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {_2015Pattern}
*/
function create_2015Pattern(client, acc) {
return {
bitcoin: createMetricPattern4(client, _m(acc, 'btc')),
dollars: createMetricPattern4(client, _m(acc, 'usd')),
sats: createMetricPattern4(client, acc),
};
}
/**
* @typedef {Object} CoinbasePattern
* @property {BitcoinPattern} bitcoin
@@ -2621,44 +2621,23 @@ function createCoinbasePattern(client, acc) {
}
/**
* @typedef {Object} SegwitAdoptionPattern
* @property {MetricPattern11<StoredF32>} base
* @property {MetricPattern2<StoredF32>} cumulative
* @property {MetricPattern2<StoredF32>} sum
* @typedef {Object} UnclaimedRewardsPattern
* @property {BitcoinPattern2<Bitcoin>} bitcoin
* @property {BlockCountPattern<Dollars>} dollars
* @property {BlockCountPattern<Sats>} sats
*/
/**
* Create a SegwitAdoptionPattern pattern node
* Create a UnclaimedRewardsPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {SegwitAdoptionPattern}
* @returns {UnclaimedRewardsPattern}
*/
function createSegwitAdoptionPattern(client, acc) {
function createUnclaimedRewardsPattern(client, acc) {
return {
base: createMetricPattern11(client, acc),
cumulative: createMetricPattern2(client, _m(acc, 'cumulative')),
sum: createMetricPattern2(client, _m(acc, 'sum')),
};
}
/**
* @typedef {Object} CostBasisPattern2
* @property {ActivePricePattern} max
* @property {ActivePricePattern} min
* @property {PercentilesPattern} percentiles
*/
/**
* Create a CostBasisPattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {CostBasisPattern2}
*/
function createCostBasisPattern2(client, acc) {
return {
max: createActivePricePattern(client, _m(acc, 'max_cost_basis')),
min: createActivePricePattern(client, _m(acc, 'min_cost_basis')),
percentiles: createPercentilesPattern(client, _m(acc, 'cost_basis')),
bitcoin: createBitcoinPattern2(client, _m(acc, 'btc')),
dollars: createBlockCountPattern(client, _m(acc, 'usd')),
sats: createBlockCountPattern(client, acc),
};
}
@@ -2684,21 +2663,23 @@ function createCoinbasePattern2(client, acc) {
}
/**
* @typedef {Object} RelativePattern4
* @property {MetricPattern1<StoredF64>} supplyInLossRelToOwnSupply
* @property {MetricPattern1<StoredF64>} supplyInProfitRelToOwnSupply
* @typedef {Object} CostBasisPattern2
* @property {ActivePricePattern} max
* @property {ActivePricePattern} min
* @property {PercentilesPattern} percentiles
*/
/**
* Create a RelativePattern4 pattern node
* Create a CostBasisPattern2 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {RelativePattern4}
* @returns {CostBasisPattern2}
*/
function createRelativePattern4(client, acc) {
function createCostBasisPattern2(client, acc) {
return {
supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'loss_rel_to_own_supply')),
supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'profit_rel_to_own_supply')),
max: createActivePricePattern(client, _m(acc, 'max_cost_basis')),
min: createActivePricePattern(client, _m(acc, 'min_cost_basis')),
percentiles: createPercentilesPattern(client, _m(acc, 'cost_basis')),
};
}
@@ -2722,21 +2703,21 @@ function createActivePricePattern(client, acc) {
}
/**
* @typedef {Object} _1dReturns1mSdPattern
* @property {MetricPattern4<StoredF32>} sd
* @property {MetricPattern4<StoredF32>} sma
* @typedef {Object} _0sdUsdPattern
* @property {MetricPattern4<Dollars>} dollars
* @property {MetricPattern4<SatsFract>} sats
*/
/**
* Create a _1dReturns1mSdPattern pattern node
* Create a _0sdUsdPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {_1dReturns1mSdPattern}
* @returns {_0sdUsdPattern}
*/
function create_1dReturns1mSdPattern(client, acc) {
function create_0sdUsdPattern(client, acc) {
return {
sd: createMetricPattern4(client, _m(acc, 'sd')),
sma: createMetricPattern4(client, _m(acc, 'sma')),
dollars: createMetricPattern4(client, acc),
sats: createMetricPattern4(client, _m(acc, 'sats')),
};
}
@@ -2759,25 +2740,6 @@ function createSupplyPattern2(client, acc) {
};
}
/**
* @typedef {Object} _0sdUsdPattern
* @property {MetricPattern4<Dollars>} dollars
* @property {MetricPattern4<SatsFract>} sats
*/
/**
* Create a _0sdUsdPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {_0sdUsdPattern}
*/
function create_0sdUsdPattern(client, acc) {
return {
dollars: createMetricPattern4(client, acc),
sats: createMetricPattern4(client, _m(acc, 'sats')),
};
}
/**
* @typedef {Object} CostBasisPattern
* @property {ActivePricePattern} max
@@ -2797,6 +2759,44 @@ function createCostBasisPattern(client, acc) {
};
}
/**
* @typedef {Object} _1dReturns1mSdPattern
* @property {MetricPattern4<StoredF32>} sd
* @property {MetricPattern4<StoredF32>} sma
*/
/**
* Create a _1dReturns1mSdPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {_1dReturns1mSdPattern}
*/
function create_1dReturns1mSdPattern(client, acc) {
return {
sd: createMetricPattern4(client, _m(acc, 'sd')),
sma: createMetricPattern4(client, _m(acc, 'sma')),
};
}
/**
* @typedef {Object} RelativePattern4
* @property {MetricPattern1<StoredF64>} supplyInLossRelToOwnSupply
* @property {MetricPattern1<StoredF64>} supplyInProfitRelToOwnSupply
*/
/**
* Create a RelativePattern4 pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {RelativePattern4}
*/
function createRelativePattern4(client, acc) {
return {
supplyInLossRelToOwnSupply: createMetricPattern1(client, _m(acc, 'loss_rel_to_own_supply')),
supplyInProfitRelToOwnSupply: createMetricPattern1(client, _m(acc, 'profit_rel_to_own_supply')),
};
}
/**
* @template T
* @typedef {Object} BlockCountPattern
@@ -2860,23 +2860,6 @@ function createSatsPattern(client, acc) {
};
}
/**
* @typedef {Object} OutputsPattern
* @property {MetricPattern1<StoredU64>} utxoCount
*/
/**
* Create a OutputsPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {OutputsPattern}
*/
function createOutputsPattern(client, acc) {
return {
utxoCount: createMetricPattern1(client, acc),
};
}
/**
* @typedef {Object} RealizedPriceExtraPattern
* @property {MetricPattern4<StoredF32>} ratio
@@ -2894,6 +2877,23 @@ function createRealizedPriceExtraPattern(client, acc) {
};
}
/**
* @typedef {Object} OutputsPattern
* @property {MetricPattern1<StoredU64>} utxoCount
*/
/**
* Create a OutputsPattern pattern node
* @param {BrkClientBase} client
* @param {string} acc - Accumulated metric name
* @returns {OutputsPattern}
*/
function createOutputsPattern(client, acc) {
return {
utxoCount: createMetricPattern1(client, acc),
};
}
// Catalog tree typedefs
/**
@@ -3743,10 +3743,10 @@ function createRealizedPriceExtraPattern(client, acc) {
* @typedef {Object} MetricsTree_Market_Dca
* @property {MetricsTree_Market_Dca_ClassAveragePrice} classAveragePrice
* @property {MetricsTree_Market_Dca_ClassDaysInLoss} classDaysInLoss
* @property {ClassDaysInLossPattern<StoredU32>} classDaysInProfit
* @property {MetricsTree_Market_Dca_ClassDaysInProfit} classDaysInProfit
* @property {MetricsTree_Market_Dca_ClassMaxDrawdown} classMaxDrawdown
* @property {MetricsTree_Market_Dca_ClassMaxReturn} classMaxReturn
* @property {MetricsTree_Market_Dca_ClassReturns} classReturns
* @property {ClassDaysInLossPattern<StoredF32>} classReturns
* @property {MetricsTree_Market_Dca_ClassStack} classStack
* @property {MetricsTree_Market_Dca_PeriodAveragePrice} periodAveragePrice
* @property {PeriodCagrPattern} periodCagr
@@ -3796,6 +3796,22 @@ function createRealizedPriceExtraPattern(client, acc) {
* @property {MetricPattern4<StoredU32>} _2026
*/
/**
* @typedef {Object} MetricsTree_Market_Dca_ClassDaysInProfit
* @property {MetricPattern4<StoredU32>} _2015
* @property {MetricPattern4<StoredU32>} _2016
* @property {MetricPattern4<StoredU32>} _2017
* @property {MetricPattern4<StoredU32>} _2018
* @property {MetricPattern4<StoredU32>} _2019
* @property {MetricPattern4<StoredU32>} _2020
* @property {MetricPattern4<StoredU32>} _2021
* @property {MetricPattern4<StoredU32>} _2022
* @property {MetricPattern4<StoredU32>} _2023
* @property {MetricPattern4<StoredU32>} _2024
* @property {MetricPattern4<StoredU32>} _2025
* @property {MetricPattern4<StoredU32>} _2026
*/
/**
* @typedef {Object} MetricsTree_Market_Dca_ClassMaxDrawdown
* @property {MetricPattern4<StoredF32>} _2015
@@ -3828,22 +3844,6 @@ function createRealizedPriceExtraPattern(client, acc) {
* @property {MetricPattern4<StoredF32>} _2026
*/
/**
* @typedef {Object} MetricsTree_Market_Dca_ClassReturns
* @property {MetricPattern4<StoredF32>} _2015
* @property {MetricPattern4<StoredF32>} _2016
* @property {MetricPattern4<StoredF32>} _2017
* @property {MetricPattern4<StoredF32>} _2018
* @property {MetricPattern4<StoredF32>} _2019
* @property {MetricPattern4<StoredF32>} _2020
* @property {MetricPattern4<StoredF32>} _2021
* @property {MetricPattern4<StoredF32>} _2022
* @property {MetricPattern4<StoredF32>} _2023
* @property {MetricPattern4<StoredF32>} _2024
* @property {MetricPattern4<StoredF32>} _2025
* @property {MetricPattern4<StoredF32>} _2026
*/
/**
* @typedef {Object} MetricsTree_Market_Dca_ClassStack
* @property {_2015Pattern} _2015
@@ -4371,7 +4371,7 @@ function createRealizedPriceExtraPattern(client, acc) {
* @extends BrkClientBase
*/
class BrkClient extends BrkClientBase {
VERSION = "v0.1.0";
VERSION = "v0.1.1";
INDEXES = /** @type {const} */ ([
"dateindex",
@@ -5906,7 +5906,20 @@ class BrkClient extends BrkClientBase {
_2025: createMetricPattern4(this, 'dca_class_2025_days_in_loss'),
_2026: createMetricPattern4(this, 'dca_class_2026_days_in_loss'),
},
classDaysInProfit: createClassDaysInLossPattern(this, 'dca_class'),
classDaysInProfit: {
_2015: createMetricPattern4(this, 'dca_class_2015_days_in_profit'),
_2016: createMetricPattern4(this, 'dca_class_2016_days_in_profit'),
_2017: createMetricPattern4(this, 'dca_class_2017_days_in_profit'),
_2018: createMetricPattern4(this, 'dca_class_2018_days_in_profit'),
_2019: createMetricPattern4(this, 'dca_class_2019_days_in_profit'),
_2020: createMetricPattern4(this, 'dca_class_2020_days_in_profit'),
_2021: createMetricPattern4(this, 'dca_class_2021_days_in_profit'),
_2022: createMetricPattern4(this, 'dca_class_2022_days_in_profit'),
_2023: createMetricPattern4(this, 'dca_class_2023_days_in_profit'),
_2024: createMetricPattern4(this, 'dca_class_2024_days_in_profit'),
_2025: createMetricPattern4(this, 'dca_class_2025_days_in_profit'),
_2026: createMetricPattern4(this, 'dca_class_2026_days_in_profit'),
},
classMaxDrawdown: {
_2015: createMetricPattern4(this, 'dca_class_2015_max_drawdown'),
_2016: createMetricPattern4(this, 'dca_class_2016_max_drawdown'),
@@ -5935,20 +5948,7 @@ class BrkClient extends BrkClientBase {
_2025: createMetricPattern4(this, 'dca_class_2025_max_return'),
_2026: createMetricPattern4(this, 'dca_class_2026_max_return'),
},
classReturns: {
_2015: createMetricPattern4(this, 'dca_class_2015_returns'),
_2016: createMetricPattern4(this, 'dca_class_2016_returns'),
_2017: createMetricPattern4(this, 'dca_class_2017_returns'),
_2018: createMetricPattern4(this, 'dca_class_2018_returns'),
_2019: createMetricPattern4(this, 'dca_class_2019_returns'),
_2020: createMetricPattern4(this, 'dca_class_2020_returns'),
_2021: createMetricPattern4(this, 'dca_class_2021_returns'),
_2022: createMetricPattern4(this, 'dca_class_2022_returns'),
_2023: createMetricPattern4(this, 'dca_class_2023_returns'),
_2024: createMetricPattern4(this, 'dca_class_2024_returns'),
_2025: createMetricPattern4(this, 'dca_class_2025_returns'),
_2026: createMetricPattern4(this, 'dca_class_2026_returns'),
},
classReturns: createClassDaysInLossPattern(this, 'dca_class'),
classStack: {
_2015: create_2015Pattern(this, 'dca_class_2015_stack'),
_2016: create_2015Pattern(this, 'dca_class_2016_stack'),

View File

@@ -2047,18 +2047,18 @@ class ClassDaysInLossPattern(Generic[T]):
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_days_in_profit'))
self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_days_in_profit'))
self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_days_in_profit'))
self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_days_in_profit'))
self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_days_in_profit'))
self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_days_in_profit'))
self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_days_in_profit'))
self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_days_in_profit'))
self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_days_in_profit'))
self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_days_in_profit'))
self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_days_in_profit'))
self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2026_days_in_profit'))
self._2015: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2015_returns'))
self._2016: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2016_returns'))
self._2017: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2017_returns'))
self._2018: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2018_returns'))
self._2019: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2019_returns'))
self._2020: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2020_returns'))
self._2021: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2021_returns'))
self._2022: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2022_returns'))
self._2023: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2023_returns'))
self._2024: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2024_returns'))
self._2025: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2025_returns'))
self._2026: MetricPattern4[T] = MetricPattern4(client, _m(acc, '2026_returns'))
class BitcoinPattern:
"""Pattern struct for repeated tree structure."""
@@ -2094,22 +2094,6 @@ class DollarsPattern(Generic[T]):
self.pct90: MetricPattern6[T] = MetricPattern6(client, _m(acc, 'pct90'))
self.sum: MetricPattern2[T] = MetricPattern2(client, _m(acc, 'sum'))
class RelativePattern2:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap'))
self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl'))
self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap'))
self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl'))
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply'))
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply'))
self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap'))
self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl'))
self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap'))
self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl'))
class RelativePattern:
"""Pattern struct for repeated tree structure."""
@@ -2126,6 +2110,22 @@ class RelativePattern:
self.unrealized_loss_rel_to_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_market_cap'))
self.unrealized_profit_rel_to_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_market_cap'))
class RelativePattern2:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.neg_unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_market_cap'))
self.neg_unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss_rel_to_own_total_unrealized_pnl'))
self.net_unrealized_pnl_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_market_cap'))
self.net_unrealized_pnl_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl_rel_to_own_total_unrealized_pnl'))
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_loss_rel_to_own_supply'))
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'supply_in_profit_rel_to_own_supply'))
self.unrealized_loss_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_market_cap'))
self.unrealized_loss_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_loss_rel_to_own_total_unrealized_pnl'))
self.unrealized_profit_rel_to_own_market_cap: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_market_cap'))
self.unrealized_profit_rel_to_own_total_unrealized_pnl: MetricPattern1[StoredF32] = MetricPattern1(client, _m(acc, 'unrealized_profit_rel_to_own_total_unrealized_pnl'))
class CountPattern2(Generic[T]):
"""Pattern struct for repeated tree structure."""
@@ -2201,6 +2201,19 @@ class _0satsPattern:
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
class PeriodCagrPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self._10y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('10y', acc))
self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('2y', acc))
self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('3y', acc))
self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('4y', acc))
self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('5y', acc))
self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc))
self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc))
class _100btcPattern:
"""Pattern struct for repeated tree structure."""
@@ -2240,32 +2253,6 @@ class _10yPattern:
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
class UnrealizedPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.neg_unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss'))
self.net_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl'))
self.supply_in_loss: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_in_loss'))
self.supply_in_profit: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_in_profit'))
self.total_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'total_unrealized_pnl'))
self.unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_loss'))
self.unrealized_profit: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_profit'))
class PeriodCagrPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self._10y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('10y', acc))
self._2y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('2y', acc))
self._3y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('3y', acc))
self._4y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('4y', acc))
self._5y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('5y', acc))
self._6y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('6y', acc))
self._8y: MetricPattern4[StoredF32] = MetricPattern4(client, _p('8y', acc))
class _10yTo12yPattern:
"""Pattern struct for repeated tree structure."""
@@ -2279,6 +2266,19 @@ class _10yTo12yPattern:
self.supply: SupplyPattern2 = SupplyPattern2(client, _m(acc, 'supply'))
self.unrealized: UnrealizedPattern = UnrealizedPattern(client, acc)
class UnrealizedPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.neg_unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'neg_unrealized_loss'))
self.net_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'net_unrealized_pnl'))
self.supply_in_loss: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_in_loss'))
self.supply_in_profit: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'supply_in_profit'))
self.total_unrealized_pnl: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'total_unrealized_pnl'))
self.unrealized_loss: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_loss'))
self.unrealized_profit: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'unrealized_profit'))
class AllPattern:
"""Pattern struct for repeated tree structure."""
@@ -2312,23 +2312,14 @@ class SplitPattern2(Generic[T]):
self.low: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'low'))
self.open: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'open'))
class UnclaimedRewardsPattern:
class SegwitAdoptionPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.bitcoin: BitcoinPattern2[Bitcoin] = BitcoinPattern2(client, _m(acc, 'btc'))
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
class _2015Pattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.bitcoin: MetricPattern4[Bitcoin] = MetricPattern4(client, _m(acc, 'btc'))
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd'))
self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc)
self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc)
self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative'))
self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum'))
class ActiveSupplyPattern:
"""Pattern struct for repeated tree structure."""
@@ -2339,6 +2330,15 @@ class ActiveSupplyPattern:
self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, _m(acc, 'usd'))
self.sats: MetricPattern1[Sats] = MetricPattern1(client, acc)
class _2015Pattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.bitcoin: MetricPattern4[Bitcoin] = MetricPattern4(client, _m(acc, 'btc'))
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, _m(acc, 'usd'))
self.sats: MetricPattern4[Sats] = MetricPattern4(client, acc)
class CoinbasePattern:
"""Pattern struct for repeated tree structure."""
@@ -2348,23 +2348,14 @@ class CoinbasePattern:
self.dollars: DollarsPattern[Dollars] = DollarsPattern(client, _m(acc, 'usd'))
self.sats: DollarsPattern[Sats] = DollarsPattern(client, acc)
class SegwitAdoptionPattern:
class UnclaimedRewardsPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.base: MetricPattern11[StoredF32] = MetricPattern11(client, acc)
self.cumulative: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'cumulative'))
self.sum: MetricPattern2[StoredF32] = MetricPattern2(client, _m(acc, 'sum'))
class CostBasisPattern2:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.max: ActivePricePattern = ActivePricePattern(client, _m(acc, 'max_cost_basis'))
self.min: ActivePricePattern = ActivePricePattern(client, _m(acc, 'min_cost_basis'))
self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis'))
self.bitcoin: BitcoinPattern2[Bitcoin] = BitcoinPattern2(client, _m(acc, 'btc'))
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
class CoinbasePattern2:
"""Pattern struct for repeated tree structure."""
@@ -2375,13 +2366,14 @@ class CoinbasePattern2:
self.dollars: BlockCountPattern[Dollars] = BlockCountPattern(client, _m(acc, 'usd'))
self.sats: BlockCountPattern[Sats] = BlockCountPattern(client, acc)
class RelativePattern4:
class CostBasisPattern2:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'loss_rel_to_own_supply'))
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'profit_rel_to_own_supply'))
self.max: ActivePricePattern = ActivePricePattern(client, _m(acc, 'max_cost_basis'))
self.min: ActivePricePattern = ActivePricePattern(client, _m(acc, 'min_cost_basis'))
self.percentiles: PercentilesPattern = PercentilesPattern(client, _m(acc, 'cost_basis'))
class ActivePricePattern:
"""Pattern struct for repeated tree structure."""
@@ -2391,13 +2383,13 @@ class ActivePricePattern:
self.dollars: MetricPattern1[Dollars] = MetricPattern1(client, acc)
self.sats: MetricPattern1[SatsFract] = MetricPattern1(client, _m(acc, 'sats'))
class _1dReturns1mSdPattern:
class _0sdUsdPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd'))
self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma'))
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, acc)
self.sats: MetricPattern4[SatsFract] = MetricPattern4(client, _m(acc, 'sats'))
class SupplyPattern2:
"""Pattern struct for repeated tree structure."""
@@ -2407,14 +2399,6 @@ class SupplyPattern2:
self.halved: ActiveSupplyPattern = ActiveSupplyPattern(client, _m(acc, 'halved'))
self.total: ActiveSupplyPattern = ActiveSupplyPattern(client, acc)
class _0sdUsdPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.dollars: MetricPattern4[Dollars] = MetricPattern4(client, acc)
self.sats: MetricPattern4[SatsFract] = MetricPattern4(client, _m(acc, 'sats'))
class CostBasisPattern:
"""Pattern struct for repeated tree structure."""
@@ -2423,6 +2407,22 @@ class CostBasisPattern:
self.max: ActivePricePattern = ActivePricePattern(client, _m(acc, 'max_cost_basis'))
self.min: ActivePricePattern = ActivePricePattern(client, _m(acc, 'min_cost_basis'))
class _1dReturns1mSdPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.sd: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sd'))
self.sma: MetricPattern4[StoredF32] = MetricPattern4(client, _m(acc, 'sma'))
class RelativePattern4:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.supply_in_loss_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'loss_rel_to_own_supply'))
self.supply_in_profit_rel_to_own_supply: MetricPattern1[StoredF64] = MetricPattern1(client, _m(acc, 'profit_rel_to_own_supply'))
class BlockCountPattern(Generic[T]):
"""Pattern struct for repeated tree structure."""
@@ -2447,13 +2447,6 @@ class SatsPattern(Generic[T]):
self.ohlc: MetricPattern1[T] = MetricPattern1(client, _m(acc, 'ohlc_sats'))
self.split: SplitPattern2[T] = SplitPattern2(client, _m(acc, 'sats'))
class OutputsPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, acc)
class RealizedPriceExtraPattern:
"""Pattern struct for repeated tree structure."""
@@ -2461,6 +2454,13 @@ class RealizedPriceExtraPattern:
"""Create pattern node with accumulated metric name."""
self.ratio: MetricPattern4[StoredF32] = MetricPattern4(client, acc)
class OutputsPattern:
"""Pattern struct for repeated tree structure."""
def __init__(self, client: BrkClientBase, acc: str):
"""Create pattern node with accumulated metric name."""
self.utxo_count: MetricPattern1[StoredU64] = MetricPattern1(client, acc)
# Metrics tree classes
class MetricsTree_Addresses:
@@ -3384,6 +3384,23 @@ class MetricsTree_Market_Dca_ClassDaysInLoss:
self._2025: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2025_days_in_loss')
self._2026: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2026_days_in_loss')
class MetricsTree_Market_Dca_ClassDaysInProfit:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self._2015: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2015_days_in_profit')
self._2016: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2016_days_in_profit')
self._2017: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2017_days_in_profit')
self._2018: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2018_days_in_profit')
self._2019: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2019_days_in_profit')
self._2020: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2020_days_in_profit')
self._2021: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2021_days_in_profit')
self._2022: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2022_days_in_profit')
self._2023: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2023_days_in_profit')
self._2024: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2024_days_in_profit')
self._2025: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2025_days_in_profit')
self._2026: MetricPattern4[StoredU32] = MetricPattern4(client, 'dca_class_2026_days_in_profit')
class MetricsTree_Market_Dca_ClassMaxDrawdown:
"""Metrics tree node."""
@@ -3418,23 +3435,6 @@ class MetricsTree_Market_Dca_ClassMaxReturn:
self._2025: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2025_max_return')
self._2026: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2026_max_return')
class MetricsTree_Market_Dca_ClassReturns:
"""Metrics tree node."""
def __init__(self, client: BrkClientBase, base_path: str = ''):
self._2015: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2015_returns')
self._2016: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2016_returns')
self._2017: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2017_returns')
self._2018: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2018_returns')
self._2019: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2019_returns')
self._2020: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2020_returns')
self._2021: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2021_returns')
self._2022: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2022_returns')
self._2023: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2023_returns')
self._2024: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2024_returns')
self._2025: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2025_returns')
self._2026: MetricPattern4[StoredF32] = MetricPattern4(client, 'dca_class_2026_returns')
class MetricsTree_Market_Dca_ClassStack:
"""Metrics tree node."""
@@ -3475,10 +3475,10 @@ class MetricsTree_Market_Dca:
def __init__(self, client: BrkClientBase, base_path: str = ''):
self.class_average_price: MetricsTree_Market_Dca_ClassAveragePrice = MetricsTree_Market_Dca_ClassAveragePrice(client)
self.class_days_in_loss: MetricsTree_Market_Dca_ClassDaysInLoss = MetricsTree_Market_Dca_ClassDaysInLoss(client)
self.class_days_in_profit: ClassDaysInLossPattern[StoredU32] = ClassDaysInLossPattern(client, 'dca_class')
self.class_days_in_profit: MetricsTree_Market_Dca_ClassDaysInProfit = MetricsTree_Market_Dca_ClassDaysInProfit(client)
self.class_max_drawdown: MetricsTree_Market_Dca_ClassMaxDrawdown = MetricsTree_Market_Dca_ClassMaxDrawdown(client)
self.class_max_return: MetricsTree_Market_Dca_ClassMaxReturn = MetricsTree_Market_Dca_ClassMaxReturn(client)
self.class_returns: MetricsTree_Market_Dca_ClassReturns = MetricsTree_Market_Dca_ClassReturns(client)
self.class_returns: ClassDaysInLossPattern[StoredF32] = ClassDaysInLossPattern(client, 'dca_class')
self.class_stack: MetricsTree_Market_Dca_ClassStack = MetricsTree_Market_Dca_ClassStack(client)
self.period_average_price: MetricsTree_Market_Dca_PeriodAveragePrice = MetricsTree_Market_Dca_PeriodAveragePrice(client)
self.period_cagr: PeriodCagrPattern = PeriodCagrPattern(client, 'dca_cagr')
@@ -4052,7 +4052,7 @@ class MetricsTree:
class BrkClient(BrkClientBase):
"""Main BRK client with metrics tree and API methods."""
VERSION = "v0.1.0"
VERSION = "v0.1.1"
INDEXES = [
"dateindex",