1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//! 持仓对象(`object.py:235-264`;含迅投 XtPosition 扩展字段)。
use crate::constant::{Direction, Exchange};
/// 逐向持仓数据。
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct PositionData {
/// 上游网关名
pub gateway_name: String,
/// 合约代码
pub symbol: String,
/// 交易所
pub exchange: Exchange,
/// 方向(Python 必填;Rust `Default` 为 [`Direction::NET`],见 constant.rs 说明)
pub direction: Direction,
/// 持仓量
pub volume: f64,
/// 冻结量
pub frozen: f64,
/// 持仓均价(网关侧口径)
pub price: f64,
/// 持仓盈亏
pub pnl: f64,
/// 隔夜仓量(Yesterday)
pub yd_volume: f64,
// —— 迅投 XtPosition 扩展(object.py:250-257)——
/// 证券名称
pub name: String,
/// 可用数量
pub can_use_volume: f64,
/// 市值
pub market_value: f64,
/// 在途股份
pub on_road_volume: f64,
/// 成本价
pub avg_price: f64,
/// 最新价
pub last_price: f64,
/// 盈亏比例
pub profit_rate: f64,
}
impl PositionData {
/// `en_symbol`(派生方法;分配一次)。
pub fn en_symbol(&self) -> String {
let mut buf = String::with_capacity(self.exchange.as_str().len() + 1 + self.symbol.len());
self.en_symbol_into(&mut buf);
buf
}
/// 零分配版本:追加到复用缓冲。
pub fn en_symbol_into(&self, buf: &mut String) {
crate::symbol::write_vt_symbol(buf, &self.symbol, self.exchange);
}
/// `en_positionid` =
/// `"{gateway_name}.{en_symbol}.{direction 线值}"`(`object.py:262-264`)。
///
/// 注意:Python 版第三段用中文线值(`"多"`),Rust 版依线值决定 3 用英文
/// (`"LONG"`/`"SHORT"`/`"NET"`;DESIGN.md 决定 3)。
pub fn en_positionid(&self) -> String {
format!(
"{}.{}.{}",
self.gateway_name,
self.en_symbol(),
self.direction.as_str()
)
}
}