stock-trek 0.6.0

Stock Trek time-series analysis
Documentation
use crate::{
    asset_id::AssetId,
    error::result::StockTrekResult,
    execute::{
        capability::{Capability, HasRequiredCapabilities},
        increment_sizes::IncrementSizes,
    },
    order::{
        orders::{
            one_cancels_other::OneCancelsOtherOrderGeneric,
            one_triggers_oco::OneTriggersOcoOrderGeneric,
            one_triggers_other::OneTriggersOtherOrderGeneric, single::SingleOrderGeneric,
        },
        trading_pair::TradingPair,
    },
    resolved_context::ResolvedContext,
    resolvers::resolveable::Resolvable,
    values::value::{AssetIdValue, NumberValue},
};
use rust_decimal::{Decimal, RoundingStrategy};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, hash::Hash};
use strum::Display;

#[derive(Debug, Display, Clone, Hash, Serialize, Deserialize)]
pub enum OrderRequest<A, N> {
    Single(SingleOrderGeneric<A, N>),
    OneCancelsOther(OneCancelsOtherOrderGeneric<A, N>),
    OneTriggersOther(OneTriggersOtherOrderGeneric<A, N>),
    OneTriggersOco(OneTriggersOcoOrderGeneric<A, N>),
}

impl Resolvable<OrderRequest<AssetId, f64>> for OrderRequest<AssetIdValue, NumberValue> {
    fn try_resolve(
        &self,
        context: &ResolvedContext,
    ) -> StockTrekResult<OrderRequest<AssetId, f64>> {
        match self {
            Self::Single(order) => Ok(OrderRequest::Single(order.try_resolve(context)?)),
            Self::OneCancelsOther(order) => {
                Ok(OrderRequest::OneCancelsOther(order.try_resolve(context)?))
            }
            Self::OneTriggersOther(order) => {
                Ok(OrderRequest::OneTriggersOther(order.try_resolve(context)?))
            }
            Self::OneTriggersOco(order) => {
                Ok(OrderRequest::OneTriggersOco(order.try_resolve(context)?))
            }
        }
    }
}

impl<A, N> HasRequiredCapabilities for OrderRequest<A, N> {
    fn required_capabilities(&self) -> Vec<Capability> {
        match self {
            Self::Single(order) => order.required_capabilities(),
            Self::OneCancelsOther(order) => order.required_capabilities(),
            Self::OneTriggersOther(order) => order.required_capabilities(),
            Self::OneTriggersOco(order) => order.required_capabilities(),
        }
    }
}

impl OrderRequest<AssetId, f64> {
    pub fn into_precise(
        self,
        increments: &HashMap<TradingPair, IncrementSizes>,
        price_rounding: RoundingStrategy,
        quantity_rounding: RoundingStrategy,
        rate_rounding: RoundingStrategy,
    ) -> StockTrekResult<OrderRequest<AssetId, Decimal>> {
        match self {
            OrderRequest::OneCancelsOther(oco) => {
                let primary = oco.primary.into_precise(
                    increments,
                    price_rounding,
                    quantity_rounding,
                    rate_rounding,
                )?;
                let secondary = oco.secondary.into_precise(
                    increments,
                    price_rounding,
                    quantity_rounding,
                    rate_rounding,
                )?;
                let precise = OneCancelsOtherOrderGeneric { primary, secondary };
                Ok(OrderRequest::OneCancelsOther(precise))
            }
            OrderRequest::OneTriggersOther(oco) => {
                let primary = oco.primary.into_precise(
                    increments,
                    price_rounding,
                    quantity_rounding,
                    rate_rounding,
                )?;
                let secondary = oco.secondary.into_precise(
                    increments,
                    price_rounding,
                    quantity_rounding,
                    rate_rounding,
                )?;
                let precise = OneTriggersOtherOrderGeneric { primary, secondary };
                Ok(OrderRequest::OneTriggersOther(precise))
            }
            OrderRequest::OneTriggersOco(oco) => {
                let primary = oco.primary.into_precise(
                    increments,
                    price_rounding,
                    quantity_rounding,
                    rate_rounding,
                )?;
                let oco_primary = oco.oco_order.primary.into_precise(
                    increments,
                    price_rounding,
                    quantity_rounding,
                    rate_rounding,
                )?;
                let oco_secondary = oco.oco_order.secondary.into_precise(
                    increments,
                    price_rounding,
                    quantity_rounding,
                    rate_rounding,
                )?;
                let oco_order = OneCancelsOtherOrderGeneric {
                    primary: oco_primary,
                    secondary: oco_secondary,
                };
                let precise = OneTriggersOcoOrderGeneric { primary, oco_order };
                Ok(OrderRequest::OneTriggersOco(precise))
            }
            OrderRequest::Single(single) => {
                let precise = single.into_precise(
                    increments,
                    price_rounding,
                    quantity_rounding,
                    rate_rounding,
                )?;
                Ok(OrderRequest::Single(precise))
            }
        }
    }
}