mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-27 16:19:59 -07:00
global: snapshot
This commit is contained in:
@@ -13,7 +13,7 @@ use crate::{
|
||||
datasets::{AllDatasets, ComputeData},
|
||||
io::OUTPUTS_FOLDER_PATH,
|
||||
states::{AddressCohortsDurableStates, States, UTXOCohortsDurableStates},
|
||||
structs::{Date, DateData, MapKey},
|
||||
structs::{DateData, MapKey, Timestamp},
|
||||
utils::{generate_allocation_files, log, time},
|
||||
Config, Exit, Height,
|
||||
};
|
||||
@@ -81,9 +81,9 @@ pub fn iter_blocks(
|
||||
if let Some((_current_block_height, current_block, _current_block_hash)) =
|
||||
current_block_opt
|
||||
{
|
||||
let timestamp = current_block.header.time;
|
||||
let timestamp = Timestamp::wrap(current_block.header.time);
|
||||
|
||||
let current_block_date = Date::from_timestamp(timestamp);
|
||||
let current_block_date = timestamp.to_date();
|
||||
let current_block_height: Height = height + blocks_loop_i;
|
||||
|
||||
if current_block_height.to_usize() != _current_block_height {
|
||||
@@ -91,9 +91,9 @@ pub fn iter_blocks(
|
||||
panic!()
|
||||
}
|
||||
|
||||
let next_block_date = next_block_opt
|
||||
.as_ref()
|
||||
.map(|(_, next_block, _)| Date::from_timestamp(next_block.header.time));
|
||||
let next_block_date = next_block_opt.as_ref().map(|(_, next_block, _)| {
|
||||
Timestamp::wrap(next_block.header.time).to_date()
|
||||
});
|
||||
|
||||
// Always run for the first block of the loop
|
||||
if blocks_loop_date.is_none() {
|
||||
@@ -168,7 +168,6 @@ pub fn iter_blocks(
|
||||
height: current_block_height,
|
||||
is_date_last_block,
|
||||
states: &mut states,
|
||||
timestamp,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -213,7 +212,7 @@ pub fn iter_blocks(
|
||||
});
|
||||
}
|
||||
|
||||
if !config.dry_run {
|
||||
if !config.dry_run() {
|
||||
let is_safe = height.is_safe(approx_block_count);
|
||||
|
||||
export(ExportedData {
|
||||
@@ -225,7 +224,7 @@ pub fn iter_blocks(
|
||||
exit: exit.clone(),
|
||||
})?;
|
||||
|
||||
if config.record_ram_usage {
|
||||
if config.record_ram_usage() {
|
||||
time("Exporing allocation files", || {
|
||||
generate_allocation_files(&datasets, &databases, &states, last_height)
|
||||
})?;
|
||||
|
||||
@@ -20,7 +20,7 @@ use crate::{
|
||||
},
|
||||
structs::{
|
||||
Address, AddressData, AddressRealizedData, Amount, BlockData, BlockPath, Counter, Date,
|
||||
EmptyAddressData, Height, PartialTxoutData, Price, SentData, TxData, TxoutIndex,
|
||||
EmptyAddressData, Height, PartialTxoutData, Price, SentData, Timestamp, TxData, TxoutIndex,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -37,7 +37,6 @@ pub struct ParseData<'a> {
|
||||
pub is_date_last_block: bool,
|
||||
pub rpc: &'a biter::bitcoincore_rpc::Client,
|
||||
pub states: &'a mut States,
|
||||
pub timestamp: u32,
|
||||
}
|
||||
|
||||
pub fn parse(
|
||||
@@ -53,11 +52,12 @@ pub fn parse(
|
||||
is_date_last_block,
|
||||
rpc,
|
||||
states,
|
||||
timestamp,
|
||||
}: ParseData,
|
||||
) {
|
||||
// log(&format!("{height}"));
|
||||
|
||||
let timestamp = Timestamp::wrap(block.header.time);
|
||||
|
||||
// If false, expect that the code is flawless
|
||||
// or create a 0 value txid database
|
||||
let enable_check_if_txout_value_is_zero_in_db: bool = true;
|
||||
@@ -89,9 +89,9 @@ pub fn parse(
|
||||
let block_size = block.total_size();
|
||||
let block_weight = block.weight().to_wu();
|
||||
let block_vbytes = block.weight().to_vbytes_floor();
|
||||
let block_interval = previous_timestamp.map_or(0, |previous_timestamp| {
|
||||
let block_interval = previous_timestamp.map_or(Timestamp::ZERO, |previous_timestamp| {
|
||||
if previous_timestamp >= timestamp {
|
||||
0
|
||||
Timestamp::ZERO
|
||||
} else {
|
||||
timestamp - previous_timestamp
|
||||
}
|
||||
@@ -519,6 +519,8 @@ pub fn parse(
|
||||
input_amount,
|
||||
block_price,
|
||||
previous_price,
|
||||
timestamp,
|
||||
input_block_data.timestamp,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -645,6 +647,7 @@ pub fn parse(
|
||||
&states.date_data_vec,
|
||||
&block_path_to_sent_data,
|
||||
block_price,
|
||||
timestamp,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use allocative::Allocative;
|
||||
|
||||
use crate::{
|
||||
datasets::AnyDataset,
|
||||
structs::{AnyHeightMap, Date, HeightMap},
|
||||
structs::{AnyHeightMap, Date, HeightMap, Timestamp},
|
||||
};
|
||||
|
||||
use super::{InsertData, MinInitialStates};
|
||||
@@ -13,7 +13,7 @@ pub struct BlockMetadataDataset {
|
||||
|
||||
// Inserted
|
||||
pub date: HeightMap<Date>,
|
||||
pub timestamp: HeightMap<u32>,
|
||||
pub timestamp: HeightMap<Timestamp>,
|
||||
}
|
||||
|
||||
impl BlockMetadataDataset {
|
||||
@@ -41,7 +41,7 @@ impl BlockMetadataDataset {
|
||||
) {
|
||||
self.timestamp.insert(height, timestamp);
|
||||
|
||||
self.date.insert(height, Date::from_timestamp(timestamp));
|
||||
self.date.insert(height, timestamp.to_date());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -302,7 +302,7 @@ impl MiningDataset {
|
||||
self.block_weight
|
||||
.insert(height, block_weight as f32 / BYTES_IN_MB as f32);
|
||||
self.block_vbytes.insert(height, block_vbytes);
|
||||
self.block_interval.insert(height, block_interval);
|
||||
self.block_interval.insert(height, *block_interval);
|
||||
|
||||
if is_date_last_block {
|
||||
self.coinbase.date_insert_sum_range(date, date_blocks_range);
|
||||
|
||||
@@ -45,7 +45,7 @@ use crate::{
|
||||
// UTXOCohortsReceivedStates,
|
||||
UTXOCohortsSentStates,
|
||||
},
|
||||
structs::{Amount, Date, Height, Price},
|
||||
structs::{Amount, Date, Height, Price, Timestamp},
|
||||
};
|
||||
|
||||
pub struct InsertData<'a> {
|
||||
@@ -53,7 +53,7 @@ pub struct InsertData<'a> {
|
||||
pub address_cohorts_one_shot_states: &'a Option<AddressCohortsOneShotStates>,
|
||||
pub address_cohorts_realized_states: &'a Option<AddressCohortsRealizedStates>,
|
||||
pub amount_sent: Amount,
|
||||
pub block_interval: u32,
|
||||
pub block_interval: Timestamp,
|
||||
pub block_price: Price,
|
||||
pub block_size: usize,
|
||||
pub block_vbytes: u64,
|
||||
@@ -71,7 +71,7 @@ pub struct InsertData<'a> {
|
||||
pub satblocks_destroyed: Amount,
|
||||
pub satdays_destroyed: Amount,
|
||||
pub states: &'a States,
|
||||
pub timestamp: u32,
|
||||
pub timestamp: Timestamp,
|
||||
pub transaction_count: usize,
|
||||
pub utxo_cohorts_one_shot_states: &'a UTXOCohortsOneShotStates,
|
||||
// pub utxo_cohorts_received_states: &'a UTXOCohortsReceivedStates,
|
||||
|
||||
@@ -3,17 +3,16 @@ mod ohlc;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use allocative::Allocative;
|
||||
use chrono::{Days, NaiveDateTime, NaiveTime, TimeZone, Timelike, Utc};
|
||||
use chrono::Days;
|
||||
use color_eyre::eyre::Error;
|
||||
|
||||
pub use ohlc::*;
|
||||
|
||||
use crate::{
|
||||
log,
|
||||
price::{Binance, Kibo, Kraken},
|
||||
structs::{
|
||||
AnyBiMap, AnyDateMap, BiMap, Date, DateMap, DateMapChunkId, Height, HeightMapChunkId,
|
||||
MapKey,
|
||||
Amount, AnyBiMap, AnyDateMap, BiMap, Date, DateMap, DateMapChunkId, Height,
|
||||
HeightMapChunkId, MapKey, Timestamp,
|
||||
},
|
||||
utils::{ONE_MONTH_IN_DAYS, ONE_WEEK_IN_DAYS, ONE_YEAR_IN_DAYS},
|
||||
};
|
||||
@@ -76,9 +75,11 @@ pub struct PriceDatasets {
|
||||
pub price_10y_total_return: DateMap<f32>,
|
||||
pub price_4y_compound_return: DateMap<f32>,
|
||||
// projection via lowest 4y compound value
|
||||
pub all_time_high: BiMap<f32>,
|
||||
pub market_price_to_all_time_high_ratio: BiMap<f32>,
|
||||
pub drawdown: BiMap<f32>,
|
||||
pub sats_per_dollar: BiMap<f32>,
|
||||
// volatility
|
||||
// drawdown
|
||||
// sats per dollar
|
||||
}
|
||||
|
||||
impl PriceDatasets {
|
||||
@@ -138,6 +139,13 @@ impl PriceDatasets {
|
||||
price_8y_total_return: DateMap::new_bin(1, &f("price_8y_total_return")),
|
||||
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")),
|
||||
market_price_to_all_time_high_ratio: BiMap::new_bin(
|
||||
1,
|
||||
&f("market_price_to_all_time_high_ratio"),
|
||||
),
|
||||
drawdown: BiMap::new_bin(1, &f("drawdown")),
|
||||
sats_per_dollar: BiMap::new_bin(1, &f("sats_per_dollar")),
|
||||
};
|
||||
|
||||
s.min_initial_states
|
||||
@@ -306,6 +314,26 @@ impl PriceDatasets {
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_144d_sma);
|
||||
self.price_200w_sma_ratio
|
||||
.compute(compute_data, &mut self.closes, &mut self.price_200w_sma);
|
||||
|
||||
self.all_time_high
|
||||
.multi_insert_max(heights, dates, &mut self.closes);
|
||||
|
||||
self.market_price_to_all_time_high_ratio
|
||||
.multi_insert_percentage(heights, dates, &mut self.closes, &mut self.all_time_high);
|
||||
|
||||
self.drawdown.multi_insert_simple_transform(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.market_price_to_all_time_high_ratio,
|
||||
&|v| -(100.0 - v),
|
||||
);
|
||||
|
||||
self.sats_per_dollar.multi_insert_simple_transform(
|
||||
heights,
|
||||
dates,
|
||||
&mut self.closes,
|
||||
&|price| Amount::ONE_BTC_F32 / price,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_date_ohlc(&mut self, date: Date) -> color_eyre::Result<OHLC> {
|
||||
@@ -396,31 +424,20 @@ impl PriceDatasets {
|
||||
pub fn get_height_ohlc(
|
||||
&mut self,
|
||||
height: Height,
|
||||
timestamp: u32,
|
||||
previous_timestamp: Option<u32>,
|
||||
timestamp: Timestamp,
|
||||
previous_timestamp: Option<Timestamp>,
|
||||
) -> color_eyre::Result<OHLC> {
|
||||
if let Some(ohlc) = self.ohlcs.height.get(&height) {
|
||||
return Ok(ohlc);
|
||||
}
|
||||
|
||||
let clean_timestamp = |timestamp| {
|
||||
let date_time = Utc.timestamp_opt(i64::from(timestamp), 0).unwrap();
|
||||
|
||||
NaiveDateTime::new(
|
||||
date_time.date_naive(),
|
||||
NaiveTime::from_hms_opt(date_time.hour(), date_time.minute(), 0).unwrap(),
|
||||
)
|
||||
.and_utc()
|
||||
.timestamp() as u32
|
||||
};
|
||||
|
||||
let timestamp = clean_timestamp(timestamp);
|
||||
let timestamp = timestamp.to_floored_seconds();
|
||||
|
||||
if previous_timestamp.is_none() && !height.is_first() {
|
||||
panic!("Shouldn't be possible");
|
||||
}
|
||||
|
||||
let previous_timestamp = previous_timestamp.map(clean_timestamp);
|
||||
let previous_timestamp = previous_timestamp.map(|t| t.to_floored_seconds());
|
||||
|
||||
let ohlc = self
|
||||
.get_from_1mn_kraken(timestamp, previous_timestamp)
|
||||
@@ -430,7 +447,7 @@ impl PriceDatasets {
|
||||
self.get_from_har_binance(timestamp, previous_timestamp)
|
||||
.unwrap_or_else(|_| {
|
||||
self.get_from_height_kibo(&height).unwrap_or_else(|_| {
|
||||
let date = Date::from_timestamp(timestamp);
|
||||
let date = timestamp.to_date();
|
||||
|
||||
panic!(
|
||||
"Can't find the price for: height: {height} - date: {date}
|
||||
@@ -479,8 +496,8 @@ How to fix this:
|
||||
|
||||
fn get_from_1mn_kraken(
|
||||
&mut self,
|
||||
timestamp: u32,
|
||||
previous_timestamp: Option<u32>,
|
||||
timestamp: Timestamp,
|
||||
previous_timestamp: Option<Timestamp>,
|
||||
) -> color_eyre::Result<OHLC> {
|
||||
if self.kraken_1mn.is_none()
|
||||
|| self
|
||||
@@ -500,8 +517,8 @@ How to fix this:
|
||||
|
||||
fn get_from_1mn_binance(
|
||||
&mut self,
|
||||
timestamp: u32,
|
||||
previous_timestamp: Option<u32>,
|
||||
timestamp: Timestamp,
|
||||
previous_timestamp: Option<Timestamp>,
|
||||
) -> color_eyre::Result<OHLC> {
|
||||
if self.binance_1mn.is_none()
|
||||
|| self
|
||||
@@ -526,8 +543,8 @@ How to fix this:
|
||||
|
||||
fn get_from_har_binance(
|
||||
&mut self,
|
||||
timestamp: u32,
|
||||
previous_timestamp: Option<u32>,
|
||||
timestamp: Timestamp,
|
||||
previous_timestamp: Option<Timestamp>,
|
||||
) -> color_eyre::Result<OHLC> {
|
||||
if self.binance_har.is_none() {
|
||||
self.binance_har
|
||||
@@ -544,8 +561,8 @@ How to fix this:
|
||||
|
||||
fn find_height_ohlc(
|
||||
tree: &Option<BTreeMap<u32, OHLC>>,
|
||||
timestamp: u32,
|
||||
previous_timestamp: Option<u32>,
|
||||
timestamp: Timestamp,
|
||||
previous_timestamp: Option<Timestamp>,
|
||||
name: &str,
|
||||
) -> color_eyre::Result<OHLC> {
|
||||
let tree = tree.as_ref().unwrap();
|
||||
@@ -572,12 +589,12 @@ How to fix this:
|
||||
close: previous_ohlc.close,
|
||||
};
|
||||
|
||||
let start = previous_timestamp.unwrap_or(0);
|
||||
let start = previous_timestamp.unwrap_or_default();
|
||||
let end = timestamp;
|
||||
|
||||
// Otherwise it's a re-org
|
||||
if start < end {
|
||||
tree.range(&start..=&end).skip(1).for_each(|(_, ohlc)| {
|
||||
tree.range(&*start..=&*end).skip(1).for_each(|(_, ohlc)| {
|
||||
if ohlc.high > final_ohlc.high {
|
||||
final_ohlc.high = ohlc.high
|
||||
}
|
||||
@@ -624,6 +641,10 @@ impl AnyDataset for PriceDatasets {
|
||||
&self.price_89d_sma,
|
||||
&self.price_144d_sma,
|
||||
&self.price_200w_sma,
|
||||
&self.all_time_high,
|
||||
&self.market_price_to_all_time_high_ratio,
|
||||
&self.drawdown,
|
||||
&self.sats_per_dollar,
|
||||
];
|
||||
|
||||
v.append(&mut self.price_1w_sma_ratio.to_computed_bi_map_vec());
|
||||
@@ -660,6 +681,10 @@ impl AnyDataset for PriceDatasets {
|
||||
&mut self.price_89d_sma,
|
||||
&mut self.price_144d_sma,
|
||||
&mut self.price_200w_sma,
|
||||
&mut self.all_time_high,
|
||||
&mut self.market_price_to_all_time_high_ratio,
|
||||
&mut self.drawdown,
|
||||
&mut self.sats_per_dollar,
|
||||
];
|
||||
|
||||
v.append(&mut self.price_1w_sma_ratio.to_computed_mut_bi_map_vec());
|
||||
|
||||
@@ -66,7 +66,7 @@ impl CapitalizationDataset {
|
||||
let realized_cap = self
|
||||
.realized_cap
|
||||
.height
|
||||
.insert(height, state.realized_cap.to_dollar() as f32);
|
||||
.insert(height, state.realized_cap().to_dollar() as f32);
|
||||
|
||||
if is_date_last_block {
|
||||
self.realized_cap.date.insert(date, realized_cap);
|
||||
|
||||
@@ -51,9 +51,12 @@ impl InputSubDataset {
|
||||
}: &InsertData,
|
||||
state: &InputState,
|
||||
) {
|
||||
let count = self.count.height.insert(height, state.count.round() as u64);
|
||||
let count = self
|
||||
.count
|
||||
.height
|
||||
.insert(height, state.count().round() as u64);
|
||||
|
||||
self.volume.height.insert(height, state.volume.to_btc());
|
||||
self.volume.height.insert(height, state.volume().to_btc());
|
||||
|
||||
if is_date_last_block {
|
||||
self.count.date.insert(date, count);
|
||||
|
||||
@@ -83,28 +83,25 @@ impl PricePaidSubDataset {
|
||||
}: &InsertData,
|
||||
state: &PricePaidState,
|
||||
) {
|
||||
let PricePaidState {
|
||||
pp_05p,
|
||||
pp_10p,
|
||||
pp_15p,
|
||||
pp_20p,
|
||||
pp_25p,
|
||||
pp_30p,
|
||||
pp_35p,
|
||||
pp_40p,
|
||||
pp_45p,
|
||||
pp_median,
|
||||
pp_55p,
|
||||
pp_60p,
|
||||
pp_65p,
|
||||
pp_70p,
|
||||
pp_75p,
|
||||
pp_80p,
|
||||
pp_85p,
|
||||
pp_90p,
|
||||
pp_95p,
|
||||
..
|
||||
} = state;
|
||||
let pp_05p = state.pp_05p();
|
||||
let pp_10p = state.pp_10p();
|
||||
let pp_15p = state.pp_15p();
|
||||
let pp_20p = state.pp_20p();
|
||||
let pp_25p = state.pp_25p();
|
||||
let pp_30p = state.pp_30p();
|
||||
let pp_35p = state.pp_35p();
|
||||
let pp_40p = state.pp_40p();
|
||||
let pp_45p = state.pp_45p();
|
||||
let pp_median = state.pp_median();
|
||||
let pp_55p = state.pp_55p();
|
||||
let pp_60p = state.pp_60p();
|
||||
let pp_65p = state.pp_65p();
|
||||
let pp_70p = state.pp_70p();
|
||||
let pp_75p = state.pp_75p();
|
||||
let pp_80p = state.pp_80p();
|
||||
let pp_85p = state.pp_85p();
|
||||
let pp_90p = state.pp_90p();
|
||||
let pp_95p = state.pp_95p();
|
||||
|
||||
// Check if iter was empty
|
||||
if pp_05p.is_none() {
|
||||
|
||||
@@ -15,9 +15,12 @@ pub struct RealizedSubDataset {
|
||||
// Inserted
|
||||
realized_profit: BiMap<f32>,
|
||||
realized_loss: BiMap<f32>,
|
||||
value_destroyed: BiMap<f32>,
|
||||
value_created: BiMap<f32>,
|
||||
adjusted_value_created: BiMap<f32>,
|
||||
value_destroyed: BiMap<f32>,
|
||||
adjusted_value_destroyed: BiMap<f32>,
|
||||
spent_output_profit_ratio: BiMap<f32>,
|
||||
adjusted_spent_output_profit_ratio: BiMap<f32>,
|
||||
|
||||
// Computed
|
||||
negative_realized_loss: BiMap<f32>,
|
||||
@@ -47,8 +50,14 @@ impl RealizedSubDataset {
|
||||
realized_profit: BiMap::new_bin(1, &f("realized_profit")),
|
||||
realized_loss: BiMap::new_bin(1, &f("realized_loss")),
|
||||
value_created: BiMap::new_bin(1, &f("value_created")),
|
||||
adjusted_value_created: BiMap::new_bin(1, &f("adjusted_value_created")),
|
||||
value_destroyed: BiMap::new_bin(1, &f("value_destroyed")),
|
||||
adjusted_value_destroyed: BiMap::new_bin(1, &f("adjusted_value_destroyed")),
|
||||
spent_output_profit_ratio: BiMap::new_bin(2, &f("spent_output_profit_ratio")),
|
||||
adjusted_spent_output_profit_ratio: BiMap::new_bin(
|
||||
2,
|
||||
&f("adjusted_spent_output_profit_ratio"),
|
||||
),
|
||||
|
||||
negative_realized_loss: BiMap::new_bin(2, &f("negative_realized_loss")),
|
||||
net_realized_profit_and_loss: BiMap::new_bin(1, &f("net_realized_profit_and_loss")),
|
||||
@@ -89,29 +98,51 @@ impl RealizedSubDataset {
|
||||
) {
|
||||
self.realized_profit
|
||||
.height
|
||||
.insert(height, height_state.realized_profit.to_dollar() as f32);
|
||||
.insert(height, height_state.realized_profit().to_dollar() as f32);
|
||||
|
||||
self.realized_loss
|
||||
.height
|
||||
.insert(height, height_state.realized_loss.to_dollar() as f32);
|
||||
.insert(height, height_state.realized_loss().to_dollar() as f32);
|
||||
|
||||
self.value_created
|
||||
.height
|
||||
.insert(height, height_state.value_created.to_dollar() as f32);
|
||||
.insert(height, height_state.value_created().to_dollar() as f32);
|
||||
|
||||
self.adjusted_value_created.height.insert(
|
||||
height,
|
||||
height_state.adjusted_value_created().to_dollar() as f32,
|
||||
);
|
||||
|
||||
self.value_destroyed
|
||||
.height
|
||||
.insert(height, height_state.value_destroyed.to_dollar() as f32);
|
||||
.insert(height, height_state.value_destroyed().to_dollar() as f32);
|
||||
|
||||
self.adjusted_value_destroyed.height.insert(
|
||||
height,
|
||||
height_state.adjusted_value_destroyed().to_dollar() as f32,
|
||||
);
|
||||
|
||||
self.spent_output_profit_ratio.height.insert(height, {
|
||||
if height_state.value_destroyed > Price::ZERO {
|
||||
(height_state.value_created.to_cent() as f64
|
||||
/ height_state.value_destroyed.to_cent() as f64) as f32
|
||||
if height_state.value_destroyed() > Price::ZERO {
|
||||
(height_state.value_created().to_cent() as f64
|
||||
/ height_state.value_destroyed().to_cent() as f64) as f32
|
||||
} else {
|
||||
1.0
|
||||
}
|
||||
});
|
||||
|
||||
self.adjusted_spent_output_profit_ratio
|
||||
.height
|
||||
.insert(height, {
|
||||
if height_state.adjusted_value_destroyed() > Price::ZERO {
|
||||
(height_state.adjusted_value_created().to_cent() as f64
|
||||
/ height_state.adjusted_value_destroyed().to_cent() as f64)
|
||||
as f32
|
||||
} else {
|
||||
1.0
|
||||
}
|
||||
});
|
||||
|
||||
if is_date_last_block {
|
||||
self.realized_profit
|
||||
.date_insert_sum_range(date, date_blocks_range);
|
||||
@@ -122,14 +153,31 @@ impl RealizedSubDataset {
|
||||
self.value_created
|
||||
.date_insert_sum_range(date, date_blocks_range);
|
||||
|
||||
self.adjusted_value_created
|
||||
.date_insert_sum_range(date, date_blocks_range);
|
||||
|
||||
self.value_destroyed
|
||||
.date_insert_sum_range(date, date_blocks_range);
|
||||
|
||||
self.adjusted_value_destroyed
|
||||
.date_insert_sum_range(date, date_blocks_range);
|
||||
|
||||
self.spent_output_profit_ratio.date.insert(
|
||||
date,
|
||||
self.value_created.height.sum_range(date_blocks_range)
|
||||
/ self.value_destroyed.height.sum_range(date_blocks_range),
|
||||
);
|
||||
|
||||
self.adjusted_spent_output_profit_ratio.date.insert(
|
||||
date,
|
||||
self.adjusted_value_created
|
||||
.height
|
||||
.sum_range(date_blocks_range)
|
||||
/ self
|
||||
.adjusted_value_destroyed
|
||||
.height
|
||||
.sum_range(date_blocks_range),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,8 +256,11 @@ impl AnyDataset for RealizedSubDataset {
|
||||
&self.realized_loss,
|
||||
&self.realized_profit,
|
||||
&self.value_created,
|
||||
&self.adjusted_value_created,
|
||||
&self.value_destroyed,
|
||||
&self.adjusted_value_destroyed,
|
||||
&self.spent_output_profit_ratio,
|
||||
&self.adjusted_spent_output_profit_ratio,
|
||||
]
|
||||
}
|
||||
|
||||
@@ -218,8 +269,11 @@ impl AnyDataset for RealizedSubDataset {
|
||||
&mut self.realized_loss,
|
||||
&mut self.realized_profit,
|
||||
&mut self.value_created,
|
||||
&mut self.adjusted_value_created,
|
||||
&mut self.value_destroyed,
|
||||
&mut self.adjusted_value_destroyed,
|
||||
&mut self.spent_output_profit_ratio,
|
||||
&mut self.adjusted_spent_output_profit_ratio,
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -254,99 +254,3 @@ where
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
// impl<Key, Value, ChunkId, Serialized> AnyDataset for RecapDataset<Key, Value, ChunkId, Serialized>
|
||||
// where
|
||||
// Value: MapValue,
|
||||
// ChunkId: MapChunkId,
|
||||
// Key: MapKey<ChunkId>,
|
||||
// Serialized: MapSerialized<Key, Value, ChunkId>,
|
||||
// {
|
||||
// fn get_min_initial_states(&self) -> &MinInitialStates {
|
||||
// &self.min_initial_states
|
||||
// }
|
||||
|
||||
// fn to_computed_date_map_vec(&self) -> Vec<&(dyn AnyDateMap + Send + Sync)> {
|
||||
// let mut v: Vec<&(dyn AnyDateMap + Send + Sync)> = vec![];
|
||||
|
||||
// if let Some(min) = self.min.as_ref() {
|
||||
// v.push(min);
|
||||
// }
|
||||
|
||||
// if let Some(max) = self.max.as_ref() {
|
||||
// v.push(max);
|
||||
// }
|
||||
|
||||
// if let Some(median) = self.median.as_ref() {
|
||||
// v.push(median);
|
||||
// }
|
||||
|
||||
// if let Some(average) = self.average.as_ref() {
|
||||
// v.push(average);
|
||||
// }
|
||||
|
||||
// if let Some(sum) = self.sum.as_ref() {
|
||||
// v.push(sum);
|
||||
// }
|
||||
|
||||
// if let Some(_90p) = self._90p.as_ref() {
|
||||
// v.push(_90p);
|
||||
// }
|
||||
|
||||
// if let Some(_75p) = self._75p.as_ref() {
|
||||
// v.push(_75p);
|
||||
// }
|
||||
|
||||
// if let Some(_25p) = self._25p.as_ref() {
|
||||
// v.push(_25p);
|
||||
// }
|
||||
|
||||
// if let Some(_10p) = self._10p.as_ref() {
|
||||
// v.push(_10p);
|
||||
// }
|
||||
|
||||
// v
|
||||
// }
|
||||
|
||||
// fn to_computed_mut_date_map_vec(&mut self) -> Vec<&mut dyn AnyDateMap> {
|
||||
// let mut v: Vec<&mut dyn AnyDateMap> = vec![];
|
||||
|
||||
// if let Some(min) = self.min.as_mut() {
|
||||
// v.push(min);
|
||||
// }
|
||||
|
||||
// if let Some(max) = self.max.as_mut() {
|
||||
// v.push(max);
|
||||
// }
|
||||
|
||||
// if let Some(median) = self.median.as_mut() {
|
||||
// v.push(median);
|
||||
// }
|
||||
|
||||
// if let Some(average) = self.average.as_mut() {
|
||||
// v.push(average);
|
||||
// }
|
||||
|
||||
// if let Some(sum) = self.sum.as_mut() {
|
||||
// v.push(sum);
|
||||
// }
|
||||
|
||||
// if let Some(_90p) = self._90p.as_mut() {
|
||||
// v.push(_90p);
|
||||
// }
|
||||
|
||||
// if let Some(_75p) = self._75p.as_mut() {
|
||||
// v.push(_75p);
|
||||
// }
|
||||
|
||||
// if let Some(_25p) = self._25p.as_mut() {
|
||||
// v.push(_25p);
|
||||
// }
|
||||
|
||||
// if let Some(_10p) = self._10p.as_mut() {
|
||||
// v.push(_10p);
|
||||
// }
|
||||
|
||||
// v
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -60,7 +60,7 @@ impl SupplySubDataset {
|
||||
}: &InsertData,
|
||||
state: &SupplyState,
|
||||
) {
|
||||
let total_supply = self.supply.height.insert(height, state.supply.to_btc());
|
||||
let total_supply = self.supply.height.insert(height, state.supply().to_btc());
|
||||
|
||||
if is_date_last_block {
|
||||
self.supply.date.insert(date, total_supply);
|
||||
|
||||
@@ -86,30 +86,30 @@ impl UnrealizedSubDataset {
|
||||
) {
|
||||
self.supply_in_profit
|
||||
.height
|
||||
.insert(height, block_state.supply_in_profit.to_btc());
|
||||
.insert(height, block_state.supply_in_profit().to_btc());
|
||||
|
||||
self.unrealized_profit
|
||||
.height
|
||||
.insert(height, block_state.unrealized_profit.to_dollar() as f32);
|
||||
.insert(height, block_state.unrealized_profit().to_dollar() as f32);
|
||||
|
||||
self.unrealized_loss
|
||||
.height
|
||||
.insert(height, block_state.unrealized_loss.to_dollar() as f32);
|
||||
.insert(height, block_state.unrealized_loss().to_dollar() as f32);
|
||||
|
||||
if is_date_last_block {
|
||||
let date_state = date_state.as_ref().unwrap();
|
||||
|
||||
self.supply_in_profit
|
||||
.date
|
||||
.insert(date, date_state.supply_in_profit.to_btc());
|
||||
.insert(date, date_state.supply_in_profit().to_btc());
|
||||
|
||||
self.unrealized_profit
|
||||
.date
|
||||
.insert(date, date_state.unrealized_profit.to_dollar() as f32);
|
||||
.insert(date, date_state.unrealized_profit().to_dollar() as f32);
|
||||
|
||||
self.unrealized_loss
|
||||
.date
|
||||
.insert(date, date_state.unrealized_loss.to_dollar() as f32);
|
||||
.insert(date, date_state.unrealized_loss().to_dollar() as f32);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ impl UTXOSubDataset {
|
||||
}: &InsertData,
|
||||
state: &UTXOState,
|
||||
) {
|
||||
let count = self.count.height.insert(height, state.count);
|
||||
let count = self.count.height.insert(height, state.count());
|
||||
|
||||
if is_date_last_block {
|
||||
self.count.date.insert(date, count);
|
||||
|
||||
@@ -9,7 +9,7 @@ use serde_json::Value;
|
||||
use crate::{
|
||||
datasets::OHLC,
|
||||
io::{Json, INPUTS_FOLDER_PATH},
|
||||
structs::Date,
|
||||
structs::{Date, Timestamp},
|
||||
utils::{log, retry},
|
||||
};
|
||||
|
||||
@@ -169,9 +169,10 @@ impl Binance {
|
||||
// [timestamp, open, high, low, close, volume, ...]
|
||||
let array = value.as_array().unwrap();
|
||||
|
||||
let date = Date::from_timestamp(
|
||||
let date = Timestamp::wrap(
|
||||
(array.first().unwrap().as_u64().unwrap() / 1_000) as u32,
|
||||
);
|
||||
)
|
||||
.to_date();
|
||||
|
||||
let get_f32 = |index: usize| {
|
||||
array
|
||||
|
||||
@@ -5,7 +5,7 @@ use serde_json::Value;
|
||||
|
||||
use crate::{
|
||||
datasets::OHLC,
|
||||
structs::Date,
|
||||
structs::{Date, Timestamp},
|
||||
utils::{log, retry},
|
||||
};
|
||||
|
||||
@@ -91,8 +91,8 @@ impl Kraken {
|
||||
.map(|value| {
|
||||
let array = value.as_array().unwrap();
|
||||
|
||||
let date =
|
||||
Date::from_timestamp(array.first().unwrap().as_u64().unwrap() as u32);
|
||||
let date = Timestamp::wrap(array.first().unwrap().as_u64().unwrap() as u32)
|
||||
.to_date();
|
||||
|
||||
let get_f32 = |index: usize| {
|
||||
array
|
||||
|
||||
@@ -93,7 +93,7 @@ impl AddressCohortDurableStates {
|
||||
|
||||
let one_shot_states_ref = &mut one_shot_states;
|
||||
|
||||
let supply = self.durable_states.supply_state.supply;
|
||||
let supply = self.durable_states.supply_state.supply();
|
||||
|
||||
self.price_to_amount.iterate(supply, |price_paid, amount| {
|
||||
one_shot_states_ref
|
||||
|
||||
@@ -19,14 +19,18 @@ impl AddressCohortsRealizedStates {
|
||||
let realized_profit = realized_data.profit;
|
||||
let realized_loss = realized_data.loss;
|
||||
let value_created = realized_data.value_created;
|
||||
let adjusted_value_created = realized_data.adjusted_value_created;
|
||||
let value_destroyed = realized_data.value_destroyed;
|
||||
let adjusted_value_destroyed = realized_data.adjusted_value_destroyed;
|
||||
|
||||
let normal_iteration = move |state: &mut RealizedState| -> color_eyre::Result<()> {
|
||||
state.iterate(
|
||||
realized_profit,
|
||||
realized_loss,
|
||||
value_created,
|
||||
adjusted_value_created,
|
||||
value_destroyed,
|
||||
adjusted_value_destroyed,
|
||||
);
|
||||
Ok(())
|
||||
};
|
||||
@@ -35,8 +39,12 @@ impl AddressCohortsRealizedStates {
|
||||
liquidity_classification.split(realized_profit.to_cent() as f64);
|
||||
let split_realized_loss = liquidity_classification.split(realized_loss.to_cent() as f64);
|
||||
let split_value_created = liquidity_classification.split(value_created.to_cent() as f64);
|
||||
let split_adjusted_value_created =
|
||||
liquidity_classification.split(adjusted_value_created.to_cent() as f64);
|
||||
let split_value_destroyed =
|
||||
liquidity_classification.split(value_destroyed.to_cent() as f64);
|
||||
let split_adjusted_value_destroyed =
|
||||
liquidity_classification.split(adjusted_value_destroyed.to_cent() as f64);
|
||||
|
||||
let liquified_iteration =
|
||||
move |liquidity, state: &mut RealizedState| -> color_eyre::Result<()> {
|
||||
@@ -44,7 +52,9 @@ impl AddressCohortsRealizedStates {
|
||||
Price::from_cent(split_realized_profit.from(liquidity) as u64),
|
||||
Price::from_cent(split_realized_loss.from(liquidity) as u64),
|
||||
Price::from_cent(split_value_created.from(liquidity) as u64),
|
||||
Price::from_cent(split_adjusted_value_created.from(liquidity) as u64),
|
||||
Price::from_cent(split_value_destroyed.from(liquidity) as u64),
|
||||
Price::from_cent(split_adjusted_value_destroyed.from(liquidity) as u64),
|
||||
);
|
||||
Ok(())
|
||||
};
|
||||
|
||||
@@ -6,10 +6,14 @@ use crate::structs::Price;
|
||||
|
||||
#[derive(Debug, Default, Allocative)]
|
||||
pub struct CapitalizationState {
|
||||
pub realized_cap: Price,
|
||||
realized_cap: Price,
|
||||
}
|
||||
|
||||
impl CapitalizationState {
|
||||
pub fn realized_cap(&self) -> Price {
|
||||
self.realized_cap
|
||||
}
|
||||
|
||||
pub fn increment(&mut self, realized_cap: Price) {
|
||||
self.realized_cap += realized_cap;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,19 @@ use crate::structs::Amount;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct InputState {
|
||||
pub count: f64,
|
||||
pub volume: Amount,
|
||||
count: f64,
|
||||
volume: Amount,
|
||||
}
|
||||
|
||||
impl InputState {
|
||||
pub fn count(&self) -> f64 {
|
||||
self.count
|
||||
}
|
||||
|
||||
pub fn volume(&self) -> Amount {
|
||||
self.volume
|
||||
}
|
||||
|
||||
pub fn iterate(&mut self, count: f64, volume: Amount) {
|
||||
self.count += count;
|
||||
self.volume += volume;
|
||||
|
||||
@@ -2,11 +2,19 @@ use crate::structs::Amount;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct OutputState {
|
||||
pub count: f64,
|
||||
pub volume: Amount,
|
||||
count: f64,
|
||||
volume: Amount,
|
||||
}
|
||||
|
||||
impl OutputState {
|
||||
// pub fn count(&self) -> f64 {
|
||||
// self.count
|
||||
// }
|
||||
|
||||
// pub fn volume(&self) -> Amount {
|
||||
// self.volume
|
||||
// }
|
||||
|
||||
pub fn iterate(&mut self, count: f64, volume: Amount) {
|
||||
self.count += count;
|
||||
self.volume += volume;
|
||||
|
||||
@@ -2,30 +2,106 @@ use crate::structs::{Amount, Price};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct PricePaidState {
|
||||
pub pp_05p: Option<Price>,
|
||||
pub pp_10p: Option<Price>,
|
||||
pub pp_15p: Option<Price>,
|
||||
pub pp_20p: Option<Price>,
|
||||
pub pp_25p: Option<Price>,
|
||||
pub pp_30p: Option<Price>,
|
||||
pub pp_35p: Option<Price>,
|
||||
pub pp_40p: Option<Price>,
|
||||
pub pp_45p: Option<Price>,
|
||||
pub pp_median: Option<Price>,
|
||||
pub pp_55p: Option<Price>,
|
||||
pub pp_60p: Option<Price>,
|
||||
pub pp_65p: Option<Price>,
|
||||
pub pp_70p: Option<Price>,
|
||||
pub pp_75p: Option<Price>,
|
||||
pub pp_80p: Option<Price>,
|
||||
pub pp_85p: Option<Price>,
|
||||
pub pp_90p: Option<Price>,
|
||||
pub pp_95p: Option<Price>,
|
||||
pp_05p: Option<Price>,
|
||||
pp_10p: Option<Price>,
|
||||
pp_15p: Option<Price>,
|
||||
pp_20p: Option<Price>,
|
||||
pp_25p: Option<Price>,
|
||||
pp_30p: Option<Price>,
|
||||
pp_35p: Option<Price>,
|
||||
pp_40p: Option<Price>,
|
||||
pp_45p: Option<Price>,
|
||||
pp_median: Option<Price>,
|
||||
pp_55p: Option<Price>,
|
||||
pp_60p: Option<Price>,
|
||||
pp_65p: Option<Price>,
|
||||
pp_70p: Option<Price>,
|
||||
pp_75p: Option<Price>,
|
||||
pp_80p: Option<Price>,
|
||||
pp_85p: Option<Price>,
|
||||
pp_90p: Option<Price>,
|
||||
pp_95p: Option<Price>,
|
||||
|
||||
pub processed_amount: Amount,
|
||||
processed_amount: Amount,
|
||||
}
|
||||
|
||||
impl PricePaidState {
|
||||
pub fn pp_05p(&self) -> Option<Price> {
|
||||
self.pp_05p
|
||||
}
|
||||
|
||||
pub fn pp_10p(&self) -> Option<Price> {
|
||||
self.pp_10p
|
||||
}
|
||||
|
||||
pub fn pp_15p(&self) -> Option<Price> {
|
||||
self.pp_15p
|
||||
}
|
||||
|
||||
pub fn pp_20p(&self) -> Option<Price> {
|
||||
self.pp_20p
|
||||
}
|
||||
|
||||
pub fn pp_25p(&self) -> Option<Price> {
|
||||
self.pp_25p
|
||||
}
|
||||
|
||||
pub fn pp_30p(&self) -> Option<Price> {
|
||||
self.pp_30p
|
||||
}
|
||||
|
||||
pub fn pp_35p(&self) -> Option<Price> {
|
||||
self.pp_35p
|
||||
}
|
||||
|
||||
pub fn pp_40p(&self) -> Option<Price> {
|
||||
self.pp_40p
|
||||
}
|
||||
|
||||
pub fn pp_45p(&self) -> Option<Price> {
|
||||
self.pp_45p
|
||||
}
|
||||
|
||||
pub fn pp_median(&self) -> Option<Price> {
|
||||
self.pp_median
|
||||
}
|
||||
|
||||
pub fn pp_55p(&self) -> Option<Price> {
|
||||
self.pp_55p
|
||||
}
|
||||
|
||||
pub fn pp_60p(&self) -> Option<Price> {
|
||||
self.pp_60p
|
||||
}
|
||||
|
||||
pub fn pp_65p(&self) -> Option<Price> {
|
||||
self.pp_65p
|
||||
}
|
||||
|
||||
pub fn pp_70p(&self) -> Option<Price> {
|
||||
self.pp_70p
|
||||
}
|
||||
|
||||
pub fn pp_75p(&self) -> Option<Price> {
|
||||
self.pp_75p
|
||||
}
|
||||
|
||||
pub fn pp_80p(&self) -> Option<Price> {
|
||||
self.pp_80p
|
||||
}
|
||||
|
||||
pub fn pp_85p(&self) -> Option<Price> {
|
||||
self.pp_85p
|
||||
}
|
||||
|
||||
pub fn pp_90p(&self) -> Option<Price> {
|
||||
self.pp_90p
|
||||
}
|
||||
|
||||
pub fn pp_95p(&self) -> Option<Price> {
|
||||
self.pp_95p
|
||||
}
|
||||
|
||||
pub fn iterate(&mut self, price: Price, amount: Amount, supply: Amount) {
|
||||
let PricePaidState {
|
||||
processed_amount: processed_supply,
|
||||
|
||||
@@ -2,23 +2,53 @@ use crate::structs::Price;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct RealizedState {
|
||||
pub realized_profit: Price,
|
||||
pub realized_loss: Price,
|
||||
pub value_created: Price,
|
||||
pub value_destroyed: Price,
|
||||
realized_profit: Price,
|
||||
realized_loss: Price,
|
||||
value_created: Price,
|
||||
adjusted_value_created: Price,
|
||||
value_destroyed: Price,
|
||||
adjusted_value_destroyed: Price,
|
||||
}
|
||||
|
||||
impl RealizedState {
|
||||
pub fn realized_profit(&self) -> Price {
|
||||
self.realized_profit
|
||||
}
|
||||
|
||||
pub fn realized_loss(&self) -> Price {
|
||||
self.realized_loss
|
||||
}
|
||||
|
||||
pub fn value_created(&self) -> Price {
|
||||
self.value_created
|
||||
}
|
||||
|
||||
pub fn adjusted_value_created(&self) -> Price {
|
||||
self.adjusted_value_created
|
||||
}
|
||||
|
||||
pub fn value_destroyed(&self) -> Price {
|
||||
self.value_destroyed
|
||||
}
|
||||
|
||||
pub fn adjusted_value_destroyed(&self) -> Price {
|
||||
self.adjusted_value_destroyed
|
||||
}
|
||||
|
||||
pub fn iterate(
|
||||
&mut self,
|
||||
realized_profit: Price,
|
||||
realized_loss: Price,
|
||||
value_created: Price,
|
||||
adjusted_value_created: Price,
|
||||
value_destroyed: Price,
|
||||
adjusted_value_destroyed: Price,
|
||||
) {
|
||||
self.realized_profit += realized_profit;
|
||||
self.realized_loss += realized_loss;
|
||||
self.value_created += value_created;
|
||||
self.adjusted_value_created += adjusted_value_created;
|
||||
self.value_destroyed += value_destroyed;
|
||||
self.adjusted_value_destroyed += adjusted_value_destroyed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,14 @@ use crate::structs::Amount;
|
||||
|
||||
#[derive(Debug, Default, Allocative)]
|
||||
pub struct SupplyState {
|
||||
pub supply: Amount,
|
||||
supply: Amount,
|
||||
}
|
||||
|
||||
impl SupplyState {
|
||||
pub fn supply(&self) -> Amount {
|
||||
self.supply
|
||||
}
|
||||
|
||||
pub fn increment(&mut self, amount: Amount) {
|
||||
self.supply += amount;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,24 @@ use crate::structs::{Amount, Price};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct UnrealizedState {
|
||||
pub supply_in_profit: Amount,
|
||||
pub unrealized_profit: Price,
|
||||
pub unrealized_loss: Price,
|
||||
supply_in_profit: Amount,
|
||||
unrealized_profit: Price,
|
||||
unrealized_loss: Price,
|
||||
}
|
||||
|
||||
impl UnrealizedState {
|
||||
pub fn supply_in_profit(&self) -> Amount {
|
||||
self.supply_in_profit
|
||||
}
|
||||
|
||||
pub fn unrealized_profit(&self) -> Price {
|
||||
self.unrealized_profit
|
||||
}
|
||||
|
||||
pub fn unrealized_loss(&self) -> Price {
|
||||
self.unrealized_loss
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iterate(&mut self, price_then: Price, price_now: Price, amount: Amount) {
|
||||
match price_then.cmp(&price_now) {
|
||||
|
||||
@@ -5,10 +5,14 @@ use color_eyre::eyre::eyre;
|
||||
|
||||
#[derive(Debug, Default, Allocative)]
|
||||
pub struct UTXOState {
|
||||
pub count: f64,
|
||||
count: f64,
|
||||
}
|
||||
|
||||
impl UTXOState {
|
||||
pub fn count(&self) -> f64 {
|
||||
self.count
|
||||
}
|
||||
|
||||
pub fn increment(&mut self, utxo_count: f64) {
|
||||
self.count += utxo_count;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ impl UTXOCohortDurableStates {
|
||||
.replace(UnrealizedState::default());
|
||||
}
|
||||
|
||||
let supply = self.durable_states.supply_state.supply;
|
||||
let supply = self.durable_states.supply_state.supply();
|
||||
|
||||
let one_shot_states_ref = &mut one_shot_states;
|
||||
|
||||
|
||||
@@ -5,9 +5,7 @@ use rayon::prelude::*;
|
||||
|
||||
use crate::{
|
||||
states::DateDataVec,
|
||||
structs::{Amount, BlockData, Price, SentData},
|
||||
utils::difference_in_days_between_timestamps,
|
||||
Date,
|
||||
structs::{Amount, BlockData, Price, SentData, Timestamp},
|
||||
};
|
||||
|
||||
use super::{SplitByUTXOCohort, UTXOCohortDurableStates, UTXOCohortsOneShotStates};
|
||||
@@ -32,7 +30,7 @@ impl UTXOCohortsDurableStates {
|
||||
return;
|
||||
}
|
||||
|
||||
let increment_days_old = difference_in_days_between_timestamps(
|
||||
let increment_days_old = Timestamp::difference_in_days_between(
|
||||
block_data.timestamp,
|
||||
last_block_data.timestamp,
|
||||
);
|
||||
@@ -65,18 +63,18 @@ impl UTXOCohortsDurableStates {
|
||||
}
|
||||
|
||||
if block_data.height == last_block_data.height {
|
||||
let year = Date::from_timestamp(block_data.timestamp).year() as u32;
|
||||
let year = block_data.timestamp.to_year();
|
||||
|
||||
self.initial_filtered_apply(&0, &year, |state| {
|
||||
state.increment(amount, utxo_count, price).unwrap();
|
||||
})
|
||||
} else {
|
||||
let increment_days_old = difference_in_days_between_timestamps(
|
||||
let increment_days_old = Timestamp::difference_in_days_between(
|
||||
block_data.timestamp,
|
||||
last_block_data.timestamp,
|
||||
);
|
||||
|
||||
let decrement_days_old = difference_in_days_between_timestamps(
|
||||
let decrement_days_old = Timestamp::difference_in_days_between(
|
||||
block_data.timestamp,
|
||||
previous_last_block_data
|
||||
.unwrap_or_else(|| {
|
||||
@@ -117,12 +115,12 @@ impl UTXOCohortsDurableStates {
|
||||
return;
|
||||
}
|
||||
|
||||
let days_old = difference_in_days_between_timestamps(
|
||||
let days_old = Timestamp::difference_in_days_between(
|
||||
block_data.timestamp,
|
||||
previous_last_block_data.timestamp,
|
||||
);
|
||||
|
||||
let year = Date::from_timestamp(block_data.timestamp).year() as u32;
|
||||
let year = block_data.timestamp.to_year();
|
||||
|
||||
self.initial_filtered_apply(&days_old, &year, |state| {
|
||||
state
|
||||
|
||||
@@ -5,8 +5,7 @@ use derive_deref::{Deref, DerefMut};
|
||||
|
||||
use crate::{
|
||||
states::{DateDataVec, InputState, RealizedState},
|
||||
structs::{BlockPath, Price, SentData},
|
||||
utils::difference_in_days_between_timestamps,
|
||||
structs::{BlockPath, Price, SentData, Timestamp},
|
||||
};
|
||||
|
||||
use super::SplitByUTXOCohort;
|
||||
@@ -26,6 +25,7 @@ impl UTXOCohortsSentStates {
|
||||
date_data_vec: &DateDataVec,
|
||||
block_path_to_sent_data: &BTreeMap<BlockPath, SentData>,
|
||||
current_price: Price,
|
||||
current_timestamp: Timestamp,
|
||||
) {
|
||||
if let Some(last_block_data) = date_data_vec.last_block() {
|
||||
block_path_to_sent_data
|
||||
@@ -37,11 +37,12 @@ impl UTXOCohortsSentStates {
|
||||
|
||||
let block_data = date_data.get_block_data(block_path).unwrap();
|
||||
|
||||
let days_old = difference_in_days_between_timestamps(
|
||||
let days_old = Timestamp::difference_in_days_between(
|
||||
block_data.timestamp,
|
||||
last_block_data.timestamp,
|
||||
);
|
||||
|
||||
let previous_timestamp = block_data.timestamp;
|
||||
let previous_price = block_data.price;
|
||||
|
||||
let amount_sent = sent_data.volume;
|
||||
@@ -52,18 +53,34 @@ impl UTXOCohortsSentStates {
|
||||
let previous_value = previous_price * amount_sent;
|
||||
let current_value = current_price * amount_sent;
|
||||
|
||||
state.realized.value_destroyed += previous_value;
|
||||
state.realized.value_created += current_value;
|
||||
let mut realized_profit = Price::ZERO;
|
||||
let mut realized_loss = Price::ZERO;
|
||||
let value_created = current_value;
|
||||
let mut adjusted_value_created = Price::ZERO;
|
||||
let value_destroyed = previous_value;
|
||||
let mut adjusted_value_destroyed = Price::ZERO;
|
||||
|
||||
match previous_value.cmp(¤t_value) {
|
||||
Ordering::Less => {
|
||||
state.realized.realized_profit += current_value - previous_value;
|
||||
}
|
||||
Ordering::Less => realized_profit = current_value - previous_value,
|
||||
Ordering::Greater => {
|
||||
state.realized.realized_loss += previous_value - current_value;
|
||||
realized_loss = previous_value - current_value;
|
||||
}
|
||||
Ordering::Equal => {}
|
||||
}
|
||||
|
||||
if previous_timestamp.older_by_1h_plus_than(current_timestamp) {
|
||||
adjusted_value_created = value_created;
|
||||
adjusted_value_destroyed = value_destroyed;
|
||||
}
|
||||
|
||||
state.realized.iterate(
|
||||
realized_profit,
|
||||
realized_loss,
|
||||
value_created,
|
||||
adjusted_value_created,
|
||||
value_destroyed,
|
||||
adjusted_value_destroyed,
|
||||
);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{AddressData, Amount, Price};
|
||||
use super::{AddressData, Amount, Price, Timestamp};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AddressRealizedData {
|
||||
@@ -8,7 +8,9 @@ pub struct AddressRealizedData {
|
||||
pub profit: Price,
|
||||
pub loss: Price,
|
||||
pub value_created: Price,
|
||||
pub adjusted_value_created: Price,
|
||||
pub value_destroyed: Price,
|
||||
pub adjusted_value_destroyed: Price,
|
||||
pub utxos_created: u32,
|
||||
pub utxos_destroyed: u32,
|
||||
}
|
||||
@@ -23,7 +25,9 @@ impl AddressRealizedData {
|
||||
utxos_created: 0,
|
||||
utxos_destroyed: 0,
|
||||
value_created: Price::ZERO,
|
||||
adjusted_value_created: Price::ZERO,
|
||||
value_destroyed: Price::ZERO,
|
||||
adjusted_value_destroyed: Price::ZERO,
|
||||
initial_address_data: *initial_address_data,
|
||||
}
|
||||
}
|
||||
@@ -33,7 +37,14 @@ impl AddressRealizedData {
|
||||
self.utxos_created += 1;
|
||||
}
|
||||
|
||||
pub fn send(&mut self, amount: Amount, current_price: Price, previous_price: Price) {
|
||||
pub fn send(
|
||||
&mut self,
|
||||
amount: Amount,
|
||||
current_price: Price,
|
||||
previous_price: Price,
|
||||
current_timestamp: Timestamp,
|
||||
previous_timestamp: Timestamp,
|
||||
) {
|
||||
self.sent += amount;
|
||||
|
||||
self.utxos_destroyed += 1;
|
||||
@@ -44,6 +55,11 @@ impl AddressRealizedData {
|
||||
self.value_created += current_value;
|
||||
self.value_destroyed += previous_value;
|
||||
|
||||
if previous_timestamp.older_by_1h_plus_than(current_timestamp) {
|
||||
self.adjusted_value_created += current_value;
|
||||
self.adjusted_value_destroyed += previous_value;
|
||||
}
|
||||
|
||||
if current_value >= previous_value {
|
||||
self.profit += current_value - previous_value;
|
||||
} else {
|
||||
|
||||
@@ -36,6 +36,7 @@ direct_repr!(Amount);
|
||||
|
||||
impl Amount {
|
||||
pub const ZERO: Self = Self(BitcoinAmount::ZERO);
|
||||
pub const ONE_BTC_F32: f32 = 100_000_000.0;
|
||||
pub const ONE_BTC_F64: f64 = 100_000_000.0;
|
||||
|
||||
#[inline(always)]
|
||||
|
||||
@@ -299,6 +299,18 @@ where
|
||||
self.date
|
||||
.multi_insert_percentile(dates, date_map_and_percentiles, days);
|
||||
}
|
||||
|
||||
pub fn multi_insert_max(
|
||||
&mut self,
|
||||
heights: &[Height],
|
||||
dates: &[Date],
|
||||
source: &mut BiMap<Value>,
|
||||
) where
|
||||
Value: PartialOrd,
|
||||
{
|
||||
self.height.multi_insert_max(heights, &mut source.height);
|
||||
self.date.multi_insert_max(dates, &mut source.date);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AnyBiMap {
|
||||
|
||||
@@ -2,19 +2,19 @@ use allocative::Allocative;
|
||||
use bincode::{Decode, Encode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{Amount, Height, Price};
|
||||
use super::{Amount, Height, Price, Timestamp};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Encode, Decode, Allocative)]
|
||||
pub struct BlockData {
|
||||
pub height: Height,
|
||||
pub price: Price,
|
||||
pub timestamp: u32,
|
||||
pub timestamp: Timestamp,
|
||||
pub amount: Amount,
|
||||
pub utxos: u32,
|
||||
}
|
||||
|
||||
impl BlockData {
|
||||
pub fn new(height: Height, price: Price, timestamp: u32) -> Self {
|
||||
pub fn new(height: Height, price: Price, timestamp: Timestamp) -> Self {
|
||||
Self {
|
||||
height,
|
||||
price,
|
||||
|
||||
@@ -33,20 +33,21 @@ pub struct Config {
|
||||
pub delay: Option<u64>,
|
||||
|
||||
/// Start a dry run, default: false, not saved
|
||||
#[arg(long, default_value_t = false)]
|
||||
pub dry_run: bool,
|
||||
#[arg(long, value_name = "BOOL")]
|
||||
dry_run: Option<bool>,
|
||||
|
||||
/// Record ram usage, default: false, not saved
|
||||
#[arg(long, default_value_t = false)]
|
||||
pub record_ram_usage: bool,
|
||||
#[arg(long, value_name = "BOOL")]
|
||||
record_ram_usage: Option<bool>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
const PATH: &'static str = "./config.toml";
|
||||
|
||||
pub fn import() -> color_eyre::Result<Self> {
|
||||
let mut config_saved = fs::read_to_string(Self::PATH)
|
||||
.map_or(Config::default(), |contents| {
|
||||
let mut config_saved =
|
||||
fs::read_to_string(Self::PATH).map_or(Config::default(), |contents| {
|
||||
dbg!(&contents);
|
||||
toml::from_str(&contents).unwrap_or_default()
|
||||
});
|
||||
|
||||
@@ -92,8 +93,8 @@ impl Config {
|
||||
log(&format!("rpcuser: {:?}", config.rpcuser));
|
||||
log(&format!("rpcpassword: {:?}", config.rpcpassword));
|
||||
log(&format!("delay: {:?}", config.delay));
|
||||
log(&format!("dry_run: {}", config.dry_run));
|
||||
log(&format!("record_ram_usage: {}", config.record_ram_usage));
|
||||
log(&format!("dry_run: {:?}", config.dry_run));
|
||||
log(&format!("record_ram_usage: {:?}", config.record_ram_usage));
|
||||
log("---");
|
||||
|
||||
Ok(config)
|
||||
@@ -124,4 +125,12 @@ impl Config {
|
||||
fn write(&self) -> std::io::Result<()> {
|
||||
fs::write(Self::PATH, toml::to_string(self).unwrap())
|
||||
}
|
||||
|
||||
pub fn dry_run(&self) -> bool {
|
||||
self.dry_run.is_some_and(|b| b)
|
||||
}
|
||||
|
||||
pub fn record_ram_usage(&self) -> bool {
|
||||
self.record_ram_usage.is_some_and(|b| b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use bincode::{
|
||||
error::{DecodeError, EncodeError},
|
||||
BorrowDecode, Decode, Encode,
|
||||
};
|
||||
use chrono::{Datelike, Days, NaiveDate, TimeZone, Utc};
|
||||
use chrono::{Datelike, Days, NaiveDate};
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -38,14 +38,6 @@ impl Date {
|
||||
Self(date)
|
||||
}
|
||||
|
||||
pub fn from_timestamp(timestamp: u32) -> Self {
|
||||
Self(
|
||||
Utc.timestamp_opt(i64::from(timestamp), 0)
|
||||
.unwrap()
|
||||
.date_naive(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn today() -> Self {
|
||||
Self(chrono::offset::Utc::now().date_naive())
|
||||
}
|
||||
|
||||
@@ -818,4 +818,36 @@ where
|
||||
ControlFlow::Continue(())
|
||||
});
|
||||
}
|
||||
|
||||
pub fn multi_insert_max(&mut self, keys: &[Key], source: &mut Self)
|
||||
where
|
||||
Value: Default + PartialOrd,
|
||||
{
|
||||
let mut max = None;
|
||||
|
||||
keys.iter().for_each(|key| {
|
||||
let previous_max = max.unwrap_or_else(|| {
|
||||
key.checked_sub(1)
|
||||
.and_then(|previous_max_key| self.get(&previous_max_key))
|
||||
.unwrap_or_default()
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
self.insert(
|
||||
*key,
|
||||
max.unwrap_or_else(|| {
|
||||
dbg!(previous_max, last_value, max);
|
||||
panic!();
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
use crate::datasets::OHLC;
|
||||
|
||||
use super::{Date, Height};
|
||||
use super::{Date, Height, Timestamp};
|
||||
|
||||
pub trait MapValue:
|
||||
Clone
|
||||
@@ -32,3 +32,4 @@ impl MapValue for f64 {}
|
||||
impl MapValue for Date {}
|
||||
impl MapValue for OHLC {}
|
||||
impl MapValue for Height {}
|
||||
impl MapValue for Timestamp {}
|
||||
|
||||
@@ -29,6 +29,7 @@ mod price;
|
||||
mod sent_data;
|
||||
mod serialized_btreemap;
|
||||
mod serialized_vec;
|
||||
mod timestamp;
|
||||
mod tx_data;
|
||||
mod txout_index;
|
||||
|
||||
@@ -63,5 +64,6 @@ pub use price::*;
|
||||
pub use sent_data::*;
|
||||
pub use serialized_btreemap::*;
|
||||
pub use serialized_vec::*;
|
||||
pub use timestamp::*;
|
||||
pub use tx_data::*;
|
||||
pub use txout_index::*;
|
||||
|
||||
83
parser/src/structs/timestamp.rs
Normal file
83
parser/src/structs/timestamp.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use std::ops::Sub;
|
||||
|
||||
use allocative::Allocative;
|
||||
use bincode::{Decode, Encode};
|
||||
use chrono::{Datelike, NaiveDateTime, NaiveTime, TimeZone, Timelike, Utc};
|
||||
use derive_deref::{Deref, DerefMut};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::utils::{ONE_DAY_IN_S, ONE_HOUR_IN_S};
|
||||
|
||||
use super::Date;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
Allocative,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Deref,
|
||||
DerefMut,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Encode,
|
||||
Decode,
|
||||
)]
|
||||
pub struct Timestamp(u32);
|
||||
|
||||
impl Timestamp {
|
||||
pub const ZERO: Self = Self(0);
|
||||
|
||||
pub fn wrap(timestamp: u32) -> Self {
|
||||
Self(timestamp)
|
||||
}
|
||||
|
||||
pub fn to_date(self) -> Date {
|
||||
Date::wrap(
|
||||
Utc.timestamp_opt(i64::from(self.0), 0)
|
||||
.unwrap()
|
||||
.date_naive(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_year(self) -> u32 {
|
||||
self.to_date().year() as u32
|
||||
}
|
||||
|
||||
pub fn to_floored_seconds(self) -> Self {
|
||||
let date_time = Utc.timestamp_opt(i64::from(self.0), 0).unwrap();
|
||||
|
||||
Self::wrap(
|
||||
NaiveDateTime::new(
|
||||
date_time.date_naive(),
|
||||
NaiveTime::from_hms_opt(date_time.hour(), date_time.minute(), 0).unwrap(),
|
||||
)
|
||||
.and_utc()
|
||||
.timestamp() as u32,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn difference_in_days_between(older: Self, younger: Self) -> u32 {
|
||||
if younger <= older {
|
||||
0
|
||||
} else {
|
||||
*(younger - older) / ONE_DAY_IN_S as u32
|
||||
}
|
||||
}
|
||||
|
||||
pub fn older_by_1h_plus_than(&self, younger: Self) -> bool {
|
||||
younger.checked_sub(**self).unwrap_or_default() > ONE_HOUR_IN_S as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Timestamp {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self::wrap(self.0 - rhs.0)
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ use std::time::Instant;
|
||||
|
||||
use crate::utils::log;
|
||||
|
||||
use super::ONE_DAY_IN_S;
|
||||
|
||||
pub fn time<F, T>(name: &str, function: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
@@ -16,11 +14,3 @@ where
|
||||
|
||||
returned
|
||||
}
|
||||
|
||||
pub fn difference_in_days_between_timestamps(older: u32, younger: u32) -> u32 {
|
||||
if younger <= older {
|
||||
0
|
||||
} else {
|
||||
(younger - older) / ONE_DAY_IN_S as u32
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user