减少运行时辅助函数参数分配

This commit is contained in:
boris
2026-08-29 21:03:42 +08:00
parent ccac2a2399
commit cdc60f616f
+37 -8
View File
@@ -6158,7 +6158,7 @@ impl PlatformExprStrategy {
) -> Result<RuntimeHelperResolution, BacktestError> {
match helper {
"factor" => {
let key = Self::normalize_runtime_factor_key(&Self::parse_string_or_identifier(
let key = Self::normalize_runtime_factor_key(Self::parse_string_or_identifier_ref(
args.first().map(String::as_str).unwrap_or_default(),
)?);
if let Some((field, lookback)) = framework_stock_rolling_factor_requirement(&key) {
@@ -6190,7 +6190,7 @@ impl PlatformExprStrategy {
)))
}
"day_factor" => {
let key = Self::normalize_runtime_factor_key(&Self::parse_string_or_identifier(
let key = Self::normalize_runtime_factor_key(Self::parse_string_or_identifier_ref(
args.first().map(String::as_str).unwrap_or_default(),
)?);
Ok(RuntimeHelperResolution::Expression(format!(
@@ -6204,7 +6204,7 @@ impl PlatformExprStrategy {
"{helper} expects 2 arguments"
)));
}
let field = Self::parse_string_or_identifier(&args[0])?;
let field = Self::parse_string_or_identifier_ref(&args[0])?;
let lookback = Self::parse_positive_usize(&args[1])?;
let value = self.resolve_rolling_mean(ctx, day, stock, &field, lookback)?;
Ok(RuntimeHelperResolution::Number(value))
@@ -6215,7 +6215,7 @@ impl PlatformExprStrategy {
"rolling_mean_current expects 2 arguments".to_string(),
));
}
let field = Self::parse_string_or_identifier(&args[0])?;
let field = Self::parse_string_or_identifier_ref(&args[0])?;
let lookback = Self::parse_positive_usize(&args[1])?;
let value = self.resolve_current_rolling_mean(ctx, day, stock, &field, lookback)?;
Ok(RuntimeHelperResolution::Number(value))
@@ -6226,7 +6226,7 @@ impl PlatformExprStrategy {
"rolling_max_current expects field and lookback".to_string(),
));
}
let field = Self::parse_string_or_identifier(&args[0])?;
let field = Self::parse_string_or_identifier_ref(&args[0])?;
let lookback = Self::parse_positive_usize(&args[1])?;
let values =
self.resolve_current_rolling_values(ctx, day, stock, &field, lookback)?;
@@ -6239,7 +6239,7 @@ impl PlatformExprStrategy {
"rolling_return_stddev_current expects field and return count".to_string(),
));
}
let field = Self::parse_string_or_identifier(&args[0])?;
let field = Self::parse_string_or_identifier_ref(&args[0])?;
let return_count = Self::parse_positive_usize(&args[1])?;
let values = self.resolve_current_rolling_values(
ctx,
@@ -6278,7 +6278,7 @@ impl PlatformExprStrategy {
"{helper} expects field and lookback"
)));
}
let field = Self::parse_string_or_identifier(&args[0])?;
let field = Self::parse_string_or_identifier_ref(&args[0])?;
let lookback = Self::parse_positive_usize(&args[1])?;
let values = self.resolve_rolling_values(ctx, day, stock, &field, lookback)?;
let value = match helper {
@@ -6297,7 +6297,7 @@ impl PlatformExprStrategy {
"pct_change expects field and lookback".to_string(),
));
}
let field = Self::parse_string_or_identifier(&args[0])?;
let field = Self::parse_string_or_identifier_ref(&args[0])?;
let lookback = Self::parse_positive_usize(&args[1])?;
let values = self.resolve_rolling_values(
ctx,
@@ -7083,6 +7083,35 @@ impl PlatformExprStrategy {
)))
}
/// Parse the literal/identifier forms used by runtime helpers without
/// allocating a new String on every stock evaluation. The owned parser
/// above remains the boundary for helpers that must retain the value.
fn parse_string_or_identifier_ref(raw: &str) -> Result<&str, BacktestError> {
let trimmed = raw.trim();
if trimmed.is_empty() {
return Err(BacktestError::Execution(
"platform helper argument cannot be empty".to_string(),
));
}
if let Some(value) = trimmed
.strip_prefix('"')
.and_then(|value| value.strip_suffix('"'))
.or_else(|| {
trimmed
.strip_prefix('\'')
.and_then(|value| value.strip_suffix('\''))
})
{
return Ok(value);
}
if Self::is_expression_identifier(trimmed) {
return Ok(trimmed);
}
Err(BacktestError::Execution(format!(
"platform helper expects a factor name or string literal, got {trimmed}"
)))
}
fn normalize_runtime_factor_key(key: &str) -> String {
key.trim()
.trim_matches('"')