global: wip

This commit is contained in:
nym21
2025-06-06 10:46:38 +02:00
parent d568469e8b
commit 1921c3d901
24 changed files with 2837 additions and 1277 deletions

3
.gitignore vendored
View File

@@ -35,3 +35,6 @@ _outputs
# Logs
.log
# Cloudflare
cloudflared

View File

@@ -1,9 +1,9 @@
use std::path::Path;
use brk_core::{Bitcoin, DateIndex, Dollars, Sats, Version};
use brk_core::{Bitcoin, DateIndex, Dollars, Result, Sats, Version};
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{AnyCollectableVec, CollectableVec, Format, StoredVec};
use brk_vec::{AnyCollectableVec, CollectableVec, EagerVec, Format, StoredVec};
use crate::vecs::{Indexes, fetched, grouped::ComputedVecsFromDateIndex, indexes};
@@ -59,37 +59,37 @@ impl ComputedValueVecsFromDateIndex {
})
}
// pub fn compute_all<F>(
// &mut self,
// indexer: &Indexer,
// indexes: &indexes::Vecs,
// fetched: Option<&fetched::Vecs>,
// starting_indexes: &Indexes,
// exit: &Exit,
// mut compute: F,
// ) -> color_eyre::Result<()>
// where
// F: FnMut(
// &mut EagerVec<DateIndex, Sats>,
// &Indexer,
// &indexes::Vecs,
// &Indexes,
// &Exit,
// ) -> Result<()>,
// {
// compute(
// self.sats.dateindex.as_mut().unwrap(),
// indexer,
// indexes,
// starting_indexes,
// exit,
// )?;
pub fn compute_all<F>(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
fetched: Option<&fetched::Vecs>,
starting_indexes: &Indexes,
exit: &Exit,
mut compute: F,
) -> color_eyre::Result<()>
where
F: FnMut(
&mut EagerVec<DateIndex, Sats>,
&Indexer,
&indexes::Vecs,
&Indexes,
&Exit,
) -> Result<()>,
{
compute(
self.sats.dateindex.as_mut().unwrap(),
indexer,
indexes,
starting_indexes,
exit,
)?;
// let dateindex: Option<&StoredVec<DateIndex, Sats>> = None;
// self.compute_rest(indexer, indexes, fetched, starting_indexes, exit, dateindex)?;
let dateindex: Option<&StoredVec<DateIndex, Sats>> = None;
self.compute_rest(indexer, indexes, fetched, starting_indexes, exit, dateindex)?;
// Ok(())
// }
Ok(())
}
pub fn compute_rest(
&mut self,

View File

@@ -1,10 +1,11 @@
use std::path::Path;
use brk_core::{Bitcoin, Dollars, Height, Sats, Version};
use brk_core::{Bitcoin, Dollars, Height, Result, Sats, Version};
use brk_exit::Exit;
use brk_vec::{AnyCollectableVec, CollectableVec, EagerVec, Format};
use brk_indexer::Indexer;
use brk_vec::{AnyCollectableVec, CollectableVec, EagerVec, Format, StoredVec};
use crate::vecs::{Indexes, fetched};
use crate::vecs::{Indexes, fetched, indexes};
#[derive(Clone)]
pub struct ComputedHeightValueVecs {
@@ -47,37 +48,37 @@ impl ComputedHeightValueVecs {
})
}
// pub fn compute_all<F>(
// &mut self,
// indexer: &Indexer,
// indexes: &indexes::Vecs,
// fetched: Option<&fetched::Vecs>,
// starting_indexes: &Indexes,
// exit: &Exit,
// mut compute: F,
// ) -> color_eyre::Result<()>
// where
// F: FnMut(
// &mut EagerVec<Height, Sats>,
// &Indexer,
// &indexes::Vecs,
// &Indexes,
// &Exit,
// ) -> Result<()>,
// {
// compute(
// self.sats.as_mut().unwrap(),
// indexer,
// indexes,
// starting_indexes,
// exit,
// )?;
pub fn compute_all<F>(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
fetched: Option<&fetched::Vecs>,
starting_indexes: &Indexes,
exit: &Exit,
mut compute: F,
) -> color_eyre::Result<()>
where
F: FnMut(
&mut EagerVec<Height, Sats>,
&Indexer,
&indexes::Vecs,
&Indexes,
&Exit,
) -> Result<()>,
{
compute(
self.sats.as_mut().unwrap(),
indexer,
indexes,
starting_indexes,
exit,
)?;
// let height: Option<&StoredVec<Height, Sats>> = None;
// self.compute_rest(fetched, starting_indexes, exit, height)?;
let height: Option<&StoredVec<Height, Sats>> = None;
self.compute_rest(fetched, starting_indexes, exit, height)?;
// Ok(())
// }
Ok(())
}
pub fn compute_rest(
&mut self,

View File

@@ -1,7 +1,8 @@
use core::panic;
use std::{fs, path::Path};
use brk_core::{
DateIndex, Dollars, Height, Result, Sats, StoredF32, StoredF64, StoredUsize, Version,
Bitcoin, DateIndex, Dollars, Height, Result, Sats, StoredF32, StoredF64, StoredUsize, Version,
};
use brk_exit::Exit;
use brk_indexer::Indexer;
@@ -16,8 +17,7 @@ use crate::vecs::{
Indexes, fetched,
grouped::{
ComputedHeightValueVecs, ComputedRatioVecsFromDateIndex, ComputedValueVecsFromDateIndex,
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight,
StorableVecGeneatorOptions,
ComputedVecsFromDateIndex, ComputedVecsFromHeight, StorableVecGeneatorOptions,
},
indexes, market,
};
@@ -52,7 +52,11 @@ pub struct Vecs {
pub height_to_unrealized_profit: Option<EagerVec<Height, Dollars>>,
pub height_to_value_created: Option<EagerVec<Height, Dollars>>,
pub height_to_value_destroyed: Option<EagerVec<Height, Dollars>>,
pub height_to_satblocks_destroyed: EagerVec<Height, Sats>,
pub height_to_satdays_destroyed: EagerVec<Height, Sats>,
pub indexes_to_coinblocks_destroyed: ComputedVecsFromHeight<Bitcoin>,
pub indexes_to_coindays_destroyed: ComputedVecsFromHeight<Bitcoin>,
pub dateindex_to_adjusted_spent_output_profit_ratio: Option<EagerVec<DateIndex, StoredF32>>,
pub dateindex_to_realized_cap_30d_change: Option<EagerVec<DateIndex, Dollars>>,
pub dateindex_to_sell_side_risk_ratio: Option<EagerVec<DateIndex, StoredF32>>,
@@ -67,7 +71,8 @@ pub struct Vecs {
pub indexes_to_realized_price_extra: Option<ComputedRatioVecsFromDateIndex>,
pub indexes_to_realized_profit: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_realized_value: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_supply: ComputedValueVecsFromHeight,
pub height_to_supply_value: ComputedHeightValueVecs,
pub indexes_to_supply: ComputedValueVecsFromDateIndex,
pub indexes_to_utxo_count: ComputedVecsFromHeight<StoredUsize>,
pub indexes_to_value_created: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_value_destroyed: Option<ComputedVecsFromHeight<Dollars>>,
@@ -75,7 +80,8 @@ pub struct Vecs {
pub indexes_to_unrealized_loss: Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_min_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_max_price_paid: Option<ComputedVecsFromHeight<Dollars>>,
pub indexes_to_halved_supply: ComputedValueVecsFromHeight,
pub height_to_halved_supply_value: ComputedHeightValueVecs,
pub indexes_to_halved_supply: ComputedValueVecsFromDateIndex,
pub height_to_negative_unrealized_loss: Option<EagerVec<Height, Dollars>>,
pub indexes_to_negative_unrealized_loss: Option<ComputedVecsFromDateIndex<Dollars>>,
pub height_to_net_unrealized_profit_and_loss: Option<EagerVec<Height, Dollars>>,
@@ -139,7 +145,7 @@ impl Vecs {
keyspace,
stores_path,
cohort_name.unwrap_or_default(),
version,
version + VERSION + Version::ZERO,
compute_dollars,
)?;
@@ -361,12 +367,20 @@ impl Vecs {
version + VERSION + Version::ZERO,
format,
)?,
indexes_to_supply: ComputedValueVecsFromHeight::forced_import(
height_to_supply_value: ComputedHeightValueVecs::forced_import(
path,
&suffix("supply"),
false,
version + VERSION + Version::ZERO,
format,
compute_dollars,
)?,
indexes_to_supply: ComputedValueVecsFromDateIndex::forced_import(
path,
&suffix("supply"),
true,
version + VERSION + Version::ONE,
format,
StorableVecGeneatorOptions::default().add_last(),
compute_dollars,
)?,
@@ -595,7 +609,15 @@ impl Vecs {
)
.unwrap()
}),
indexes_to_halved_supply: ComputedValueVecsFromHeight::forced_import(
height_to_halved_supply_value: ComputedHeightValueVecs::forced_import(
path,
&suffix("halved_supply"),
true,
version + VERSION + Version::ZERO,
format,
compute_dollars,
)?,
indexes_to_halved_supply: ComputedValueVecsFromDateIndex::forced_import(
path,
&suffix("halved_supply"),
true,
@@ -604,7 +626,6 @@ impl Vecs {
StorableVecGeneatorOptions::default().add_last(),
compute_dollars,
)?,
height_to_negative_unrealized_loss: compute_dollars.then(|| {
EagerVec::forced_import(
path,
@@ -687,7 +708,7 @@ impl Vecs {
path,
&suffix("supply_even"),
false,
version,
version + VERSION + Version::ZERO,
format,
compute_dollars,
)
@@ -698,7 +719,7 @@ impl Vecs {
path,
&suffix("supply_in_loss"),
false,
version,
version + VERSION + Version::ZERO,
format,
compute_dollars,
)
@@ -709,7 +730,7 @@ impl Vecs {
path,
&suffix("supply_in_profit"),
false,
version,
version + VERSION + Version::ZERO,
format,
compute_dollars,
)
@@ -719,7 +740,7 @@ impl Vecs {
EagerVec::forced_import(
path,
&suffix("supply_even_relative_to_own_supply"),
version,
version + VERSION + Version::ZERO,
format,
)
.unwrap()
@@ -728,7 +749,7 @@ impl Vecs {
EagerVec::forced_import(
path,
&suffix("supply_in_loss_relative_to_own_supply"),
version,
version + VERSION + Version::ZERO,
format,
)
.unwrap()
@@ -737,7 +758,7 @@ impl Vecs {
EagerVec::forced_import(
path,
&suffix("supply_in_profit_relative_to_own_supply"),
version,
version + VERSION + Version::ZERO,
format,
)
.unwrap()
@@ -747,7 +768,7 @@ impl Vecs {
path,
&suffix("supply_even_relative_to_own_supply"),
true,
version,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_last(),
)
@@ -758,7 +779,7 @@ impl Vecs {
path,
&suffix("supply_in_loss_relative_to_own_supply"),
true,
version,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_last(),
)
@@ -769,7 +790,7 @@ impl Vecs {
path,
&suffix("supply_in_profit_relative_to_own_supply"),
true,
version,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_last(),
)
@@ -780,7 +801,7 @@ impl Vecs {
path,
&suffix("supply_relative_to_circulating_supply"),
true,
version,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_last(),
)
@@ -792,7 +813,7 @@ impl Vecs {
EagerVec::forced_import(
path,
&suffix("supply_even_relative_to_circulating_supply"),
version,
version + VERSION + Version::ZERO,
format,
)
.unwrap()
@@ -803,7 +824,7 @@ impl Vecs {
EagerVec::forced_import(
path,
&suffix("supply_in_loss_relative_to_circulating_supply"),
version,
version + VERSION + Version::ZERO,
format,
)
.unwrap()
@@ -814,7 +835,7 @@ impl Vecs {
EagerVec::forced_import(
path,
&suffix("supply_in_profit_relative_to_circulating_supply"),
version,
version + VERSION + Version::ZERO,
format,
)
.unwrap()
@@ -826,7 +847,7 @@ impl Vecs {
path,
&suffix("supply_even_relative_to_circulating_supply"),
true,
version,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_last(),
)
@@ -839,7 +860,7 @@ impl Vecs {
path,
&suffix("supply_in_loss_relative_to_circulating_supply"),
true,
version,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_last(),
)
@@ -852,12 +873,44 @@ impl Vecs {
path,
&suffix("supply_in_profit_relative_to_circulating_supply"),
true,
version,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_last(),
)
.unwrap()
}),
height_to_satblocks_destroyed: EagerVec::forced_import(
path,
&suffix("satblocks_destroyed"),
version + VERSION + Version::ZERO,
format,
)?,
height_to_satdays_destroyed: EagerVec::forced_import(
path,
&suffix("satdays_destroyed"),
version + VERSION + Version::ZERO,
format,
)?,
indexes_to_coinblocks_destroyed: ComputedVecsFromHeight::forced_import(
path,
&suffix("coinblocks_destroyed"),
true,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default()
.add_sum()
.add_cumulative(),
)?,
indexes_to_coindays_destroyed: ComputedVecsFromHeight::forced_import(
path,
&suffix("coindays_destroyed"),
true,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default()
.add_sum()
.add_cumulative(),
)?,
})
}
@@ -911,6 +964,8 @@ impl Vecs {
self.height_to_max_price_paid
.as_ref()
.map_or(usize::MAX, |v| v.len()),
self.height_to_satdays_destroyed.len(),
self.height_to_satblocks_destroyed.len(),
]
.into_iter()
.map(Height::from)
@@ -956,6 +1011,16 @@ impl Vecs {
base_version + self.height_to_utxo_count.inner_version(),
)?;
self.height_to_satblocks_destroyed
.validate_computed_version_or_reset_file(
base_version + self.height_to_satblocks_destroyed.inner_version(),
)?;
self.height_to_satdays_destroyed
.validate_computed_version_or_reset_file(
base_version + self.height_to_satdays_destroyed.inner_version(),
)?;
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut().as_mut() {
height_to_realized_cap.validate_computed_version_or_reset_file(
base_version + height_to_realized_cap.inner_version(),
@@ -1175,6 +1240,18 @@ impl Vecs {
exit,
)?;
self.height_to_satblocks_destroyed.forced_push_at(
height,
self.state.satblocks_destroyed,
exit,
)?;
self.height_to_satdays_destroyed.forced_push_at(
height,
self.state.satdays_destroyed,
exit,
)?;
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
let realized = self.state.realized.as_ref().unwrap_or_else(|| {
dbg!((&self.state.realized, &self.state.supply));
@@ -1301,8 +1378,9 @@ impl Vecs {
pub fn safe_flush_stateful_vecs(&mut self, height: Height, exit: &Exit) -> Result<()> {
self.height_to_supply.safe_flush(exit)?;
self.height_to_utxo_count.safe_flush(exit)?;
self.height_to_satdays_destroyed.safe_flush(exit)?;
self.height_to_satblocks_destroyed.safe_flush(exit)?;
if let Some(height_to_realized_cap) = self.height_to_realized_cap.as_mut() {
height_to_realized_cap.safe_flush(exit)?;
@@ -1409,6 +1487,24 @@ impl Vecs {
.as_slice(),
exit,
)?;
self.height_to_satblocks_destroyed.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| &v.height_to_satblocks_destroyed)
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
self.height_to_satdays_destroyed.compute_sum_of_others(
starting_indexes.height,
others
.iter()
.map(|v| &v.height_to_satdays_destroyed)
.collect::<Vec<_>>()
.as_slice(),
exit,
)?;
if let Some(height_to_realized_cap) = &mut self.height_to_realized_cap {
height_to_realized_cap.compute_sum_of_others(
@@ -1675,13 +1771,37 @@ impl Vecs {
starting_indexes: &Indexes,
exit: &Exit,
) -> color_eyre::Result<()> {
self.indexes_to_supply.compute_rest(
self.height_to_supply_value.compute_rest(
fetched,
starting_indexes,
exit,
Some(&self.height_to_supply),
)?;
self.indexes_to_supply.compute_all(
indexer,
indexes,
fetched,
starting_indexes,
exit,
Some(&self.height_to_supply),
|v, _, indexes, starting_indexes, exit| {
let mut dateindex_to_height_count_iter =
indexes.dateindex_to_height_count.into_iter();
let mut height_to_supply_iter = self.height_to_supply.into_iter();
v.compute_transform(
starting_indexes.dateindex,
&indexes.dateindex_to_first_height,
|(i, height, ..)| {
let count = dateindex_to_height_count_iter.unwrap_get_inner(i);
if count == StoredUsize::default() {
unreachable!()
}
let supply = height_to_supply_iter.unwrap_get_inner(height + (*count - 1));
(i, supply)
},
exit,
)
},
)?;
self.indexes_to_utxo_count.compute_rest(
@@ -1691,6 +1811,22 @@ impl Vecs {
Some(&self.height_to_utxo_count),
)?;
self.height_to_halved_supply_value.compute_all(
indexer,
indexes,
fetched,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_transform(
starting_indexes.height,
&self.height_to_supply,
|(h, v, ..)| (h, v / 2),
exit,
)
},
)?;
self.indexes_to_halved_supply.compute_all(
indexer,
indexes,
@@ -1699,9 +1835,37 @@ impl Vecs {
exit,
|v, _, _, starting_indexes, exit| {
v.compute_transform(
starting_indexes.dateindex,
self.indexes_to_supply.sats.dateindex.as_ref().unwrap(),
|(i, sats, ..)| (i, sats / 2),
exit,
)
},
)?;
self.indexes_to_coinblocks_destroyed.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_from_sats(
starting_indexes.height,
&self.height_to_supply,
|(h, sats, ..)| (h, sats / 2),
&self.height_to_satblocks_destroyed,
exit,
)
},
)?;
self.indexes_to_coindays_destroyed.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_from_sats(
starting_indexes.height,
&self.height_to_satdays_destroyed,
exit,
)
},
@@ -1718,8 +1882,8 @@ impl Vecs {
fetched: Option<&fetched::Vecs>,
starting_indexes: &Indexes,
market: &market::Vecs,
height_to_supply: &impl AnyIterableVec<Height, Sats>,
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Sats>,
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
exit: &Exit,
) -> color_eyre::Result<()> {
@@ -1735,7 +1899,7 @@ impl Vecs {
|v, _, _, starting_indexes, exit| {
v.compute_percentage(
starting_indexes.height,
&self.height_to_supply,
&self.height_to_supply_value.bitcoin,
height_to_supply,
exit,
)
@@ -1763,7 +1927,7 @@ impl Vecs {
vec.compute_divide(
starting_indexes.height,
self.height_to_realized_cap.as_ref().unwrap(),
self.indexes_to_supply.bitcoin.height.as_ref().unwrap(),
&self.height_to_supply_value.bitcoin,
exit,
)
},
@@ -2213,7 +2377,7 @@ impl Vecs {
v.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_supply_even.as_ref().unwrap(),
self.indexes_to_supply.sats.dateindex.unwrap_last(),
self.indexes_to_supply.sats.dateindex.as_ref().unwrap(),
exit,
)
},
@@ -2230,7 +2394,7 @@ impl Vecs {
v.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_supply_even.as_ref().unwrap(),
self.indexes_to_supply.sats.dateindex.unwrap_last(),
self.indexes_to_supply.sats.dateindex.as_ref().unwrap(),
exit,
)
},
@@ -2247,7 +2411,7 @@ impl Vecs {
v.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_supply_even.as_ref().unwrap(),
self.indexes_to_supply.sats.dateindex.unwrap_last(),
self.indexes_to_supply.sats.dateindex.as_ref().unwrap(),
exit,
)
},
@@ -2259,7 +2423,7 @@ impl Vecs {
{
height_to_supply_even_relative_to_circulating_supply.compute_percentage(
starting_indexes.height,
self.height_to_supply_even.as_ref().unwrap(),
&self.height_to_supply_even_value.as_ref().unwrap().bitcoin,
height_to_supply,
exit,
)?;
@@ -2268,7 +2432,11 @@ impl Vecs {
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_supply_in_loss.as_ref().unwrap(),
&self
.height_to_supply_in_loss_value
.as_ref()
.unwrap()
.bitcoin,
height_to_supply,
exit,
)?;
@@ -2277,7 +2445,11 @@ impl Vecs {
.unwrap()
.compute_percentage(
starting_indexes.height,
self.height_to_supply_in_profit.as_ref().unwrap(),
&self
.height_to_supply_in_profit_value
.as_ref()
.unwrap()
.bitcoin,
height_to_supply,
exit,
)?;
@@ -2292,7 +2464,13 @@ impl Vecs {
|v, _, _, starting_indexes, exit| {
v.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_supply_even.as_ref().unwrap(),
self.indexes_to_supply_even
.as_ref()
.unwrap()
.bitcoin
.dateindex
.as_ref()
.unwrap(),
dateindex_to_supply,
exit,
)
@@ -2309,7 +2487,13 @@ impl Vecs {
|v, _, _, starting_indexes, exit| {
v.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_supply_in_loss.as_ref().unwrap(),
self.indexes_to_supply_in_loss
.as_ref()
.unwrap()
.bitcoin
.dateindex
.as_ref()
.unwrap(),
dateindex_to_supply,
exit,
)
@@ -2326,7 +2510,13 @@ impl Vecs {
|v, _, _, starting_indexes, exit| {
v.compute_percentage(
starting_indexes.dateindex,
self.dateindex_to_supply_in_profit.as_ref().unwrap(),
self.indexes_to_supply_in_profit
.as_ref()
.unwrap()
.bitcoin
.dateindex
.as_ref()
.unwrap(),
dateindex_to_supply,
exit,
)
@@ -2343,10 +2533,14 @@ impl Vecs {
vec![
&self.height_to_supply as &dyn AnyCollectableVec,
&self.height_to_utxo_count,
&self.height_to_satblocks_destroyed,
&self.height_to_satdays_destroyed,
],
self.height_to_realized_cap
.as_ref()
.map_or(vec![], |v| vec![v as &dyn AnyCollectableVec]),
self.height_to_supply_value.vecs(),
self.height_to_halved_supply_value.vecs(),
self.indexes_to_supply.vecs(),
self.indexes_to_utxo_count.vecs(),
self.indexes_to_realized_cap
@@ -2542,6 +2736,8 @@ impl Vecs {
self.indexes_to_supply_in_profit_relative_to_circulating_supply
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_coinblocks_destroyed.vecs(),
self.indexes_to_coindays_destroyed.vecs(),
]
.into_iter()
.flatten()

View File

@@ -29,7 +29,7 @@ use super::{
pub mod cohort;
mod outputs;
const VERSION: Version = Version::new(9);
const VERSION: Version = Version::new(5);
#[derive(Clone)]
pub struct Vecs {
@@ -40,10 +40,6 @@ pub struct Vecs {
pub indexes_to_unspendable_supply: ComputedValueVecsFromHeight,
pub height_to_opreturn_supply: EagerVec<Height, Sats>,
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
// pub height_to_satdays_destroyed: EagerVec<Height, Sats>,
// pub indexes_to_satdays_destroyed: ComputedValueVecsFromHeight,
// pub height_to_satblocks_destroyed: EagerVec<Height, Sats>,
// pub indexes_to_satblocks_destroyed: ComputedValueVecsFromHeight,
utxos_vecs: Outputs<(OutputFilter, cohort::Vecs)>,
}
@@ -102,36 +98,6 @@ impl Vecs {
StorableVecGeneatorOptions::default().add_last(),
compute_dollars,
)?,
// height_to_satdays_destroyed: EagerVec::forced_import(
// path,
// "satdays_destroyed",
// version,
// format,
// )?,
// indexes_to_satdays_destroyed: ComputedValueVecsFromHeight::forced_import(
// path,
// "satdays_destroyed",
// false,
// version + VERSION + Version::ZERO,
// format,
// StorableVecGeneatorOptions::default().add_last(),
// compute_dollars,
// )?,
// height_to_satblocks_destroyed: EagerVec::forced_import(
// path,
// "satblocks_destroyed",
// version,
// format,
// )?,
// indexes_to_satblocks_destroyed: ComputedValueVecsFromHeight::forced_import(
// path,
// "satblocks_destroyed",
// false,
// version + VERSION + Version::ZERO,
// format,
// StorableVecGeneatorOptions::default().add_last(),
// compute_dollars,
// )?,
utxos_vecs: {
Outputs::<(OutputFilter, cohort::Vecs)>::from(Outputs {
all: cohort::Vecs::forced_import(
@@ -603,9 +569,9 @@ impl Vecs {
&stores_path,
true,
)?,
_1m_to_3m: cohort::Vecs::forced_import(
_1m_to_2m: cohort::Vecs::forced_import(
path,
Some("from_1m_to_3m"),
Some("from_1m_to_2m"),
_computation,
format,
version + VERSION + Version::ZERO,
@@ -614,9 +580,42 @@ impl Vecs {
&stores_path,
true,
)?,
_3m_to_6m: cohort::Vecs::forced_import(
_2m_to_3m: cohort::Vecs::forced_import(
path,
Some("from_3m_to_6m"),
Some("from_2m_to_3m"),
_computation,
format,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
true,
)?,
_3m_to_4m: cohort::Vecs::forced_import(
path,
Some("from_3m_to_4m"),
_computation,
format,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
true,
)?,
_4m_to_5m: cohort::Vecs::forced_import(
path,
Some("from_4m_to_5m"),
_computation,
format,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
true,
)?,
_5m_to_6m: cohort::Vecs::forced_import(
path,
Some("from_5m_to_6m"),
_computation,
format,
version + VERSION + Version::ZERO,
@@ -680,9 +679,9 @@ impl Vecs {
&stores_path,
true,
)?,
_5y_to_7y: cohort::Vecs::forced_import(
_5y_to_6y: cohort::Vecs::forced_import(
path,
Some("from_5y_to_7y"),
Some("from_5y_to_6y"),
_computation,
format,
version + VERSION + Version::ZERO,
@@ -691,9 +690,31 @@ impl Vecs {
&stores_path,
true,
)?,
_7y_to_10y: cohort::Vecs::forced_import(
_6y_to_7y: cohort::Vecs::forced_import(
path,
Some("from_7y_to_10y"),
Some("from_6y_to_7y"),
_computation,
format,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
true,
)?,
_7y_to_8y: cohort::Vecs::forced_import(
path,
Some("from_7y_to_8y"),
_computation,
format,
version + VERSION + Version::ZERO,
fetched,
keyspace,
&stores_path,
true,
)?,
_8y_to_10y: cohort::Vecs::forced_import(
path,
Some("from_8y_to_10y"),
_computation,
format,
version + VERSION + Version::ZERO,
@@ -1377,14 +1398,6 @@ impl Vecs {
.validate_computed_version_or_reset_file(
base_version + self.height_to_opreturn_supply.inner_version(),
)?;
// self.height_to_satblocks_destroyed
// .validate_computed_version_or_reset_file(
// base_version + self.height_to_satblocks_destroyed.inner_version(),
// )?;
// self.height_to_satdays_destroyed
// .validate_computed_version_or_reset_file(
// base_version + self.height_to_satdays_destroyed.inner_version(),
// )?;
let mut chain_state: Vec<BlockState>;
let mut chain_state_starting_height = Height::from(self.chain_state.len());
@@ -1437,8 +1450,6 @@ impl Vecs {
.min(stateful_starting_height)
.min(Height::from(self.height_to_unspendable_supply.len()))
.min(Height::from(self.height_to_opreturn_supply.len()));
// .min(Height::from(self.height_to_satblocks_destroyed.len()));
// .min(Height::from(self.height_to_satdays_destroyed.len()));
// ---
// INIT
@@ -1462,20 +1473,6 @@ impl Vecs {
} else {
Sats::ZERO
};
// let mut satblocks_destroyed = if let Some(prev_height) = starting_height.decremented() {
// self.height_to_satblocks_destroyed
// .into_iter()
// .unwrap_get_inner(prev_height)
// } else {
// Sats::ZERO
// };
// let mut satdays_destroyed = if let Some(prev_height) = starting_height.decremented() {
// self.height_to_satdays_destroyed
// .into_iter()
// .unwrap_get_inner(prev_height)
// } else {
// Sats::ZERO
// };
let mut height = starting_height;
starting_indexes.update_from_height(height, indexes);
@@ -1717,18 +1714,16 @@ impl Vecs {
.try_for_each(|(_, v)| {
v.compute_rest_part1(indexer, indexes, fetched, &starting_indexes, exit)
})?;
let height_to_supply = self.utxos_vecs.all.1.height_to_supply.clone();
let height_to_supply = self.utxos_vecs.all.1.height_to_supply_value.bitcoin.clone();
let dateindex_to_supply = self
.utxos_vecs
.all
.1
.indexes_to_supply
.sats
.bitcoin
.dateindex
.unwrap_last()
.clone();
let height_to_realized_cap = self.utxos_vecs.all.1.height_to_realized_cap.clone();
let height_to_realized_cap = height_to_realized_cap.as_ref();
self.utxos_vecs
.as_mut_vecs()
.par_iter_mut()
@@ -1740,8 +1735,8 @@ impl Vecs {
&starting_indexes,
market,
&height_to_supply,
&dateindex_to_supply,
height_to_realized_cap,
dateindex_to_supply.as_ref().unwrap(),
height_to_realized_cap.as_ref(),
exit,
)
})?;
@@ -1761,22 +1756,6 @@ impl Vecs {
exit,
Some(&self.height_to_opreturn_supply),
)?;
// self.indexes_to_satblocks_destroyed.compute_rest(
// indexer,
// indexes,
// fetched,
// &starting_indexes,
// exit,
// Some(&self.height_to_satblocks_destroyed),
// )?;
// self.indexes_to_satdays_destroyed.compute_rest(
// indexer,
// indexes,
// fetched,
// &starting_indexes,
// exit,
// Some(&self.height_to_satdays_destroyed),
// )?;
exit.release();
@@ -1795,8 +1774,6 @@ impl Vecs {
.try_for_each(|(_, v)| v.safe_flush_stateful_vecs(height, exit))?;
self.height_to_unspendable_supply.safe_flush(exit)?;
self.height_to_opreturn_supply.safe_flush(exit)?;
// self.height_to_satblocks_destroyed.safe_flush(exit)?;
// self.height_to_satdays_destroyed.safe_flush(exit)?;
self.chain_state.truncate_if_needed(Height::ZERO)?;
chain_state.iter().for_each(|block_state| {
@@ -1820,16 +1797,6 @@ impl Vecs {
&self.height_to_unspendable_supply,
&self.height_to_opreturn_supply,
],
// self.indexes_to_satblocks_destroyed.vecs(),
// vec![
// &self.height_to_unspendable_supply,
// &self.height_to_satblocks_destroyed,
// ],
// self.indexes_to_satdays_destroyed.vecs(),
// vec![
// &self.height_to_unspendable_supply,
// &self.height_to_satdays_destroyed,
// ],
]
.into_iter()
.flatten()

View File

@@ -72,10 +72,16 @@ impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
let block_state = chain_state.get(height.unwrap_to_usize()).unwrap();
let prev_price = block_state.price;
let blocks_old = chain_state.len() - 1 - height.unwrap_to_usize();
let days_old = block_state
.timestamp
.difference_in_days_between(last_timestamp);
let days_old_foat = block_state
.timestamp
.difference_in_days_between_float(last_timestamp);
let older_than_hour =
jiff::Timestamp::from(last_timestamp.checked_sub(block_state.timestamp).unwrap())
.as_second()
@@ -95,6 +101,8 @@ impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
&sent.spendable_supply,
current_price,
prev_price,
blocks_old,
days_old_foat,
older_than_hour,
);
});
@@ -105,6 +113,8 @@ impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
supply_state,
current_price,
prev_price,
blocks_old,
days_old_foat,
older_than_hour,
)
},
@@ -117,6 +127,8 @@ impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
&supply_state,
current_price,
prev_price,
blocks_old,
days_old_foat,
older_than_hour,
);
});
@@ -159,93 +171,86 @@ impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
}
fn compute_overlaping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
self.all
.1
.compute_from_stateful(starting_indexes, &self.by_epoch.vecs(), exit)?;
let by_date_range = self.by_date_range.as_vec();
let by_size_range = self.by_size_range.as_vec();
self.by_from_date
.as_mut_vec()
.into_iter()
.try_for_each(|(filter, vecs)| {
vecs.compute_from_stateful(
starting_indexes,
self.by_date_range
.as_vec()
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>()
.as_slice(),
exit,
)
})?;
self.by_up_to_date
.as_mut_vec()
.into_iter()
.try_for_each(|(filter, vecs)| {
vecs.compute_from_stateful(
starting_indexes,
self.by_date_range
.as_vec()
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>()
.as_slice(),
exit,
)
})?;
self.by_term
.as_mut_vec()
.into_iter()
.try_for_each(|(filter, vecs)| {
vecs.compute_from_stateful(
starting_indexes,
self.by_date_range
.as_vec()
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>()
.as_slice(),
exit,
)
})?;
self.by_up_to_size
.as_mut_vec()
.into_iter()
.try_for_each(|(filter, vecs)| {
vecs.compute_from_stateful(
starting_indexes,
self.by_date_range
.as_vec()
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>()
.as_slice(),
exit,
)
})?;
self.by_from_size
.as_mut_vec()
.into_iter()
.try_for_each(|(filter, vecs)| {
vecs.compute_from_stateful(
starting_indexes,
self.by_size_range
.as_vec()
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>()
.as_slice(),
exit,
)
})
[
vec![(&mut self.all.1, self.by_epoch.vecs().to_vec())],
self.by_from_date
.as_mut_vec()
.into_iter()
.map(|(filter, vecs)| {
(
vecs,
by_date_range
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>(),
self.by_up_to_date
.as_mut_vec()
.into_iter()
.map(|(filter, vecs)| {
(
vecs,
by_date_range
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>(),
self.by_term
.as_mut_vec()
.into_iter()
.map(|(filter, vecs)| {
(
vecs,
by_date_range
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>(),
self.by_from_size
.as_mut_vec()
.into_iter()
.map(|(filter, vecs)| {
(
vecs,
by_size_range
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>(),
self.by_up_to_size
.as_mut_vec()
.into_iter()
.map(|(filter, vecs)| {
(
vecs,
by_size_range
.into_iter()
.filter(|(other, _)| filter.includes(other))
.map(|(_, v)| v)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>(),
]
.into_par_iter()
.flatten()
.try_for_each(|(vecs, stateful)| {
vecs.compute_from_stateful(starting_indexes, &stateful, exit)
})
}
}

View File

@@ -6,6 +6,8 @@ use std::{
use serde::Serialize;
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::CheckedSub;
use super::{Sats, StoredF64};
#[derive(Debug, Default, Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize)]
@@ -25,6 +27,20 @@ impl Mul for Bitcoin {
}
}
impl Mul<usize> for Bitcoin {
type Output = Self;
fn mul(self, rhs: usize) -> Self::Output {
Self::from(Sats::from(self) * rhs)
}
}
impl Div<Bitcoin> for Bitcoin {
type Output = Self;
fn div(self, rhs: Bitcoin) -> Self::Output {
Self::from(Sats::from(self) / Sats::from(rhs))
}
}
impl Div<usize> for Bitcoin {
type Output = Self;
fn div(self, rhs: usize) -> Self::Output {
@@ -93,3 +109,9 @@ impl Ord for Bitcoin {
}
}
}
impl CheckedSub<usize> for Bitcoin {
fn checked_sub(self, rhs: usize) -> Option<Self> {
Some(Self(self.0 - rhs as f64))
}
}

View File

@@ -7,7 +7,7 @@ use derive_deref::Deref;
use serde::Serialize;
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
use crate::{CheckedSub, Sats};
use crate::{Bitcoin, CheckedSub, Sats};
#[derive(
Debug, Deref, Default, Clone, Copy, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize,
@@ -102,3 +102,9 @@ impl From<Sats> for StoredF64 {
Self(u64::from(value) as f64)
}
}
impl From<Bitcoin> for StoredF64 {
fn from(value: Bitcoin) -> Self {
Self(f64::from(value))
}
}

View File

@@ -62,6 +62,19 @@ impl Timestamp {
}
}
}
pub fn difference_in_days_between_float(&self, other: Self) -> f64 {
match self.cmp(&other) {
Ordering::Equal => 0.0,
Ordering::Greater => other.difference_in_days_between_float(*self),
Ordering::Less => {
jiff::Timestamp::from(*self)
.duration_until(jiff::Timestamp::from(other))
.as_secs() as f64
/ ONE_DAY_IN_SEC as f64
}
}
}
}
impl From<u32> for Timestamp {

View File

@@ -8,11 +8,11 @@ fn main() -> color_eyre::Result<()> {
let mut fetcher = Fetcher::import(None)?;
dbg!(fetcher.get_date(Date::new(2025, 1, 1))?);
dbg!(fetcher.get_date(Date::new(2025, 6, 5))?);
dbg!(fetcher.get_height(
881_000_u32.into(),
1740683986_u32.into(),
Some(1740683000_u32.into())
899911_u32.into(),
1749133056_u32.into(),
Some(1749132055_u32.into())
)?);
Ok(())

View File

@@ -95,7 +95,7 @@ impl Binance {
}
pub fn fetch_1d() -> color_eyre::Result<BTreeMap<Date, OHLCCents>> {
info!("Fetching daily prices from Kraken...");
info!("Fetching daily prices from Binance...");
retry(
|_| Self::json_to_date_to_ohlc(&minreq::get(Self::url("interval=1d")).send()?.json()?),

View File

@@ -1,9 +1,9 @@
mod binance;
mod kibo;
mod kraken;
// mod kraken;
mod retry;
pub use binance::*;
pub use kibo::*;
pub use kraken::*;
// pub use kraken::*;
use retry::*;

View File

@@ -18,7 +18,7 @@ const TRIES: usize = 12 * 60 * 2;
#[derive(Clone)]
pub struct Fetcher {
binance: Binance,
kraken: Kraken,
// kraken: Kraken,
kibo: Kibo,
}
@@ -30,7 +30,7 @@ impl Fetcher {
Ok(Self {
binance: Binance::init(hars_path),
kraken: Kraken::default(),
// kraken: Kraken::default(),
kibo: Kibo::default(),
})
}
@@ -40,12 +40,8 @@ impl Fetcher {
}
fn get_date_(&mut self, date: Date, tries: usize) -> color_eyre::Result<OHLCCents> {
self.kraken
self.binance
.get_from_1d(&date)
.or_else(|_| {
// eprintln!("{e}");
self.binance.get_from_1d(&date)
})
.or_else(|_| {
// eprintln!("{e}");
self.kibo.get_from_date(&date)
@@ -89,33 +85,36 @@ impl Fetcher {
let previous_timestamp = previous_timestamp.map(|t| t.floor_seconds());
let ohlc = self
.kraken
.binance
.get_from_1mn(timestamp, previous_timestamp)
.unwrap_or_else(|_| {
// eprintln!("{e}");
self.binance
.get_from_1mn(timestamp, previous_timestamp)
.unwrap_or_else(|_| {
// eprintln!("{e}");
self.kibo.get_from_height(height).unwrap_or_else(|_| {
sleep(Duration::from_secs(30));
.unwrap_or_else(|_report| {
// eprintln!("{_report}");
// self.kraken
// .get_from_1mn(timestamp, previous_timestamp)
// .unwrap_or_else(|_report| {
// // eprintln!("{_report}");
self.kibo.get_from_height(height).unwrap_or_else(|_report| {
// eprintln!("{_report}");
if tries < TRIES {
self.clear();
sleep(Duration::from_secs(30));
info!("Retrying to fetch height prices...");
if tries < TRIES {
self.clear();
return self
.get_height_(height, timestamp, previous_timestamp, tries + 1)
.unwrap();
}
info!("Retrying to fetch height prices...");
// dbg!((height, timestamp, previous_timestamp));
info!("Failed to fetch height prices");
return self
.get_height_(height, timestamp, previous_timestamp, tries + 1)
.unwrap();
}
let date = Date::from(timestamp);
// eprintln!("{e}");
panic!(
"
info!("Failed to fetch height prices");
let date = Date::from(timestamp);
// eprintln!("{e}");
panic!(
"
Can't find the price for: height: {height} - date: {date}
1mn APIs are limited to the last 16 hours for Binance's and the last 10 hours for Kraken's
How to fix this:
@@ -130,9 +129,9 @@ How to fix this:
8. Export to a har file (if there is no explicit button, click on the cog button)
9. Move the file to 'parser/imports/binance.har'
"
)
})
})
)
})
// })
});
Ok(ohlc)
@@ -183,6 +182,6 @@ How to fix this:
pub fn clear(&mut self) {
self.binance.clear();
self.kibo.clear();
self.kraken.clear();
// self.kraken.clear();
}
}

View File

@@ -24,6 +24,7 @@ impl<'a> VecTrees<'a> {
|| s.ends_with("relative")
|| s.starts_with("from")
|| s == &"cumulative_up"
|| s.starts_with("cumulative_start")
|| s.starts_with("cumulative_from")
}))
&& !(split.len() == 4

View File

@@ -12,6 +12,8 @@ use super::{RealizedState, SupplyState};
pub struct CohortState {
pub supply: SupplyState,
pub realized: Option<RealizedState>,
pub satblocks_destroyed: Sats,
pub satdays_destroyed: Sats,
pub price_to_amount: Store<Dollars, Sats>,
}
@@ -26,6 +28,8 @@ impl CohortState {
Ok(Self {
supply: SupplyState::default(),
realized: compute_dollars.then_some(RealizedState::NAN),
satblocks_destroyed: Sats::ZERO,
satdays_destroyed: Sats::ZERO,
price_to_amount: Store::import(
keyspace,
path,
@@ -37,6 +41,8 @@ impl CohortState {
}
pub fn reset_single_iteration_values(&mut self) {
self.satdays_destroyed = Sats::ZERO;
self.satblocks_destroyed = Sats::ZERO;
if let Some(realized) = self.realized.as_mut() {
realized.reset_single_iteration_values();
}
@@ -74,9 +80,17 @@ impl CohortState {
supply_state: &SupplyState,
current_price: Option<Dollars>,
prev_price: Option<Dollars>,
blocks_old: usize,
days_old: f64,
older_than_hour: bool,
) {
self.supply -= supply_state;
self.satblocks_destroyed += supply_state.value * blocks_old;
self.satdays_destroyed +=
Sats::from((u64::from(supply_state.value) as f64 * days_old).floor() as u64);
if let Some(realized) = self.realized.as_mut() {
let current_price = current_price.unwrap();
let prev_price = prev_price.unwrap();

View File

@@ -5,15 +5,20 @@ pub struct OutputsByDateRange<T> {
pub start_to_1d: T,
pub _1d_to_1w: T,
pub _1w_to_1m: T,
pub _1m_to_3m: T,
pub _3m_to_6m: T,
pub _1m_to_2m: T,
pub _2m_to_3m: T,
pub _3m_to_4m: T,
pub _4m_to_5m: T,
pub _5m_to_6m: T,
pub _6m_to_1y: T,
pub _1y_to_2y: T,
pub _2y_to_3y: T,
pub _3y_to_4y: T,
pub _4y_to_5y: T,
pub _5y_to_7y: T,
pub _7y_to_10y: T,
pub _5y_to_6y: T,
pub _6y_to_7y: T,
pub _7y_to_8y: T,
pub _8y_to_10y: T,
pub _10y_to_15y: T,
pub _15y_to_end: T,
}
@@ -24,15 +29,20 @@ impl<T> From<OutputsByDateRange<T>> for OutputsByDateRange<(OutputFilter, T)> {
start_to_1d: (OutputFilter::To(1), value.start_to_1d),
_1d_to_1w: (OutputFilter::Range(1..7), value._1d_to_1w),
_1w_to_1m: (OutputFilter::Range(7..30), value._1w_to_1m),
_1m_to_3m: (OutputFilter::Range(30..3 * 30), value._1m_to_3m),
_3m_to_6m: (OutputFilter::Range(3 * 30..6 * 30), value._3m_to_6m),
_1m_to_2m: (OutputFilter::Range(30..2 * 30), value._1m_to_2m),
_2m_to_3m: (OutputFilter::Range(2 * 30..3 * 30), value._2m_to_3m),
_3m_to_4m: (OutputFilter::Range(3 * 30..4 * 30), value._3m_to_4m),
_4m_to_5m: (OutputFilter::Range(4 * 30..5 * 30), value._4m_to_5m),
_5m_to_6m: (OutputFilter::Range(5 * 30..6 * 30), value._5m_to_6m),
_6m_to_1y: (OutputFilter::Range(6 * 30..365), value._6m_to_1y),
_1y_to_2y: (OutputFilter::Range(365..2 * 365), value._1y_to_2y),
_2y_to_3y: (OutputFilter::Range(2 * 365..3 * 365), value._2y_to_3y),
_3y_to_4y: (OutputFilter::Range(3 * 365..4 * 365), value._3y_to_4y),
_4y_to_5y: (OutputFilter::Range(4 * 365..5 * 365), value._4y_to_5y),
_5y_to_7y: (OutputFilter::Range(5 * 365..7 * 365), value._5y_to_7y),
_7y_to_10y: (OutputFilter::Range(7 * 365..10 * 365), value._7y_to_10y),
_5y_to_6y: (OutputFilter::Range(5 * 365..6 * 365), value._5y_to_6y),
_6y_to_7y: (OutputFilter::Range(6 * 365..7 * 365), value._6y_to_7y),
_7y_to_8y: (OutputFilter::Range(7 * 365..8 * 365), value._7y_to_8y),
_8y_to_10y: (OutputFilter::Range(7 * 365..10 * 365), value._8y_to_10y),
_10y_to_15y: (OutputFilter::Range(10 * 365..15 * 365), value._10y_to_15y),
_15y_to_end: (OutputFilter::From(15 * 365), value._15y_to_end),
}
@@ -40,39 +50,49 @@ impl<T> From<OutputsByDateRange<T>> for OutputsByDateRange<(OutputFilter, T)> {
}
impl<T> OutputsByDateRange<T> {
pub fn as_vec(&mut self) -> [&T; 14] {
pub fn as_vec(&mut self) -> [&T; 19] {
[
&self.start_to_1d,
&self._1d_to_1w,
&self._1w_to_1m,
&self._1m_to_3m,
&self._3m_to_6m,
&self._1m_to_2m,
&self._2m_to_3m,
&self._3m_to_4m,
&self._4m_to_5m,
&self._5m_to_6m,
&self._6m_to_1y,
&self._1y_to_2y,
&self._2y_to_3y,
&self._3y_to_4y,
&self._4y_to_5y,
&self._5y_to_7y,
&self._7y_to_10y,
&self._5y_to_6y,
&self._6y_to_7y,
&self._7y_to_8y,
&self._8y_to_10y,
&self._10y_to_15y,
&self._15y_to_end,
]
}
pub fn as_mut_vec(&mut self) -> [&mut T; 14] {
pub fn as_mut_vec(&mut self) -> [&mut T; 19] {
[
&mut self.start_to_1d,
&mut self._1d_to_1w,
&mut self._1w_to_1m,
&mut self._1m_to_3m,
&mut self._3m_to_6m,
&mut self._1m_to_2m,
&mut self._2m_to_3m,
&mut self._3m_to_4m,
&mut self._4m_to_5m,
&mut self._5m_to_6m,
&mut self._6m_to_1y,
&mut self._1y_to_2y,
&mut self._2y_to_3y,
&mut self._3y_to_4y,
&mut self._4y_to_5y,
&mut self._5y_to_7y,
&mut self._7y_to_10y,
&mut self._5y_to_6y,
&mut self._6y_to_7y,
&mut self._7y_to_8y,
&mut self._8y_to_10y,
&mut self._10y_to_15y,
&mut self._15y_to_end,
]
@@ -80,20 +100,25 @@ impl<T> OutputsByDateRange<T> {
}
impl<T> OutputsByDateRange<(OutputFilter, T)> {
pub fn vecs(&self) -> [&T; 14] {
pub fn vecs(&self) -> [&T; 19] {
[
&self.start_to_1d.1,
&self._1d_to_1w.1,
&self._1w_to_1m.1,
&self._1m_to_3m.1,
&self._3m_to_6m.1,
&self._1m_to_2m.1,
&self._2m_to_3m.1,
&self._3m_to_4m.1,
&self._4m_to_5m.1,
&self._5m_to_6m.1,
&self._6m_to_1y.1,
&self._1y_to_2y.1,
&self._2y_to_3y.1,
&self._3y_to_4y.1,
&self._4y_to_5y.1,
&self._5y_to_7y.1,
&self._7y_to_10y.1,
&self._5y_to_6y.1,
&self._6y_to_7y.1,
&self._7y_to_8y.1,
&self._8y_to_10y.1,
&self._10y_to_15y.1,
&self._15y_to_end.1,
]

View File

@@ -408,20 +408,23 @@ where
T: From<T4>,
{
self.validate_computed_version_or_reset_file(
Version::ZERO + self.inner.version() + divided.version() + divider.version(),
Version::ONE + self.inner.version() + divided.version() + divider.version(),
)?;
let index = max_from.min(I::from(self.len()));
let multiplier = if as_percentage { 100 } else { 1 };
let subtract = if as_difference { multiplier } else { 0 };
let mut divider_iter = divider.iter();
divided.iter_at(index).try_for_each(|(i, divided)| {
let divided = divided.into_inner();
let divider = divider_iter.unwrap_get_inner(i);
let v = (divided / divider * multiplier)
.checked_sub(subtract)
.unwrap();
let mut v = divided / divider;
if as_percentage {
v = v * multiplier;
}
if as_difference {
v = v.checked_sub(multiplier).unwrap();
}
self.forced_push_at(i, T::from(v), exit)
})?;

View File

@@ -441,14 +441,14 @@
h1,
h2 {
text-transform: uppercase;
font-size: var(--font-size-xl);
line-height: var(--line-height-xl);
font-weight: 350;
font-size: var(--font-size-lg);
line-height: var(--line-height-lg);
font-weight: 375;
}
h3 {
font-size: var(--font-size-xl);
line-height: var(--line-height-xl);
font-size: var(--font-size-lg);
line-height: var(--line-height-lg);
}
h4 {
@@ -978,6 +978,22 @@
}
}
.chart > legend,
#charts > fieldset {
text-transform: lowercase;
flex-shrink: 0;
display: flex;
align-items: center;
gap: 1.5rem;
margin: -0.75rem var(--negative-main-padding);
padding: 0.75rem var(--main-padding);
overflow-x: auto;
min-width: 0;
font-size: var(--font-size-sm);
line-height: var(--line-height-sm);
scrollbar-width: thin;
}
.chart {
display: flex;
flex-direction: column;
@@ -987,19 +1003,6 @@
margin-bottom: 1rem;
> legend {
text-transform: lowercase;
flex-shrink: 0;
display: flex;
align-items: center;
gap: 1.5rem;
margin: -0.5rem var(--negative-main-padding);
padding: 1rem var(--main-padding);
overflow-x: auto;
min-width: 0;
font-size: var(--font-size-sm);
line-height: var(--line-height-sm);
scrollbar-width: thin;
&:empty {
display: none;
}
@@ -1052,6 +1055,8 @@
height: 100%;
margin-right: var(--negative-main-padding);
margin-left: var(--negative-main-padding);
margin-top: 0.25rem;
margin-bottom: 0.25rem;
fieldset {
padding: 0.5rem;

View File

@@ -503,8 +503,6 @@ export default import("./v5.0.6-treeshaked/script.js").then((lc) => {
const paneIndex = _paneIndex ?? 0;
console.log("OPTIONS", options);
const series = ichart.addSeries(
/** @type {SeriesDefinition<'Baseline'>} */ (lc.BaselineSeries),
{

View File

@@ -238,8 +238,10 @@ export function init({
paneIndex,
options: {
...blueprint.options,
topLineColor: blueprint.colors?.[0](),
bottomLineColor: blueprint.colors?.[1](),
topLineColor:
blueprint.color?.() ?? blueprint.colors?.[0](),
bottomLineColor:
blueprint.color?.() ?? blueprint.colors?.[1](),
},
});
break;

View File

@@ -16,7 +16,10 @@
* @typedef {"" |
* "BTC" |
* "Cents" |
* "Coinblocks" |
* "coinblocks" |
* "coindays" |
* "satblocks" |
* "satdays" |
* "Count" |
* "Date" |
* "Difficulty" |
@@ -874,6 +877,22 @@ function createUtils() {
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
unit = "Timestamp";
}
if ((!unit || thoroughUnitCheck) && id.includes("coinblocks")) {
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
unit = "coinblocks";
}
if ((!unit || thoroughUnitCheck) && id.includes("coindays")) {
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
unit = "coindays";
}
if ((!unit || thoroughUnitCheck) && id.includes("satblocks")) {
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
unit = "satblocks";
}
if ((!unit || thoroughUnitCheck) && id.includes("satdays")) {
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
unit = "satdays";
}
if ((!unit || thoroughUnitCheck) && id.endsWith("height")) {
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
unit = "Height";

View File

@@ -465,15 +465,33 @@ function createPartialOptions(colors) {
color: colors.orange,
},
{
key: "from-1m-to-3m",
name: "1m..3m",
title: "From 1 Month ago to 3 Months ago",
key: "from-1m-to-2m",
name: "1m..2m",
title: "From 1 Month ago to 2 Months ago",
color: colors.yellow,
},
{
key: "from-3m-to-6m",
name: "3m..6m",
title: "From 3 Month ago to 6 Months ago",
key: "from-2m-to-3m",
name: "2m..3m",
title: "From 2 Month ago to 3 Months ago",
color: colors.yellow,
},
{
key: "from-3m-to-4m",
name: "3m..4m",
title: "From 3 Month ago to 4 Months ago",
color: colors.lime,
},
{
key: "from-4m-to-5m",
name: "4m..5m",
title: "From 4 Month ago to 5 Months ago",
color: colors.lime,
},
{
key: "from-5m-to-6m",
name: "5m..6m",
title: "From 5 Month ago to 6 Months ago",
color: colors.lime,
},
{
@@ -507,15 +525,27 @@ function createPartialOptions(colors) {
color: colors.violet,
},
{
key: "from-5y-to-7y",
name: "5y..7y",
title: "From 5 Years ago to 7 Years ago",
key: "from-5y-to-6y",
name: "5y..6y",
title: "From 5 Years ago to 6 Years ago",
color: colors.purple,
},
{
key: "from-7y-to-10y",
name: "7y..10y",
title: "From 7 Years ago to 10 Years ago",
key: "from-6y-to-7y",
name: "6y..7y",
title: "From 6 Years ago to 7 Years ago",
color: colors.purple,
},
{
key: "from-7y-to-8y",
name: "7y..8y",
title: "From 7 Years ago to 8 Years ago",
color: colors.fuchsia,
},
{
key: "from-8y-to-10y",
name: "8y..10y",
title: "From 8 Years ago to 10 Years ago",
color: colors.fuchsia,
},
{
@@ -1489,34 +1519,78 @@ function createPartialOptions(colors) {
}),
]),
},
{
name: "sopr",
title: `${args.title} Spent Output Profit Ratio`,
bottom: list.flatMap(({ color, name, key }) => [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}spent-output-profit-ratio`,
title: useGroupName ? name : "sopr",
color: useGroupName ? color : undefined,
options: {
createPriceLine: {
value: 1,
},
...(!("list" in args)
? [
{
name: "sopr",
title: `${args.title} Spent Output Profit Ratio`,
bottom: list.flatMap(({ color, name, key }) => [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}spent-output-profit-ratio`,
title: useGroupName ? name : "sopr",
color: useGroupName ? color : undefined,
options: {
createPriceLine: {
value: 1,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}adjusted-spent-output-profit-ratio`,
title: useGroupName ? name : "asopr",
color: useGroupName ? color : undefined,
options: {
createPriceLine: {
value: 1,
},
},
}),
]),
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}adjusted-spent-output-profit-ratio`,
title: useGroupName ? name : "asopr",
color: useGroupName ? color : undefined,
options: {
createPriceLine: {
value: 1,
},
]
: [
{
name: "sopr",
tree: [
{
name: "Normal",
title: `${args.title} Spent Output Profit Ratio`,
bottom: list.flatMap(({ color, name, key }) => [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}spent-output-profit-ratio`,
title: useGroupName ? name : "sopr",
color: useGroupName ? color : undefined,
options: {
createPriceLine: {
value: 1,
},
},
}),
]),
},
{
name: "Adjusted",
title: `${args.title} Adjusted Spent Output Profit Ratio`,
bottom: list.flatMap(({ color, name, key }) => [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}adjusted-spent-output-profit-ratio`,
title: useGroupName ? name : "asopr",
color: useGroupName ? color : undefined,
options: {
createPriceLine: {
value: 1,
},
},
}),
]),
},
],
},
}),
]),
},
]),
{
name: "Sell Side Risk Ratio",
title: `${args.title} Sell Side Risk Ratio`,
@@ -1634,7 +1708,7 @@ function createPartialOptions(colors) {
{
name: "Average",
title: `${args.title} Average Price Paid`,
bottom: list.flatMap(({ color, name, key: _key }) => {
top: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
@@ -1648,7 +1722,7 @@ function createPartialOptions(colors) {
{
name: "Min",
title: `${args.title} Min Price Paid`,
bottom: list.flatMap(({ color, name, key: _key }) => {
top: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
@@ -1662,7 +1736,7 @@ function createPartialOptions(colors) {
{
name: "Max",
title: `${args.title} Max Price Paid`,
bottom: list.flatMap(({ color, name, key: _key }) => {
top: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
@@ -1701,6 +1775,35 @@ function createPartialOptions(colors) {
],
},
]),
{
name: "Coins Destroyed",
title: `${args.title} Coins Destroyed`,
bottom: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
key: `${key}coinblocks-destroyed`,
name: useGroupName ? name : "destroyed",
color,
}),
createBaseSeries({
key: `${key}coindays-destroyed`,
name: useGroupName ? name : "destroyed",
color,
}),
createBaseSeries({
key: `${key}coinblocks-destroyed-sum`,
name: useGroupName ? name : "destroyed",
color,
}),
createBaseSeries({
key: `${key}coindays-destroyed-sum`,
name: useGroupName ? name : "destroyed",
color,
}),
]);
}),
},
],
});
}
@@ -2722,14 +2825,14 @@ function createPartialOptions(colors) {
],
},
{
name: "Services",
name: "Hosting",
tree: [
{
name: "Self-host",
name: "Self",
url: () => "https://crates.io/crates/brk_cli",
},
{
name: "Hosting as a service",
name: "As a service",
url: () =>
"https://github.com/bitcoinresearchkit/brk?tab=readme-ov-file#hosting-as-a-service",
},

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
white-space: nowrap;
overflow-x: auto;
padding-bottom: 1rem;
margin-bottom: -1rem;
margin-bottom: -2rem;
padding-left: var(--main-padding);
margin-left: var(--negative-main-padding);
padding-right: var(--main-padding);
@@ -28,7 +28,11 @@
flex: 1;
}
> * {
.lightweight-chart {
z-index: 30;
}
> * {
/* z-index: 30; */
}
}