use crate::{error::RithmicError, types::ManualOrAutoEntry};
#[derive(Debug, Clone, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
#[must_use = "a command does nothing until passed to a plant handle"]
pub struct RithmicExitPosition {
pub symbol: Option<String>,
pub exchange: Option<String>,
pub manual_or_auto: ManualOrAutoEntry,
pub window_name: Option<String>,
pub trading_algorithm: Option<String>,
}
impl RithmicExitPosition {
pub fn new() -> Self {
Self::default()
}
pub fn symbol(mut self, symbol: impl Into<String>) -> Self {
self.symbol = Some(symbol.into());
self
}
pub fn exchange(mut self, exchange: impl Into<String>) -> Self {
self.exchange = Some(exchange.into());
self
}
pub fn manual_or_auto(mut self, manual_or_auto: ManualOrAutoEntry) -> Self {
self.manual_or_auto = manual_or_auto;
self
}
pub fn window_name(mut self, window_name: impl Into<String>) -> Self {
self.window_name = Some(window_name.into());
self
}
pub fn trading_algorithm(mut self, trading_algorithm: impl Into<String>) -> Self {
self.trading_algorithm = Some(trading_algorithm.into());
self
}
pub fn validate(&self) -> Result<(), RithmicError> {
match (&self.symbol, &self.exchange) {
(Some(symbol), _) if symbol.is_empty() => Err(RithmicError::InvalidArgument(
"the exit symbol must be non-empty; leave both unset to flatten the account"
.to_string(),
)),
(_, Some(exchange)) if exchange.is_empty() => Err(RithmicError::InvalidArgument(
"the exit exchange must be non-empty; leave both unset to flatten the account"
.to_string(),
)),
(Some(_), None) | (None, Some(_)) => Err(RithmicError::InvalidArgument(
"symbol and exchange come as a pair: set both to flatten one instrument, \
neither to flatten the account"
.to_string(),
)),
_ => Ok(()),
}
}
pub fn build(self) -> Result<Self, RithmicError> {
self.validate()?;
Ok(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn an_exit_takes_the_instrument_as_a_pair_or_not_at_all() {
assert!(RithmicExitPosition::new().build().is_ok());
assert!(RithmicExitPosition::new().symbol("ESM6").build().is_err());
assert!(RithmicExitPosition::new().exchange("CME").build().is_err());
assert!(
RithmicExitPosition::new()
.symbol("")
.exchange("CME")
.build()
.is_err()
);
assert!(
RithmicExitPosition::new()
.symbol("ESM6")
.exchange("")
.build()
.is_err()
);
assert!(
RithmicExitPosition::new()
.symbol("ESM6")
.exchange("CME")
.build()
.is_ok()
);
}
}