ek-data 0.2.5

Trading data contracts for the enkeep ek ecosystem: venue enums, zero-dep epoch-nanosecond time, decimal-exact price rounding, vt-symbol convention, bus event dictionary, tick/bar/order/trade/position/account/contract objects and request objects (Python enkeep_trade trader/object.py + constant.py, faithfully ported).
Documentation
//! 持仓对象(`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()
        )
    }
}