Blog / Perspectives

[13 / 15]

Oct '256 min read

Sentiment is not a direction

A release can read glowing and still be worth nothing. Novelty carries 0.30 of the actionability score, the gate sits at 60, and that ordering is the only reason a tone reading is any use on a wire feed.

Yin Nguyen Quant Research

A wire release crossed at 07:02 on a Tuesday in March with the word record in it four times. Every off-the-shelf sentiment tool I've ever used would have loved it, and read purely on tone ours saw the same thing: clarity 9, magnitude 7. It also scored 46 on actionability, so it never surfaced on anyone's screen, and that was the right outcome. The quarter had been guided in January and confirmed on the February call. The release was a recap with adjectives on it.

Here's the distinction people collapse. Sentiment is a property of a sentence. Direction is a property of a price. Measuring tone is a reading of the text in front of you and nothing else; predicting direction is a claim about what a market that has already read the same text is going to do next. The second problem runs through a question the words by themselves cannot answer: did anyone not already know this?

Actionability is that question, and it runs first.

Novelty carries 0.30, and that's most of the argument

The actionability head is a convex combination of five sub-scores, each rated 0–10 on its own merits, weighted and multiplied out to 0–100:

score = 10 × ( 0.30·novelty + 0.25·materiality + 0.20·surprise             + 0.15·specificity + 0.10·directness )

Novelty is the largest single weight in the whole engine, because it's the one of the five a promotional writer can't manufacture. Specificity is easy to fake: put numbers in the release. Directness is trivially high on anything a company publishes about itself. Materiality is real but slow-moving and mostly a function of the issuer's own volatility. Surprise and novelty are the two that cost something to produce, and they're 0.50 of the score between them.

Run the March release through it. Novelty 2, materiality 5, surprise 2, specificity 9, directness 10. That's 0.6 + 1.25 + 0.4 + 1.35 + 1.0 = 4.6, so 46. The gate is 60. It fails, and under the default score_sentiment: "if_actionable" the sentiment head never runs at all. The sentiment key is simply absent from the verdict object. Callers have to handle the missing key. That's deliberate. A null is an answer; a confidently-scored direction on a recap is a lie with a decimal point.

46gate
0100
Where the March release landed, and where the argument sits. Everything left of 60 is a company clearing its throat.actionability, 0–100

The shape of that distribution is the thing worth staring at. It isn't Gaussian and it isn't bimodal. There's a fat lump in the 30s and 40s that is corporate throat-clearing, a thin waist through the 50s where the arguments happen, and a long right tail that is the actual business. The 50s are where I spend my time, because that's where a two-point move on a single sub-score flips an item in or out of a desk's morning.

A good objection I can't fully answer

The strongest version goes like this. Tone on non-actionable text is not noise; it's a slow factor. Aggregate the language of every release an issuer puts out over a quarter and the drift in that tone carries information about how management feels, whether or not any single release moved the stock. Gating sentiment on actionability throws that away. You're optimising for the event and discarding the panel.

That's correct, and I don't have a good rebuttal. What I have is an option. POST /v1/score takes score_sentiment: "always", which runs both heads regardless of the gate, and if you're building a cross-sectional tone panel that's the flag you want. Pro gets 100 of those calls a day, Quant gets 1,000. The default is gated because the default consumer is a live feed, where a spurious direction costs more than a missing one. Ungated tone isn't worthless. It's just a different product from an alerting surface, and it shouldn't be the thing that fires at 07:02.

One boundary I'd rather state than have you find. The gate at 60 is a single global number, not one per sector or per market cap. Small caps carry thinner disclosure and fewer prior events to judge novelty against, so a 58 on a small-cap name and a 58 on a mega-cap are not quite the same statement about the world. We run one threshold today because a threshold that moves by bucket is one nobody can reason about across a portfolio, and consistency across the tape has been worth more to the desks we work with than a marginal gain in any single bucket. That trade is under review.

Two directions, one conviction, sized differently

When the gate does open, the sentiment head emits four numbers that matter and one that exists for backwards compatibility.

short_direction and long_direction are both signed integers from −5 to +5, and they're allowed to disagree. A buyback authorisation is the canonical case: short +3, long +1. Something is being bid tomorrow; whether the capital allocation is good news for the equity in two quarters is a different question with a different answer. A going-concern paragraph runs the other way, mild in the short direction because it's buried on page 40 and brutal in the long one.

Conviction is separate, 0–100, built from three sub-scores:

conviction = 10 × ( 0.35·clarity + 0.35·magnitude + 0.30·consensus_gap )

Direction picks the side. Conviction sizes it. Those are different desk functions and they belong in different columns, which is the part one-dimensional sentiment gets wrong. A 0–10 "sentiment score" of 9 can't tell you whether it means clearly up a little or possibly up a lot, and those are opposite trades at the same nominal score.

Watch what a systematic book does with the pair and the separation stops being philosophical. Direction goes into the sign of the position. Conviction goes into the sizing function, usually as a multiplier on whatever the risk model already allowed. Splitting them means a low-conviction +4 gets taken at a fraction of the notional of a high-conviction +2, which you cannot express if the two are baked into one number. In my experience clarity does most of the work in that multiplier: magnitude and consensus gap are estimates about the world beyond the release, while clarity is a read on the language in front of it, and its behaviour is the steadiest across sectors.

Guidance cut−4
Going concern−2
Buyback+3
Capital raise+1
Same nominal direction, different trades. Conviction is what the sizing function reads.conviction, 0–100

A naming note worth ten seconds of your time. The REST filter on GET /v1/feeds speaks the older scale: sentiment_min and sentiment_max are integers 0–10, mapped from short_direction with 5 as neutral. So sentiment_min=7 filters for bullish, not for high conviction. The signed directions and the conviction score live on the verdict object itself. We keep the older query parameter on purpose, because breaking a filter live consumers depend on is worse than an awkward name.

The weights are an argument, and arguments can be inspected

Those weights are not taste. They're fitted against what actually happened to prices after millions of headlines, which is why the ordering above is defensible rather than merely tidy. Somebody's intuition about how much novelty should count is worth very little; the realized behaviour of a tape is worth a lot.

What matters just as much for a desk is that the compound number is decomposable. Actionability isn't one opaque output with a threshold bolted on. It's five ratings, each with a stated meaning and its own 0–10 scale, combined by weights we publish. When an item lands at 58 you can see that novelty was a 2 and specificity was a 9, and tell the difference between a release that failed because it said nothing new and one that failed because it said something new in vague terms. Those deserve different treatment on a research desk, and a black box can't tell them apart for you.

That's the standard I'd hold any scoring vendor to, this one included. Not is the number right, which is unanswerable in the abstract, but can I see what it's made of, and does the decomposition track my own reading when I disagree with the total.

The decomposition earns its keep hardest at the edge of what this engine is for. It scores first-party disclosure about the issuer the disclosure is about, and directness exists precisely to measure that: a name mentioned once in a subordinate clause of somebody else's filing is correctly a low reading on a first-party scale. Second-order relevance, the supplier whose customer just guided down, is a different problem with a different shape, and we treat it as its own line of work rather than as a knob on this one. If you're trading the chain rather than the name, you should know which of the two you're buying.