How to Interpret the Output of the Stock Analysis in ZhuLinsen/daily_stock_analysis

The ZhuLinsen/daily_stock_analysis system produces structured JSON via the AnalysisResult dataclass and AnalysisReportSchema, which you can render into Markdown, WeChat, or brief formats using Jinja2 templates, with key trading signals located in the sentiment_score, decision_type, and nested dashboard object.

The repository provides an LLM-powered pipeline that returns both machine-readable data and narrative reports for Chinese equities. Understanding the hierarchy of fields—from top-level metadata to the granular sniper_points—is essential for building automated trading bots, screening dashboards, or manual review workflows.

Understanding the Core Data Model

The foundation of the output is the AnalysisResult dataclass defined in src/analyzer.py. This object encapsulates all metadata and analysis results returned after the LLM call.

Key attributes include:

  • code and name: Stock identifier (e.g., 600519) and localized name (e.g., 贵州茅台)
  • sentiment_score: A 0-100 composite confidence where higher values indicate more bullish sentiment
  • trend_prediction: Narrative description such as "强烈看多" or "看空"
  • operation_advice: Action recommendation like "买入", "持有", or "卖出"
  • decision_type: Machine-friendly normalized tag (buy, hold, sell) used for statistics and filtering
  • confidence_level: Human-readable confidence rating ("高", "中", "低")
  • dashboard: Optional nested JSON containing the full "决策仪表盘" with technical data
  • analysis_summary: One-paragraph high-level synthesis of the investment thesis

Decoding the Full Report Schema

The detailed structure is governed by AnalysisReportSchema in src/schemas/report_schema.py. This schema validates the JSON returned by the LLM and organizes data into four logical dashboard sections.

Core Conclusion

The dashboard.core_conclusion object contains the final verdict:

  • one_sentence: A single-sentence take-away (≤30 characters) suitable for alert pipelines
  • signal_type: Visual emoji indicator (🟢 Buy, 🟡 Hold, 🔴 Sell, ⚠️ Risk warning)
  • time_sensitivity: Urgency indicator for the signal
  • Position-specific advice: Separate recommendations for "no-position" vs "has-position" states

Data Perspective

The dashboard.data_perspective section provides technical metrics:

  • trend_status: MA alignment, bullish flags, and trend scores
  • price_position: Current price, MA5/10/20 values, bias percentages, and support/resistance levels
  • volume_analysis: Volume ratios, status, and turnover metrics
  • chip_structure: Profit ratio, average cost, concentration metrics, and chip health status (健康/一般/警惕)

Intelligence

The dashboard.intelligence object aggregates qualitative data:

  • latest_news: Recent relevant news items
  • risk_alerts: Critical risk factors
  • positive_catalysts: Upcoming earnings or events
  • earnings_outlook: Forward-looking earnings analysis
  • sentiment_summary: Aggregated market sentiment

Battle Plan

The dashboard.battle_plan section contains actionable trading parameters:

  • sniper_points: Ideal entry, secondary entry, stop-loss, and target price levels. The renderer strips prefixes via _clean_sniper_value
  • position_strategy: Suggested position sizing, entry plan, and risk control parameters
  • action_checklist: Emoji-prefixed validation items (✅ pass, ⚠️ warning, ❌ fail). Failed checks are collected into failed_checks for highlighting

Rendering Human-Readable Reports

Raw JSON converts to formatted documents via the Jinja2 renderer in src/services/report_renderer.py.

from src.services.report_renderer import render

# results is a list of AnalysisResult objects

markdown = render(
    platform="markdown",      # Options: "markdown", "wechat", "brief"

    results=[result],
    report_date="2026-04-30",
    summary_only=False,
)

The renderer selects templates from templates/ based on the platform parameter:

  • templates/report_markdown.j2: Full Markdown formatting
  • templates/report_wechat.j2: Optimized for WeChat messaging
  • templates/report_brief.j2: Condensed summary

The rendering engine automatically resolves language settings, computes signal text via get_signal_level, localizes stock names, and injects helper functions like _escape_md and _clean_sniper_value.

Interpreting Key Output Fields

Field Interpretation Practical Application
Sentiment Score (sentiment_score) 0-100 scale: >80="强烈看多", 60-79="看多", 40-59="震荡", <40="看空" Rank stocks or trigger alerts when exceeding thresholds
Decision Type (decision_type) Normalized tags (buy/hold/sell) Database storage, statistical aggregation, automated filtering
Signal Emoji (dashboard.core_conclusion.signal_type) 🟢 Buy, 🟡 Hold, 🔴 Sell, ⚠️ Risk Visual UI badges, chatbot responses
MA Alignment (dashboard.data_perspective.trend_status.ma_alignment) Short-term vs long-term moving average positioning Algorithmic trend-following entry/exit logic
Bias (dashboard.data_perspective.price_position.bias_ma5) Percentage deviation from MA5 Mean-reversion strategies
Chip Health (dashboard.data_perspective.chip_structure.chip_health) 健康/一般/警惕 indicates concentration risk Risk-adjusted position sizing
Sniper Points (dashboard.battle_plan.sniper_points) Concrete price levels for entries and exits Direct order placement in trading systems

Practical Workflow Example

Complete pipeline from analysis to automated trading:

from src.analyzer import GeminiAnalyzer, AnalysisResult
from src.schemas.report_schema import AnalysisReportSchema
from src.services.report_renderer import render

# 1. Run analysis programmatically

analyzer = GeminiAnalyzer()
results: list[AnalysisResult] = analyzer.analyze(context, news_context)

# 2. Validate schema (optional but recommended)

for r in results:
    schema = AnalysisReportSchema(**r.to_dict())

# 3. Render for human review

markdown_report = render(
    platform="markdown",
    results=results,
    report_date="2026-04-30",
    summary_only=False,
)

# 4. Extract actionable fields for automated trading

first = results[0]
if first.decision_type == "buy":
    sniper = first.get_sniper_points()
    print(f"Buy {first.code} at ≤{sniper.get('ideal_buy')}, "
          f"SL={sniper.get('stop_loss')}, TP={sniper.get('take_profit')}")

Summary

  • The AnalysisResult dataclass in src/analyzer.py provides the top-level structure with sentiment_score, decision_type, and optional dashboard data
  • The AnalysisReportSchema in src/schemas/report_schema.py validates the LLM JSON and organizes deep data into core_conclusion, data_perspective, intelligence, and battle_plan sections
  • Use render() from src/services/report_renderer.py to convert JSON into markdown, wechat, or brief formats using Jinja2 templates
  • Interpret sentiment_score using the 0-100 scale with specific bullish/bearish thresholds
  • Access sniper_points for algorithmic entry/exit levels and action_checklist for validation gates
  • Check report_language (zh or en) to handle multilingual deployments correctly

Frequently Asked Questions

What does the sentiment_score value mean?

The sentiment_score is a 0-100 composite confidence metric where higher values indicate stronger bullish conviction. According to the source code thresholds implemented in the analyzer: scores above 80 indicate "强烈看多" (strongly bullish), 60-79 indicate "看多" (bullish), 40-59 indicate "震荡" (consolidation), and below 40 indicate "看空" (bearish). Use this field to rank stocks or trigger automated alerts when specific thresholds are exceeded.

How do I extract actionable price levels for automated trading?

Access the sniper_points object within dashboard.battle_plan to retrieve ideal_buy, secondary_entry, stop_loss, and take_profit values. These fields provide concrete price levels that the renderer cleans via _clean_sniper_value to remove prefixes like "止损位:". You can feed these values directly into order placement scripts or risk management calculators without manual parsing.

Can I customize the output language?

Yes. The report_language field controls whether human-readable strings are returned in Chinese (zh) or English (en). When set to en, the system forces English output through GeminiAnalyzer._get_analysis_system_prompt according to the source code. Ensure your rendering template supports the selected language, or the system will default to the configuration in src/config.py.

What should I check first when reviewing an analysis output?

Start with dashboard.core_conclusion.one_sentence for the final verdict, then verify decision_type (the machine-friendly tag) and sentiment_score (the numerical confidence). Next, inspect dashboard.battle_plan.action_checklist for any items prefixed with ❌ or ⚠️, which indicate failed validation checks or warnings that might invalidate the trading signal despite the overall recommendation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →