use super::*;
use crate::{
symbology::{ExecutionVenue, MarketdataVenue},
AccountIdOrName, Dir,
};
use anyhow::{bail, Result};
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct QuoteOneSide;
impl Algo for QuoteOneSide {
const NAME: &'static str = "QUOTE_ONE_SIDE";
type Params = QuoteOneSideParams;
type Status = QuoteOneSideStatus;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub enum ImproveOrJoin {
Improve,
Join,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct QuoteOneSideParams {
pub symbol: String,
pub marketdata_venue: MarketdataVenue,
pub execution_venue: ExecutionVenue,
pub account: Option<AccountIdOrName>,
pub dir: Dir,
pub quantity: Decimal,
pub limit_price: Decimal,
pub max_ticks_outside: Option<Decimal>,
pub improve_or_join: ImproveOrJoin,
pub quantity_filled: Decimal,
}
impl DisplaySymbols for QuoteOneSideParams {
fn display_symbols(&self) -> Option<Vec<String>> {
Some(vec![self.symbol.clone()])
}
}
impl Validate for QuoteOneSideParams {
fn validate(&self) -> Result<()> {
if !self.quantity.is_sign_positive() {
bail!("quantity must be positive");
}
if let Some(max_ticks) = self.max_ticks_outside {
if !max_ticks.is_sign_positive() && max_ticks != Decimal::ZERO {
bail!("max_ticks_outside must be non-negative");
}
if !max_ticks.is_integer() {
bail!("max_ticks_outside must be an integer");
}
}
Ok(())
}
}
#[derive(Debug, Default, Clone, Serialize, Deserialize, JsonSchema)]
pub struct QuoteOneSideStatus {
pub realized_avg_price: Option<Decimal>,
pub quantity_filled: Decimal,
pub current_quote_price: Option<Decimal>,
pub front_of_queue: bool,
pub orders_sent: u32,
pub is_cancelling: bool,
}