global: snapshot

This commit is contained in:
nym21
2026-03-17 12:37:56 +01:00
parent f62943199c
commit 42540fba99
22 changed files with 736 additions and 794 deletions

View File

@@ -16,7 +16,7 @@ impl Vecs {
exit: &Exit,
) -> Result<()> {
self.spent
.compute(&self.db, indexer, starting_indexes, exit)?;
.compute(indexer, starting_indexes, exit)?;
self.count
.compute(indexer, indexes, blocks, starting_indexes, exit)?;

View File

@@ -2,7 +2,7 @@ use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{Indexes, Sats, TxIndex, TxOutIndex, Vout};
use tracing::info;
use vecdb::{AnyStoredVec, AnyVec, Database, Exit, ReadableVec, VecIndex, WritableVec};
use vecdb::{AnyStoredVec, AnyVec, Exit, ReadableVec, VecIndex, WritableVec};
use super::Vecs;
@@ -11,7 +11,6 @@ const BATCH_SIZE: usize = 2 * 1024 * 1024 * 1024 / size_of::<Entry>();
impl Vecs {
pub(crate) fn compute(
&mut self,
db: &Database,
indexer: &Indexer,
starting_indexes: &Indexes,
exit: &Exit,
@@ -105,14 +104,13 @@ impl Vecs {
self.value.push(out_value[i]);
}
if batch_end < target {
info!("TxIns: {:.2}%", batch_end as f64 / target as f64 * 100.0);
}
let _lock = exit.lock();
self.txout_index.write()?;
self.value.write()?;
db.flush()?;
if batch_end < target {
info!("TxIns: {:.2}%", batch_end as f64 / target as f64 * 100.0);
}
batch_start = batch_end;
}

View File

@@ -10,6 +10,7 @@ pub struct Windows<A> {
impl<A> Windows<A> {
pub const SUFFIXES: [&'static str; 4] = ["24h", "1w", "1m", "1y"];
pub const DAYS: [usize; 4] = [1, 7, 30, 365];
pub fn try_from_fn<E>(
mut f: impl FnMut(&str) -> std::result::Result<A, E>,

View File

@@ -136,7 +136,7 @@ impl RatioPerBlockPercentiles {
{
let _lock = exit.lock();
self.mut_pct_vecs().try_for_each(|v| v.flush())?;
self.mut_pct_vecs().try_for_each(|v| v.write().map(|_| ()))?;
}
// Cents bands

View File

@@ -162,7 +162,7 @@ impl StdDevPerBlockExtended {
{
let _lock = exit.lock();
self.mut_band_height_vecs().try_for_each(|v| v.flush())?;
self.mut_band_height_vecs().try_for_each(|v| v.write().map(|_| ()))?;
}
self.zscore.height.compute_zscore(

View File

@@ -30,6 +30,11 @@ pub trait SqrtDays {
const FACTOR: f32;
}
pub struct Days1;
impl SqrtDays for Days1 {
const FACTOR: f32 = 1.0; // 1.0_f32.sqrt()
}
pub struct Days7;
impl SqrtDays for Days7 {
const FACTOR: f32 = 2.6457513; // 7.0_f32.sqrt()

View File

@@ -20,7 +20,7 @@ pub use currency::{
SatsToBitcoin, SatsToCents,
};
pub use derived::{
Days7, Days30, Days365, DaysToYears, PerSec, PriceTimesRatioBp32Cents, PriceTimesRatioCents,
Days1, Days7, Days30, Days365, DaysToYears, PerSec, PriceTimesRatioBp32Cents, PriceTimesRatioCents,
RatioCents64, TimesSqrt,
};
pub use ratio::{

View File

@@ -46,11 +46,7 @@ impl Vecs {
let _24h_price_return_ratio = &self.periods._24h.ratio.height;
for sd in [
&mut self.sd_24h._1w,
&mut self.sd_24h._1m,
&mut self.sd_24h._1y,
] {
for sd in self.sd_24h.as_mut_array() {
sd.compute_all(blocks, starting_indexes, exit, _24h_price_return_ratio)?;
}

View File

@@ -3,10 +3,10 @@ use brk_types::Version;
use vecdb::Database;
use super::super::lookback::ByLookbackPeriod;
use super::{vecs::PriceReturn24hSdVecs, Vecs};
use super::Vecs;
use crate::{
indexes,
internal::{StdDevPerBlock, PercentPerBlock},
internal::{StdDevPerBlock, PercentPerBlock, Windows},
market::dca::ByDcaCagr,
};
@@ -18,46 +18,27 @@ impl Vecs {
) -> Result<Self> {
let v1 = Version::ONE;
let price_return = ByLookbackPeriod::try_new(|name, _days| {
let periods = ByLookbackPeriod::try_new(|name, _days| {
PercentPerBlock::forced_import(db, &format!("price_return_{name}"), version, indexes)
})?;
// CAGR (computed, 2y+ only)
let price_cagr = ByDcaCagr::try_new(|name, _days| {
let cagr = ByDcaCagr::try_new(|name, _days| {
PercentPerBlock::forced_import(db, &format!("price_cagr_{name}"), version, indexes)
})?;
let price_return_24h_sd = PriceReturn24hSdVecs {
_1w: StdDevPerBlock::forced_import(
let mut days_iter = Windows::<()>::DAYS.iter();
let sd_24h = Windows::try_from_fn(|suffix| {
let days = *days_iter.next().unwrap();
StdDevPerBlock::forced_import(
db,
"price_return_24h",
"1w",
7,
suffix,
days,
version + v1,
indexes,
)?,
_1m: StdDevPerBlock::forced_import(
db,
"price_return_24h",
"1m",
30,
version + v1,
indexes,
)?,
_1y: StdDevPerBlock::forced_import(
db,
"price_return_24h",
"1y",
365,
version + v1,
indexes,
)?,
};
)
})?;
Ok(Self {
periods: price_return,
cagr: price_cagr,
sd_24h: price_return_24h_sd,
})
Ok(Self { periods, cagr, sd_24h })
}
}

View File

@@ -3,20 +3,13 @@ use brk_types::BasisPointsSigned32;
use vecdb::{Rw, StorageMode};
use crate::{
internal::{PercentPerBlock, StdDevPerBlock},
internal::{PercentPerBlock, StdDevPerBlock, Windows},
market::{dca::ByDcaCagr, lookback::ByLookbackPeriod},
};
#[derive(Traversable)]
pub struct PriceReturn24hSdVecs<M: StorageMode = Rw> {
pub _1w: StdDevPerBlock<M>,
pub _1m: StdDevPerBlock<M>,
pub _1y: StdDevPerBlock<M>,
}
#[derive(Traversable)]
pub struct Vecs<M: StorageMode = Rw> {
pub periods: ByLookbackPeriod<PercentPerBlock<BasisPointsSigned32, M>>,
pub cagr: ByDcaCagr<PercentPerBlock<BasisPointsSigned32, M>>,
pub sd_24h: PriceReturn24hSdVecs<M>,
pub sd_24h: Windows<StdDevPerBlock<M>>,
}

View File

@@ -22,54 +22,43 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
// Stochastic Oscillator: K = (close - low_2w) / (high_2w - low_2w), stored as ratio (0-1)
{
let price = &prices.spot.usd.height;
self.stoch_k.bps.height.compute_transform3(
starting_indexes.height,
price,
&range.min._2w.usd.height,
&range.max._2w.usd.height,
|(h, close, low, high, ..)| {
let range = *high - *low;
let stoch = if range == 0.0 {
BasisPoints16::ZERO
} else {
BasisPoints16::from((*close - *low) / range)
};
(h, stoch)
},
exit,
)?;
self.stoch_k.bps.height.compute_transform3(
starting_indexes.height,
&prices.spot.usd.height,
&range.min._2w.usd.height,
&range.max._2w.usd.height,
|(h, close, low, high, ..)| {
let range = *high - *low;
let stoch = if range == 0.0 {
BasisPoints16::ZERO
} else {
BasisPoints16::from((*close - *low) / range)
};
(h, stoch)
},
exit,
)?;
self.stoch_d.bps.height.compute_rolling_average(
starting_indexes.height,
&blocks.lookback._3d,
&self.stoch_k.bps.height,
exit,
)?;
}
self.stoch_d.bps.height.compute_rolling_average(
starting_indexes.height,
&blocks.lookback._3d,
&self.stoch_k.bps.height,
exit,
)?;
// RSI per timeframe
let return_sources = [
&returns.periods._24h.ratio.height,
&returns.periods._1w.ratio.height,
&returns.periods._1m.ratio.height,
&returns.periods._1y.ratio.height,
];
for (rsi_chain, ret) in self.rsi.as_mut_array().into_iter().zip(return_sources) {
let daily_returns = &returns.periods._24h.ratio.height;
for (rsi_chain, &m) in self.rsi.as_mut_array().into_iter().zip(&TF_MULTIPLIERS) {
rsi::compute(
rsi_chain,
blocks,
ret,
14,
3,
daily_returns,
14 * m,
3 * m,
starting_indexes,
exit,
)?;
}
// MACD per timeframe
for (macd_chain, &m) in self.macd.as_mut_array().into_iter().zip(&TF_MULTIPLIERS) {
macd::compute(
macd_chain,
@@ -83,7 +72,6 @@ impl Vecs {
)?;
}
// Pi Cycle: sma_111d / sma_350d_x2
self.pi_cycle
.bps
.compute_binary::<Dollars, Dollars, RatioDollarsBp32>(

View File

@@ -107,7 +107,7 @@ impl Vecs {
let v = version + VERSION;
let rsi =
Windows::try_from_fn(|tf| RsiChain::forced_import(db, tf, v + Version::ONE, indexes))?;
Windows::try_from_fn(|tf| RsiChain::forced_import(db, tf, v + Version::TWO, indexes))?;
let macd = Windows::try_from_fn(|tf| MacdChain::forced_import(db, tf, v, indexes))?;
let stoch_k = PercentPerBlock::forced_import(db, "stoch_k", v, indexes)?;

View File

@@ -4,48 +4,40 @@ use vecdb::ReadableCloneableVec;
use super::super::returns;
use super::Vecs;
use crate::internal::{Days30, Days365, Days7, LazyPerBlock, TimesSqrt};
use crate::internal::{Days1, Days7, Days30, Days365, LazyPerBlock, TimesSqrt, Windows};
impl Vecs {
pub(crate) fn forced_import(version: Version, returns: &returns::Vecs) -> Result<Self> {
let v2 = Version::TWO;
let _24h = LazyPerBlock::from_computed::<TimesSqrt<Days1>>(
"price_volatility_24h",
version + v2,
returns.sd_24h._24h.sd.height.read_only_boxed_clone(),
&returns.sd_24h._24h.sd,
);
let _1w = LazyPerBlock::from_computed::<TimesSqrt<Days7>>(
"price_volatility_1w",
version + v2,
returns
.sd_24h
._1w
.sd
.height
.read_only_boxed_clone(),
returns.sd_24h._1w.sd.height.read_only_boxed_clone(),
&returns.sd_24h._1w.sd,
);
let _1m = LazyPerBlock::from_computed::<TimesSqrt<Days30>>(
"price_volatility_1m",
version + v2,
returns
.sd_24h
._1m
.sd
.height
.read_only_boxed_clone(),
returns.sd_24h._1m.sd.height.read_only_boxed_clone(),
&returns.sd_24h._1m.sd,
);
let _1y = LazyPerBlock::from_computed::<TimesSqrt<Days365>>(
"price_volatility_1y",
version + v2,
returns
.sd_24h
._1y
.sd
.height
.read_only_boxed_clone(),
returns.sd_24h._1y.sd.height.read_only_boxed_clone(),
&returns.sd_24h._1y.sd,
);
Ok(Self { _1w, _1m, _1y })
Ok(Windows { _24h, _1w, _1m, _1y })
}
}

View File

@@ -1,11 +1,5 @@
use brk_traversable::Traversable;
use crate::internal::LazyPerBlock;
use brk_types::StoredF32;
#[derive(Clone, Traversable)]
pub struct Vecs {
pub _1w: LazyPerBlock<StoredF32>,
pub _1m: LazyPerBlock<StoredF32>,
pub _1y: LazyPerBlock<StoredF32>,
}
use crate::internal::{LazyPerBlock, Windows};
pub type Vecs = Windows<LazyPerBlock<StoredF32>>;

View File

@@ -18,8 +18,6 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
self.spent
.compute(&self.db, indexer, inputs, starting_indexes, exit)?;
self.count.compute(
indexer,
indexes,
@@ -29,8 +27,9 @@ impl Vecs {
starting_indexes,
exit,
)?;
let _lock = exit.lock();
let _lock = self
.spent
.compute(indexer, inputs, starting_indexes, exit)?;
self.db.compact()?;
Ok(())
}

View File

@@ -2,7 +2,7 @@ use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::{Height, Indexes, TxInIndex, TxOutIndex};
use tracing::info;
use vecdb::{AnyStoredVec, AnyVec, Database, Exit, ReadableVec, Stamp, VecIndex, WritableVec};
use vecdb::{AnyStoredVec, AnyVec, Exit, ExitGuard, ReadableVec, Stamp, VecIndex, WritableVec};
use super::Vecs;
use crate::inputs;
@@ -10,17 +10,16 @@ use crate::inputs;
const HEIGHT_BATCH: u32 = 10_000;
impl Vecs {
pub(crate) fn compute(
pub(crate) fn compute<'a>(
&mut self,
db: &Database,
indexer: &Indexer,
inputs: &inputs::Vecs,
starting_indexes: &Indexes,
exit: &Exit,
) -> Result<()> {
exit: &'a Exit,
) -> Result<ExitGuard<'a>> {
let target_height = indexer.vecs.blocks.blockhash.len();
if target_height == 0 {
return Ok(());
return Ok(exit.lock());
}
let target_height = Height::from(target_height - 1);
@@ -125,17 +124,15 @@ impl Vecs {
"TxOuts: {:.2}%",
batch_end_height.to_usize() as f64 / target_height.to_usize() as f64 * 100.0
);
db.flush()?;
}
batch_start_height = batch_end_height + 1_u32;
}
let _lock = exit.lock();
let lock = exit.lock();
self.txin_index
.stamped_write_with_changes(Stamp::from(target_height))?;
db.flush()?;
Ok(())
Ok(lock)
}
}

View File

@@ -128,16 +128,16 @@ impl Vecs {
if *block.height() % 1_000 == 0 {
let _lock = exit.lock();
self.block.flush()?;
self.tx.flush()?;
self.block.write()?;
self.tx.write()?;
}
Ok(())
})?;
let _lock = exit.lock();
self.block.flush()?;
self.tx.flush()?;
self.block.write()?;
self.tx.write()?;
Ok(())
}