Add instrument history helpers
This commit is contained in:
@@ -802,6 +802,21 @@ impl DataSet {
|
|||||||
instruments
|
instruments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn instruments_history(&self, symbols: &[&str]) -> Vec<&Instrument> {
|
||||||
|
symbols
|
||||||
|
.iter()
|
||||||
|
.filter_map(|symbol| self.instruments.get(*symbol))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active_instruments(&self, date: NaiveDate, symbols: &[&str]) -> Vec<&Instrument> {
|
||||||
|
symbols
|
||||||
|
.iter()
|
||||||
|
.filter_map(|symbol| self.instruments.get(*symbol))
|
||||||
|
.filter(|instrument| instrument.is_active_on(date))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn instrument(&self, symbol: &str) -> Option<&Instrument> {
|
pub fn instrument(&self, symbol: &str) -> Option<&Instrument> {
|
||||||
self.instruments.get(symbol)
|
self.instruments.get(symbol)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,12 @@ impl Instrument {
|
|||||||
self.delisted_at
|
self.delisted_at
|
||||||
.is_some_and(|delisted_at| delisted_at < date)
|
.is_some_and(|delisted_at| delisted_at < date)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_active_on(&self, date: NaiveDate) -> bool {
|
||||||
|
self.listed_at.is_none_or(|listed_at| listed_at <= date)
|
||||||
|
&& !self.is_delisted_before(date)
|
||||||
|
&& !self.status.eq_ignore_ascii_case("inactive")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_status() -> String {
|
fn default_status() -> String {
|
||||||
|
|||||||
@@ -269,6 +269,14 @@ impl StrategyContext<'_> {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn instruments_history(&self, symbols: &[&str]) -> Vec<&Instrument> {
|
||||||
|
self.data.instruments_history(symbols)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active_instruments(&self, symbols: &[&str]) -> Vec<&Instrument> {
|
||||||
|
self.data.active_instruments(self.execution_date, symbols)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn all_instruments(&self) -> Vec<&Instrument> {
|
pub fn all_instruments(&self) -> Vec<&Instrument> {
|
||||||
self.data.all_instruments()
|
self.data.all_instruments()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ pub fn built_in_strategy_manual() -> StrategyAiManual {
|
|||||||
ManualFunction { name: "history_bars".to_string(), signature: "ctx.history_bars(symbol, count, \"1d\" | \"1m\" | \"tick\", \"close\", include_now)".to_string(), detail: "回测内核策略上下文数据 API,返回指定证券最近 N 条数值序列。日线字段支持 open/high/low/close/last/prev_close/volume/upper_limit/lower_limit;分钟或 tick 字段支持 last/bid1/ask1/volume_delta/amount_delta。日线 include_now=false 排除当前交易日;分钟/tick 会按当前 on_bar、on_tick 或调度时刻截断,include_now=false 排除当前 bar/tick,避免未来函数。".to_string() },
|
ManualFunction { name: "history_bars".to_string(), signature: "ctx.history_bars(symbol, count, \"1d\" | \"1m\" | \"tick\", \"close\", include_now)".to_string(), detail: "回测内核策略上下文数据 API,返回指定证券最近 N 条数值序列。日线字段支持 open/high/low/close/last/prev_close/volume/upper_limit/lower_limit;分钟或 tick 字段支持 last/bid1/ask1/volume_delta/amount_delta。日线 include_now=false 排除当前交易日;分钟/tick 会按当前 on_bar、on_tick 或调度时刻截断,include_now=false 排除当前 bar/tick,避免未来函数。".to_string() },
|
||||||
ManualFunction { name: "current_snapshot".to_string(), signature: "ctx.current_snapshot(symbol)".to_string(), detail: "读取当前交易日指定证券的日级快照,可用于获得当日 open/close/last/upper_limit/lower_limit 等字段。".to_string() },
|
ManualFunction { name: "current_snapshot".to_string(), signature: "ctx.current_snapshot(symbol)".to_string(), detail: "读取当前交易日指定证券的日级快照,可用于获得当日 open/close/last/upper_limit/lower_limit 等字段。".to_string() },
|
||||||
ManualFunction { name: "instrument/instruments/all_instruments".to_string(), signature: "ctx.instrument(symbol)".to_string(), detail: "读取证券元数据,包括名称、板块、上市日期、退市日期、最小下单量、整手、最小价位等;all_instruments 按证券代码稳定排序返回全量证券。".to_string() },
|
ManualFunction { name: "instrument/instruments/all_instruments".to_string(), signature: "ctx.instrument(symbol)".to_string(), detail: "读取证券元数据,包括名称、板块、上市日期、退市日期、最小下单量、整手、最小价位等;all_instruments 按证券代码稳定排序返回全量证券。".to_string() },
|
||||||
|
ManualFunction { name: "active_instruments/instruments_history".to_string(), signature: "ctx.active_instruments(&[symbol])".to_string(), detail: "active_instruments 返回当前交易日已上市且未退市的证券;instruments_history 返回给定代码的历史证券记录,包含当前已退市标的,对齐 RQAlpha 的 active_instruments/instruments_history 能力。".to_string() },
|
||||||
ManualFunction { name: "get_trading_dates/get_previous_trading_date/get_next_trading_date".to_string(), signature: "ctx.get_previous_trading_date(date, n)".to_string(), detail: "交易日历 API。get_trading_dates 返回闭区间交易日;previous/next 返回相对某日向前或向后的第 n 个交易日,当前日自身不计入。".to_string() },
|
ManualFunction { name: "get_trading_dates/get_previous_trading_date/get_next_trading_date".to_string(), signature: "ctx.get_previous_trading_date(date, n)".to_string(), detail: "交易日历 API。get_trading_dates 返回闭区间交易日;previous/next 返回相对某日向前或向后的第 n 个交易日,当前日自身不计入。".to_string() },
|
||||||
ManualFunction { name: "is_suspended/is_st_stock".to_string(), signature: "ctx.is_suspended(symbol, count)".to_string(), detail: "读取指定证券截至当前交易日最近 count 个交易日的停牌或 ST 标记,返回 bool 序列,顺序从旧到新;对应 RQAlpha 的 is_suspended/is_st_stock 数据源能力。".to_string() },
|
ManualFunction { name: "is_suspended/is_st_stock".to_string(), signature: "ctx.is_suspended(symbol, count)".to_string(), detail: "读取指定证券截至当前交易日最近 count 个交易日的停牌或 ST 标记,返回 bool 序列,顺序从旧到新;对应 RQAlpha 的 is_suspended/is_st_stock 数据源能力。".to_string() },
|
||||||
ManualFunction { name: "get_price".to_string(), signature: "ctx.get_price(symbol, start_date, end_date, \"1d\" | \"1m\" | \"tick\")".to_string(), detail: "按日期区间读取统一 PriceBar 序列。日线返回 open/high/low/close/last/volume/盘口字段;分钟或 tick 返回按 timestamp 排序的 last/bid1/ask1/volume_delta/amount_delta 映射,便于服务层转成表格或前端明细。".to_string() },
|
ManualFunction { name: "get_price".to_string(), signature: "ctx.get_price(symbol, start_date, end_date, \"1d\" | \"1m\" | \"tick\")".to_string(), detail: "按日期区间读取统一 PriceBar 序列。日线返回 open/high/low/close/last/volume/盘口字段;分钟或 tick 返回按 timestamp 排序的 last/bid1/ask1/volume_delta/amount_delta 映射,便于服务层转成表格或前端明细。".to_string() },
|
||||||
|
|||||||
@@ -436,8 +436,11 @@ impl Strategy for DataApiProbeStrategy {
|
|||||||
let tick_price_count = ctx
|
let tick_price_count = ctx
|
||||||
.get_price("000001.SZ", d(2025, 1, 3), ctx.execution_date, "tick")
|
.get_price("000001.SZ", d(2025, 1, 3), ctx.execution_date, "tick")
|
||||||
.len();
|
.len();
|
||||||
|
let instrument_history_count =
|
||||||
|
ctx.instruments_history(&["000001.SZ", "000002.SZ"]).len();
|
||||||
|
let active_instrument_count = ctx.active_instruments(&["000001.SZ", "000002.SZ"]).len();
|
||||||
self.snapshots.borrow_mut().push(format!(
|
self.snapshots.borrow_mut().push(format!(
|
||||||
"daily={daily_close};previous={previous_close};tick={tick_last};previous_tick={previous_tick_last};current={current_close};instrument={instrument_name};all={};range={trading_date_count};prev={prev_date};next={next_date};suspended={suspended};st={st_flags};price_daily={daily_price_count};price_tick={tick_price_count}",
|
"daily={daily_close};previous={previous_close};tick={tick_last};previous_tick={previous_tick_last};current={current_close};instrument={instrument_name};all={};history={instrument_history_count};active={active_instrument_count};range={trading_date_count};prev={prev_date};next={next_date};suspended={suspended};st={st_flags};price_daily={daily_price_count};price_tick={tick_price_count}",
|
||||||
ctx.all_instruments().len()
|
ctx.all_instruments().len()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -897,15 +900,26 @@ fn strategy_context_exposes_rqalpha_style_data_helpers() {
|
|||||||
let date1 = d(2025, 1, 2);
|
let date1 = d(2025, 1, 2);
|
||||||
let date2 = d(2025, 1, 3);
|
let date2 = d(2025, 1, 3);
|
||||||
let date3 = d(2025, 1, 6);
|
let date3 = d(2025, 1, 6);
|
||||||
let instrument = Instrument {
|
let instruments = vec![
|
||||||
symbol: "000001.SZ".to_string(),
|
Instrument {
|
||||||
name: "Anchor".to_string(),
|
symbol: "000001.SZ".to_string(),
|
||||||
board: "SZ".to_string(),
|
name: "Anchor".to_string(),
|
||||||
round_lot: 100,
|
board: "SZ".to_string(),
|
||||||
listed_at: Some(d(2020, 1, 1)),
|
round_lot: 100,
|
||||||
delisted_at: None,
|
listed_at: Some(d(2020, 1, 1)),
|
||||||
status: "active".to_string(),
|
delisted_at: None,
|
||||||
};
|
status: "active".to_string(),
|
||||||
|
},
|
||||||
|
Instrument {
|
||||||
|
symbol: "000002.SZ".to_string(),
|
||||||
|
name: "Historical".to_string(),
|
||||||
|
board: "SZ".to_string(),
|
||||||
|
round_lot: 100,
|
||||||
|
listed_at: Some(d(2020, 1, 1)),
|
||||||
|
delisted_at: Some(date2),
|
||||||
|
status: "active".to_string(),
|
||||||
|
},
|
||||||
|
];
|
||||||
let market = [
|
let market = [
|
||||||
(date1, 10.0, 10.0, 10.0, 100_000),
|
(date1, 10.0, 10.0, 10.0, 100_000),
|
||||||
(date2, 10.1, 10.1, 10.0, 110_000),
|
(date2, 10.1, 10.1, 10.0, 110_000),
|
||||||
@@ -1026,7 +1040,7 @@ fn strategy_context_exposes_rqalpha_style_data_helpers() {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
let data = DataSet::from_components_with_actions_and_quotes(
|
let data = DataSet::from_components_with_actions_and_quotes(
|
||||||
vec![instrument],
|
instruments,
|
||||||
market,
|
market,
|
||||||
factors,
|
factors,
|
||||||
candidates,
|
candidates,
|
||||||
@@ -1065,7 +1079,7 @@ fn strategy_context_exposes_rqalpha_style_data_helpers() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
snapshots.borrow().as_slice(),
|
snapshots.borrow().as_slice(),
|
||||||
[
|
[
|
||||||
"daily=10.10,10.20;previous=10.00,10.10;tick=10.15,10.25;previous_tick=10.15;current=10.20;instrument=Anchor;all=1;range=3;prev=2025-01-03;next=2025-01-06;suspended=0,1,0;st=0,1,0;price_daily=2;price_tick=3"
|
"daily=10.10,10.20;previous=10.00,10.10;tick=10.15,10.25;previous_tick=10.15;current=10.20;instrument=Anchor;all=2;history=2;active=1;range=3;prev=2025-01-03;next=2025-01-06;suspended=0,1,0;st=0,1,0;price_daily=2;price_tick=3"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ current alignment pass.
|
|||||||
- [x] `is_suspended`
|
- [x] `is_suspended`
|
||||||
- [x] `is_st_stock`
|
- [x] `is_st_stock`
|
||||||
- [x] `get_price` style date-range tabular API
|
- [x] `get_price` style date-range tabular API
|
||||||
- [ ] `instruments_history`
|
- [x] `active_instruments`
|
||||||
|
- [x] `instruments_history`
|
||||||
|
|
||||||
## Execution Order
|
## Execution Order
|
||||||
|
|
||||||
@@ -76,6 +77,5 @@ current alignment pass.
|
|||||||
|
|
||||||
## Current Step
|
## Current Step
|
||||||
|
|
||||||
Active implementation target: continue stock data-source API parity after
|
Active implementation target: continue parity audit for remaining account and
|
||||||
covering suspended/ST historical flags and `get_price` style date-range
|
order object APIs after the core stock data-source APIs are covered.
|
||||||
queries; next larger gap is instruments history.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user