ek-data 0.2.8

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
//! parity:ID/线值字符串与 Python 版逐字节对照。

use ek_data::constant::{Direction, Exchange, Offset, Status};
use ek_data::{AccountData, OrderData, OrderRequest, PositionData, TradeData};

/// Python `f"{exchange.value}.{symbol}"` —— en_symbol 四对象共用;
/// 注意网络值决定 3:exchange 线值即 Python `.value`(CBOT→"CBT" 等)。
#[test]
fn en_symbol_matches_python_value() {
    let tick = ek_data::TickData {
        symbol: "IF2506".to_string(),
        exchange: Exchange::CFFEX,
        ..ek_data::TickData::default()
    };
    assert_eq!(tick.en_symbol(), "CFFEX.IF2506");

    let bar = ek_data::BarData {
        symbol: "600519".to_string(),
        exchange: Exchange::SSE,
        ..ek_data::BarData::default()
    };
    assert_eq!(bar.en_symbol(), "SSE.600519");

    let contract = ek_data::ContractData {
        symbol: "IF2506".to_string(),
        exchange: Exchange::CFFEX,
        ..ek_data::ContractData::default()
    };
    assert_eq!(contract.en_symbol(), "CFFEX.IF2506");

    // 交易所线值特例:CBOT→CBT, EUREX→EUX, ETF_INDEX→ETF_index
    let mut c = ek_data::ContractData {
        symbol: "US".to_string(),
        ..ek_data::ContractData::default()
    };
    c.exchange = Exchange::CBOT;
    assert_eq!(c.en_symbol(), "CBT.US");
    c.exchange = Exchange::EUREX;
    assert_eq!(c.en_symbol(), "EUX.US");
    c.exchange = Exchange::ETF_INDEX;
    assert_eq!(c.en_symbol(), "ETF_index.US");
}

/// Python `f"{gateway_name}.{orderid}"` (`object.py:180`)。
#[test]
fn en_orderid_matches_python() {
    let o = OrderData {
        gateway_name: "xt".into(),
        orderid: "101".into(),
        ..OrderData::default()
    };
    assert_eq!(o.en_orderid(), "xt.101");

    let t = TradeData {
        gateway_name: "xt".into(),
        tradeid: "9001".into(),
        ..TradeData::default()
    };
    assert_eq!(t.en_tradeid(), "xt.9001");
}

/// Python `f"{gateway_name}.{en_symbol}.{direction.value}"`(object.py:262-264)。
/// 线值决定 3:第三段为英文令牌。
#[test]
fn en_positionid_matches_python_shape() {
    let p = PositionData {
        gateway_name: "xt".into(),
        symbol: "IF2506".into(),
        exchange: Exchange::CFFEX,
        direction: Direction::LONG,
        ..PositionData::default()
    };
    assert_eq!(p.en_positionid(), "xt.CFFEX.IF2506.LONG");
    let p_short = PositionData {
        direction: Direction::SHORT,
        ..p.clone()
    };
    assert_eq!(p_short.en_positionid(), "xt.CFFEX.IF2506.SHORT");
    let p_net = PositionData {
        direction: Direction::NET,
        ..p
    };
    assert_eq!(p_net.en_positionid(), "xt.CFFEX.IF2506.NET");
}

/// Python `f"{gateway_name}.{accountid}"` (`object.py:282`)。
#[test]
fn en_accountid_matches_python() {
    let a = AccountData {
        gateway_name: "xt".into(),
        accountid: "88888".into(),
        ..AccountData::default()
    };
    assert_eq!(a.en_accountid(), "xt.88888");
}

/// create_order_data 字段移植面(`object.py:541-557`:req 的字段全量搬入 OrderData)。
#[test]
fn create_order_data_matches_python() {
    let req = OrderRequest {
        symbol: "IF2506".into(),
        exchange: Exchange::CFFEX,
        direction: Direction::LONG,
        order_type: ek_data::OrderType::LIMIT,
        volume: 2.0,
        price: 3500.0,
        offset: Offset::OPEN,
        reference: "demo".into(),
        old_order_id: "xt.99".into(),
    };
    let order = req.create_order_data("A1", "xt");
    assert_eq!(order.gateway_name, "xt");
    assert_eq!(order.symbol, "IF2506");
    assert_eq!(order.exchange, Exchange::CFFEX);
    assert_eq!(order.orderid, "A1");
    assert_eq!(order.order_type, ek_data::OrderType::LIMIT);
    assert_eq!(order.direction, Some(Direction::LONG));
    assert_eq!(order.offset, Offset::OPEN);
    assert_eq!(order.price, 3500.0);
    assert_eq!(order.volume, 2.0);
    assert_eq!(order.traded, 0.0);
    assert_eq!(order.status, Status::SUBMITTING);
    assert_eq!(order.en_symbol(), "CFFEX.IF2506");
    // object.py:554:reference 一并搬入(第二轮审计补上的断言)
    assert_eq!(order.reference, "demo");
}