feat(strategy): 策略可读取指数/ETF日K (market_data 模块 + 白名单 + 测试) - #207
Open
shuolol wants to merge 1 commit into
Open
Conversation
Custom/AI 策略此前被沙箱隔离, filter_history(df, params) 只能拿到个股历史窗口, 无法读取指数K线, 也就做不了「大盘指数 MACD 死叉」这类市场级过滤。 本改动新增框架侧受信模块 backend/app/strategy/market_data.py, 暴露只读纯函数: - get_index_daily / get_etf_daily: 读取指数/ETF 日K(含技术指标, 支持列下推) - get_daily: 按 repo.resolve_asset_type 自动分派(指数/ETF/股票) - list_index_symbols: 枚举已收录指数 模块线程安全懒加载 repo (DataStore() 默认 settings.data_dir, 与 main.py 同源), 未知 symbol/缺数据返回空 DataFrame 不抛; 不向策略暴露文件访问或写能力。 ai_generator._ALLOWED_IMPORT_MODULES 放行 "app.strategy.market_data", 使 AI 生成与磁盘 Custom 策略均可 import 该模块; 其余模块/危险调用照旧拦截。 附 9 项框架级测试: 白名单放行/拦截、注入 fake repo 后委托与日期规范化、 按资产类型分派、坏 symbol/缺数据返回空、list_index_symbols。对既有策略零影响。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题与复现
Custom/AI 策略被沙箱隔离,
filter_history(df, params)只能拿到个股历史窗口,无法读取指数K线,因此做不了「大盘指数 MACD 死叉」这类市场级过滤。复现:在任意策略内from app.strategy.market_data import get_index_daily会被AIStrategyGenerator._validate_safety拒绝。根因
策略 import 白名单(
ai_generator._ALLOWED_IMPORT_MODULES)仅放行polars / numpy / app.backtest.matrix / datetime,框架侧没有提供任何可达指数/ETF 日K的只读入口。解决方案
新增框架侧受信模块
backend/app/strategy/market_data.py,暴露只读纯函数:get_index_daily(symbol, start, end, columns)/get_etf_daily(...):读取指数/ETF 日K(含技术指标,支持列下推)。get_daily(symbol, ...):按repo.resolve_asset_type自动分派(指数/ETF/股票)。list_index_symbols():枚举已收录指数。模块线程安全懒加载 repo(
DataStore()默认settings.data_dir,与main.py同源);未知 symbol/缺数据返回空 DataFrame 不抛;不向策略暴露文件访问或写能力。_ALLOWED_IMPORT_MODULES放行精确的"app.strategy.market_data"(非裸app,不会连带放行其它app.*),AST 检查对其它模块/危险调用照旧拦截。对既有策略零影响(纯新增模块 + 白名单一行)。兼容性
filter_history签名、StrategyDataContext、面板构建,不影响任何现有策略。KlineRepository通道;ETF 无独立数据时回退旧版 index-enriched(与get_etf_daily现状一致)。性能
非热路径。
get_index_daily仅在策略显式调用时触发一次指数 enriched 查询;模块缓存 repo 实例(懒加载一次),不缓存查询结果,v1 足够。验证结果
uv run --frozen --extra dev pytest tests/test_strategy_market_data.py -q→ 9 passeduv run --frozen --extra dev ruff check app/strategy/market_data.py tests/test_strategy_market_data.py→ All checks passedAIStrategyGenerator._validate_safety('from app.strategy.market_data import get_index_daily')→ 通过get_index_daily('000001.SH')返回 248 行 enriched(含 macd_dif/dea、ma5/10/20/30);list_index_symbols()返回 610 个指数;空串/None/未知 symbol 均返回空、不抛。界面证据
无前端/UI 改动。
风险与回滚
market_data.py+ai_generator.py白名单一行回退);对既有策略无影响。