diff --git a/crates/fidc-core/src/platform_expr_strategy.rs b/crates/fidc-core/src/platform_expr_strategy.rs index 6788702..656c9a9 100644 --- a/crates/fidc-core/src/platform_expr_strategy.rs +++ b/crates/fidc-core/src/platform_expr_strategy.rs @@ -9878,6 +9878,31 @@ impl PlatformExprStrategy { .unwrap_or_else(|| self.field_value_from_caps(market_cap_bn, free_float_cap_bn)) } + fn selection_factor_field_value( + &self, + market_cap_bn: f64, + free_float_cap_bn: f64, + ) -> Option { + match self.config.market_cap_field.as_str() { + "market_cap" | "candidate_market_cap" => { + Some(Self::market_cap_storage_to_strategy_unit(market_cap_bn)) + } + "market_cap_bn" | "candidate_market_cap_bn" => Some(market_cap_bn), + "free_float_cap" | "free_float_market_cap" | "candidate_free_float_cap" => { + Some(Self::market_cap_storage_to_strategy_unit(free_float_cap_bn)) + } + "free_float_cap_bn" | "candidate_free_float_cap_bn" => Some(free_float_cap_bn), + "free_float_cap_or_market_cap" => Some(Self::market_cap_storage_to_strategy_unit( + if free_float_cap_bn.is_finite() && free_float_cap_bn > 0.0 { + free_float_cap_bn + } else { + market_cap_bn + }, + )), + _ => None, + } + } + fn rank_value_from_caps( &self, ctx: &StrategyContext<'_>, @@ -10226,6 +10251,16 @@ impl PlatformExprStrategy { let symbol = factor.symbol.as_str(); let market_cap_bn = decision_market_cap_bn(factor); let free_float_cap_bn = decision_free_float_cap_bn(factor); + let factor_field_value = + self.selection_factor_field_value(market_cap_bn, free_float_cap_bn); + if let Some(field_value) = factor_field_value + && (!field_value.is_finite() || field_value < band_low || field_value > band_high) + { + if !field_value.is_finite() && diagnostics.len() < 12 { + diagnostics.push(format!("{symbol} rejected by missing selection field")); + } + continue; + } let stock = self.uncached_selection_stock_state_from_views_by_symbol_id( ctx, date, @@ -10235,8 +10270,9 @@ impl PlatformExprStrategy { &execution_day, &factor_day, )?; - let field_value = - self.selection_field_value_from_caps(market_cap_bn, free_float_cap_bn, &stock); + let field_value = factor_field_value.unwrap_or_else(|| { + self.selection_field_value_from_caps(market_cap_bn, free_float_cap_bn, &stock) + }); if !field_value.is_finite() { if diagnostics.len() < 12 { diagnostics.push(format!("{symbol} rejected by missing selection field")); @@ -10968,6 +11004,18 @@ impl PlatformExprStrategy { let symbol = factor.symbol.as_str(); let market_cap_bn = decision_market_cap_bn(factor); let free_float_cap_bn = decision_free_float_cap_bn(factor); + let factor_field_value = + self.selection_factor_field_value(market_cap_bn, free_float_cap_bn); + if let Some(field_value) = factor_field_value + && (!field_value.is_finite() || field_value < band_low || field_value > band_high) + { + if !field_value.is_finite() && diagnostics.len() < 12 { + diagnostics.push(format!( + "{symbol} quote_plan rejected by missing selection field" + )); + } + continue; + } let stock = self.uncached_selection_stock_state_from_views_by_symbol_id( ctx, date, @@ -10977,8 +11025,9 @@ impl PlatformExprStrategy { &execution_day, &factor_day, )?; - let field_value = - self.selection_field_value_from_caps(market_cap_bn, free_float_cap_bn, &stock); + let field_value = factor_field_value.unwrap_or_else(|| { + self.selection_field_value_from_caps(market_cap_bn, free_float_cap_bn, &stock) + }); if !field_value.is_finite() { if diagnostics.len() < 12 { diagnostics.push(format!(