Revert "perf: build expression scope values lazily"
This reverts commit 1b449287fd.
This commit is contained in:
@@ -917,17 +917,6 @@ impl<'a> SelectiveExpressionScope<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
fn push_lazy<T, F>(&mut self, name: &str, build: F) -> &mut Self
|
||||
where
|
||||
T: Into<Dynamic>,
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
if self.requires(name) {
|
||||
self.inner.push_dynamic(name.to_string(), build().into());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn push_required<T: Into<Dynamic>>(&mut self, name: &str, value: T) -> &mut Self {
|
||||
self.inner.push_dynamic(name.to_string(), value.into());
|
||||
self
|
||||
@@ -4459,15 +4448,14 @@ impl PlatformExprStrategy {
|
||||
include_process_event_counts: bool,
|
||||
) -> Scope<'static> {
|
||||
let mut scope = SelectiveExpressionScope::new(scope_identifiers);
|
||||
scope.push_lazy("trade_date", || day.date.format("%Y-%m-%d").to_string());
|
||||
scope.push_lazy("current_date", || day.date.format("%Y-%m-%d").to_string());
|
||||
scope.push_lazy("date", || day.date.format("%Y-%m-%d").to_string());
|
||||
scope.push_lazy("decision_date", || {
|
||||
ctx.decision_date.format("%Y-%m-%d").to_string()
|
||||
});
|
||||
scope.push_lazy("execution_date", || {
|
||||
ctx.execution_date.format("%Y-%m-%d").to_string()
|
||||
});
|
||||
let trade_date = day.date.format("%Y-%m-%d").to_string();
|
||||
let decision_date = ctx.decision_date.format("%Y-%m-%d").to_string();
|
||||
let execution_date = ctx.execution_date.format("%Y-%m-%d").to_string();
|
||||
scope.push("trade_date", trade_date.clone());
|
||||
scope.push("current_date", trade_date.clone());
|
||||
scope.push("date", trade_date);
|
||||
scope.push("decision_date", decision_date);
|
||||
scope.push("execution_date", execution_date);
|
||||
scope.push("signal_open", day.signal_open);
|
||||
scope.push("signal_close", day.signal_close);
|
||||
scope.push("benchmark_open", day.benchmark_open);
|
||||
@@ -4554,63 +4542,74 @@ impl PlatformExprStrategy {
|
||||
scope.push("is_month_start", day.is_month_start);
|
||||
scope.push("is_month_end", day.is_month_end);
|
||||
scope.push("signal_ma30", day.signal_ma30);
|
||||
scope.push_lazy("has_open_orders", || ctx.has_open_orders());
|
||||
scope.push_lazy("open_order_count", || ctx.open_order_count() as i64);
|
||||
scope.push_lazy("open_buy_order_count", || ctx.open_buy_order_count() as i64);
|
||||
scope.push_lazy("open_sell_order_count", || {
|
||||
ctx.open_sell_order_count() as i64
|
||||
});
|
||||
scope.push_lazy("open_buy_qty", || ctx.open_buy_quantity() as i64);
|
||||
scope.push_lazy("open_sell_qty", || ctx.open_sell_quantity() as i64);
|
||||
scope.push_lazy("latest_open_order_id", || ctx.latest_open_order_id() as i64);
|
||||
scope.push_lazy("latest_open_order_status", || {
|
||||
ctx.latest_open_order_status().to_string()
|
||||
});
|
||||
scope.push_lazy("latest_open_order_unfilled_qty", || {
|
||||
ctx.latest_open_order_unfilled_quantity() as i64
|
||||
});
|
||||
scope.push_lazy("has_dynamic_universe", || ctx.has_dynamic_universe());
|
||||
scope.push_lazy("dynamic_universe_count", || {
|
||||
ctx.dynamic_universe_count() as i64
|
||||
});
|
||||
scope.push_lazy("has_subscriptions", || ctx.has_subscriptions());
|
||||
scope.push_lazy("subscription_count", || ctx.subscription_count() as i64);
|
||||
scope.push("has_open_orders", ctx.has_open_orders());
|
||||
scope.push("open_order_count", ctx.open_order_count() as i64);
|
||||
scope.push("open_buy_order_count", ctx.open_buy_order_count() as i64);
|
||||
scope.push("open_sell_order_count", ctx.open_sell_order_count() as i64);
|
||||
scope.push("open_buy_qty", ctx.open_buy_quantity() as i64);
|
||||
scope.push("open_sell_qty", ctx.open_sell_quantity() as i64);
|
||||
scope.push("latest_open_order_id", ctx.latest_open_order_id() as i64);
|
||||
scope.push(
|
||||
"latest_open_order_status",
|
||||
ctx.latest_open_order_status().to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"latest_open_order_unfilled_qty",
|
||||
ctx.latest_open_order_unfilled_quantity() as i64,
|
||||
);
|
||||
scope.push("has_dynamic_universe", ctx.has_dynamic_universe());
|
||||
scope.push(
|
||||
"dynamic_universe_count",
|
||||
ctx.dynamic_universe_count() as i64,
|
||||
);
|
||||
scope.push("has_subscriptions", ctx.has_subscriptions());
|
||||
scope.push("subscription_count", ctx.subscription_count() as i64);
|
||||
scope.push(
|
||||
"subscription_guard_required",
|
||||
self.config.subscription_guard_required,
|
||||
);
|
||||
scope.push_lazy("has_process_events", || ctx.has_process_events());
|
||||
scope.push_lazy("process_event_count", || ctx.process_event_count() as i64);
|
||||
scope.push_lazy("current_process_kind", || {
|
||||
ctx.current_process_event_kind().to_string()
|
||||
});
|
||||
scope.push_lazy("current_process_order_id", || {
|
||||
ctx.current_process_event_order_id() as i64
|
||||
});
|
||||
scope.push_lazy("current_process_symbol", || {
|
||||
ctx.current_process_event_symbol().to_string()
|
||||
});
|
||||
scope.push_lazy("current_process_side", || {
|
||||
ctx.current_process_event_side().to_string()
|
||||
});
|
||||
scope.push_lazy("current_process_detail", || {
|
||||
ctx.current_process_event_detail().to_string()
|
||||
});
|
||||
scope.push_lazy("latest_process_kind", || {
|
||||
ctx.latest_process_event_kind().to_string()
|
||||
});
|
||||
scope.push_lazy("latest_process_order_id", || {
|
||||
ctx.latest_process_event_order_id() as i64
|
||||
});
|
||||
scope.push_lazy("latest_process_symbol", || {
|
||||
ctx.latest_process_event_symbol().to_string()
|
||||
});
|
||||
scope.push_lazy("latest_process_side", || {
|
||||
ctx.latest_process_event_side().to_string()
|
||||
});
|
||||
scope.push_lazy("latest_process_detail", || {
|
||||
ctx.latest_process_event_detail().to_string()
|
||||
});
|
||||
scope.push("has_process_events", ctx.has_process_events());
|
||||
scope.push("process_event_count", ctx.process_event_count() as i64);
|
||||
scope.push(
|
||||
"current_process_kind",
|
||||
ctx.current_process_event_kind().to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"current_process_order_id",
|
||||
ctx.current_process_event_order_id() as i64,
|
||||
);
|
||||
scope.push(
|
||||
"current_process_symbol",
|
||||
ctx.current_process_event_symbol().to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"current_process_side",
|
||||
ctx.current_process_event_side().to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"current_process_detail",
|
||||
ctx.current_process_event_detail().to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"latest_process_kind",
|
||||
ctx.latest_process_event_kind().to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"latest_process_order_id",
|
||||
ctx.latest_process_event_order_id() as i64,
|
||||
);
|
||||
scope.push(
|
||||
"latest_process_symbol",
|
||||
ctx.latest_process_event_symbol().to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"latest_process_side",
|
||||
ctx.latest_process_event_side().to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"latest_process_detail",
|
||||
ctx.latest_process_event_detail().to_string(),
|
||||
);
|
||||
let process_event_counts = if include_day_factors || include_process_event_counts {
|
||||
let mut counts = Map::new();
|
||||
for (key, value) in ctx.process_event_counts() {
|
||||
@@ -4821,7 +4820,7 @@ impl PlatformExprStrategy {
|
||||
stock.lower_limit,
|
||||
stock.price_tick,
|
||||
);
|
||||
scope.push_lazy("symbol", || stock.symbol.to_string());
|
||||
scope.push("symbol", stock.symbol.to_string());
|
||||
scope.push("market_cap", stock.market_cap);
|
||||
scope.push("market_cap_bn", stock.market_cap_bn);
|
||||
scope.push("free_float_cap", stock.free_float_cap);
|
||||
@@ -4867,29 +4866,36 @@ impl PlatformExprStrategy {
|
||||
scope.push("listed_days", stock.listed_days);
|
||||
scope.push("at_upper_limit", at_upper_limit);
|
||||
scope.push("at_lower_limit", at_lower_limit);
|
||||
scope.push_lazy("symbol_open_order_count", || {
|
||||
ctx.symbol_open_order_count(&stock.symbol) as i64
|
||||
});
|
||||
scope.push_lazy("symbol_open_buy_qty", || {
|
||||
ctx.symbol_open_buy_quantity(&stock.symbol) as i64
|
||||
});
|
||||
scope.push_lazy("symbol_open_sell_qty", || {
|
||||
ctx.symbol_open_sell_quantity(&stock.symbol) as i64
|
||||
});
|
||||
scope.push_lazy("latest_symbol_open_order_id", || {
|
||||
ctx.latest_symbol_open_order_id(&stock.symbol) as i64
|
||||
});
|
||||
scope.push_lazy("latest_symbol_open_order_status", || {
|
||||
scope.push(
|
||||
"symbol_open_order_count",
|
||||
ctx.symbol_open_order_count(&stock.symbol) as i64,
|
||||
);
|
||||
scope.push(
|
||||
"symbol_open_buy_qty",
|
||||
ctx.symbol_open_buy_quantity(&stock.symbol) as i64,
|
||||
);
|
||||
scope.push(
|
||||
"symbol_open_sell_qty",
|
||||
ctx.symbol_open_sell_quantity(&stock.symbol) as i64,
|
||||
);
|
||||
scope.push(
|
||||
"latest_symbol_open_order_id",
|
||||
ctx.latest_symbol_open_order_id(&stock.symbol) as i64,
|
||||
);
|
||||
scope.push(
|
||||
"latest_symbol_open_order_status",
|
||||
ctx.latest_symbol_open_order_status(&stock.symbol)
|
||||
.to_string()
|
||||
});
|
||||
scope.push_lazy("latest_symbol_open_order_unfilled_qty", || {
|
||||
ctx.latest_symbol_open_order_unfilled_quantity(&stock.symbol) as i64
|
||||
});
|
||||
scope.push_lazy("in_dynamic_universe", || {
|
||||
ctx.dynamic_universe_contains(&stock.symbol)
|
||||
});
|
||||
scope.push_lazy("is_subscribed", || ctx.is_subscribed(&stock.symbol));
|
||||
.to_string(),
|
||||
);
|
||||
scope.push(
|
||||
"latest_symbol_open_order_unfilled_qty",
|
||||
ctx.latest_symbol_open_order_unfilled_quantity(&stock.symbol) as i64,
|
||||
);
|
||||
scope.push(
|
||||
"in_dynamic_universe",
|
||||
ctx.dynamic_universe_contains(&stock.symbol),
|
||||
);
|
||||
scope.push("is_subscribed", ctx.is_subscribed(&stock.symbol));
|
||||
scope.push("stock_ma_short", stock.stock_ma_short);
|
||||
scope.push("stock_ma_mid", stock.stock_ma_mid);
|
||||
scope.push("stock_ma_long", stock.stock_ma_long);
|
||||
@@ -5071,7 +5077,7 @@ impl PlatformExprStrategy {
|
||||
}
|
||||
}
|
||||
if let Some(position) = position {
|
||||
scope.push_lazy("order_book_id", || position.order_book_id.clone());
|
||||
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);
|
||||
@@ -5105,19 +5111,18 @@ impl PlatformExprStrategy {
|
||||
scope.push("trading_pnl", position.trading_pnl);
|
||||
scope.push("position_pnl", position.position_pnl);
|
||||
scope.push("dividend_receivable", position.dividend_receivable);
|
||||
scope.push_lazy("available_sellable_qty", || {
|
||||
stock
|
||||
.map(|stock| {
|
||||
ctx.available_sellable_qty(&stock.symbol, position.sellable_qty as u32)
|
||||
as i64
|
||||
})
|
||||
.unwrap_or(position.sellable_qty.max(0))
|
||||
});
|
||||
scope.push_lazy("reserved_open_sell_qty", || {
|
||||
let available_sellable_qty = stock
|
||||
.map(|stock| {
|
||||
ctx.available_sellable_qty(&stock.symbol, position.sellable_qty as u32)
|
||||
})
|
||||
.unwrap_or(position.sellable_qty.max(0) as u32);
|
||||
scope.push("available_sellable_qty", available_sellable_qty as i64);
|
||||
scope.push(
|
||||
"reserved_open_sell_qty",
|
||||
stock
|
||||
.map(|stock| ctx.symbol_open_sell_quantity(&stock.symbol) as i64)
|
||||
.unwrap_or(0)
|
||||
});
|
||||
.unwrap_or(0),
|
||||
);
|
||||
scope.push("profit_pct", position.holding_return * 100.0);
|
||||
}
|
||||
scope.into_inner()
|
||||
@@ -12828,11 +12833,9 @@ fn code_number_value(value: &str) -> i64 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::cell::Cell;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use ahash::AHashSet;
|
||||
use chrono::{NaiveDate, NaiveTime};
|
||||
|
||||
use super::{
|
||||
@@ -12841,9 +12844,9 @@ mod tests {
|
||||
PlatformExprStrategyConfig, PlatformPortfolioDrawdownControlConfig,
|
||||
PlatformPortfolioDrawdownController, PlatformRebalanceSchedule, PlatformScheduleFrequency,
|
||||
PlatformStopTakeReferencePriceMode, PlatformTradeAction, PlatformUniverseActionKind,
|
||||
RuntimeHelperResolution, SelectionRiskDeferral, SelectiveExpressionScope,
|
||||
StockFilterQuoteUsage, StockRollingField, StockSnapshotFieldRequirements,
|
||||
framework_stock_rolling_factor_requirement, scheduled_position_exposure,
|
||||
RuntimeHelperResolution, SelectionRiskDeferral, StockFilterQuoteUsage, StockRollingField,
|
||||
StockSnapshotFieldRequirements, framework_stock_rolling_factor_requirement,
|
||||
scheduled_position_exposure,
|
||||
};
|
||||
use crate::{
|
||||
AlgoOrderStyle, BenchmarkSnapshot, CandidateEligibility, CorporateAction,
|
||||
@@ -12859,25 +12862,6 @@ mod tests {
|
||||
NaiveDate::from_ymd_opt(year, month, day).expect("valid date")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selective_expression_scope_does_not_build_unreferenced_values() {
|
||||
let required = AHashSet::from_iter(["needed".to_string()]);
|
||||
let builds = Cell::new(0);
|
||||
let mut scope = SelectiveExpressionScope::new(&required);
|
||||
|
||||
scope.push_lazy("unused", || {
|
||||
builds.set(builds.get() + 1);
|
||||
"unused".to_string()
|
||||
});
|
||||
scope.push_lazy("needed", || {
|
||||
builds.set(builds.get() + 1);
|
||||
"value".to_string()
|
||||
});
|
||||
|
||||
assert_eq!(builds.get(), 1);
|
||||
assert!(scope.into_inner().contains("needed"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stock_state_cache_resets_before_reusing_compact_keys_on_another_date() {
|
||||
let dates = [d(2025, 1, 2), d(2025, 1, 3)];
|
||||
|
||||
Reference in New Issue
Block a user