Initial commit: A-share stock analysis project with screening, backtesting, and multi-factor analysis tools

This commit is contained in:
2026-07-01 06:39:40 +00:00
commit d80c208004
19 changed files with 1542 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
---
name: market-overview
description: Assess current A-share market environment including index trends, market breadth, sector rotation, and position sizing recommendation
---
## What I Do
Evaluate the overall A-share market environment to determine:
1. Whether the market is favorable for medium-term trading
2. Suggested position sizing in RMB (capital-aware, for ~5万 account)
3. Current hot sectors and rotation patterns
4. Key risk factors
## Capital Context (CRITICAL)
**The user has ~5万 RMB capital.** Position sizing must be translated to concrete RMB amounts, not abstract percentages alone.
### Position Sizing for 5万 Account
| Signal | Total Position | Max Per Stock | Holding Count |
|--------|---------------|---------------|---------------|
| **Heavy (bullish)** | ¥35,00040,000 (7080%) | ¥10,00015,000 each | 34 positions |
| **Moderate (neutral)** | ¥15,00025,000 (3050%) | ¥5,00010,000 each | 23 positions |
| **Light (bearish)** | <¥15,000 (<30%) | <¥5,000 each | 12 positions |
Always present both: percentage of capital AND the corresponding RMB range.
## Assessment Dimensions
### Index Trend
- Shanghai Composite (000001), Shenzhen Component (399001), ChiNext (399006)
- Direction, strength, and stage of trend
- Key support/resistance levels
- 20/60-day MA relationship
### Market Breadth
- Advancing vs declining stocks ratio
- Volume trend (expanding / contracting)
- New highs vs new lows
- % of stocks above 20-day MA
### Sector Rotation
- Leading and lagging sectors
- Sector fund flow
- Continuity of sector trends (how many days in a row?)
## When to Use Me
Use when the user asks to:
- Check market conditions
- Decide position size
- Understand sector rotation
- Before running any stock screening
## Workflow
1. Fetch major index data via `stock-data index`
2. Fetch sector performance via `stock-data sector`
3. Analyze market breadth indicators
4. Identify sector hotspots and rotation signals
5. Output a structured market assessment:
### Output Format
1. **Market Signal**: Strong / Moderate / Weak — with justification
2. **Index Summary**: each index trend + key level
3. **Market Breadth**: breadth reading and what it means
4. **Hot Sectors**: top 35 sectors with momentum
5. **Position Recommendation**:
- Signal-based allocation in RMB and %
- Max per stock in RMB
- Suggested holding count
6. **Key Risks**: specific market risks to watch this week
## Risk Disclaimer
Always remind the user: results are for reference only. Market conditions can change rapidly. Position sizing is a suggestion, not financial advice.
+97
View File
@@ -0,0 +1,97 @@
---
name: stock-analyzer
description: Deep analysis of a single A-share stock covering technical, fundamental, capital flow, and sentiment dimensions
---
## What I Do
Generate a comprehensive analysis report for a single stock:
1. Fetch all relevant data for the stock
2. Analyze across four dimensions
3. Score each dimension (0-100)
4. Provide overall rating and actionable insights
## Capital Context (CRITICAL)
**The user has ~5万 RMB capital.** Every analysis must include:
- **Affordability check**: confirm the stock price × 100 shares is within reach
- **Position sizing advice**: based on market conditions and stock risk profile, suggest how many lots the user should buy
- **Risk in RMB**: always show stop-loss and take-profit levels in both percentage AND absolute RMB amount
- **Transaction cost**: calculate estimated round-trip cost for the suggested position
### Affordability Check
```
这股票一手要多少钱? 股价 × 100 = ____ 元
用户能买几手? 分配的仓位金额 ÷ (股价 × 100) = ____ 手
```
## Analysis Dimensions
### Technical Analysis
- Trend positioning: identify if stock is in uptrend/downtrend/sideways
- Moving average status: check MA alignment (5/10/20/60 day)
- Support/Resistance levels: identify key price levels
- Volume analysis: volume trend, volume-price divergence signals
- RSI/MACD: oscillator readings and signals
### Capital Flow Analysis
- Main fund flow: net inflow trend over 3/5/10 days
- Northbound capital: recent changes (if available)
- Large order ratio: institutional activity signals
### Fundamental Analysis
- Valuation: PE/PB historical percentile
- Profitability: ROE trend
- Growth: revenue and profit YoY growth
- Quick health check: debt ratio, cash flow
### Sentiment Analysis
- Recent news: key announcements in past 30 days
- Analyst ratings: direction of recent rating changes
## Scoring
Weighted composite score (0-100):
- Technical: 35%
- Capital Flow: 30%
- Fundamental: 25%
- Sentiment: 10%
## When to Use Me
Use when the user asks to:
- Analyze a specific stock by name or code
- Evaluate whether a stock is worth buying
- Get a detailed report on a stock
## Workflow
1. Get stock code (ask user if not provided)
2. Call `stock-data` tools to fetch all data
3. Analyze each dimension, calculate scores
4. Perform affordability check (price × 100 vs 5万 budget)
5. Present a structured report with:
### Report Sections
1. **Basic Info**: name, code, price, sector, market cap, 1手 cost
2. **Overall Score**: composite rating with grade (A/B/C/D)
3. **Dimension Breakdown**: each dimension's score with key observations
4. **Technical Check**: trend, support/resistance, volume signal
5. **Capital Flow Check**: recent money flow pattern and what it means
6. **Fundamental Check**: valuation context, growth trajectory
7. **News & Sentiment**: key events, sentiment direction
8. **Position Suggestion**:
- Suggested lot count (based on market signal + stock risk)
- Total cost in RMB
- Estimated round-trip transaction cost
9. **Risk Management**:
- Stop-loss level: price (¥) and loss amount (¥) with percentage
- Take-profit target: price (¥) and gain amount (¥) with percentage
10. **Verdict**: Watch / Consider / Caution / Avoid — with one-sentence reason
11. **Risk Disclaimer**: results for reference only
## Risk Disclaimer
Always remind the user: results are for reference only. Past performance does not guarantee future results. The user bears all trading risk.
+78
View File
@@ -0,0 +1,78 @@
---
name: stock-backtest
description: Design, run, and interpret strategy backtests for A-share stocks
---
## What I Do
Guide the agent through backtesting trading strategies:
1. Help design strategy rules from user descriptions
2. Run backtests on historical data
3. Interpret results and identify potential issues
4. Suggest improvements
## Capital Context (CRITICAL)
**The user has ~5万 RMB capital.** Backtest interpretation must be capital-aware:
- When presenting metrics, translate key numbers to the user's context:
- "Annualized return 15% = ¥7,500 on 5万"
- "Max drawdown 12% = ¥6,000 worst-case loss"
- "Average win ¥800, average loss ¥1,200 per trade"
- Assess whether a strategy is **practically usable** with 5万 considering position sizing constraints
- Flag if a strategy requires more positions than 5万 can support
## Key Backtest Metrics
- **Cumulative return**: total return over the period
- **Annualized return**: normalized yearly return (translate to ¥ on 5万)
- **Win rate**: percentage of profitable trades
- **Max drawdown**: worst peak-to-trough decline (translate to ¥)
- **Sharpe ratio**: risk-adjusted return
- **Benchmark comparison**: vs CSI 300 index
## Strategy Parameters
Common strategy elements to help users define:
- Entry conditions (e.g., MA crossover, breakout, pullback)
- Exit conditions (e.g., stop loss %, take profit %, trailing stop, time-based)
- Position sizing (e.g., fixed %, Kelly fraction)
- Test period and stock universe
## When to Use Me
Use when the user asks to:
- Backtest a trading strategy
- Verify a strategy's historical performance
- Compare multiple strategies
- Evaluate whether a strategy is worth using
## Workflow
1. Clarify strategy rules with user
2. Translate rules into testable parameters
3. Run backtest via `stock-backtest` tools
4. Present results with interpretation:
### Output Format
1. **Strategy Summary**: rules in plain language
2. **Performance Metrics**: all key metrics in table form
3. **Capital Context Translation**:
| Metric | Value | On 5万 Capital |
|--------|-------|----------------|
| Annualized Return | 18% | ¥9,000/year |
| Max Drawdown | 15% | ¥7,500 worst case |
| Avg Win per Trade | ¥450 | — |
| Avg Loss per Trade | ¥600 | — |
4. **Equity Curve Description**: shape, drawdown periods, recovery time
5. **Benchmark Comparison**: outperformance/underperformance vs CSI 300
6. **Practicality Assessment for 5万**:
- Can the user afford the position sizes?
- Does the strategy require too many concurrent positions?
- Is the max drawdown psychologically tolerable?
7. **Potential Concerns**: overfitting, look-ahead bias, survivorship bias, regime dependence
## Risk Disclaimer
Always remind: backtest results reflect historical data. Live performance will differ. Strategies can fail in new market regimes. The user bears all trading risk.
+79
View File
@@ -0,0 +1,79 @@
---
name: stock-screener
description: Multi-factor A-share stock screening workflow for medium-to-short-term selection
---
## What I Do
Guide the agent through a structured stock screening process:
1. Understand user preferences (industry, market cap, holding period)
2. Assess market environment via `market-overview` skill
3. Call screening tools to find candidates
4. Score and rank candidates by multi-factor model
5. Output **Top 3-5** picks with rationale, position sizing, and cost estimates
## Capital Context (CRITICAL)
**The user has ~5万 RMB capital.** Every recommendation must account for this:
- **Stock price filter**: each recommended stock must cost ¥10–¥50 per share so the user can afford at least 1手 (100 shares). Stocks >¥200 need explicit justification (concentrated bet). Stocks >¥500 are completely inaccessible — never recommend them.
- **Portfolio concentration**: default output is 35 stocks, not 10+. The user holds 24 stocks max.
- **Position sizing**: for each recommended stock, suggest a specific lot count and total cost in RMB.
- **Transaction cost**: for each recommended position, calculate estimated one-way cost (commission + stamp tax). Surface it alongside the position suggestion.
### Position Sizing Table (5万 context)
| Market Signal | Total Exposure | Max Per Stock | Holding Count |
|---------------|---------------|---------------|---------------|
| Strong uptrend | 35,00040,000 (7080%) | 10,00015,000 | 34 positions |
| Neutral/sideways | 15,00025,000 (3050%) | 5,00010,000 | 23 positions |
| Weak/downtrend | <15,000 (<30%) | <5,000 | 12 positions |
### Affordability Check
Before recommending any stock, verify:
```
股价 × 100 shares ≤ 计划分配给该股的仓位金额
```
Example: ¥38 stock × 100 = ¥3,800. With ¥10,000 allocation, the user can buy 2手 (200 shares, ¥7,600).
## Screening Dimensions
- **Technical (35%)**: Trend strength, moving average alignment, volume-price coordination, RSI position
- **Capital Flow (30%)**: Main fund net inflow trend, northbound capital, large order ratio
- **Fundamental (25%)**: PE percentile, ROE, profit growth, revenue growth
- **Sentiment (10%)**: News heat, analyst rating direction
## When to Use Me
Use when the user asks to:
- Find/screen stocks for investment
- Get stock recommendations
- Filter stocks by any criteria
## Workflow
1. Ask the user about preferences if not specified (sector, style, time horizon)
2. Load `market-overview` skill to check if market is favorable and get position sizing signal
3. Use `stock-screen` tools to filter candidates (default top_n=5)
4. For each top candidate, verify affordability:
- Check share price, calculate minimum buy cost (price × 100)
- Cross-check against the position sizing budget
- Filter out any stock the user cannot afford
5. For remaining candidates, run quick analysis with relevant tools
6. Present a ranked list with:
- Rank and composite score (0-100)
- Key strengths (why buy?) and risks (what can go wrong?)
- Suggested position: lot count × share price = total cost
- Estimated transaction cost for this position
- Stop-loss price in both ¥ and percentage
### Output Format Example
| Rank | Stock | Price | Score | Position | Cost | Stop-Loss | Rationale |
|------|-------|-------|-------|----------|------|-----------|-----------|
| 1 | 600XXX | ¥28.5 | 82 | 3手 (300股) = ¥8,550 | 交易费~¥14 | ¥25.7 (-10%, -¥855) | 放量突破+主力净流入 |
## Risk Disclaimer
Always remind: results are for reference only. Past performance does not guarantee future results. The user bears all trading risk.
+53
View File
@@ -0,0 +1,53 @@
import { tool } from "@opencode-ai/plugin";
import path from "path";
const SCRIPTS_DIR = (ctx: { worktree: string }) =>
path.join(ctx.worktree, "scripts");
async function runPython(
ctx: { worktree: string },
fn: string,
args: Record<string, unknown>,
): Promise<string> {
const scriptPath = path.join(SCRIPTS_DIR(ctx), "backtest_engine.py");
const argsJson = JSON.stringify(args);
const result = await Bun.$`python3 ${scriptPath} ${fn} ${argsJson}`.text();
return result.trim();
}
export const run = tool({
description: "Run a backtest for a trading strategy on specified stock universe and period",
args: {
strategy_name: tool.schema.string().optional().describe("Name of a predefined strategy, or omit to use custom rules"),
entry_rule: tool.schema.string().optional().describe("Custom entry condition (Python expression using df columns like close, ma20, ma60, volume, etc.)"),
exit_rule: tool.schema.string().optional().describe("Custom exit condition (Python expression) or 'stop_loss:0.05,take_profit:0.15,max_hold:20'"),
universe: tool.schema.enum(["hs300", "zz500", "all", "custom"]).default("hs300").describe("Stock universe to test on"),
symbols: tool.schema.string().optional().describe("Comma-separated stock codes for custom universe"),
start_date: tool.schema.string().default("20210101").describe("Start date YYYYMMDD"),
end_date: tool.schema.string().default("20251231").describe("End date YYYYMMDD"),
},
async execute(args, context) {
return runPython(context, "run", args);
},
});
export const predefined = tool({
description: "List all predefined backtest strategies with descriptions",
args: {},
async execute(args, context) {
return runPython(context, "predefined", args);
},
});
export const compare = tool({
description: "Compare multiple predefined strategies on the same universe and period",
args: {
strategies: tool.schema.string().describe("Comma-separated strategy names to compare"),
universe: tool.schema.enum(["hs300", "zz500", "all"]).default("hs300").describe("Stock universe"),
start_date: tool.schema.string().default("20210101").describe("Start date YYYYMMDD"),
end_date: tool.schema.string().default("20251231").describe("End date YYYYMMDD"),
},
async execute(args, context) {
return runPython(context, "compare", args);
},
});
+83
View File
@@ -0,0 +1,83 @@
import { tool } from "@opencode-ai/plugin";
import path from "path";
const SCRIPTS_DIR = (ctx: { worktree: string }) =>
path.join(ctx.worktree, "scripts");
async function runPython(
ctx: { worktree: string },
script: string,
fn: string,
args: Record<string, unknown>,
): Promise<string> {
const scriptPath = path.join(SCRIPTS_DIR(ctx), script);
const argsJson = JSON.stringify(args);
const result = await Bun.$`python3 ${scriptPath} ${fn} ${argsJson}`.text();
return result.trim();
}
export const quote = tool({
description: "Get daily/weekly K-line and real-time quotes for a stock",
args: {
symbol: tool.schema.string().describe("Stock code (e.g. 600519 for Kweichow Moutai)"),
period: tool.schema.enum(["daily", "weekly", "monthly"]).default("daily").describe("K-line period"),
start_date: tool.schema.string().optional().describe("Start date YYYYMMDD, defaults to 90 days ago"),
end_date: tool.schema.string().optional().describe("End date YYYYMMDD, defaults to today"),
},
async execute(args, context) {
return runPython(context, "market_data.py", "quote", args);
},
});
export const financial = tool({
description: "Get financial statement indicators for a stock",
args: {
symbol: tool.schema.string().describe("Stock code (e.g. 600519)"),
},
async execute(args, context) {
return runPython(context, "market_data.py", "financial", args);
},
});
export const moneyflow = tool({
description: "Get capital flow data (main fund, northbound) for a stock",
args: {
symbol: tool.schema.string().describe("Stock code (e.g. 600519)"),
days: tool.schema.number().default(10).describe("Number of recent days"),
},
async execute(args, context) {
return runPython(context, "market_data.py", "moneyflow", args);
},
});
export const news = tool({
description: "Get recent news and announcements for a stock",
args: {
symbol: tool.schema.string().describe("Stock code (e.g. 600519)"),
limit: tool.schema.number().default(20).describe("Max number of news items"),
},
async execute(args, context) {
return runPython(context, "sentiment.py", "news", args);
},
});
export const index = tool({
description: "Get major A-share index data (Shanghai Composite, Shenzhen Component, ChiNext)",
args: {
index_code: tool.schema.enum(["sh", "sz", "cyb", "all"]).default("all").describe("Index to fetch"),
days: tool.schema.number().default(30).describe("Number of recent trading days"),
},
async execute(args, context) {
return runPython(context, "market_data.py", "index", args);
},
});
export const sector = tool({
description: "Get sector/industry performance and ranking",
args: {
date: tool.schema.string().optional().describe("Date YYYYMMDD, defaults to latest"),
},
async execute(args, context) {
return runPython(context, "market_data.py", "sector", args);
},
});
+61
View File
@@ -0,0 +1,61 @@
import { tool } from "@opencode-ai/plugin";
import path from "path";
const SCRIPTS_DIR = (ctx: { worktree: string }) =>
path.join(ctx.worktree, "scripts");
async function runPython(
ctx: { worktree: string },
fn: string,
args: Record<string, unknown>,
): Promise<string> {
const scriptPath = path.join(SCRIPTS_DIR(ctx), "stock_screener.py");
const argsJson = JSON.stringify(args);
const result = await Bun.$`python3 ${scriptPath} ${fn} ${argsJson}`.text();
return result.trim();
}
export const multi_factor = tool({
description: "Screen stocks using multi-factor scoring model (technical + capital flow + fundamental + sentiment)",
args: {
strategy: tool.schema.enum(["comprehensive", "momentum", "value", "breakout"]).default("comprehensive").describe("Screening strategy"),
sector: tool.schema.string().optional().describe("Filter by sector/industry name"),
market_cap: tool.schema.enum(["large", "medium", "small", "all"]).default("all").describe("Market cap filter"),
top_n: tool.schema.number().default(5).describe("Number of top stocks to return (user has 5万 capital, keep it tight)"),
},
async execute(args, context) {
return runPython(context, "multi_factor", args);
},
});
export const strong = tool({
description: "Screen for strong-trend stocks (MA bull alignment + relative strength)",
args: {
sector: tool.schema.string().optional().describe("Filter by sector/industry name"),
top_n: tool.schema.number().default(5).describe("Number of top stocks to return (user has 5万 capital, keep it tight)"),
},
async execute(args, context) {
return runPython(context, "strong", args);
},
});
export const breakout = tool({
description: "Screen for volume breakout stocks (price breaking resistance with expanding volume)",
args: {
lookback_days: tool.schema.number().default(60).describe("Lookback period for resistance identification"),
top_n: tool.schema.number().default(5).describe("Number of top stocks to return (user has 5万 capital, keep it tight)"),
},
async execute(args, context) {
return runPython(context, "breakout", args);
},
});
export const oversold = tool({
description: "Screen for oversold stocks with potential rebound signals",
args: {
top_n: tool.schema.number().default(5).describe("Number of top stocks to return (user has 5万 capital, keep it tight)"),
},
async execute(args, context) {
return runPython(context, "oversold", args);
},
});