mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-25 07:09:59 -07:00
parser: added ratio and co datasets
This commit is contained in:
@@ -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),
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user