perf(strategy): retain compact factor values in expression contexts

This commit is contained in:
boris
2026-09-13 00:41:51 +08:00
committed by boris
parent fe7243bbc3
commit 07b7b181b6
+29 -9
View File
@@ -27,6 +27,7 @@ use crate::numeric_expr_vm::{
self, EvalError as NumericVmEvalError, Program as NumericVmProgram,
Scratch as NumericVmScratch, Value as NumericVmValue, ValueType as NumericVmValueType,
};
use crate::numeric_factors::NumericFactorMap;
use crate::portfolio::PortfolioState;
use crate::holding_policy::{AutomaticTradeProtection, AutomaticTradePermission, HoldingLifecycleEvidence};
@@ -1010,7 +1011,7 @@ struct StockExpressionState {
stock_volume_ma60: f64,
stock_volume_ma100: f64,
current_series_end: Option<usize>,
extra_factors: BTreeMap<String, f64>,
extra_factors: NumericFactorMap,
extra_text_factors: BTreeMap<String, String>,
}
@@ -4390,11 +4391,14 @@ impl PlatformExprStrategy {
.factor_snapshot_rows_on(date)
.iter()
.flat_map(|row| {
row.extra_factors.keys().map(|key| key.to_string()).chain(
row.extra_factors.keys().map(|key| key.as_ref()).chain(
row.adjustment_factor_backward1
.map(|_| BACKWARD_ADJUSTMENT_FACTOR_FIELD.to_string()),
.map(|_| BACKWARD_ADJUSTMENT_FACTOR_FIELD),
)
})
.collect::<BTreeSet<_>>()
.into_iter()
.map(str::to_owned)
.collect()
} else {
BTreeSet::new()
@@ -4403,7 +4407,10 @@ impl PlatformExprStrategy {
ctx.data
.factor_text_rows_on(date)
.iter()
.map(|row| row.field.clone())
.map(|row| row.field.as_str())
.collect::<BTreeSet<_>>()
.into_iter()
.map(str::to_owned)
.collect()
} else {
BTreeSet::new()
@@ -4896,10 +4903,10 @@ impl PlatformExprStrategy {
self.stock_extra_factor_map_required
|| self.stock_extra_factor_identifiers.contains(field.as_ref())
})
.map(|(field, value)| (field.to_string(), *value))
.map(|(field, value)| (field.clone(), *value))
.collect()
} else {
BTreeMap::new()
NumericFactorMap::new()
};
if !self.config.completed_session_factor_fields.is_empty() {
let visible_date = completed_session_factor_date(
@@ -4914,7 +4921,7 @@ impl PlatformExprStrategy {
.and_then(|row| row.extra_factors.get(field.as_str()))
.copied()
.unwrap_or(f64::NAN);
extra_factors.insert(field.clone(), value);
extra_factors.insert(field.clone().into(), value);
}
}
}
@@ -4925,7 +4932,7 @@ impl PlatformExprStrategy {
.contains(BACKWARD_ADJUSTMENT_FACTOR_FIELD))
&& let Some(value) = factor.adjustment_factor_backward1
{
extra_factors.insert(BACKWARD_ADJUSTMENT_FACTOR_FIELD.to_string(), value);
extra_factors.insert(BACKWARD_ADJUSTMENT_FACTOR_FIELD.into(), value);
}
let state = StockExpressionState {
@@ -5642,7 +5649,7 @@ impl PlatformExprStrategy {
Dynamic::from(stock.stock_volume_ma100),
);
for (key, value) in &stock.extra_factors {
factors.insert(key.clone().into(), Dynamic::from(*value));
factors.insert(key.as_ref().into(), Dynamic::from(*value));
}
for (key, value) in &stock.extra_text_factors {
factors.insert(key.clone().into(), Dynamic::from(value.clone()));
@@ -14546,6 +14553,7 @@ mod tests {
use std::sync::Arc;
use chrono::{NaiveDate, NaiveTime};
use rhai::{Dynamic, Map};
use super::{
CompiledRuntimeHelperArgs, PlatformAccountActionKind, PlatformExplicitActionStage,
@@ -17542,6 +17550,18 @@ mod tests {
.stock_state_with_factor_date(&ctx, date, date, present_symbol)
.expect("factor map stock state");
assert!(map_stock.extra_factors.contains_key("unused_factor"));
let mut numeric_state = (*map_stock).clone();
numeric_state.extra_factors.insert("negative_zero".into(), -0.0);
numeric_state.extra_factors.insert("undefined_value".into(), f64::NAN);
let copied_state = numeric_state.clone();
assert_eq!(copied_state.extra_factors["negative_zero"].to_bits(), (-0.0_f64).to_bits());
assert!(copied_state.extra_factors["undefined_value"].is_nan());
let exposed = copied_state.extra_factors.iter()
.map(|(key, value)| (key.as_ref().into(), Dynamic::from(*value)))
.collect::<Map>();
assert_eq!(exposed["negative_zero"].as_float().unwrap().to_bits(), (-0.0_f64).to_bits());
assert!(exposed["undefined_value"].as_float().unwrap().is_nan());
assert!(!exposed.contains_key("missing_factor"));
let map_day = map_strategy
.day_state(&ctx, date)
.expect("factor map day state");