diff --git a/Cargo.toml b/Cargo.toml index 5d5687e..f43b9a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trade_aggregation" -version = "9.0.0" +version = "9.1.0" authors = ["MathisWellmann "] edition = "2021" license-file = "LICENSE" diff --git a/README.md b/README.md index 262a91e..a957ba6 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ WeightedPrice | The volume weighted price StdDevPrices | Keeps track of the standard deviation of prices StdDevSizes | Keeps track of the standard deviaton of sizes TimeVelocity | Essentially how fast the candle was created time wise +Entropy | Binary shannon entropy using the trade side as inputs And again, if these don't satisfy your needs, just bring your own by implementing the [CandleComponent](src/candle_components/candle_component_trait.rs) trait and you can plug them into your own candle struct. diff --git a/src/candle_components/entropy.rs b/src/candle_components/entropy.rs new file mode 100644 index 0000000..c39100b --- /dev/null +++ b/src/candle_components/entropy.rs @@ -0,0 +1,37 @@ +use crate::{CandleComponent, CandleComponentUpdate, TakerTrade}; + +/// A `CandleComponent` that computes the binary entropy of whether a trade is a buy or a sell. +#[derive(Default, Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Entropy { + buys: usize, + total_observed_trades: usize, +} + +impl CandleComponent for Entropy { + fn value(&self) -> f64 { + let pt = self.buys as f64 / self.total_observed_trades as f64; + let pn = 1_f64 - pt; + + let mut h = pt * pt.log2() + pn * pn.log2(); + if h.is_nan() { + h = 0.0; + } + + -h + } + + fn reset(&mut self) { + self.buys = 0; + self.total_observed_trades = 0; + } +} + +impl CandleComponentUpdate for Entropy { + fn update(&mut self, trade: &T) { + if trade.size() > 0.0 { + self.buys += 1 + } + self.total_observed_trades += 1; + } +} diff --git a/src/candle_components/mod.rs b/src/candle_components/mod.rs index c6ba4a3..d468da3 100644 --- a/src/candle_components/mod.rs +++ b/src/candle_components/mod.rs @@ -6,6 +6,7 @@ mod candle_component_trait; mod close; mod directional_trade_ratio; mod directional_volume_ratio; +mod entropy; mod high; mod low; mod median_price; @@ -25,6 +26,7 @@ pub use candle_component_trait::{CandleComponent, CandleComponentUpdate}; pub use close::Close; pub use directional_trade_ratio::DirectionalTradeRatio; pub use directional_volume_ratio::DirectionalVolumeRatio; +pub use entropy::Entropy; pub use high::High; pub use low::Low; pub use median_price::MedianPrice; diff --git a/src/candle_components/open_datetime.rs b/src/candle_components/open_datetime.rs index 4c52721..a944ca6 100644 --- a/src/candle_components/open_datetime.rs +++ b/src/candle_components/open_datetime.rs @@ -1,9 +1,7 @@ -use crate::CandleComponent; -use crate::CandleComponentUpdate; -use crate::TakerTrade; -use crate::TimestampResolution; use chrono::{DateTime, TimeZone, Utc}; +use crate::{CandleComponent, CandleComponentUpdate, TakerTrade, TimestampResolution}; + /// This 'CandleComponent' keeps track of the opening [DateTime] of a Candle. #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]