From 2bec7ddcbec3a1eeabc502c4317510198cb80347 Mon Sep 17 00:00:00 2001 From: Sebastian Rollen Date: Mon, 26 Jul 2021 14:11:46 -0400 Subject: [PATCH 1/2] remove percent, rename to amount --- Cargo.toml | 2 +- src/position_intents.rs | 30 ++++++++++++++---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8027197..775868f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trading-base" -version = "0.1.0" +version = "0.2.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/position_intents.rs b/src/position_intents.rs index cb748ba..0bdf9fb 100644 --- a/src/position_intents.rs +++ b/src/position_intents.rs @@ -15,21 +15,19 @@ pub enum UpdatePolicy { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[serde(rename_all = "snake_case")] -pub enum AmountSpec { +pub enum Amount { Dollars(Decimal), Shares(Decimal), - Percent(Decimal), Zero, } -impl AmountSpec { +impl Amount { pub fn merge(self, other: Self) -> Result { match (self, other) { - (AmountSpec::Dollars(x), AmountSpec::Dollars(y)) => Ok(AmountSpec::Dollars(x + y)), - (AmountSpec::Shares(x), AmountSpec::Shares(y)) => Ok(AmountSpec::Shares(x + y)), - (AmountSpec::Percent(x), AmountSpec::Percent(y)) => Ok(AmountSpec::Percent(x + y)), - (AmountSpec::Zero, AmountSpec::Zero) => Ok(AmountSpec::Zero), - (AmountSpec::Zero, y) => Ok(y), - (x, AmountSpec::Zero) => Ok(x), + (Amount::Dollars(x), Amount::Dollars(y)) => Ok(Amount::Dollars(x + y)), + (Amount::Shares(x), Amount::Shares(y)) => Ok(Amount::Shares(x + y)), + (Amount::Zero, Amount::Zero) => Ok(Amount::Zero), + (Amount::Zero, y) => Ok(y), + (x, Amount::Zero) => Ok(x), (x, y) => Err(Error::IncompatibleAmountError(x, y)), } } @@ -53,7 +51,7 @@ pub struct PositionIntentBuilder { strategy: String, sub_strategy: Option, ticker: TickerSpec, - amount: AmountSpec, + amount: Amount, update_policy: UpdatePolicy, decision_price: Option, limit_price: Option, @@ -105,8 +103,8 @@ impl PositionIntentBuilder { } } match (self.ticker.clone(), self.amount.clone()) { - (TickerSpec::All, AmountSpec::Dollars(_)) => return Err(Error::InvalidCombination), - (TickerSpec::All, AmountSpec::Shares(_)) => return Err(Error::InvalidCombination), + (TickerSpec::All, Amount::Dollars(_)) => return Err(Error::InvalidCombination), + (TickerSpec::All, Amount::Shares(_)) => return Err(Error::InvalidCombination), _ => (), } Ok(PositionIntent { @@ -139,7 +137,7 @@ pub struct PositionIntent { pub sub_strategy: Option, pub timestamp: DateTime, pub ticker: TickerSpec, - pub amount: AmountSpec, + pub amount: Amount, pub update_policy: UpdatePolicy, /// The price at which the decision was made to send a position request. This can be used by /// other parts of the app for execution analysis. This field might also be used for @@ -160,7 +158,7 @@ impl PositionIntent { pub fn builder( strategy: impl Into, ticker: impl Into, - amount: AmountSpec, + amount: Amount, ) -> PositionIntentBuilder { PositionIntentBuilder { strategy: strategy.into(), @@ -184,7 +182,7 @@ mod test { #[test] fn can_construct_position_intent() { - let builder = PositionIntent::builder("A", "AAPL", AmountSpec::Dollars(Decimal::new(1, 0))); + let builder = PositionIntent::builder("A", "AAPL", Amount::Dollars(Decimal::new(1, 0))); let _intent = builder .sub_strategy("B") .decision_price(Decimal::new(2, 0)) @@ -199,7 +197,7 @@ mod test { #[test] fn can_serialize_and_deserialize() { - let builder = PositionIntent::builder("A", "AAPL", AmountSpec::Shares(Decimal::new(1, 0))); + let builder = PositionIntent::builder("A", "AAPL", Amount::Shares(Decimal::new(1, 0))); let intent = builder .sub_strategy("B") .decision_price(Decimal::new(2, 0)) From 9f611543e84f288347f47789ca0f28a745d503fd Mon Sep 17 00:00:00 2001 From: Sebastian Rollen Date: Mon, 26 Jul 2021 14:14:22 -0400 Subject: [PATCH 2/2] rename tickerspec to identifier --- src/lib.rs | 6 +++--- src/position_intents.rs | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 44cd3f1..b13efba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ use thiserror::Error; mod position_intents; pub use position_intents::{ - AmountSpec, PositionIntent, PositionIntentBuilder, TickerSpec, UpdatePolicy, + Amount, Identifier, PositionIntent, PositionIntentBuilder, UpdatePolicy, }; mod trade_intents; pub use trade_intents::{OrderType, TimeInForce, TradeIntent}; @@ -13,9 +13,9 @@ pub enum Error { #[error( "Non-`Zero` `AmountSpec`s of different type cannot be merged.\nLeft: {0:?}, Right: {1:?}" )] - IncompatibleAmountError(AmountSpec, AmountSpec), + IncompatibleAmountError(Amount, Amount), #[error("Cannot create PositionIntent with `before` < `after`. \nBefore: {0}, After: {1}")] InvalidBeforeAfter(DateTime, DateTime), - #[error("TickerSpec `All` can only be used with the `Dollars` and `Shares` `AmountSpec`s")] + #[error("Identifier `All` can only be used with the `Dollars` and `Shares` `Amount`s")] InvalidCombination, } diff --git a/src/position_intents.rs b/src/position_intents.rs index 0bdf9fb..5f853b5 100644 --- a/src/position_intents.rs +++ b/src/position_intents.rs @@ -35,12 +35,12 @@ impl Amount { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[serde(rename_all = "lowercase")] -pub enum TickerSpec { +pub enum Identifier { Ticker(String), All, } -impl From for TickerSpec { +impl From for Identifier { fn from(s: T) -> Self { Self::Ticker(s.to_string()) } @@ -50,7 +50,7 @@ impl From for TickerSpec { pub struct PositionIntentBuilder { strategy: String, sub_strategy: Option, - ticker: TickerSpec, + identifier: Identifier, amount: Amount, update_policy: UpdatePolicy, decision_price: Option, @@ -102,9 +102,9 @@ impl PositionIntentBuilder { return Err(Error::InvalidBeforeAfter(before, after)); } } - match (self.ticker.clone(), self.amount.clone()) { - (TickerSpec::All, Amount::Dollars(_)) => return Err(Error::InvalidCombination), - (TickerSpec::All, Amount::Shares(_)) => return Err(Error::InvalidCombination), + match (self.identifier.clone(), self.amount.clone()) { + (Identifier::All, Amount::Dollars(_)) => return Err(Error::InvalidCombination), + (Identifier::All, Amount::Shares(_)) => return Err(Error::InvalidCombination), _ => (), } Ok(PositionIntent { @@ -112,7 +112,7 @@ impl PositionIntentBuilder { strategy: self.strategy, sub_strategy: self.sub_strategy, timestamp: Utc::now(), - ticker: self.ticker, + identifier: self.identifier, amount: self.amount, update_policy: self.update_policy, decision_price: self.decision_price, @@ -136,7 +136,7 @@ pub struct PositionIntent { #[serde(skip_serializing_if = "Option::is_none")] pub sub_strategy: Option, pub timestamp: DateTime, - pub ticker: TickerSpec, + pub identifier: Identifier, pub amount: Amount, pub update_policy: UpdatePolicy, /// The price at which the decision was made to send a position request. This can be used by @@ -157,13 +157,13 @@ pub struct PositionIntent { impl PositionIntent { pub fn builder( strategy: impl Into, - ticker: impl Into, + identifier: impl Into, amount: Amount, ) -> PositionIntentBuilder { PositionIntentBuilder { strategy: strategy.into(), sub_strategy: None, - ticker: ticker.into(), + identifier: identifier.into(), amount, update_policy: UpdatePolicy::Update, decision_price: None,