pragma_common/entries/
position.rs1use super::trade::TradeSide;
2use crate::{instrument_type::InstrumentType, pair::Pair};
3#[cfg(feature = "proto")]
4use crate::{ProtoDeserialize, ProtoSerialize};
5#[cfg(feature = "proto")]
6use prost::Message;
7#[derive(Debug, Clone, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9#[cfg_attr(
10 feature = "borsh",
11 derive(borsh::BorshSerialize, borsh::BorshDeserialize)
12)]
13#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
14pub struct PositionEntry {
15 pub source: String,
16 pub instrument_type: InstrumentType,
17 pub pair: Pair,
18 pub timestamp_ms: i64,
19 pub received_timestamp_ms: i64,
20 pub side: TradeSide,
21 pub notional_in_usd: f64,
22 pub size: f64,
23}
24#[cfg(feature = "proto")]
25impl PositionEntry {
26 fn to_proto(&self) -> crate::schema::PositionEntry {
27 crate::schema::PositionEntry {
28 source: self.source.clone(),
29 instrument_type: match self.instrument_type {
30 InstrumentType::Spot => crate::schema::InstrumentType::Spot as i32,
31 InstrumentType::Perp => crate::schema::InstrumentType::Perp as i32,
32 },
33 pair: Some(crate::schema::Pair {
34 base: self.pair.base.clone(),
35 quote: self.pair.quote.clone(),
36 }),
37 timestamp_ms: self.timestamp_ms,
38 received_timestamp_ms: self.received_timestamp_ms,
39 side: match self.side {
40 TradeSide::Buy => crate::schema::TradeSide::Buy as i32,
41 TradeSide::Sell => crate::schema::TradeSide::Sell as i32,
42 },
43 notional_in_usd: self.notional_in_usd,
44 size: self.size,
45 }
46 }
47 fn from_proto(proto: crate::schema::PositionEntry) -> Result<Self, prost::DecodeError> {
48 let pair = proto
49 .pair
50 .ok_or_else(|| prost::DecodeError::new("Missing pair field in PositionEntry"))?;
51
52 let instrument_type = match proto.instrument_type {
53 x if x == crate::schema::InstrumentType::Spot as i32 => InstrumentType::Spot,
54 x if x == crate::schema::InstrumentType::Perp as i32 => InstrumentType::Perp,
55 _ => {
56 return Err(prost::DecodeError::new(format!(
57 "Invalid instrument_type value: {}",
58 proto.instrument_type,
59 )))
60 }
61 };
62
63 let side = match proto.side {
64 x if x == crate::schema::TradeSide::Buy as i32 => TradeSide::Buy,
65 x if x == crate::schema::TradeSide::Sell as i32 => TradeSide::Sell,
66 _ => {
67 return Err(prost::DecodeError::new(format!(
68 "Invalid side value: {}",
69 proto.side,
70 )))
71 }
72 };
73
74 Ok(PositionEntry {
75 source: proto.source,
76 instrument_type,
77 pair: Pair {
78 base: pair.base,
79 quote: pair.quote,
80 },
81 timestamp_ms: proto.timestamp_ms,
82 received_timestamp_ms: proto.received_timestamp_ms,
83 side,
84 notional_in_usd: proto.notional_in_usd,
85 size: proto.size,
86 })
87 }
88}
89#[cfg(feature = "proto")]
90impl ProtoSerialize for PositionEntry {
91 fn to_proto_bytes(&self) -> Vec<u8> {
92 let proto = self.to_proto();
93 let mut buf = Vec::new();
94 proto
95 .encode(&mut buf)
96 .expect("Failed to encode PositionEntry to protobuf");
97 buf
98 }
99}
100#[cfg(feature = "proto")]
101impl ProtoDeserialize for PositionEntry {
102 fn from_proto_bytes(bytes: &[u8]) -> Result<Self, prost::DecodeError> {
103 let proto = crate::schema::PositionEntry::decode(bytes)?;
104 Self::from_proto(proto)
105 }
106}