fix: preserve missing numeric factors and reject nonfinite truthiness
This commit is contained in:
@@ -4687,7 +4687,7 @@ impl PlatformExprStrategy {
|
|||||||
} else if intraday_same_day_factor {
|
} else if intraday_same_day_factor {
|
||||||
f64::NAN
|
f64::NAN
|
||||||
} else {
|
} else {
|
||||||
factor.extra_factors.get("amount").copied().unwrap_or(0.0)
|
factor.extra_factors.get("amount").copied().unwrap_or(f64::NAN)
|
||||||
};
|
};
|
||||||
let market_cap_bn = decision_market_cap_bn(factor);
|
let market_cap_bn = decision_market_cap_bn(factor);
|
||||||
let free_float_cap_bn = decision_free_float_cap_bn(factor);
|
let free_float_cap_bn = decision_free_float_cap_bn(factor);
|
||||||
@@ -4769,8 +4769,8 @@ impl PlatformExprStrategy {
|
|||||||
minute_volume: market.minute_volume as i64,
|
minute_volume: market.minute_volume as i64,
|
||||||
bid1_volume: market.bid1_volume as i64,
|
bid1_volume: market.bid1_volume as i64,
|
||||||
ask1_volume: market.ask1_volume as i64,
|
ask1_volume: market.ask1_volume as i64,
|
||||||
turnover_ratio: factor.turnover_ratio.unwrap_or(0.0),
|
turnover_ratio: factor.turnover_ratio.unwrap_or(f64::NAN),
|
||||||
effective_turnover_ratio: factor.effective_turnover_ratio.unwrap_or(0.0),
|
effective_turnover_ratio: factor.effective_turnover_ratio.unwrap_or(f64::NAN),
|
||||||
open: feature_market.day_open,
|
open: feature_market.day_open,
|
||||||
high: expression_high,
|
high: expression_high,
|
||||||
low: expression_low,
|
low: expression_low,
|
||||||
@@ -8359,7 +8359,7 @@ impl PlatformExprStrategy {
|
|||||||
if let Some(value) = self.eval_numeric_vm(ctx, expr, day, stock, position)? {
|
if let Some(value) = self.eval_numeric_vm(ctx, expr, day, stock, position)? {
|
||||||
return match value {
|
return match value {
|
||||||
NumericVmValue::Boolean(boolean) => Ok(boolean),
|
NumericVmValue::Boolean(boolean) => Ok(boolean),
|
||||||
NumericVmValue::Number(number) => Ok(number != 0.0),
|
NumericVmValue::Number(number) => Ok(number.is_finite() && number != 0.0),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
let value = self.eval_dynamic(ctx, expr, day, stock, position)?;
|
let value = self.eval_dynamic(ctx, expr, day, stock, position)?;
|
||||||
@@ -8367,7 +8367,7 @@ impl PlatformExprStrategy {
|
|||||||
return Ok(boolean);
|
return Ok(boolean);
|
||||||
}
|
}
|
||||||
if let Some(number) = value.clone().try_cast::<f64>() {
|
if let Some(number) = value.clone().try_cast::<f64>() {
|
||||||
return Ok(number != 0.0);
|
return Ok(number.is_finite() && number != 0.0);
|
||||||
}
|
}
|
||||||
if let Some(number) = value.try_cast::<i64>() {
|
if let Some(number) = value.try_cast::<i64>() {
|
||||||
return Ok(number != 0);
|
return Ok(number != 0);
|
||||||
@@ -16524,8 +16524,8 @@ mod tests {
|
|||||||
market_cap_bn: 12.0,
|
market_cap_bn: 12.0,
|
||||||
free_float_cap_bn: 10.0,
|
free_float_cap_bn: 10.0,
|
||||||
pe_ttm: 8.0,
|
pe_ttm: 8.0,
|
||||||
turnover_ratio: Some(1.0),
|
turnover_ratio: None,
|
||||||
effective_turnover_ratio: Some(1.0),
|
effective_turnover_ratio: None,
|
||||||
adjustment_factor_backward1: None,
|
adjustment_factor_backward1: None,
|
||||||
extra_factors: BTreeMap::new(),
|
extra_factors: BTreeMap::new(),
|
||||||
},
|
},
|
||||||
@@ -16535,8 +16535,8 @@ mod tests {
|
|||||||
market_cap_bn: 12.0,
|
market_cap_bn: 12.0,
|
||||||
free_float_cap_bn: 10.0,
|
free_float_cap_bn: 10.0,
|
||||||
pe_ttm: 8.0,
|
pe_ttm: 8.0,
|
||||||
turnover_ratio: Some(1.0),
|
turnover_ratio: Some(0.0),
|
||||||
effective_turnover_ratio: Some(1.0),
|
effective_turnover_ratio: Some(0.0),
|
||||||
adjustment_factor_backward1: None,
|
adjustment_factor_backward1: None,
|
||||||
extra_factors: BTreeMap::from([
|
extra_factors: BTreeMap::from([
|
||||||
("model_score".into(), 2.0),
|
("model_score".into(), 2.0),
|
||||||
@@ -16601,6 +16601,16 @@ mod tests {
|
|||||||
.expect("present stock state");
|
.expect("present stock state");
|
||||||
|
|
||||||
assert!(day.available_factor_names.contains("model_score"));
|
assert!(day.available_factor_names.contains("model_score"));
|
||||||
|
assert!(missing_stock.turnover_ratio.is_nan());
|
||||||
|
assert!(missing_stock.effective_turnover_ratio.is_nan());
|
||||||
|
assert_eq!(present_stock.turnover_ratio, 0.0);
|
||||||
|
assert!(!strategy.eval_bool(&ctx, "model_score", &day, Some(&missing_stock), None).unwrap());
|
||||||
|
assert!(strategy.eval_bool(&ctx, "model_score", &day, Some(&present_stock), None).unwrap());
|
||||||
|
for field in ["turnover_ratio", "effective_turnover_ratio"] {
|
||||||
|
let predicate = format!("{field} < 1.0");
|
||||||
|
assert!(!strategy.eval_bool(&ctx, &predicate, &day, Some(&missing_stock), None).unwrap());
|
||||||
|
assert!(strategy.eval_bool(&ctx, &predicate, &day, Some(&present_stock), None).unwrap());
|
||||||
|
}
|
||||||
assert!(
|
assert!(
|
||||||
!strategy
|
!strategy
|
||||||
.stock_passes_expr(&ctx, &day, &missing_stock)
|
.stock_passes_expr(&ctx, &day, &missing_stock)
|
||||||
|
|||||||
Reference in New Issue
Block a user