Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f62d82420 |
@@ -1,7 +1,7 @@
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
use chrono::{NaiveDate, NaiveDateTime};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -997,7 +997,7 @@ pub struct DataSet {
|
||||
benchmark_by_date: BTreeMap<NaiveDate, BenchmarkSnapshot>,
|
||||
market_series_by_symbol: HashMap<String, SymbolPriceSeries>,
|
||||
benchmark_series_cache: BenchmarkPriceSeries,
|
||||
eligible_universe_by_date: BTreeMap<NaiveDate, Vec<EligibleUniverseSnapshot>>,
|
||||
eligible_universe_by_date: Arc<OnceLock<BTreeMap<NaiveDate, Vec<EligibleUniverseSnapshot>>>>,
|
||||
benchmark_code: String,
|
||||
futures_params_by_symbol: HashMap<String, Vec<FuturesTradingParameter>>,
|
||||
}
|
||||
@@ -1303,12 +1303,6 @@ impl DataSet {
|
||||
let market_series_by_symbol = build_market_series(&market_by_date);
|
||||
let benchmark_series_cache =
|
||||
BenchmarkPriceSeries::new(&benchmark_by_date.values().cloned().collect::<Vec<_>>());
|
||||
let eligible_universe_by_date = build_eligible_universe(
|
||||
&factor_by_date,
|
||||
&candidate_index,
|
||||
&market_index,
|
||||
&instruments,
|
||||
);
|
||||
let futures_params_by_symbol = build_futures_params_index(futures_params);
|
||||
|
||||
Ok(Self {
|
||||
@@ -1328,7 +1322,7 @@ impl DataSet {
|
||||
benchmark_by_date,
|
||||
market_series_by_symbol,
|
||||
benchmark_series_cache,
|
||||
eligible_universe_by_date,
|
||||
eligible_universe_by_date: Arc::new(OnceLock::new()),
|
||||
benchmark_code,
|
||||
futures_params_by_symbol,
|
||||
})
|
||||
@@ -2625,6 +2619,14 @@ impl DataSet {
|
||||
|
||||
pub fn eligible_universe_on(&self, date: NaiveDate) -> &[EligibleUniverseSnapshot] {
|
||||
self.eligible_universe_by_date
|
||||
.get_or_init(|| {
|
||||
build_eligible_universe(
|
||||
&self.factor_by_date,
|
||||
&self.candidate_index,
|
||||
&self.market_index,
|
||||
&self.instruments,
|
||||
)
|
||||
})
|
||||
.get(&date)
|
||||
.map(Vec::as_slice)
|
||||
.unwrap_or(&[])
|
||||
@@ -3595,7 +3597,10 @@ fn build_market_series(
|
||||
let mut grouped = HashMap::<String, Vec<&DailyMarketSnapshot>>::new();
|
||||
for rows in market_by_date.values() {
|
||||
for row in rows {
|
||||
grouped.entry(row.symbol.clone()).or_default().push(row.as_ref());
|
||||
grouped
|
||||
.entry(row.symbol.clone())
|
||||
.or_default()
|
||||
.push(row.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6374,6 +6374,7 @@ impl PlatformExprStrategy {
|
||||
return requirements;
|
||||
}
|
||||
Self::require_stock_rollings_for_identifiers(&mut requirements, config, &normalized);
|
||||
Self::require_stock_rollings_for_helper_calls(&mut requirements, &normalized);
|
||||
}
|
||||
Self::require_stock_rollings_for_fast_filter(
|
||||
&mut requirements,
|
||||
@@ -6612,6 +6613,96 @@ impl PlatformExprStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
fn require_stock_rollings_for_helper_calls(
|
||||
requirements: &mut StockRollingRequirements,
|
||||
expr: &str,
|
||||
) {
|
||||
let compact = Self::compact_expr(expr);
|
||||
Self::require_stock_rollings_for_named_helper(requirements, &compact, "rolling_mean");
|
||||
Self::require_stock_rollings_for_named_helper(requirements, &compact, "sma");
|
||||
Self::require_stock_rollings_for_named_helper(requirements, &compact, "ma");
|
||||
Self::require_stock_rollings_for_vma_helper(requirements, &compact);
|
||||
}
|
||||
|
||||
fn require_stock_rollings_for_named_helper(
|
||||
requirements: &mut StockRollingRequirements,
|
||||
compact: &str,
|
||||
helper: &str,
|
||||
) {
|
||||
let needle = format!("{helper}(");
|
||||
let mut offset = 0usize;
|
||||
while let Some(relative) = compact[offset..].find(&needle) {
|
||||
let args_start = offset + relative + needle.len();
|
||||
let args = &compact[args_start..];
|
||||
let Some((field, rest)) = Self::parse_quoted_arg(args) else {
|
||||
offset = args_start;
|
||||
continue;
|
||||
};
|
||||
let Some(rest) = rest.strip_prefix(',') else {
|
||||
offset = args_start;
|
||||
continue;
|
||||
};
|
||||
let Some(lookback) = Self::parse_usize_prefix(rest) else {
|
||||
offset = args_start;
|
||||
continue;
|
||||
};
|
||||
let normalized_field = field.trim().to_ascii_lowercase();
|
||||
match normalized_field.as_str() {
|
||||
"close" | "prev_close" | "stock_close" | "price" => {
|
||||
requirements.require(StockRollingField::Close, lookback)
|
||||
}
|
||||
"volume" | "stock_volume" => {
|
||||
requirements.require(StockRollingField::Volume, lookback)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
offset = args_start;
|
||||
}
|
||||
}
|
||||
|
||||
fn require_stock_rollings_for_vma_helper(
|
||||
requirements: &mut StockRollingRequirements,
|
||||
compact: &str,
|
||||
) {
|
||||
let needle = "vma(";
|
||||
let mut offset = 0usize;
|
||||
while let Some(relative) = compact[offset..].find(needle) {
|
||||
let args_start = offset + relative + needle.len();
|
||||
if let Some(lookback) = Self::parse_usize_prefix(&compact[args_start..]) {
|
||||
requirements.require(StockRollingField::Volume, lookback);
|
||||
}
|
||||
offset = args_start;
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_quoted_arg(input: &str) -> Option<(String, &str)> {
|
||||
let mut chars = input.char_indices();
|
||||
let (_, quote) = chars.next()?;
|
||||
if quote != '"' && quote != '\'' {
|
||||
return None;
|
||||
}
|
||||
for (idx, ch) in chars {
|
||||
if ch == quote {
|
||||
let value = input[1..idx].to_string();
|
||||
let rest = &input[idx + ch.len_utf8()..];
|
||||
return Some((value, rest));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn parse_usize_prefix(input: &str) -> Option<usize> {
|
||||
let end = input
|
||||
.char_indices()
|
||||
.take_while(|(_, ch)| ch.is_ascii_digit())
|
||||
.map(|(idx, ch)| idx + ch.len_utf8())
|
||||
.last()?;
|
||||
input[..end]
|
||||
.parse::<usize>()
|
||||
.ok()
|
||||
.filter(|value| *value > 0)
|
||||
}
|
||||
|
||||
fn require_stock_rollings_for_fast_filter(
|
||||
requirements: &mut StockRollingRequirements,
|
||||
config: &PlatformExprStrategyConfig,
|
||||
|
||||
Reference in New Issue
Block a user