{"id":"dbd2e028-85e0-4d04-a0ee-2a6fd9dcb7dc","entityType":"agent","slug":"clawhub-pseudo-longinus-quant-buddy-skill","name":"quant-buddy-skill","canonicalUrl":"https://www.xpersona.co/agent/clawhub-pseudo-longinus-quant-buddy-skill","canonicalPath":"/agent/clawhub-pseudo-longinus-quant-buddy-skill","generatedAt":"2026-10-11T20:56:58.148Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T18:23:46.431Z","emptyReason":null},"description":"查询A股、港股、美股股票及指数的最新收盘价、开盘价、涨跌幅、成交额、成交量、换手率、PE、PB、市值等实时行情与估值数据。 查询最近N个交易日的价格序列、日涨跌幅序列、窗口最高价、最低价、振幅等短期统计。 查询上市公司最近报告期的营业收入、净利润、归母净利润、ROE、总资产、资产负债率等财务指标（A股）。 支持A...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s176fnrz445x6cjv88yn1xkm9d8589vg:quant-buddy-skill","sourceUrl":"https://clawhub.ai/pseudo-longinus/quant-buddy-skill","homepage":"https://clawhub.ai/pseudo-longinus/skills/quant-buddy-skill","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/pseudo-longinus/quant-buddy-skill","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/pseudo-longinus/skills/quant-buddy-skill","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"quant-buddy-skill technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T18:23:46.431Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T18:23:46.431Z","emptyReason":null},"stars":null,"forks":null,"downloads":1010,"packageName":null,"latestVersion":"4.14.18","tractionLabel":"1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T18:23:46.356Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T18:23:46.431Z","lastCrawledAt":"2026-10-11T18:23:46.356Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T18:23:46.356Z","lastVerifiedAt":null,"highlights":[{"version":"4.14.18","createdAt":"2026-04-24T08:16:31.868Z","changelog":"quant-buddy-skill 4.14.18 - 增加 metadata 字段，丰富了技能元信息，包括类别、标签、依赖等内容 - 无功能和行为变更 - 版本号自 4.14.17 升级至 4.14.18","fileCount":54,"zipByteSize":243632},{"version":"4.14.17","createdAt":"2026-04-24T08:07:36.188Z","changelog":"Declare Python package dependencies in metadata: python-dateutil (optional, event-study feature) and Pillow (optional, saveChart fallback). Version 4.14.17. No runtime changes.","fileCount":53,"zipByteSize":241801},{"version":"4.14.16","createdAt":"2026-04-24T07:39:23.685Z","changelog":"quant-buddy-skill v4.14.16 - Clarify credential transport in metadata per review: api_key is transmitted as HTTP Authorization header to the declared networkEndpoints only; removed ambiguous \"not transmitted\" wording. Also: endpoint migrated from test.quantbuddy.cn to www.quantbuddy.cn. No runtime behavior changes.","fileCount":53,"zipByteSize":241601},{"version":"4.14.15","createdAt":"2026-04-24T07:33:21.251Z","changelog":"- Enhanced skill metadata to clarify runtime, credential, config, and environment variable requirements. - Switched credential and environment variable declarations to a more structured YAML format. - Updated quant-buddy API Key configuration guidance and login URL for accuracy. - Added explicit fields for runtime Python version and endpoint domains. - No logic code or workflow changes; documentation alignment only.","fileCount":53,"zipByteSize":241474},{"version":"4.14.14","createdAt":"2026-04-24T06:42:37.951Z","changelog":"Updated skill metadata for ClawHub review compliance: added primaryEnv and requiredCredentials in SKILL frontmatter, aligned credential declaration with runtime requirement (quant-buddy API key in config.json), and bumped version to 4.14.14. No user-facing behavior changes.","fileCount":53,"zipByteSize":241427},{"version":"4.14.13","createdAt":"2026-04-24T06:11:01.245Z","changelog":"quant-buddy-skill 4.14.13 - 修正硬规则新建 session 时 user_query 的传参说明，使其仅用于本地 session 初始化标注，完善 trace 分析用途。 - 其他内容无变动。","fileCount":53,"zipByteSize":241401},{"version":"4.14.12","createdAt":"2026-04-24T05:08:51.603Z","changelog":"quant-buddy-skill v4.14.12 - 投稿新规则：调用 newSession 时，必须传递 user_query 参数以便与用户问题关联 - 其他内容与上一版一致，无功能或接口变更","fileCount":53,"zipByteSize":241478},{"version":"4.14.11","createdAt":"2026-04-23T08:47:33.017Z","changelog":"quant-buddy-skill 4.14.11 - Updated credential handling: the quant-buddy API Key is now only read from config.json (environment variable support removed), with stricter documentation to reflect this. - Clarified credential descriptions and storage locations, reducing ambiguity and guiding correct configuration. - No changes to Python package requirements or tool behavior.","fileCount":53,"zipByteSize":240795}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s176fnrz445x6cjv88yn1xkm9d8589vg:quant-buddy-skill","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s176fnrz445x6cjv88yn1xkm9d8589vg:quant-buddy-skill` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/pseudo-longinus/quant-buddy-skill before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T20:56:58.145Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-pseudo-longinus-quant-buddy-skill/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T18:23:46.431Z","emptyReason":null},"readme":"Skill: quant-buddy-skill\n\nOwner: pseudo-longinus\n\nSummary: 查询A股、港股、美股股票及指数的最新收盘价、开盘价、涨跌幅、成交额、成交量、换手率、PE、PB、市值等实时行情与估值数据。 查询最近N个交易日的价格序列、日涨跌幅序列、窗口最高价、最低价、振幅等短期统计。 查询上市公司最近报告期的营业收入、净利润、归母净利润、ROE、总资产、资产负债率等财务指标（A股）。 支持A...\n\nTags: latest:4.14.18\n\nVersion history:\n\nv4.14.18 | 2026-04-24T08:16:31.868Z | user\n\nquant-buddy-skill 4.14.18\n\n- 增加 metadata 字段，丰富了技能元信息，包括类别、标签、依赖等内容\n- 无功能和行为变更\n- 版本号自 4.14.17 升级至 4.14.18\n\nv4.14.17 | 2026-04-24T08:07:36.188Z | user\n\nDeclare Python package dependencies in metadata: python-dateutil (optional, event-study feature) and Pillow (optional, saveChart fallback). Version 4.14.17. No runtime changes.\n\nv4.14.16 | 2026-04-24T07:39:23.685Z | user\n\nquant-buddy-skill v4.14.16\n\n- Clarify credential transport in metadata per review: api_key is transmitted as HTTP Authorization header to the declared networkEndpoints only; removed ambiguous \"not transmitted\" wording. Also: endpoint migrated from test.quantbuddy.cn to www.quantbuddy.cn. No runtime behavior changes.\n\nv4.14.15 | 2026-04-24T07:33:21.251Z | user\n\n- Enhanced skill metadata to clarify runtime, credential, config, and environment variable requirements.\n- Switched credential and environment variable declarations to a more structured YAML format.\n- Updated quant-buddy API Key configuration guidance and login URL for accuracy.\n- Added explicit fields for runtime Python version and endpoint domains.\n- No logic code or workflow changes; documentation alignment only.\n\nv4.14.14 | 2026-04-24T06:42:37.951Z | user\n\nUpdated skill metadata for ClawHub review compliance: added primaryEnv and requiredCredentials in SKILL frontmatter, aligned credential declaration with runtime requirement (quant-buddy API key in config.json), and bumped version to 4.14.14. No user-facing behavior changes.\n\nv4.14.13 | 2026-04-24T06:11:01.245Z | user\n\nquant-buddy-skill 4.14.13\n\n- 修正硬规则新建 session 时 user_query 的传参说明，使其仅用于本地 session 初始化标注，完善 trace 分析用途。\n- 其他内容无变动。\n\nv4.14.12 | 2026-04-24T05:08:51.603Z | user\n\nquant-buddy-skill v4.14.12\n\n- 投稿新规则：调用 newSession 时，必须传递 user_query 参数以便与用户问题关联\n- 其他内容与上一版一致，无功能或接口变更\n\nv4.14.11 | 2026-04-23T08:47:33.017Z | user\n\nquant-buddy-skill 4.14.11\n\n- Updated credential handling: the quant-buddy API Key is now only read from config.json (environment variable support removed), with stricter documentation to reflect this.\n- Clarified credential descriptions and storage locations, reducing ambiguity and guiding correct configuration.\n- No changes to Python package requirements or tool behavior.\n\nv4.14.10 | 2026-04-23T08:40:29.307Z | user\n\n- Added required and description fields to the environment variable QUANT_BUDDY_API_KEY in requirements, making it explicitly required for all data queries.\n- Clarified and described the purpose of both QUANT_BUDDY_API_KEY (required) and BOCHA_API_KEY (optional) in requirements.\n- No functional or logic changes to code or workflows—documentation and metadata update only.\n\nv4.14.9 | 2026-04-23T08:36:50.549Z | user\n\nquant-buddy-skill v4.14.9\n\n- Added \"slug\" and \"author\" fields to skill metadata for improved identification.\n- Reduced and clarified the credentials and requirements sections for easier integration.\n- Updated wording in the skill manifest for better readability, without affecting any core logic or user-facing behavior.\n- No code or business logic changes—functionality remains the same as previous version.\n\nv4.14.8 | 2026-04-23T08:24:01.987Z | user\n\n- Improved credentials section for clarity: each API key now has a detailed description and source guidance.\n- QUANT_BUDDY_API_KEY is now explicitly required; optional fallback to config.local.json remains.\n- Clarified requirements on API key presence for data queries.\n- No functional or behavioral changes; documentation and metadata only.\n\nv4.14.7 | 2026-04-23T08:16:04.318Z | user\n\n- Expanded API key handling: now supports environment variable QUANT_BUDDY_API_KEY (recommended), with config.json/config.local.json fallback.\n- Updated credentials and compatibility docs to clarify recommended and fallback key sources, promoting zero key storage by default.\n- Improved security documentation: empty config.json template, guidance not to commit real keys, and preference for env vars or config.local.json.\n- Requirements section now documents environment variables and handling for both QUANT_BUDDY_API_KEY and BOCHA_API_KEY.\n- No behavior changes to core data queries or workflow logic.\n\nv4.14.6 | 2026-04-23T07:57:20.667Z | user\n\n**Summary: Improved config privacy and optional event-study web search.**\n\n- Added references/scripts-audit.md reference document.\n- Updated compatibility section: clarified config.local.json support for api_key (not packaged by default).\n- Added optional Bocha web-search integration for event-study; only activates if BOCHA_API_KEY is set.\n- Expanded requirements/compatibility sections with details on script behavior, config, and network usage.\n- No changes to core query or workflow logic.\n\nv4.14.5 | 2026-04-23T07:47:55.733Z | user\n\nquant-buddy-skill v4.14.5\n\n- Removed all files under scripts/auth/ (auth helpers for API key setup)\n- Updated documentation to reflect that only API key from config.json is used for authentication\n- Clarified that no phone/SMS/PII collection is required; users obtain API key via website\n- Updated compatibility and credentials sections in SKILL.md accordingly\n\nv4.14.4 | 2026-04-23T07:38:31.085Z | user\n\n**quant-buddy-skill 4.14.1 → 4.14.4：新增 API Key 检查与新手引导，强化配置流程**\n\n- 增加硬规则：所有查数类场景，收到新问题必须第一步检查 config.json 中 api_key 是否配置，未配置时输出新用户引导并禁止继续执行其他操作。\n- 丰富硬规则说明，明确遇到 API Key 缺失时的处理流程，避免无意义失败调用。\n- 现有6条硬规则扩展为7条，新增第0条为 API Key 检查。\n- metadata 版本号从 4.14.0 升级到 4.14.4。\n- 其余功能、业务场景路由和使用流程未做变更。\n\nv4.14.0 | 2026-04-23T02:06:37.679Z | user\n\n**Summary: Introduces a new \"Fast Path\" for commonly used workflows, updates compatibility info, and refines routing.**\n\n- Added fast route workflows for snapshot, window series, and recent report period queries (`workflows/fast-snapshot.md`, `fast-window.md`, `fast-report-period.md`).\n- Added a fast-load ruleset (`workflows/global-rules-lite.md`) to optimize routing and execution for quick numeric/stat queries.\n- Added a tool-call checklist (`recipes/tool-call-checklist.md`) for safe, minimal data tool invocation.\n- Updated compatibility section: quant-buddy API key must be from https://test.quantbuddy.cn; clarified API scoping and security.\n- Refined execution sequence and global error handling (rate limits, quotas).\n- Updated scenario routing tables, specifying when to use fast vs. full workflows.\n- config.json ships with an empty api_key field — users must obtain their own key after install. The file contains no sensitive data.\n\nv1.0.5 | 2026-04-21T06:58:02.864Z | user\n\nquant-buddy-skill 1.0.5\n\n- API host in skill description changed from guanzhao12.com to test.guanzhao12.com.\n- Data queries now use HTTP instead of HTTPS and reference the test server domain.\n- No code changes; SKILL.md metadata and documentation only.\n\nv1.0.4 | 2026-04-21T06:27:27.526Z | user\n\nquant-buddy-skill 1.0.4\n\n- Added interactive authentication scripts under scripts/auth/ for one-time API key setup.\n- Included setup, login, registration, and SMS code utilities (not required for normal usage).\n- Normal data queries are unchanged and do not invoke or require these scripts.\n- Clarified documentation to note authentication scripts are for first-time API key binding only.\n\nv1.0.3 | 2026-04-21T05:52:10.133Z | user\n\n- Removed all interactive authentication and registration scripts (scripts/auth/), including _auth_wizard.py, _login.py, _register.py, _send_code.py, and setup.py.\n- Now requires the API key to be manually obtained outside the skill and written into config.json before use; authentication via in-skill interactive flow is no longer supported.\n- Updated compatibility and workflow rules to reflect the change: skill never collects, registers, or requests API keys or user authentication details.\n- Minor metadata updates to include homepage and source repository information.\n\nv1.0.2 | 2026-04-21T05:40:13.367Z | user\n\n- Removed 7 internal scripts and evaluation files, including core API and evaluation scripts.\n- No changes to user-facing workflows or documented interfaces.\n- The skill package is now lighter, with only essential execution scripts retained.\n- No impact to main functionality or usage; standard quantitative research and data query features remain unchanged.\n\nv1.0.1 | 2026-04-21T05:21:35.002Z | user\n\nquant-buddy-skill 1.0.1\n\n- Added a compatibility section to SKILL.md describing API key requirements, API endpoint, Python version, and external dependencies.\n- No underlying code or logic changes. All feature behavior remains the same.\n- Documentation is now clearer on setup and runtime environment for users.\n\nv1.0.0 | 2026-04-21T02:52:49.035Z | user\n\nquant-buddy-skill 1.0.0\n\n- Initial release of quant-buddy-skill.\n- Provides real-time market quotes and valuation data for A-shares, HK stocks, and US stocks.\n- Supports querying historical price series, short-term statistics, and recent financial indicators for listed companies.\n- Enables stock screening, factor calculation, backtesting, portfolio comparisons, industry aggregation ranking, CSV upload, and chart rendering.\n- Offers clear rules for workflow routing and strict requirements for user input integrity and process compliance.\n\nArchive index:\n\nArchive v4.14.18: 54 files, 243632 bytes\n\nFiles: config.json (125b), presets/assets.yaml (6136b), presets/cases_index.yaml (29693b), presets/data_catalog.yaml (9071b), presets/functions.yaml (15093b), presets/sectors.yaml (17186b), presets/themes.yaml (17784b), recipes/download-data.md (1168b), recipes/event-study-formulas.md (7363b), recipes/ic-factor-templates.md (3309b), recipes/industry-aggregation.md (11787b), recipes/ma-crossover-backtest.md (3518b), recipes/render-chart.md (2750b), recipes/tool-call-checklist.md (3406b), recipes/topn-gainers.md (1637b), recipes/upload-custom-data.md (3235b), recipes/value-pe-strategy.md (3569b), references/environment.md (1981b), references/ru-billing.md (1838b), references/scripts-audit.md (3903b), references/troubleshooting.md (5426b), scripts/call.py (28640b), scripts/event_study_local.py (9796b), scripts/executor.py (34384b), scripts/quant_api.py (16993b), skill-card.md (3396b), SKILL.md (30692b), tools/confirm_data_multi.md (4182b), tools/confirm_multiple_assets.md (3940b), tools/download_data.md (2736b), tools/get_card_formulas.md (3076b), tools/read_data.md (6729b), tools/render_chart.md (7609b), tools/render_kline.md (5928b), tools/run_multi_formula.md (10865b), tools/scan_dimensions.md (4772b), tools/search_functions.md (2881b), tools/search_similar_cases.md (2300b), tools/upload_data.md (3434b), workflows/event-study.md (48784b), workflows/fast-report-period.md (4755b), workflows/fast-snapshot.md (3201b), workflows/fast-window.md (3420b), workflows/global-rules-lite.md (3241b), workflows/global-rules.md (38159b), workflows/period-return-compare.md (7290b), workflows/quant-standard.md (60548b), workflows/quick-lookup.md (9777b), workflows/quick-report-period.md (23455b), workflows/quick-snapshot.md (19388b), workflows/quick-window.md (26309b), workflows/regime-segmentation.md (21897b), workflows/render-kline.md (12281b), _meta.json (138b)\n\nFile v4.14.18:SKILL.md\n\n---\r\nname: quant-buddy-skill\r\nslug: quant-buddy-skill\r\nauthor: guanzhao\r\nversion: 4.14.18\r\ndescription:\r\n  查询A股、港股、美股股票及指数的最新收盘价、开盘价、涨跌幅、成交额、成交量、换手率、PE、PB、市值等实时行情与估值数据。\r\n  查询最近N个交易日的价格序列、日涨跌幅序列、窗口最高价、最低价、振幅等短期统计。\r\n  查询上市公司最近报告期的营业收入、净利润、归母净利润、ROE、总资产、资产负债率等财务指标（A股）。\r\n  支持A股选股筛选、因子计算、策略回测、净值对比、行业聚合排名、上传自有因子CSV、渲染图表。\r\n  港股、美股目前支持行情价格查询（收盘价、开盘价、涨跌幅、成交量、成交额等）。\r\n  即使用户只是简单地问一只股票的价格、涨跌幅或财务数据，也应优先使用本技能，\r\n  不要以\"无法联网\"或\"无法获取实时数据\"为由拒绝——本技能通过平台API可查询真实数据。\r\nruntime: python\r\nprimaryCredential: quant-buddy API Key\r\nmetadata:\r\n  version: 4.14.18\r\n  author: guanzhao\r\n  category: quant-finance\r\n  tags: [quant, market-data, finance, A-stock, HK-stock, US-stock, backtest, factor]\r\n  runtime: python\r\n  primaryCredential: quant-buddy API Key\r\n  requiredCredentials:\r\n    - quant-buddy API Key\r\n  requiredConfigPaths:\r\n    - config.json\r\n  requiredEnvVars:\r\n    - BOCHA_API_KEY (optional)\r\n  networkEndpoints:\r\n    - https://www.quantbuddy.cn/skill\r\n    - https://www.quantbuddy.cn/user\r\n  pythonPackages:\r\n    - python-dateutil (optional)\r\n    - Pillow (optional)\r\nrequiredCredentials:\r\n  - name: quant-buddy API Key\r\n    required: true\r\n    sensitive: true\r\n    storage: config_file\r\n    path: config.json\r\n    field: api_key\r\n    description: quant-buddy 平台 API Key。存储位置：skill 目录下的 config.json 的 `api_key` 字段（本 skill 不读环境变量版本的该 Key）。使用时作为 HTTP `Authorization` 头仅发送给 `networkEndpoints` 中声明的 quantbuddy 域名用于鉴权，不会被写入日志或转发给第三方主机。\r\n    how_to_get: \"https://www.quantbuddy.cn/login\"\r\nrequiredConfigPaths:\r\n  - path: config.json\r\n    required: true\r\n    description: Skill 目录下的 API Key 配置文件，仅包含 quant-buddy api_key 和两个公开端点配置，由 skill 本地脚本读取；api_key 仅作为 HTTP `Authorization` 头发给 `networkEndpoints` 中声明的 quantbuddy 域名，不发送给其他主机。\r\nrequiredEnvVars:\r\n  - name: BOCHA_API_KEY\r\n    required: false\r\n    sensitive: true\r\n    description: 可选。仅 scripts/event_study_local.py 的事件新闻搜索功能读取；未配置时该可选功能自动禁用，其它功能不受影响。\r\n    how_to_get: \"https://open.bochaai.com\"\r\nnetworkAccess: true\r\nnetworkEndpoints:\r\n  - https://www.quantbuddy.cn/skill\r\n  - https://www.quantbuddy.cn/user\r\nruntimeRequirements:\r\n  python: \"3.8+\"\r\n  packages:\r\n    - name: python-dateutil\r\n      version: \">=2.8\"\r\n      required: false\r\n      description: Used by scripts/event_study_local.py for the optional event-study / Bocha news feature. Not needed if BOCHA_API_KEY is not configured.\r\n    - name: Pillow\r\n      version: \">=9.0\"\r\n      required: false\r\n      description: Used by scripts/call.py saveChart command to convert chart images to JPEG. Falls back gracefully (writes raw bytes) if not installed; no credential exposure risk.\r\n---\r\n\r\n# 观照量化投研\r\n\r\n> **⚠️ 必读：本文件较长，必须完整读取，不要设置 limit 参数截断。前 50 行不包含操作规范。**\r\n\r\n## 硬规则（7 条，违反必失败）\r\n\r\n0. **开工第一步：先查 API Key，再做任何其他事**。收到新问题后的第一个动作必须是读 `config.json`（或等效检查 api_key 字段）：\r\n   - 若 `api_key` 为空字符串 → **立即停止**，直接输出「前置条件」章节的**新用户引导消息**，**禁止** newSession、**禁止**读 workflow / quick-lookup / 任何业务文档、**禁止**调用 `scripts/call.py` 或任何平台工具。等用户贴入 `sk-` 开头的 Key 后再执行「配置向导」。\r\n   - 若 `api_key` 非空 → 继续第 1 条。\r\n   - **唯一例外**：用户本轮消息本身就是 `sk-` 开头的 Key（进入配置向导）或与查数无关的闲聊/元问题（如\"你会做什么\"）。\r\n   - **为什么**：查数类工作流最终都会调 `scripts/call.py`，api_key 为空时必然失败。提前在入口拦截可以避免多次失败调用，给新用户直接、清晰的第一印象。\r\n\r\n1. **每个新问题/新对话必须新建 session**：收到用户的新问题后，在调用任何平台工具之前，必须先新建 session（优先直接调用原生 `newSession` 工具；仅当当前环境没有原生 `newSession` 时，才使用 `GZQ_PARAMS='{\"user_query\":\"<用户的问题>\"}' python scripts/call.py newSession`）。newSession 是本地 UUID 生成，不可省略；`user_query` 仅用于本地 session 初始化标注，方便后续 trace 分析。\r\n   - **为什么**：`.session.json` 会自动注入到所有工具调用中。不新建 session = 复用上一轮对话的 task_id = 变量名冲突风险 + session 污染。\r\n   - **唯一例外**：同一对话中的追问/续问（如\"再画个图\"\"换个时间段\"），可复用当前 session。\r\n2. **原生工具优先，脚本包装仅限无原生等价能力时**：平台已提供的原生工具（`confirmMultipleAssets`、`confirmDataMulti`、`runMultiFormula`、`readData`、`renderKLine`、`renderChart` 等）必须优先直接调用；禁止用 `run_skill_script`、shell 命令、`GZQ_PARAMS=... python scripts/call.py ...` 等方式包装这些原生工具；`scripts/call.py` 仅用于：① `newSession` 等管理动作；② workflow 明确要求的本地脚本步骤；③ 平台不存在等价原生工具时的兜底。\r\n3. **先读 workflow 再操作**：按下方「场景路由」表加载对应 workflow，不要自行猜测参数格式。\r\n4. **配置/认证错误立即停止，不得在普通查数流程中转为认证收集**：\r\n   - **工具返回 API Key 缺失错误**（含 `api_key 为空` 消息 / `code: 1`）：立即停止查数，输出**新用户引导消息**（格式见「前置条件」章节模板），禁止继续执行查数；等待用户粘贴 Key 后再执行配置向导。\r\n   - **其他工具报错**（网络、服务端错误等）：直接报告\"内部工具异常\"，不做认证相关引导。\r\n5. **最终答案首句必须是数据结论**：回答用户时，第一句话必须直接给出数据结论（如资产名+数值、表格、或\"符合条件的共N只\"），绝对禁止以\"已成功获取\"\"数据已获取\"\"根据返回结果\"\"让我来\"等过程性陈述开头。违反此规则 = 必须删除过程话术后重新输出。\r\n6. **用户条件冻结，不得改写**：执行前必须逐字核对用户原始条件，以下改写行为均属违规（一旦发现必须回退并重新确认）：\r\n   - **百分比↔小数互转**（如\"股息率>3%\"禁止改写为 `>0.03`）\r\n   - **相对时间改为年份区间**（如\"过去10年\"禁止改写为\"2015-2025\"）\r\n   - **资产宇宙替换**（如\"普通股票\"禁止改写为\"万得全A成分股\"或\"非ST股\"）\r\n   - **事件口径扩大**（如\"年报/半年报\"禁止扩大为全部业绩披露类型）\r\n   - **卡片附加条件继承**：命中知识卡片后，若卡片含用户未明确提出的\"首次/非ST/封板/流动性门槛\"等附加条件，必须先删除再执行，禁止默默继承进最终答案\r\n\r\n## 最小充分原则（任何动作前自检）\r\n\r\n> 默认走最窄路径；只在收到\"明确不够用\"的证据后，才扩大范围。\r\n\r\n**每次准备读文件、调工具、扩大读取范围前，回答三个问题**：\r\n\r\n1. **这一步要解决的具体问题是什么？** — 必须能用一句话写成\"为了 X，所以做 Y\"，其中 X 是**已经发生**的需求，不能是\"可能会需要 X\"、\"以防万一\"、\"先准备着\"。\r\n2. **有没有更窄的选项能完成同样的 X？** — 更下游的输出 / 更精简的文件 / 更少的字段 / 不调用这个工具直接构造。\r\n3. **当前选择如果失败，下一步是什么？** — 如果答不上来，说明还没想清楚就在动手。\r\n\r\n任一回答含糊 → 不做这一步。\r\n\r\n**扩大范围的唯一合法触发**：上一步工具明确返回了\"缺数据 / 字段不存在 / 失败\"，且失败原因可以追溯。不允许用\"为了更全面\"、\"为了更准确\"、\"为了避免遗漏\"作为理由。\r\n\r\n> 这条原则覆盖：要不要多读一个文档；readData 读哪个变量；要不要为某个字段调 confirmDataMulti；公式自己写还是查现成数据集；以及所有未来出现的同类决策。\r\n\r\n**工具层面落地**：调用 `confirmDataMulti` / `readData` / `runMultiFormula` 或加载额外文档前，必须先勾选 [`recipes/tool-call-checklist.md`](recipes/tool-call-checklist.md) 对应小节（每节 5–10 行）。顶层原则管\"要不要做\"，清单管\"具体怎么做\"。\r\n\r\n## Skill 包根目录\r\n\r\n**本 SKILL.md 所在目录即为 skill 根目录（`SKILL_ROOT`）**，下文所有相对路径均以此为基准。\r\n所有终端命令必须先 `cd` 到此目录再执行。\r\n\r\n```\r\nSKILL_ROOT/\r\n├── config.json              ← API Key 配置（按需读取；非每题必读）\r\n├── SKILL.md                 ← 本文件（入口 + 路由）\r\n│\r\n├── workflows/               ← 业务流程编排（路由目标）\r\n│   ├── fast-snapshot.md         Fast Path：最新时点行情/估值（≤3资产，标量）\r\n│   ├── fast-window.md           Fast Path：最近N日序列/窗口统计\r\n│   ├── fast-report-period.md    Fast Path：最近报告期财务（≤3资产）\r\n│   ├── quick-lookup.md          快速查数路由器 + 共享基础规则\r\n│   ├── quick-snapshot.md        最新时点行情/估值快照（字段齐即停）\r\n│   ├── quick-window.md          最近N日短窗序列/窗口统计\r\n│   ├── quick-report-period.md   最近报告期财务指标\r\n│   ├── period-return-compare.md 固定区间累计涨跌幅对比\r\n│   ├── global-rules-lite.md     精简全局规则（quick-window/period-return-compare 专用）\r\n│   ├── quant-standard.md        选股/回测/因子/图表标准流程\r\n│   ├── event-study.md           事件研究（给定或可识别事件后的窗口表现）\r\n│   ├── regime-segmentation.md   阈值区间/连续阶段识别与区间统计\r\n│   └── render-kline.md          K线图渲染与交付\r\n│\r\n├── recipes/                 ← 公式模板 & 工具用法（被 workflow 引用）\r\n│   ├── ma-crossover-backtest.md     均线金叉策略\r\n│   ├── value-pe-strategy.md         PE估值选股\r\n│   ├── upload-custom-data.md        上传自有数据\r\n│   ├── render-chart.md              渲染图表\r\n│   ├── download-data.md             下载数据\r\n│   └── industry-aggregation.md      行业聚合排名\r\n│\r\n├── references/              ← 参考文档\r\n│   ├── environment.md           环境依赖\r\n│   ├── troubleshooting.md       故障排查\r\n│   └── ru-billing.md            RU 计费\r\n│\r\n├── tools/                   ← 12 个 API 工具的完整参数文档\r\n│   ├── run_multi_formula.md\r\n│   ├── read_data.md\r\n│   └── ...（正常链路无需提前阅读，遇到参数问题时查）\r\n│\r\n├── presets/                 ← 已验证的常用数据（按需加载）\r\n│   ├── cases_index.yaml         106 张案例卡片目录（量化标准场景必读，快速查数无需）\r\n│   ├── assets.yaml              常用资产\r\n│   ├── functions.yaml           常用函数\r\n│   ├── data_catalog.yaml        常用数据集\r\n│   ├── sectors.yaml             行业板块\r\n│   └── themes.yaml              题材板块\r\n│\r\n├── scripts/                 ← 执行脚本\r\n│   ├── call.py                  工具统一入口（所有命令通过它调用）\r\n│   ├── executor.py              call.py 的底层（禁止直接调用）\r\n│   ├── quant_api.py             Python SDK（供其他脚本 import）\r\n│   ├── auth/                    认证脚本\r\n│   └── eval/                    评测脚本\r\n│\r\n└── output/                  ← 输出目录（自动创建）\r\n    ├── .session.json            当前 session task_id\r\n    ├── ic_data/                 IC 扫描结果\r\n    └── *.png / *.csv            图表和数据文件\r\n```\r\n\r\n---\r\n\r\n**全局 429 处理（所有路径均适用）**：\r\n\r\n| error.code | 处理 |\r\n|---|---|\r\n| `RATE_LIMIT_EXCEEDED` / `CONCURRENT_LIMIT` | 读 `retryAfter` 秒后**静默重试**，不向用户暴露 |\r\n| `WINDOW_QUOTA_EXCEEDED` | **立即停止**，读 `references/troubleshooting.md` 配额限流段，输出提示 |\r\n| `DAILY_QUOTA_EXCEEDED` / `DAILY_SCAN_EXCEEDED` | **立即停止**，输出：`⚠️ 今日额度已满，次日 00:00 重置。` |\r\n| `SERVICE_OVERLOADED`（503） | `retryAfter` 秒后静默重试 1 次，仍失败则告知\"系统繁忙，请稍后重试\" |\r\n\r\n---\r\n\r\n## ⛔ 执行顺序（路由前必读，所有场景必须遵守）\r\n\r\n**无论匹配到哪个 leaf workflow，执行顺序固定为：**\r\n\r\n```\r\n① read_skill_file(global-rules 版本，见下表)  →  ② read_skill_file(leaf workflow)  →  ③ 执行\r\n```\r\n\r\n**步骤 ① 全局规则文件选择（按目标 leaf workflow 确定）**：\r\n\r\n| 目标 leaf workflow | 步骤 ① 读取的文件 |\r\n|---|---|\r\n| `quick-window.md` | `workflows/global-rules-lite.md` |\r\n| `period-return-compare.md` | `workflows/global-rules-lite.md` |\r\n| 其他所有 workflow | `workflows/global-rules.md` |\r\n\r\n- **步骤 ① 是硬前置条件**。确定目标 leaf 后，先按上表选择并读取对应 global-rules 版本，再读 leaf workflow，最后执行。\r\n- 禁止读完路由表就直接跳转 leaf workflow（Fast Path 中读 fast 文件除外）。\r\n\r\n---\r\n\r\n## 场景路由\r\n\r\n**先识别用户意图，确定目标 leaf workflow；然后按上方执行顺序加载**：\r\n\r\n| 场景 | 触发词 | 目标 leaf workflow |\r\n|------|--------|----------|\r\n| 最新时点行情 / 估值（快照） | 最新价、今日收盘、最新涨跌幅、当前换手率、最新PE/PB/市值… | Fast Path → `fast-snapshot.md` / 完整链路 → `global-rules.md` → `quick-snapshot.md` |\r\n| 最近N日序列 / 窗口统计 | 最近5日、最近20日、近N个交易日、窗口最高/最低/振幅…（仅单资产、最近N日） | Fast Path → `fast-window.md` / 完整链路 → `global-rules-lite.md` → `quick-window.md` |\r\n| 最近报告期财务 | 营收、净利润、归母净利润、ROE、总资产、总负债、资产负债率… | Fast Path → `fast-report-period.md` / 完整链路 → `global-rules.md` → `quick-report-period.md` |\r\n| K线图（可视化） | K线图、画图、展示走势… | `global-rules.md` → `render-kline.md` |\r\n| 固定区间累计涨跌幅 | 从A到B、某年某月至某年某月、区间收益、累计涨跌幅、区间表现、多资产区间对比 | `global-rules-lite.md` → `period-return-compare.md` |\r\n| 量化选股 / 回测 / 因子 / 图表 / 上传下载 | 选股、回测、均线、PE选股、因子、净值、上传CSV、下载数据、画图… | `global-rules.md` → `quant-standard.md` |\r\n| 事件研究 | 复盘、历次、涨价、降息、加息、事件窗口、随后表现、超预期、不及预期、政策后表现…（给定事件或需先识别事件日） | `global-rules.md` → `event-study.md` |\r\n| 阈值区间统计 / 连续阶段 | 历次、每次、平均、回撤超过、从高点下跌超过、熊市区间、连续阶段、regime | `global-rules.md` → `regime-segmentation.md` |\r\n\r\n> 上传、下载、画图不是独立场景——它们是 workflow 内的子步骤，workflow 文档会在需要时指引你读对应的 `recipes/`。\r\n\r\n### 路由硬排除（优先于触发词匹配）\r\n\r\n以下规则在触发词匹配**之前**检查，命中即强制改道，不得被触发词覆盖：\r\n\r\n| 用户意图特征 | 禁止进入 | 强制导向 | 判断依据 |\r\n|-------------|---------|---------|---------|\r\n| 盘中/实时/当前/现在/今天/今日/当日 + 查询日内行情（涨幅排名、涨停、日内跌幅等） | `quick-snapshot` `quick-window` | `quant-standard.md`（优先匹配分钟频卡片） | 需要分钟频卡片的专用公式；`use_minute_data: true` 已是全局默认 |\r\n| 盘中/实时/当前/今天/今日/当日 + 全市场/板块 + TopN/排名/阈值名单/选股/筛选/信号 | `quick-snapshot` `quick-window` | `quant-standard.md` → 优先命中\"实时横截面 TopN 排名\"或\"盘中阈值筛选_名单查询\"微流程 | 这类高频短题有专用封闭微流程 |\r\n| 给出明确起止日期，只问区间累计涨跌幅/收益 | `event-study` `quick-window` `quant-standard` | `period-return-compare.md` | 本质是固定区间收益比较，不是因果窗口分析，也不是复杂量化流程 |\r\n| 行业/板块聚合排名（如\"申万行业涨幅前5\"） | `quick-window` `quick-snapshot` | `quant-standard.md` | 需要横截面聚合，不是单资产序列 |\r\n| 阈值触发型离散事件识别（如\"跌幅超过X%的次数\"，问每次后表现） | — | `event-study.md`（阈值触发模式） | 需先识别阈值事件日，再做窗口分析 |\r\n| 由阈值条件定义连续区间（如\"历次熊市\"\"回撤超30%的阶段\"） | `event-study` | `regime-segmentation.md` | 研究的是连续阶段而非离散事件后的窗口 |\r\n| \"创近N日新高/新低\"（不含\"首次\"修饰词） | 不得加\"昨日未满足\"条件 | 按**当前状态**判断（state check），公式只比较当前值与昨日的N日极值 | 只有用户明确出现\"首次突破/首次跌破\"\"新晋\"\"今日第一次\"时，才允许追加首次触发条件；详见 `quant-standard.md` |\r\n\r\n判断口诀：\r\n- **有明确起止日 + 只问区间数值** → `period-return-compare`（固定区间收益比较）\r\n- **有事件 + 问\"随后N天/月表现\"** → `event-study`（因果窗口）\r\n- **有阈值条件 + 问\"每次发生后表现\"** → `event-study`（阈值触发模式）\r\n- **有阈值条件 + 问\"连续阶段/区间内表现\"** → `regime-segmentation`（连续阶段统计）\r\n\r\n若用户请求满足以下任一模式，应优先判定为【快速查数任务】，按以下路由直接跳转，不得先进入其他 workflow：\r\n\r\n**快速查数路由（按优先级依次判断，首个匹配即停）：**\r\n\r\n1. 时间锚点是\"最近 N 日窗口/序列\" → Fast Path 条件满足时读 `workflows/fast-window.md`，不满足则 `workflows/global-rules-lite.md` → `workflows/quick-window.md`\r\n2. 时间锚点是\"最近报告期\"且字段属于财务类 → Fast Path 条件满足时读 `workflows/fast-report-period.md`，不满足则 `workflows/global-rules.md` → `workflows/quick-report-period.md`\r\n3. 用户明确要\"画图 / K线 / 带成交量走势\" → 直接加载 `workflows/render-kline.md`\r\n4. 其余（明确是最近完成交易日的行情/估值/多资产对比，且**不含** 今天/今日/当日/当前/现在/实时/盘中/排名/筛选 语义）→ Fast Path 条件满足时读 `workflows/fast-snapshot.md`，不满足则 `workflows/global-rules.md` → `workflows/quick-snapshot.md`\r\n\r\n> 上述路由不需要先读 `workflows/quick-lookup.md`。\r\n\r\n### 关键红线速查（即使未读 global-rules.md 也必须遵守）\r\n\r\n以下 4 条规则从 global-rules.md 摘录，**优先级最高**，对所有场景生效：\r\n\r\n1. **事件定义冻结**：事件类型/范围必须**逐字匹配用户原始措辞**。用户说\"年报/半年报\"就只查年报和半年报，不得扩大到业绩预告/快报/季报；用户说\"国务院或住建部\"就只纳入该层级，不得扩大到央行/银保监会/地方政府。若认为用户定义可能遗漏，在回答末尾**建议**扩大，不得擅自扩大。\r\n2. **evidence-only 回答**：最终答案只输出本轮工具结果直接支持的数值、日期、排名、口径说明。未经工具验证，禁止默认输出宏观归因、政策归因、方向性判断（\"通常\"\"往往\"\"偏正面\"）。\r\n3. **去过程化交付**：禁止「已成功获取」「让我来」「按照流程」「Step 1/2/3」「根据 workflow」等过程性话术；禁止泄露 `_working/` 路径、checkpoint 名称、workflow 文件名。查到即答，不展示内部过程。\r\n4. **条件口径冻结**：用户条件必须原样执行，禁止任何改写（百分比↔小数、相对时间→年份区间、资产宇宙替换、卡片附加条件继承）。详见硬规则第 6 条。\r\n\r\n触发词参考：\r\n- 最近交易日收盘 / 最新已披露PE / 最新市值（非盘中、非筛选） → `quick-snapshot`\r\n- 最近5日 / 最近20个交易日 / 近N日序列 / 窗口最高最低 → `quick-window`\r\n- 营收 / 净利润 / ROE / 总资产 / 总负债 / 资产负债率 → `quick-report-period`\r\n\r\n禁止：\r\n- 优先调用 `scanDimensions`、`renderKLine`（除非用户明确要看图）\r\n- 先做分析性扩写，再补充结构化数值\r\n- **在读取对应 leaf workflow 之前**直接调用 `runMultiFormula` / `renderKLine` / `scanDimensions` / 输出\"无法联网\"或\"无法获取实时数据\"\r\n- 把卡片附加条件（首次/非ST/封板/流动性门槛等）默默继承进最终答案\r\n- 以 `description`、`samples`、预览行、截断大表作为**名单题**的完整结果直接收尾（必须提取完整名单或明确声明不完整）\r\n\r\n**leaf workflow 最终回答合同优先**：leaf workflow 中的\"最终回答合同\"优先负责收紧该场景的输出格式；若 leaf workflow 已满足停止条件，必须直接按该合同输出，不得再解释内部过程。\r\n\r\n## 执行权授权规则\r\n\r\n**规则层级（从高到低）：**\r\n\r\n1. **SKILL.md**：路由 + 全局门禁（硬规则 4 条、路由硬排除）\r\n2. **global-rules.md**：所有 leaf 必须遵守的全局合同（执行合同、证据分级、简答模式、不补精度、方法限制说明、参数规范、数值精度、终答一致性检查）\r\n3. **leaf workflow**：当前任务的具体执行流程（checkpoint、模板、停止条件、格式化）\r\n\r\n**冲突解决**：\r\n- leaf workflow 中的具体规则（如 readData 模式选择）优先于 global-rules 的一般规则\r\n- 但 leaf workflow 不得**放宽** global-rules 的红线（如证据分级门槛、不补精度原则）\r\n- 不得从其他 leaf workflow 借用模板、fallback 或回答格式\r\n\r\n**quick-lookup.md 的定位**：\r\n- 仅作为快查子流程的路由入口和规则参考总表\r\n- 各 leaf workflow 已自包含所有执行规则，执行时无需回到 quick-lookup.md\r\n- quick-lookup.md 不定义任何 leaf 独有规则\r\n\r\n## 全局执行规则\r\n\r\n> **全局合同详见 `workflows/global-rules.md`，进入任何 leaf workflow 时自动生效。**\r\n> leaf workflow 可在其内部添加更严格的约束，但不得豁免或放宽 global-rules 中的规则。\r\n\r\n## 平台数据覆盖范围\r\n\r\n| ✅ 支持 | ⚠️ 有条件支持 | ❌ 不支持（短期内不会支持） |\r\n|------|------|------|\r\n| A股个股（沪深主板/创业板/科创板/北交所） | ETF / LOF / 场外基金（先以 `confirmMultipleAssets` 结果为准，能确认则正常执行；确认失败才告知不支持） | 期货 / 期权 |\r\n| 港股个股（HK + 代码，如 HK0001） | | 台股 / 韩股 / 日股 / 德股等其他境外市场 |\r\n| 美股个股（NASDAQ: 代码.N；NYSE: 代码.O；AMEX: 代码.A） | | |\r\n| 主要宽基指数（沪深300、中证500、万得全A等） | | |\r\n\r\n> **港股 / 美股数据范围限制**：港股和美股目前仅支持**行情价格类数据**（收盘价、开盘价、最高价、最低价、涨跌幅、成交量、成交额）。估值数据（PE/PB/市值等）和财务数据（营收/净利润/ROE等）暂不支持。查询港股/美股的估值或财务字段时，应主动告知用户当前不支持，而不是静默跳过。\r\n\r\n### 股票代码格式速查\r\n\r\n| 市场 | 格式 | 示例 |\r\n|------|------|------|\r\n| A股-上交所 | SH + 代码 | SH600000 |\r\n| A股-深交所 | SZ + 代码 | SZ000001 |\r\n| 港股 | HK + 代码 | HK0001 |\r\n| 美股-NASDAQ | 代码.N | AAPL.N |\r\n| 美股-NYSE | 代码.O | AAL.O |\r\n| 美股-AMEX | 代码.A | SBE.A |\r\n\r\n> 确认资产失败（熔断规则）详见 `workflows/quick-lookup.md` § Step 1。\r\n\r\n> 环境依赖（Python版本、Playwright、API Key）→ `references/environment.md`\r\n> 故障排查 → `references/troubleshooting.md`\r\n> RU 计费 → `references/ru-billing.md`\r\n\r\n---\r\n\r\n## 前置条件（按需执行，不是简单查数的默认首步）\r\n\r\n> **凭据存储说明**：本 skill 的 quant-buddy API Key **只存放在 skill 目录下的 `config.json` 的 `api_key` 字段**，不使用环境变量（`QUANT_BUDDY_API_KEY` 等环境变量不会被读取）。仅可选的 `BOCHA_API_KEY`（事件新闻搜索）走环境变量。\r\n\r\n仅在以下情形下，才需要显式读取 `config.json` 检查 `api_key`：\r\n- 本轮实际需要调用本地脚本或平台工具，且当前环境尚未建立可用 session\r\n- 上一轮工具调用已出现 401 / 402 / 明确认证错误\r\n- workflow 明确要求执行脚本链（如本地 Python 脚本渲染）\r\n\r\n对已命中 leaf workflow 的简单查数题（quick-snapshot / quick-window / quick-report-period / render-kline）：\r\n- 不要为了形式完整额外读取 `config.json`\r\n- 优先直接按 leaf workflow 执行\r\n- 仅当工具调用出现明确认证问题时，再回到认证向导\r\n\r\n原则：认证检查服务于执行，不应成为简单题的固定额外步骤。\r\n\r\n- 若 `api_key` **非空** → 正常继续\r\n- 若 `api_key` **为空** → **立即停止**，禁止继续查数，输出以下**新用户引导消息**（原样输出，不得删减）：\r\n\r\n  ---\r\n  ⚠️ 尚未配置 API Key，当前无法查询数据。\r\n\r\n  前往 https://www.quantbuddy.cn/login 登录/注册并获取 API Key，然后直接发给我：\r\n  > 帮我配置 APIkey：sk-xxxxxxxx\r\n  ---\r\n\r\n---\r\n\r\n### 配置向导（用户粘贴 Key）\r\n\r\n当用户消息中包含 `sk-` 开头的字符串时：\r\n\r\n1. 从用户消息中提取 `sk-` 开头的完整 Key 字符串\r\n2. 将 Key 写入 `config.json` 的 `api_key` 字段（用 `replace_string_in_file` 直接写入）\r\n3. **必须输出**：「✅ API Key 配置成功！」\r\n4. **自动重试**：若本对话中有被 api_key 缺失错误中断的查询（如之前用户问过行情），**立即重新执行该查询并给出数据结论**，不需要用户再次发起。\r\n\r\n**运行时 401/402** → 立即停止，提示用户 API Key 无效/过期/配额耗尽，请重新前往官网获取新的 Key 并重新配置。\r\n\r\n---\r\n\r\n## 工具调用方式\r\n\r\n所有工具通过 `scripts/call.py` 调用。`call.py` 会同时将结果打印到 stdout 和写入临时文件。\r\n\r\n### 标准调用（一步完成）\r\n\r\n```bash\r\npython scripts/call.py <工具名> '{\"key\":\"value\"}'\r\n```\r\n\r\n结果直接从 stdout 获取。若 stdout 被截断，可回读 `/tmp/gzq_out.txt`。\r\n\r\n也可通过环境变量传参（适用于参数含特殊字符的场景）：\r\n\r\n```bash\r\nGZQ_PARAMS='<JSON>' python scripts/call.py <工具名>\r\n```\r\n\r\n### 禁止事项\r\n\r\n| 禁止 | 原因 |\r\n|------|------|\r\n| 创建自定义 .py 写参数文件 | 环境变量方案已解决编码问题 |\r\n| 直接调用 `scripts/executor.py` | `call.py` 封装了 renderChart 自动保存等逻辑 |\r\n| `echo` 管道传参（Windows） | GBK 编码截断中文 |\r\n| 命令行参数传 JSON（Windows） | PS 吃掉双引号 |\r\n\r\n---\r\n\r\n## presets/、recipes/、tools/ 三个目录的分工\r\n\r\n| 目录 | 是什么 | 何时读 |\r\n|------|---------|--------|\r\n| **presets/** | 平台实际返回值的本地快照（YAML）。资产名、函数格式、数据集 index_title、行业/概念名等。**直接可用于公式**，省掉确认类 API 调用。 | 写公式前先查 preset；找不到再调对应 API，并把新结果补回 preset。`cases_index.yaml` 仅在**选股/回测/因子/图表等量化标准场景**（`quant-standard.md`）开始时必读；快速查数场景（quick-snapshot/window/report-period）无需读取。 |\r\n| **recipes/** | 端到端使用示例（Markdown）。展示完整场景——从参数准备到最终输出。 | 由 workflow 在具体步骤中指引加载（不独立触发）。 |\r\n| **tools/** | API 参数手册（Markdown）。每个工具的字段、类型、约束。 | 默认不读。workflow 工具表标注了「必读」或报错时再查。 |\r\n\r\n> **简言之**：presets 是数据快照，recipes 是完整教程，tools 是参数字典。\r\n> presets 6 个文件的详细用法和加载时机→ 当前 workflow 文档内的「预设资源」表。\r\n\r\n---\r\n\r\n## Skill 更新部署规范（LLM 必读）\r\n\r\n当用户要求更新本 skill（发送 zip 压缩包）时，必须严格遵守以下规则：\r\n\r\n### 备份位置\r\n\r\n⚠️ **备份目录禁止放在 `skills/` 目录下。** 否则 openclaw 会把备份也识别为一个独立 skill，导致后续请求可能误用旧版代码。\r\n\r\n正确做法：\r\n\r\n```bash\r\n# 备份到 skills/ 之外的位置\r\ncp -r ~/.openclaw/workspace/skills/quant-buddy-skill ~/.openclaw/workspace/quant-buddy-skill-backup-$(date +%Y%m%d%H%M)\r\n\r\n# ❌ 错误：备份仍在 skills/ 下\r\n# cp -r ~/.openclaw/workspace/skills/quant-buddy-skill ~/.openclaw/workspace/skills/quant-buddy-skill-backup-xxx\r\n```\r\n\r\n### 解压覆盖\r\n\r\n```bash\r\n# 解压到临时目录再拷贝（避免嵌套）\r\nTMPDIR=$(mktemp -d)\r\nunzip -o <压缩包路径> -d \"$TMPDIR\"\r\n# 如果解压出嵌套目录 quant-buddy-skill/，取内层\r\nif [ -d \"$TMPDIR/quant-buddy-skill\" ]; then\r\n  cp -rf \"$TMPDIR/quant-buddy-skill/\"* ~/.openclaw/workspace/skills/quant-buddy-skill/\r\nelse\r\n  cp -rf \"$TMPDIR/\"* ~/.openclaw/workspace/skills/quant-buddy-skill/\r\nfi\r\nrm -rf \"$TMPDIR\"\r\n```\r\n\r\n### 部署后检查\r\n\r\n1. 确认 `~/.openclaw/workspace/skills/` 下只有 `quant-buddy-skill/` 一个与本 skill 相关的目录\r\n2. 读取 `SKILL.md` 确认版本号\r\n3. 保留 `config.json` 中已有的 `api_key`（若用户之前已认证过）\n\nFile v4.14.18:_meta.json\n\n{\n  \"ownerId\": \"kn7b02063x75b1b8yswrzgesph858j2j\",\n  \"slug\": \"quant-buddy-skill\",\n  \"version\": \"4.14.18\",\n  \"publishedAt\": 1777018591868\n}\n\nFile v4.14.18:references/environment.md\n\n# 环境依赖说明\r\n\r\n本文档描述运行 `quant-buddy-skill` 及其子场景所需的环境配置。\r\n\r\n---\r\n\r\n## Python\r\n\r\n- **版本要求**：Python 3.8+（推荐 3.11）\r\n- **核心功能**：仅依赖标准库，无需额外 `pip install`\r\n- **Windows 推荐启动方式**：所有涉及中文路径的脚本加 `-X utf8` 标志\r\n\r\n```bash\r\npython -X utf8 scripts/call.py <工具名>\r\n```\r\n\r\n---\r\n\r\n## API Key 配置\r\n\r\n前往 https://www.quantbuddy.cn/login 登录/注册，在账户页面获取 API Key。获取后有两种方式写入：\r\n\r\n1. **手动编辑**：直接打开 skill 根目录下的 `config.json`，把 `api_key` 字段改为你的 Key。\r\n2. **贴给 AI 助手**：在对话中把 `sk-...` 开头的 Key 发给 AI，AI 会写入 `config.json`。\r\n\r\n若你需要保留私有配置或覆盖默认端点，请使用 `config.local.json`；该文件仅供本地使用，不应打包或提交。\r\n\r\n若出现 `401 Unauthorized` 或 `402 Quota`，请重新获取并更新 `config.json` 中的 `api_key`。\r\n\r\n---\r\n\r\n## 可选 Bocha 搜索能力\r\n\r\n仅部分 Web 搜索辅助场景需要博查凭证；核心行情、财务、选股、回测能力不依赖该凭证。\r\n\r\n可选配置方式（任一即可）：\r\n\r\n- 环境变量 `BOCHA_API_KEY`\r\n- `config.local.json` 中手动添加 `bocha_api_key`\r\n- `config.json` 中手动添加 `bocha_api_key`\r\n\r\n---\r\n\r\n## 运行时输出目录\r\n\r\n- `output/.session.json`：当前 session 的 task_id\r\n- `output/ic_data/`：IC 扫描结果（若 workflow 触发相关能力）\r\n- 其他 `csv / png / json / html`：运行过程中的临时或交付产物\r\n\r\n---\r\n\r\n## readData 批量限制\r\n\r\n`readData` 单次调用最多传入 **10 个 data_id**。如需读取更多结果，拆分多次调用。\r\n\r\n---\r\n\r\n## 终端注意事项\r\n\r\n- 终端缓冲可能导致长输出不完整显示，`call.py` 会额外写入系统临时目录下的 `gzq_out.txt`\r\n- 若需排查，可在系统临时目录中查看该文件内容\n\nFile v4.14.18:references/ru-billing.md\n\n# RU 计费体系\r\n\r\n> 更新于 2026-04-15。统一 RU（Resource Unit）体系，所有端点共享一个 RU 池。\r\n> 每个请求按端点类型 + 请求参数动态扣减 RU（1～26 RU）。\r\n> 规划流程时优先减少冗余调用。\r\n\r\n---\r\n\r\n## RU 权重速查表\r\n\r\n| 工具 | 模式 | RU 消耗 | 说明 |\r\n|------|:---:|:---:|------|\r\n| `search_functions` | fixed | 1 | |\r\n| `get_card_formulas` | fixed | 1 | |\r\n| `upload_preview` | fixed | 1 | |\r\n| `upload_confirm` | fixed | 1 | |\r\n| `download_data` | fixed | 1 | |\r\n| `render_kline` | fixed | 1 | |\r\n| `re_render_chart` | fixed | 1 | |\r\n| `read_data` | fixed | 2 | |\r\n| `search_similar_cases` | fixed | 5 | |\r\n| `confirm_multiple_assets` | deferred | 1～6 × 意图数 | DB 精确匹配 1 RU，LLM 路径 6 RU |\r\n| `confirm_data_multi` | deferred | 1～26 × 意图数 | DB 精确匹配 1 RU，LLM 路径 26 RU |\r\n| `run_multi_formula` | dynamic | **7 × 公式数** | 单次最多 20/30/40 个（free/plus/pro） |\r\n| `scan_dimensions` | dynamic | **12 × 维度数** | 全维度(8) = 96 RU |\r\n| `render_chart` | dynamic | **1 × 线数** | 如 3 条线 = 3 RU |\r\n\r\n> **deferred 模式**：先预扣 1 RU/意图，请求完成后按实际路径补扣差额。\r\n> **错误请求退款**：所有端点发生错误时（4xx/5xx），实际 RU 降为 1 RU。\r\n\r\n---\r\n\r\n## 配额池说明\r\n\r\n| 池 | 重置方式 | 说明 |\r\n|------|------|------|\r\n| **窗口 RU** | 个人滚动（最早请求 +4h） | 不是全部一次恢复，按请求逐批恢复 |\r\n| **日 RU** | 每天 00:00（北京时间） | 次日零点统一重置 |\r\n\r\n---\r\n\r\n## 场景成本参考\r\n\r\n| 场景 | 典型 RU 消耗 |\r\n|------|:---:|\r\n| 单只股票价格/PE/PB | ~3 RU |\r\n| 条件选股（1 条公式）| ~10 RU |\r\n| 条件选股+回测（5 公式）| ~37 RU |\r\n| IC 全维度扫描 | 96 RU |\n\nFile v4.14.18:references/scripts-audit.md\n\n# Bundled Scripts Audit\r\n\r\nThis document enumerates every Python script shipped inside this skill, what it does, and its network / subprocess / filesystem behavior. Reviewers can use it to verify the skill's declared behavior without reading every line of code.\r\n\r\nLast audited against version: **4.14.7**\r\n\r\n---\r\n\r\n## Top-level scripts\r\n\r\n### `scripts/call.py`\r\n- **Purpose**: Thin CLI dispatcher. Takes a tool name + JSON params, forwards to `scripts/executor.py` via a subprocess of the same Python interpreter.\r\n- **Network**: None directly. Network calls happen inside `executor.py`.\r\n- **Subprocess**: `subprocess.run([sys.executable, \"scripts/executor.py\", ...])`. No shell, no external binary.\r\n- **Filesystem writes**: None.\r\n- **Reads secrets**: Only `config.json` / `config.local.json` pass-through; secrets are handled by `executor.py`.\r\n\r\n### `scripts/executor.py`\r\n- **Purpose**: Calls the quant-buddy HTTPS API and returns the response.\r\n- **Network**: Only `https://www.quantbuddy.cn/**` via `urllib.request` (stdlib). Host is taken from `config.json#endpoint` with a hardcoded default; no redirects to third-party hosts are followed without verification.\r\n- **Authentication**: Resolves `api_key` in this order: (1) `QUANT_BUDDY_API_KEY` env var, (2) `config.local.json` `api_key` field, (3) `config.json` `api_key` field. The resolved key is sent **only** in the `Authorization: Bearer <key>` header. It is never logged, printed to stdout/stderr, or written to files.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: Optional response cache under `.cache/` within the skill root; chart / CSV outputs under `output/` when invoked by chart or download tools.\r\n\r\n### `scripts/quant_api.py`\r\n- **Purpose**: Python wrapper around `executor.py` for use as a library (not invoked during normal agent flow).\r\n- **Network**: Same as `executor.py` (delegates to it).\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: None.\r\n\r\n### `scripts/event_study_local.py`\r\n- **Purpose**: Optional event-study helper. Combines quant-buddy data with a Bocha web-search step for news context.\r\n- **Network**:\r\n  - `https://www.quantbuddy.cn/**` (via `executor.py`) — required.\r\n  - `https://api.bochaai.com/v1/web-search` — **opt-in only**. The function returns `{\"ok\": false, \"error\": \"BOCHA_API_KEY 未配置\"}` immediately if the user has not set `BOCHA_API_KEY` (env var / `bocha_api_key` in `config.local.json` / `config.json`). No request is made without the key.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: None.\r\n- **Dependency**: Requires the `requests` package **only when Bocha is enabled**. Without BOCHA_API_KEY the import path is bypassed.\r\n\r\n### `scripts/repro_scan_null.py`, `scripts/update_cases_index.py`\r\n- **Purpose**: Developer utilities for curating the skill's own preset/case files. Not invoked by the agent at runtime; intended for the skill author to regenerate local indices.\r\n- **Network**: None.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: Only under `scripts/` and `presets/` within the skill root.\r\n\r\n---\r\n\r\n## `scripts/eval/`\r\nOffline evaluation harness for the skill author to measure quality regressions. Not invoked at runtime. No network access, no subprocess, writes only to `scripts/eval/` outputs.\r\n\r\n---\r\n\r\n## Summary guarantees\r\n\r\n| Concern | Status |\r\n|---|---|\r\n| Outbound network hosts | `www.quantbuddy.cn` (required), `api.bochaai.com` (opt-in only) |\r\n| api_key ever logged / transmitted to other host | No |\r\n| PII (phone / SMS / email / device ID) collected | No |\r\n| Subprocess / shell to external binary | No (only re-invokes `sys.executable` for dispatch) |\r\n| Writes outside skill root | No |\r\n| Reads OS credentials / env vars beyond the declared ones | No (only reads `BOCHA_API_KEY` when the optional Bocha feature is used) |\r\n\r\nIf any of the above statements is inaccurate, it is a bug and should be reported to the skill author.\n\nFile v4.14.18:references/troubleshooting.md\n\n# 故障排查\r\n\r\n> 汇总所有场景（量化选股、渲染图表、数据下载）的常见错误与解决方式。\r\n\r\n---\r\n\r\n## 公式 / 变量\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `公式变量未找到` | 同一批公式 task_id 不一致 | 确保所有公式用同一个 task_id |\r\n| `函数不存在` / 函数名报错 | 案例原文笔误，或抄写时引入差异 | 用 `searchFunctions` 找正确函数名 |\r\n| `数据名不存在` | 公式中名称与 confirmDataMulti 的 index_title 不一致 | 以 index_title 为准 |\r\n| `公式格式检测失败：MA(dataid(...),N)` | 平台**无 `MA()` 函数** | 简单均线用 `平均(\"数据名\", N)`；指数均线用 `ema(\"数据名\", N)` |\r\n| `函数不存在：取出最后值` | 该函数不存在于平台 | 替代：① `取前(数据, n, 返回数值)` 获取截面 TopN；② `readData(mode=last_day_stats)` 获取最新截面 |\r\n| PE 选股包含亏损股 | 未过滤负 PE | 加 `(\"PE\">0)` 条件 |\r\n| 多因子选股数为 0 | 非季报日截面财务数据为空 | ① 检查结束日期是否临近季报日；② 用 `readData(mode=last_day_stats)`；③ 调整至最近季报日（3/31、6/30、9/30、12/31） |\r\n\r\n---\r\n\r\n## 工具参数\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `参数 xxx 必填` / `400` | 参数名错误 | 读对应 `tools/<tool>.md` 确认正确字段名 |\r\n| `readData` 返回 400 | 参数名用了 `variable_names` | 改为 `ids` 数组 |\r\n| `match_quality=low` | searchSimilarCases 未找到好模板 | 调整 query 关键词，**最多重试 1 次** |\r\n| confirmDataMulti 返回 404 | 查询的是单资产价格，不是平台聚合数据 | 用 `收盘价(资产名)` 函数，无需 confirmDataMulti |\r\n| confirmMultipleAssets 30次超时 | intentions 用了前缀格式如 `CMX-铜` | 用简洁中文品种名如 `铜`、`黄金` |\r\n\r\n---\r\n\r\n## 图表渲染\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| renderChart 图中无曲线 | 数据为二维，renderChart 仅支持一维 | 确保公式输出一维时序 |\r\n| `参数 lines 必须是非空数组` | 误用了 `variable_names` 参数 | 改为 `lines: [{id, name}]`，id 来自 runMultiFormula 的 `_id` |\r\n| K线图报 `必须包含 open_id/high_id/low_id/close_id` | candlestick 参数缺少必填字段 | 传入完整 4 个 ID；或改用 `renderKLine` |\r\n| K线图日期对不齐 / 数据缺失 | OHLC 4 个 data ID 来自不同 task_id | 确保在同一个 runMultiFormula 中计算 |\r\n| renderKLine 报 ticker 不存在 | ticker 格式错误 | 使用 `SH`/`SZ` 前缀格式如 `SH600519` |\r\n| renderKLine indicators 无效 | 指标名拼写错误 | 参照 `tools/render_kline.md` 支持列表，全小写 |\r\n| 图表不知道在哪里 | 未找到输出文件 | `call.py` 已自动保存到 `output/` 并打开 |\r\n\r\n---\r\n\r\n## 认证 / 网络\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `401 Unauthorized` | api_key 无效或过期 | **立即停止**，提示用户重新认证 |\r\n| `402 Quota` | 配额耗尽 | **立即停止**，提示用户等待恢复或次日重置 |\r\n| 终端命令无输出 | 终端缓冲 stdout | `call.py` 已写 `/tmp/gzq_out.txt`，用 `cat /tmp/gzq_out.txt` 读取 |\r\n\r\n## 业务错误（HTTP 200 + success: false）\r\n\r\n部分错误走 HTTP 200 返回，通过 `success: false` + `error` 对象区分：\r\n\r\n```json\r\n{\"code\": -1, \"success\": false, \"error\": {\"message\": \"参数 ids 必须是非空数组\"}}\r\n```\r\n\r\n| 判断方式 | 说明 |\r\n|----------|------|\r\n| `success === false` 或 `code !== 0` | 均可判定为错误 |\r\n| `error.message` | 错误描述 |\r\n\r\n> 业务错误与 429 配额超限使用相同的 `{ success: false, error: { message } }` 结构。\r\n> 429/503 的 `error` 中额外包含 `code`（语义化字符串）和恢复时间字段。\r\n> 调用方应先检查 HTTP status（429/503），再检查 body 的 `success` / `code`。\r\n\r\n---\r\n\r\n## 配额限流（429 错误码）\r\n\r\n| 错误码 | 含义 | 处理方式 |\r\n|--------|------|----------|\r\n| `WINDOW_QUOTA_EXCEEDED` | 窗口 RU 已耗尽 | **停止调用**，告知用户等待时间（`error.nextResetIn` 秒后最早一批恢复） |\r\n| `DAILY_QUOTA_EXCEEDED` | 今日 RU 已耗尽 | **停止调用**，告知用户次日 00:00 重置（`error.resetIn` 秒） |\r\n| `DAILY_SCAN_EXCEEDED` | IC 扫描今日次数已满 | **停止调用**，告知用户次日 00:00 重置（free=2次/天，plus=10次/天）（`error.resetIn` 秒） |\r\n| `RATE_LIMIT_EXCEEDED` | 每分钟请求过于频繁 | **静默等待** `error.retryAfter` 秒后重试，不暴露给用户 |\r\n| `CONCURRENT_LIMIT` | 有计算任务正在执行 | **静默等待** `error.retryAfter` 秒后重试，不暴露给用户 |\r\n| `SERVICE_OVERLOADED` | 系统熔断（503） | **静默等待** `error.retryAfter` 秒后重试 1 次；若仍失败则告知用户\"系统繁忙，请稍后重试\" |\r\n\r\n---\r\n\r\n## 数据下载\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| downloadData 返回 403 | 计算结果 `provider=dunhe`，无权限 | 改用 `readData(mode=full)` |\r\n| 下载到全量历史几千行 | 未传 begin_date | 调用前先问用户要哪段时间 |\r\n| 上传数据 NaN 率高 | CSV 列标题缺少交易所后缀 | 改为 `600519.SH` 格式 |\n\nFile v4.14.18:recipes/download-data.md\n\n# Recipe：下载数据到本地 CSV\r\n\r\n## 触发词\r\n\r\n> \"把数据下载成 CSV\"、\"导出到本地\"、\"下载历史数据\"\r\n\r\n---\r\n\r\n## 调用方式\r\n\r\n```bash\r\npython scripts/call.py downloadData '{\"data_id\":\"<data_id>\",\"begin_date\":<YYYYMMDD>,\"end_date\":<YYYYMMDD>}'\r\n```\r\n\r\n`call.py` 调用 `downloadData` 时会**自动**将 CSV 保存到 `output/<data_name>.csv`，终端输出摘要（total_rows、begin_date、saved_to），不刷屏。\r\n\r\n---\r\n\r\n## 使用限制\r\n\r\n| 条件 | 说明 |\r\n|------|------|\r\n| **可下载** | 持久化一维时序：上传数据 (`provider=mydata`) 或平台数据 (`provider=guanzhao`) |\r\n| **不可下载** | `runMultiFormula` 的计算结果 (`provider=dunhe`)，普通用户无 `access_dunhe` 权限 → 返回 403 |\r\n| **替代方案** | 计算结果用 `readData(mode=full)` 读取，再自行保存为 CSV |\r\n\r\n---\r\n\r\n## 必须确认时间范围\r\n\r\n数据通常从 2015 年起，直接下载可能几千行。**调用前先问用户**：\r\n\r\n> \"您需要下载哪段时间的数据？（默认：最近一年）\"\r\n\r\n- 用户给出范围 → 传 `begin_date` / `end_date`\r\n- 用户说\"所有历史\" → 不传日期参数\n\nFile v4.14.18:recipes/event-study-formulas.md\n\n# 事件研究公式模板\r\n\r\n保留四条真正稳定的模板。\r\n\r\n## 模板 A: 单组事件固定持有期\r\n\r\n适用于绝大多数事件研究问题。\r\n\r\n```text\r\n{prefix}_事件日=选取日期({date1},{date2},...)\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_后{N1}日路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_事件日\",{N1})\r\n{prefix}_后{N2}日路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_事件日\",{N2})\r\n{prefix}_后{N1}日收益=分段最终值(\"{prefix}_后{N1}日路径\")\r\n{prefix}_后{N2}日收益=分段最终值(\"{prefix}_后{N2}日路径\")\r\n```\r\n\r\n### 窗口映射\r\n\r\n| 说法 | N |\r\n|------|---|\r\n| 1周 | 5 |\r\n| 2周 | 10 |\r\n| 1月 | 21 |\r\n| 3月 | 63 |\r\n| 半年 | 126 |\r\n| 1年 | 252 |\r\n\r\n### 使用建议\r\n\r\n1. 同时给逐次结果和均值\r\n2. 窗口不宜超过相邻事件最小间距\r\n3. 样本很少时不要强行做胜率和分位数\r\n\r\n## 模板 B: 两组事件对比（compare）\r\n\r\n适用于超预期 vs 不及预期、利好 vs 利空这类问题。\r\n\r\n```text\r\n{prefix}_A组=选取日期({group_a_dates...})\r\n{prefix}_B组=选取日期({group_b_dates...})\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_A后{N}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_A组\",{N})\r\n{prefix}_A后{N}收益=分段最终值(\"{prefix}_A后{N}路径\")\r\n{prefix}_B后{N}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_B组\",{N})\r\n{prefix}_B后{N}收益=分段最终值(\"{prefix}_B后{N}路径\")\r\n```\r\n\r\n### 使用建议\r\n\r\n1. 两组共享同一条价格和日收益序列\r\n2. 输出时先列每次事件，再列各组均值\r\n3. 两组样本数不一致时，要在解释里显式写出来\r\n\r\n## 模板 C: 事件后偏移区间回报（排除事件日）\r\n\r\n适用于\"事件后第 N 天到第 M 天\"的区间涨幅，排除事件当天。\r\n与模板 A 的区别：模板 A 从 T+1 起算固定窗口；本模板通过收盘价比值法精确计算任意偏移区间。\r\n\r\n```text\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_收盘_T加{N}=取某天(\"{prefix}_收盘\",交易日位移({event_date},{N}))\r\n{prefix}_收盘_T加{M}=取某天(\"{prefix}_收盘\",交易日位移({event_date},{M}))\r\n{prefix}_T{N+1}到T{M}涨幅=\"{prefix}_收盘_T加{M}\"/\"{prefix}_收盘_T加{N}\"-1\r\n```\r\n\r\n### 参数映射\r\n\r\n| 占位符 | 含义 | 示例值 |\r\n|--------|------|--------|\r\n| `{prefix}` | 变量前缀 | `fomc` |\r\n| `{event_date}` | 事件日期（YYYYMMDD 整数） | `20241218` |\r\n| `{asset_name}` | 标的资产名 | `沪深300` |\r\n| `{N}` | 起始边界交易日数（用户起始天数 - 1） | `1` |\r\n| `{M}` | 终止边界交易日数（用户结束天数） | `20` |\r\n\r\n### 数学原理\r\n\r\n`取某天` 将指定日期的收盘价填充为常数序列，两个常数序列相除天然对齐：\r\n\r\n$$\\text{T+N+1 到 T+M 涨幅} = \\frac{P_{T+M}}{P_{T+N}} - 1$$\r\n\r\n其中 $P_{T+N}$ 和 $P_{T+M}$ 均由 `交易日位移` 按 A 股交易日历精确计数（非自然日）。\r\n\r\n例如用户说\"第 2 天到第 20 天\" → N=1, M=20 → 计算 $P_{T+20} / P_{T+1} - 1$（持有 T+1 收盘到 T+20 收盘）。\r\n\r\n### N 值推导\r\n\r\n| 用户表述 | N | M | 实际区间 |\r\n|----------|---|---|----------|\r\n| \"第 2 天到第 20 天\" | 1 | 20 | T+1 收盘 → T+20 收盘 |\r\n| \"第 3 天到第 60 天\" | 2 | 60 | T+2 收盘 → T+60 收盘 |\r\n| \"排除前 2 天，看第 3 天起\" | 2 | M | T+2 收盘 → T+M 收盘 |\r\n\r\n核心规则：**N = 用户起始天数 - 1，M = 用户结束天数**\r\n\r\n### 使用建议\r\n\r\n1. 当用户说\"排除事件当天\"或\"T+2 到 T+20\"时使用本模板\r\n2. 多事件场景需为每个事件单独建立一套前缀变量（`取某天` 只能绑定一个日期）\r\n3. 同一会话中不同事件使用不同 `{prefix}`，避免变量覆盖\r\n4. 结果为精确价格比值，无累加近似误差\r\n\r\n## 模板 D: 搜索新闻打标分类（财报超预期类 compare 专用）\r\n\r\n适用于：需要先搜索新闻判断财报是否超预期，再分组计算事件后收益的场景。\r\n\r\n与模板 B 的区别：模板 B 默认两组日期已知；模板 D 需要先把正式年报/半年报披露日逐期打标，再将结果代入 compare 公式链。\r\n\r\n### 执行步骤（配合 `event-study.md` 的财报业绩超预期分类细则使用）\r\n\r\nStep D1：获取正式财报披露日\r\n\r\n```text\r\nREV_2D=\"A股营业总收入〔报告期利润表〕\"\r\nPUB_DATE=报告期转发布日(\"REV_2D\")\r\n```\r\n\r\n从 `PUB_DATE` 中提取目标股票的正式年报（Q4）和半年报（Q2）披露日。若需要补证，再用交易所公告页或东财年报季报页交叉验证。\r\n\r\nStep D2：逐期搜索并打标\r\n\r\n对每个披露日执行搜索，关键词格式：\r\n\r\n```text\r\n{股票简称} {报告类型} {yyyymmdd} 超预期 OR 不及预期\r\n```\r\n\r\n打标规则、证据门槛和 `label_confidence` 约束以 `event-study.md` 中的财报业绩超预期分类细则为准。\r\n\r\nStep D3：将打标结果代入 compare 公式链\r\n\r\n```text\r\n{prefix}_超预期组=选取日期({beat_dates...})\r\n{prefix}_不及预期组=选取日期({miss_dates...})\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_超预期后{N1}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_超预期组\",{N1})\r\n{prefix}_超预期后{N1}收益=分段最终值(\"{prefix}_超预期后{N1}路径\")\r\n{prefix}_超预期后{N2}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_超预期组\",{N2})\r\n{prefix}_超预期后{N2}收益=分段最终值(\"{prefix}_超预期后{N2}路径\")\r\n{prefix}_不及预期后{N1}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_不及预期组\",{N1})\r\n{prefix}_不及预期后{N1}收益=分段最终值(\"{prefix}_不及预期后{N1}路径\")\r\n{prefix}_不及预期后{N2}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_不及预期组\",{N2})\r\n{prefix}_不及预期后{N2}收益=分段最终值(\"{prefix}_不及预期后{N2}路径\")\r\n```\r\n\r\n### 参数说明\r\n\r\n| 占位符 | 说明 | 示例 |\r\n|--------|------|------|\r\n| `{prefix}` | 变量前缀 | `MT` |\r\n| `{beat_dates...}` | 超预期组日期列表 | `20210330,20220331,20240403` |\r\n| `{miss_dates...}` | 不及预期组日期列表 | `20220803` |\r\n| `{asset_name}` | 资产名称 | `贵州茅台` |\r\n| `{N1}` | 短窗口交易日数 | `5` |\r\n| `{N2}` | 长窗口交易日数 | `20` |\r\n\r\n### 使用建议\r\n\r\n1. 日期分组必须来自 Step D2 的搜索打标结果，不得凭记忆填入\r\n2. 若用户要比较\"符合预期\"而不是\"不及预期\"，只替换第二组标签和日期列表，不改整条公式链\r\n3. 两组共享同一条价格序列和日收益序列，减少公式冗余\r\n4. 样本数 < 5 时，均值行必须标注\"有限样本，仅供参考\"\r\n5. 若某组样本为 0（全部证据不足），保留 compare 框架，并在输出中明确说明该组无满足证据标准的样本，不得静默降级为 single 模式\r\n\r\n## 可选扩展: 超额收益\r\n\r\n如果用户明确要求相对基准表现，可额外生成：\r\n\r\n```text\r\n{prefix}_基准收盘=收盘价(沪深300)\r\n{prefix}_基准日收益=涨跌幅(\"{prefix}_基准收盘\")\r\n{prefix}_超额日收益=\"{prefix}_日收益\"-\"{prefix}_基准日收益\"\r\n```\r\n\r\n然后用 `{prefix}_超额日收益` 替代 `{prefix}_日收益` 进入同样的窗口链路。\n\nFile v4.14.18:recipes/ic-factor-templates.md\n\n# IC 因子公式模板\r\n\r\n> 来源：`workflows/quant-standard.md` Step 2 手动因子构建\r\n> 通常由 `scanDimensions` 脚本自动完成，仅在需要**自定义指标**或脚本不可用时手动使用\r\n\r\n---\r\n\r\n## 基础数据（所有因子前置）\r\n\r\n```python\r\nB_Close = 收盘价(X)         # X = 目标资产名（来自 confirmMultipleAssets 的 name）\r\nB_Ind   = 收盘价(Ind)       # Ind = 行业指数名\r\nB_Mkt   = 收盘价(Mkt)       # Mkt = 大盘指数（如 万得全A 或 沪深300）\r\n```\r\n\r\n---\r\n\r\n## D1 估值\r\n\r\n```python\r\nB_PE      = \"A股市盈率（PE, TTM）〔估值数据〕\" * 取出(X的代码)\r\nB_PB      = \"A股市净率（PB）〔估值数据〕\" * 取出(X的代码)\r\nB_PE_Rank = 数值水位(\"B_PE\", 250)\r\nB_PB_Rank = 数值水位(\"B_PB\", 250)\r\n```\r\n\r\n> PE 必须使用 TTM 口径（`A股市盈率（PE, TTM）〔估值数据〕`）\r\n\r\n---\r\n\r\n## D3 资金\r\n\r\n```python\r\nB_AllAmt    = 按天求和(\"全市场每日成交额\")\r\nB_Amt       = \"全市场每日成交额\" * 取出(X的代码)\r\nB_AmtRatio  = \"B_Amt\" / \"B_AllAmt\"\r\nB_AmtRank   = 数值水位(\"B_AmtRatio\", 250)\r\nB_Short     = \"A股融券空头持仓比例\" * 取出(X的代码)\r\nB_ShortRank = 数值水位(\"B_Short\", 250)\r\nB_Fund      = \"A股持股市值占基金股票投资市值比\" * 取出(X的代码)\r\nB_FundRank  = 数值水位(\"B_Fund\", 250)\r\n```\r\n\r\n---\r\n\r\n## D4 波动率 / 风险\r\n\r\n```python\r\nB_PrevClose = 前几天(\"B_Close\", 1)\r\nB_High      = 最高价(X)\r\nB_Low       = 最低价(X)\r\nB_TR  = 比较取大(\"B_High\"-\"B_Low\", 比较取大(绝对值(\"B_High\"-\"B_PrevClose\"), 绝对值(\"B_Low\"-\"B_PrevClose\")))\r\nB_ATR = 平均(\"B_TR\", 14)\r\n```\r\n\r\n---\r\n\r\n## D5 宏观 / 大盘环境\r\n\r\n```python\r\nB_Mkt_MA60  = 平均(\"B_Mkt\", 60)\r\nB_Mkt_Above = (\"B_Mkt\" > \"B_Mkt_MA60\")\r\n```\r\n\r\n---\r\n\r\n## D7 技术形态\r\n\r\n```python\r\n# 均线\r\nB_MA10 = 平均(\"B_Close\", 10)\r\nB_MA20 = 平均(\"B_Close\", 20)\r\nB_MA60 = 平均(\"B_Close\", 60)\r\n\r\n# MACD\r\nB_EMA12     = EMA(\"B_Close\", 12)\r\nB_EMA26     = EMA(\"B_Close\", 26)\r\nB_MACD      = \"B_EMA12\" - \"B_EMA26\"\r\nB_Signal    = EMA(\"B_MACD\", 9)\r\nB_MACD_Hist = \"B_MACD\" - \"B_Signal\"\r\n\r\n# 布林带\r\nB_SD20  = 标准差(\"B_Close\", 20)\r\nB_BollZ = (\"B_Close\" - \"B_MA20\") / \"B_SD20\"\r\n```\r\n\r\n---\r\n\r\n## D9 财务\r\n\r\n```python\r\nB_Profit_Raw = 报告期转发布日(\"A股净利润同比增长率：单季〔财务指标〕\")\r\nB_Profit_F   = 缺失填充(\"B_Profit_Raw\" * 取出(X的代码))\r\n```\r\n\r\n---\r\n\r\n## 收益率 / 位置（跨维度通用）\r\n\r\n```python\r\nB_Ret20       = 涨跌幅(\"B_Close\", 20)\r\nB_IndRet20    = 涨跌幅(\"B_Ind\", 20)\r\nB_Alpha20     = \"B_Ret20\" - \"B_IndRet20\"\r\nB_Ret20_Next  = 前几天(涨跌幅(\"B_Close\", 20), -20)   # 未来20日收益（IC计算目标）\r\n\r\nB_PriceRank   = 数值水位(\"B_Close\", 250)\r\nB_RS          = \"B_Close\" / \"B_Ind\"\r\nB_RS_Rank     = 数值水位(\"B_RS\", 250)\r\n```\r\n\r\n---\r\n\r\n## IC 计算公式\r\n\r\n```python\r\n# 内联写法（推荐，无跨变量依赖）\r\nPE_IC = 相关系数(前几天(数值水位(\"B_PE\", 250), 20), 涨跌幅(收盘价(X), 20), 250)\r\n\r\n# 引用写法（同一 task_id 内）\r\nB_PE_Rank = 数值水位(\"B_PE\", 250)\r\nPE_IC     = 相关系数(前几天(\"B_PE_Rank\", 20), 涨跌幅(\"B_Close\", 20), 250)\r\n```\r\n\r\n> 不同 task_id 之间不能引用变量——newSession 后旧 session 的变量全部丢失\n\nFile v4.14.18:recipes/industry-aggregation.md\n\n# 示例五：成交量加权行业聚合——放量日申万行业涨跌幅排名\r\n\r\n## 快速模板：行业近N日平均涨跌幅前K\r\n\r\n适用：\r\n- 申万一级行业最近一个月平均涨跌幅前5\r\n- 某板块体系近N日涨跌幅排名\r\n\r\n标准公式模板：\r\n```text\r\n个股近N日涨跌幅=涨跌幅(\"全市场每日收盘价\",N)\r\n行业近N日涨跌幅=成分平均汇总(\"个股近N日涨跌幅\",\"申万资产所属指数\")\r\n行业TopK=取前(\"行业近N日涨跌幅\",K,返回数值)\r\n```\r\n\r\n注意：\r\n- 所有数据名/变量名在函数参数中必须使用双引号\r\n- \"最近一个月\"默认按近20个交易日处理，回答中需明示口径\r\n- 若 runMultiFormula 已返回最后一天 top 数据，且足以回答用户问题，可不再 readData\r\n- 仅当内置数据名无法命中时，才使用 confirmDataMulti\r\n\r\n**⚠️ 输出口径声明硬规则**：上述模板的计算结果是\"**行业近N日平均涨跌幅**\"（行业内各成分股N日区间回报的算术均值）。在最终答案中**只能**称为\"行业近N日平均涨跌幅\"或\"行业近N日涨跌幅均值\"，**绝对禁止**将其改写为\"近N日累计涨跌幅\"——\"累计涨跌幅\"与\"平均涨跌幅\"统计含义不同，用户问的是\"平均\"就必须说\"平均\"。\r\n\r\n---\r\n\r\n## 用户意图\r\n\r\n> \"在A股放量日（当日成交量超过5日均值2倍时），哪些申万行业板块的平均涨跌幅最好？帮我排个名\"\r\n\r\n---\r\n\r\n## 核心挑战：跨维度聚合\r\n\r\n本示例的关键难点是**维度不匹配**：\r\n\r\n- 全市场回报率（如万得全A 7700+ 只）：资产×日期 二维矩阵\r\n- 申万行业指数（31个）：与全市场股票维度不同\r\n\r\n**不能直接用全市场列做行业均值**——同一个二维矩阵按行业分组后，维度（资产轴）不一致，必须用 `成分平均汇总()` 做桥接：\r\n\r\n```\r\n成分平均汇总(全市场数据, 申万资产所属指数)\r\n→ 输出：31个申万行业 × 日期 的二维矩阵（行业轴替换了资产轴）\r\n```\r\n\r\n类比：`成分平均汇总` 是\"按组取平均\"，第二个参数指定分组依据（哪家公司属于哪个行业）。\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 0 — 初始化会话\r\n\r\n```bash\r\npython scripts/call.py newSession\r\n```\r\n\r\n```json\r\n{\"code\": 0, \"task_id\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"}\r\n```\r\n\r\n---\r\n\r\n### Step 1 — 查案例（cases_index 优先）\r\n\r\n**1a. 读取 `presets/cases_index.yaml`**，搜索 tags 含 `行业`、`聚合`、`成分` 的卡片（约 1-3 张）。\r\n\r\n**1b.** 找到后调 `getCardFormulas` 拉取公式，理解 `成分平均汇总` 的参数用法：\r\n\r\n```bash\r\npython scripts/call.py getCardFormulas '{\"card_ids\": [\"<相关卡片id>\"]}'\r\n```\r\n\r\n**1c.** 若目录中未找到合适卡片，fallback 到：\r\n\r\n```bash\r\npython scripts/call.py searchSimilarCases '{\"query\": \"申万行业聚合成分平均汇总涨跌幅\", \"top_k\": 3}'\r\n```\r\n\r\n> **重点关注**返回案例中 `成分平均汇总()` 的参数格式、`申万资产所属指数` 的数据名称写法；案例解决的是案例自身的问题，当前问题的公式需根据用户需求重新组织。\r\n\r\n---\r\n\r\n### Step 2 — 确认全市场数据\r\n\r\n```bash\r\npython scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日成交量, 全市场每日回报率, 申万资产所属指数\"}'\r\n```\r\n\r\n**预期返回**（记录三个 index_title）：\r\n\r\n| 描述词 | index_title（示例） | dimension | 说明 |\r\n|-------|-------------------|-----------|------|\r\n| 全市场每日成交量 | `全市场每日成交量` | two | 资产×日期 |\r\n| 全市场每日回报率 | `全市场每日回报率` | two | 资产×日期 |\r\n| 申万资产所属指数 | `申万资产所属指数` | two | 资产×日期，值为申万指数代码 |\r\n\r\n> **Windows PowerShell 传参**：\r\n> ```bash\r\n> python scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日成交量, 全市场每日回报率, 申万资产所属指数\"}'\r\n> ```\r\n\r\n---\r\n\r\n### Step 3 — 搜索聚合函数（若 presets/functions.yaml 中已有则跳过）\r\n\r\n```bash\r\npython scripts/call.py searchFunctions '{\"query\": \"成分平均汇总 行业聚合\", \"top_k\": 3}'\r\npython scripts/call.py searchFunctions '{\"query\": \"区间统计量 掩码过滤\", \"top_k\": 3}'\r\npython scripts/call.py searchFunctions '{\"query\": \"按天求和 全市场聚合\", \"top_k\": 3}'\r\n```\r\n\r\n确认以下函数的参数格式：\r\n- `按天求和(数据)` → 将二维数据按日期求和，得到一维时序\r\n- `成分平均汇总(数据, 指数数据)` → 按指数成分分组取平均，输出指数×日期 矩阵\r\n- `区间统计量(数据, 掩码, 统计函数)` → 用布尔掩码过滤时间段，对各段计算统计量\r\n\r\n---\r\n\r\n### Step 4 — 执行公式（5条，共享同一 task_id）\r\n\r\n```bash\r\npython scripts/call.py runMultiFormula '{\r\n  \"task_id\": \"<Step 0 的 task_id>\",\r\n  \"begin_date\": 20150101,\r\n  \"formulas\": [\r\n    \"全市场总成交量=按天求和(\\\"全市场每日成交量\\\")\",\r\n    \"全市场成交量5日均=平均(\\\"全市场总成交量\\\",5)\",\r\n    \"放量日标记=(\\\"全市场总成交量\\\">\\\"全市场成交量5日均\\\"*2)\",\r\n    \"申万行业每日回报率=成分平均汇总(\\\"全市场每日成交量\\\"*\\\"全市场每日回报率\\\",\\\"申万资产所属指数\\\")\",\r\n    \"放量日行业平均涨跌幅=区间统计量(\\\"申万行业每日回报率\\\",\\\"放量日标记\\\",平均)\"\r\n  ],\r\n  \"intents\": [\"全市场每日总量（一维）\", \"5日均量（一维）\", \"放量日布尔标记（一维）\", \"成交量加权行业日回报率（31行业×日期）\", \"放量日区间内各行业平均涨跌幅（31行业×区间数）\"]\r\n}'\r\n```\r\n\r\n**关键设计决策**：\r\n\r\n| 设计点 | 说明 |\r\n|-------|------|\r\n| 公式4使用 `成交量×回报率` 而非直接 `回报率` | 这是**成交量加权平均**的计算模式：分子=成交量×回报率之和，分母=成交量之和，`成分平均汇总` 内部会自动完成加权除法 |\r\n| 公式1-3先把全市场压缩到一维 | `按天求和` 把 7700+ 只的成交量矩阵折叠为每天一个数——这是后续做\"全市场放量日\"判断的前提 |\r\n| `放量日标记` 是一维布尔序列 | 可直接作为 `区间统计量` 的掩码，标记哪些日期属于\"放量日\" |\r\n| `申万行业每日回报率` 维度是 31 × 4000+ 天 | 行业轴（31个申万行业）替代了原来的资产轴（7700+ 只股票） |\r\n\r\n**预期返回（各公式 data_id）**：\r\n```json\r\n{\r\n  \"results\": [\r\n    {\"variable_name\": \"全市场总成交量\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"全市场成交量5日均\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"放量日标记\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"申万行业每日回报率\", \"data_id\": \"xxx\", \"dimension\": \"two\", \"assets\": 31},\r\n    {\"variable_name\": \"放量日行业平均涨跌幅\", \"data_id\": \"xxx\", \"dimension\": \"two\", \"assets\": 31}\r\n  ]\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 5 — 验证结果（必做）\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<放量日行业平均涨跌幅的data_id>\"], \"mode\": \"smart_sample\"}'\r\n```\r\n\r\n**检查项**：\r\n- `assets` = 31（申万31个行业全部覆盖）\r\n- `dates`（列数）= 识别到的放量日区间数（历史通常 80-150 个）\r\n- NaN 率 < 10%（若过高，检查 `申万资产所属指数` 的 index_title 是否正确）\r\n- 取样值有正有负，数量级在 0.001 ~ 0.05 之间（日回报率级别）\r\n\r\n---\r\n\r\n### Step 6 — 读取完整截面排名\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<放量日行业平均涨跌幅的data_id>\"], \"mode\": \"last_day_stats\"}'\r\n```\r\n\r\n**预期返回**：31 个行业在所有放量日的平均涨跌幅，按值降序排列即可得到排名。\r\n\r\n---\r\n\r\n### Step 7（可选）— 柱状图可视化\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"放量日申万行业平均涨跌幅排名（2015至今）\",\r\n  \"lines\": [\r\n    {\"id\": \"<放量日行业平均涨跌幅的data_id>\", \"name\": \"放量日平均日涨幅\"}\r\n  ],\r\n  \"chart_type\": \"bar\",\r\n  \"task_id\": \"<task_id>\"\r\n}'\r\n```\r\n\r\n> ```bash\r\n> python scripts/call.py renderChart '{\"title\":\"放量日申万行业平均涨跌幅排名\", \"lines\":[{\"id\":\"<data_id>\",\"name\":\"放量日平均日涨幅\"}], \"chart_type\":\"bar\", \"task_id\":\"<task_id>\"}'\r\n> ```\r\n\r\n---\r\n\r\n## 常见错误与处理\r\n\r\n| 错误 | 原因 | 处理 |\r\n|------|------|------|\r\n| `成分平均汇总` 返回 assets=0 | `申wx资产所属指数` 的 index_title 写错 | 重新 confirmDataMulti，严格用返回的 index_title |\r\n| `放量日行业平均涨跌幅` assets=7700+（未聚合） | 公式4写错，误用的是全市场回报率而非行业聚合结果 | 确认公式4的变量名用的是 `申万行业每日回报率` |\r\n| 区间统计量 dates=0 | 放量日标记全为 False（条件过严或数据期太短） | 检查 begin_date / 阈值倍数；可先用 `readData(mode=smart_sample)` 看 `放量日标记` 的 True 比例 |\r\n| renderChart 报\"仅支持一维数据\" | `放量日行业平均涨跌幅` 是二维（31×区间数） | 先用 readData 读出截面均值，整理成一维序列后再图表；或改为 last_day_stats 下载后自行排序呈现文本 |\r\n| `数据名不存在：申万资产所属指数` | index_title 与实际返回不符 | 以 confirmDataMulti 返回的 index_title 为准，不要凭记忆猜测 |\r\n\r\n---\r\n\r\n## 延伸用法\r\n\r\n同样的模式可以应用于：\r\n\r\n- **涨停日** / **大跌日** 行业表现：把放量日的布尔公式替换为涨跌幅阈值条件\r\n- **宏观事件标记**：上传一列 0/1 事件标记 CSV，作为 `区间统计量` 的掩码\r\n- **基于成分平均汇总的因子聚合**：把任意全市场因子（估值、动量、质量）映射到行业维度，做行业风格分析\r\n\r\n---\r\n\r\n## 行业聚合排名题执行硬规则\r\n\r\n1. **直接执行公式**：行业聚合题的核心公式（如 `成分平均汇总(涨跌幅(...), \"申万资产所属指数\")`）应直接通过 `runMultiFormula` 执行，不需要先用 `confirmDataMulti` 查\"行业涨跌幅\"等聚合后数据是否存在——聚合结果是公式计算产出的，不是预置数据集\r\n2. **行业名称原样复用**：最终答案中的行业名称必须与工具返回的完全一致（如工具返回\"公用事业\"，不得改写为\"公共事业\"）\r\n3. **TopN 安全读取**：行业聚合结果通常为 31 行（申万一级），可安全使用 `readData(mode=\"last_column_full\")`；但若聚合维度更细（二级行业/概念板块），必须先用 `readData(mode=\"precheck\")` 确认行数\r\n\r\n---\r\n\r\n## 语义恒等：申万一级行业最近一个月涨跌幅排名 TopN\r\n\r\n### 用户意图\r\n> \"请统计申万一级行业中，最近一个月涨跌幅排名前5的行业，并列出各行业月涨幅。\"\r\n\r\n### 正确思路\r\n1. \"最近一个月\"若未特别说明，默认按近 20 个交易日处理\r\n2. \"月涨幅 / 最近一个月涨跌幅\"应理解为**窗口累计涨跌幅**，不是 20 日日均回报\r\n3. 先计算个股近 20 日涨跌幅，再按申万行业做成分平均汇总\r\n\r\n### 正确公式\r\n```\r\n申万行业近20日涨跌幅 = 成分平均汇总(涨跌幅(\"全市场每日收盘价\", 20), \"申万资产所属指数\")\r\n```\r\n\r\n### 易错写法（不要用）\r\n```\r\n# ❌ 这两步算的是\"20日日均回报\"，不是\"20日涨跌幅\"\r\n申万行业每日回报率 = 成分平均汇总(\"全市场每日回报率\", \"申万资产所属指数\")\r\n申万行业月涨跌幅 = 平均(\"申万行业每日回报率\", 20)\r\n```\r\n> 上述结果是\"20日日均回报的算术平均\"（约 0.05%），不是\"20日区间涨跌幅\"（约 1%~5%）。用它回答\"月涨幅\"是语义错误。\n\nFile v4.14.18:recipes/ma-crossover-backtest.md\n\n# 示例一：均线策略选股 + 回测\r\n\r\n## 用户意图\r\n\r\n> \"帮我做一个5日均线上穿20日均线的选股策略，看看历史回测表现怎么样\"\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 0 — 初始化会话\r\n\r\n```bash\r\npython scripts/call.py newSession\r\n```\r\n\r\n---\r\n\r\n### Step 1 — 查案例（cases_index 优先）\r\n\r\n**1a. 读取 `presets/cases_index.yaml`**，搜索 tags 含 `均线`、`MA`、`金叉`、`回测` 的卡片。\r\n\r\n**1b.** 找到后调 `getCardFormulas` 批量拉取：\r\n\r\n```bash\r\npython scripts/call.py getCardFormulas '{\"card_ids\": [\"<相关卡片id>\"]}'  \r\n```\r\n\r\n**1c.** 目录中未找到才 fallback：\r\n\r\n```bash\r\npython scripts/call.py searchSimilarCases '{\"query\": \"均线金叉买入区间持仓回测\", \"top_k\": 3}'\r\n```\r\n\r\n**LLM 操作**：理解案例中均线/金叉公式结构，提炼思路后针对用户的 5/20 均线需求重新组织公式，不照抄案例。\r\n\r\n---\r\n\r\n### Step 2 — 确认数据名称\r\n\r\n```bash\r\npython scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日收盘价, 非ST股\"}'\r\n```\r\n\r\n**预期返回**：\r\n- `全市场每日收盘价` → `index_title: \"全市场每日收盘价\"`（dimension=two）\r\n- `非ST股` → `index_title: \"非ST股\"`（dimension=two, is_bool=true）\r\n\r\n**LLM 操作**：用返回的 `index_title` 写进公式，不要用原始查询词。\r\n\r\n---\r\n\r\n### Step 3 — 执行公式（生成信号 + 回测）\r\n\r\n```bash\r\npython scripts/call.py runMultiFormula '{\r\n  \"task_id\": \"<Step 0 的 task_id>\",\r\n  \"begin_date\": 20150101,\r\n  \"formulas\": [\r\n    \"MA5=平均(\\\"全市场每日收盘价\\\", 5)\",\r\n    \"MA20=平均(\\\"全市场每日收盘价\\\", 20)\",\r\n    \"金叉信号=(\\\"MA5\\\">\\\"MA20\\\")*(昨天(\\\"MA5\\\")<=昨天(\\\"MA20\\\"))*板块(万得全A)*缺失填零(\\\"非ST股\\\")\",\r\n    \"死叉信号=(\\\"MA5\\\"<\\\"MA20\\\")*(昨天(\\\"MA5\\\")>=昨天(\\\"MA20\\\"))*板块(万得全A)*缺失填零(\\\"非ST股\\\")\",\r\n    \"持仓区间=进出场区间(\\\"金叉信号\\\",\\\"死叉信号\\\")\",\r\n    \"NAV=回测(\\\"持仓区间\\\",当天收盘买入,返回复利净值,信号按列归一)\"\r\n  ],\r\n  \"intents\": [\"5日均线\", \"20日均线\", \"金叉信号（排除ST）\", \"等权回测净值\"]\r\n}'\r\n```\r\n\r\n**关键点**：\r\n- 4 个公式共享同一个 `task_id`，后面的公式才能引用前面的变量\r\n- 返回每条公式的 `data_id`，记录 `NAV` 对应的 `data_id`\r\n\r\n---\r\n\r\n### Step 4 — 验证回测结果\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<NAV的data_id>\"], \"mode\": \"precheck\"}'\r\n```\r\n\r\n**预期返回**：\r\n```json\r\n{\r\n  \"type\": \"nav_1d\",\r\n  \"first_value\": 1.0,\r\n  \"last_value\": 3.xx,\r\n  \"total_return\": 2.xx,\r\n  \"curve_samples\": [[20150101, 1.0], ..., [20260227, 3.xx]]\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 5（可选）— 渲染净值曲线图\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"均线金叉策略净值（2015至今）\",\r\n  \"lines\": [{\"id\": \"<NAV的data_id>\", \"name\": \"MA5/20金叉策略\"}],\r\n  \"width\": 1400,\r\n  \"height\": 600\r\n}'\r\n```\r\n\r\n**LLM 操作**：返回 `data.base64`，解码后保存为 PNG 文件，或直接展示给用户。\r\n\r\n---\r\n\r\n## 常见错误与处理\r\n\r\n| 错误 | 原因 | 处理 |\r\n|------|------|------|\r\n| `公式变量未找到` | task_id 不一致，Signal 找不到 MA5 | 确保 4 个公式用同一个 task_id |\r\n| `数据名不存在` | 公式里写的名称和 confirmDataMulti 返回的 index_title 不一致 | 以 index_title 为准 |\r\n| `matchQuality=low` | searchSimilarCases 没搜到好模板 | 换 query 关键词重试一次 |\n\nFile v4.14.18:recipes/render-chart.md\n\n# 示例四：生成多策略净值对比图\r\n\r\n## 用户意图\r\n\r\n> \"我已经跑了两个策略的回测，帮我把净值曲线画成一张图，并和沪深300比较\"\r\n\r\n---\r\n\r\n## 前置条件\r\n\r\n假设已通过 `runMultiFormula` 得到以下 `data_id`：\r\n- 策略A净值：`nav_aaa111`\r\n- 策略B净值：`nav_bbb222`\r\n- 沪深300净值：`nav_ccc333`\r\n\r\n如果还没跑，先参考示例一（均线策略）或示例二（低PE策略）的 Step 3~4。\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 1 — 验证三条净值曲线的基本情况\r\n\r\n```bash\r\npython scripts/call.py readData '{\r\n  \"ids\": [\"nav_aaa111\", \"nav_bbb222\", \"nav_ccc333\"],\r\n  \"mode\": \"precheck\",\r\n  \"sample_points\": 50\r\n}'\r\n```\r\n\r\n**LLM 操作**：\r\n- 确认三条曲线的起止日期一致（都从 `begin_date` 开始）\r\n- 检查 `last_value` 对比，判断哪个策略更优\r\n- 若曲线出现异常（如 last_value=0 或 NaN 率过高），先排查公式错误\r\n\r\n---\r\n\r\n### Step 2 — 渲染对比图\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"策略A vs 策略B vs 沪深300 净值对比\",\r\n  \"lines\": [\r\n    {\"id\": \"nav_aaa111\", \"name\": \"策略A：均线金叉\", \"axis\": \"left\"},\r\n    {\"id\": \"nav_bbb222\", \"name\": \"策略B：低PE 20%\", \"axis\": \"left\"},\r\n    {\"id\": \"nav_ccc333\", \"name\": \"沪深300基准\", \"axis\": \"left\"}\r\n  ],\r\n  \"width\": 1400,\r\n  \"height\": 600,\r\n  \"start_date\": 20150101\r\n}'\r\n```\r\n\r\n**预期返回**：\r\n```json\r\n{\r\n  \"success\": true,\r\n  \"data\": {\r\n    \"base64\": \"iVBORw0KGgoAAAANSUhEUgAA...\",\r\n    \"lines_count\": 3,\r\n    \"width\": 1400,\r\n    \"height\": 600,\r\n    \"errors\": []\r\n  }\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 3 — 保存图片（Python 示例）\r\n\r\nLLM 可以把 base64 解码并保存：\r\n\r\n```python\r\nimport base64\r\nb64 = \"<返回的 base64 字符串>\"\r\nwith open(\"strategy_comparison.png\", \"wb\") as f:\r\n    f.write(base64.b64decode(b64))\r\nprint(\"图片已保存到 strategy_comparison.png\")\r\n```\r\n\r\n---\r\n\r\n## 二维数据绑定资产（非净值曲线的画法）\r\n\r\n如果要画某只个股的价格走势（二维数据中的某一列），需要额外传 `ticker`：\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"贵州茅台收盘价\",\r\n  \"lines\": [\r\n    {\"id\": \"<收盘价data_id>\", \"name\": \"600519.SH\", \"axis\": \"left\", \"ticker\": \"600519.SH\"}\r\n  ]\r\n}'\r\n```\r\n\r\n---\r\n\r\n## 注意事项\r\n\r\n| 场景 | 处理 |\r\n|------|------|\r\n| `errors` 非空 | 某条 line 的 id 不存在或数据类型不支持渲染 |\r\n| 净值曲线起点不一致 | 用 `start_date` 截断至同一起点再渲染 |\r\n| 图片太小看不清 | 调大 `width`（最大建议 1800）和 `height`（最大建议 900） |\r\n| 需要左右双轴 | 把量纲差异大的曲线（如换手率 vs 净值）设为 `\"axis\": \"right\"` |\n\nArchive v4.14.17: 53 files, 241801 bytes\n\nFiles: config.json (125b), presets/assets.yaml (6136b), presets/cases_index.yaml (29693b), presets/data_catalog.yaml (9071b), presets/functions.yaml (15093b), presets/sectors.yaml (17186b), presets/themes.yaml (17784b), recipes/download-data.md (1168b), recipes/event-study-formulas.md (7363b), recipes/ic-factor-templates.md (3309b), recipes/industry-aggregation.md (11787b), recipes/ma-crossover-backtest.md (3518b), recipes/render-chart.md (2750b), recipes/tool-call-checklist.md (3406b), recipes/topn-gainers.md (1637b), recipes/upload-custom-data.md (3235b), recipes/value-pe-strategy.md (3569b), references/environment.md (1981b), references/ru-billing.md (1838b), references/scripts-audit.md (3903b), references/troubleshooting.md (5426b), scripts/call.py (28640b), scripts/event_study_local.py (9796b), scripts/executor.py (34384b), scripts/quant_api.py (16993b), SKILL.md (30145b), tools/confirm_data_multi.md (4182b), tools/confirm_multiple_assets.md (3940b), tools/download_data.md (2736b), tools/get_card_formulas.md (3076b), tools/read_data.md (6729b), tools/render_chart.md (7609b), tools/render_kline.md (5928b), tools/run_multi_formula.md (10865b), tools/scan_dimensions.md (4772b), tools/search_functions.md (2881b), tools/search_similar_cases.md (2300b), tools/upload_data.md (3434b), workflows/event-study.md (48784b), workflows/fast-report-period.md (4755b), workflows/fast-snapshot.md (3201b), workflows/fast-window.md (3420b), workflows/global-rules-lite.md (3241b), workflows/global-rules.md (38159b), workflows/period-return-compare.md (7290b), workflows/quant-standard.md (60548b), workflows/quick-lookup.md (9777b), workflows/quick-report-period.md (23455b), workflows/quick-snapshot.md (19388b), workflows/quick-window.md (26309b), workflows/regime-segmentation.md (21897b), workflows/render-kline.md (12281b), _meta.json (138b)\n\nFile v4.14.17:SKILL.md\n\n---\r\nname: quant-buddy-skill\r\nslug: quant-buddy-skill\r\nauthor: guanzhao\r\nversion: 4.14.17\r\ndescription:\r\n  查询A股、港股、美股股票及指数的最新收盘价、开盘价、涨跌幅、成交额、成交量、换手率、PE、PB、市值等实时行情与估值数据。\r\n  查询最近N个交易日的价格序列、日涨跌幅序列、窗口最高价、最低价、振幅等短期统计。\r\n  查询上市公司最近报告期的营业收入、净利润、归母净利润、ROE、总资产、资产负债率等财务指标（A股）。\r\n  支持A股选股筛选、因子计算、策略回测、净值对比、行业聚合排名、上传自有因子CSV、渲染图表。\r\n  港股、美股目前支持行情价格查询（收盘价、开盘价、涨跌幅、成交量、成交额等）。\r\n  即使用户只是简单地问一只股票的价格、涨跌幅或财务数据，也应优先使用本技能，\r\n  不要以\"无法联网\"或\"无法获取实时数据\"为由拒绝——本技能通过平台API可查询真实数据。\r\nruntime: python\r\nprimaryCredential: quant-buddy API Key\r\nrequiredCredentials:\r\n  - name: quant-buddy API Key\r\n    required: true\r\n    sensitive: true\r\n    storage: config_file\r\n    path: config.json\r\n    field: api_key\r\n    description: quant-buddy 平台 API Key。存储位置：skill 目录下的 config.json 的 `api_key` 字段（本 skill 不读环境变量版本的该 Key）。使用时作为 HTTP `Authorization` 头仅发送给 `networkEndpoints` 中声明的 quantbuddy 域名用于鉴权，不会被写入日志或转发给第三方主机。\r\n    how_to_get: \"https://www.quantbuddy.cn/login\"\r\nrequiredConfigPaths:\r\n  - path: config.json\r\n    required: true\r\n    description: Skill 目录下的 API Key 配置文件，仅包含 quant-buddy api_key 和两个公开端点配置，由 skill 本地脚本读取；api_key 仅作为 HTTP `Authorization` 头发给 `networkEndpoints` 中声明的 quantbuddy 域名，不发送给其他主机。\r\nrequiredEnvVars:\r\n  - name: BOCHA_API_KEY\r\n    required: false\r\n    sensitive: true\r\n    description: 可选。仅 scripts/event_study_local.py 的事件新闻搜索功能读取；未配置时该可选功能自动禁用，其它功能不受影响。\r\n    how_to_get: \"https://open.bochaai.com\"\r\nnetworkAccess: true\r\nnetworkEndpoints:\r\n  - https://www.quantbuddy.cn/skill\r\n  - https://www.quantbuddy.cn/user\r\nruntimeRequirements:\r\n  python: \"3.8+\"\r\n  packages:\r\n    - name: python-dateutil\r\n      version: \">=2.8\"\r\n      required: false\r\n      description: Used by scripts/event_study_local.py for the optional event-study / Bocha news feature. Not needed if BOCHA_API_KEY is not configured.\r\n    - name: Pillow\r\n      version: \">=9.0\"\r\n      required: false\r\n      description: Used by scripts/call.py saveChart command to convert chart images to JPEG. Falls back gracefully (writes raw bytes) if not installed; no credential exposure risk.\r\n---\r\n\r\n# 观照量化投研\r\n\r\n> **⚠️ 必读：本文件较长，必须完整读取，不要设置 limit 参数截断。前 50 行不包含操作规范。**\r\n\r\n## 硬规则（7 条，违反必失败）\r\n\r\n0. **开工第一步：先查 API Key，再做任何其他事**。收到新问题后的第一个动作必须是读 `config.json`（或等效检查 api_key 字段）：\r\n   - 若 `api_key` 为空字符串 → **立即停止**，直接输出「前置条件」章节的**新用户引导消息**，**禁止** newSession、**禁止**读 workflow / quick-lookup / 任何业务文档、**禁止**调用 `scripts/call.py` 或任何平台工具。等用户贴入 `sk-` 开头的 Key 后再执行「配置向导」。\r\n   - 若 `api_key` 非空 → 继续第 1 条。\r\n   - **唯一例外**：用户本轮消息本身就是 `sk-` 开头的 Key（进入配置向导）或与查数无关的闲聊/元问题（如\"你会做什么\"）。\r\n   - **为什么**：查数类工作流最终都会调 `scripts/call.py`，api_key 为空时必然失败。提前在入口拦截可以避免多次失败调用，给新用户直接、清晰的第一印象。\r\n\r\n1. **每个新问题/新对话必须新建 session**：收到用户的新问题后，在调用任何平台工具之前，必须先新建 session（优先直接调用原生 `newSession` 工具；仅当当前环境没有原生 `newSession` 时，才使用 `GZQ_PARAMS='{\"user_query\":\"<用户的问题>\"}' python scripts/call.py newSession`）。newSession 是本地 UUID 生成，不可省略；`user_query` 仅用于本地 session 初始化标注，方便后续 trace 分析。\r\n   - **为什么**：`.session.json` 会自动注入到所有工具调用中。不新建 session = 复用上一轮对话的 task_id = 变量名冲突风险 + session 污染。\r\n   - **唯一例外**：同一对话中的追问/续问（如\"再画个图\"\"换个时间段\"），可复用当前 session。\r\n2. **原生工具优先，脚本包装仅限无原生等价能力时**：平台已提供的原生工具（`confirmMultipleAssets`、`confirmDataMulti`、`runMultiFormula`、`readData`、`renderKLine`、`renderChart` 等）必须优先直接调用；禁止用 `run_skill_script`、shell 命令、`GZQ_PARAMS=... python scripts/call.py ...` 等方式包装这些原生工具；`scripts/call.py` 仅用于：① `newSession` 等管理动作；② workflow 明确要求的本地脚本步骤；③ 平台不存在等价原生工具时的兜底。\r\n3. **先读 workflow 再操作**：按下方「场景路由」表加载对应 workflow，不要自行猜测参数格式。\r\n4. **配置/认证错误立即停止，不得在普通查数流程中转为认证收集**：\r\n   - **工具返回 API Key 缺失错误**（含 `api_key 为空` 消息 / `code: 1`）：立即停止查数，输出**新用户引导消息**（格式见「前置条件」章节模板），禁止继续执行查数；等待用户粘贴 Key 后再执行配置向导。\r\n   - **其他工具报错**（网络、服务端错误等）：直接报告\"内部工具异常\"，不做认证相关引导。\r\n5. **最终答案首句必须是数据结论**：回答用户时，第一句话必须直接给出数据结论（如资产名+数值、表格、或\"符合条件的共N只\"），绝对禁止以\"已成功获取\"\"数据已获取\"\"根据返回结果\"\"让我来\"等过程性陈述开头。违反此规则 = 必须删除过程话术后重新输出。\r\n6. **用户条件冻结，不得改写**：执行前必须逐字核对用户原始条件，以下改写行为均属违规（一旦发现必须回退并重新确认）：\r\n   - **百分比↔小数互转**（如\"股息率>3%\"禁止改写为 `>0.03`）\r\n   - **相对时间改为年份区间**（如\"过去10年\"禁止改写为\"2015-2025\"）\r\n   - **资产宇宙替换**（如\"普通股票\"禁止改写为\"万得全A成分股\"或\"非ST股\"）\r\n   - **事件口径扩大**（如\"年报/半年报\"禁止扩大为全部业绩披露类型）\r\n   - **卡片附加条件继承**：命中知识卡片后，若卡片含用户未明确提出的\"首次/非ST/封板/流动性门槛\"等附加条件，必须先删除再执行，禁止默默继承进最终答案\r\n\r\n## 最小充分原则（任何动作前自检）\r\n\r\n> 默认走最窄路径；只在收到\"明确不够用\"的证据后，才扩大范围。\r\n\r\n**每次准备读文件、调工具、扩大读取范围前，回答三个问题**：\r\n\r\n1. **这一步要解决的具体问题是什么？** — 必须能用一句话写成\"为了 X，所以做 Y\"，其中 X 是**已经发生**的需求，不能是\"可能会需要 X\"、\"以防万一\"、\"先准备着\"。\r\n2. **有没有更窄的选项能完成同样的 X？** — 更下游的输出 / 更精简的文件 / 更少的字段 / 不调用这个工具直接构造。\r\n3. **当前选择如果失败，下一步是什么？** — 如果答不上来，说明还没想清楚就在动手。\r\n\r\n任一回答含糊 → 不做这一步。\r\n\r\n**扩大范围的唯一合法触发**：上一步工具明确返回了\"缺数据 / 字段不存在 / 失败\"，且失败原因可以追溯。不允许用\"为了更全面\"、\"为了更准确\"、\"为了避免遗漏\"作为理由。\r\n\r\n> 这条原则覆盖：要不要多读一个文档；readData 读哪个变量；要不要为某个字段调 confirmDataMulti；公式自己写还是查现成数据集；以及所有未来出现的同类决策。\r\n\r\n**工具层面落地**：调用 `confirmDataMulti` / `readData` / `runMultiFormula` 或加载额外文档前，必须先勾选 [`recipes/tool-call-checklist.md`](recipes/tool-call-checklist.md) 对应小节（每节 5–10 行）。顶层原则管\"要不要做\"，清单管\"具体怎么做\"。\r\n\r\n## Skill 包根目录\r\n\r\n**本 SKILL.md 所在目录即为 skill 根目录（`SKILL_ROOT`）**，下文所有相对路径均以此为基准。\r\n所有终端命令必须先 `cd` 到此目录再执行。\r\n\r\n```\r\nSKILL_ROOT/\r\n├── config.json              ← API Key 配置（按需读取；非每题必读）\r\n├── SKILL.md                 ← 本文件（入口 + 路由）\r\n│\r\n├── workflows/               ← 业务流程编排（路由目标）\r\n│   ├── fast-snapshot.md         Fast Path：最新时点行情/估值（≤3资产，标量）\r\n│   ├── fast-window.md           Fast Path：最近N日序列/窗口统计\r\n│   ├── fast-report-period.md    Fast Path：最近报告期财务（≤3资产）\r\n│   ├── quick-lookup.md          快速查数路由器 + 共享基础规则\r\n│   ├── quick-snapshot.md        最新时点行情/估值快照（字段齐即停）\r\n│   ├── quick-window.md          最近N日短窗序列/窗口统计\r\n│   ├── quick-report-period.md   最近报告期财务指标\r\n│   ├── period-return-compare.md 固定区间累计涨跌幅对比\r\n│   ├── global-rules-lite.md     精简全局规则（quick-window/period-return-compare 专用）\r\n│   ├── quant-standard.md        选股/回测/因子/图表标准流程\r\n│   ├── event-study.md           事件研究（给定或可识别事件后的窗口表现）\r\n│   ├── regime-segmentation.md   阈值区间/连续阶段识别与区间统计\r\n│   └── render-kline.md          K线图渲染与交付\r\n│\r\n├── recipes/                 ← 公式模板 & 工具用法（被 workflow 引用）\r\n│   ├── ma-crossover-backtest.md     均线金叉策略\r\n│   ├── value-pe-strategy.md         PE估值选股\r\n│   ├── upload-custom-data.md        上传自有数据\r\n│   ├── render-chart.md              渲染图表\r\n│   ├── download-data.md             下载数据\r\n│   └── industry-aggregation.md      行业聚合排名\r\n│\r\n├── references/              ← 参考文档\r\n│   ├── environment.md           环境依赖\r\n│   ├── troubleshooting.md       故障排查\r\n│   └── ru-billing.md            RU 计费\r\n│\r\n├── tools/                   ← 12 个 API 工具的完整参数文档\r\n│   ├── run_multi_formula.md\r\n│   ├── read_data.md\r\n│   └── ...（正常链路无需提前阅读，遇到参数问题时查）\r\n│\r\n├── presets/                 ← 已验证的常用数据（按需加载）\r\n│   ├── cases_index.yaml         106 张案例卡片目录（量化标准场景必读，快速查数无需）\r\n│   ├── assets.yaml              常用资产\r\n│   ├── functions.yaml           常用函数\r\n│   ├── data_catalog.yaml        常用数据集\r\n│   ├── sectors.yaml             行业板块\r\n│   └── themes.yaml              题材板块\r\n│\r\n├── scripts/                 ← 执行脚本\r\n│   ├── call.py                  工具统一入口（所有命令通过它调用）\r\n│   ├── executor.py              call.py 的底层（禁止直接调用）\r\n│   ├── quant_api.py             Python SDK（供其他脚本 import）\r\n│   ├── auth/                    认证脚本\r\n│   └── eval/                    评测脚本\r\n│\r\n└── output/                  ← 输出目录（自动创建）\r\n    ├── .session.json            当前 session task_id\r\n    ├── ic_data/                 IC 扫描结果\r\n    └── *.png / *.csv            图表和数据文件\r\n```\r\n\r\n---\r\n\r\n**全局 429 处理（所有路径均适用）**：\r\n\r\n| error.code | 处理 |\r\n|---|---|\r\n| `RATE_LIMIT_EXCEEDED` / `CONCURRENT_LIMIT` | 读 `retryAfter` 秒后**静默重试**，不向用户暴露 |\r\n| `WINDOW_QUOTA_EXCEEDED` | **立即停止**，读 `references/troubleshooting.md` 配额限流段，输出提示 |\r\n| `DAILY_QUOTA_EXCEEDED` / `DAILY_SCAN_EXCEEDED` | **立即停止**，输出：`⚠️ 今日额度已满，次日 00:00 重置。` |\r\n| `SERVICE_OVERLOADED`（503） | `retryAfter` 秒后静默重试 1 次，仍失败则告知\"系统繁忙，请稍后重试\" |\r\n\r\n---\r\n\r\n## ⛔ 执行顺序（路由前必读，所有场景必须遵守）\r\n\r\n**无论匹配到哪个 leaf workflow，执行顺序固定为：**\r\n\r\n```\r\n① read_skill_file(global-rules 版本，见下表)  →  ② read_skill_file(leaf workflow)  →  ③ 执行\r\n```\r\n\r\n**步骤 ① 全局规则文件选择（按目标 leaf workflow 确定）**：\r\n\r\n| 目标 leaf workflow | 步骤 ① 读取的文件 |\r\n|---|---|\r\n| `quick-window.md` | `workflows/global-rules-lite.md` |\r\n| `period-return-compare.md` | `workflows/global-rules-lite.md` |\r\n| 其他所有 workflow | `workflows/global-rules.md` |\r\n\r\n- **步骤 ① 是硬前置条件**。确定目标 leaf 后，先按上表选择并读取对应 global-rules 版本，再读 leaf workflow，最后执行。\r\n- 禁止读完路由表就直接跳转 leaf workflow（Fast Path 中读 fast 文件除外）。\r\n\r\n---\r\n\r\n## 场景路由\r\n\r\n**先识别用户意图，确定目标 leaf workflow；然后按上方执行顺序加载**：\r\n\r\n| 场景 | 触发词 | 目标 leaf workflow |\r\n|------|--------|----------|\r\n| 最新时点行情 / 估值（快照） | 最新价、今日收盘、最新涨跌幅、当前换手率、最新PE/PB/市值… | Fast Path → `fast-snapshot.md` / 完整链路 → `global-rules.md` → `quick-snapshot.md` |\r\n| 最近N日序列 / 窗口统计 | 最近5日、最近20日、近N个交易日、窗口最高/最低/振幅…（仅单资产、最近N日） | Fast Path → `fast-window.md` / 完整链路 → `global-rules-lite.md` → `quick-window.md` |\r\n| 最近报告期财务 | 营收、净利润、归母净利润、ROE、总资产、总负债、资产负债率… | Fast Path → `fast-report-period.md` / 完整链路 → `global-rules.md` → `quick-report-period.md` |\r\n| K线图（可视化） | K线图、画图、展示走势… | `global-rules.md` → `render-kline.md` |\r\n| 固定区间累计涨跌幅 | 从A到B、某年某月至某年某月、区间收益、累计涨跌幅、区间表现、多资产区间对比 | `global-rules-lite.md` → `period-return-compare.md` |\r\n| 量化选股 / 回测 / 因子 / 图表 / 上传下载 | 选股、回测、均线、PE选股、因子、净值、上传CSV、下载数据、画图… | `global-rules.md` → `quant-standard.md` |\r\n| 事件研究 | 复盘、历次、涨价、降息、加息、事件窗口、随后表现、超预期、不及预期、政策后表现…（给定事件或需先识别事件日） | `global-rules.md` → `event-study.md` |\r\n| 阈值区间统计 / 连续阶段 | 历次、每次、平均、回撤超过、从高点下跌超过、熊市区间、连续阶段、regime | `global-rules.md` → `regime-segmentation.md` |\r\n\r\n> 上传、下载、画图不是独立场景——它们是 workflow 内的子步骤，workflow 文档会在需要时指引你读对应的 `recipes/`。\r\n\r\n### 路由硬排除（优先于触发词匹配）\r\n\r\n以下规则在触发词匹配**之前**检查，命中即强制改道，不得被触发词覆盖：\r\n\r\n| 用户意图特征 | 禁止进入 | 强制导向 | 判断依据 |\r\n|-------------|---------|---------|---------|\r\n| 盘中/实时/当前/现在/今天/今日/当日 + 查询日内行情（涨幅排名、涨停、日内跌幅等） | `quick-snapshot` `quick-window` | `quant-standard.md`（优先匹配分钟频卡片） | 需要分钟频卡片的专用公式；`use_minute_data: true` 已是全局默认 |\r\n| 盘中/实时/当前/今天/今日/当日 + 全市场/板块 + TopN/排名/阈值名单/选股/筛选/信号 | `quick-snapshot` `quick-window` | `quant-standard.md` → 优先命中\"实时横截面 TopN 排名\"或\"盘中阈值筛选_名单查询\"微流程 | 这类高频短题有专用封闭微流程 |\r\n| 给出明确起止日期，只问区间累计涨跌幅/收益 | `event-study` `quick-window` `quant-standard` | `period-return-compare.md` | 本质是固定区间收益比较，不是因果窗口分析，也不是复杂量化流程 |\r\n| 行业/板块聚合排名（如\"申万行业涨幅前5\"） | `quick-window` `quick-snapshot` | `quant-standard.md` | 需要横截面聚合，不是单资产序列 |\r\n| 阈值触发型离散事件识别（如\"跌幅超过X%的次数\"，问每次后表现） | — | `event-study.md`（阈值触发模式） | 需先识别阈值事件日，再做窗口分析 |\r\n| 由阈值条件定义连续区间（如\"历次熊市\"\"回撤超30%的阶段\"） | `event-study` | `regime-segmentation.md` | 研究的是连续阶段而非离散事件后的窗口 |\r\n| \"创近N日新高/新低\"（不含\"首次\"修饰词） | 不得加\"昨日未满足\"条件 | 按**当前状态**判断（state check），公式只比较当前值与昨日的N日极值 | 只有用户明确出现\"首次突破/首次跌破\"\"新晋\"\"今日第一次\"时，才允许追加首次触发条件；详见 `quant-standard.md` |\r\n\r\n判断口诀：\r\n- **有明确起止日 + 只问区间数值** → `period-return-compare`（固定区间收益比较）\r\n- **有事件 + 问\"随后N天/月表现\"** → `event-study`（因果窗口）\r\n- **有阈值条件 + 问\"每次发生后表现\"** → `event-study`（阈值触发模式）\r\n- **有阈值条件 + 问\"连续阶段/区间内表现\"** → `regime-segmentation`（连续阶段统计）\r\n\r\n若用户请求满足以下任一模式，应优先判定为【快速查数任务】，按以下路由直接跳转，不得先进入其他 workflow：\r\n\r\n**快速查数路由（按优先级依次判断，首个匹配即停）：**\r\n\r\n1. 时间锚点是\"最近 N 日窗口/序列\" → Fast Path 条件满足时读 `workflows/fast-window.md`，不满足则 `workflows/global-rules-lite.md` → `workflows/quick-window.md`\r\n2. 时间锚点是\"最近报告期\"且字段属于财务类 → Fast Path 条件满足时读 `workflows/fast-report-period.md`，不满足则 `workflows/global-rules.md` → `workflows/quick-report-period.md`\r\n3. 用户明确要\"画图 / K线 / 带成交量走势\" → 直接加载 `workflows/render-kline.md`\r\n4. 其余（明确是最近完成交易日的行情/估值/多资产对比，且**不含** 今天/今日/当日/当前/现在/实时/盘中/排名/筛选 语义）→ Fast Path 条件满足时读 `workflows/fast-snapshot.md`，不满足则 `workflows/global-rules.md` → `workflows/quick-snapshot.md`\r\n\r\n> 上述路由不需要先读 `workflows/quick-lookup.md`。\r\n\r\n### 关键红线速查（即使未读 global-rules.md 也必须遵守）\r\n\r\n以下 4 条规则从 global-rules.md 摘录，**优先级最高**，对所有场景生效：\r\n\r\n1. **事件定义冻结**：事件类型/范围必须**逐字匹配用户原始措辞**。用户说\"年报/半年报\"就只查年报和半年报，不得扩大到业绩预告/快报/季报；用户说\"国务院或住建部\"就只纳入该层级，不得扩大到央行/银保监会/地方政府。若认为用户定义可能遗漏，在回答末尾**建议**扩大，不得擅自扩大。\r\n2. **evidence-only 回答**：最终答案只输出本轮工具结果直接支持的数值、日期、排名、口径说明。未经工具验证，禁止默认输出宏观归因、政策归因、方向性判断（\"通常\"\"往往\"\"偏正面\"）。\r\n3. **去过程化交付**：禁止「已成功获取」「让我来」「按照流程」「Step 1/2/3」「根据 workflow」等过程性话术；禁止泄露 `_working/` 路径、checkpoint 名称、workflow 文件名。查到即答，不展示内部过程。\r\n4. **条件口径冻结**：用户条件必须原样执行，禁止任何改写（百分比↔小数、相对时间→年份区间、资产宇宙替换、卡片附加条件继承）。详见硬规则第 6 条。\r\n\r\n触发词参考：\r\n- 最近交易日收盘 / 最新已披露PE / 最新市值（非盘中、非筛选） → `quick-snapshot`\r\n- 最近5日 / 最近20个交易日 / 近N日序列 / 窗口最高最低 → `quick-window`\r\n- 营收 / 净利润 / ROE / 总资产 / 总负债 / 资产负债率 → `quick-report-period`\r\n\r\n禁止：\r\n- 优先调用 `scanDimensions`、`renderKLine`（除非用户明确要看图）\r\n- 先做分析性扩写，再补充结构化数值\r\n- **在读取对应 leaf workflow 之前**直接调用 `runMultiFormula` / `renderKLine` / `scanDimensions` / 输出\"无法联网\"或\"无法获取实时数据\"\r\n- 把卡片附加条件（首次/非ST/封板/流动性门槛等）默默继承进最终答案\r\n- 以 `description`、`samples`、预览行、截断大表作为**名单题**的完整结果直接收尾（必须提取完整名单或明确声明不完整）\r\n\r\n**leaf workflow 最终回答合同优先**：leaf workflow 中的\"最终回答合同\"优先负责收紧该场景的输出格式；若 leaf workflow 已满足停止条件，必须直接按该合同输出，不得再解释内部过程。\r\n\r\n## 执行权授权规则\r\n\r\n**规则层级（从高到低）：**\r\n\r\n1. **SKILL.md**：路由 + 全局门禁（硬规则 4 条、路由硬排除）\r\n2. **global-rules.md**：所有 leaf 必须遵守的全局合同（执行合同、证据分级、简答模式、不补精度、方法限制说明、参数规范、数值精度、终答一致性检查）\r\n3. **leaf workflow**：当前任务的具体执行流程（checkpoint、模板、停止条件、格式化）\r\n\r\n**冲突解决**：\r\n- leaf workflow 中的具体规则（如 readData 模式选择）优先于 global-rules 的一般规则\r\n- 但 leaf workflow 不得**放宽** global-rules 的红线（如证据分级门槛、不补精度原则）\r\n- 不得从其他 leaf workflow 借用模板、fallback 或回答格式\r\n\r\n**quick-lookup.md 的定位**：\r\n- 仅作为快查子流程的路由入口和规则参考总表\r\n- 各 leaf workflow 已自包含所有执行规则，执行时无需回到 quick-lookup.md\r\n- quick-lookup.md 不定义任何 leaf 独有规则\r\n\r\n## 全局执行规则\r\n\r\n> **全局合同详见 `workflows/global-rules.md`，进入任何 leaf workflow 时自动生效。**\r\n> leaf workflow 可在其内部添加更严格的约束，但不得豁免或放宽 global-rules 中的规则。\r\n\r\n## 平台数据覆盖范围\r\n\r\n| ✅ 支持 | ⚠️ 有条件支持 | ❌ 不支持（短期内不会支持） |\r\n|------|------|------|\r\n| A股个股（沪深主板/创业板/科创板/北交所） | ETF / LOF / 场外基金（先以 `confirmMultipleAssets` 结果为准，能确认则正常执行；确认失败才告知不支持） | 期货 / 期权 |\r\n| 港股个股（HK + 代码，如 HK0001） | | 台股 / 韩股 / 日股 / 德股等其他境外市场 |\r\n| 美股个股（NASDAQ: 代码.N；NYSE: 代码.O；AMEX: 代码.A） | | |\r\n| 主要宽基指数（沪深300、中证500、万得全A等） | | |\r\n\r\n> **港股 / 美股数据范围限制**：港股和美股目前仅支持**行情价格类数据**（收盘价、开盘价、最高价、最低价、涨跌幅、成交量、成交额）。估值数据（PE/PB/市值等）和财务数据（营收/净利润/ROE等）暂不支持。查询港股/美股的估值或财务字段时，应主动告知用户当前不支持，而不是静默跳过。\r\n\r\n### 股票代码格式速查\r\n\r\n| 市场 | 格式 | 示例 |\r\n|------|------|------|\r\n| A股-上交所 | SH + 代码 | SH600000 |\r\n| A股-深交所 | SZ + 代码 | SZ000001 |\r\n| 港股 | HK + 代码 | HK0001 |\r\n| 美股-NASDAQ | 代码.N | AAPL.N |\r\n| 美股-NYSE | 代码.O | AAL.O |\r\n| 美股-AMEX | 代码.A | SBE.A |\r\n\r\n> 确认资产失败（熔断规则）详见 `workflows/quick-lookup.md` § Step 1。\r\n\r\n> 环境依赖（Python版本、Playwright、API Key）→ `references/environment.md`\r\n> 故障排查 → `references/troubleshooting.md`\r\n> RU 计费 → `references/ru-billing.md`\r\n\r\n---\r\n\r\n## 前置条件（按需执行，不是简单查数的默认首步）\r\n\r\n> **凭据存储说明**：本 skill 的 quant-buddy API Key **只存放在 skill 目录下的 `config.json` 的 `api_key` 字段**，不使用环境变量（`QUANT_BUDDY_API_KEY` 等环境变量不会被读取）。仅可选的 `BOCHA_API_KEY`（事件新闻搜索）走环境变量。\r\n\r\n仅在以下情形下，才需要显式读取 `config.json` 检查 `api_key`：\r\n- 本轮实际需要调用本地脚本或平台工具，且当前环境尚未建立可用 session\r\n- 上一轮工具调用已出现 401 / 402 / 明确认证错误\r\n- workflow 明确要求执行脚本链（如本地 Python 脚本渲染）\r\n\r\n对已命中 leaf workflow 的简单查数题（quick-snapshot / quick-window / quick-report-period / render-kline）：\r\n- 不要为了形式完整额外读取 `config.json`\r\n- 优先直接按 leaf workflow 执行\r\n- 仅当工具调用出现明确认证问题时，再回到认证向导\r\n\r\n原则：认证检查服务于执行，不应成为简单题的固定额外步骤。\r\n\r\n- 若 `api_key` **非空** → 正常继续\r\n- 若 `api_key` **为空** → **立即停止**，禁止继续查数，输出以下**新用户引导消息**（原样输出，不得删减）：\r\n\r\n  ---\r\n  ⚠️ 尚未配置 API Key，当前无法查询数据。\r\n\r\n  前往 https://www.quantbuddy.cn/login 登录/注册并获取 API Key，然后直接发给我：\r\n  > 帮我配置 APIkey：sk-xxxxxxxx\r\n  ---\r\n\r\n---\r\n\r\n### 配置向导（用户粘贴 Key）\r\n\r\n当用户消息中包含 `sk-` 开头的字符串时：\r\n\r\n1. 从用户消息中提取 `sk-` 开头的完整 Key 字符串\r\n2. 将 Key 写入 `config.json` 的 `api_key` 字段（用 `replace_string_in_file` 直接写入）\r\n3. **必须输出**：「✅ API Key 配置成功！」\r\n4. **自动重试**：若本对话中有被 api_key 缺失错误中断的查询（如之前用户问过行情），**立即重新执行该查询并给出数据结论**，不需要用户再次发起。\r\n\r\n**运行时 401/402** → 立即停止，提示用户 API Key 无效/过期/配额耗尽，请重新前往官网获取新的 Key 并重新配置。\r\n\r\n---\r\n\r\n## 工具调用方式\r\n\r\n所有工具通过 `scripts/call.py` 调用。`call.py` 会同时将结果打印到 stdout 和写入临时文件。\r\n\r\n### 标准调用（一步完成）\r\n\r\n```bash\r\npython scripts/call.py <工具名> '{\"key\":\"value\"}'\r\n```\r\n\r\n结果直接从 stdout 获取。若 stdout 被截断，可回读 `/tmp/gzq_out.txt`。\r\n\r\n也可通过环境变量传参（适用于参数含特殊字符的场景）：\r\n\r\n```bash\r\nGZQ_PARAMS='<JSON>' python scripts/call.py <工具名>\r\n```\r\n\r\n### 禁止事项\r\n\r\n| 禁止 | 原因 |\r\n|------|------|\r\n| 创建自定义 .py 写参数文件 | 环境变量方案已解决编码问题 |\r\n| 直接调用 `scripts/executor.py` | `call.py` 封装了 renderChart 自动保存等逻辑 |\r\n| `echo` 管道传参（Windows） | GBK 编码截断中文 |\r\n| 命令行参数传 JSON（Windows） | PS 吃掉双引号 |\r\n\r\n---\r\n\r\n## presets/、recipes/、tools/ 三个目录的分工\r\n\r\n| 目录 | 是什么 | 何时读 |\r\n|------|---------|--------|\r\n| **presets/** | 平台实际返回值的本地快照（YAML）。资产名、函数格式、数据集 index_title、行业/概念名等。**直接可用于公式**，省掉确认类 API 调用。 | 写公式前先查 preset；找不到再调对应 API，并把新结果补回 preset。`cases_index.yaml` 仅在**选股/回测/因子/图表等量化标准场景**（`quant-standard.md`）开始时必读；快速查数场景（quick-snapshot/window/report-period）无需读取。 |\r\n| **recipes/** | 端到端使用示例（Markdown）。展示完整场景——从参数准备到最终输出。 | 由 workflow 在具体步骤中指引加载（不独立触发）。 |\r\n| **tools/** | API 参数手册（Markdown）。每个工具的字段、类型、约束。 | 默认不读。workflow 工具表标注了「必读」或报错时再查。 |\r\n\r\n> **简言之**：presets 是数据快照，recipes 是完整教程，tools 是参数字典。\r\n> presets 6 个文件的详细用法和加载时机→ 当前 workflow 文档内的「预设资源」表。\r\n\r\n---\r\n\r\n## Skill 更新部署规范（LLM 必读）\r\n\r\n当用户要求更新本 skill（发送 zip 压缩包）时，必须严格遵守以下规则：\r\n\r\n### 备份位置\r\n\r\n⚠️ **备份目录禁止放在 `skills/` 目录下。** 否则 openclaw 会把备份也识别为一个独立 skill，导致后续请求可能误用旧版代码。\r\n\r\n正确做法：\r\n\r\n```bash\r\n# 备份到 skills/ 之外的位置\r\ncp -r ~/.openclaw/workspace/skills/quant-buddy-skill ~/.openclaw/workspace/quant-buddy-skill-backup-$(date +%Y%m%d%H%M)\r\n\r\n# ❌ 错误：备份仍在 skills/ 下\r\n# cp -r ~/.openclaw/workspace/skills/quant-buddy-skill ~/.openclaw/workspace/skills/quant-buddy-skill-backup-xxx\r\n```\r\n\r\n### 解压覆盖\r\n\r\n```bash\r\n# 解压到临时目录再拷贝（避免嵌套）\r\nTMPDIR=$(mktemp -d)\r\nunzip -o <压缩包路径> -d \"$TMPDIR\"\r\n# 如果解压出嵌套目录 quant-buddy-skill/，取内层\r\nif [ -d \"$TMPDIR/quant-buddy-skill\" ]; then\r\n  cp -rf \"$TMPDIR/quant-buddy-skill/\"* ~/.openclaw/workspace/skills/quant-buddy-skill/\r\nelse\r\n  cp -rf \"$TMPDIR/\"* ~/.openclaw/workspace/skills/quant-buddy-skill/\r\nfi\r\nrm -rf \"$TMPDIR\"\r\n```\r\n\r\n### 部署后检查\r\n\r\n1. 确认 `~/.openclaw/workspace/skills/` 下只有 `quant-buddy-skill/` 一个与本 skill 相关的目录\r\n2. 读取 `SKILL.md` 确认版本号\r\n3. 保留 `config.json` 中已有的 `api_key`（若用户之前已认证过）\n\nFile v4.14.17:_meta.json\n\n{\n  \"ownerId\": \"kn7b02063x75b1b8yswrzgesph858j2j\",\n  \"slug\": \"quant-buddy-skill\",\n  \"version\": \"4.14.17\",\n  \"publishedAt\": 1777018056188\n}\n\nFile v4.14.17:references/environment.md\n\n# 环境依赖说明\r\n\r\n本文档描述运行 `quant-buddy-skill` 及其子场景所需的环境配置。\r\n\r\n---\r\n\r\n## Python\r\n\r\n- **版本要求**：Python 3.8+（推荐 3.11）\r\n- **核心功能**：仅依赖标准库，无需额外 `pip install`\r\n- **Windows 推荐启动方式**：所有涉及中文路径的脚本加 `-X utf8` 标志\r\n\r\n```bash\r\npython -X utf8 scripts/call.py <工具名>\r\n```\r\n\r\n---\r\n\r\n## API Key 配置\r\n\r\n前往 https://www.quantbuddy.cn/login 登录/注册，在账户页面获取 API Key。获取后有两种方式写入：\r\n\r\n1. **手动编辑**：直接打开 skill 根目录下的 `config.json`，把 `api_key` 字段改为你的 Key。\r\n2. **贴给 AI 助手**：在对话中把 `sk-...` 开头的 Key 发给 AI，AI 会写入 `config.json`。\r\n\r\n若你需要保留私有配置或覆盖默认端点，请使用 `config.local.json`；该文件仅供本地使用，不应打包或提交。\r\n\r\n若出现 `401 Unauthorized` 或 `402 Quota`，请重新获取并更新 `config.json` 中的 `api_key`。\r\n\r\n---\r\n\r\n## 可选 Bocha 搜索能力\r\n\r\n仅部分 Web 搜索辅助场景需要博查凭证；核心行情、财务、选股、回测能力不依赖该凭证。\r\n\r\n可选配置方式（任一即可）：\r\n\r\n- 环境变量 `BOCHA_API_KEY`\r\n- `config.local.json` 中手动添加 `bocha_api_key`\r\n- `config.json` 中手动添加 `bocha_api_key`\r\n\r\n---\r\n\r\n## 运行时输出目录\r\n\r\n- `output/.session.json`：当前 session 的 task_id\r\n- `output/ic_data/`：IC 扫描结果（若 workflow 触发相关能力）\r\n- 其他 `csv / png / json / html`：运行过程中的临时或交付产物\r\n\r\n---\r\n\r\n## readData 批量限制\r\n\r\n`readData` 单次调用最多传入 **10 个 data_id**。如需读取更多结果，拆分多次调用。\r\n\r\n---\r\n\r\n## 终端注意事项\r\n\r\n- 终端缓冲可能导致长输出不完整显示，`call.py` 会额外写入系统临时目录下的 `gzq_out.txt`\r\n- 若需排查，可在系统临时目录中查看该文件内容\n\nFile v4.14.17:references/ru-billing.md\n\n# RU 计费体系\r\n\r\n> 更新于 2026-04-15。统一 RU（Resource Unit）体系，所有端点共享一个 RU 池。\r\n> 每个请求按端点类型 + 请求参数动态扣减 RU（1～26 RU）。\r\n> 规划流程时优先减少冗余调用。\r\n\r\n---\r\n\r\n## RU 权重速查表\r\n\r\n| 工具 | 模式 | RU 消耗 | 说明 |\r\n|------|:---:|:---:|------|\r\n| `search_functions` | fixed | 1 | |\r\n| `get_card_formulas` | fixed | 1 | |\r\n| `upload_preview` | fixed | 1 | |\r\n| `upload_confirm` | fixed | 1 | |\r\n| `download_data` | fixed | 1 | |\r\n| `render_kline` | fixed | 1 | |\r\n| `re_render_chart` | fixed | 1 | |\r\n| `read_data` | fixed | 2 | |\r\n| `search_similar_cases` | fixed | 5 | |\r\n| `confirm_multiple_assets` | deferred | 1～6 × 意图数 | DB 精确匹配 1 RU，LLM 路径 6 RU |\r\n| `confirm_data_multi` | deferred | 1～26 × 意图数 | DB 精确匹配 1 RU，LLM 路径 26 RU |\r\n| `run_multi_formula` | dynamic | **7 × 公式数** | 单次最多 20/30/40 个（free/plus/pro） |\r\n| `scan_dimensions` | dynamic | **12 × 维度数** | 全维度(8) = 96 RU |\r\n| `render_chart` | dynamic | **1 × 线数** | 如 3 条线 = 3 RU |\r\n\r\n> **deferred 模式**：先预扣 1 RU/意图，请求完成后按实际路径补扣差额。\r\n> **错误请求退款**：所有端点发生错误时（4xx/5xx），实际 RU 降为 1 RU。\r\n\r\n---\r\n\r\n## 配额池说明\r\n\r\n| 池 | 重置方式 | 说明 |\r\n|------|------|------|\r\n| **窗口 RU** | 个人滚动（最早请求 +4h） | 不是全部一次恢复，按请求逐批恢复 |\r\n| **日 RU** | 每天 00:00（北京时间） | 次日零点统一重置 |\r\n\r\n---\r\n\r\n## 场景成本参考\r\n\r\n| 场景 | 典型 RU 消耗 |\r\n|------|:---:|\r\n| 单只股票价格/PE/PB | ~3 RU |\r\n| 条件选股（1 条公式）| ~10 RU |\r\n| 条件选股+回测（5 公式）| ~37 RU |\r\n| IC 全维度扫描 | 96 RU |\n\nFile v4.14.17:references/scripts-audit.md\n\n# Bundled Scripts Audit\r\n\r\nThis document enumerates every Python script shipped inside this skill, what it does, and its network / subprocess / filesystem behavior. Reviewers can use it to verify the skill's declared behavior without reading every line of code.\r\n\r\nLast audited against version: **4.14.7**\r\n\r\n---\r\n\r\n## Top-level scripts\r\n\r\n### `scripts/call.py`\r\n- **Purpose**: Thin CLI dispatcher. Takes a tool name + JSON params, forwards to `scripts/executor.py` via a subprocess of the same Python interpreter.\r\n- **Network**: None directly. Network calls happen inside `executor.py`.\r\n- **Subprocess**: `subprocess.run([sys.executable, \"scripts/executor.py\", ...])`. No shell, no external binary.\r\n- **Filesystem writes**: None.\r\n- **Reads secrets**: Only `config.json` / `config.local.json` pass-through; secrets are handled by `executor.py`.\r\n\r\n### `scripts/executor.py`\r\n- **Purpose**: Calls the quant-buddy HTTPS API and returns the response.\r\n- **Network**: Only `https://www.quantbuddy.cn/**` via `urllib.request` (stdlib). Host is taken from `config.json#endpoint` with a hardcoded default; no redirects to third-party hosts are followed without verification.\r\n- **Authentication**: Resolves `api_key` in this order: (1) `QUANT_BUDDY_API_KEY` env var, (2) `config.local.json` `api_key` field, (3) `config.json` `api_key` field. The resolved key is sent **only** in the `Authorization: Bearer <key>` header. It is never logged, printed to stdout/stderr, or written to files.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: Optional response cache under `.cache/` within the skill root; chart / CSV outputs under `output/` when invoked by chart or download tools.\r\n\r\n### `scripts/quant_api.py`\r\n- **Purpose**: Python wrapper around `executor.py` for use as a library (not invoked during normal agent flow).\r\n- **Network**: Same as `executor.py` (delegates to it).\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: None.\r\n\r\n### `scripts/event_study_local.py`\r\n- **Purpose**: Optional event-study helper. Combines quant-buddy data with a Bocha web-search step for news context.\r\n- **Network**:\r\n  - `https://www.quantbuddy.cn/**` (via `executor.py`) — required.\r\n  - `https://api.bochaai.com/v1/web-search` — **opt-in only**. The function returns `{\"ok\": false, \"error\": \"BOCHA_API_KEY 未配置\"}` immediately if the user has not set `BOCHA_API_KEY` (env var / `bocha_api_key` in `config.local.json` / `config.json`). No request is made without the key.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: None.\r\n- **Dependency**: Requires the `requests` package **only when Bocha is enabled**. Without BOCHA_API_KEY the import path is bypassed.\r\n\r\n### `scripts/repro_scan_null.py`, `scripts/update_cases_index.py`\r\n- **Purpose**: Developer utilities for curating the skill's own preset/case files. Not invoked by the agent at runtime; intended for the skill author to regenerate local indices.\r\n- **Network**: None.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: Only under `scripts/` and `presets/` within the skill root.\r\n\r\n---\r\n\r\n## `scripts/eval/`\r\nOffline evaluation harness for the skill author to measure quality regressions. Not invoked at runtime. No network access, no subprocess, writes only to `scripts/eval/` outputs.\r\n\r\n---\r\n\r\n## Summary guarantees\r\n\r\n| Concern | Status |\r\n|---|---|\r\n| Outbound network hosts | `www.quantbuddy.cn` (required), `api.bochaai.com` (opt-in only) |\r\n| api_key ever logged / transmitted to other host | No |\r\n| PII (phone / SMS / email / device ID) collected | No |\r\n| Subprocess / shell to external binary | No (only re-invokes `sys.executable` for dispatch) |\r\n| Writes outside skill root | No |\r\n| Reads OS credentials / env vars beyond the declared ones | No (only reads `BOCHA_API_KEY` when the optional Bocha feature is used) |\r\n\r\nIf any of the above statements is inaccurate, it is a bug and should be reported to the skill author.\n\nFile v4.14.17:references/troubleshooting.md\n\n# 故障排查\r\n\r\n> 汇总所有场景（量化选股、渲染图表、数据下载）的常见错误与解决方式。\r\n\r\n---\r\n\r\n## 公式 / 变量\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `公式变量未找到` | 同一批公式 task_id 不一致 | 确保所有公式用同一个 task_id |\r\n| `函数不存在` / 函数名报错 | 案例原文笔误，或抄写时引入差异 | 用 `searchFunctions` 找正确函数名 |\r\n| `数据名不存在` | 公式中名称与 confirmDataMulti 的 index_title 不一致 | 以 index_title 为准 |\r\n| `公式格式检测失败：MA(dataid(...),N)` | 平台**无 `MA()` 函数** | 简单均线用 `平均(\"数据名\", N)`；指数均线用 `ema(\"数据名\", N)` |\r\n| `函数不存在：取出最后值` | 该函数不存在于平台 | 替代：① `取前(数据, n, 返回数值)` 获取截面 TopN；② `readData(mode=last_day_stats)` 获取最新截面 |\r\n| PE 选股包含亏损股 | 未过滤负 PE | 加 `(\"PE\">0)` 条件 |\r\n| 多因子选股数为 0 | 非季报日截面财务数据为空 | ① 检查结束日期是否临近季报日；② 用 `readData(mode=last_day_stats)`；③ 调整至最近季报日（3/31、6/30、9/30、12/31） |\r\n\r\n---\r\n\r\n## 工具参数\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `参数 xxx 必填` / `400` | 参数名错误 | 读对应 `tools/<tool>.md` 确认正确字段名 |\r\n| `readData` 返回 400 | 参数名用了 `variable_names` | 改为 `ids` 数组 |\r\n| `match_quality=low` | searchSimilarCases 未找到好模板 | 调整 query 关键词，**最多重试 1 次** |\r\n| confirmDataMulti 返回 404 | 查询的是单资产价格，不是平台聚合数据 | 用 `收盘价(资产名)` 函数，无需 confirmDataMulti |\r\n| confirmMultipleAssets 30次超时 | intentions 用了前缀格式如 `CMX-铜` | 用简洁中文品种名如 `铜`、`黄金` |\r\n\r\n---\r\n\r\n## 图表渲染\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| renderChart 图中无曲线 | 数据为二维，renderChart 仅支持一维 | 确保公式输出一维时序 |\r\n| `参数 lines 必须是非空数组` | 误用了 `variable_names` 参数 | 改为 `lines: [{id, name}]`，id 来自 runMultiFormula 的 `_id` |\r\n| K线图报 `必须包含 open_id/high_id/low_id/close_id` | candlestick 参数缺少必填字段 | 传入完整 4 个 ID；或改用 `renderKLine` |\r\n| K线图日期对不齐 / 数据缺失 | OHLC 4 个 data ID 来自不同 task_id | 确保在同一个 runMultiFormula 中计算 |\r\n| renderKLine 报 ticker 不存在 | ticker 格式错误 | 使用 `SH`/`SZ` 前缀格式如 `SH600519` |\r\n| renderKLine indicators 无效 | 指标名拼写错误 | 参照 `tools/render_kline.md` 支持列表，全小写 |\r\n| 图表不知道在哪里 | 未找到输出文件 | `call.py` 已自动保存到 `output/` 并打开 |\r\n\r\n---\r\n\r\n## 认证 / 网络\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `401 Unauthorized` | api_key 无效或过期 | **立即停止**，提示用户重新认证 |\r\n| `402 Quota` | 配额耗尽 | **立即停止**，提示用户等待恢复或次日重置 |\r\n| 终端命令无输出 | 终端缓冲 stdout | `call.py` 已写 `/tmp/gzq_out.txt`，用 `cat /tmp/gzq_out.txt` 读取 |\r\n\r\n## 业务错误（HTTP 200 + success: false）\r\n\r\n部分错误走 HTTP 200 返回，通过 `success: false` + `error` 对象区分：\r\n\r\n```json\r\n{\"code\": -1, \"success\": false, \"error\": {\"message\": \"参数 ids 必须是非空数组\"}}\r\n```\r\n\r\n| 判断方式 | 说明 |\r\n|----------|------|\r\n| `success === false` 或 `code !== 0` | 均可判定为错误 |\r\n| `error.message` | 错误描述 |\r\n\r\n> 业务错误与 429 配额超限使用相同的 `{ success: false, error: { message } }` 结构。\r\n> 429/503 的 `error` 中额外包含 `code`（语义化字符串）和恢复时间字段。\r\n> 调用方应先检查 HTTP status（429/503），再检查 body 的 `success` / `code`。\r\n\r\n---\r\n\r\n## 配额限流（429 错误码）\r\n\r\n| 错误码 | 含义 | 处理方式 |\r\n|--------|------|----------|\r\n| `WINDOW_QUOTA_EXCEEDED` | 窗口 RU 已耗尽 | **停止调用**，告知用户等待时间（`error.nextResetIn` 秒后最早一批恢复） |\r\n| `DAILY_QUOTA_EXCEEDED` | 今日 RU 已耗尽 | **停止调用**，告知用户次日 00:00 重置（`error.resetIn` 秒） |\r\n| `DAILY_SCAN_EXCEEDED` | IC 扫描今日次数已满 | **停止调用**，告知用户次日 00:00 重置（free=2次/天，plus=10次/天）（`error.resetIn` 秒） |\r\n| `RATE_LIMIT_EXCEEDED` | 每分钟请求过于频繁 | **静默等待** `error.retryAfter` 秒后重试，不暴露给用户 |\r\n| `CONCURRENT_LIMIT` | 有计算任务正在执行 | **静默等待** `error.retryAfter` 秒后重试，不暴露给用户 |\r\n| `SERVICE_OVERLOADED` | 系统熔断（503） | **静默等待** `error.retryAfter` 秒后重试 1 次；若仍失败则告知用户\"系统繁忙，请稍后重试\" |\r\n\r\n---\r\n\r\n## 数据下载\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| downloadData 返回 403 | 计算结果 `provider=dunhe`，无权限 | 改用 `readData(mode=full)` |\r\n| 下载到全量历史几千行 | 未传 begin_date | 调用前先问用户要哪段时间 |\r\n| 上传数据 NaN 率高 | CSV 列标题缺少交易所后缀 | 改为 `600519.SH` 格式 |\n\nFile v4.14.17:recipes/download-data.md\n\n# Recipe：下载数据到本地 CSV\r\n\r\n## 触发词\r\n\r\n> \"把数据下载成 CSV\"、\"导出到本地\"、\"下载历史数据\"\r\n\r\n---\r\n\r\n## 调用方式\r\n\r\n```bash\r\npython scripts/call.py downloadData '{\"data_id\":\"<data_id>\",\"begin_date\":<YYYYMMDD>,\"end_date\":<YYYYMMDD>}'\r\n```\r\n\r\n`call.py` 调用 `downloadData` 时会**自动**将 CSV 保存到 `output/<data_name>.csv`，终端输出摘要（total_rows、begin_date、saved_to），不刷屏。\r\n\r\n---\r\n\r\n## 使用限制\r\n\r\n| 条件 | 说明 |\r\n|------|------|\r\n| **可下载** | 持久化一维时序：上传数据 (`provider=mydata`) 或平台数据 (`provider=guanzhao`) |\r\n| **不可下载** | `runMultiFormula` 的计算结果 (`provider=dunhe`)，普通用户无 `access_dunhe` 权限 → 返回 403 |\r\n| **替代方案** | 计算结果用 `readData(mode=full)` 读取，再自行保存为 CSV |\r\n\r\n---\r\n\r\n## 必须确认时间范围\r\n\r\n数据通常从 2015 年起，直接下载可能几千行。**调用前先问用户**：\r\n\r\n> \"您需要下载哪段时间的数据？（默认：最近一年）\"\r\n\r\n- 用户给出范围 → 传 `begin_date` / `end_date`\r\n- 用户说\"所有历史\" → 不传日期参数\n\nFile v4.14.17:recipes/event-study-formulas.md\n\n# 事件研究公式模板\r\n\r\n保留四条真正稳定的模板。\r\n\r\n## 模板 A: 单组事件固定持有期\r\n\r\n适用于绝大多数事件研究问题。\r\n\r\n```text\r\n{prefix}_事件日=选取日期({date1},{date2},...)\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_后{N1}日路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_事件日\",{N1})\r\n{prefix}_后{N2}日路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_事件日\",{N2})\r\n{prefix}_后{N1}日收益=分段最终值(\"{prefix}_后{N1}日路径\")\r\n{prefix}_后{N2}日收益=分段最终值(\"{prefix}_后{N2}日路径\")\r\n```\r\n\r\n### 窗口映射\r\n\r\n| 说法 | N |\r\n|------|---|\r\n| 1周 | 5 |\r\n| 2周 | 10 |\r\n| 1月 | 21 |\r\n| 3月 | 63 |\r\n| 半年 | 126 |\r\n| 1年 | 252 |\r\n\r\n### 使用建议\r\n\r\n1. 同时给逐次结果和均值\r\n2. 窗口不宜超过相邻事件最小间距\r\n3. 样本很少时不要强行做胜率和分位数\r\n\r\n## 模板 B: 两组事件对比（compare）\r\n\r\n适用于超预期 vs 不及预期、利好 vs 利空这类问题。\r\n\r\n```text\r\n{prefix}_A组=选取日期({group_a_dates...})\r\n{prefix}_B组=选取日期({group_b_dates...})\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_A后{N}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_A组\",{N})\r\n{prefix}_A后{N}收益=分段最终值(\"{prefix}_A后{N}路径\")\r\n{prefix}_B后{N}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_B组\",{N})\r\n{prefix}_B后{N}收益=分段最终值(\"{prefix}_B后{N}路径\")\r\n```\r\n\r\n### 使用建议\r\n\r\n1. 两组共享同一条价格和日收益序列\r\n2. 输出时先列每次事件，再列各组均值\r\n3. 两组样本数不一致时，要在解释里显式写出来\r\n\r\n## 模板 C: 事件后偏移区间回报（排除事件日）\r\n\r\n适用于\"事件后第 N 天到第 M 天\"的区间涨幅，排除事件当天。\r\n与模板 A 的区别：模板 A 从 T+1 起算固定窗口；本模板通过收盘价比值法精确计算任意偏移区间。\r\n\r\n```text\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_收盘_T加{N}=取某天(\"{prefix}_收盘\",交易日位移({event_date},{N}))\r\n{prefix}_收盘_T加{M}=取某天(\"{prefix}_收盘\",交易日位移({event_date},{M}))\r\n{prefix}_T{N+1}到T{M}涨幅=\"{prefix}_收盘_T加{M}\"/\"{prefix}_收盘_T加{N}\"-1\r\n```\r\n\r\n### 参数映射\r\n\r\n| 占位符 | 含义 | 示例值 |\r\n|--------|------|--------|\r\n| `{prefix}` | 变量前缀 | `fomc` |\r\n| `{event_date}` | 事件日期（YYYYMMDD 整数） | `20241218` |\r\n| `{asset_name}` | 标的资产名 | `沪深300` |\r\n| `{N}` | 起始边界交易日数（用户起始天数 - 1） | `1` |\r\n| `{M}` | 终止边界交易日数（用户结束天数） | `20` |\r\n\r\n### 数学原理\r\n\r\n`取某天` 将指定日期的收盘价填充为常数序列，两个常数序列相除天然对齐：\r\n\r\n$$\\text{T+N+1 到 T+M 涨幅} = \\frac{P_{T+M}}{P_{T+N}} - 1$$\r\n\r\n其中 $P_{T+N}$ 和 $P_{T+M}$ 均由 `交易日位移` 按 A 股交易日历精确计数（非自然日）。\r\n\r\n例如用户说\"第 2 天到第 20 天\" → N=1, M=20 → 计算 $P_{T+20} / P_{T+1} - 1$（持有 T+1 收盘到 T+20 收盘）。\r\n\r\n### N 值推导\r\n\r\n| 用户表述 | N | M | 实际区间 |\r\n|----------|---|---|----------|\r\n| \"第 2 天到第 20 天\" | 1 | 20 | T+1 收盘 → T+20 收盘 |\r\n| \"第 3 天到第 60 天\" | 2 | 60 | T+2 收盘 → T+60 收盘 |\r\n| \"排除前 2 天，看第 3 天起\" | 2 | M | T+2 收盘 → T+M 收盘 |\r\n\r\n核心规则：**N = 用户起始天数 - 1，M = 用户结束天数**\r\n\r\n### 使用建议\r\n\r\n1. 当用户说\"排除事件当天\"或\"T+2 到 T+20\"时使用本模板\r\n2. 多事件场景需为每个事件单独建立一套前缀变量（`取某天` 只能绑定一个日期）\r\n3. 同一会话中不同事件使用不同 `{prefix}`，避免变量覆盖\r\n4. 结果为精确价格比值，无累加近似误差\r\n\r\n## 模板 D: 搜索新闻打标分类（财报超预期类 compare 专用）\r\n\r\n适用于：需要先搜索新闻判断财报是否超预期，再分组计算事件后收益的场景。\r\n\r\n与模板 B 的区别：模板 B 默认两组日期已知；模板 D 需要先把正式年报/半年报披露日逐期打标，再将结果代入 compare 公式链。\r\n\r\n### 执行步骤（配合 `event-study.md` 的财报业绩超预期分类细则使用）\r\n\r\nStep D1：获取正式财报披露日\r\n\r\n```text\r\nREV_2D=\"A股营业总收入〔报告期利润表〕\"\r\nPUB_DATE=报告期转发布日(\"REV_2D\")\r\n```\r\n\r\n从 `PUB_DATE` 中提取目标股票的正式年报（Q4）和半年报（Q2）披露日。若需要补证，再用交易所公告页或东财年报季报页交叉验证。\r\n\r\nStep D2：逐期搜索并打标\r\n\r\n对每个披露日执行搜索，关键词格式：\r\n\r\n```text\r\n{股票简称} {报告类型} {yyyymmdd} 超预期 OR 不及预期\r\n```\r\n\r\n打标规则、证据门槛和 `label_confidence` 约束以 `event-study.md` 中的财报业绩超预期分类细则为准。\r\n\r\nStep D3：将打标结果代入 compare 公式链\r\n\r\n```text\r\n{prefix}_超预期组=选取日期({beat_dates...})\r\n{prefix}_不及预期组=选取日期({miss_dates...})\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_超预期后{N1}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_超预期组\",{N1})\r\n{prefix}_超预期后{N1}收益=分段最终值(\"{prefix}_超预期后{N1}路径\")\r\n{prefix}_超预期后{N2}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_超预期组\",{N2})\r\n{prefix}_超预期后{N2}收益=分段最终值(\"{prefix}_超预期后{N2}路径\")\r\n{prefix}_不及预期后{N1}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_不及预期组\",{N1})\r\n{prefix}_不及预期后{N1}收益=分段最终值(\"{prefix}_不及预期后{N1}路径\")\r\n{prefix}_不及预期后{N2}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_不及预期组\",{N2})\r\n{prefix}_不及预期后{N2}收益=分段最终值(\"{prefix}_不及预期后{N2}路径\")\r\n```\r\n\r\n### 参数说明\r\n\r\n| 占位符 | 说明 | 示例 |\r\n|--------|------|------|\r\n| `{prefix}` | 变量前缀 | `MT` |\r\n| `{beat_dates...}` | 超预期组日期列表 | `20210330,20220331,20240403` |\r\n| `{miss_dates...}` | 不及预期组日期列表 | `20220803` |\r\n| `{asset_name}` | 资产名称 | `贵州茅台` |\r\n| `{N1}` | 短窗口交易日数 | `5` |\r\n| `{N2}` | 长窗口交易日数 | `20` |\r\n\r\n### 使用建议\r\n\r\n1. 日期分组必须来自 Step D2 的搜索打标结果，不得凭记忆填入\r\n2. 若用户要比较\"符合预期\"而不是\"不及预期\"，只替换第二组标签和日期列表，不改整条公式链\r\n3. 两组共享同一条价格序列和日收益序列，减少公式冗余\r\n4. 样本数 < 5 时，均值行必须标注\"有限样本，仅供参考\"\r\n5. 若某组样本为 0（全部证据不足），保留 compare 框架，并在输出中明确说明该组无满足证据标准的样本，不得静默降级为 single 模式\r\n\r\n## 可选扩展: 超额收益\r\n\r\n如果用户明确要求相对基准表现，可额外生成：\r\n\r\n```text\r\n{prefix}_基准收盘=收盘价(沪深300)\r\n{prefix}_基准日收益=涨跌幅(\"{prefix}_基准收盘\")\r\n{prefix}_超额日收益=\"{prefix}_日收益\"-\"{prefix}_基准日收益\"\r\n```\r\n\r\n然后用 `{prefix}_超额日收益` 替代 `{prefix}_日收益` 进入同样的窗口链路。\n\nFile v4.14.17:recipes/ic-factor-templates.md\n\n# IC 因子公式模板\r\n\r\n> 来源：`workflows/quant-standard.md` Step 2 手动因子构建\r\n> 通常由 `scanDimensions` 脚本自动完成，仅在需要**自定义指标**或脚本不可用时手动使用\r\n\r\n---\r\n\r\n## 基础数据（所有因子前置）\r\n\r\n```python\r\nB_Close = 收盘价(X)         # X = 目标资产名（来自 confirmMultipleAssets 的 name）\r\nB_Ind   = 收盘价(Ind)       # Ind = 行业指数名\r\nB_Mkt   = 收盘价(Mkt)       # Mkt = 大盘指数（如 万得全A 或 沪深300）\r\n```\r\n\r\n---\r\n\r\n## D1 估值\r\n\r\n```python\r\nB_PE      = \"A股市盈率（PE, TTM）〔估值数据〕\" * 取出(X的代码)\r\nB_PB      = \"A股市净率（PB）〔估值数据〕\" * 取出(X的代码)\r\nB_PE_Rank = 数值水位(\"B_PE\", 250)\r\nB_PB_Rank = 数值水位(\"B_PB\", 250)\r\n```\r\n\r\n> PE 必须使用 TTM 口径（`A股市盈率（PE, TTM）〔估值数据〕`）\r\n\r\n---\r\n\r\n## D3 资金\r\n\r\n```python\r\nB_AllAmt    = 按天求和(\"全市场每日成交额\")\r\nB_Amt       = \"全市场每日成交额\" * 取出(X的代码)\r\nB_AmtRatio  = \"B_Amt\" / \"B_AllAmt\"\r\nB_AmtRank   = 数值水位(\"B_AmtRatio\", 250)\r\nB_Short     = \"A股融券空头持仓比例\" * 取出(X的代码)\r\nB_ShortRank = 数值水位(\"B_Short\", 250)\r\nB_Fund      = \"A股持股市值占基金股票投资市值比\" * 取出(X的代码)\r\nB_FundRank  = 数值水位(\"B_Fund\", 250)\r\n```\r\n\r\n---\r\n\r\n## D4 波动率 / 风险\r\n\r\n```python\r\nB_PrevClose = 前几天(\"B_Close\", 1)\r\nB_High      = 最高价(X)\r\nB_Low       = 最低价(X)\r\nB_TR  = 比较取大(\"B_High\"-\"B_Low\", 比较取大(绝对值(\"B_High\"-\"B_PrevClose\"), 绝对值(\"B_Low\"-\"B_PrevClose\")))\r\nB_ATR = 平均(\"B_TR\", 14)\r\n```\r\n\r\n---\r\n\r\n## D5 宏观 / 大盘环境\r\n\r\n```python\r\nB_Mkt_MA60  = 平均(\"B_Mkt\", 60)\r\nB_Mkt_Above = (\"B_Mkt\" > \"B_Mkt_MA60\")\r\n```\r\n\r\n---\r\n\r\n## D7 技术形态\r\n\r\n```python\r\n# 均线\r\nB_MA10 = 平均(\"B_Close\", 10)\r\nB_MA20 = 平均(\"B_Close\", 20)\r\nB_MA60 = 平均(\"B_Close\", 60)\r\n\r\n# MACD\r\nB_EMA12     = EMA(\"B_Close\", 12)\r\nB_EMA26     = EMA(\"B_Close\", 26)\r\nB_MACD      = \"B_EMA12\" - \"B_EMA26\"\r\nB_Signal    = EMA(\"B_MACD\", 9)\r\nB_MACD_Hist = \"B_MACD\" - \"B_Signal\"\r\n\r\n# 布林带\r\nB_SD20  = 标准差(\"B_Close\", 20)\r\nB_BollZ = (\"B_Close\" - \"B_MA20\") / \"B_SD20\"\r\n```\r\n\r\n---\r\n\r\n## D9 财务\r\n\r\n```python\r\nB_Profit_Raw = 报告期转发布日(\"A股净利润同比增长率：单季〔财务指标〕\")\r\nB_Profit_F   = 缺失填充(\"B_Profit_Raw\" * 取出(X的代码))\r\n```\r\n\r\n---\r\n\r\n## 收益率 / 位置（跨维度通用）\r\n\r\n```python\r\nB_Ret20       = 涨跌幅(\"B_Close\", 20)\r\nB_IndRet20    = 涨跌幅(\"B_Ind\", 20)\r\nB_Alpha20     = \"B_Ret20\" - \"B_IndRet20\"\r\nB_Ret20_Next  = 前几天(涨跌幅(\"B_Close\", 20), -20)   # 未来20日收益（IC计算目标）\r\n\r\nB_PriceRank   = 数值水位(\"B_Close\", 250)\r\nB_RS          = \"B_Close\" / \"B_Ind\"\r\nB_RS_Rank     = 数值水位(\"B_RS\", 250)\r\n```\r\n\r\n---\r\n\r\n## IC 计算公式\r\n\r\n```python\r\n# 内联写法（推荐，无跨变量依赖）\r\nPE_IC = 相关系数(前几天(数值水位(\"B_PE\", 250), 20), 涨跌幅(收盘价(X), 20), 250)\r\n\r\n# 引用写法（同一 task_id 内）\r\nB_PE_Rank = 数值水位(\"B_PE\", 250)\r\nPE_IC     = 相关系数(前几天(\"B_PE_Rank\", 20), 涨跌幅(\"B_Close\", 20), 250)\r\n```\r\n\r\n> 不同 task_id 之间不能引用变量——newSession 后旧 session 的变量全部丢失\n\nFile v4.14.17:recipes/industry-aggregation.md\n\n# 示例五：成交量加权行业聚合——放量日申万行业涨跌幅排名\r\n\r\n## 快速模板：行业近N日平均涨跌幅前K\r\n\r\n适用：\r\n- 申万一级行业最近一个月平均涨跌幅前5\r\n- 某板块体系近N日涨跌幅排名\r\n\r\n标准公式模板：\r\n```text\r\n个股近N日涨跌幅=涨跌幅(\"全市场每日收盘价\",N)\r\n行业近N日涨跌幅=成分平均汇总(\"个股近N日涨跌幅\",\"申万资产所属指数\")\r\n行业TopK=取前(\"行业近N日涨跌幅\",K,返回数值)\r\n```\r\n\r\n注意：\r\n- 所有数据名/变量名在函数参数中必须使用双引号\r\n- \"最近一个月\"默认按近20个交易日处理，回答中需明示口径\r\n- 若 runMultiFormula 已返回最后一天 top 数据，且足以回答用户问题，可不再 readData\r\n- 仅当内置数据名无法命中时，才使用 confirmDataMulti\r\n\r\n**⚠️ 输出口径声明硬规则**：上述模板的计算结果是\"**行业近N日平均涨跌幅**\"（行业内各成分股N日区间回报的算术均值）。在最终答案中**只能**称为\"行业近N日平均涨跌幅\"或\"行业近N日涨跌幅均值\"，**绝对禁止**将其改写为\"近N日累计涨跌幅\"——\"累计涨跌幅\"与\"平均涨跌幅\"统计含义不同，用户问的是\"平均\"就必须说\"平均\"。\r\n\r\n---\r\n\r\n## 用户意图\r\n\r\n> \"在A股放量日（当日成交量超过5日均值2倍时），哪些申万行业板块的平均涨跌幅最好？帮我排个名\"\r\n\r\n---\r\n\r\n## 核心挑战：跨维度聚合\r\n\r\n本示例的关键难点是**维度不匹配**：\r\n\r\n- 全市场回报率（如万得全A 7700+ 只）：资产×日期 二维矩阵\r\n- 申万行业指数（31个）：与全市场股票维度不同\r\n\r\n**不能直接用全市场列做行业均值**——同一个二维矩阵按行业分组后，维度（资产轴）不一致，必须用 `成分平均汇总()` 做桥接：\r\n\r\n```\r\n成分平均汇总(全市场数据, 申万资产所属指数)\r\n→ 输出：31个申万行业 × 日期 的二维矩阵（行业轴替换了资产轴）\r\n```\r\n\r\n类比：`成分平均汇总` 是\"按组取平均\"，第二个参数指定分组依据（哪家公司属于哪个行业）。\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 0 — 初始化会话\r\n\r\n```bash\r\npython scripts/call.py newSession\r\n```\r\n\r\n```json\r\n{\"code\": 0, \"task_id\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"}\r\n```\r\n\r\n---\r\n\r\n### Step 1 — 查案例（cases_index 优先）\r\n\r\n**1a. 读取 `presets/cases_index.yaml`**，搜索 tags 含 `行业`、`聚合`、`成分` 的卡片（约 1-3 张）。\r\n\r\n**1b.** 找到后调 `getCardFormulas` 拉取公式，理解 `成分平均汇总` 的参数用法：\r\n\r\n```bash\r\npython scripts/call.py getCardFormulas '{\"card_ids\": [\"<相关卡片id>\"]}'\r\n```\r\n\r\n**1c.** 若目录中未找到合适卡片，fallback 到：\r\n\r\n```bash\r\npython scripts/call.py searchSimilarCases '{\"query\": \"申万行业聚合成分平均汇总涨跌幅\", \"top_k\": 3}'\r\n```\r\n\r\n> **重点关注**返回案例中 `成分平均汇总()` 的参数格式、`申万资产所属指数` 的数据名称写法；案例解决的是案例自身的问题，当前问题的公式需根据用户需求重新组织。\r\n\r\n---\r\n\r\n### Step 2 — 确认全市场数据\r\n\r\n```bash\r\npython scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日成交量, 全市场每日回报率, 申万资产所属指数\"}'\r\n```\r\n\r\n**预期返回**（记录三个 index_title）：\r\n\r\n| 描述词 | index_title（示例） | dimension | 说明 |\r\n|-------|-------------------|-----------|------|\r\n| 全市场每日成交量 | `全市场每日成交量` | two | 资产×日期 |\r\n| 全市场每日回报率 | `全市场每日回报率` | two | 资产×日期 |\r\n| 申万资产所属指数 | `申万资产所属指数` | two | 资产×日期，值为申万指数代码 |\r\n\r\n> **Windows PowerShell 传参**：\r\n> ```bash\r\n> python scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日成交量, 全市场每日回报率, 申万资产所属指数\"}'\r\n> ```\r\n\r\n---\r\n\r\n### Step 3 — 搜索聚合函数（若 presets/functions.yaml 中已有则跳过）\r\n\r\n```bash\r\npython scripts/call.py searchFunctions '{\"query\": \"成分平均汇总 行业聚合\", \"top_k\": 3}'\r\npython scripts/call.py searchFunctions '{\"query\": \"区间统计量 掩码过滤\", \"top_k\": 3}'\r\npython scripts/call.py searchFunctions '{\"query\": \"按天求和 全市场聚合\", \"top_k\": 3}'\r\n```\r\n\r\n确认以下函数的参数格式：\r\n- `按天求和(数据)` → 将二维数据按日期求和，得到一维时序\r\n- `成分平均汇总(数据, 指数数据)` → 按指数成分分组取平均，输出指数×日期 矩阵\r\n- `区间统计量(数据, 掩码, 统计函数)` → 用布尔掩码过滤时间段，对各段计算统计量\r\n\r\n---\r\n\r\n### Step 4 — 执行公式（5条，共享同一 task_id）\r\n\r\n```bash\r\npython scripts/call.py runMultiFormula '{\r\n  \"task_id\": \"<Step 0 的 task_id>\",\r\n  \"begin_date\": 20150101,\r\n  \"formulas\": [\r\n    \"全市场总成交量=按天求和(\\\"全市场每日成交量\\\")\",\r\n    \"全市场成交量5日均=平均(\\\"全市场总成交量\\\",5)\",\r\n    \"放量日标记=(\\\"全市场总成交量\\\">\\\"全市场成交量5日均\\\"*2)\",\r\n    \"申万行业每日回报率=成分平均汇总(\\\"全市场每日成交量\\\"*\\\"全市场每日回报率\\\",\\\"申万资产所属指数\\\")\",\r\n    \"放量日行业平均涨跌幅=区间统计量(\\\"申万行业每日回报率\\\",\\\"放量日标记\\\",平均)\"\r\n  ],\r\n  \"intents\": [\"全市场每日总量（一维）\", \"5日均量（一维）\", \"放量日布尔标记（一维）\", \"成交量加权行业日回报率（31行业×日期）\", \"放量日区间内各行业平均涨跌幅（31行业×区间数）\"]\r\n}'\r\n```\r\n\r\n**关键设计决策**：\r\n\r\n| 设计点 | 说明 |\r\n|-------|------|\r\n| 公式4使用 `成交量×回报率` 而非直接 `回报率` | 这是**成交量加权平均**的计算模式：分子=成交量×回报率之和，分母=成交量之和，`成分平均汇总` 内部会自动完成加权除法 |\r\n| 公式1-3先把全市场压缩到一维 | `按天求和` 把 7700+ 只的成交量矩阵折叠为每天一个数——这是后续做\"全市场放量日\"判断的前提 |\r\n| `放量日标记` 是一维布尔序列 | 可直接作为 `区间统计量` 的掩码，标记哪些日期属于\"放量日\" |\r\n| `申万行业每日回报率` 维度是 31 × 4000+ 天 | 行业轴（31个申万行业）替代了原来的资产轴（7700+ 只股票） |\r\n\r\n**预期返回（各公式 data_id）**：\r\n```json\r\n{\r\n  \"results\": [\r\n    {\"variable_name\": \"全市场总成交量\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"全市场成交量5日均\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"放量日标记\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"申万行业每日回报率\", \"data_id\": \"xxx\", \"dimension\": \"two\", \"assets\": 31},\r\n    {\"variable_name\": \"放量日行业平均涨跌幅\", \"data_id\": \"xxx\", \"dimension\": \"two\", \"assets\": 31}\r\n  ]\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 5 — 验证结果（必做）\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<放量日行业平均涨跌幅的data_id>\"], \"mode\": \"smart_sample\"}'\r\n```\r\n\r\n**检查项**：\r\n- `assets` = 31（申万31个行业全部覆盖）\r\n- `dates`（列数）= 识别到的放量日区间数（历史通常 80-150 个）\r\n- NaN 率 < 10%（若过高，检查 `申万资产所属指数` 的 index_title 是否正确）\r\n- 取样值有正有负，数量级在 0.001 ~ 0.05 之间（日回报率级别）\r\n\r\n---\r\n\r\n### Step 6 — 读取完整截面排名\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<放量日行业平均涨跌幅的data_id>\"], \"mode\": \"last_day_stats\"}'\r\n```\r\n\r\n**预期返回**：31 个行业在所有放量日的平均涨跌幅，按值降序排列即可得到排名。\r\n\r\n---\r\n\r\n### Step 7（可选）— 柱状图可视化\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"放量日申万行业平均涨跌幅排名（2015至今）\",\r\n  \"lines\": [\r\n    {\"id\": \"<放量日行业平均涨跌幅的data_id>\", \"name\": \"放量日平均日涨幅\"}\r\n  ],\r\n  \"chart_type\": \"bar\",\r\n  \"task_id\": \"<task_id>\"\r\n}'\r\n```\r\n\r\n> ```bash\r\n> python scripts/call.py renderChart '{\"title\":\"放量日申万行业平均涨跌幅排名\", \"lines\":[{\"id\":\"<data_id>\",\"name\":\"放量日平均日涨幅\"}], \"chart_type\":\"bar\", \"task_id\":\"<task_id>\"}'\r\n> ```\r\n\r\n---\r\n\r\n## 常见错误与处理\r\n\r\n| 错误 | 原因 | 处理 |\r\n|------|------|------|\r\n| `成分平均汇总` 返回 assets=0 | `申wx资产所属指数` 的 index_title 写错 | 重新 confirmDataMulti，严格用返回的 index_title |\r\n| `放量日行业平均涨跌幅` assets=7700+（未聚合） | 公式4写错，误用的是全市场回报率而非行业聚合结果 | 确认公式4的变量名用的是 `申万行业每日回报率` |\r\n| 区间统计量 dates=0 | 放量日标记全为 False（条件过严或数据期太短） | 检查 begin_date / 阈值倍数；可先用 `readData(mode=smart_sample)` 看 `放量日标记` 的 True 比例 |\r\n| renderChart 报\"仅支持一维数据\" | `放量日行业平均涨跌幅` 是二维（31×区间数） | 先用 readData 读出截面均值，整理成一维序列后再图表；或改为 last_day_stats 下载后自行排序呈现文本 |\r\n| `数据名不存在：申万资产所属指数` | index_title 与实际返回不符 | 以 confirmDataMulti 返回的 index_title 为准，不要凭记忆猜测 |\r\n\r\n---\r\n\r\n## 延伸用法\r\n\r\n同样的模式可以应用于：\r\n\r\n- **涨停日** / **大跌日** 行业表现：把放量日的布尔公式替换为涨跌幅阈值条件\r\n- **宏观事件标记**：上传一列 0/1 事件标记 CSV，作为 `区间统计量` 的掩码\r\n- **基于成分平均汇总的因子聚合**：把任意全市场因子（估值、动量、质量）映射到行业维度，做行业风格分析\r\n\r\n---\r\n\r\n## 行业聚合排名题执行硬规则\r\n\r\n1. **直接执行公式**：行业聚合题的核心公式（如 `成分平均汇总(涨跌幅(...), \"申万资产所属指数\")`）应直接通过 `runMultiFormula` 执行，不需要先用 `confirmDataMulti` 查\"行业涨跌幅\"等聚合后数据是否存在——聚合结果是公式计算产出的，不是预置数据集\r\n2. **行业名称原样复用**：最终答案中的行业名称必须与工具返回的完全一致（如工具返回\"公用事业\"，不得改写为\"公共事业\"）\r\n3. **TopN 安全读取**：行业聚合结果通常为 31 行（申万一级），可安全使用 `readData(mode=\"last_column_full\")`；但若聚合维度更细（二级行业/概念板块），必须先用 `readData(mode=\"precheck\")` 确认行数\r\n\r\n---\r\n\r\n## 语义恒等：申万一级行业最近一个月涨跌幅排名 TopN\r\n\r\n### 用户意图\r\n> \"请统计申万一级行业中，最近一个月涨跌幅排名前5的行业，并列出各行业月涨幅。\"\r\n\r\n### 正确思路\r\n1. \"最近一个月\"若未特别说明，默认按近 20 个交易日处理\r\n2. \"月涨幅 / 最近一个月涨跌幅\"应理解为**窗口累计涨跌幅**，不是 20 日日均回报\r\n3. 先计算个股近 20 日涨跌幅，再按申万行业做成分平均汇总\r\n\r\n### 正确公式\r\n```\r\n申万行业近20日涨跌幅 = 成分平均汇总(涨跌幅(\"全市场每日收盘价\", 20), \"申万资产所属指数\")\r\n```\r\n\r\n### 易错写法（不要用）\r\n```\r\n# ❌ 这两步算的是\"20日日均回报\"，不是\"20日涨跌幅\"\r\n申万行业每日回报率 = 成分平均汇总(\"全市场每日回报率\", \"申万资产所属指数\")\r\n申万行业月涨跌幅 = 平均(\"申万行业每日回报率\", 20)\r\n```\r\n> 上述结果是\"20日日均回报的算术平均\"（约 0.05%），不是\"20日区间涨跌幅\"（约 1%~5%）。用它回答\"月涨幅\"是语义错误。\n\nFile v4.14.17:recipes/ma-crossover-backtest.md\n\n# 示例一：均线策略选股 + 回测\r\n\r\n## 用户意图\r\n\r\n> \"帮我做一个5日均线上穿20日均线的选股策略，看看历史回测表现怎么样\"\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 0 — 初始化会话\r\n\r\n```bash\r\npython scripts/call.py newSession\r\n```\r\n\r\n---\r\n\r\n### Step 1 — 查案例（cases_index 优先）\r\n\r\n**1a. 读取 `presets/cases_index.yaml`**，搜索 tags 含 `均线`、`MA`、`金叉`、`回测` 的卡片。\r\n\r\n**1b.** 找到后调 `getCardFormulas` 批量拉取：\r\n\r\n```bash\r\npython scripts/call.py getCardFormulas '{\"card_ids\": [\"<相关卡片id>\"]}'  \r\n```\r\n\r\n**1c.** 目录中未找到才 fallback：\r\n\r\n```bash\r\npython scripts/call.py searchSimilarCases '{\"query\": \"均线金叉买入区间持仓回测\", \"top_k\": 3}'\r\n```\r\n\r\n**LLM 操作**：理解案例中均线/金叉公式结构，提炼思路后针对用户的 5/20 均线需求重新组织公式，不照抄案例。\r\n\r\n---\r\n\r\n### Step 2 — 确认数据名称\r\n\r\n```bash\r\npython scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日收盘价, 非ST股\"}'\r\n```\r\n\r\n**预期返回**：\r\n- `全市场每日收盘价` → `index_title: \"全市场每日收盘价\"`（dimension=two）\r\n- `非ST股` → `index_title: \"非ST股\"`（dimension=two, is_bool=true）\r\n\r\n**LLM 操作**：用返回的 `index_title` 写进公式，不要用原始查询词。\r\n\r\n---\r\n\r\n### Step 3 — 执行公式（生成信号 + 回测）\r\n\r\n```bash\r\npython scripts/call.py runMultiFormula '{\r\n  \"task_id\": \"<Step 0 的 task_id>\",\r\n  \"begin_date\": 20150101,\r\n  \"formulas\": [\r\n    \"MA5=平均(\\\"全市场每日收盘价\\\", 5)\",\r\n    \"MA20=平均(\\\"全市场每日收盘价\\\", 20)\",\r\n    \"金叉信号=(\\\"MA5\\\">\\\"MA20\\\")*(昨天(\\\"MA5\\\")<=昨天(\\\"MA20\\\"))*板块(万得全A)*缺失填零(\\\"非ST股\\\")\",\r\n    \"死叉信号=(\\\"MA5\\\"<\\\"MA20\\\")*(昨天(\\\"MA5\\\")>=昨天(\\\"MA20\\\"))*板块(万得全A)*缺失填零(\\\"非ST股\\\")\",\r\n    \"持仓区间=进出场区间(\\\"金叉信号\\\",\\\"死叉信号\\\")\",\r\n    \"NAV=回测(\\\"持仓区间\\\",当天收盘买入,返回复利净值,信号按列归一)\"\r\n  ],\r\n  \"intents\": [\"5日均线\", \"20日均线\", \"金叉信号（排除ST）\", \"等权回测净值\"]\r\n}'\r\n```\r\n\r\n**关键点**：\r\n- 4 个公式共享同一个 `task_id`，后面的公式才能引用前面的变量\r\n- 返回每条公式的 `data_id`，记录 `NAV` 对应的 `data_id`\r\n\r\n---\r\n\r\n### Step 4 — 验证回测结果\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<NAV的data_id>\"], \"mode\": \"precheck\"}'\r\n```\r\n\r\n**预期返回**：\r\n```json\r\n{\r\n  \"type\": \"nav_1d\",\r\n  \"first_value\": 1.0,\r\n  \"last_value\": 3.xx,\r\n  \"total_return\": 2.xx,\r\n  \"curve_samples\": [[20150101, 1.0], ..., [20260227, 3.xx]]\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 5（可选）— 渲染净值曲线图\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"均线金叉策略净值（2015至今）\",\r\n  \"lines\": [{\"id\": \"<NAV的data_id>\", \"name\": \"MA5/20金叉策略\"}],\r\n  \"width\": 1400,\r\n  \"height\": 600\r\n}'\r\n```\r\n\r\n**LLM 操作**：返回 `data.base64`，解码后保存为 PNG 文件，或直接展示给用户。\r\n\r\n---\r\n\r\n## 常见错误与处理\r\n\r\n| 错误 | 原因 | 处理 |\r\n|------|------|------|\r\n| `公式变量未找到` | task_id 不一致，Signal 找不到 MA5 | 确保 4 个公式用同一个 task_id |\r\n| `数据名不存在` | 公式里写的名称和 confirmDataMulti 返回的 index_title 不一致 | 以 index_title 为准 |\r\n| `matchQuality=low` | searchSimilarCases 没搜到好模板 | 换 query 关键词重试一次 |\n\nFile v4.14.17:recipes/render-chart.md\n\n# 示例四：生成多策略净值对比图\r\n\r\n## 用户意图\r\n\r\n> \"我已经跑了两个策略的回测，帮我把净值曲线画成一张图，并和沪深300比较\"\r\n\r\n---\r\n\r\n## 前置条件\r\n\r\n假设已通过 `runMultiFormula` 得到以下 `data_id`：\r\n- 策略A净值：`nav_aaa111`\r\n- 策略B净值：`nav_bbb222`\r\n- 沪深300净值：`nav_ccc333`\r\n\r\n如果还没跑，先参考示例一（均线策略）或示例二（低PE策略）的 Step 3~4。\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 1 — 验证三条净值曲线的基本情况\r\n\r\n```bash\r\npython scripts/call.py readData '{\r\n  \"ids\": [\"nav_aaa111\", \"nav_bbb222\", \"nav_ccc333\"],\r\n  \"mode\": \"precheck\",\r\n  \"sample_points\": 50\r\n}'\r\n```\r\n\r\n**LLM 操作**：\r\n- 确认三条曲线的起止日期一致（都从 `begin_date` 开始）\r\n- 检查 `last_value` 对比，判断哪个策略更优\r\n- 若曲线出现异常（如 last_value=0 或 NaN 率过高），先排查公式错误\r\n\r\n---\r\n\r\n### Step 2 — 渲染对比图\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"策略A vs 策略B vs 沪深300 净值对比\",\r\n  \"lines\": [\r\n    {\"id\": \"nav_aaa111\", \"name\": \"策略A：均线金叉\", \"axis\": \"left\"},\r\n    {\"id\": \"nav_bbb222\", \"name\": \"策略B：低PE 20%\", \"axis\": \"left\"},\r\n    {\"id\": \"nav_ccc333\", \"name\": \"沪深300基准\", \"axis\": \"left\"}\r\n  ],\r\n  \"width\": 1400,\r\n  \"height\": 600,\r\n  \"start_date\": 20150101\r\n}'\r\n```\r\n\r\n**预期返回**：\r\n```json\r\n{\r\n  \"success\": true,\r\n  \"data\": {\r\n    \"base64\": \"iVBORw0KGgoAAAANSUhEUgAA...\",\r\n    \"lines_count\": 3,\r\n    \"width\": 1400,\r\n    \"height\": 600,\r\n    \"errors\": []\r\n  }\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 3 — 保存图片（Python 示例）\r\n\r\nLLM 可以把 base64 解码并保存：\r\n\r\n```python\r\nimport base64\r\nb64 = \"<返回的 base64 字符串>\"\r\nwith open(\"strategy_comparison.png\", \"wb\") as f:\r\n    f.write(base64.b64decode(b64))\r\nprint(\"图片已保存到 strategy_comparison.png\")\r\n```\r\n\r\n---\r\n\r\n## 二维数据绑定资产（非净值曲线的画法）\r\n\r\n如果要画某只个股的价格走势（二维数据中的某一列），需要额外传 `ticker`：\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"贵州茅台收盘价\",\r\n  \"lines\": [\r\n    {\"id\": \"<收盘价data_id>\", \"name\": \"600519.SH\", \"axis\": \"left\", \"ticker\": \"600519.SH\"}\r\n  ]\r\n}'\r\n```\r\n\r\n---\r\n\r\n## 注意事项\r\n\r\n| 场景 | 处理 |\r\n|------|------|\r\n| `errors` 非空 | 某条 line 的 id 不存在或数据类型不支持渲染 |\r\n| 净值曲线起点不一致 | 用 `start_date` 截断至同一起点再渲染 |\r\n| 图片太小看不清 | 调大 `width`（最大建议 1800）和 `height`（最大建议 900） |\r\n| 需要左右双轴 | 把量纲差异大的曲线（如换手率 vs 净值）设为 `\"axis\": \"right\"` |\n\nArchive v4.14.16: 53 files, 241601 bytes\n\nFiles: config.json (125b), presets/assets.yaml (6136b), presets/cases_index.yaml (29693b), presets/data_catalog.yaml (9071b), presets/functions.yaml (15093b), presets/sectors.yaml (17186b), presets/themes.yaml (17784b), recipes/download-data.md (1168b), recipes/event-study-formulas.md (7363b), recipes/ic-factor-templates.md (3309b), recipes/industry-aggregation.md (11787b), recipes/ma-crossover-backtest.md (3518b), recipes/render-chart.md (2750b), recipes/tool-call-checklist.md (3406b), recipes/topn-gainers.md (1637b), recipes/upload-custom-data.md (3235b), recipes/value-pe-strategy.md (3569b), references/environment.md (1981b), references/ru-billing.md (1838b), references/scripts-audit.md (3903b), references/troubleshooting.md (5426b), scripts/call.py (28640b), scripts/event_study_local.py (9796b), scripts/executor.py (34384b), scripts/quant_api.py (16993b), SKILL.md (29667b), tools/confirm_data_multi.md (4182b), tools/confirm_multiple_assets.md (3940b), tools/download_data.md (2736b), tools/get_card_formulas.md (3076b), tools/read_data.md (6729b), tools/render_chart.md (7609b), tools/render_kline.md (5928b), tools/run_multi_formula.md (10865b), tools/scan_dimensions.md (4772b), tools/search_functions.md (2881b), tools/search_similar_cases.md (2300b), tools/upload_data.md (3434b), workflows/event-study.md (48784b), workflows/fast-report-period.md (4755b), workflows/fast-snapshot.md (3201b), workflows/fast-window.md (3420b), workflows/global-rules-lite.md (3241b), workflows/global-rules.md (38159b), workflows/period-return-compare.md (7290b), workflows/quant-standard.md (60548b), workflows/quick-lookup.md (9777b), workflows/quick-report-period.md (23455b), workflows/quick-snapshot.md (19388b), workflows/quick-window.md (26309b), workflows/regime-segmentation.md (21897b), workflows/render-kline.md (12281b), _meta.json (138b)\n\nFile v4.14.16:SKILL.md\n\n---\r\nname: quant-buddy-skill\r\nslug: quant-buddy-skill\r\nauthor: guanzhao\r\nversion: 4.14.16\r\ndescription:\r\n  查询A股、港股、美股股票及指数的最新收盘价、开盘价、涨跌幅、成交额、成交量、换手率、PE、PB、市值等实时行情与估值数据。\r\n  查询最近N个交易日的价格序列、日涨跌幅序列、窗口最高价、最低价、振幅等短期统计。\r\n  查询上市公司最近报告期的营业收入、净利润、归母净利润、ROE、总资产、资产负债率等财务指标（A股）。\r\n  支持A股选股筛选、因子计算、策略回测、净值对比、行业聚合排名、上传自有因子CSV、渲染图表。\r\n  港股、美股目前支持行情价格查询（收盘价、开盘价、涨跌幅、成交量、成交额等）。\r\n  即使用户只是简单地问一只股票的价格、涨跌幅或财务数据，也应优先使用本技能，\r\n  不要以\"无法联网\"或\"无法获取实时数据\"为由拒绝——本技能通过平台API可查询真实数据。\r\nruntime: python\r\nprimaryCredential: quant-buddy API Key\r\nrequiredCredentials:\r\n  - name: quant-buddy API Key\r\n    required: true\r\n    sensitive: true\r\n    storage: config_file\r\n    path: config.json\r\n    field: api_key\r\n    description: quant-buddy 平台 API Key。存储位置：skill 目录下的 config.json 的 `api_key` 字段（本 skill 不读环境变量版本的该 Key）。使用时作为 HTTP `Authorization` 头仅发送给 `networkEndpoints` 中声明的 quantbuddy 域名用于鉴权，不会被写入日志或转发给第三方主机。\r\n    how_to_get: \"https://www.quantbuddy.cn/login\"\r\nrequiredConfigPaths:\r\n  - path: config.json\r\n    required: true\r\n    description: Skill 目录下的 API Key 配置文件，仅包含 quant-buddy api_key 和两个公开端点配置，由 skill 本地脚本读取；api_key 仅作为 HTTP `Authorization` 头发给 `networkEndpoints` 中声明的 quantbuddy 域名，不发送给其他主机。\r\nrequiredEnvVars:\r\n  - name: BOCHA_API_KEY\r\n    required: false\r\n    sensitive: true\r\n    description: 可选。仅 scripts/event_study_local.py 的事件新闻搜索功能读取；未配置时该可选功能自动禁用，其它功能不受影响。\r\n    how_to_get: \"https://open.bochaai.com\"\r\nnetworkAccess: true\r\nnetworkEndpoints:\r\n  - https://www.quantbuddy.cn/skill\r\n  - https://www.quantbuddy.cn/user\r\nruntimeRequirements:\r\n  python: \"3.8+\"\r\n  packages: []\r\n---\r\n\r\n# 观照量化投研\r\n\r\n> **⚠️ 必读：本文件较长，必须完整读取，不要设置 limit 参数截断。前 50 行不包含操作规范。**\r\n\r\n## 硬规则（7 条，违反必失败）\r\n\r\n0. **开工第一步：先查 API Key，再做任何其他事**。收到新问题后的第一个动作必须是读 `config.json`（或等效检查 api_key 字段）：\r\n   - 若 `api_key` 为空字符串 → **立即停止**，直接输出「前置条件」章节的**新用户引导消息**，**禁止** newSession、**禁止**读 workflow / quick-lookup / 任何业务文档、**禁止**调用 `scripts/call.py` 或任何平台工具。等用户贴入 `sk-` 开头的 Key 后再执行「配置向导」。\r\n   - 若 `api_key` 非空 → 继续第 1 条。\r\n   - **唯一例外**：用户本轮消息本身就是 `sk-` 开头的 Key（进入配置向导）或与查数无关的闲聊/元问题（如\"你会做什么\"）。\r\n   - **为什么**：查数类工作流最终都会调 `scripts/call.py`，api_key 为空时必然失败。提前在入口拦截可以避免多次失败调用，给新用户直接、清晰的第一印象。\r\n\r\n1. **每个新问题/新对话必须新建 session**：收到用户的新问题后，在调用任何平台工具之前，必须先新建 session（优先直接调用原生 `newSession` 工具；仅当当前环境没有原生 `newSession` 时，才使用 `GZQ_PARAMS='{\"user_query\":\"<用户的问题>\"}' python scripts/call.py newSession`）。newSession 是本地 UUID 生成，不可省略；`user_query` 仅用于本地 session 初始化标注，方便后续 trace 分析。\r\n   - **为什么**：`.session.json` 会自动注入到所有工具调用中。不新建 session = 复用上一轮对话的 task_id = 变量名冲突风险 + session 污染。\r\n   - **唯一例外**：同一对话中的追问/续问（如\"再画个图\"\"换个时间段\"），可复用当前 session。\r\n2. **原生工具优先，脚本包装仅限无原生等价能力时**：平台已提供的原生工具（`confirmMultipleAssets`、`confirmDataMulti`、`runMultiFormula`、`readData`、`renderKLine`、`renderChart` 等）必须优先直接调用；禁止用 `run_skill_script`、shell 命令、`GZQ_PARAMS=... python scripts/call.py ...` 等方式包装这些原生工具；`scripts/call.py` 仅用于：① `newSession` 等管理动作；② workflow 明确要求的本地脚本步骤；③ 平台不存在等价原生工具时的兜底。\r\n3. **先读 workflow 再操作**：按下方「场景路由」表加载对应 workflow，不要自行猜测参数格式。\r\n4. **配置/认证错误立即停止，不得在普通查数流程中转为认证收集**：\r\n   - **工具返回 API Key 缺失错误**（含 `api_key 为空` 消息 / `code: 1`）：立即停止查数，输出**新用户引导消息**（格式见「前置条件」章节模板），禁止继续执行查数；等待用户粘贴 Key 后再执行配置向导。\r\n   - **其他工具报错**（网络、服务端错误等）：直接报告\"内部工具异常\"，不做认证相关引导。\r\n5. **最终答案首句必须是数据结论**：回答用户时，第一句话必须直接给出数据结论（如资产名+数值、表格、或\"符合条件的共N只\"），绝对禁止以\"已成功获取\"\"数据已获取\"\"根据返回结果\"\"让我来\"等过程性陈述开头。违反此规则 = 必须删除过程话术后重新输出。\r\n6. **用户条件冻结，不得改写**：执行前必须逐字核对用户原始条件，以下改写行为均属违规（一旦发现必须回退并重新确认）：\r\n   - **百分比↔小数互转**（如\"股息率>3%\"禁止改写为 `>0.03`）\r\n   - **相对时间改为年份区间**（如\"过去10年\"禁止改写为\"2015-2025\"）\r\n   - **资产宇宙替换**（如\"普通股票\"禁止改写为\"万得全A成分股\"或\"非ST股\"）\r\n   - **事件口径扩大**（如\"年报/半年报\"禁止扩大为全部业绩披露类型）\r\n   - **卡片附加条件继承**：命中知识卡片后，若卡片含用户未明确提出的\"首次/非ST/封板/流动性门槛\"等附加条件，必须先删除再执行，禁止默默继承进最终答案\r\n\r\n## 最小充分原则（任何动作前自检）\r\n\r\n> 默认走最窄路径；只在收到\"明确不够用\"的证据后，才扩大范围。\r\n\r\n**每次准备读文件、调工具、扩大读取范围前，回答三个问题**：\r\n\r\n1. **这一步要解决的具体问题是什么？** — 必须能用一句话写成\"为了 X，所以做 Y\"，其中 X 是**已经发生**的需求，不能是\"可能会需要 X\"、\"以防万一\"、\"先准备着\"。\r\n2. **有没有更窄的选项能完成同样的 X？** — 更下游的输出 / 更精简的文件 / 更少的字段 / 不调用这个工具直接构造。\r\n3. **当前选择如果失败，下一步是什么？** — 如果答不上来，说明还没想清楚就在动手。\r\n\r\n任一回答含糊 → 不做这一步。\r\n\r\n**扩大范围的唯一合法触发**：上一步工具明确返回了\"缺数据 / 字段不存在 / 失败\"，且失败原因可以追溯。不允许用\"为了更全面\"、\"为了更准确\"、\"为了避免遗漏\"作为理由。\r\n\r\n> 这条原则覆盖：要不要多读一个文档；readData 读哪个变量；要不要为某个字段调 confirmDataMulti；公式自己写还是查现成数据集；以及所有未来出现的同类决策。\r\n\r\n**工具层面落地**：调用 `confirmDataMulti` / `readData` / `runMultiFormula` 或加载额外文档前，必须先勾选 [`recipes/tool-call-checklist.md`](recipes/tool-call-checklist.md) 对应小节（每节 5–10 行）。顶层原则管\"要不要做\"，清单管\"具体怎么做\"。\r\n\r\n## Skill 包根目录\r\n\r\n**本 SKILL.md 所在目录即为 skill 根目录（`SKILL_ROOT`）**，下文所有相对路径均以此为基准。\r\n所有终端命令必须先 `cd` 到此目录再执行。\r\n\r\n```\r\nSKILL_ROOT/\r\n├── config.json              ← API Key 配置（按需读取；非每题必读）\r\n├── SKILL.md                 ← 本文件（入口 + 路由）\r\n│\r\n├── workflows/               ← 业务流程编排（路由目标）\r\n│   ├── fast-snapshot.md         Fast Path：最新时点行情/估值（≤3资产，标量）\r\n│   ├── fast-window.md           Fast Path：最近N日序列/窗口统计\r\n│   ├── fast-report-period.md    Fast Path：最近报告期财务（≤3资产）\r\n│   ├── quick-lookup.md          快速查数路由器 + 共享基础规则\r\n│   ├── quick-snapshot.md        最新时点行情/估值快照（字段齐即停）\r\n│   ├── quick-window.md          最近N日短窗序列/窗口统计\r\n│   ├── quick-report-period.md   最近报告期财务指标\r\n│   ├── period-return-compare.md 固定区间累计涨跌幅对比\r\n│   ├── global-rules-lite.md     精简全局规则（quick-window/period-return-compare 专用）\r\n│   ├── quant-standard.md        选股/回测/因子/图表标准流程\r\n│   ├── event-study.md           事件研究（给定或可识别事件后的窗口表现）\r\n│   ├── regime-segmentation.md   阈值区间/连续阶段识别与区间统计\r\n│   └── render-kline.md          K线图渲染与交付\r\n│\r\n├── recipes/                 ← 公式模板 & 工具用法（被 workflow 引用）\r\n│   ├── ma-crossover-backtest.md     均线金叉策略\r\n│   ├── value-pe-strategy.md         PE估值选股\r\n│   ├── upload-custom-data.md        上传自有数据\r\n│   ├── render-chart.md              渲染图表\r\n│   ├── download-data.md             下载数据\r\n│   └── industry-aggregation.md      行业聚合排名\r\n│\r\n├── references/              ← 参考文档\r\n│   ├── environment.md           环境依赖\r\n│   ├── troubleshooting.md       故障排查\r\n│   └── ru-billing.md            RU 计费\r\n│\r\n├── tools/                   ← 12 个 API 工具的完整参数文档\r\n│   ├── run_multi_formula.md\r\n│   ├── read_data.md\r\n│   └── ...（正常链路无需提前阅读，遇到参数问题时查）\r\n│\r\n├── presets/                 ← 已验证的常用数据（按需加载）\r\n│   ├── cases_index.yaml         106 张案例卡片目录（量化标准场景必读，快速查数无需）\r\n│   ├── assets.yaml              常用资产\r\n│   ├── functions.yaml           常用函数\r\n│   ├── data_catalog.yaml        常用数据集\r\n│   ├── sectors.yaml             行业板块\r\n│   └── themes.yaml              题材板块\r\n│\r\n├── scripts/                 ← 执行脚本\r\n│   ├── call.py                  工具统一入口（所有命令通过它调用）\r\n│   ├── executor.py              call.py 的底层（禁止直接调用）\r\n│   ├── quant_api.py             Python SDK（供其他脚本 import）\r\n│   ├── auth/                    认证脚本\r\n│   └── eval/                    评测脚本\r\n│\r\n└── output/                  ← 输出目录（自动创建）\r\n    ├── .session.json            当前 session task_id\r\n    ├── ic_data/                 IC 扫描结果\r\n    └── *.png / *.csv            图表和数据文件\r\n```\r\n\r\n---\r\n\r\n**全局 429 处理（所有路径均适用）**：\r\n\r\n| error.code | 处理 |\r\n|---|---|\r\n| `RATE_LIMIT_EXCEEDED` / `CONCURRENT_LIMIT` | 读 `retryAfter` 秒后**静默重试**，不向用户暴露 |\r\n| `WINDOW_QUOTA_EXCEEDED` | **立即停止**，读 `references/troubleshooting.md` 配额限流段，输出提示 |\r\n| `DAILY_QUOTA_EXCEEDED` / `DAILY_SCAN_EXCEEDED` | **立即停止**，输出：`⚠️ 今日额度已满，次日 00:00 重置。` |\r\n| `SERVICE_OVERLOADED`（503） | `retryAfter` 秒后静默重试 1 次，仍失败则告知\"系统繁忙，请稍后重试\" |\r\n\r\n---\r\n\r\n## ⛔ 执行顺序（路由前必读，所有场景必须遵守）\r\n\r\n**无论匹配到哪个 leaf workflow，执行顺序固定为：**\r\n\r\n```\r\n① read_skill_file(global-rules 版本，见下表)  →  ② read_skill_file(leaf workflow)  →  ③ 执行\r\n```\r\n\r\n**步骤 ① 全局规则文件选择（按目标 leaf workflow 确定）**：\r\n\r\n| 目标 leaf workflow | 步骤 ① 读取的文件 |\r\n|---|---|\r\n| `quick-window.md` | `workflows/global-rules-lite.md` |\r\n| `period-return-compare.md` | `workflows/global-rules-lite.md` |\r\n| 其他所有 workflow | `workflows/global-rules.md` |\r\n\r\n- **步骤 ① 是硬前置条件**。确定目标 leaf 后，先按上表选择并读取对应 global-rules 版本，再读 leaf workflow，最后执行。\r\n- 禁止读完路由表就直接跳转 leaf workflow（Fast Path 中读 fast 文件除外）。\r\n\r\n---\r\n\r\n## 场景路由\r\n\r\n**先识别用户意图，确定目标 leaf workflow；然后按上方执行顺序加载**：\r\n\r\n| 场景 | 触发词 | 目标 leaf workflow |\r\n|------|--------|----------|\r\n| 最新时点行情 / 估值（快照） | 最新价、今日收盘、最新涨跌幅、当前换手率、最新PE/PB/市值… | Fast Path → `fast-snapshot.md` / 完整链路 → `global-rules.md` → `quick-snapshot.md` |\r\n| 最近N日序列 / 窗口统计 | 最近5日、最近20日、近N个交易日、窗口最高/最低/振幅…（仅单资产、最近N日） | Fast Path → `fast-window.md` / 完整链路 → `global-rules-lite.md` → `quick-window.md` |\r\n| 最近报告期财务 | 营收、净利润、归母净利润、ROE、总资产、总负债、资产负债率… | Fast Path → `fast-report-period.md` / 完整链路 → `global-rules.md` → `quick-report-period.md` |\r\n| K线图（可视化） | K线图、画图、展示走势… | `global-rules.md` → `render-kline.md` |\r\n| 固定区间累计涨跌幅 | 从A到B、某年某月至某年某月、区间收益、累计涨跌幅、区间表现、多资产区间对比 | `global-rules-lite.md` → `period-return-compare.md` |\r\n| 量化选股 / 回测 / 因子 / 图表 / 上传下载 | 选股、回测、均线、PE选股、因子、净值、上传CSV、下载数据、画图… | `global-rules.md` → `quant-standard.md` |\r\n| 事件研究 | 复盘、历次、涨价、降息、加息、事件窗口、随后表现、超预期、不及预期、政策后表现…（给定事件或需先识别事件日） | `global-rules.md` → `event-study.md` |\r\n| 阈值区间统计 / 连续阶段 | 历次、每次、平均、回撤超过、从高点下跌超过、熊市区间、连续阶段、regime | `global-rules.md` → `regime-segmentation.md` |\r\n\r\n> 上传、下载、画图不是独立场景——它们是 workflow 内的子步骤，workflow 文档会在需要时指引你读对应的 `recipes/`。\r\n\r\n### 路由硬排除（优先于触发词匹配）\r\n\r\n以下规则在触发词匹配**之前**检查，命中即强制改道，不得被触发词覆盖：\r\n\r\n| 用户意图特征 | 禁止进入 | 强制导向 | 判断依据 |\r\n|-------------|---------|---------|---------|\r\n| 盘中/实时/当前/现在/今天/今日/当日 + 查询日内行情（涨幅排名、涨停、日内跌幅等） | `quick-snapshot` `quick-window` | `quant-standard.md`（优先匹配分钟频卡片） | 需要分钟频卡片的专用公式；`use_minute_data: true` 已是全局默认 |\r\n| 盘中/实时/当前/今天/今日/当日 + 全市场/板块 + TopN/排名/阈值名单/选股/筛选/信号 | `quick-snapshot` `quick-window` | `quant-standard.md` → 优先命中\"实时横截面 TopN 排名\"或\"盘中阈值筛选_名单查询\"微流程 | 这类高频短题有专用封闭微流程 |\r\n| 给出明确起止日期，只问区间累计涨跌幅/收益 | `event-study` `quick-window` `quant-standard` | `period-return-compare.md` | 本质是固定区间收益比较，不是因果窗口分析，也不是复杂量化流程 |\r\n| 行业/板块聚合排名（如\"申万行业涨幅前5\"） | `quick-window` `quick-snapshot` | `quant-standard.md` | 需要横截面聚合，不是单资产序列 |\r\n| 阈值触发型离散事件识别（如\"跌幅超过X%的次数\"，问每次后表现） | — | `event-study.md`（阈值触发模式） | 需先识别阈值事件日，再做窗口分析 |\r\n| 由阈值条件定义连续区间（如\"历次熊市\"\"回撤超30%的阶段\"） | `event-study` | `regime-segmentation.md` | 研究的是连续阶段而非离散事件后的窗口 |\r\n| \"创近N日新高/新低\"（不含\"首次\"修饰词） | 不得加\"昨日未满足\"条件 | 按**当前状态**判断（state check），公式只比较当前值与昨日的N日极值 | 只有用户明确出现\"首次突破/首次跌破\"\"新晋\"\"今日第一次\"时，才允许追加首次触发条件；详见 `quant-standard.md` |\r\n\r\n判断口诀：\r\n- **有明确起止日 + 只问区间数值** → `period-return-compare`（固定区间收益比较）\r\n- **有事件 + 问\"随后N天/月表现\"** → `event-study`（因果窗口）\r\n- **有阈值条件 + 问\"每次发生后表现\"** → `event-study`（阈值触发模式）\r\n- **有阈值条件 + 问\"连续阶段/区间内表现\"** → `regime-segmentation`（连续阶段统计）\r\n\r\n若用户请求满足以下任一模式，应优先判定为【快速查数任务】，按以下路由直接跳转，不得先进入其他 workflow：\r\n\r\n**快速查数路由（按优先级依次判断，首个匹配即停）：**\r\n\r\n1. 时间锚点是\"最近 N 日窗口/序列\" → Fast Path 条件满足时读 `workflows/fast-window.md`，不满足则 `workflows/global-rules-lite.md` → `workflows/quick-window.md`\r\n2. 时间锚点是\"最近报告期\"且字段属于财务类 → Fast Path 条件满足时读 `workflows/fast-report-period.md`，不满足则 `workflows/global-rules.md` → `workflows/quick-report-period.md`\r\n3. 用户明确要\"画图 / K线 / 带成交量走势\" → 直接加载 `workflows/render-kline.md`\r\n4. 其余（明确是最近完成交易日的行情/估值/多资产对比，且**不含** 今天/今日/当日/当前/现在/实时/盘中/排名/筛选 语义）→ Fast Path 条件满足时读 `workflows/fast-snapshot.md`，不满足则 `workflows/global-rules.md` → `workflows/quick-snapshot.md`\r\n\r\n> 上述路由不需要先读 `workflows/quick-lookup.md`。\r\n\r\n### 关键红线速查（即使未读 global-rules.md 也必须遵守）\r\n\r\n以下 4 条规则从 global-rules.md 摘录，**优先级最高**，对所有场景生效：\r\n\r\n1. **事件定义冻结**：事件类型/范围必须**逐字匹配用户原始措辞**。用户说\"年报/半年报\"就只查年报和半年报，不得扩大到业绩预告/快报/季报；用户说\"国务院或住建部\"就只纳入该层级，不得扩大到央行/银保监会/地方政府。若认为用户定义可能遗漏，在回答末尾**建议**扩大，不得擅自扩大。\r\n2. **evidence-only 回答**：最终答案只输出本轮工具结果直接支持的数值、日期、排名、口径说明。未经工具验证，禁止默认输出宏观归因、政策归因、方向性判断（\"通常\"\"往往\"\"偏正面\"）。\r\n3. **去过程化交付**：禁止「已成功获取」「让我来」「按照流程」「Step 1/2/3」「根据 workflow」等过程性话术；禁止泄露 `_working/` 路径、checkpoint 名称、workflow 文件名。查到即答，不展示内部过程。\r\n4. **条件口径冻结**：用户条件必须原样执行，禁止任何改写（百分比↔小数、相对时间→年份区间、资产宇宙替换、卡片附加条件继承）。详见硬规则第 6 条。\r\n\r\n触发词参考：\r\n- 最近交易日收盘 / 最新已披露PE / 最新市值（非盘中、非筛选） → `quick-snapshot`\r\n- 最近5日 / 最近20个交易日 / 近N日序列 / 窗口最高最低 → `quick-window`\r\n- 营收 / 净利润 / ROE / 总资产 / 总负债 / 资产负债率 → `quick-report-period`\r\n\r\n禁止：\r\n- 优先调用 `scanDimensions`、`renderKLine`（除非用户明确要看图）\r\n- 先做分析性扩写，再补充结构化数值\r\n- **在读取对应 leaf workflow 之前**直接调用 `runMultiFormula` / `renderKLine` / `scanDimensions` / 输出\"无法联网\"或\"无法获取实时数据\"\r\n- 把卡片附加条件（首次/非ST/封板/流动性门槛等）默默继承进最终答案\r\n- 以 `description`、`samples`、预览行、截断大表作为**名单题**的完整结果直接收尾（必须提取完整名单或明确声明不完整）\r\n\r\n**leaf workflow 最终回答合同优先**：leaf workflow 中的\"最终回答合同\"优先负责收紧该场景的输出格式；若 leaf workflow 已满足停止条件，必须直接按该合同输出，不得再解释内部过程。\r\n\r\n## 执行权授权规则\r\n\r\n**规则层级（从高到低）：**\r\n\r\n1. **SKILL.md**：路由 + 全局门禁（硬规则 4 条、路由硬排除）\r\n2. **global-rules.md**：所有 leaf 必须遵守的全局合同（执行合同、证据分级、简答模式、不补精度、方法限制说明、参数规范、数值精度、终答一致性检查）\r\n3. **leaf workflow**：当前任务的具体执行流程（checkpoint、模板、停止条件、格式化）\r\n\r\n**冲突解决**：\r\n- leaf workflow 中的具体规则（如 readData 模式选择）优先于 global-rules 的一般规则\r\n- 但 leaf workflow 不得**放宽** global-rules 的红线（如证据分级门槛、不补精度原则）\r\n- 不得从其他 leaf workflow 借用模板、fallback 或回答格式\r\n\r\n**quick-lookup.md 的定位**：\r\n- 仅作为快查子流程的路由入口和规则参考总表\r\n- 各 leaf workflow 已自包含所有执行规则，执行时无需回到 quick-lookup.md\r\n- quick-lookup.md 不定义任何 leaf 独有规则\r\n\r\n## 全局执行规则\r\n\r\n> **全局合同详见 `workflows/global-rules.md`，进入任何 leaf workflow 时自动生效。**\r\n> leaf workflow 可在其内部添加更严格的约束，但不得豁免或放宽 global-rules 中的规则。\r\n\r\n## 平台数据覆盖范围\r\n\r\n| ✅ 支持 | ⚠️ 有条件支持 | ❌ 不支持（短期内不会支持） |\r\n|------|------|------|\r\n| A股个股（沪深主板/创业板/科创板/北交所） | ETF / LOF / 场外基金（先以 `confirmMultipleAssets` 结果为准，能确认则正常执行；确认失败才告知不支持） | 期货 / 期权 |\r\n| 港股个股（HK + 代码，如 HK0001） | | 台股 / 韩股 / 日股 / 德股等其他境外市场 |\r\n| 美股个股（NASDAQ: 代码.N；NYSE: 代码.O；AMEX: 代码.A） | | |\r\n| 主要宽基指数（沪深300、中证500、万得全A等） | | |\r\n\r\n> **港股 / 美股数据范围限制**：港股和美股目前仅支持**行情价格类数据**（收盘价、开盘价、最高价、最低价、涨跌幅、成交量、成交额）。估值数据（PE/PB/市值等）和财务数据（营收/净利润/ROE等）暂不支持。查询港股/美股的估值或财务字段时，应主动告知用户当前不支持，而不是静默跳过。\r\n\r\n### 股票代码格式速查\r\n\r\n| 市场 | 格式 | 示例 |\r\n|------|------|------|\r\n| A股-上交所 | SH + 代码 | SH600000 |\r\n| A股-深交所 | SZ + 代码 | SZ000001 |\r\n| 港股 | HK + 代码 | HK0001 |\r\n| 美股-NASDAQ | 代码.N | AAPL.N |\r\n| 美股-NYSE | 代码.O | AAL.O |\r\n| 美股-AMEX | 代码.A | SBE.A |\r\n\r\n> 确认资产失败（熔断规则）详见 `workflows/quick-lookup.md` § Step 1。\r\n\r\n> 环境依赖（Python版本、Playwright、API Key）→ `references/environment.md`\r\n> 故障排查 → `references/troubleshooting.md`\r\n> RU 计费 → `references/ru-billing.md`\r\n\r\n---\r\n\r\n## 前置条件（按需执行，不是简单查数的默认首步）\r\n\r\n> **凭据存储说明**：本 skill 的 quant-buddy API Key **只存放在 skill 目录下的 `config.json` 的 `api_key` 字段**，不使用环境变量（`QUANT_BUDDY_API_KEY` 等环境变量不会被读取）。仅可选的 `BOCHA_API_KEY`（事件新闻搜索）走环境变量。\r\n\r\n仅在以下情形下，才需要显式读取 `config.json` 检查 `api_key`：\r\n- 本轮实际需要调用本地脚本或平台工具，且当前环境尚未建立可用 session\r\n- 上一轮工具调用已出现 401 / 402 / 明确认证错误\r\n- workflow 明确要求执行脚本链（如本地 Python 脚本渲染）\r\n\r\n对已命中 leaf workflow 的简单查数题（quick-snapshot / quick-window / quick-report-period / render-kline）：\r\n- 不要为了形式完整额外读取 `config.json`\r\n- 优先直接按 leaf workflow 执行\r\n- 仅当工具调用出现明确认证问题时，再回到认证向导\r\n\r\n原则：认证检查服务于执行，不应成为简单题的固定额外步骤。\r\n\r\n- 若 `api_key` **非空** → 正常继续\r\n- 若 `api_key` **为空** → **立即停止**，禁止继续查数，输出以下**新用户引导消息**（原样输出，不得删减）：\r\n\r\n  ---\r\n  ⚠️ 尚未配置 API Key，当前无法查询数据。\r\n\r\n  前往 https://www.quantbuddy.cn/login 登录/注册并获取 API Key，然后直接发给我：\r\n  > 帮我配置 APIkey：sk-xxxxxxxx\r\n  ---\r\n\r\n---\r\n\r\n### 配置向导（用户粘贴 Key）\r\n\r\n当用户消息中包含 `sk-` 开头的字符串时：\r\n\r\n1. 从用户消息中提取 `sk-` 开头的完整 Key 字符串\r\n2. 将 Key 写入 `config.json` 的 `api_key` 字段（用 `replace_string_in_file` 直接写入）\r\n3. **必须输出**：「✅ API Key 配置成功！」\r\n4. **自动重试**：若本对话中有被 api_key 缺失错误中断的查询（如之前用户问过行情），**立即重新执行该查询并给出数据结论**，不需要用户再次发起。\r\n\r\n**运行时 401/402** → 立即停止，提示用户 API Key 无效/过期/配额耗尽，请重新前往官网获取新的 Key 并重新配置。\r\n\r\n---\r\n\r\n## 工具调用方式\r\n\r\n所有工具通过 `scripts/call.py` 调用。`call.py` 会同时将结果打印到 stdout 和写入临时文件。\r\n\r\n### 标准调用（一步完成）\r\n\r\n```bash\r\npython scripts/call.py <工具名> '{\"key\":\"value\"}'\r\n```\r\n\r\n结果直接从 stdout 获取。若 stdout 被截断，可回读 `/tmp/gzq_out.txt`。\r\n\r\n也可通过环境变量传参（适用于参数含特殊字符的场景）：\r\n\r\n```bash\r\nGZQ_PARAMS='<JSON>' python scripts/call.py <工具名>\r\n```\r\n\r\n### 禁止事项\r\n\r\n| 禁止 | 原因 |\r\n|------|------|\r\n| 创建自定义 .py 写参数文件 | 环境变量方案已解决编码问题 |\r\n| 直接调用 `scripts/executor.py` | `call.py` 封装了 renderChart 自动保存等逻辑 |\r\n| `echo` 管道传参（Windows） | GBK 编码截断中文 |\r\n| 命令行参数传 JSON（Windows） | PS 吃掉双引号 |\r\n\r\n---\r\n\r\n## presets/、recipes/、tools/ 三个目录的分工\r\n\r\n| 目录 | 是什么 | 何时读 |\r\n|------|---------|--------|\r\n| **presets/** | 平台实际返回值的本地快照（YAML）。资产名、函数格式、数据集 index_title、行业/概念名等。**直接可用于公式**，省掉确认类 API 调用。 | 写公式前先查 preset；找不到再调对应 API，并把新结果补回 preset。`cases_index.yaml` 仅在**选股/回测/因子/图表等量化标准场景**（`quant-standard.md`）开始时必读；快速查数场景（quick-snapshot/window/report-period）无需读取。 |\r\n| **recipes/** | 端到端使用示例（Markdown）。展示完整场景——从参数准备到最终输出。 | 由 workflow 在具体步骤中指引加载（不独立触发）。 |\r\n| **tools/** | API 参数手册（Markdown）。每个工具的字段、类型、约束。 | 默认不读。workflow 工具表标注了「必读」或报错时再查。 |\r\n\r\n> **简言之**：presets 是数据快照，recipes 是完整教程，tools 是参数字典。\r\n> presets 6 个文件的详细用法和加载时机→ 当前 workflow 文档内的「预设资源」表。\r\n\r\n---\r\n\r\n## Skill 更新部署规范（LLM 必读）\r\n\r\n当用户要求更新本 skill（发送 zip 压缩包）时，必须严格遵守以下规则：\r\n\r\n### 备份位置\r\n\r\n⚠️ **备份目录禁止放在 `skills/` 目录下。** 否则 openclaw 会把备份也识别为一个独立 skill，导致后续请求可能误用旧版代码。\r\n\r\n正确做法：\r\n\r\n```bash\r\n# 备份到 skills/ 之外的位置\r\ncp -r ~/.openclaw/workspace/skills/quant-buddy-skill ~/.openclaw/workspace/quant-buddy-skill-backup-$(date +%Y%m%d%H%M)\r\n\r\n# ❌ 错误：备份仍在 skills/ 下\r\n# cp -r ~/.openclaw/workspace/skills/quant-buddy-skill ~/.openclaw/workspace/skills/quant-buddy-skill-backup-xxx\r\n```\r\n\r\n### 解压覆盖\r\n\r\n```bash\r\n# 解压到临时目录再拷贝（避免嵌套）\r\nTMPDIR=$(mktemp -d)\r\nunzip -o <压缩包路径> -d \"$TMPDIR\"\r\n# 如果解压出嵌套目录 quant-buddy-skill/，取内层\r\nif [ -d \"$TMPDIR/quant-buddy-skill\" ]; then\r\n  cp -rf \"$TMPDIR/quant-buddy-skill/\"* ~/.openclaw/workspace/skills/quant-buddy-skill/\r\nelse\r\n  cp -rf \"$TMPDIR/\"* ~/.openclaw/workspace/skills/quant-buddy-skill/\r\nfi\r\nrm -rf \"$TMPDIR\"\r\n```\r\n\r\n### 部署后检查\r\n\r\n1. 确认 `~/.openclaw/workspace/skills/` 下只有 `quant-buddy-skill/` 一个与本 skill 相关的目录\r\n2. 读取 `SKILL.md` 确认版本号\r\n3. 保留 `config.json` 中已有的 `api_key`（若用户之前已认证过）\n\nFile v4.14.16:_meta.json\n\n{\n  \"ownerId\": \"kn7b02063x75b1b8yswrzgesph858j2j\",\n  \"slug\": \"quant-buddy-skill\",\n  \"version\": \"4.14.16\",\n  \"publishedAt\": 1777016363685\n}\n\nFile v4.14.16:references/environment.md\n\n# 环境依赖说明\r\n\r\n本文档描述运行 `quant-buddy-skill` 及其子场景所需的环境配置。\r\n\r\n---\r\n\r\n## Python\r\n\r\n- **版本要求**：Python 3.8+（推荐 3.11）\r\n- **核心功能**：仅依赖标准库，无需额外 `pip install`\r\n- **Windows 推荐启动方式**：所有涉及中文路径的脚本加 `-X utf8` 标志\r\n\r\n```bash\r\npython -X utf8 scripts/call.py <工具名>\r\n```\r\n\r\n---\r\n\r\n## API Key 配置\r\n\r\n前往 https://www.quantbuddy.cn/login 登录/注册，在账户页面获取 API Key。获取后有两种方式写入：\r\n\r\n1. **手动编辑**：直接打开 skill 根目录下的 `config.json`，把 `api_key` 字段改为你的 Key。\r\n2. **贴给 AI 助手**：在对话中把 `sk-...` 开头的 Key 发给 AI，AI 会写入 `config.json`。\r\n\r\n若你需要保留私有配置或覆盖默认端点，请使用 `config.local.json`；该文件仅供本地使用，不应打包或提交。\r\n\r\n若出现 `401 Unauthorized` 或 `402 Quota`，请重新获取并更新 `config.json` 中的 `api_key`。\r\n\r\n---\r\n\r\n## 可选 Bocha 搜索能力\r\n\r\n仅部分 Web 搜索辅助场景需要博查凭证；核心行情、财务、选股、回测能力不依赖该凭证。\r\n\r\n可选配置方式（任一即可）：\r\n\r\n- 环境变量 `BOCHA_API_KEY`\r\n- `config.local.json` 中手动添加 `bocha_api_key`\r\n- `config.json` 中手动添加 `bocha_api_key`\r\n\r\n---\r\n\r\n## 运行时输出目录\r\n\r\n- `output/.session.json`：当前 session 的 task_id\r\n- `output/ic_data/`：IC 扫描结果（若 workflow 触发相关能力）\r\n- 其他 `csv / png / json / html`：运行过程中的临时或交付产物\r\n\r\n---\r\n\r\n## readData 批量限制\r\n\r\n`readData` 单次调用最多传入 **10 个 data_id**。如需读取更多结果，拆分多次调用。\r\n\r\n---\r\n\r\n## 终端注意事项\r\n\r\n- 终端缓冲可能导致长输出不完整显示，`call.py` 会额外写入系统临时目录下的 `gzq_out.txt`\r\n- 若需排查，可在系统临时目录中查看该文件内容\n\nFile v4.14.16:references/ru-billing.md\n\n# RU 计费体系\r\n\r\n> 更新于 2026-04-15。统一 RU（Resource Unit）体系，所有端点共享一个 RU 池。\r\n> 每个请求按端点类型 + 请求参数动态扣减 RU（1～26 RU）。\r\n> 规划流程时优先减少冗余调用。\r\n\r\n---\r\n\r\n## RU 权重速查表\r\n\r\n| 工具 | 模式 | RU 消耗 | 说明 |\r\n|------|:---:|:---:|------|\r\n| `search_functions` | fixed | 1 | |\r\n| `get_card_formulas` | fixed | 1 | |\r\n| `upload_preview` | fixed | 1 | |\r\n| `upload_confirm` | fixed | 1 | |\r\n| `download_data` | fixed | 1 | |\r\n| `render_kline` | fixed | 1 | |\r\n| `re_render_chart` | fixed | 1 | |\r\n| `read_data` | fixed | 2 | |\r\n| `search_similar_cases` | fixed | 5 | |\r\n| `confirm_multiple_assets` | deferred | 1～6 × 意图数 | DB 精确匹配 1 RU，LLM 路径 6 RU |\r\n| `confirm_data_multi` | deferred | 1～26 × 意图数 | DB 精确匹配 1 RU，LLM 路径 26 RU |\r\n| `run_multi_formula` | dynamic | **7 × 公式数** | 单次最多 20/30/40 个（free/plus/pro） |\r\n| `scan_dimensions` | dynamic | **12 × 维度数** | 全维度(8) = 96 RU |\r\n| `render_chart` | dynamic | **1 × 线数** | 如 3 条线 = 3 RU |\r\n\r\n> **deferred 模式**：先预扣 1 RU/意图，请求完成后按实际路径补扣差额。\r\n> **错误请求退款**：所有端点发生错误时（4xx/5xx），实际 RU 降为 1 RU。\r\n\r\n---\r\n\r\n## 配额池说明\r\n\r\n| 池 | 重置方式 | 说明 |\r\n|------|------|------|\r\n| **窗口 RU** | 个人滚动（最早请求 +4h） | 不是全部一次恢复，按请求逐批恢复 |\r\n| **日 RU** | 每天 00:00（北京时间） | 次日零点统一重置 |\r\n\r\n---\r\n\r\n## 场景成本参考\r\n\r\n| 场景 | 典型 RU 消耗 |\r\n|------|:---:|\r\n| 单只股票价格/PE/PB | ~3 RU |\r\n| 条件选股（1 条公式）| ~10 RU |\r\n| 条件选股+回测（5 公式）| ~37 RU |\r\n| IC 全维度扫描 | 96 RU |\n\nFile v4.14.16:references/scripts-audit.md\n\n# Bundled Scripts Audit\r\n\r\nThis document enumerates every Python script shipped inside this skill, what it does, and its network / subprocess / filesystem behavior. Reviewers can use it to verify the skill's declared behavior without reading every line of code.\r\n\r\nLast audited against version: **4.14.7**\r\n\r\n---\r\n\r\n## Top-level scripts\r\n\r\n### `scripts/call.py`\r\n- **Purpose**: Thin CLI dispatcher. Takes a tool name + JSON params, forwards to `scripts/executor.py` via a subprocess of the same Python interpreter.\r\n- **Network**: None directly. Network calls happen inside `executor.py`.\r\n- **Subprocess**: `subprocess.run([sys.executable, \"scripts/executor.py\", ...])`. No shell, no external binary.\r\n- **Filesystem writes**: None.\r\n- **Reads secrets**: Only `config.json` / `config.local.json` pass-through; secrets are handled by `executor.py`.\r\n\r\n### `scripts/executor.py`\r\n- **Purpose**: Calls the quant-buddy HTTPS API and returns the response.\r\n- **Network**: Only `https://www.quantbuddy.cn/**` via `urllib.request` (stdlib). Host is taken from `config.json#endpoint` with a hardcoded default; no redirects to third-party hosts are followed without verification.\r\n- **Authentication**: Resolves `api_key` in this order: (1) `QUANT_BUDDY_API_KEY` env var, (2) `config.local.json` `api_key` field, (3) `config.json` `api_key` field. The resolved key is sent **only** in the `Authorization: Bearer <key>` header. It is never logged, printed to stdout/stderr, or written to files.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: Optional response cache under `.cache/` within the skill root; chart / CSV outputs under `output/` when invoked by chart or download tools.\r\n\r\n### `scripts/quant_api.py`\r\n- **Purpose**: Python wrapper around `executor.py` for use as a library (not invoked during normal agent flow).\r\n- **Network**: Same as `executor.py` (delegates to it).\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: None.\r\n\r\n### `scripts/event_study_local.py`\r\n- **Purpose**: Optional event-study helper. Combines quant-buddy data with a Bocha web-search step for news context.\r\n- **Network**:\r\n  - `https://www.quantbuddy.cn/**` (via `executor.py`) — required.\r\n  - `https://api.bochaai.com/v1/web-search` — **opt-in only**. The function returns `{\"ok\": false, \"error\": \"BOCHA_API_KEY 未配置\"}` immediately if the user has not set `BOCHA_API_KEY` (env var / `bocha_api_key` in `config.local.json` / `config.json`). No request is made without the key.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: None.\r\n- **Dependency**: Requires the `requests` package **only when Bocha is enabled**. Without BOCHA_API_KEY the import path is bypassed.\r\n\r\n### `scripts/repro_scan_null.py`, `scripts/update_cases_index.py`\r\n- **Purpose**: Developer utilities for curating the skill's own preset/case files. Not invoked by the agent at runtime; intended for the skill author to regenerate local indices.\r\n- **Network**: None.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: Only under `scripts/` and `presets/` within the skill root.\r\n\r\n---\r\n\r\n## `scripts/eval/`\r\nOffline evaluation harness for the skill author to measure quality regressions. Not invoked at runtime. No network access, no subprocess, writes only to `scripts/eval/` outputs.\r\n\r\n---\r\n\r\n## Summary guarantees\r\n\r\n| Concern | Status |\r\n|---|---|\r\n| Outbound network hosts | `www.quantbuddy.cn` (required), `api.bochaai.com` (opt-in only) |\r\n| api_key ever logged / transmitted to other host | No |\r\n| PII (phone / SMS / email / device ID) collected | No |\r\n| Subprocess / shell to external binary | No (only re-invokes `sys.executable` for dispatch) |\r\n| Writes outside skill root | No |\r\n| Reads OS credentials / env vars beyond the declared ones | No (only reads `BOCHA_API_KEY` when the optional Bocha feature is used) |\r\n\r\nIf any of the above statements is inaccurate, it is a bug and should be reported to the skill author.\n\nFile v4.14.16:references/troubleshooting.md\n\n# 故障排查\r\n\r\n> 汇总所有场景（量化选股、渲染图表、数据下载）的常见错误与解决方式。\r\n\r\n---\r\n\r\n## 公式 / 变量\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `公式变量未找到` | 同一批公式 task_id 不一致 | 确保所有公式用同一个 task_id |\r\n| `函数不存在` / 函数名报错 | 案例原文笔误，或抄写时引入差异 | 用 `searchFunctions` 找正确函数名 |\r\n| `数据名不存在` | 公式中名称与 confirmDataMulti 的 index_title 不一致 | 以 index_title 为准 |\r\n| `公式格式检测失败：MA(dataid(...),N)` | 平台**无 `MA()` 函数** | 简单均线用 `平均(\"数据名\", N)`；指数均线用 `ema(\"数据名\", N)` |\r\n| `函数不存在：取出最后值` | 该函数不存在于平台 | 替代：① `取前(数据, n, 返回数值)` 获取截面 TopN；② `readData(mode=last_day_stats)` 获取最新截面 |\r\n| PE 选股包含亏损股 | 未过滤负 PE | 加 `(\"PE\">0)` 条件 |\r\n| 多因子选股数为 0 | 非季报日截面财务数据为空 | ① 检查结束日期是否临近季报日；② 用 `readData(mode=last_day_stats)`；③ 调整至最近季报日（3/31、6/30、9/30、12/31） |\r\n\r\n---\r\n\r\n## 工具参数\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `参数 xxx 必填` / `400` | 参数名错误 | 读对应 `tools/<tool>.md` 确认正确字段名 |\r\n| `readData` 返回 400 | 参数名用了 `variable_names` | 改为 `ids` 数组 |\r\n| `match_quality=low` | searchSimilarCases 未找到好模板 | 调整 query 关键词，**最多重试 1 次** |\r\n| confirmDataMulti 返回 404 | 查询的是单资产价格，不是平台聚合数据 | 用 `收盘价(资产名)` 函数，无需 confirmDataMulti |\r\n| confirmMultipleAssets 30次超时 | intentions 用了前缀格式如 `CMX-铜` | 用简洁中文品种名如 `铜`、`黄金` |\r\n\r\n---\r\n\r\n## 图表渲染\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| renderChart 图中无曲线 | 数据为二维，renderChart 仅支持一维 | 确保公式输出一维时序 |\r\n| `参数 lines 必须是非空数组` | 误用了 `variable_names` 参数 | 改为 `lines: [{id, name}]`，id 来自 runMultiFormula 的 `_id` |\r\n| K线图报 `必须包含 open_id/high_id/low_id/close_id` | candlestick 参数缺少必填字段 | 传入完整 4 个 ID；或改用 `renderKLine` |\r\n| K线图日期对不齐 / 数据缺失 | OHLC 4 个 data ID 来自不同 task_id | 确保在同一个 runMultiFormula 中计算 |\r\n| renderKLine 报 ticker 不存在 | ticker 格式错误 | 使用 `SH`/`SZ` 前缀格式如 `SH600519` |\r\n| renderKLine indicators 无效 | 指标名拼写错误 | 参照 `tools/render_kline.md` 支持列表，全小写 |\r\n| 图表不知道在哪里 | 未找到输出文件 | `call.py` 已自动保存到 `output/` 并打开 |\r\n\r\n---\r\n\r\n## 认证 / 网络\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| `401 Unauthorized` | api_key 无效或过期 | **立即停止**，提示用户重新认证 |\r\n| `402 Quota` | 配额耗尽 | **立即停止**，提示用户等待恢复或次日重置 |\r\n| 终端命令无输出 | 终端缓冲 stdout | `call.py` 已写 `/tmp/gzq_out.txt`，用 `cat /tmp/gzq_out.txt` 读取 |\r\n\r\n## 业务错误（HTTP 200 + success: false）\r\n\r\n部分错误走 HTTP 200 返回，通过 `success: false` + `error` 对象区分：\r\n\r\n```json\r\n{\"code\": -1, \"success\": false, \"error\": {\"message\": \"参数 ids 必须是非空数组\"}}\r\n```\r\n\r\n| 判断方式 | 说明 |\r\n|----------|------|\r\n| `success === false` 或 `code !== 0` | 均可判定为错误 |\r\n| `error.message` | 错误描述 |\r\n\r\n> 业务错误与 429 配额超限使用相同的 `{ success: false, error: { message } }` 结构。\r\n> 429/503 的 `error` 中额外包含 `code`（语义化字符串）和恢复时间字段。\r\n> 调用方应先检查 HTTP status（429/503），再检查 body 的 `success` / `code`。\r\n\r\n---\r\n\r\n## 配额限流（429 错误码）\r\n\r\n| 错误码 | 含义 | 处理方式 |\r\n|--------|------|----------|\r\n| `WINDOW_QUOTA_EXCEEDED` | 窗口 RU 已耗尽 | **停止调用**，告知用户等待时间（`error.nextResetIn` 秒后最早一批恢复） |\r\n| `DAILY_QUOTA_EXCEEDED` | 今日 RU 已耗尽 | **停止调用**，告知用户次日 00:00 重置（`error.resetIn` 秒） |\r\n| `DAILY_SCAN_EXCEEDED` | IC 扫描今日次数已满 | **停止调用**，告知用户次日 00:00 重置（free=2次/天，plus=10次/天）（`error.resetIn` 秒） |\r\n| `RATE_LIMIT_EXCEEDED` | 每分钟请求过于频繁 | **静默等待** `error.retryAfter` 秒后重试，不暴露给用户 |\r\n| `CONCURRENT_LIMIT` | 有计算任务正在执行 | **静默等待** `error.retryAfter` 秒后重试，不暴露给用户 |\r\n| `SERVICE_OVERLOADED` | 系统熔断（503） | **静默等待** `error.retryAfter` 秒后重试 1 次；若仍失败则告知用户\"系统繁忙，请稍后重试\" |\r\n\r\n---\r\n\r\n## 数据下载\r\n\r\n| 问题现象 | 可能原因 | 处理方式 |\r\n|----------|----------|----------|\r\n| downloadData 返回 403 | 计算结果 `provider=dunhe`，无权限 | 改用 `readData(mode=full)` |\r\n| 下载到全量历史几千行 | 未传 begin_date | 调用前先问用户要哪段时间 |\r\n| 上传数据 NaN 率高 | CSV 列标题缺少交易所后缀 | 改为 `600519.SH` 格式 |\n\nFile v4.14.16:recipes/download-data.md\n\n# Recipe：下载数据到本地 CSV\r\n\r\n## 触发词\r\n\r\n> \"把数据下载成 CSV\"、\"导出到本地\"、\"下载历史数据\"\r\n\r\n---\r\n\r\n## 调用方式\r\n\r\n```bash\r\npython scripts/call.py downloadData '{\"data_id\":\"<data_id>\",\"begin_date\":<YYYYMMDD>,\"end_date\":<YYYYMMDD>}'\r\n```\r\n\r\n`call.py` 调用 `downloadData` 时会**自动**将 CSV 保存到 `output/<data_name>.csv`，终端输出摘要（total_rows、begin_date、saved_to），不刷屏。\r\n\r\n---\r\n\r\n## 使用限制\r\n\r\n| 条件 | 说明 |\r\n|------|------|\r\n| **可下载** | 持久化一维时序：上传数据 (`provider=mydata`) 或平台数据 (`provider=guanzhao`) |\r\n| **不可下载** | `runMultiFormula` 的计算结果 (`provider=dunhe`)，普通用户无 `access_dunhe` 权限 → 返回 403 |\r\n| **替代方案** | 计算结果用 `readData(mode=full)` 读取，再自行保存为 CSV |\r\n\r\n---\r\n\r\n## 必须确认时间范围\r\n\r\n数据通常从 2015 年起，直接下载可能几千行。**调用前先问用户**：\r\n\r\n> \"您需要下载哪段时间的数据？（默认：最近一年）\"\r\n\r\n- 用户给出范围 → 传 `begin_date` / `end_date`\r\n- 用户说\"所有历史\" → 不传日期参数\n\nFile v4.14.16:recipes/event-study-formulas.md\n\n# 事件研究公式模板\r\n\r\n保留四条真正稳定的模板。\r\n\r\n## 模板 A: 单组事件固定持有期\r\n\r\n适用于绝大多数事件研究问题。\r\n\r\n```text\r\n{prefix}_事件日=选取日期({date1},{date2},...)\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_后{N1}日路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_事件日\",{N1})\r\n{prefix}_后{N2}日路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_事件日\",{N2})\r\n{prefix}_后{N1}日收益=分段最终值(\"{prefix}_后{N1}日路径\")\r\n{prefix}_后{N2}日收益=分段最终值(\"{prefix}_后{N2}日路径\")\r\n```\r\n\r\n### 窗口映射\r\n\r\n| 说法 | N |\r\n|------|---|\r\n| 1周 | 5 |\r\n| 2周 | 10 |\r\n| 1月 | 21 |\r\n| 3月 | 63 |\r\n| 半年 | 126 |\r\n| 1年 | 252 |\r\n\r\n### 使用建议\r\n\r\n1. 同时给逐次结果和均值\r\n2. 窗口不宜超过相邻事件最小间距\r\n3. 样本很少时不要强行做胜率和分位数\r\n\r\n## 模板 B: 两组事件对比（compare）\r\n\r\n适用于超预期 vs 不及预期、利好 vs 利空这类问题。\r\n\r\n```text\r\n{prefix}_A组=选取日期({group_a_dates...})\r\n{prefix}_B组=选取日期({group_b_dates...})\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_A后{N}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_A组\",{N})\r\n{prefix}_A后{N}收益=分段最终值(\"{prefix}_A后{N}路径\")\r\n{prefix}_B后{N}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_B组\",{N})\r\n{prefix}_B后{N}收益=分段最终值(\"{prefix}_B后{N}路径\")\r\n```\r\n\r\n### 使用建议\r\n\r\n1. 两组共享同一条价格和日收益序列\r\n2. 输出时先列每次事件，再列各组均值\r\n3. 两组样本数不一致时，要在解释里显式写出来\r\n\r\n## 模板 C: 事件后偏移区间回报（排除事件日）\r\n\r\n适用于\"事件后第 N 天到第 M 天\"的区间涨幅，排除事件当天。\r\n与模板 A 的区别：模板 A 从 T+1 起算固定窗口；本模板通过收盘价比值法精确计算任意偏移区间。\r\n\r\n```text\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_收盘_T加{N}=取某天(\"{prefix}_收盘\",交易日位移({event_date},{N}))\r\n{prefix}_收盘_T加{M}=取某天(\"{prefix}_收盘\",交易日位移({event_date},{M}))\r\n{prefix}_T{N+1}到T{M}涨幅=\"{prefix}_收盘_T加{M}\"/\"{prefix}_收盘_T加{N}\"-1\r\n```\r\n\r\n### 参数映射\r\n\r\n| 占位符 | 含义 | 示例值 |\r\n|--------|------|--------|\r\n| `{prefix}` | 变量前缀 | `fomc` |\r\n| `{event_date}` | 事件日期（YYYYMMDD 整数） | `20241218` |\r\n| `{asset_name}` | 标的资产名 | `沪深300` |\r\n| `{N}` | 起始边界交易日数（用户起始天数 - 1） | `1` |\r\n| `{M}` | 终止边界交易日数（用户结束天数） | `20` |\r\n\r\n### 数学原理\r\n\r\n`取某天` 将指定日期的收盘价填充为常数序列，两个常数序列相除天然对齐：\r\n\r\n$$\\text{T+N+1 到 T+M 涨幅} = \\frac{P_{T+M}}{P_{T+N}} - 1$$\r\n\r\n其中 $P_{T+N}$ 和 $P_{T+M}$ 均由 `交易日位移` 按 A 股交易日历精确计数（非自然日）。\r\n\r\n例如用户说\"第 2 天到第 20 天\" → N=1, M=20 → 计算 $P_{T+20} / P_{T+1} - 1$（持有 T+1 收盘到 T+20 收盘）。\r\n\r\n### N 值推导\r\n\r\n| 用户表述 | N | M | 实际区间 |\r\n|----------|---|---|----------|\r\n| \"第 2 天到第 20 天\" | 1 | 20 | T+1 收盘 → T+20 收盘 |\r\n| \"第 3 天到第 60 天\" | 2 | 60 | T+2 收盘 → T+60 收盘 |\r\n| \"排除前 2 天，看第 3 天起\" | 2 | M | T+2 收盘 → T+M 收盘 |\r\n\r\n核心规则：**N = 用户起始天数 - 1，M = 用户结束天数**\r\n\r\n### 使用建议\r\n\r\n1. 当用户说\"排除事件当天\"或\"T+2 到 T+20\"时使用本模板\r\n2. 多事件场景需为每个事件单独建立一套前缀变量（`取某天` 只能绑定一个日期）\r\n3. 同一会话中不同事件使用不同 `{prefix}`，避免变量覆盖\r\n4. 结果为精确价格比值，无累加近似误差\r\n\r\n## 模板 D: 搜索新闻打标分类（财报超预期类 compare 专用）\r\n\r\n适用于：需要先搜索新闻判断财报是否超预期，再分组计算事件后收益的场景。\r\n\r\n与模板 B 的区别：模板 B 默认两组日期已知；模板 D 需要先把正式年报/半年报披露日逐期打标，再将结果代入 compare 公式链。\r\n\r\n### 执行步骤（配合 `event-study.md` 的财报业绩超预期分类细则使用）\r\n\r\nStep D1：获取正式财报披露日\r\n\r\n```text\r\nREV_2D=\"A股营业总收入〔报告期利润表〕\"\r\nPUB_DATE=报告期转发布日(\"REV_2D\")\r\n```\r\n\r\n从 `PUB_DATE` 中提取目标股票的正式年报（Q4）和半年报（Q2）披露日。若需要补证，再用交易所公告页或东财年报季报页交叉验证。\r\n\r\nStep D2：逐期搜索并打标\r\n\r\n对每个披露日执行搜索，关键词格式：\r\n\r\n```text\r\n{股票简称} {报告类型} {yyyymmdd} 超预期 OR 不及预期\r\n```\r\n\r\n打标规则、证据门槛和 `label_confidence` 约束以 `event-study.md` 中的财报业绩超预期分类细则为准。\r\n\r\nStep D3：将打标结果代入 compare 公式链\r\n\r\n```text\r\n{prefix}_超预期组=选取日期({beat_dates...})\r\n{prefix}_不及预期组=选取日期({miss_dates...})\r\n{prefix}_收盘=收盘价({asset_name})\r\n{prefix}_日收益=涨跌幅(\"{prefix}_收盘\")\r\n{prefix}_超预期后{N1}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_超预期组\",{N1})\r\n{prefix}_超预期后{N1}收益=分段最终值(\"{prefix}_超预期后{N1}路径\")\r\n{prefix}_超预期后{N2}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_超预期组\",{N2})\r\n{prefix}_超预期后{N2}收益=分段最终值(\"{prefix}_超预期后{N2}路径\")\r\n{prefix}_不及预期后{N1}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_不及预期组\",{N1})\r\n{prefix}_不及预期后{N1}收益=分段最终值(\"{prefix}_不及预期后{N1}路径\")\r\n{prefix}_不及预期后{N2}路径=某天后累加(\"{prefix}_日收益\",\"{prefix}_不及预期组\",{N2})\r\n{prefix}_不及预期后{N2}收益=分段最终值(\"{prefix}_不及预期后{N2}路径\")\r\n```\r\n\r\n### 参数说明\r\n\r\n| 占位符 | 说明 | 示例 |\r\n|--------|------|------|\r\n| `{prefix}` | 变量前缀 | `MT` |\r\n| `{beat_dates...}` | 超预期组日期列表 | `20210330,20220331,20240403` |\r\n| `{miss_dates...}` | 不及预期组日期列表 | `20220803` |\r\n| `{asset_name}` | 资产名称 | `贵州茅台` |\r\n| `{N1}` | 短窗口交易日数 | `5` |\r\n| `{N2}` | 长窗口交易日数 | `20` |\r\n\r\n### 使用建议\r\n\r\n1. 日期分组必须来自 Step D2 的搜索打标结果，不得凭记忆填入\r\n2. 若用户要比较\"符合预期\"而不是\"不及预期\"，只替换第二组标签和日期列表，不改整条公式链\r\n3. 两组共享同一条价格序列和日收益序列，减少公式冗余\r\n4. 样本数 < 5 时，均值行必须标注\"有限样本，仅供参考\"\r\n5. 若某组样本为 0（全部证据不足），保留 compare 框架，并在输出中明确说明该组无满足证据标准的样本，不得静默降级为 single 模式\r\n\r\n## 可选扩展: 超额收益\r\n\r\n如果用户明确要求相对基准表现，可额外生成：\r\n\r\n```text\r\n{prefix}_基准收盘=收盘价(沪深300)\r\n{prefix}_基准日收益=涨跌幅(\"{prefix}_基准收盘\")\r\n{prefix}_超额日收益=\"{prefix}_日收益\"-\"{prefix}_基准日收益\"\r\n```\r\n\r\n然后用 `{prefix}_超额日收益` 替代 `{prefix}_日收益` 进入同样的窗口链路。\n\nFile v4.14.16:recipes/ic-factor-templates.md\n\n# IC 因子公式模板\r\n\r\n> 来源：`workflows/quant-standard.md` Step 2 手动因子构建\r\n> 通常由 `scanDimensions` 脚本自动完成，仅在需要**自定义指标**或脚本不可用时手动使用\r\n\r\n---\r\n\r\n## 基础数据（所有因子前置）\r\n\r\n```python\r\nB_Close = 收盘价(X)         # X = 目标资产名（来自 confirmMultipleAssets 的 name）\r\nB_Ind   = 收盘价(Ind)       # Ind = 行业指数名\r\nB_Mkt   = 收盘价(Mkt)       # Mkt = 大盘指数（如 万得全A 或 沪深300）\r\n```\r\n\r\n---\r\n\r\n## D1 估值\r\n\r\n```python\r\nB_PE      = \"A股市盈率（PE, TTM）〔估值数据〕\" * 取出(X的代码)\r\nB_PB      = \"A股市净率（PB）〔估值数据〕\" * 取出(X的代码)\r\nB_PE_Rank = 数值水位(\"B_PE\", 250)\r\nB_PB_Rank = 数值水位(\"B_PB\", 250)\r\n```\r\n\r\n> PE 必须使用 TTM 口径（`A股市盈率（PE, TTM）〔估值数据〕`）\r\n\r\n---\r\n\r\n## D3 资金\r\n\r\n```python\r\nB_AllAmt    = 按天求和(\"全市场每日成交额\")\r\nB_Amt       = \"全市场每日成交额\" * 取出(X的代码)\r\nB_AmtRatio  = \"B_Amt\" / \"B_AllAmt\"\r\nB_AmtRank   = 数值水位(\"B_AmtRatio\", 250)\r\nB_Short     = \"A股融券空头持仓比例\" * 取出(X的代码)\r\nB_ShortRank = 数值水位(\"B_Short\", 250)\r\nB_Fund      = \"A股持股市值占基金股票投资市值比\" * 取出(X的代码)\r\nB_FundRank  = 数值水位(\"B_Fund\", 250)\r\n```\r\n\r\n---\r\n\r\n## D4 波动率 / 风险\r\n\r\n```python\r\nB_PrevClose = 前几天(\"B_Close\", 1)\r\nB_High      = 最高价(X)\r\nB_Low       = 最低价(X)\r\nB_TR  = 比较取大(\"B_High\"-\"B_Low\", 比较取大(绝对值(\"B_High\"-\"B_PrevClose\"), 绝对值(\"B_Low\"-\"B_PrevClose\")))\r\nB_ATR = 平均(\"B_TR\", 14)\r\n```\r\n\r\n---\r\n\r\n## D5 宏观 / 大盘环境\r\n\r\n```python\r\nB_Mkt_MA60  = 平均(\"B_Mkt\", 60)\r\nB_Mkt_Above = (\"B_Mkt\" > \"B_Mkt_MA60\")\r\n```\r\n\r\n---\r\n\r\n## D7 技术形态\r\n\r\n```python\r\n# 均线\r\nB_MA10 = 平均(\"B_Close\", 10)\r\nB_MA20 = 平均(\"B_Close\", 20)\r\nB_MA60 = 平均(\"B_Close\", 60)\r\n\r\n# MACD\r\nB_EMA12     = EMA(\"B_Close\", 12)\r\nB_EMA26     = EMA(\"B_Close\", 26)\r\nB_MACD      = \"B_EMA12\" - \"B_EMA26\"\r\nB_Signal    = EMA(\"B_MACD\", 9)\r\nB_MACD_Hist = \"B_MACD\" - \"B_Signal\"\r\n\r\n# 布林带\r\nB_SD20  = 标准差(\"B_Close\", 20)\r\nB_BollZ = (\"B_Close\" - \"B_MA20\") / \"B_SD20\"\r\n```\r\n\r\n---\r\n\r\n## D9 财务\r\n\r\n```python\r\nB_Profit_Raw = 报告期转发布日(\"A股净利润同比增长率：单季〔财务指标〕\")\r\nB_Profit_F   = 缺失填充(\"B_Profit_Raw\" * 取出(X的代码))\r\n```\r\n\r\n---\r\n\r\n## 收益率 / 位置（跨维度通用）\r\n\r\n```python\r\nB_Ret20       = 涨跌幅(\"B_Close\", 20)\r\nB_IndRet20    = 涨跌幅(\"B_Ind\", 20)\r\nB_Alpha20     = \"B_Ret20\" - \"B_IndRet20\"\r\nB_Ret20_Next  = 前几天(涨跌幅(\"B_Close\", 20), -20)   # 未来20日收益（IC计算目标）\r\n\r\nB_PriceRank   = 数值水位(\"B_Close\", 250)\r\nB_RS          = \"B_Close\" / \"B_Ind\"\r\nB_RS_Rank     = 数值水位(\"B_RS\", 250)\r\n```\r\n\r\n---\r\n\r\n## IC 计算公式\r\n\r\n```python\r\n# 内联写法（推荐，无跨变量依赖）\r\nPE_IC = 相关系数(前几天(数值水位(\"B_PE\", 250), 20), 涨跌幅(收盘价(X), 20), 250)\r\n\r\n# 引用写法（同一 task_id 内）\r\nB_PE_Rank = 数值水位(\"B_PE\", 250)\r\nPE_IC     = 相关系数(前几天(\"B_PE_Rank\", 20), 涨跌幅(\"B_Close\", 20), 250)\r\n```\r\n\r\n> 不同 task_id 之间不能引用变量——newSession 后旧 session 的变量全部丢失\n\nFile v4.14.16:recipes/industry-aggregation.md\n\n# 示例五：成交量加权行业聚合——放量日申万行业涨跌幅排名\r\n\r\n## 快速模板：行业近N日平均涨跌幅前K\r\n\r\n适用：\r\n- 申万一级行业最近一个月平均涨跌幅前5\r\n- 某板块体系近N日涨跌幅排名\r\n\r\n标准公式模板：\r\n```text\r\n个股近N日涨跌幅=涨跌幅(\"全市场每日收盘价\",N)\r\n行业近N日涨跌幅=成分平均汇总(\"个股近N日涨跌幅\",\"申万资产所属指数\")\r\n行业TopK=取前(\"行业近N日涨跌幅\",K,返回数值)\r\n```\r\n\r\n注意：\r\n- 所有数据名/变量名在函数参数中必须使用双引号\r\n- \"最近一个月\"默认按近20个交易日处理，回答中需明示口径\r\n- 若 runMultiFormula 已返回最后一天 top 数据，且足以回答用户问题，可不再 readData\r\n- 仅当内置数据名无法命中时，才使用 confirmDataMulti\r\n\r\n**⚠️ 输出口径声明硬规则**：上述模板的计算结果是\"**行业近N日平均涨跌幅**\"（行业内各成分股N日区间回报的算术均值）。在最终答案中**只能**称为\"行业近N日平均涨跌幅\"或\"行业近N日涨跌幅均值\"，**绝对禁止**将其改写为\"近N日累计涨跌幅\"——\"累计涨跌幅\"与\"平均涨跌幅\"统计含义不同，用户问的是\"平均\"就必须说\"平均\"。\r\n\r\n---\r\n\r\n## 用户意图\r\n\r\n> \"在A股放量日（当日成交量超过5日均值2倍时），哪些申万行业板块的平均涨跌幅最好？帮我排个名\"\r\n\r\n---\r\n\r\n## 核心挑战：跨维度聚合\r\n\r\n本示例的关键难点是**维度不匹配**：\r\n\r\n- 全市场回报率（如万得全A 7700+ 只）：资产×日期 二维矩阵\r\n- 申万行业指数（31个）：与全市场股票维度不同\r\n\r\n**不能直接用全市场列做行业均值**——同一个二维矩阵按行业分组后，维度（资产轴）不一致，必须用 `成分平均汇总()` 做桥接：\r\n\r\n```\r\n成分平均汇总(全市场数据, 申万资产所属指数)\r\n→ 输出：31个申万行业 × 日期 的二维矩阵（行业轴替换了资产轴）\r\n```\r\n\r\n类比：`成分平均汇总` 是\"按组取平均\"，第二个参数指定分组依据（哪家公司属于哪个行业）。\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 0 — 初始化会话\r\n\r\n```bash\r\npython scripts/call.py newSession\r\n```\r\n\r\n```json\r\n{\"code\": 0, \"task_id\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"}\r\n```\r\n\r\n---\r\n\r\n### Step 1 — 查案例（cases_index 优先）\r\n\r\n**1a. 读取 `presets/cases_index.yaml`**，搜索 tags 含 `行业`、`聚合`、`成分` 的卡片（约 1-3 张）。\r\n\r\n**1b.** 找到后调 `getCardFormulas` 拉取公式，理解 `成分平均汇总` 的参数用法：\r\n\r\n```bash\r\npython scripts/call.py getCardFormulas '{\"card_ids\": [\"<相关卡片id>\"]}'\r\n```\r\n\r\n**1c.** 若目录中未找到合适卡片，fallback 到：\r\n\r\n```bash\r\npython scripts/call.py searchSimilarCases '{\"query\": \"申万行业聚合成分平均汇总涨跌幅\", \"top_k\": 3}'\r\n```\r\n\r\n> **重点关注**返回案例中 `成分平均汇总()` 的参数格式、`申万资产所属指数` 的数据名称写法；案例解决的是案例自身的问题，当前问题的公式需根据用户需求重新组织。\r\n\r\n---\r\n\r\n### Step 2 — 确认全市场数据\r\n\r\n```bash\r\npython scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日成交量, 全市场每日回报率, 申万资产所属指数\"}'\r\n```\r\n\r\n**预期返回**（记录三个 index_title）：\r\n\r\n| 描述词 | index_title（示例） | dimension | 说明 |\r\n|-------|-------------------|-----------|------|\r\n| 全市场每日成交量 | `全市场每日成交量` | two | 资产×日期 |\r\n| 全市场每日回报率 | `全市场每日回报率` | two | 资产×日期 |\r\n| 申万资产所属指数 | `申万资产所属指数` | two | 资产×日期，值为申万指数代码 |\r\n\r\n> **Windows PowerShell 传参**：\r\n> ```bash\r\n> python scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日成交量, 全市场每日回报率, 申万资产所属指数\"}'\r\n> ```\r\n\r\n---\r\n\r\n### Step 3 — 搜索聚合函数（若 presets/functions.yaml 中已有则跳过）\r\n\r\n```bash\r\npython scripts/call.py searchFunctions '{\"query\": \"成分平均汇总 行业聚合\", \"top_k\": 3}'\r\npython scripts/call.py searchFunctions '{\"query\": \"区间统计量 掩码过滤\", \"top_k\": 3}'\r\npython scripts/call.py searchFunctions '{\"query\": \"按天求和 全市场聚合\", \"top_k\": 3}'\r\n```\r\n\r\n确认以下函数的参数格式：\r\n- `按天求和(数据)` → 将二维数据按日期求和，得到一维时序\r\n- `成分平均汇总(数据, 指数数据)` → 按指数成分分组取平均，输出指数×日期 矩阵\r\n- `区间统计量(数据, 掩码, 统计函数)` → 用布尔掩码过滤时间段，对各段计算统计量\r\n\r\n---\r\n\r\n### Step 4 — 执行公式（5条，共享同一 task_id）\r\n\r\n```bash\r\npython scripts/call.py runMultiFormula '{\r\n  \"task_id\": \"<Step 0 的 task_id>\",\r\n  \"begin_date\": 20150101,\r\n  \"formulas\": [\r\n    \"全市场总成交量=按天求和(\\\"全市场每日成交量\\\")\",\r\n    \"全市场成交量5日均=平均(\\\"全市场总成交量\\\",5)\",\r\n    \"放量日标记=(\\\"全市场总成交量\\\">\\\"全市场成交量5日均\\\"*2)\",\r\n    \"申万行业每日回报率=成分平均汇总(\\\"全市场每日成交量\\\"*\\\"全市场每日回报率\\\",\\\"申万资产所属指数\\\")\",\r\n    \"放量日行业平均涨跌幅=区间统计量(\\\"申万行业每日回报率\\\",\\\"放量日标记\\\",平均)\"\r\n  ],\r\n  \"intents\": [\"全市场每日总量（一维）\", \"5日均量（一维）\", \"放量日布尔标记（一维）\", \"成交量加权行业日回报率（31行业×日期）\", \"放量日区间内各行业平均涨跌幅（31行业×区间数）\"]\r\n}'\r\n```\r\n\r\n**关键设计决策**：\r\n\r\n| 设计点 | 说明 |\r\n|-------|------|\r\n| 公式4使用 `成交量×回报率` 而非直接 `回报率` | 这是**成交量加权平均**的计算模式：分子=成交量×回报率之和，分母=成交量之和，`成分平均汇总` 内部会自动完成加权除法 |\r\n| 公式1-3先把全市场压缩到一维 | `按天求和` 把 7700+ 只的成交量矩阵折叠为每天一个数——这是后续做\"全市场放量日\"判断的前提 |\r\n| `放量日标记` 是一维布尔序列 | 可直接作为 `区间统计量` 的掩码，标记哪些日期属于\"放量日\" |\r\n| `申万行业每日回报率` 维度是 31 × 4000+ 天 | 行业轴（31个申万行业）替代了原来的资产轴（7700+ 只股票） |\r\n\r\n**预期返回（各公式 data_id）**：\r\n```json\r\n{\r\n  \"results\": [\r\n    {\"variable_name\": \"全市场总成交量\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"全市场成交量5日均\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"放量日标记\", \"data_id\": \"xxx\", \"dimension\": \"one\"},\r\n    {\"variable_name\": \"申万行业每日回报率\", \"data_id\": \"xxx\", \"dimension\": \"two\", \"assets\": 31},\r\n    {\"variable_name\": \"放量日行业平均涨跌幅\", \"data_id\": \"xxx\", \"dimension\": \"two\", \"assets\": 31}\r\n  ]\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 5 — 验证结果（必做）\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<放量日行业平均涨跌幅的data_id>\"], \"mode\": \"smart_sample\"}'\r\n```\r\n\r\n**检查项**：\r\n- `assets` = 31（申万31个行业全部覆盖）\r\n- `dates`（列数）= 识别到的放量日区间数（历史通常 80-150 个）\r\n- NaN 率 < 10%（若过高，检查 `申万资产所属指数` 的 index_title 是否正确）\r\n- 取样值有正有负，数量级在 0.001 ~ 0.05 之间（日回报率级别）\r\n\r\n---\r\n\r\n### Step 6 — 读取完整截面排名\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<放量日行业平均涨跌幅的data_id>\"], \"mode\": \"last_day_stats\"}'\r\n```\r\n\r\n**预期返回**：31 个行业在所有放量日的平均涨跌幅，按值降序排列即可得到排名。\r\n\r\n---\r\n\r\n### Step 7（可选）— 柱状图可视化\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"放量日申万行业平均涨跌幅排名（2015至今）\",\r\n  \"lines\": [\r\n    {\"id\": \"<放量日行业平均涨跌幅的data_id>\", \"name\": \"放量日平均日涨幅\"}\r\n  ],\r\n  \"chart_type\": \"bar\",\r\n  \"task_id\": \"<task_id>\"\r\n}'\r\n```\r\n\r\n> ```bash\r\n> python scripts/call.py renderChart '{\"title\":\"放量日申万行业平均涨跌幅排名\", \"lines\":[{\"id\":\"<data_id>\",\"name\":\"放量日平均日涨幅\"}], \"chart_type\":\"bar\", \"task_id\":\"<task_id>\"}'\r\n> ```\r\n\r\n---\r\n\r\n## 常见错误与处理\r\n\r\n| 错误 | 原因 | 处理 |\r\n|------|------|------|\r\n| `成分平均汇总` 返回 assets=0 | `申wx资产所属指数` 的 index_title 写错 | 重新 confirmDataMulti，严格用返回的 index_title |\r\n| `放量日行业平均涨跌幅` assets=7700+（未聚合） | 公式4写错，误用的是全市场回报率而非行业聚合结果 | 确认公式4的变量名用的是 `申万行业每日回报率` |\r\n| 区间统计量 dates=0 | 放量日标记全为 False（条件过严或数据期太短） | 检查 begin_date / 阈值倍数；可先用 `readData(mode=smart_sample)` 看 `放量日标记` 的 True 比例 |\r\n| renderChart 报\"仅支持一维数据\" | `放量日行业平均涨跌幅` 是二维（31×区间数） | 先用 readData 读出截面均值，整理成一维序列后再图表；或改为 last_day_stats 下载后自行排序呈现文本 |\r\n| `数据名不存在：申万资产所属指数` | index_title 与实际返回不符 | 以 confirmDataMulti 返回的 index_title 为准，不要凭记忆猜测 |\r\n\r\n---\r\n\r\n## 延伸用法\r\n\r\n同样的模式可以应用于：\r\n\r\n- **涨停日** / **大跌日** 行业表现：把放量日的布尔公式替换为涨跌幅阈值条件\r\n- **宏观事件标记**：上传一列 0/1 事件标记 CSV，作为 `区间统计量` 的掩码\r\n- **基于成分平均汇总的因子聚合**：把任意全市场因子（估值、动量、质量）映射到行业维度，做行业风格分析\r\n\r\n---\r\n\r\n## 行业聚合排名题执行硬规则\r\n\r\n1. **直接执行公式**：行业聚合题的核心公式（如 `成分平均汇总(涨跌幅(...), \"申万资产所属指数\")`）应直接通过 `runMultiFormula` 执行，不需要先用 `confirmDataMulti` 查\"行业涨跌幅\"等聚合后数据是否存在——聚合结果是公式计算产出的，不是预置数据集\r\n2. **行业名称原样复用**：最终答案中的行业名称必须与工具返回的完全一致（如工具返回\"公用事业\"，不得改写为\"公共事业\"）\r\n3. **TopN 安全读取**：行业聚合结果通常为 31 行（申万一级），可安全使用 `readData(mode=\"last_column_full\")`；但若聚合维度更细（二级行业/概念板块），必须先用 `readData(mode=\"precheck\")` 确认行数\r\n\r\n---\r\n\r\n## 语义恒等：申万一级行业最近一个月涨跌幅排名 TopN\r\n\r\n### 用户意图\r\n> \"请统计申万一级行业中，最近一个月涨跌幅排名前5的行业，并列出各行业月涨幅。\"\r\n\r\n### 正确思路\r\n1. \"最近一个月\"若未特别说明，默认按近 20 个交易日处理\r\n2. \"月涨幅 / 最近一个月涨跌幅\"应理解为**窗口累计涨跌幅**，不是 20 日日均回报\r\n3. 先计算个股近 20 日涨跌幅，再按申万行业做成分平均汇总\r\n\r\n### 正确公式\r\n```\r\n申万行业近20日涨跌幅 = 成分平均汇总(涨跌幅(\"全市场每日收盘价\", 20), \"申万资产所属指数\")\r\n```\r\n\r\n### 易错写法（不要用）\r\n```\r\n# ❌ 这两步算的是\"20日日均回报\"，不是\"20日涨跌幅\"\r\n申万行业每日回报率 = 成分平均汇总(\"全市场每日回报率\", \"申万资产所属指数\")\r\n申万行业月涨跌幅 = 平均(\"申万行业每日回报率\", 20)\r\n```\r\n> 上述结果是\"20日日均回报的算术平均\"（约 0.05%），不是\"20日区间涨跌幅\"（约 1%~5%）。用它回答\"月涨幅\"是语义错误。\n\nFile v4.14.16:recipes/ma-crossover-backtest.md\n\n# 示例一：均线策略选股 + 回测\r\n\r\n## 用户意图\r\n\r\n> \"帮我做一个5日均线上穿20日均线的选股策略，看看历史回测表现怎么样\"\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 0 — 初始化会话\r\n\r\n```bash\r\npython scripts/call.py newSession\r\n```\r\n\r\n---\r\n\r\n### Step 1 — 查案例（cases_index 优先）\r\n\r\n**1a. 读取 `presets/cases_index.yaml`**，搜索 tags 含 `均线`、`MA`、`金叉`、`回测` 的卡片。\r\n\r\n**1b.** 找到后调 `getCardFormulas` 批量拉取：\r\n\r\n```bash\r\npython scripts/call.py getCardFormulas '{\"card_ids\": [\"<相关卡片id>\"]}'  \r\n```\r\n\r\n**1c.** 目录中未找到才 fallback：\r\n\r\n```bash\r\npython scripts/call.py searchSimilarCases '{\"query\": \"均线金叉买入区间持仓回测\", \"top_k\": 3}'\r\n```\r\n\r\n**LLM 操作**：理解案例中均线/金叉公式结构，提炼思路后针对用户的 5/20 均线需求重新组织公式，不照抄案例。\r\n\r\n---\r\n\r\n### Step 2 — 确认数据名称\r\n\r\n```bash\r\npython scripts/call.py confirmDataMulti '{\"data_desc\": \"全市场每日收盘价, 非ST股\"}'\r\n```\r\n\r\n**预期返回**：\r\n- `全市场每日收盘价` → `index_title: \"全市场每日收盘价\"`（dimension=two）\r\n- `非ST股` → `index_title: \"非ST股\"`（dimension=two, is_bool=true）\r\n\r\n**LLM 操作**：用返回的 `index_title` 写进公式，不要用原始查询词。\r\n\r\n---\r\n\r\n### Step 3 — 执行公式（生成信号 + 回测）\r\n\r\n```bash\r\npython scripts/call.py runMultiFormula '{\r\n  \"task_id\": \"<Step 0 的 task_id>\",\r\n  \"begin_date\": 20150101,\r\n  \"formulas\": [\r\n    \"MA5=平均(\\\"全市场每日收盘价\\\", 5)\",\r\n    \"MA20=平均(\\\"全市场每日收盘价\\\", 20)\",\r\n    \"金叉信号=(\\\"MA5\\\">\\\"MA20\\\")*(昨天(\\\"MA5\\\")<=昨天(\\\"MA20\\\"))*板块(万得全A)*缺失填零(\\\"非ST股\\\")\",\r\n    \"死叉信号=(\\\"MA5\\\"<\\\"MA20\\\")*(昨天(\\\"MA5\\\")>=昨天(\\\"MA20\\\"))*板块(万得全A)*缺失填零(\\\"非ST股\\\")\",\r\n    \"持仓区间=进出场区间(\\\"金叉信号\\\",\\\"死叉信号\\\")\",\r\n    \"NAV=回测(\\\"持仓区间\\\",当天收盘买入,返回复利净值,信号按列归一)\"\r\n  ],\r\n  \"intents\": [\"5日均线\", \"20日均线\", \"金叉信号（排除ST）\", \"等权回测净值\"]\r\n}'\r\n```\r\n\r\n**关键点**：\r\n- 4 个公式共享同一个 `task_id`，后面的公式才能引用前面的变量\r\n- 返回每条公式的 `data_id`，记录 `NAV` 对应的 `data_id`\r\n\r\n---\r\n\r\n### Step 4 — 验证回测结果\r\n\r\n```bash\r\npython scripts/call.py readData '{\"ids\": [\"<NAV的data_id>\"], \"mode\": \"precheck\"}'\r\n```\r\n\r\n**预期返回**：\r\n```json\r\n{\r\n  \"type\": \"nav_1d\",\r\n  \"first_value\": 1.0,\r\n  \"last_value\": 3.xx,\r\n  \"total_return\": 2.xx,\r\n  \"curve_samples\": [[20150101, 1.0], ..., [20260227, 3.xx]]\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 5（可选）— 渲染净值曲线图\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"均线金叉策略净值（2015至今）\",\r\n  \"lines\": [{\"id\": \"<NAV的data_id>\", \"name\": \"MA5/20金叉策略\"}],\r\n  \"width\": 1400,\r\n  \"height\": 600\r\n}'\r\n```\r\n\r\n**LLM 操作**：返回 `data.base64`，解码后保存为 PNG 文件，或直接展示给用户。\r\n\r\n---\r\n\r\n## 常见错误与处理\r\n\r\n| 错误 | 原因 | 处理 |\r\n|------|------|------|\r\n| `公式变量未找到` | task_id 不一致，Signal 找不到 MA5 | 确保 4 个公式用同一个 task_id |\r\n| `数据名不存在` | 公式里写的名称和 confirmDataMulti 返回的 index_title 不一致 | 以 index_title 为准 |\r\n| `matchQuality=low` | searchSimilarCases 没搜到好模板 | 换 query 关键词重试一次 |\n\nFile v4.14.16:recipes/render-chart.md\n\n# 示例四：生成多策略净值对比图\r\n\r\n## 用户意图\r\n\r\n> \"我已经跑了两个策略的回测，帮我把净值曲线画成一张图，并和沪深300比较\"\r\n\r\n---\r\n\r\n## 前置条件\r\n\r\n假设已通过 `runMultiFormula` 得到以下 `data_id`：\r\n- 策略A净值：`nav_aaa111`\r\n- 策略B净值：`nav_bbb222`\r\n- 沪深300净值：`nav_ccc333`\r\n\r\n如果还没跑，先参考示例一（均线策略）或示例二（低PE策略）的 Step 3~4。\r\n\r\n---\r\n\r\n## 工具调用序列\r\n\r\n### Step 1 — 验证三条净值曲线的基本情况\r\n\r\n```bash\r\npython scripts/call.py readData '{\r\n  \"ids\": [\"nav_aaa111\", \"nav_bbb222\", \"nav_ccc333\"],\r\n  \"mode\": \"precheck\",\r\n  \"sample_points\": 50\r\n}'\r\n```\r\n\r\n**LLM 操作**：\r\n- 确认三条曲线的起止日期一致（都从 `begin_date` 开始）\r\n- 检查 `last_value` 对比，判断哪个策略更优\r\n- 若曲线出现异常（如 last_value=0 或 NaN 率过高），先排查公式错误\r\n\r\n---\r\n\r\n### Step 2 — 渲染对比图\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"策略A vs 策略B vs 沪深300 净值对比\",\r\n  \"lines\": [\r\n    {\"id\": \"nav_aaa111\", \"name\": \"策略A：均线金叉\", \"axis\": \"left\"},\r\n    {\"id\": \"nav_bbb222\", \"name\": \"策略B：低PE 20%\", \"axis\": \"left\"},\r\n    {\"id\": \"nav_ccc333\", \"name\": \"沪深300基准\", \"axis\": \"left\"}\r\n  ],\r\n  \"width\": 1400,\r\n  \"height\": 600,\r\n  \"start_date\": 20150101\r\n}'\r\n```\r\n\r\n**预期返回**：\r\n```json\r\n{\r\n  \"success\": true,\r\n  \"data\": {\r\n    \"base64\": \"iVBORw0KGgoAAAANSUhEUgAA...\",\r\n    \"lines_count\": 3,\r\n    \"width\": 1400,\r\n    \"height\": 600,\r\n    \"errors\": []\r\n  }\r\n}\r\n```\r\n\r\n---\r\n\r\n### Step 3 — 保存图片（Python 示例）\r\n\r\nLLM 可以把 base64 解码并保存：\r\n\r\n```python\r\nimport base64\r\nb64 = \"<返回的 base64 字符串>\"\r\nwith open(\"strategy_comparison.png\", \"wb\") as f:\r\n    f.write(base64.b64decode(b64))\r\nprint(\"图片已保存到 strategy_comparison.png\")\r\n```\r\n\r\n---\r\n\r\n## 二维数据绑定资产（非净值曲线的画法）\r\n\r\n如果要画某只个股的价格走势（二维数据中的某一列），需要额外传 `ticker`：\r\n\r\n```bash\r\npython scripts/call.py renderChart '{\r\n  \"title\": \"贵州茅台收盘价\",\r\n  \"lines\": [\r\n    {\"id\": \"<收盘价data_id>\", \"name\": \"600519.SH\", \"axis\": \"left\", \"ticker\": \"600519.SH\"}\r\n  ]\r\n}'\r\n```\r\n\r\n---\r\n\r\n## 注意事项\r\n\r\n| 场景 | 处理 |\r\n|------|------|\r\n| `errors` 非空 | 某条 line 的 id 不存在或数据类型不支持渲染 |\r\n| 净值曲线起点不一致 | 用 `start_date` 截断至同一起点再渲染 |\r\n| 图片太小看不清 | 调大 `width`（最大建议 1800）和 `height`（最大建议 900） |\r\n| 需要左右双轴 | 把量纲差异大的曲线（如换手率 vs 净值）设为 `\"axis\": \"right\"` |\n\nArchive v4.14.15: 53 files, 241474 bytes\n\nFiles: config.json (125b), presets/assets.yaml (6136b), presets/cases_index.yaml (29693b), presets/data_catalog.yaml (9071b), presets/functions.yaml (15093b), presets/sectors.yaml (17186b), presets/themes.yaml (17784b), recipes/download-data.md (1168b), recipes/event-study-formulas.md (7363b), recipes/ic-factor-templates.md (3309b), recipes/industry-aggregation.md (11787b), recipes/ma-crossover-backtest.md (3518b), recipes/render-chart.md (2750b), recipes/tool-call-checklist.md (3406b), recipes/topn-gainers.md (1637b), recipes/upload-custom-data.md (3235b), recipes/value-pe-strategy.md (3569b), references/environment.md (1981b), references/ru-billing.md (1838b), references/scripts-audit.md (3903b), references/troubleshooting.md (5426b), scripts/call.py (28640b), scripts/event_study_local.py (9796b), scripts/executor.py (34384b), scripts/quant_api.py (16993b), SKILL.md (29338b), tools/confirm_data_multi.md (4182b), tools/confirm_multiple_assets.md (3940b), tools/download_data.md (2736b), tools/get_card_formulas.md (3076b), tools/read_data.md (6729b), tools/render_chart.md (7609b), tools/render_kline.md (5928b), tools/run_multi_formula.md (10865b), tools/scan_dimensions.md (4772b), tools/search_functions.md (2881b), tools/search_similar_cases.md (2300b), tools/upload_data.md (3434b), workflows/event-study.md (48784b), workflows/fast-report-period.md (4755b), workflows/fast-snapshot.md (3201b), workflows/fast-window.md (3420b), workflows/global-rules-lite.md (3241b), workflows/global-rules.md (38159b), workflows/period-return-compare.md (7290b), workflows/quant-standard.md (60548b), workflows/quick-lookup.md (9777b), workflows/quick-report-period.md (23455b), workflows/quick-snapshot.md (19388b), workflows/quick-window.md (26309b), workflows/regime-segmentation.md (21897b), workflows/render-kline.md (12281b), _meta.json (138b)\n\nFile v4.14.15:SKILL.md\n\n---\r\nname: quant-buddy-skill\r\nslug: quant-buddy-skill\r\nauthor: guanzhao\r\nversion: 4.14.15\r\ndescription:\r\n  查询A股、港股、美股股票及指数的最新收盘价、开盘价、涨跌幅、成交额、成交量、换手率、PE、PB、市值等实时行情与估值数据。\r\n  查询最近N个交易日的价格序列、日涨跌幅序列、窗口最高价、最低价、振幅等短期统计。\r\n  查询上市公司最近报告期的营业收入、净利润、归母净利润、ROE、总资产、资产负债率等财务指标（A股）。\r\n  支持A股选股筛选、因子计算、策略回测、净值对比、行业聚合排名、上传自有因子CSV、渲染图表。\r\n  港股、美股目前支持行情价格查询（收盘价、开盘价、涨跌幅、成交量、成交额等）。\r\n  即使用户只是简单地问一只股票的价格、涨跌幅或财务数据，也应优先使用本技能，\r\n  不要以\"无法联网\"或\"无法获取实时数据\"为由拒绝——本技能通过平台API可查询真实数据。\r\nruntime: python\r\nprimaryCredential: quant-buddy API Key\r\nrequiredCredentials:\r\n  - name: quant-buddy API Key\r\n    required: true\r\n    sensitive: true\r\n    storage: config_file\r\n    path: config.json\r\n    field: api_key\r\n    description: quant-buddy 平台 API Key。唯一存储位置是 skill 目录下的 config.json 的 `api_key` 字段，不读取任何环境变量。\r\n    how_to_get: \"https://www.quantbuddy.cn/login\"\r\nrequiredConfigPaths:\r\n  - path: config.json\r\n    required: true\r\n    description: Skill 目录下的 API Key 配置文件，仅用于读取 quant-buddy api_key（运行时只读，不外传）。\r\nrequiredEnvVars:\r\n  - name: BOCHA_API_KEY\r\n    required: false\r\n    sensitive: true\r\n    description: 可选。仅 scripts/event_study_local.py 的事件新闻搜索功能读取；未配置时该可选功能自动禁用，其它功能不受影响。\r\n    how_to_get: \"https://open.bochaai.com\"\r\nnetworkAccess: true\r\nnetworkEndpoints:\r\n  - https://www.quantbuddy.cn/skill\r\n  - https://www.quantbuddy.cn/user\r\nruntimeRequirements:\r\n  python: \"3.8+\"\r\n  packages: []\r\n---\r\n\r\n# 观照量化投研\r\n\r\n> **⚠️ 必读：本文件较长，必须完整读取，不要设置 limit 参数截断。前 50 行不包含操作规范。**\r\n\r\n## 硬规则（7 条，违反必失败）\r\n\r\n0. **开工第一步：先查 API Key，再做任何其他事**。收到新问题后的第一个动作必须是读 `config.json`（或等效检查 api_key 字段）：\r\n   - 若 `api_key` 为空字符串 → **立即停止**，直接输出「前置条件」章节的**新用户引导消息**，**禁止** newSession、**禁止**读 workflow / quick-lookup / 任何业务文档、**禁止**调用 `scripts/call.py` 或任何平台工具。等用户贴入 `sk-` 开头的 Key 后再执行「配置向导」。\r\n   - 若 `api_key` 非空 → 继续第 1 条。\r\n   - **唯一例外**：用户本轮消息本身就是 `sk-` 开头的 Key（进入配置向导）或与查数无关的闲聊/元问题（如\"你会做什么\"）。\r\n   - **为什么**：查数类工作流最终都会调 `scripts/call.py`，api_key 为空时必然失败。提前在入口拦截可以避免多次失败调用，给新用户直接、清晰的第一印象。\r\n\r\n1. **每个新问题/新对话必须新建 session**：收到用户的新问题后，在调用任何平台工具之前，必须先新建 session（优先直接调用原生 `newSession` 工具；仅当当前环境没有原生 `newSession` 时，才使用 `GZQ_PARAMS='{\"user_query\":\"<用户的问题>\"}' python scripts/call.py newSession`）。newSession 是本地 UUID 生成，不可省略；`user_query` 仅用于本地 session 初始化标注，方便后续 trace 分析。\r\n   - **为什么**：`.session.json` 会自动注入到所有工具调用中。不新建 session = 复用上一轮对话的 task_id = 变量名冲突风险 + session 污染。\r\n   - **唯一例外**：同一对话中的追问/续问（如\"再画个图\"\"换个时间段\"），可复用当前 session。\r\n2. **原生工具优先，脚本包装仅限无原生等价能力时**：平台已提供的原生工具（`confirmMultipleAssets`、`confirmDataMulti`、`runMultiFormula`、`readData`、`renderKLine`、`renderChart` 等）必须优先直接调用；禁止用 `run_skill_script`、shell 命令、`GZQ_PARAMS=... python scripts/call.py ...` 等方式包装这些原生工具；`scripts/call.py` 仅用于：① `newSession` 等管理动作；② workflow 明确要求的本地脚本步骤；③ 平台不存在等价原生工具时的兜底。\r\n3. **先读 workflow 再操作**：按下方「场景路由」表加载对应 workflow，不要自行猜测参数格式。\r\n4. **配置/认证错误立即停止，不得在普通查数流程中转为认证收集**：\r\n   - **工具返回 API Key 缺失错误**（含 `api_key 为空` 消息 / `code: 1`）：立即停止查数，输出**新用户引导消息**（格式见「前置条件」章节模板），禁止继续执行查数；等待用户粘贴 Key 后再执行配置向导。\r\n   - **其他工具报错**\n\nArchive v4.14.14: 53 files, 241427 bytes\n\nFiles: config.json (127b), presets/assets.yaml (6136b), presets/cases_index.yaml (29693b), presets/data_catalog.yaml (9071b), presets/functions.yaml (15093b), presets/sectors.yaml (17186b), presets/themes.yaml (17784b), recipes/download-data.md (1168b), recipes/event-study-formulas.md (7363b), recipes/ic-factor-templates.md (3309b), recipes/industry-aggregation.md (11787b), recipes/ma-crossover-backtest.md (3518b), recipes/render-chart.md (2750b), recipes/tool-call-checklist.md (3406b), recipes/topn-gainers.md (1637b), recipes/upload-custom-data.md (3235b), recipes/value-pe-strategy.md (3569b), references/environment.md (1982b), references/ru-billing.md (1838b), references/scripts-audit.md (3906b), references/troubleshooting.md (5426b), scripts/call.py (28640b), scripts/event_study_local.py (9796b), scripts/executor.py (34385b), scripts/quant_api.py (16993b), SKILL.md (29245b), tools/confirm_data_multi.md (4182b), tools/confirm_multiple_assets.md (3940b), tools/download_data.md (2736b), tools/get_card_formulas.md (3076b), tools/read_data.md (6729b), tools/render_chart.md (7609b), tools/render_kline.md (5928b), tools/run_multi_formula.md (10865b), tools/scan_dimensions.md (4772b), tools/search_functions.md (2881b), tools/search_similar_cases.md (2300b), tools/upload_data.md (3434b), workflows/event-study.md (48784b), workflows/fast-report-period.md (4755b), workflows/fast-snapshot.m...","readmeExcerpt":"Skill: quant-buddy-skill Owner: pseudo-longinus Summary: 查询A股、港股、美股股票及指数的最新收盘价、开盘价、涨跌幅、成交额、成交量、换手率、PE、PB、市值等实时行情与估值数据。 查询最近N个交易日的价格序列、日涨跌幅序列、窗口最高价、最低价、振幅等短期统计。 查询上市公司最近报告期的营业收入、净利润、归母净利润、ROE、总资产、资产负债率等财务指标（A股）。 支持A... Tags: latest:4.14.18 Version history: v4.14.18 | 2026-04-24T08:16:31.868Z | user quant-buddy-skill 4.14.18 - 增加 metadata 字段，丰富了技能元信息，包括类别、标签、依赖等内容 - 无功能和行为变更 - 版本号自 4.14.17 升级至 4.14.18 v4.14.17 | 2026-0","codeSnippets":[],"executableExamples":[],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\r\nname: quant-buddy-skill\r\nslug: quant-buddy-skill\r\nauthor: guanzhao\r\nversion: 4.14.18\r\ndescription:\r\n  查询A股、港股、美股股票及指数的最新收盘价、开盘价、涨跌幅、成交额、成交量、换手率、PE、PB、市值等实时行情与估值数据。\r\n  查询最近N个交易日的价格序列、日涨跌幅序列、窗口最高价、最低价、振幅等短期统计。\r\n  查询上市公司最近报告期的营业收入、净利润、归母净利润、ROE、总资产、资产负债率等财务指标（A股）。\r\n  支持A股选股筛选、因子计算、策略回测、净值对比、行业聚合排名、上传自有因子CSV、渲染图表。\r\n  港股、美股目前支持行情价格查询（收盘价、开盘价、涨跌幅、成交量、成交额等）。\r\n  即使用户只是简单地问一只股票的价格、涨跌幅或财务数据，也应优先使用本技能，\r\n  不要以\"无法联网\"或\"无法获取实时数据\"为由拒绝——本技能通过平台API可查询真实数据。\r\nruntime: python\r\nprimaryCredential: quant-buddy API Key\r\nmetadata:\r\n  version: 4.14.18\r\n  author: guanzhao\r\n  category: quant-finance\r\n  tags: [quant, market-data, finance, A-stock, HK-stock, US-stock, backtest, factor]\r\n  runtime: python\r\n  primaryCredential: quant-buddy API Key\r\n  requiredCredentials:\r\n    - quant-buddy API Key\r\n  requiredConfigPaths:\r\n    - config.json\r\n  requiredEnvVars:\r\n    - BOCHA_API_KEY (optional)\r\n  networkEndpoints:\r\n    - https://www.quantbuddy.cn/skill\r\n    - https://www.quantbuddy.cn/user\r\n  pythonPackages:\r\n    - python-dateutil (optional)\r\n    - Pillow (optional)\r\nrequiredCredentials:\r\n  - name: quant-buddy API Key\r\n    required: true\r\n    sensitive: true\r\n    storage: config_file\r\n    path: config.json\r\n    field: api_key\r\n    description: quant-buddy 平台 API Key。存储位置：skill 目录下的 config.json 的 `api_key` 字段（本 skill 不读环境变量版本的该 Key）。使用时作为 HTTP `Authorization` 头仅发送给 `networkEndpoints` 中声明的 quantbuddy 域名用于鉴权，不会被写入日志或转发给第三方主机。\r\n    how_to_get: \"https://www.quantbuddy.cn/login\"\r\nrequiredConfigPaths:\r\n  - path: config.json\r\n    required: true\r\n    description: Skill 目录下的 API Key 配置文件，仅包含 quant-buddy api_key 和两个公开端点配置，由 skill 本地脚本读取；api_key 仅作为 HTTP `Authorization` 头发给 `networkEndpoints` 中声明的 quantbuddy 域名，不发送给其他主机。\r\nrequiredEnvVars:\r\n  - name: BOCHA_API_KEY\r\n    required: false\r\n    sensitive: true\r\n    description: 可选。仅 scripts/event_study_local.py 的事件新闻搜索功能读取；未配置时该可选功能自动禁用，其它功能不受影响。\r\n    how_to_get: \"https://open.bochaai.com\"\r\nnetworkAccess: true\r\nnetworkEndpoints:\r\n  - https://www.quantbuddy.cn/skill\r\n  - https://www.quantbuddy.cn/user\r\nruntimeRequirements:\r\n  python: \"3.8+\"\r\n  packages:\r\n    - name: python-dateutil\r\n      version: \">=2.8\"\r\n      required: false\r\n      description: Used by scripts/event_study_local.py for the optional event-study / Bocha news feature. Not needed if BOCHA_API_KEY is not configured.\r\n    - name: Pillow\r\n      version: \">=9.0\"\r\n      required: false\r\n      description: Used by scripts/call.py saveChart command to convert chart images to JPEG. Falls back gracefully (writes raw bytes) if not installed; no credential exposure risk.\r\n---\r\n\r\n# 观照量化投研\r\n\r\n> **⚠️ 必读：本文件较长，必须完整读取，不要设置 limit 参数截断。前 50 行不包含操作规范。**\r\n\r\n## 硬规则（7 条，违反必失败）\r\n\r\n0. **开工第一步：先查 API Key，再做任何其他事**。收到新问题后的第一个动作必须是读 `config.json`（或等效检查 api_key 字段）：\r\n   - 若 `api_key` 为空字符串 → **立即停止**，直接输出「前置条件」章节的**新用户引导消息**，**禁止** newSession、**禁止**读 workflow / quick-lookup / 任何业务文档、**禁止**调用 `scripts/call.py` 或任何平台工具。等用户贴入 `sk-` 开头的 Key 后再执行「配置向导」。\r\n   - 若 `api_key` 非空 → 继续第 1 条。\r\n   - **唯一例外**：用户本轮消息本身就是 `s"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b02063x75b1b8yswrzgesph858j2j\",\n  \"slug\": \"quant-buddy-skill\",\n  \"version\": \"4.14.18\",\n  \"publishedAt\": 1777018591868\n}"},{"path":"references/environment.md","content":"# 环境依赖说明\r\n\r\n本文档描述运行 `quant-buddy-skill` 及其子场景所需的环境配置。\r\n\r\n---\r\n\r\n## Python\r\n\r\n- **版本要求**：Python 3.8+（推荐 3.11）\r\n- **核心功能**：仅依赖标准库，无需额外 `pip install`\r\n- **Windows 推荐启动方式**：所有涉及中文路径的脚本加 `-X utf8` 标志\r\n\r\n```bash\r\npython -X utf8 scripts/call.py <工具名>\r\n```\r\n\r\n---\r\n\r\n## API Key 配置\r\n\r\n前往 https://www.quantbuddy.cn/login 登录/注册，在账户页面获取 API Key。获取后有两种方式写入：\r\n\r\n1. **手动编辑**：直接打开 skill 根目录下的 `config.json`，把 `api_key` 字段改为你的 Key。\r\n2. **贴给 AI 助手**：在对话中把 `sk-...` 开头的 Key 发给 AI，AI 会写入 `config.json`。\r\n\r\n若你需要保留私有配置或覆盖默认端点，请使用 `config.local.json`；该文件仅供本地使用，不应打包或提交。\r\n\r\n若出现 `401 Unauthorized` 或 `402 Quota`，请重新获取并更新 `config.json` 中的 `api_key`。\r\n\r\n---\r\n\r\n## 可选 Bocha 搜索能力\r\n\r\n仅部分 Web 搜索辅助场景需要博查凭证；核心行情、财务、选股、回测能力不依赖该凭证。\r\n\r\n可选配置方式（任一即可）：\r\n\r\n- 环境变量 `BOCHA_API_KEY`\r\n- `config.local.json` 中手动添加 `bocha_api_key`\r\n- `config.json` 中手动添加 `bocha_api_key`\r\n\r\n---\r\n\r\n## 运行时输出目录\r\n\r\n- `output/.session.json`：当前 session 的 task_id\r\n- `output/ic_data/`：IC 扫描结果（若 workflow 触发相关能力）\r\n- 其他 `csv / png / json / html`：运行过程中的临时或交付产物\r\n\r\n---\r\n\r\n## readData 批量限制\r\n\r\n`readData` 单次调用最多传入 **10 个 data_id**。如需读取更多结果，拆分多次调用。\r\n\r\n---\r\n\r\n## 终端注意事项\r\n\r\n- 终端缓冲可能导致长输出不完整显示，`call.py` 会额外写入系统临时目录下的 `gzq_out.txt`\r\n- 若需排查，可在系统临时目录中查看该文件内容"},{"path":"references/ru-billing.md","content":"# RU 计费体系\r\n\r\n> 更新于 2026-04-15。统一 RU（Resource Unit）体系，所有端点共享一个 RU 池。\r\n> 每个请求按端点类型 + 请求参数动态扣减 RU（1～26 RU）。\r\n> 规划流程时优先减少冗余调用。\r\n\r\n---\r\n\r\n## RU 权重速查表\r\n\r\n| 工具 | 模式 | RU 消耗 | 说明 |\r\n|------|:---:|:---:|------|\r\n| `search_functions` | fixed | 1 | |\r\n| `get_card_formulas` | fixed | 1 | |\r\n| `upload_preview` | fixed | 1 | |\r\n| `upload_confirm` | fixed | 1 | |\r\n| `download_data` | fixed | 1 | |\r\n| `render_kline` | fixed | 1 | |\r\n| `re_render_chart` | fixed | 1 | |\r\n| `read_data` | fixed | 2 | |\r\n| `search_similar_cases` | fixed | 5 | |\r\n| `confirm_multiple_assets` | deferred | 1～6 × 意图数 | DB 精确匹配 1 RU，LLM 路径 6 RU |\r\n| `confirm_data_multi` | deferred | 1～26 × 意图数 | DB 精确匹配 1 RU，LLM 路径 26 RU |\r\n| `run_multi_formula` | dynamic | **7 × 公式数** | 单次最多 20/30/40 个（free/plus/pro） |\r\n| `scan_dimensions` | dynamic | **12 × 维度数** | 全维度(8) = 96 RU |\r\n| `render_chart` | dynamic | **1 × 线数** | 如 3 条线 = 3 RU |\r\n\r\n> **deferred 模式**：先预扣 1 RU/意图，请求完成后按实际路径补扣差额。\r\n> **错误请求退款**：所有端点发生错误时（4xx/5xx），实际 RU 降为 1 RU。\r\n\r\n---\r\n\r\n## 配额池说明\r\n\r\n| 池 | 重置方式 | 说明 |\r\n|------|------|------|\r\n| **窗口 RU** | 个人滚动（最早请求 +4h） | 不是全部一次恢复，按请求逐批恢复 |\r\n| **日 RU** | 每天 00:00（北京时间） | 次日零点统一重置 |\r\n\r\n---\r\n\r\n## 场景成本参考\r\n\r\n| 场景 | 典型 RU 消耗 |\r\n|------|:---:|\r\n| 单只股票价格/PE/PB | ~3 RU |\r\n| 条件选股（1 条公式）| ~10 RU |\r\n| 条件选股+回测（5 公式）| ~37 RU |\r\n| IC 全维度扫描 | 96 RU |"},{"path":"references/scripts-audit.md","content":"# Bundled Scripts Audit\r\n\r\nThis document enumerates every Python script shipped inside this skill, what it does, and its network / subprocess / filesystem behavior. Reviewers can use it to verify the skill's declared behavior without reading every line of code.\r\n\r\nLast audited against version: **4.14.7**\r\n\r\n---\r\n\r\n## Top-level scripts\r\n\r\n### `scripts/call.py`\r\n- **Purpose**: Thin CLI dispatcher. Takes a tool name + JSON params, forwards to `scripts/executor.py` via a subprocess of the same Python interpreter.\r\n- **Network**: None directly. Network calls happen inside `executor.py`.\r\n- **Subprocess**: `subprocess.run([sys.executable, \"scripts/executor.py\", ...])`. No shell, no external binary.\r\n- **Filesystem writes**: None.\r\n- **Reads secrets**: Only `config.json` / `config.local.json` pass-through; secrets are handled by `executor.py`.\r\n\r\n### `scripts/executor.py`\r\n- **Purpose**: Calls the quant-buddy HTTPS API and returns the response.\r\n- **Network**: Only `https://www.quantbuddy.cn/**` via `urllib.request` (stdlib). Host is taken from `config.json#endpoint` with a hardcoded default; no redirects to third-party hosts are followed without verification.\r\n- **Authentication**: Resolves `api_key` in this order: (1) `QUANT_BUDDY_API_KEY` env var, (2) `config.local.json` `api_key` field, (3) `config.json` `api_key` field. The resolved key is sent **only** in the `Authorization: Bearer <key>` header. It is never logged, printed to stdout/stderr, or written to files.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: Optional response cache under `.cache/` within the skill root; chart / CSV outputs under `output/` when invoked by chart or download tools.\r\n\r\n### `scripts/quant_api.py`\r\n- **Purpose**: Python wrapper around `executor.py` for use as a library (not invoked during normal agent flow).\r\n- **Network**: Same as `executor.py` (delegates to it).\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: None.\r\n\r\n### `scripts/event_study_local.py`\r\n- **Purpose**: Optional event-study helper. Combines quant-buddy data with a Bocha web-search step for news context.\r\n- **Network**:\r\n  - `https://www.quantbuddy.cn/**` (via `executor.py`) — required.\r\n  - `https://api.bochaai.com/v1/web-search` — **opt-in only**. The function returns `{\"ok\": false, \"error\": \"BOCHA_API_KEY 未配置\"}` immediately if the user has not set `BOCHA_API_KEY` (env var / `bocha_api_key` in `config.local.json` / `config.json`). No request is made without the key.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: None.\r\n- **Dependency**: Requires the `requests` package **only when Bocha is enabled**. Without BOCHA_API_KEY the import path is bypassed.\r\n\r\n### `scripts/repro_scan_null.py`, `scripts/update_cases_index.py`\r\n- **Purpose**: Developer utilities for curating the skill's own preset/case files. Not invoked by the agent at runtime; intended for the skill author to regenerate local indices.\r\n- **Network**: None.\r\n- **Subprocess**: None.\r\n- **Filesystem writes**: Only under `scripts/` and "}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1502,"uniquenessScore":42,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T18:23:46.431Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T18:23:46.431Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T20:56:58.148Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}