crates: snapshot

This commit is contained in:
nym21
2025-12-30 18:09:08 +01:00
parent bd376f86ea
commit 8cff55a405
176 changed files with 7317 additions and 4539 deletions

View File

@@ -67,12 +67,26 @@ fn update_package_json_version(package_json_path: &Path) -> io::Result<()> {
Ok(())
}
/// Convert only top-level object keys to camelCase (for consistency with tree field names)
/// Nested values (including id fields) are left unchanged for URL paths
fn camel_case_top_level_keys(value: Value) -> Value {
match value {
Value::Object(map) => {
let new_map: serde_json::Map<String, Value> = map
.into_iter()
.map(|(k, v)| (to_camel_case(&k), v))
.collect();
Value::Object(new_map)
}
other => other,
}
}
fn generate_static_constants(output: &mut String) {
use serde::Serialize;
fn static_const<T: Serialize>(output: &mut String, name: &str, value: &T) {
fn instance_const<T: Serialize>(output: &mut String, name: &str, value: &T) {
let json = serde_json::to_string_pretty(value).unwrap();
// Indent the JSON for proper formatting inside the class
let indented = json
.lines()
.enumerate()
@@ -87,23 +101,23 @@ fn generate_static_constants(output: &mut String) {
.join("\n");
writeln!(
output,
" static {} = /** @type {{const}} */ ({});\n",
" {} = /** @type {{const}} */ ({});\n",
name, indented
)
.unwrap();
}
fn static_const_raw(output: &mut String, name: &str, value: &str) {
writeln!(output, " static {} = {};\n", name, value).unwrap();
fn instance_const_raw(output: &mut String, name: &str, value: &str) {
writeln!(output, " {} = {};\n", name, value).unwrap();
}
// VERSION
static_const_raw(output, "VERSION", &format!("\"v{}\"", VERSION));
instance_const_raw(output, "VERSION", &format!("\"v{}\"", VERSION));
// INDEXES
let indexes = Index::all();
let indexes_json: Vec<&'static str> = indexes.iter().map(|i| i.serialize_long()).collect();
static_const(output, "INDEXES", &indexes_json);
instance_const(output, "INDEXES", &indexes_json);
// POOL_ID_TO_POOL_NAME
let pools = pools();
@@ -111,19 +125,43 @@ fn generate_static_constants(output: &mut String) {
sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
let pool_map: std::collections::BTreeMap<PoolSlug, &'static str> =
sorted_pools.iter().map(|p| (p.slug(), p.name)).collect();
static_const(output, "POOL_ID_TO_POOL_NAME", &pool_map);
instance_const(output, "POOL_ID_TO_POOL_NAME", &pool_map);
// Cohort names
static_const(output, "TERM_NAMES", &TERM_NAMES);
static_const(output, "EPOCH_NAMES", &EPOCH_NAMES);
static_const(output, "YEAR_NAMES", &YEAR_NAMES);
static_const(output, "SPENDABLE_TYPE_NAMES", &SPENDABLE_TYPE_NAMES);
static_const(output, "AGE_RANGE_NAMES", &AGE_RANGE_NAMES);
static_const(output, "MAX_AGE_NAMES", &MAX_AGE_NAMES);
static_const(output, "MIN_AGE_NAMES", &MIN_AGE_NAMES);
static_const(output, "AMOUNT_RANGE_NAMES", &AMOUNT_RANGE_NAMES);
static_const(output, "GE_AMOUNT_NAMES", &GE_AMOUNT_NAMES);
static_const(output, "LT_AMOUNT_NAMES", &LT_AMOUNT_NAMES);
// Cohort names - top-level keys converted to camelCase to match tree field names
fn instance_const_camel<T: Serialize>(output: &mut String, name: &str, value: &T) {
let json_value: Value = serde_json::to_value(value).unwrap();
let camel_value = camel_case_top_level_keys(json_value);
let json = serde_json::to_string_pretty(&camel_value).unwrap();
let indented = json
.lines()
.enumerate()
.map(|(i, line)| {
if i == 0 {
line.to_string()
} else {
format!(" {}", line)
}
})
.collect::<Vec<_>>()
.join("\n");
writeln!(
output,
" {} = /** @type {{const}} */ ({});\n",
name, indented
)
.unwrap();
}
instance_const_camel(output, "TERM_NAMES", &TERM_NAMES);
instance_const_camel(output, "EPOCH_NAMES", &EPOCH_NAMES);
instance_const_camel(output, "YEAR_NAMES", &YEAR_NAMES);
instance_const_camel(output, "SPENDABLE_TYPE_NAMES", &SPENDABLE_TYPE_NAMES);
instance_const_camel(output, "AGE_RANGE_NAMES", &AGE_RANGE_NAMES);
instance_const_camel(output, "MAX_AGE_NAMES", &MAX_AGE_NAMES);
instance_const_camel(output, "MIN_AGE_NAMES", &MIN_AGE_NAMES);
instance_const_camel(output, "AMOUNT_RANGE_NAMES", &AMOUNT_RANGE_NAMES);
instance_const_camel(output, "GE_AMOUNT_NAMES", &GE_AMOUNT_NAMES);
instance_const_camel(output, "LT_AMOUNT_NAMES", &LT_AMOUNT_NAMES);
}
fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {

View File

@@ -1,240 +0,0 @@
use std::{
collections::{BTreeMap, HashMap},
fs, io,
path::Path,
};
use brk_query::Query;
use brk_types::{Index, pools};
use crate::VERSION;
const AUTO_GENERATED_DISCLAIMER: &str = "//
// File auto-generated, any modifications will be overwritten
//";
pub fn generate_js_files(query: &Query, modules_path: &Path) -> io::Result<()> {
let path = modules_path.join("brk-client");
if !fs::exists(&path)? {
return Ok(());
}
let path = path.join("generated");
fs::create_dir_all(&path)?;
generate_version_file(&path)?;
generate_metrics_file(query, &path)?;
generate_pools_file(&path)
}
fn generate_version_file(parent: &Path) -> io::Result<()> {
let path = parent.join(Path::new("version.js"));
let contents = format!(
"{AUTO_GENERATED_DISCLAIMER}
export const VERSION = \"v{VERSION}\";
"
);
fs::write(path, contents)
}
fn generate_pools_file(parent: &Path) -> io::Result<()> {
let path = parent.join(Path::new("pools.js"));
let pools = pools();
let mut contents = format!("{AUTO_GENERATED_DISCLAIMER}\n");
contents += "
/**
* @typedef {typeof POOL_ID_TO_POOL_NAME} PoolIdToPoolName
* @typedef {keyof PoolIdToPoolName} PoolId
*/
export const POOL_ID_TO_POOL_NAME = /** @type {const} */ ({
";
let mut sorted_pools: Vec<_> = pools.iter().collect();
sorted_pools.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
contents += &sorted_pools
.iter()
.map(|pool| {
let slug = pool.slug();
format!(" {slug}: \"{}\",", pool.name)
})
.collect::<Vec<_>>()
.join("\n");
contents += "\n});\n";
fs::write(path, contents)
}
fn generate_metrics_file(query: &Query, parent: &Path) -> io::Result<()> {
let path = parent.join(Path::new("metrics.js"));
let indexes = Index::all();
let mut contents = format!(
"{AUTO_GENERATED_DISCLAIMER}
export const INDEXES = /** @type {{const}} */ ([
{}
]);
/**
* @typedef {{typeof INDEXES[number]}} IndexName
*/
",
indexes
.iter()
.map(|i| format!(" \"{}\"", i.serialize_long()))
.collect::<Vec<_>>()
.join(",\n")
);
// contents += &indexes
// .iter()
// .map(|i| format!(" * @typedef {{\"{}\"}} {i}", i.serialize_long()))
// .collect::<Vec<_>>()
// .join("\n");
// contents += &format!(
// "
// * @typedef {{{}}} Index
// */
// ",
// indexes
// .iter()
// .map(|i| i.to_string())
// .collect::<Vec<_>>()
// .join(" | ")
// );
let mut unique_index_groups = BTreeMap::new();
let mut word_to_freq: BTreeMap<_, usize> = BTreeMap::new();
query.metric_to_index_to_vec().keys().for_each(|metric| {
metric.split("_").for_each(|word| {
*word_to_freq.entry(word).or_default() += 1;
});
});
let mut word_to_freq = word_to_freq.into_iter().collect::<Vec<_>>();
word_to_freq.sort_unstable_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(b.0)));
let words = word_to_freq
.into_iter()
.map(|(str, _)| str)
.collect::<Vec<_>>();
contents += &format!(
"
export const INDEX_TO_WORD = [
{}
];
",
words
.iter()
.enumerate()
.map(|(index, word)| format!("\"{word}\", // {}", index_to_letters(index)))
.collect::<Vec<_>>()
.join("\n ")
);
let word_to_base62 = words
.into_iter()
.enumerate()
.map(|(i, w)| (w, index_to_letters(i)))
.collect::<HashMap<_, _>>();
let mut ser_metric_to_indexes = "
/** @type {Record<string, IndexName[]>} */
export const COMPRESSED_METRIC_TO_INDEXES = {
"
.to_string();
query
.metric_to_index_to_vec()
.iter()
.for_each(|(metric, index_to_vec)| {
let indexes = index_to_vec
.keys()
.map(|i| format!("\"{}\"", i.serialize_long()))
.collect::<Vec<_>>()
.join(", ");
let indexes = format!("[{indexes}]");
let unique = unique_index_groups.len();
let index = index_to_letters(*unique_index_groups.entry(indexes).or_insert(unique));
let compressed_metric = metric.split('_').fold(String::new(), |mut acc, w| {
if !acc.is_empty() {
acc.push('_');
}
acc.push_str(&word_to_base62[w]);
acc
});
ser_metric_to_indexes += &format!(" {compressed_metric}: {index},\n");
});
ser_metric_to_indexes += "};
";
let mut sorted_groups: Vec<_> = unique_index_groups.into_iter().collect();
sorted_groups.sort_by_key(|(_, index)| *index);
sorted_groups.into_iter().for_each(|(group, index)| {
let index = index_to_letters(index);
contents += &format!("/** @type {{IndexName[]}} */\nconst {index} = {group};\n");
});
contents += &ser_metric_to_indexes;
fs::write(path, contents)
}
fn index_to_letters(mut index: usize) -> String {
if index < 52 {
return (index_to_char(index) as char).to_string();
}
let mut result = [0u8; 8];
let mut pos = 8;
loop {
pos -= 1;
result[pos] = index_to_char(index % 52);
index /= 52;
if index == 0 {
break;
}
index -= 1;
}
unsafe { String::from_utf8_unchecked(result[pos..].to_vec()) }
}
fn index_to_char(index: usize) -> u8 {
match index {
0..=25 => b'A' + index as u8,
26..=51 => b'a' + (index - 26) as u8,
_ => unreachable!(),
}
}
// fn letters_to_index(s: &str) -> usize {
// let mut result = 0;
// for byte in s.bytes() {
// let value = char_to_index(byte) as usize;
// result = result * 52 + value + 1;
// }
// result - 1
// }
// fn char_to_index(byte: u8) -> u8 {
// match byte {
// b'A'..=b'Z' => byte - b'A',
// b'a'..=b'z' => byte - b'a' + 26,
// _ => 255, // Invalid
// }
// }

View File

@@ -23,7 +23,8 @@ pub fn generate_rust_client(
writeln!(output, "#![allow(non_camel_case_types)]").unwrap();
writeln!(output, "#![allow(dead_code)]").unwrap();
writeln!(output, "#![allow(unused_variables)]").unwrap();
writeln!(output, "#![allow(clippy::useless_format)]\n").unwrap();
writeln!(output, "#![allow(clippy::useless_format)]").unwrap();
writeln!(output, "#![allow(clippy::unnecessary_to_owned)]\n").unwrap();
generate_imports(&mut output);
generate_base_client(&mut output);

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@ fn run() -> Result<()> {
let computer = Computer::forced_import(&outputs_dir, &indexer, Some(fetcher))?;
let _a = dbg!(computer.chain.txindex_to_fee.region().meta());
let _a = dbg!(computer.chain.transaction.txindex_to_fee.region().meta());
Ok(())
}

View File

@@ -0,0 +1,139 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{CheckedSub, Height, StoredU32, StoredU64, Timestamp};
use vecdb::{Exit, TypedVecIterator};
use super::Vecs;
use crate::{Indexes, indexes};
impl Vecs {
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let mut height_to_timestamp_fixed_iter =
indexes.block.height_to_timestamp_fixed.into_iter();
let mut prev = Height::ZERO;
self.height_to_24h_block_count.compute_transform(
starting_indexes.height,
&indexes.block.height_to_timestamp_fixed,
|(h, t, ..)| {
while t.difference_in_days_between(height_to_timestamp_fixed_iter.get_unwrap(prev))
> 0
{
prev.increment();
if prev > h {
unreachable!()
}
}
(h, StoredU32::from(*h + 1 - *prev))
},
exit,
)?;
self.indexes_to_block_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_range(
starting_indexes.height,
&indexer.vecs.block.height_to_weight,
|h| (h, StoredU32::from(1_u32)),
exit,
)?;
Ok(())
})?;
self.indexes_to_1w_block_count
.compute_all(starting_indexes, exit, |v| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_block_count.dateindex.unwrap_sum(),
7,
exit,
)?;
Ok(())
})?;
self.indexes_to_1m_block_count
.compute_all(starting_indexes, exit, |v| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_block_count.dateindex.unwrap_sum(),
30,
exit,
)?;
Ok(())
})?;
self.indexes_to_1y_block_count
.compute_all(starting_indexes, exit, |v| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_block_count.dateindex.unwrap_sum(),
365,
exit,
)?;
Ok(())
})?;
let mut height_to_timestamp_iter = indexer.vecs.block.height_to_timestamp.iter()?;
self.height_to_interval.compute_transform(
starting_indexes.height,
&indexer.vecs.block.height_to_timestamp,
|(height, timestamp, ..)| {
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
let prev_timestamp = height_to_timestamp_iter.get_unwrap(prev_h);
timestamp
.checked_sub(prev_timestamp)
.unwrap_or(Timestamp::ZERO)
});
(height, interval)
},
exit,
)?;
self.indexes_to_block_interval.compute_rest(
indexes,
starting_indexes,
exit,
Some(&self.height_to_interval),
)?;
self.indexes_to_block_weight.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.block.height_to_weight),
)?;
self.indexes_to_block_size.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.block.height_to_total_size),
)?;
self.height_to_vbytes.compute_transform(
starting_indexes.height,
&indexer.vecs.block.height_to_weight,
|(h, w, ..)| {
(
h,
StoredU64::from(bitcoin::Weight::from(w).to_vbytes_floor()),
)
},
exit,
)?;
self.indexes_to_block_vbytes.compute_rest(
indexes,
starting_indexes,
exit,
Some(&self.height_to_vbytes),
)?;
Ok(())
}
}

View File

@@ -0,0 +1,171 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{StoredU64, Version};
use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec, LazyVecFrom1};
use super::Vecs;
use crate::{
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source, VecBuilderOptions},
indexes,
};
use crate::chain::{
TARGET_BLOCKS_PER_DAY, TARGET_BLOCKS_PER_DECADE, TARGET_BLOCKS_PER_MONTH,
TARGET_BLOCKS_PER_QUARTER, TARGET_BLOCKS_PER_SEMESTER, TARGET_BLOCKS_PER_WEEK,
TARGET_BLOCKS_PER_YEAR,
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let last = || VecBuilderOptions::default().add_last();
let sum_cum = || VecBuilderOptions::default().add_sum().add_cumulative();
let stats = || {
VecBuilderOptions::default()
.add_average()
.add_minmax()
.add_percentiles()
};
let full_stats = || {
VecBuilderOptions::default()
.add_average()
.add_minmax()
.add_percentiles()
.add_sum()
.add_cumulative()
};
let dateindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + v0,
indexes.time.dateindex_to_dateindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)),
);
let weekindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + v0,
indexes.time.weekindex_to_weekindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)),
);
let monthindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + v0,
indexes.time.monthindex_to_monthindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)),
);
let quarterindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + v0,
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)),
);
let semesterindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + v0,
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)),
);
let yearindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + v0,
indexes.time.yearindex_to_yearindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)),
);
let decadeindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + v0,
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)),
);
let height_to_interval = EagerVec::forced_import(db, "interval", version + v0)?;
let height_to_vbytes = EagerVec::forced_import(db, "vbytes", version + v0)?;
Ok(Self {
dateindex_to_block_count_target,
weekindex_to_block_count_target,
monthindex_to_block_count_target,
quarterindex_to_block_count_target,
semesterindex_to_block_count_target,
yearindex_to_block_count_target,
decadeindex_to_block_count_target,
height_to_interval: height_to_interval.clone(),
height_to_24h_block_count: EagerVec::forced_import(
db,
"24h_block_count",
version + v0,
)?,
height_to_vbytes: height_to_vbytes.clone(),
indexes_to_block_count: ComputedVecsFromHeight::forced_import(
db,
"block_count",
Source::Compute,
version + v0,
indexes,
sum_cum(),
)?,
indexes_to_1w_block_count: ComputedVecsFromDateIndex::forced_import(
db,
"1w_block_count",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_1m_block_count: ComputedVecsFromDateIndex::forced_import(
db,
"1m_block_count",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_1y_block_count: ComputedVecsFromDateIndex::forced_import(
db,
"1y_block_count",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_block_interval: ComputedVecsFromHeight::forced_import(
db,
"block_interval",
Source::Vec(height_to_interval.boxed_clone()),
version + v0,
indexes,
stats(),
)?,
indexes_to_block_size: ComputedVecsFromHeight::forced_import(
db,
"block_size",
Source::Vec(indexer.vecs.block.height_to_total_size.boxed_clone()),
version + v0,
indexes,
full_stats(),
)?,
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
db,
"block_vbytes",
Source::Vec(height_to_vbytes.boxed_clone()),
version + v0,
indexes,
full_stats(),
)?,
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
db,
"block_weight",
Source::Vec(indexer.vecs.block.height_to_weight.boxed_clone()),
version + v0,
indexes,
full_stats(),
)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,35 @@
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, StoredU32, StoredU64,
Timestamp, WeekIndex, Weight, YearIndex,
};
use vecdb::{EagerVec, LazyVecFrom1, PcoVec};
use crate::grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight};
/// Block-related metrics: count, interval, size, weight, vbytes
#[derive(Clone, Traversable)]
pub struct Vecs {
pub dateindex_to_block_count_target: LazyVecFrom1<DateIndex, StoredU64, DateIndex, DateIndex>,
pub weekindex_to_block_count_target: LazyVecFrom1<WeekIndex, StoredU64, WeekIndex, WeekIndex>,
pub monthindex_to_block_count_target:
LazyVecFrom1<MonthIndex, StoredU64, MonthIndex, MonthIndex>,
pub quarterindex_to_block_count_target:
LazyVecFrom1<QuarterIndex, StoredU64, QuarterIndex, QuarterIndex>,
pub semesterindex_to_block_count_target:
LazyVecFrom1<SemesterIndex, StoredU64, SemesterIndex, SemesterIndex>,
pub yearindex_to_block_count_target: LazyVecFrom1<YearIndex, StoredU64, YearIndex, YearIndex>,
pub decadeindex_to_block_count_target:
LazyVecFrom1<DecadeIndex, StoredU64, DecadeIndex, DecadeIndex>,
pub height_to_interval: EagerVec<PcoVec<Height, Timestamp>>,
pub height_to_24h_block_count: EagerVec<PcoVec<Height, StoredU32>>,
pub height_to_vbytes: EagerVec<PcoVec<Height, StoredU64>>,
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_1w_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_1m_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_1y_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
}

View File

@@ -0,0 +1,225 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{CheckedSub, Dollars, HalvingEpoch, Height, Sats, StoredF32, TxOutIndex};
use vecdb::{Exit, IterableVec, TypedVecIterator, VecIndex};
use super::Vecs;
use crate::{
Indexes,
chain::{block, transaction},
indexes, price,
utils::OptionExt,
};
impl Vecs {
#[allow(clippy::too_many_arguments)]
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
block_vecs: &block::Vecs,
transaction_vecs: &transaction::Vecs,
starting_indexes: &Indexes,
price: Option<&price::Vecs>,
exit: &Exit,
) -> Result<()> {
self.indexes_to_coinbase
.compute_all(indexes, price, starting_indexes, exit, |vec| {
let mut txindex_to_first_txoutindex_iter =
indexer.vecs.tx.txindex_to_first_txoutindex.iter()?;
let mut txindex_to_output_count_iter =
indexes.transaction.txindex_to_output_count.iter();
let mut txoutindex_to_value_iter = indexer.vecs.txout.txoutindex_to_value.iter()?;
vec.compute_transform(
starting_indexes.height,
&indexer.vecs.tx.height_to_first_txindex,
|(height, txindex, ..)| {
let first_txoutindex = txindex_to_first_txoutindex_iter
.get_unwrap(txindex)
.to_usize();
let output_count = txindex_to_output_count_iter.get_unwrap(txindex);
let mut sats = Sats::ZERO;
(first_txoutindex..first_txoutindex + usize::from(output_count)).for_each(
|txoutindex| {
sats += txoutindex_to_value_iter
.get_unwrap(TxOutIndex::from(txoutindex));
},
);
(height, sats)
},
exit,
)?;
Ok(())
})?;
let mut height_to_coinbase_iter = self
.indexes_to_coinbase
.sats
.height
.as_ref()
.unwrap()
.into_iter();
self.height_to_24h_coinbase_sum.compute_transform(
starting_indexes.height,
&block_vecs.height_to_24h_block_count,
|(h, count, ..)| {
let range = *h - (*count - 1)..=*h;
let sum = range
.map(Height::from)
.map(|h| height_to_coinbase_iter.get_unwrap(h))
.sum::<Sats>();
(h, sum)
},
exit,
)?;
drop(height_to_coinbase_iter);
if let Some(mut height_to_coinbase_iter) = self
.indexes_to_coinbase
.dollars
.as_ref()
.map(|c| c.height.u().into_iter())
{
self.height_to_24h_coinbase_usd_sum.compute_transform(
starting_indexes.height,
&block_vecs.height_to_24h_block_count,
|(h, count, ..)| {
let range = *h - (*count - 1)..=*h;
let sum = range
.map(Height::from)
.map(|h| height_to_coinbase_iter.get_unwrap(h))
.sum::<Dollars>();
(h, sum)
},
exit,
)?;
}
self.indexes_to_subsidy
.compute_all(indexes, price, starting_indexes, exit, |vec| {
vec.compute_transform2(
starting_indexes.height,
self.indexes_to_coinbase.sats.height.u(),
transaction_vecs.indexes_to_fee.sats.height.unwrap_sum(),
|(height, coinbase, fees, ..)| {
(
height,
coinbase.checked_sub(fees).unwrap_or_else(|| {
dbg!(height, coinbase, fees);
panic!()
}),
)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_unclaimed_rewards.compute_all(
indexes,
price,
starting_indexes,
exit,
|vec| {
vec.compute_transform(
starting_indexes.height,
self.indexes_to_subsidy.sats.height.u(),
|(height, subsidy, ..)| {
let halving = HalvingEpoch::from(height);
let expected = Sats::FIFTY_BTC / 2_usize.pow(halving.to_usize() as u32);
(height, expected.checked_sub(subsidy).unwrap())
},
exit,
)?;
Ok(())
},
)?;
self.indexes_to_inflation_rate
.compute_all(starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.dateindex,
self.indexes_to_subsidy.sats.dateindex.unwrap_sum(),
self.indexes_to_subsidy.sats.dateindex.unwrap_cumulative(),
|(i, subsidy_1d_sum, subsidy_cumulative, ..)| {
(
i,
(365.0 * *subsidy_1d_sum as f64 / *subsidy_cumulative as f64 * 100.0)
.into(),
)
},
exit,
)?;
Ok(())
})?;
self.dateindex_to_fee_dominance.compute_transform2(
starting_indexes.dateindex,
transaction_vecs.indexes_to_fee.sats.dateindex.unwrap_sum(),
self.indexes_to_coinbase.sats.dateindex.unwrap_sum(),
|(i, fee, coinbase, ..)| {
(
i,
StoredF32::from(u64::from(fee) as f64 / u64::from(coinbase) as f64 * 100.0),
)
},
exit,
)?;
self.dateindex_to_subsidy_dominance.compute_transform2(
starting_indexes.dateindex,
self.indexes_to_subsidy.sats.dateindex.unwrap_sum(),
self.indexes_to_coinbase.sats.dateindex.unwrap_sum(),
|(i, subsidy, coinbase, ..)| {
(
i,
StoredF32::from(u64::from(subsidy) as f64 / u64::from(coinbase) as f64 * 100.0),
)
},
exit,
)?;
if self.indexes_to_subsidy_usd_1y_sma.is_some() {
let date_to_coinbase_usd_sum = self
.indexes_to_coinbase
.dollars
.as_ref()
.unwrap()
.dateindex
.unwrap_sum();
self.indexes_to_subsidy_usd_1y_sma
.as_mut()
.unwrap()
.compute_all(starting_indexes, exit, |v| {
v.compute_sma(
starting_indexes.dateindex,
date_to_coinbase_usd_sum,
365,
exit,
)?;
Ok(())
})?;
self.indexes_to_puell_multiple
.as_mut()
.unwrap()
.compute_all(starting_indexes, exit, |v| {
v.compute_divide(
starting_indexes.dateindex,
date_to_coinbase_usd_sum,
self.indexes_to_subsidy_usd_1y_sma
.as_ref()
.unwrap()
.dateindex
.as_ref()
.unwrap(),
exit,
)?;
Ok(())
})?;
}
Ok(())
}
}

View File

@@ -0,0 +1,109 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::{Database, EagerVec, ImportableVec};
use super::Vecs;
use crate::{
grouped::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions},
indexes,
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v0 = Version::ZERO;
let last = || VecBuilderOptions::default().add_last();
Ok(Self {
height_to_24h_coinbase_sum: EagerVec::forced_import(
db,
"24h_coinbase_sum",
version + v0,
)?,
height_to_24h_coinbase_usd_sum: EagerVec::forced_import(
db,
"24h_coinbase_usd_sum",
version + v0,
)?,
indexes_to_coinbase: ComputedValueVecsFromHeight::forced_import(
db,
"coinbase",
Source::Compute,
version + v0,
VecBuilderOptions::default()
.add_sum()
.add_cumulative()
.add_percentiles()
.add_minmax()
.add_average(),
compute_dollars,
indexes,
)?,
indexes_to_subsidy: ComputedValueVecsFromHeight::forced_import(
db,
"subsidy",
Source::Compute,
version + v0,
VecBuilderOptions::default()
.add_percentiles()
.add_sum()
.add_cumulative()
.add_minmax()
.add_average(),
compute_dollars,
indexes,
)?,
indexes_to_unclaimed_rewards: ComputedValueVecsFromHeight::forced_import(
db,
"unclaimed_rewards",
Source::Compute,
version + v0,
VecBuilderOptions::default().add_sum().add_cumulative(),
compute_dollars,
indexes,
)?,
dateindex_to_fee_dominance: EagerVec::forced_import(db, "fee_dominance", version + v0)?,
dateindex_to_subsidy_dominance: EagerVec::forced_import(
db,
"subsidy_dominance",
version + v0,
)?,
indexes_to_subsidy_usd_1y_sma: compute_dollars
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
"subsidy_usd_1y_sma",
Source::Compute,
version + v0,
indexes,
last(),
)
})
.transpose()?,
indexes_to_puell_multiple: compute_dollars
.then(|| {
ComputedVecsFromDateIndex::forced_import(
db,
"puell_multiple",
Source::Compute,
version + v0,
indexes,
last(),
)
})
.transpose()?,
indexes_to_inflation_rate: ComputedVecsFromDateIndex::forced_import(
db,
"inflation_rate",
Source::Compute,
version + v0,
indexes,
last(),
)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,20 @@
use brk_traversable::Traversable;
use brk_types::{DateIndex, Dollars, Height, Sats, StoredF32};
use vecdb::{EagerVec, PcoVec};
use crate::grouped::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex};
/// Coinbase/subsidy/rewards metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub height_to_24h_coinbase_sum: EagerVec<PcoVec<Height, Sats>>,
pub height_to_24h_coinbase_usd_sum: EagerVec<PcoVec<Height, Dollars>>,
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
pub indexes_to_subsidy: ComputedValueVecsFromHeight,
pub indexes_to_unclaimed_rewards: ComputedValueVecsFromHeight,
pub dateindex_to_fee_dominance: EagerVec<PcoVec<DateIndex, StoredF32>>,
pub dateindex_to_subsidy_dominance: EagerVec<PcoVec<DateIndex, StoredF32>>,
pub indexes_to_subsidy_usd_1y_sma: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_puell_multiple: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_inflation_rate: ComputedVecsFromDateIndex<StoredF32>,
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,85 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::Timestamp;
use vecdb::{Exit, TypedVecIterator};
use super::Vecs;
use crate::{Indexes, indexes};
impl Vecs {
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.timeindexes_to_timestamp
.compute_all(starting_indexes, exit, |vec| {
vec.compute_transform(
starting_indexes.dateindex,
&indexes.time.dateindex_to_date,
|(di, d, ..)| (di, Timestamp::from(d)),
exit,
)?;
Ok(())
})?;
let mut height_to_timestamp_iter = indexer.vecs.block.height_to_timestamp.iter()?;
self.difficultyepoch_to_timestamp.compute_transform(
starting_indexes.difficultyepoch,
&indexes.block.difficultyepoch_to_first_height,
|(i, h, ..)| (i, height_to_timestamp_iter.get_unwrap(h)),
exit,
)?;
self.halvingepoch_to_timestamp.compute_transform(
starting_indexes.halvingepoch,
&indexes.block.halvingepoch_to_first_height,
|(i, h, ..)| (i, height_to_timestamp_iter.get_unwrap(h)),
exit,
)?;
let mut height_to_difficultyepoch_iter =
indexes.block.height_to_difficultyepoch.into_iter();
self.indexes_to_difficultyepoch
.compute_all(starting_indexes, exit, |vec| {
let mut height_count_iter = indexes.time.dateindex_to_height_count.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&indexes.time.dateindex_to_first_height,
|(di, height, ..)| {
(
di,
height_to_difficultyepoch_iter
.get_unwrap(height + (*height_count_iter.get_unwrap(di) - 1)),
)
},
exit,
)?;
Ok(())
})?;
let mut height_to_halvingepoch_iter = indexes.block.height_to_halvingepoch.into_iter();
self.indexes_to_halvingepoch
.compute_all(starting_indexes, exit, |vec| {
let mut height_count_iter = indexes.time.dateindex_to_height_count.into_iter();
vec.compute_transform(
starting_indexes.dateindex,
&indexes.time.dateindex_to_first_height,
|(di, height, ..)| {
(
di,
height_to_halvingepoch_iter
.get_unwrap(height + (*height_count_iter.get_unwrap(di) - 1)),
)
},
exit,
)?;
Ok(())
})?;
Ok(())
}
}

View File

@@ -0,0 +1,45 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::{Database, EagerVec, ImportableVec};
use super::Vecs;
use crate::{
grouped::{ComputedVecsFromDateIndex, Source, VecBuilderOptions},
indexes,
};
impl Vecs {
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let v0 = Version::ZERO;
let last = || VecBuilderOptions::default().add_last();
Ok(Self {
difficultyepoch_to_timestamp: EagerVec::forced_import(db, "timestamp", version + v0)?,
halvingepoch_to_timestamp: EagerVec::forced_import(db, "timestamp", version + v0)?,
timeindexes_to_timestamp: ComputedVecsFromDateIndex::forced_import(
db,
"timestamp",
Source::Compute,
version + v0,
indexes,
VecBuilderOptions::default().add_first(),
)?,
indexes_to_difficultyepoch: ComputedVecsFromDateIndex::forced_import(
db,
"difficultyepoch",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_halvingepoch: ComputedVecsFromDateIndex::forced_import(
db,
"halvingepoch",
Source::Compute,
version + v0,
indexes,
last(),
)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,15 @@
use brk_traversable::Traversable;
use brk_types::{DifficultyEpoch, HalvingEpoch, Timestamp};
use vecdb::{EagerVec, PcoVec};
use crate::grouped::ComputedVecsFromDateIndex;
/// Epoch and timestamp metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub difficultyepoch_to_timestamp: EagerVec<PcoVec<DifficultyEpoch, Timestamp>>,
pub halvingepoch_to_timestamp: EagerVec<PcoVec<HalvingEpoch, Timestamp>>,
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
}

View File

@@ -3,24 +3,14 @@ use std::path::Path;
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{StoredBool, StoredU64, TxIndex, Version, Weight};
use vecdb::{
Database, EagerVec, ImportableVec, IterableCloneableVec, LazyVecFrom1, LazyVecFrom2, PAGE_SIZE,
VecIndex,
};
use brk_types::Version;
use vecdb::{Database, PAGE_SIZE};
use crate::{
grouped::{
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromDateIndex,
ComputedVecsFromHeight, ComputedVecsFromTxindex, Source, VecBuilderOptions,
},
indexes, price,
};
use crate::{indexes, price};
use super::{
TARGET_BLOCKS_PER_DAY, TARGET_BLOCKS_PER_DECADE, TARGET_BLOCKS_PER_MONTH,
TARGET_BLOCKS_PER_QUARTER, TARGET_BLOCKS_PER_SEMESTER, TARGET_BLOCKS_PER_WEEK,
TARGET_BLOCKS_PER_YEAR, Vecs,
BlockVecs, CoinbaseVecs, EpochVecs, MiningVecs, OutputTypeVecs, TransactionVecs, Vecs,
VolumeVecs,
};
impl Vecs {
@@ -35,470 +25,25 @@ impl Vecs {
db.set_min_len(PAGE_SIZE * 50_000_000)?;
let version = parent_version + Version::ZERO;
let compute_dollars = price.is_some();
let v0 = Version::ZERO;
let v2 = Version::TWO;
let v4 = Version::new(4);
let v5 = Version::new(5);
macro_rules! eager {
($name:expr) => {
EagerVec::forced_import(&db, $name, version + v0)?
};
($name:expr, $v:expr) => {
EagerVec::forced_import(&db, $name, version + $v)?
};
}
macro_rules! computed_h {
($name:expr, $source:expr, $opts:expr) => {
ComputedVecsFromHeight::forced_import(
&db,
$name,
$source,
version + v0,
indexes,
$opts,
)?
};
($name:expr, $source:expr, $v:expr, $opts:expr) => {
ComputedVecsFromHeight::forced_import(
&db,
$name,
$source,
version + $v,
indexes,
$opts,
)?
};
}
macro_rules! computed_di {
($name:expr, $opts:expr) => {
ComputedVecsFromDateIndex::forced_import(
&db,
$name,
Source::Compute,
version + v0,
indexes,
$opts,
)?
};
($name:expr, $v:expr, $opts:expr) => {
ComputedVecsFromDateIndex::forced_import(
&db,
$name,
Source::Compute,
version + $v,
indexes,
$opts,
)?
};
}
macro_rules! computed_tx {
($name:expr, $source:expr, $opts:expr) => {
ComputedVecsFromTxindex::forced_import(
&db,
$name,
$source,
version + v0,
indexes,
$opts,
)?
};
}
let last = || VecBuilderOptions::default().add_last();
let sum = || VecBuilderOptions::default().add_sum();
let sum_cum = || VecBuilderOptions::default().add_sum().add_cumulative();
let stats = || {
VecBuilderOptions::default()
.add_average()
.add_minmax()
.add_percentiles()
};
let full_stats = || {
VecBuilderOptions::default()
.add_average()
.add_minmax()
.add_percentiles()
.add_sum()
.add_cumulative()
};
let txindex_to_weight = LazyVecFrom2::init(
"weight",
version + Version::ZERO,
indexer.vecs.tx.txindex_to_base_size.boxed_clone(),
indexer.vecs.tx.txindex_to_total_size.boxed_clone(),
|index: TxIndex, txindex_to_base_size_iter, txindex_to_total_size_iter| {
let index = index.to_usize();
txindex_to_base_size_iter.get_at(index).map(|base_size| {
let total_size = txindex_to_total_size_iter.get_at_unwrap(index);
// This is the exact definition of a weight unit, as defined by BIP-141 (quote above).
let wu = usize::from(base_size) * 3 + usize::from(total_size);
Weight::from(bitcoin::Weight::from_wu_usize(wu))
})
},
);
let txindex_to_vsize = LazyVecFrom1::init(
"vsize",
version + Version::ZERO,
txindex_to_weight.boxed_clone(),
|index: TxIndex, iter| iter.get(index).map(brk_types::VSize::from),
);
let txindex_to_is_coinbase = LazyVecFrom2::init(
"is_coinbase",
version + Version::ZERO,
indexer.vecs.tx.txindex_to_height.boxed_clone(),
indexer.vecs.tx.height_to_first_txindex.boxed_clone(),
|index: TxIndex, txindex_to_height_iter, height_to_first_txindex_iter| {
txindex_to_height_iter.get(index).map(|height| {
let txindex = height_to_first_txindex_iter.get_unwrap(height);
StoredBool::from(index == txindex)
})
},
);
let txindex_to_input_value = eager!("input_value");
let txindex_to_output_value = eager!("output_value");
let txindex_to_fee = eager!("fee");
let txindex_to_fee_rate = eager!("fee_rate");
let dateindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + Version::ZERO,
indexes.dateindex_to_dateindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DAY)),
);
let weekindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + Version::ZERO,
indexes.weekindex_to_weekindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_WEEK)),
);
let monthindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + Version::ZERO,
indexes.monthindex_to_monthindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_MONTH)),
);
let quarterindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + Version::ZERO,
indexes.quarterindex_to_quarterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_QUARTER)),
);
let semesterindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + Version::ZERO,
indexes.semesterindex_to_semesterindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_SEMESTER)),
);
let yearindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + Version::ZERO,
indexes.yearindex_to_yearindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_YEAR)),
);
let decadeindex_to_block_count_target = LazyVecFrom1::init(
"block_count_target",
version + Version::ZERO,
indexes.decadeindex_to_decadeindex.boxed_clone(),
|_, _| Some(StoredU64::from(TARGET_BLOCKS_PER_DECADE)),
);
let height_to_interval = eager!("interval");
let height_to_vbytes = eager!("vbytes");
let block = BlockVecs::forced_import(&db, version, indexer, indexes)?;
let epoch = EpochVecs::forced_import(&db, version, indexes)?;
let mining = MiningVecs::forced_import(&db, version, indexer, indexes)?;
let coinbase = CoinbaseVecs::forced_import(&db, version, indexes, compute_dollars)?;
let transaction = TransactionVecs::forced_import(&db, version, indexer, indexes, price)?;
let output_type = OutputTypeVecs::forced_import(&db, version, indexes)?;
let volume = VolumeVecs::forced_import(&db, version, indexes, compute_dollars)?;
let this = Self {
dateindex_to_block_count_target,
weekindex_to_block_count_target,
monthindex_to_block_count_target,
quarterindex_to_block_count_target,
semesterindex_to_block_count_target,
yearindex_to_block_count_target,
decadeindex_to_block_count_target,
timeindexes_to_timestamp: computed_di!(
"timestamp",
VecBuilderOptions::default().add_first()
),
indexes_to_block_interval: computed_h!(
"block_interval",
Source::Vec(height_to_interval.boxed_clone()),
stats()
),
indexes_to_block_count: computed_h!("block_count", Source::Compute, sum_cum()),
indexes_to_1w_block_count: computed_di!("1w_block_count", last()),
indexes_to_1m_block_count: computed_di!("1m_block_count", last()),
indexes_to_1y_block_count: computed_di!("1y_block_count", last()),
indexes_to_block_weight: computed_h!(
"block_weight",
Source::Vec(indexer.vecs.block.height_to_weight.boxed_clone()),
full_stats()
),
indexes_to_block_size: computed_h!(
"block_size",
Source::Vec(indexer.vecs.block.height_to_total_size.boxed_clone()),
full_stats()
),
height_to_24h_block_count: eager!("24h_block_count"),
height_to_24h_coinbase_sum: eager!("24h_coinbase_sum"),
height_to_24h_coinbase_usd_sum: eager!("24h_coinbase_usd_sum"),
indexes_to_block_vbytes: computed_h!(
"block_vbytes",
Source::Vec(height_to_vbytes.boxed_clone()),
full_stats()
),
difficultyepoch_to_timestamp: eager!("timestamp"),
halvingepoch_to_timestamp: eager!("timestamp"),
dateindex_to_fee_dominance: eager!("fee_dominance"),
dateindex_to_subsidy_dominance: eager!("subsidy_dominance"),
indexes_to_difficulty: computed_h!(
"difficulty",
Source::Vec(indexer.vecs.block.height_to_difficulty.boxed_clone()),
last()
),
height_to_interval,
height_to_vbytes,
indexes_to_difficultyepoch: computed_di!("difficultyepoch", last()),
indexes_to_halvingepoch: computed_di!("halvingepoch", last()),
indexes_to_tx_count: computed_h!("tx_count", Source::Compute, full_stats()),
indexes_to_input_count: computed_tx!(
"input_count",
Source::Vec(indexes.txindex_to_input_count.boxed_clone()),
full_stats()
),
indexes_to_output_count: computed_tx!(
"output_count",
Source::Vec(indexes.txindex_to_output_count.boxed_clone()),
full_stats()
),
indexes_to_tx_v1: computed_h!("tx_v1", Source::Compute, sum_cum()),
indexes_to_tx_v2: computed_h!("tx_v2", Source::Compute, sum_cum()),
indexes_to_tx_v3: computed_h!("tx_v3", Source::Compute, sum_cum()),
indexes_to_sent_sum: ComputedValueVecsFromHeight::forced_import(
&db,
"sent_sum",
Source::Compute,
version + Version::ZERO,
VecBuilderOptions::default().add_sum(),
compute_dollars,
indexes,
)?,
indexes_to_fee: ComputedValueVecsFromTxindex::forced_import(
&db,
"fee",
indexer,
indexes,
Source::Vec(txindex_to_fee.boxed_clone()),
version + Version::ZERO,
price,
VecBuilderOptions::default()
.add_sum()
.add_cumulative()
.add_percentiles()
.add_minmax()
.add_average(),
)?,
indexes_to_fee_rate: computed_tx!(
"fee_rate",
Source::Vec(txindex_to_fee_rate.boxed_clone()),
stats()
),
indexes_to_tx_vsize: computed_tx!(
"tx_vsize",
Source::Vec(txindex_to_vsize.boxed_clone()),
stats()
),
indexes_to_tx_weight: computed_tx!(
"tx_weight",
Source::Vec(txindex_to_weight.boxed_clone()),
stats()
),
indexes_to_subsidy: ComputedValueVecsFromHeight::forced_import(
&db,
"subsidy",
Source::Compute,
version + Version::ZERO,
VecBuilderOptions::default()
.add_percentiles()
.add_sum()
.add_cumulative()
.add_minmax()
.add_average(),
compute_dollars,
indexes,
)?,
indexes_to_coinbase: ComputedValueVecsFromHeight::forced_import(
&db,
"coinbase",
Source::Compute,
version + Version::ZERO,
VecBuilderOptions::default()
.add_sum()
.add_cumulative()
.add_percentiles()
.add_minmax()
.add_average(),
compute_dollars,
indexes,
)?,
indexes_to_unclaimed_rewards: ComputedValueVecsFromHeight::forced_import(
&db,
"unclaimed_rewards",
Source::Compute,
version + Version::ZERO,
VecBuilderOptions::default().add_sum().add_cumulative(),
compute_dollars,
indexes,
)?,
indexes_to_p2a_count: computed_h!("p2a_count", Source::Compute, full_stats()),
indexes_to_p2ms_count: computed_h!("p2ms_count", Source::Compute, full_stats()),
indexes_to_p2pk33_count: computed_h!("p2pk33_count", Source::Compute, full_stats()),
indexes_to_p2pk65_count: computed_h!("p2pk65_count", Source::Compute, full_stats()),
indexes_to_p2pkh_count: computed_h!("p2pkh_count", Source::Compute, full_stats()),
indexes_to_p2sh_count: computed_h!("p2sh_count", Source::Compute, full_stats()),
indexes_to_p2tr_count: computed_h!("p2tr_count", Source::Compute, full_stats()),
indexes_to_p2wpkh_count: computed_h!("p2wpkh_count", Source::Compute, full_stats()),
indexes_to_p2wsh_count: computed_h!("p2wsh_count", Source::Compute, full_stats()),
indexes_to_opreturn_count: computed_h!("opreturn_count", Source::Compute, full_stats()),
indexes_to_unknownoutput_count: computed_h!(
"unknownoutput_count",
Source::Compute,
full_stats()
),
indexes_to_emptyoutput_count: computed_h!(
"emptyoutput_count",
Source::Compute,
full_stats()
),
indexes_to_exact_utxo_count: computed_h!("exact_utxo_count", Source::Compute, last()),
indexes_to_subsidy_usd_1y_sma: compute_dollars
.then(|| {
ComputedVecsFromDateIndex::forced_import(
&db,
"subsidy_usd_1y_sma",
Source::Compute,
version + v0,
indexes,
last(),
)
})
.transpose()?,
indexes_to_puell_multiple: compute_dollars
.then(|| {
ComputedVecsFromDateIndex::forced_import(
&db,
"puell_multiple",
Source::Compute,
version + v0,
indexes,
last(),
)
})
.transpose()?,
indexes_to_hash_rate: computed_h!("hash_rate", Source::Compute, v5, last()),
indexes_to_hash_rate_1w_sma: computed_di!("hash_rate_1w_sma", last()),
indexes_to_hash_rate_1m_sma: computed_di!("hash_rate_1m_sma", last()),
indexes_to_hash_rate_2m_sma: computed_di!("hash_rate_2m_sma", last()),
indexes_to_hash_rate_1y_sma: computed_di!("hash_rate_1y_sma", last()),
indexes_to_difficulty_as_hash: computed_h!(
"difficulty_as_hash",
Source::Compute,
last()
),
indexes_to_difficulty_adjustment: computed_h!(
"difficulty_adjustment",
Source::Compute,
sum()
),
indexes_to_blocks_before_next_difficulty_adjustment: computed_h!(
"blocks_before_next_difficulty_adjustment",
Source::Compute,
v2,
last()
),
indexes_to_days_before_next_difficulty_adjustment: computed_h!(
"days_before_next_difficulty_adjustment",
Source::Compute,
v2,
last()
),
indexes_to_blocks_before_next_halving: computed_h!(
"blocks_before_next_halving",
Source::Compute,
v2,
last()
),
indexes_to_days_before_next_halving: computed_h!(
"days_before_next_halving",
Source::Compute,
v2,
last()
),
indexes_to_hash_price_ths: computed_h!("hash_price_ths", Source::Compute, v4, last()),
indexes_to_hash_price_phs: computed_h!("hash_price_phs", Source::Compute, v4, last()),
indexes_to_hash_value_ths: computed_h!("hash_value_ths", Source::Compute, v4, last()),
indexes_to_hash_value_phs: computed_h!("hash_value_phs", Source::Compute, v4, last()),
indexes_to_hash_price_ths_min: computed_h!(
"hash_price_ths_min",
Source::Compute,
v4,
last()
),
indexes_to_hash_price_phs_min: computed_h!(
"hash_price_phs_min",
Source::Compute,
v4,
last()
),
indexes_to_hash_price_rebound: computed_h!(
"hash_price_rebound",
Source::Compute,
v4,
last()
),
indexes_to_hash_value_ths_min: computed_h!(
"hash_value_ths_min",
Source::Compute,
v4,
last()
),
indexes_to_hash_value_phs_min: computed_h!(
"hash_value_phs_min",
Source::Compute,
v4,
last()
),
indexes_to_hash_value_rebound: computed_h!(
"hash_value_rebound",
Source::Compute,
v4,
last()
),
indexes_to_inflation_rate: computed_di!("inflation_rate", last()),
indexes_to_annualized_volume: computed_di!("annualized_volume", last()),
indexes_to_annualized_volume_btc: computed_di!("annualized_volume_btc", last()),
indexes_to_annualized_volume_usd: computed_di!("annualized_volume_usd", last()),
indexes_to_tx_btc_velocity: computed_di!("tx_btc_velocity", last()),
indexes_to_tx_usd_velocity: computed_di!("tx_usd_velocity", last()),
indexes_to_tx_per_sec: computed_di!("tx_per_sec", v2, last()),
indexes_to_outputs_per_sec: computed_di!("outputs_per_sec", v2, last()),
indexes_to_inputs_per_sec: computed_di!("inputs_per_sec", v2, last()),
txindex_to_is_coinbase,
txindex_to_input_value,
txindex_to_output_value,
txindex_to_fee,
txindex_to_fee_rate,
txindex_to_vsize,
txindex_to_weight,
db,
block,
epoch,
mining,
coinbase,
transaction,
output_type,
volume,
};
this.db.retain_regions(

View File

@@ -0,0 +1,301 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{StoredF32, StoredF64, StoredU32};
use vecdb::Exit;
use super::Vecs;
use crate::{
chain::{block, coinbase, ONE_TERA_HASH, TARGET_BLOCKS_PER_DAY_F32, TARGET_BLOCKS_PER_DAY_F64},
indexes,
utils::OptionExt,
Indexes,
};
impl Vecs {
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
block_vecs: &block::Vecs,
coinbase_vecs: &coinbase::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.indexes_to_difficulty.compute_rest(
indexes,
starting_indexes,
exit,
Some(&indexer.vecs.block.height_to_difficulty),
)?;
self.indexes_to_difficulty_as_hash
.compute_all(indexes, starting_indexes, exit, |v| {
let multiplier = 2.0_f64.powi(32) / 600.0;
v.compute_transform(
starting_indexes.height,
&indexer.vecs.block.height_to_difficulty,
|(i, v, ..)| (i, StoredF32::from(*v * multiplier)),
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_rate
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.height,
&block_vecs.height_to_24h_block_count,
self.indexes_to_difficulty_as_hash.height.u(),
|(i, block_count_sum, difficulty_as_hash, ..)| {
(
i,
StoredF64::from(
(f64::from(block_count_sum) / TARGET_BLOCKS_PER_DAY_F64)
* f64::from(difficulty_as_hash),
),
)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_rate_1w_sma
.compute_all(starting_indexes, exit, |v| {
v.compute_sma(
starting_indexes.dateindex,
self.indexes_to_hash_rate.dateindex.unwrap_last(),
7,
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_rate_1m_sma
.compute_all(starting_indexes, exit, |v| {
v.compute_sma(
starting_indexes.dateindex,
self.indexes_to_hash_rate.dateindex.unwrap_last(),
30,
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_rate_2m_sma
.compute_all(starting_indexes, exit, |v| {
v.compute_sma(
starting_indexes.dateindex,
self.indexes_to_hash_rate.dateindex.unwrap_last(),
2 * 30,
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_rate_1y_sma
.compute_all(starting_indexes, exit, |v| {
v.compute_sma(
starting_indexes.dateindex,
self.indexes_to_hash_rate.dateindex.unwrap_last(),
365,
exit,
)?;
Ok(())
})?;
self.indexes_to_difficulty_adjustment.compute_all(
indexes,
starting_indexes,
exit,
|v| {
v.compute_percentage_change(
starting_indexes.height,
&indexer.vecs.block.height_to_difficulty,
1,
exit,
)?;
Ok(())
},
)?;
self.indexes_to_blocks_before_next_difficulty_adjustment
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.height,
&indexes.block.height_to_height,
|(h, ..)| (h, StoredU32::from(h.left_before_next_diff_adj())),
exit,
)?;
Ok(())
})?;
self.indexes_to_days_before_next_difficulty_adjustment
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.height,
self.indexes_to_blocks_before_next_difficulty_adjustment
.height
.as_ref()
.unwrap(),
|(h, blocks, ..)| (h, (*blocks as f32 / TARGET_BLOCKS_PER_DAY_F32).into()),
exit,
)?;
Ok(())
})?;
self.indexes_to_blocks_before_next_halving.compute_all(
indexes,
starting_indexes,
exit,
|v| {
v.compute_transform(
starting_indexes.height,
&indexes.block.height_to_height,
|(h, ..)| (h, StoredU32::from(h.left_before_next_halving())),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_days_before_next_halving.compute_all(
indexes,
starting_indexes,
exit,
|v| {
v.compute_transform(
starting_indexes.height,
self.indexes_to_blocks_before_next_halving
.height
.as_ref()
.unwrap(),
|(h, blocks, ..)| (h, (*blocks as f32 / TARGET_BLOCKS_PER_DAY_F32).into()),
exit,
)?;
Ok(())
},
)?;
self.indexes_to_hash_price_ths
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.height,
&coinbase_vecs.height_to_24h_coinbase_usd_sum,
self.indexes_to_hash_rate.height.u(),
|(i, coinbase_sum, hashrate, ..)| {
(i, (*coinbase_sum / (*hashrate / ONE_TERA_HASH)).into())
},
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_price_phs
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.height,
self.indexes_to_hash_price_ths.height.u(),
|(i, price, ..)| (i, (*price * 1000.0).into()),
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_value_ths
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.height,
&coinbase_vecs.height_to_24h_coinbase_sum,
self.indexes_to_hash_rate.height.u(),
|(i, coinbase_sum, hashrate, ..)| {
(
i,
(*coinbase_sum as f64 / (*hashrate / ONE_TERA_HASH)).into(),
)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_value_phs
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_transform(
starting_indexes.height,
self.indexes_to_hash_value_ths.height.u(),
|(i, value, ..)| (i, (*value * 1000.0).into()),
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_price_ths_min
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_all_time_low_(
starting_indexes.height,
self.indexes_to_hash_price_ths.height.u(),
exit,
true,
)?;
Ok(())
})?;
self.indexes_to_hash_price_phs_min
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_all_time_low_(
starting_indexes.height,
self.indexes_to_hash_price_phs.height.u(),
exit,
true,
)?;
Ok(())
})?;
self.indexes_to_hash_value_ths_min
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_all_time_low_(
starting_indexes.height,
self.indexes_to_hash_value_ths.height.u(),
exit,
true,
)?;
Ok(())
})?;
self.indexes_to_hash_value_phs_min
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_all_time_low_(
starting_indexes.height,
self.indexes_to_hash_value_phs.height.u(),
exit,
true,
)?;
Ok(())
})?;
self.indexes_to_hash_price_rebound
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_percentage_difference(
starting_indexes.height,
self.indexes_to_hash_price_phs.height.u(),
self.indexes_to_hash_price_phs_min.height.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_hash_value_rebound
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_percentage_difference(
starting_indexes.height,
self.indexes_to_hash_value_phs.height.u(),
self.indexes_to_hash_value_phs_min.height.u(),
exit,
)?;
Ok(())
})?;
Ok(())
}
}

View File

@@ -0,0 +1,208 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::Version;
use vecdb::{Database, IterableCloneableVec};
use super::Vecs;
use crate::{
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source, VecBuilderOptions},
indexes,
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexer: &Indexer,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let v2 = Version::TWO;
let v4 = Version::new(4);
let v5 = Version::new(5);
let last = || VecBuilderOptions::default().add_last();
let sum = || VecBuilderOptions::default().add_sum();
Ok(Self {
indexes_to_hash_rate: ComputedVecsFromHeight::forced_import(
db,
"hash_rate",
Source::Compute,
version + v5,
indexes,
last(),
)?,
indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex::forced_import(
db,
"hash_rate_1w_sma",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex::forced_import(
db,
"hash_rate_1m_sma",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex::forced_import(
db,
"hash_rate_2m_sma",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex::forced_import(
db,
"hash_rate_1y_sma",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_hash_price_ths: ComputedVecsFromHeight::forced_import(
db,
"hash_price_ths",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_price_ths_min: ComputedVecsFromHeight::forced_import(
db,
"hash_price_ths_min",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_price_phs: ComputedVecsFromHeight::forced_import(
db,
"hash_price_phs",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_price_phs_min: ComputedVecsFromHeight::forced_import(
db,
"hash_price_phs_min",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_price_rebound: ComputedVecsFromHeight::forced_import(
db,
"hash_price_rebound",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_value_ths: ComputedVecsFromHeight::forced_import(
db,
"hash_value_ths",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_value_ths_min: ComputedVecsFromHeight::forced_import(
db,
"hash_value_ths_min",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_value_phs: ComputedVecsFromHeight::forced_import(
db,
"hash_value_phs",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_value_phs_min: ComputedVecsFromHeight::forced_import(
db,
"hash_value_phs_min",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_hash_value_rebound: ComputedVecsFromHeight::forced_import(
db,
"hash_value_rebound",
Source::Compute,
version + v4,
indexes,
last(),
)?,
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
db,
"difficulty",
Source::Vec(indexer.vecs.block.height_to_difficulty.boxed_clone()),
version + v0,
indexes,
last(),
)?,
indexes_to_difficulty_as_hash: ComputedVecsFromHeight::forced_import(
db,
"difficulty_as_hash",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_difficulty_adjustment: ComputedVecsFromHeight::forced_import(
db,
"difficulty_adjustment",
Source::Compute,
version + v0,
indexes,
sum(),
)?,
indexes_to_blocks_before_next_difficulty_adjustment:
ComputedVecsFromHeight::forced_import(
db,
"blocks_before_next_difficulty_adjustment",
Source::Compute,
version + v2,
indexes,
last(),
)?,
indexes_to_days_before_next_difficulty_adjustment:
ComputedVecsFromHeight::forced_import(
db,
"days_before_next_difficulty_adjustment",
Source::Compute,
version + v2,
indexes,
last(),
)?,
indexes_to_blocks_before_next_halving: ComputedVecsFromHeight::forced_import(
db,
"blocks_before_next_halving",
Source::Compute,
version + v2,
indexes,
last(),
)?,
indexes_to_days_before_next_halving: ComputedVecsFromHeight::forced_import(
db,
"days_before_next_halving",
Source::Compute,
version + v2,
indexes,
last(),
)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,31 @@
use brk_traversable::Traversable;
use brk_types::{StoredF32, StoredF64, StoredU32};
use crate::grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight};
/// Mining-related metrics: hash rate, hash price, hash value, difficulty
#[derive(Clone, Traversable)]
pub struct Vecs {
pub indexes_to_hash_rate: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_hash_price_ths: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_price_ths_min: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_price_phs: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_price_phs_min: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_price_rebound: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_ths: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_ths_min: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_phs: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_phs_min: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_rebound: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_difficulty_as_hash: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_difficulty_adjustment: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_blocks_before_next_difficulty_adjustment: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_days_before_next_difficulty_adjustment: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_blocks_before_next_halving: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_days_before_next_halving: ComputedVecsFromHeight<StoredF32>,
}

View File

@@ -1,18 +1,23 @@
pub mod block;
pub mod coinbase;
mod compute;
pub mod epoch;
mod import;
pub mod mining;
pub mod output_type;
pub mod transaction;
pub mod volume;
use brk_traversable::Traversable;
use brk_types::{
Bitcoin, DateIndex, DecadeIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch, Height,
MonthIndex, QuarterIndex, Sats, SemesterIndex, StoredBool, StoredF32, StoredF64, StoredU32,
StoredU64, Timestamp, TxIndex, VSize, WeekIndex, Weight, YearIndex,
};
use vecdb::{Database, EagerVec, LazyVecFrom1, LazyVecFrom2, PcoVec};
use vecdb::Database;
use crate::grouped::{
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromDateIndex,
ComputedVecsFromHeight, ComputedVecsFromTxindex,
};
pub use block::Vecs as BlockVecs;
pub use coinbase::Vecs as CoinbaseVecs;
pub use epoch::Vecs as EpochVecs;
pub use mining::Vecs as MiningVecs;
pub use output_type::Vecs as OutputTypeVecs;
pub use transaction::Vecs as TransactionVecs;
pub use volume::Vecs as VolumeVecs;
pub const DB_NAME: &str = "chain";
@@ -27,107 +32,16 @@ pub(crate) const TARGET_BLOCKS_PER_YEAR: u64 = 2 * TARGET_BLOCKS_PER_SEMESTER;
pub(crate) const TARGET_BLOCKS_PER_DECADE: u64 = 10 * TARGET_BLOCKS_PER_YEAR;
pub(crate) const ONE_TERA_HASH: f64 = 1_000_000_000_000.0;
/// Main chain metrics struct composed of sub-modules
#[derive(Clone, Traversable)]
pub struct Vecs {
#[traversable(skip)]
pub(crate) db: Database,
pub dateindex_to_block_count_target: LazyVecFrom1<DateIndex, StoredU64, DateIndex, DateIndex>,
pub weekindex_to_block_count_target: LazyVecFrom1<WeekIndex, StoredU64, WeekIndex, WeekIndex>,
pub monthindex_to_block_count_target:
LazyVecFrom1<MonthIndex, StoredU64, MonthIndex, MonthIndex>,
pub quarterindex_to_block_count_target:
LazyVecFrom1<QuarterIndex, StoredU64, QuarterIndex, QuarterIndex>,
pub semesterindex_to_block_count_target:
LazyVecFrom1<SemesterIndex, StoredU64, SemesterIndex, SemesterIndex>,
pub yearindex_to_block_count_target: LazyVecFrom1<YearIndex, StoredU64, YearIndex, YearIndex>,
pub decadeindex_to_block_count_target:
LazyVecFrom1<DecadeIndex, StoredU64, DecadeIndex, DecadeIndex>,
pub height_to_interval: EagerVec<PcoVec<Height, Timestamp>>,
pub height_to_24h_block_count: EagerVec<PcoVec<Height, StoredU32>>,
pub height_to_24h_coinbase_sum: EagerVec<PcoVec<Height, Sats>>,
pub height_to_24h_coinbase_usd_sum: EagerVec<PcoVec<Height, Dollars>>,
pub height_to_vbytes: EagerVec<PcoVec<Height, StoredU64>>,
pub difficultyepoch_to_timestamp: EagerVec<PcoVec<DifficultyEpoch, Timestamp>>,
pub halvingepoch_to_timestamp: EagerVec<PcoVec<HalvingEpoch, Timestamp>>,
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_1w_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_1m_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_1y_block_count: ComputedVecsFromDateIndex<StoredU32>,
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_fee: ComputedValueVecsFromTxindex,
pub indexes_to_fee_rate: ComputedVecsFromTxindex<FeeRate>,
/// Value == 0 when Coinbase
pub txindex_to_input_value: EagerVec<PcoVec<TxIndex, Sats>>,
pub indexes_to_sent_sum: ComputedValueVecsFromHeight,
pub indexes_to_opreturn_count: ComputedVecsFromHeight<StoredU64>,
pub txindex_to_output_value: EagerVec<PcoVec<TxIndex, Sats>>,
pub indexes_to_p2a_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2ms_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2pk33_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2pk65_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2pkh_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2sh_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2tr_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2wpkh_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2wsh_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_subsidy: ComputedValueVecsFromHeight,
pub indexes_to_unclaimed_rewards: ComputedValueVecsFromHeight,
pub indexes_to_tx_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_tx_v1: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_tx_v2: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_tx_v3: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_tx_vsize: ComputedVecsFromTxindex<VSize>,
pub indexes_to_tx_weight: ComputedVecsFromTxindex<Weight>,
pub indexes_to_unknownoutput_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_input_count: ComputedVecsFromTxindex<StoredU64>,
pub txindex_to_is_coinbase: LazyVecFrom2<TxIndex, StoredBool, TxIndex, Height, Height, TxIndex>,
pub indexes_to_output_count: ComputedVecsFromTxindex<StoredU64>,
pub txindex_to_vsize: LazyVecFrom1<TxIndex, VSize, TxIndex, Weight>,
pub txindex_to_weight: LazyVecFrom2<TxIndex, Weight, TxIndex, StoredU32, TxIndex, StoredU32>,
pub txindex_to_fee: EagerVec<PcoVec<TxIndex, Sats>>,
pub txindex_to_fee_rate: EagerVec<PcoVec<TxIndex, FeeRate>>,
pub indexes_to_exact_utxo_count: ComputedVecsFromHeight<StoredU64>,
pub dateindex_to_fee_dominance: EagerVec<PcoVec<DateIndex, StoredF32>>,
pub dateindex_to_subsidy_dominance: EagerVec<PcoVec<DateIndex, StoredF32>>,
pub indexes_to_subsidy_usd_1y_sma: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_puell_multiple: Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_hash_rate: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_hash_price_ths: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_price_ths_min: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_price_phs: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_price_phs_min: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_price_rebound: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_ths: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_ths_min: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_phs: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_phs_min: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_hash_value_rebound: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_difficulty_as_hash: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_difficulty_adjustment: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_blocks_before_next_difficulty_adjustment: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_days_before_next_difficulty_adjustment: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_blocks_before_next_halving: ComputedVecsFromHeight<StoredU32>,
pub indexes_to_days_before_next_halving: ComputedVecsFromHeight<StoredF32>,
pub indexes_to_inflation_rate: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_annualized_volume: ComputedVecsFromDateIndex<Sats>,
pub indexes_to_annualized_volume_btc: ComputedVecsFromDateIndex<Bitcoin>,
pub indexes_to_annualized_volume_usd: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_tx_btc_velocity: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_tx_usd_velocity: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_tx_per_sec: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_outputs_per_sec: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_inputs_per_sec: ComputedVecsFromDateIndex<StoredF32>,
pub block: BlockVecs,
pub epoch: EpochVecs,
pub mining: MiningVecs,
pub coinbase: CoinbaseVecs,
pub transaction: TransactionVecs,
pub output_type: OutputTypeVecs,
pub volume: VolumeVecs,
}

View File

@@ -0,0 +1,203 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{Height, StoredU64};
use vecdb::{Exit, TypedVecIterator};
use super::Vecs;
use crate::{chain::transaction, indexes, Indexes};
impl Vecs {
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
transaction_vecs: &transaction::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.indexes_to_p2a_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.address.height_to_first_p2aaddressindex,
&indexer.vecs.address.p2aaddressindex_to_p2abytes,
exit,
)?;
Ok(())
})?;
self.indexes_to_p2ms_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.output.height_to_first_p2msoutputindex,
&indexer.vecs.output.p2msoutputindex_to_txindex,
exit,
)?;
Ok(())
})?;
self.indexes_to_p2pk33_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.address.height_to_first_p2pk33addressindex,
&indexer.vecs.address.p2pk33addressindex_to_p2pk33bytes,
exit,
)?;
Ok(())
})?;
self.indexes_to_p2pk65_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.address.height_to_first_p2pk65addressindex,
&indexer.vecs.address.p2pk65addressindex_to_p2pk65bytes,
exit,
)?;
Ok(())
})?;
self.indexes_to_p2pkh_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.address.height_to_first_p2pkhaddressindex,
&indexer.vecs.address.p2pkhaddressindex_to_p2pkhbytes,
exit,
)?;
Ok(())
})?;
self.indexes_to_p2sh_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.address.height_to_first_p2shaddressindex,
&indexer.vecs.address.p2shaddressindex_to_p2shbytes,
exit,
)?;
Ok(())
})?;
self.indexes_to_p2tr_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.address.height_to_first_p2traddressindex,
&indexer.vecs.address.p2traddressindex_to_p2trbytes,
exit,
)?;
Ok(())
})?;
self.indexes_to_p2wpkh_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.address.height_to_first_p2wpkhaddressindex,
&indexer.vecs.address.p2wpkhaddressindex_to_p2wpkhbytes,
exit,
)?;
Ok(())
})?;
self.indexes_to_p2wsh_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.address.height_to_first_p2wshaddressindex,
&indexer.vecs.address.p2wshaddressindex_to_p2wshbytes,
exit,
)?;
Ok(())
})?;
self.indexes_to_opreturn_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.output.height_to_first_opreturnindex,
&indexer.vecs.output.opreturnindex_to_txindex,
exit,
)?;
Ok(())
})?;
self.indexes_to_unknownoutput_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.output.height_to_first_unknownoutputindex,
&indexer.vecs.output.unknownoutputindex_to_txindex,
exit,
)?;
Ok(())
})?;
self.indexes_to_emptyoutput_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.output.height_to_first_emptyoutputindex,
&indexer.vecs.output.emptyoutputindex_to_txindex,
exit,
)?;
Ok(())
})?;
self.indexes_to_exact_utxo_count
.compute_all(indexes, starting_indexes, exit, |v| {
let mut input_count_iter = transaction_vecs
.indexes_to_input_count
.height
.unwrap_cumulative()
.into_iter();
let mut opreturn_count_iter = self
.indexes_to_opreturn_count
.height_extra
.unwrap_cumulative()
.into_iter();
v.compute_transform(
starting_indexes.height,
transaction_vecs
.indexes_to_output_count
.height
.unwrap_cumulative(),
|(h, output_count, ..)| {
let input_count = input_count_iter.get_unwrap(h);
let opreturn_count = opreturn_count_iter.get_unwrap(h);
let block_count = u64::from(h + 1_usize);
// -1 > genesis output is unspendable
let mut utxo_count =
*output_count - (*input_count - block_count) - *opreturn_count - 1;
// txid dup: e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468
// Block 91_722 https://mempool.space/block/00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e
// Block 91_880 https://mempool.space/block/00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721
//
// txid dup: d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599
// Block 91_812 https://mempool.space/block/00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f
// Block 91_842 https://mempool.space/block/00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec
//
// Warning: Dups invalidate the previous coinbase according to
// https://chainquery.com/bitcoin-cli/gettxoutsetinfo
if h >= Height::new(91_842) {
utxo_count -= 1;
}
if h >= Height::new(91_880) {
utxo_count -= 1;
}
(h, StoredU64::from(utxo_count))
},
exit,
)?;
Ok(())
})?;
Ok(())
}
}

View File

@@ -0,0 +1,131 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{
grouped::{ComputedVecsFromHeight, Source, VecBuilderOptions},
indexes,
};
impl Vecs {
pub fn forced_import(db: &Database, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
let v0 = Version::ZERO;
let last = || VecBuilderOptions::default().add_last();
let full_stats = || {
VecBuilderOptions::default()
.add_average()
.add_minmax()
.add_percentiles()
.add_sum()
.add_cumulative()
};
Ok(Self {
indexes_to_p2a_count: ComputedVecsFromHeight::forced_import(
db,
"p2a_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_p2ms_count: ComputedVecsFromHeight::forced_import(
db,
"p2ms_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_p2pk33_count: ComputedVecsFromHeight::forced_import(
db,
"p2pk33_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_p2pk65_count: ComputedVecsFromHeight::forced_import(
db,
"p2pk65_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_p2pkh_count: ComputedVecsFromHeight::forced_import(
db,
"p2pkh_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_p2sh_count: ComputedVecsFromHeight::forced_import(
db,
"p2sh_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_p2tr_count: ComputedVecsFromHeight::forced_import(
db,
"p2tr_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_p2wpkh_count: ComputedVecsFromHeight::forced_import(
db,
"p2wpkh_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_p2wsh_count: ComputedVecsFromHeight::forced_import(
db,
"p2wsh_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_opreturn_count: ComputedVecsFromHeight::forced_import(
db,
"opreturn_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_emptyoutput_count: ComputedVecsFromHeight::forced_import(
db,
"emptyoutput_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_unknownoutput_count: ComputedVecsFromHeight::forced_import(
db,
"unknownoutput_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_exact_utxo_count: ComputedVecsFromHeight::forced_import(
db,
"exact_utxo_count",
Source::Compute,
version + v0,
indexes,
last(),
)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,22 @@
use brk_traversable::Traversable;
use brk_types::StoredU64;
use crate::grouped::ComputedVecsFromHeight;
/// Output type count metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub indexes_to_p2a_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2ms_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2pk33_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2pk65_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2pkh_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2sh_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2tr_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2wpkh_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_p2wsh_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_opreturn_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_unknownoutput_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_exact_utxo_count: ComputedVecsFromHeight<StoredU64>,
}

View File

@@ -0,0 +1,141 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{FeeRate, Sats, StoredU64, TxVersion};
use vecdb::{Exit, TypedVecIterator, unlikely};
use super::Vecs;
use crate::{Indexes, grouped::ComputedVecsFromHeight, indexes, price, txins};
impl Vecs {
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
txins: &txins::Vecs,
starting_indexes: &Indexes,
price: Option<&price::Vecs>,
exit: &Exit,
) -> Result<()> {
self.indexes_to_tx_count
.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.tx.height_to_first_txindex,
&indexer.vecs.tx.txindex_to_txid,
exit,
)?;
Ok(())
})?;
self.indexes_to_input_count.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(&indexes.transaction.txindex_to_input_count),
)?;
self.indexes_to_output_count.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(&indexes.transaction.txindex_to_output_count),
)?;
let compute_indexes_to_tx_vany =
|indexes_to_tx_vany: &mut ComputedVecsFromHeight<StoredU64>, txversion: TxVersion| {
let mut txindex_to_txversion_iter = indexer.vecs.tx.txindex_to_txversion.iter()?;
indexes_to_tx_vany.compute_all(indexes, starting_indexes, exit, |vec| {
vec.compute_filtered_count_from_indexes(
starting_indexes.height,
&indexer.vecs.tx.height_to_first_txindex,
&indexer.vecs.tx.txindex_to_txid,
|txindex| {
let v = txindex_to_txversion_iter.get_unwrap(txindex);
v == txversion
},
exit,
)?;
Ok(())
})
};
compute_indexes_to_tx_vany(&mut self.indexes_to_tx_v1, TxVersion::ONE)?;
compute_indexes_to_tx_vany(&mut self.indexes_to_tx_v2, TxVersion::TWO)?;
compute_indexes_to_tx_vany(&mut self.indexes_to_tx_v3, TxVersion::THREE)?;
self.txindex_to_input_value.compute_sum_from_indexes(
starting_indexes.txindex,
&indexer.vecs.tx.txindex_to_first_txinindex,
&indexes.transaction.txindex_to_input_count,
&txins.txinindex_to_value,
exit,
)?;
self.txindex_to_output_value.compute_sum_from_indexes(
starting_indexes.txindex,
&indexer.vecs.tx.txindex_to_first_txoutindex,
&indexes.transaction.txindex_to_output_count,
&indexer.vecs.txout.txoutindex_to_value,
exit,
)?;
self.txindex_to_fee.compute_transform2(
starting_indexes.txindex,
&self.txindex_to_input_value,
&self.txindex_to_output_value,
|(i, input, output, ..)| {
let fee = if unlikely(input.is_max()) {
Sats::ZERO
} else {
input - output
};
(i, fee)
},
exit,
)?;
self.txindex_to_fee_rate.compute_transform2(
starting_indexes.txindex,
&self.txindex_to_fee,
&self.txindex_to_vsize,
|(txindex, fee, vsize, ..)| (txindex, FeeRate::from((fee, vsize))),
exit,
)?;
self.indexes_to_fee.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(&self.txindex_to_fee),
price,
)?;
self.indexes_to_fee_rate.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(&self.txindex_to_fee_rate),
)?;
self.indexes_to_tx_weight.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(&self.txindex_to_weight),
)?;
self.indexes_to_tx_vsize.compute_rest(
indexer,
indexes,
starting_indexes,
exit,
Some(&self.txindex_to_vsize),
)?;
Ok(())
}
}

View File

@@ -0,0 +1,180 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{StoredBool, TxIndex, VSize, Version, Weight};
use vecdb::{
Database, EagerVec, ImportableVec, IterableCloneableVec, LazyVecFrom1, LazyVecFrom2, VecIndex,
};
use super::Vecs;
use crate::{
grouped::{
ComputedValueVecsFromTxindex, ComputedVecsFromHeight, ComputedVecsFromTxindex, Source,
VecBuilderOptions,
},
indexes, price,
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexer: &Indexer,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let v0 = Version::ZERO;
let stats = || {
VecBuilderOptions::default()
.add_average()
.add_minmax()
.add_percentiles()
};
let full_stats = || {
VecBuilderOptions::default()
.add_average()
.add_minmax()
.add_percentiles()
.add_sum()
.add_cumulative()
};
let sum_cum = || VecBuilderOptions::default().add_sum().add_cumulative();
let txindex_to_weight = LazyVecFrom2::init(
"weight",
version + v0,
indexer.vecs.tx.txindex_to_base_size.boxed_clone(),
indexer.vecs.tx.txindex_to_total_size.boxed_clone(),
|index: TxIndex, txindex_to_base_size_iter, txindex_to_total_size_iter| {
let index = index.to_usize();
txindex_to_base_size_iter.get_at(index).map(|base_size| {
let total_size = txindex_to_total_size_iter.get_at_unwrap(index);
let wu = usize::from(base_size) * 3 + usize::from(total_size);
Weight::from(bitcoin::Weight::from_wu_usize(wu))
})
},
);
let txindex_to_vsize = LazyVecFrom1::init(
"vsize",
version + v0,
txindex_to_weight.boxed_clone(),
|index: TxIndex, iter| iter.get(index).map(VSize::from),
);
let txindex_to_is_coinbase = LazyVecFrom2::init(
"is_coinbase",
version + v0,
indexer.vecs.tx.txindex_to_height.boxed_clone(),
indexer.vecs.tx.height_to_first_txindex.boxed_clone(),
|index: TxIndex, txindex_to_height_iter, height_to_first_txindex_iter| {
txindex_to_height_iter.get(index).map(|height| {
let txindex = height_to_first_txindex_iter.get_unwrap(height);
StoredBool::from(index == txindex)
})
},
);
let txindex_to_input_value = EagerVec::forced_import(db, "input_value", version + v0)?;
let txindex_to_output_value = EagerVec::forced_import(db, "output_value", version + v0)?;
let txindex_to_fee = EagerVec::forced_import(db, "fee", version + v0)?;
let txindex_to_fee_rate = EagerVec::forced_import(db, "fee_rate", version + v0)?;
Ok(Self {
indexes_to_tx_count: ComputedVecsFromHeight::forced_import(
db,
"tx_count",
Source::Compute,
version + v0,
indexes,
full_stats(),
)?,
indexes_to_tx_v1: ComputedVecsFromHeight::forced_import(
db,
"tx_v1",
Source::Compute,
version + v0,
indexes,
sum_cum(),
)?,
indexes_to_tx_v2: ComputedVecsFromHeight::forced_import(
db,
"tx_v2",
Source::Compute,
version + v0,
indexes,
sum_cum(),
)?,
indexes_to_tx_v3: ComputedVecsFromHeight::forced_import(
db,
"tx_v3",
Source::Compute,
version + v0,
indexes,
sum_cum(),
)?,
indexes_to_tx_vsize: ComputedVecsFromTxindex::forced_import(
db,
"tx_vsize",
Source::Vec(txindex_to_vsize.boxed_clone()),
version + v0,
indexes,
stats(),
)?,
indexes_to_tx_weight: ComputedVecsFromTxindex::forced_import(
db,
"tx_weight",
Source::Vec(txindex_to_weight.boxed_clone()),
version + v0,
indexes,
stats(),
)?,
indexes_to_input_count: ComputedVecsFromTxindex::forced_import(
db,
"input_count",
Source::Vec(indexes.transaction.txindex_to_input_count.boxed_clone()),
version + v0,
indexes,
full_stats(),
)?,
indexes_to_output_count: ComputedVecsFromTxindex::forced_import(
db,
"output_count",
Source::Vec(indexes.transaction.txindex_to_output_count.boxed_clone()),
version + v0,
indexes,
full_stats(),
)?,
txindex_to_is_coinbase,
txindex_to_vsize,
txindex_to_weight,
txindex_to_input_value,
txindex_to_output_value,
txindex_to_fee: txindex_to_fee.clone(),
txindex_to_fee_rate: txindex_to_fee_rate.clone(),
indexes_to_fee: ComputedValueVecsFromTxindex::forced_import(
db,
"fee",
indexer,
indexes,
Source::Vec(txindex_to_fee.boxed_clone()),
version + v0,
price,
VecBuilderOptions::default()
.add_sum()
.add_cumulative()
.add_percentiles()
.add_minmax()
.add_average(),
)?,
indexes_to_fee_rate: ComputedVecsFromTxindex::forced_import(
db,
"fee_rate",
Source::Vec(txindex_to_fee_rate.boxed_clone()),
version + v0,
indexes,
stats(),
)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,28 @@
use brk_traversable::Traversable;
use brk_types::{FeeRate, Height, Sats, StoredBool, StoredU32, StoredU64, TxIndex, VSize, Weight};
use vecdb::{EagerVec, LazyVecFrom1, LazyVecFrom2, PcoVec};
use crate::grouped::{ComputedValueVecsFromTxindex, ComputedVecsFromHeight, ComputedVecsFromTxindex};
/// Transaction-related metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub indexes_to_tx_count: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_tx_v1: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_tx_v2: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_tx_v3: ComputedVecsFromHeight<StoredU64>,
pub indexes_to_tx_vsize: ComputedVecsFromTxindex<VSize>,
pub indexes_to_tx_weight: ComputedVecsFromTxindex<Weight>,
pub indexes_to_input_count: ComputedVecsFromTxindex<StoredU64>,
pub indexes_to_output_count: ComputedVecsFromTxindex<StoredU64>,
pub txindex_to_is_coinbase: LazyVecFrom2<TxIndex, StoredBool, TxIndex, Height, Height, TxIndex>,
pub txindex_to_vsize: LazyVecFrom1<TxIndex, VSize, TxIndex, Weight>,
pub txindex_to_weight: LazyVecFrom2<TxIndex, Weight, TxIndex, StoredU32, TxIndex, StoredU32>,
/// Value == 0 when Coinbase
pub txindex_to_input_value: EagerVec<PcoVec<TxIndex, Sats>>,
pub txindex_to_output_value: EagerVec<PcoVec<TxIndex, Sats>>,
pub txindex_to_fee: EagerVec<PcoVec<TxIndex, Sats>>,
pub txindex_to_fee_rate: EagerVec<PcoVec<TxIndex, FeeRate>>,
pub indexes_to_fee: ComputedValueVecsFromTxindex,
pub indexes_to_fee_rate: ComputedVecsFromTxindex<FeeRate>,
}

View File

@@ -0,0 +1,169 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::ONE_DAY_IN_SEC_F64;
use vecdb::Exit;
use super::Vecs;
use crate::{
chain::{coinbase, transaction},
indexes, price, Indexes,
};
impl Vecs {
#[allow(clippy::too_many_arguments)]
pub fn compute(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
transaction_vecs: &transaction::Vecs,
coinbase_vecs: &coinbase::Vecs,
starting_indexes: &Indexes,
price: Option<&price::Vecs>,
exit: &Exit,
) -> Result<()> {
self.indexes_to_sent_sum
.compute_all(indexes, price, starting_indexes, exit, |v| {
v.compute_filtered_sum_from_indexes(
starting_indexes.height,
&indexer.vecs.tx.height_to_first_txindex,
&indexes.block.height_to_txindex_count,
&transaction_vecs.txindex_to_input_value,
|sats| !sats.is_max(),
exit,
)?;
Ok(())
})?;
self.indexes_to_annualized_volume
.compute_all(starting_indexes, exit, |v| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_sent_sum.sats.dateindex.unwrap_sum(),
365,
exit,
)?;
Ok(())
})?;
self.indexes_to_annualized_volume_btc
.compute_all(starting_indexes, exit, |v| {
v.compute_sum(
starting_indexes.dateindex,
self.indexes_to_sent_sum.bitcoin.dateindex.unwrap_sum(),
365,
exit,
)?;
Ok(())
})?;
self.indexes_to_tx_btc_velocity
.compute_all(starting_indexes, exit, |v| {
v.compute_divide(
starting_indexes.dateindex,
self.indexes_to_annualized_volume_btc
.dateindex
.as_ref()
.unwrap(),
coinbase_vecs
.indexes_to_subsidy
.bitcoin
.dateindex
.unwrap_cumulative(),
exit,
)?;
Ok(())
})?;
if let Some(indexes_to_sent_sum) = self.indexes_to_sent_sum.dollars.as_ref() {
self.indexes_to_annualized_volume_usd
.compute_all(starting_indexes, exit, |v| {
v.compute_sum(
starting_indexes.dateindex,
indexes_to_sent_sum.dateindex.unwrap_sum(),
365,
exit,
)?;
Ok(())
})?;
self.indexes_to_tx_usd_velocity
.compute_all(starting_indexes, exit, |v| {
v.compute_divide(
starting_indexes.dateindex,
self.indexes_to_annualized_volume_usd
.dateindex
.as_ref()
.unwrap(),
coinbase_vecs
.indexes_to_subsidy
.dollars
.as_ref()
.unwrap()
.dateindex
.unwrap_cumulative(),
exit,
)?;
Ok(())
})?;
}
self.indexes_to_tx_per_sec
.compute_all(starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.dateindex,
transaction_vecs.indexes_to_tx_count.dateindex.unwrap_sum(),
&indexes.time.dateindex_to_date,
|(i, tx_count, date, ..)| {
(
i,
(*tx_count as f64 / (date.completion() * ONE_DAY_IN_SEC_F64)).into(),
)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_inputs_per_sec
.compute_all(starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.dateindex,
transaction_vecs
.indexes_to_input_count
.dateindex
.unwrap_sum(),
&indexes.time.dateindex_to_date,
|(i, tx_count, date, ..)| {
(
i,
(*tx_count as f64 / (date.completion() * ONE_DAY_IN_SEC_F64)).into(),
)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_outputs_per_sec
.compute_all(starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.dateindex,
transaction_vecs
.indexes_to_output_count
.dateindex
.unwrap_sum(),
&indexes.time.dateindex_to_date,
|(i, tx_count, date, ..)| {
(
i,
(*tx_count as f64 / (date.completion() * ONE_DAY_IN_SEC_F64)).into(),
)
},
exit,
)?;
Ok(())
})?;
Ok(())
}
}

View File

@@ -0,0 +1,98 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{
grouped::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, Source, VecBuilderOptions},
indexes,
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v0 = Version::ZERO;
let v2 = Version::TWO;
let last = || VecBuilderOptions::default().add_last();
Ok(Self {
indexes_to_sent_sum: ComputedValueVecsFromHeight::forced_import(
db,
"sent_sum",
Source::Compute,
version + v0,
VecBuilderOptions::default().add_sum(),
compute_dollars,
indexes,
)?,
indexes_to_annualized_volume: ComputedVecsFromDateIndex::forced_import(
db,
"annualized_volume",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_annualized_volume_btc: ComputedVecsFromDateIndex::forced_import(
db,
"annualized_volume_btc",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_annualized_volume_usd: ComputedVecsFromDateIndex::forced_import(
db,
"annualized_volume_usd",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_tx_btc_velocity: ComputedVecsFromDateIndex::forced_import(
db,
"tx_btc_velocity",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_tx_usd_velocity: ComputedVecsFromDateIndex::forced_import(
db,
"tx_usd_velocity",
Source::Compute,
version + v0,
indexes,
last(),
)?,
indexes_to_tx_per_sec: ComputedVecsFromDateIndex::forced_import(
db,
"tx_per_sec",
Source::Compute,
version + v2,
indexes,
last(),
)?,
indexes_to_outputs_per_sec: ComputedVecsFromDateIndex::forced_import(
db,
"outputs_per_sec",
Source::Compute,
version + v2,
indexes,
last(),
)?,
indexes_to_inputs_per_sec: ComputedVecsFromDateIndex::forced_import(
db,
"inputs_per_sec",
Source::Compute,
version + v2,
indexes,
last(),
)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,18 @@
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Sats, StoredF32, StoredF64};
use crate::grouped::{ComputedValueVecsFromHeight, ComputedVecsFromDateIndex};
/// Volume and velocity metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub indexes_to_sent_sum: ComputedValueVecsFromHeight,
pub indexes_to_annualized_volume: ComputedVecsFromDateIndex<Sats>,
pub indexes_to_annualized_volume_btc: ComputedVecsFromDateIndex<Bitcoin>,
pub indexes_to_annualized_volume_usd: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_tx_btc_velocity: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_tx_usd_velocity: ComputedVecsFromDateIndex<StoredF64>,
pub indexes_to_tx_per_sec: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_outputs_per_sec: ComputedVecsFromDateIndex<StoredF32>,
pub indexes_to_inputs_per_sec: ComputedVecsFromDateIndex<StoredF32>,
}

View File

@@ -341,7 +341,7 @@ impl Vecs {
self.indexes_to_activity_to_vaultedness_ratio
.dateindex
.unwrap_last(),
chain.indexes_to_inflation_rate.dateindex.u(),
chain.coinbase.indexes_to_inflation_rate.dateindex.u(),
exit,
)?;
Ok(())
@@ -354,7 +354,7 @@ impl Vecs {
self.indexes_to_activity_to_vaultedness_ratio
.dateindex
.unwrap_last(),
chain.indexes_to_tx_btc_velocity.dateindex.u(),
chain.volume.indexes_to_tx_btc_velocity.dateindex.u(),
exit,
)?;
Ok(())
@@ -383,7 +383,7 @@ impl Vecs {
vec.compute_transform(
starting_indexes.height,
chain
.indexes_to_subsidy
.coinbase.indexes_to_subsidy
.dollars
.as_ref()
.unwrap()
@@ -575,7 +575,7 @@ impl Vecs {
self.indexes_to_activity_to_vaultedness_ratio
.dateindex
.unwrap_last(),
chain.indexes_to_tx_usd_velocity.dateindex.u(),
chain.volume.indexes_to_tx_usd_velocity.dateindex.u(),
exit,
)?;
Ok(())

View File

@@ -108,6 +108,7 @@ impl Vecs {
.get_unwrap(prev_i)
}));
indexes
.time
.dateindex_to_date
.iter()
.enumerate()

View File

@@ -9,7 +9,7 @@ use vecdb::{
use crate::utils::{OptionExt, get_percentile};
use super::ComputedVecValue;
use super::super::ComputedVecValue;
const VERSION: Version = Version::ZERO;

View File

@@ -6,7 +6,7 @@ use vecdb::{FromCoarserIndex, IterableBoxedVec, IterableCloneableVec, LazyVecFro
use crate::grouped::{EagerVecsBuilder, VecBuilderOptions};
use crate::utils::OptionExt;
use super::ComputedVecValue;
use super::super::ComputedVecValue;
#[allow(clippy::type_complexity)]
#[derive(Clone, Traversable)]

View File

@@ -0,0 +1,9 @@
mod eager;
mod lazy;
mod transform;
mod transform2;
pub use eager::*;
pub use lazy::*;
pub use transform::*;
pub use transform2::*;

View File

@@ -3,7 +3,11 @@ use brk_types::Version;
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, LazyVecFrom1, UnaryTransform, VecIndex};
use super::{ComputedVecValue, EagerVecsBuilder, LazyVecsBuilder};
use super::{
super::ComputedVecValue,
eager::EagerVecsBuilder,
lazy::LazyVecsBuilder,
};
const VERSION: Version = Version::ZERO;

View File

@@ -3,7 +3,11 @@ use brk_types::Version;
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableCloneableVec, LazyVecFrom2, VecIndex};
use super::{ComputedVecValue, EagerVecsBuilder, LazyVecsBuilder};
use super::{
super::ComputedVecValue,
eager::EagerVecsBuilder,
lazy::LazyVecsBuilder,
};
const VERSION: Version = Version::ZERO;

View File

@@ -11,7 +11,7 @@ use vecdb::{
use crate::{Indexes, grouped::LazyVecsBuilder, indexes, utils::OptionExt};
use super::{ComputedVecValue, EagerVecsBuilder, Source, VecBuilderOptions};
use crate::grouped::{ComputedVecValue, EagerVecsBuilder, Source, VecBuilderOptions};
#[derive(Clone)]
pub struct ComputedVecsFromDateIndex<T>
@@ -64,7 +64,7 @@ where
version + VERSION + Version::ZERO,
dateindex_source.clone(),
&dateindex_extra,
indexes.weekindex_to_weekindex.boxed_clone(),
indexes.time.weekindex_to_weekindex.boxed_clone(),
options.into(),
),
monthindex: LazyVecsBuilder::forced_import(
@@ -72,7 +72,7 @@ where
version + VERSION + Version::ZERO,
dateindex_source.clone(),
&dateindex_extra,
indexes.monthindex_to_monthindex.boxed_clone(),
indexes.time.monthindex_to_monthindex.boxed_clone(),
options.into(),
),
quarterindex: LazyVecsBuilder::forced_import(
@@ -80,7 +80,7 @@ where
version + VERSION + Version::ZERO,
dateindex_source.clone(),
&dateindex_extra,
indexes.quarterindex_to_quarterindex.boxed_clone(),
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
options.into(),
),
semesterindex: LazyVecsBuilder::forced_import(
@@ -88,7 +88,7 @@ where
version + VERSION + Version::ZERO,
dateindex_source.clone(),
&dateindex_extra,
indexes.semesterindex_to_semesterindex.boxed_clone(),
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
options.into(),
),
yearindex: LazyVecsBuilder::forced_import(
@@ -96,7 +96,7 @@ where
version + VERSION + Version::ZERO,
dateindex_source.clone(),
&dateindex_extra,
indexes.yearindex_to_yearindex.boxed_clone(),
indexes.time.yearindex_to_yearindex.boxed_clone(),
options.into(),
),
decadeindex: LazyVecsBuilder::forced_import(
@@ -104,7 +104,7 @@ where
version + VERSION + Version::ZERO,
dateindex_source.clone(),
&dateindex_extra,
indexes.decadeindex_to_decadeindex.boxed_clone(),
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
options.into(),
),
dateindex,

View File

@@ -0,0 +1,5 @@
mod standard;
mod strict;
pub use standard::*;
pub use strict::*;

View File

@@ -18,7 +18,7 @@ use crate::{
utils::OptionExt,
};
use super::{ComputedVecValue, EagerVecsBuilder, VecBuilderOptions};
use crate::grouped::{ComputedVecValue, EagerVecsBuilder, VecBuilderOptions};
#[derive(Clone)]
pub struct ComputedVecsFromHeight<T>
@@ -78,7 +78,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.weekindex_to_weekindex.boxed_clone(),
indexes.time.weekindex_to_weekindex.boxed_clone(),
options.into(),
),
monthindex: LazyVecsBuilder::forced_import(
@@ -86,7 +86,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.monthindex_to_monthindex.boxed_clone(),
indexes.time.monthindex_to_monthindex.boxed_clone(),
options.into(),
),
quarterindex: LazyVecsBuilder::forced_import(
@@ -94,7 +94,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.quarterindex_to_quarterindex.boxed_clone(),
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
options.into(),
),
semesterindex: LazyVecsBuilder::forced_import(
@@ -102,7 +102,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.semesterindex_to_semesterindex.boxed_clone(),
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
options.into(),
),
yearindex: LazyVecsBuilder::forced_import(
@@ -110,7 +110,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.yearindex_to_yearindex.boxed_clone(),
indexes.time.yearindex_to_yearindex.boxed_clone(),
options.into(),
),
decadeindex: LazyVecsBuilder::forced_import(
@@ -118,7 +118,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.decadeindex_to_decadeindex.boxed_clone(),
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
options.into(),
),
// halvingepoch: StorableVecGeneator::forced_import(db, name, version + VERSION + Version::ZERO, format, options)?,
@@ -127,7 +127,7 @@ where
version + VERSION + Version::ZERO,
height_source,
&height_extra,
indexes.difficultyepoch_to_difficultyepoch.boxed_clone(),
indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(),
options.into(),
),
height,
@@ -166,8 +166,8 @@ where
self.dateindex.compute(
starting_indexes.dateindex,
height,
&indexes.dateindex_to_first_height,
&indexes.dateindex_to_height_count,
&indexes.time.dateindex_to_first_height,
&indexes.time.dateindex_to_height_count,
exit,
)?;
} else {
@@ -179,8 +179,8 @@ where
self.dateindex.compute(
starting_indexes.dateindex,
height,
&indexes.dateindex_to_first_height,
&indexes.dateindex_to_height_count,
&indexes.time.dateindex_to_first_height,
&indexes.time.dateindex_to_height_count,
exit,
)?;
}

View File

@@ -9,7 +9,7 @@ use vecdb::{
use crate::{Indexes, indexes};
use super::{ComputedVecValue, EagerVecsBuilder, LazyVecsBuilder, VecBuilderOptions};
use crate::grouped::{ComputedVecValue, EagerVecsBuilder, LazyVecsBuilder, VecBuilderOptions};
#[derive(Clone)]
pub struct ComputedVecsFromHeightStrict<T>
@@ -53,7 +53,7 @@ where
version + VERSION + Version::ZERO,
Some(height.boxed_clone()),
&height_extra,
indexes.difficultyepoch_to_difficultyepoch.boxed_clone(),
indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(),
options.into(),
),
height,

View File

@@ -18,7 +18,7 @@ use crate::{
utils::OptionExt,
};
use super::{ComputedVecValue, EagerVecsBuilder, VecBuilderOptions};
use crate::grouped::{ComputedVecValue, EagerVecsBuilder, VecBuilderOptions};
#[derive(Clone)]
pub struct ComputedVecsFromTxindex<T>
@@ -72,7 +72,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.weekindex_to_weekindex.boxed_clone(),
indexes.time.weekindex_to_weekindex.boxed_clone(),
options.into(),
),
difficultyepoch: LazyVecsBuilder::forced_import(
@@ -80,7 +80,7 @@ where
version + VERSION + Version::ZERO,
None,
&height,
indexes.difficultyepoch_to_difficultyepoch.boxed_clone(),
indexes.block.difficultyepoch_to_difficultyepoch.boxed_clone(),
options.into(),
),
monthindex: LazyVecsBuilder::forced_import(
@@ -88,7 +88,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.monthindex_to_monthindex.boxed_clone(),
indexes.time.monthindex_to_monthindex.boxed_clone(),
options.into(),
),
quarterindex: LazyVecsBuilder::forced_import(
@@ -96,7 +96,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.quarterindex_to_quarterindex.boxed_clone(),
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
options.into(),
),
semesterindex: LazyVecsBuilder::forced_import(
@@ -104,7 +104,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.semesterindex_to_semesterindex.boxed_clone(),
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
options.into(),
),
yearindex: LazyVecsBuilder::forced_import(
@@ -112,7 +112,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.yearindex_to_yearindex.boxed_clone(),
indexes.time.yearindex_to_yearindex.boxed_clone(),
options.into(),
),
decadeindex: LazyVecsBuilder::forced_import(
@@ -120,7 +120,7 @@ where
version + VERSION + Version::ZERO,
None,
&dateindex,
indexes.decadeindex_to_decadeindex.boxed_clone(),
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
options.into(),
),
@@ -175,7 +175,7 @@ where
starting_indexes.height,
txindex,
&indexer.vecs.tx.height_to_first_txindex,
&indexes.height_to_txindex_count,
&indexes.block.height_to_txindex_count,
exit,
)?;
} else {
@@ -185,7 +185,7 @@ where
starting_indexes.height,
txindex,
&indexer.vecs.tx.height_to_first_txindex,
&indexes.height_to_txindex_count,
&indexes.block.height_to_txindex_count,
exit,
)?;
}
@@ -202,8 +202,8 @@ where
self.dateindex.from_aligned(
starting_indexes.dateindex,
&self.height,
&indexes.dateindex_to_first_height,
&indexes.dateindex_to_height_count,
&indexes.time.dateindex_to_first_height,
&indexes.time.dateindex_to_height_count,
exit,
)?;

View File

@@ -0,0 +1,9 @@
mod from_dateindex;
mod from_height;
mod from_txindex;
mod traits;
pub use from_dateindex::*;
pub use from_height::*;
pub use from_txindex::*;
pub use traits::*;

View File

@@ -5,7 +5,7 @@ use brk_types::{
use schemars::JsonSchema;
use vecdb::{AnyExportableVec, BinaryTransform, IterableCloneableVec, LazyVecFrom2};
use super::{ComputedVecValue, ComputedVecsFromDateIndex, ComputedVecsFromHeight, LazyTransform2Builder};
use crate::grouped::{ComputedVecValue, ComputedVecsFromDateIndex, ComputedVecsFromHeight, LazyTransform2Builder};
const VERSION: Version = Version::ZERO;

View File

@@ -6,7 +6,7 @@ use brk_types::{
use schemars::JsonSchema;
use vecdb::{AnyExportableVec, BinaryTransform, IterableBoxedVec, LazyVecFrom2};
use super::{ComputedVecValue, ComputedVecsFromHeight, LazyTransform2Builder};
use crate::grouped::{ComputedVecValue, ComputedVecsFromHeight, LazyTransform2Builder};
const VERSION: Version = Version::ZERO;

View File

@@ -0,0 +1,5 @@
mod from_dateindex;
mod from_height;
pub use from_dateindex::*;
pub use from_height::*;

View File

@@ -5,7 +5,7 @@ use brk_types::{
use schemars::JsonSchema;
use vecdb::{AnyExportableVec, IterableBoxedVec, LazyVecFrom1, UnaryTransform};
use super::{ComputedVecValue, ComputedVecsFromDateIndex, LazyTransformBuilder};
use crate::grouped::{ComputedVecValue, ComputedVecsFromDateIndex, LazyTransformBuilder};
const VERSION: Version = Version::ZERO;

View File

@@ -6,7 +6,7 @@ use brk_types::{
use schemars::JsonSchema;
use vecdb::{AnyExportableVec, IterableBoxedVec, LazyVecFrom1, UnaryTransform};
use super::{ComputedVecValue, ComputedVecsFromHeight, LazyTransformBuilder};
use crate::grouped::{ComputedVecValue, ComputedVecsFromHeight, LazyTransformBuilder};
const VERSION: Version = Version::ZERO;

View File

@@ -0,0 +1,7 @@
mod binary;
mod from_dateindex;
mod from_height;
pub use binary::*;
pub use from_dateindex::*;
pub use from_height::*;

View File

@@ -1,57 +1,15 @@
mod builder_eager;
mod builder_lazy;
mod builder_transform;
mod builder_transform2;
mod builder;
mod computed;
mod constant;
mod computed_from_dateindex;
mod computed_from_height;
mod computed_from_height_strict;
mod computed_from_txindex;
mod lazy2_from_dateindex;
mod lazy2_from_height;
mod lazy_from_dateindex;
mod lazy_from_height;
mod lazy_value_from_dateindex;
mod lazy_value_height;
mod lazy_value2_from_height;
// mod lazy_from_height_strict;
// mod lazy_from_txindex;
mod price_percentiles;
mod ratio_from_dateindex;
mod sd_from_dateindex;
mod lazy;
mod source;
mod specialized;
mod transforms;
mod value_from_dateindex;
mod value_from_height;
mod value_from_txindex;
mod value_height;
mod value;
pub use builder_eager::*;
pub use builder_lazy::*;
pub use builder_transform::*;
pub use builder_transform2::*;
use computed::*;
pub use constant::*;
pub use computed_from_dateindex::*;
pub use computed_from_height::*;
pub use computed_from_height_strict::*;
pub use computed_from_txindex::*;
pub use lazy_from_dateindex::*;
pub use lazy_from_height::*;
pub use lazy_value_from_dateindex::*;
pub use lazy_value_height::*;
pub use lazy_value2_from_height::*;
pub use lazy2_from_dateindex::*;
pub use lazy2_from_height::*;
// pub use lazy_from_height_strict::*;
// pub use lazy_from_txindex::*;
pub use price_percentiles::*;
pub use ratio_from_dateindex::*;
pub use sd_from_dateindex::*;
pub use builder::*;
pub use computed::*;
pub use lazy::*;
pub use source::*;
pub use specialized::*;
pub use transforms::*;
pub use value_from_dateindex::*;
pub use value_from_height::*;
pub use value_from_txindex::*;
pub use value_height::*;
pub use value::*;

View File

@@ -43,42 +43,42 @@ impl<T: VecValue + Formattable + Serialize + JsonSchema> ConstantVecs<T> {
height: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.height_to_height.boxed_clone(),
indexes.block.height_to_height.boxed_clone(),
),
dateindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.dateindex_to_dateindex.boxed_clone(),
indexes.time.dateindex_to_dateindex.boxed_clone(),
),
weekindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.weekindex_to_weekindex.boxed_clone(),
indexes.time.weekindex_to_weekindex.boxed_clone(),
),
monthindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.monthindex_to_monthindex.boxed_clone(),
indexes.time.monthindex_to_monthindex.boxed_clone(),
),
quarterindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.quarterindex_to_quarterindex.boxed_clone(),
indexes.time.quarterindex_to_quarterindex.boxed_clone(),
),
semesterindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.semesterindex_to_semesterindex.boxed_clone(),
indexes.time.semesterindex_to_semesterindex.boxed_clone(),
),
yearindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.yearindex_to_yearindex.boxed_clone(),
indexes.time.yearindex_to_yearindex.boxed_clone(),
),
decadeindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.decadeindex_to_decadeindex.boxed_clone(),
indexes.time.decadeindex_to_decadeindex.boxed_clone(),
),
}
}

View File

@@ -0,0 +1,9 @@
mod constant;
mod percentiles;
mod ratio;
mod stddev;
pub use constant::*;
pub use percentiles::*;
pub use ratio::*;
pub use stddev::*;

View File

@@ -8,7 +8,7 @@ use vecdb::{
use crate::{Indexes, indexes};
use super::{ComputedVecsFromDateIndex, Source, VecBuilderOptions};
use super::super::{ComputedVecsFromDateIndex, Source, VecBuilderOptions};
pub const PERCENTILES: [u8; 19] = [
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95,

View File

@@ -16,7 +16,7 @@ use crate::{
utils::{OptionExt, get_percentile},
};
use super::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, VecBuilderOptions};
use super::super::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, VecBuilderOptions};
#[derive(Clone, Traversable)]
pub struct ComputedRatioVecsFromDateIndex {

View File

@@ -10,7 +10,7 @@ use vecdb::{
use crate::{Indexes, grouped::source::Source, indexes, price, utils::OptionExt};
use super::{
use super::super::{
ClosePriceTimesRatio, ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, VecBuilderOptions,
};

View File

@@ -11,7 +11,7 @@ use crate::{
utils::OptionExt,
};
use super::{Source, VecBuilderOptions};
use crate::grouped::{Source, VecBuilderOptions};
#[derive(Clone, Traversable)]
pub struct ComputedValueVecsFromDateIndex {

View File

@@ -11,7 +11,7 @@ use crate::{
utils::OptionExt,
};
use super::{ComputedVecsFromHeight, VecBuilderOptions};
use crate::grouped::{ComputedVecsFromHeight, VecBuilderOptions};
#[derive(Clone, Traversable)]
pub struct ComputedValueVecsFromHeight {

View File

@@ -9,7 +9,7 @@ use vecdb::{
use crate::{Indexes, grouped::Source, indexes, price, utils::OptionExt};
use super::{ComputedVecsFromTxindex, VecBuilderOptions};
use crate::grouped::{ComputedVecsFromTxindex, VecBuilderOptions};
#[derive(Clone, Traversable)]
pub struct ComputedValueVecsFromTxindex {

View File

@@ -0,0 +1,7 @@
mod from_dateindex;
mod from_height;
mod from_txindex;
pub use from_dateindex::*;
pub use from_height::*;
pub use from_txindex::*;

View File

@@ -2,7 +2,7 @@ use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec};
use super::{ComputedValueVecsFromHeight, LazyVecsFrom2FromHeight};
use crate::grouped::{ComputedValueVecsFromHeight, LazyVecsFrom2FromHeight};
/// Lazy value vecs computed from two `ComputedValueVecsFromHeight` sources via binary transforms.
/// Used for computing coinbase = subsidy + fee.

View File

@@ -2,7 +2,7 @@ use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Sats, Version};
use vecdb::{IterableCloneableVec, UnaryTransform};
use super::{ComputedValueVecsFromDateIndex, LazyVecsFromDateIndex};
use crate::grouped::{ComputedValueVecsFromDateIndex, LazyVecsFromDateIndex};
const VERSION: Version = Version::ZERO;

View File

@@ -0,0 +1,9 @@
mod binary_from_height;
mod from_dateindex;
mod height;
mod value_height;
pub use binary_from_height::*;
pub use from_dateindex::*;
pub use height::*;
pub use value_height::*;

View File

@@ -0,0 +1,5 @@
mod computed;
mod lazy;
pub use computed::*;
pub use lazy::*;

View File

@@ -1,667 +0,0 @@
use std::{ops::Deref, path::Path};
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{
Date, DateIndex, DecadeIndex, DifficultyEpoch, EmptyOutputIndex, HalvingEpoch, Height,
MonthIndex, OpReturnIndex, OutPoint, P2AAddressIndex, P2ABytes, P2MSOutputIndex,
P2PK33AddressIndex, P2PK33Bytes, P2PK65AddressIndex, P2PK65Bytes, P2PKHAddressIndex,
P2PKHBytes, P2SHAddressIndex, P2SHBytes, P2TRAddressIndex, P2TRBytes, P2WPKHAddressIndex,
P2WPKHBytes, P2WSHAddressIndex, P2WSHBytes, QuarterIndex, Sats, SemesterIndex, StoredU64,
Timestamp, TxInIndex, TxIndex, TxOutIndex, Txid, UnknownOutputIndex, Version, WeekIndex,
YearIndex,
};
use vecdb::{
Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, LazyVecFrom1, PAGE_SIZE, PcoVec,
TypedVecIterator,
};
const VERSION: Version = Version::ZERO;
pub const DB_NAME: &str = "indexes";
#[derive(Clone, Traversable)]
pub struct Vecs {
db: Database,
pub dateindex_to_date: EagerVec<PcoVec<DateIndex, Date>>,
pub dateindex_to_dateindex: EagerVec<PcoVec<DateIndex, DateIndex>>,
pub dateindex_to_first_height: EagerVec<PcoVec<DateIndex, Height>>,
pub dateindex_to_height_count: EagerVec<PcoVec<DateIndex, StoredU64>>,
pub dateindex_to_monthindex: EagerVec<PcoVec<DateIndex, MonthIndex>>,
pub dateindex_to_weekindex: EagerVec<PcoVec<DateIndex, WeekIndex>>,
pub decadeindex_to_decadeindex: EagerVec<PcoVec<DecadeIndex, DecadeIndex>>,
pub decadeindex_to_first_yearindex: EagerVec<PcoVec<DecadeIndex, YearIndex>>,
pub decadeindex_to_yearindex_count: EagerVec<PcoVec<DecadeIndex, StoredU64>>,
pub difficultyepoch_to_difficultyepoch: EagerVec<PcoVec<DifficultyEpoch, DifficultyEpoch>>,
pub difficultyepoch_to_first_height: EagerVec<PcoVec<DifficultyEpoch, Height>>,
pub difficultyepoch_to_height_count: EagerVec<PcoVec<DifficultyEpoch, StoredU64>>,
pub emptyoutputindex_to_emptyoutputindex:
LazyVecFrom1<EmptyOutputIndex, EmptyOutputIndex, EmptyOutputIndex, TxIndex>,
pub halvingepoch_to_first_height: EagerVec<PcoVec<HalvingEpoch, Height>>,
pub halvingepoch_to_halvingepoch: EagerVec<PcoVec<HalvingEpoch, HalvingEpoch>>,
pub height_to_date: EagerVec<PcoVec<Height, Date>>,
pub height_to_date_fixed: EagerVec<PcoVec<Height, Date>>,
pub height_to_dateindex: EagerVec<PcoVec<Height, DateIndex>>,
pub height_to_difficultyepoch: EagerVec<PcoVec<Height, DifficultyEpoch>>,
pub height_to_halvingepoch: EagerVec<PcoVec<Height, HalvingEpoch>>,
pub height_to_height: EagerVec<PcoVec<Height, Height>>,
pub height_to_timestamp_fixed: EagerVec<PcoVec<Height, Timestamp>>,
pub height_to_txindex_count: EagerVec<PcoVec<Height, StoredU64>>,
pub monthindex_to_dateindex_count: EagerVec<PcoVec<MonthIndex, StoredU64>>,
pub monthindex_to_first_dateindex: EagerVec<PcoVec<MonthIndex, DateIndex>>,
pub monthindex_to_monthindex: EagerVec<PcoVec<MonthIndex, MonthIndex>>,
pub monthindex_to_quarterindex: EagerVec<PcoVec<MonthIndex, QuarterIndex>>,
pub monthindex_to_semesterindex: EagerVec<PcoVec<MonthIndex, SemesterIndex>>,
pub monthindex_to_yearindex: EagerVec<PcoVec<MonthIndex, YearIndex>>,
pub opreturnindex_to_opreturnindex:
LazyVecFrom1<OpReturnIndex, OpReturnIndex, OpReturnIndex, TxIndex>,
pub p2aaddressindex_to_p2aaddressindex:
LazyVecFrom1<P2AAddressIndex, P2AAddressIndex, P2AAddressIndex, P2ABytes>,
pub p2msoutputindex_to_p2msoutputindex:
LazyVecFrom1<P2MSOutputIndex, P2MSOutputIndex, P2MSOutputIndex, TxIndex>,
pub p2pk33addressindex_to_p2pk33addressindex:
LazyVecFrom1<P2PK33AddressIndex, P2PK33AddressIndex, P2PK33AddressIndex, P2PK33Bytes>,
pub p2pk65addressindex_to_p2pk65addressindex:
LazyVecFrom1<P2PK65AddressIndex, P2PK65AddressIndex, P2PK65AddressIndex, P2PK65Bytes>,
pub p2pkhaddressindex_to_p2pkhaddressindex:
LazyVecFrom1<P2PKHAddressIndex, P2PKHAddressIndex, P2PKHAddressIndex, P2PKHBytes>,
pub p2shaddressindex_to_p2shaddressindex:
LazyVecFrom1<P2SHAddressIndex, P2SHAddressIndex, P2SHAddressIndex, P2SHBytes>,
pub p2traddressindex_to_p2traddressindex:
LazyVecFrom1<P2TRAddressIndex, P2TRAddressIndex, P2TRAddressIndex, P2TRBytes>,
pub p2wpkhaddressindex_to_p2wpkhaddressindex:
LazyVecFrom1<P2WPKHAddressIndex, P2WPKHAddressIndex, P2WPKHAddressIndex, P2WPKHBytes>,
pub p2wshaddressindex_to_p2wshaddressindex:
LazyVecFrom1<P2WSHAddressIndex, P2WSHAddressIndex, P2WSHAddressIndex, P2WSHBytes>,
pub quarterindex_to_first_monthindex: EagerVec<PcoVec<QuarterIndex, MonthIndex>>,
pub quarterindex_to_monthindex_count: EagerVec<PcoVec<QuarterIndex, StoredU64>>,
pub quarterindex_to_quarterindex: EagerVec<PcoVec<QuarterIndex, QuarterIndex>>,
pub semesterindex_to_first_monthindex: EagerVec<PcoVec<SemesterIndex, MonthIndex>>,
pub semesterindex_to_monthindex_count: EagerVec<PcoVec<SemesterIndex, StoredU64>>,
pub semesterindex_to_semesterindex: EagerVec<PcoVec<SemesterIndex, SemesterIndex>>,
pub txindex_to_input_count: EagerVec<PcoVec<TxIndex, StoredU64>>,
pub txindex_to_output_count: EagerVec<PcoVec<TxIndex, StoredU64>>,
pub txindex_to_txindex: LazyVecFrom1<TxIndex, TxIndex, TxIndex, Txid>,
pub txinindex_to_txinindex: LazyVecFrom1<TxInIndex, TxInIndex, TxInIndex, OutPoint>,
pub txoutindex_to_txoutindex: LazyVecFrom1<TxOutIndex, TxOutIndex, TxOutIndex, Sats>,
pub unknownoutputindex_to_unknownoutputindex:
LazyVecFrom1<UnknownOutputIndex, UnknownOutputIndex, UnknownOutputIndex, TxIndex>,
pub weekindex_to_dateindex_count: EagerVec<PcoVec<WeekIndex, StoredU64>>,
pub weekindex_to_first_dateindex: EagerVec<PcoVec<WeekIndex, DateIndex>>,
pub weekindex_to_weekindex: EagerVec<PcoVec<WeekIndex, WeekIndex>>,
pub yearindex_to_decadeindex: EagerVec<PcoVec<YearIndex, DecadeIndex>>,
pub yearindex_to_first_monthindex: EagerVec<PcoVec<YearIndex, MonthIndex>>,
pub yearindex_to_monthindex_count: EagerVec<PcoVec<YearIndex, StoredU64>>,
pub yearindex_to_yearindex: EagerVec<PcoVec<YearIndex, YearIndex>>,
}
impl Vecs {
pub fn forced_import(
parent: &Path,
parent_version: Version,
indexer: &Indexer,
) -> Result<Self> {
let db = Database::open(&parent.join(DB_NAME))?;
db.set_min_len(PAGE_SIZE * 10_000_000)?;
let version = parent_version + VERSION;
macro_rules! eager {
($name:expr) => {
EagerVec::forced_import(&db, $name, version)?
};
}
macro_rules! lazy {
($name:expr, $source:expr) => {
LazyVecFrom1::init($name, version, $source.boxed_clone(), |index, _| {
Some(index)
})
};
}
let this = Self {
txoutindex_to_txoutindex: lazy!("txoutindex", indexer.vecs.txout.txoutindex_to_value),
txinindex_to_txinindex: lazy!("txinindex", indexer.vecs.txin.txinindex_to_outpoint),
p2pk33addressindex_to_p2pk33addressindex: lazy!(
"p2pk33addressindex",
indexer.vecs.address.p2pk33addressindex_to_p2pk33bytes
),
p2pk65addressindex_to_p2pk65addressindex: lazy!(
"p2pk65addressindex",
indexer.vecs.address.p2pk65addressindex_to_p2pk65bytes
),
p2pkhaddressindex_to_p2pkhaddressindex: lazy!(
"p2pkhaddressindex",
indexer.vecs.address.p2pkhaddressindex_to_p2pkhbytes
),
p2shaddressindex_to_p2shaddressindex: lazy!(
"p2shaddressindex",
indexer.vecs.address.p2shaddressindex_to_p2shbytes
),
p2traddressindex_to_p2traddressindex: lazy!(
"p2traddressindex",
indexer.vecs.address.p2traddressindex_to_p2trbytes
),
p2wpkhaddressindex_to_p2wpkhaddressindex: lazy!(
"p2wpkhaddressindex",
indexer.vecs.address.p2wpkhaddressindex_to_p2wpkhbytes
),
p2wshaddressindex_to_p2wshaddressindex: lazy!(
"p2wshaddressindex",
indexer.vecs.address.p2wshaddressindex_to_p2wshbytes
),
p2aaddressindex_to_p2aaddressindex: lazy!(
"p2aaddressindex",
indexer.vecs.address.p2aaddressindex_to_p2abytes
),
p2msoutputindex_to_p2msoutputindex: lazy!(
"p2msoutputindex",
indexer.vecs.output.p2msoutputindex_to_txindex
),
emptyoutputindex_to_emptyoutputindex: lazy!(
"emptyoutputindex",
indexer.vecs.output.emptyoutputindex_to_txindex
),
unknownoutputindex_to_unknownoutputindex: lazy!(
"unknownoutputindex",
indexer.vecs.output.unknownoutputindex_to_txindex
),
opreturnindex_to_opreturnindex: lazy!(
"opreturnindex",
indexer.vecs.output.opreturnindex_to_txindex
),
txindex_to_txindex: lazy!("txindex", indexer.vecs.tx.txindex_to_txid),
txindex_to_input_count: eager!("input_count"),
txindex_to_output_count: eager!("output_count"),
dateindex_to_date: eager!("date"),
dateindex_to_dateindex: eager!("dateindex"),
dateindex_to_first_height: eager!("first_height"),
dateindex_to_monthindex: eager!("monthindex"),
dateindex_to_weekindex: eager!("weekindex"),
decadeindex_to_decadeindex: eager!("decadeindex"),
decadeindex_to_first_yearindex: eager!("first_yearindex"),
difficultyepoch_to_difficultyepoch: eager!("difficultyepoch"),
difficultyepoch_to_first_height: eager!("first_height"),
halvingepoch_to_first_height: eager!("first_height"),
halvingepoch_to_halvingepoch: eager!("halvingepoch"),
height_to_date: eager!("date"),
height_to_difficultyepoch: eager!("difficultyepoch"),
height_to_halvingepoch: eager!("halvingepoch"),
height_to_height: eager!("height"),
monthindex_to_first_dateindex: eager!("first_dateindex"),
monthindex_to_monthindex: eager!("monthindex"),
monthindex_to_quarterindex: eager!("quarterindex"),
monthindex_to_semesterindex: eager!("semesterindex"),
monthindex_to_yearindex: eager!("yearindex"),
quarterindex_to_first_monthindex: eager!("first_monthindex"),
semesterindex_to_first_monthindex: eager!("first_monthindex"),
weekindex_to_first_dateindex: eager!("first_dateindex"),
yearindex_to_first_monthindex: eager!("first_monthindex"),
quarterindex_to_quarterindex: eager!("quarterindex"),
semesterindex_to_semesterindex: eager!("semesterindex"),
weekindex_to_weekindex: eager!("weekindex"),
yearindex_to_decadeindex: eager!("decadeindex"),
yearindex_to_yearindex: eager!("yearindex"),
height_to_date_fixed: eager!("date_fixed"),
height_to_dateindex: eager!("dateindex"),
height_to_timestamp_fixed: eager!("timestamp_fixed"),
height_to_txindex_count: eager!("txindex_count"),
dateindex_to_height_count: eager!("height_count"),
weekindex_to_dateindex_count: eager!("dateindex_count"),
difficultyepoch_to_height_count: eager!("height_count"),
monthindex_to_dateindex_count: eager!("dateindex_count"),
quarterindex_to_monthindex_count: eager!("monthindex_count"),
semesterindex_to_monthindex_count: eager!("monthindex_count"),
yearindex_to_monthindex_count: eager!("monthindex_count"),
decadeindex_to_yearindex_count: eager!("yearindex_count"),
db,
};
this.db.retain_regions(
this.iter_any_exportable()
.flat_map(|v| v.region_names())
.collect(),
)?;
this.db.compact()?;
Ok(this)
}
pub fn compute(
&mut self,
indexer: &Indexer,
starting_indexes: brk_indexer::Indexes,
exit: &Exit,
) -> Result<Indexes> {
let indexes = self.compute_(indexer, starting_indexes, exit)?;
let _lock = exit.lock();
self.db.compact()?;
Ok(indexes)
}
fn compute_(
&mut self,
indexer: &Indexer,
starting_indexes: brk_indexer::Indexes,
exit: &Exit,
) -> Result<Indexes> {
self.txindex_to_input_count.compute_count_from_indexes(
starting_indexes.txindex,
&indexer.vecs.tx.txindex_to_first_txinindex,
&indexer.vecs.txin.txinindex_to_outpoint,
exit,
)?;
self.txindex_to_output_count.compute_count_from_indexes(
starting_indexes.txindex,
&indexer.vecs.tx.txindex_to_first_txoutindex,
&indexer.vecs.txout.txoutindex_to_value,
exit,
)?;
self.height_to_txindex_count.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.tx.height_to_first_txindex,
&indexer.vecs.tx.txindex_to_txid,
exit,
)?;
self.height_to_height.compute_from_index(
starting_indexes.height,
&indexer.vecs.block.height_to_weight,
exit,
)?;
self.height_to_date.compute_transform(
starting_indexes.height,
&indexer.vecs.block.height_to_timestamp,
|(h, t, ..)| (h, Date::from(t)),
exit,
)?;
let mut prev_timestamp_fixed = None;
self.height_to_timestamp_fixed.compute_transform(
starting_indexes.height,
&indexer.vecs.block.height_to_timestamp,
|(h, timestamp, height_to_timestamp_fixed_iter)| {
if prev_timestamp_fixed.is_none()
&& let Some(prev_h) = h.decremented()
{
prev_timestamp_fixed.replace(
height_to_timestamp_fixed_iter
.into_iter()
.get_unwrap(prev_h),
);
}
let timestamp_fixed =
prev_timestamp_fixed.map_or(timestamp, |prev_d| prev_d.max(timestamp));
prev_timestamp_fixed.replace(timestamp_fixed);
(h, timestamp_fixed)
},
exit,
)?;
self.height_to_date_fixed.compute_transform(
starting_indexes.height,
&self.height_to_timestamp_fixed,
|(h, t, ..)| (h, Date::from(t)),
exit,
)?;
let decremented_starting_height = starting_indexes.height.decremented().unwrap_or_default();
let starting_dateindex = self
.height_to_dateindex
.into_iter()
.get(decremented_starting_height)
.unwrap_or_default();
self.height_to_dateindex.compute_transform(
starting_indexes.height,
&self.height_to_date_fixed,
|(h, d, ..)| (h, DateIndex::try_from(d).unwrap()),
exit,
)?;
let starting_dateindex = if let Some(dateindex) = self
.height_to_dateindex
.into_iter()
.get(decremented_starting_height)
{
starting_dateindex.min(dateindex)
} else {
starting_dateindex
};
self.dateindex_to_first_height.compute_coarser(
starting_indexes.height,
&self.height_to_dateindex,
exit,
)?;
self.dateindex_to_dateindex.compute_from_index(
starting_dateindex,
&self.dateindex_to_first_height,
exit,
)?;
self.dateindex_to_date.compute_from_index(
starting_dateindex,
&self.dateindex_to_first_height,
exit,
)?;
self.dateindex_to_height_count.compute_count_from_indexes(
starting_dateindex,
&self.dateindex_to_first_height,
&indexer.vecs.block.height_to_weight,
exit,
)?;
let starting_weekindex = self
.dateindex_to_weekindex
.into_iter()
.get(starting_dateindex)
.unwrap_or_default();
self.dateindex_to_weekindex.compute_range(
starting_dateindex,
&self.dateindex_to_dateindex,
|i| (i, WeekIndex::from(i)),
exit,
)?;
self.weekindex_to_first_dateindex.compute_coarser(
starting_dateindex,
&self.dateindex_to_weekindex,
exit,
)?;
self.weekindex_to_weekindex.compute_from_index(
starting_weekindex,
&self.weekindex_to_first_dateindex,
exit,
)?;
self.weekindex_to_dateindex_count
.compute_count_from_indexes(
starting_weekindex,
&self.weekindex_to_first_dateindex,
&self.dateindex_to_date,
exit,
)?;
let starting_difficultyepoch = self
.height_to_difficultyepoch
.into_iter()
.get(decremented_starting_height)
.unwrap_or_default();
self.height_to_difficultyepoch.compute_from_index(
starting_indexes.height,
&indexer.vecs.block.height_to_weight,
exit,
)?;
self.difficultyepoch_to_first_height.compute_coarser(
starting_indexes.height,
&self.height_to_difficultyepoch,
exit,
)?;
self.difficultyepoch_to_difficultyepoch.compute_from_index(
starting_difficultyepoch,
&self.difficultyepoch_to_first_height,
exit,
)?;
self.difficultyepoch_to_height_count
.compute_count_from_indexes(
starting_difficultyepoch,
&self.difficultyepoch_to_first_height,
&self.height_to_date,
exit,
)?;
let starting_monthindex = self
.dateindex_to_monthindex
.into_iter()
.get(starting_dateindex)
.unwrap_or_default();
self.dateindex_to_monthindex.compute_range(
starting_dateindex,
&self.dateindex_to_dateindex,
|i| (i, MonthIndex::from(i)),
exit,
)?;
self.monthindex_to_first_dateindex.compute_coarser(
starting_dateindex,
&self.dateindex_to_monthindex,
exit,
)?;
self.monthindex_to_monthindex.compute_from_index(
starting_monthindex,
&self.monthindex_to_first_dateindex,
exit,
)?;
self.monthindex_to_dateindex_count
.compute_count_from_indexes(
starting_monthindex,
&self.monthindex_to_first_dateindex,
&self.dateindex_to_date,
exit,
)?;
let starting_quarterindex = self
.monthindex_to_quarterindex
.into_iter()
.get(starting_monthindex)
.unwrap_or_default();
self.monthindex_to_quarterindex.compute_from_index(
starting_monthindex,
&self.monthindex_to_first_dateindex,
exit,
)?;
self.quarterindex_to_first_monthindex.compute_coarser(
starting_monthindex,
&self.monthindex_to_quarterindex,
exit,
)?;
// let quarter_count = self.quarterindex_to_first_monthindex.len();
self.quarterindex_to_quarterindex.compute_from_index(
starting_quarterindex,
&self.quarterindex_to_first_monthindex,
exit,
)?;
self.quarterindex_to_monthindex_count
.compute_count_from_indexes(
starting_quarterindex,
&self.quarterindex_to_first_monthindex,
&self.monthindex_to_monthindex,
exit,
)?;
let starting_semesterindex = self
.monthindex_to_semesterindex
.into_iter()
.get(starting_monthindex)
.unwrap_or_default();
self.monthindex_to_semesterindex.compute_from_index(
starting_monthindex,
&self.monthindex_to_first_dateindex,
exit,
)?;
self.semesterindex_to_first_monthindex.compute_coarser(
starting_monthindex,
&self.monthindex_to_semesterindex,
exit,
)?;
// let semester_count = self.semesterindex_to_first_monthindex.len();
self.semesterindex_to_semesterindex.compute_from_index(
starting_semesterindex,
&self.semesterindex_to_first_monthindex,
exit,
)?;
self.semesterindex_to_monthindex_count
.compute_count_from_indexes(
starting_semesterindex,
&self.semesterindex_to_first_monthindex,
&self.monthindex_to_monthindex,
exit,
)?;
let starting_yearindex = self
.monthindex_to_yearindex
.into_iter()
.get(starting_monthindex)
.unwrap_or_default();
self.monthindex_to_yearindex.compute_from_index(
starting_monthindex,
&self.monthindex_to_first_dateindex,
exit,
)?;
self.yearindex_to_first_monthindex.compute_coarser(
starting_monthindex,
&self.monthindex_to_yearindex,
exit,
)?;
self.yearindex_to_yearindex.compute_from_index(
starting_yearindex,
&self.yearindex_to_first_monthindex,
exit,
)?;
self.yearindex_to_monthindex_count
.compute_count_from_indexes(
starting_yearindex,
&self.yearindex_to_first_monthindex,
&self.monthindex_to_monthindex,
exit,
)?;
let starting_halvingepoch = self
.height_to_halvingepoch
.into_iter()
.get(decremented_starting_height)
.unwrap_or_default();
self.height_to_halvingepoch.compute_from_index(
starting_indexes.height,
&indexer.vecs.block.height_to_weight,
exit,
)?;
self.halvingepoch_to_first_height.compute_coarser(
starting_indexes.height,
&self.height_to_halvingepoch,
exit,
)?;
self.halvingepoch_to_halvingepoch.compute_from_index(
starting_halvingepoch,
&self.halvingepoch_to_first_height,
exit,
)?;
let starting_decadeindex = self
.yearindex_to_decadeindex
.into_iter()
.get(starting_yearindex)
.unwrap_or_default();
self.yearindex_to_decadeindex.compute_from_index(
starting_yearindex,
&self.yearindex_to_first_monthindex,
exit,
)?;
self.decadeindex_to_first_yearindex.compute_coarser(
starting_yearindex,
&self.yearindex_to_decadeindex,
exit,
)?;
self.decadeindex_to_decadeindex.compute_from_index(
starting_decadeindex,
&self.decadeindex_to_first_yearindex,
exit,
)?;
self.decadeindex_to_yearindex_count
.compute_count_from_indexes(
starting_decadeindex,
&self.decadeindex_to_first_yearindex,
&self.yearindex_to_yearindex,
exit,
)?;
Ok(Indexes {
indexes: starting_indexes,
dateindex: starting_dateindex,
weekindex: starting_weekindex,
monthindex: starting_monthindex,
quarterindex: starting_quarterindex,
semesterindex: starting_semesterindex,
yearindex: starting_yearindex,
decadeindex: starting_decadeindex,
difficultyepoch: starting_difficultyepoch,
halvingepoch: starting_halvingepoch,
})
}
}
#[derive(Debug, Clone)]
pub struct Indexes {
indexes: brk_indexer::Indexes,
pub dateindex: DateIndex,
pub weekindex: WeekIndex,
pub monthindex: MonthIndex,
pub quarterindex: QuarterIndex,
pub semesterindex: SemesterIndex,
pub yearindex: YearIndex,
pub decadeindex: DecadeIndex,
pub difficultyepoch: DifficultyEpoch,
pub halvingepoch: HalvingEpoch,
}
impl Indexes {
pub fn update_from_height(&mut self, height: Height, indexes: &Vecs) {
self.indexes.height = height;
self.dateindex =
DateIndex::try_from(indexes.height_to_date_fixed.into_iter().get_unwrap(height))
.unwrap();
self.weekindex = WeekIndex::from(self.dateindex);
self.monthindex = MonthIndex::from(self.dateindex);
self.quarterindex = QuarterIndex::from(self.monthindex);
self.semesterindex = SemesterIndex::from(self.monthindex);
self.yearindex = YearIndex::from(self.monthindex);
self.decadeindex = DecadeIndex::from(self.dateindex);
self.difficultyepoch = DifficultyEpoch::from(self.height);
self.halvingepoch = HalvingEpoch::from(self.height);
}
}
impl Deref for Indexes {
type Target = brk_indexer::Indexes;
fn deref(&self) -> &Self::Target {
&self.indexes
}
}

View File

@@ -0,0 +1,84 @@
use brk_indexer::Indexer;
use brk_types::Version;
use vecdb::{IterableCloneableVec, LazyVecFrom1};
use super::Vecs;
impl Vecs {
pub fn forced_import(version: Version, indexer: &Indexer) -> Self {
Self {
p2pk33addressindex_to_p2pk33addressindex: LazyVecFrom1::init(
"p2pk33addressindex",
version,
indexer.vecs.address.p2pk33addressindex_to_p2pk33bytes.boxed_clone(),
|index, _| Some(index),
),
p2pk65addressindex_to_p2pk65addressindex: LazyVecFrom1::init(
"p2pk65addressindex",
version,
indexer.vecs.address.p2pk65addressindex_to_p2pk65bytes.boxed_clone(),
|index, _| Some(index),
),
p2pkhaddressindex_to_p2pkhaddressindex: LazyVecFrom1::init(
"p2pkhaddressindex",
version,
indexer.vecs.address.p2pkhaddressindex_to_p2pkhbytes.boxed_clone(),
|index, _| Some(index),
),
p2shaddressindex_to_p2shaddressindex: LazyVecFrom1::init(
"p2shaddressindex",
version,
indexer.vecs.address.p2shaddressindex_to_p2shbytes.boxed_clone(),
|index, _| Some(index),
),
p2traddressindex_to_p2traddressindex: LazyVecFrom1::init(
"p2traddressindex",
version,
indexer.vecs.address.p2traddressindex_to_p2trbytes.boxed_clone(),
|index, _| Some(index),
),
p2wpkhaddressindex_to_p2wpkhaddressindex: LazyVecFrom1::init(
"p2wpkhaddressindex",
version,
indexer.vecs.address.p2wpkhaddressindex_to_p2wpkhbytes.boxed_clone(),
|index, _| Some(index),
),
p2wshaddressindex_to_p2wshaddressindex: LazyVecFrom1::init(
"p2wshaddressindex",
version,
indexer.vecs.address.p2wshaddressindex_to_p2wshbytes.boxed_clone(),
|index, _| Some(index),
),
p2aaddressindex_to_p2aaddressindex: LazyVecFrom1::init(
"p2aaddressindex",
version,
indexer.vecs.address.p2aaddressindex_to_p2abytes.boxed_clone(),
|index, _| Some(index),
),
p2msoutputindex_to_p2msoutputindex: LazyVecFrom1::init(
"p2msoutputindex",
version,
indexer.vecs.output.p2msoutputindex_to_txindex.boxed_clone(),
|index, _| Some(index),
),
emptyoutputindex_to_emptyoutputindex: LazyVecFrom1::init(
"emptyoutputindex",
version,
indexer.vecs.output.emptyoutputindex_to_txindex.boxed_clone(),
|index, _| Some(index),
),
unknownoutputindex_to_unknownoutputindex: LazyVecFrom1::init(
"unknownoutputindex",
version,
indexer.vecs.output.unknownoutputindex_to_txindex.boxed_clone(),
|index, _| Some(index),
),
opreturnindex_to_opreturnindex: LazyVecFrom1::init(
"opreturnindex",
version,
indexer.vecs.output.opreturnindex_to_txindex.boxed_clone(),
|index, _| Some(index),
),
}
}
}

View File

@@ -0,0 +1,4 @@
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,36 @@
use brk_traversable::Traversable;
use brk_types::{
EmptyOutputIndex, OpReturnIndex, P2AAddressIndex, P2ABytes, P2MSOutputIndex,
P2PK33AddressIndex, P2PK33Bytes, P2PK65AddressIndex, P2PK65Bytes, P2PKHAddressIndex,
P2PKHBytes, P2SHAddressIndex, P2SHBytes, P2TRAddressIndex, P2TRBytes, P2WPKHAddressIndex,
P2WPKHBytes, P2WSHAddressIndex, P2WSHBytes, TxIndex, UnknownOutputIndex,
};
use vecdb::LazyVecFrom1;
#[derive(Clone, Traversable)]
pub struct Vecs {
pub emptyoutputindex_to_emptyoutputindex:
LazyVecFrom1<EmptyOutputIndex, EmptyOutputIndex, EmptyOutputIndex, TxIndex>,
pub opreturnindex_to_opreturnindex:
LazyVecFrom1<OpReturnIndex, OpReturnIndex, OpReturnIndex, TxIndex>,
pub p2aaddressindex_to_p2aaddressindex:
LazyVecFrom1<P2AAddressIndex, P2AAddressIndex, P2AAddressIndex, P2ABytes>,
pub p2msoutputindex_to_p2msoutputindex:
LazyVecFrom1<P2MSOutputIndex, P2MSOutputIndex, P2MSOutputIndex, TxIndex>,
pub p2pk33addressindex_to_p2pk33addressindex:
LazyVecFrom1<P2PK33AddressIndex, P2PK33AddressIndex, P2PK33AddressIndex, P2PK33Bytes>,
pub p2pk65addressindex_to_p2pk65addressindex:
LazyVecFrom1<P2PK65AddressIndex, P2PK65AddressIndex, P2PK65AddressIndex, P2PK65Bytes>,
pub p2pkhaddressindex_to_p2pkhaddressindex:
LazyVecFrom1<P2PKHAddressIndex, P2PKHAddressIndex, P2PKHAddressIndex, P2PKHBytes>,
pub p2shaddressindex_to_p2shaddressindex:
LazyVecFrom1<P2SHAddressIndex, P2SHAddressIndex, P2SHAddressIndex, P2SHBytes>,
pub p2traddressindex_to_p2traddressindex:
LazyVecFrom1<P2TRAddressIndex, P2TRAddressIndex, P2TRAddressIndex, P2TRBytes>,
pub p2wpkhaddressindex_to_p2wpkhaddressindex:
LazyVecFrom1<P2WPKHAddressIndex, P2WPKHAddressIndex, P2WPKHAddressIndex, P2WPKHBytes>,
pub p2wshaddressindex_to_p2wshaddressindex:
LazyVecFrom1<P2WSHAddressIndex, P2WSHAddressIndex, P2WSHAddressIndex, P2WSHBytes>,
pub unknownoutputindex_to_unknownoutputindex:
LazyVecFrom1<UnknownOutputIndex, UnknownOutputIndex, UnknownOutputIndex, TxIndex>,
}

View File

@@ -0,0 +1,149 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{Date, DateIndex, DifficultyEpoch, HalvingEpoch};
use vecdb::{Exit, TypedVecIterator};
use super::Vecs;
impl Vecs {
pub fn compute(
&mut self,
indexer: &Indexer,
starting_indexes: &brk_indexer::Indexes,
exit: &Exit,
) -> Result<(DateIndex, DifficultyEpoch, HalvingEpoch)> {
self.height_to_txindex_count.compute_count_from_indexes(
starting_indexes.height,
&indexer.vecs.tx.height_to_first_txindex,
&indexer.vecs.tx.txindex_to_txid,
exit,
)?;
self.height_to_height.compute_from_index(
starting_indexes.height,
&indexer.vecs.block.height_to_weight,
exit,
)?;
self.height_to_date.compute_transform(
starting_indexes.height,
&indexer.vecs.block.height_to_timestamp,
|(h, t, ..)| (h, Date::from(t)),
exit,
)?;
let mut prev_timestamp_fixed = None;
self.height_to_timestamp_fixed.compute_transform(
starting_indexes.height,
&indexer.vecs.block.height_to_timestamp,
|(h, timestamp, height_to_timestamp_fixed_iter)| {
if prev_timestamp_fixed.is_none()
&& let Some(prev_h) = h.decremented()
{
prev_timestamp_fixed.replace(
height_to_timestamp_fixed_iter
.into_iter()
.get_unwrap(prev_h),
);
}
let timestamp_fixed =
prev_timestamp_fixed.map_or(timestamp, |prev_d| prev_d.max(timestamp));
prev_timestamp_fixed.replace(timestamp_fixed);
(h, timestamp_fixed)
},
exit,
)?;
self.height_to_date_fixed.compute_transform(
starting_indexes.height,
&self.height_to_timestamp_fixed,
|(h, t, ..)| (h, Date::from(t)),
exit,
)?;
let decremented_starting_height = starting_indexes.height.decremented().unwrap_or_default();
// DateIndex (computed before time module needs it)
let starting_dateindex = self
.height_to_dateindex
.into_iter()
.get(decremented_starting_height)
.unwrap_or_default();
self.height_to_dateindex.compute_transform(
starting_indexes.height,
&self.height_to_date_fixed,
|(h, d, ..)| (h, DateIndex::try_from(d).unwrap()),
exit,
)?;
let starting_dateindex = if let Some(dateindex) = self
.height_to_dateindex
.into_iter()
.get(decremented_starting_height)
{
starting_dateindex.min(dateindex)
} else {
starting_dateindex
};
// Difficulty epoch
let starting_difficultyepoch = self
.height_to_difficultyepoch
.into_iter()
.get(decremented_starting_height)
.unwrap_or_default();
self.height_to_difficultyepoch.compute_from_index(
starting_indexes.height,
&indexer.vecs.block.height_to_weight,
exit,
)?;
self.difficultyepoch_to_first_height.compute_coarser(
starting_indexes.height,
&self.height_to_difficultyepoch,
exit,
)?;
self.difficultyepoch_to_difficultyepoch.compute_from_index(
starting_difficultyepoch,
&self.difficultyepoch_to_first_height,
exit,
)?;
self.difficultyepoch_to_height_count.compute_count_from_indexes(
starting_difficultyepoch,
&self.difficultyepoch_to_first_height,
&self.height_to_date,
exit,
)?;
// Halving epoch
let starting_halvingepoch = self
.height_to_halvingepoch
.into_iter()
.get(decremented_starting_height)
.unwrap_or_default();
self.height_to_halvingepoch.compute_from_index(
starting_indexes.height,
&indexer.vecs.block.height_to_weight,
exit,
)?;
self.halvingepoch_to_first_height.compute_coarser(
starting_indexes.height,
&self.height_to_halvingepoch,
exit,
)?;
self.halvingepoch_to_halvingepoch.compute_from_index(
starting_halvingepoch,
&self.halvingepoch_to_first_height,
exit,
)?;
Ok((starting_dateindex, starting_difficultyepoch, starting_halvingepoch))
}
}

View File

@@ -0,0 +1,25 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::{Database, EagerVec, ImportableVec};
use super::Vecs;
impl Vecs {
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
Ok(Self {
height_to_date: EagerVec::forced_import(db, "date", version)?,
height_to_date_fixed: EagerVec::forced_import(db, "date_fixed", version)?,
height_to_dateindex: EagerVec::forced_import(db, "dateindex", version)?,
height_to_difficultyepoch: EagerVec::forced_import(db, "difficultyepoch", version)?,
height_to_halvingepoch: EagerVec::forced_import(db, "halvingepoch", version)?,
height_to_height: EagerVec::forced_import(db, "height", version)?,
height_to_timestamp_fixed: EagerVec::forced_import(db, "timestamp_fixed", version)?,
height_to_txindex_count: EagerVec::forced_import(db, "txindex_count", version)?,
difficultyepoch_to_difficultyepoch: EagerVec::forced_import(db, "difficultyepoch", version)?,
difficultyepoch_to_first_height: EagerVec::forced_import(db, "first_height", version)?,
difficultyepoch_to_height_count: EagerVec::forced_import(db, "height_count", version)?,
halvingepoch_to_first_height: EagerVec::forced_import(db, "first_height", version)?,
halvingepoch_to_halvingepoch: EagerVec::forced_import(db, "halvingepoch", version)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,20 @@
use brk_traversable::Traversable;
use brk_types::{Date, DateIndex, DifficultyEpoch, HalvingEpoch, Height, StoredU64, Timestamp};
use vecdb::{EagerVec, PcoVec};
#[derive(Clone, Traversable)]
pub struct Vecs {
pub height_to_date: EagerVec<PcoVec<Height, Date>>,
pub height_to_date_fixed: EagerVec<PcoVec<Height, Date>>,
pub height_to_dateindex: EagerVec<PcoVec<Height, DateIndex>>,
pub height_to_difficultyepoch: EagerVec<PcoVec<Height, DifficultyEpoch>>,
pub height_to_halvingepoch: EagerVec<PcoVec<Height, HalvingEpoch>>,
pub height_to_height: EagerVec<PcoVec<Height, Height>>,
pub height_to_timestamp_fixed: EagerVec<PcoVec<Height, Timestamp>>,
pub height_to_txindex_count: EagerVec<PcoVec<Height, StoredU64>>,
pub difficultyepoch_to_difficultyepoch: EagerVec<PcoVec<DifficultyEpoch, DifficultyEpoch>>,
pub difficultyepoch_to_first_height: EagerVec<PcoVec<DifficultyEpoch, Height>>,
pub difficultyepoch_to_height_count: EagerVec<PcoVec<DifficultyEpoch, StoredU64>>,
pub halvingepoch_to_first_height: EagerVec<PcoVec<HalvingEpoch, Height>>,
pub halvingepoch_to_halvingepoch: EagerVec<PcoVec<HalvingEpoch, HalvingEpoch>>,
}

View File

@@ -0,0 +1,149 @@
mod address;
mod block;
mod time;
mod transaction;
use std::{ops::Deref, path::Path};
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, DifficultyEpoch, HalvingEpoch, Height, MonthIndex, QuarterIndex,
SemesterIndex, Version, WeekIndex, YearIndex,
};
use vecdb::{Database, Exit, PAGE_SIZE, TypedVecIterator};
pub use address::Vecs as AddressVecs;
pub use block::Vecs as BlockVecs;
pub use time::Vecs as TimeVecs;
pub use transaction::Vecs as TransactionVecs;
const VERSION: Version = Version::ZERO;
pub const DB_NAME: &str = "indexes";
#[derive(Clone, Traversable)]
pub struct Vecs {
db: Database,
pub address: AddressVecs,
pub block: BlockVecs,
pub time: TimeVecs,
pub transaction: TransactionVecs,
}
impl Vecs {
pub fn forced_import(
parent: &Path,
parent_version: Version,
indexer: &Indexer,
) -> Result<Self> {
let db = Database::open(&parent.join(DB_NAME))?;
db.set_min_len(PAGE_SIZE * 10_000_000)?;
let version = parent_version + VERSION;
let this = Self {
address: AddressVecs::forced_import(version, indexer),
block: BlockVecs::forced_import(&db, version)?,
time: TimeVecs::forced_import(&db, version)?,
transaction: TransactionVecs::forced_import(&db, version, indexer)?,
db,
};
this.db.retain_regions(
this.iter_any_exportable()
.flat_map(|v| v.region_names())
.collect(),
)?;
this.db.compact()?;
Ok(this)
}
pub fn compute(
&mut self,
indexer: &Indexer,
starting_indexes: brk_indexer::Indexes,
exit: &Exit,
) -> Result<Indexes> {
let indexes = self.compute_(indexer, starting_indexes, exit)?;
let _lock = exit.lock();
self.db.compact()?;
Ok(indexes)
}
fn compute_(
&mut self,
indexer: &Indexer,
starting_indexes: brk_indexer::Indexes,
exit: &Exit,
) -> Result<Indexes> {
// Transaction indexes
self.transaction.compute(indexer, &starting_indexes, exit)?;
// Block indexes (height, dateindex, difficultyepoch, halvingepoch)
let (starting_dateindex, starting_difficultyepoch, starting_halvingepoch) =
self.block.compute(indexer, &starting_indexes, exit)?;
// Time indexes (depends on block.height_to_dateindex)
let time_indexes = self
.time
.compute(indexer, &starting_indexes, starting_dateindex, &self.block, exit)?;
Ok(Indexes {
indexes: starting_indexes,
dateindex: time_indexes.dateindex,
weekindex: time_indexes.weekindex,
monthindex: time_indexes.monthindex,
quarterindex: time_indexes.quarterindex,
semesterindex: time_indexes.semesterindex,
yearindex: time_indexes.yearindex,
decadeindex: time_indexes.decadeindex,
difficultyepoch: starting_difficultyepoch,
halvingepoch: starting_halvingepoch,
})
}
}
#[derive(Debug, Clone)]
pub struct Indexes {
indexes: brk_indexer::Indexes,
pub dateindex: DateIndex,
pub weekindex: WeekIndex,
pub monthindex: MonthIndex,
pub quarterindex: QuarterIndex,
pub semesterindex: SemesterIndex,
pub yearindex: YearIndex,
pub decadeindex: DecadeIndex,
pub difficultyepoch: DifficultyEpoch,
pub halvingepoch: HalvingEpoch,
}
impl Indexes {
pub fn update_from_height(&mut self, height: Height, indexes: &Vecs) {
self.indexes.height = height;
self.dateindex = DateIndex::try_from(
indexes
.block
.height_to_date_fixed
.into_iter()
.get_unwrap(height),
)
.unwrap();
self.weekindex = WeekIndex::from(self.dateindex);
self.monthindex = MonthIndex::from(self.dateindex);
self.quarterindex = QuarterIndex::from(self.monthindex);
self.semesterindex = SemesterIndex::from(self.monthindex);
self.yearindex = YearIndex::from(self.monthindex);
self.decadeindex = DecadeIndex::from(self.dateindex);
self.difficultyepoch = DifficultyEpoch::from(self.height);
self.halvingepoch = HalvingEpoch::from(self.height);
}
}
impl Deref for Indexes {
type Target = brk_indexer::Indexes;
fn deref(&self) -> &Self::Target {
&self.indexes
}
}

View File

@@ -0,0 +1,246 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{DateIndex, MonthIndex, WeekIndex};
use vecdb::{Exit, TypedVecIterator};
use super::{super::block, vecs::StartingTimeIndexes, Vecs};
impl Vecs {
pub fn compute(
&mut self,
indexer: &Indexer,
starting_indexes: &brk_indexer::Indexes,
starting_dateindex: DateIndex,
block_vecs: &block::Vecs,
exit: &Exit,
) -> Result<StartingTimeIndexes> {
self.dateindex_to_first_height.compute_coarser(
starting_indexes.height,
&block_vecs.height_to_dateindex,
exit,
)?;
self.dateindex_to_dateindex.compute_from_index(
starting_dateindex,
&self.dateindex_to_first_height,
exit,
)?;
self.dateindex_to_date.compute_from_index(
starting_dateindex,
&self.dateindex_to_first_height,
exit,
)?;
self.dateindex_to_height_count.compute_count_from_indexes(
starting_dateindex,
&self.dateindex_to_first_height,
&indexer.vecs.block.height_to_weight,
exit,
)?;
// Week
let starting_weekindex = self
.dateindex_to_weekindex
.into_iter()
.get(starting_dateindex)
.unwrap_or_default();
self.dateindex_to_weekindex.compute_range(
starting_dateindex,
&self.dateindex_to_dateindex,
|i| (i, WeekIndex::from(i)),
exit,
)?;
self.weekindex_to_first_dateindex.compute_coarser(
starting_dateindex,
&self.dateindex_to_weekindex,
exit,
)?;
self.weekindex_to_weekindex.compute_from_index(
starting_weekindex,
&self.weekindex_to_first_dateindex,
exit,
)?;
self.weekindex_to_dateindex_count.compute_count_from_indexes(
starting_weekindex,
&self.weekindex_to_first_dateindex,
&self.dateindex_to_date,
exit,
)?;
// Month
let starting_monthindex = self
.dateindex_to_monthindex
.into_iter()
.get(starting_dateindex)
.unwrap_or_default();
self.dateindex_to_monthindex.compute_range(
starting_dateindex,
&self.dateindex_to_dateindex,
|i| (i, MonthIndex::from(i)),
exit,
)?;
self.monthindex_to_first_dateindex.compute_coarser(
starting_dateindex,
&self.dateindex_to_monthindex,
exit,
)?;
self.monthindex_to_monthindex.compute_from_index(
starting_monthindex,
&self.monthindex_to_first_dateindex,
exit,
)?;
self.monthindex_to_dateindex_count.compute_count_from_indexes(
starting_monthindex,
&self.monthindex_to_first_dateindex,
&self.dateindex_to_date,
exit,
)?;
// Quarter
let starting_quarterindex = self
.monthindex_to_quarterindex
.into_iter()
.get(starting_monthindex)
.unwrap_or_default();
self.monthindex_to_quarterindex.compute_from_index(
starting_monthindex,
&self.monthindex_to_first_dateindex,
exit,
)?;
self.quarterindex_to_first_monthindex.compute_coarser(
starting_monthindex,
&self.monthindex_to_quarterindex,
exit,
)?;
self.quarterindex_to_quarterindex.compute_from_index(
starting_quarterindex,
&self.quarterindex_to_first_monthindex,
exit,
)?;
self.quarterindex_to_monthindex_count.compute_count_from_indexes(
starting_quarterindex,
&self.quarterindex_to_first_monthindex,
&self.monthindex_to_monthindex,
exit,
)?;
// Semester
let starting_semesterindex = self
.monthindex_to_semesterindex
.into_iter()
.get(starting_monthindex)
.unwrap_or_default();
self.monthindex_to_semesterindex.compute_from_index(
starting_monthindex,
&self.monthindex_to_first_dateindex,
exit,
)?;
self.semesterindex_to_first_monthindex.compute_coarser(
starting_monthindex,
&self.monthindex_to_semesterindex,
exit,
)?;
self.semesterindex_to_semesterindex.compute_from_index(
starting_semesterindex,
&self.semesterindex_to_first_monthindex,
exit,
)?;
self.semesterindex_to_monthindex_count.compute_count_from_indexes(
starting_semesterindex,
&self.semesterindex_to_first_monthindex,
&self.monthindex_to_monthindex,
exit,
)?;
// Year
let starting_yearindex = self
.monthindex_to_yearindex
.into_iter()
.get(starting_monthindex)
.unwrap_or_default();
self.monthindex_to_yearindex.compute_from_index(
starting_monthindex,
&self.monthindex_to_first_dateindex,
exit,
)?;
self.yearindex_to_first_monthindex.compute_coarser(
starting_monthindex,
&self.monthindex_to_yearindex,
exit,
)?;
self.yearindex_to_yearindex.compute_from_index(
starting_yearindex,
&self.yearindex_to_first_monthindex,
exit,
)?;
self.yearindex_to_monthindex_count.compute_count_from_indexes(
starting_yearindex,
&self.yearindex_to_first_monthindex,
&self.monthindex_to_monthindex,
exit,
)?;
// Decade
let starting_decadeindex = self
.yearindex_to_decadeindex
.into_iter()
.get(starting_yearindex)
.unwrap_or_default();
self.yearindex_to_decadeindex.compute_from_index(
starting_yearindex,
&self.yearindex_to_first_monthindex,
exit,
)?;
self.decadeindex_to_first_yearindex.compute_coarser(
starting_yearindex,
&self.yearindex_to_decadeindex,
exit,
)?;
self.decadeindex_to_decadeindex.compute_from_index(
starting_decadeindex,
&self.decadeindex_to_first_yearindex,
exit,
)?;
self.decadeindex_to_yearindex_count.compute_count_from_indexes(
starting_decadeindex,
&self.decadeindex_to_first_yearindex,
&self.yearindex_to_yearindex,
exit,
)?;
Ok(StartingTimeIndexes {
dateindex: starting_dateindex,
weekindex: starting_weekindex,
monthindex: starting_monthindex,
quarterindex: starting_quarterindex,
semesterindex: starting_semesterindex,
yearindex: starting_yearindex,
decadeindex: starting_decadeindex,
})
}
}

View File

@@ -0,0 +1,40 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::{Database, EagerVec, ImportableVec};
use super::Vecs;
impl Vecs {
pub fn forced_import(db: &Database, version: Version) -> Result<Self> {
Ok(Self {
dateindex_to_date: EagerVec::forced_import(db, "date", version)?,
dateindex_to_dateindex: EagerVec::forced_import(db, "dateindex", version)?,
dateindex_to_first_height: EagerVec::forced_import(db, "first_height", version)?,
dateindex_to_height_count: EagerVec::forced_import(db, "height_count", version)?,
dateindex_to_monthindex: EagerVec::forced_import(db, "monthindex", version)?,
dateindex_to_weekindex: EagerVec::forced_import(db, "weekindex", version)?,
weekindex_to_dateindex_count: EagerVec::forced_import(db, "dateindex_count", version)?,
weekindex_to_first_dateindex: EagerVec::forced_import(db, "first_dateindex", version)?,
weekindex_to_weekindex: EagerVec::forced_import(db, "weekindex", version)?,
monthindex_to_dateindex_count: EagerVec::forced_import(db, "dateindex_count", version)?,
monthindex_to_first_dateindex: EagerVec::forced_import(db, "first_dateindex", version)?,
monthindex_to_monthindex: EagerVec::forced_import(db, "monthindex", version)?,
monthindex_to_quarterindex: EagerVec::forced_import(db, "quarterindex", version)?,
monthindex_to_semesterindex: EagerVec::forced_import(db, "semesterindex", version)?,
monthindex_to_yearindex: EagerVec::forced_import(db, "yearindex", version)?,
quarterindex_to_first_monthindex: EagerVec::forced_import(db, "first_monthindex", version)?,
quarterindex_to_monthindex_count: EagerVec::forced_import(db, "monthindex_count", version)?,
quarterindex_to_quarterindex: EagerVec::forced_import(db, "quarterindex", version)?,
semesterindex_to_first_monthindex: EagerVec::forced_import(db, "first_monthindex", version)?,
semesterindex_to_monthindex_count: EagerVec::forced_import(db, "monthindex_count", version)?,
semesterindex_to_semesterindex: EagerVec::forced_import(db, "semesterindex", version)?,
yearindex_to_decadeindex: EagerVec::forced_import(db, "decadeindex", version)?,
yearindex_to_first_monthindex: EagerVec::forced_import(db, "first_monthindex", version)?,
yearindex_to_monthindex_count: EagerVec::forced_import(db, "monthindex_count", version)?,
yearindex_to_yearindex: EagerVec::forced_import(db, "yearindex", version)?,
decadeindex_to_decadeindex: EagerVec::forced_import(db, "decadeindex", version)?,
decadeindex_to_first_yearindex: EagerVec::forced_import(db, "first_yearindex", version)?,
decadeindex_to_yearindex_count: EagerVec::forced_import(db, "yearindex_count", version)?,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,48 @@
use brk_traversable::Traversable;
use brk_types::{
Date, DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, StoredU64,
WeekIndex, YearIndex,
};
use vecdb::{EagerVec, PcoVec};
#[derive(Clone, Traversable)]
pub struct Vecs {
pub dateindex_to_date: EagerVec<PcoVec<DateIndex, Date>>,
pub dateindex_to_dateindex: EagerVec<PcoVec<DateIndex, DateIndex>>,
pub dateindex_to_first_height: EagerVec<PcoVec<DateIndex, Height>>,
pub dateindex_to_height_count: EagerVec<PcoVec<DateIndex, StoredU64>>,
pub dateindex_to_monthindex: EagerVec<PcoVec<DateIndex, MonthIndex>>,
pub dateindex_to_weekindex: EagerVec<PcoVec<DateIndex, WeekIndex>>,
pub weekindex_to_dateindex_count: EagerVec<PcoVec<WeekIndex, StoredU64>>,
pub weekindex_to_first_dateindex: EagerVec<PcoVec<WeekIndex, DateIndex>>,
pub weekindex_to_weekindex: EagerVec<PcoVec<WeekIndex, WeekIndex>>,
pub monthindex_to_dateindex_count: EagerVec<PcoVec<MonthIndex, StoredU64>>,
pub monthindex_to_first_dateindex: EagerVec<PcoVec<MonthIndex, DateIndex>>,
pub monthindex_to_monthindex: EagerVec<PcoVec<MonthIndex, MonthIndex>>,
pub monthindex_to_quarterindex: EagerVec<PcoVec<MonthIndex, QuarterIndex>>,
pub monthindex_to_semesterindex: EagerVec<PcoVec<MonthIndex, SemesterIndex>>,
pub monthindex_to_yearindex: EagerVec<PcoVec<MonthIndex, YearIndex>>,
pub quarterindex_to_first_monthindex: EagerVec<PcoVec<QuarterIndex, MonthIndex>>,
pub quarterindex_to_monthindex_count: EagerVec<PcoVec<QuarterIndex, StoredU64>>,
pub quarterindex_to_quarterindex: EagerVec<PcoVec<QuarterIndex, QuarterIndex>>,
pub semesterindex_to_first_monthindex: EagerVec<PcoVec<SemesterIndex, MonthIndex>>,
pub semesterindex_to_monthindex_count: EagerVec<PcoVec<SemesterIndex, StoredU64>>,
pub semesterindex_to_semesterindex: EagerVec<PcoVec<SemesterIndex, SemesterIndex>>,
pub yearindex_to_decadeindex: EagerVec<PcoVec<YearIndex, DecadeIndex>>,
pub yearindex_to_first_monthindex: EagerVec<PcoVec<YearIndex, MonthIndex>>,
pub yearindex_to_monthindex_count: EagerVec<PcoVec<YearIndex, StoredU64>>,
pub yearindex_to_yearindex: EagerVec<PcoVec<YearIndex, YearIndex>>,
pub decadeindex_to_decadeindex: EagerVec<PcoVec<DecadeIndex, DecadeIndex>>,
pub decadeindex_to_first_yearindex: EagerVec<PcoVec<DecadeIndex, YearIndex>>,
pub decadeindex_to_yearindex_count: EagerVec<PcoVec<DecadeIndex, StoredU64>>,
}
pub struct StartingTimeIndexes {
pub dateindex: DateIndex,
pub weekindex: WeekIndex,
pub monthindex: MonthIndex,
pub quarterindex: QuarterIndex,
pub semesterindex: SemesterIndex,
pub yearindex: YearIndex,
pub decadeindex: DecadeIndex,
}

View File

@@ -0,0 +1,25 @@
use brk_error::Result;
use brk_indexer::Indexer;
use vecdb::Exit;
use super::Vecs;
impl Vecs {
pub fn compute(&mut self, indexer: &Indexer, starting_indexes: &brk_indexer::Indexes, exit: &Exit) -> Result<()> {
self.txindex_to_input_count.compute_count_from_indexes(
starting_indexes.txindex,
&indexer.vecs.tx.txindex_to_first_txinindex,
&indexer.vecs.txin.txinindex_to_outpoint,
exit,
)?;
self.txindex_to_output_count.compute_count_from_indexes(
starting_indexes.txindex,
&indexer.vecs.tx.txindex_to_first_txoutindex,
&indexer.vecs.txout.txoutindex_to_value,
exit,
)?;
Ok(())
}
}

View File

@@ -0,0 +1,33 @@
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::Version;
use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec, LazyVecFrom1};
use super::Vecs;
impl Vecs {
pub fn forced_import(db: &Database, version: Version, indexer: &Indexer) -> Result<Self> {
Ok(Self {
txindex_to_input_count: EagerVec::forced_import(db, "input_count", version)?,
txindex_to_output_count: EagerVec::forced_import(db, "output_count", version)?,
txindex_to_txindex: LazyVecFrom1::init(
"txindex",
version,
indexer.vecs.tx.txindex_to_txid.boxed_clone(),
|index, _| Some(index),
),
txinindex_to_txinindex: LazyVecFrom1::init(
"txinindex",
version,
indexer.vecs.txin.txinindex_to_outpoint.boxed_clone(),
|index, _| Some(index),
),
txoutindex_to_txoutindex: LazyVecFrom1::init(
"txoutindex",
version,
indexer.vecs.txout.txoutindex_to_value.boxed_clone(),
|index, _| Some(index),
),
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,12 @@
use brk_traversable::Traversable;
use brk_types::{OutPoint, Sats, StoredU64, TxInIndex, TxIndex, TxOutIndex, Txid};
use vecdb::{EagerVec, LazyVecFrom1, PcoVec};
#[derive(Clone, Traversable)]
pub struct Vecs {
pub txindex_to_input_count: EagerVec<PcoVec<TxIndex, StoredU64>>,
pub txindex_to_output_count: EagerVec<PcoVec<TxIndex, StoredU64>>,
pub txindex_to_txindex: LazyVecFrom1<TxIndex, TxIndex, TxIndex, Txid>,
pub txinindex_to_txinindex: LazyVecFrom1<TxInIndex, TxInIndex, TxInIndex, OutPoint>,
pub txoutindex_to_txoutindex: LazyVecFrom1<TxOutIndex, TxOutIndex, TxOutIndex, Sats>,
}

View File

@@ -0,0 +1,93 @@
use brk_error::Result;
use brk_types::StoredU16;
use vecdb::{Exit, GenericStoredVec, TypedVecIterator, VecIndex};
use super::Vecs;
use crate::{Indexes, price, traits::ComputeDrawdown, utils::OptionExt};
impl Vecs {
pub fn compute(
&mut self,
price: &price::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.height_to_price_ath.compute_all_time_high(
starting_indexes.height,
&price.chainindexes_to_price_high.height,
exit,
)?;
self.height_to_price_drawdown.compute_drawdown(
starting_indexes.height,
&price.chainindexes_to_price_close.height,
&self.height_to_price_ath,
exit,
)?;
self.indexes_to_price_ath
.compute_all(starting_indexes, exit, |v| {
v.compute_all_time_high(
starting_indexes.dateindex,
price.timeindexes_to_price_high.dateindex.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_days_since_price_ath
.compute_all(starting_indexes, exit, |v| {
let mut high_iter = price.timeindexes_to_price_high.dateindex.u().into_iter();
let mut prev = None;
v.compute_transform(
starting_indexes.dateindex,
self.indexes_to_price_ath.dateindex.u(),
|(i, ath, slf)| {
if prev.is_none() {
let i = i.to_usize();
prev.replace(if i > 0 {
slf.get_pushed_or_read_at_unwrap_once(i - 1)
} else {
StoredU16::default()
});
}
let days = if *high_iter.get_unwrap(i) == ath {
StoredU16::default()
} else {
prev.unwrap() + StoredU16::new(1)
};
prev.replace(days);
(i, days)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_max_days_between_price_aths
.compute_all(starting_indexes, exit, |v| {
let mut prev = None;
v.compute_transform(
starting_indexes.dateindex,
self.indexes_to_days_since_price_ath.dateindex.u(),
|(i, days, slf)| {
if prev.is_none() {
let i = i.to_usize();
prev.replace(if i > 0 {
slf.get_pushed_or_read_at_unwrap_once(i - 1)
} else {
StoredU16::ZERO
});
}
let max = prev.unwrap().max(days);
prev.replace(max);
(i, max)
},
exit,
)?;
Ok(())
})?;
Ok(())
}
}

View File

@@ -0,0 +1,78 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::{Database, EagerVec, ImportableVec, IterableCloneableVec};
use super::Vecs;
use crate::{
grouped::{
ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, LazyVecsFromDateIndex,
PercentageDiffCloseDollars, Source, StoredU16ToYears, VecBuilderOptions,
},
indexes, price,
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
price: &price::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let last = VecBuilderOptions::default().add_last();
let indexes_to_price_ath = ComputedVecsFromDateIndex::forced_import(
db,
"price_ath",
Source::Compute,
version + v0,
indexes,
last,
)?;
let indexes_to_max_days_between_price_aths = ComputedVecsFromDateIndex::forced_import(
db,
"max_days_between_price_aths",
Source::Compute,
version + v0,
indexes,
last,
)?;
let indexes_to_max_years_between_price_aths =
LazyVecsFromDateIndex::from_computed::<StoredU16ToYears>(
"max_years_between_price_aths",
version + v0,
indexes_to_max_days_between_price_aths
.dateindex
.as_ref()
.map(|v| v.boxed_clone()),
&indexes_to_max_days_between_price_aths,
);
let indexes_to_price_drawdown =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"price_drawdown",
version + v0,
&price.timeindexes_to_price_close,
&indexes_to_price_ath,
);
Ok(Self {
height_to_price_ath: EagerVec::forced_import(db, "price_ath", version + v0)?,
height_to_price_drawdown: EagerVec::forced_import(db, "price_drawdown", version + v0)?,
indexes_to_price_ath,
indexes_to_price_drawdown,
indexes_to_days_since_price_ath: ComputedVecsFromDateIndex::forced_import(
db,
"days_since_price_ath",
Source::Compute,
version + v0,
indexes,
last,
)?,
indexes_to_max_days_between_price_aths,
indexes_to_max_years_between_price_aths,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,19 @@
use brk_traversable::Traversable;
use brk_types::{Close, Dollars, Height, StoredF32, StoredU16};
use vecdb::{EagerVec, PcoVec};
use crate::grouped::{
ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, LazyVecsFromDateIndex,
};
/// All-time high related metrics
#[derive(Clone, Traversable)]
pub struct Vecs {
pub height_to_price_ath: EagerVec<PcoVec<Height, Dollars>>,
pub height_to_price_drawdown: EagerVec<PcoVec<Height, StoredF32>>,
pub indexes_to_price_ath: ComputedVecsFromDateIndex<Dollars>,
pub indexes_to_price_drawdown: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub indexes_to_days_since_price_ath: ComputedVecsFromDateIndex<StoredU16>,
pub indexes_to_max_days_between_price_aths: ComputedVecsFromDateIndex<StoredU16>,
pub indexes_to_max_years_between_price_aths: LazyVecsFromDateIndex<StoredF32, StoredU16>,
}

View File

@@ -1,14 +1,8 @@
use std::thread;
use brk_error::Result;
use brk_types::{Date, DateIndex, StoredF32, StoredU16};
use vecdb::{Exit, GenericStoredVec, TypedVecIterator, VecIndex};
use vecdb::Exit;
use crate::{
Indexes, price,
traits::{ComputeDCAAveragePriceViaLen, ComputeDCAStackViaLen, ComputeDrawdown},
utils::OptionExt,
};
use crate::{price, Indexes};
use crate::utils::OptionExt;
use super::Vecs;
@@ -19,636 +13,30 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.compute_(price, starting_indexes, exit)?;
// ATH metrics (independent)
self.ath.compute(price, starting_indexes, exit)?;
// History metrics (independent)
self.history.compute(price, starting_indexes, exit)?;
// Volatility metrics (depends on history._1d_price_returns)
self.volatility.compute(
starting_indexes,
exit,
self.history._1d_price_returns.dateindex.u(),
)?;
// Range metrics (independent)
self.range.compute(price, starting_indexes, exit)?;
// Moving average metrics (independent)
self.moving_average.compute(price, starting_indexes, exit)?;
// DCA metrics
self.dca.compute(price, starting_indexes, exit)?;
let _lock = exit.lock();
self.db.compact()?;
Ok(())
}
fn compute_(
&mut self,
price: &price::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.height_to_price_ath.compute_all_time_high(
starting_indexes.height,
&price.chainindexes_to_price_high.height,
exit,
)?;
self.height_to_price_drawdown.compute_drawdown(
starting_indexes.height,
&price.chainindexes_to_price_close.height,
&self.height_to_price_ath,
exit,
)?;
self.indexes_to_price_ath
.compute_all(starting_indexes, exit, |v| {
v.compute_all_time_high(
starting_indexes.dateindex,
price.timeindexes_to_price_high.dateindex.u(),
exit,
)?;
Ok(())
})?;
self.indexes_to_days_since_price_ath
.compute_all(starting_indexes, exit, |v| {
let mut high_iter = price.timeindexes_to_price_high.dateindex.u().into_iter();
let mut prev = None;
v.compute_transform(
starting_indexes.dateindex,
self.indexes_to_price_ath.dateindex.u(),
|(i, ath, slf)| {
if prev.is_none() {
let i = i.to_usize();
prev.replace(if i > 0 {
slf.get_pushed_or_read_at_unwrap_once(i - 1)
} else {
StoredU16::default()
});
}
let days = if *high_iter.get_unwrap(i) == ath {
StoredU16::default()
} else {
prev.unwrap() + StoredU16::new(1)
};
prev.replace(days);
(i, days)
},
exit,
)?;
Ok(())
})?;
self.indexes_to_max_days_between_price_aths
.compute_all(starting_indexes, exit, |v| {
let mut prev = None;
v.compute_transform(
starting_indexes.dateindex,
self.indexes_to_days_since_price_ath.dateindex.u(),
|(i, days, slf)| {
if prev.is_none() {
let i = i.to_usize();
prev.replace(if i > 0 {
slf.get_pushed_or_read_at_unwrap_once(i - 1)
} else {
StoredU16::ZERO
});
}
let max = prev.unwrap().max(days);
prev.replace(max);
(i, max)
},
exit,
)?;
Ok(())
})?;
[
(1, &mut self.price_1d_ago, &self._1d_price_returns, None),
(7, &mut self.price_1w_ago, &self._1w_price_returns, None),
(30, &mut self.price_1m_ago, &self._1m_price_returns, None),
(
3 * 30,
&mut self.price_3m_ago,
&self._3m_price_returns,
None,
),
(
6 * 30,
&mut self.price_6m_ago,
&self._6m_price_returns,
None,
),
(365, &mut self.price_1y_ago, &self._1y_price_returns, None),
(
2 * 365,
&mut self.price_2y_ago,
&self._2y_price_returns,
Some(&mut self._2y_cagr),
),
(
3 * 365,
&mut self.price_3y_ago,
&self._3y_price_returns,
Some(&mut self._3y_cagr),
),
(
4 * 365,
&mut self.price_4y_ago,
&self._4y_price_returns,
Some(&mut self._4y_cagr),
),
(
5 * 365,
&mut self.price_5y_ago,
&self._5y_price_returns,
Some(&mut self._5y_cagr),
),
(
6 * 365,
&mut self.price_6y_ago,
&self._6y_price_returns,
Some(&mut self._6y_cagr),
),
(
8 * 365,
&mut self.price_8y_ago,
&self._8y_price_returns,
Some(&mut self._8y_cagr),
),
(
10 * 365,
&mut self.price_10y_ago,
&self._10y_price_returns,
Some(&mut self._10y_cagr),
),
]
.into_iter()
.try_for_each(|(days, ago, returns, cagr)| -> Result<()> {
ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(
starting_indexes.dateindex,
price.timeindexes_to_price_close.dateindex.u(),
days,
exit,
)?;
Ok(())
})?;
if let Some(cagr) = cagr {
cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
returns.dateindex.u(),
days,
exit,
)?;
Ok(())
})?;
}
Ok(())
})?;
[
(
7,
&mut self._1w_dca_stack,
&mut self._1w_dca_avg_price,
&self._1w_dca_returns,
None,
),
(
30,
&mut self._1m_dca_stack,
&mut self._1m_dca_avg_price,
&self._1m_dca_returns,
None,
),
(
3 * 30,
&mut self._3m_dca_stack,
&mut self._3m_dca_avg_price,
&self._3m_dca_returns,
None,
),
(
6 * 30,
&mut self._6m_dca_stack,
&mut self._6m_dca_avg_price,
&self._6m_dca_returns,
None,
),
(
365,
&mut self._1y_dca_stack,
&mut self._1y_dca_avg_price,
&self._1y_dca_returns,
None,
),
(
2 * 365,
&mut self._2y_dca_stack,
&mut self._2y_dca_avg_price,
&self._2y_dca_returns,
Some(&mut self._2y_dca_cagr),
),
(
3 * 365,
&mut self._3y_dca_stack,
&mut self._3y_dca_avg_price,
&self._3y_dca_returns,
Some(&mut self._3y_dca_cagr),
),
(
4 * 365,
&mut self._4y_dca_stack,
&mut self._4y_dca_avg_price,
&self._4y_dca_returns,
Some(&mut self._4y_dca_cagr),
),
(
5 * 365,
&mut self._5y_dca_stack,
&mut self._5y_dca_avg_price,
&self._5y_dca_returns,
Some(&mut self._5y_dca_cagr),
),
(
6 * 365,
&mut self._6y_dca_stack,
&mut self._6y_dca_avg_price,
&self._6y_dca_returns,
Some(&mut self._6y_dca_cagr),
),
(
8 * 365,
&mut self._8y_dca_stack,
&mut self._8y_dca_avg_price,
&self._8y_dca_returns,
Some(&mut self._8y_dca_cagr),
),
(
10 * 365,
&mut self._10y_dca_stack,
&mut self._10y_dca_avg_price,
&self._10y_dca_returns,
Some(&mut self._10y_dca_cagr),
),
]
.into_iter()
.try_for_each(
|(days, dca_stack, dca_avg_price, dca_returns, dca_cagr)| -> Result<()> {
dca_stack.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(
starting_indexes.dateindex,
price.timeindexes_to_price_close.dateindex.u(),
days,
exit,
)?;
Ok(())
})?;
dca_avg_price.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
dca_stack.dateindex.u(),
days,
exit,
)?;
Ok(())
})?;
if let Some(dca_cagr) = dca_cagr {
dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
dca_returns.dateindex.u(),
days,
exit,
)?;
Ok(())
})?;
}
Ok(())
},
)?;
[
(
2015,
&mut self.dca_class_2015_avg_price,
&mut self.dca_class_2015_stack,
),
(
2016,
&mut self.dca_class_2016_avg_price,
&mut self.dca_class_2016_stack,
),
(
2017,
&mut self.dca_class_2017_avg_price,
&mut self.dca_class_2017_stack,
),
(
2018,
&mut self.dca_class_2018_avg_price,
&mut self.dca_class_2018_stack,
),
(
2019,
&mut self.dca_class_2019_avg_price,
&mut self.dca_class_2019_stack,
),
(
2020,
&mut self.dca_class_2020_avg_price,
&mut self.dca_class_2020_stack,
),
(
2021,
&mut self.dca_class_2021_avg_price,
&mut self.dca_class_2021_stack,
),
(
2022,
&mut self.dca_class_2022_avg_price,
&mut self.dca_class_2022_stack,
),
(
2023,
&mut self.dca_class_2023_avg_price,
&mut self.dca_class_2023_stack,
),
(
2024,
&mut self.dca_class_2024_avg_price,
&mut self.dca_class_2024_stack,
),
(
2025,
&mut self.dca_class_2025_avg_price,
&mut self.dca_class_2025_stack,
),
]
.into_iter()
.try_for_each(|(year, avg_price, stack)| -> Result<()> {
let dateindex = DateIndex::try_from(Date::new(year, 1, 1)).unwrap();
stack.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_from(
starting_indexes.dateindex,
price.timeindexes_to_price_close.dateindex.u(),
dateindex,
exit,
)?;
Ok(())
})?;
avg_price.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_from(
starting_indexes.dateindex,
stack.dateindex.u(),
dateindex,
exit,
)?;
Ok(())
})?;
Ok(())
})?;
thread::scope(|s| -> Result<()> {
[
(
&mut self.indexes_to_price_1w_sma,
&mut self.indexes_to_price_1w_ema,
7,
),
(
&mut self.indexes_to_price_8d_sma,
&mut self.indexes_to_price_8d_ema,
8,
),
(
&mut self.indexes_to_price_13d_sma,
&mut self.indexes_to_price_13d_ema,
13,
),
(
&mut self.indexes_to_price_21d_sma,
&mut self.indexes_to_price_21d_ema,
21,
),
(
&mut self.indexes_to_price_1m_sma,
&mut self.indexes_to_price_1m_ema,
30,
),
(
&mut self.indexes_to_price_34d_sma,
&mut self.indexes_to_price_34d_ema,
34,
),
(
&mut self.indexes_to_price_55d_sma,
&mut self.indexes_to_price_55d_ema,
55,
),
(
&mut self.indexes_to_price_89d_sma,
&mut self.indexes_to_price_89d_ema,
89,
),
(
&mut self.indexes_to_price_144d_sma,
&mut self.indexes_to_price_144d_ema,
144,
),
(
&mut self.indexes_to_price_200d_sma,
&mut self.indexes_to_price_200d_ema,
200,
),
(
&mut self.indexes_to_price_1y_sma,
&mut self.indexes_to_price_1y_ema,
365,
),
(
&mut self.indexes_to_price_2y_sma,
&mut self.indexes_to_price_2y_ema,
2 * 365,
),
(
&mut self.indexes_to_price_200w_sma,
&mut self.indexes_to_price_200w_ema,
200 * 7,
),
(
&mut self.indexes_to_price_4y_sma,
&mut self.indexes_to_price_4y_ema,
4 * 365,
),
]
.into_iter()
.for_each(|(sma, ema, days)| {
s.spawn(move || -> Result<()> {
sma.compute_all(price, starting_indexes, exit, |v| {
v.compute_sma(
starting_indexes.dateindex,
price.timeindexes_to_price_close.dateindex.u(),
days,
exit,
)?;
Ok(())
})?;
ema.compute_all(price, starting_indexes, exit, |v| {
v.compute_ema(
starting_indexes.dateindex,
price.timeindexes_to_price_close.dateindex.u(),
days,
exit,
)?;
Ok(())
})
});
});
Ok(())
})?;
self.indexes_to_1d_returns_1w_sd.compute_all(
starting_indexes,
exit,
self._1d_price_returns.dateindex.u(),
)?;
self.indexes_to_1d_returns_1m_sd.compute_all(
starting_indexes,
exit,
self._1d_price_returns.dateindex.u(),
)?;
self.indexes_to_1d_returns_1y_sd.compute_all(
starting_indexes,
exit,
self._1d_price_returns.dateindex.u(),
)?;
self.dateindex_to_price_true_range.compute_transform3(
starting_indexes.dateindex,
price.timeindexes_to_price_open.dateindex.u(),
price.timeindexes_to_price_high.dateindex.u(),
price.timeindexes_to_price_low.dateindex.u(),
|(i, open, high, low, ..)| {
let high_min_low = **high - **low;
let high_min_open = (**high - **open).abs();
let low_min_open = (**low - **open).abs();
(i, high_min_low.max(high_min_open).max(low_min_open).into())
},
exit,
)?;
self.dateindex_to_price_true_range_2w_sum.compute_sum(
starting_indexes.dateindex,
&self.dateindex_to_price_true_range,
14,
exit,
)?;
self.indexes_to_price_1w_max
.compute_all(starting_indexes, exit, |v| {
v.compute_max(
starting_indexes.dateindex,
price.timeindexes_to_price_high.dateindex.u(),
7,
exit,
)?;
Ok(())
})?;
self.indexes_to_price_1w_min
.compute_all(starting_indexes, exit, |v| {
v.compute_min(
starting_indexes.dateindex,
price.timeindexes_to_price_low.dateindex.u(),
7,
exit,
)?;
Ok(())
})?;
self.indexes_to_price_2w_max
.compute_all(starting_indexes, exit, |v| {
v.compute_max(
starting_indexes.dateindex,
price.timeindexes_to_price_high.dateindex.u(),
14,
exit,
)?;
Ok(())
})?;
self.indexes_to_price_2w_min
.compute_all(starting_indexes, exit, |v| {
v.compute_min(
starting_indexes.dateindex,
price.timeindexes_to_price_low.dateindex.u(),
14,
exit,
)?;
Ok(())
})?;
self.indexes_to_price_1m_max
.compute_all(starting_indexes, exit, |v| {
v.compute_max(
starting_indexes.dateindex,
price.timeindexes_to_price_high.dateindex.u(),
30,
exit,
)?;
Ok(())
})?;
self.indexes_to_price_1m_min
.compute_all(starting_indexes, exit, |v| {
v.compute_min(
starting_indexes.dateindex,
price.timeindexes_to_price_low.dateindex.u(),
30,
exit,
)?;
Ok(())
})?;
self.indexes_to_price_1y_max
.compute_all(starting_indexes, exit, |v| {
v.compute_max(
starting_indexes.dateindex,
price.timeindexes_to_price_high.dateindex.u(),
365,
exit,
)?;
Ok(())
})?;
self.indexes_to_price_1y_min
.compute_all(starting_indexes, exit, |v| {
v.compute_min(
starting_indexes.dateindex,
price.timeindexes_to_price_low.dateindex.u(),
365,
exit,
)?;
Ok(())
})?;
self.indexes_to_price_2w_choppiness_index
.compute_all(starting_indexes, exit, |v| {
let n = 14;
let log10n = (n as f32).log10();
v.compute_transform3(
starting_indexes.dateindex,
&self.dateindex_to_price_true_range_2w_sum,
self.indexes_to_price_2w_max.dateindex.u(),
self.indexes_to_price_2w_min.dateindex.u(),
|(i, tr_sum, max, min, ..)| {
(
i,
StoredF32::from(
100.0 * (*tr_sum / (*max - *min) as f32).log10() / log10n,
),
)
},
exit,
)?;
Ok(())
})?;
Ok(())
}
}

View File

@@ -0,0 +1,364 @@
use brk_error::Result;
use brk_types::{Date, DateIndex};
use vecdb::Exit;
use super::Vecs;
use crate::{
price,
traits::{ComputeDCAAveragePriceViaLen, ComputeDCAStackViaLen},
utils::OptionExt,
Indexes,
};
impl Vecs {
pub fn compute(
&mut self,
price: &price::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let close = price.timeindexes_to_price_close.dateindex.u();
// DCA by period - stack and avg_price
self._1w_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 7, exit)?;
Ok(())
})?;
self._1w_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._1w_dca_stack.dateindex.u(),
7,
exit,
)?;
Ok(())
})?;
self._1m_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 30, exit)?;
Ok(())
})?;
self._1m_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._1m_dca_stack.dateindex.u(),
30,
exit,
)?;
Ok(())
})?;
self._3m_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 3 * 30, exit)?;
Ok(())
})?;
self._3m_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._3m_dca_stack.dateindex.u(),
3 * 30,
exit,
)?;
Ok(())
})?;
self._6m_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 6 * 30, exit)?;
Ok(())
})?;
self._6m_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._6m_dca_stack.dateindex.u(),
6 * 30,
exit,
)?;
Ok(())
})?;
self._1y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 365, exit)?;
Ok(())
})?;
self._1y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._1y_dca_stack.dateindex.u(),
365,
exit,
)?;
Ok(())
})?;
self._2y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 2 * 365, exit)?;
Ok(())
})?;
self._2y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._2y_dca_stack.dateindex.u(),
2 * 365,
exit,
)?;
Ok(())
})?;
self._3y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 3 * 365, exit)?;
Ok(())
})?;
self._3y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._3y_dca_stack.dateindex.u(),
3 * 365,
exit,
)?;
Ok(())
})?;
self._4y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 4 * 365, exit)?;
Ok(())
})?;
self._4y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._4y_dca_stack.dateindex.u(),
4 * 365,
exit,
)?;
Ok(())
})?;
self._5y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 5 * 365, exit)?;
Ok(())
})?;
self._5y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._5y_dca_stack.dateindex.u(),
5 * 365,
exit,
)?;
Ok(())
})?;
self._6y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 6 * 365, exit)?;
Ok(())
})?;
self._6y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._6y_dca_stack.dateindex.u(),
6 * 365,
exit,
)?;
Ok(())
})?;
self._8y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 8 * 365, exit)?;
Ok(())
})?;
self._8y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._8y_dca_stack.dateindex.u(),
8 * 365,
exit,
)?;
Ok(())
})?;
self._10y_dca_stack
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_len(starting_indexes.dateindex, close, 10 * 365, exit)?;
Ok(())
})?;
self._10y_dca_avg_price
.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_len(
starting_indexes.dateindex,
self._10y_dca_stack.dateindex.u(),
10 * 365,
exit,
)?;
Ok(())
})?;
// DCA by period - CAGR (computed from returns)
self._2y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._2y_dca_returns.dateindex.u(),
2 * 365,
exit,
)?;
Ok(())
})?;
self._3y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._3y_dca_returns.dateindex.u(),
3 * 365,
exit,
)?;
Ok(())
})?;
self._4y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._4y_dca_returns.dateindex.u(),
4 * 365,
exit,
)?;
Ok(())
})?;
self._5y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._5y_dca_returns.dateindex.u(),
5 * 365,
exit,
)?;
Ok(())
})?;
self._6y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._6y_dca_returns.dateindex.u(),
6 * 365,
exit,
)?;
Ok(())
})?;
self._8y_dca_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._8y_dca_returns.dateindex.u(),
8 * 365,
exit,
)?;
Ok(())
})?;
self._10y_dca_cagr
.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._10y_dca_returns.dateindex.u(),
10 * 365,
exit,
)?;
Ok(())
})?;
// DCA by year class - stack and avg_price
// Each year class computes DCA from Jan 1 of that year
[
(
2025,
&mut self.dca_class_2025_stack,
&mut self.dca_class_2025_avg_price,
),
(
2024,
&mut self.dca_class_2024_stack,
&mut self.dca_class_2024_avg_price,
),
(
2023,
&mut self.dca_class_2023_stack,
&mut self.dca_class_2023_avg_price,
),
(
2022,
&mut self.dca_class_2022_stack,
&mut self.dca_class_2022_avg_price,
),
(
2021,
&mut self.dca_class_2021_stack,
&mut self.dca_class_2021_avg_price,
),
(
2020,
&mut self.dca_class_2020_stack,
&mut self.dca_class_2020_avg_price,
),
(
2019,
&mut self.dca_class_2019_stack,
&mut self.dca_class_2019_avg_price,
),
(
2018,
&mut self.dca_class_2018_stack,
&mut self.dca_class_2018_avg_price,
),
(
2017,
&mut self.dca_class_2017_stack,
&mut self.dca_class_2017_avg_price,
),
(
2016,
&mut self.dca_class_2016_stack,
&mut self.dca_class_2016_avg_price,
),
(
2015,
&mut self.dca_class_2015_stack,
&mut self.dca_class_2015_avg_price,
),
]
.into_iter()
.try_for_each(|(year, stack, avg_price)| -> Result<()> {
let dateindex = DateIndex::try_from(Date::new(year, 1, 1)).unwrap();
stack.compute_all(starting_indexes, exit, |v| {
v.compute_dca_stack_via_from(starting_indexes.dateindex, close, dateindex, exit)?;
Ok(())
})?;
avg_price.compute_all(starting_indexes, exit, |v| {
v.compute_dca_avg_price_via_from(
starting_indexes.dateindex,
stack.dateindex.u(),
dateindex,
exit,
)?;
Ok(())
})?;
Ok(())
})?;
Ok(())
}
}

View File

@@ -0,0 +1,697 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{
grouped::{
ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, PercentageDiffCloseDollars, Source,
VecBuilderOptions,
},
indexes, price,
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
price: &price::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let last = VecBuilderOptions::default().add_last();
// DCA by period - stack
let _1w_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"1w_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1m_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"1m_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3m_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"3m_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6m_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"6m_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"1y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _2y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"2y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"3y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _4y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"4y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _5y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"5y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"6y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _8y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"8y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _10y_dca_stack = ComputedVecsFromDateIndex::forced_import(
db,
"10y_dca_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
// DCA by period - avg price
let _1w_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"1w_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1m_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"1m_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3m_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"3m_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6m_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"6m_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"1y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _2y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"2y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"3y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _4y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"4y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _5y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"5y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"6y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _8y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"8y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _10y_dca_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"10y_dca_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
// DCA by period - returns (lazy)
let _1w_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1w_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_1w_dca_avg_price,
);
let _1m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1m_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_1m_dca_avg_price,
);
let _3m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"3m_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_3m_dca_avg_price,
);
let _6m_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"6m_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_6m_dca_avg_price,
);
let _1y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1y_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_1y_dca_avg_price,
);
let _2y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"2y_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_2y_dca_avg_price,
);
let _3y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"3y_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_3y_dca_avg_price,
);
let _4y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"4y_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_4y_dca_avg_price,
);
let _5y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"5y_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_5y_dca_avg_price,
);
let _6y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"6y_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_6y_dca_avg_price,
);
let _8y_dca_returns = LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"8y_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_8y_dca_avg_price,
);
let _10y_dca_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"10y_dca_returns",
version + v0,
&price.timeindexes_to_price_close,
&_10y_dca_avg_price,
);
// DCA by period - CAGR
let _2y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"2y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _3y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"3y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _4y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"4y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _5y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"5y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _6y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"6y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _8y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"8y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _10y_dca_cagr = ComputedVecsFromDateIndex::forced_import(
db,
"10y_dca_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?;
// DCA by year class - stack
let dca_class_2025_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2025_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2024_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2024_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2023_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2023_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2022_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2022_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2021_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2021_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2020_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2020_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2019_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2019_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2018_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2018_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2017_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2017_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2016_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2016_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2015_stack = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2015_stack",
Source::Compute,
version + v0,
indexes,
last,
)?;
// DCA by year class - avg price
let dca_class_2025_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2025_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2024_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2024_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2023_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2023_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2022_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2022_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2021_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2021_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2020_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2020_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2019_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2019_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2018_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2018_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2017_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2017_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2016_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2016_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
let dca_class_2015_avg_price = ComputedVecsFromDateIndex::forced_import(
db,
"dca_class_2015_avg_price",
Source::Compute,
version + v0,
indexes,
last,
)?;
// DCA by year class - returns (lazy)
let dca_class_2025_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2025_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2025_avg_price,
);
let dca_class_2024_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2024_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2024_avg_price,
);
let dca_class_2023_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2023_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2023_avg_price,
);
let dca_class_2022_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2022_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2022_avg_price,
);
let dca_class_2021_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2021_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2021_avg_price,
);
let dca_class_2020_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2020_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2020_avg_price,
);
let dca_class_2019_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2019_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2019_avg_price,
);
let dca_class_2018_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2018_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2018_avg_price,
);
let dca_class_2017_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2017_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2017_avg_price,
);
let dca_class_2016_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2016_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2016_avg_price,
);
let dca_class_2015_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"dca_class_2015_returns",
version + v0,
&price.timeindexes_to_price_close,
&dca_class_2015_avg_price,
);
Ok(Self {
_1w_dca_stack,
_1m_dca_stack,
_3m_dca_stack,
_6m_dca_stack,
_1y_dca_stack,
_2y_dca_stack,
_3y_dca_stack,
_4y_dca_stack,
_5y_dca_stack,
_6y_dca_stack,
_8y_dca_stack,
_10y_dca_stack,
_1w_dca_avg_price,
_1m_dca_avg_price,
_3m_dca_avg_price,
_6m_dca_avg_price,
_1y_dca_avg_price,
_2y_dca_avg_price,
_3y_dca_avg_price,
_4y_dca_avg_price,
_5y_dca_avg_price,
_6y_dca_avg_price,
_8y_dca_avg_price,
_10y_dca_avg_price,
_1w_dca_returns,
_1m_dca_returns,
_3m_dca_returns,
_6m_dca_returns,
_1y_dca_returns,
_2y_dca_returns,
_3y_dca_returns,
_4y_dca_returns,
_5y_dca_returns,
_6y_dca_returns,
_8y_dca_returns,
_10y_dca_returns,
_2y_dca_cagr,
_3y_dca_cagr,
_4y_dca_cagr,
_5y_dca_cagr,
_6y_dca_cagr,
_8y_dca_cagr,
_10y_dca_cagr,
dca_class_2025_stack,
dca_class_2024_stack,
dca_class_2023_stack,
dca_class_2022_stack,
dca_class_2021_stack,
dca_class_2020_stack,
dca_class_2019_stack,
dca_class_2018_stack,
dca_class_2017_stack,
dca_class_2016_stack,
dca_class_2015_stack,
dca_class_2025_avg_price,
dca_class_2024_avg_price,
dca_class_2023_avg_price,
dca_class_2022_avg_price,
dca_class_2021_avg_price,
dca_class_2020_avg_price,
dca_class_2019_avg_price,
dca_class_2018_avg_price,
dca_class_2017_avg_price,
dca_class_2016_avg_price,
dca_class_2015_avg_price,
dca_class_2025_returns,
dca_class_2024_returns,
dca_class_2023_returns,
dca_class_2022_returns,
dca_class_2021_returns,
dca_class_2020_returns,
dca_class_2019_returns,
dca_class_2018_returns,
dca_class_2017_returns,
dca_class_2016_returns,
dca_class_2015_returns,
})
}
}

View File

@@ -0,0 +1,5 @@
mod compute;
mod import;
mod vecs;
pub use vecs::Vecs;

View File

@@ -0,0 +1,98 @@
use brk_traversable::Traversable;
use brk_types::{Close, Dollars, Sats, StoredF32};
use crate::grouped::{ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex};
/// Dollar-cost averaging metrics by time period and year class
#[derive(Clone, Traversable)]
pub struct Vecs {
// DCA by period - stack
pub _1w_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _1m_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _3m_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _6m_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _1y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _2y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _3y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _4y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _5y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _6y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _8y_dca_stack: ComputedVecsFromDateIndex<Sats>,
pub _10y_dca_stack: ComputedVecsFromDateIndex<Sats>,
// DCA by period - avg price
pub _1w_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _1m_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _3m_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _6m_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _1y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _2y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _3y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _4y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _5y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _6y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _8y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub _10y_dca_avg_price: ComputedVecsFromDateIndex<Dollars>,
// DCA by period - returns (lazy)
pub _1w_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _1m_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _3m_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _6m_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _1y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _2y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _3y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _4y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _5y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _6y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _8y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub _10y_dca_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
// DCA by period - CAGR
pub _2y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _3y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _4y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _5y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _6y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _8y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
pub _10y_dca_cagr: ComputedVecsFromDateIndex<StoredF32>,
// DCA by year class - stack
pub dca_class_2025_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2024_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2023_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2022_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2021_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2020_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2019_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2018_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2017_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2016_stack: ComputedVecsFromDateIndex<Sats>,
pub dca_class_2015_stack: ComputedVecsFromDateIndex<Sats>,
// DCA by year class - avg price
pub dca_class_2025_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2024_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2023_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2022_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2021_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2020_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2019_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2018_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2017_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2016_avg_price: ComputedVecsFromDateIndex<Dollars>,
pub dca_class_2015_avg_price: ComputedVecsFromDateIndex<Dollars>,
// DCA by year class - returns (lazy)
pub dca_class_2025_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2024_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2023_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2022_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2021_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2020_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2019_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2018_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2017_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2016_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
pub dca_class_2015_returns: LazyVecsFrom2FromDateIndex<StoredF32, Close<Dollars>, Dollars>,
}

View File

@@ -0,0 +1,149 @@
use brk_error::Result;
use vecdb::Exit;
use super::Vecs;
use crate::{price, utils::OptionExt, Indexes};
impl Vecs {
pub fn compute(
&mut self,
price: &price::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
let close = price.timeindexes_to_price_close.dateindex.u();
self.price_1d_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 1, exit)?;
Ok(())
})?;
self.price_1w_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 7, exit)?;
Ok(())
})?;
self.price_1m_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 30, exit)?;
Ok(())
})?;
self.price_3m_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 3 * 30, exit)?;
Ok(())
})?;
self.price_6m_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 6 * 30, exit)?;
Ok(())
})?;
self.price_1y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 365, exit)?;
Ok(())
})?;
self.price_2y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 2 * 365, exit)?;
Ok(())
})?;
self.price_3y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 3 * 365, exit)?;
Ok(())
})?;
self.price_4y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 4 * 365, exit)?;
Ok(())
})?;
self.price_5y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 5 * 365, exit)?;
Ok(())
})?;
self.price_6y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 6 * 365, exit)?;
Ok(())
})?;
self.price_8y_ago.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 8 * 365, exit)?;
Ok(())
})?;
self.price_10y_ago
.compute_all(starting_indexes, exit, |v| {
v.compute_previous_value(starting_indexes.dateindex, close, 10 * 365, exit)?;
Ok(())
})?;
// CAGR computed from returns
self._2y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._2y_price_returns.dateindex.u(),
2 * 365,
exit,
)?;
Ok(())
})?;
self._3y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._3y_price_returns.dateindex.u(),
3 * 365,
exit,
)?;
Ok(())
})?;
self._4y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._4y_price_returns.dateindex.u(),
4 * 365,
exit,
)?;
Ok(())
})?;
self._5y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._5y_price_returns.dateindex.u(),
5 * 365,
exit,
)?;
Ok(())
})?;
self._6y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._6y_price_returns.dateindex.u(),
6 * 365,
exit,
)?;
Ok(())
})?;
self._8y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._8y_price_returns.dateindex.u(),
8 * 365,
exit,
)?;
Ok(())
})?;
self._10y_cagr.compute_all(starting_indexes, exit, |v| {
v.compute_cagr(
starting_indexes.dateindex,
self._10y_price_returns.dateindex.u(),
10 * 365,
exit,
)?;
Ok(())
})?;
Ok(())
}
}

View File

@@ -0,0 +1,308 @@
use brk_error::Result;
use brk_types::Version;
use vecdb::Database;
use super::Vecs;
use crate::{
grouped::{
ComputedVecsFromDateIndex, LazyVecsFrom2FromDateIndex, PercentageDiffCloseDollars, Source,
VecBuilderOptions,
},
indexes, price,
};
impl Vecs {
pub fn forced_import(
db: &Database,
version: Version,
indexes: &indexes::Vecs,
price: &price::Vecs,
) -> Result<Self> {
let v0 = Version::ZERO;
let last = VecBuilderOptions::default().add_last();
let price_1d_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_1d_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_1w_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_1w_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_1m_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_1m_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_3m_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_3m_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_6m_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_6m_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_1y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_1y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_2y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_2y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_3y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_3y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_4y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_4y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_5y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_5y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_6y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_6y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_8y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_8y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let price_10y_ago = ComputedVecsFromDateIndex::forced_import(
db,
"price_10y_ago",
Source::Compute,
version + v0,
indexes,
last,
)?;
let _1d_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1d_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_1d_ago,
);
let _1w_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1w_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_1w_ago,
);
let _1m_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1m_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_1m_ago,
);
let _3m_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"3m_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_3m_ago,
);
let _6m_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"6m_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_6m_ago,
);
let _1y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"1y_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_1y_ago,
);
let _2y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"2y_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_2y_ago,
);
let _3y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"3y_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_3y_ago,
);
let _4y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"4y_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_4y_ago,
);
let _5y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"5y_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_5y_ago,
);
let _6y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"6y_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_6y_ago,
);
let _8y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"8y_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_8y_ago,
);
let _10y_price_returns =
LazyVecsFrom2FromDateIndex::from_computed::<PercentageDiffCloseDollars>(
"10y_price_returns",
version + v0,
&price.timeindexes_to_price_close,
&price_10y_ago,
);
Ok(Self {
price_1d_ago,
price_1w_ago,
price_1m_ago,
price_3m_ago,
price_6m_ago,
price_1y_ago,
price_2y_ago,
price_3y_ago,
price_4y_ago,
price_5y_ago,
price_6y_ago,
price_8y_ago,
price_10y_ago,
_1d_price_returns,
_1w_price_returns,
_1m_price_returns,
_3m_price_returns,
_6m_price_returns,
_1y_price_returns,
_2y_price_returns,
_3y_price_returns,
_4y_price_returns,
_5y_price_returns,
_6y_price_returns,
_8y_price_returns,
_10y_price_returns,
_2y_cagr: ComputedVecsFromDateIndex::forced_import(
db,
"2y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?,
_3y_cagr: ComputedVecsFromDateIndex::forced_import(
db,
"3y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?,
_4y_cagr: ComputedVecsFromDateIndex::forced_import(
db,
"4y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?,
_5y_cagr: ComputedVecsFromDateIndex::forced_import(
db,
"5y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?,
_6y_cagr: ComputedVecsFromDateIndex::forced_import(
db,
"6y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?,
_8y_cagr: ComputedVecsFromDateIndex::forced_import(
db,
"8y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?,
_10y_cagr: ComputedVecsFromDateIndex::forced_import(
db,
"10y_cagr",
Source::Compute,
version + v0,
indexes,
last,
)?,
})
}
}

Some files were not shown because too many files have changed in this diff Show More