Kartan · Del två · Maskinen · Kapitel 14 av 23
Hur programmet är uppbyggt
Sju sorters delar och väggarna mellan dem. Det intressanta är inte vad varje del gör utan vad den är förbjuden att göra. Ungefär 9 minuter.
Programmet är en uppsättning små delar, var och en med ett enda jobb, och konstruktionsfrågan var aldrig "vad ska varje del göra" utan "vad måste varje del vara oförmögen att göra". Det här kapitlet går igenom delarna som en bild och namnger sedan väggarna. Det finns ingen kod i det.
De sju sorternas delar
Hämtning: att föra in siffror utifrån
En del hämtar dagliga kurser och sparar en kopia på disk, så att körningen, när kurstjänsten ligger nere, har gårdagens siffror markerade som gamla i stället för ingenting alls. En annan läser den strukturerade data som amerikanska bolag måste lämna till sin tillsynsmyndighet. Ytterligare två läser de nordiska börsernas egna flöden för offentliggöranden, där ett svenskt eller norskt bolags rapporter faktiskt dyker upp. En läser ett bolags kalkylbladsbilaga via en karta, incheckad tillsammans med koden, som säger vilken cell som är vilken siffra. En hämtar ett bolags egen rapportsida och inget annat: den söker inte, gissar inte och följer inga länkar. Och en lämnar ett hämtat dokument till en språkmodell med en snäv instruktion: plocka ut de uppgivna siffrorna och citera meningen var och en kom från; härled, uppskatta eller stäm aldrig av en siffra, avgör aldrig om något är väsentligt, skriv aldrig någon löptext.11Modulbeskrivningar i vss/fetch.py, vss/xbrl.py, vss/nordic.py, vss/oslo.py, vss/appendix.py, vss/source.py och vss/extract.py; README om extraktorn: den 'härleder, uppskattar eller stämmer aldrig av en siffra, avgör aldrig väsentlighet och skriver aldrig löptext.'
Det förbjudna, för varje hämtare: den får inte döma det den hämtat. Den för in en siffra med dess ursprung fastsatt, och stannar där.
Registret: att spara varje siffra
En del skriver en rad per bolag och körning i en liten databas, så att historiken kan byggas upp igen senare. En för körningsprotokollet för varje värdering, de åtta saker som måste vara deklarerade innan ett värde får skrivas ut (kapitel 15). En sparar en ögonblicksbild av varje screeningkörning, de råa kurserna och listan över bolag, så att körningen kan spelas upp igen exakt. En håller handinmatade siffror för bolag som ingen datakälla täcker, var och en markerad som kontrollerad eller inte. En testar om en kursserie är en verklig mätning eller en artefakt från datakällan.22vss/store.py, vss/runrecord.py, vss/snapshot.py, vss/manual.py, vss/series_sanity.py.
Det förbjudna: registret fyller aldrig ett hål. En siffra som inte hämtades saknas, och fortsätter att saknas.
Beräkning: aritmetiken, hållen ren
De delar som räknar fram nyckeltal, tillämpar reglerna och löser värderingen gör ingen inmatning och ingen utmatning. De läser inga filer, rör inte nätverket och vet inte vad klockan är; datumet lämnas alltid till dem. Det här är en vägg, inte en konvention: det betyder att en uträknad siffra kan återskapas senare från samma indata och bli densamma, eftersom ingenting i beräkningen kunde ha berott på världen utanför.33Regelmodulen: 'Den här modulen gör NOLL I/O. Ingen filåtkomst, inget nätverk, ingen loggning och avsiktligt ingen datetime.now().' Nyckeltalsmodulen är likadan, med as-of-datumet alltid överlämnat.
Rapportering: rapporten och sidan
En del skriver nattrapporten i en fast ordning: när körningen skedde och hur färsk datan var; sedan blockeringar, det som stoppade en bedömning; sedan åtgärder, det som kräver ägaren; sedan hela tabellen över varje bolag. En annan genererar översiktssidan på en sida som når telefonen (kapitel 21). En tredje sätter ihop ett underlag för ett bolag som läses, en samling av siffrorna och deras källor, inte en uppfattning.44vss/report.py, vss/overview.py, vss/briefing.py.
Det förbjudna: ingen rapport säger köp, sälj eller bra. Den säger hur långt, hur färskt och vad som saknas.
Screeningen
Delarna från kapitel 4: den fasta listan över bolag, de två filtren, rangordningen och ett skal som kör dem en lördagsmorgon. Plus en liten del, och den är den enda delen i screenern som får skriva i ägarens fil: den som tar in ett föreslaget bolag. Den körs bara när ägaren startar den för hand.55vss/screen.py, vss/filters.py, vss/universe.py, vss/ranking.py, vss/screenwatch.py; vss/pipeline.py är 'den enda modulen i screenern som skriver till filen med ägarens levande positioner', och den schemalagda enheten startas utan den flagga som skulle anropa den.
Bevakning
Två delar. Den ena bevakar flödena för offentliggöranden för bolagen på väntelistorna och rapporterar bara tre sorters dokument: en periodisk rapport, en ändring av bolagets egen prognos, en vinstvarning. Allt annat börsen publicerar avvisas och avvisningen skrivs ut. Den andra bevakar kurserna för screenerns tjugo främsta mot en vägledande nivå och pekar, en gång, när en kurs korsar den. Nivån är ett avstånd från ett grovt värde, inte en köplinje, och beslutet säger det.66vss/watch.py; vss/pricewatch.py, beslut E97: 'ett avstånd, inte en köplinje'.
Hjärtslaget
En del vars enda uppgift är att få en körning som uteblev att se annorlunda ut än en körning som inte hade något att säga. Kapitel 18.
Körningsledaren
En del knyter ihop nattkörningen: läs in ägarens fil, hämta, räkna, bedöm, rapportera. All läsning och skrivning i körningen bor här och i delarna för hämtning, lagring och rapport, så att allt annat kan förbli rent.77vss/runner.py: 'All I/O bor här och i fetch/store/report. rules.py och metrics.py förblir rena.'
De två väggarna
Den första väggen går runt ägarens fil. Den rymmer varje status, varje nivå, varje värde, varje stopp: besluten. Ingen del som körs enligt schema får skriva i den. Uppdateringskommandot hävdar att det inte gjorde det. Den schemalagda screeningens enhet kan inte skriva i mappen. En handskriven köpkurs i filen får körningen att misslyckas rakt av, eftersom en köpkurs måste komma från ett värde och en nivå, annars har den inget ursprung.88Besluten E92 och E93; README om proveniensmotsägelsen; den skrivskyddade konfigurationsmappen i deploy/vss-screen.service.
Den andra väggen går runt aritmetiken. Inget som räknar får hämta, och inget som hämtar får räkna. En siffra tar sig från den ena sidan till den andra bara genom registret, med sitt ursprung fastsatt. Det är det som gör ett tal reproducerbart, och som gör att ett felaktigt tal kan spåras till hämtningen som förde in det i stället för att försvinna inuti en beräkning.
Kommandona, för den nyfikne
Programmet körs från kommandoraden som python -m vss följt av ett av sexton underkommandon. De som en läsare av den här webbplatsen har mött: run (nattkörningen), screen (veckoscreeningen), watch (offentliggöranden), refresh (läs om ett bolags siffror på rapportdagen), earnings, xbrl, nordic, manual, appendix (sätten som siffror kommer in), briefing (sätt ihop ett underlag), overview (sidan), checkin (hjärtslagets egen timer), sales (stängda positioner mätta mot index), shadow (skuggboken). Varje en av dem skriver en rapport till standard output och loggar till standard error, och ingen av dem skriver ett beslut.
Källor för det här kapitlet
- Modulernas uppbyggnad och vars och ens angivna omfång — läst ur det här repot: vss/*.py module docstrings; vss/__main__.py; README.md
Den långsamma vägen, gjord uthärdlig. Byggd 2026-09-13 ur repot som det såg ut den dagen. BOLAG A och BOLAG B är påhittade; inget bolag, ingen kurs och inget innehav förekommer på den här sajten. Inte finansiell rådgivning: en privatinvesterares metod, delad som den är.