# The model never gets to make up a number

_An LLM that writes a daily read on Vietnamese equities sounds useful right up until it invents a P/E ratio with total confidence. For anything with money attached, a plausible wrong number is worse than no number. So the model isn't allowed to produce one._

`running·live·VNStock`

## The one rule

Language models are pattern machines, not calculators. Ask one for a return or a moving average and it will happily emit something that _looks_ like an answer — sometimes right, sometimes off by a decimal, always delivered with the same even tone. In finance that tone is the danger.

> Code computes every number deterministically. The model is only ever allowed to reason on top of numbers it was handed — it never gets to make one up.

Everything about the system is arranged to enforce that one sentence. Reasoning is welcome; invention is designed out.

## The pipeline

The numbers are produced and locked before the model sees anything. Only the last step is an LLM, and it receives a finished scorecard, not raw data to "interpret".

```
collector  →  quant  →  state.diff  →  analyze  →  notify
(prices)    (metrics,  (what moved   (claude -p   (Telegram)
             all in     since last    reasons on
             code)      run)          the numbers)
```

The `quant` step owns every figure — returns, ratios, volatility, the lot — in plain, tested Python. `state.diff` decides what actually changed since the previous run, so the commentary is about movement, not noise. Only then does `claude -p` get invited, and its job is narrow: explain the numbers in front of it, in words, without ever restating a figure it wasn't given.

## Tests are the safety rail

Because the quant layer is the source of truth, it's the part that's guarded hardest: a suite of tests is the gate every change has to pass before it can ship or self-correct. If a metric's math drifts, a test goes red — long before a wrong number reaches a human reading it over morning coffee.

## Why this generalizes

This isn't really a stocks trick. It's the same line I keep drawing across every project in this log: let deterministic code own the facts, and let the model do the one thing it's genuinely good at — turning facts into language. The moment you let it own the facts too, you've built something that lies fluently. Keep the two jobs apart and you get a system you can actually trust in production.
