Install
openclaw skills install market-signal-fusionAdaptive-language stock-analysis skill that interprets macro and political news, fuses it with retail/social sentiment, applies quantified value fallback rul...
openclaw skills install market-signal-fusionUse this skill when the user wants stock analysis driven by macro/political news + market sentiment + value screening + technical timing.
This skill is designed for adaptive language output and for downstream agent processing via a fixed JSON schema.
This skill runs a five-stage workflow:
This version also adds three functional upgrades:
If tools are available, prefer real market data and recent sources. Do not invent numbers.
NVDA, Forward P/E, FCF Yield, PEG, RSI, 200DMA.For user-facing narrative sections:
Whenever the task is analytical and structured, output in two layers:
If the user asks for only JSON, output only the JSON. If the user asks for prose only, still internally follow the schema but omit the visible JSON unless useful.
Extract these if the user provided them; otherwise use sensible defaults:
Identify market-relevant developments from areas such as:
For each major development, produce a structured record:
Then aggregate across catalysts and rank the top favorable sectors.
Before final sector ranking, classify the current market into one primary regime and optional secondary regime:
risk_on_growthrisk_off_defensiveinflation_reflationrate_sensitivecommodity_shockearnings_revision_recoverypolicy_transition_mixedFor the chosen regime, provide:
The regime detector should influence later ranking rules. Examples:
risk_off_defensive, reduce tolerance for speculative sentiment names.inflation_reflation or commodity_shock, boost Energy / Materials / selected Industrials where supported by evidence.risk_on_growth, allow stronger weight to AI / semis / software if revisions and charts confirm.For each sector, compute an informal score from 0 to 100 using:
Call this Macro Tailwind Score.
Focus on market sentiment sources such as:
If the runtime has a dedicated social-data tool or plugin, prefer it over free-form browsing. Treat Stage 2 as a data module when possible, not only a narrative step.
Inputs:
subreddits: default ["wallstreetbets", "stocks", "investing"]lookback_window: default 24h, optional 72h and 7dmin_mentions_threshold: default 5 when enough data existsdeduplicate_spam: true by defaultexclude_etfs_or_indexes: optional, false by defaultPreferred outputs per ticker:
mentionsmentions_accelerationbullish_countbearish_countbullish_ratiosentiment_heat_scoresupport_typespeculation_riskIf only partial data exists, degrade gracefully:
For the broad market:
For single names:
For each stock, form a Sentiment Heat Score from 0 to 100 using:
Also assign a Speculation Risk Flag: low / medium / high.
Every Stage 2 conclusion should reflect these checks:
data_freshness: fresh / acceptable / stalesource_count: how many distinct sentiment sources were usedpolarity_completeness: full / partial / attention_onlyduplicate_filtering: yes / no / unknownconfidence: high / medium / lowIf polarity_completeness = attention_only, do not make a strong bullish/bearish market call from Stage 2 alone.
Use the market regime detector as a top-level weighting control.
If Stage 1 finds bullish sectors and Stage 2 contains stocks matching those sectors, prioritize the overlap.
If Stage 1 finds bullish sectors but Stage 2 does not contain good matches, perform a quantified value-investing fallback screen inside those sectors.
If Stage 1 does not produce a clear sector conclusion, output the Stage 2 hot-stock list, ranked and filtered for quality.
For each candidate stock, combine:
Use judgment to override only when one signal is obviously distorted, for example meme-driven sentiment with broken fundamentals.
When a favored sector lacks sentiment candidates, screen for potentially undervalued stocks using as many of these as available:
Prefer a harder quantified fallback over loose narrative value language.
When enough data exists, compute a Value Fallback Composite Score (0–100) with this default weighting:
Score higher when:
Suggested informal mapping:
Compare company forward P/E to:
Score higher when the stock trades at a meaningful discount without obvious deterioration in business quality.
Prefer higher free cash flow yield, especially when:
Penalty conditions:
Measure whether analyst expectations are improving:
Score higher when revisions are improving and the stock still looks inexpensive.
Do not let a cheap-looking stock pass if the balance sheet is stressed. Check:
A stock should usually not survive the fallback screen if several of the following are true:
For fallback-selected stocks, explicitly show:
Call the final valuation score in fallback mode: Valuation Attractiveness Score and preserve the component breakdown in JSON.
For each final stock, provide:
Use available metrics such as:
Then score:
Estimate four levels when data supports it:
Base these on a mix of:
When exact valuation is unavailable, label the ranges as technical estimate rather than intrinsic value.
For each final stock, analyze:
Then provide a tactical plan:
Do not imply certainty. Present it as a conditional trade plan.
Wherever possible, attach concise structured tags that explain why a candidate passed or failed.
Examples of reason_codes:
MACRO_ENERGY_TAILWINDMACRO_DEFENSE_SPENDINGREGIME_RISK_OFF_DEFENSIVEWSB_HEAT_HIGHWSB_POLARITY_PARTIALREVISION_MOMENTUM_STRONGFCF_YIELD_STRONGTECH_PULLBACK_TO_50DMATECH_BREAKOUT_WITH_VOLUMEExamples of rejection_codes:
SPECULATION_RISK_HIGHVALUATION_DATA_INCOMPLETEFUNDAMENTALS_WEAKNEGATIVE_FCFBROKEN_CHARTNO_CLEAR_CATALYSTUse short, stable codes so downstream agents can filter, rank, and audit decisions.
When structured output is appropriate, emit a fenced json block that follows this schema as closely as possible.
Omit unavailable fields or set them to null; do not fabricate values.
Use the same single language as the user-facing report for all free-text values inside the JSON. Keep keys in English.
{
"meta": {
"skill": "market-signal-fusion",
"version": "1.2.0",
"language_mode": "auto_single_language",
"output_language": "zh|en",
"market_universe": "US equities",
"as_of_date": "YYYY-MM-DD",
"time_windows": {
"macro_news": "last_7d",
"sentiment": "last_3d",
"technicals": "daily_weekly"
},
"strict_mode": false
},
"macro": {
"market_bias": "bullish|neutral|bearish|mixed",
"market_regime": {
"primary": "risk_on_growth|risk_off_defensive|inflation_reflation|rate_sensitive|commodity_shock|earnings_revision_recovery|policy_transition_mixed",
"secondary": null,
"evidence": [""],
"style_implication": ""
},
"top_catalysts": [
{
"title": "",
"summary": "",
"direction": "bullish|bearish|mixed",
"affected_sectors": [""],
"mechanism": "",
"time_horizon": "immediate|medium_term|long_term",
"confidence": "high|medium|low",
"confidence_gate": {
"data_freshness": "fresh|acceptable|stale",
"source_count": 0,
"source_quality": "high|medium|low",
"missing_fields": [""]
}
}
],
"favored_sectors": [
{
"sector": "",
"macro_tailwind_score": 0,
"rationale": ""
}
],
"headwind_sectors": [""]
},
"sentiment": {
"broad_market_mood": "bullish|neutral|bearish",
"risk_mode": "risk_on|neutral|risk_off",
"summary": "",
"confidence_gate": {
"data_freshness": "fresh|acceptable|stale",
"source_count": 0,
"polarity_completeness": "full|partial|attention_only",
"duplicate_filtering": "yes|no|unknown",
"confidence": "high|medium|low"
},
"hot_stocks": [
{
"ticker": "",
"company": "",
"sector": "",
"dominant_narrative": "",
"sentiment_label": "bullish|bearish|mixed",
"signal_type": "full_sentiment|attention_only",
"sentiment_heat_score": 0,
"mentions": null,
"mentions_acceleration": null,
"bullish_count": null,
"bearish_count": null,
"bullish_ratio": null,
"speculation_risk": "low|medium|high",
"support_type": "speculative|fundamentally_supported|mixed"
}
]
},
"selection": {
"selection_mode": "macro_sentiment_overlap|macro_value_fallback|sentiment_only_fallback",
"final_candidates": [
{
"ticker": "",
"company": "",
"sector": "",
"selection_reason": "",
"overlap_type": "macro_plus_sentiment|macro_plus_value|sentiment_only",
"reason_codes": [""],
"rejection_codes": [],
"confidence_gate": {
"data_freshness": "fresh|acceptable|stale",
"source_count": 0,
"source_quality": "high|medium|low",
"missing_fields": [""]
},
"scores": {
"macro_tailwind_score": 0,
"sentiment_heat_score": 0,
"valuation_attractiveness_score": 0,
"quality_score": 0,
"technical_setup_score": 0,
"composite_score": 0
},
"value_fallback": {
"used": true,
"style_bucket": "classic_value|garp|deep_value_higher_risk|null",
"component_scores": {
"peg_score": 0,
"forward_pe_relative_score": 0,
"fcf_yield_score": 0,
"revision_momentum_score": 0,
"balance_sheet_quality_score": 0
},
"value_fallback_composite_score": 0
}
}
]
},
"stock_analysis": [
{
"ticker": "",
"company": "",
"sector": "",
"thesis": "",
"bull_case": [""],
"risks": [""],
"reason_codes": [""],
"rejection_codes": [],
"confidence_gate": {
"data_freshness": "fresh|acceptable|stale",
"source_count": 0,
"source_quality": "high|medium|low",
"missing_fields": [""]
},
"metrics": {
"price": null,
"market_cap": null,
"trailing_pe": null,
"forward_pe": null,
"peg": null,
"ev_ebitda": null,
"fcf_yield": null,
"revenue_growth": null,
"eps_growth": null,
"operating_margin": null,
"net_debt_ebitda": null,
"revision_momentum": null
},
"scores": {
"valuation_attractiveness_score": 0,
"fundamental_quality_score": 0,
"theme_alignment_score": 0,
"risk_score": 0
},
"price_zones": {
"aggressive_buy_zone": "",
"preferred_buy_zone": "",
"fair_value_hold_zone": "",
"trim_take_profit_zone": "",
"zone_basis": "valuation|technical|mixed"
},
"technical_plan": {
"trend": "uptrend|sideways|downtrend|mixed",
"stance": "buy_pullback|breakout_watch|wait|avoid|take_profit",
"support": [""],
"resistance": [""],
"entry_idea": "",
"stop_invalidation": "",
"target_1": "",
"target_2": ""
}
}
],
"summary": {
"best_sector_now": {
"name": "",
"reason": ""
},
"best_value_candidate": "",
"best_momentum_candidate": "",
"market_stance_1_4w": ""
}
}
Use this structure unless the user requests another format.
For each chosen stock, show:
For each final stock, include:
For each final stock, include:
Close with:
After the single-language report, include the JSON block unless the user asked not to.
Say explicitly that the stock is sentiment-driven, not value-supported.
Mark as good company / bad timing and prefer waiting for technical repair.
Mark as watchlist value, low urgency.
Prefer the signal with the clearer time horizon and stronger evidence. Explain the conflict.
Use the fallback framework with only available factors, state which factors are missing, and lower confidence accordingly.
In strict mode, require stronger evidence to issue a final candidate:
attention_only for strong sentiment claims