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:
codeandname: Stock identifier (e.g.,600519) and localized name (e.g.,贵州茅台)sentiment_score: A 0-100 composite confidence where higher values indicate more bullish sentimenttrend_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 filteringconfidence_level: Human-readable confidence rating ("高", "中", "低")dashboard: Optional nested JSON containing the full "决策仪表盘" with technical dataanalysis_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 pipelinessignal_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 scoresprice_position: Current price, MA5/10/20 values, bias percentages, and support/resistance levelsvolume_analysis: Volume ratios, status, and turnover metricschip_structure: Profit ratio, average cost, concentration metrics, and chip health status (健康/一般/警惕)
Intelligence
The dashboard.intelligence object aggregates qualitative data:
latest_news: Recent relevant news itemsrisk_alerts: Critical risk factorspositive_catalysts: Upcoming earnings or eventsearnings_outlook: Forward-looking earnings analysissentiment_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_valueposition_strategy: Suggested position sizing, entry plan, and risk control parametersaction_checklist: Emoji-prefixed validation items (✅pass,⚠️warning,❌fail). Failed checks are collected intofailed_checksfor 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 formattingtemplates/report_wechat.j2: Optimized for WeChat messagingtemplates/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
AnalysisResultdataclass insrc/analyzer.pyprovides the top-level structure withsentiment_score,decision_type, and optionaldashboarddata - The
AnalysisReportSchemainsrc/schemas/report_schema.pyvalidates the LLM JSON and organizes deep data intocore_conclusion,data_perspective,intelligence, andbattle_plansections - Use
render()fromsrc/services/report_renderer.pyto convert JSON intomarkdown,wechat, orbriefformats 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(zhoren) 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →