Add position runtime aliases

This commit is contained in:
boris
2026-04-23 20:21:04 -07:00
parent c843de078f
commit 8bbca8c3a0
3 changed files with 37 additions and 16 deletions

View File

@@ -377,11 +377,16 @@ struct StockExpressionState {
#[derive(Debug, Clone)]
struct PositionExpressionState {
order_book_id: String,
avg_cost: f64,
avg_price: f64,
current_price: f64,
prev_close: f64,
holding_return: f64,
quantity: i64,
sellable_qty: i64,
sellable: i64,
closable: i64,
old_quantity: i64,
bought_quantity: i64,
sold_quantity: i64,
@@ -391,6 +396,7 @@ struct PositionExpressionState {
sold_value: f64,
transaction_cost: f64,
market_value: f64,
equity: f64,
value_percent: f64,
unrealized_pnl: f64,
realized_pnl: f64,
@@ -584,11 +590,17 @@ impl PlatformExprStrategy {
"ma20",
"ma30",
"factors",
"order_book_id",
"avg_cost",
"avg_price",
"current_price",
"position_prev_close",
"prev_position_close",
"holding_return",
"quantity",
"sellable_qty",
"sellable",
"closable",
"old_quantity",
"buy_quantity",
"sell_quantity",
@@ -600,6 +612,7 @@ impl PlatformExprStrategy {
"sold_value",
"transaction_cost",
"position_market_value",
"equity",
"value_percent",
"unrealized_pnl",
"realized_pnl",
@@ -1795,11 +1808,17 @@ impl PlatformExprStrategy {
}
}
if let Some(position) = position {
scope.push("order_book_id", position.order_book_id.clone());
scope.push("avg_cost", position.avg_cost);
scope.push("avg_price", position.avg_price);
scope.push("current_price", position.current_price);
scope.push("position_prev_close", position.prev_close);
scope.push("prev_position_close", position.prev_close);
scope.push("holding_return", position.holding_return);
scope.push("quantity", position.quantity);
scope.push("sellable_qty", position.sellable_qty);
scope.push("sellable", position.sellable);
scope.push("closable", position.closable);
scope.push("old_quantity", position.old_quantity);
scope.push("buy_quantity", position.bought_quantity);
scope.push("sell_quantity", position.sold_quantity);
@@ -1811,6 +1830,7 @@ impl PlatformExprStrategy {
scope.push("sold_value", position.sold_value);
scope.push("transaction_cost", position.transaction_cost);
scope.push("position_market_value", position.market_value);
scope.push("equity", position.equity);
scope.push("value_percent", position.value_percent);
scope.push("unrealized_pnl", position.unrealized_pnl);
scope.push("realized_pnl", position.realized_pnl);
@@ -3506,11 +3526,16 @@ impl PlatformExprStrategy {
0.0
};
let position_state = PositionExpressionState {
order_book_id: position.symbol.clone(),
avg_cost: position.average_cost,
avg_price: position.average_cost,
current_price,
prev_close: stock.prev_close,
holding_return,
quantity: position.quantity as i64,
sellable_qty: position.sellable_qty(date) as i64,
sellable: position.sellable_qty(date) as i64,
closable: position.sellable_qty(date) as i64,
old_quantity: position.day_start_quantity() as i64,
bought_quantity: position.bought_quantity() as i64,
sold_quantity: position.sold_quantity() as i64,
@@ -3520,6 +3545,7 @@ impl PlatformExprStrategy {
sold_value: position.sold_value(),
transaction_cost: position.transaction_cost(),
market_value,
equity: market_value,
value_percent,
unrealized_pnl: position.unrealized_pnl(),
realized_pnl: position.realized_pnl,
@@ -5419,20 +5445,13 @@ mod tests {
cfg.benchmark_short_ma_days = 1;
cfg.benchmark_long_ma_days = 1;
cfg.stop_loss_expr = concat!(
"old_quantity == 100 && buy_quantity == 100 && sell_quantity == 50",
" && bought_quantity == 100 && sold_quantity == 50",
" && buy_avg_price == 9.0 && sell_avg_price == 10.0",
" && bought_value == 900.0 && sold_value == 500.0",
" && transaction_cost == 2.0 && position_market_value > 0.0",
" && value_percent > 0.0 && unrealized_pnl > 0.0",
" && realized_pnl > 0.0 && pnl > 0.0",
" && day_trade_quantity_delta == 50 && trading_pnl > 90.0",
" && available_cash == cash && frozen_cash == 0.0",
" && total_value == total_equity && portfolio_value == total_equity",
" && starting_cash == 1000000.0 && unit_net_value > 1.0",
" && static_unit_net_value > 1.0 && daily_pnl > 290.0",
" && daily_returns > 0.0 && total_returns > 0.0",
" && cash_liabilities == 0.0"
"order_book_id == \"000001.SZ\" && avg_price == avg_cost",
" && sellable == sellable_qty && closable == sellable_qty",
" && equity == position_market_value",
" && position_prev_close == prev_position_close",
" && old_quantity == 100 && buy_quantity == 100",
" && sell_quantity == 50 && trading_pnl > 90.0",
" && daily_pnl > 290.0 && total_returns > 0.0"
)
.to_string();
let mut strategy = PlatformExprStrategy::new(cfg);

View File

@@ -185,10 +185,10 @@ pub fn built_in_strategy_manual() -> StrategyAiManual {
ManualField { name: "current_price".to_string(), field_type: "float".to_string(), detail: "当前盘中价格。".to_string() },
ManualField { name: "holding_return".to_string(), field_type: "float".to_string(), detail: "持仓收益率,小数。".to_string() },
ManualField { name: "profit_pct".to_string(), field_type: "float".to_string(), detail: "持仓收益率,百分比。".to_string() },
ManualField { name: "quantity/sellable_qty".to_string(), field_type: "int".to_string(), detail: "持仓数量与可卖数量。".to_string() },
ManualField { name: "order_book_id/quantity/sellable_qty/sellable/closable".to_string(), field_type: "string/int".to_string(), detail: "持仓代码、持仓数量与可卖数量sellable/closable 是 RQAlpha StockPosition 常用别名".to_string() },
ManualField { name: "old_quantity/buy_quantity/sell_quantity".to_string(), field_type: "int".to_string(), detail: "交易日开始时老仓数量、当日买入数量、当日卖出数量。buy_quantity/sell_quantity 也可写成 bought_quantity/sold_quantity。".to_string() },
ManualField { name: "buy_avg_price/sell_avg_price/bought_value/sold_value".to_string(), field_type: "float".to_string(), detail: "当日买入均价、卖出均价、买入成交额、卖出成交额。".to_string() },
ManualField { name: "position_market_value/value_percent".to_string(), field_type: "float".to_string(), detail: "当前持仓市值,以及该持仓市值占账户总权益比例".to_string() },
ManualField { name: "avg_price/position_prev_close/position_market_value/equity/value_percent".to_string(), field_type: "float".to_string(), detail: "平均开仓价、持仓昨收、市值/权益以及该持仓市值占账户总权益比例avg_price/equity 对齐 RQAlpha 持仓对象别名".to_string() },
ManualField { name: "unrealized_pnl/realized_pnl/pnl/transaction_cost".to_string(), field_type: "float".to_string(), detail: "未实现盈亏、累计已实现盈亏、总持仓盈亏和当日交易成本。".to_string() },
ManualField { name: "trading_pnl/position_pnl".to_string(), field_type: "float".to_string(), detail: "当日交易收益和昨仓持有收益,口径更接近 rqalpha StockPosition。".to_string() },
ManualField { name: "dividend_receivable".to_string(), field_type: "float".to_string(), detail: "当前 symbol 尚未到账的应收分红。".to_string() },

View File

@@ -45,6 +45,8 @@ current alignment pass.
- [x] `position_pnl`
- [x] `dividend_receivable`
- [x] richer position lifecycle fields exposed to strategy runtime
- [x] RQAlpha-style stock position aliases (`order_book_id`, `avg_price`,
`sellable`, `closable`, `equity`, `position_prev_close`)
### Phase 6: Strategy data API parity