global: add a bunch of realized datasets + charts

This commit is contained in:
nym21
2025-06-17 18:47:04 +02:00
parent bbe9f1bad2
commit c559f26d0e
14 changed files with 1928 additions and 639 deletions
+2 -1
View File
@@ -52,7 +52,8 @@ pub async fn bundle(websites_path: &Path, source_folder: &str, watch: bool) -> i
if let Some(start) = entry.find("main") {
if let Some(end) = entry.find(".js") {
let main_hashed = &entry[start..end];
contents = contents.replace("/scripts/main.js", &format!("/scripts/{main_hashed}.js"));
contents =
contents.replace("/scripts/main.js", &format!("/scripts/{main_hashed}.js"));
}
}
}
@@ -130,7 +130,11 @@ where
Box::new(
EagerVec::forced_import(
path,
&maybe_suffix("sum"),
&(if !options.last {
name.to_string()
} else {
maybe_suffix("sum")
}),
version + VERSION + Version::ZERO,
format,
)
+208 -20
View File
@@ -57,7 +57,7 @@ pub struct Vecs {
pub indexes_to_coinblocks_destroyed: ComputedVecsFromHeight<StoredF64>,
pub indexes_to_coindays_destroyed: ComputedVecsFromHeight<StoredF64>,
pub dateindex_to_adjusted_spent_output_profit_ratio: Option<EagerVec<DateIndex, StoredF32>>,
pub dateindex_to_realized_cap_30d_change: Option<EagerVec<DateIndex, Dollars>>,
pub indexes_to_realized_cap_30d_change: Option<ComputedVecsFromDateIndex<Dollars>>,
pub dateindex_to_sell_side_risk_ratio: Option<EagerVec<DateIndex, StoredF32>>,
pub dateindex_to_spent_output_profit_ratio: Option<EagerVec<DateIndex, StoredF32>>,
pub indexes_to_adjusted_value_created: Option<ComputedVecsFromHeight<Dollars>>,
@@ -89,6 +89,10 @@ pub struct Vecs {
Option<EagerVec<Height, StoredF32>>,
pub indexes_to_net_unrealized_profit_and_loss_relative_to_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_realized_profit_relative_to_realized_cap:
Option<ComputedVecsFromHeight<StoredF32>>,
pub indexes_to_realized_loss_relative_to_realized_cap:
Option<ComputedVecsFromHeight<StoredF32>>,
pub indexes_to_net_realized_profit_and_loss_relative_to_realized_cap:
Option<ComputedVecsFromHeight<StoredF32>>,
pub height_to_supply_even_value: Option<ComputedHeightValueVecs>,
@@ -117,6 +121,12 @@ pub struct Vecs {
Option<ComputedVecsFromDateIndex<StoredF64>>,
pub indexes_to_supply_in_profit_relative_to_circulating_supply:
Option<ComputedVecsFromDateIndex<StoredF64>>,
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change:
Option<ComputedVecsFromDateIndex<Dollars>>,
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
pub indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap:
Option<ComputedVecsFromDateIndex<StoredF32>>,
}
impl Vecs {
@@ -432,7 +442,9 @@ impl Vecs {
false,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_sum(),
StorableVecGeneatorOptions::default()
.add_sum()
.add_cumulative(),
)
.unwrap()
}),
@@ -452,7 +464,9 @@ impl Vecs {
false,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_sum(),
StorableVecGeneatorOptions::default()
.add_sum()
.add_cumulative(),
)
.unwrap()
}),
@@ -463,7 +477,7 @@ impl Vecs {
true,
version + VERSION + Version::ONE,
format,
StorableVecGeneatorOptions::default().add_sum(),
StorableVecGeneatorOptions::default().add_sum().add_cumulative(),
)
.unwrap()
}),
@@ -558,12 +572,14 @@ impl Vecs {
)
.unwrap()
}),
dateindex_to_realized_cap_30d_change: compute_dollars.then(|| {
EagerVec::forced_import(
indexes_to_realized_cap_30d_change: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
path,
&suffix("realized_cap_30d_change"),
true,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_last(),
)
.unwrap()
}),
@@ -574,7 +590,9 @@ impl Vecs {
true,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_sum(),
StorableVecGeneatorOptions::default()
.add_sum()
.add_cumulative(),
)
.unwrap()
}),
@@ -686,15 +704,37 @@ impl Vecs {
.unwrap()
},
),
indexes_to_realized_profit_relative_to_realized_cap: compute_dollars.then(|| {
ComputedVecsFromHeight::forced_import(
path,
&suffix("realized_profit_relative_to_realized_cap"),
true,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_sum(),
)
.unwrap()
}),
indexes_to_realized_loss_relative_to_realized_cap: compute_dollars.then(|| {
ComputedVecsFromHeight::forced_import(
path,
&suffix("realized_loss_relative_to_realized_cap"),
true,
version + VERSION + Version::ZERO,
format,
StorableVecGeneatorOptions::default().add_sum(),
)
.unwrap()
}),
indexes_to_net_realized_profit_and_loss_relative_to_realized_cap: compute_dollars.then(
|| {
ComputedVecsFromHeight::forced_import(
path,
&suffix("net_realized_profit_and_loss_relative_to_realized_cap"),
true,
version + VERSION + Version::ZERO,
version + VERSION + Version::ONE,
format,
StorableVecGeneatorOptions::default().add_last(),
StorableVecGeneatorOptions::default().add_sum(),
)
.unwrap()
},
@@ -903,6 +943,39 @@ impl Vecs {
format,
StorableVecGeneatorOptions::default().add_sum(),
)?,
indexes_to_cumulative_net_realized_profit_and_loss_30d_change: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
path,
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change")),
true,
version + VERSION + Version::TWO,
format,
StorableVecGeneatorOptions::default().add_last()
)
.unwrap()
}),
indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
path,
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change_relative_to_realized_cap")),
true,
version + VERSION + Version::TWO,
format,
StorableVecGeneatorOptions::default().add_last()
)
.unwrap()
}),
indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap: compute_dollars.then(|| {
ComputedVecsFromDateIndex::forced_import(
path,
&format!("cumulative_{}", suffix("net_realized_profit_and_loss_30d_change_relative_to_market_cap")),
true,
version + VERSION + Version::TWO,
format,
StorableVecGeneatorOptions::default().add_last()
)
.unwrap()
}),
})
}
@@ -1877,6 +1950,7 @@ impl Vecs {
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
exit: &Exit,
) -> color_eyre::Result<()> {
if let Some(v) = self
@@ -2021,18 +2095,26 @@ impl Vecs {
Some(self.height_to_adjusted_value_destroyed.as_ref().unwrap()),
)?;
self.dateindex_to_realized_cap_30d_change
self.indexes_to_realized_cap_30d_change
.as_mut()
.unwrap()
.compute_change(
starting_indexes.dateindex,
self.indexes_to_realized_cap
.as_ref()
.unwrap()
.dateindex
.unwrap_last(),
30,
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_change(
starting_indexes.dateindex,
self.indexes_to_realized_cap
.as_ref()
.unwrap()
.dateindex
.unwrap_last(),
30,
exit,
)
},
)?;
self.indexes_to_net_realized_profit_and_loss
@@ -2280,6 +2362,42 @@ impl Vecs {
},
)?;
self.indexes_to_realized_profit_relative_to_realized_cap
.as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_percentage(
starting_indexes.height,
self.height_to_realized_profit.as_ref().unwrap(),
*height_to_realized_cap.as_ref().unwrap(),
exit,
)
},
)?;
self.indexes_to_realized_loss_relative_to_realized_cap
.as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|vec, _, _, starting_indexes, exit| {
vec.compute_percentage(
starting_indexes.height,
self.height_to_realized_loss.as_ref().unwrap(),
*height_to_realized_cap.as_ref().unwrap(),
exit,
)
},
)?;
self.indexes_to_net_realized_profit_and_loss_relative_to_realized_cap
.as_mut()
.unwrap()
@@ -2435,6 +2553,64 @@ impl Vecs {
},
)?;
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change
.as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_change(
starting_indexes.dateindex,
self.indexes_to_net_realized_profit_and_loss
.as_ref()
.unwrap()
.dateindex
.unwrap_cumulative(),
30,
exit,
)
},
)?;
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap.
as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref().unwrap().dateindex.as_ref().unwrap(),
*dateindex_to_realized_cap.as_ref().unwrap(),
exit,
)
},
)?;
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap.
as_mut()
.unwrap()
.compute_all(
indexer,
indexes,
starting_indexes,
exit,
|v, _, _, starting_indexes, exit| {
v.compute_percentage(
starting_indexes.dateindex,
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref().unwrap().dateindex.as_ref().unwrap(),
market.indexes_to_marketcap.dateindex.as_ref().unwrap(),
exit,
)
},
)?;
if let Some(height_to_supply_even_relative_to_circulating_supply) = self
.height_to_supply_even_relative_to_circulating_supply
.as_mut()
@@ -2618,9 +2794,9 @@ impl Vecs {
self.indexes_to_adjusted_value_destroyed
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.dateindex_to_realized_cap_30d_change
self.indexes_to_realized_cap_30d_change
.as_ref()
.map_or(vec![], |v| vec![v]),
.map_or(vec![], |v| v.vecs()),
self.indexes_to_net_realized_profit_and_loss
.as_ref()
.map_or(vec![], |v| v.vecs()),
@@ -2703,6 +2879,12 @@ impl Vecs {
self.indexes_to_net_unrealized_profit_and_loss_relative_to_market_cap
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_realized_profit_relative_to_realized_cap
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_realized_loss_relative_to_realized_cap
.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_net_realized_profit_and_loss_relative_to_realized_cap
.as_ref()
.map_or(vec![], |v| v.vecs()),
@@ -2756,6 +2938,12 @@ impl Vecs {
.map_or(vec![], |v| v.vecs()),
self.indexes_to_coinblocks_destroyed.vecs(),
self.indexes_to_coindays_destroyed.vecs(),
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_realized_cap.as_ref()
.map_or(vec![], |v| v.vecs()),
self.indexes_to_cumulative_net_realized_profit_and_loss_30d_change_relative_to_market_cap.as_ref()
.map_or(vec![], |v| v.vecs()),
]
.into_iter()
.flatten()
+254 -249
View File
@@ -4,8 +4,8 @@ use brk_core::{DateIndex, Height, InputIndex, OutputIndex, OutputType, Result, S
use brk_exit::Exit;
use brk_indexer::Indexer;
use brk_vec::{
AnyCollectableVec, AnyVec, BaseVecIterator, CollectableVec, Computation, EagerVec, Format,
GenericStoredVec, StoredIndex, StoredVec, UnsafeSlice, VecIterator,
AnyCollectableVec, AnyVec, CollectableVec, Computation, EagerVec, Format, GenericStoredVec,
StoredIndex, StoredVec, UnsafeSlice, VecIterator,
};
use log::info;
use outputs::OutputCohorts;
@@ -1343,268 +1343,265 @@ impl Vecs {
.try_for_each(|(_, v)| v.state.price_to_amount.reset())?;
}
if starting_height == Height::from(height_to_date_fixed.len()) {
return Ok(());
}
if starting_height < Height::from(height_to_date_fixed.len()) {
starting_indexes.update_from_height(starting_height, indexes);
// ---
// INIT
// ---
separate_utxo_vecs
.par_iter_mut()
.for_each(|(_, v)| v.init(starting_height));
separate_utxo_vecs
.par_iter_mut()
.for_each(|(_, v)| v.init(starting_height));
let mut unspendable_supply = if let Some(prev_height) = starting_height.decremented() {
self.height_to_unspendable_supply
.into_iter()
.unwrap_get_inner(prev_height)
} else {
Sats::ZERO
};
let mut opreturn_supply = if let Some(prev_height) = starting_height.decremented() {
self.height_to_opreturn_supply
.into_iter()
.unwrap_get_inner(prev_height)
} else {
Sats::ZERO
};
let mut height = starting_height;
starting_indexes.update_from_height(height, indexes);
(height.unwrap_to_usize()..height_to_first_outputindex_iter.len())
.map(Height::from)
.try_for_each(|_height| -> color_eyre::Result<()> {
height = _height;
self.utxos_vecs
.as_mut_separate_vecs()
.iter_mut()
.for_each(|(_, v)| v.state.reset_single_iteration_values());
info!("Processing chain at {height}...");
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
let price = height_to_close_iter
.as_mut()
.map(|i| *i.unwrap_get_inner(height));
let first_outputindex = height_to_first_outputindex_iter
.unwrap_get_inner(height)
.unwrap_to_usize();
let first_inputindex = height_to_first_inputindex_iter
.unwrap_get_inner(height)
.unwrap_to_usize();
let output_count = height_to_output_count_iter.unwrap_get_inner(height);
let input_count = height_to_input_count_iter.unwrap_get_inner(height);
let (mut height_to_sent, mut received) = thread::scope(|s| {
if chain_state_starting_height <= height {
s.spawn(|| {
self.utxos_vecs
.tick_tock_next_block(&chain_state, timestamp);
});
}
let sent_handle = s.spawn(|| {
// Skip coinbase
(first_inputindex + 1..first_inputindex + *input_count)
.into_par_iter()
.map(InputIndex::from)
.map(|inputindex| {
let outputindex = inputindex_to_outputindex
.get_or_read(inputindex, &inputindex_to_outputindex_mmap)
.unwrap()
.unwrap()
.into_inner();
let value = outputindex_to_value
.get_or_read(outputindex, &outputindex_to_value_mmap)
.unwrap()
.unwrap()
.into_inner();
let input_type = outputindex_to_outputtype
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
.unwrap()
.unwrap()
.into_inner();
// dbg!(input_type);
if input_type.is_unspendable() {
unreachable!()
}
let input_txindex = outputindex_to_txindex
.get_or_read(outputindex, &outputindex_to_txindex_mmap)
.unwrap()
.unwrap()
.into_inner();
let height = txindex_to_height
.get_or_read(input_txindex, &txindex_to_height_mmap)
.unwrap()
.unwrap()
.into_inner();
(height, value, input_type)
})
.fold(
BTreeMap::<Height, Transacted>::default,
|mut tree, (height, value, input_type)| {
tree.entry(height).or_default().iterate(value, input_type);
tree
},
)
.reduce(BTreeMap::<Height, Transacted>::default, |first, second| {
let (mut source, to_consume) = if first.len() > second.len() {
(first, second)
} else {
(second, first)
};
to_consume.into_iter().for_each(|(k, v)| {
*source.entry(k).or_default() += v;
});
source
})
});
let received_handle = s.spawn(|| {
(first_outputindex..first_outputindex + *output_count)
.into_par_iter()
.map(OutputIndex::from)
.map(|outputindex| {
let value = outputindex_to_value
.get_or_read(outputindex, &outputindex_to_value_mmap)
.unwrap()
.unwrap()
.into_inner();
let output_type = outputindex_to_outputtype
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
.unwrap()
.unwrap()
.into_inner();
(value, output_type)
})
.fold(
Transacted::default,
|mut transacted, (value, output_type)| {
transacted.iterate(value, output_type);
transacted
},
)
.reduce(Transacted::default, |acc, transacted| acc + transacted)
});
(sent_handle.join().unwrap(), received_handle.join().unwrap())
});
unspendable_supply += received
.by_type
.unspendable
.as_vec()
let mut unspendable_supply = if let Some(prev_height) = starting_height.decremented() {
self.height_to_unspendable_supply
.into_iter()
.map(|state| state.value)
.sum::<Sats>()
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
opreturn_supply += received.by_type.unspendable.opreturn.value;
if height == Height::new(0) {
received = Transacted::default();
unspendable_supply += Sats::FIFTY_BTC;
} else if height == Height::new(91_842) || height == Height::new(91_880) {
// Need to destroy invalid coinbases due to duplicate txids
if height == Height::new(91_842) {
height_to_sent.entry(Height::new(91_812)).or_default()
} else {
height_to_sent.entry(Height::new(91_722)).or_default()
}
.iterate(Sats::FIFTY_BTC, OutputType::P2PK65);
};
if chain_state_starting_height <= height {
// Push current block state before processing sends and receives
chain_state.push(BlockState {
supply: received.spendable_supply.clone(),
price,
timestamp,
});
self.utxos_vecs.receive(received, height, price);
let unsafe_chain_state = UnsafeSlice::new(&mut chain_state);
height_to_sent.par_iter().for_each(|(height, sent)| unsafe {
(*unsafe_chain_state.get(height.unwrap_to_usize())).supply -=
&sent.spendable_supply;
});
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
} else {
dbg!(chain_state_starting_height, height);
panic!("temp, just making sure")
}
let mut separate_utxo_vecs = self.utxos_vecs.as_mut_separate_vecs();
separate_utxo_vecs
.iter_mut()
.try_for_each(|(_, v)| v.forced_pushed_at(height, exit))?;
self.height_to_unspendable_supply.forced_push_at(
height,
unspendable_supply,
exit,
)?;
.unwrap_get_inner(prev_height)
} else {
Sats::ZERO
};
let mut opreturn_supply = if let Some(prev_height) = starting_height.decremented() {
self.height_to_opreturn_supply
.forced_push_at(height, opreturn_supply, exit)?;
.into_iter()
.unwrap_get_inner(prev_height)
} else {
Sats::ZERO
};
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
let dateindex = DateIndex::try_from(date).unwrap();
let date_first_height = dateindex_to_first_height_iter.unwrap_get_inner(dateindex);
let date_height_count = dateindex_to_height_count_iter.unwrap_get_inner(dateindex);
let is_date_last_height = date_first_height
+ Height::from(date_height_count).decremented().unwrap()
== height;
let date_price = dateindex_to_close_iter
.as_mut()
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
let mut height = starting_height;
separate_utxo_vecs.par_iter_mut().try_for_each(|(_, v)| {
v.compute_then_force_push_unrealized_states(
(height.unwrap_to_usize()..height_to_date_fixed.len())
.map(Height::from)
.try_for_each(|_height| -> color_eyre::Result<()> {
height = _height;
self.utxos_vecs
.as_mut_separate_vecs()
.iter_mut()
.for_each(|(_, v)| v.state.reset_single_iteration_values());
info!("Processing chain at {height}...");
let timestamp = height_to_timestamp_fixed_iter.unwrap_get_inner(height);
let price = height_to_close_iter
.as_mut()
.map(|i| *i.unwrap_get_inner(height));
let first_outputindex = height_to_first_outputindex_iter
.unwrap_get_inner(height)
.unwrap_to_usize();
let first_inputindex = height_to_first_inputindex_iter
.unwrap_get_inner(height)
.unwrap_to_usize();
let output_count = height_to_output_count_iter.unwrap_get_inner(height);
let input_count = height_to_input_count_iter.unwrap_get_inner(height);
let (mut height_to_sent, mut received) = thread::scope(|s| {
if chain_state_starting_height <= height {
s.spawn(|| {
self.utxos_vecs
.tick_tock_next_block(&chain_state, timestamp);
});
}
let sent_handle = s.spawn(|| {
// Skip coinbase
(first_inputindex + 1..first_inputindex + *input_count)
.into_par_iter()
.map(InputIndex::from)
.map(|inputindex| {
let outputindex = inputindex_to_outputindex
.get_or_read(inputindex, &inputindex_to_outputindex_mmap)
.unwrap()
.unwrap()
.into_inner();
let value = outputindex_to_value
.get_or_read(outputindex, &outputindex_to_value_mmap)
.unwrap()
.unwrap()
.into_inner();
let input_type = outputindex_to_outputtype
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
.unwrap()
.unwrap()
.into_inner();
// dbg!(input_type);
if input_type.is_unspendable() {
unreachable!()
}
let input_txindex = outputindex_to_txindex
.get_or_read(outputindex, &outputindex_to_txindex_mmap)
.unwrap()
.unwrap()
.into_inner();
let height = txindex_to_height
.get_or_read(input_txindex, &txindex_to_height_mmap)
.unwrap()
.unwrap()
.into_inner();
(height, value, input_type)
})
.fold(
BTreeMap::<Height, Transacted>::default,
|mut tree, (height, value, input_type)| {
tree.entry(height).or_default().iterate(value, input_type);
tree
},
)
.reduce(BTreeMap::<Height, Transacted>::default, |first, second| {
let (mut source, to_consume) = if first.len() > second.len() {
(first, second)
} else {
(second, first)
};
to_consume.into_iter().for_each(|(k, v)| {
*source.entry(k).or_default() += v;
});
source
})
});
let received_handle = s.spawn(|| {
(first_outputindex..first_outputindex + *output_count)
.into_par_iter()
.map(OutputIndex::from)
.map(|outputindex| {
let value = outputindex_to_value
.get_or_read(outputindex, &outputindex_to_value_mmap)
.unwrap()
.unwrap()
.into_inner();
let output_type = outputindex_to_outputtype
.get_or_read(outputindex, &outputindex_to_outputtype_mmap)
.unwrap()
.unwrap()
.into_inner();
(value, output_type)
})
.fold(
Transacted::default,
|mut transacted, (value, output_type)| {
transacted.iterate(value, output_type);
transacted
},
)
.reduce(Transacted::default, |acc, transacted| acc + transacted)
});
(sent_handle.join().unwrap(), received_handle.join().unwrap())
});
unspendable_supply += received
.by_type
.unspendable
.as_vec()
.into_iter()
.map(|state| state.value)
.sum::<Sats>()
+ height_to_unclaimed_rewards_iter.unwrap_get_inner(height);
opreturn_supply += received.by_type.unspendable.opreturn.value;
if height == Height::new(0) {
received = Transacted::default();
unspendable_supply += Sats::FIFTY_BTC;
} else if height == Height::new(91_842) || height == Height::new(91_880) {
// Need to destroy invalid coinbases due to duplicate txids
if height == Height::new(91_842) {
height_to_sent.entry(Height::new(91_812)).or_default()
} else {
height_to_sent.entry(Height::new(91_722)).or_default()
}
.iterate(Sats::FIFTY_BTC, OutputType::P2PK65);
};
if chain_state_starting_height <= height {
// Push current block state before processing sends and receives
chain_state.push(BlockState {
supply: received.spendable_supply.clone(),
price,
timestamp,
});
self.utxos_vecs.receive(received, height, price);
let unsafe_chain_state = UnsafeSlice::new(&mut chain_state);
height_to_sent.par_iter().for_each(|(height, sent)| unsafe {
(*unsafe_chain_state.get(height.unwrap_to_usize())).supply -=
&sent.spendable_supply;
});
self.utxos_vecs.send(height_to_sent, chain_state.as_slice());
} else {
dbg!(chain_state_starting_height, height);
panic!("temp, just making sure")
}
let mut separate_utxo_vecs = self.utxos_vecs.as_mut_separate_vecs();
separate_utxo_vecs
.iter_mut()
.try_for_each(|(_, v)| v.forced_pushed_at(height, exit))?;
self.height_to_unspendable_supply.forced_push_at(
height,
price,
is_date_last_height.then_some(dateindex),
date_price,
unspendable_supply,
exit,
)
)?;
self.height_to_opreturn_supply
.forced_push_at(height, opreturn_supply, exit)?;
let date = height_to_date_fixed_iter.unwrap_get_inner(height);
let dateindex = DateIndex::try_from(date).unwrap();
let date_first_height =
dateindex_to_first_height_iter.unwrap_get_inner(dateindex);
let date_height_count =
dateindex_to_height_count_iter.unwrap_get_inner(dateindex);
let is_date_last_height = date_first_height
+ Height::from(date_height_count).decremented().unwrap()
== height;
let date_price = dateindex_to_close_iter
.as_mut()
.map(|v| is_date_last_height.then(|| *v.unwrap_get_inner(dateindex)));
separate_utxo_vecs.par_iter_mut().try_for_each(|(_, v)| {
v.compute_then_force_push_unrealized_states(
height,
price,
is_date_last_height.then_some(dateindex),
date_price,
exit,
)
})?;
if height != Height::ZERO && height.unwrap_to_usize() % 20_000 == 0 {
info!("Flushing...");
exit.block();
self.flush_states(height, &chain_state, exit)?;
exit.release();
}
Ok(())
})?;
if height != Height::ZERO && height.unwrap_to_usize() % 20_000 == 0 {
info!("Flushing...");
exit.block();
self.flush_states(height, &chain_state, exit)?;
exit.release();
}
exit.block();
Ok(())
})?;
info!("Flushing...");
exit.block();
self.flush_states(height, &chain_state, exit)?;
}
info!("Flushing...");
self.flush_states(height, &chain_state, exit)?;
info!("Computing overlaping...");
info!("Computing overlapping...");
self.utxos_vecs
.compute_overlaping_vecs(&starting_indexes, exit)?;
.compute_overlapping_vecs(&starting_indexes, exit)?;
info!("Computing rest part 1...");
@@ -1627,6 +1624,13 @@ impl Vecs {
.dateindex
.clone();
let height_to_realized_cap = self.utxos_vecs.all.1.height_to_realized_cap.clone();
let dateindex_to_realized_cap = self
.utxos_vecs
.all
.1
.indexes_to_realized_cap
.as_ref()
.map(|v| v.dateindex.unwrap_last().clone());
self.utxos_vecs
.as_mut_vecs()
@@ -1641,6 +1645,7 @@ impl Vecs {
&height_to_supply,
dateindex_to_supply.as_ref().unwrap(),
height_to_realized_cap.as_ref(),
dateindex_to_realized_cap.as_ref(),
exit,
)
})?;
@@ -14,7 +14,7 @@ pub trait OutputCohorts {
fn tick_tock_next_block(&mut self, chain_state: &[BlockState], timestamp: Timestamp);
fn send(&mut self, height_to_sent: BTreeMap<Height, Transacted>, chain_state: &[BlockState]);
fn receive(&mut self, received: Transacted, height: Height, price: Option<Dollars>);
fn compute_overlaping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
fn compute_overlapping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()>;
}
impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
@@ -172,7 +172,7 @@ impl OutputCohorts for Outputs<(OutputFilter, cohort::Vecs)> {
});
}
fn compute_overlaping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
fn compute_overlapping_vecs(&mut self, starting_indexes: &Indexes, exit: &Exit) -> Result<()> {
let by_date_range = self.by_date_range.as_vec();
let by_size_range = self.by_size_range.as_vec();
+3 -1
View File
@@ -3,5 +3,7 @@ use log::info;
pub fn pause() {
info!("Press enter to continue...");
let mut buffer = String::new();
std::io::stdin().read_line(&mut buffer).expect("Failed to read line");
std::io::stdin()
.read_line(&mut buffer)
.expect("Failed to read line");
}
+8 -3
View File
@@ -28,9 +28,14 @@ impl<'a> VecTrees<'a> {
|| s.starts_with("cumulative_from")
}))
&& !(split.len() == 4
&& split
.get(1)
.is_some_and(|s| s == &"up" || s == &"start" || s.starts_with("from"))
&& split.get(1).is_some_and(|s| {
s == &"up"
|| s == &"start"
|| s.starts_with("from")
|| s == &"cumulative_up"
|| s == &"cumulative_start"
|| s.starts_with("cumulative_from")
})
&& split.get(2).is_some_and(|s| s.ends_with("relative")))
{
dbg!(&name, &split);
@@ -0,0 +1 @@
+1 -1
View File
@@ -70,7 +70,7 @@ impl<T> Outputs<T> {
.collect::<Vec<_>>()
}
pub fn as_mut_overlaping_vecs(&mut self) -> Vec<&mut T> {
pub fn as_mut_overlapping_vecs(&mut self) -> Vec<&mut T> {
[&mut self.all]
.into_iter()
.chain(self.by_term.as_mut_vec())
@@ -141,7 +141,7 @@ function createChartElement({
}
: {}),
// ..._options,
}),
})
);
ichart.priceScale("right").applyOptions({
@@ -173,7 +173,7 @@ function createChartElement({
},
},
});
},
}
);
signals.createEffect(index, (index) => {
@@ -181,12 +181,12 @@ function createChartElement({
index === /** @satisfies {MonthIndex} */ (7)
? 1
: index === /** @satisfies {QuarterIndex} */ (19)
? 2
: index === /** @satisfies {YearIndex} */ (23)
? 6
: index === /** @satisfies {DecadeIndex} */ (1)
? 60
: 0.5;
? 2
: index === /** @satisfies {YearIndex} */ (23)
? 6
: index === /** @satisfies {DecadeIndex} */ (1)
? 60
: 0.5;
ichart.applyOptions({
timeScale: {
@@ -209,7 +209,7 @@ function createChartElement({
activeResources.forEach((v) => {
v.fetch();
});
}),
})
);
if (fitContent) {
@@ -240,8 +240,7 @@ function createChartElement({
const children = Array.from(parent.childNodes).filter(
(element) =>
/** @type {HTMLElement} */ (element).dataset.position ===
position,
/** @type {HTMLElement} */ (element).dataset.position === position
);
if (children.length === 1) {
@@ -263,7 +262,7 @@ function createChartElement({
fieldset.append(createChild(pane));
}),
paneIndex ? 50 : 0,
paneIndex ? 50 : 0
);
}
@@ -347,7 +346,7 @@ function createChartElement({
// Or remove ?
iseries.applyOptions({
visible: active,
}),
})
);
iseries.setSeriesOrder(order);
@@ -378,7 +377,7 @@ function createChartElement({
index,
index === /** @satisfies {Height} */ (5)
? "timestamp-fixed"
: "timestamp",
: "timestamp"
);
timeResource.fetch();
@@ -438,16 +437,18 @@ function createChartElement({
if (sameTime) {
console.log(data[offsetedI]);
}
const candles = /** @type {CandlestickData[]} */ (data);
let [open, high, low, close] = v;
candles[offsetedI] = {
data[offsetedI] = {
time,
open: sameTime ? candles[offsetedI].open : open,
// @ts-ignore
open: sameTime ? data[offsetedI].open : open,
high: sameTime
? Math.max(candles[offsetedI].high, high)
? // @ts-ignore
Math.max(data[offsetedI].high, high)
: high,
low: sameTime
? Math.min(candles[offsetedI].low, low)
? // @ts-ignore
Math.min(data[offsetedI].low, low)
: low,
close,
};
@@ -580,7 +581,7 @@ function createChartElement({
});
console.timeEnd(consoleTimeLabel);
},
}
);
} else {
activeResources.delete(valuesResource);
@@ -673,7 +674,7 @@ function createChartElement({
borderVisible: false,
visible: defaultActive !== false,
},
paneIndex,
paneIndex
)
);
@@ -729,7 +730,7 @@ function createChartElement({
color: color(),
...options,
},
paneIndex,
paneIndex
)
);
@@ -797,7 +798,7 @@ function createChartElement({
topFillColor2: "transparent",
lineVisible: true,
},
paneIndex,
paneIndex
)
);
@@ -960,7 +961,7 @@ function createLegend({ signals, utils }) {
} else {
spanColor.style.backgroundColor = tameColor(color);
}
},
}
);
});
@@ -1120,17 +1121,17 @@ function numberToShortUSFormat(value, digits) {
if (modulused === 0) {
return `${numberToUSFormat(
value / (1_000_000 * 1_000 ** letterIndex),
3,
3
)}${letter}`;
} else if (modulused === 1) {
return `${numberToUSFormat(
value / (1_000_000 * 1_000 ** letterIndex),
2,
2
)}${letter}`;
} else {
return `${numberToUSFormat(
value / (1_000_000 * 1_000 ** letterIndex),
1,
1
)}${letter}`;
}
}
@@ -1180,7 +1181,7 @@ function createOklchToRGBA() {
return rgb.map((c) =>
Math.abs(c) > 0.0031308
? (c < 0 ? -1 : 1) * (1.055 * Math.abs(c) ** (1 / 2.4) - 0.055)
: 12.92 * c,
: 12.92 * c
);
}
/**
@@ -1192,7 +1193,7 @@ function createOklchToRGBA() {
1, 0.3963377773761749, 0.2158037573099136, 1, -0.1055613458156586,
-0.0638541728258133, 1, -0.0894841775298119, -1.2914855480194092,
]),
lab,
lab
);
const LMS = /** @type {[number, number, number]} */ (
LMSg.map((val) => val ** 3)
@@ -1203,7 +1204,7 @@ function createOklchToRGBA() {
-0.0405757452148008, 1.112286803280317, -0.0717110580655164,
-0.0763729366746601, -0.4214933324022432, 1.5869240198367816,
]),
LMS,
LMS
);
}
/**
@@ -1216,7 +1217,7 @@ function createOklchToRGBA() {
-0.9692436362808796, 1.8759675015077202, 0.04155505740717559,
0.05563007969699366, -0.20397695888897652, 1.0569715142428786,
],
xyz,
xyz
);
}
@@ -1239,8 +1240,8 @@ function createOklchToRGBA() {
});
const rgb = srgbLinear2rgb(
xyz2rgbLinear(
oklab2xyz(oklch2oklab(/** @type {[number, number, number]} */ (lch))),
),
oklab2xyz(oklch2oklab(/** @type {[number, number, number]} */ (lch)))
)
).map((v) => {
return Math.max(Math.min(Math.round(v * 255), 255), 0);
});
+1
View File
@@ -396,6 +396,7 @@ export function init({
blueprints[unit]?.forEach((blueprint, order) => {
order += orderStart;
console.log(blueprint.key);
const indexes = /** @type {readonly number[]} */ (
vecIdToIndexes[blueprint.key]
);
+77 -79
View File
@@ -63,14 +63,14 @@ function initPackages() {
const imports = {
async signals() {
return import("../packages/solid-signals/wrapper.js").then(
(d) => d.default,
(d) => d.default
);
},
async lightweightCharts() {
return window.document.fonts.ready.then(() =>
import("../packages/lightweight-charts/wrapper.js").then(
(d) => d.default,
),
(d) => d.default
)
);
},
async leanQr() {
@@ -78,7 +78,7 @@ function initPackages() {
},
async ufuzzy() {
return import("../packages/ufuzzy/v1.0.18/script.js").then(
({ default: d }) => d,
({ default: d }) => d
);
},
};
@@ -586,7 +586,7 @@ function createUtils() {
window.history.pushState(
null,
"",
`${pathname}?${urlParams.toString()}`,
`${pathname}?${urlParams.toString()}`
);
} catch (_) {}
},
@@ -603,7 +603,7 @@ function createUtils() {
window.history.replaceState(
null,
"",
`${pathname}?${urlParams.toString()}`,
`${pathname}?${urlParams.toString()}`
);
} catch (_) {}
},
@@ -839,7 +839,7 @@ function createUtils() {
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
unit = "Bytes";
}
if ((!unit || thoroughUnitCheck) && id.endsWith("standard-deviation")) {
if ((!unit || thoroughUnitCheck) && id.endsWith("-sd")) {
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
unit = "sd";
}
@@ -1243,8 +1243,8 @@ function createUtils() {
today.getUTCDate(),
0,
0,
0,
),
0
)
);
},
/**
@@ -1265,12 +1265,6 @@ function createUtils() {
return 0;
return this.differenceBetween(date, new Date("2009-01-09"));
},
/**
* @param {Date} start
*/
getRangeUpToToday(start) {
return this.getRange(start, new Date());
},
/**
* @param {Date} start
* @param {Date} end
@@ -1337,7 +1331,7 @@ function createUtils() {
*/
function getNumberOfDaysBetweenTwoDates(oldest, youngest) {
return Math.round(
Math.abs((youngest.getTime() - oldest.getTime()) / date.ONE_DAY_IN_MS),
Math.abs((youngest.getTime() - oldest.getTime()) / date.ONE_DAY_IN_MS)
);
}
@@ -1555,7 +1549,7 @@ function createVecsResources(signals, utils) {
const fetchedRecord = signals.createSignal(
/** @type {Map<string, {loading: boolean, at: Date | null, vec: Signal<T[] | null>}>} */ (
new Map()
),
)
);
return {
@@ -1579,7 +1573,9 @@ function createVecsResources(signals, utils) {
map.set(fetchedKey, {
loading: false,
at: null,
vec: signals.createSignal(/** @type {T[] | null} */ (null)),
vec: signals.createSignal(/** @type {T[] | null} */ (null), {
equals: false,
}),
});
return map;
});
@@ -1603,7 +1599,7 @@ function createVecsResources(signals, utils) {
index,
id,
from,
to,
to
)
);
fetched.at = new Date();
@@ -1864,7 +1860,7 @@ function initWebSockets(signals, utils) {
window.document.addEventListener(
"visibilitychange",
reinitWebSocketIfDocumentNotHidden,
reinitWebSocketIfDocumentNotHidden
);
window.document.addEventListener("online", reinitWebSocket);
@@ -1873,7 +1869,7 @@ function initWebSockets(signals, utils) {
ws?.close();
window.document.removeEventListener(
"visibilitychange",
reinitWebSocketIfDocumentNotHidden,
reinitWebSocketIfDocumentNotHidden
);
window.document.removeEventListener("online", reinitWebSocket);
live.set(false);
@@ -1899,7 +1895,7 @@ function initWebSockets(signals, utils) {
symbol: ["BTC/USD"],
interval: 1440,
},
}),
})
);
});
@@ -1928,7 +1924,7 @@ function initWebSockets(signals, utils) {
/** @type {ReturnType<typeof createWebsocket<CandlestickData>>} */
const kraken1dCandle = createWebsocket((callback) =>
krakenCandleWebSocketCreator(callback),
krakenCandleWebSocketCreator(callback)
);
kraken1dCandle.open();
@@ -1987,7 +1983,7 @@ function main() {
}
const frame = window.document.getElementById(
/** @type {string} */ (input.value),
/** @type {string} */ (input.value)
);
if (!frame) {
@@ -2085,23 +2081,23 @@ function main() {
function initDark() {
const preferredColorSchemeMatchMedia = window.matchMedia(
"(prefers-color-scheme: dark)",
"(prefers-color-scheme: dark)"
);
const dark = signals.createSignal(
preferredColorSchemeMatchMedia.matches,
preferredColorSchemeMatchMedia.matches
);
preferredColorSchemeMatchMedia.addEventListener(
"change",
({ matches }) => {
dark.set(matches);
},
}
);
return dark;
}
const dark = initDark();
const qrcode = signals.createSignal(
/** @type {string | null} */ (null),
/** @type {string | null} */ (null)
);
function createLastHeightResource() {
@@ -2112,7 +2108,7 @@ function main() {
lastHeight.set(h);
},
/** @satisfies {Height} */ (5),
"height",
"height"
);
}
fetchLastHeight();
@@ -2156,10 +2152,10 @@ function main() {
const owner = signals.getOwner();
const chartOption = signals.createSignal(
/** @type {ChartOption | null} */ (null),
/** @type {ChartOption | null} */ (null)
);
const simOption = signals.createSignal(
/** @type {SimulationOption | null} */ (null),
/** @type {SimulationOption | null} */ (null)
);
let previousElement = /** @type {HTMLElement | undefined} */ (
@@ -2205,9 +2201,9 @@ function main() {
webSockets,
vecsResources,
vecIdToIndexes,
}),
),
),
})
)
)
);
}
firstTimeLoadingChart = false;
@@ -2228,8 +2224,8 @@ function main() {
vecsResources,
option,
vecIdToIndexes,
}),
),
})
)
);
}
firstTimeLoadingTable = false;
@@ -2253,9 +2249,9 @@ function main() {
signals,
utils,
vecsResources,
}),
),
),
})
)
)
);
}
firstTimeLoadingSimulation = false;
@@ -2284,42 +2280,42 @@ function main() {
createMobileSwitchEffect();
utils.dom.onFirstIntersection(elements.aside, () =>
signals.runWithOwner(owner, initSelectedFrame),
signals.runWithOwner(owner, initSelectedFrame)
);
}
initSelected();
function initFolders() {
// async function scrollToSelected() {
// if (!options.selected()) throw "Selected should be set by now";
// const selectedId = options.selected().id;
async function scrollToSelected() {
if (!options.selected()) throw "Selected should be set by now";
const selectedId = options.selected().id;
// const path = options.selected().path;
const path = options.selected().path;
// let i = 0;
// while (i !== path.length) {
// try {
// const id = path[i];
// const details = /** @type {HTMLDetailsElement} */ (
// utils.dom.getElementById(id)
// );
// details.open = true;
// i++;
// } catch {
// await utils.next();
// }
// }
let i = 0;
while (i !== path.length) {
try {
const id = path[i];
const details = /** @type {HTMLDetailsElement} */ (
utils.dom.getElementById(id)
);
details.open = true;
i++;
} catch {
await utils.next();
}
}
// await utils.next();
// await utils.next();
await utils.next();
await utils.next();
// utils.dom
// .getElementById(`${selectedId}-nav-selector`)
// .scrollIntoView({
// behavior: "instant",
// block: "center",
// });
// }
utils.dom
.getElementById(`${selectedId}-nav-selector`)
.scrollIntoView({
behavior: "instant",
block: "center",
});
}
utils.dom.onFirstIntersection(elements.nav, () => {
options.treeElement.set(() => {
@@ -2329,7 +2325,9 @@ function main() {
return treeElement;
});
// setTimeout(scrollToSelected, 10);
if (localhost) {
setTimeout(scrollToSelected, 10);
}
});
}
initFolders();
@@ -2362,7 +2360,7 @@ function main() {
if (indexes?.length) {
const maxIndex = Math.min(
(order || indexes).length - 1,
minIndex + RESULTS_PER_PAGE - 1,
minIndex + RESULTS_PER_PAGE - 1
);
list = Array(maxIndex - minIndex + 1);
@@ -2438,7 +2436,7 @@ function main() {
haystack,
needle,
undefined,
infoThresh,
infoThresh
);
if (!result?.[0]?.length || !result?.[1]) {
@@ -2446,7 +2444,7 @@ function main() {
haystack,
needle,
outOfOrder,
infoThresh,
infoThresh
);
}
@@ -2455,7 +2453,7 @@ function main() {
haystack,
needle,
outOfOrder,
infoThresh,
infoThresh
);
}
@@ -2464,7 +2462,7 @@ function main() {
haystack,
needle,
outOfOrder,
infoThresh,
infoThresh
);
}
@@ -2473,7 +2471,7 @@ function main() {
haystack,
needle,
undefined,
infoThresh,
infoThresh
);
}
@@ -2482,7 +2480,7 @@ function main() {
haystack,
needle,
outOfOrder,
infoThresh,
infoThresh
);
}
@@ -2565,7 +2563,7 @@ function main() {
shareDiv.hidden = false;
});
}),
})
);
}
initShare();
@@ -2589,7 +2587,7 @@ function main() {
utils.storage.write(barWidthLocalStorageKey, String(width));
} else {
elements.main.style.width = elements.style.getPropertyValue(
"--default-main-width",
"--default-main-width"
);
utils.storage.remove(barWidthLocalStorageKey);
}
@@ -2626,9 +2624,9 @@ function main() {
window.addEventListener("mouseleave", setResizeFalse);
}
initDesktopResizeBar();
}),
),
),
})
)
)
);
}
main();
+318 -86
View File
@@ -132,9 +132,6 @@ function createPartialOptions(colors) {
* @typedef {"cumulative-"} CumulativePrefix
* @typedef {StartsWith<CumulativePrefix>} CumulativeVecId
* @typedef {WithoutPrefix<CumulativeVecId, CumulativePrefix>} CumulativeVecIdBase
* @typedef {"-sum"} SumSuffix
* @typedef {EndsWith<SumSuffix>} VecIdSum
* @typedef {WithoutSuffix<VecIdSum, SumSuffix>} VecIdSumBase
* @typedef {"-average"} AverageSuffix
* @typedef {EndsWith<AverageSuffix>} VecIdAverage
* @typedef {WithoutSuffix<VecIdAverage, AverageSuffix>} VecIdAverageBase
@@ -832,13 +829,13 @@ function createPartialOptions(colors) {
/**
* @param {Object} args
* @param {VecIdSumBase & CumulativeVecIdBase} args.concat
* @param {CumulativeVecIdBase} args.concat
* @param {string} [args.name]
*/
function createSumCumulativeSeries({ concat, name }) {
return /** @satisfies {AnyFetchedSeriesBlueprint[]} */ ([
{
key: `${concat}-sum`,
key: concat,
title: name ? `${name} Sum` : "Sum",
color: colors.orange,
},
@@ -903,7 +900,7 @@ function createPartialOptions(colors) {
}
/**
* @param {VecIdAverageBase & VecIdSumBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} key
* @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} key
*/
function createAverageSumCumulativeMinMaxPercentilesSeries(key) {
return [
@@ -915,7 +912,7 @@ function createPartialOptions(colors) {
/**
* @param {Object} args
* @param {VecId & VecIdAverageBase & VecIdSumBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.key
* @param {VecId & VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.key
* @param {string} args.name
*/
function createBaseAverageSumCumulativeMinMaxPercentilesSeries({
@@ -933,7 +930,7 @@ function createPartialOptions(colors) {
/**
* @param {Object} args
* @param {VecId & VecIdSumBase & CumulativeVecIdBase} args.key
* @param {VecId & CumulativeVecIdBase} args.key
* @param {string} args.name
*/
function createBaseSumCumulativeSeries({ key, name }) {
@@ -1431,7 +1428,7 @@ function createPartialOptions(colors) {
key: `${fixKey(key)}realized-price`,
name,
color,
}),
})
),
}
: createPriceWithRatio({
@@ -1452,19 +1449,170 @@ function createPartialOptions(colors) {
name: "Profit",
color: colors.green,
}),
createBaseSeries({
key: `cumulative-${fixKey(args.key)}realized-profit`,
name: "Cumulative Profit",
color: colors.green,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}realized-loss`,
name: "Loss",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `cumulative-${fixKey(args.key)}realized-loss`,
name: "Cumulative Loss",
color: colors.red,
defaultActive: false,
}),
createBaseSeries({
key: `${fixKey(args.key)}negative-realized-loss`,
name: "Negative Loss",
color: colors.red,
}),
createBaseSeries({
key: `cumulative-${fixKey(
args.key
)}negative-realized-loss`,
name: "Cumulative Negative Loss",
color: colors.red,
defaultActive: false,
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
args.key
)}realized-profit-relative-to-realized-cap`,
title: "Profit",
color: colors.green,
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
args.key
)}realized-loss-relative-to-realized-cap`,
title: "Loss",
color: colors.red,
options: {
createPriceLine: {
value: 0,
},
},
}),
],
},
{
name: "Net pnl",
title: `${args.title} Net Realized Profit And Loss`,
bottom: list.flatMap(({ color, name, key }) => [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}net-realized-profit-and-loss`,
title: "Net",
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `cumulative-${fixKey(
key
)}net-realized-profit-and-loss`,
title: "Cumulative net",
defaultActive: false,
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `cumulative-${fixKey(
key
)}net-realized-profit-and-loss-30d-change`,
title: "cum net 30d change",
defaultActive: false,
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key
)}net-realized-profit-and-loss-relative-to-realized-cap`,
title: "Net",
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `cumulative-${fixKey(
key
)}net-realized-profit-and-loss-30d-change-relative-to-realized-cap`,
title: "cum net 30d change",
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `cumulative-${fixKey(
key
)}net-realized-profit-and-loss-30d-change-relative-to-market-cap`,
title: "cum net 30d change",
options: {
createPriceLine: {
value: 0,
},
},
}),
]),
},
{
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: "sopr",
options: {
createPriceLine: {
value: 1,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}adjusted-spent-output-profit-ratio`,
title: "asopr",
colors: [colors.yellow, colors.pink],
options: {
createPriceLine: {
value: 1,
},
},
}),
]),
},
]
: [
{
@@ -1475,8 +1623,19 @@ function createPartialOptions(colors) {
return /** @type {const} */ ([
createBaseSeries({
key: `${key}realized-profit`,
name: useGroupName ? name : "Profit",
color: useGroupName ? color : colors.green,
name,
color,
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${key}realized-profit-relative-to-realized-cap`,
title: name,
color,
options: {
createPriceLine: {
value: 0,
},
},
}),
]);
}),
@@ -1489,78 +1648,151 @@ function createPartialOptions(colors) {
return /** @type {const} */ ([
createBaseSeries({
key: `${key}realized-loss`,
name: useGroupName ? name : "Loss",
color: useGroupName ? color : colors.red,
name,
color,
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${key}realized-loss-relative-to-realized-cap`,
title: name,
color,
options: {
createPriceLine: {
value: 0,
},
},
}),
]);
}),
},
]),
{
name: "Net pnl",
title: `${args.title} Net Realized Profit And Loss`,
bottom: list.flatMap(({ color, name, key }) => [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}net-realized-profit-and-loss`,
title: useGroupName ? name : "Net",
color: useGroupName ? color : undefined,
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key,
)}net-realized-profit-and-loss-relative-to-realized-cap`,
title: useGroupName ? name : "Net",
color: useGroupName ? color : undefined,
options: {
createPriceLine: {
value: 0,
},
},
}),
]),
},
...(!("list" in args)
? [
{
name: "sopr",
title: `${args.title} Spent Output Profit Ratio`,
name: "Net pnl",
title: `${args.title} Net Realized Profit And Loss`,
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,
key: `${fixKey(key)}net-realized-profit-and-loss`,
title: name,
color,
options: {
createPriceLine: {
value: 1,
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}adjusted-spent-output-profit-ratio`,
title: useGroupName ? name : "asopr",
color: useGroupName ? color : undefined,
colors: useGroupName
? undefined
: [colors.yellow, colors.pink],
key: `${fixKey(
key
)}net-realized-profit-and-loss-relative-to-realized-cap`,
title: name,
color,
options: {
createPriceLine: {
value: 1,
value: 0,
},
},
}),
]),
},
]
: [
{
name: "cumulative",
tree: [
{
name: "profit",
title: `Cumulative ${args.title} Realized Profit`,
bottom: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
key: `cumulative-${key}realized-profit`,
name,
color,
}),
]);
}),
},
{
name: "loss",
title: `Cumulative ${args.title} Realized Loss`,
bottom: list.flatMap(({ color, name, key: _key }) => {
const key = fixKey(_key);
return /** @type {const} */ ([
createBaseSeries({
key: `cumulative-${key}realized-loss`,
name,
color,
}),
]);
}),
},
{
name: "Net pnl",
title: `Cumulative ${args.title} Net Realized Profit And Loss`,
bottom: list.flatMap(({ color, name, key }) => [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `cumulative-${fixKey(
key
)}net-realized-profit-and-loss`,
title: name,
color,
defaultActive: false,
options: {
createPriceLine: {
value: 0,
},
},
}),
]),
},
{
name: "Net pnl 30d change",
title: `Cumulative ${args.title} Net Realized Profit And Loss 30 Day Change`,
bottom: list.flatMap(({ color, name, key }) => [
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `cumulative-${fixKey(
key
)}net-realized-profit-and-loss-30d-change`,
title: name,
color,
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `cumulative-${fixKey(
key
)}net-realized-profit-and-loss-30d-change-relative-to-realized-cap`,
title: name,
color,
options: {
createPriceLine: {
value: 0,
},
},
}),
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `cumulative-${fixKey(
key
)}net-realized-profit-and-loss-30d-change-relative-to-market-cap`,
title: name,
color,
options: {
createPriceLine: {
value: 0,
},
},
}),
]),
},
],
},
{
name: "sopr",
tree: [
@@ -1571,8 +1803,8 @@ function createPartialOptions(colors) {
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(key)}spent-output-profit-ratio`,
title: useGroupName ? name : "sopr",
color: useGroupName ? color : undefined,
title: name,
color,
options: {
createPriceLine: {
value: 1,
@@ -1588,10 +1820,10 @@ function createPartialOptions(colors) {
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key,
key
)}adjusted-spent-output-profit-ratio`,
title: useGroupName ? name : "asopr",
color: useGroupName ? color : undefined,
title: name,
color,
options: {
createPriceLine: {
value: 1,
@@ -1611,7 +1843,7 @@ function createPartialOptions(colors) {
key: `${fixKey(key)}sell-side-risk-ratio`,
name: useGroupName ? name : "Risk",
color: color,
}),
})
),
},
],
@@ -1700,7 +1932,7 @@ function createPartialOptions(colors) {
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
type: "Baseline",
key: `${fixKey(
key,
key
)}net-unrealized-profit-and-loss-relative-to-market-cap`,
title: useGroupName ? name : "Net",
color: useGroupName ? color : undefined,
@@ -1878,7 +2110,7 @@ function createPartialOptions(colors) {
key: `${key}-sma`,
name: key,
color,
}),
})
),
},
...averages.map(({ key, name, color }) =>
@@ -1888,7 +2120,7 @@ function createPartialOptions(colors) {
title: `${name} Market Price Moving Average`,
legend: "average",
color,
}),
})
),
],
},
@@ -1929,8 +2161,8 @@ function createPartialOptions(colors) {
name: "Indicators",
tree: [
{
name: "Mayer's multiple",
title: "Mayer's multiple",
name: "Mayer multiple",
title: "Mayer multiple",
top: [
createBaseSeries({
key: `200d-sma`,
@@ -2005,7 +2237,7 @@ function createPartialOptions(colors) {
},
}),
],
}),
})
),
.../** @type {const} */ ([
{ name: "2 Year", key: "2y" },
@@ -2076,7 +2308,7 @@ function createPartialOptions(colors) {
},
}),
],
}),
})
),
],
},
@@ -2092,7 +2324,7 @@ function createPartialOptions(colors) {
name: `${year}`,
color,
defaultActive,
}),
})
),
},
...dcaClasses.map(
@@ -2119,7 +2351,7 @@ function createPartialOptions(colors) {
},
}),
],
}),
})
),
],
},
@@ -2180,10 +2412,10 @@ function createPartialOptions(colors) {
bottom: [
...createAverageSumCumulativeMinMaxPercentilesSeries("fee"),
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee-in-btc",
"fee-in-btc"
),
...createAverageSumCumulativeMinMaxPercentilesSeries(
"fee-in-usd",
"fee-in-usd"
),
],
},
@@ -2779,7 +3011,7 @@ function createPartialOptions(colors) {
bottom: [
createBaseSeries({ key: "opreturn-count", name: "Count" }),
createBaseSeries({
key: "opreturn-count-sum",
key: "opreturn-count",
name: "sum",
}),
createBaseSeries({
@@ -2939,7 +3171,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
const detailsList = [];
const treeElement = signals.createSignal(
/** @type {HTMLDivElement | null} */ (null),
/** @type {HTMLDivElement | null} */ (null)
);
/** @type {string[] | undefined} */
@@ -3051,7 +3283,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
return null;
}
},
null,
null
);
partialTree.forEach((anyPartial, partialIndex) => {
@@ -3074,7 +3306,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
if ("tree" in anyPartial) {
const folderId = utils.stringToId(
`${(path || []).join(" ")} ${anyPartial.name} folder`,
`${(path || []).join(" ")} ${anyPartial.name} folder`
);
/** @type {Omit<OptionsGroup, keyof PartialOptionsGroup>} */
@@ -3089,13 +3321,13 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
const thisPath = groupAddons.id;
const passedDetails = signals.createSignal(
/** @type {HTMLDivElement | HTMLDetailsElement | null} */ (null),
/** @type {HTMLDivElement | HTMLDetailsElement | null} */ (null)
);
const childOptionsCount = recursiveProcessPartialTree(
anyPartial.tree,
passedDetails,
[...(path || []), thisPath],
[...(path || []), thisPath]
);
listForSum.push(childOptionsCount);
@@ -3227,7 +3459,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
});
return signals.createMemo(() =>
listForSum.reduce((acc, s) => acc + s(), 0),
listForSum.reduce((acc, s) => acc + s(), 0)
);
}
recursiveProcessPartialTree(partialOptions, treeElement);
@@ -3254,7 +3486,7 @@ export function initOptions({ colors, signals, env, utils, qrcode }) {
console.log(
[...m.entries()]
.filter(([_, value]) => value > 1)
.map(([key, _]) => key),
.map(([key, _]) => key)
);
throw Error("ID duplicate");
File diff suppressed because it is too large Load Diff