parser: added ratio and co datasets

This commit is contained in:
k
2024-07-10 18:34:01 +02:00
parent 6976f5af0f
commit 4a82ee0b05
20 changed files with 624 additions and 237 deletions

View File

@@ -43,12 +43,7 @@ impl AddressData {
self.realized_cap += received_value;
}
pub fn send(
&mut self,
amount: WAmount,
current_price: Price,
sent_amount_price: Price,
) -> color_eyre::Result<ProfitOrLoss> {
pub fn send(&mut self, amount: WAmount, previous_price: Price) -> color_eyre::Result<()> {
let previous_amount = self.amount;
if previous_amount < amount {
@@ -63,18 +58,10 @@ impl AddressData {
self.outputs_len -= 1;
let previous_sent_dollar_value = sent_amount_price * amount;
let previous_sent_dollar_value = previous_price * amount;
self.realized_cap -= previous_sent_dollar_value;
let current_sent_dollar_value = current_price * amount;
let profit_or_loss = if current_sent_dollar_value >= previous_sent_dollar_value {
ProfitOrLoss::Profit(current_sent_dollar_value - previous_sent_dollar_value)
} else {
ProfitOrLoss::Loss(previous_sent_dollar_value - current_sent_dollar_value)
};
Ok(profit_or_loss)
Ok(())
}
#[inline(always)]
@@ -105,8 +92,3 @@ impl AddressData {
LiquidityClassification::new(self.sent, self.received)
}
}
pub enum ProfitOrLoss {
Profit(Price),
Loss(Price),
}

View File

@@ -1,4 +1,4 @@
use super::{AddressData, Price, ProfitOrLoss, WAmount};
use super::{AddressData, Price, WAmount};
#[derive(Debug)]
pub struct AddressRealizedData {
@@ -7,6 +7,8 @@ pub struct AddressRealizedData {
pub sent: WAmount,
pub profit: Price,
pub loss: Price,
pub value_created: Price,
pub value_destroyed: Price,
pub utxos_created: u32,
pub utxos_destroyed: u32,
}
@@ -20,6 +22,8 @@ impl AddressRealizedData {
loss: Price::ZERO,
utxos_created: 0,
utxos_destroyed: 0,
value_created: Price::ZERO,
value_destroyed: Price::ZERO,
initial_address_data: *initial_address_data,
}
}
@@ -29,18 +33,21 @@ impl AddressRealizedData {
self.utxos_created += 1;
}
pub fn send(&mut self, amount: WAmount, realized_profit_or_loss: ProfitOrLoss) {
pub fn send(&mut self, amount: WAmount, current_price: Price, previous_price: Price) {
self.sent += amount;
self.utxos_destroyed += 1;
match realized_profit_or_loss {
ProfitOrLoss::Profit(price) => {
self.profit += price;
}
ProfitOrLoss::Loss(price) => {
self.loss += price;
}
let current_value = current_price * amount;
let previous_value = previous_price * amount;
self.value_created += current_value;
self.value_destroyed += previous_value;
if current_value >= previous_value {
self.profit += current_value - previous_value;
} else {
self.loss += previous_value - current_value;
}
}
}

View File

@@ -277,20 +277,29 @@ where
&mut self,
heights: &[usize],
dates: &[WNaiveDate],
source: &mut BiMap<T>,
percentile: f32,
mut map_and_percentiles: Vec<(&mut BiMap<T>, f32)>,
days: Option<usize>,
) where
T: FloatCore,
{
let mut date_map_and_percentiles = vec![];
let mut height_map_and_percentiles = vec![];
map_and_percentiles
.iter_mut()
.for_each(|(map, percentile)| {
date_map_and_percentiles.push((&mut map.date, *percentile));
height_map_and_percentiles.push((&mut map.height, *percentile));
});
self.height.multi_insert_percentile(
heights,
&mut source.height,
percentile,
height_map_and_percentiles,
days.map(|days| TARGET_BLOCKS_PER_DAY * days),
);
self.date
.multi_insert_percentile(dates, &mut source.date, percentile, days);
.multi_insert_percentile(dates, date_map_and_percentiles, days);
}
}

View File

@@ -423,10 +423,10 @@ where
&mut self,
dates: &[WNaiveDate],
source: &mut DateMap<K>,
transform: F,
mut transform: F,
) where
K: MapValue,
F: Fn((K, &WNaiveDate, &mut DateMap<K>)) -> T,
F: FnMut((K, &WNaiveDate, &mut DateMap<K>)) -> T,
{
dates.iter().for_each(|date| {
self.insert(
@@ -706,113 +706,129 @@ where
) where
T: FloatCore,
{
self.multi_insert_percentile(dates, source, 0.5, days);
source.multi_insert_percentile(dates, vec![(self, 0.5)], days);
}
pub fn multi_insert_percentile(
&mut self,
dates: &[WNaiveDate],
source: &mut DateMap<T>,
percentile: f32,
mut map_and_percentiles: Vec<(&mut DateMap<T>, f32)>,
days: Option<usize>,
) where
T: FloatCore,
{
if !(0.0..=1.0).contains(&percentile) {
panic!("The percentile should be between 0.0 and 1.0");
}
if days.map_or(false, |size| size < 3) {
panic!("Computing a median for a size lower than 3 is useless");
panic!("Computing a percentile for a size lower than 3 is useless");
}
let mut ordered_vec = None;
let mut sorted_vec = None;
dates.iter().for_each(|date| {
let value = {
if let Some(start) = days
.map_or(chrono::NaiveDate::from_ymd_opt(2009, 3, 1), |size| {
date.checked_sub_days(Days::new(size as u64))
})
{
if ordered_vec.is_none() {
let mut vec = start
.iter_days()
.take_while(|d| *d != **date)
.flat_map(|date| source.get_or_import(&WNaiveDate::wrap(date)))
.map(|f| OrderedFloat(f))
.collect_vec();
if let Some(start) = days.map_or(chrono::NaiveDate::from_ymd_opt(2009, 1, 3), |size| {
date.checked_sub_days(Days::new(size as u64))
}) {
if sorted_vec.is_none() {
let mut vec = start
.iter_days()
.take_while(|d| *d != **date)
.flat_map(|date| self.get_or_import(&WNaiveDate::wrap(date)))
.map(|f| OrderedFloat(f))
.collect_vec();
if days.is_some() {
ordered_vec.replace(VecDeque::from(vec.clone()));
}
vec.sort_unstable();
sorted_vec.replace(vec);
} else {
let float_value = OrderedFloat(source.get_or_import(date).unwrap());
if let Some(days) = days {
if let Some(ordered_vec) = ordered_vec.as_mut() {
if ordered_vec.len() == days {
let first = ordered_vec.pop_front().unwrap();
let pos =
sorted_vec.as_ref().unwrap().binary_search(&first).unwrap();
sorted_vec.as_mut().unwrap().remove(pos);
}
ordered_vec.push_back(float_value);
}
}
let pos = sorted_vec
.as_ref()
.unwrap()
.binary_search(&float_value)
.unwrap_or_else(|pos| pos);
sorted_vec.as_mut().unwrap().insert(pos, float_value);
if days.is_some() {
ordered_vec.replace(VecDeque::from(vec.clone()));
}
let vec = sorted_vec.as_ref().unwrap();
if vec.is_empty() {
T::default()
} else {
let index = vec.len() as f32 * percentile;
if index.fract() != 0.0 && vec.len() > 1 {
(vec.get(index.ceil() as usize)
.unwrap_or_else(|| {
dbg!(vec, index, &self.path_all, &source.path_all, days);
panic!()
})
.0
+ vec
.get(index.floor() as usize)
.unwrap_or_else(|| {
dbg!(vec, index, &self.path_all, &source.path_all, days);
panic!()
})
.0)
/ T::from(2.0).unwrap()
} else {
vec.get(index.floor() as usize)
.unwrap_or_else(|| {
dbg!(vec, index);
panic!();
})
.0
}
}
vec.sort_unstable();
sorted_vec.replace(vec);
} else {
T::default()
}
};
let float_value = OrderedFloat(self.get_or_import(date).unwrap());
self.insert(*date, value);
if let Some(days) = days {
if let Some(ordered_vec) = ordered_vec.as_mut() {
if ordered_vec.len() == days {
let first = ordered_vec.pop_front().unwrap();
let pos =
sorted_vec.as_ref().unwrap().binary_search(&first).unwrap();
sorted_vec.as_mut().unwrap().remove(pos);
}
ordered_vec.push_back(float_value);
}
}
let pos = sorted_vec
.as_ref()
.unwrap()
.binary_search(&float_value)
.unwrap_or_else(|pos| pos);
sorted_vec.as_mut().unwrap().insert(pos, float_value);
}
let vec = sorted_vec.as_ref().unwrap();
let len = vec.len();
map_and_percentiles
.iter_mut()
.for_each(|(map, percentile)| {
if !(0.0..=1.0).contains(percentile) {
panic!("The percentile should be between 0.0 and 1.0");
}
let value = {
if vec.is_empty() {
T::default()
} else {
let index = (len - 1) as f32 * *percentile;
let fract = index.fract();
let fract_t = T::from(fract).unwrap();
if fract != 0.0 {
(vec.get(index.ceil() as usize)
.unwrap_or_else(|| {
dbg!(vec, index, &self.path_all, &self.path_all, days);
panic!()
})
.0
* fract_t
+ vec
.get(index.floor() as usize)
.unwrap_or_else(|| {
dbg!(
vec,
index,
&self.path_all,
&self.path_all,
days
);
panic!()
})
.0)
* T::from(1.0 - fract).unwrap()
} else {
vec.get(index.floor() as usize)
.unwrap_or_else(|| {
dbg!(vec, index);
panic!();
})
.0
}
}
};
(*map).insert(*date, value);
});
} else {
map_and_percentiles.iter_mut().for_each(|(map, _)| {
(*map).insert(*date, T::default());
});
}
});
}

View File

@@ -444,10 +444,10 @@ where
&mut self,
heights: &[usize],
source: &mut HeightMap<K>,
transform: F,
mut transform: F,
) where
K: MapValue,
F: Fn((K, &usize)) -> T,
F: FnMut((K, &usize)) -> T,
{
heights.iter().for_each(|height| {
self.insert(*height, transform((source.get_or_import(height), height)));
@@ -695,24 +695,19 @@ where
) where
T: FloatCore,
{
self.multi_insert_percentile(heights, source, 0.5, block_time);
source.multi_insert_percentile(heights, vec![(self, 0.5)], block_time);
}
pub fn multi_insert_percentile(
&mut self,
heights: &[usize],
source: &mut HeightMap<T>,
percentile: f32,
mut map_and_percentiles: Vec<(&mut HeightMap<T>, f32)>,
block_time: Option<usize>,
) where
T: FloatCore,
{
if !(0.0..=1.0).contains(&percentile) {
panic!("The percentile should be between 0.0 and 1.0");
}
if block_time.map_or(false, |size| size < 3) {
panic!("Computing a median for a size lower than 3 is useless");
panic!("Computing a percentile for a size lower than 3 is useless");
}
let mut ordered_vec = None;
@@ -721,66 +716,100 @@ where
heights.iter().for_each(|height| {
let height = *height;
let value = {
if let Some(start) = block_time.map_or(Some(0), |size| height.checked_sub(size)) {
if ordered_vec.is_none() {
let mut vec = (start..=height)
.map(|height| OrderedFloat(source.get_or_import(&height)))
.collect_vec();
if let Some(start) = block_time.map_or(Some(0), |size| height.checked_sub(size)) {
if sorted_vec.is_none() {
let mut vec = (start..=height)
.map(|height| OrderedFloat(self.get_or_import(&height)))
.collect_vec();
if block_time.is_some() {
ordered_vec.replace(VecDeque::from(vec.clone()));
}
vec.sort_unstable();
sorted_vec.replace(vec);
} else {
let float_value = OrderedFloat(source.get_or_import(&height));
if block_time.is_some() {
let first = ordered_vec.as_mut().unwrap().pop_front().unwrap();
let pos = sorted_vec.as_ref().unwrap().binary_search(&first).unwrap();
sorted_vec.as_mut().unwrap().remove(pos);
ordered_vec.as_mut().unwrap().push_back(float_value);
}
let pos = sorted_vec
.as_ref()
.unwrap()
.binary_search(&float_value)
.unwrap_or_else(|pos| pos);
sorted_vec.as_mut().unwrap().insert(pos, float_value);
if block_time.is_some() {
ordered_vec.replace(VecDeque::from(vec.clone()));
}
let vec = sorted_vec.as_ref().unwrap();
vec.sort_unstable();
let index = vec.len() as f32 * percentile;
if index.fract() != 0.0 {
(vec.get(index.ceil() as usize)
.unwrap_or_else(|| {
dbg!(index, &self.path_all, &source.path_all, block_time);
panic!()
})
.0
+ vec
.get(index.floor() as usize)
.unwrap_or_else(|| {
dbg!(index, &self.path_all, &source.path_all, block_time);
panic!()
})
.0)
/ T::from(2.0).unwrap()
} else {
vec.get(index as usize).unwrap().0
}
sorted_vec.replace(vec);
} else {
T::default()
}
};
let float_value = OrderedFloat(self.get_or_import(&height));
self.insert(height, value);
if block_time.is_some() {
let first = ordered_vec.as_mut().unwrap().pop_front().unwrap();
let pos = sorted_vec.as_ref().unwrap().binary_search(&first).unwrap();
sorted_vec.as_mut().unwrap().remove(pos);
ordered_vec.as_mut().unwrap().push_back(float_value);
}
let pos = sorted_vec
.as_ref()
.unwrap()
.binary_search(&float_value)
.unwrap_or_else(|pos| pos);
sorted_vec.as_mut().unwrap().insert(pos, float_value);
}
let vec = sorted_vec.as_ref().unwrap();
let len = vec.len();
map_and_percentiles
.iter_mut()
.for_each(|(map, percentile)| {
if !(0.0..=1.0).contains(percentile) {
panic!("The percentile should be between 0.0 and 1.0");
}
let value = {
if vec.is_empty() {
T::default()
} else {
let index = (len - 1) as f32 * *percentile;
let fract = index.fract();
let fract_t = T::from(fract).unwrap();
if fract != 0.0 {
(vec.get(index.ceil() as usize)
.unwrap_or_else(|| {
dbg!(
index,
&self.path_all,
&self.path_all,
&self.to_insert,
block_time,
vec
);
panic!()
})
.0
* fract_t
+ vec
.get(index.floor() as usize)
.unwrap_or_else(|| {
dbg!(
index,
&self.path_all,
&self.path_all,
block_time
);
panic!()
})
.0)
* T::from(1.0 - fract).unwrap()
} else {
vec.get(index as usize).unwrap().0
}
}
};
(*map).insert(height, value);
});
} else {
map_and_percentiles.iter_mut().for_each(|(map, _)| {
(*map).insert(height, T::default());
});
}
});
}