<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Philip</title>
    <description>The latest articles on DEV Community by Philip (@philipvdb).</description>
    <link>https://dev.to/philipvdb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3966988%2Fdd22fdd0-16a5-4504-8562-0a3822e1a6ba.jpg</url>
      <title>DEV Community: Philip</title>
      <link>https://dev.to/philipvdb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/philipvdb"/>
    <language>en</language>
    <item>
      <title>I rewrote my calculators in a second language to test them. It found four wrong numbers.</title>
      <dc:creator>Philip</dc:creator>
      <pubDate>Mon, 31 Aug 2026 19:10:41 +0000</pubDate>
      <link>https://dev.to/philipvdb/i-rewrote-my-calculators-in-a-second-language-to-test-them-it-found-four-wrong-numbers-3i7k</link>
      <guid>https://dev.to/philipvdb/i-rewrote-my-calculators-in-a-second-language-to-test-them-it-found-four-wrong-numbers-3i7k</guid>
      <description>&lt;p&gt;I shipped a set of free investing calculators. Each one has a card on the index page showing a worked example: given these inputs, here is the answer.&lt;/p&gt;

&lt;p&gt;Last week I found that one of those cards said &lt;strong&gt;$2,282&lt;/strong&gt; while the calculator underneath it produced &lt;strong&gt;$1,160&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Nobody had complained. Every test passed. TypeScript was happy. The number had been wrong for weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this kind of bug is invisible
&lt;/h2&gt;

&lt;p&gt;The calculation lives in a React component. The published example lives somewhere else entirely, in a plain manifest file that feeds the index cards.&lt;/p&gt;

&lt;p&gt;Those two files have no relationship. Neither imports the other. So when I changed the model to let uninvested cash earn interest, the component's output moved and the manifest quietly did not.&lt;/p&gt;

&lt;p&gt;This is not a code bug. The code was correct the whole time. It is a &lt;strong&gt;claim&lt;/strong&gt; bug: the site asserted something that was no longer true, and no type system checks assertions about arithmetic.&lt;/p&gt;

&lt;p&gt;I suspect this is extremely common. Most products publish numbers somewhere, in a pricing table, a docs example, a README, a marketing card, and almost nobody has a test that says "the thing we told people is still what the software does."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a unit test would not have caught it
&lt;/h2&gt;

&lt;p&gt;The obvious fix is a unit test. But a unit test written against the same implementation only encodes whatever that implementation currently does. If I had asserted that the function returns 1,160, I would have been asserting that the code does what the code does. Useful for catching regressions, useless for catching a wrong published claim.&lt;/p&gt;

&lt;p&gt;What I actually needed to check was different: does the number we &lt;strong&gt;publish&lt;/strong&gt; match the number the tool &lt;strong&gt;produces&lt;/strong&gt;? That needs a second, independent implementation, ideally written by someone who read the description rather than the source.&lt;/p&gt;

&lt;p&gt;I do not have that someone. So I used a different language as a rough substitute for a different brain.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;A small script in Python that reimplements every calculator from scratch, then compares its results against the figures published on the site.&lt;/p&gt;

&lt;p&gt;Three decisions made it worth the afternoon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It reads the inputs out of the component source.&lt;/strong&gt; Rather than keeping its own copy of each calculator's default values, the script parses them out of the React files directly. If I change a default, the script picks it up automatically and the expected published figure fails. There is no second copy of the inputs to forget about, which is the failure mode that created the original bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It reimplements the maths from the description, not the code.&lt;/strong&gt; I worked from what each tool is supposed to do rather than translating the TypeScript line by line. Translating would have carried any logical error straight across into the test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where a closed form exists, it checks both.&lt;/strong&gt; The compound interest tool loops month by month. There is also a standard annuity formula that produces the same answer in one step. The script runs both and requires them to agree to nine decimal places. Two different routes arriving at the same number is much stronger evidence than one route agreeing with itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it found
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;102 checks. Four defects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The $2,282 that should have been $1,160.&lt;/p&gt;

&lt;p&gt;The same card describing the result as "ahead after &lt;strong&gt;11 years&lt;/strong&gt;" on a setup that runs for &lt;strong&gt;12 months&lt;/strong&gt;. Two separate errors in one sentence, both invisible because nobody re-reads a card they wrote months ago.&lt;/p&gt;

&lt;p&gt;An FAQ on the &lt;a href="https://intrinsiqq.com/tools/coast-fire" rel="noopener noreferrer"&gt;Coast FIRE calculator&lt;/a&gt; claiming that retiring at 55 instead of 65 raises the balance you need at 40 from $276,400 to $762,500. The real figure is &lt;strong&gt;$543,700&lt;/strong&gt;. I had built a correct lookup table of these values and then, two paragraphs later, transcribed the wrong row into prose. $762,500 is the ten-year horizon. Retiring at 55 when you are 40 is fifteen years.&lt;/p&gt;

&lt;p&gt;And two worked examples that quietly omitted inputs the tool actually uses. One said "$500 a month for 30 years" while the calculator also starts with $10,000 already invested, which makes the stated result impossible for a reader to reproduce.&lt;/p&gt;

&lt;p&gt;The third one is the one that bothers me. It was not stale data or a refactor. I did the arithmetic correctly, wrote the correct numbers into a table, and then quoted the wrong cell in a sentence underneath it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extending it past the outputs
&lt;/h2&gt;

&lt;p&gt;Once the script existed, the cheap win was pointing it at every number in the surrounding prose, not just the calculator results.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://intrinsiqq.com/tools/dividend-reinvestment" rel="noopener noreferrer"&gt;dividend reinvestment calculator&lt;/a&gt; has an explainer noting that over twenty years the annual income grows 5.9 times, and that this decomposes into the dividend per share growing 3.2 times multiplied by the share count growing 1.85 times. It is a satisfying line. It is also three numbers and a multiplication, every part of which can be wrong independently.&lt;/p&gt;

&lt;p&gt;So the script checks all three values, and then separately checks that multiplying the first two actually produces the third. That last check is about the sentence being internally consistent rather than about any single figure being right. If one number drifts, the claim stops holding together and the test fails. No human proofreader catches that on the fortieth read.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is worth stealing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Test the claims you publish, not only your functions.&lt;/strong&gt; Any number in marketing copy, a docs example or a card is an assertion your software should be able to verify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read the inputs from the source of truth.&lt;/strong&gt; A test carrying its own copy of the defaults passes happily forever after the defaults change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use a genuinely separate implementation for anything with real arithmetic.&lt;/strong&gt; A different language, a closed form, even a spreadsheet. Checking an implementation against itself only proves it is consistent with itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compare with tolerances rather than exact equality.&lt;/strong&gt; Floating point plus values displayed rounded means you want a small relative allowance, tight for derived maths and looser for anything shown to the nearest dollar.&lt;/p&gt;

&lt;p&gt;The whole thing runs in under a second and is roughly two hundred lines. It has already caught four things that were live on pages real people read.&lt;/p&gt;

&lt;p&gt;If you want to see what it is checking, the calculators are &lt;a href="https://intrinsiqq.com/tools" rel="noopener noreferrer"&gt;all here&lt;/a&gt;, free and with no account. But the transferable part is the idea rather than the tools: &lt;strong&gt;the numbers you publish are part of your product, and almost nobody tests them.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The SEC gives away every company's financials. Parsing them was the hard part</title>
      <dc:creator>Philip</dc:creator>
      <pubDate>Thu, 30 Jul 2026 14:01:54 +0000</pubDate>
      <link>https://dev.to/philipvdb/the-sec-gives-away-every-companys-financials-parsing-them-was-the-hard-part-41np</link>
      <guid>https://dev.to/philipvdb/the-sec-gives-away-every-companys-financials-parsing-them-was-the-hard-part-41np</guid>
      <description>&lt;p&gt;I build &lt;a href="https://intrinsiqq.com" rel="noopener noreferrer"&gt;Intrinsiqq&lt;/a&gt;, which computes quality scores, valuations and ten years of financials for around 7,800 listed companies. Every number comes from companies' own filings with the SEC.&lt;/p&gt;

&lt;p&gt;People assume the hard part was the finance. It was not. The hard part was that financial filing data is free, structured, machine readable, and constantly, quietly wrong in ways that do not announce themselves.&lt;/p&gt;

&lt;p&gt;I want to describe the shape of that problem, because I have not seen it written down anywhere and I would have saved months if someone had.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why build on filings at all
&lt;/h2&gt;

&lt;p&gt;Most finance sites buy aggregated data from a vendor. I went to the source instead, because filings are free, public, legally usable, and they contain what a company actually told a regulator rather than a vendor's cleaned-up interpretation. It means the numbers on my site reconcile with the annual report, and it is the reason the product can be free at all. I wrote up &lt;a href="https://intrinsiqq.com/blog/how-we-turn-sec-filings-into-stock-analysis" rel="noopener noreferrer"&gt;how the pipeline fits together&lt;/a&gt; if you want the overview.&lt;/p&gt;

&lt;p&gt;That decision was right. It was also much more expensive than I budgeted for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure mode is silence
&lt;/h2&gt;

&lt;p&gt;This is the thing I want to convey above everything else.&lt;/p&gt;

&lt;p&gt;When you consume a normal API and something is wrong, it fails. You get a 500, a schema mismatch, a null where you expected a number, and your monitoring tells you. Filing data does not behave like that. It hands you a number of the correct type, in the correct currency, in the correct shape, sitting in the correct field. And it is wrong.&lt;/p&gt;

&lt;p&gt;Nothing throws. Nothing logs. Your tests pass. The page renders. A revenue figure eight billion dollars short of reality looks exactly as convincing as a correct one, because there is no context in which it looks odd unless you already know what the answer should be.&lt;/p&gt;

&lt;p&gt;So the entire discipline of the project turned out to be: how do you detect being wrong when nothing tells you that you are?&lt;/p&gt;

&lt;h2&gt;
  
  
  Fiscal calendars do not agree with anything
&lt;/h2&gt;

&lt;p&gt;Roughly every assumption a developer brings to a date field is wrong here.&lt;/p&gt;

&lt;p&gt;Companies do not share a financial year. Some end in December, plenty do not. The year label attached to a filing describes the document, not the numbers inside it, and a single annual report carries several prior years of comparative figures all wearing the same label. Group by the obvious field and you quietly blend three different years into one.&lt;/p&gt;

&lt;p&gt;Then there are markers that look like they identify a quarter and actually identify a calendar period, which coincide for some companies and are months apart for others. Two of the largest companies in the world fall on the wrong side of that distinction. If your logic assumes those are the same thing, you misclassify a large fraction of your history and every derived figure inherits it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quarters are partly a fiction
&lt;/h2&gt;

&lt;p&gt;Companies file three quarterly reports and then an annual one. There is no fourth quarterly report. The fourth quarter exists only as the difference between the year and the three quarters you have, so anything quarterly has to be reconstructed rather than read.&lt;/p&gt;

&lt;p&gt;Reconstruction is where things get interesting, because it is arithmetic on top of data you have already possibly misclassified. Different statements in the same filing also cover different spans: some figures are for the three months just ended, others are cumulative from the start of the year. They sit side by side, look identical structurally, and mean different things. Treat them uniformly and your cash flow figures are inflated by a factor that grows as the year goes on.&lt;/p&gt;

&lt;p&gt;There is also a whole category of bugs where a reconstruction runs against incomplete inputs and produces something plausible instead of nothing. Those are the worst ones. A missing value you can catch. A confidently derived wrong value hides.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same number appears many times and the copies disagree
&lt;/h2&gt;

&lt;p&gt;Any given figure shows up in several filings across several years, and the versions differ, for legitimate reasons. Companies sell divisions and restate history so the comparison is like for like. Companies split their stock and restate per-share figures onto the new basis.&lt;/p&gt;

&lt;p&gt;Which means for every duplicate you have to decide which version you want, and the answer is not the same for all kinds of figures. Some of them you want as originally reported. Some of them you want as most recently restated. Pick one rule and apply it across the board, which is the obvious thing to do, and you will be wrong about a large slice of your data while being right about the rest, which makes it very hard to notice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every industry breaks your assumptions
&lt;/h2&gt;

&lt;p&gt;I built the first version around a normal operating company: revenue, costs, margins, cash flow, debt.&lt;/p&gt;

&lt;p&gt;Then I pointed it at a bank, and there was no revenue, because a bank's revenue is interest and it does not live where revenue lives. Debt is not a risk signal for a bank, it is the raw material. For a property company, the largest expense is a non-cash accounting entry, so the headline profit figure is close to meaningless and the cash figure is what matters. An insurer works differently again.&lt;/p&gt;

&lt;p&gt;The lesson generalised well past parsing. A single scoring framework applied to every industry produces confident nonsense, so we route several sectors to their own scorecards. I wrote about &lt;a href="https://intrinsiqq.com/blog/why-we-chose-these-quality-metrics" rel="noopener noreferrer"&gt;how we picked the metrics&lt;/a&gt; and why some industries get different rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Broad categories sweep in things you did not want
&lt;/h2&gt;

&lt;p&gt;My favourite bug, in hindsight.&lt;/p&gt;

&lt;p&gt;Where a specific figure was missing, I fell back to a broader category, which felt like sensible defensive design. Then a payroll processing company showed several billion dollars of investments it did not own, because the broad category included money the company merely holds on behalf of its clients. The correct figure was zero. Nothing looked wrong. It was a perfectly reasonable-looking balance sheet for a company with a five-billion-dollar hole in it.&lt;/p&gt;

&lt;p&gt;The general lesson: a fallback that is broader than the thing you are looking for is not a safety net, it is a slow leak. Better to show nothing than to show something adjacent.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would do differently
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Build the verification harness before the parser.&lt;/strong&gt; Almost every problem above was found by a person looking at a page and thinking "that cannot be right", not by a test. The only real defence against silent wrongness is checking computed output against totals the filing already states. Does the balance sheet balance? Do the parts sum to the whole? That is unglamorous and it would have caught most of this years earlier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treat "no data" as a legitimate answer.&lt;/strong&gt; A lot of my early bugs came from an instinct to always produce a number. Some companies genuinely have no debt. Some figures genuinely are not reported. Guessing to avoid a blank is how you turn a gap into a lie.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write down why, publicly.&lt;/strong&gt; We publish &lt;a href="https://intrinsiqq.com/methodology" rel="noopener noreferrer"&gt;a methodology page&lt;/a&gt; covering how each figure is computed, and a &lt;a href="https://intrinsiqq.com/editorial-standards" rel="noopener noreferrer"&gt;process for correcting errors&lt;/a&gt; when someone finds one. Partly that is a trust obligation for anything financial. Mostly it is that being forced to explain a calculation in plain language is what exposed several of these bugs, because a rule you cannot justify out loud is usually wrong.&lt;/p&gt;

&lt;p&gt;If you want to see the output, &lt;a href="https://intrinsiqq.com/stock/MSFT/financials" rel="noopener noreferrer"&gt;Microsoft's financials&lt;/a&gt; are built from filings through everything described here.&lt;/p&gt;

&lt;p&gt;If you are working on something similar and hitting a category of weirdness I have not mentioned, I would genuinely like to hear about it. I am fairly sure I have not found the last one.&lt;/p&gt;

</description>
      <category>api</category>
      <category>data</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why we score company quality the way we do (and why REITs and banks get different rules)</title>
      <dc:creator>Philip</dc:creator>
      <pubDate>Mon, 15 Jun 2026 14:09:54 +0000</pubDate>
      <link>https://dev.to/philipvdb/why-we-score-company-quality-the-way-we-do-and-why-reits-and-banks-get-different-rules-44pa</link>
      <guid>https://dev.to/philipvdb/why-we-score-company-quality-the-way-we-do-and-why-reits-and-banks-get-different-rules-44pa</guid>
      <description>&lt;p&gt;"Quality" is a vague word. Every investor agrees a quality company is good, and nobody agrees on how to measure it. When we built a free stock analyzer, we had to turn that vague word into a number between 0 and 100, which meant making real decisions about which metrics actually capture quality and which ones just look smart on a dashboard.&lt;/p&gt;

&lt;p&gt;Here is how we landed on the metrics we use, and the reasoning behind each.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eight metrics, four questions
&lt;/h2&gt;

&lt;p&gt;We did not want a soup of thirty ratios. More metrics feels rigorous but dilutes the signal: every weak metric you add drags the strong ones toward noise. So we forced ourselves down to four questions a quality investor actually asks, with two metrics each:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Is it cheap enough?&lt;/strong&gt; Price to earnings, and price to free cash flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is it growing?&lt;/strong&gt; Revenue growth, and free cash flow growth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is it well run?&lt;/strong&gt; Operating margin trend, and return on invested capital.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is it financially sound?&lt;/strong&gt; Share dilution, and net debt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each metric earns its place by answering something the others do not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why these specific eight
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Valuation: earnings and cash flow.&lt;/strong&gt; Price to earnings is the obvious one, but earnings can be massaged with accounting choices. So we pair it with price to free cash flow, which is much harder to fake, free cash flow is what is actually left after the business spends what it needs to. A company that looks cheap on earnings but expensive on cash flow is waving a flag, which is why we weight the cash-flow measure more heavily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Growth: revenue and cash.&lt;/strong&gt; Revenue growth shows demand. Free cash flow growth shows that the growth is turning into real money rather than just bookings. One without the other is a warning: fast revenue growth with no cash generation is how a lot of stories end badly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quality of the business: margins and returns.&lt;/strong&gt; We deliberately look at the margin &lt;em&gt;trend&lt;/em&gt;, not the absolute level. A 40 percent margin tells you about the past; a margin that is expanding tells you the business is getting stronger right now. And &lt;a href="https://intrinsiqq.com/blog/how-to-tell-if-a-company-is-high-quality" rel="noopener noreferrer"&gt;return on invested capital&lt;/a&gt; is the single best "is this actually a good business" number we know: it asks whether the company earns more than its cost of capital. A business that does not clear that bar is destroying value no matter how fast it grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Financial soundness: dilution and debt.&lt;/strong&gt; Share dilution is the quiet killer of returns. A company can grow revenue ten percent a year and still erode your stake by quietly printing shares, so we reward buybacks and penalize heavy issuance. For debt, the key decision was to measure net debt &lt;em&gt;relative to free cash flow&lt;/em&gt;, not in absolute dollars. A large debt number is terrifying for a small company and trivial for one generating enormous cash flow. What matters is whether the company can comfortably service it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why REITs get different rules
&lt;/h2&gt;

&lt;p&gt;This is where most simple scoring breaks, and where we had to build a separate scorecard. A real estate investment trust looks terrible through a normal lens, and that is the lens's fault, not the company's. REITs own buildings, and accounting forces them to record huge depreciation charges every year as if their properties are steadily becoming worthless. In reality, well-located real estate often appreciates. That depreciation crushes reported earnings, so a price to earnings ratio on a REIT is close to meaningless.&lt;/p&gt;

&lt;p&gt;The industry solved this long ago with a measure called Funds From Operations, which adds that non-cash depreciation back to get a truer picture of what the REIT actually earns. So our REIT scorecard throws out price to earnings and uses &lt;strong&gt;price to Funds From Operations&lt;/strong&gt; instead. We also swap in the metrics that actually matter for a landlord business: &lt;strong&gt;dividend coverage&lt;/strong&gt;, because REITs are income vehicles legally required to pay most of their income out, so the real question is whether they can sustain the dividend, and &lt;strong&gt;leverage measures&lt;/strong&gt; like debt to earnings and interest coverage, because real estate is a debt-heavy business by nature. Forcing a healthy REIT through a standard scorecard would wrongly mark it as garbage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why banks get different rules too
&lt;/h2&gt;

&lt;p&gt;Banks break the standard scorecard for a different reason: for a bank, debt is not a liability to minimize, it is the raw material of the business. A bank takes in deposits, which are debt, and lends them out. Penalizing a bank for having a lot of debt misunderstands what a bank is. Banks also do not have an operating margin in the normal sense.&lt;/p&gt;

&lt;p&gt;So the bank scorecard swaps in the measures lenders are actually judged on: &lt;strong&gt;price to book value&lt;/strong&gt; instead of price to cash flow, because banks are valued on the assets on their balance sheet; &lt;strong&gt;return on equity&lt;/strong&gt; instead of return on invested capital; &lt;strong&gt;book value per share growth&lt;/strong&gt;, the cleanest sign a bank is compounding; and &lt;strong&gt;capital adequacy&lt;/strong&gt;, which asks whether the bank holds enough equity to absorb losses without collapsing. That last one is the metric regulators themselves watch most closely, for good reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  The principle underneath all of it
&lt;/h2&gt;

&lt;p&gt;The lesson we kept relearning is that a quality score is only as good as its willingness to admit that "quality" means different things in different sectors. A single one-size scorecard is easy to build and quietly produces nonsense the moment it meets a bank or a REIT. The harder, more honest version recognizes that the right question for a software company is not the right question for a landlord or a lender.&lt;/p&gt;

&lt;p&gt;If you want to see it in action, you can &lt;a href="https://intrinsiqq.com/stock/MSFT" rel="noopener noreferrer"&gt;view a live quality score with the full per-metric breakdown&lt;/a&gt; for any of 8,000 plus US stocks, read the &lt;a href="https://intrinsiqq.com/methodology" rel="noopener noreferrer"&gt;full methodology&lt;/a&gt; including the exact thresholds we use, or see &lt;a href="https://intrinsiqq.com/blog/how-we-turn-sec-filings-into-stock-analysis" rel="noopener noreferrer"&gt;how we turn SEC filings into the underlying data&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I would genuinely love to hear which metrics you would weight differently. The thresholds are the part we still debate the most.&lt;/p&gt;

</description>
      <category>investing</category>
      <category>stocks</category>
      <category>saas</category>
      <category>datascience</category>
    </item>
    <item>
      <title>How We Turn SEC Filings Into Free Stock Analysis</title>
      <dc:creator>Philip</dc:creator>
      <pubDate>Wed, 03 Jun 2026 18:43:32 +0000</pubDate>
      <link>https://dev.to/philipvdb/how-we-turn-sec-filings-into-free-stock-analysis-2ji2</link>
      <guid>https://dev.to/philipvdb/how-we-turn-sec-filings-into-free-stock-analysis-2ji2</guid>
      <description>&lt;p&gt;Every number on &lt;strong&gt;Intrinsiqq&lt;/strong&gt; comes from one place: companies' own filings with the U.S. Securities and Exchange Commission. That sounds simple, but turning raw SEC XBRL data into clean quality scores, DCF valuations, and 10 years of financials for 8,000+ stocks is genuinely messy work. Here is how the pipeline works, and the parts that are harder than they look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why SEC EDGAR
&lt;/h2&gt;

&lt;p&gt;Most finance sites buy aggregated data from third-party vendors. &lt;a href="https://www.sec.gov/edgar" rel="noopener noreferrer"&gt;SEC EDGAR&lt;/a&gt; is the primary source underneath much of that data: it is free, public, and legally usable, and it contains exactly what companies reported to regulators, not consensus estimates or vendor adjustments. Building directly on it means the numbers you see match the 10-K and 10-Q, and it is why the analysis can stay free.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline, end to end
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pull the filings.&lt;/strong&gt; We read each company's structured financial data from the EDGAR XBRL CompanyFacts API, focused on the &lt;code&gt;us-gaap&lt;/code&gt; taxonomy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Map the concepts.&lt;/strong&gt; Each metric (revenue, free cash flow, debt, shares) is resolved through a chain of candidate XBRL tags, because companies do not all tag the same concept the same way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assemble trailing-twelve-month figures.&lt;/strong&gt; Quarterly filings are stitched into a rolling 12-month window so the numbers are current, not a year stale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compute the analysis.&lt;/strong&gt; From clean financials we derive the quality score, the DCF valuation, dividend safety, and the ratios.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why XBRL is messier than it looks
&lt;/h2&gt;

&lt;p&gt;The reason "just read the SEC data" is harder than it sounds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Challenge&lt;/th&gt;
&lt;th&gt;Why it is hard&lt;/th&gt;
&lt;th&gt;How we handle it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tag switching&lt;/td&gt;
&lt;td&gt;The same concept gets a different XBRL tag over time&lt;/td&gt;
&lt;td&gt;A prioritized fallback chain of tags per metric&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deriving Q4&lt;/td&gt;
&lt;td&gt;Q4 only appears inside the annual 10-K, not as a quarter&lt;/td&gt;
&lt;td&gt;Subtract Q1 + Q2 + Q3 from the annual total&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Year-to-date cash flow&lt;/td&gt;
&lt;td&gt;10-Q cash flow is cumulative YTD, not the quarter&lt;/td&gt;
&lt;td&gt;YTD math so quarters are not double-counted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duration vs instant&lt;/td&gt;
&lt;td&gt;Flows vs point-in-time balance-sheet values&lt;/td&gt;
&lt;td&gt;Sum flows over 4 quarters; take the latest for balances&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EPS&lt;/td&gt;
&lt;td&gt;Summing quarterly EPS mixes different share counts&lt;/td&gt;
&lt;td&gt;TTM net income divided by the latest share count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Foreign + fiscal years&lt;/td&gt;
&lt;td&gt;20-F filers, non-USD currencies, non-calendar years&lt;/td&gt;
&lt;td&gt;Currency fallbacks and filing-type handling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;None of this is glamorous. But it is the difference between numbers that match the filings and numbers that quietly drift from them. We chose to do the unglamorous part so the output is trustworthy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  From clean data to a verdict
&lt;/h2&gt;

&lt;p&gt;Once the financials are clean, the analysis is deterministic and fully documented. The &lt;a href="https://intrinsiqq.com/methodology" rel="noopener noreferrer"&gt;quality score&lt;/a&gt; is a weighted composite of eight fundamental checks; the &lt;a href="https://intrinsiqq.com/blog/how-does-a-dcf-work" rel="noopener noreferrer"&gt;DCF&lt;/a&gt; is a two-stage discounted cash flow you can adjust yourself; the dividend score weighs safety and growth. The same clean, TTM-assembled data also drives a fundamental charting tool, so any metric (or its historical valuation multiple) can be plotted over a decade and broken down by business segment. Every figure traces back to a specific filing, and the full methodology is public.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://intrinsiqq.com/stock/AAPL" rel="noopener noreferrer"&gt;See the output on a real stock: analyze AAPL free →&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Quality score, DCF fair value, and 10 years of SEC-sourced financials. Free, no account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why build it this way
&lt;/h2&gt;

&lt;p&gt;Building on the primary source is more work than licensing a feed, but it is what lets Intrinsiqq be free, transparent, and auditable. You can check any number against the original filing, and we can show our work on the &lt;a href="https://intrinsiqq.com/methodology" rel="noopener noreferrer"&gt;methodology page&lt;/a&gt;. For a tool meant to help people make real decisions, that traceability is the whole point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.sec.gov/edgar" rel="noopener noreferrer"&gt;SEC EDGAR: the XBRL CompanyFacts API and filings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://intrinsiqq.com/methodology" rel="noopener noreferrer"&gt;Intrinsiqq methodology: data sources, TTM assembly, and scoring&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://intrinsiqq.com/blog/how-we-turn-sec-filings-into-stock-analysis" rel="noopener noreferrer"&gt;intrinsiqq.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>programming</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
