mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
website: snapshot
This commit is contained in:
@@ -30,7 +30,7 @@ where
|
||||
pub dates: LazyDateDerivedFull<T>,
|
||||
}
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
const VERSION: Version = Version::ONE;
|
||||
|
||||
impl<T> TxDerivedFull<T>
|
||||
where
|
||||
@@ -111,7 +111,7 @@ where
|
||||
|
||||
self.dateindex.compute(
|
||||
starting_indexes.dateindex,
|
||||
&self.height.average().0,
|
||||
&self.height.sum().0,
|
||||
&indexes.dateindex.first_height,
|
||||
&indexes.dateindex.height_count,
|
||||
exit,
|
||||
|
||||
@@ -14,6 +14,7 @@ pub const DCA_CLASS_YEARS: ByDcaClass<u16> = ByDcaClass {
|
||||
_2023: 2023,
|
||||
_2024: 2024,
|
||||
_2025: 2025,
|
||||
_2026: 2026,
|
||||
};
|
||||
|
||||
/// DCA class names
|
||||
@@ -29,6 +30,7 @@ pub const DCA_CLASS_NAMES: ByDcaClass<&'static str> = ByDcaClass {
|
||||
_2023: "dca_class_2023",
|
||||
_2024: "dca_class_2024",
|
||||
_2025: "dca_class_2025",
|
||||
_2026: "dca_class_2026",
|
||||
};
|
||||
|
||||
/// Generic wrapper for DCA year class data
|
||||
@@ -45,6 +47,7 @@ pub struct ByDcaClass<T> {
|
||||
pub _2023: T,
|
||||
pub _2024: T,
|
||||
pub _2025: T,
|
||||
pub _2026: T,
|
||||
}
|
||||
|
||||
impl<T> ByDcaClass<T> {
|
||||
@@ -66,6 +69,7 @@ impl<T> ByDcaClass<T> {
|
||||
_2023: create(n._2023, y._2023, Self::dateindex(y._2023)),
|
||||
_2024: create(n._2024, y._2024, Self::dateindex(y._2024)),
|
||||
_2025: create(n._2025, y._2025, Self::dateindex(y._2025)),
|
||||
_2026: create(n._2026, y._2026, Self::dateindex(y._2026)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +91,7 @@ impl<T> ByDcaClass<T> {
|
||||
_2023: create(n._2023, y._2023, Self::dateindex(y._2023))?,
|
||||
_2024: create(n._2024, y._2024, Self::dateindex(y._2024))?,
|
||||
_2025: create(n._2025, y._2025, Self::dateindex(y._2025))?,
|
||||
_2026: create(n._2026, y._2026, Self::dateindex(y._2026))?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -107,6 +112,7 @@ impl<T> ByDcaClass<T> {
|
||||
&self._2023,
|
||||
&self._2024,
|
||||
&self._2025,
|
||||
&self._2026,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@@ -124,6 +130,7 @@ impl<T> ByDcaClass<T> {
|
||||
&mut self._2023,
|
||||
&mut self._2024,
|
||||
&mut self._2025,
|
||||
&mut self._2026,
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
@@ -142,11 +149,12 @@ impl<T> ByDcaClass<T> {
|
||||
(&mut self._2023, Self::dateindex(y._2023)),
|
||||
(&mut self._2024, Self::dateindex(y._2024)),
|
||||
(&mut self._2025, Self::dateindex(y._2025)),
|
||||
(&mut self._2026, Self::dateindex(y._2026)),
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
|
||||
pub fn dateindexes() -> [DateIndex; 11] {
|
||||
pub fn dateindexes() -> [DateIndex; 12] {
|
||||
let y = DCA_CLASS_YEARS;
|
||||
[
|
||||
Self::dateindex(y._2015),
|
||||
@@ -160,6 +168,7 @@ impl<T> ByDcaClass<T> {
|
||||
Self::dateindex(y._2023),
|
||||
Self::dateindex(y._2024),
|
||||
Self::dateindex(y._2025),
|
||||
Self::dateindex(y._2026),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -176,6 +185,7 @@ impl<T> ByDcaClass<T> {
|
||||
_2023: (self._2023, other._2023),
|
||||
_2024: (self._2024, other._2024),
|
||||
_2025: (self._2025, other._2025),
|
||||
_2026: (self._2026, other._2026),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +202,7 @@ impl<T> ByDcaClass<T> {
|
||||
_2023: (&self._2023, &other._2023),
|
||||
_2024: (&self._2024, &other._2024),
|
||||
_2025: (&self._2025, &other._2025),
|
||||
_2026: (&self._2026, &other._2026),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +219,7 @@ impl<T> ByDcaClass<T> {
|
||||
_2023: f(self._2023),
|
||||
_2024: f(self._2024),
|
||||
_2025: f(self._2025),
|
||||
_2026: f(self._2026),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,9 @@ impl Vecs {
|
||||
// Step 7: Aggregate to daily OHLC
|
||||
self.compute_daily_ohlc(indexes, starting_indexes, exit)?;
|
||||
|
||||
// Step 7b: Compute close-only and mid-price daily OHLC
|
||||
self.compute_close_and_mid_ohlc(indexes, price_cents, starting_indexes, exit)?;
|
||||
|
||||
// Step 8: Compute Phase Oracle V2 (round USD template matching)
|
||||
// 8a: Per-block 200-bin histograms (uses ALL outputs, not pair-filtered)
|
||||
self.compute_phase_v2_histograms(indexer, indexes, starting_indexes, exit)?;
|
||||
@@ -1120,6 +1123,143 @@ impl Vecs {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute daily OHLC from height close only and mid price ((open+close)/2)
|
||||
fn compute_close_and_mid_ohlc(
|
||||
&mut self,
|
||||
indexes: &indexes::Vecs,
|
||||
price_cents: ¢s::Vecs,
|
||||
starting_indexes: &ComputeIndexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let last_dateindex = DateIndex::from(indexes.dateindex.date.len());
|
||||
let start_dateindex = starting_indexes
|
||||
.dateindex
|
||||
.min(DateIndex::from(self.close_ohlc_cents.len()))
|
||||
.min(DateIndex::from(self.mid_ohlc_cents.len()));
|
||||
|
||||
if start_dateindex >= last_dateindex {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let last_height = Height::from(price_cents.ohlc.height.len());
|
||||
let mut close_iter = price_cents.split.height.close.iter();
|
||||
let mut open_iter = price_cents.split.height.open.iter();
|
||||
let mut dateindex_to_first_height_iter = indexes.dateindex.first_height.iter();
|
||||
let mut height_count_iter = indexes.dateindex.height_count.iter();
|
||||
|
||||
for dateindex in start_dateindex.to_usize()..last_dateindex.to_usize() {
|
||||
let dateindex = DateIndex::from(dateindex);
|
||||
let first_height = dateindex_to_first_height_iter.get_unwrap(dateindex);
|
||||
let count = height_count_iter.get_unwrap(dateindex);
|
||||
|
||||
if *count == 0 || first_height >= last_height {
|
||||
continue;
|
||||
}
|
||||
|
||||
let count = *count as usize;
|
||||
|
||||
// Close-only OHLC
|
||||
let mut close_open = None;
|
||||
let mut close_high = Cents::from(0i64);
|
||||
let mut close_low = Cents::from(i64::MAX);
|
||||
let mut close_close = Cents::from(0i64);
|
||||
|
||||
// Mid-price OHLC
|
||||
let mut mid_open = None;
|
||||
let mut mid_high = Cents::from(0i64);
|
||||
let mut mid_low = Cents::from(i64::MAX);
|
||||
let mut mid_close = Cents::from(0i64);
|
||||
|
||||
for i in 0..count {
|
||||
let height = first_height + Height::from(i);
|
||||
if height >= last_height {
|
||||
break;
|
||||
}
|
||||
|
||||
// Get close price for this height
|
||||
if let Some(close_price) = close_iter.get(height) {
|
||||
let close_cents = Cents::from(*close_price);
|
||||
|
||||
// Close-only OHLC
|
||||
if close_open.is_none() {
|
||||
close_open = Some(close_cents);
|
||||
}
|
||||
if close_cents > close_high {
|
||||
close_high = close_cents;
|
||||
}
|
||||
if close_cents < close_low {
|
||||
close_low = close_cents;
|
||||
}
|
||||
close_close = close_cents;
|
||||
|
||||
// Mid-price OHLC
|
||||
if let Some(open_price) = open_iter.get(height) {
|
||||
let open_cents = Cents::from(*open_price);
|
||||
let mid_cents =
|
||||
Cents::from((i64::from(open_cents) + i64::from(close_cents)) / 2);
|
||||
|
||||
if mid_open.is_none() {
|
||||
mid_open = Some(mid_cents);
|
||||
}
|
||||
if mid_cents > mid_high {
|
||||
mid_high = mid_cents;
|
||||
}
|
||||
if mid_cents < mid_low {
|
||||
mid_low = mid_cents;
|
||||
}
|
||||
mid_close = mid_cents;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build close-only OHLC
|
||||
let close_ohlc = if let Some(open_price) = close_open {
|
||||
OHLCCents {
|
||||
open: Open::new(open_price),
|
||||
high: High::new(close_high),
|
||||
low: Low::new(close_low),
|
||||
close: Close::new(close_close),
|
||||
}
|
||||
} else if dateindex > DateIndex::from(0usize) {
|
||||
self.close_ohlc_cents
|
||||
.iter()?
|
||||
.get(dateindex.decremented().unwrap())
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
OHLCCents::default()
|
||||
};
|
||||
|
||||
// Build mid-price OHLC
|
||||
let mid_ohlc = if let Some(open_price) = mid_open {
|
||||
OHLCCents {
|
||||
open: Open::new(open_price),
|
||||
high: High::new(mid_high),
|
||||
low: Low::new(mid_low),
|
||||
close: Close::new(mid_close),
|
||||
}
|
||||
} else if dateindex > DateIndex::from(0usize) {
|
||||
self.mid_ohlc_cents
|
||||
.iter()?
|
||||
.get(dateindex.decremented().unwrap())
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
OHLCCents::default()
|
||||
};
|
||||
|
||||
self.close_ohlc_cents.truncate_push(dateindex, close_ohlc)?;
|
||||
self.mid_ohlc_cents.truncate_push(dateindex, mid_ohlc)?;
|
||||
}
|
||||
|
||||
// Write daily data
|
||||
{
|
||||
let _lock = exit.lock();
|
||||
self.close_ohlc_cents.write()?;
|
||||
self.mid_ohlc_cents.write()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Compute Phase Oracle V2 - Step 1: Per-block 200-bin phase histograms
|
||||
///
|
||||
/// Uses ALL outputs (like Python test), filtered only by sats range (1k-100k BTC).
|
||||
|
||||
@@ -46,6 +46,24 @@ impl Vecs {
|
||||
|di: DateIndex, iter| iter.get(di).map(|o: OHLCCents| OHLCDollars::from(o)),
|
||||
);
|
||||
|
||||
// Daily OHLC from height close only
|
||||
let close_ohlc_cents = BytesVec::forced_import(db, "close_ohlc_cents", version)?;
|
||||
let close_ohlc_dollars = LazyVecFrom1::init(
|
||||
"close_ohlc_dollars",
|
||||
version,
|
||||
close_ohlc_cents.boxed_clone(),
|
||||
|di: DateIndex, iter| iter.get(di).map(|o: OHLCCents| OHLCDollars::from(o)),
|
||||
);
|
||||
|
||||
// Daily OHLC from height mid price ((open+close)/2)
|
||||
let mid_ohlc_cents = BytesVec::forced_import(db, "mid_ohlc_cents", version)?;
|
||||
let mid_ohlc_dollars = LazyVecFrom1::init(
|
||||
"mid_ohlc_dollars",
|
||||
version,
|
||||
mid_ohlc_cents.boxed_clone(),
|
||||
|di: DateIndex, iter| iter.get(di).map(|o: OHLCCents| OHLCDollars::from(o)),
|
||||
);
|
||||
|
||||
// Phase Oracle V2 (round USD template matching)
|
||||
// v3: Peak prices use 100 bins (downsampled from 200)
|
||||
let phase_v2_version = version + Version::new(3);
|
||||
@@ -111,6 +129,10 @@ impl Vecs {
|
||||
ohlc_cents,
|
||||
ohlc_dollars,
|
||||
tx_count,
|
||||
close_ohlc_cents,
|
||||
close_ohlc_dollars,
|
||||
mid_ohlc_cents,
|
||||
mid_ohlc_dollars,
|
||||
phase_v2_histogram,
|
||||
phase_v2_price_cents,
|
||||
phase_v2_peak_price_cents,
|
||||
|
||||
@@ -56,6 +56,20 @@ pub struct Vecs {
|
||||
/// Number of qualifying transactions per day (for confidence)
|
||||
pub tx_count: PcoVec<DateIndex, StoredU32>,
|
||||
|
||||
// ========== Daily OHLC from height close only ==========
|
||||
/// Daily OHLC computed from height close prices only
|
||||
pub close_ohlc_cents: BytesVec<DateIndex, OHLCCents>,
|
||||
|
||||
/// Daily OHLC from close in dollars (lazy conversion)
|
||||
pub close_ohlc_dollars: LazyVecFrom1<DateIndex, OHLCDollars, DateIndex, OHLCCents>,
|
||||
|
||||
// ========== Daily OHLC from height mid price (open+close)/2 ==========
|
||||
/// Daily OHLC computed from height mid prices ((open+close)/2)
|
||||
pub mid_ohlc_cents: BytesVec<DateIndex, OHLCCents>,
|
||||
|
||||
/// Daily OHLC from mid in dollars (lazy conversion)
|
||||
pub mid_ohlc_dollars: LazyVecFrom1<DateIndex, OHLCDollars, DateIndex, OHLCCents>,
|
||||
|
||||
// ========== Phase Oracle V2 (round USD template matching) ==========
|
||||
/// Per-block 200-bin phase histogram
|
||||
pub phase_v2_histogram: BytesVec<Height, OracleBinsV2>,
|
||||
|
||||
630000
crates/brk_computer/src/price/prices.txt
Normal file
630000
crates/brk_computer/src/price/prices.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,18 @@ impl Vecs {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.received_sum
|
||||
.compute_all(indexes, starting_indexes, exit, |v| {
|
||||
v.compute_sum_from_indexes(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.transactions.first_txindex,
|
||||
&indexes.height.txindex_count,
|
||||
&fees_vecs.output_value,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.annualized_volume.compute_sats(|v| {
|
||||
v.compute_sum(
|
||||
starting_indexes.dateindex,
|
||||
|
||||
@@ -23,6 +23,13 @@ impl Vecs {
|
||||
indexes,
|
||||
price,
|
||||
)?,
|
||||
received_sum: ValueFromHeightSum::forced_import(
|
||||
db,
|
||||
"received_sum",
|
||||
version,
|
||||
indexes,
|
||||
price,
|
||||
)?,
|
||||
annualized_volume: ValueFromDateLast::forced_import(
|
||||
db,
|
||||
"annualized_volume",
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::internal::{ComputedFromDateLast, ValueFromHeightSum, ValueFromDateLas
|
||||
#[derive(Clone, Traversable)]
|
||||
pub struct Vecs {
|
||||
pub sent_sum: ValueFromHeightSum,
|
||||
pub received_sum: ValueFromHeightSum,
|
||||
pub annualized_volume: ValueFromDateLast,
|
||||
pub tx_per_sec: ComputedFromDateLast<StoredF32>,
|
||||
pub outputs_per_sec: ComputedFromDateLast<StoredF32>,
|
||||
|
||||
Reference in New Issue
Block a user