fix: reject missing numeric sizing and execution parameters
This commit is contained in:
@@ -8363,6 +8363,25 @@ impl PlatformExprStrategy {
|
||||
day: &DayExpressionState,
|
||||
stock: Option<&StockExpressionState>,
|
||||
position: Option<&PositionExpressionState>,
|
||||
) -> Result<f64, BacktestError> {
|
||||
let value = self.eval_float_or_missing(ctx, expr, day, stock, position)?;
|
||||
if !value.is_finite() {
|
||||
return Err(BacktestError::Execution(format!(
|
||||
"missing_numeric_result: expression={expr:?}, symbol={}, decision_date={}, execution_date={}",
|
||||
stock.map(|item| item.symbol.as_ref()).unwrap_or("portfolio"),
|
||||
ctx.decision_date, ctx.execution_date,
|
||||
)));
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn eval_float_or_missing(
|
||||
&self,
|
||||
ctx: &StrategyContext<'_>,
|
||||
expr: &str,
|
||||
day: &DayExpressionState,
|
||||
stock: Option<&StockExpressionState>,
|
||||
position: Option<&PositionExpressionState>,
|
||||
) -> Result<f64, BacktestError> {
|
||||
if let Some(value) = self.eval_numeric_vm(ctx, expr, day, stock, position)? {
|
||||
return match value {
|
||||
@@ -10441,7 +10460,7 @@ impl PlatformExprStrategy {
|
||||
stock: &StockExpressionState,
|
||||
) -> Result<f64, BacktestError> {
|
||||
if self.rank_expr_present {
|
||||
return match self.eval_float(ctx, &self.config.rank_expr, day, Some(stock), None) {
|
||||
return match self.eval_float_or_missing(ctx, &self.config.rank_expr, day, Some(stock), None) {
|
||||
Ok(value) => Ok(value),
|
||||
Err(error) if Self::is_missing_rolling_mean_error(&error) => Ok(f64::NAN),
|
||||
Err(error) if Self::is_non_numeric_expr_error(&error) => Ok(f64::NAN),
|
||||
@@ -16644,6 +16663,12 @@ mod tests {
|
||||
assert!(missing_stock.turnover_ratio.is_nan());
|
||||
assert!(missing_stock.effective_turnover_ratio.is_nan());
|
||||
assert_eq!(present_stock.turnover_ratio, 0.0);
|
||||
for expression in ["model_score", "min(model_score, 1.0)", "model_score / 100.0"] {
|
||||
let error = strategy.eval_float(&ctx, expression, &day, Some(&missing_stock), None).unwrap_err();
|
||||
assert!(error.to_string().contains("missing_numeric_result"), "{error}");
|
||||
}
|
||||
assert!(strategy.eval_float_or_missing(&ctx, "model_score", &day, Some(&missing_stock), None).unwrap().is_nan());
|
||||
assert_eq!(strategy.eval_float(&ctx, "nz(model_score, 0.0)", &day, Some(&missing_stock), None).unwrap(), 0.0);
|
||||
for predicate in [
|
||||
"!(model_score > 0.0)",
|
||||
"!(model_score != 0.0)",
|
||||
|
||||
Reference in New Issue
Block a user