A China A-share analysis tool based on value investing theory, aimed at ordinary investors engaging in low-frequency trading.
When to Use
Invoke this skill when the user requests the following operations:
- Analyze a certain A-share stock
- Screen stocks that meet the criteria
- Compare multiple stocks or stocks within an industry
- Calculate stock valuation or intrinsic value
- Check a stock's financial health
- Detect financial anomaly risks
Prerequisites
Python environment requirements (venv must be used)
All script commands should be run in the project virtual environment.
python3 -m venv .venv
source .venv/bin/activate
Install dependencies:
pip install tushare pandas numpy
Environment Bootstrap (must be completed automatically before execution)
Before running any script, first execute in the current project directory:
cd <skill项目目录>
if [ ! -d ".venv" ]; then
python3 -m venv .venv
fi
source .venv/bin/activate
python3 -m pip install -U pip
python3 -m pip install tushare pandas numpy
Note:
.venvMust be located under the skill project root directory (not the global directory)- If
import tusharefails, the above bootstrap must be executed first before continuing the subsequent analysis process
TUSHARE_TOKEN / BRAVE_API_KEY It is recommended to save it in ~/.aj-skills/.env, and load it into the current shell before execution:
set -a
source ~/.aj-skills/.env
set +a
Note:
- The script will not automatically read
~/.aj-skills/.env - It must be explicitly passed in via CLI parameters:
--token "${TUSHARE_TOKEN}"、--brave-api-key "${BRAVE_API_KEY}"
Pre-execution parameter check (using the test command):
test -n "${TUSHARE_TOKEN}" || { echo "缺少 TUSHARE_TOKEN"; exit 1; }
# 仅当使用 Brave 新闻源时检查
test -n "${BRAVE_API_KEY}" || { echo "缺少 BRAVE_API_KEY(news-provider=brave 时必填)"; exit 1; }
Dependency check
Before performing any analysis, first check whether tushare is installed:
python3 -c "import tushare; print(tushare.__version__)"
Core Modules
1. Stock Screener (stock screener)
Screen stocks that meet the criteria
2. Financial Analyzer (financial analyzer)
In-depth financial analysis of individual stocks
3. Industry Comparator (industry comparison)
Horizontal comparative analysis within the same industry
4. Valuation Calculator (valuation calculator)
Intrinsic value estimation and margin of safety calculation
5. News & Sentiment (news and sentiment)
Scrape recent public news and generate a sentiment risk assessment
Workflow 1: Stock Screening (stock screening)
Used when the user requests stock screening.
Step 1: Collect Screening Criteria
Ask the user for screening criteria. Provide the following options for the user to choose from or customize:
Valuation metrics:
- PE (price-to-earnings ratio): e.g., PE < 15
- PB (price-to-book ratio): e.g., PB < 2
- PS (price-to-sales ratio): e.g., PS < 3
Profitability:
- ROE (return on equity): e.g., ROE > 15%
- ROA (return on assets): e.g., ROA > 8%
- Gross margin: e.g., > 30%
- Net margin: e.g., > 10%
Growth:
- Revenue growth rate: e.g., > 10%
- Net profit growth rate: e.g., > 15%
- Number of consecutive years of growth: e.g., >= 3 years
Dividends:
- Dividend yield: e.g., > 3%
- Number of consecutive years of dividend payments: e.g., >= 5 years
Financial safety:
- Debt-to-asset ratio: e.g., < 60%
- Current ratio: e.g., > 1.5
- Quick ratio: e.g., > 1
Screening scope:
- All A-shares
- CSI 300 constituent stocks
- CSI 500 constituent stocks
- ChiNext/STAR Market
- User-defined list
Step 2: Execute Screening
python scripts/stock_screener.py \
--scope "hs300" \
--token "${TUSHARE_TOKEN}" \
--pe-max 15 \
--roe-min 15 \
--debt-ratio-max 60 \
--dividend-min 2 \
--output screening_result.json
Parameter description:
--scope: Screening scope (all/hs300/zz500/cyb/kcb/custom:600519,000858,...)--pe-max/--pe-min: PE range--pb-max/--pb-min: PB range--roe-min: Minimum ROE--growth-min: Minimum growth rate--debt-ratio-max: Maximum debt-to-asset ratio--dividend-min: Minimum dividend yield--token: tushare token (required)--format: Output format (json/table)--quiet: Silent mode--output: Output file path
Step 3: Present Results
Read screening_result.json and present it to the user in table form:
| Code | Name | PE | PB | ROE | Dividend yield | Score |
|---|---|---|---|---|---|---|
| 600519 | Kweichow Moutai | 25.3 | 8.5 | 30.2% | 2.1% | 85 |
Workflow 2: Stock Analysis (Individual Stock Analysis)
Used when the user requests analysis of a certain stock.
Step 1: Collect Stock Information
Ask the user:
- Stock code or name
- Analysis depth level:
- Summary level: Key metrics + investment conclusion (1 page)
- Standard level: Financial analysis + valuation + industry comparison + risk warnings
- Deep level: Complete research report, including historical data tracking
Step 1.5: Prepare Output Directory
When analyzing a single stock, the skill needs to automatically create an output directory, naming rule:
${股票名称}_${股票代码}
Example:
stock_dir="贵州茅台_600519"
mkdir -p "${stock_dir}"
Step 2: Fetch Stock Data
It is recommended to use the "modular scraping + aggregation" process (CLI decoupled):
mkdir -p "${stock_dir}/data"
# 1) 基础信息
python scripts/fetch_basic.py \
--code "600519" \
--token "${TUSHARE_TOKEN}" \
--output "${stock_dir}/data/basic.json"
# 2) 财务数据
python scripts/fetch_financial.py \
--code "600519" \
--token "${TUSHARE_TOKEN}" \
--years 5 \
--output "${stock_dir}/data/financial.json"
# 3) 估值与行情
python scripts/fetch_valuation.py \
--code "600519" \
--token "${TUSHARE_TOKEN}" \
--output "${stock_dir}/data/valuation.json"
python scripts/fetch_price.py \
--code "600519" \
--token "${TUSHARE_TOKEN}" \
--days 180 \
--output "${stock_dir}/data/price.json"
# 4) 新闻舆情
python scripts/fetch_news_data.py \
--code "600519" \
--name "贵州茅台" \
--days 7 \
--limit 20 \
--provider brave \
--brave-api-key "${BRAVE_API_KEY}" \
--output "${stock_dir}/data/news.json"
# 5) 实时与事件窗口
python scripts/fetch_realtime.py \
--code "600519" \
--token "${TUSHARE_TOKEN}" \
--benchmark hs300 \
--window 60 \
--output "${stock_dir}/data/realtime.json"
python scripts/fetch_event_window.py \
--code "600519" \
--token "${TUSHARE_TOKEN}" \
--name "贵州茅台" \
--benchmark hs300 \
--pre-days 1 \
--post-days 1,3,5 \
--provider brave \
--brave-api-key "${BRAVE_API_KEY}" \
--output "${stock_dir}/data/event_window.json"
# 6) 聚合为分析输入
python scripts/assemble_data.py \
--input-dir "${stock_dir}/data" \
--output "${stock_dir}/stock_data.json"
Compatibility mode (single-command scraping) is retained as follows:
python scripts/data_fetcher.py \
--code "600519" \
--token "${TUSHARE_TOKEN}" \
--data-type all \
--with-news \
--news-provider brave \
--brave-api-key "${BRAVE_API_KEY}" \
--with-realtime \
--with-event-window \
--benchmark hs300 \
--realtime-window 60 \
--event-window-pre 1 \
--event-window-post 1,3,5 \
--news-days 7 \
--news-limit 20 \
--years 5 \
--output "${stock_dir}/stock_data.json"
Parameter description:
--code: Stock code--data-type: Data type (basic/financial/valuation/holder/news/all)--years: How many years of historical data to retrieve--token: tushare token (required)--with-news: Additional news and public sentiment--news-days: News window days--news-limit: Maximum number of news items--news-sources: News source filter (comma-separated)--news-provider: News source (auto/brave/tushare/rss)--brave-api-key: Brave Search API Key(news-provider=bravewhen required)--with-realtime: Additional real-time indicators (trend/confirmation/risk/chips)--with-event-window: Additional event window analysis (reaction 1/3/5 days after the event)--benchmark: Relative strength benchmark index (hs300/zz500/zz1000/cyb/kcb)--realtime-window: Real-time indicator calculation window (days)--event-window-pre: Number of days before the event window--event-window-post: Number of days after the event window (comma-separated)--cache-ttl-min: Cache validity period (minutes)--format: Output format (json/table)--quiet: Silent mode--output: Output file
Optional: Run the news and public sentiment process separately
python scripts/news_fetcher.py --code 600519 --name 贵州茅台 --token "${TUSHARE_TOKEN}" --days 7 --limit 20 --provider brave --brave-api-key "${BRAVE_API_KEY}" --output "${stock_dir}/news.json"
python scripts/sentiment_analyzer.py --input "${stock_dir}/news.json" --output "${stock_dir}/sentiment.json"
Step 3: Run Financial Analysis
python scripts/financial_analyzer.py \
--input "${stock_dir}/stock_data.json" \
--level standard \
--output "${stock_dir}/analysis_result.json"
Or directly read the modular directory (automatic aggregation):
python scripts/financial_analyzer.py \
--input-dir "${stock_dir}/data" \
--level standard \
--output "${stock_dir}/analysis_result.json"
Parameter description:
--input: Input stock data file--input-dir: Modular directory (automatically read and aggregate into analysis input)--level: Analysis depth (summary/standard/deep)--output: Output file
Step 4: Calculate Valuation
python scripts/valuation_calculator.py \
--input "${stock_dir}/stock_data.json" \
--methods dcf,ddm,relative \
--discount-rate 10 \
--growth-rate 8 \
--output "${stock_dir}/valuation_result.json"
Parameter description:
--input: Stock data file--methods: Valuation method (dcf/ddm/relative/all)--discount-rate: Discount rate (%)--terminal-growth: Perpetual growth rate (%)--growth-rate: Perpetual growth rate compatibility alias (%)--margin-of-safety: Margin of safety (%)--format: Output format (json/table)--quiet: Silent mode--output: Output file
Step 5: Generate Report
Read the analysis results, refer to the templates/analysis_report.md template to generate a Chinese analysis report.
Mandatory report generation checklist (all must be satisfied):
0. The final report must be saved to disk as a Markdown file (.md)
- Must include the "News and Public Opinion" section
- Must use
stock_data.jsonfromnews_sentiment/news_itemsto fill in the corresponding fields - If news scraping fails, the failure reason must be clearly stated in the report (from
news_sentiment.error) - Not allowed to omit from the template
summary_titleand the "Performance and Audit Signals" section - If
stock_data.jsoncontainsrealtime_metrics, the report must include the "Real-time Indicator Dashboard" section (trend/confirmation/risk/chips) - If
stock_data.jsoncontainsevent_window, the report must include "Event Window Reaction" content (number of events, 1/3/5-day post-event returns, 1/3/5-day post-event excess returns) - If
realtime_metricsexists, the composite score must use Financial 40% + Real-time 60%(real-time priority)
Report structure (standard level):
- Company Overview: basic information, main business
- Financial Health: balance sheet analysis
- Profitability: DuPont analysis, profit margin trends
- Growth Analysis: revenue/profit growth trends
- Real-time Indicator Dashboard: trend/confirmation/risk/chips
- Event Window Analysis: post-event returns and excess returns
- Valuation Analysis: DCF/DDM/relative valuation
- Risk Disclosure: financial anomaly detection, shareholder reductions
- Investment Conclusion: composite score, operational recommendations (real-time priority)
Report title specification:
summary_titleUse format:股票名称(股票代码):总结性结论- Example:
贵州茅台(600519):财务稳健,估值与风险匹配度较好
Output file:
${stock_dir}/final_report.md
Step 6: humanize Output
Read ${stock_dir}/final_report.md, and call the humanizer-zh skill for polishing and optimization.
Output file:
${stock_dir}/final_report_humanized.md
Workflow 3: Industry Comparison (industry comparison)
CLI method (sector analysis, recommended)
# 1) 获取板块数据
python scripts/sector_fetcher.py \
--sector-name "算力板块" \
--token "${TUSHARE_TOKEN}" \
--sector-file config/sector_computing_default.json \
--output "${stock_dir}/sector_data.json"
# 2) 生成板块分析结果 + Markdown报告
python scripts/sector_analyze.py \
--input "${stock_dir}/sector_data.json" \
--output "${stock_dir}/sector_analysis.json"
Step 1: Collect Comparison Targets
Ask the user:
- Target stock code(s) (multiple allowed)
- Or: industry classification + number of comparisons
Step 2: Fetch Industry Data
python scripts/data_fetcher.py \
--codes "600519,000858,002304" \
--token "${TUSHARE_TOKEN}" \
--data-type comparison \
--output industry_data.json
Or retrieve by industry:
python scripts/data_fetcher.py \
--industry "白酒" \
--token "${TUSHARE_TOKEN}" \
--top 10 \
--output industry_data.json
Step 3: Generate Comparison
python scripts/financial_analyzer.py \
--input industry_data.json \
--mode comparison \
--output comparison_result.json
Step 4: Present Comparison Table
| Metric | Kweichow Moutai | Wuliangye | Yanghe Shares | Industry average |
|---|---|---|---|---|
| PE | 25.3 | 18.2 | 15.6 | 22.4 |
| ROE | 30.2% | 22.5% | 20.1% | 18.5% |
| Gross margin | 91.5% | 75.2% | 72.3% | 65.4% |
| Score | 85 | 78 | 75 | - |
Workflow 4: Valuation Calculator (valuation calculation)
Step 1: Collect Valuation Parameters
Ask the user for valuation parameters (or use defaults):
DCF model parameters:
- Discount rate (WACC): default 10%
- Forecast period: default 5 years
- Perpetual growth rate: default 3%
DDM model parameters:
- Required rate of return: default 10%
- Dividend growth rate: estimated using historical data
Relative valuation parameters:
- Comparison benchmark: industry average / historical average
Step 2: Run Valuation
python scripts/valuation_calculator.py \
--code "600519" \
--methods all \
--discount-rate 10 \
--terminal-growth 3 \
--forecast-years 5 \
--margin-of-safety 30 \
--output valuation.json
Step 3: Present Valuation Results
| Valuation method | Intrinsic value | Current price | Margin of Safety Price | Conclusion |
|---|---|---|---|---|
| DCF | ¥2,150 | ¥1,680 | ¥1,505 | Undervalued |
| DDM | ¥1,980 | ¥1,680 | ¥1,386 | Undervalued |
| Relative Valuation | ¥1,850 | ¥1,680 | ¥1,295 | Fair |
Financial Anomaly Detection
The following anomaly signals are automatically detected during analysis:
Detection Item
-
Accounts Receivable Anomaly
- Accounts receivable growth > revenue growth × 1.5
- Accounts receivable turnover days increase significantly
-
Cash Flow Divergence
- Net profit continues to grow but operating cash flow declines
- Cash-to-revenue ratio < 80%
-
Inventory Anomaly
- Inventory growth > revenue growth × 2
- Inventory turnover days increase significantly
-
Gross Margin Anomaly
- Gross margin fluctuation > industry average fluctuation × 2
- Gross margin deviates significantly from peers
-
Related-party Transactions
- Related-party transaction proportion too high (> 30%)
-
Shareholder Reduction
- Recent reduction announcement by major shareholder
- Concentrated reduction by executives
Risk Level
- 🟢 Low Risk: No obvious anomaly
- 🟡 Medium Risk: 1-2 minor anomalies
- 🔴 High Risk: Multiple anomalies or severe anomalies
A-Share Specific Analysis
Policy Sensitivity
Provide policy-related alerts based on industry classification:
- Real Estate: housing is for living in, not for speculation policy
- New Energy: changes in subsidy policies
- Pharmaceuticals: impact of centralized procurement policies
- Internet: antitrust, data security
Shareholder Structure Analysis
- Type of controlling shareholder (state-owned/private/foreign)
- Equity concentration
- Recent increases/decreases in holdings
- Pledge ratio
Output Format
JSON/Table Output Format
- Default
json - Optional
--format tablefor quick terminal viewing - Use
--quietto disable process logs
All scripts output in JSON format for subsequent processing:
{
"code": "600519",
"name": "贵州茅台",
"analysis_date": "2025-01-25",
"level": "standard",
"summary": {
"score": 85,
"conclusion": "低估",
"recommendation": "建议关注"
},
"financials": { ... },
"valuation": { ... },
"risks": [ ... ]
}
Markdown Report
Generate a structured Chinese Markdown report, refer to templates/analysis_report.md。
Data Contract
The core data structure is constrained by scripts/data_contract.py . The analysis script validates before running:
- Top-level required fields:
code/fetch_time/data_type/basic_info - Common optional fields:
financial_data/financial_indicators/valuation/price/holder/dividend - News-related fields:
news_items/news_sentiment - Performance audit fields:
performance_data(includingforecast/express/audit/main_business) - Statement field requirements:
financial_data.balance_sheetmust be an arrayfinancial_data.income_statementmust be an arrayfinancial_data.cash_flowmust be an array
Field Mapping (Akshare -> Tushare)
| Compatible Semantics | Current Field (Recommended) | Compatible Alias/Source |
|---|---|---|
| PE(TTM) | valuation.latest.pe_ttm |
valuation.latest.pe |
| PB | valuation.latest.pb |
- |
| Net Profit | financial_data.income_statement[].净利润 |
n_income |
| Net Operating Cash Flow | financial_data.cash_flow[].经营活动产生的现金流量净额 |
n_cashflow_act |
| Capital Expenditure Cash | financial_data.cash_flow[].购建固定资产、无形资产和其他长期资产支付的现金 |
c_pay_acq_const_fiolta |
| ROE | financial_indicators[].净资产收益率 |
roe |
| Debt-to-Asset Ratio | financial_indicators[].资产负债率 |
debt_to_assets |
Error Handling
Network Error
If tushare data retrieval fails, prompt the user to:
- Check network connection
- Retry later (may be API rate limiting)
- Try switching data sources
Invalid stock symbol
Prompt the user to check whether the stock symbol is correct and provide possible matching suggestions.
Incomplete data
For newly listed stocks or cases with incomplete financial data, explain the data limitations and conduct the analysis based on the available data.
Best Practices
- Data timeliness: Financial data is based on the latest quarterly/annual report, and price data is the closing price of the day; when enabled,
--with-realtime/--with-event-windowsupplement dynamic indicators of trends and event shocks - Investment advice: All analysis is for reference only and does not constitute investment advice
- Risk disclosure: Always include risk disclosures, especially the results of financial anomaly detection
- Comparative analysis: When analyzing a single stock, automatically include comparison with the industry average
- Scoring weights: When real-time data is available, use
财务40% + 实时60%; when real-time data is missing, degrade to the financial score
Important Notes
- All analysis is based on public financial data and does not involve any inside information
- The parameter assumptions of valuation models have a significant impact on the results and must be explained to the user
- The A-share market is greatly affected by policy, and quantitative analysis needs to be combined with qualitative judgment