stock-trek 0.2.2

Stock Trek time-series analysis
Documentation
use crate::{
    data::{
        flags::MarketSide,
        market::market::Market,
        order_request::{OrderKind, OrderRequest, OrderTrigger},
        trading_pair::TradingPair,
        validation::{
            validate_client_order_id, validate_price, validate_quantity, validate_trading_pair,
        },
    },
    errors::StockTrekError,
};
use rust_decimal::Decimal;
use std::collections::{HashMap, HashSet};

#[derive(Debug)]
pub struct Exchange {
    name: String,
    currencies: HashSet<String>,
    markets: HashMap<TradingPair, Market>,
}

impl Exchange {
    pub fn market(&self, trading_pair: &TradingPair) -> Result<&Market, StockTrekError> {
        self.markets.get(trading_pair).ok_or_else(|| {
            StockTrekError::Validation(crate::errors::ValidationError::DoesNotExist {
                name: trading_pair.to_string(),
                container: self.name.to_string(),
            })
        })
    }
    pub fn market_order(
        &self,
        client_order_id: &str,
        trading_pair: TradingPair,
        side: MarketSide,
        quantity: Decimal,
    ) -> Result<OrderRequest, StockTrekError> {
        let kind = OrderKind::Market;
        let trigger = OrderTrigger::None;
        self.validate_and_create_order(client_order_id, trading_pair, side, quantity, kind, trigger)
    }
    pub fn limit_order(
        &self,
        client_order_id: &str,
        trading_pair: TradingPair,
        side: MarketSide,
        quantity: Decimal,
        price: Decimal,
    ) -> Result<OrderRequest, StockTrekError> {
        let kind = OrderKind::Limit { price };
        let trigger = OrderTrigger::None;
        self.validate_and_create_order(client_order_id, trading_pair, side, quantity, kind, trigger)
    }
    pub fn stop_order(
        &self,
        client_order_id: &str,
        trading_pair: TradingPair,
        side: MarketSide,
        quantity: Decimal,
        stop_price: Decimal,
    ) -> Result<OrderRequest, StockTrekError> {
        let kind = OrderKind::Market;
        let trigger = OrderTrigger::Stop { stop_price };
        self.validate_and_create_order(client_order_id, trading_pair, side, quantity, kind, trigger)
    }
    pub fn stop_limit_order(
        &self,
        client_order_id: &str,
        trading_pair: TradingPair,
        side: MarketSide,
        quantity: Decimal,
        price: Decimal,
        stop_price: Decimal,
    ) -> Result<OrderRequest, StockTrekError> {
        let kind = OrderKind::Limit { price };
        let trigger = OrderTrigger::Stop { stop_price };
        self.validate_and_create_order(client_order_id, trading_pair, side, quantity, kind, trigger)
    }

    fn validate_and_create_order(
        &self,
        client_order_id: &str,
        trading_pair: TradingPair,
        side: MarketSide,
        quantity: Decimal,
        kind: OrderKind,
        trigger: OrderTrigger,
    ) -> Result<OrderRequest, StockTrekError> {
        validate_client_order_id(client_order_id)?;
        validate_trading_pair(&trading_pair, &self.currencies)?;
        let market = self.market(&trading_pair)?;
        let base_increment = market.base_increment();
        let quote_increment = market.quote_increment();
        validate_quantity(quantity, base_increment)?;
        match (&kind, &trigger) {
            (OrderKind::Market, OrderTrigger::None) => {}
            (OrderKind::Limit { price }, OrderTrigger::None) => {
                validate_price(*price, quote_increment)?;
            }
            (OrderKind::Market, OrderTrigger::Stop { stop_price }) => {
                validate_price(*stop_price, quote_increment)?;
            }
            (OrderKind::Limit { price }, OrderTrigger::Stop { stop_price }) => {
                validate_price(*price, quote_increment)?;
                validate_price(*stop_price, quote_increment)?;
            }
        }
        Ok(OrderRequest::new(
            client_order_id.into(),
            trading_pair,
            side,
            kind,
            trigger,
            quantity,
        ))
    }
}