复用策略表达式解析计划
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::{Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime};
|
||||
use rhai::{AST, Dynamic, Engine, Map, Scope};
|
||||
@@ -835,6 +836,11 @@ impl<'a> SelectiveExpressionScope<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
struct ExpressionEvalPlan {
|
||||
normalized: String,
|
||||
identifiers: BTreeSet<String>,
|
||||
}
|
||||
|
||||
pub struct PlatformExprStrategy {
|
||||
config: PlatformExprStrategyConfig,
|
||||
engine: Engine,
|
||||
@@ -857,6 +863,7 @@ pub struct PlatformExprStrategy {
|
||||
/// 命中计数与未命中计数,便于在 unit test 中验证缓存生效;非生产指标。
|
||||
cache_hits: RefCell<u64>,
|
||||
cache_misses: RefCell<u64>,
|
||||
expression_plan_cache: RefCell<HashMap<String, Arc<ExpressionEvalPlan>>>,
|
||||
normalized_prelude: String,
|
||||
prelude_identifier_candidates: BTreeSet<String>,
|
||||
prelude_declared_identifiers: BTreeSet<String>,
|
||||
@@ -1177,6 +1184,7 @@ impl PlatformExprStrategy {
|
||||
compiled_cache: RefCell::new(HashMap::new()),
|
||||
cache_hits: RefCell::new(0),
|
||||
cache_misses: RefCell::new(0),
|
||||
expression_plan_cache: RefCell::new(HashMap::new()),
|
||||
normalized_prelude,
|
||||
prelude_identifier_candidates,
|
||||
prelude_declared_identifiers,
|
||||
@@ -4453,8 +4461,9 @@ impl PlatformExprStrategy {
|
||||
stock: Option<&StockExpressionState>,
|
||||
position: Option<&PositionExpressionState>,
|
||||
) -> Result<Dynamic, BacktestError> {
|
||||
let normalized_expr = Self::normalize_expr(expr);
|
||||
let normalized_identifiers = Self::extract_identifier_candidates(&normalized_expr);
|
||||
let expression_plan = self.expression_eval_plan(expr);
|
||||
let normalized_expr = expression_plan.normalized.as_str();
|
||||
let normalized_identifiers = &expression_plan.identifiers;
|
||||
let prelude_identifiers = &self.prelude_identifier_candidates;
|
||||
let include_day_factors = normalized_identifiers.contains("day_factors")
|
||||
|| normalized_identifiers.contains("day_factor")
|
||||
@@ -4481,27 +4490,30 @@ impl PlatformExprStrategy {
|
||||
let expanded_expr =
|
||||
self.expand_runtime_helpers(ctx, day, stock, &normalized_expr, &mut scope)?;
|
||||
if let Some(item) = stock {
|
||||
let mut expanded_identifiers = Self::extract_identifier_candidates(&expanded_prelude);
|
||||
expanded_identifiers.extend(Self::extract_identifier_candidates(&expanded_expr));
|
||||
for identifier in expanded_identifiers {
|
||||
let factor_identifiers = normalized_identifiers.iter().chain(
|
||||
prelude_identifiers
|
||||
.iter()
|
||||
.filter(|identifier| !normalized_identifiers.contains(*identifier)),
|
||||
);
|
||||
for identifier in factor_identifiers {
|
||||
if Self::is_reserved_scope_name(identifier.as_str())
|
||||
|| self.prelude_declared_identifiers.contains(&identifier)
|
||||
|| (!self.stock_extra_factor_identifiers.contains(&identifier)
|
||||
&& !item.extra_factors.contains_key(&identifier)
|
||||
&& !day.available_factor_names.contains(&identifier)
|
||||
&& !day.available_text_factor_names.contains(&identifier))
|
||||
|| self.prelude_declared_identifiers.contains(identifier)
|
||||
|| (!self.stock_extra_factor_identifiers.contains(identifier)
|
||||
&& !item.extra_factors.contains_key(identifier)
|
||||
&& !day.available_factor_names.contains(identifier)
|
||||
&& !day.available_text_factor_names.contains(identifier))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if let Some(value) = item.extra_text_factors.get(&identifier) {
|
||||
scope.push_dynamic(identifier, Dynamic::from(value.clone()));
|
||||
if let Some(value) = item.extra_text_factors.get(identifier) {
|
||||
scope.push_dynamic(identifier.clone(), Dynamic::from(value.clone()));
|
||||
} else {
|
||||
let value = item
|
||||
.extra_factors
|
||||
.get(&identifier)
|
||||
.get(identifier)
|
||||
.copied()
|
||||
.unwrap_or(f64::NAN);
|
||||
scope.push_dynamic(identifier, Dynamic::from(value));
|
||||
scope.push_dynamic(identifier.clone(), Dynamic::from(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4514,6 +4526,21 @@ impl PlatformExprStrategy {
|
||||
self.eval_with_cache(&mut scope, &script)
|
||||
}
|
||||
|
||||
fn expression_eval_plan(&self, expr: &str) -> Arc<ExpressionEvalPlan> {
|
||||
if let Some(plan) = self.expression_plan_cache.borrow().get(expr).cloned() {
|
||||
return plan;
|
||||
}
|
||||
let normalized = Self::normalize_expr(expr);
|
||||
let plan = Arc::new(ExpressionEvalPlan {
|
||||
identifiers: Self::extract_identifier_candidates(&normalized),
|
||||
normalized,
|
||||
});
|
||||
self.expression_plan_cache
|
||||
.borrow_mut()
|
||||
.insert(expr.to_string(), Arc::clone(&plan));
|
||||
plan
|
||||
}
|
||||
|
||||
fn normalize_expr(expr: &str) -> String {
|
||||
let expr = Self::normalize_runtime_field_aliases(expr.trim());
|
||||
let expr = Self::normalize_python_numeric_division(&expr);
|
||||
|
||||
Reference in New Issue
Block a user