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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! 下单请求(`object.py:521-588` + 方法四件套)。
use crate::constant::{Direction, Exchange, Offset, OrderType, Status};
use crate::order::OrderData;
/// 发往网关的开仓/平仓请求。
#[derive(Debug, Clone, PartialEq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct OrderRequest {
/// 合约代码
pub symbol: String,
/// 交易所
pub exchange: Exchange,
/// 方向(必填)
pub direction: Direction,
/// 委托类型(Python `type`;Rust 改名避关键字,serde 线上字段名还原为 `"type"`)
#[cfg_attr(feature = "serde", serde(rename = "type"))]
pub order_type: OrderType,
/// 委托量
pub volume: f64,
/// 委托价(市价单可 0)
pub price: f64,
/// 开平(缺省 NONE)
pub offset: Offset,
/// 策略/来源备注
pub reference: String,
/// 追单统计字段(原委托号)
pub old_order_id: String,
}
impl OrderRequest {
/// `en_symbol`(派生方法)。
pub fn en_symbol(&self) -> String {
crate::symbol::vt_symbol(&self.symbol, self.exchange)
}
/// 生成订单数据(`object.py:541`;补 id/gateway 两字段即成 OrderData;
/// reference 一并搬入,对齐原稿 554 行)。
pub fn create_order_data(&self, orderid: &str, gateway_name: &str) -> OrderData {
OrderData {
gateway_name: gateway_name.to_string(),
symbol: self.symbol.clone(),
exchange: self.exchange,
orderid: orderid.to_string(),
order_type: self.order_type,
direction: Some(self.direction),
offset: self.offset,
price: self.price,
volume: self.volume,
reference: self.reference.clone(),
// ── 其余字段显式给值,不靠 `..Default`(那会让新增字段静默变默认)──
// 这是**本地意向单**:刚生成、还没经柜台,所以是"已提交"而不是"未成交"。
// 柜台真回报到了会按 `onRtnOrder` 整条覆盖。
status: Status::SUBMITTING,
// 没成交当然是 0;成交价对委托单没有意义(价在 TradeData 里)。
traded: 0.0,
traded_price: 0.0,
// 本地生成时刻由调用方决定要不要填;此处不装钟。
datetime: None,
// 合约中文名要查合约表,`ek-data` 不持有合约表。
name: String::new(),
// 本地单还没有柜台反馈,没有废单原因。
status_msg: String::new(),
}
}
/// 最小交易量校验(`object.py:559`;volume >= min_volume)。
pub fn is_min_volume_ok(&self, min_volume: f64) -> bool {
self.volume >= min_volume
}
/// 最大交易量校验(`object.py:567`;volume <= max_volume)。
pub fn is_max_volume_ok(&self, max_volume: f64) -> bool {
self.volume <= max_volume
}
/// 区间校验(`object.py:575`;闭区间 [min_volume, max_volume])。
pub fn is_volume_range_ok(&self, min_volume: f64, max_volume: f64) -> bool {
self.volume >= min_volume && self.volume <= max_volume
}
/// 倍数校验(`object.py:582`;volume 是 sub_beishu 的整数倍;
/// Python 除零会抛 ZeroDivisionError,Rust 版约定返回 false)。
pub fn is_volume_beishu_ok(&self, sub_beishu: f64) -> bool {
if sub_beishu == 0.0 {
return false;
}
let r = self.volume - (self.volume / sub_beishu).trunc() * sub_beishu;
r == 0.0
}
}