pub(crate) mod bracket;
pub(crate) mod cancel;
pub(crate) mod exit;
pub(crate) mod link;
pub(crate) mod modify;
pub(crate) mod oco;
pub(crate) mod order;
pub(crate) mod triggers;
use crate::{error::RithmicError, types::OrderType};
pub use bracket::{RithmicBracketLevelAdjustment, RithmicBracketOrder};
pub use cancel::{RithmicCancelAllOrders, RithmicCancelOrder};
pub use exit::RithmicExitPosition;
pub use link::RithmicLinkOrders;
pub use modify::{RithmicModifyOrder, RithmicModifyOrderReferenceData};
pub use oco::{RithmicOcoOrder, RithmicOcoOrderLeg};
pub use order::RithmicOrder;
pub use triggers::{RithmicIfTouchedTrigger, TrailingStop};
pub(crate) fn validate_instrument(
symbol: &str,
exchange: &str,
quantity: i32,
) -> Result<(), RithmicError> {
if symbol.is_empty() {
return Err(RithmicError::InvalidArgument(
"a symbol is required".to_string(),
));
}
if exchange.is_empty() {
return Err(RithmicError::InvalidArgument(
"an exchange is required".to_string(),
));
}
if quantity < 1 {
return Err(RithmicError::InvalidArgument(format!(
"quantity must be at least 1, got {quantity}"
)));
}
Ok(())
}
pub(crate) fn price_requirements(price_type: OrderType) -> (bool, bool) {
match price_type {
OrderType::Market => (false, false),
OrderType::Limit => (true, false),
OrderType::StopMarket | OrderType::MarketIfTouched => (false, true),
OrderType::StopLimit | OrderType::LimitIfTouched => (true, true),
}
}
pub(crate) fn require_prices(
price_type: OrderType,
price: Option<f64>,
trigger_price: Option<f64>,
) -> Result<(), RithmicError> {
let (needs_price, needs_trigger) = price_requirements(price_type);
let order_type = price_type.as_str_name();
if needs_price && price.is_none() {
return Err(RithmicError::InvalidArgument(format!(
"price is required for a {order_type} order"
)));
}
if needs_trigger && trigger_price.is_none() {
return Err(RithmicError::InvalidArgument(format!(
"trigger_price is required for a {order_type} order"
)));
}
Ok(())
}