All projects

Research system

Valuation App

A weekly research run that values groups of public companies six ways and keeps every result as history.

Role
Designed and built
When
2026 – present
Status
Private
Built with
Python, SEC EDGAR, pytest, mypy, ruff

Research log, still running

Every Sunday at 06:00, the research runs again.

This is the real run history, week by week: when each run started, how far each company got through the pipeline, and why the rest were set aside. The findings stay private, so there are no company names, values or rankings here, and the groups being studied carry generic labels.

Next run
Last run
Oct 18 Incomplete
Log updated
  • 9weeks on the log, since Sep 5
  • 4/6scheduled runs completed in full
  • 93companies tracked across 4 groups
  • 6/8data issues found and fixed
Companies valued each week

Weeks start on Sunday. Each bar is the run of record for that week: the scheduled run when there was one, otherwise the last manual run.

Week of Aug 30

Completed with warnings

Manual run, Sat Sep 5 at 21:00Ran for 63 min75 price requests refused for rate limitingBaseline run: the reference point for all later history

How far companies got

  1. In the groups93
  2. Identified86
  3. Filings loaded81
  4. Classified64
  5. Valued62

Why the rest were set aside

  • No recent filing15
  • Identifier could not be resolved6
  • Reports in a non-USD currency5
  • Fewer than two usable methods2
  • Business type not supported1
  • Exchange not supported1
  • Negative book value1

By group

GroupCompaniesValued
ETF holdings3026
Curated list A1814
Curated list B2520
Curated list C202

Warnings raised by the run

  • Curated list C: classification success rate 16% is below the 70% threshold

Flagged afterwards

Later audits found problems in this week's data. The history is kept as it was and marked, not rewritten.

  • DI-001 A delisted company valued against its frozen final price
  • DI-003 Negative method estimates averaged into the consensus
  • DI-004 Net income missed under alternative filing tags
  • DI-005 Data-quality scores understated for one company type

Other activity this week

Week of Sep 6

Completed with warnings

Manual run, Wed Sep 9 at 14:38Ran for 62 min20 price requests refused for rate limiting

How far companies got

  1. In the groups93
  2. Identified86
  3. Filings loaded81
  4. Classified69
  5. Valued62

Why the rest were set aside

  • Fewer than two usable methods7
  • Identifier could not be resolved6
  • No price available6
  • Reports in a non-USD currency5
  • Required figure missing from filings4
  • Business type not supported1
  • Exchange not supported1
  • Negative book value1

By group

GroupCompaniesValued
ETF holdings3026
Curated list A1814
Curated list B2515
Curated list C207

Warnings raised by the run

  • Curated list C: classification success rate 68% is below the 70% threshold

Flagged afterwards

Later audits found problems in this week's data. The history is kept as it was and marked, not rewritten.

  • DI-001 A delisted company valued against its frozen final price
  • DI-003 Negative method estimates averaged into the consensus
  • DI-004 Net income missed under alternative filing tags
  • DI-005 Data-quality scores understated for one company type
  • DI-006 Companies lost to price-provider rate limiting

Other activity this week

  • 3 configuration checks (dry runs, no data)

Week of Sep 13

Completed with warnings

Scheduled run, Sun Sep 13 at 15:14Started 9 h 15 min late (the machine was off or asleep at 06:00)Ran for 51 min67 price requests refused for rate limiting

How far companies got

  1. In the groups93
  2. Identified86
  3. Filings loaded81
  4. Classified65
  5. Valued63

Why the rest were set aside

  • No price available13
  • Identifier could not be resolved6
  • Reports in a non-USD currency5
  • Fewer than two usable methods2
  • Business type not supported1
  • Exchange not supported1
  • Required figure missing from filings1
  • Negative book value1

By group

GroupCompaniesValued
ETF holdings3026
Curated list A1814
Curated list B2520
Curated list C203

Warnings raised by the run

  • Curated list C: classification success rate 21% is below the 70% threshold

Flagged afterwards

Later audits found problems in this week's data. The history is kept as it was and marked, not rewritten.

  • DI-001 A delisted company valued against its frozen final price
  • DI-003 Negative method estimates averaged into the consensus
  • DI-004 Net income missed under alternative filing tags
  • DI-005 Data-quality scores understated for one company type
  • DI-006 Companies lost to price-provider rate limiting

Week of Sep 20

Failed

Scheduled run, Sun Sep 20 at 09:56Started 3 h 57 min late (the machine was off or asleep at 06:00)Ran for 1 min

No network at run time (preflight could not reach SEC EDGAR).

Week of Sep 27

Completed with warnings

Scheduled run, Sun Sep 27 at 11:40Started 5 h 40 min late (the machine was off or asleep at 06:00)Ran for 26 min

How far companies got

  1. In the groups93
  2. Identified86
  3. Filings loaded81
  4. Classified74
  5. Valued67

Why the rest were set aside

  • Fewer than two usable methods7
  • Identifier could not be resolved6
  • Reports in a non-USD currency5
  • Required figure missing from filings4
  • Business type not supported1
  • Exchange not supported1
  • Negative book value1
  • No price available1

By group

GroupCompaniesValued
ETF holdings3026
Curated list A1814
Curated list B2520
Curated list C207

Warnings raised by the run

  • Curated list C: classification success rate 68% is below the 70% threshold

Flagged afterwards

Later audits found problems in this week's data. The history is kept as it was and marked, not rewritten.

  • DI-001 A delisted company valued against its frozen final price
  • DI-003 Negative method estimates averaged into the consensus
  • DI-004 Net income missed under alternative filing tags
  • DI-005 Data-quality scores understated for one company type
  • DI-006 Companies lost to price-provider rate limiting

Week of Oct 4

Completed with warnings

Scheduled run, Sun Oct 4 at 10:16Started 4 h 16 min late (the machine was off or asleep at 06:00)Ran for 5 h 53 min95 price requests refused for rate limiting

How far companies got

  1. In the groups93
  2. Identified86
  3. Filings loaded79
  4. Classified56
  5. Valued53

Why the rest were set aside

  • No price available19
  • Identifier could not be resolved6
  • Reports in a non-USD currency5
  • Fewer than two usable methods3
  • No recent filing2
  • Required figure missing from filings2
  • Business type not supported1
  • Exchange not supported1
  • Negative book value1

By group

GroupCompaniesValued
ETF holdings3024
Curated list A1814
Curated list B2511
Curated list C204

Warnings raised by the run

  • Curated list B: classification success rate 52% is below the 70% threshold
  • Curated list C: classification success rate 32% is below the 70% threshold

Flagged afterwards

Later audits found problems in this week's data. The history is kept as it was and marked, not rewritten.

  • DI-001 A delisted company valued against its frozen final price
  • DI-003 Negative method estimates averaged into the consensus
  • DI-004 Net income missed under alternative filing tags
  • DI-005 Data-quality scores understated for one company type
  • DI-006 Companies lost to price-provider rate limiting

Week of Oct 11

Completed with warnings

Scheduled run, Sun Oct 11 at 10:57Started 4 h 57 min late (the machine was off or asleep at 06:00)Ran for 72 min113 price requests refused for rate limiting

How far companies got

  1. In the groups93
  2. Identified86
  3. Filings loaded81
  4. Classified56
  5. Valued53

Why the rest were set aside

  • No price available22
  • Identifier could not be resolved6
  • Reports in a non-USD currency5
  • Fewer than two usable methods3
  • Business type not supported1
  • Exchange not supported1
  • Required figure missing from filings1
  • Negative book value1

By group

GroupCompaniesValued
ETF holdings3026
Curated list A1814
Curated list B259
Curated list C204

Warnings raised by the run

  • Curated list B: classification success rate 43% is below the 70% threshold
  • Curated list C: classification success rate 32% is below the 70% threshold

Flagged afterwards

Later audits found problems in this week's data. The history is kept as it was and marked, not rewritten.

  • DI-001 A delisted company valued against its frozen final price
  • DI-003 Negative method estimates averaged into the consensus
  • DI-004 Net income missed under alternative filing tags
  • DI-005 Data-quality scores understated for one company type
  • DI-006 Companies lost to price-provider rate limiting

Week of Oct 18

Incomplete

Scheduled run, Sun Oct 18 at 08:57Ran for 54 min106 price requests refused for rate limiting

Stopped before the last group finished; no run record was written.

How far companies got

  1. In the groups73
  2. Identified67
  3. Filings loaded62
  4. Classified50
  5. Valued49

Why the rest were set aside

  • No price available11
  • Identifier could not be resolved6
  • Reports in a non-USD currency5
  • Fewer than two usable methods1
  • Business type not supported1

By group

GroupCompaniesValued
ETF holdings3026
Curated list A1814
Curated list B259
Curated list CNot reached this week

Flagged afterwards

Later audits found problems in this week's data. The history is kept as it was and marked, not rewritten.

  • DI-001 A delisted company valued against its frozen final price
  • DI-003 Negative method estimates averaged into the consensus
  • DI-004 Net income missed under alternative filing tags
  • DI-005 Data-quality scores understated for one company type
  • DI-006 Companies lost to price-provider rate limiting

Week of Oct 25

Scheduled

The next run is set for . It will be the first with the fixes from the latest round of work: one shared price budget with a second provider as fallback, a stale-price gate, and negative estimates kept out of the consensus.

Show every week as a table
Run of record for each week
Week ofStatusStartedDurationCompaniesValuedRate-limited
Aug 30Completed with warningsSat 21:0063 min936275
Sep 6Completed with warningsWed 14:3862 min936220
Sep 13Completed with warningsSun 15:1451 min936367
Sep 20FailedSun 09:561 min000
Sep 27Completed with warningsSun 11:4026 min93670
Oct 4Completed with warningsSun 10:165 h 53 min935395
Oct 11Completed with warningsSun 10:5772 min9353113
Oct 18IncompleteSun 08:5754 min7349106
Oct 25Scheduled—————

Data issues register

Problems found by auditing past runs. Each one is fixed at the root, and the affected history is flagged instead of rewritten.

  • DI-001high Fixed

    A delisted company valued against its frozen final price

    The price provider kept serving a final close after an acquisition. A stale-price gate now excludes any price more than seven days old.

    Found Oct 20. Marked in 7 weeks of history.

  • DI-002high Fixed

    Month-old cached prices served as "latest"

    The first two baseline-day runs read prices from a month-old cache. Fixed the same day; the baseline run itself is unaffected.

    Found Sep 6. Marked in 1 week of history.

  • DI-003high Fixed

    Negative method estimates averaged into the consensus

    A negative DCF could drag a consensus below every positive method. Non-positive estimates are now dropped before blending.

    Found Oct 20. Marked in 7 weeks of history.

  • DI-004medium Fixed

    Net income missed under alternative filing tags

    Some filers report net income under less common XBRL tags. Tag fallbacks added; affected observations are kept but read with caution.

    Found Oct 20. Marked in 7 weeks of history.

  • DI-005low Fixed

    Data-quality scores understated for one company type

    Some companies were marked down for figures their industry does not report. Required figures now depend on the company type.

    Found Oct 20. Marked in 7 weeks of history.

  • DI-006medium Fixed

    Companies lost to price-provider rate limiting

    Each group started with its own request budget, so later groups ran out. One shared budget, no futile retries, and a second price provider as fallback.

    Found Oct 20. Marked in 6 weeks of history.

  • DI-007low Open

    Missing weeks from failed or interrupted runs

    Gaps rather than errors. Runs now record themselves at start, so an interruption is flagged instead of leaving no trace.

    Found Oct 20. A gap or coverage problem; no stored result is affected.

  • DI-008medium Open

    One group structurally under-covered

    Most of one group never reaches two usable methods because of AFFO and share-count gaps in filings. Needs per-filer work.

    Found Oct 20. A gap or coverage problem; no stored result is affected.

Work on the system

  1. Research data audit
  2. Diagnose why the weekly scheduled runs were losing companies, fix Tiingo rate limiting
  3. A large, single-session build-out of two new layers on top of the S1–S6 scanner
  4. Documentation deliverable
  1. Problem

    Valuing a company properly means pulling filings, normalising the numbers and running several models. Doing that across a whole sector every week by hand isn't realistic, and a spreadsheet quietly overwrites last week's thinking with this week's.

  2. Approach

    Treat research as a repeatable run instead of a one-off analysis: gather the data, value every company with several methods, blend them into one consensus with a confidence score, and store each run as point-in-time history that can be compared and audited later. It never trades.

  3. Implementation

    A Python command-line pipeline. SEC EDGAR is the system of record for filings and fundamentals; a market data provider supplies prices, with a fallback when it's rate-limited. Six methods run per company (DCF, Graham, relative, residual income, DDM and AFFO), and non-positive estimates are dropped before blending. Scans can target curated lists, SIC sectors or ETF holdings. Stale prices are detected and excluded, known data issues are kept in a register, and affected runs are flagged rather than rewritten. Strict typing with mypy, a pytest suite and ruff.

  4. Outcome

    Runs unattended every week as a scheduled task, and the research log above is its real run history, refreshed after each run. The findings stay private; what's shown here is how the system runs, not what it found.