brokapi_alor/map/
execution.rs1use std::time::Instant;
4
5use brokapi_alor_protocol::http::models::TradeRecord;
6use brokapi_core::{BrokerOrderId, ClientOrderId, Execution, Money, Price, Qty};
7
8use super::market::side_of;
9use super::{parse_time, timestamps};
10use crate::util::instrument_id;
11
12pub fn execution(r: &TradeRecord, cid: Option<ClientOrderId>, now: Instant) -> Option<Execution> {
15 let qty = Qty::new(r.qty_units?);
16 Some(Execution {
17 cid,
18 broker_order_id: BrokerOrderId::new(r.orderno.clone().unwrap_or_default()),
19 instrument: instrument_id(&r.symbol, r.board.as_deref().unwrap_or_default()),
20 side: side_of(r.side.as_deref())?,
21 price: Price::new(r.price),
22 qty,
23 commission: Money::new(r.commission.unwrap_or_default()),
24 trade_id: r.id.clone(),
25 ts: timestamps(now, parse_time(r.date.as_deref())),
26 })
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 #[test]
34 fn a_trade_becomes_an_execution_in_pieces() {
35 let r: TradeRecord = serde_json::from_str(
36 r#"{"id":"T1","orderno":"77","symbol":"SBER","board":"TQBR","qtyUnits":20,"qty":2,"price":100.50,"side":"buy","commission":0.05,"date":"2026-10-22T10:00:00Z"}"#,
37 )
38 .unwrap();
39 let e = execution(&r, None, Instant::now()).unwrap();
40 assert_eq!(e.qty, Qty::from(20));
41 assert_eq!(e.price.to_string(), "100.50");
42 assert_eq!(e.trade_id, "T1");
43 assert_eq!(e.broker_order_id.as_str(), "77");
44 assert_eq!(e.commission.to_string(), "0.05");
45 }
46}