timing-verdict API · for quant desks

You found the right what.
We tell you about the when.

POST the shortlist your models already chose. Get back, per symbol, a deterministic verdict on whether now is the moment — read from where the sector sits in its cycle and where the name sits inside the move. Not a signal source. Not a backtest. A market-state timing overlay on names you already like.

Request access See how it works private beta · semis first
AMAT our #1
0/100
favorable
XLK · hot_extended · constructive_continuation
dist_piv+1.7 vol_tr1.24 clpos0.96

full size — measured, volume-confirmed, room before the chase ceiling.

KLAC our #4
0/100
wait
XLK · hot_extended · extended
dist_piv+4.7 ret_3d+19% clpos0.99

leader, but at the ceiling after +19%/3d — a gap-up open is buying the top.

Same sector. Same day. Opposite calls. KLAC's fundamentals score 88 — strong, and inert. The company isn't the problem; the setup is.

the gap we close

Your factor models are structurally backward-looking. Their weakest read is the one that decays within the sessionis now the moment? stock87 is the overlay for exactly that.

It's the read your models are worst at by construction: where the sector sits in its current cycle, and where your name sits within that move, right now. A short-term swing judgment — holding measured in days, decaying within the session. Explicitly not a long-term view.


how it works

One endpoint. Your shortlist in, verdicts out.

A personal, rotatable key — sent as Authorization: Bearer or X-API-Key. No SDK, no import wizard. POST application/json, text/csv, or a bare newline-delimited list. The key also works in the path for one-line curl / browser checks.

request · the names you like
$ curl -X POST \
  https://stock87.io/v1/judge \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d @shortlist.json

[
  { "symbol": "AMAT", "input_rank": 6 },
  { "symbol": "KLAC", "input_rank": 2 },
  { "symbol": "MU",   "context": "strategy:reversal" }
]
response · what to act on right now
{
  "as_of": "2026-06-15T20:00:00Z",
  "methodology_version": "0.4.0",
  "set": {
    "frame": "relative_to_submitted_set",
    "ranking": [
      { "symbol":"AMAT", "input_rank":6, "timing_rank":1,
        "score":87, "timing_verdict":"favorable",
        "scenario_profile":"regime_dependent" },
      { "symbol":"KLAC", "input_rank":2, "timing_rank":4,
        "score":58, "timing_verdict":"wait",
        "risk_flag":"give_back_risk", "scenario_profile":"pure_beta" }
    ]
  },
  "results": [ /* full per-symbol verdicts → */ ]
}
GET /v1/judge/{symbol} — one name, one verdict, in a single GET: curl -H "X-API-Key: $KEY" https://stock87.io/v1/judge/AMAT. A single symbol returns just the verdict; a set adds the set ranking.
input_rank — supply your own priority per name and the response lights up rank_divergence: your order beside ours. The most valuable view. Omit it and you still get a full ranking.
?live=true — adds a real-time overlay reflecting what the session has done since the open. Noisier, and labelled confidence: lower.

anatomy of a verdict

Branchable fields, not prose.

A strategy can route on the verdict object directly — skip, down-size, or fire — without parsing a sentence. The narrative is optional and lives behind a flag.

timing_verdict favorable · neutral · wait · conditional · avoid_now. The call itself — the deterministic product of sector regime × symbol position.
scenarios continuation · cooler · bear. The same name scored under three fixed market paths — posture under assumptions, not a forecast. Collapses to a scenario_profile. The set-level score is a stable 0–100 projection of the verdict, never contradicting the tier.
risk_flag First-class, branchable: give_back_risk · unconfirmed · low_conviction · event. Branch on it; never parse prose for it.
rank_divergence Your rank vs. ours: { input_rank, timing_rank, delta }. The whole point in one field — your factor order against current-market fitness.
sizing_note Human-facing sizing guidance — always paired with the branchable risk_flag so machines and people read the same call.
fundamentals Reported and inert — score + one word, never applied to the verdict. The one carve-out is event_risk: a timing risk wearing fundamentals' clothing.
branchable — a strategy can route on these
{
  "symbol": "AMAT",
  "fundamentals": {
    "fundamentals_score": 80,
    "fundamentals": "strong",
    "event_risk": null
  },
  "market_state": {
    "sector": "XLK",
    "sector_regime": "hot_extended",
    "symbol_position": "constructive_continuation",
    "measures": {
      "dist_piv":1.7, "ret_3d":0.136,
      "vol_tr":1.24, "clpos":0.96
    }
  },
  "timing_verdict": "favorable",
  "scenarios": {
    "continuation": { "score":87, "verdict":"favorable" },
    "cooler":       { "score":72, "verdict":"neutral" },
    "bear":         { "score":44, "verdict":"wait" }
  },
  "scenario_profile": "regime_dependent",
  "risk_flag": null,
  "sizing_note": "full size — measured, room before chase",
  "rank_divergence": { "input_rank":6, "timing_rank":1, "delta":5 }
}

the edge · the engine

The verdict is an interaction, not a score.

Two symbols in the same hot sector, on the same day, can earn opposite calls — because symbol_position is assigned by a precedence-ordered rule set. The order is the trading logic. First match wins.

1
Extension is a veto.→ extended
At or over the chase ceiling (dist_piv ≥ ceiling) or blown off (ret_3d ≥ blow_off) — regardless of how perfect the close is. A flawless close near the high does not rescue a name that already made its move. → KLAC.
2
Volume-confirmed near the pivot.→ constructive_continuation
Not extended, sitting in a band around the pivot, with volume behind it (vol_tr > confirm) and a strong close (clpos > strong). Slightly below pivot is tolerated only if volume confirms. → AMAT.
3
Below pivot, unconfirmed.→ pre_move
Below pivot (dist_piv < 0) with no volume. Hasn't confirmed anything yet — could be the next leg, could be dead money.
4
Deeply below pivot, weak.→ laggard_trap
Far below pivot with weak or negative short-term return and no volume. The "too deep, not breaking out" case.

Two precedence rules carry the whole edge: extension vetoes session quality (rule 1 beats a perfect close), and volume-confirmation is the splitter (rule 2 vs. rule 3). timing_verdict is then the deterministic product of sector_regime × symbol_position — and those two lines are exactly where our output diverges from your raw factor rank.


scenarios · conditional positioning

Not one verdict. A posture under each path.

A name doesn't have a single timing call — it has one conditional on which way the tape goes next. We score every symbol under three fixed paths — continuation, cooler, bear — without claiming any will occur. The shape of the three is the product.

AMATregime_dependent
continuation87
cooler72
bear44

Strong if the rally holds, softer if it doesn't — good, but it needs the tape to cooperate.

KLACpure_beta
continuation82
cooler34
bear18

Tops the continuation column, bottoms the rest — a wide spread that is the warning: a pure directional bet on the rally.

The four profiles — all_weather · pure_beta · regime_dependent · defensive — fall straight out of the three scores. The headline timing_verdict tracks the path that matches today's regime; the scenario columns are the conditional breakdown behind it, sortable at set level so a desk with no regime view can rank by the all_weather names instead. Posture under assumptions — never a forecast.


rank divergence · the payoff

Your order, beside ours.

Hand the API a set and it returns the verdicts plus a ranking — best of these to trade right now, relative to the set you submitted. The gap between your factor rank and current-market fitness is the reason to call us.

YOUR RANK OUR TIMING RANK #14FTNT #2KLAC #6AMAT #8LRCX #13SNEX 1AMAT 2LRCX 3SNEX 4KLAC 5FTNT
divergence_note Your top pick KLAC (rank 2) falls to 4th — top continuation score but worst cooler/bear exposure; AMAT (your rank 6) leads on today's regime. Frame: relative_to_submitted_set — best of the names you handed us, right now.

deterministic · explainable

No black box. No number an LLM guessed.

01 · reproducible

Same inputs, same payload.

Same inputs plus the same methodology_version return an identical deterministic object, every time. Versioned so a desk can reconstruct exactly why a name scored 87 versus 84.

02 · the engine decides

The rules compute every field.

Every consumable field — metrics, flags, sector_regime, symbol_position, timing_verdict, score — comes from the deterministic rules engine. Nothing consumable is a judgment call.

03 · the LLM is a sidecar

It writes prose. Nothing else.

The model receives the finished object and writes only the rationale string, behind ?include=narrative. It never produces a number and never feeds back. Switch it off — not one consumable field changes.


what it is · what it isn't

An overlay, not an oracle.

+ stock87 is

  • +A second-opinion verdict on a pre-selected shortlist — names your models already chose.
  • +A current-market-state timing overlay, read from sector cycle × position-in-move.
  • +Deterministic, versioned, explainable — every field reconstructable.
  • +A re-ranking of your shortlist by current-market fitness, relative to the set.

stock87 isn't

  • A screener or alpha source. We don't find names — you already did.
  • A point-in-time dataset for backtesting. That's your mastery, not ours.
  • A fundamentals-only quality score — you already have that, and it's the wrong horizon.
  • A black box, or an LLM guessing a number.
the things we won't build

The product is the shorter list.

×

No signals or strategies

We judge the when of names you chose. We never supply the trades. Want a strategy? Wrong product.

×

No backtest, no history

We owe a trustworthy current judgment — not reconstructable past. Point-in-time panels and bulk export are out of scope by design.

×

Fundamentals don't drive the call

Reported and inert. A 5-year ROIC is the wrong input for a multi-day swing. The one carve-out is event_risk — a timing risk in fundamentals' clothing.

×

No number you can't trace

Every consumable field is deterministic and pinned to a methodology_version. If score and timing_verdict could ever disagree, the design is wrong.

You found the right what.
Let us read the when.

Private beta, opening narrow and deep — semiconductors and semi-equipment first. The close-based baseline ships first; the live intraday overlay is the fast-follow.

baseline + live cadence versioned methodology JSON · CSV · bare list