stock-trek 0.2.7

Stock Trek time-series analysis
Documentation
use crate::{
    data::trading_pair::TradingPair,
    errors::{StockTrekError, ValidationError},
};
use rust_decimal::Decimal;
use std::collections::HashSet;

pub fn validate_client_order_id(client_order_id: &str) -> Result<(), StockTrekError> {
    validate_string_is_not_empty("client_order_id", client_order_id)
}

pub fn validate_trading_pair(
    trading_pair: &TradingPair,
    currencies: &HashSet<String>,
) -> Result<(), StockTrekError> {
    validate_string_is_not_empty("base_currency", trading_pair.base_currency())?;
    validate_string_is_not_empty("quote_currency", trading_pair.quote_currency())?;
    validate_currency(trading_pair.base_currency(), currencies)?;
    validate_currency(trading_pair.quote_currency(), currencies)?;
    Ok(())
}

pub fn validate_price(price: Decimal, increment: Decimal) -> Result<(), StockTrekError> {
    let name = "price";
    validate_is_positive(name, price)?;
    validate_increment(name, price, increment)?;
    Ok(())
}

pub fn validate_quantity(quantity: Decimal, increment: Decimal) -> Result<(), StockTrekError> {
    let name = "quantity";
    validate_is_positive(name, quantity)?;
    validate_increment(name, quantity, increment)?;
    Ok(())
}

pub fn validate_remaining_quantity(remaining_quantity: Decimal) -> Result<(), StockTrekError> {
    validate_is_positive("remaining_quantity", remaining_quantity)
}

fn validate_currency(currency: &str, currencies: &HashSet<String>) -> Result<(), StockTrekError> {
    if !currencies.contains(currency) {
        return Err(StockTrekError::Validation(ValidationError::DoesNotExist {
            name: currency.into(),
            container: "currencies".into(),
        }));
    }
    Ok(())
}

fn validate_string_is_not_empty(name: &str, value: &str) -> Result<(), StockTrekError> {
    if value.is_empty() {
        return Err(StockTrekError::Validation(ValidationError::IsEmpty {
            name: name.to_string(),
        }));
    }
    Ok(())
}

fn validate_is_positive(name: &str, value: Decimal) -> Result<(), StockTrekError> {
    if value <= Decimal::ZERO {
        return Err(StockTrekError::Validation(ValidationError::IsNotPositive {
            name: name.to_string(),
            value,
        }));
    }
    Ok(())
}

fn validate_increment(
    name: &str,
    value: Decimal,
    increment: Decimal,
) -> Result<(), StockTrekError> {
    if value % increment != Decimal::ZERO {
        return Err(StockTrekError::Validation(
            ValidationError::InvalidIncrement {
                name: name.to_string(),
                value,
                increment,
            },
        ));
    }
    Ok(())
}