Skip to content

Conviction and direction

The two most important fields on any per-ticker brief, and the two most commonly misinterpreted. This page explains exactly how they're calibrated and how an AI agent should read them.

The fields

Every brief carries:

{
  "direction": "neutral",      // long_bias | short_bias | neutral | no_signal
  "conviction": 0.24,          // 0.0 to 1.0
  ...
}

These come from the direction signal — a deterministic composite computed in novaframe.analytics.analyst.direction_signal, not an LLM judgement. The analyst writes the brief AFTER the direction signal is computed, and the brief is required to be coherent with the signal (gated by validate_brief_against_signal).

What direction means

Value Reading
long_bias The substrate stack (price, regime, structure, positioning, critical events) leans bullish. The publication thinks the next material move is more likely up than down.
short_bias The substrate stack leans bearish. Next material move more likely down than up.
neutral Substrates conflict or compress; no clear directional lean. Could resolve either way.
no_signal Insufficient data to call. Usually a new ticker, recently halted, or substrate ingest issues.

neutral is not weak long_bias. A neutral read is an active call that the tape is balanced. It carries information — "wait for resolution before committing" is a valid strategic position.

no_signal is the absence of a call, not a third direction. When you see this, the publication is telling you it doesn't have enough to say anything responsible. Most reasonable agent responses: skip the ticker, retry next cycle.

What conviction means

A float from 0.0 to 1.0 expressing the publication's confidence in the directional call — not in the trade idea, not in the price target. It answers: "how strongly does the substrate stack support this direction value?"

Banding

Conviction range Label Plain-English read
0.0 – 0.20 minimal Direction is the slightly-more-likely outcome, but the call is weak. Substrates are noisy or thinly aligned.
0.20 – 0.40 low Direction is supported but with significant disagreement across substrates. Treat as soft.
0.40 – 0.60 moderate Substrate alignment is reasonable. A typical "we think this matters" conviction.
0.60 – 0.80 strong Substrates strongly aligned. The publication is confident in the directional read.
0.80 – 0.95 very strong Rare. Multiple substrates flagging the same direction at high intensity.
0.95 – 1.00 extreme Almost never seen. Either a major news catalyst with structural follow-through, or a data quality flag (check the brief's data_quality_notes).

How conviction interacts with direction

The combination matters:

Direction × Conviction What it means
long_bias + 0.65 "We think this is bullish, with strong substrate alignment." Tradeable read.
long_bias + 0.18 "We think this is bullish, but the call is weak." Informational only.
neutral + 0.55 "We're confident there's no directional lean here." Active call to wait.
neutral + 0.10 "We're not confident there's no lean — substrates conflict and we can't break the tie." Genuine uncertainty.
short_bias + 0.40 "Moderate bearish call."
no_signal + anything The conviction is informational — usually reflects substrate availability, not market confidence.

Common misreadings to avoid

"High conviction means buy" — No. Conviction is about the directional call, not about whether to trade. A neutral brief with conviction 0.75 is a strong "do nothing" signal.

"Conviction values are comparable across tickers" — Mostly yes, but with caveats. The direction signal uses the same composite formula across the universe, so a 0.60 on BTC and a 0.60 on AAVE are calibrated the same way. However, alts often have noisier substrates (thinner orderbook, less consistent regime classification), so conviction values on small-cap alts can be slightly more volatile cycle-to-cycle.

"Conviction will trend" — No. The signal recomputes every cycle from scratch. A ticker can go from conviction 0.55 to 0.20 in the next cycle if the substrate stack shifts. This isn't a bug — it's the system honestly responding to changed conditions.

"Low conviction = wrong" — No. Low conviction means we have less confidence, not we're more likely to be wrong. A low-conviction long_bias that resolved up still counts as the right call. A high-conviction short_bias that resolved up was wrong — and the next cycle will show that resolution in the substrate stack.

How to use these in an agent

Pattern 1: Gate decisions on conviction band

brief = call_tool("get_ticker_brief", {"ticker": "BTC-USD"})
direction = brief["direction"]
conviction = brief["conviction"]

if direction == "no_signal":
    skip_ticker(brief["ticker"], reason="no_signal")
elif conviction < 0.40:
    treat_as_informational(brief)
elif conviction >= 0.60:
    surface_to_user(brief, framing="high-confidence")
else:
    surface_to_user(brief, framing="moderate-confidence")

Pattern 2: Look for cross-substrate corroboration

A long_bias brief with conviction 0.55 is more interesting if the get_ticker_sentiment call shows positive sentiment trajectory in the editorial corpus, AND get_ticker_research shows a constructive direction_arc (e.g., conviction rising over the past 48h). Three independent surfaces aligned is structurally meaningful.

Pattern 3: Watch for direction flips

If the brief's cross_validation.divergences is empty AND the conviction is rising AND the continuity_diff shows a recent direction change, that's a fresh directional read. Distinct from a stable read that's been at the same direction for cycles.

mar = call_tool("get_active_market_report")
continuity = mar.get("continuity", {})
direction_changes = continuity.get("direction_changes", [])
for change in direction_changes:
    if change["ticker"] == my_ticker:
        # The publication just changed its mind about this ticker.
        # Worth a closer look.
        ...

Where conviction comes from

The composite formula weights price action, regime classification, structural levels, positioning data (funding / OI / L/S ratios), and critical events. Each component contributes a sub-score; the final conviction is a calibrated combination.

For the curious: the formula lives in novaframe.analytics.analyst.direction_signal.compute_direction_signal() and is documented in docs/nep/phase 7 - Direction DDB/direction_signal_spec_v1.md in the analytics repo. The MCP doesn't expose the per-component breakdown — the brief surfaces the composite, not the math, because the math is the publication's IP.

Refresh cadence

Conviction values refresh every cycle. The analyst runs every 2 hours (configurable via cycle_interval_hours in the orchestrator), plus a forced cycle at 15:00 UTC ahead of the daily long-form broadcast at 16:00 UTC. So at any moment the data you read is at most ~2 hours stale.