<?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: Bruno Costanzo</title>
    <description>The latest articles on DEV Community by Bruno Costanzo (@bruno_costanzo).</description>
    <link>https://dev.to/bruno_costanzo</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%2F625153%2F4c8aebf9-3252-4c8f-9112-6bafe3c2e94b.png</url>
      <title>DEV Community: Bruno Costanzo</title>
      <link>https://dev.to/bruno_costanzo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bruno_costanzo"/>
    <language>en</language>
    <item>
      <title>Fundamental analysis in Ruby, straight from SEC EDGAR</title>
      <dc:creator>Bruno Costanzo</dc:creator>
      <pubDate>Sun, 06 Sep 2026 19:49:41 +0000</pubDate>
      <link>https://dev.to/bruno_costanzo/fundamental-analysis-in-ruby-straight-from-sec-edgar-45b1</link>
      <guid>https://dev.to/bruno_costanzo/fundamental-analysis-in-ruby-straight-from-sec-edgar-45b1</guid>
      <description>&lt;p&gt;&lt;code&gt;fundamentalista&lt;/code&gt; is a Ruby gem for fundamental analysis of listed companies. Version 0.6.0 is on RubyGems.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Fundamentalista&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;edgar_user_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Acme Research research@acme.com"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;apple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Fundamentalista&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;company&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"AAPL"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;financials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latest&lt;/span&gt;

&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;income&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revenue&lt;/span&gt;              &lt;span class="c1"&gt;# BigDecimal&lt;/span&gt;
&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ratios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;roe&lt;/span&gt;
&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ratios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cash_conversion_cycle&lt;/span&gt;
&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;piotroski&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;score&lt;/span&gt;

&lt;span class="n"&gt;valuation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valuation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;price: &lt;/span&gt;&lt;span class="mi"&gt;230&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;valuation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pe&lt;/span&gt;
&lt;span class="n"&gt;valuation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fcf_yield&lt;/span&gt;
&lt;span class="n"&gt;valuation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;altman_z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zone&lt;/span&gt;          &lt;span class="c1"&gt;# =&amp;gt; :safe&lt;/span&gt;
&lt;span class="n"&gt;valuation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intrinsic_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;growth: &lt;/span&gt;&lt;span class="mf"&gt;0.06&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;discount_rate: &lt;/span&gt;&lt;span class="mf"&gt;0.09&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why another one
&lt;/h2&gt;

&lt;p&gt;Most fundamental data libraries wrap a paid API and hand you a hash. I wanted the shape of RubyLLM: small value objects, one obvious call per question, &lt;code&gt;nil&lt;/code&gt; when a filing lacks an input so a ratio never raises on an incomplete company, and &lt;code&gt;to_json&lt;/code&gt; on everything so it drops into a Rails view.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the data comes from
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SEC EDGAR&lt;/strong&gt; XBRL company facts. Free, no key, only a User-Agent with your contact. US GAAP and IFRS filers, in their reporting currency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial Modeling Prep&lt;/strong&gt; with a key, for quotes, estimates, prices, segments and exchange rates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;EDGAR is the interesting part. Companies tag the same idea under different concepts, so every line item has an ordered list of alternatives measured over the 500 largest filers with &lt;code&gt;script/coverage&lt;/code&gt;. Fourth quarters exist only as annual figures, so they are derived, except weighted average shares, which are not additive. Some filers negate expenses, some tag three currencies. Every figure remembers the concept, form and filing it came from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;source&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:revenue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;Fundamentalista::Source concept: "RevenueFromContractWithCustomerExcludingAssessedTax", form: "10-K", filed: 2025-10-31, derivation: :reported&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What is inside
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Income, balance and cash flow statements with derived lines (EBIT, EBITDA, free cash flow, net debt, working capital)&lt;/li&gt;
&lt;li&gt;Annual, quarterly and trailing twelve months periods&lt;/li&gt;
&lt;li&gt;Profitability, liquidity, leverage, efficiency and working capital ratios, DuPont, accruals&lt;/li&gt;
&lt;li&gt;Piotroski F, Altman Z, Beneish M, owner earnings&lt;/li&gt;
&lt;li&gt;Multiples, yields, Graham number, DCF with fading growth, reverse DCF, earnings power value, residual income, WACC&lt;/li&gt;
&lt;li&gt;Banking and insurance lines and ratios: net interest margin, cost of risk, combined ratio, the float&lt;/li&gt;
&lt;li&gt;Peer comparison with rankings, Greenblatt's magic formula and currency conversion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rails
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fundamentalista-rails&lt;/code&gt; is a mountable engine with watchlists that snapshot ratios and valuations per holding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;As-filed data has edges the gem documents rather than hides: stock splits are restated only in later filings, multi-class companies tag share counts per class, and a filer that negates a provision keeps its sign.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/bruno-costanzo/fundamentalista" rel="noopener noreferrer"&gt;https://github.com/bruno-costanzo/fundamentalista&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>finance</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
