mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-05-20 23:04:46 -07:00
global: snapshot
This commit is contained in:
@@ -12,10 +12,16 @@
|
||||
## Datasets
|
||||
|
||||
- Added `Sell Side Risk Ratio` to all entities
|
||||
- Added `Adjusted Value Created`, `Adjusted Value Destroyed` and `Adjusted Spent Output Profit Ratio` to all entities
|
||||
- Added `Open`, `High` and `Low` datasets
|
||||
- Added `Satoshis Per Dollar`
|
||||
- Added `All Time High`
|
||||
- Added `All Time High Date`
|
||||
- Added `Days Since All Time High`
|
||||
- Added `Max Days Between All Time Highs`
|
||||
- Added `Max Years Between All Time Highs`
|
||||
- Added `Drawdown`
|
||||
- Added `Adjusted Value Created`, `Adjusted Value Destroyed` and `Adjusted Spent Output Profit Ratio` to all entities
|
||||
- Added `Realized Profit To Loss Ratio` to all entities
|
||||
- Removed datasets split by liquidity for all datasets already split by any address kind, while fun to have, they took time to compute, ram, and space to store and no one was actually checking them
|
||||
- Fixed a lot of values in split by liquidity datasets
|
||||
|
||||
|
||||
2
biter/Cargo.lock
generated
2
biter/Cargo.lock
generated
@@ -110,7 +110,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "biter"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
|
||||
@@ -10,7 +10,6 @@ allocative = "0.3.3"
|
||||
bincode = { git = "https://github.com/bincode-org/bincode.git", features = [
|
||||
"serde",
|
||||
] }
|
||||
# biter = "0.1.0"
|
||||
biter = { path = "../biter" }
|
||||
bitcoin_hashes = { version = "0.14.0" }
|
||||
chrono = { version = "0.4.38", features = ["serde"] }
|
||||
|
||||
@@ -27,12 +27,10 @@ pub fn iter_blocks(
|
||||
log("Starting...");
|
||||
|
||||
let mut datasets = AllDatasets::import()?;
|
||||
// RAM: 200MB at this point
|
||||
|
||||
log("Imported datasets");
|
||||
|
||||
let mut databases = Databases::import();
|
||||
// RAM: 200MB too
|
||||
|
||||
log("Imported databases");
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ type Database = _Database<Key, Value>;
|
||||
pub struct AddressIndexToAddressData {
|
||||
pub metadata: Metadata,
|
||||
|
||||
map: BTreeMap<usize, Database>,
|
||||
pub map: BTreeMap<usize, Database>,
|
||||
}
|
||||
|
||||
impl Deref for AddressIndexToAddressData {
|
||||
@@ -99,7 +99,7 @@ impl AddressIndexToAddressData {
|
||||
})
|
||||
}
|
||||
|
||||
fn open_all(&mut self) {
|
||||
pub fn open_all(&mut self) {
|
||||
let path = Self::full_path();
|
||||
|
||||
fs::create_dir_all(&path).unwrap();
|
||||
|
||||
@@ -19,7 +19,7 @@ type Database = _Database<Key, Value>;
|
||||
pub struct TxoutIndexToAmount {
|
||||
pub metadata: Metadata,
|
||||
|
||||
pub map: BTreeMap<usize, Database>,
|
||||
map: BTreeMap<usize, Database>,
|
||||
}
|
||||
|
||||
impl Deref for TxoutIndexToAmount {
|
||||
|
||||
@@ -186,7 +186,7 @@ impl CointimeDataset {
|
||||
.multi_insert_simple_transform(
|
||||
heights,
|
||||
&mut circulating_supply.height,
|
||||
|circulating_supply| circulating_supply as f32,
|
||||
|circulating_supply, _| circulating_supply as f32,
|
||||
);
|
||||
self.coinblocks_created
|
||||
.multi_date_insert_sum_range(dates, first_height, last_height);
|
||||
@@ -414,7 +414,7 @@ impl CointimeDataset {
|
||||
.multi_insert_complex_transform(
|
||||
dates,
|
||||
&mut self.active_cap.date,
|
||||
|(active_cap, date, _)| {
|
||||
|(active_cap, date, _, _)| {
|
||||
let investor_cap = self.investor_cap.date.get(date).unwrap();
|
||||
(active_cap - investor_cap) / active_cap
|
||||
},
|
||||
|
||||
@@ -215,14 +215,14 @@ impl AllDatasets {
|
||||
|
||||
self.address.compute(
|
||||
&compute_data,
|
||||
&mut self.price.closes,
|
||||
&mut self.price.close,
|
||||
&mut self.mining.cumulative_subsidy,
|
||||
&mut self.price.market_cap,
|
||||
);
|
||||
|
||||
self.utxo.compute(
|
||||
&compute_data,
|
||||
&mut self.price.closes,
|
||||
&mut self.price.close,
|
||||
&mut self.mining.cumulative_subsidy,
|
||||
&mut self.price.market_cap,
|
||||
);
|
||||
@@ -255,7 +255,7 @@ impl AllDatasets {
|
||||
&compute_data,
|
||||
&mut self.date_metadata.first_height,
|
||||
&mut self.date_metadata.last_height,
|
||||
&mut self.price.closes,
|
||||
&mut self.price.close,
|
||||
&mut self.mining.cumulative_subsidy,
|
||||
&mut self.address.cohorts.all.subs.capitalization.realized_cap,
|
||||
&mut self.address.cohorts.all.subs.capitalization.realized_price,
|
||||
|
||||
@@ -32,10 +32,13 @@ pub struct PriceDatasets {
|
||||
kibo_by_date: BTreeMap<DateMapChunkId, BTreeMap<Date, OHLC>>,
|
||||
|
||||
// Inserted
|
||||
pub ohlcs: BiMap<OHLC>,
|
||||
pub ohlc: BiMap<OHLC>,
|
||||
|
||||
// Computed
|
||||
pub closes: BiMap<f32>,
|
||||
pub open: BiMap<f32>,
|
||||
pub high: BiMap<f32>,
|
||||
pub low: BiMap<f32>,
|
||||
pub close: BiMap<f32>,
|
||||
pub market_cap: BiMap<f32>,
|
||||
pub price_1w_sma: BiMap<f32>,
|
||||
pub price_1w_sma_ratio: RatioDataset,
|
||||
@@ -76,6 +79,10 @@ pub struct PriceDatasets {
|
||||
pub price_4y_compound_return: DateMap<f32>,
|
||||
// projection via lowest 4y compound value
|
||||
pub all_time_high: BiMap<f32>,
|
||||
pub all_time_high_date: DateMap<Date>,
|
||||
pub days_since_all_time_high: DateMap<u32>,
|
||||
pub max_days_between_all_time_highs: DateMap<u32>,
|
||||
pub max_years_between_all_time_highs: DateMap<f32>,
|
||||
pub market_price_to_all_time_high_ratio: BiMap<f32>,
|
||||
pub drawdown: BiMap<f32>,
|
||||
pub sats_per_dollar: BiMap<f32>,
|
||||
@@ -99,8 +106,11 @@ impl PriceDatasets {
|
||||
kibo_by_height: BTreeMap::default(),
|
||||
kibo_by_date: BTreeMap::default(),
|
||||
|
||||
ohlcs: BiMap::new_json(1, price_path),
|
||||
closes: BiMap::new_bin(1, &f("close")),
|
||||
ohlc: BiMap::new_json(1, price_path),
|
||||
open: BiMap::new_bin(1, &f("open")),
|
||||
high: BiMap::new_bin(1, &f("high")),
|
||||
low: BiMap::new_bin(1, &f("low")),
|
||||
close: BiMap::new_bin(1, &f("close")),
|
||||
market_cap: BiMap::new_bin(1, &f("market_cap")),
|
||||
price_1w_sma: BiMap::new_bin(1, &f("price_1w_sma")),
|
||||
price_1w_sma_ratio: RatioDataset::import(datasets_path, "price_1w_sma")?,
|
||||
@@ -140,6 +150,16 @@ impl PriceDatasets {
|
||||
price_10y_total_return: DateMap::new_bin(1, &f("price_10y_total_return")),
|
||||
price_4y_compound_return: DateMap::new_bin(1, &f("price_4y_compound_return")),
|
||||
all_time_high: BiMap::new_bin(1, &f("all_time_high")),
|
||||
all_time_high_date: DateMap::new_bin(1, &f("all_time_high_date")),
|
||||
days_since_all_time_high: DateMap::new_bin(1, &f("days_since_all_time_high")),
|
||||
max_days_between_all_time_highs: DateMap::new_bin(
|
||||
1,
|
||||
&f("max_days_between_all_time_highs"),
|
||||
),
|
||||
max_years_between_all_time_highs: DateMap::new_bin(
|
||||
2,
|
||||
&f("max_years_between_all_time_highs"),
|
||||
),
|
||||
market_price_to_all_time_high_ratio: BiMap::new_bin(
|
||||
1,
|
||||
&f("market_price_to_all_time_high_ratio"),
|
||||
@@ -157,128 +177,137 @@ impl PriceDatasets {
|
||||
pub fn compute(&mut self, compute_data: &ComputeData, circulating_supply: &mut BiMap<f64>) {
|
||||
let &ComputeData { dates, heights, .. } = compute_data;
|
||||
|
||||
self.closes
|
||||
.multi_insert_simple_transform(heights, dates, &mut self.ohlcs, &|ohlc| ohlc.close);
|
||||
self.open
|
||||
.multi_insert_simple_transform(heights, dates, &mut self.ohlc, &|ohlc| ohlc.open);
|
||||
|
||||
self.high
|
||||
.multi_insert_simple_transform(heights, dates, &mut self.ohlc, &|ohlc| ohlc.high);
|
||||
|
||||
self.low
|
||||
.multi_insert_simple_transform(heights, dates, &mut self.ohlc, &|ohlc| ohlc.low);
|
||||
|
||||
self.close
|
||||
.multi_insert_simple_transform(heights, dates, &mut self.ohlc, &|ohlc| ohlc.close);
|
||||
|
||||
self.market_cap
|
||||
.multi_insert_multiply(heights, dates, &mut self.closes, circulating_supply);
|
||||
.multi_insert_multiply(heights, dates, &mut self.close, circulating_supply);
|
||||
|
||||
self.price_1w_sma.multi_insert_simple_average(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.closes,
|
||||
&mut self.close,
|
||||
ONE_WEEK_IN_DAYS,
|
||||
);
|
||||
|
||||
self.price_1m_sma.multi_insert_simple_average(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.closes,
|
||||
&mut self.close,
|
||||
ONE_MONTH_IN_DAYS,
|
||||
);
|
||||
|
||||
self.price_1y_sma.multi_insert_simple_average(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.closes,
|
||||
&mut self.close,
|
||||
ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
|
||||
self.price_2y_sma.multi_insert_simple_average(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.closes,
|
||||
&mut self.close,
|
||||
2 * ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
|
||||
self.price_4y_sma.multi_insert_simple_average(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.closes,
|
||||
&mut self.close,
|
||||
4 * ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
|
||||
self.price_8d_sma
|
||||
.multi_insert_simple_average(heights, dates, &mut self.closes, 8);
|
||||
.multi_insert_simple_average(heights, dates, &mut self.close, 8);
|
||||
|
||||
self.price_13d_sma
|
||||
.multi_insert_simple_average(heights, dates, &mut self.closes, 13);
|
||||
.multi_insert_simple_average(heights, dates, &mut self.close, 13);
|
||||
|
||||
self.price_21d_sma
|
||||
.multi_insert_simple_average(heights, dates, &mut self.closes, 21);
|
||||
.multi_insert_simple_average(heights, dates, &mut self.close, 21);
|
||||
|
||||
self.price_34d_sma
|
||||
.multi_insert_simple_average(heights, dates, &mut self.closes, 34);
|
||||
.multi_insert_simple_average(heights, dates, &mut self.close, 34);
|
||||
|
||||
self.price_55d_sma
|
||||
.multi_insert_simple_average(heights, dates, &mut self.closes, 55);
|
||||
.multi_insert_simple_average(heights, dates, &mut self.close, 55);
|
||||
|
||||
self.price_89d_sma
|
||||
.multi_insert_simple_average(heights, dates, &mut self.closes, 89);
|
||||
.multi_insert_simple_average(heights, dates, &mut self.close, 89);
|
||||
|
||||
self.price_144d_sma
|
||||
.multi_insert_simple_average(heights, dates, &mut self.closes, 144);
|
||||
.multi_insert_simple_average(heights, dates, &mut self.close, 144);
|
||||
|
||||
self.price_200w_sma.multi_insert_simple_average(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.closes,
|
||||
&mut self.close,
|
||||
200 * ONE_WEEK_IN_DAYS,
|
||||
);
|
||||
|
||||
self.price_1d_total_return
|
||||
.multi_insert_percentage_change(dates, &mut self.closes.date, 1);
|
||||
.multi_insert_percentage_change(dates, &mut self.close.date, 1);
|
||||
self.price_1m_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
ONE_MONTH_IN_DAYS,
|
||||
);
|
||||
self.price_6m_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
6 * ONE_MONTH_IN_DAYS,
|
||||
);
|
||||
self.price_1y_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
self.price_2y_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
2 * ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
self.price_3y_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
3 * ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
self.price_4y_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
4 * ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
self.price_6y_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
6 * ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
self.price_8y_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
8 * ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
self.price_10y_total_return.multi_insert_percentage_change(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
&mut self.close.date,
|
||||
10 * ONE_YEAR_IN_DAYS,
|
||||
);
|
||||
|
||||
self.price_4y_compound_return
|
||||
.multi_insert_complex_transform(
|
||||
dates,
|
||||
&mut self.closes.date,
|
||||
|(last_value, date, closes)| {
|
||||
&mut self.close.date,
|
||||
|(last_value, date, closes, _)| {
|
||||
let previous_value = date
|
||||
.checked_sub_days(Days::new(4 * ONE_YEAR_IN_DAYS as u64))
|
||||
.and_then(|date| closes.get_or_import(&Date::wrap(date)))
|
||||
@@ -289,37 +318,69 @@ impl PriceDatasets {
|
||||
);
|
||||
|
||||
self.price_1w_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_1w_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_1w_sma);
|
||||
self.price_1m_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_1m_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_1m_sma);
|
||||
self.price_1y_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_1y_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_1y_sma);
|
||||
self.price_2y_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_2y_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_2y_sma);
|
||||
self.price_4y_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_4y_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_4y_sma);
|
||||
self.price_8d_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_8d_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_8d_sma);
|
||||
self.price_13d_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_13d_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_13d_sma);
|
||||
self.price_21d_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_21d_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_21d_sma);
|
||||
self.price_34d_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_34d_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_34d_sma);
|
||||
self.price_55d_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_55d_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_55d_sma);
|
||||
self.price_89d_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_89d_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_89d_sma);
|
||||
self.price_144d_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_144d_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_144d_sma);
|
||||
self.price_200w_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_200w_sma);
|
||||
.compute(compute_data, &mut self.close, &mut self.price_200w_sma);
|
||||
|
||||
self.all_time_high
|
||||
.multi_insert_max(heights, dates, &mut self.closes);
|
||||
.multi_insert_max(heights, dates, &mut self.high);
|
||||
|
||||
self.market_price_to_all_time_high_ratio
|
||||
.multi_insert_percentage(heights, dates, &mut self.closes, &mut self.all_time_high);
|
||||
.multi_insert_percentage(heights, dates, &mut self.close, &mut self.all_time_high);
|
||||
|
||||
self.all_time_high_date.multi_insert_complex_transform(
|
||||
dates,
|
||||
&mut self.all_time_high.date,
|
||||
|(value, date, _, map)| {
|
||||
let high = self.high.date.get(date).unwrap();
|
||||
let is_ath = high == value;
|
||||
|
||||
if is_ath {
|
||||
*date
|
||||
} else {
|
||||
let previous_date = date.checked_sub(1).unwrap();
|
||||
*map.get(&previous_date).as_ref().unwrap_or(date)
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
self.days_since_all_time_high.multi_insert_simple_transform(
|
||||
dates,
|
||||
&mut self.all_time_high_date,
|
||||
|value, key| key.difference_in_days_between(value),
|
||||
);
|
||||
|
||||
self.max_days_between_all_time_highs
|
||||
.multi_insert_max(dates, &mut self.days_since_all_time_high);
|
||||
|
||||
self.max_years_between_all_time_highs
|
||||
.multi_insert_simple_transform(
|
||||
dates,
|
||||
&mut self.max_days_between_all_time_highs,
|
||||
|days, _| (days as f64 / ONE_YEAR_IN_DAYS as f64) as f32,
|
||||
);
|
||||
|
||||
self.drawdown.multi_insert_simple_transform(
|
||||
heights,
|
||||
@@ -331,21 +392,21 @@ impl PriceDatasets {
|
||||
self.sats_per_dollar.multi_insert_simple_transform(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.closes,
|
||||
&mut self.close,
|
||||
&|price| Amount::ONE_BTC_F32 / price,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_date_ohlc(&mut self, date: Date) -> color_eyre::Result<OHLC> {
|
||||
if self.ohlcs.date.is_key_safe(date) {
|
||||
Ok(self.ohlcs.date.get(&date).unwrap().to_owned())
|
||||
if self.ohlc.date.is_key_safe(date) {
|
||||
Ok(self.ohlc.date.get(&date).unwrap().to_owned())
|
||||
} else {
|
||||
let ohlc = self
|
||||
.get_from_daily_kraken(&date)
|
||||
.or_else(|_| self.get_from_daily_binance(&date))
|
||||
.or_else(|_| self.get_from_date_kibo(&date))?;
|
||||
|
||||
self.ohlcs.date.insert(date, ohlc);
|
||||
self.ohlc.date.insert(date, ohlc);
|
||||
|
||||
Ok(ohlc)
|
||||
}
|
||||
@@ -427,7 +488,7 @@ impl PriceDatasets {
|
||||
timestamp: Timestamp,
|
||||
previous_timestamp: Option<Timestamp>,
|
||||
) -> color_eyre::Result<OHLC> {
|
||||
if let Some(ohlc) = self.ohlcs.height.get(&height) {
|
||||
if let Some(ohlc) = self.ohlc.height.get(&height) {
|
||||
return Ok(ohlc);
|
||||
}
|
||||
|
||||
@@ -469,7 +530,7 @@ How to fix this:
|
||||
})
|
||||
});
|
||||
|
||||
self.ohlcs.height.insert(height, ohlc);
|
||||
self.ohlc.height.insert(height, ohlc);
|
||||
|
||||
Ok(ohlc)
|
||||
}
|
||||
@@ -617,16 +678,19 @@ impl AnyDataset for PriceDatasets {
|
||||
}
|
||||
|
||||
fn to_inserted_bi_map_vec(&self) -> Vec<&(dyn AnyBiMap + Send + Sync)> {
|
||||
vec![&self.ohlcs]
|
||||
vec![&self.ohlc]
|
||||
}
|
||||
|
||||
fn to_inserted_mut_bi_map_vec(&mut self) -> Vec<&mut dyn AnyBiMap> {
|
||||
vec![&mut self.ohlcs]
|
||||
vec![&mut self.ohlc]
|
||||
}
|
||||
|
||||
fn to_computed_bi_map_vec(&self) -> Vec<&(dyn AnyBiMap + Send + Sync)> {
|
||||
let mut v = vec![
|
||||
&self.closes as &(dyn AnyBiMap + Send + Sync),
|
||||
&self.open as &(dyn AnyBiMap + Send + Sync),
|
||||
&self.high,
|
||||
&self.low,
|
||||
&self.close,
|
||||
&self.market_cap,
|
||||
&self.price_1w_sma,
|
||||
&self.price_1m_sma,
|
||||
@@ -666,7 +730,10 @@ impl AnyDataset for PriceDatasets {
|
||||
|
||||
fn to_computed_mut_bi_map_vec(&mut self) -> Vec<&mut dyn AnyBiMap> {
|
||||
let mut v = vec![
|
||||
&mut self.closes as &mut dyn AnyBiMap,
|
||||
&mut self.open as &mut dyn AnyBiMap,
|
||||
&mut self.high,
|
||||
&mut self.low,
|
||||
&mut self.close,
|
||||
&mut self.market_cap,
|
||||
&mut self.price_1w_sma,
|
||||
&mut self.price_1m_sma,
|
||||
@@ -717,6 +784,10 @@ impl AnyDataset for PriceDatasets {
|
||||
&self.price_8y_total_return,
|
||||
&self.price_10y_total_return,
|
||||
&self.price_4y_compound_return,
|
||||
&self.all_time_high_date,
|
||||
&self.days_since_all_time_high,
|
||||
&self.max_days_between_all_time_highs,
|
||||
&self.max_years_between_all_time_highs,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -733,6 +804,10 @@ impl AnyDataset for PriceDatasets {
|
||||
&mut self.price_8y_total_return,
|
||||
&mut self.price_10y_total_return,
|
||||
&mut self.price_4y_compound_return,
|
||||
&mut self.all_time_high_date,
|
||||
&mut self.days_since_all_time_high,
|
||||
&mut self.max_days_between_all_time_highs,
|
||||
&mut self.max_years_between_all_time_highs,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ impl RatioDataset {
|
||||
|
||||
self.ratio_1y_sma_momentum_oscillator
|
||||
.date
|
||||
.multi_insert_complex_transform(dates, &mut self.ratio.date, |(ratio, date, _)| {
|
||||
.multi_insert_complex_transform(dates, &mut self.ratio.date, |(ratio, date, _, _)| {
|
||||
(ratio / self.ratio_1y_sma.date.get_or_import(date).unwrap()) - 1.0
|
||||
});
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ pub struct RealizedSubDataset {
|
||||
cumulative_net_realized_profit_and_loss_1m_net_change: BiMap<f32>,
|
||||
realized_value: BiMap<f32>,
|
||||
sell_side_risk_ratio: DateMap<f32>,
|
||||
realized_profit_to_loss_ratio: BiMap<f32>,
|
||||
}
|
||||
|
||||
impl RealizedSubDataset {
|
||||
@@ -77,6 +78,7 @@ impl RealizedSubDataset {
|
||||
),
|
||||
realized_value: BiMap::new_bin(1, &f("realized_value")),
|
||||
sell_side_risk_ratio: DateMap::new_bin(1, &f("sell_side_risk_ratio")),
|
||||
realized_profit_to_loss_ratio: BiMap::new_bin(1, &f("realized_profit_to_loss_ratio")),
|
||||
};
|
||||
|
||||
s.min_initial_states
|
||||
@@ -243,6 +245,13 @@ impl RealizedSubDataset {
|
||||
&mut self.realized_value.date,
|
||||
&mut market_cap.date,
|
||||
);
|
||||
|
||||
self.realized_profit_to_loss_ratio.multi_insert_divide(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.realized_profit,
|
||||
&mut self.realized_loss,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,6 +296,7 @@ impl AnyDataset for RealizedSubDataset {
|
||||
&self.cumulative_net_realized_profit_and_loss,
|
||||
&self.cumulative_net_realized_profit_and_loss_1m_net_change,
|
||||
&self.realized_value,
|
||||
&self.realized_profit_to_loss_ratio,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -304,6 +314,7 @@ impl AnyDataset for RealizedSubDataset {
|
||||
&mut self.cumulative_net_realized_profit_and_loss,
|
||||
&mut self.cumulative_net_realized_profit_and_loss_1m_net_change,
|
||||
&mut self.realized_value,
|
||||
&mut self.realized_profit_to_loss_ratio,
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ impl TransactionDataset {
|
||||
|
||||
self.transactions_per_second
|
||||
.date
|
||||
.multi_insert_simple_transform(dates, &mut self.count.date, |count| {
|
||||
.multi_insert_simple_transform(dates, &mut self.count.date, |count, _| {
|
||||
count as f32 / ONE_DAY_IN_S as f32
|
||||
});
|
||||
|
||||
|
||||
@@ -67,21 +67,21 @@ where
|
||||
self.date.multi_insert_const(dates, constant);
|
||||
}
|
||||
|
||||
pub fn multi_insert_simple_transform<F, K>(
|
||||
pub fn multi_insert_simple_transform<F, V>(
|
||||
&mut self,
|
||||
heights: &[Height],
|
||||
dates: &[Date],
|
||||
source: &mut BiMap<K>,
|
||||
source: &mut BiMap<V>,
|
||||
transform: &F,
|
||||
) where
|
||||
Value: Div<Output = Value>,
|
||||
F: Fn(K) -> Value,
|
||||
K: MapValue,
|
||||
F: Fn(V) -> Value,
|
||||
V: MapValue,
|
||||
{
|
||||
self.height
|
||||
.multi_insert_simple_transform(heights, &mut source.height, transform);
|
||||
.multi_insert_simple_transform(heights, &mut source.height, |v, _| transform(v));
|
||||
self.date
|
||||
.multi_insert_simple_transform(dates, &mut source.date, transform);
|
||||
.multi_insert_simple_transform(dates, &mut source.date, |v, _| transform(v));
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
|
||||
@@ -45,6 +45,10 @@ impl Date {
|
||||
pub fn yesterday() -> Self {
|
||||
Self(Self::today().checked_sub_days(Days::new(1)).unwrap())
|
||||
}
|
||||
|
||||
pub fn difference_in_days_between(&self, older: Self) -> u32 {
|
||||
(**self - *older).num_days() as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl MapKey<DateMapChunkId> for Date {
|
||||
|
||||
@@ -21,8 +21,8 @@ impl MapChunkId for DateMapChunkId {
|
||||
self.0.to_string()
|
||||
}
|
||||
|
||||
fn from_path(path: &Path) -> Self {
|
||||
Self(
|
||||
fn from_path(path: &Path) -> color_eyre::Result<Self> {
|
||||
Ok(Self(
|
||||
path.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
@@ -30,9 +30,8 @@ impl MapChunkId for DateMapChunkId {
|
||||
.split(".")
|
||||
.next()
|
||||
.unwrap()
|
||||
.parse::<i32>()
|
||||
.unwrap(),
|
||||
)
|
||||
.parse::<i32>()?,
|
||||
))
|
||||
}
|
||||
|
||||
fn to_usize(self) -> usize {
|
||||
|
||||
@@ -63,7 +63,7 @@ where
|
||||
Self: Ord + Debug + Copy + Clone,
|
||||
{
|
||||
fn to_name(&self) -> String;
|
||||
fn from_path(path: &Path) -> Self;
|
||||
fn from_path(path: &Path) -> color_eyre::Result<Self>;
|
||||
fn to_usize(self) -> usize;
|
||||
fn from_usize(id: usize) -> Self;
|
||||
}
|
||||
@@ -189,9 +189,12 @@ where
|
||||
.unwrap()
|
||||
.map(|entry| entry.unwrap().path())
|
||||
.filter(|path| serialization.is_serializable(path))
|
||||
.map(|path| {
|
||||
let chunk_id = ChunkId::from_path(&path);
|
||||
(chunk_id, path)
|
||||
.flat_map(|path| {
|
||||
if let Ok(chunk_id) = ChunkId::from_path(&path) {
|
||||
Some((chunk_id, path))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -414,10 +417,10 @@ where
|
||||
) where
|
||||
SourceValue: MapValue,
|
||||
SourceSerialized: MapSerialized<Key, SourceValue, ChunkId>,
|
||||
F: Fn(SourceValue) -> Value,
|
||||
F: Fn(SourceValue, &Key) -> Value,
|
||||
{
|
||||
keys.iter().for_each(|key| {
|
||||
self.insert(*key, transform(source.get_or_import(key).unwrap()));
|
||||
self.insert(*key, transform(source.get_or_import(key).unwrap(), key));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -434,13 +437,14 @@ where
|
||||
SourceValue,
|
||||
&Key,
|
||||
&mut GenericMap<Key, SourceValue, ChunkId, SourceSerialized>,
|
||||
&Self,
|
||||
),
|
||||
) -> Value,
|
||||
{
|
||||
keys.iter().for_each(|key| {
|
||||
self.insert(
|
||||
*key,
|
||||
transform((source.get_or_import(key).unwrap(), key, source)),
|
||||
transform((source.get_or_import(key).unwrap(), key, source, self)),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -823,31 +827,27 @@ where
|
||||
where
|
||||
Value: Default + PartialOrd,
|
||||
{
|
||||
let mut max = None;
|
||||
let mut previous_max = None;
|
||||
|
||||
keys.iter().for_each(|key| {
|
||||
let previous_max = max.unwrap_or_else(|| {
|
||||
if previous_max.is_none() {
|
||||
key.checked_sub(1)
|
||||
.and_then(|previous_max_key| self.get(&previous_max_key))
|
||||
.unwrap_or_default()
|
||||
});
|
||||
.and_then(|v| previous_max.replace(v));
|
||||
}
|
||||
|
||||
let last_value = source.get_or_import(key).unwrap_or_else(|| {
|
||||
dbg!(key);
|
||||
panic!()
|
||||
});
|
||||
|
||||
if max.is_none() || last_value > previous_max {
|
||||
max.replace(last_value);
|
||||
if previous_max.is_none()
|
||||
|| previous_max.is_some_and(|previous_max| previous_max < last_value)
|
||||
{
|
||||
previous_max.replace(last_value);
|
||||
}
|
||||
|
||||
self.insert(
|
||||
*key,
|
||||
max.unwrap_or_else(|| {
|
||||
dbg!(previous_max, last_value, max);
|
||||
panic!();
|
||||
}),
|
||||
);
|
||||
self.insert(*key, previous_max.unwrap());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ impl MapChunkId for HeightMapChunkId {
|
||||
format!("{start}..{end}")
|
||||
}
|
||||
|
||||
fn from_path(path: &Path) -> Self {
|
||||
Self(Height::new(
|
||||
fn from_path(path: &Path) -> color_eyre::Result<Self> {
|
||||
Ok(Self(Height::new(
|
||||
path.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
@@ -37,12 +37,8 @@ impl MapChunkId for HeightMapChunkId {
|
||||
.split("..")
|
||||
.next()
|
||||
.unwrap()
|
||||
.parse::<u32>()
|
||||
.unwrap_or_else(|_| {
|
||||
dbg!(path);
|
||||
panic!()
|
||||
}),
|
||||
))
|
||||
.parse::<u32>()?,
|
||||
)))
|
||||
}
|
||||
|
||||
fn to_usize(self) -> usize {
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<script type="module" crossorigin src="./script.js"></script>
|
||||
|
||||
<!-- ------ -->
|
||||
<!-- Styles -->
|
||||
<!-- ------ -->
|
||||
|
||||
<!-- Tailwind Base -->
|
||||
<style>
|
||||
/* Tailwind base */
|
||||
|
||||
*,
|
||||
::after,
|
||||
::before,
|
||||
@@ -217,6 +218,7 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Custom -->
|
||||
<style>
|
||||
:root {
|
||||
--default-font-family: "Satoshi";
|
||||
@@ -803,6 +805,23 @@
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
summary {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
&::marker,
|
||||
&::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--orange);
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -888,21 +907,8 @@
|
||||
}
|
||||
|
||||
> details > summary {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
|
||||
&::marker,
|
||||
&::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--orange);
|
||||
}
|
||||
|
||||
details[open] > & {
|
||||
&::after {
|
||||
content: "";
|
||||
@@ -1024,49 +1030,56 @@
|
||||
}
|
||||
|
||||
> #dashboards {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 50;
|
||||
margin: -0.5px calc(-1.5rem - 1px);
|
||||
display: flex;
|
||||
|
||||
> table {
|
||||
flex: 1;
|
||||
table-layout: auto;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0px 1px;
|
||||
border: 1px;
|
||||
border-top: 0;
|
||||
padding: 0.25rem 0;
|
||||
margin: -0.5px;
|
||||
/* font-size: var(--font-size-xs);
|
||||
line-height: var(--line-height-xs); */
|
||||
> details {
|
||||
/* border: 1px; */
|
||||
|
||||
caption {
|
||||
border-bottom-style: dashed !important;
|
||||
border-width: 1px;
|
||||
padding: 0.375rem 0.625rem;
|
||||
> summary {
|
||||
margin: -0.5px;
|
||||
display: block;
|
||||
padding: 0.5rem 1.5rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
tr {
|
||||
border: 1px;
|
||||
|
||||
&:hover,
|
||||
&:hover * {
|
||||
color: var(--orange) !important;
|
||||
details[open] > & {
|
||||
border-bottom-style: dashed !important;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0.125rem 0.625rem;
|
||||
text-align: right;
|
||||
> table {
|
||||
border: 1px;
|
||||
border-top-width: 0px;
|
||||
margin: -0.5px;
|
||||
width: calc(100% + 1px);
|
||||
border-collapse: separate;
|
||||
|
||||
&:first-child {
|
||||
text-align: left;
|
||||
color: var(--off-color);
|
||||
table-layout: auto;
|
||||
padding: 0.375rem 1.5rem;
|
||||
|
||||
tr {
|
||||
/* border: 1px; */
|
||||
|
||||
&:hover,
|
||||
&:hover * {
|
||||
color: var(--orange) !important;
|
||||
}
|
||||
|
||||
> i {
|
||||
color: var(--off-color);
|
||||
td {
|
||||
padding: 0.125rem 0;
|
||||
text-align: right;
|
||||
|
||||
&:first-child {
|
||||
text-align: left;
|
||||
color: var(--off-color);
|
||||
}
|
||||
|
||||
> i {
|
||||
color: var(--off-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1373,7 +1386,184 @@
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Flex Masonry -->
|
||||
<style>
|
||||
.flexmasonry {
|
||||
display: flex;
|
||||
flex-flow: column wrap;
|
||||
align-content: space-between;
|
||||
}
|
||||
|
||||
.flexmasonry-item {
|
||||
width: 100%;
|
||||
|
||||
.flexmasonry-cols-2 & {
|
||||
width: 50%;
|
||||
|
||||
&:nth-child(2n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
&:nth-child(2n) {
|
||||
order: 2;
|
||||
}
|
||||
}
|
||||
.flexmasonry-cols-3 & {
|
||||
width: 33.333%;
|
||||
|
||||
&:nth-child(3n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
&:nth-child(3n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
&:nth-child(3n) {
|
||||
order: 3;
|
||||
}
|
||||
}
|
||||
.flexmasonry-cols-4 & {
|
||||
width: 25%;
|
||||
|
||||
&:nth-child(4n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
&:nth-child(4n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
&:nth-child(4n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
&:nth-child(4n) {
|
||||
order: 4;
|
||||
}
|
||||
}
|
||||
.flexmasonry-cols-5 & {
|
||||
width: 20%;
|
||||
|
||||
&:nth-child(5n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
&:nth-child(5n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
&:nth-child(5n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
&:nth-child(5n + 4) {
|
||||
order: 4;
|
||||
}
|
||||
&:nth-child(5n) {
|
||||
order: 5;
|
||||
}
|
||||
}
|
||||
.flexmasonry-cols-6 & {
|
||||
width: 16.666%;
|
||||
|
||||
&:nth-child(6n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
&:nth-child(6n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
&:nth-child(6n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
&:nth-child(6n + 4) {
|
||||
order: 4;
|
||||
}
|
||||
&:nth-child(6n + 5) {
|
||||
order: 5;
|
||||
}
|
||||
&:nth-child(6n) {
|
||||
order: 6;
|
||||
}
|
||||
}
|
||||
.flexmasonry-cols-7 & {
|
||||
width: 14.285%;
|
||||
|
||||
&:nth-child(7n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
&:nth-child(7n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
&:nth-child(7n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
&:nth-child(7n + 4) {
|
||||
order: 4;
|
||||
}
|
||||
&:nth-child(7n + 5) {
|
||||
order: 5;
|
||||
}
|
||||
&:nth-child(7n + 6) {
|
||||
order: 6;
|
||||
}
|
||||
&:nth-child(7n) {
|
||||
order: 7;
|
||||
}
|
||||
}
|
||||
.flexmasonry-cols-8 & {
|
||||
width: 12.5%;
|
||||
|
||||
&:nth-child(8n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
&:nth-child(8n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
&:nth-child(8n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
&:nth-child(8n + 4) {
|
||||
order: 4;
|
||||
}
|
||||
&:nth-child(8n + 5) {
|
||||
order: 5;
|
||||
}
|
||||
&:nth-child(8n + 6) {
|
||||
order: 6;
|
||||
}
|
||||
&:nth-child(8n + 7) {
|
||||
order: 7;
|
||||
}
|
||||
&:nth-child(8n) {
|
||||
order: 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flexmasonry-break {
|
||||
content: "";
|
||||
flex-basis: 100%;
|
||||
width: 0 !important;
|
||||
margin: 0;
|
||||
}
|
||||
.flexmasonry-break-1 {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-break-2 {
|
||||
order: 2;
|
||||
}
|
||||
.flexmasonry-break-3 {
|
||||
order: 3;
|
||||
}
|
||||
.flexmasonry-break-4 {
|
||||
order: 4;
|
||||
}
|
||||
.flexmasonry-break-5 {
|
||||
order: 5;
|
||||
}
|
||||
.flexmasonry-break-6 {
|
||||
order: 6;
|
||||
}
|
||||
.flexmasonry-break-7 {
|
||||
order: 7;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- ------- -->
|
||||
<!-- Scripts -->
|
||||
<!-- ------- -->
|
||||
|
||||
<script>
|
||||
// @ts-check
|
||||
|
||||
3
website/packages/flexmasonry/README.md
Normal file
3
website/packages/flexmasonry/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
URL + Version:
|
||||
|
||||
https://unpkg.com/browse/flexmasonry@latest/
|
||||
198
website/packages/flexmasonry/v0.2.3-modified/script.js
Normal file
198
website/packages/flexmasonry/v0.2.3-modified/script.js
Normal file
@@ -0,0 +1,198 @@
|
||||
const defaultOptions = {
|
||||
/*
|
||||
* If `responsive` is `true`, `breakpointCols` will be used to determine
|
||||
* how many columns a grid should have at a given responsive breakpoint.
|
||||
*/
|
||||
responsive: true,
|
||||
/*
|
||||
* A list of how many columns should be shown at different responsive
|
||||
* breakpoints, defined by media queries.
|
||||
*/
|
||||
breakpointCols: {
|
||||
1500: 5,
|
||||
1200: 4,
|
||||
992: 3,
|
||||
768: 2,
|
||||
576: 1,
|
||||
},
|
||||
/*
|
||||
* If `responsive` is `false`, this number of columns will always be shown,
|
||||
* no matter the width of the screen.
|
||||
*/
|
||||
numCols: 4,
|
||||
};
|
||||
|
||||
let _resizeId = null;
|
||||
let _options = {};
|
||||
let _targets = [];
|
||||
|
||||
function init(targets, options = {}) {
|
||||
if (typeof targets === "string") {
|
||||
_targets = document.querySelectorAll(targets);
|
||||
} else {
|
||||
_targets = targets;
|
||||
}
|
||||
|
||||
_options = Object.assign(defaultOptions, options);
|
||||
|
||||
_targets.forEach(function (target) {
|
||||
setUp(target);
|
||||
// setHeight(target);
|
||||
});
|
||||
|
||||
addEventListeners();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function setUp(target) {
|
||||
target.classList.add("flexmasonry");
|
||||
|
||||
if (_options.responsive) {
|
||||
target.classList.add("flexmasonry-responsive");
|
||||
}
|
||||
|
||||
setColsClass(target);
|
||||
|
||||
Array.from(target.children).forEach(function (item) {
|
||||
item.classList.add("flexmasonry-item");
|
||||
});
|
||||
|
||||
addBreakElements(target);
|
||||
}
|
||||
|
||||
// function onLoad() {
|
||||
// _targets.forEach(function (target) {
|
||||
// setHeight(target);
|
||||
// });
|
||||
// }
|
||||
|
||||
function onResize() {
|
||||
if (_resizeId) {
|
||||
window.cancelAnimationFrame(_resizeId);
|
||||
}
|
||||
|
||||
_resizeId = window.requestAnimationFrame(function () {
|
||||
refreshAll();
|
||||
});
|
||||
}
|
||||
|
||||
function addEventListeners() {
|
||||
// window.addEventListener("load", onLoad);
|
||||
window.addEventListener("resize", onResize);
|
||||
}
|
||||
|
||||
function removeEventListeners() {
|
||||
// window.removeEventListener("load", onLoad);
|
||||
window.removeEventListener("resize", onResize);
|
||||
}
|
||||
|
||||
// function setHeight(target) {
|
||||
// if (getCurrentCols(target) < 2) {
|
||||
// target.style.removeProperty("height");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// let heights = [];
|
||||
|
||||
// Array.from(target.children).forEach(function (item) {
|
||||
// if (item.classList.contains("flexmasonry-break")) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const comp = window.getComputedStyle(item);
|
||||
// const order = comp.getPropertyValue("order");
|
||||
// const height = comp.getPropertyValue("height");
|
||||
|
||||
// if (!heights[order - 1]) {
|
||||
// heights[order - 1] = 0;
|
||||
// }
|
||||
// heights[order - 1] += Math.ceil(parseFloat(height));
|
||||
// });
|
||||
|
||||
// const maxHeight = Math.max(...heights);
|
||||
// target.style.height = maxHeight + "px";
|
||||
// }
|
||||
|
||||
function addBreakElements(target) {
|
||||
const breakEls = target.querySelectorAll(".flexmasonry-break");
|
||||
if (Array.from(breakEls).length === getCurrentCols(target) - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 1; i < getCurrentCols(target); i++) {
|
||||
const breakDiv = document.createElement("div");
|
||||
breakDiv.classList.add("flexmasonry-break");
|
||||
breakDiv.classList.add("flexmasonry-break-" + i);
|
||||
target.appendChild(breakDiv);
|
||||
}
|
||||
}
|
||||
|
||||
function removeBreakElements(target) {
|
||||
const breakEls = target.querySelectorAll(".flexmasonry-break");
|
||||
if (Array.from(breakEls).length === getCurrentCols(target) - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Array.from(breakEls).forEach(function (breakEl) {
|
||||
breakEl.parentNode.removeChild(breakEl);
|
||||
});
|
||||
}
|
||||
|
||||
function setColsClass(target) {
|
||||
if (target.classList.contains("flexmasonry-cols-" + getCurrentCols(target))) {
|
||||
return;
|
||||
}
|
||||
|
||||
target.className = target.className.replace(/(flexmasonry-cols-\d+)/, "");
|
||||
target.classList.add("flexmasonry-cols-" + getCurrentCols(target));
|
||||
}
|
||||
|
||||
function getCurrentCols(target) {
|
||||
if (!_options.responsive) {
|
||||
return _options.numCols;
|
||||
}
|
||||
|
||||
const descendingMinWidths = Object.keys(_options.breakpointCols)
|
||||
.map((key) => Number(key))
|
||||
.sort()
|
||||
.reverse();
|
||||
|
||||
for (const minWidth of descendingMinWidths) {
|
||||
if (target.clientWidth >= minWidth) {
|
||||
return _options.breakpointCols[minWidth];
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
function refresh(target, options = {}) {
|
||||
_options = Object.assign(defaultOptions, options);
|
||||
|
||||
setColsClass(target);
|
||||
removeBreakElements(target);
|
||||
addBreakElements(target);
|
||||
// setHeight(target);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function refreshAll(options = {}) {
|
||||
_targets.forEach(function (target) {
|
||||
refresh(target, options);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function destroyAll() {
|
||||
removeEventListeners();
|
||||
}
|
||||
|
||||
export default {
|
||||
init,
|
||||
refresh,
|
||||
refreshAll,
|
||||
destroyAll,
|
||||
};
|
||||
170
website/packages/flexmasonry/v0.2.3-modified/style.css
Normal file
170
website/packages/flexmasonry/v0.2.3-modified/style.css
Normal file
@@ -0,0 +1,170 @@
|
||||
.flexmasonry {
|
||||
display: flex;
|
||||
flex-flow: column wrap;
|
||||
align-content: space-between;
|
||||
}
|
||||
|
||||
.flexmasonry-item {
|
||||
width: 100%;
|
||||
}
|
||||
.flexmasonry-cols-2 .flexmasonry-item {
|
||||
width: 50%;
|
||||
}
|
||||
.flexmasonry-cols-3 .flexmasonry-item {
|
||||
width: 33.333%;
|
||||
}
|
||||
.flexmasonry-cols-4 .flexmasonry-item {
|
||||
width: 25%;
|
||||
}
|
||||
.flexmasonry-cols-5 .flexmasonry-item {
|
||||
width: 20%;
|
||||
}
|
||||
.flexmasonry-cols-6 .flexmasonry-item {
|
||||
width: 16.666%;
|
||||
}
|
||||
.flexmasonry-cols-7 .flexmasonry-item {
|
||||
width: 14.285%;
|
||||
}
|
||||
.flexmasonry-cols-8 .flexmasonry-item {
|
||||
width: 12.5%;
|
||||
}
|
||||
|
||||
.flexmasonry-cols-2 .flexmasonry-item:nth-child(2n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-cols-2 .flexmasonry-item:nth-child(2n) {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.flexmasonry-cols-3 .flexmasonry-item:nth-child(3n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-cols-3 .flexmasonry-item:nth-child(3n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
.flexmasonry-cols-3 .flexmasonry-item:nth-child(3n) {
|
||||
order: 3;
|
||||
}
|
||||
|
||||
.flexmasonry-cols-4 .flexmasonry-item:nth-child(4n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-cols-4 .flexmasonry-item:nth-child(4n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
.flexmasonry-cols-4 .flexmasonry-item:nth-child(4n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
.flexmasonry-cols-4 .flexmasonry-item:nth-child(4n) {
|
||||
order: 4;
|
||||
}
|
||||
|
||||
.flexmasonry-cols-5 .flexmasonry-item:nth-child(5n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-cols-5 .flexmasonry-item:nth-child(5n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
.flexmasonry-cols-5 .flexmasonry-item:nth-child(5n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
.flexmasonry-cols-5 .flexmasonry-item:nth-child(5n + 4) {
|
||||
order: 4;
|
||||
}
|
||||
.flexmasonry-cols-5 .flexmasonry-item:nth-child(5n) {
|
||||
order: 5;
|
||||
}
|
||||
|
||||
.flexmasonry-cols-6 .flexmasonry-item:nth-child(6n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-cols-6 .flexmasonry-item:nth-child(6n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
.flexmasonry-cols-6 .flexmasonry-item:nth-child(6n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
.flexmasonry-cols-6 .flexmasonry-item:nth-child(6n + 4) {
|
||||
order: 4;
|
||||
}
|
||||
.flexmasonry-cols-6 .flexmasonry-item:nth-child(6n + 5) {
|
||||
order: 5;
|
||||
}
|
||||
.flexmasonry-cols-6 .flexmasonry-item:nth-child(6n) {
|
||||
order: 6;
|
||||
}
|
||||
|
||||
.flexmasonry-cols-7 .flexmasonry-item:nth-child(7n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-cols-7 .flexmasonry-item:nth-child(7n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
.flexmasonry-cols-7 .flexmasonry-item:nth-child(7n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
.flexmasonry-cols-7 .flexmasonry-item:nth-child(7n + 4) {
|
||||
order: 4;
|
||||
}
|
||||
.flexmasonry-cols-7 .flexmasonry-item:nth-child(7n + 5) {
|
||||
order: 5;
|
||||
}
|
||||
.flexmasonry-cols-7 .flexmasonry-item:nth-child(7n + 6) {
|
||||
order: 6;
|
||||
}
|
||||
.flexmasonry-cols-7 .flexmasonry-item:nth-child(7n) {
|
||||
order: 7;
|
||||
}
|
||||
|
||||
.flexmasonry-cols-8 .flexmasonry-item:nth-child(8n + 1) {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-cols-8 .flexmasonry-item:nth-child(8n + 2) {
|
||||
order: 2;
|
||||
}
|
||||
.flexmasonry-cols-8 .flexmasonry-item:nth-child(8n + 3) {
|
||||
order: 3;
|
||||
}
|
||||
.flexmasonry-cols-8 .flexmasonry-item:nth-child(8n + 4) {
|
||||
order: 4;
|
||||
}
|
||||
.flexmasonry-cols-8 .flexmasonry-item:nth-child(8n + 5) {
|
||||
order: 5;
|
||||
}
|
||||
.flexmasonry-cols-8 .flexmasonry-item:nth-child(8n + 6) {
|
||||
order: 6;
|
||||
}
|
||||
.flexmasonry-cols-8 .flexmasonry-item:nth-child(8n + 7) {
|
||||
order: 7;
|
||||
}
|
||||
.flexmasonry-cols-8 .flexmasonry-item:nth-child(8n) {
|
||||
order: 8;
|
||||
}
|
||||
|
||||
.flexmasonry-break {
|
||||
content: "";
|
||||
flex-basis: 100%;
|
||||
width: 0 !important;
|
||||
margin: 0;
|
||||
}
|
||||
.flexmasonry-break-1 {
|
||||
order: 1;
|
||||
}
|
||||
.flexmasonry-break-2 {
|
||||
order: 2;
|
||||
}
|
||||
.flexmasonry-break-3 {
|
||||
order: 3;
|
||||
}
|
||||
.flexmasonry-break-4 {
|
||||
order: 4;
|
||||
}
|
||||
.flexmasonry-break-5 {
|
||||
order: 5;
|
||||
}
|
||||
.flexmasonry-break-6 {
|
||||
order: 6;
|
||||
}
|
||||
.flexmasonry-break-7 {
|
||||
order: 7;
|
||||
}
|
||||
3095
website/script.js
3095
website/script.js
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,8 @@
|
||||
const version = "v1";
|
||||
|
||||
self.addEventListener("install", (_event) => {
|
||||
console.log("service-worker: install");
|
||||
|
||||
const event = /** @type {any} */ (_event);
|
||||
|
||||
event.waitUntil(
|
||||
@@ -17,66 +19,66 @@ self.addEventListener("install", (_event) => {
|
||||
"/packages/lightweight-charts/v4.2.0/script.js",
|
||||
"/assets/fonts/satoshi/2024-09/font.var.woff2",
|
||||
]);
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Response | undefined} cachedResponse
|
||||
* @param {Response | undefined} badResponse
|
||||
*/
|
||||
function pickCorrectResponse(cachedResponse, badResponse) {
|
||||
if (cachedResponse) {
|
||||
return cachedResponse;
|
||||
} else {
|
||||
return caches
|
||||
.match("/")
|
||||
.then((response) => {
|
||||
return response ?? badResponse;
|
||||
})
|
||||
.catch(() => {
|
||||
return badResponse;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
self.addEventListener("fetch", (_event) => {
|
||||
const event = /** @type {any} */ (_event);
|
||||
|
||||
/** @type {Request} */
|
||||
const request = event.request;
|
||||
const { url, method } = request;
|
||||
let request = event.request;
|
||||
const method = request.method;
|
||||
let url = request.url;
|
||||
|
||||
const { pathname, origin } = new URL(url);
|
||||
|
||||
const slashMatches = url.match(/\//g);
|
||||
const dotMatches = pathname.split("/").at(-1)?.match(/./g);
|
||||
const endsWithDotHtml = pathname.endsWith(".html");
|
||||
const slashApiSlashMatches = url.match(/\/api\//g);
|
||||
|
||||
if (
|
||||
slashMatches &&
|
||||
slashMatches.length <= 3 &&
|
||||
!slashApiSlashMatches &&
|
||||
(!dotMatches || endsWithDotHtml)
|
||||
) {
|
||||
url = `${origin}/`;
|
||||
}
|
||||
request = new Request(url, request.mode !== "navigate" ? request : undefined);
|
||||
|
||||
console.log(`service-worker: fetching: ${url}`);
|
||||
|
||||
event.respondWith(
|
||||
caches.match(request).then((cachedResponse) => {
|
||||
caches.match(request).then(async (cachedResponse) => {
|
||||
return fetch(request)
|
||||
.then((response) => {
|
||||
const { status } = response;
|
||||
|
||||
// @ts-ignore
|
||||
if (method !== "GET" || url.includes("/api/")) {
|
||||
if (method !== "GET" || slashApiSlashMatches) {
|
||||
// API calls are cached in script.js
|
||||
return response;
|
||||
}
|
||||
|
||||
return caches.open(version).then((cache) => {
|
||||
if (status === 200 || status === 304) {
|
||||
if (status === 200) {
|
||||
cache.put(request, response.clone());
|
||||
}
|
||||
return response;
|
||||
} else {
|
||||
return pickCorrectResponse(cachedResponse, response);
|
||||
} else if (status === 200 || status === 304) {
|
||||
if (status === 200) {
|
||||
const clonedResponse = response.clone();
|
||||
caches.open(version).then((cache) => {
|
||||
cache.put(request, clonedResponse);
|
||||
});
|
||||
}
|
||||
});
|
||||
return response;
|
||||
} else {
|
||||
return cachedResponse || response;
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
return pickCorrectResponse(cachedResponse, undefined);
|
||||
console.log("service-worker: offline");
|
||||
|
||||
return cachedResponse;
|
||||
});
|
||||
})
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
6
website/types/paths.d.ts
vendored
6
website/types/paths.d.ts
vendored
File diff suppressed because one or more lines are too long
34
website/types/self.d.ts
vendored
34
website/types/self.d.ts
vendored
@@ -77,21 +77,23 @@ type SeriesBlueprint = {
|
||||
} & AnySpecificSeriesBlueprint;
|
||||
|
||||
type Unit =
|
||||
| "US Dollars"
|
||||
| ""
|
||||
| "Bitcoin"
|
||||
| "Percentage"
|
||||
| "Height"
|
||||
| "Count"
|
||||
| "Megabytes"
|
||||
| "Transactions"
|
||||
| "Weight"
|
||||
| "Ratio"
|
||||
| "Virtual Bytes"
|
||||
| "Seconds"
|
||||
| "Coinblocks"
|
||||
| "ExaHash / Second"
|
||||
| "Count"
|
||||
| "Date"
|
||||
| "Dollars / (PetaHash / Second)"
|
||||
| "";
|
||||
| "ExaHash / Second"
|
||||
| "Height"
|
||||
| "Megabytes"
|
||||
| "Percentage"
|
||||
| "Ratio"
|
||||
| "Satoshis"
|
||||
| "Seconds"
|
||||
| "Transactions"
|
||||
| "US Dollars"
|
||||
| "Virtual Bytes"
|
||||
| "Weight";
|
||||
|
||||
interface PartialOption {
|
||||
icon: string;
|
||||
@@ -107,6 +109,7 @@ interface PartialHomeOption extends PartialOption {
|
||||
interface PartialDashboardOption extends PartialOption {
|
||||
title: string;
|
||||
description: string;
|
||||
defaultOpen?: false;
|
||||
groups: {
|
||||
name: string;
|
||||
unit?: Unit;
|
||||
@@ -114,6 +117,7 @@ interface PartialDashboardOption extends PartialOption {
|
||||
name: string;
|
||||
path?: LastPath;
|
||||
unit?: Unit;
|
||||
long?: true;
|
||||
}[];
|
||||
}[];
|
||||
}
|
||||
@@ -194,7 +198,7 @@ interface OHLC {
|
||||
|
||||
interface ResourceDataset<
|
||||
Scale extends TimeScale,
|
||||
Type extends OHLC | number = number
|
||||
Type extends OHLC | number = number,
|
||||
> {
|
||||
scale: Scale;
|
||||
url: string;
|
||||
@@ -212,7 +216,7 @@ interface FetchedResult<
|
||||
SingleValueData | ValuedCandlestickData
|
||||
> = DatasetValue<
|
||||
Type extends number ? SingleValueData : ValuedCandlestickData
|
||||
>
|
||||
>,
|
||||
> {
|
||||
at: Date | null;
|
||||
json: Signal<FetchedJSON<Scale, Type> | null>;
|
||||
@@ -242,7 +246,7 @@ interface FetchedChunk {
|
||||
|
||||
type FetchedDataset<
|
||||
Scale extends TimeScale,
|
||||
Type extends number | OHLC
|
||||
Type extends number | OHLC,
|
||||
> = Scale extends "date"
|
||||
? FetchedDateDataset<Type>
|
||||
: FetchedHeightDataset<Type>;
|
||||
|
||||
Reference in New Issue
Block a user