修复执行价索引和平台表达式回退
This commit is contained in:
@@ -734,6 +734,27 @@ impl BenchmarkPriceSeries {
|
||||
Some(sum / lookback as f64)
|
||||
}
|
||||
|
||||
fn decision_values_for(
|
||||
&self,
|
||||
date: NaiveDate,
|
||||
lookback: usize,
|
||||
field: PriceField,
|
||||
) -> Vec<f64> {
|
||||
if lookback == 0 {
|
||||
return Vec::new();
|
||||
}
|
||||
let end = match self.dates.binary_search(&date) {
|
||||
Ok(idx) => idx,
|
||||
Err(0) => return Vec::new(),
|
||||
Err(idx) => idx,
|
||||
};
|
||||
let start = end.saturating_sub(lookback);
|
||||
match field {
|
||||
PriceField::DayOpen | PriceField::Open => self.opens[start..end].to_vec(),
|
||||
PriceField::Close | PriceField::Last => self.closes[start..end].to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
fn moving_average_for(
|
||||
&self,
|
||||
date: NaiveDate,
|
||||
@@ -791,7 +812,7 @@ pub struct DataSet {
|
||||
candidate_by_date: BTreeMap<NaiveDate, Vec<CandidateEligibility>>,
|
||||
candidate_index: HashMap<(NaiveDate, String), CandidateEligibility>,
|
||||
corporate_actions_by_date: BTreeMap<NaiveDate, Vec<CorporateAction>>,
|
||||
execution_quotes_index: HashMap<(NaiveDate, String), Vec<IntradayExecutionQuote>>,
|
||||
execution_quotes_by_date: HashMap<NaiveDate, HashMap<String, Vec<IntradayExecutionQuote>>>,
|
||||
order_book_depth_index: HashMap<(NaiveDate, String), Vec<IntradayOrderBookDepthLevel>>,
|
||||
benchmark_by_date: BTreeMap<NaiveDate, BenchmarkSnapshot>,
|
||||
market_series_by_symbol: HashMap<String, SymbolPriceSeries>,
|
||||
@@ -1075,7 +1096,7 @@ impl DataSet {
|
||||
.map(|item| ((item.date, item.symbol.clone()), item))
|
||||
.collect::<HashMap<_, _>>();
|
||||
let corporate_actions_by_date = group_by_date(corporate_actions, |item| item.date);
|
||||
let execution_quotes_index = build_execution_quote_index(execution_quotes);
|
||||
let execution_quotes_by_date = build_execution_quote_index(execution_quotes);
|
||||
let order_book_depth_index = build_order_book_depth_index(order_book_depth);
|
||||
|
||||
let benchmark_by_date = benchmarks
|
||||
@@ -1105,7 +1126,7 @@ impl DataSet {
|
||||
candidate_by_date,
|
||||
candidate_index,
|
||||
corporate_actions_by_date,
|
||||
execution_quotes_index,
|
||||
execution_quotes_by_date,
|
||||
order_book_depth_index,
|
||||
benchmark_by_date,
|
||||
market_series_by_symbol,
|
||||
@@ -1177,14 +1198,22 @@ impl DataSet {
|
||||
}
|
||||
|
||||
pub fn execution_quotes_on(&self, date: NaiveDate, symbol: &str) -> &[IntradayExecutionQuote] {
|
||||
self.execution_quotes_index
|
||||
.get(&(date, symbol.to_string()))
|
||||
self.execution_quotes_by_date
|
||||
.get(&date)
|
||||
.and_then(|rows_by_symbol| rows_by_symbol.get(symbol))
|
||||
.map(Vec::as_slice)
|
||||
.unwrap_or(&[])
|
||||
}
|
||||
|
||||
pub fn execution_quote_key_set(&self) -> HashSet<(NaiveDate, String)> {
|
||||
self.execution_quotes_index.keys().cloned().collect()
|
||||
self.execution_quotes_by_date
|
||||
.iter()
|
||||
.flat_map(|(date, rows_by_symbol)| {
|
||||
rows_by_symbol
|
||||
.keys()
|
||||
.map(move |symbol| (*date, symbol.clone()))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn add_execution_quotes(&mut self, quotes: Vec<IntradayExecutionQuote>) -> usize {
|
||||
@@ -1192,7 +1221,12 @@ impl DataSet {
|
||||
let mut touched = HashSet::<(NaiveDate, String)>::new();
|
||||
for quote in quotes {
|
||||
let key = (quote.date, quote.symbol.clone());
|
||||
let rows = self.execution_quotes_index.entry(key.clone()).or_default();
|
||||
let rows = self
|
||||
.execution_quotes_by_date
|
||||
.entry(quote.date)
|
||||
.or_default()
|
||||
.entry(quote.symbol.clone())
|
||||
.or_default();
|
||||
if rows.iter().any(|existing| {
|
||||
existing.timestamp == quote.timestamp && existing.symbol == quote.symbol
|
||||
}) {
|
||||
@@ -1202,8 +1236,12 @@ impl DataSet {
|
||||
touched.insert(key);
|
||||
added += 1;
|
||||
}
|
||||
for key in touched {
|
||||
if let Some(rows) = self.execution_quotes_index.get_mut(&key) {
|
||||
for (date, symbol) in touched {
|
||||
if let Some(rows) = self
|
||||
.execution_quotes_by_date
|
||||
.get_mut(&date)
|
||||
.and_then(|rows_by_symbol| rows_by_symbol.get_mut(&symbol))
|
||||
{
|
||||
rows.sort_by_key(|quote| quote.timestamp);
|
||||
}
|
||||
}
|
||||
@@ -1223,10 +1261,11 @@ impl DataSet {
|
||||
|
||||
pub fn execution_quotes_on_date(&self, date: NaiveDate) -> Vec<IntradayExecutionQuote> {
|
||||
let mut quotes = self
|
||||
.execution_quotes_index
|
||||
.iter()
|
||||
.filter(|((quote_date, _), _)| *quote_date == date)
|
||||
.flat_map(|(_, rows)| rows.iter().cloned())
|
||||
.execution_quotes_by_date
|
||||
.get(&date)
|
||||
.into_iter()
|
||||
.flat_map(|rows_by_symbol| rows_by_symbol.values())
|
||||
.flat_map(|rows| rows.iter().cloned())
|
||||
.collect::<Vec<_>>();
|
||||
quotes.sort_by(|left, right| {
|
||||
left.timestamp
|
||||
@@ -1346,10 +1385,10 @@ impl DataSet {
|
||||
return Vec::new();
|
||||
}
|
||||
let mut quotes = self
|
||||
.execution_quotes_index
|
||||
.iter()
|
||||
.filter(|((_, quote_symbol), _)| quote_symbol == symbol)
|
||||
.flat_map(|(_, rows)| rows.iter())
|
||||
.execution_quotes_by_date
|
||||
.values()
|
||||
.filter_map(|rows_by_symbol| rows_by_symbol.get(symbol))
|
||||
.flat_map(|rows| rows.iter())
|
||||
.filter(|quote| intraday_quote_visible(quote, date, active_datetime, include_now))
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
@@ -1846,12 +1885,11 @@ impl DataSet {
|
||||
.collect(),
|
||||
Some("1m") | Some("tick") => {
|
||||
let mut bars = self
|
||||
.execution_quotes_index
|
||||
.execution_quotes_by_date
|
||||
.iter()
|
||||
.filter(|((date, quote_symbol), _)| {
|
||||
quote_symbol == symbol && *date >= start && *date <= end
|
||||
})
|
||||
.flat_map(|(_, rows)| rows.iter())
|
||||
.filter(|(date, _)| **date >= start && **date <= end)
|
||||
.filter_map(|(_, rows_by_symbol)| rows_by_symbol.get(symbol))
|
||||
.flat_map(|rows| rows.iter())
|
||||
.map(intraday_quote_price_bar)
|
||||
.collect::<Vec<_>>();
|
||||
bars.sort_by(|left, right| {
|
||||
@@ -2269,6 +2307,25 @@ impl DataSet {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn benchmark_decision_numeric_values(
|
||||
&self,
|
||||
date: NaiveDate,
|
||||
field: &str,
|
||||
lookback: usize,
|
||||
) -> Vec<f64> {
|
||||
let field = normalize_field(field);
|
||||
match field.as_str() {
|
||||
"open" | "day_open" | "dayopen" | "benchmark_open" => self
|
||||
.benchmark_series_cache
|
||||
.trailing_values_for(date, lookback, PriceField::Open),
|
||||
_ => self.benchmark_series_cache.decision_values_for(
|
||||
date,
|
||||
lookback,
|
||||
PriceField::Close,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn market_open_moving_average(
|
||||
&self,
|
||||
date: NaiveDate,
|
||||
@@ -3279,17 +3336,21 @@ fn build_futures_params_index(
|
||||
|
||||
fn build_execution_quote_index(
|
||||
execution_quotes: Vec<IntradayExecutionQuote>,
|
||||
) -> HashMap<(NaiveDate, String), Vec<IntradayExecutionQuote>> {
|
||||
let mut grouped = HashMap::<(NaiveDate, String), Vec<IntradayExecutionQuote>>::new();
|
||||
) -> HashMap<NaiveDate, HashMap<String, Vec<IntradayExecutionQuote>>> {
|
||||
let mut grouped = HashMap::<NaiveDate, HashMap<String, Vec<IntradayExecutionQuote>>>::new();
|
||||
for quote in execution_quotes {
|
||||
grouped
|
||||
.entry((quote.date, quote.symbol.clone()))
|
||||
.entry(quote.date)
|
||||
.or_default()
|
||||
.entry(quote.symbol.clone())
|
||||
.or_default()
|
||||
.push(quote);
|
||||
}
|
||||
|
||||
for quotes in grouped.values_mut() {
|
||||
quotes.sort_by_key(|quote| quote.timestamp);
|
||||
for rows_by_symbol in grouped.values_mut() {
|
||||
for quotes in rows_by_symbol.values_mut() {
|
||||
quotes.sort_by_key(|quote| quote.timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
grouped
|
||||
|
||||
Reference in New Issue
Block a user