The slow way, made survivable Chapter 14 of 23 Svenska

The map · Part Two · The machine · Chapter 14 of 23

How the program is put together

Seven kinds of piece and the walls between them. The interesting part is not what each piece does but what it is forbidden from doing. About 9 minutes.

The program is a set of small parts, each with one job, and the design question was never "what should each part do" but "what must each part be unable to do". This chapter walks the parts as a picture and then names the walls. There is no code in it.

The program's pieces and the walls between themBoxes for FETCH, THE RECORD, COMPUTE, REPORT and PAGE, SCREEN, WATCH and HEARTBEAT, with arrows showing figures flowing from outside feeds through fetch and the record to compute and the report. A purple box at the bottom, THE WATCHLIST, the owner's file, is separated from the pieces by a thick wall labelled: nothing that runs on a schedule may write below this line. A second wall separates compute from fetching. outside the machineprice feeds, filingsFETCHbrings figures inTHE RECORDkeeps every figureCOMPUTEno files, no networkREPORT and PAGEstate, never adviceSCREEN2,000 to a shortlistWATCHfilings and pricesHEARTBEATsays the run happenedwall: the arithmetic never fetcheswall: nothing that runs on a schedule may write below this lineTHE WATCHLIST: the owner's filestatuses, tiers, values, stops;every decision, written by handread onlysolid arrows: figures flowdashed: read, never writtenthick lines: walls in codethe ownerwrites here
Seven kinds of piece and two walls. Figures flow left to right and down. The owner's file sits below a wall that no scheduled piece can write across, and the arithmetic sits behind a wall that keeps it away from the network and the clock.

The seven kinds of piece

Fetching: bringing figures in from outside

One part fetches daily prices and keeps a copy on disk, so that when the price service is down the run has yesterday's figures marked as stale rather than nothing at all. Another reads the structured data American companies must file with their regulator. Two more read the Nordic exchanges' own disclosure feeds, which is where a Swedish or Norwegian company's reports actually appear. One reads a company's spreadsheet appendix through a map, committed with the code, that says which cell is which figure. One fetches a company's own report page and nothing else: it does not search, guess or follow links. And one hands a fetched document to a language model with a narrow instruction: pull out the stated figures and quote the sentence each came from; never derive, estimate or reconcile a figure, never decide whether something is material, never write prose.11Module descriptions in vss/fetch.py, vss/xbrl.py, vss/nordic.py, vss/oslo.py, vss/appendix.py, vss/source.py and vss/extract.py; README on the extractor: it 'never derives, estimates or reconciles a figure, never decides materiality, and never writes prose.'

The forbidden thing, for every fetcher: it may not judge what it fetched. It brings a figure in with its origin attached, and stops.

The record: keeping every figure

One part writes one row per company per run into a small database, so the history can be rebuilt later. One keeps the run record for each valuation, the eight things that must be declared before a value may be printed (chapter 15). One keeps a snapshot of every screening run, the raw prices and the list of names, so the run can be replayed exactly. One holds hand-entered figures for companies no feed serves, each marked as checked or not. One tests whether a price series is a real measurement or a feed artefact.22vss/store.py, vss/runrecord.py, vss/snapshot.py, vss/manual.py, vss/series_sanity.py.

The forbidden thing: the record never fills a gap. A figure that was not fetched is absent, and stays absent.

Computing: the arithmetic, kept pure

The parts that compute figures, apply the rules and solve the valuation do no input and no output. They do not read files, do not touch the network, and do not know what time it is; the date is always handed to them. This is a wall, not a convention: it means a computed figure can be reproduced later from the same inputs and will come out the same, because nothing in the computation could have depended on the world outside it.33The rules module: 'This module performs ZERO I/O. No file access, no network, no logging, and deliberately no datetime.now().' The metrics module is the same, with the as-of date always passed in.

Reporting: the report and the page

One part writes the nightly report in a fixed order: when the run happened and how fresh the data was; then blockers, the things that stopped a judgement; then actions, the things that need the owner; then the full table of every name. Another generates the one-page overview that reaches the phone (chapter 21). A third assembles a research briefing for a name being read, which is a collection of the figures and their sources, not a view.44vss/report.py, vss/overview.py, vss/briefing.py.

The forbidden thing: no report says buy, sell, or good. It says how far, how fresh, and what is missing.

The screen

The parts from chapter 4: the fixed list of names, the two filters, the ranking, and a wrapper that runs them on a Saturday morning. Plus one small part, and it is the only piece in the screener allowed to write into the owner's file: the one that enters a proposed name. It runs only when the owner starts it by hand.55vss/screen.py, vss/filters.py, vss/universe.py, vss/ranking.py, vss/screenwatch.py; vss/pipeline.py is 'the only module in the screener that writes to the file holding the owner's live positions', and the scheduled unit is started without the flag that would invoke it.

Watching

Two parts. One watches the disclosure feeds for the names on the waiting lists and reports only three kinds of document: a periodic report, a change to the company's own forecast, a profit warning. Everything else the exchange publishes is rejected and the rejection printed. The other watches the prices of the screener's top twenty against an indicative level and points, once, when a price crosses it. The level is a distance from a rough value, not a buy line, and the ruling says so.66vss/watch.py; vss/pricewatch.py, ruling E97: 'a distance, not a buy line'.

The heartbeat

One part whose only job is to make a run that did not happen look different from a run that had nothing to say. Chapter 18.

The runner

One part ties the nightly run together: load the owner's file, fetch, compute, assess, report. All the reading and writing of the run lives here and in the fetch, store and report parts, so that everything else can stay pure.77vss/runner.py: 'All I/O lives here and in fetch/store/report. rules.py and metrics.py stay pure.'

The two walls

The first wall is around the owner's file. It holds every status, every tier, every value, every stop: the decisions. No part that runs on a schedule may write to it. The refresh command asserts it did not. The scheduled screen's unit cannot write to the folder. A hand-typed buy price in the file fails the run outright, because a buy price must come from a value and a tier or it has no origin.88Rulings E92 and E93; README on the provenance conflict; the read-only configuration directory in deploy/vss-screen.service.

The second wall is around the arithmetic. Nothing that computes may fetch, and nothing that fetches may compute. A figure crosses from one side to the other only through the record, with its origin attached. This is what makes a number reproducible, and what makes a wrong number traceable to the fetch that brought it in rather than lost inside a calculation.

The commands, for the curious

The program is run from the command line as python -m vss followed by one of sixteen sub-commands. The ones a reader of this site has met: run (the nightly run), screen (the weekly screen), watch (disclosures), refresh (re-read a company's figures on a report date), earnings, xbrl, nordic, manual, appendix (the ways figures come in), briefing (assemble a reading), overview (the page), checkin (the heartbeat's own timer), sales (closed positions measured against the index), shadow (the shadow book). Every one of them prints a report to standard output and logs to standard error, and none of them writes a decision.

Sources for this chapter

  1. Module layout and each module's stated scope — read from this repository: vss/*.py module docstrings; vss/__main__.py; README.md

The slow way, made survivable. Built 2026-09-13 from the repository as it stood that day. NAME A and NAME B are fictional; no company, price or holding appears on this site. Not financial advice: one private investor's method, shared as it is.