Screening correctness and delivery recovery
When involving stock selection, TopN, or confirmed filter conditions, first read Research contract and recovery. Research and page status are recorded separately; if data is missing or the result is empty, still deliver a readable research page, and do not write unverified results as zero hits.
Guanzhao Quantitative Investment ResearchWebAgent host delivery conventions take priority: When the host requires that financial questions uniformly use "complete Q&A + live page", all financial questions must first actually route, then be verified via QBS query and sent a non-terminal first answer, and QBV continues in the same turn. This includes specific fields, concept explanations, and "How has 601137 been recently?", without relying on page-building keywords. The Worker's QBS_DEFAULT_PAGE_REQUESTED=1 is automatically inherited by the script; the "answer only/end/do not build a page" defaults in this file and the leaf workflow apply only to standalone QBS. Cases of explicitly not wanting a webpage/replying only with text, read-only interpretation of an existing page, file hosting, and pure maintenance are handled according to their respective rules. See Host default page building。
First screen priority: First read the "Platform Tool Parameter Quick Reference", "Hard Rules", and "Scenario Routing" in the earlier part of this file. When high-frequency tasks such as simple market quotes, window series, the most recent reporting period, fixed-interval returns, and K-line charts hit the Fast Path, there is no need to continue reading the entire book.
Local delivery must reuse the real path returned by the tool; do not add sandbox: or guess the Skill installation directory. Check the ranking table column by column for data ID, unit, and date; ratio columns must not be copied into the PE column. See Global Execution Rules。
The content contract for individual stock profiles and comprehensive analysis is in workflows/stock-profile.md: By default, deliver five data sections and comprehensive observations; only reduce when the user explicitly requests brevity or limits fields. After reading the Skill, you must continue to read the matching workflow, actually query, and reply; "will read the document/prepare to query" is not a business delivery and cannot be the final answer. Explicitly not wanting a webpage only cancels page building, not the above query and complete analysis.
Default conventions for common requests
- For Chinese stock all-market rankings and top-N heatmaps by price change without a specified market, default to A-shares and state this in the first answer; industry grouping defaults to Shenwan Level 1, and colors preserve the stocks' original price change percentages, with area or quantity clearly meaning what it means. If the user specifies another market, comply, and do not stop clarifying just because of these disclosable defaults.
- For a refresh dashboard with an already given industry scope such as "baijiu stocks", first verify the corresponding platform sector and constituents, default to PE TTM and PB; query according to
quant-standard.mdand give the first answer with actual market data, trading volume, and valuation, then continue QBV according toanswer-first.md. Refresh intent does not allow registering a formula package first, nor replying with only a dashboard design. Do not first ask the user to list stock names. Clarify only when the exact sector does not exist or there is indeed ambiguity with the same name, and do not use a few leading stocks to impersonate the entire industry. - For common single moving average backtests, the disclosed default values of quant-standard may be used to continue execution; if the user explicitly does not want a webpage, do not build a page.
Platform Tool Parameter Quick Reference (high-frequency pitfalls, read this section first)
The table below shows the three schemas that LLMs most easily get wrong. Check before any call, and do not guess parameter names based on what "looks reasonable".
| Tool | ✅ Correct parameters | ❌ Common model errors (already automatically normalized or intercepted by call.py, but should still be avoided) |
|---|---|---|
confirmDataMulti |
{"data_desc": "市盈率 TTM,股息率"} — Comma-separated string |
{"queries": [...]} / {"query": "..."} / {"names": [...]} |
runMultiFormulaBatchStream Reference session intermediate variables in formulas |
Must usedouble quotesto wrap:排序値 = "A股股息率〔估値数据〕" * "条件合并" |
Multiplying bare variable names:"A股股息率…" * 条件合并 ← The platform directly reports an error |
readData |
{"ids": ["69fe…<24位hex>"], "mode": "last_column_full"} — Must be the runMultiFormulaBatchStream returned by data_id field (hex) |
Passing a Chinese variable name {"ids": ["Top10股息"]} / Using the wrong parameter name {"index_title": "..."} / {"variable_names": [...]} / Passing expression_id instead of data_id(the two are adjacent and easily confused; passing the wrong one returns "error": "IndexInfo {id}") |
Caliber conversion (confirmDataMulti query term): When the user writes PE(TTM) / 归母净利润 or other English terms or abbreviations, the query term should use theChinese canonical name(e.g., 市盈率 TTM / 归母净利润), rather than copying the user's original text verbatim into data_desc. For detailed rules, see workflows/global-rules.md#指标口径精确匹配。
US stock options corresponding contract query
When the user asks about the contract corresponding to a slot, contract rollover/month rollover, or wants an explanation of option IV, price, or open interest changes, read tools/query_option_contracts.md, use the independent tool query_option_contracts. The new parameter is asset + query_type: snapshot queries the latest effective contract for each slot; window uses lookback_days to query a rolling natural-day window; provide parameters according to the tool description. Supports QBV option_contracts data authorization, dynamically advancing the date on each data retrieval. Preserve the actual trade_date, align by the actual market date and the contract selection effective date, do not treat the stitched price as holding return, and do not forward-fill missing mappings. Public parameters are converted by skill_server into the existing Celery date query; the dataServer protocol is unchanged; if the new version of skill_server is not deployed, do not pretend the query succeeded.
Convert existing files to live pages: first submit to QBV static hosting
When the user provides existing files such as JPG/PNG, HTML, PDF, etc. and requests conversion to a live page or public sharing, prioritize entering QBV workflows/existing-file-static-first.md: first file_prepare saves the original file, generates the original hosting page and persistent publishing parameters, retains file_publish_dir to perform static publishing, and after acceptance, before the next tool call, first send the link to the user; file_confirm_delivery confirms the message actually sent, then automatically continue the already-authorized research, error correction, metric supplementation, and QBS integration. Even for composite requests, do not research first and publish later. This order takes precedence over asset mapping, data lookup, formula validation, chart classifier, and "calculate first, then Handoff"; the first version does not require a calculation capsule, and does not rewrite the original report first. Reuse the real task_id/turn_id and the same page_id; do not create another user-visible task. QBS query/integration failure only affects enhancement; retain the successful online version; not finding it does not mean the platform does not support it. Pure file analysis and explicit non-publishing do not trigger this; genuine public authorization, unreadable files, and conversion/first-time hosting issues must be truthfully explained. Do not mark snapshots as real-time or verified.
Hard rules (violation guarantees failure)
-
Tool names and the unknown-tool red line (highest priority):
- The only callable tool name for formula execution:
runMultiFormulaBatchStream。 - It is forbidden to call or retry old/wrong names:
runMultiFormulaBatch/runMultiFormula/run_multi_formula。 - After any tool returns
未知工具/Unknown tool/tool not found, the same-named tool 0 retries, and do not attempt name variants. - If the workflow has declared a unique correct native tool, switching to that tool is allowed only once; if it still fails, immediately output a controlled failure response.
- If the result of the previous step is already sufficient to answer the user's question, immediately give the business answer and do not escalate the data-query chain further; when there is already a clear page-creation intent, first send a non-terminal initial answer, then continue QBV in the same turn according to workflows/answer-first.md.
- The only callable tool name for formula execution:
-
Post-authentication verification and session initialization:
- Do not, in the first step of an ordinary data-query question, read
config.json, and do not check.session.json、output/.session*.jsonor any local session file. - As long as this turn is preparing to call a platform-native tool, directly call the native
newSessionfirst; do not use Bash / Glob / Read / ls to probe for session existence. - quant-buddy-view upstream inheritance exception: if the current task is orchestrated by quant-buddy-view, and the upstream has already created a task_id via
trace_context.py begin, do not generate a second task_id. Preferably, QBV'sscripts/qbs_bridge.pyshould call this skill; the bridge will pass{"task_mode":"inherit","task_id":"<上游 task_id>","task_source":"quant-buddy-view","user_query":"<用户原始问题>"}and useQBS_SESSION_KEY=<task_id>to isolate concurrent sessions. This exception is only for cross-Skill session binding. - When inheriting a task_id, an explicit
task_mode=inheritmust be used; do not guess the source through string prefixes such asqbv_. An inherited session will lock the task_id; if subsequent parameters pass in a different value, you must stop according toTASK_ID_CONTEXT_MISMATCH, and must not silently break the chain. - When quant-buddy-skill is used independently, keep the original behavior: do not pass
task_mode/task_id, and letnewSessionautomatically generate a new UUID and report session begin. - Only when the tool actually returns
api_key 为空/code: 1/ 401/402 should you enter authentication guidance and stop the current data-query task. - A follow-up in the same conversation may reuse the current session; a new question must create a new session.
- All business HTTP/SSE requests uniformly carry
x-skill-name: quant-buddy-skilland the currentx-task-id, for cross-Skill Trace aggregation; upstream tasks from quant-buddy-view must not switch task_id.
- Do not, in the first step of an ordinary data-query question, read
-
Native tools take priority; script wrapping is prohibited:
- When the platform already has a native tool, the native tool must be called directly:
fast_query、fast_query_minute、fast_query_minute_range、confirmDataMulti、selectByComposition、runMultiFormulaBatchStream、resumeJob、readData、renderKLine、renderChart, etc.; but ordinary K-line live pages must first go throughkline-page-fast-path.md, and must not callrenderKLine。 - It is prohibited to use Bash / shell / Python /
scripts/call.py/run_skill_scriptto wrap an existing native platform tool. The only orchestration exception is quant-buddy-view'sqbs_bridge.py, which is only responsible for inheriting the task_id and isolating the session, and does not rewrite business parameters or results. - Only when the platform clearly has no equivalent native tool, and the workflow explicitly allows script fallback, may a local script be used.
- Permitted exception (csv parsing): when
fast_queryreturnsmode:"csv"+csv_url(normal delivery for data points > 500), callingpython scripts/fetch_fastquery_csv.py "<csv_url>"to download and parse that csv is apermitted path—this is consuming an OSS artifact returned by a tool (the platform has no equivalent native parsing tool), and does not count as "wrapping a native tool". Historical minute long tables usescripts/fetch_minute_range_csv.py @output/minute-manifest.json --output output/minute-data.json, and the daily-frequency wide-table parser cannot be applied. However, it is still prohibited to use barecurl/ self-written temporary scripts to replace that script. - When assets are involved, it is still necessary to first use
grep presets/assets_db/{类型}.yamlSearch the local asset library; full-file reads are prohibited; if multiple matches are hit, clarify first; if no match is hit, hand it over to the server for fallback parsing. - When English code has no market suffix, you must first grep the corresponding asset library to confirm the ticker format.
- When the platform already has a native tool, the native tool must be called directly:
-
Tool failure circuit breaker: the same type of error must not be repeated
- Local
RESUME_CONTEXT_MISMATCHcan be corrected once according to the uniqueresume_paramsreturned by the tool;UNIVERSE_SCOPE_MISMATCHcan be corrected once to the exact industry after verifying the directory. These two types have not yet submitted a network request, and this exception must not be used to repeat real query errors. - After the same tool, same parameter structure, and same error type occur for the 1st time, you may only switch according to the fallback path declared by the workflow; if there is no fallback path, fail in a controlled manner.
- Do not repeatedly call a failed tool without new information; do not attempt name variants; do not read more documents instead of executing; do not use shell/Python wrappers to bypass a failed tool.
runMultiFormulaBatchStream/resumeJobOnly the finalcompletedand when all results succeed isvalidation_receipt_file;failed, partial failure,deferredall do not generate a receipt. QBV orchestration must use this receipt as evidence of progress completion. Long results may passoutput_mode:"summary": completed retainsdata_id/expression_id/status; deferred additionally fully retainsstatus/task_id/trace_id/job_id/stream_url/_deferred. When deferred lackstask_id/trace_id, returnDEFERRED_CONTINUATION_MISSING, and do not resubmit the original batch.
- Local
-
When any workflow fails and exits, a controlled failure reply must be output: do not end the conversation with blank content or pure process logs. The failure reply must include:
- ①The user's original question (restate in one sentence)
- ②Which step the failure occurred at (tool name + error summary)
- ③A one-sentence explanation to the user ("Currently unable to obtain..., reason: ...")
- Optional ④: the next step the user can take (such as "retry later" or "switch to the full pipeline")
-
Read the workflow before operating: load the corresponding workflow according to the "Scenario Routing" table below; do not guess the parameter format yourself.
-
Configuration/authentication errors stop immediately and must not be turned into authentication collection in a normal data query process:
- The tool returns an API Key missing error(including
api_key 为空message /code: 1): stop the data query immediately and outputthe new user guidance message(for the format, see the template in the "Prerequisites" section); do not continue executing the data query; wait for the user to paste the Key before executing the configuration wizard. - Other tool errors(network, server errors, etc.): directly report "internal tool exception" and do not provide authentication-related guidance.
- The tool returns an API Key missing error(including
-
The first sentence of the final answer must be the data conclusion: when answering the user, the first sentence must directly give the data conclusion (such as asset name + value, a table, or "N items meet the conditions"); it is absolutely prohibited to begin with process statements such as "successfully obtained", "data has been obtained", "according to the returned results", or "let me". Violating this rule = the process remarks must be deleted and the output regenerated.
- Do not paste tool JSON verbatim: after the tool returns
code:0/success:true, the final reply mustdata.resultsand other business fields should be rewritten into human-readable conclusions (one sentence, a short table, or a list). Unless the user explicitly requests "give me the raw JSON / debug output", the complete tool response must not be sent to the user as-is. - Hide runtime-state fields: the final answer should by default ignore
code、success、task_id、_quota、skill_latest_version、skill_update_available、skill_update_enforced、skill_self_update、auto_upgrade*、version_checkand other runtime/upgrade fields; these fields are only for the Agent to determine the process, not answer content for ordinary users. - Version heartbeats do not interrupt business answers: if the business
datahas already returned successfully, then even if the response body carries a version heartbeat, the user's question must still be answered first; only when the tool explicitly returns a business failure orSKILL_VERSION_MISMATCHshould the self-healing/troubleshooting process be entered.
- Do not paste tool JSON verbatim: after the tool returns
-
User conditions are frozen and must not be rewritten: before execution, the user's original conditions must be checked word by word. The following rewriting behaviors are all violations (once discovered, they must be rolled back and reconfirmed):
- Percentage ↔ decimal conversion(e.g., "dividend yield > 3%" must not be rewritten as
>0.03) - Relative time changed to a year range(e.g., "the past 10 years" must not be rewritten as "2015-2025")
- Asset universe replacement(e.g., "ordinary stocks" must not be rewritten as "Wind All A constituent stocks" or "non-ST stocks")
- Event scope expansion(e.g., "annual report/semi-annual report" must not be expanded to all performance disclosure types)
- Card additional conditions inheritance: after a knowledge card is matched, if the card contains additional conditions not explicitly proposed by the user, such as "first time/non-ST/limit-up/liquidity threshold", they must be deleted before execution; it is forbidden to silently inherit them into the final answer
- Percentage ↔ decimal conversion(e.g., "dividend yield > 3%" must not be rewritten as
-
When the task is ambiguous, ask first; do not guess and start: if the user's instruction has two or more reasonable interpretations(e.g., "batch confirm X" is unclear whether it means confirming the index itself or all constituent stocks, and "analyze Y" is unclear which dimension is wanted),the first step must be to ask the user for clarification, and one interpretation must not be chosen by speculation and executed on one's own. The clarifying question should concisely list the possibilities (e.g., "Do you mean ① ... or ② ...?"), and continue only after the user confirms.The only exception: if the user's semantics are clear and unambiguous (e.g., "give me Guizhou Moutai's closing price today"), no clarifying question is needed.
⚠️ Rules for handling ambiguous words (first determine whether there is true ambiguity, then decide whether to ask or use the default convention and proceed):
The following words have multiple definitions in quantitative semantics and must be handled correctly:
- Technical analysis category: support level / resistance level / pressure level / neckline level / key level / key point level / breakout level
- Trend judgment category: trend / trend forecast / market outlook judgment / can it still rise / will it fall / short-term view / medium-term view
- Market characterization category: unusual movement / main force / main force flow / market maker movements / strong / weak / resistant to decline / downside resistance
- Health category: are the fundamentals good / is the valuation expensive / financial health / how are the performance results / fundamentals
Determination process (match in order, stop once matched):
-
Comprehensive analysis request → use the default convention and proceed directly, no clarifying question blocking. Determination: The user lists ≥2 analysis dimensions in one sentence (e.g., "fundamentals + technical indicators + trend", "valuation + financials + price action"), or explicitly says "comprehensive analysis / take a comprehensive look / give me a report". Approach: Directly follow
stockProfile(comprehensive profile) + conventional technical indicators + default trend methodology,First sentence of the reportInforms the user of the methodology used (e.g., "This output follows the default methodology: fundamentals = comprehensive profile (valuation + financials + capital flows + volatility), technicals = MACD/KDJ/RSI/Bollinger Bands, trend = MA20/MA60 alignment direction. If you need to adjust the methodology, please let me know."). -
Isolated single-point definition request → must ask a clarifying question. Determination: The trigger word appears alone, and its definition directly determines the conclusion value (e.g., "What is Kweichow Moutai's support level", "How is CATL's trend", with no other dimensional context). Approach: Ask ① the definition of the methodology (e.g., "support level" = lowest of recent N days / lower Bollinger Band / moving average cluster); ② the time window; ③ the output format.
-
Trigger word is only a modifier → proceed directly. Determination: The user's main request is clear, and the trigger word is only incidental description (e.g., "find stocks with recent fundamental improvement" — the main request is screening, and "fundamental improvement" already implies executable criteria such as "year-over-year revenue/net profit increase"). Approach: Execute using the most common executable methodology, and note the methodology in the results.
Tested lesson (T-036): The user asked about "Kweichow Moutai's support level", and the model arbitrarily used "near the 60-day low" as the definition and executed directly — this is an isolated single-point request and should have followed process 2 by asking a clarifying question. Counter-example (do not repeat): The user asked "analyze East Money's fundamentals, technical indicators, and trend forecast", and the model asked 4 questions and blocked — this is a comprehensive analysis request and should have followed process 1 with the default methodology and proceeded directly.
-
When a tool returns
SKILL_VERSION_MISMATCH, self-healing is mandatory; the original task must not continue to be executed: When"error": "SKILL_VERSION_MISMATCH"appears in the output of any tool call, it indicates that the tool signatures/parameter formats in the current conversation context are outdated. In this case, the following self-healing process must be executed (no step may be omitted): -
Immediately stopthe current task; no further platform tools may be called;
-
Call
newSession(create a new session, obtain a new task_id); -
Force re-read
SKILL.md(this file) + the workflow document corresponding to the current scenario + the involved tools/*.md; -
Re-executethe user's original task using the newly readtool signatures and parameter formats;
-
It is forbiddento ask the user "whether to continue" or explain the version upgrade process — silently complete the self-healing and return the result.
-
CHANGELOG / skill-changelog serves only as an audit, not as a rule source:
CHANGELOG.md、skill-changelog/**is a change record accumulated over time, containing old methodologies that have been reversed or deprecated by later versions. For any judgment related to "execution order, field names, protocol block semantics, tool signatures, parameter formats",mustuseSKILL.md+workflows/**+tools/**+references/troubleshooting.mdas the sole authority; when the CHANGELOG description conflicts with the above files, the above files shall prevail. The CHANGELOG may only be used for: ① reviewing "which version changed what" when troubleshooting; ② making a version context summary of no more than 5 items after a successful upgrade.Prohibited: treating a historical narrative in the CHANGELOG as a current execution rule, inferring the current parameter format based on the CHANGELOG, or favoring the CHANGELOG when it conflicts with SKILL.md. -
To judge whether a tool succeeds or fails, look at the returned body's
code/success, not the HTTP status code: HTTP 200 does not mean business success—if the body contains"code": -1/"success": false, that is abusiness error, and it must be handled as a failure (readerror/messagebefore deciding whether to retry/adjust parameters/consult the troubleshooting table); it is prohibited to continue onward by assuming "if HTTP went through, it succeeded." Also:call.pyreturning"error": "INVALID_TOOL_NAME"indicates that the tool name is wrong or missing (the tool name must come first in the command and must be a registered tool name), which is a local error that can be corrected immediately. See details inreferences/troubleshooting.mdat the top of "General Rules for Success/Failure Determination." -
Answer first, then build the page: operational requests such as daily/periodic review, market monitoring, line drawing/charting, executing backtests, and viewing K-lines, as well as already-registered stable rankings (low PE + high ROE + stock selection/ranking + TopN), must actually execute
scripts/live_page_routing.py route, and ordinary TopN must not all be upgraded into live pages. The above operations themselves constitute live page intent, and the user is not required to separately say "web page"; purely conceptual explanations do not build pages. A genuine page-building intent in the context may be passed as--page-requested, while an explicit request not to have a web page/not to publish for now still takes priority; not wanting charts only constrains the form of presentation and cannot veto a table-type live page. Execute according to Answer first, then build the page : after QBS query validation, first send the complete non-terminal business answer, then prepare the Capsule/Handoff/Job, with the defaultsame_turnentering QBV; reliable internal delegation is an optional branch and must not be executed repeatedly.prepare-validated-pageacceptsanswer_structure; when not passed, generate a conservative table structure according to the validated_roles in the order of the first answer. **Full computation scale and page display scale are separated: when the ranking does not specify a quantity, Top20 is default, and the page renders only Top20; the Formula Package/Data Grant is responsible for server-side caching and dynamic data retrieval, and the page must not be downgraded to a static snapshot just because many stocks participate in the computation. Only when the user explicitly requests a fixed snapshot, or the dynamic data routing is verified to be truly unavailable, mayvalidated_snapshotbe used, and the reply must truthfully state that it will not update automatically.** After success, continue according to next_action and do not repeat handoff/prepare. prepare is not chart or page completion; when QBV is inaccessible, this Skill's update must be used to write back the returned on_unavailable failure field, and it must not be left as queued or falsely claimed to be executed in the background. Routing/page failure does not revoke a normal first answer; when there is no capability for intermediate visible messages, truthfully record the limitation. Page routing, permissions, same-page updates, and public acceptance are still the responsibility of QBV. Multiple standard fields of a single asset in the same chart and near-N-day industry rankings each follow dedicated fast paths, and the fast paths must also answer first and then prepare the page. -
QBS→QBV only reuses the part already computed in this round, and does not turn QBV into a QBS-specific renderer:
create|existing_pageBefore Handoff, preferentially runscripts/qbv_computation_capsule.py build @capsule-input.json, generatingqbs_computation_capsule_v1. The capsule must simultaneously contain the user's core question/main chart intent, asset normalization results, a reproducible query or formula contract and fingerprint, a result snapshot or artifact SHA256, field mappings, conclusions and verification receipts; it is prohibited to deliver only a PNG or a one-sentence summary. When the same business role corresponds to multiple materialized results,data_idsmay be passed; the builder expands them in the original order intorole__01、role__02..., preserving the original ID strings and synchronizingrequired_rolesmust not manually rewrite or copy IDs. The QBV thin adapter determinescoveredmust not re-identify assets or recompute the same role,partialmust only supplementmissing_roles,unusablemust losslessly fall back to the original QBV→QBS bridge; direct/fork/unmatched, ownership, build, runtime registration, release, and acceptance still fully belong to QBV. Users directly using QBV's quantitative page building likewise answer first; when there is no capsule, the original query capability is retained, and existing file/interpretation/display maintenance exceptions remain unchanged. -
A formula execution contract that has already run successfully must be handed to QBV as-is, with no second rewrite:
runMultiFormulaBatchStreamAfter success, the original execution is evidenced by the Validation Receipt'sexecution_contractfor proof; secure page reads separately useqbs_formula_runtime_contract_v1(may be omitted), the two must not be conflated, and theformulas's count, order, full metric names, quotation marks,begin_date、include_description、use_minute_data、force_reusable_array、readsand fingerprint must be retained.prepare-validated-pagemust write this contract into the computation capsule; it must not abbreviate the platform-confirmed"A股市盈率(PE, TTM)〔估值数据〕"/"A股净资产收益率ROE"intoPE(TTM)/ROEand then hand it to QBV, nor merge multiple verified formulas into one new formula. If the explicit contract and the Receipt are inconsistent, the fingerprints are inconsistent, or the output left-hand side is incomplete, it must fail closed and must not guess at a fix. When preparing the handoff JSON, if the Receipt already contains the original formula, do not manually copy a second copy invalidated_roles[].formulaand do not repeat the same Receipt under every role; prefer passing the Receipt object once at the top levelvalidation_receipts, or pass a Receipt file path string, and you may also letprepare-validated-pageautomatically discover alldata_idfor the same task, avoiding quotation-escape failures and invalid retries.
Boundaries of personal data and execution capability: before personal holdings, costs, shares, and transaction records enter a persistent live page, state that the current live page is publicly accessible via link; when collecting the necessary parameters, also confirm whether public disclosure of this information is permitted. A request to "record holdings" does not equal consent to disclose; when public disclosure has already been explicitly authorized, do not confirm again, and ordinary public market-data queries are not subject to this restriction. Do not promise unverified private access. Fetching data when a page is opened/refreshed does not equal scheduled daily execution, proactive notification, or automated trading; only after the host has the corresponding capability and it has actually been created successfully may enabled status be promised. See capability and personal data boundaries。
Hard gate at the top of the Fast Path / Leaf workflow (takes effect every time a leaf is entered)
Fix the issue where leaves such as T-001 / T-011 / T-024 do not treat
newSessionas the first mandatory step and skip directly to calling platform tools.
Regardless of how routing enters fast-snapshot / fast-window / fast-report-period / render-kline / any leaf workflow:
- When the current Skill Session has not yet been established, before calling any platform-native tool, you must first call
newSession;newSessionand also register the first Turn of this Session. - When the same Session receives a new user message (including follow-ups), you must first call
beginTurn, and theuser_queryin the parameters must be this round's original wording; when calling multiple tools consecutively within the same Turn, reuse the current context and do not repeatbeginTurn。- When a normal Agent calls
newSession/beginTurn, it must simultaneously generate the optionalagent_intent: use brief text to clearly state the object, action, constraints, and expected output to be addressed in this round; 20–160 characters is recommended. References in follow-ups such as "what about it / compared with the previous one / continue" must be expanded using the existing context, but must not overwrite the user's original wording. agent_intentExample: first question分析贵州茅台的盈利质量、估值水平与主要风险。; follow-up "What about compared with Wuliangye?" →延续上一轮贵州茅台分析,对比五粮液的盈利能力、估值水平与主要风险。; For constrained questions such as "only the last three years, make it into a table" →整理目标公司近三年的核心指标并输出单表对比,不扩展到其他期间。- Do not directly copy
user_queryto serve as Intent; do not record Chain of Thought, internal reasoning steps, or conclusions that have not undergone data analysis. Old clients, automated tests, and bypasses that cannot generate an Intent are allowed to omit it, and the server handles it asnullwithout blocking business.
- When a normal Agent calls
- Only when a genuinely new independent Skill Session is started should it be re-
newSession. It is not allowed to skip the firstnewSessionby using "already read SKILL.md / leaf workflow", nor to replace the follow-up question'snewSessionwith a repeatedbeginTurn。- The single version check of the new
newSessionmay also return an optional companion (currentlyquant-buddy-view): when QBS itself needs to be upgraded, only QBS must be upgraded first and reloaded; only when QBS is already up to date may the current Agent's companion registration be installed, updated, or completed. A companion failure is a bypass error and must not block the current QBS data business; as long as it returnsreload_required=true, the final reply must explicitly prompt the user to reload the Agent, and it is forbidden to ignore this prompt and then claim that the live-page capability has taken effect in the current session. - It is recommended that in
newSessionalso passagent_model: fill in the current Agent's real model identifier (for examplegpt-4o/claude-sonnet-4/gemini-2.5-pro); if unsure, leave it empty, and guessing is forbidden.
- The single version check of the new
- Calling platform tools directly without establishing a Session will still return
MISSING_NEW_SESSION. If the new question does not firstbeginTurn, or an explicitturn_id/user_querydrifts from the current Turn, the client must cancel the unsafe Turn association, retain the realuser_queryof this round, and continue with business tools; only output tracking diagnostics, and it is forbidden to stop answering the user because of a Turn recording failure, and also forbidden to attach the call error to other Sessions.
Minimal sufficiency principle (self-check before any action)
By default take the narrowest path; only after receiving evidence of "clearly insufficient" may the scope be expanded.
Before each preparation to read a file, call a tool, or expand the reading scope, answer three questions:
- What specific problem does this step solve? — It must be expressible in one sentence as "in order to do X, therefore do Y", where X is arequirement that has already occurred, and cannot be "may need X", "just in case", or "prepare it first".
- Is there a narrower option that can accomplish the same X? — A more downstream output / a more concise file / fewer fields / constructing it directly without calling this tool.
- If the current choice fails, what is the next step? — If you cannot answer, it means you have not thought it through before acting.
If any answer is vague → do not do this step.
The only legitimate trigger for expanding scope: The previous tool step explicitly returned "missing data / field does not exist / failure", and the failure reason can be traced. It is not allowed to use "for more comprehensiveness", "for more accuracy", or "to avoid omissions" as a reason.
This principle covers: whether to read one more document; which variable readData should read; whether to call confirmDataMulti for a certain field; whether to write a formula yourself or look up an existing dataset; and all similar decisions that arise in the future.
Implementation at the tool level: Before calling confirmDataMulti / readData / runMultiFormulaBatchStream or loading additional documents, you must mentally complete the tool checklist self-check;do not search, load, or read recipes/tool-call-checklist.md. Regardless of whether the file is already in context, just complete the following three minimal self-checks in your head (these three are already a condensed version of the checklist; there is no need to consult the original text):
- Does this call directly serve the user's current question?
- Is there a narrower output or fewer fields that can be read?
- If the call fails, is the next step clear and does it change only one dimension?
Top-level principles govern \"whether to do it\"; the checklist governs \"specifically how to do it\".
Skill package root directory
The directory where this SKILL.md is located is the skill root directory (SKILL_ROOT), and all relative paths below are based on this. Script paths are based on the actual location of the Skill that has been read in this round: if the document comes from /work/<本会话>/project/.claude/skills/quant-buddy-skill/SKILL.md, you can directly use the full absolute path of scripts/call.py in the same directory; do not guess the session ID. Only use python3 scripts/call.py ...when cwd is already the Skill root directory; when cwd is the project root directory, do not copy that relative path. Do not use the .claude/skills/... relative prefix, and do not use the /opt/... installation directory as a substitute for the session copy. After a path is rejected, correct it only once based on the confirmed working directory; do not repeatedly try permutations of /opt、.claude/skills、cd , and do not probe or relax permissions.
When the host has fixed the command working directory (cwd) as this Skill root directory,do not execute cdagain; directly run using relative paths; only in a manual terminal or when the host has not set cwd, switch to this directory first.
SKILL_ROOT/
├── config.json ← API Key 配置(按需读取;非每题必读)
├── SKILL.md ← 本文件(入口 + 路由)
│
├── workflows/ ← 业务流程编排(路由目标)
│ ├── fast-snapshot.md Fast Path:最新时点行情/估值(≤1000资产,标量/CSV)
│ ├── fast-window.md Fast Path:最近N日序列/窗口统计(≤2500日)
│ ├── fast-report-period.md Fast Path:最近报告期财务(≤1000资产)
│ ├── quick-lookup.md 快速查数路由器 + 共享基础规则
│ ├── quick-snapshot.md 最新时点行情/估值快照(字段齐即停)
│ ├── quick-window.md 最近N日短窗序列/窗口统计
│ ├── quick-report-period.md 最近报告期财务指标
│ ├── period-return-compare.md 固定区间累计涨跌幅对比
│ ├── stock-profile.md 单股预计算指标画像
│ ├── external-fact-verification.md 上市/退市/更名/换代码及知识冲突核验
│ ├── composition-select.md 已物化维度组合选股(selectByComposition 快路径)
│ ├── global-rules-lite.md 精简全局规则(quick-window/period-return-compare 专用)
│ ├── quant-standard.md 选股/回测/因子/图表标准流程
│ ├── live-page-routing.md QBS→QBV 非阻塞活页路由、Handoff 与 Job 合同
│ ├── visual-page-fast-path.md 单资产标准历史字段同图的取数复用快路径
│ ├── event-study.md 事件研究(给定或可识别事件后的窗口表现)
│ ├── regime-segmentation.md 阈值区间/连续阶段识别与区间统计
│ └── render-kline.md K线图渲染与交付
│
├── recipes/ ← 公式模板 & 工具用法(被 workflow 引用)
│ ├── ma-crossover-backtest.md 均线金叉策略
│ ├── value-pe-strategy.md PE估值选股
│ ├── upload-custom-data.md 上传自有数据
│ ├── render-chart.md 渲染图表
│ ├── download-data.md 下载数据
│ └── industry-aggregation.md 行业聚合排名
│
├── references/ ← 参考文档
│ ├── environment.md 环境依赖
│ ├── troubleshooting.md 故障排查
│ └── ru-billing.md RU 计费
│
├── tools/ ← API 工具完整参数文档(默认不读;workflow 标注「必读」或报错时再查)
│ │ ⚠️ 下表列出所有可用工具的**实际调用名**,调用时必须使用此名,不得变体
│ ├── fast_query.md → 工具名 `fast_query` 快速合并查询(行情/估值/财务,≤1000资产,支持CSV)
│ ├── fast_query_minute_range.md → 历史单资产跨日1分钟CSV全列(日期/自然日offset)
│ ├── fast_query_minute.md → 工具名 `fast_query_minute` 单资产当前盘中/最近完整日分钟 OHLCVA 序列
│ ├── confirm_data_multi.md → 工具名 `confirmDataMulti` 批量确认数据项存在性与维度(写公式前必查)
│ ├── run_multi_formula.md → 工具名 `runMultiFormulaBatchStream` 执行公式批次(选股/回测/因子计算)
│ ├── read_data.md → 工具名 `readData` 读取公式计算结果(需传 data_id,非 expression_id)
│ ├── render_kline.md → 工具名 `renderKLine` 渲染 K 线图(直接传 ticker,无需提前跑公式)
│ ├── stock_profile.md → 工具名 `stockProfile` 单股预计算指标画像(估值/财务/资金/波动/走势)
│ ├── select_by_composition.md → 工具名 `selectByComposition` 已物化维度组合选股/筛选(不走公式引擎)
│ ├── dimension_indicators.md → 工具名 `listDimensionIndicators` 按维度列出指标目录(细分+综合)
│ │ → 工具名 `getIndicatorFormulas` 按指标名取该指标的完整公式组
│ │ ⚠️ 二者非平台原生工具,走 `python scripts/call.py <工具名>`(硬规则 #2 许可路径)
│ ├── render_chart.md → 工具名 `renderChart` 渲染折线/柱状/面积图(需先有 data_id)
│ ├── get_card_formulas.md → 工具名 `getCardFormulas` 按卡片名拉取完整公式组(量化场景使用)
│ ├── scan_dimensions.md → 工具名 `scanDimensions` 九维度 IC 扫描(单股多维度预测力分析)
│ ├── search_similar_cases.md → 工具名 `searchSimilarCases` 向量检索相似案例(设计策略前的 fallback 查找)
│ ├── search_functions.md → 工具名 `searchFunctions` 检索平台函数名称与调用格式
│ ├── download_data.md → 工具名 `downloadData` 按 data_id 下载一维时序到 CSV/JSON
│ ├── upload_data.md → 工具名 `uploadData` 上传自有因子 CSV,上传后可在公式中引用
│ ├── refresh_snapshot_time.md → 工具名 `refreshSnapshotTime` 强制刷新分钟数据截止时间(盘中实时场景)
│ ├── resume_job.md → 工具名 `resumeJob` 续传 deferred 后台任务(配合 research_24h 使用)
│ └── formula_package.md → 脚本 `scripts/formula_package.py` 注册公式组为「任务包」→ 凭 package_id+signature 无 key 取数(对外只读/前端页面接入)
│
├── presets/ ← 已验证的常用数据(按需加载)
│ ├── cases_index.yaml 106 张案例卡片目录(量化标准场景必读,快速查数无需)
│ ├── assets.yaml 常用资产(99 行精选,可一次读完)
│ ├── assets_db/ 全量资产字典(按类型分文件,⚠️ 仅 grep 检索,禁止 read_file 整文件;不含指数成分股映射)
│ │ ├── stock_a.yaml A 股 5316 条(SH/SZ,含场内 ETF)
│ │ ├── stock_hk.yaml 港股 2858 条(HK 前缀;行情优先,财务以 fast_query 返回为准)
│ │ ├── stock_us.yaml 美股及境外ETF 1069 条(.N/.O/.A/.BAT;行情优先,财务以 fast_query 返回为准)
│ │ ├── index.yaml 指数 513 条
│ │ └── future.yaml 期货 239 条
│ ├── functions.yaml 常用函数(170 条)
│ ├── data_catalog.yaml 常用精选数据集(高频 index_title)
│ ├── index_info_catalog/ 系统支持数据名全量索引(2566 条,按业务分类分 YAML,grep 检索)
│ ├── dimensions.yaml 已物化指标候选的本地快照,用于 selectByComposition 的常见快速映射
│ │ ⚠️ 细分指标、快照未命中项和实时可选状态,用 `listDimensionIndicators` 在线确认;公式口径用 `getIndicatorFormulas`
│ ├── sectors.yaml 行业板块(742 条,10 个分类)
│ └── themes.yaml 题材板块
│
├── scripts/ ← 执行脚本
│ ├── call.py 工具统一入口(所有命令通过它调用)
│ ├── executor.py call.py 的底层(禁止直接调用)
│ ├── formula_package.py 公式任务包客户端(register/query/list/revoke/refresh,取数走 SSE)
│ ├── quant_api.py Python SDK(供其他脚本 import)
│ ├── auth/ 认证脚本
│ └── eval/ 评测脚本
│
└── output/ ← 输出目录(自动创建)
├── .session.<key>.json 当前 session task_id(按 QBS_SESSION_KEY 派生,多会话隔离)
├── ic_data/ IC 扫描结果
└── *.png / *.csv 图表和数据文件
Global 429 handling (applicable to all paths):
| error.code | Handling |
|---|---|
RATE_LIMIT_EXCEEDED / CONCURRENT_LIMIT |
Read retryAfter seconds and thenretry silently, without exposing it to the user |
WINDOW_QUOTA_EXCEEDED |
stop immediately, read the references/troubleshooting.md quota throttling section, and output a prompt |
DAILY_QUOTA_EXCEEDED / DAILY_SCAN_EXCEEDED |
stop immediately, output:⚠️ 今日额度已满,次日 00:00 重置。 |
SERVICE_OVERLOADED(503) |
retryAfter retry silently once after seconds; if it still fails, inform the user \"the system is busy, please try again later\" |
⛔ Execution order (required reading before routing; must be followed in all scenarios)
For converting existing files to loose-leaf, first execute the static hosting priority exception above and do not enter the QBS leaf in the table below; data enhancement after the first static delivery is loaded according to the query rules in this section.
No matter which leaf workflow is matched, the execution order is fixed as follows:
① read_skill_file(global-rules 版本,见下表) → ② read_skill_file(leaf workflow) → ③ 执行
Step ① Global rule file selection (determined by the target leaf workflow):
| Target leaf workflow | File read in Step ① |
|---|---|
fast-snapshot.md |
None (Fast Path, skip Step ①, execute directly) |
fast-window.md |
None (Fast Path, skip Step ①, execute directly) |
fast-report-period.md |
None (Fast Path, skip Step ①, execute directly) |
quick-window.md |
workflows/global-rules-lite.md |
period-return-compare.md |
workflows/global-rules-lite.md |
| All other workflows | workflows/global-rules.md |
- Step ① is a hard prerequisite. After determining the target leaf, first select and read the corresponding global-rules version according to the table above, then read the leaf workflow, and finally execute.
- Fast Path (fast-*.md) starts directly from Step ② and does not require Step ①.
Scenario routing
First identify the user's intent and determine the target leaf workflow; then load according to the execution order above:
| Scenario | Trigger words | Target leaf workflow |
|---|---|---|
| Single-asset historical/cross-day minute | The user explicitly provides the original 1-minute/intraday CSV for a historical trading day or a cross-day interval | Confirm the unique asset → tools/fast_query_minute_range.md → fast_query_minute_range; do not pass fields/format/remove_nan |
| single-asset intraday minute / time-series sequence | explicitly request minute, time-series, 1-minute, per-minute, intraday OHLCV, minute-by-minute open/high/low/close/volume; excluding historical dates, ranges, or multiple assets | first confirm the unique asset according to asset library rules → directly call fast_query_minute → stop on success |
| latest point-in-time quotes / valuation / basic information (snapshot) | latest price, today's close, latest change percentage, current turnover rate, latest PE/PB/market cap, industry... | Fast Path conditions satisfied → only read fast-snapshot.md; not satisfied/unable to query → global-rules.md → quick-snapshot.md |
| recent N-day series / window statistics | last 5 days, last 20 days, last N trading days, window high/low/amplitude... (single asset only, last N days) | Fast Path conditions satisfied → only read fast-window.md; not satisfied/unable to query → global-rules-lite.md → quick-window.md |
| most recent reporting period financials | revenue, net profit, net profit attributable to parent, ROE, total assets, total liabilities, debt-to-asset ratio... | Fast Path conditions satisfied → only read fast-report-period.md; not satisfied/unable to query → global-rules.md → quick-report-period.md |
| single A-share quick profile | Kweichow Moutai, Moutai, 600519, SH600519; or simple comprehensive analyses such as "analyze Kweichow Moutai" "analyze Shenzhen Xinxing (SH:603978)", where the asset is unique and the name and code match | live-page-routing.md → single_a_stock_fast → QBV guides/answer-first.md, answer first then new_asset_page |
| single-stock indicator profile / individual stock comprehensive analysis | analyze stock XX, take a look at stock XX, stock profile, indicator overview, comprehensive look at valuation financials capital trends, how are the fundamentals and valuation... | global-rules.md → stock-profile.md |
| latest listing/delisting/renaming/code change or asset status conflict | is it currently listed, latest code, whether delisted; or local asset library hit but platform returns ASSET_NOT_FOUND |
global-rules.md → external-fact-verification.md; external facts and Quant Buddy data status must be judged separately |
| single-asset standard historical fields in the same chart | one asset + 2–4 standard historical fields of price/volume/valuation + "put in one chart / draw as a chart / compare in the same chart" | only read visual-page-fast-path.md; route first, then one fast_query, one command to prepare capsule + Handoff + Job; forbidden to enter quant-standard.md、render-kline.md and static rendering |
| SW Level 1 industry recent N-day change ranking chart | SW Level 1 industry/industry sector + last N days/last month + change percentage + ranking chart/bar chart/visualization | only read industry-ranking-fast.md; one fixed industry aggregation formula, only read indexinfo_id, directly prepare the materialized QBV Job; forbidden to enter global-rules.md、quant-standard.md, industry recipe, and renderChart |
| K-line live page (continuously openable) | explicitly contains K-line/K line/candlestick/OHLC/open high low close, and does not explicitly ask for only an image | only read kline-page-fast-path.md;QBS fast_query(window) after verifying OHLCV answer first, then hand over to QBV's candlestick runtime panel; forbidden to call image-type renderKLine |
| K-line image (explicitly only wants PNG/image) | user explicitly does not want a webpage, only wants an image artifact | global-rules.md → render-kline.md; only at this point is it allowed renderKLine |
| fixed-period cumulative change percentage | From A to B, from a certain year and month to a certain year and month, interval return, cumulative change, interval performance, multi-asset interval comparison | global-rules-lite.md → period-return-compare.md |
| Data download / export local CSV | Download as CSV, export to local, save to local, download historical data | global-rules.md → recipes/download-data.md; single-asset single-field time series takes priority runMultiFormulaBatchStream → downloadData → write_skill_file, Bash fallback prohibited |
| Stock selection by materialized indicators / dimension scores or sub-indicator TopN / recommended stocks | Highest score, highest composite score, dimension score, or recommendation/selection/screening TopN composed of materialized sub-score/screen indicators | global-rules.md → composition-select.md(newSession → local snapshot matching or online directory confirmation → selectByComposition) |
| High-frequency stable factor ranking: low PE + high ROE TopN | Low PE/low price-to-earnings ratio, high ROE/high return on equity, stock selection/screening/ranking, and TopN/top N appear at the same time; even if charts or workbooks are not mentioned | global-rules.md → quant-standard.md 's "high-frequency default caliber"; after validating TopN, route must actually be executed,create use three materialized data_id in one prepare-validated-page, QBS answers first, QBV supplements the link in the same round after completion; if web pages are explicitly not wanted then none, if only a table is wanted and there is no other page-creation intent, also keep none |
| Dimension indicator library query / indicator caliber and formula | What dimensions does the platform have, what indicators are under dimension XX, how is indicator XX calculated/what is its caliber/what is its formula, want to modify the caliber based on an existing indicator | tools/dimension_indicators.md(use scripts/call.py to call listDimensionIndicators → getIndicatorFormulas, not a platform-native tool; to run numbers with a modified formula, then switch to quant-standard.md) |
| Quantitative stock selection / backtesting / factors / charts / upload and download | Stock selection, backtesting, moving averages, PE stock selection, factors, net value, uploading CSV, downloading data, drawing charts, putting multiple indicators into the same chart...; or when the directory has no matching dimension and indicators/historical curves/custom formulas need to be constructed temporarily | global-rules.md → quant-standard.md; to execute backtests, monitoring, line drawing, or any chart artifact, before the first answer it is mandatory to actually run live_page_routing.py route, after hitting create non-blockingly hand off to QBV |
| Directly run the formula chain file specified by the user | "Run/run through/execute all formulas in this file", "formula chain file", "formula chain", "run according to this md/json" | global-rules.md → run-formula-chain.md |
| Event study | Review, past occurrences, price increases, rate cuts, rate hikes, event window, subsequent performance, above expectations, below expectations, post-policy performance... (given event or event date needs to be identified first) | global-rules.md → event-study.md |
| Threshold interval statistics / continuous phases | Past occurrences, each time, average, drawdown exceeding, decline from high exceeding, bear market interval, continuous phases, regime | global-rules.md → regime-segmentation.md |
| Daily review / continuous monitoring / watch industry stocks every day | Daily or periodic review, watch every day, monitoring/market watching, refreshing the dashboard, making a page that can be opened directly | global-rules.md → quant-standard.md → answer-first.md; first perform native query and complete business first answer, then hand off to QBV; do not enter the old process of registering the package first |
| Explicitly develop interfaces / manage formula task packages | The user explicitly requests registering a formula package, package_id, signed data retrieval, external read-only interface, or third-party interface integration | tools/formula_package.md + recipes/formula-package.md; only interface management requests, ordinary research dashboards follow the previous line; before registration, formulas and runtime frequency must still be verified |
Uploading, downloading, and charting are not independent scenarios—they are sub-steps within a workflow, and the workflow documentation will guide you to read the corresponding
recipes/。
Routing hard exclusions (take precedence over trigger word matching)
The following rules are checkedbeforetrigger word matching; if matched, they forcibly reroute and cannot be overridden by trigger words:
| User intent characteristics | Prohibited entry | Forced routing | Basis for judgment |
|---|---|---|---|
| Intraday/real-time/current/now/today/today's/on that day + query intraday market conditions (gain ranking, limit-up, intraday decline, etc.) | quick-snapshot quick-window |
quant-standard.md(preferentially match minute-frequency cards) |
requires dedicated formulas for minute-frequency cards;use_minute_data: true is already the global default |
| Intraday/real-time/current/today/today's/on that day + whole market/sector + TopN/ranking/threshold list/stock selection/screening/signal | quick-snapshot quick-window |
quant-standard.md → preferentially match the "real-time cross-sectional TopN ranking" or "intraday threshold screening_list query" micro-workflow |
These high-frequency short questions have dedicated closed micro-workflows |
| Give explicit start and end dates, and ask only about cumulative interval return/performance | event-study quick-window quant-standard |
period-return-compare.md |
This is essentially fixed-interval return comparison, not causal window analysis, nor a complex quantitative workflow |
| Industry/sector aggregate ranking (e.g., "top 5 SW industry gainers") | quick-window quick-snapshot |
quant-standard.md |
requires cross-sectional aggregation, not a single-asset series |
| Threshold-triggered discrete event identification (e.g., "number of times the decline exceeded X%", asking about performance after each occurrence) | — | event-study.md(threshold-trigger mode) |
Need to first identify threshold event days, then perform window analysis |
| Define continuous intervals by threshold conditions (e.g., "past bear markets", "stages with drawdown over 30%") | event-study |
regime-segmentation.md |
The study is on continuous stages rather than windows after discrete events |
| "hitting a new N-day high/low" (excluding the modifier "first") | must not add the condition "not satisfied yesterday" | Judge bycurrent state, and the formula only compares the current value with yesterday's N-day extreme | Only when the user explicitly says "first breakout/first breakdown", "newly entered", or "today's first time" is it allowed to add the first-trigger condition; see quant-standard.md |
Judgment mnemonic:
- Has explicit start and end dates + asks only about interval values →
period-return-compare(fixed-interval return comparison) - Has an event + asks about "performance in the following N days/months" →
event-study(causal window) - Has threshold conditions + asks about "performance after each occurrence" →
event-study(threshold-trigger mode) - Has threshold conditions + asks about "performance within continuous stages/intervals" →
regime-segmentation(continuous-stage statistics)
If the user's request satisfies any of the following modes, it should first be determined as a 【quick data lookup task】 and routed directly according to the following routing, without first entering other workflows:
Fast Path conditions (must satisfy both of the following to use Fast Path; otherwise use the full chain):
- All target fields belong to the fast_query whitelist (price/valuation/financials/derivatives/fund flows · northbound-southbound holdings/commodity spot · inventory, as well as basic information fields for the industry a China A-share belongs to; see
tools/fast_query.md), and do not involve custom formulas/stock selection/ranking - Non-whole-market cross-sectional query (not scenarios such as "whole-market ranking/top N/industry screening")
Asset count no longer limits Fast Path routing (the server supports ≤1000 assets). When there are more than 500 data points, the server automatically returns CSV format (an OSS download link). See
tools/fast_query.mdthe rate limiting and CSV mode section.
Fast data query routing (judged in order of priority, stopping at the first match):
-
The user explicitly requests2–4 standard historical fields of one asset placed in the same chart, and does not explicitly ask for only PNG → read only
workflows/visual-page-fast-path.md; this is the page's main-chart fast path, and you must not continue readingquant-standard.md/render-kline.md. 0a. The user explicitly requestsa chart/bar chart/visualization of the recent N trading days' price change ranking for SW Level 1 industries, and does not explicitly ask for only PNG → read onlyworkflows/industry-ranking-fast.md; do not readglobal-rules.md、quant-standard.mdor the industry recipe, and do not callrenderChart。 Minute coverage pre-check: first confirm the market/asset type and judge according to minute support range . A-shares/US stocks start from 2026-05-13, domestic futures start from 2005-01-04, Hong Kong stocks start from 2026-05-20, and domestic indices start from 2026-08-13; US/Hong Kong indices and futures are not currently supported. If the historical window is earlier than the boundary, you must first warn: do not query if the entire window is out of bounds; if partially covered, clearly state the missing range, and do not silently change the date or claim complete coverage. This restriction does not apply to daily-frequency quotes. -
The user explicitly wants a single-asset historical/cross-day minute series or minute CSV →
tools/fast_query_minute_range.md; only historical dates are supported, and all columns are returned completely; the window and offset are mutually exclusive, and you must not stealthily switch to daily frequency or intraday minutes. When the user requests 30-minute K-lines, first fetch the raw 1-minute data, then generate derived 30-minute data according to the controlled aggregation steps in that tool's documentation, while preserving the original interval, timezone, and source interval. -
The user explicitly wantssingle-asseta complete minute/intraday/per-minute series or minute OHLCVA, and has not specified a historical date, date range, minute aggregation, or multiple assets → first confirm the unique asset according to the asset library rules, and call
fast_query_minute; for the index-paired return ofdates[]andfields.<name>[], preserve thedata_scope/trade_date/timezonesemantics, and stop on success. If only the latest scalar is asked, still use snapshot; for historical/range queries, switch to fast_query_minute_range; multiple assets cannot be stuffed into any single-asset tool. For continuous futures, interpret contract_info only according to the selected trade_date, and do not describe inferred as having been verified in real time; attached warnings do not affect successful quotes. -
When the entire sentence is an asset name/abbreviation/code, or a simple single-stock comprehensive analysis (e.g., “analyze Kweichow Moutai”), first execute
live_page_routing.py route; if it hitssingle_a_stock_fast, read QBVguides/answer-first.md, and after QBS verifies the first answer, in the same roundnew_asset_page, and you must not end after only outputting the profile. For other open-ended single-stock comprehensive indicator overviews (e.g., “analyze stock XX”, “stock profile”, “indicator overview”), and when it is not asking only about a single field/a specific window/IC predictive power →workflows/global-rules.md→workflows/stock-profile.md -
The time anchor is a "recent N-day window/series", or the user explicitly gives start and end dates and requests a range series (e.g., "the daily ... trend/series/data from date X to date Y"), or the user only says "recent trend/view the trend" but does not explicitly ask for an image/K-line → when Fast Path conditions are met, read
workflows/fast-window.md, otherwiseworkflows/global-rules-lite.md→workflows/quick-window.md; if N is not given, default to the most recent 20 trading days -
The time anchor is the "latest reporting period" and the fields are financial-type → when the Fast Path condition is met, read
workflows/fast-report-period.md, otherwiseworkflows/global-rules.md→workflows/quick-report-period.md -
The user explicitly asks for "K-line / candlestick chart / OHLC / open-high-low-close": when there is a live-page intent, load
workflows/kline-page-fast-path.md; only when it is explicitly clear that only a PNG/image is wanted, loadworkflows/render-kline.md -
The rest (explicitly the market quotes/valuation/multi-asset comparison for the most recently completed trading day or the current day, andnot containing ranking/screening/whole-market semantics) → when the Fast Path condition is met, read
workflows/fast-snapshot.md, otherwiseworkflows/global-rules.md→workflows/quick-snapshot.mdNote: contains "today/current day/the day/current/now/real-time/intraday" but only queries a single asset's quote fields, which belongs to the intraday refresh scenario,
fast_query snapshotintraday refresh has been automatically enabled (equivalent touse_minute_data: true), and the Fast Path should be used directly; the "routing hard exclusions" above already intercept "today + whole market/sector + ranking/screening", so there is no need to repeat the exclusion here.
The above routing does not require reading
workflows/quick-lookup.md。
Quick reference of key red lines (must be followed even if global-rules.md has not been read)
The following 4 rules are excerpted from global-rules.md,have the highest priority, and apply to all scenarios:
- Event definition is frozen: the event type/scope mustmatch the user's original wording verbatim. If the user says "annual report/interim report", only query the annual report and interim report, and do not expand to earnings forecasts/express reports/quarterly reports; if the user says "State Council or Ministry of Housing and Urban-Rural Development", only include that level, and do not expand to the central bank/CBIRC/local government. If it is believed that the user's definition may have omissions, at the end of the answersuggestexpanding it, and do not expand it on your own.
- evidence-only answer: the final answer outputs only the values, dates, rankings, and methodology explanations directly supported by the tool results of this round. Without tool verification, it is forbidden to output by default macroeconomic attribution, policy attribution, or directional judgments ("usually", "often", "somewhat positive").
- De-processualized delivery: process-oriented phrasing such as "successfully obtained", "let me", "according to the process", "Step 1/2/3", and "according to the workflow" is forbidden; leaking
_working/paths, checkpoint names, and workflow file names is forbidden. Answer as soon as it is found, and do not show the internal process. - Conditional methodology is frozen: user conditions must be executed as-is, and any rewriting is forbidden (percentages ↔ decimals, relative time → year range, asset universe replacement, card additional condition inheritance). See hard rule No. 8 for details.
- Timeliness fact verification: when it involves the latest listing/delisting/renaming/code change, or the local asset library has a hit but the platform returns
ASSET_NOT_FOUND, it is necessary to readexternal-fact-verification.md。ASSET_NOT_FOUNDonly indicates that the current interface does not recognize the asset, and it must not be inferred that the company is not listed.
Trigger word reference:
- analyze XX stock / take a look at this stock XX / stock profile / indicator overview / comprehensive look at valuation, financials, capital flow, and trend →
stock-profile - most recent trading day close / latest disclosed PE / latest market cap (not intraday, not screening) →
quick-snapshot - last 5 days / last 20 trading days / last N-day series / window high and low →
quick-window - revenue / net profit / ROE / total assets / total liabilities / debt-to-asset ratio →
quick-report-period
Forbidden:
- ordinary K-line live pages must not preferentially call
renderKLine; first readkline-page-fast-path.mdand usefast_query(window)obtain OHLCV. Only callrenderKLine - First perform analytical expansion, then supplement structured numerical values
- before reading the corresponding leaf workflowdirectly call
runMultiFormulaBatchStream/renderKLine/scanDimensions/stockProfile/ output "Unable to connect to the internet" or "Unable to retrieve real-time data" - asset has uniquely matched
presets/assets_db/future.yaml, statically output "the platform does not support futures/options" or "futures cannot be queried"; you should first try via the quote/window series toolchain, and after failure, only state according to the tool's return that the current instrument or field is temporarily unavailable - silently inherit the card's additional conditions (first-time/non-ST/limit-up/liquidity threshold, etc.) into the final answer
- using
description、samples, preview rows, or truncated large tables aslist-type questiondirectly conclude with the complete result (you must extract the complete list or explicitly state that it is incomplete)
the leaf workflow's final answer contract takes priority: the "final answer contract" in the leaf workflow is primarily responsible for tightening the output format for that scenario; if the leaf workflow has already met the stopping conditions, you must output directly according to that contract and must not further explain the internal process.
Execution authority authorization rules
Rule hierarchy (from high to low):
- SKILL.md: routing + global gatekeeping (10 hard rules, routing hard exclusions)
- global-rules.md: global contracts that all leaves must follow (execution contract, evidence grading, concise-answer mode, no precision supplementation, method limitation statements, parameter specifications, numerical precision, final-answer consistency check)
- leaf workflow: the specific execution flow for the current task (checkpoints, templates, stopping conditions, formatting)
Conflict resolution:
- specific rules in the leaf workflow (such as readData mode selection (see
tools/read_data.mdscenario table)) take priority over the general rules of global-rules - but the leaf workflow must notrelax the red lines of global-rules (such as the evidence grading threshold and the principle of no precision supplementation)
- must not borrow templates, fallbacks, or answer formats from other leaf workflows
Positioning of quick-lookup.md:
- serves only as the routing entry point and general rules reference table for the quick-lookup sub-flow
- Each leaf workflow already contains all execution rules, and during execution there is no need to return to quick-lookup.md
- quick-lookup.md does not define any leaf-specific rules
Global execution rules
See
workflows/global-rules.mdfor global contracts, which take effect automatically upon entering any leaf workflow. A leaf workflow may add stricter constraints internally, but must not exempt or relax the rules in global-rules.
Platform data coverage
| ✅ Supported | ⚠️ Conditionally supported | ❌ Not supported (and will not be supported in the short term) |
|---|---|---|
| A-share individual stocks (Shanghai/Shenzhen Main Board/ChiNext/STAR Market/Beijing Stock Exchange) | ETF / LOF / off-exchange funds (first grep the local asset library; if uniquely matched, execute normally; only if not matched, state that it is unsupported); futures quotes/window series (first grep presets/assets_db/future.yaml, after a unique match try quote fields according to the tool's return; no commitment to valuation/financials/K-line charts); some U.S. stock options slot contract mapping and contract rollover (query_option_contracts, subject to the actual return) |
complete option chains and options for markets/underlyings not covered |
| Hong Kong stocks (HK + code, e.g. HK0001) | Other overseas markets such as Taiwan / Korea / Japan / Germany stocks | |
| US stocks (NASDAQ: code.N; NYSE: code.O; AMEX: code.A) | ||
| Major broad-based indices (CSI 300, CSI 500, Wind All A, etc.) |
Hong Kong / US stock data scope limitations:
- Market price type(close price, open price, high price, low price, change percentage, trading volume, turnover): supported for A / HK / US.
- Basic information on the industry the stock belongs to: only supported for A-share stocks
所属行业, usefast_query(snapshot/value)asset must betype=stockandmarket_id=1/2. Returns SW Level 1swl1, SW Level 2swl2and concept listjqc; Hong Kong stocks, US stocks, indices and other assets are not yet supported.- Valuation type:
- A/US/HK:
PE/PE_TTM/PB/PS_TTM/股息率/PCF/总市值(daily frequency, the server automatically maps by field; PB does not have TTM)- A shares only:
流通市值/换手率- PE (static): A shares use static PE, HK/US stocks are automatically mapped to the TTM version
- Legacy compatibility entry: HK/US stocks
PE_单季/PB_单季/PS_单季/股息率_单季are actually mapped to daily-frequency valuation, not quarterly data; for new calls usePE_TTM/PB/PS_TTM/股息率- Financial type(operating revenue/net profit/net profit attributable to parent, etc.): supported for A / HK / US (via the
fast_queryinterface);ROE is A shares only。- Fund flow / northbound-southbound holdings type(
fast_querysnapshot/window,Notreport):
- A shares only:
主力资金净额/主力资金净占比、超大单/大单/中单/小单 净额·净占比(main force = extra-large orders + large orders)- A shares only:
北向持股比例(陆股通持股比例)/北向持股市值(quarterly/sparse after 2024-08)- Hong Kong stocks only:
南向持股比例/南向持股市值(daily frequency)- Goes through dynamic parsing (not a whitelist, must use the full name): northbound/southbound "top ten active stocks turnover"
- Not supported: northbound/southbound "fund turnover · volume · net buy" (market-level one-dimensional series, no per-stock dimension) — should go through
confirmDataMulti+readData, rather thanfast_query。- Commodity futures type(
fast_querysnapshot/window, A-share futures varieties only, units by variety):
- Futures quotes
收盘价/开盘价/最高价/最低价: units by variety (silver yuan/kg, rebar yuan/ton, gold yuan/gram…)现货价格(basis, mostly yuan/ton),商品库存/库存按发布日(units by varietyinferred, withSTOCK_UNIT_INFERREDwarning)- Query with the futures ticker (e.g.
RB.SHF);when units diverge by varietyfields_meta[字段].unit_per_asset=true, units sink down to each asset value ({v, unit}), when reading values prioritize the asset inlineunit- When querying Hong Kong/US stocks, if a field is not within the above supported scope, proactively inform the user instead of silently skipping it.
Dimension metric library (dimension / metric / formula, three layers)
Besides the "dataset" (全市场每日收盘价 such raw fields), the platform also maintains a set ofalready computed metric library, which is a different thing, don't mix them up:
维度 dimension ──包含──▶ 指标 indicator ──定义于──▶ 公式组 formulas
17 个(趋势结构、动量与反转、 163 个 每个指标一组,
资金流向、盈利能力、异动监控…) 依赖在前、目标在最后
- dimensionIt is only a grouping container, carries no weight, and is not computable by itself.
- Indicatorsfall into two categories:
细分= single-caliber basic indicators (such as "20-day high approaching breakout");综合= that dimension'sdimension score, aggregated from the sub-indicators within the dimension (such as "A-share momentum and reversal"). There is also an orthogonaloutput_type:scorecontinuous score /screen0-1 boolean. selectByCompositiondoes not use细分/综合as an admission condition: both categories are usable, but must already be materialized, currently selectable, support the target market, and have a known snapshot date. Different valid snapshots may be combined, and the result must be disclosed according todate_alignment; the request position is determined byoutput_type: score is used for ranking/thresholds, screen is used for intersection filtering.- An indicator has two names:
name(20日高点接近突破, the short name in the catalog) andindex_title(通用_20日高点接近突破得分, the variable name in formulas),the two are never the same; plus the stable keyindicator_id, and all three can be used when retrieving formulas.
Which path to take:
| What the user wants | Which path |
|---|---|
| Materialized indicator TopN / screening ("the 10 stocks with the highest A-share momentum and reversal", "short-term highs and lows rising and RSI strong but not overheated") | composition-select.md → locally snapshot-map common indicators; for subdivisions or unmatched items, confirm online output_type、selection_ready、as_of then → selectByComposition |
| What dimensions/indicators exist, the caliber and formula of an indicator, wanting to modify the caliber based on ready-made indicators | tools/dimension_indicators.md → use scripts/call.py to call listDimensionIndicators / getIndicatorFormulas(full online set, including both subdivisions and composites; not a platform-native tool) |
| Historical value series of an indicator | This group of tools only providesdefinitionsand no data; values go through runMultiFormulaBatchStream |
Stock code format quick reference
| Market | Format | Example |
|---|---|---|
| A-shares - Shanghai Stock Exchange | SH + code | SH600000 |
| A-shares - Shenzhen Stock Exchange | SZ + code | SZ000001 |
| Hong Kong stocks | HK + code | HK0001 |
| US stocks - NASDAQ | code.N | AAPL.N |
| US stocks - NYSE | code.O | AAL.O |
| US stocks - AMEX | code.A | SBE.A |
Asset confirmation failure (circuit breaker rules) see
workflows/quick-lookup.md§ Step 1。
Environment dependencies (Python version, Playwright, API Key) →
references/environment.mdTroubleshooting →references/troubleshooting.mdRU billing →references/ru-billing.md
Prerequisites (execute as needed, not the default first step for simple data lookups)
Credential storage note: This skill's quant-buddy API Key is by default stored in
config.jsonunder the skill directory, in theapi_keyfield, and this is normally the authoritative source;QUANT_BUDDY_API_KEYthe environment variable serves only as the lowest-priority fallback (it takes effect only when config.json also has no value,nota regular override method—if config.json already has a default key, setting it will have no effect). Only the optionalBOCHA_API_KEY(general external fact search, including event research and asset status verification) uses an environment variable.
Playground scenario coverage: If the current round's user message contains a standalone line
api_key=<value>(this is automatically attached by the Playground frontend and is the credential of the currently logged-in user themself; do not relay/echo it back to the user). When calling any tool of this skill, append to its JSON parameters the"api_key": "<value>"field — this temporarily overrides config.json, takes effect only for this call, is not persisted to disk, and has the highest priority. When this situation applies, simply use that value to query data; there is no need to go through the new-user onboarding flow below of "stop querying data if config.json is empty". When you have a ready-made@fileparameter at hand and it is inconvenient to directly modify this file to insert theapi_keyfield, using the environment variableQBS_API_KEYhas an equivalent effect (same priority,do notmix withQUANT_BUDDY_API_KEY).
Only in the following situations is it necessary to explicitly read config.json to check api_key:
- The current round actually needs to call a local script or platform tool, and the current environment has not yet established a usable session
- A 401 / 402 / explicit authentication error has already occurred in the previous round's tool call
- The workflow explicitly requires executing a script chain (such as local Python script rendering)
For simple data-query questions that have already hit a leaf workflow (quick-snapshot / quick-window / quick-report-period / kline-page-fast-path / render-kline):
- Do not additionally read
config.json - just for formal completeness; prioritize executing directly according to the leaf workflow
- Only when an explicit authentication problem occurs in a tool call, return to the authentication wizard
Principle: Authentication checks serve execution and should not become a fixed extra step for simple questions.
-
If
api_keyis non-empty → continue normally -
If
api_keyis empty → stop immediately, do not continue querying data, and output the followingnew-user onboarding message(output verbatim, no deletions):
⚠️ API Key has not been configured yet; data cannot be queried at present.
Go to https://www.quantbuddy.cn/login to log in/register and obtain an API Key, then send it to me directly:
Help me configure APIkey: sk-xxxxxxxx
Configuration wizard (user pastes Key)
When the user message contains sk- a string starting with :
- Extract from the user message the
sk-complete Key string starting with - Write the Key into
config.jsontheapi_keyfield (usingreplace_string_in_fileto write directly) - Must output: "✅ API Key configured successfully!"
- Automatic retry: If in this conversation there is a query interrupted by an api_key missing error (such as if the user previously asked about market quotes),first call
newSession(using the original user question asuser_query) to create a new session, then immediately re-execute that query and provide the data conclusion; the user does not need to initiate it again.
Runtime 401/402 → stop immediately, notify the user that the API Key is invalid/expired/quota exhausted, and ask them to go to the official website again to obtain a new Key and reconfigure it.
Tool invocation method
All tools are invoked through scripts/call.py .call.py will both print results to stdout and write them to a temporary file.
Standard invocation (completed in one step)
python scripts/call.py <工具名> '{"key":"value"}'
Retrieve the result directly from stdout. If stdout is truncated, you can read back /tmp/gzq_out.txt。
Parameters can also be passed via environment variables (suitable for scenarios where parameters contain special characters):
GZQ_PARAMS='<JSON>' python scripts/call.py <工具名>
Prohibitions
| Prohibited | Reason |
|---|---|
| Create a custom .py to write the parameter file | The environment variable approach has resolved the encoding issue |
Call directly scripts/executor.py |
call.py encapsulates logic such as renderChart auto-save |
echo Pipe-based parameter passing (Windows) |
GBK encoding truncates Chinese characters |
| Pass JSON via command-line argument (Windows) | PS swallows double quotes |
Division of labor among the three directories presets/, recipes/, tools/
| Directory | What it is | When to read |
|---|---|---|
| presets/ | Local snapshot (YAML) of actual platform return values. Asset names, function formats, dataset index_title, industry/concept names, etc.Can be used directly in formulas, saving confirmation-type API calls.data_catalog.yaml is a commonly used curated selection;index_info_catalog/ is the full index of system-supported data names. |
Before writing a formula, check the preset first; for common market/valuation/financial fields, check data_catalog.yamlfirst; if not found, use rg "关键词" presets/index_info_catalog to search the full catalog. After finding a candidate, the exact index_titlemust be used in the formula; do not use the user's colloquial term directly as a data name.cases_index.yaml is only inquantitative standard scenarios such as stock screening/backtesting/factors/charts(quant-standard.md) required reading at the start; quick data-query scenarios (quick-snapshot/window/report-period) do not need to read it. |
| recipes/ | End-to-end usage examples (Markdown). Demonstrates complete scenarios—from parameter preparation to final output. | Guided to load by the workflow within specific steps (not triggered independently). |
| tools/ | API parameter manual (Markdown). Fields, types, and constraints of each tool. | Not read by default. Consult again when the workflow tool table marks it as "required reading" or when an error occurs. |
In short: presets are data snapshots, recipes are complete tutorials, tools is the parameter dictionary.
data_catalog.yamlonly maintains high-frequency curated fields;index_info_catalog/*.yamlcarries the full set of system data names. For data names that are high-frequency and confirmed as commonly used, manually add them todata_catalog.yaml。index_info_catalog/stores system-supported data names by business category. Formulas use the exactindex_title; do not infer or show internal sources to the user. The catalog is generated by an external repository maintenance process; do not manually modify the records.
Skill update and deployment specification (required reading for LLM)
When the user requests an update to this skill (by sending a zip archive), the following rules must be strictly followed:
Backup location and automatic retention
⚠️ The backup directory is prohibited from being placed under the skills/ directory. The runtime updater writes managed backups to:
<workbuddy-root>/backups/skills/quant-buddy-skill/
Each backup directory is named after the time and the replaced version, and includes backup-metadata.json(containing slug, old version, creation time, and source). The updater migrates old root-directory backups and cleans up history only after the new package validation, atomic replacement, and active directory health check all succeed:Keep at most 3 recognized backups, and only those within 30 days。
--backup-root <dir>The backup root directory can be explicitly specified; it will not be rewritten to the default location.- Cleanup only deletes directories that contain managed metadata and
skill_slug=quant-buddy-skill; unknown manual directories, active directories, lock, staging, trash, and any directories underskills/will not be cleaned up. - Historical
<workbuddy-root>/quant-buddy-skill-backup-*are migrated only after the new version passes the health check and_skillhub_meta.json/_meta.jsonexplicitly writes the same slug; when an update fails, the old backup is never deleted.
Extract and overwrite
# 解压到临时目录再拷贝(避免嵌套)
TMPDIR=$(mktemp -d)
unzip -o <压缩包路径> -d "$TMPDIR"
# 如果解压出嵌套目录 quant-buddy-skill/,取内层
if [ -d "$TMPDIR/quant-buddy-skill" ]; then
cp -rf "$TMPDIR/quant-buddy-skill/"* ~/.openclaw/workspace/skills/quant-buddy-skill/
else
cp -rf "$TMPDIR/"* ~/.openclaw/workspace/skills/quant-buddy-skill/
fi
rm -rf "$TMPDIR"
Post-deployment check
- Confirm that under
~/.openclaw/workspace/skills/there is onlyquant-buddy-skill/one directory related to this skill - Read
SKILL.mdto confirm the version number - Preserve the existing
config.jsoninapi_key(if the user has authenticated before)