Imported from Super-YYQ/stock_selector (
AGENTS.md). Install upstream withnpx skills add Super-YYQ/stock_selector. Copyright stays with the author.
AGENTS.md
Mission
This repository is a local, explainable A-share post-market selector. It updates daily bars, scores the market, sectors and stocks, applies configurable strategies and risk penalties, then generates Excel and responsive web reports. It never submits orders.
Start Here
Read these files before changing behavior:
README.mdfor user workflowsdocs/ARCHITECTURE.mdfor module boundaries and data flowdocs/STRATEGIES.mdfor strategy semanticsdocs/CONFIGURATION.mdfor every supported setting and unitconfig/strategy.yml,config/stock_pool.yml, andconfig/custom_strategies.ymlfor active values
Main entry points:
run_daily.pydelegates tosrc.run_daily.runpython -m src.panelstarts the FastAPI panelscripts/bootstrap.pyowns one-click environment setup- GitHub Pages deploys only from the generated
gh-pagesbranch;site/is untracked onmainand produced by every run fromweb/.
Architecture
src/fetch_data.py: provider adapters and parallel TDX backfillsrc/database.py: SQLite schema, upserts, health, run and selection historysrc/build_pool.py: eligibility filterssrc/market_score.py,sector_score.py: environment factorssrc/stock_character.py,volume_price_score.py: stock factorssrc/stock_context.py: cached industry, concept, limit-up clue, and sector-stage narratives for ranked candidatessrc/strategies/: independent strategy signals and shared feature cachesrc/custom_formulas.py: safe declarative formula validation, evaluation, and result projectionsrc/risk_filter.py,scoring.py: penalties and rankingsrc/report.py: styled Excel outputsrc/web_report.py: JSON/static report outputsrc/panel.py: local API and background task runnersrc/scheduler.py: fixed-command Windows scheduled-task boundaryweb/: build-free HTML/CSS/JS shared by local panel and Pagessite/: generated, publishable static output
Non-Negotiable Behavior
- Default provider is
tdx, which needs no account login. - TDX hosts are probed for real bar data before use. If every host fails, read
docs/incidents/2026-09-10-tdx-hosts-empty-bars.mdbefore changing anything else; hosts are configurable viadata.tdx_hosts. - Keep Baostock optional and conservative. Do not increase its concurrency or retry loops; upstream blacklisting is a known operational risk.
- Initialization must remain resumable and validate stock coverage, row count and index count.
- Daily updates must remain incremental.
- A single symbol failure must not abort the whole universe unless a circuit breaker identifies systemic provider failure.
- Do not commit
data/*.db, logs, Excel reports or virtual environments. - GitHub Pages may receive only generated static files (site content) plus the Pages deploy workflow.
- The panel binds to
127.0.0.1by default. Public server deployment requires reverse-proxy authentication and HTTPS. - Scheduled-task management must keep the task name and script paths fixed. Never accept arbitrary shell commands from the panel.
- Strategy scores are aggregated by family maximum, then summed across families. Do not restore naive summation of related strategies.
- Every selected stock must retain an explainable reason and risk warning.
- Custom formulas are an independent observation surface and must not silently alter the main ranking.
- Custom formulas must remain declarative and allowlisted. Never add
eval, arbitrary Python expressions, uploaded scripts, or dynamic imports. - Treat concept and limit-up context as best-effort enrichment. Label inferred relationships as clues, never as confirmed news causes.
- Market-board exclusion must recognize both current and legacy Beijing Exchange code prefixes.
Strategy Development
All strategies subclass src.strategies.base.Strategy and define:
keynamefamilydescriptionscoreevaluate(...)
Use the shared frame from build_strategy_features. Avoid recalculating moving averages, volatility or breakouts inside each strategy. Register new strategies in src/strategies/registry.py, assign a family and add focused tests.
Current families: breakout, trend, pullback, event, sector, pattern.
Custom chart-derived rules live in config/custom_strategies.yml. Add indicator fields to the shared feature builder only when a requested formula cannot be expressed with existing fields. Formula failures must be isolated so the main daily report still completes.
Data and Schema
SQLite tables include market data plus:
stock_sync_statusfor resumable provider migration/backfillstock_context,stock_event, andsector_contextfor cached candidate narrativesselection_historyfor Top N snapshots and forward returnsrun_historyfor panel and scheduled-run visibility
Schema changes must be additive and safe for an existing data/stock.db. CREATE TABLE IF NOT EXISTS is the current migration mechanism.
Frontend Rules
The interface is an operational dashboard, not a marketing page.
- Preserve responsive desktop/mobile layouts.
- Keep local-only controls marked with
local-onlyso Pages stays read-only. - Avoid build tooling unless it solves a real maintenance problem.
- Keep the JSON contract in
src/web_report.pybackward compatible or incrementschema_version. - Keep built-in strategy configuration and custom-formula results as separate navigation and data contracts.
- Test desktop and mobile layouts after meaningful UI changes.
Verification
Run the focused tests while editing, then the full suite:
.\.venv\Scripts\python.exe -m compileall -q src scripts
.\.venv\Scripts\python.exe -m pytest -q
For pipeline changes, run against the existing database with a known date and verify:
- Excel opens and required sheets exist
site/data/latest.jsonis valid JSON- the panel serves
/api/statusand/api/latest - no unexpected full-history fetch occurs on a daily run
For deployment changes, validate docker compose config and inspect the Pages workflow.
Git and Generated Files
The user may have unrelated work in the tree. Never revert it.
site/ is untracked on main and ignored; the publish script syncs it to the gh-pages orphan branch, which is the durable store for report history. Historical JSON retention is controlled by report.history_days.
Before committing, scan Chinese text files for replacement characters or accidental question-mark corruption.