use log::error;
use crate::client::transport::GlobalResponseIterator;
use crate::contracts::Contract;
use crate::messages::IncomingMessages;
use crate::{server_versions, Client, Error};
mod decoders;
mod encoders;
#[derive(Debug, Default)]
pub struct Position {
pub account: String,
pub contract: Contract,
pub position: f64,
pub average_cost: f64,
}
pub(crate) fn positions(client: &Client) -> Result<impl Iterator<Item = Position> + '_, Error> {
client.check_server_version(server_versions::ACCOUNT_SUMMARY, "It does not support position requests.")?;
let message = encoders::request_positions()?;
let messages = client.request_positions(message)?;
Ok(PositionIterator { client, messages })
}
pub(crate) fn cancel_positions(client: &Client) -> Result<(), Error> {
client.check_server_version(server_versions::ACCOUNT_SUMMARY, "It does not support position cancellation.")?;
let message = encoders::cancel_positions()?;
client.request_positions(message)?;
Ok(())
}
pub(crate) struct PositionIterator<'a> {
client: &'a Client,
messages: GlobalResponseIterator,
}
impl<'a> Iterator for PositionIterator<'a> {
type Item = Position;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(mut message) = self.messages.next() {
match message.message_type() {
IncomingMessages::Position => match decoders::position(&mut message) {
Ok(val) => return Some(val),
Err(err) => {
error!("error decoding execution data: {err}");
}
},
IncomingMessages::PositionEnd => {
if let Err(e) = cancel_positions(self.client) {
error!("error cancelling positions: {e}")
}
return None;
}
message => {
error!("order data iterator unexpected message: {message:?}");
}
}
} else {
return None;
}
}
}
}