#![allow(unsafe_code)]
use std::ops::Deref;
use nautilus_model::{
enums::{PositionSide, TimeInForce},
identifiers::{ClientId, InstrumentId, PositionId},
};
use ustr::Ustr;
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ClosePositionCommand {
pub position_id: PositionId,
pub client_id: Option<ClientId>,
pub tags: Option<Vec<Ustr>>,
pub time_in_force: Option<TimeInForce>,
pub reduce_only: Option<bool>,
pub quote_quantity: Option<bool>,
}
impl ClosePositionCommand {
#[must_use]
pub const fn new(
position_id: PositionId,
client_id: Option<ClientId>,
tags: Option<Vec<Ustr>>,
time_in_force: Option<TimeInForce>,
reduce_only: Option<bool>,
quote_quantity: Option<bool>,
) -> Self {
Self {
position_id,
client_id,
tags,
time_in_force,
reduce_only,
quote_quantity,
}
}
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct ClosePositionHandle(Box<ClosePositionCommand>);
impl ClosePositionHandle {
#[must_use]
pub fn new(command: ClosePositionCommand) -> Self {
Self(Box::new(command))
}
#[must_use]
pub fn command(&self) -> &ClosePositionCommand {
&self.0
}
#[must_use]
pub fn into_inner(self) -> ClosePositionCommand {
*self.0
}
}
impl Deref for ClosePositionHandle {
type Target = ClosePositionCommand;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CloseAllPositionsCommand {
pub instrument_id: InstrumentId,
pub position_side: Option<PositionSide>,
pub client_id: Option<ClientId>,
pub tags: Option<Vec<Ustr>>,
pub time_in_force: Option<TimeInForce>,
pub reduce_only: Option<bool>,
pub quote_quantity: Option<bool>,
}
impl CloseAllPositionsCommand {
#[allow(clippy::too_many_arguments)]
#[must_use]
pub const fn new(
instrument_id: InstrumentId,
position_side: Option<PositionSide>,
client_id: Option<ClientId>,
tags: Option<Vec<Ustr>>,
time_in_force: Option<TimeInForce>,
reduce_only: Option<bool>,
quote_quantity: Option<bool>,
) -> Self {
Self {
instrument_id,
position_side,
client_id,
tags,
time_in_force,
reduce_only,
quote_quantity,
}
}
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct CloseAllPositionsHandle(Box<CloseAllPositionsCommand>);
impl CloseAllPositionsHandle {
#[must_use]
pub fn new(command: CloseAllPositionsCommand) -> Self {
Self(Box::new(command))
}
#[must_use]
pub fn command(&self) -> &CloseAllPositionsCommand {
&self.0
}
#[must_use]
pub fn into_inner(self) -> CloseAllPositionsCommand {
*self.0
}
}
impl Deref for CloseAllPositionsHandle {
type Target = CloseAllPositionsCommand;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
#[rstest]
fn close_position_handle_round_trips_command() {
let cmd = ClosePositionCommand::new(
PositionId::from("P-001"),
None,
Some(vec![Ustr::from("exit")]),
Some(TimeInForce::Ioc),
None,
None,
);
let handle = ClosePositionHandle::new(cmd.clone());
assert_eq!(handle.command(), &cmd);
assert_eq!(&*handle, &cmd);
assert_eq!(handle.into_inner(), cmd);
}
#[rstest]
fn close_all_positions_handle_round_trips_command() {
let cmd = CloseAllPositionsCommand::new(
InstrumentId::from("ETH-USDT.BINANCE"),
Some(PositionSide::Long),
None,
None,
None,
None,
None,
);
let handle = CloseAllPositionsHandle::new(cmd.clone());
assert_eq!(handle.command(), &cmd);
assert_eq!(&*handle, &cmd);
assert_eq!(handle.into_inner(), cmd);
}
}