Daisy Financial Research
Autonomous stock / company / sector research workflow — plan, gather data, validate numbers, produce a sourced report. Inspired by the virattt/dexter design patterns (iterative agent loop, scratchpad, soft loop limits, numerical validation), packaged as a multi-platform skill.
Dexter’s key ideas:
- Treat financial research as an iterative agent loop, not a one-shot answer.
- First create a compact research plan, then execute data-gathering steps.
- Use a scratchpad as the single source of truth for tool calls, results, assumptions, and partial conclusions.
- Prefer high-level meta-queries to finance data tools, but fall back to specific interfaces when needed.
- Use soft loop limits and repeat-query detection to avoid runaway tool use.
- Validate numerical answers before finalizing.
- For valuation, use an explicit DCF workflow with sensitivity analysis and sanity checks.
- Output concise, sourced analysis with caveats; never present investment advice as certainty.
Python interpreter convention
Command examples in this skill use a bare python. Substitute it with whichever interpreter in the caller's environment has tushare, pandas, and requests installed — for example python3, ~/.hermes/venv/bin/python, ~\.hermes\venv\Scripts\python.exe, a conda env, uv run python, or a pyenv-managed version. The skill does not assume any specific install location and works on macOS, Linux, and Windows.
Agent-native CLI conventions
All scripts under scripts/ follow a uniform agent-native contract so an LLM agent can call them without parsing prose:
- Output format auto-detection. When stdout is not a TTY (e.g. captured by
subprocess.run), scripts emit a single JSON envelope on stdout. When stdout is a TTY, scripts emit the legacy human table. Override with --format json|table.
- Stable success envelope:
{"ok": true, "data": {...}, "meta": {"schema_version", "request_id", "latency_ms"}}.
- Stable error envelope:
{"ok": false, "error": {"code", "message", "retryable", "context"}, "meta": {...}}. Error messages stay on stderr in table mode.
- Schema introspection.
python <this-skill-dir>/scripts/<name>.py --schema returns parameter types, preset registries, upstream interfaces, and error codes as JSON. Agents should prefer --schema over parsing --help.
- Dry-run preview.
--dry-run echoes the request shape (would_call, would_write, filters, search_window) without making upstream API calls or writing files. Available on all mutating scripts.
- Documented exit codes:
0 ok · 1 runtime · 2 auth · 3 validation · 4 no_data · 5 dependency.
- Long-running progress.
screen_hk_connect.py --with-momentum and financial_report.py emit NDJSON progress events on stderr (one JSON per line) so agents can detect liveness during multi-second runs.
- Idempotency. Output files are date-stamped (
YYYYMMDD_* or YYYYMMDD-HHMMSS_*); re-runs are deterministic and overwrite the same path.
Agents calling these scripts should:
- Run
--schema once per script to learn parameters/presets, instead of parsing --help.
- Capture stdout as JSON (auto-detected when piped) and branch on
data.ok.
- Read
error.code (not error.message) to decide retry vs. escalate. retryable: true + a no_data code typically means "loosen filters or extend --lookback-days".
Trigger conditions
Use this skill for:
- “研究一下 / analyze / deep dive” on a stock, company, ETF, index, sector, or market theme
- “DCF / intrinsic value / fair value / undervalued / overvalued / price target”
- Financial statement trend analysis, valuation comparison, earnings/catalyst analysis
- “Compare A vs B” for companies/sectors
- “Why did this stock move?” or “what changed recently?”
- Chinese A-share/HK/ETF queries where Tushare can provide data
- Stock screening / watchlist construction across A-share or Hong Kong markets, including dividend, quality, valuation, growth, momentum, and risk filters
Do not use for:
- Direct buy/sell/order execution
- Personalized portfolio advice without explicit risk/timeline context
- Unverifiable rumors
- Questions that can be answered from stable definitions without external data
Mandatory workflow
Step 0. Update check (notify, don't pull) — first use per conversation
Throttle to one check per 24 hours per installation; never mutate the skill directory without explicit user consent.
If <this-skill-dir>/.last_update exists and is less than 24 hours old, skip this step entirely.
Otherwise, fetch the latest tag from upstream:
git -C <this-skill-dir> ls-remote --tags origin 'v*' 2>/dev/null \
| awk '{print $2}' | sed 's|refs/tags/||' \
| sort -V | tail -1
Compare with this skill's metadata.version from the frontmatter. If the upstream tag is strictly newer (semver), tell the user one line and ask:
"A newer version of this skill is available: vX.Y.Z → vA.B.C. Want me to git pull?"
If they say yes, run git -C <this-skill-dir> pull --ff-only. Refresh .last_update either way so the prompt doesn't repeat for 24 hours.
If upstream is the same or older, refresh .last_update silently and continue.
On any failure (offline, not a git checkout — e.g. ClawHub-installed copy, read-only path, no permission), swallow the error silently and continue with the user's task. Do not mention the failure.
0. State scope and assumptions briefly
Infer obvious defaults instead of asking:
- “recent” = last 60 calendar days / ~40 trading days
- “financial trend” = last 8 quarters or last 5 annual periods when available
- “valuation” = DCF + multiple sanity check
- “A股” = Tushare first; US stocks = web/search or available market APIs first
Ask only if ambiguity changes the analysis materially.
1. Create a research scratchpad
For any non-trivial finance task, keep a local scratchpad file under:
./financial-research/scratchpad/
Use the helper script in this skill when useful:
python <this-skill-dir>/scripts/dexter_scratchpad.py init "original query"
python <this-skill-dir>/scripts/dexter_scratchpad.py add /path/to/file.jsonl tool_result tool_name='tushare.daily' args='...' result='...'
If not using the helper, still preserve internally:
- original query
- plan
- each data source/tool/interface used
- parameters/date ranges
- raw key data and transformed metrics
- errors/empty results/permission issues
- assumptions and interim conclusions
1b. Pull cross-session decision memory (optional but recommended)
The scratchpad is per-task. For learning across sessions and tickers, use the decision-log helper to read past calls before the plan step and to record the new call after the final answer:
# At plan step: pull recent same-ticker analyses + cross-ticker lessons
python <this-skill-dir>/scripts/dexter_memory_log.py context --ticker 600519.SH
# After final answer: record a pending decision
python <this-skill-dir>/scripts/dexter_memory_log.py record \
--ticker 600519.SH --rating Buy --date 20260502 \
--decision "Thesis: PE22, ROE30, dividend stable, demand resilient. Plan: re-check at next earnings."
# Later, when realized returns are known: resolve the pending entry.
# Recommended path — let daisy fetch close prices and benchmark automatically:
python <this-skill-dir>/scripts/dexter_memory_log.py auto-resolve \
--ticker 600519.SH --date 20260502 \
--reflection "Held 17d, raw +4.8% vs CSI300 +3.6%, alpha +1.2%. Dividend+ROE thesis worked."
# Or if you've already computed the numbers yourself:
python <this-skill-dir>/scripts/dexter_memory_log.py resolve \
--ticker 600519.SH --date 20260502 \
--raw-return 4.8 --alpha-return 1.2 --holding-days 17 \
--reflection "..."
auto-resolve is the recommended path. It fetches close[decision_date] and close[as_of_date] for the ticker, walks forward / backward to the nearest trading day, fetches the right benchmark by ticker suffix (CSI 300 for *.SH/SZ/BJ, HSI for *.HK, SPY for US tickers), computes raw + alpha + holding days, then runs the same atomic-rewrite resolve logic as the manual path. For HK names, when Tushare's HK index endpoints aren't available in the user's plan, the helper falls through to AKShare's stock_hk_index_daily_sina for HSI (requires pip install akshare).
Use dexter_memory_log.py compute-returns to inspect the numbers without persisting:
python <this-skill-dir>/scripts/dexter_memory_log.py compute-returns \
--ticker 600519.SH --date 20260415
# → JSON envelope with raw_return_pct / alpha_return_pct / benchmark_return_pct / holding_days
To audit your own track record across many resolved entries, run backtest:
# Auto-derived window covering every resolved entry
python <this-skill-dir>/scripts/dexter_memory_log.py backtest
# Explicit window, Buy ratings only
python <this-skill-dir>/scripts/dexter_memory_log.py backtest \
--from 20260101 --to 20260430 --rating Buy
Returns per-rating count / mean alpha / alpha_hit_rate / alpha_t_stat / annualized_alpha_pct, plus an overall block with the cumulative-alpha drawdown. The metric names make explicit that this is decision-level — daisy logs decisions, not a continuous portfolio NAV, so a textbook Sharpe ratio doesn't apply.
When writing the --reflection text, follow the standard 2–4-sentence shape in references/reflection-prompt.md so lessons stay short enough to be re-injected on future runs.
Storage: a single Markdown file at ./financial-research/memory/decision-log.md. Entries are separated by the HTML comment <!-- ENTRY_END -->. Tag lines start as [YYYY-MM-DD | ticker | rating | pending] and become [YYYY-MM-DD | ticker | rating | +X.X% | +Y.Y% | Nd] on resolve. record is idempotent on (date, ticker) — re-running with the same key skips silently. Ratings are constrained to Buy / Overweight / Hold / Underweight / Sell (see references/decision-schema.md for the full rating vocabulary and report markdown contract). Use dexter_memory_log.py stats for a hit-rate / mean-alpha summary.
2. Plan before tools
Write a 3–7 item plan. Keep it tactical:
- identify company/ticker/universe
- collect price/market data
- collect financials/ratios/estimates/filings/news as relevant
- compute metrics or valuation
- validate numbers and sources
- synthesize concise answer
3. Tool/data routing policy
The canonical per-market routing reference (A-share / HK / US, primary + documented fallback chain for each data type) lives at references/data-source-routing.md. Read it before the plan step; the rest of this section is the agent-facing summary.
For Chinese market / Tushare-accessible data:
- Load/use the
tushare skill if not already loaded.
- Use
TUSHARE_TOKEN from environment.
- Prefer Tushare for: A-share daily prices, stock_basic, daily_basic, income, balancesheet, cashflow, fina_indicator, forecast/express, moneyflow, margin, concept/index/ETF/fund/macro data.
- Use date format
YYYYMMDD and stock code format like 000001.SZ, 600000.SH.
For Hong Kong stocks:
- Use Tushare HK interfaces when available before falling back to web quote sites.
pro.hk_basic(ts_code='00005.HK', ...) and pro.hk_daily(ts_code='00005.HK', start_date='YYYYMMDD', end_date='YYYYMMDD') are known-good for HK tickers such as HSBC 00005.HK.
- For the user's Hong Kong Stock Connect universe (港股通) preference when explicitly requested, use
pro.hk_hold(trade_date='YYYYMMDD') as a first-pass universe identifier. It returns Southbound Stock Connect holdings with fields such as code,trade_date,ts_code,name,vol,ratio,exchange.
- Use the bundled helper to export the latest 港股通 universe:
python <this-skill-dir>/scripts/hk_connect_universe.py --date YYYYMMDD --top 20
- The helper searches backward when the requested date has no data and writes a CSV under
./financial-research/universes/YYYYMMDD_hk-connect-universe.csv.
- For 港股通 flow/capital attention, optionally use
pro.ggt_top10(...), pro.ggt_daily(...), and pro.moneyflow_hsgt(...).
- Do not assume every advertised HK interface works in the installed Tushare version; in this environment
pro.hk_daily_basic(...) returned 请指定正确的接口名, so treat it as unavailable unless re-tested. Fallback: when an HK valuation/fundamentals call fails on Tushare, use the bundled AKShare helper (no Tushare token, no auth):
# PE-TTM / PB / PS / PCF snapshot + Stock Connect eligibility
python <this-skill-dir>/scripts/akshare_hk_valuation.py valuation --ts-code 00005.HK
# Annual or quarterly fundamentals: ROE_YEARLY, EPS_TTM, BPS, ROA, leverage
python <this-skill-dir>/scripts/akshare_hk_valuation.py fundamentals --ts-code 00005.HK --period 年度 --limit 8
# Local-dict-only Chinese name lookup (no API call) — covers ~30 HK majors
python <this-skill-dir>/scripts/akshare_hk_valuation.py name --ts-code 00700.HK
Sources: AKShare stock_hk_valuation_comparison_em + stock_hk_security_profile_em for valuation; stock_financial_hk_analysis_indicator_em for fundamentals. Optional pip install akshare; the helper emits dependency_missing (exit=5) with a clear install hint if the package is absent.
- For banks, DCF is usually the wrong primary valuation frame. Prefer RoTE/ROE, CET1, dividend payout/yield, NIM/NII guidance, credit cost, P/B or P/E, buyback capacity, and analyst target sanity checks.
- Maintain the user's preferred finance-search stack: Tushare for structured market/financial data; Brave MCP as primary web search; Bailian WebSearch MCP as Chinese/China-market supplement; Python for calculations; browser only for dynamic/interactive pages. Do not include Asta/Semantic Scholar as a default route for finance evidence.
- Session detail: see
references/hsbc-hk-bank-research-test-20260429.md for the HSBC test workflow and pitfalls.
For web/current context:
- Prefer Brave MCP search (
brave_web_search / brave_local_search when available) for current news, filings, company pages, market context, source discovery, and broad English/global web coverage.
- Use Bailian WebSearch MCP (
bailian_web_search) as an optional/secondary search channel, especially for Chinese-language queries, China-market news, general encyclopedia-style facts, weather/news/current info, or when Brave results are sparse.
- Cross-check important claims with at least two independent sources when the answer depends on recent news, market rumors, policy, regulation, or company events.
- Use browser only when interaction, dynamic pages, paywall/login behavior, or visual inspection is needed.
- Use terminal Python for calculations and tabulation.
- If a dedicated finance API/tool is unavailable, be explicit about source limits.
Routing heuristics adapted from Dexter:
- Price / market movement / news / insider activity → market data or web search.
- Income statement / balance sheet / cash flow / ratios / estimates → financials.
- SEC filing details → filings/web sources.
- Broad market or macro news → web search.
- Screening by financial criteria → Tushare screening script or Python filtering.
- DCF / fair value → follow the DCF checklist below.
- Revenue breakdown by product / region / segment → A-share has a structured source (
scripts/segments.py → AKShare stock_zygc_em); for HK / US there is no free segment API, so read the annual report's "Segment Information" note via filings / Brave search.
When the user asks "why is the market down today" / "今天大盘为什么跌" / "what's moving the Hang Seng" — no specific ticker — go straight to broad web search (Brave MCP for English / global, Bailian MCP for Chinese-language sources) with a market-wide query like 美股下跌 原因 YYYY-MM-DD or S&P 500 selloff YYYY-MM-DD. Do not pick one large-cap ticker and search its news as a proxy; the intent is macro / sector-rotation / rates / geopolitical catalysts, not a company event.
4. Soft loop limits
Avoid repetitive tool calls:
- Suggested max per tool/interface: 3 attempts per query.
- If a query/interface fails twice, change strategy: different endpoint, broader/narrower date range, web fallback, or explain limitation.
- Do not keep calling the same endpoint with near-identical parameters.
- If data is incomplete, proceed with caveated analysis rather than fabricating.
When the scratchpad helper is active, you can ask it to flag both failure modes before a tool call:
python <this-skill-dir>/scripts/dexter_scratchpad.py can-call \
<scratchpad.jsonl> tushare.daily 'ts_code=600519.SH start=20240101 end=20240630'
# → {allowed: true, warning: null|string, current_count: int, similar_to: [...]}
allowed is always true (this is a soft warning, not a block). React to a non-null warning: if current_count >= max_calls, change endpoint; if similar_to is non-empty, the tool is about to repeat a recent call — adjust the query or skip.
5. Numerical validation checklist
Before final answer, verify:
- Date ranges and units are stated.
- Currency/unit scale is consistent: yuan vs USD, CNY vs HKD, millions/billions.
- Growth rates use comparable periods.
- Per-share metrics use correct shares if computed manually.
- Market cap / EV / price are from a stated date.
- Any ranking/screening has universe and filters stated.
- If data is missing or permission-limited, say so.
6. Final answer format
Use this concise structure:
- Scope/Data: tickers, period, sources/interfaces used.
- Key Findings: 3–6 bullets with numbers.
- Evidence Table: compact table when comparative/numerical.
- Interpretation: what the data suggests, not overclaimed.
- Risks / Missing Data / Caveats.
- If exported: file path.
Always include: “Data analysis only, not investment advice.” when discussing securities.
7. Report export policy
For substantial research tasks, generate a durable report under:
./financial-research/reports/
Preferred report stack:
- Markdown source (
.md) as the canonical editable record.
- HTML report (
.html) as the primary polished output.
- PDF (
.pdf) only when the user asks for a printable/shareable file, or when HTML-to-PDF tooling is available and stable.
Default behavior:
- For quick answers: reply in chat only, optionally with scratchpad path.
- For medium/deep research: create both
.md and .html.
- For formal deliverables: create
.md, .html, and .pdf if possible.
Hermes back-compat note. Hermes installations that want to keep the legacy archive layout (~/.hermes/reports/financial-research/) can pass --out-dir ~/.hermes/reports/financial-research to any script — the script appends the matching subdir (reports/, watchlists/, universes/, scratchpad/) automatically.
Use the bundled report generator:
# medium/deep research: Markdown + HTML
python <this-skill-dir>/scripts/financial_report.py report.md --title "Company Research Report" --slug company-research
# formal deliverable: Markdown + HTML + PDF
python <this-skill-dir>/scripts/financial_report.py report.md --title "Company Research Report" --slug company-research --pdf
The generator copies the Markdown source and renders the report to:
./financial-research/reports/YYYYMMDD-HHMMSS_slug.{md,html,pdf}
Why HTML first:
- Easier to render tables, charts, color-coded risks, source links, and sensitivity matrices.
- More reliable than PDF generation in CLI environments.
- Can be opened directly in a browser and later printed/exported to PDF.
PDF guidance:
- Use PDF for sharing, archiving, printing, or sending to non-technical readers.
- Prefer generating PDF from the HTML report using browser print, Playwright/Chromium, or another available HTML-to-PDF tool.
- If PDF generation fails, keep the HTML and state the limitation rather than blocking the analysis.
Recommended report sections:
Executive summary / investment view.
Company and ticker scope.
Data sources and dates.
Price and valuation snapshot. When the report needs a technical-analysis layer, pick up to 8 complementary indicators from references/technical-indicator-cheatsheet.md and compute them via scripts/technical_indicators.py --ts-code <code> (auto-routes A-share/HK/US, applies a strict look-ahead-bias guard at --as-of). Skip TA entirely for banks / insurers — RoTE / CET1 / NIM are the right frame for those.
Financial performance and key drivers. For A-share names, pulling a revenue-by-segment / 主营构成 breakdown often surfaces concentration risk (one product line / one region) that the headline P&L hides:
# All classifications (按产品 / 按地区 / 按行业), 4 most recent reports
python <this-skill-dir>/scripts/segments.py --ts-code 600519.SH
# Filter to one axis
python <this-skill-dir>/scripts/segments.py --ts-code 000001.SZ --classification 按地区
HK / US names: no free segment API — read the latest annual report's "Segment Information" note (10-K for US, annual report "Operating Segments" section for HK) via the filings tool or Brave search.
News/catalyst review. For A-share / 港股 names, pull China-market context (涨跌停 risk, 北向资金, 板块 rotation, 监管 backdrop) using the system prompt in references/cn-market-analyst-prompts.md.
Bull/base/bear scenarios. For balanced single-company research, run the three-prompt debate template in references/debate-prompts.md (Bull → Bear → Synthesis) instead of writing scenarios free-form. The synthesis output's 5-tier rating maps directly onto dexter_memory_log.py record --rating. For position-sizing follow-up after the directional rating is set, optionally run references/risk-debate-prompts.md (Aggressive → Conservative → Neutral → Portfolio Manager). All synthesis outputs use the markdown shape and rating vocabulary documented in references/decision-schema.md. Either loop can be driven mechanically by scripts/debate_runner.py (subcommands init / next / synthesize, --type research|risk) — the script enforces the rotation rules and exit conditions so the agent only has to write each speaker's argument; full usage in the "Programmatic loop driver" sections of the two prompt files.
Risks and what would change the view.
Evidence tables and calculations.
Disclaimer: data analysis only, not investment advice.
8. Stock screening and watchlist workflow
Use this when the user asks “怎么选股”, “筛一批股票”, “A股/港股有什么值得关注”, or wants a watchlist rather than a single-company report.
Reusable files:
- Presets/reference:
references/stock-screening-presets.md
- Screening report template:
templates/screening_report.md
- A-share screener:
scripts/screen_a_share.py
- Hong Kong Stock Connect screener:
scripts/screen_hk_connect.py (only when 港股通 is explicitly requested)
- Report generator:
scripts/financial_report.py
Common commands:
# A-share dividend/quality watchlist + Markdown report source
python <this-skill-dir>/scripts/screen_a_share.py --preset a_dividend_quality --top 50 --report
# A-share value watchlist
python <this-skill-dir>/scripts/screen_a_share.py --preset a_value --top 50 --report
# 港股通 watchlist only when explicitly requested
python <this-skill-dir>/scripts/screen_hk_connect.py --top 50 --with-momentum
# Turn generated Markdown into the three-layer report stack
python <this-skill-dir>/scripts/financial_report.py report.md --title "Watchlist Report" --slug watchlist --pdf
Watchlist outputs go under:
./financial-research/watchlists/
Do not try to predict winners directly. Build a funnel:
Define universe
- A-share: all listed stocks, index constituents, industry, market-cap band, dividend universe, or user-defined list.
- Hong Kong: HK main board / H-share / Hang Seng indexes / Hong Kong Stock Connect (港股通, when explicitly requested) / user-defined HK tickers.
- Exclude suspended, ST/*ST, newly listed names, illiquid names, or missing-data names unless the user explicitly wants them.
Choose screening style
- Dividend/income: dividend yield, payout sustainability, ROE/ROTE, cash flow, debt, earnings stability.
- Quality compounder: ROE/ROIC, gross/net margin, revenue/profit CAGR, low leverage, stable cash flow.
- Value: low PE/PB/EV metrics, but require profitability and no obvious balance-sheet trap.
- Growth: revenue/profit growth, margin trend, industry tailwind, valuation sanity.
- Turnaround/event: earnings inflection, policy catalyst, restructuring, buyback, sector cycle.
- Momentum: 1/3/6/12-month returns, relative strength, drawdown, volume confirmation.
Apply hard filters first
- Liquidity: daily turnover or volume threshold.
- Size: market cap threshold.
- Financial health: positive earnings or operating cash flow, leverage not extreme.
- Valuation: remove obvious extreme outliers unless justified.
- Data completeness: remove rows with missing critical fields.
Score candidates
- Build 4–6 factor scores rather than one magic metric.
- Suggested default weights: quality 30%, valuation 25%, growth 20%, shareholder return 15%, momentum 10%.
- For bank/insurance stocks, replace generic DCF/gross-margin metrics with ROE/ROTE, CET1/solvency, NIM/NII, credit cost, PB/PE, dividend and buyback capacity.
Produce a shortlist
- Output 10–30 names for broad screens, then 3–8 names for deep-dive priority.
- Include “why selected”, key metrics, red flags, and next verification step.
- Never present the screen as a buy list; call it a research watchlist.
Deep-dive the finalists
- For each finalist, run the single-company research workflow: data, news/catalysts, valuation, risks, scenario view.
- Generate Markdown + HTML reports for substantial screens; add PDF for formal deliverables.
Suggested output tables:
- Universe and filters table.
- Top candidates table with ticker, name, industry, market cap, PE/PB, ROE/ROTE, dividend yield, growth, momentum, score, red flag.
- Priority deep-dive list: top 3–8 names and why they deserve follow-up.
- Exclusion notes: important names removed and why.
Screening caveats:
- Tushare/HK data availability varies by interface and user permissions; document missing fields.
- A cheap stock can be a value trap; require at least one quality or catalyst confirmation.
- A high dividend can be unsafe; check payout ratio, earnings stability, balance sheet and cash flow.
- Momentum screens need risk controls; do not confuse recent price strength with intrinsic value.
DCF valuation workflow
Use when the user asks for intrinsic/fair value, DCF, price target, undervalued/overvalued.
Progress checklist:
Data to gather
- 5 years annual cash flow: operating cash flow, capex, free cash flow
- latest balance sheet: cash, investments, total debt, shares outstanding
- financial metrics: market cap, enterprise value, margins, ROE/ROIC, debt/equity, revenue growth
- analyst estimates if available
- latest price
- sector/industry for WACC sanity
Assumptions
- FCF = operating cash flow - capex if not directly available
- Growth: use 5-year FCF CAGR if stable, haircut by 10–20%; cap sustained base growth at 15% unless justified
- For volatile FCF, triangulate with revenue growth, EPS estimates, and margin trend
- WACC: default 8–10% for mature companies; higher for cyclicals/small caps/high leverage; lower for stable defensives
- Terminal growth: default 2.5%; sensitivity 2.0%, 2.5%, 3.0%
- Years 1–5 growth decay: base growth × 1.00, 0.95, 0.90, 0.85, 0.80
DCF validation
- Terminal value should usually be 50–80% of EV for mature companies; >90% is fragile.
- Calculated EV should be directionally plausible vs market EV; if >30–50% away, explain drivers.
- Cross-check fair value against FCF/share × 15–25 or sector multiple.
- Include a 3×3 sensitivity matrix: WACC base ±1% vs terminal growth 2.0/2.5/3.0%.
A-share quick-start patterns with Tushare
Environment check:
import os, tushare as ts
assert os.getenv('TUSHARE_TOKEN') or ts.get_token(), 'Missing TUSHARE_TOKEN'
pro = ts.pro_api(os.getenv('TUSHARE_TOKEN') or ts.get_token())
Common interfaces:
# Stock list
pro.stock_basic(list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
# Daily price
pro.daily(ts_code='000001.SZ', start_date='20240101', end_date='20241231')
# Daily valuation/market metrics
pro.daily_basic(ts_code='000001.SZ', start_date='20240101', end_date='20241231', fields='ts_code,trade_date,close,pe,pb,total_mv,circ_mv,turnover_rate,volume_ratio')
# Financial indicators
pro.fina_indicator(ts_code='000001.SZ', period='20231231')
# Income / balance sheet / cash flow
pro.income(ts_code='000001.SZ', period='20231231')
pro.balancesheet(ts_code='000001.SZ', period='20231231')
pro.cashflow(ts_code='000001.SZ', period='20231231')
Quality bar
A good Dexter-style answer should be:
- grounded: every important number has a source/interface/date
- multi-step: shows it planned, gathered, computed, validated
- honest: says what is missing or permission-limited
- compact: useful to a finance reader, not a data dump
- reproducible: scratchpad/export path if the analysis used substantial data
1---2name: daisy-financial-research3description: Use when user asks for stock / company / sector deep-dive research, DCF or valuation, financial comparison, market-catalyst analysis, or stock screening across A-share, Hong Kong, or US markets. Plans, gathers data via Tushare and web search, validates numbers, and produces a sourced report.4license: MIT5---67# Daisy Financial Research89Autonomous stock / company / sector research workflow — plan, gather data, validate numbers, produce a sourced report. Inspired by the `virattt/dexter` design patterns (iterative agent loop, scratchpad, soft loop limits, numerical validation), packaged as a multi-platform skill.1011Dexter’s key ideas:12131. Treat financial research as an iterative agent loop, not a one-shot answer.142. First create a compact research plan, then execute data-gathering steps.153. Use a scratchpad as the single source of truth for tool calls, results, assumptions, and partial conclusions.164. Prefer high-level meta-queries to finance data tools, but fall back to specific interfaces when needed.175. Use soft loop limits and repeat-query detection to avoid runaway tool use.186. Validate numerical answers before finalizing.197. For valuation, use an explicit DCF workflow with sensitivity analysis and sanity checks.208. Output concise, sourced analysis with caveats; never present investment advice as certainty.2122## Python interpreter convention2324Command examples in this skill use a bare `python`. Substitute it with whichever interpreter in the caller's environment has `tushare`, `pandas`, and `requests` installed — for example `python3`, `~/.hermes/venv/bin/python`, `~\.hermes\venv\Scripts\python.exe`, a conda env, `uv run python`, or a pyenv-managed version. The skill does not assume any specific install location and works on macOS, Linux, and Windows.2526## Agent-native CLI conventions2728All scripts under `scripts/` follow a uniform agent-native contract so an LLM agent can call them without parsing prose:2930- **Output format auto-detection.** When stdout is not a TTY (e.g. captured by `subprocess.run`), scripts emit a single JSON envelope on stdout. When stdout is a TTY, scripts emit the legacy human table. Override with `--format json|table`.31- **Stable success envelope:** `{"ok": true, "data": {...}, "meta": {"schema_version", "request_id", "latency_ms"}}`.32- **Stable error envelope:** `{"ok": false, "error": {"code", "message", "retryable", "context"}, "meta": {...}}`. Error messages stay on stderr in table mode.33- **Schema introspection.** `python <this-skill-dir>/scripts/<name>.py --schema` returns parameter types, preset registries, upstream interfaces, and error codes as JSON. Agents should prefer `--schema` over parsing `--help`.34- **Dry-run preview.** `--dry-run` echoes the request shape (would_call, would_write, filters, search_window) without making upstream API calls or writing files. Available on all mutating scripts.35- **Documented exit codes:** `0` ok · `1` runtime · `2` auth · `3` validation · `4` no_data · `5` dependency.36- **Long-running progress.** `screen_hk_connect.py --with-momentum` and `financial_report.py` emit NDJSON progress events on stderr (one JSON per line) so agents can detect liveness during multi-second runs.37- **Idempotency.** Output files are date-stamped (`YYYYMMDD_*` or `YYYYMMDD-HHMMSS_*`); re-runs are deterministic and overwrite the same path.3839Agents calling these scripts should:40411. Run `--schema` once per script to learn parameters/presets, instead of parsing `--help`.422. Capture stdout as JSON (auto-detected when piped) and branch on `data.ok`.433. Read `error.code` (not `error.message`) to decide retry vs. escalate. `retryable: true` + a `no_data` code typically means "loosen filters or extend `--lookback-days`".4445## Trigger conditions4647Use this skill for:4849- “研究一下 / analyze / deep dive” on a stock, company, ETF, index, sector, or market theme50- “DCF / intrinsic value / fair value / undervalued / overvalued / price target”51- Financial statement trend analysis, valuation comparison, earnings/catalyst analysis52- “Compare A vs B” for companies/sectors53- “Why did this stock move?” or “what changed recently?”54- Chinese A-share/HK/ETF queries where Tushare can provide data55- Stock screening / watchlist construction across A-share or Hong Kong markets, including dividend, quality, valuation, growth, momentum, and risk filters5657Do not use for:5859- Direct buy/sell/order execution60- Personalized portfolio advice without explicit risk/timeline context61- Unverifiable rumors62- Questions that can be answered from stable definitions without external data6364## Mandatory workflow6566### Step 0. Update check (notify, don't pull) — first use per conversation6768Throttle to one check per 24 hours per installation; never mutate the skill directory without explicit user consent.69701. If `<this-skill-dir>/.last_update` exists and is less than 24 hours old, skip this step entirely.71722. Otherwise, fetch the latest tag from upstream:7374 ```bash75 git -C <this-skill-dir> ls-remote --tags origin 'v*' 2>/dev/null \76 | awk '{print $2}' | sed 's|refs/tags/||' \77 | sort -V | tail -178 ```79803. Compare with this skill's `metadata.version` from the frontmatter. If the upstream tag is strictly newer (semver), tell the user one line and ask:8182 > "A newer version of this skill is available: vX.Y.Z → vA.B.C. Want me to `git pull`?"8384 If they say yes, run `git -C <this-skill-dir> pull --ff-only`. Refresh `.last_update` either way so the prompt doesn't repeat for 24 hours.85864. If upstream is the same or older, refresh `.last_update` silently and continue.87885. On any failure (offline, not a git checkout — e.g. ClawHub-installed copy, read-only path, no permission), swallow the error silently and continue with the user's task. Do not mention the failure.8990### 0. State scope and assumptions briefly9192Infer obvious defaults instead of asking:9394- “recent” = last 60 calendar days / ~40 trading days95- “financial trend” = last 8 quarters or last 5 annual periods when available96- “valuation” = DCF + multiple sanity check97- “A股” = Tushare first; US stocks = web/search or available market APIs first9899Ask only if ambiguity changes the analysis materially.100101### 1. Create a research scratchpad102103For any non-trivial finance task, keep a local scratchpad file under:104105`./financial-research/scratchpad/`106107Use the helper script in this skill when useful:108109```bash110python <this-skill-dir>/scripts/dexter_scratchpad.py init "original query"111python <this-skill-dir>/scripts/dexter_scratchpad.py add /path/to/file.jsonl tool_result tool_name='tushare.daily' args='...' result='...'112```113114If not using the helper, still preserve internally:115116- original query117- plan118- each data source/tool/interface used119- parameters/date ranges120- raw key data and transformed metrics121- errors/empty results/permission issues122- assumptions and interim conclusions123124### 1b. Pull cross-session decision memory (optional but recommended)125126The scratchpad is per-task. For learning across sessions and tickers, use the decision-log helper to read past calls before the plan step and to record the new call after the final answer:127128```bash129# At plan step: pull recent same-ticker analyses + cross-ticker lessons130python <this-skill-dir>/scripts/dexter_memory_log.py context --ticker 600519.SH131132# After final answer: record a pending decision133python <this-skill-dir>/scripts/dexter_memory_log.py record \134 --ticker 600519.SH --rating Buy --date 20260502 \135 --decision "Thesis: PE22, ROE30, dividend stable, demand resilient. Plan: re-check at next earnings."136137# Later, when realized returns are known: resolve the pending entry.138# Recommended path — let daisy fetch close prices and benchmark automatically:139python <this-skill-dir>/scripts/dexter_memory_log.py auto-resolve \140 --ticker 600519.SH --date 20260502 \141 --reflection "Held 17d, raw +4.8% vs CSI300 +3.6%, alpha +1.2%. Dividend+ROE thesis worked."142143# Or if you've already computed the numbers yourself:144python <this-skill-dir>/scripts/dexter_memory_log.py resolve \145 --ticker 600519.SH --date 20260502 \146 --raw-return 4.8 --alpha-return 1.2 --holding-days 17 \147 --reflection "..."148```149150`auto-resolve` is the recommended path. It fetches `close[decision_date]` and `close[as_of_date]` for the ticker, walks forward / backward to the nearest trading day, fetches the right benchmark by ticker suffix (CSI 300 for `*.SH/SZ/BJ`, HSI for `*.HK`, SPY for US tickers), computes raw + alpha + holding days, then runs the same atomic-rewrite resolve logic as the manual path. For HK names, when Tushare's HK index endpoints aren't available in the user's plan, the helper falls through to AKShare's `stock_hk_index_daily_sina` for HSI (requires `pip install akshare`).151152Use `dexter_memory_log.py compute-returns` to inspect the numbers without persisting:153154```bash155python <this-skill-dir>/scripts/dexter_memory_log.py compute-returns \156 --ticker 600519.SH --date 20260415157# → JSON envelope with raw_return_pct / alpha_return_pct / benchmark_return_pct / holding_days158```159160To audit your own track record across many resolved entries, run `backtest`:161162```bash163# Auto-derived window covering every resolved entry164python <this-skill-dir>/scripts/dexter_memory_log.py backtest165166# Explicit window, Buy ratings only167python <this-skill-dir>/scripts/dexter_memory_log.py backtest \168 --from 20260101 --to 20260430 --rating Buy169```170171Returns per-rating count / mean alpha / `alpha_hit_rate` / `alpha_t_stat` / `annualized_alpha_pct`, plus an overall block with the cumulative-alpha drawdown. The metric names make explicit that this is decision-level — daisy logs decisions, not a continuous portfolio NAV, so a textbook Sharpe ratio doesn't apply.172173When writing the `--reflection` text, follow the standard 2–4-sentence shape in `references/reflection-prompt.md` so lessons stay short enough to be re-injected on future runs.174175Storage: a single Markdown file at `./financial-research/memory/decision-log.md`. Entries are separated by the HTML comment `<!-- ENTRY_END -->`. Tag lines start as `[YYYY-MM-DD | ticker | rating | pending]` and become `[YYYY-MM-DD | ticker | rating | +X.X% | +Y.Y% | Nd]` on resolve. `record` is idempotent on (date, ticker) — re-running with the same key skips silently. Ratings are constrained to `Buy / Overweight / Hold / Underweight / Sell` (see `references/decision-schema.md` for the full rating vocabulary and report markdown contract). Use `dexter_memory_log.py stats` for a hit-rate / mean-alpha summary.176177### 2. Plan before tools178179Write a 3–7 item plan. Keep it tactical:180181- identify company/ticker/universe182- collect price/market data183- collect financials/ratios/estimates/filings/news as relevant184- compute metrics or valuation185- validate numbers and sources186- synthesize concise answer187188### 3. Tool/data routing policy189190The canonical per-market routing reference (A-share / HK / US, primary + documented fallback chain for each data type) lives at `references/data-source-routing.md`. Read it before the plan step; the rest of this section is the agent-facing summary.191192For Chinese market / Tushare-accessible data:193194- Load/use the `tushare` skill if not already loaded.195- Use `TUSHARE_TOKEN` from environment.196- Prefer Tushare for: A-share daily prices, stock_basic, daily_basic, income, balancesheet, cashflow, fina_indicator, forecast/express, moneyflow, margin, concept/index/ETF/fund/macro data.197- Use date format `YYYYMMDD` and stock code format like `000001.SZ`, `600000.SH`.198199For Hong Kong stocks:200201- Use Tushare HK interfaces when available before falling back to web quote sites.202- `pro.hk_basic(ts_code='00005.HK', ...)` and `pro.hk_daily(ts_code='00005.HK', start_date='YYYYMMDD', end_date='YYYYMMDD')` are known-good for HK tickers such as HSBC `00005.HK`.203- For the user's Hong Kong Stock Connect universe (港股通) preference when explicitly requested, use `pro.hk_hold(trade_date='YYYYMMDD')` as a first-pass universe identifier. It returns Southbound Stock Connect holdings with fields such as `code,trade_date,ts_code,name,vol,ratio,exchange`.204- Use the bundled helper to export the latest 港股通 universe:205206```bash207python <this-skill-dir>/scripts/hk_connect_universe.py --date YYYYMMDD --top 20208```209210- The helper searches backward when the requested date has no data and writes a CSV under `./financial-research/universes/YYYYMMDD_hk-connect-universe.csv`.211- For 港股通 flow/capital attention, optionally use `pro.ggt_top10(...)`, `pro.ggt_daily(...)`, and `pro.moneyflow_hsgt(...)`.212- Do not assume every advertised HK interface works in the installed Tushare version; in this environment `pro.hk_daily_basic(...)` returned `请指定正确的接口名`, so treat it as unavailable unless re-tested. **Fallback:** when an HK valuation/fundamentals call fails on Tushare, use the bundled AKShare helper (no Tushare token, no auth):213214```bash215# PE-TTM / PB / PS / PCF snapshot + Stock Connect eligibility216python <this-skill-dir>/scripts/akshare_hk_valuation.py valuation --ts-code 00005.HK217218# Annual or quarterly fundamentals: ROE_YEARLY, EPS_TTM, BPS, ROA, leverage219python <this-skill-dir>/scripts/akshare_hk_valuation.py fundamentals --ts-code 00005.HK --period 年度 --limit 8220221# Local-dict-only Chinese name lookup (no API call) — covers ~30 HK majors222python <this-skill-dir>/scripts/akshare_hk_valuation.py name --ts-code 00700.HK223```224225Sources: AKShare `stock_hk_valuation_comparison_em` + `stock_hk_security_profile_em` for valuation; `stock_financial_hk_analysis_indicator_em` for fundamentals. Optional `pip install akshare`; the helper emits `dependency_missing` (exit=5) with a clear install hint if the package is absent.226- For banks, DCF is usually the wrong primary valuation frame. Prefer RoTE/ROE, CET1, dividend payout/yield, NIM/NII guidance, credit cost, P/B or P/E, buyback capacity, and analyst target sanity checks.227- Maintain the user's preferred finance-search stack: Tushare for structured market/financial data; Brave MCP as primary web search; Bailian WebSearch MCP as Chinese/China-market supplement; Python for calculations; browser only for dynamic/interactive pages. Do not include Asta/Semantic Scholar as a default route for finance evidence.228- Session detail: see `references/hsbc-hk-bank-research-test-20260429.md` for the HSBC test workflow and pitfalls.229230For web/current context:231232- Prefer Brave MCP search (`brave_web_search` / `brave_local_search` when available) for current news, filings, company pages, market context, source discovery, and broad English/global web coverage.233- Use Bailian WebSearch MCP (`bailian_web_search`) as an optional/secondary search channel, especially for Chinese-language queries, China-market news, general encyclopedia-style facts, weather/news/current info, or when Brave results are sparse.234- Cross-check important claims with at least two independent sources when the answer depends on recent news, market rumors, policy, regulation, or company events.235- Use browser only when interaction, dynamic pages, paywall/login behavior, or visual inspection is needed.236- Use terminal Python for calculations and tabulation.237- If a dedicated finance API/tool is unavailable, be explicit about source limits.238239Routing heuristics adapted from Dexter:240241- Price / market movement / news / insider activity → market data or web search.242- Income statement / balance sheet / cash flow / ratios / estimates → financials.243- SEC filing details → filings/web sources.244- Broad market or macro news → web search.245- Screening by financial criteria → Tushare screening script or Python filtering.246- DCF / fair value → follow the DCF checklist below.247- **Revenue breakdown by product / region / segment** → A-share has a structured source (`scripts/segments.py` → AKShare `stock_zygc_em`); for HK / US there is no free segment API, so read the annual report's "Segment Information" note via filings / Brave search.248249When the user asks "why is the market down today" / "今天大盘为什么跌" / "what's moving the Hang Seng" — no specific ticker — go straight to broad web search (Brave MCP for English / global, Bailian MCP for Chinese-language sources) with a market-wide query like `美股下跌 原因 YYYY-MM-DD` or `S&P 500 selloff YYYY-MM-DD`. Do **not** pick one large-cap ticker and search its news as a proxy; the intent is macro / sector-rotation / rates / geopolitical catalysts, not a company event.250251### 4. Soft loop limits252253Avoid repetitive tool calls:254255- Suggested max per tool/interface: 3 attempts per query.256- If a query/interface fails twice, change strategy: different endpoint, broader/narrower date range, web fallback, or explain limitation.257- Do not keep calling the same endpoint with near-identical parameters.258- If data is incomplete, proceed with caveated analysis rather than fabricating.259260When the scratchpad helper is active, you can ask it to flag both failure modes before a tool call:261262```bash263python <this-skill-dir>/scripts/dexter_scratchpad.py can-call \264 <scratchpad.jsonl> tushare.daily 'ts_code=600519.SH start=20240101 end=20240630'265# → {allowed: true, warning: null|string, current_count: int, similar_to: [...]}266```267268`allowed` is always `true` (this is a *soft* warning, not a block). React to a non-null `warning`: if `current_count >= max_calls`, change endpoint; if `similar_to` is non-empty, the tool is about to repeat a recent call — adjust the query or skip.269270### 5. Numerical validation checklist271272Before final answer, verify:273274- Date ranges and units are stated.275- Currency/unit scale is consistent: yuan vs USD, CNY vs HKD, millions/billions.276- Growth rates use comparable periods.277- Per-share metrics use correct shares if computed manually.278- Market cap / EV / price are from a stated date.279- Any ranking/screening has universe and filters stated.280- If data is missing or permission-limited, say so.281282### 6. Final answer format283284Use this concise structure:2852861. Scope/Data: tickers, period, sources/interfaces used.2872. Key Findings: 3–6 bullets with numbers.2883. Evidence Table: compact table when comparative/numerical.2894. Interpretation: what the data suggests, not overclaimed.2905. Risks / Missing Data / Caveats.2916. If exported: file path.292293Always include: “Data analysis only, not investment advice.” when discussing securities.294295### 7. Report export policy296297For substantial research tasks, generate a durable report under:298299`./financial-research/reports/`300301Preferred report stack:3023031. Markdown source (`.md`) as the canonical editable record.3042. HTML report (`.html`) as the primary polished output.3053. PDF (`.pdf`) only when the user asks for a printable/shareable file, or when HTML-to-PDF tooling is available and stable.306307Default behavior:308309- For quick answers: reply in chat only, optionally with scratchpad path.310- For medium/deep research: create both `.md` and `.html`.311- For formal deliverables: create `.md`, `.html`, and `.pdf` if possible.312313**Hermes back-compat note.** Hermes installations that want to keep the legacy archive layout (`~/.hermes/reports/financial-research/`) can pass `--out-dir ~/.hermes/reports/financial-research` to any script — the script appends the matching subdir (`reports/`, `watchlists/`, `universes/`, `scratchpad/`) automatically.314315Use the bundled report generator:316317```bash318# medium/deep research: Markdown + HTML319python <this-skill-dir>/scripts/financial_report.py report.md --title "Company Research Report" --slug company-research320321# formal deliverable: Markdown + HTML + PDF322python <this-skill-dir>/scripts/financial_report.py report.md --title "Company Research Report" --slug company-research --pdf323```324325The generator copies the Markdown source and renders the report to:326327`./financial-research/reports/YYYYMMDD-HHMMSS_slug.{md,html,pdf}`328329Why HTML first:330331- Easier to render tables, charts, color-coded risks, source links, and sensitivity matrices.332- More reliable than PDF generation in CLI environments.333- Can be opened directly in a browser and later printed/exported to PDF.334335PDF guidance:336337- Use PDF for sharing, archiving, printing, or sending to non-technical readers.338- Prefer generating PDF from the HTML report using browser print, Playwright/Chromium, or another available HTML-to-PDF tool.339- If PDF generation fails, keep the HTML and state the limitation rather than blocking the analysis.340341Recommended report sections:3423431. Executive summary / investment view.3442. Company and ticker scope.3453. Data sources and dates.3464. Price and valuation snapshot. When the report needs a technical-analysis layer, pick up to 8 complementary indicators from `references/technical-indicator-cheatsheet.md` and compute them via `scripts/technical_indicators.py --ts-code <code>` (auto-routes A-share/HK/US, applies a strict look-ahead-bias guard at `--as-of`). Skip TA entirely for banks / insurers — RoTE / CET1 / NIM are the right frame for those.3475. Financial performance and key drivers. For A-share names, pulling a revenue-by-segment / 主营构成 breakdown often surfaces concentration risk (one product line / one region) that the headline P&L hides:348349 ```bash350 # All classifications (按产品 / 按地区 / 按行业), 4 most recent reports351 python <this-skill-dir>/scripts/segments.py --ts-code 600519.SH352353 # Filter to one axis354 python <this-skill-dir>/scripts/segments.py --ts-code 000001.SZ --classification 按地区355 ```356357 HK / US names: no free segment API — read the latest annual report's "Segment Information" note (10-K for US, annual report "Operating Segments" section for HK) via the filings tool or Brave search.3586. News/catalyst review. For A-share / 港股 names, pull China-market context (涨跌停 risk, 北向资金, 板块 rotation, 监管 backdrop) using the system prompt in `references/cn-market-analyst-prompts.md`.3597. Bull/base/bear scenarios. For balanced single-company research, run the three-prompt debate template in `references/debate-prompts.md` (Bull → Bear → Synthesis) instead of writing scenarios free-form. The synthesis output's 5-tier rating maps directly onto `dexter_memory_log.py record --rating`. For position-sizing follow-up after the directional rating is set, optionally run `references/risk-debate-prompts.md` (Aggressive → Conservative → Neutral → Portfolio Manager). All synthesis outputs use the markdown shape and rating vocabulary documented in `references/decision-schema.md`. Either loop can be driven mechanically by `scripts/debate_runner.py` (subcommands `init` / `next` / `synthesize`, `--type research|risk`) — the script enforces the rotation rules and exit conditions so the agent only has to write each speaker's argument; full usage in the "Programmatic loop driver" sections of the two prompt files.3608. Risks and what would change the view.3619. Evidence tables and calculations.36210. Disclaimer: data analysis only, not investment advice.363364### 8. Stock screening and watchlist workflow365366Use this when the user asks “怎么选股”, “筛一批股票”, “A股/港股有什么值得关注”, or wants a watchlist rather than a single-company report.367368Reusable files:369370- Presets/reference: `references/stock-screening-presets.md`371- Screening report template: `templates/screening_report.md`372- A-share screener: `scripts/screen_a_share.py`373- Hong Kong Stock Connect screener: `scripts/screen_hk_connect.py` (only when 港股通 is explicitly requested)374- Report generator: `scripts/financial_report.py`375376Common commands:377378```bash379# A-share dividend/quality watchlist + Markdown report source380python <this-skill-dir>/scripts/screen_a_share.py --preset a_dividend_quality --top 50 --report381382# A-share value watchlist383python <this-skill-dir>/scripts/screen_a_share.py --preset a_value --top 50 --report384385# 港股通 watchlist only when explicitly requested386python <this-skill-dir>/scripts/screen_hk_connect.py --top 50 --with-momentum387388# Turn generated Markdown into the three-layer report stack389python <this-skill-dir>/scripts/financial_report.py report.md --title "Watchlist Report" --slug watchlist --pdf390```391392Watchlist outputs go under:393394`./financial-research/watchlists/`395396Do not try to predict winners directly. Build a funnel:3973981. Define universe399 - A-share: all listed stocks, index constituents, industry, market-cap band, dividend universe, or user-defined list.400 - Hong Kong: HK main board / H-share / Hang Seng indexes / Hong Kong Stock Connect (港股通, when explicitly requested) / user-defined HK tickers.401 - Exclude suspended, ST/*ST, newly listed names, illiquid names, or missing-data names unless the user explicitly wants them.4024032. Choose screening style404 - Dividend/income: dividend yield, payout sustainability, ROE/ROTE, cash flow, debt, earnings stability.405 - Quality compounder: ROE/ROIC, gross/net margin, revenue/profit CAGR, low leverage, stable cash flow.406 - Value: low PE/PB/EV metrics, but require profitability and no obvious balance-sheet trap.407 - Growth: revenue/profit growth, margin trend, industry tailwind, valuation sanity.408 - Turnaround/event: earnings inflection, policy catalyst, restructuring, buyback, sector cycle.409 - Momentum: 1/3/6/12-month returns, relative strength, drawdown, volume confirmation.4104113. Apply hard filters first412 - Liquidity: daily turnover or volume threshold.413 - Size: market cap threshold.414 - Financial health: positive earnings or operating cash flow, leverage not extreme.415 - Valuation: remove obvious extreme outliers unless justified.416 - Data completeness: remove rows with missing critical fields.4174184. Score candidates419 - Build 4–6 factor scores rather than one magic metric.420 - Suggested default weights: quality 30%, valuation 25%, growth 20%, shareholder return 15%, momentum 10%.421 - For bank/insurance stocks, replace generic DCF/gross-margin metrics with ROE/ROTE, CET1/solvency, NIM/NII, credit cost, PB/PE, dividend and buyback capacity.4224235. Produce a shortlist424 - Output 10–30 names for broad screens, then 3–8 names for deep-dive priority.425 - Include “why selected”, key metrics, red flags, and next verification step.426 - Never present the screen as a buy list; call it a research watchlist.4274286. Deep-dive the finalists429 - For each finalist, run the single-company research workflow: data, news/catalysts, valuation, risks, scenario view.430 - Generate Markdown + HTML reports for substantial screens; add PDF for formal deliverables.431432Suggested output tables:433434- Universe and filters table.435- Top candidates table with ticker, name, industry, market cap, PE/PB, ROE/ROTE, dividend yield, growth, momentum, score, red flag.436- Priority deep-dive list: top 3–8 names and why they deserve follow-up.437- Exclusion notes: important names removed and why.438439Screening caveats:440441- Tushare/HK data availability varies by interface and user permissions; document missing fields.442- A cheap stock can be a value trap; require at least one quality or catalyst confirmation.443- A high dividend can be unsafe; check payout ratio, earnings stability, balance sheet and cash flow.444- Momentum screens need risk controls; do not confuse recent price strength with intrinsic value.445446## DCF valuation workflow447448Use when the user asks for intrinsic/fair value, DCF, price target, undervalued/overvalued.449450Progress checklist:451452- [ ] Gather financial data453- [ ] Calculate FCF base and historical FCF growth454- [ ] Estimate discount rate / WACC455- [ ] Project FCF for years 1–5 + terminal value456- [ ] Discount to present value and compute fair value per share457- [ ] Run sensitivity analysis458- [ ] Validate result459- [ ] Present assumptions and caveats460461### Data to gather462463- 5 years annual cash flow: operating cash flow, capex, free cash flow464- latest balance sheet: cash, investments, total debt, shares outstanding465- financial metrics: market cap, enterprise value, margins, ROE/ROIC, debt/equity, revenue growth466- analyst estimates if available467- latest price468- sector/industry for WACC sanity469470### Assumptions471472- FCF = operating cash flow - capex if not directly available473- Growth: use 5-year FCF CAGR if stable, haircut by 10–20%; cap sustained base growth at 15% unless justified474- For volatile FCF, triangulate with revenue growth, EPS estimates, and margin trend475- WACC: default 8–10% for mature companies; higher for cyclicals/small caps/high leverage; lower for stable defensives476- Terminal growth: default 2.5%; sensitivity 2.0%, 2.5%, 3.0%477- Years 1–5 growth decay: base growth × 1.00, 0.95, 0.90, 0.85, 0.80478479### DCF validation480481- Terminal value should usually be 50–80% of EV for mature companies; >90% is fragile.482- Calculated EV should be directionally plausible vs market EV; if >30–50% away, explain drivers.483- Cross-check fair value against FCF/share × 15–25 or sector multiple.484- Include a 3×3 sensitivity matrix: WACC base ±1% vs terminal growth 2.0/2.5/3.0%.485486## A-share quick-start patterns with Tushare487488Environment check:489490```python491import os, tushare as ts492assert os.getenv('TUSHARE_TOKEN') or ts.get_token(), 'Missing TUSHARE_TOKEN'493pro = ts.pro_api(os.getenv('TUSHARE_TOKEN') or ts.get_token())494```495496Common interfaces:497498```python499# Stock list500pro.stock_basic(list_status='L', fields='ts_code,symbol,name,area,industry,list_date')501502# Daily price503pro.daily(ts_code='000001.SZ', start_date='20240101', end_date='20241231')504505# Daily valuation/market metrics506pro.daily_basic(ts_code='000001.SZ', start_date='20240101', end_date='20241231', fields='ts_code,trade_date,close,pe,pb,total_mv,circ_mv,turnover_rate,volume_ratio')507508# Financial indicators509pro.fina_indicator(ts_code='000001.SZ', period='20231231')510511# Income / balance sheet / cash flow512pro.income(ts_code='000001.SZ', period='20231231')513pro.balancesheet(ts_code='000001.SZ', period='20231231')514pro.cashflow(ts_code='000001.SZ', period='20231231')515```516517## Quality bar518519A good Dexter-style answer should be:520521- grounded: every important number has a source/interface/date522- multi-step: shows it planned, gathered, computed, validated523- honest: says what is missing or permission-limited524- compact: useful to a finance reader, not a data dump525- reproducible: scratchpad/export path if the analysis used substantial data