<?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: Kevin Meneses González</title>
    <description>The latest articles on DEV Community by Kevin Meneses González (@kevin_menesesgonzlez).</description>
    <link>https://dev.to/kevin_menesesgonzlez</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%2F2412421%2F23a50b66-3e3e-4d13-8809-9bc0b03c0f40.png</url>
      <title>DEV Community: Kevin Meneses González</title>
      <link>https://dev.to/kevin_menesesgonzlez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kevin_menesesgonzlez"/>
    <language>en</language>
    <item>
      <title>Best Stock Market API for Python Developers (2026)</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Fri, 10 Jul 2026 11:17:45 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/best-stock-market-api-for-python-developers-2026-11h2</link>
      <guid>https://dev.to/kevin_menesesgonzlez/best-stock-market-api-for-python-developers-2026-11h2</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Scraping and unofficial wrappers like &lt;code&gt;yfinance&lt;/code&gt; break in production. For Python projects that need historical + real-time stock data without stitching together multiple providers, EODHD offers the widest coverage (150,000+ tickers, 70+ exchanges) under one API key. Massive is a strong alternative for low-latency US real-time feeds, Alpha Vantage works for prototyping, and &lt;code&gt;yfinance&lt;/code&gt; should stay limited to personal scripts.&lt;/p&gt;

&lt;p&gt;Many developers believe you need to pay hundreds of dollars a month for reliable stock market data in Python. That's not true.&lt;/p&gt;

&lt;p&gt;The real problem isn't price. It's picking the wrong API before you know what production actually demands.&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building a stock screener,&lt;/li&gt;
&lt;li&gt;backtesting a trading strategy,&lt;/li&gt;
&lt;li&gt;or adding market data to a fintech app,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this decision will follow you for months. Get it wrong and you rebuild the whole data layer later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scraping Works Until It Doesn't
&lt;/h2&gt;

&lt;p&gt;Most Python developers start the same way. &lt;code&gt;yfinance&lt;/code&gt;, a scraping script, maybe an unofficial endpoint someone shared on GitHub.&lt;/p&gt;

&lt;p&gt;It works. In local testing.&lt;/p&gt;

&lt;p&gt;Then it hits production.&lt;/p&gt;

&lt;p&gt;Rate limits appear out of nowhere. Endpoints change without warning. A field that returned a float last month now returns a string. Your script that ran perfectly on Tuesday throws a &lt;code&gt;KeyError&lt;/code&gt; on Wednesday.&lt;/p&gt;

&lt;p&gt;Developers often discover this too late — after building an entire pipeline around a source that was never meant to be an API in the first place.&lt;/p&gt;

&lt;p&gt;The symptoms are always the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Silent failures during market hours&lt;/li&gt;
&lt;li&gt;Historical data with random gaps&lt;/li&gt;
&lt;li&gt;No SLA, no support, no changelog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is a coding problem. It's an infrastructure problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem Is Infrastructure, Not Data
&lt;/h2&gt;

&lt;p&gt;Stock data itself isn't scarce. Every exchange publishes it.&lt;/p&gt;

&lt;p&gt;The real problem is structure: getting that data through a stable, documented, rate-limit-transparent REST API instead of a scraper held together with &lt;code&gt;try/except&lt;/code&gt; blocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Actually Look For
&lt;/h2&gt;

&lt;p&gt;Before picking any stock market API for a Python project, check for four things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A real REST API&lt;/strong&gt; — documented endpoints, not reverse-engineered JSON from a webpage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear rate limits&lt;/strong&gt; — published numbers, not "fair use" vagueness&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Both historical and real-time coverage&lt;/strong&gt; — screeners need history, alerts need live data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean JSON responses&lt;/strong&gt; — no HTML parsing, no regex, no fragile scraping logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After testing multiple providers for backtesting and screener projects, I consistently reach for &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-stock-market-api-python-developers&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;EODHD&lt;/a&gt; for this type of work. Here's why.&lt;/p&gt;

&lt;p&gt;EODHD covers over 150,000 tickers across 70+ exchanges, with end-of-day, intraday, and real-time endpoints under one API key. That means one integration instead of stitching together three providers for three data types.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you're a software or API company looking to explain your product through high-quality educational content (not marketing fluff), feel free to connect with me on LinkedIn.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Getting Stock Data in Python: A Working Example
&lt;/h2&gt;

&lt;p&gt;Let's pull historical daily prices for a single ticker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests pandas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_api_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAPL.US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://eodhd.com/api/eod/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fmt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;period&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]].&lt;/span&gt;&lt;span class="nf"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csvs"&gt;&lt;code&gt;        &lt;span class="k"&gt;date&lt;/span&gt;    &lt;span class="k"&gt;open&lt;/span&gt;    &lt;span class="k"&gt;high&lt;/span&gt;     &lt;span class="k"&gt;low&lt;/span&gt;   &lt;span class="k"&gt;close&lt;/span&gt;    &lt;span class="k"&gt;volume&lt;/span&gt;
&lt;span class="mf"&gt;495&lt;/span&gt;  &lt;span class="ld"&gt;2026-06-24&lt;/span&gt;  &lt;span class="mf"&gt;198.31&lt;/span&gt;  &lt;span class="mf"&gt;200.12&lt;/span&gt;  &lt;span class="mf"&gt;197.85&lt;/span&gt;  &lt;span class="mf"&gt;199.40&lt;/span&gt;  &lt;span class="mf"&gt;48213500&lt;/span&gt;
&lt;span class="mf"&gt;496&lt;/span&gt;  &lt;span class="ld"&gt;2026-06-25&lt;/span&gt;  &lt;span class="mf"&gt;199.50&lt;/span&gt;  &lt;span class="mf"&gt;201.03&lt;/span&gt;  &lt;span class="mf"&gt;198.90&lt;/span&gt;  &lt;span class="mf"&gt;200.77&lt;/span&gt;  &lt;span class="mf"&gt;39871200&lt;/span&gt;
&lt;span class="mf"&gt;497&lt;/span&gt;  &lt;span class="ld"&gt;2026-06-26&lt;/span&gt;  &lt;span class="mf"&gt;200.90&lt;/span&gt;  &lt;span class="mf"&gt;202.44&lt;/span&gt;  &lt;span class="mf"&gt;199.75&lt;/span&gt;  &lt;span class="mf"&gt;201.15&lt;/span&gt;  &lt;span class="mf"&gt;41205300&lt;/span&gt;
&lt;span class="mf"&gt;498&lt;/span&gt;  &lt;span class="ld"&gt;2026-06-29&lt;/span&gt;  &lt;span class="mf"&gt;201.20&lt;/span&gt;  &lt;span class="mf"&gt;203.01&lt;/span&gt;  &lt;span class="mf"&gt;200.44&lt;/span&gt;  &lt;span class="mf"&gt;202.63&lt;/span&gt;  &lt;span class="mf"&gt;36994800&lt;/span&gt;
&lt;span class="mf"&gt;499&lt;/span&gt;  &lt;span class="ld"&gt;2026-06-30&lt;/span&gt;  &lt;span class="mf"&gt;202.70&lt;/span&gt;  &lt;span class="mf"&gt;204.15&lt;/span&gt;  &lt;span class="mf"&gt;201.98&lt;/span&gt;  &lt;span class="mf"&gt;203.29&lt;/span&gt;  &lt;span class="mf"&gt;44012700&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a stock screener that filters by volume or volatility&lt;/li&gt;
&lt;li&gt;a backtesting engine for a trading strategy&lt;/li&gt;
&lt;li&gt;a real-time alert system on top of the same API key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No scraper to maintain. No parsing HTML. Just a request and a DataFrame.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing the Top Stock Market APIs for Python
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. EODHD — Broad coverage, one API for everything
&lt;/h3&gt;

&lt;p&gt;Covers historical, real-time, and fundamental data across global exchanges through a single REST API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;150,000+ tickers across 70+ exchanges&lt;/li&gt;
&lt;li&gt;Historical, real-time, and fundamentals in one API key&lt;/li&gt;
&lt;li&gt;Free tier available for testing before committing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time data has a short delay on the lowest-tier plans&lt;/li&gt;
&lt;li&gt;Some fundamental endpoints require a paid plan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; developers who need historical + real-time + fundamentals without juggling three providers.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Alpha Vantage — Good for prototyping
&lt;/h3&gt;

&lt;p&gt;A free-tier-first API popular for quick prototypes and learning projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generous free tier for low-volume testing&lt;/li&gt;
&lt;li&gt;Well-documented technical indicator endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rate limits are restrictive (5 calls/minute on the free tier)&lt;/li&gt;
&lt;li&gt;Real-time data requires a premium plan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; early-stage prototypes and academic projects, not production systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Massive — Strong for US real-time data
&lt;/h3&gt;

&lt;p&gt;Focused heavily on US equities and options with fast real-time feeds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low-latency real-time data for US markets&lt;/li&gt;
&lt;li&gt;WebSocket support for live streaming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited international exchange coverage&lt;/li&gt;
&lt;li&gt;Pricier at the tiers where real-time data actually becomes usable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; US-focused trading applications that need speed over breadth (formerly Polygon.io, now rebranded as Massive).&lt;/p&gt;

&lt;h3&gt;
  
  
  4. yfinance — Fine for personal projects, risky for production
&lt;/h3&gt;

&lt;p&gt;An unofficial wrapper around Yahoo Finance's internal endpoints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free and instantly usable&lt;/li&gt;
&lt;li&gt;No API key required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not an official API — Yahoo can change the underlying structure anytime&lt;/li&gt;
&lt;li&gt;No SLA, no support, frequent silent breakages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; personal scripts and one-off analysis, never production systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  How These Fit Together
&lt;/h2&gt;

&lt;p&gt;If you're testing an idea over a weekend, &lt;code&gt;yfinance&lt;/code&gt; is fine.&lt;/p&gt;

&lt;p&gt;The moment that idea becomes a screener, a dashboard, or anything a client depends on, move to a documented REST API.&lt;/p&gt;

&lt;p&gt;EODHD covers the widest range of use cases — historical, real-time, and fundamentals — without forcing you to combine multiple providers just to cover the basics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A stock market API is infrastructure, not just a data source — treat the decision like one&lt;/li&gt;
&lt;li&gt;Documented REST endpoints beat scraping every time production matters&lt;/li&gt;
&lt;li&gt;Free tiers are enough to validate the integration before paying for anything&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;❓ Is there a free stock market API for Python?&lt;br&gt;
✅ Yes. EODHD, Alpha Vantage, and yfinance all offer free access. EODHD's free tier is the most practical for testing real projects since it includes both historical and limited real-time data under one key.&lt;/p&gt;

&lt;p&gt;❓ What's the best stock API for real-time data?&lt;br&gt;
✅ For US-only real-time feeds, Massive is strong. For global coverage combined with real-time data, EODHD covers more exchanges without needing a second provider.&lt;/p&gt;

&lt;p&gt;❓ Can I use yfinance in a production app?&lt;br&gt;
✅ Not recommended. It relies on unofficial Yahoo Finance endpoints with no SLA, so it can break without warning. Use it for prototypes only.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-stock-market-api-python-developers&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Get started with EODHD&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You'll get access to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Historical + real-time data across 70+ exchanges&lt;/li&gt;
&lt;li&gt;A free tier to test before committing&lt;/li&gt;
&lt;li&gt;Fundamentals and technical indicators under the same key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real question isn't which API has the most features. It's which one you can still trust in six months.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>stocks</category>
      <category>python</category>
      <category>api</category>
      <category>data</category>
    </item>
    <item>
      <title>I Let Claude Screen 3,000 Stocks Using the EODHD API — Here's What Made the Cut</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Fri, 10 Jul 2026 07:10:00 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/i-let-claude-screen-3000-stocks-using-the-eodhd-api-heres-what-made-the-cut-2eap</link>
      <guid>https://dev.to/kevin_menesesgonzlez/i-let-claude-screen-3000-stocks-using-the-eodhd-api-heres-what-made-the-cut-2eap</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I built a 4-stage screening funnel on top of the EODHD Screener API, starting from a universe of 3,000+ US-listed stocks with a market cap above $150M. After filtering for profitability, liquidity, and a fair price relative to earnings, only 10 names survived. No hype, no "buy this now." I also cover two ways to extend this: connecting through EODHD's official MCP server so Claude can run the screen conversationally, and a cron-based script that runs the whole funnel every day and flags what changed. Full list, code, and setup below.&lt;/p&gt;




&lt;p&gt;Most "AI picks stocks" content is theater.&lt;/p&gt;

&lt;p&gt;Someone asks ChatGPT to "recommend 5 undervalued stocks," the model pulls from stale training data, and the article calls it analysis. No live data. No verifiable filter. No way for the reader to reproduce a single number.&lt;/p&gt;

&lt;p&gt;I wanted to do the opposite.&lt;/p&gt;

&lt;p&gt;So I built a real screening pipeline: Claude connected directly to the EODHD Stock Screener API, ran a live query against thousands of tickers, and narrowed them down using nothing but hard numeric filters. Every ticker, every price, every EPS figure in this article came from that live call, made on the day this was written.&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building a quant screening tool,&lt;/li&gt;
&lt;li&gt;evaluating financial data APIs for an AI agent,&lt;/li&gt;
&lt;li&gt;or just tired of "AI stock picks" content with zero data behind it,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With Most Stock Screeners
&lt;/h2&gt;

&lt;p&gt;Free screeners on the big finance sites give you a handful of filters: market cap, sector, maybe a P/E range. Fine for a Sunday afternoon. Useless if you're trying to build something programmatic.&lt;/p&gt;

&lt;p&gt;Paid terminals solve the flexibility problem but cost more than most independent investors are willing to spend just to test an idea.&lt;/p&gt;

&lt;p&gt;And "AI-powered" stock tools usually skip the data problem entirely. They generate plausible-sounding tickers based on pattern matching, not a live query against an actual market database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real bottleneck isn't intelligence. It's access to structured, filterable data that an AI model can actually query.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving Claude a Real Data Source
&lt;/h2&gt;

&lt;p&gt;EODHD's Screener API exposes exactly what a filtering pipeline needs: market capitalization, EPS, dividend yield, trading volume, sector, and price, across every ticker on the exchange, in one request.&lt;/p&gt;

&lt;p&gt;Once Claude can call that endpoint directly, "screen the market" stops being a metaphor. It becomes a real, auditable sequence of API calls.&lt;/p&gt;

&lt;p&gt;Here's the funnel I ran:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Stage 1 — Universe:&lt;/strong&gt; US-listed common stocks with market cap &amp;gt; $150M&lt;br&gt;
&lt;strong&gt;Stage 2 — Quality filter:&lt;/strong&gt; profitable (positive EPS), liquid (200K+ average daily volume), priced above $5&lt;br&gt;
&lt;strong&gt;Stage 3 — Value zone:&lt;/strong&gt; market cap between $1B and $50B, dividend-paying, still liquid&lt;br&gt;
&lt;strong&gt;Stage 4 — Ranking:&lt;/strong&gt; sorted by earnings yield (EPS ÷ price) — the cheapest stocks relative to what they actually earn&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Stage 1 alone returned more than 1,000 matches per page and kept going past the API's pagination cap — confirming a universe well north of 3,000 tickers once you include every US exchange EODHD covers at that market cap floor. From there, each stage cuts the field down hard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Screener
&lt;/h2&gt;

&lt;p&gt;The setup is a single authenticated GET request per stage. No scraping, no manual downloads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://eodhd.com/api/screener&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_screen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization.desc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;offset&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Stage 2 + 3 combined: profitable, liquid, mid/large-cap, dividend-paying
&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,1000000000],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,50000000000],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exchange&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_share&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,0],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avgvol_1d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,300000],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,5],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dividend_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,0]]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_screen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_share&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;implied_pe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;top10&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top10&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sector&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_share&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dividend_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole pipeline. No manual screening, no spreadsheet gymnastics — just filters chained on top of each other until the list is short enough to actually read.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Made the Cut
&lt;/h2&gt;

&lt;p&gt;Out of the 3,000+ stock universe, these 10 names survived every filter: profitable, liquid, mid-to-large cap, and cheapest relative to their own earnings on the day of the screen.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ticker&lt;/th&gt;
&lt;th&gt;Company&lt;/th&gt;
&lt;th&gt;Sector&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;EPS&lt;/th&gt;
&lt;th&gt;Earnings Yield&lt;/th&gt;
&lt;th&gt;Implied P/E&lt;/th&gt;
&lt;th&gt;Dividend Yield&lt;/th&gt;
&lt;th&gt;Market Cap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JBS&lt;/td&gt;
&lt;td&gt;JBS N.V.&lt;/td&gt;
&lt;td&gt;Consumer Defensive (Packaged Foods)&lt;/td&gt;
&lt;td&gt;$11.82&lt;/td&gt;
&lt;td&gt;$1.62&lt;/td&gt;
&lt;td&gt;13.7%&lt;/td&gt;
&lt;td&gt;~7.3x&lt;/td&gt;
&lt;td&gt;8.2%&lt;/td&gt;
&lt;td&gt;$40.1B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EIX&lt;/td&gt;
&lt;td&gt;Edison International&lt;/td&gt;
&lt;td&gt;Utilities (Regulated Electric)&lt;/td&gt;
&lt;td&gt;$74.78&lt;/td&gt;
&lt;td&gt;$9.20&lt;/td&gt;
&lt;td&gt;12.3%&lt;/td&gt;
&lt;td&gt;~8.1x&lt;/td&gt;
&lt;td&gt;4.5%&lt;/td&gt;
&lt;td&gt;$28.8B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GFI&lt;/td&gt;
&lt;td&gt;Gold Fields Ltd ADR&lt;/td&gt;
&lt;td&gt;Basic Materials (Gold)&lt;/td&gt;
&lt;td&gt;$32.88&lt;/td&gt;
&lt;td&gt;$3.94&lt;/td&gt;
&lt;td&gt;12.0%&lt;/td&gt;
&lt;td&gt;~8.3x&lt;/td&gt;
&lt;td&gt;6.9%&lt;/td&gt;
&lt;td&gt;$30.0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PYPL&lt;/td&gt;
&lt;td&gt;PayPal Holdings&lt;/td&gt;
&lt;td&gt;Financial Services (Credit Services)&lt;/td&gt;
&lt;td&gt;$44.53&lt;/td&gt;
&lt;td&gt;$5.33&lt;/td&gt;
&lt;td&gt;12.0%&lt;/td&gt;
&lt;td&gt;~8.4x&lt;/td&gt;
&lt;td&gt;0.9%&lt;/td&gt;
&lt;td&gt;$40.3B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VICI&lt;/td&gt;
&lt;td&gt;VICI Properties&lt;/td&gt;
&lt;td&gt;Real Estate (REIT – Gaming)&lt;/td&gt;
&lt;td&gt;$26.09&lt;/td&gt;
&lt;td&gt;$2.92&lt;/td&gt;
&lt;td&gt;11.2%&lt;/td&gt;
&lt;td&gt;~8.9x&lt;/td&gt;
&lt;td&gt;6.7%&lt;/td&gt;
&lt;td&gt;$29.5B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUK&lt;/td&gt;
&lt;td&gt;Prudential PLC ADR&lt;/td&gt;
&lt;td&gt;Financial Services (Life Insurance)&lt;/td&gt;
&lt;td&gt;$27.36&lt;/td&gt;
&lt;td&gt;$3.02&lt;/td&gt;
&lt;td&gt;11.0%&lt;/td&gt;
&lt;td&gt;~9.1x&lt;/td&gt;
&lt;td&gt;1.0%&lt;/td&gt;
&lt;td&gt;$34.5B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HIG&lt;/td&gt;
&lt;td&gt;Hartford Financial&lt;/td&gt;
&lt;td&gt;Financial Services (Insurance)&lt;/td&gt;
&lt;td&gt;$138.74&lt;/td&gt;
&lt;td&gt;$14.12&lt;/td&gt;
&lt;td&gt;10.2%&lt;/td&gt;
&lt;td&gt;~9.8x&lt;/td&gt;
&lt;td&gt;1.6%&lt;/td&gt;
&lt;td&gt;$38.0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EQT&lt;/td&gt;
&lt;td&gt;EQT Corporation&lt;/td&gt;
&lt;td&gt;Energy (Oil &amp;amp; Gas E&amp;amp;P)&lt;/td&gt;
&lt;td&gt;$51.16&lt;/td&gt;
&lt;td&gt;$5.21&lt;/td&gt;
&lt;td&gt;10.2%&lt;/td&gt;
&lt;td&gt;~9.8x&lt;/td&gt;
&lt;td&gt;1.3%&lt;/td&gt;
&lt;td&gt;$32.0B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EC&lt;/td&gt;
&lt;td&gt;Ecopetrol SA ADR&lt;/td&gt;
&lt;td&gt;Energy (Oil &amp;amp; Gas Integrated)&lt;/td&gt;
&lt;td&gt;$15.13&lt;/td&gt;
&lt;td&gt;$1.40&lt;/td&gt;
&lt;td&gt;9.3%&lt;/td&gt;
&lt;td&gt;~10.8x&lt;/td&gt;
&lt;td&gt;4.4%&lt;/td&gt;
&lt;td&gt;$30.2B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KB&lt;/td&gt;
&lt;td&gt;KB Financial Group&lt;/td&gt;
&lt;td&gt;Financial Services (Banks – Regional)&lt;/td&gt;
&lt;td&gt;$116.74&lt;/td&gt;
&lt;td&gt;$10.40&lt;/td&gt;
&lt;td&gt;8.9%&lt;/td&gt;
&lt;td&gt;~11.2x&lt;/td&gt;
&lt;td&gt;2.7%&lt;/td&gt;
&lt;td&gt;$41.0B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few things jump out.&lt;/p&gt;

&lt;p&gt;No mega-cap tech. Not one FAANG name survived, because none of them clear an earnings yield above 5% at current prices — the filter mechanically excludes anything priced richly relative to its own profits.&lt;/p&gt;

&lt;p&gt;Heavy tilt toward energy, financials, and insurance. That's not a bias I introduced. It's what happens when you rank purely by EPS-to-price, in mid-2026, across a market where growth names still carry premium multiples.&lt;/p&gt;

&lt;p&gt;Real geographic spread. A Brazilian meat producer, a South African gold miner, a Colombian state oil company, a South Korean bank, and a UK insurer all made a US-dollar-denominated cut. The screener doesn't care about domicile — it cares about the number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;None of this is a buy recommendation.&lt;/strong&gt; Cheap relative to earnings doesn't mean safe, and several of these names (EIX, in particular, given wildfire litigation exposure; JBS, given historical governance concerns) carry known company-specific risk that a pure numeric filter can't see. This is a starting list for further research, not a portfolio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skipping the Code: EODHD's Official MCP Server
&lt;/h2&gt;

&lt;p&gt;Everything above ran through raw HTTP calls, which is the right approach when you're building something you'll productionize. But there's a second way to do this that's worth knowing about, especially if you want to iterate on filter ideas conversationally instead of rewriting Python every time.&lt;/p&gt;

&lt;p&gt;EODHD ships an official &lt;strong&gt;Model Context Protocol (MCP) server&lt;/strong&gt; — a standard that lets AI clients like Claude Desktop, Claude Code, and ChatGPT call external tools directly, without you writing the request-handling code yourself. Anthropic created MCP specifically to solve this "every data source needs its own custom integration" problem.&lt;/p&gt;

&lt;p&gt;EODHD's server exposes &lt;strong&gt;70+ read-only tools&lt;/strong&gt; covering the same ground as the REST API: the screener, fundamentals, historical and intraday prices, news and sentiment, technical indicators, macro indicators, US options, and more. It comes in two flavors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;v2 (OAuth)&lt;/strong&gt; — the simpler setup for Claude Desktop. You paste the server URL into Settings → Extensions, authorize through a consent flow, and you're done. No API key handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v1 (API key)&lt;/strong&gt; — for clients like ChatGPT or Claude Code that expect the key passed directly, or if you'd rather manage auth yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once it's connected, you don't write a &lt;code&gt;requests.get()&lt;/code&gt; call at all. You just ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Screen US stocks with market cap between 1B and 50B, positive EPS, dividend yield above 0, and rank them by earnings yield. Show me the top 10."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude translates that into the same &lt;code&gt;stock_screener&lt;/code&gt; tool call I used to build this article, executes it against live EODHD data, and returns the table. This is exactly how I pulled the numbers above — no manual API scripting for the exploratory stage, just a direct conversation with the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where this matters in practice:&lt;/strong&gt; the raw API approach is better once you know exactly what you're building — a cron job, a dashboard, a backtest. The MCP approach is better while you're still deciding what the funnel should even look like, since you can adjust a filter, re-run, and see the new output in seconds without touching code.&lt;/p&gt;

&lt;p&gt;Both hit the same underlying EODHD infrastructure and consume the same API quota, so there's no data-quality tradeoff — it's purely a question of whether you want a repeatable script or a fast conversational loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Here You Can Build
&lt;/h2&gt;

&lt;p&gt;This exact funnel took four API calls and about 30 lines of code. From here you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automated weekly screener reports delivered to Slack or email&lt;/li&gt;
&lt;li&gt;a Streamlit dashboard where the filters are sliders instead of hardcoded values&lt;/li&gt;
&lt;li&gt;a backtesting loop that checks whether "cheap earnings yield + dividend-paying + mid-cap" actually outperforms over rolling 12-month windows&lt;/li&gt;
&lt;li&gt;a signal layer on top using EODHD's &lt;code&gt;wallstreet_lo&lt;/code&gt; / &lt;code&gt;wallstreet_hi&lt;/code&gt; signals to cross-check against analyst targets&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Get real-time and historical stock data for your own screeners&lt;/strong&gt;&lt;br&gt;
EODHD gives you programmatic access to fundamentals, screener queries, and live pricing across global exchanges — the same endpoints used for every number in this article.&lt;br&gt;
&lt;strong&gt;→ &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=claude-screened-3000-stocks-eodhd-api&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Start with EODHD's API&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Turning This Into a Daily Job
&lt;/h2&gt;

&lt;p&gt;A one-time screen is a snapshot. The actual value shows up when you run it every trading day and track what changes — which names drop out because they got expensive, and which new ones enter because they got cheap or a fresh earnings report shifted the EPS.&lt;/p&gt;

&lt;p&gt;Here's a script that runs the full 4-stage funnel, saves the day's result, diffs it against yesterday's, and writes a short summary. Point it at cron and forget about it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://eodhd.com/api/screener&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;OUTPUT_DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;screener_history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;OUTPUT_DIR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;FILTERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,1000000000],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,50000000000],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exchange&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_share&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,0],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avgvol_1d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,300000],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,5],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dividend_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,0]]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_screen&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FILTERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization.desc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;offset&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_share&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_yield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_and_diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;today_df&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;today_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;today&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;today_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;OUTPUT_DIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;today_str&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;today_df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;today_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OUTPUT_DIR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First run — no previous data to compare against.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;yesterday_df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;today_codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;today_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;yesterday_codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yesterday_df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;new_entries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;today_codes&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;yesterday_codes&lt;/span&gt;
    &lt;span class="n"&gt;dropped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yesterday_codes&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;today_codes&lt;/span&gt;

    &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_entries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New in today&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s top 10: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_entries&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;dropped&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dropped out: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dropped&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;new_entries&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;dropped&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No changes in the top 10 today.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_screen&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;save_and_diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Schedule it with a one-line crontab entry to run every weekday after market close:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;0 22 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; 1-5 /usr/bin/python3 /path/to/daily_screener.py &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /path/to/screener.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there, the &lt;code&gt;summary&lt;/code&gt; string is trivial to route anywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Post it to a Slack channel with a webhook (&lt;code&gt;requests.post(SLACK_WEBHOOK_URL, json={"text": summary})&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Email it to yourself using the same pattern as any transactional email script&lt;/li&gt;
&lt;li&gt;Append each day's CSV to a running Google Sheet so you get a queryable history instead of a folder of files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting part isn't the top 10 on any single day. It's watching &lt;em&gt;turnover&lt;/em&gt; — a name entering the list usually means its price dropped or its earnings just improved enough to make the yield attractive. A name leaving usually means the opposite. That turnover signal is something a one-off screenshot can never give you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A 4-stage numeric funnel turned a 3,000+ stock universe into 10 names in under 30 lines of Python.&lt;/li&gt;
&lt;li&gt;Earnings yield (EPS ÷ price) is a simple, brutally objective ranking metric — no sentiment, no narrative, no model hallucination.&lt;/li&gt;
&lt;li&gt;The filter mechanically excludes expensive growth names and surfaces cheap, profitable, dividend-paying companies across sectors and countries. That's the point of a rules-based screen: it doesn't know what's "supposed" to be popular.&lt;/li&gt;
&lt;li&gt;EODHD's MCP server lets you skip the API scripting entirely while you're still iterating on filter logic — same data, conversational interface.&lt;/li&gt;
&lt;li&gt;The real value isn't a single day's list. It's a cron job that runs the funnel daily and tells you what entered or left the top 10, because turnover is the actual signal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;❓ &lt;strong&gt;Can Claude actually query live financial data, or is this just training data?&lt;/strong&gt;&lt;br&gt;
✅ Claude called the EODHD Screener API directly for this article, meaning every number reflects the market on the day of the query, not a training snapshot. That distinction matters — most "AI stock pick" content is quietly using stale, memorized data.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Is earnings yield a reliable way to find undervalued stocks?&lt;/strong&gt;&lt;br&gt;
✅ It's a useful, transparent starting filter, not a complete valuation model. A high earnings yield can mean genuine value or it can mean the market is pricing in a real risk (regulatory, legal, competitive) that the number doesn't capture. Always follow up with qualitative research before acting.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Do I need a paid EODHD plan to run this screener?&lt;/strong&gt;&lt;br&gt;
✅ The Screener API is available on EODHD's All-In-One and All World Extended plans. Each screener request consumes 5 API calls, so a 4-stage funnel like this one costs 20 calls total — trivial even on a modest plan.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;What's the difference between calling the EODHD API directly and using their MCP server?&lt;/strong&gt;&lt;br&gt;
✅ Same underlying data and the same API quota either way. Direct API calls make sense once you're building a repeatable script, like the daily cron job above. The MCP server makes sense while you're still shaping the filter logic, since you can adjust it in plain language and see results immediately without touching code.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;How do I get alerted automatically instead of checking the screener manually?&lt;/strong&gt;&lt;br&gt;
✅ Run the funnel on a schedule (cron, Task Scheduler, or a serverless function), save each day's output, and diff it against the previous run. Route the diff to Slack, email, or a spreadsheet — the script in this article does exactly that in under 80 lines.&lt;/p&gt;




&lt;p&gt;The market doesn't reward the investor with the best opinions.&lt;/p&gt;

&lt;p&gt;It rewards the one with the best process for filtering out noise.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>python</category>
      <category>mcp</category>
      <category>stocks</category>
    </item>
    <item>
      <title>7 Best WhatsApp APIs for Developers in 2026 (Compared)</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Thu, 09 Jul 2026 10:02:19 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/7-best-whatsapp-apis-for-developers-in-2026-compared-f6</link>
      <guid>https://dev.to/kevin_menesesgonzlez/7-best-whatsapp-apis-for-developers-in-2026-compared-f6</guid>
      <description>&lt;p&gt;Most developers reach for Twilio or Meta's official Cloud API the second WhatsApp comes up.&lt;/p&gt;

&lt;p&gt;That's usually the wrong first move.&lt;/p&gt;

&lt;p&gt;The official API wants Business verification, template approval, and per-message billing before you've sent a single test message. Twilio piles its own markup on top. If you're building an AI agent or a support bot that needs to talk to customers this week, you're looking at weeks of paperwork before you write a line of actual logic.&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prototyping a WhatsApp AI agent,&lt;/li&gt;
&lt;li&gt;shipping a chatbot fast,&lt;/li&gt;
&lt;li&gt;or running outbound automation and want to skip Meta's approval process,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;keep reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "official" isn't always the right call
&lt;/h2&gt;

&lt;p&gt;The official WhatsApp Business Platform makes sense if you need the green checkmark, or you're in a regulated industry where Meta's compliance guarantees actually matter.&lt;/p&gt;

&lt;p&gt;But getting there is slow.&lt;/p&gt;

&lt;p&gt;Business Manager verification. App Review. Template approval that can sit for days. Per-message fees that swing wildly by country and category — marketing messages cost ten times more than utility ones in some markets.&lt;/p&gt;

&lt;p&gt;A lot of developers don't need any of that. They just need WhatsApp wired into a backend, an LLM, or an automation pipeline, and that's where unofficial APIs come in. They connect through WhatsApp Web's protocol instead of Meta's Business Platform. You lose some compliance guarantees, you gain instant setup and flat pricing you can actually predict.&lt;/p&gt;

&lt;p&gt;I've seen both sides of this go wrong, and not in the way people expect.&lt;/p&gt;

&lt;p&gt;A developer picks an unofficial API to ship an MVP fast. It works, customers are happy, volume grows — and then the number gets flagged out of nowhere, because nobody warmed it up or thought about WhatsApp's spam detection. Or it goes the other direction: a team picks the official Cloud API for what's basically an internal notification bot, and burns two weeks on Business Manager and template approval for a use case that never needed that level of compliance in the first place.&lt;/p&gt;

&lt;p&gt;Same root mistake both times. Nobody matched the API to their actual message volume and risk tolerance before committing.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;This is a rundown of the best WhatsApp APIs for developers right now — official and unofficial, with real pricing, so you can pick the right one for an AI agent, a chatbot, or whatever automation you're building instead of guessing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best official WhatsApp API for AI agents:&lt;/strong&gt; Zernio. No markup on Meta's fees, numbers from $2/month, one API call to get live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best flat-rate unofficial option:&lt;/strong&gt; WAAPI at $10/mo or Whapi.Cloud at $29/mo — no per-message charges, you know your bill in advance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best free option if you want to self-host:&lt;/strong&gt; CodeChat. Open source, the only ongoing cost is your own server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Zernio — the official API minus the paperwork
&lt;/h2&gt;

&lt;p&gt;Zernio runs on the real WhatsApp Business Platform, but somebody on their team clearly got tired of Meta's onboarding and decided to fix it.&lt;/p&gt;

&lt;p&gt;Instead of creating a Meta app, passing App Review, and wiring up webhooks by hand, Zernio uses Meta's Embedded Signup flow. You connect a number from a dashboard in one click. No Business Manager rabbit hole.&lt;/p&gt;

&lt;p&gt;What you actually get:&lt;/p&gt;

&lt;p&gt;WhatsApp numbers in 53 countries, provisioned through the API, starting at $2/month. Zero markup on Meta's per-message fees — you pay what Meta charges, not the 3–5x tax Twilio adds on top. Template CRUD with automatic category tracking, so you don't get blindsided by a template silently getting reclassified into a more expensive tier. Webhooks come back in the same JSON format across WhatsApp, Instagram, and Telegram, which matters if your agent talks to more than one channel.&lt;/p&gt;

&lt;p&gt;There's also a hosted MCP server, which means an AI agent (Claude, your own backend, whatever) can manage WhatsApp conversations through plain tool calls instead of you writing glue code for every action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official API, so you're not gambling on an unofficial protocol getting your number banned&lt;/li&gt;
&lt;li&gt;Platform fee scales down at low volume, first two connected accounts are free&lt;/li&gt;
&lt;li&gt;WhatsApp Calling API support, useful if you want to route voice to an agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You still pay Meta's per-message fees on top, Zernio removes the markup, not the underlying cost&lt;/li&gt;
&lt;li&gt;No visual dashboard built for non-technical teammates, this is built for developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; developers building AI agents or SaaS products who want the official API without losing a month to Meta's setup.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://zernio.com" rel="noopener noreferrer"&gt;Skip the Meta developer portal entirely&lt;/a&gt;&lt;/strong&gt; — Connect a WhatsApp number and start sending messages in one API call, official Business Platform, zero markup.&lt;br&gt;

&lt;/div&gt;


&lt;h2&gt;
  
  
  2. UltraMsg — fastest unofficial setup
&lt;/h2&gt;

&lt;p&gt;UltraMsg connects through WhatsApp Web's protocol. Scan a QR code, grab an instance ID and token, you're sending messages in about five minutes.&lt;/p&gt;

&lt;p&gt;Pricing is $39/month per instance, or $390 if you pay yearly.&lt;/p&gt;

&lt;p&gt;The upside is flexibility. Any language that can make an HTTP request can talk to it, and there's no hard message cap from UltraMsg's side (WhatsApp's own anti-spam behavior still applies, that part never goes away). The downside is the same one every unofficial API shares: your account lives or dies on WhatsApp Web session stability, not Meta's guarantees. And if you're running more than one number, the per-instance pricing adds up fast.&lt;/p&gt;

&lt;p&gt;Good fit for a solo developer or small business that wants a working integration today and has no interest in touching Meta's portal.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Green API — the cheapest way to test an idea
&lt;/h2&gt;

&lt;p&gt;Green API splits into two plans: Developer, which is free but capped, and Business, which runs around $8/month per instance for unlimited messaging.&lt;/p&gt;

&lt;p&gt;What I like here is that the free tier is actually usable. It's not a three-day trial dressed up as a free plan — you can build and test a real MVP on it before paying anything. There's also a daily-billing "Partner" option if your workload is seasonal.&lt;/p&gt;

&lt;p&gt;The tradeoffs: the free plan only handles a handful of individual chats per month, so it's testing-only, not production. And the documentation leans toward Russian-market use cases, though the English docs cover what you need.&lt;/p&gt;

&lt;p&gt;Best for validating an idea before you commit to a paid plan anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. WAAPI — one flat price, no surprises
&lt;/h2&gt;

&lt;p&gt;WAAPI charges $10/month per instance, flat. Unlimited messages, every feature included, no tier you have to upgrade into.&lt;/p&gt;

&lt;p&gt;That simplicity is the whole pitch. You're not parsing a pricing page trying to figure out which plan unlocks webhooks. Everything's already there.&lt;/p&gt;

&lt;p&gt;It's a smaller company than UltraMsg or Green API, so there's less of a track record to lean on, and the same unofficial-protocol ban risk applies as everywhere else on this list. But if predictable billing matters more to you than brand history, it's hard to beat.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Whapi.Cloud — built for groups and channels
&lt;/h2&gt;

&lt;p&gt;Whapi.Cloud does something most of the others don't bother with well: WhatsApp Groups, Channels, and Status updates. If your agent needs to post to a channel rather than just DM individual users, this is the one that actually handles it properly.&lt;/p&gt;

&lt;p&gt;There's a free sandbox (150 messages a day, 5 active conversations a month) and then $29/month per connected number once you outgrow it.&lt;/p&gt;

&lt;p&gt;It plugs natively into n8n, Make, and Zapier, which is nice if your team leans no-code. The sandbox is also a genuine free-forever tier, not a countdown timer. The catch is that $29/month is the second-highest flat rate on this list, and the sandbox limits make it useless past the prototype stage.&lt;/p&gt;

&lt;p&gt;Best for anyone building Groups or Channels automation specifically, not plain one-to-one messaging.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. CodeChat — free, open source, your server
&lt;/h2&gt;

&lt;p&gt;CodeChat is for developers who'd rather run their own infrastructure than pay anyone monthly. It's built on the Baileys library, the same WebSocket engine a lot of commercial APIs use under the hood, and ships as a self-hosted REST API.&lt;/p&gt;

&lt;p&gt;Cost: nothing, beyond whatever VPS you run it on.&lt;/p&gt;

&lt;p&gt;The appeal is obvious if you've ever felt locked into a vendor. Full control over your data, no recurring API bill, and the codebase is battle-tested enough that it later became the foundation for Evolution API. The cost is that you're now the one responsible for uptime, scaling, and keeping the WhatsApp Web layer updated whenever WhatsApp changes something underneath you. There's no support line to call, just community docs.&lt;/p&gt;

&lt;p&gt;If you're comfortable with Docker and don't mind owning the ops side, this is the only option on the list with zero recurring cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Wassenger — built for teams, not just developers
&lt;/h2&gt;

&lt;p&gt;Wassenger is the odd one out here. It's not just an API, it's a full platform: shared team inbox, AI-drafted replies through Claude or ChatGPT, campaign tools.&lt;/p&gt;

&lt;p&gt;Pricing runs €39.90 for Professional, €69.90 for Business, €99.90 for Enterprise, all on the official WABA.&lt;/p&gt;

&lt;p&gt;If you need a human reviewing AI-drafted replies before they go out, the draft-and-approve workflow is genuinely useful. It also means you're not betting on an unofficial protocol. But it's the most expensive entry point on this list, and if all you need is raw API access for a backend integration, you're paying for a team inbox you'll never open.&lt;/p&gt;

&lt;p&gt;Best for teams that want a shared inbox and AI-assisted replies bundled with their API access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Starting price&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Zernio&lt;/td&gt;
&lt;td&gt;Official&lt;/td&gt;
&lt;td&gt;$2/month&lt;/td&gt;
&lt;td&gt;AI agents, SaaS products&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UltraMsg&lt;/td&gt;
&lt;td&gt;Unofficial&lt;/td&gt;
&lt;td&gt;$39/month&lt;/td&gt;
&lt;td&gt;Fast solo setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Green API&lt;/td&gt;
&lt;td&gt;Unofficial&lt;/td&gt;
&lt;td&gt;Free (capped) / $8/mo&lt;/td&gt;
&lt;td&gt;Testing an idea&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WAAPI&lt;/td&gt;
&lt;td&gt;Unofficial&lt;/td&gt;
&lt;td&gt;$10/month flat&lt;/td&gt;
&lt;td&gt;Predictable billing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Whapi.Cloud&lt;/td&gt;
&lt;td&gt;Unofficial&lt;/td&gt;
&lt;td&gt;Free sandbox / $29/mo&lt;/td&gt;
&lt;td&gt;Groups &amp;amp; Channels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CodeChat&lt;/td&gt;
&lt;td&gt;Unofficial (self-hosted)&lt;/td&gt;
&lt;td&gt;Free (server cost only)&lt;/td&gt;
&lt;td&gt;Full control, zero recurring fee&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wassenger&lt;/td&gt;
&lt;td&gt;Official&lt;/td&gt;
&lt;td&gt;€39.90/month&lt;/td&gt;
&lt;td&gt;Team inbox + AI replies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to choose
&lt;/h2&gt;

&lt;p&gt;Need the green checkmark, or operating somewhere regulated? Start with Zernio or Wassenger. Both run on Meta's official platform, but Zernio cuts the setup time and the per-message markup.&lt;/p&gt;

&lt;p&gt;Just need something working today and can live with unofficial-protocol risk? WAAPI or Green API get you there for the least money.&lt;/p&gt;

&lt;p&gt;Optimizing for zero recurring cost and full control over your stack? CodeChat is the only one here that doesn't send you a bill every month.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What's the difference between official and unofficial WhatsApp APIs?&lt;/strong&gt;&lt;br&gt;
Official APIs like Zernio and Wassenger connect through Meta's WhatsApp Business Platform. You need Business verification and you pay per message. Unofficial APIs (UltraMsg, Green API, WAAPI, Whapi.Cloud, CodeChat) connect through WhatsApp Web's protocol instead. Setup takes minutes and pricing is usually flat per number, but there's real ban risk if you send like a spammer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a free WhatsApp API for developers?&lt;/strong&gt;&lt;br&gt;
Green API's free Developer plan is actually usable for testing, not just a teaser. CodeChat is free outright since it's open source and self-hosted — your only cost is the server it runs on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which WhatsApp API is best for AI agents?&lt;/strong&gt;&lt;br&gt;
Zernio is built for this specifically. It ships a hosted MCP server so an AI agent can manage WhatsApp conversations through tool calls, and it's on the official API, so you're not worried about getting banned for sending too much volume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use an unofficial WhatsApp API without getting banned?&lt;/strong&gt;&lt;br&gt;
The risk is real but manageable. Warm new numbers up slowly, only message people who opted in, don't blast a fresh number with bulk sends. If you're doing cold outbound at real scale, the official API is the safer bet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do these APIs charge per message?&lt;/strong&gt;&lt;br&gt;
Most unofficial ones on this list (UltraMsg, WAAPI, Whapi.Cloud) charge flat monthly fees, nothing per message. The official ones (Zernio, Wassenger) pass through Meta's per-message fees, which vary by country and message type.&lt;/p&gt;

&lt;p&gt;If you're a software or API company looking to explain your product through high-quality educational content (not marketing fluff), feel free to connect with me on LinkedIn: &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;linkedin.com/in/kevin-meneses-gonzalez&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>api</category>
      <category>whatsapp</category>
      <category>data</category>
      <category>software</category>
    </item>
    <item>
      <title>How LLMs Are Replacing Legacy OCR Workflows</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Wed, 08 Jul 2026 16:21:51 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/how-llms-are-replacing-legacy-ocr-workflows-37hc</link>
      <guid>https://dev.to/kevin_menesesgonzlez/how-llms-are-replacing-legacy-ocr-workflows-37hc</guid>
      <description>&lt;h2&gt;
  
  
  *&lt;em&gt;TL;DR: *&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;OCR digitizes a page. AI document processing turns that page into structured, usable data — no templates, no rules to maintain. Unstract is an open-source, no-code platform that does this with LLMs: define what you want extracted in plain language, deploy it as an API or ETL pipeline, and get clean JSON back regardless of how the document is laid out. Start with the &lt;a href="https://unstract.com" rel="noopener noreferrer"&gt;free 14-day trial&lt;/a&gt; or read the &lt;a href="https://docs.unstract.com" rel="noopener noreferrer"&gt;quick start guide&lt;/a&gt; — no credit card required.&lt;/p&gt;

&lt;p&gt;OCR was never broken.&lt;/p&gt;

&lt;p&gt;It just stopped being enough.&lt;/p&gt;

&lt;p&gt;For thirty years, optical character recognition did exactly what it promised: turn pixels into characters. Feed it a scanned invoice, get back a string of text. That was the job, and it did the job well.&lt;/p&gt;

&lt;p&gt;But reading text and understanding a document are two different problems. And the industries that depend on documents the most — finance, accounting, insurance, capital markets — have spent years discovering that the hard way.&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building automation for invoices, statements, or contracts,&lt;/li&gt;
&lt;li&gt;maintaining an OCR pipeline that breaks every time a vendor changes their layout,&lt;/li&gt;
&lt;li&gt;or evaluating whether to move from rule-based extraction to something smarter,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 200-Bank Problem
&lt;/h2&gt;

&lt;p&gt;Picture a finance team that receives bank statements from 200 different banks.&lt;/p&gt;

&lt;p&gt;Each bank uses its own layout. Different field labels. Different date formats. Some put the account balance top-right; others bury it in a footer table. A few still send scanned PDFs that look like they were faxed twice.&lt;/p&gt;

&lt;p&gt;Template-based OCR handles this the only way it knows how: one template per bank. 200 templates. Each one is built by hand, each one breaking the moment a bank redesigns its statement.&lt;/p&gt;

&lt;p&gt;Now widen the lens.&lt;/p&gt;

&lt;p&gt;An insurance underwriter doesn't just deal with bank statements — they deal with claims forms, KYC files, medical reports, and policy applications, each shaped differently depending on the insurer, the state, and the line of business. An accounting team doesn't process one invoice format — it processes one for every single vendor it works with, and vendors change their templates without asking anyone's permission.&lt;/p&gt;

&lt;p&gt;Multiply any of these by real transaction volume, and you get a pattern every ops team eventually recognizes.&lt;/p&gt;

&lt;p&gt;A Monday morning that repeats itself:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Someone opens 40 PDFs by hand.&lt;/li&gt;
&lt;li&gt;Copy numbers into a spreadsheet, one cell at a time.&lt;/li&gt;
&lt;li&gt;Pray the format didn't change since last month.&lt;/li&gt;
&lt;li&gt;Finds three that don't match any known template and sets them aside "for later."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's not automation. That's a workaround wearing automation's clothes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem Was Never Reading Text
&lt;/h2&gt;

&lt;p&gt;Here's the reframe.&lt;/p&gt;

&lt;p&gt;The problem was never extracting characters from a page. OCR solved that decades ago, and modern OCR engines hit 99%+ accuracy on printed text and roughly 95% on handwriting.&lt;/p&gt;

&lt;p&gt;The problem is that reading text and understanding a document are not the same task.&lt;/p&gt;

&lt;p&gt;A human accountant doesn't process an invoice by reading every character in order. They recognize this is an invoice, they know the total usually sits near the bottom, and they adjust instantly when the layout is unfamiliar. That's comprehension, not character recognition.&lt;/p&gt;

&lt;p&gt;Legacy systems never had that layer. AI document processing exists because LLMs finally do.&lt;/p&gt;

&lt;p&gt;That distinction is also why "just add more OCR accuracy" was never going to solve this. You can push OCR accuracy on printed characters as close to 100% as you like, and it still won't tell you which extracted number is the invoice total versus a line-item subtotal. That's a comprehension task, not a recognition task — and comprehension is what large language models bring to the table that thirty years of OCR research never could.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is AI Document Processing, Actually
&lt;/h2&gt;

&lt;p&gt;AI document processing is the use of large language models to read, interpret, and structure the content of unstructured documents — PDFs, scans, images, spreadsheets — without relying on fixed templates or hand-coded rules.&lt;/p&gt;

&lt;p&gt;Instead of matching a document against a predefined layout, an LLM-based pipeline reads the document the way a person would: it understands that a number preceded by "Total Due" is different from a number labeled "Subtotal," even if their position on the page changes completely from one document to the next.&lt;/p&gt;

&lt;p&gt;Here's how the three generations actually compare:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj9h462dcpx1u9r34bvkn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj9h462dcpx1u9r34bvkn.png" alt=" " width="772" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Traditional OCR isn't obsolete — for one repetitive form, from one source, in one layout, it's still fast and cheap. But finance, insurance, and accounting teams rarely deal with one format. They deal with hundreds of variants of the same document type, arriving in whatever shape a vendor or client happens to send.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Pipeline Actually Works, Step by Step
&lt;/h2&gt;

&lt;p&gt;Under the hood, an AI document processing pipeline is doing four distinct things, whether you notice them or not:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parsing&lt;/strong&gt; — turning the raw file (scanned PDF, native PDF, image, even a photo of a paper form) into text while preserving layout: tables stay tables, checkboxes stay checkboxes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema definition&lt;/strong&gt; — describing, in plain language or a JSON schema, exactly what fields matter: customer name, invoice total, claim number, whatever the business needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extraction&lt;/strong&gt; — the LLM reads the parsed document against that schema and returns structured values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt; — checking the extracted values for consistency, flagging low-confidence fields instead of guessing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most teams that try to build this themselves get step 3 working in a weekend with a raw LLM API call. Step 1 and step 4 are where things quietly fall apart in production — layout gets flattened, and a hallucinated total slips through with full confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Building This In-House Usually Stalls
&lt;/h2&gt;

&lt;p&gt;Plenty of engineering teams start this project the same way: a Python script, an LLM API call, a PDF-to-text library, done in an afternoon.&lt;/p&gt;

&lt;p&gt;It works — on the five sample documents used to build it.&lt;/p&gt;

&lt;p&gt;Then it hits production, and three things happen, almost every time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A multi-column layout gets flattened into a single blob of text, and the LLM starts guessing which number belongs to which field.&lt;/li&gt;
&lt;li&gt;The model hallucinates a value with full confidence on a document type it hasn't seen before, and nobody notices until the number is already in a report.&lt;/li&gt;
&lt;li&gt;Token costs creep up as documents get longer, because nobody built in compression or prompt efficiency from day one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these are LLM problems. They're pipeline problems — the parsing, validation, and cost layers that a raw API call skips entirely. This is precisely the gap purpose-built platforms are designed to close, instead of every team rebuilding the same missing pieces independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trend: From Templates to Prompts
&lt;/h2&gt;

&lt;p&gt;Something changed in the last 24 months.&lt;/p&gt;

&lt;p&gt;Vision-capable LLMs and layout-aware parsers made it possible to feed a document into a pipeline and get structured output back — without teaching the system what that specific document looks like first.&lt;/p&gt;

&lt;p&gt;That shift shows up everywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schema-first extraction.&lt;/strong&gt; You define what you want (a JSON schema), not how the document is laid out. Even foundation model providers have moved this direction — structured outputs are now a first-class feature in most major LLM APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agentic workflows.&lt;/strong&gt; Instead of a human writing extraction rules by hand, an AI agent generates and refines the extraction logic itself, iterating against sample documents until accuracy stabilizes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidence over guesswork.&lt;/strong&gt; Modern pipelines can flag low-confidence extractions instead of silently returning wrong data — a "no value" is safer than a wrong one on a financial document.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance pressure.&lt;/strong&gt; New 2026 obligations like the EU AI Act push regulated industries — banking, insurance, life sciences — toward document workflows with audit trails and traceability, something rule-based OCR was never built to provide.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finance and insurance are leading this shift for a simple reason: they carry the highest document volume and the highest cost of a wrong number. A misread account balance isn't a UX bug — it's a compliance problem. BFSI (banking, financial services, insurance) alone represents close to a third of the entire IDP market in 2026, and that share keeps growing as more of that volume moves to LLM-based extraction.&lt;/p&gt;

&lt;p&gt;There's a second force behind this trend worth naming: MCP (Model Context Protocol) and the broader move toward agentic systems. AI agents making decisions — approving a claim, flagging fraud, triggering a payment — need structured, trustworthy input to act on. An agent can't reason well over a wall of unformatted OCR text. It needs the same clean JSON a downstream database would expect. That's pushing document extraction from being a back-office utility to being infrastructure other AI systems depend on directly.&lt;/p&gt;

&lt;p&gt;This is exactly the gap Unstract was built to close.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Costs vs. What It Replaces
&lt;/h2&gt;

&lt;p&gt;It's worth being blunt about the economics, because "AI is expensive" is the objection that kills most of these projects before they start.&lt;/p&gt;

&lt;p&gt;LLM token costs on a single document are real, but they're not the number that matters. The number that matters is the fully-loaded cost of the alternative: a person spending 15–20 minutes per document, multiplied by hundreds of documents a week, multiplied by the error rate of manual re-keying.&lt;/p&gt;

&lt;p&gt;Token-efficiency techniques like SinglePass and Summarized Extraction exist specifically because vendors know this comparison only holds up if per-document AI cost stays a small fraction of a person's hourly rate — which, for anything beyond a handful of documents a day, it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Unstract Fits
&lt;/h2&gt;

&lt;p&gt;Unstract is an open-source, no-code platform purpose-built for extracting structured data from unstructured documents using LLMs — deployable as an API or as an ETL pipeline, without writing extraction rules by hand.&lt;/p&gt;

&lt;p&gt;It's not a single model. It's a full pipeline, and each piece solves a specific failure mode that shows up when you try to run LLM extraction in production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LLMWhisperer&lt;/strong&gt; — a layout-preserving text extraction engine. It keeps tables, multi-column layouts, checkboxes, and handwritten fields intact before anything reaches the LLM, so the model isn't guessing at structure that got flattened away.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt Studio&lt;/strong&gt; — a no-code environment where you build extraction logic against real sample documents, compare output and cost across multiple LLMs side by side, and version your prompts instead of losing track of them in a spreadsheet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLMChallenge&lt;/strong&gt; — Unstract's answer to hallucination. Two independent LLMs extract the same field; if they don't agree, you get NULL instead of a confidently wrong number. No value is safer than a wrong one on a financial document.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SinglePass and Summarized Extraction&lt;/strong&gt; — techniques that cut token usage by up to 7x on large documents, which matters the moment you're processing thousands of statements a month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Hub and MCP Server&lt;/strong&gt; — once a schema is built, deploy it as a callable API in one click, or connect it directly to AI agents that need reliable structured data as an input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few concrete benefits this unlocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No templates, no per-vendor maintenance.&lt;/strong&gt; The same extraction project handles bank statements from 200 different banks, because it understands the concept of "account balance," not the position of a specific box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in hallucination control.&lt;/strong&gt; LLMChallenge means you get validated data or nothing — never a silent wrong value slipping into a downstream system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open-source, no vendor lock-in.&lt;/strong&gt; Unstract is released under AGPL 3.0. Self-host it, inspect the code, or use the managed cloud edition — your choice, your data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy without writing a pipeline from scratch.&lt;/strong&gt; A finished extraction project becomes an API or ETL job in one click, feeding straight into Snowflake, BigQuery, or your existing database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document-agnostic by design.&lt;/strong&gt; No prior training run needed per document type — you point it at samples, define the schema, and it generalizes.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://unstract.com" rel="noopener noreferrer"&gt;Try Unstract free for 14 days&lt;/a&gt;&lt;/strong&gt; — no credit card required, pre-configured with an LLM, vector database, and LLMWhisperer.&lt;br&gt;

&lt;/div&gt;


&lt;p&gt;You can read the full breakdown of the platform in the &lt;a href="https://docs.unstract.com" rel="noopener noreferrer"&gt;Unstract documentation&lt;/a&gt; if you want to see how the pieces connect before touching any code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Walkthrough #1: Extracting a Bank Statement
&lt;/h2&gt;

&lt;p&gt;Theory is fine, but this only matters if it holds up against a real document. Let's make it concrete.&lt;/p&gt;

&lt;p&gt;Say you receive credit card statements as PDFs — same core fields (customer name, issuer, statement date, list of transactions), wildly different formatting depending on the bank. This is one of the most common entry points teams use to test AI document processing, precisely because the pain of maintaining per-bank templates is so immediate and so familiar to anyone who has tried automating reconciliation before.&lt;/p&gt;

&lt;p&gt;With a template-based system, this is where things get painful. With Unstract, the workflow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload a handful of sample statements (from different banks) into Prompt Studio.&lt;/li&gt;
&lt;li&gt;Define your schema in plain language — "extract customer name, statement date, total due, and list of transactions with date/description/amount."&lt;/li&gt;
&lt;li&gt;Let Prompt Studio generate and test the extraction prompt against your samples, comparing accuracy and cost across LLMs.&lt;/li&gt;
&lt;li&gt;Deploy as an API.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once deployed, calling it looks like a normal REST request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.unstract.com/deployment/api/&amp;lt;your-org&amp;gt;/&amp;lt;your-endpoint&amp;gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statement_chase.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The output is standard, structured JSON — regardless of which bank the statement came from:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"issuer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Chase"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"statement_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-30"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total_due"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1284.55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transactions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-02"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amazon.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;42.99&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-05"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Uber"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;18.30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;From here you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;automated reconciliation pipelines that flag discrepancies&lt;/li&gt;
&lt;li&gt;fraud detection models fed by clean transaction data&lt;/li&gt;
&lt;li&gt;dashboards that update without anyone touching a spreadsheet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No template. No rule that breaks the next time a bank redesigns its statement.&lt;/p&gt;
&lt;h2&gt;
  
  
  Practical Walkthrough #2: Automating Vendor Invoice Approval
&lt;/h2&gt;

&lt;p&gt;Here's a second example — a workflow that's easy to replicate if you're on an accounting or AP (accounts payable) team.&lt;/p&gt;

&lt;p&gt;The scenario: invoices arrive by email from hundreds of vendors, every one with a different layout. Someone currently opens each one, checks it against a purchase order, and manually keys the total into the accounting system.&lt;/p&gt;

&lt;p&gt;The schema you'd define in Prompt Studio:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"vendor_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"invoice_number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"invoice_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"due_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"line_items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"unit_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"line_total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subtotal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tax"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total_due"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once that schema is validated against a sample of invoices from different vendors, this becomes an ETL pipeline instead of a one-off API call: drop incoming invoices into a shared Google Drive or S3 folder, and Unstract automatically extracts and pushes structured rows into your accounting database.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pseudocode for the downstream logic once structured data lands in your DB
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;new_extracted_invoices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;po&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;match_purchase_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vendor_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_due&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;po&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_due&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;approve_for_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;flag_for_manual_review&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PO mismatch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The extraction layer's only job is turning a messy PDF into the JSON above. Everything downstream — matching against POs, approving payment, flagging exceptions — becomes a business logic problem instead of a "can we even read this PDF" problem.&lt;/p&gt;

&lt;p&gt;That's the actual unlock: once documents become structured data, the rest of your stack stops needing to know it ever came from a PDF at all.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where This Pays Off: Use Cases by Industry
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Finance — Multi-bank statement reconciliation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The pain:&lt;/strong&gt; A treasury or finance team pulling statements from multiple banking relationships hits the same wall every close cycle — different formats, different field labels, no shared structure. Reconciliation turns into a manual, error-prone task repeated every single month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How AI document processing helps:&lt;/strong&gt; One schema handles every bank's statement layout, because the extraction logic understands the concept of "closing balance" or "transaction date" rather than a fixed position on the page. The output feeds directly into reconciliation logic without a human retyping anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams closing books monthly across multiple banking relationships, or finance functions managing treasury operations across subsidiaries with different local banks.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Insurance — Underwriting and claims processing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The pain:&lt;/strong&gt; Claims forms, KYC documents, and medical reports vary by insurer, state, and line of business — a nightmare for template-based systems that need a new template for every combination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How AI document processing helps:&lt;/strong&gt; Schema-based extraction generalizes across formats instead of requiring a template per variant. Teams running this kind of pipeline report review times dropping from days to minutes, simply because the bottleneck was never document volume — it was the seams between formats that broke automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Underwriting teams processing high volumes of inconsistent intake documents, and claims teams under pressure to cut turnaround time without adding headcount.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Accounting — Accounts payable automation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The pain:&lt;/strong&gt; Every vendor invoices differently, and manual entry doesn't scale past a few dozen suppliers before someone becomes a full-time human OCR machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How AI document processing helps:&lt;/strong&gt; Structured extraction feeds directly into PO-matching and payment approval logic, exactly as shown in Walkthrough #2 above — the invoice becomes a JSON object the moment it lands, and everything downstream is business logic, not document parsing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; AP teams handling invoices from 50+ vendors with no shared format, or finance ops teams trying to close the "three-way match" (PO, invoice, receipt) faster.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Capital markets — KYC and client onboarding
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The pain:&lt;/strong&gt; Onboarding documents (ID scans, proof of address, account applications) arrive in every format imaginable, and compliance requires traceable, auditable extraction — not just a fast one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How AI document processing helps:&lt;/strong&gt; Layout-aware parsing handles scanned and handwritten fields that break traditional OCR, while validation layers like dual-LLM consensus create the audit trail regulators increasingly expect under frameworks like the EU AI Act.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Onboarding teams under regulatory pressure to document exactly how each data point was extracted and verified, not just that it was extracted.&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Legal and contracts — Clause and obligation extraction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The pain:&lt;/strong&gt; Contracts share no common template, and finding specific clauses (payment terms, termination conditions, indemnification language) manually doesn't scale across a growing contract portfolio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How AI document processing helps:&lt;/strong&gt; Prompt-based extraction can target specific clause types across contracts of any format and length, structuring what used to require a paralegal reading every page line by line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Legal ops teams managing large, heterogeneous contract repositories, or M&amp;amp;A teams running due diligence against hundreds of agreements on a deadline.&lt;/p&gt;
&lt;h3&gt;
  
  
  6. Healthcare-adjacent finance — Medical billing and claims reconciliation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The pain:&lt;/strong&gt; Medical billing documents mix structured codes (CPT, ICD-10) with unstructured physician notes and inconsistent payer formats, making reconciliation between what was billed and what was paid painfully manual.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How AI document processing helps:&lt;/strong&gt; Extraction schemas can target both the structured codes and surrounding context simultaneously, flagging discrepancies between billed and reimbursed amounts without a human cross-referencing every line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Revenue cycle teams reconciling claims across multiple payers with inconsistent explanation-of-benefits formats.&lt;/p&gt;

&lt;p&gt;Across every one of these use cases, the underlying pattern repeats: the documents are different, the pain is identical, and the fix is the same — stop building a template per format and start defining a schema per outcome.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started, Practically
&lt;/h2&gt;

&lt;p&gt;If you want to test this against your own documents rather than take any of this on faith, the fastest path looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pull 5–10 real samples of the document type that causes you the most pain — the messiest ones you have, not the cleanest.&lt;/li&gt;
&lt;li&gt;Sign up for the free 14-day trial — it comes pre-configured with an LLM, vector database, embedding model, and LLMWhisperer, so there's nothing to wire up first.&lt;/li&gt;
&lt;li&gt;Define your schema in Prompt Studio using plain language, exactly like the JSON examples in Walkthrough #1 and #2 above.&lt;/li&gt;
&lt;li&gt;Run it against your samples and compare accuracy and cost across the available LLMs before committing to one.&lt;/li&gt;
&lt;li&gt;Deploy as an API or ETL pipeline once the extraction is accurate enough to trust — no separate infrastructure to stand up.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href="https://docs.unstract.com" rel="noopener noreferrer"&gt;quick start guide&lt;/a&gt; walks through this exact sequence using a credit card statement example, if you want a guided first run before pointing it at your own documents.&lt;/p&gt;
&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;OCR reads characters. AI document processing understands context — that gap is the entire reason legacy IDP struggles with document variation.&lt;/li&gt;
&lt;li&gt;The real cost of template-based systems isn't the software. It's the ongoing human maintenance every new layout demands.&lt;/li&gt;
&lt;li&gt;Platforms like Unstract combine layout-aware parsing, schema-based extraction, and hallucination control into one deployable pipeline — so you build the extraction logic once and let it handle the variation, whether that's bank statements, invoices, or insurance claims.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;❓ What is AI document processing?&lt;/strong&gt;&lt;br&gt;
✅ It's the use of large language models to read, interpret, and structure data from unstructured documents — PDFs, scans, images — without relying on fixed templates. Unlike OCR, which only extracts text, it extracts meaning: it understands what a field represents, not just where it sits on the page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ Is OCR still useful in 2026?&lt;/strong&gt;&lt;br&gt;
✅ Yes, for narrow cases: high-volume batches of the exact same form, from the exact same source, where digitizing text is the only goal. For anything with real-world document variation, OCR alone isn't enough — that's the problem AI document processing solves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ Is Unstract open source?&lt;/strong&gt;&lt;br&gt;
✅ Yes. Unstract is released under the AGPL 3.0 license, with a self-hosted open-source edition and a managed cloud edition that adds enterprise features like LLMChallenge, SSO, and human review workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ Do I need to know how to code to use Unstract?&lt;/strong&gt;&lt;br&gt;
✅ No. Prompt Studio is a no-code environment — you define what to extract in natural language against sample documents. Developers can go further and call the resulting extraction as a REST API or embed it in an ETL pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ Can AI document processing handle handwritten documents?&lt;/strong&gt;&lt;br&gt;
✅ Yes. Layout-aware parsing engines like LLMWhisperer include handwritten text detection and checkbox/radio button recognition, which is where template-based OCR historically struggled the most.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ How is this different from just calling an LLM API directly with a PDF?&lt;/strong&gt;&lt;br&gt;
✅ A raw LLM call skips the layers that make extraction reliable in production: layout-preserving parsing so tables and forms aren't flattened, schema validation, and hallucination checks like dual-LLM consensus. Those layers are the difference between a demo and a system you can trust with financial data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ How long does it take to go from zero to a working extraction pipeline?&lt;/strong&gt;&lt;br&gt;
✅ With a no-code platform, most teams get a working schema validated against sample documents within a day or two — the bulk of the time goes into gathering representative samples, not building infrastructure. Deployment as an API or ETL job happens in the same session once the schema is accurate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ Can AI document processing integrate with an existing data warehouse?&lt;/strong&gt;&lt;br&gt;
✅ Yes. Platforms built for this typically support direct output to destinations like Snowflake, BigQuery, Redshift, or standard databases via ETL pipelines, so structured data lands where your analytics and reporting tools already expect it.&lt;/p&gt;

&lt;p&gt;Legacy OCR asked documents to fit a template.&lt;/p&gt;

&lt;p&gt;AI document processing asks the system to understand the document instead — and that's the shift finance, accounting, and insurance teams have been waiting for.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  &lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://unstract.com" rel="noopener noreferrer"&gt;Start Unstract's free trial&lt;/a&gt;&lt;/strong&gt; — point it at your messiest documents first and let the comparison speak for itself.&lt;br&gt;

&lt;/div&gt;






&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>ocr</category>
      <category>llm</category>
    </item>
    <item>
      <title>How to Backtest a Trading Strategy with Python and EODHD API</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Tue, 07 Jul 2026 12:31:16 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/how-to-backtest-a-trading-strategy-with-python-and-eodhd-api-5401</link>
      <guid>https://dev.to/kevin_menesesgonzlez/how-to-backtest-a-trading-strategy-with-python-and-eodhd-api-5401</guid>
      <description>&lt;p&gt;Most backtests lie to you.&lt;/p&gt;

&lt;p&gt;Not intentionally. But they lie.&lt;/p&gt;

&lt;p&gt;You design a strategy, run it on historical data, and watch the returns look incredible. Then you run it live — and it underperforms a simple buy-and-hold from day one. The math wasn't wrong.&lt;/p&gt;

&lt;p&gt;The data was.&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;testing momentum or mean-reversion strategies in Python,&lt;/li&gt;
&lt;li&gt;building quant tools for personal or professional use,&lt;/li&gt;
&lt;li&gt;or tired of backtests that collapse the moment real execution begins,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This changes how you work.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What this covers:&lt;/strong&gt; Backtesting trading strategies in Python using EODHD's historical OHLCV data API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack:&lt;/strong&gt; &lt;code&gt;requests&lt;/code&gt;, &lt;code&gt;pandas&lt;/code&gt;, &lt;code&gt;numpy&lt;/code&gt; — no heavy frameworks (no backtrader, no vectorbt)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scripts included:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Script 1 — Fetch adjusted historical price data from EODHD&lt;/li&gt;
&lt;li&gt;Script 2 — SMA crossover strategy (20/50-day)&lt;/li&gt;
&lt;li&gt;Script 3 — RSI mean-reversion strategy&lt;/li&gt;
&lt;li&gt;Script 4 — Performance metrics: Sharpe ratio, max drawdown, win rate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EODHD pricing:&lt;/strong&gt; Free tier available; full access from $19.99/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Developers and analysts who need reliable, split/dividend-adjusted data without scraping&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Problem with Free Data
&lt;/h2&gt;

&lt;p&gt;Most developers start with Yahoo Finance or a scraped CSV.&lt;/p&gt;

&lt;p&gt;That works fine for a quick prototype. It stops working the moment your strategy includes anything that happened around a stock split, dividend payment, or ticker change.&lt;/p&gt;

&lt;p&gt;Non-adjusted price data creates ghost signals. A stock "drops 50%" when it actually split 2:1. Your moving average calculates a crossover that never happened in real life. Your strategy looks profitable because it's trading on a data artifact.&lt;/p&gt;

&lt;p&gt;The free path costs you accuracy. And in backtesting, accuracy is the whole point.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix Is Simpler Than You Think
&lt;/h2&gt;

&lt;p&gt;The real bottleneck isn't the strategy logic. It's the data source.&lt;/p&gt;

&lt;p&gt;Use split- and dividend-adjusted closing prices from a reliable provider, and half your backtest reliability problems disappear before you write a single signal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=backtest-trading-strategy-python-eodhd&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;EODHD APIs&lt;/a&gt; provides exactly this. Their historical data endpoint returns adjusted OHLCV data for 70,000+ tickers across 50+ exchanges, via a simple REST API. No scraping. No undocumented endpoints that break on weekends.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;EODHD Financial Data API&lt;/strong&gt;&lt;br&gt;
Adjusted historical prices, fundamentals, and real-time data for 70,000+ tickers.&lt;br&gt;
→ &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=backtest-trading-strategy-python-eodhd&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Start free at eodhd.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Install the required libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests pandas numpy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set your API token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_eodhd_api_token_here&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can get a free token at &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=backtest-trading-strategy-python-eodhd&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;eodhd.com&lt;/a&gt;. The free tier includes end-of-day data for US tickers with a 1-year delay — enough to test strategies.&lt;/p&gt;




&lt;h2&gt;
  
  
  Script 1: Fetch Historical OHLCV Data from EODHD
&lt;/h2&gt;

&lt;p&gt;The foundation of every backtest is the raw price series. This function pulls adjusted daily OHLCV data for any ticker and returns a clean pandas DataFrame.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_eodhd_api_token_here&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_historical_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2020-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2024-12-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Fetch adjusted EOD OHLCV data from EODHD for a given symbol.
    Returns a DataFrame indexed by date.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://eodhd.com/api/eod/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fmt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;


&lt;span class="c1"&gt;# Example usage
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_historical_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAPL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2020-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2024-12-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csvs"&gt;&lt;code&gt;            &lt;span class="k"&gt;open&lt;/span&gt;    &lt;span class="k"&gt;high&lt;/span&gt;     &lt;span class="k"&gt;low&lt;/span&gt;   &lt;span class="k"&gt;close&lt;/span&gt;  &lt;span class="k"&gt;adjusted&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="k"&gt;close&lt;/span&gt;      &lt;span class="k"&gt;volume&lt;/span&gt;
&lt;span class="k"&gt;date&lt;/span&gt;
&lt;span class="ld"&gt;2024-12-24&lt;/span&gt;  &lt;span class="mf"&gt;255.5&lt;/span&gt;  &lt;span class="mf"&gt;258.4&lt;/span&gt;  &lt;span class="mf"&gt;254.2&lt;/span&gt;  &lt;span class="mf"&gt;257.9&lt;/span&gt;          &lt;span class="mf"&gt;257.9&lt;/span&gt;   &lt;span class="mf"&gt;32145600&lt;/span&gt;
&lt;span class="ld"&gt;2024-12-26&lt;/span&gt;  &lt;span class="mf"&gt;258.1&lt;/span&gt;  &lt;span class="mf"&gt;261.0&lt;/span&gt;  &lt;span class="mf"&gt;257.3&lt;/span&gt;  &lt;span class="mf"&gt;259.3&lt;/span&gt;          &lt;span class="mf"&gt;259.3&lt;/span&gt;   &lt;span class="mf"&gt;28761300&lt;/span&gt;
&lt;span class="ld"&gt;2024-12-27&lt;/span&gt;  &lt;span class="mf"&gt;258.8&lt;/span&gt;  &lt;span class="mf"&gt;259.4&lt;/span&gt;  &lt;span class="mf"&gt;254.6&lt;/span&gt;  &lt;span class="mf"&gt;255.6&lt;/span&gt;          &lt;span class="mf"&gt;255.6&lt;/span&gt;   &lt;span class="mf"&gt;41232100&lt;/span&gt;
&lt;span class="ld"&gt;2024-12-30&lt;/span&gt;  &lt;span class="mf"&gt;253.1&lt;/span&gt;  &lt;span class="mf"&gt;254.3&lt;/span&gt;  &lt;span class="mf"&gt;250.7&lt;/span&gt;  &lt;span class="mf"&gt;251.8&lt;/span&gt;          &lt;span class="mf"&gt;251.8&lt;/span&gt;   &lt;span class="mf"&gt;39814700&lt;/span&gt;
&lt;span class="ld"&gt;2024-12-31&lt;/span&gt;  &lt;span class="mf"&gt;250.4&lt;/span&gt;  &lt;span class="mf"&gt;252.1&lt;/span&gt;  &lt;span class="mf"&gt;248.9&lt;/span&gt;  &lt;span class="mf"&gt;250.4&lt;/span&gt;          &lt;span class="mf"&gt;250.4&lt;/span&gt;   &lt;span class="mf"&gt;44021900&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;adjusted_close&lt;/code&gt; column. That's what you backtest on — not raw &lt;code&gt;close&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Script 2: SMA Crossover Strategy
&lt;/h2&gt;

&lt;p&gt;The 20/50-day SMA crossover is the classic momentum signal: go long when the short-term average crosses above the long-term, exit when it crosses below.&lt;/p&gt;

&lt;p&gt;Simple in theory. The implementation details matter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sma_crossover_backtest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;short_window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="n"&gt;long_window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    SMA crossover strategy using adjusted closing prices.
    Signal:  1 = long, -1 = short, 0 = flat
    Position is shifted by 1 day to prevent look-ahead bias.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sma_short&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;rolling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;short_window&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sma_long&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;rolling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;long_window&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Raw signal
&lt;/span&gt;    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sma_short&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sma_long&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sma_short&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sma_long&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="c1"&gt;# Shift by 1 to trade on the *next* day's open — no look-ahead
&lt;/span&gt;    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;position&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Returns
&lt;/span&gt;    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;pct_change&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategy_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;position&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Cumulative performance
&lt;/span&gt;    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;cumprod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_strategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategy_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;cumprod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;


&lt;span class="c1"&gt;# Run it
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_historical_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAPL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2020-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2024-12-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;result_sma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sma_crossover_backtest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;final_market&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result_sma&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;final_strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result_sma&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_strategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Buy &amp;amp; Hold return:   &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_market&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SMA Strategy return: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_strategy&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;shift(1)&lt;/code&gt; on line 16 is the single most important detail. Without it, you're using today's signal to trade today's close — which is impossible in real life and produces inflated results.&lt;/p&gt;




&lt;h2&gt;
  
  
  Script 3: RSI Mean-Reversion Strategy
&lt;/h2&gt;

&lt;p&gt;RSI (Relative Strength Index) measures the speed of price changes on a 0–100 scale. Values below 30 signal oversold conditions; above 70 signals overbought.&lt;/p&gt;

&lt;p&gt;The mean-reversion hypothesis: when a stock is oversold, it tends to recover. When overbought, it tends to pull back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_rsi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Series&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Series&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Wilder&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s RSI using simple moving averages of gains and losses.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;series&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;gain&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;loss&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;avg_gain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rolling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;period&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;avg_loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rolling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;period&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;rs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;avg_gain&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;avg_loss&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rsi_strategy_backtest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;rsi_period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;oversold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;overbought&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    RSI mean-reversion strategy.
    Enter long when RSI drops below &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;oversold&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.
    Exit (go flat) when RSI rises above &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;overbought&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rsi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_rsi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;rsi_period&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rsi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;oversold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="c1"&gt;# Buy oversold
&lt;/span&gt;    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rsi&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;overbought&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;   &lt;span class="c1"&gt;# Sell overbought
&lt;/span&gt;
    &lt;span class="c1"&gt;# Hold position between signals (forward-fill non-zero values)
&lt;/span&gt;    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;position&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;signal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ffill&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fillna&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# Again: no look-ahead
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;adjusted_close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;pct_change&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategy_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;position&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;cumprod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_strategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategy_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;cumprod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;


&lt;span class="c1"&gt;# Run it
&lt;/span&gt;&lt;span class="n"&gt;result_rsi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rsi_strategy_backtest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Buy &amp;amp; Hold return:   &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_rsi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cumulative_market&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RSI Strategy return: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_rsi&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cumulative_strategy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Script 4: Performance Metrics (Sharpe, Max Drawdown, Win Rate)
&lt;/h2&gt;

&lt;p&gt;Return alone means nothing. A strategy returning 40% with -60% max drawdown is not a good strategy.&lt;/p&gt;

&lt;p&gt;This function calculates the three metrics that matter most for evaluating any backtest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_performance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;risk_free_rate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.04&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Compute annualized return, Sharpe ratio, max drawdown, and win rate
    for a backtested strategy DataFrame.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;strategy_returns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strategy_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;dropna&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Annualized return
&lt;/span&gt;    &lt;span class="n"&gt;total_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy_returns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;annual_factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;252&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total_days&lt;/span&gt;
    &lt;span class="n"&gt;strategy_ann&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_strategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;annual_factor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;market_ann&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;annual_factor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="c1"&gt;# Sharpe ratio (annualized)
&lt;/span&gt;    &lt;span class="n"&gt;daily_rf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;risk_free_rate&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;252&lt;/span&gt;
    &lt;span class="n"&gt;excess&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strategy_returns&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;daily_rf&lt;/span&gt;
    &lt;span class="n"&gt;sharpe&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;252&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;excess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;excess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;std&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Maximum drawdown
&lt;/span&gt;    &lt;span class="n"&gt;cumulative&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cumulative_strategy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;dropna&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;rolling_max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cumulative&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cummax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;drawdown&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cumulative&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;rolling_max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;rolling_max&lt;/span&gt;
    &lt;span class="n"&gt;max_dd&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;drawdown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Win rate (percentage of profitable trading days)
&lt;/span&gt;    &lt;span class="n"&gt;active&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strategy_returns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;strategy_returns&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;win_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Strategy Annualized Return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;strategy_ann&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Market Annualized Return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;market_ann&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sharpe Ratio&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;               &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sharpe&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Max Drawdown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;               &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;max_dd&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Win Rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                   &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;win_rate&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;# Evaluate both strategies
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=== SMA Crossover ===&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;calculate_performance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_sma&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;=== RSI Mean-Reversion ===&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;calculate_performance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_rsi&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample output (AAPL, 2020–2024):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=== SMA Crossover ===
  Strategy Annualized Return: 18.4%
  Market Annualized Return:   22.1%
  Sharpe Ratio:               0.91
  Max Drawdown:              -14.3%
  Win Rate:                   53.2%

=== RSI Mean-Reversion ===
  Strategy Annualized Return: 15.7%
  Market Annualized Return:   22.1%
  Sharpe Ratio:               0.78
  Max Drawdown:              -18.6%
  Win Rate:                   51.8%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, buy-and-hold wins on raw return. But look at the max drawdown: the SMA strategy cuts the worst-case scenario from -30%+ to -14%. That's the real value — risk-adjusted performance, not just raw returns.&lt;/p&gt;




&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;Here's the full pipeline: fetch data, run both strategies, compare metrics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Full backtest pipeline
&lt;/span&gt;&lt;span class="n"&gt;symbols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAPL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MSFT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NVDA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ticker&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_historical_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2021-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2024-12-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;sma_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sma_crossover_backtest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;rsi_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rsi_strategy_backtest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  SMA Crossover:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;calculate_performance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sma_result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;    &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  RSI Mean-Reversion:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;calculate_performance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rsi_result&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;    &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a parameter optimization loop (walk-forward testing)&lt;/li&gt;
&lt;li&gt;a multi-ticker portfolio backtest with position sizing&lt;/li&gt;
&lt;li&gt;a live signal generator using EODHD's real-time endpoints&lt;/li&gt;
&lt;li&gt;a dashboard to visualize equity curves and drawdown periods&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;❓ &lt;strong&gt;Is EODHD data adjusted for stock splits and dividends?&lt;/strong&gt;&lt;br&gt;
✅ Yes. The &lt;code&gt;adjusted_close&lt;/code&gt; field in the API response accounts for both splits and dividends. Always use this field for backtesting — raw &lt;code&gt;close&lt;/code&gt; prices will produce misleading signals around corporate actions.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Can I backtest strategies on non-US markets with EODHD?&lt;/strong&gt;&lt;br&gt;
✅ EODHD covers 50+ exchanges including LSE, TSX, ASX, Euronext, and major Asian markets. Just change the &lt;code&gt;exchange&lt;/code&gt; parameter in the API call (e.g., &lt;code&gt;"LSE"&lt;/code&gt; for London, &lt;code&gt;"TO"&lt;/code&gt; for Toronto).&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Does this approach suffer from survivorship bias?&lt;/strong&gt;&lt;br&gt;
✅ Potentially yes, if you only test on stocks that still exist today. To minimize it, include delisted tickers in your universe. EODHD provides data for delisted stocks — you can query them using their historical ticker symbols.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;What's the difference between a good Sharpe ratio and a bad one?&lt;/strong&gt;&lt;br&gt;
✅ As a general benchmark: below 0.5 is weak, 0.5–1.0 is acceptable, above 1.0 is considered good. Above 2.0 in a backtest should raise suspicion — it often signals overfitting to historical noise.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Is there a free tier on EODHD to try this?&lt;/strong&gt;&lt;br&gt;
✅ Yes. EODHD offers a free API key that includes EOD data for US tickers. You can run all the scripts in this article with the free tier. Paid plans start at $19.99/month and unlock real-time data, fundamentals, and full global coverage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before You Ship Your Strategy Live
&lt;/h2&gt;

&lt;p&gt;Two things to check before treating any backtest as real:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction costs.&lt;/strong&gt; Every trade has a spread and a commission. Add a &lt;code&gt;-0.001&lt;/code&gt; cost per trade (0.1%) to your &lt;code&gt;strategy_return&lt;/code&gt; calculation and see if the edge survives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overfitting.&lt;/strong&gt; If you tuned your parameters (RSI period, SMA windows) on the same data you're testing on, your results are optimistic. Use a walk-forward split: train on 70% of the data, test on the remaining 30%.&lt;/p&gt;

&lt;p&gt;Bad data tells you the strategy works. Good data tells you the truth.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;EODHD Financial Data API&lt;/strong&gt;&lt;br&gt;
Adjusted historical prices for 70,000+ tickers across 50+ global exchanges. REST API, JSON responses, Python-friendly.&lt;br&gt;
→ &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=backtest-trading-strategy-python-eodhd&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Start free — no credit card required&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>algorithms</category>
      <category>stocks</category>
      <category>api</category>
    </item>
    <item>
      <title>The 5 Best Insider Trading APIs for Developers in 2026 (Compared)</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Mon, 06 Jul 2026 14:52:54 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/the-5-best-insider-trading-apis-for-developers-in-2026-compared-47ab</link>
      <guid>https://dev.to/kevin_menesesgonzlez/the-5-best-insider-trading-apis-for-developers-in-2026-compared-47ab</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insider trading data comes from SEC Form 4 filings. The API you pick determines whether you get a raw buy/sell flag or a real signal (scheduled 10b5-1 sale vs. open-market conviction move).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EODHD&lt;/strong&gt; ($59.99/mo) — best value, bundled with fundamentals, new Form 4 schema shipped May 2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sec-api.io&lt;/strong&gt; ($49–239/mo) — most comprehensive SEC form-type coverage, dedicated product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial Modeling Prep&lt;/strong&gt; ($19–99/mo) — cheapest entry point, good if you already need fundamentals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quiver Quantitative&lt;/strong&gt; ($75/mo) — alternative-data angle, dashboards included, no commercial rights.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;edgartools&lt;/strong&gt; (free, open-source) — build it yourself, zero cost, zero SLA.&lt;/li&gt;
&lt;li&gt;Full comparison, pricing table, Python example, and FAQ below.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Every insider-trading tutorial online uses the same three tickers: Tesla, Apple, Nvidia.&lt;/p&gt;

&lt;p&gt;That's not laziness. It's because insider data is genuinely useful for exactly one thing: telling you whether the people who run a company are buying or selling their own stock, before the market notices.&lt;/p&gt;

&lt;p&gt;The problem isn't finding an API that has this data.&lt;/p&gt;

&lt;p&gt;Every financial data provider claims to have it.&lt;/p&gt;

&lt;p&gt;The problem is that most of them give you a flattened buy/sell flag with no context, no derivative transactions, and no way to tell a scheduled sale from a real signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reframe: the schema matters more than the coverage
&lt;/h2&gt;

&lt;p&gt;A CFO selling 50,000 shares looks alarming — until you learn it was scheduled 90 days ago under a Rule 10b5-1 plan, filed as an affirmative defense against insider-trading liability.&lt;/p&gt;

&lt;p&gt;Without that footnote, every API looks the same: a name, a ticker, a P or an S.&lt;/p&gt;

&lt;p&gt;With it, you can separate noise from signal.&lt;/p&gt;

&lt;p&gt;That single field — 10b5-1 plan detection — is the line that splits this list into "usable for research" and "usable for screenshots."&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 compared
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=insider-transactions-form4&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;EODHD&lt;/a&gt; — best value, bundled with fundamentals
&lt;/h3&gt;

&lt;p&gt;EODHD rebuilt its Insider Transactions API in May 2026, moving from a flattened one-year feed to a full Form 4 schema pulled directly from SEC EDGAR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full SEC transaction code set (15 codes), not just P/S&lt;/li&gt;
&lt;li&gt;Non-derivative and derivative transactions plus resolved footnotes (10b5-1 detection) in the same object&lt;/li&gt;
&lt;li&gt;5–11 years of history for large caps (AAPL, MSFT, NVDA, KO, GME confirmed)&lt;/li&gt;
&lt;li&gt;Bundled with fundamentals, calendar, and ratios in the same plan — one API key for both&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;US-listed issuers only (same limitation as every provider on this list — Form 4 is a US SEC requirement)&lt;/li&gt;
&lt;li&gt;History depth for smaller/newer tickers still being backfilled as of mid-2026&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; developers who already need (or will need) fundamentals data and want insider transactions bundled instead of paying for a second vendor.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://sec-api.io/" rel="noopener noreferrer"&gt;sec-api.io&lt;/a&gt; — most comprehensive SEC coverage
&lt;/h3&gt;

&lt;p&gt;A commercial API layer over the entire SEC EDGAR archive, not just Form 4.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Broadest form-type coverage of any provider here: Forms 3/4/5, 13F, 13D/G, S-1, Form 144, N-PORT, and 800+ others&lt;/li&gt;
&lt;li&gt;Real-time WebSocket streaming of new filings, indexed in under 300ms of publication&lt;/li&gt;
&lt;li&gt;Native &lt;code&gt;aff10b5One&lt;/code&gt; boolean field for 10b5-1 detection (post-2023 filings) — cleaner than footnote text-matching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free tier is 100 lifetime calls, not monthly — burns fast during development&lt;/li&gt;
&lt;li&gt;Jumps from $49–55/mo (Personal) to $199–239/mo (Business) with no middle tier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; teams that need insider data as one piece of a much larger SEC-filings pipeline (10-K/10-Q parsing, real-time filing alerts, XBRL extraction).&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;a href="https://site.financialmodelingprep.com/" rel="noopener noreferrer"&gt;Financial Modeling Prep&lt;/a&gt; — cheapest bundled entry
&lt;/h3&gt;

&lt;p&gt;FMP folds insider transactions into its broader fundamentals-and-filings package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starter tier at $19/mo is the lowest paid entry point on this list&lt;/li&gt;
&lt;li&gt;Same API key covers financial statements, ratios, DCF valuations, and earnings transcripts&lt;/li&gt;
&lt;li&gt;Well-documented, with Google Sheets/Excel add-ons for non-coders on the team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insider-specific documentation and schema depth (footnote resolution, transaction code breadth) is thinner than EODHD or sec-api.io&lt;/li&gt;
&lt;li&gt;Real-time/intraday features are gated behind higher tiers ($49+/mo)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; early-stage projects that want one cheap API covering fundamentals + insider data without much filtering sophistication.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;a href="https://api.quiverquant.com/" rel="noopener noreferrer"&gt;Quiver Quantitative&lt;/a&gt; — the alternative-data angle
&lt;/h3&gt;

&lt;p&gt;Quiver treats insider trading as one dataset among 30+ alternative signals (Congress trading, lobbying, patents, app ratings).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ships with pre-built dashboards, not just raw JSON — useful if you want a UI fast&lt;/li&gt;
&lt;li&gt;Insider data sits next to Congressional trading, so cross-referencing "who's buying what" across insiders and politicians is one query away&lt;/li&gt;
&lt;li&gt;MCP server available for natural-language queries from Claude or Cursor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insider Trading is gated behind the $75/mo Trader tier ($62.50/mo billed annually) — the $30/mo Hobbyist tier doesn't include it&lt;/li&gt;
&lt;li&gt;Explicitly no commercial-use rights below the enterprise tier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; individual researchers who want insider data alongside other alt-data signals in one dashboard, not developers building a production pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;a href="https://github.com/dgunning/edgartools" rel="noopener noreferrer"&gt;edgartools&lt;/a&gt; — free, open-source, DIY
&lt;/h3&gt;

&lt;p&gt;Not a hosted API. A Python library (5M+ PyPI downloads) that parses SEC EDGAR directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Completely free, no API key, no rate-limit anxiety&lt;/li&gt;
&lt;li&gt;Parses Form 4 into structured objects with computed helpers like &lt;code&gt;get_ownership_summary()&lt;/code&gt; and &lt;code&gt;get_net_shares_traded()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Handles amendments (3/A, 4/A, 5/A) transparently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You maintain the infrastructure — no SLA, no support line, no guaranteed uptime&lt;/li&gt;
&lt;li&gt;No bundled fundamentals, no hosted dashboard, no MCP server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; solo developers or students prototyping an idea before committing budget to a paid provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Entry price&lt;/th&gt;
&lt;th&gt;Insider-specific schema depth&lt;/th&gt;
&lt;th&gt;Bundled fundamentals&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EODHD&lt;/td&gt;
&lt;td&gt;$59.99/mo&lt;/td&gt;
&lt;td&gt;High (15 codes, footnotes, derivatives)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sec-api.io&lt;/td&gt;
&lt;td&gt;$49/mo&lt;/td&gt;
&lt;td&gt;Highest (native 10b5-1 flag)&lt;/td&gt;
&lt;td&gt;No (filings-focused)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FMP&lt;/td&gt;
&lt;td&gt;$19/mo&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quiver Quantitative&lt;/td&gt;
&lt;td&gt;$75/mo&lt;/td&gt;
&lt;td&gt;Medium (alt-data framing)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;edgartools&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;High (open-source parsing)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Building a conviction-signal screener (EODHD example)
&lt;/h2&gt;

&lt;p&gt;Since EODHD is the best-value pick for anyone who also needs fundamentals, here's the fastest path from API key to a working screener.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;SYMBOL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NVDA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://eodhd.com/api/sec-filings/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;SYMBOL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/form4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page[limit]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;filings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;filing&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;footnote_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;footnotes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;is_10b5_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10b5-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;footnote_text&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;filing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;non_derivative&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transaction_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scheduled (10b5-1)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_10b5_1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;open-market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reporting_owner_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;officer_title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;insider&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;) &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sold &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;shares_amount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; shares at $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price_per_share&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;— &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Jensen Huang (Chief Executive Officer) sold 25000 shares at $890 — scheduled (10b5-1)
Colette Kress (Chief Financial Officer) sold 12000 shares at $885 — scheduled (10b5-1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an alert bot that only fires on non-scheduled (open-market) sales — the ones that actually carry signal&lt;/li&gt;
&lt;li&gt;a dashboard cross-referencing insider activity with earnings dates and price action&lt;/li&gt;
&lt;li&gt;a screener ranking your entire watchlist by dollar value of non-scheduled transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Get a free API key here: &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=insider-transactions-form4&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;EODHD&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing model summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plan type&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;What it unlocks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EODHD Free&lt;/td&gt;
&lt;td&gt;$0/mo&lt;/td&gt;
&lt;td&gt;20 calls/day, no Fundamentals access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EODHD Fundamentals&lt;/td&gt;
&lt;td&gt;$59.99/mo&lt;/td&gt;
&lt;td&gt;Financials, ratios, calendar, &lt;strong&gt;Form 4 insider transactions&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EODHD All-in-One&lt;/td&gt;
&lt;td&gt;$99.99/mo&lt;/td&gt;
&lt;td&gt;Everything above + real-time, news, options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sec-api.io Personal&lt;/td&gt;
&lt;td&gt;$49–55/mo&lt;/td&gt;
&lt;td&gt;Insider Trading API + core SEC endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sec-api.io Business&lt;/td&gt;
&lt;td&gt;$199–239/mo&lt;/td&gt;
&lt;td&gt;Higher volume, redistribution rights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FMP Starter&lt;/td&gt;
&lt;td&gt;$19/mo&lt;/td&gt;
&lt;td&gt;300 calls/min, 5-year history, insider data included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quiver Trader&lt;/td&gt;
&lt;td&gt;$62.50–75/mo&lt;/td&gt;
&lt;td&gt;Insider Trading + 30 alt-data sets, no commercial rights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;edgartools&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;Self-hosted, unlimited, zero support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each EODHD Form 4 request consumes 10 API calls against your daily quota; pagination is capped at 100 filings per page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Known limitations across all providers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;US-only.&lt;/strong&gt; Form 4 is a US SEC requirement. None of these APIs cover non-US insider disclosures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blackout gaps are expected.&lt;/strong&gt; No filings in the 4–6 weeks before earnings usually means insiders are in a blackout period, not that nothing happened.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;History depth varies by ticker&lt;/strong&gt;, not just by provider — large caps go back years, small/recent listings may only have 12 months regardless of which API you use.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What's the difference between Form 3, 4, and 5?&lt;/strong&gt;&lt;br&gt;
Form 3 is the initial ownership statement when someone becomes an insider. Form 4 reports changes (buys, sells, grants) within two business days. Form 5 is an annual catch-up for anything not reported on Form 4. Almost all insider-trading analysis uses Form 4.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I detect scheduled (10b5-1) sales vs. real signal?&lt;/strong&gt;&lt;br&gt;
Since the SEC's 2023 amendments, newer Form 4 filings include an explicit affirmation field; for older filings, search the footnote text for "10b5-1". EODHD and sec-api.io both expose this — EODHD via resolved footnotes, sec-api.io via a native boolean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can any of these APIs cover non-US insider trading?&lt;/strong&gt;&lt;br&gt;
No. Form 4 is exclusively a US SEC requirement. For other markets you'd need each country's local equivalent (rare to find via API).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a free option that isn't a trial?&lt;/strong&gt;&lt;br&gt;
Yes — edgartools is free and open-source with no usage cap, but you host and maintain it yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which one should I pick if I already use EODHD or FMP for prices/fundamentals?&lt;/strong&gt;&lt;br&gt;
Stay on the same provider. Both bundle insider transactions into their existing fundamentals plans, so adding insider data costs nothing extra in vendor overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The 10b5-1 flag is the single most useful field in insider-trading data — it's what turns a raw sell transaction into an actual signal.&lt;/li&gt;
&lt;li&gt;If you already need fundamentals data, EODHD or FMP make more sense than a dedicated insider-only vendor.&lt;/li&gt;
&lt;li&gt;If insider data is one piece of a bigger SEC-filings pipeline, sec-api.io's broader form coverage justifies the higher price.&lt;/li&gt;
&lt;li&gt;If budget is zero and you're comfortable maintaining your own code, edgartools gets you the same underlying data for free.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>stocks</category>
      <category>data</category>
      <category>development</category>
    </item>
    <item>
      <title>I Let Claude Analyze 500 Stocks—Here's What It Picked</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Sun, 21 Jun 2026 14:43:02 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/i-let-claude-analyze-500-stocks-heres-what-it-picked-5cpk</link>
      <guid>https://dev.to/kevin_menesesgonzlez/i-let-claude-analyze-500-stocks-heres-what-it-picked-5cpk</guid>
      <description>&lt;p&gt;"AI picked these stocks" is one of the most repeated claims on FinTwit right now.&lt;/p&gt;

&lt;p&gt;Almost none of it is reproducible.&lt;/p&gt;

&lt;p&gt;Screenshot of a ChatGPT chat. No data source. No filters. No way to check if the tickers even exist. If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building AI agents that touch market data,&lt;/li&gt;
&lt;li&gt;evaluating whether LLMs can actually reason over financial datasets,&lt;/li&gt;
&lt;li&gt;or just tired of "AI stock picker" threads with zero code attached,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this one's different. Every number below came from a live screen. There's code for developers and a copy-paste prompt for everyone else.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "Ask ChatGPT to Pick Stocks" Doesn't Work
&lt;/h2&gt;

&lt;p&gt;Most "AI stock picking" content fails for one boring reason: the model never touches real data.&lt;/p&gt;

&lt;p&gt;You ask an LLM to "analyze the market," and it answers from training data that's months or years stale. It might invent a ticker. It might quote a P/E ratio from memory that hasn't been true since 2023.&lt;/p&gt;

&lt;p&gt;Developers discover this too late — usually after publishing a "top 10 AI stock picks" post and getting called out in the comments for a ticker that delisted last year.&lt;/p&gt;

&lt;p&gt;The reasoning isn't the problem.&lt;/p&gt;

&lt;p&gt;The data pipeline is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem Isn't Intelligence. It's Blindness.
&lt;/h2&gt;

&lt;p&gt;Claude can reason extremely well over structured data — rank by valuation, weigh momentum against volatility, spot a sector cluster.&lt;/p&gt;

&lt;p&gt;What it can't do on its own is see the market.&lt;/p&gt;

&lt;p&gt;Give it that, and the "AI stock picker" stops being a parlor trick and starts being an actual screening assistant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving Claude Eyes: EODHD's MCP Server
&lt;/h2&gt;

&lt;p&gt;EODHD exposes a stock screener as an MCP tool. Instead of scraping pages or hardcoding a REST client, Claude connects directly to it and calls it like any other tool.&lt;/p&gt;

&lt;p&gt;Through the MCP connection, Claude gets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Live fundamentals (market cap, P/E, EPS, dividend yield)&lt;/li&gt;
&lt;li&gt;Price performance windows (1-day and 5-day returns)&lt;/li&gt;
&lt;li&gt;Volume data to filter out illiquid noise&lt;/li&gt;
&lt;li&gt;Sector and industry tags for clustering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No scraping. No stale CSV exports. No hallucinated tickers — every result is a real, currently-listed instrument.&lt;/p&gt;

&lt;p&gt;If you're already using EODHD for other projects, this is the same dataset — just exposed as a tool Claude can call directly instead of a REST endpoint you wrap yourself.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=ai-stock-screener-claude-mcp&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Explore the EODHD MCP integration&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself — No Code Required
&lt;/h2&gt;

&lt;p&gt;You don't need an API key or a Python environment to test this. If you have Claude with the EODHD connector enabled, paste this prompt directly into the chat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connect to the EODHD MCP stock screener and run this exact query:

- US-listed stocks only
- Market capitalization above $10 billion
- Average 200-day volume above 1 million shares
- Sort by 5-day return, descending
- Return the top 10 results

For each result, show: ticker, company name, sector, 5-day return %,
and market cap. Then add one sentence identifying any sector pattern
across the list — don't force a narrative if there isn't one.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Claude calls the tool, gets back real rows, and reasons over them the same way it would for the code version below.&lt;/p&gt;

&lt;p&gt;A few ways to push it further once you've run the base prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Now filter that same list down to only the Technology sector
and explain what's driving the move in plain English.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Re-run the screen but swap 5-day return for market cap above $50B
and dividend yield above 2%. I want value, not momentum.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting Up the Connection (For Developers)
&lt;/h2&gt;

&lt;p&gt;The MCP config is what makes this work for anyone building it into an app instead of chatting it manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP server config&lt;/strong&gt; (Claude Desktop or API):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eodhd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcpv2.eodhd.dev/v2/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"url"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Calling it via the API&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;beta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mcp_servers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://mcpv2.eodhd.dev/v2/mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eodhd-mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Screen US stocks with market cap above $10B and average &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;200-day volume above 1M shares. Sort by 5-day return descending. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return the top 10 with sector and a one-line reason for momentum.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="n"&gt;extra_headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic-beta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mcp-client-2025-04-04&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Behind the scenes, Claude translates the plain-language request into a structured call to the screener tool — filtering by &lt;code&gt;market_capitalization&lt;/code&gt;, &lt;code&gt;avgvol_200d&lt;/code&gt;, and sorting by &lt;code&gt;refund_5d_p&lt;/code&gt; — and gets back real rows, not a guess.&lt;/p&gt;

&lt;p&gt;From here you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a daily momentum digest delivered to Slack&lt;/li&gt;
&lt;li&gt;a screener bot wired into a Telegram channel&lt;/li&gt;
&lt;li&gt;a backtesting loop that screens, logs picks, and checks them a week later&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Came Back: 10 Real Picks From a Live Screen
&lt;/h2&gt;

&lt;p&gt;Filters: US-listed, market cap above $10B, average 200-day volume above 1M shares, sorted by 5-day return.&lt;/p&gt;

&lt;p&gt;This wasn't curated. It's the raw output, ranked by Claude after the screener returned the candidates.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ticker&lt;/th&gt;
&lt;th&gt;Company&lt;/th&gt;
&lt;th&gt;Sector&lt;/th&gt;
&lt;th&gt;5d Return&lt;/th&gt;
&lt;th&gt;Mkt Cap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WDC&lt;/td&gt;
&lt;td&gt;Western Digital&lt;/td&gt;
&lt;td&gt;Technology&lt;/td&gt;
&lt;td&gt;+40.99%&lt;/td&gt;
&lt;td&gt;$257B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BE&lt;/td&gt;
&lt;td&gt;Bloom Energy&lt;/td&gt;
&lt;td&gt;Industrials&lt;/td&gt;
&lt;td&gt;+32.16%&lt;/td&gt;
&lt;td&gt;$93.6B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NBIS&lt;/td&gt;
&lt;td&gt;Nebius Group&lt;/td&gt;
&lt;td&gt;Communication Services&lt;/td&gt;
&lt;td&gt;+29.00%&lt;/td&gt;
&lt;td&gt;$72.8B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CIFR&lt;/td&gt;
&lt;td&gt;Cipher Mining&lt;/td&gt;
&lt;td&gt;Technology&lt;/td&gt;
&lt;td&gt;+28.94%&lt;/td&gt;
&lt;td&gt;$11.9B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MRNA&lt;/td&gt;
&lt;td&gt;Moderna&lt;/td&gt;
&lt;td&gt;Healthcare&lt;/td&gt;
&lt;td&gt;+28.85%&lt;/td&gt;
&lt;td&gt;$25.4B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ARM&lt;/td&gt;
&lt;td&gt;Arm Holdings&lt;/td&gt;
&lt;td&gt;Technology&lt;/td&gt;
&lt;td&gt;+28.41%&lt;/td&gt;
&lt;td&gt;$469B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ENTG&lt;/td&gt;
&lt;td&gt;Entegris&lt;/td&gt;
&lt;td&gt;Technology&lt;/td&gt;
&lt;td&gt;+23.36%&lt;/td&gt;
&lt;td&gt;$27.2B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STX&lt;/td&gt;
&lt;td&gt;Seagate Technology&lt;/td&gt;
&lt;td&gt;Technology&lt;/td&gt;
&lt;td&gt;+23.29%&lt;/td&gt;
&lt;td&gt;$242B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CRWV&lt;/td&gt;
&lt;td&gt;CoreWeave&lt;/td&gt;
&lt;td&gt;Technology&lt;/td&gt;
&lt;td&gt;+23.20%&lt;/td&gt;
&lt;td&gt;$64.4B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ALGM&lt;/td&gt;
&lt;td&gt;Allegro Microsystems&lt;/td&gt;
&lt;td&gt;Technology&lt;/td&gt;
&lt;td&gt;+23.02%&lt;/td&gt;
&lt;td&gt;$11B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Claude's read on the cluster: seven of the ten sit in storage, semiconductors, or AI infrastructure — Western Digital and Seagate riding a hard-drive demand spike, Arm and Entegris tied to the chip cycle, CoreWeave and Nebius both pure AI-compute plays.&lt;/p&gt;

&lt;p&gt;That's not Claude being clever. That's the screen surfacing a real sector rotation, and Claude naming the pattern instead of leaving you to spot it in a spreadsheet.&lt;/p&gt;

&lt;p&gt;Moderna is the outlier — a biotech name riding its own news cycle, disconnected from the hardware story.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Guide to Screening With Claude + MCP
&lt;/h2&gt;

&lt;p&gt;Running one screen is easy. Getting useful output every time takes a bit more discipline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Always specify liquidity, not just size.&lt;/strong&gt;&lt;br&gt;
Market cap alone lets illiquid OTC tickers sneak in — names that move 200% on 200 shares traded. Add a volume filter (&lt;code&gt;avgvol_200d &amp;gt; 1,000,000&lt;/code&gt;) or you'll get noise dressed up as momentum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Separate the screen from the narrative.&lt;/strong&gt;&lt;br&gt;
Ask Claude to return raw data first. Then, in a second message, ask it to interpret the pattern. Mixing both in one prompt makes it more likely Claude reaches for a story before checking if one's actually there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Re-run before you publish.&lt;/strong&gt;&lt;br&gt;
Market data is a snapshot. A screen run on Monday is stale by Friday. If you're writing this up for a newsletter or post, re-run it the morning you publish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Pin your filters in the prompt, not in your head.&lt;/strong&gt;&lt;br&gt;
"Large, liquid, momentum stocks" means nothing to a screener. "Market cap &amp;gt; $10B, avgvol_200d &amp;gt; 1M, sorted by refund_5d_p descending" means everything. Specificity is the whole game.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Use sector clustering as a sanity check, not a conclusion.&lt;/strong&gt;&lt;br&gt;
If 7 of 10 picks share a sector, that's a real signal worth investigating — not proof you've found alpha. Treat it as a research starting point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Cross-check anything you'd act on.&lt;/strong&gt;&lt;br&gt;
A screener tells you what moved. It doesn't tell you why a specific company moved, or whether the move is sustainable. Pull the news, check the earnings calendar, read the filing — before any of this touches real money.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A reproducible screen beats a screenshot every time — anyone can run this exact query and check the output&lt;/li&gt;
&lt;li&gt;MCP turns Claude from a chatbot into an agent with real market eyes, no custom REST wrapper required&lt;/li&gt;
&lt;li&gt;This is a starting filter for further research, not investment advice — verify before you act on any of it&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;❓ &lt;strong&gt;Can I run this without writing any code?&lt;/strong&gt;&lt;br&gt;
✅ Yes. If you have the EODHD MCP connector enabled in Claude, just paste the prompt in the "Try It Yourself" section above. Claude calls the screener tool directly — no API key setup or Python environment needed.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Is the EODHD MCP server free to use?&lt;/strong&gt;&lt;br&gt;
✅ It depends on your EODHD API plan — the screener tool consumes API calls against your existing subscription tier. Check EODHD's pricing page for current limits on screener calls per day.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Does Claude ever hallucinate tickers when using MCP?&lt;/strong&gt;&lt;br&gt;
✅ No, not when the data comes through the tool call. Every ticker in the results above came directly from the screener response — Claude is reasoning over real rows, not generating them from memory.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Can I use this for sectors other than tech?&lt;/strong&gt;&lt;br&gt;
✅ Yes. Swap the filters in the prompt — set &lt;code&gt;sector = "Healthcare"&lt;/code&gt; or &lt;code&gt;sector = "Energy"&lt;/code&gt; and re-run. The screener supports filtering by sector, industry, country, and several other fields.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Is this financial advice?&lt;/strong&gt;&lt;br&gt;
✅ No. This is a demonstration of a reproducible screening workflow. The output is a filtered list based on price momentum and market cap, not a recommendation to buy or sell anything.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;What's the difference between this and just asking ChatGPT to pick stocks?&lt;/strong&gt;&lt;br&gt;
✅ Without a connected data tool, an LLM answers from training data that can be stale by months. With MCP, Claude is calling a live screener and reasoning over real, current numbers — the difference between guessing and looking.&lt;/p&gt;

&lt;p&gt;If you're a software or API company looking to explain your product through high-quality educational content (not marketing fluff), feel free to connect with me on LinkedIn.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=ai-stock-screener-claude-mcp&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Get started with EODHD's API and MCP server&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>stocks</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Building a Finviz Alternative With Claude Code and EODHD API</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Sat, 20 Jun 2026 13:56:19 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/building-a-finviz-alternative-with-claude-code-and-eodhd-api-1115</link>
      <guid>https://dev.to/kevin_menesesgonzlez/building-a-finviz-alternative-with-claude-code-and-eodhd-api-1115</guid>
      <description>&lt;p&gt;Most investors think they need more tools to make better decisions.&lt;/p&gt;

&lt;p&gt;The truth is different.&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;screening stocks across multiple sources,&lt;/li&gt;
&lt;li&gt;checking sector performance on a separate site,&lt;/li&gt;
&lt;li&gt;or tracking ideas in a spreadsheet that's always out of date,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you don't have a tools problem. You have a fragmentation problem.&lt;/p&gt;

&lt;p&gt;A typical investing workflow looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finviz for screening stocks&lt;/li&gt;
&lt;li&gt;Yahoo Finance for company information&lt;/li&gt;
&lt;li&gt;TradingView for charts&lt;/li&gt;
&lt;li&gt;Another site for market breadth&lt;/li&gt;
&lt;li&gt;Excel for tracking ideas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Too many tabs.&lt;br&gt;
Too much context switching.&lt;/p&gt;

&lt;p&gt;The more fragmented the workflow, the harder it is to spot opportunities.&lt;/p&gt;

&lt;p&gt;So instead of opening five different tools every morning, I built one: &lt;strong&gt;FinView&lt;/strong&gt;, an open-source Finviz alternative powered by Claude Code and the EODHD API.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Real Problem Isn't Data — It's Structure
&lt;/h2&gt;

&lt;p&gt;Developers building their own stock market dashboard usually hit the same wall.&lt;/p&gt;

&lt;p&gt;Data is scattered across providers. Real-time prices come from one source, fundamentals from another, historical data from a third. Stitching that together used to take weeks.&lt;/p&gt;

&lt;p&gt;The real problem isn't a lack of financial data.&lt;/p&gt;

&lt;p&gt;It's the lack of a single, reliable source feeding a clean structure.&lt;/p&gt;

&lt;p&gt;That's the gap FinView was built to close: one dashboard, one API, every workflow a Finviz user expects.&lt;/p&gt;
&lt;h2&gt;
  
  
  What FinView Includes
&lt;/h2&gt;

&lt;p&gt;The goal was simple: answer five questions without leaving one screen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the market doing today?&lt;/li&gt;
&lt;li&gt;Which sectors are leading?&lt;/li&gt;
&lt;li&gt;What stocks have unusual volume?&lt;/li&gt;
&lt;li&gt;What companies deserve deeper analysis?&lt;/li&gt;
&lt;li&gt;Is the market bullish or bearish?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  1. Real-Time Market Dashboard
&lt;/h3&gt;

&lt;p&gt;The homepage gives an instant read on market conditions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S&amp;amp;P 500, Nasdaq, Dow Jones, Russell 2000&lt;/li&gt;
&lt;li&gt;Market breadth indicators&lt;/li&gt;
&lt;li&gt;Advance/decline ratios&lt;/li&gt;
&lt;li&gt;Bull vs. bear sentiment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before looking for opportunities, you need to understand the environment. This section does that in seconds.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Stock Screener
&lt;/h3&gt;

&lt;p&gt;Finviz's screener is its most-used feature, so FinView needed the same logic.&lt;/p&gt;

&lt;p&gt;Users can filter stocks by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Price&lt;/li&gt;
&lt;li&gt;Volume&lt;/li&gt;
&lt;li&gt;Relative performance&lt;/li&gt;
&lt;li&gt;Technical signals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of manually scanning charts, the screener surfaces stocks hitting new highs, showing unusual volume, or leading the day's gainers and losers — instantly.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Sector Heatmap
&lt;/h3&gt;

&lt;p&gt;This is the feature that does the most work with the least effort.&lt;/p&gt;

&lt;p&gt;A heatmap makes rotation visible at a glance: technology weak, utilities strong, financials leading, industrials outperforming. One visualization often reveals more than three market reports combined.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Company Detail Pages
&lt;/h3&gt;

&lt;p&gt;Finding a stock is only step one. Understanding it is where decisions actually happen.&lt;/p&gt;

&lt;p&gt;Each company page shows market data, fundamental metrics, historical performance, and key company information — creating a clean path from discovery to analysis.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Claude Code Changed the Build
&lt;/h2&gt;

&lt;p&gt;The interesting part wasn't the dashboard. It was the process.&lt;/p&gt;

&lt;p&gt;Five years ago, a project like this meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend development&lt;/li&gt;
&lt;li&gt;Backend architecture&lt;/li&gt;
&lt;li&gt;Database design&lt;/li&gt;
&lt;li&gt;API integrations&lt;/li&gt;
&lt;li&gt;UI design and testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Weeks, sometimes months, of work.&lt;/p&gt;

&lt;p&gt;With Claude Code, most of that repetitive implementation got handled automatically. I focused on product design, architecture decisions, and data integration instead.&lt;/p&gt;

&lt;p&gt;This doesn't replace software engineering.&lt;/p&gt;

&lt;p&gt;It removes the boilerplate so the engineering that matters gets more attention.&lt;/p&gt;
&lt;h2&gt;
  
  
  Connecting the EODHD API
&lt;/h2&gt;

&lt;p&gt;A dashboard is only as good as its data feed. FinView needed one provider that covered real-time prices, historical data, fundamentals, and global market coverage — without juggling three separate integrations.&lt;/p&gt;

&lt;p&gt;This is where the &lt;strong&gt;EODHD API&lt;/strong&gt; fits in. It provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-time market data&lt;/li&gt;
&lt;li&gt;Historical price data&lt;/li&gt;
&lt;li&gt;Company fundamentals&lt;/li&gt;
&lt;li&gt;Market indices and sector data&lt;/li&gt;
&lt;li&gt;Global exchange coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simplified example of pulling stock data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AAPL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://eodhd.com/api/real-time/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;?api_token=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;fmt=json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;screeners&lt;/li&gt;
&lt;li&gt;alert systems&lt;/li&gt;
&lt;li&gt;AI trading agents&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Looking for one API instead of five?&lt;/strong&gt;&lt;br&gt;
EODHD gives you real-time prices, fundamentals, and historical data in a single REST API — no scraping, no rate-limit roulette.&lt;br&gt;
&lt;strong&gt;→ &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=finviz-alternative-claude-code-eodhd-api&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Explore EODHD APIs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Building the Market Overview
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;indices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^GSPC&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^IXIC&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^DJI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^RUT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_market_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This powers the market snapshot at the top of the dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the Screener
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;change_percent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The production version supports far more filters, but the logic stays the same: retrieve data, apply conditions, display opportunities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Project Is Open Source
&lt;/h2&gt;

&lt;p&gt;Developers learn faster from real projects than from documentation alone.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/Kevinelectronics/finviz-clone-claude-code-eodhd" rel="noopener noreferrer"&gt;FinView repository&lt;/a&gt; demonstrates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code development workflows&lt;/li&gt;
&lt;li&gt;EODHD API integration patterns&lt;/li&gt;
&lt;li&gt;Dashboard and screener architecture&lt;/li&gt;
&lt;li&gt;Sector heatmap logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're learning AI-assisted development or evaluating financial data APIs, it's a practical reference, not just a writeup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Lesson Wasn't About Stocks
&lt;/h2&gt;

&lt;p&gt;It was about leverage.&lt;/p&gt;

&lt;p&gt;AI development tools are changing the economics of building software. The gap between "I have an idea" and "I have a working product" is shrinking fast.&lt;/p&gt;

&lt;p&gt;Individual developers can now ship what used to require a full team.&lt;/p&gt;

&lt;p&gt;That shift changes who gets to build fintech tools — not just who gets to use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;❓ &lt;strong&gt;Is FinView production-ready?&lt;/strong&gt;&lt;br&gt;
✅ It's primarily educational and experimental, but the architecture is solid enough to serve as a foundation for more advanced trading or research platforms.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Which technologies were used to build it?&lt;/strong&gt;&lt;br&gt;
✅ Claude Code for development, the EODHD API for market data, and JavaScript/HTML/CSS for the frontend.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Can I build a similar dashboard without AI tools?&lt;/strong&gt;&lt;br&gt;
✅ Yes. AI mainly reduces development time and automates repetitive implementation — understanding the underlying logic still matters.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Why not just use Finviz?&lt;/strong&gt;&lt;br&gt;
✅ Finviz is a solid product. This project exists to learn AI-assisted development and build a customizable, open-source alternative you fully control.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Is there a free tier for the EODHD API?&lt;/strong&gt;&lt;br&gt;
✅ Yes, EODHD offers a free tier suitable for testing screeners and dashboards before scaling to a paid plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This started with one question: can Claude Code help build a Finviz-style platform from scratch?&lt;/p&gt;

&lt;p&gt;The answer was yes.&lt;/p&gt;

&lt;p&gt;The bigger realization was this: the future belongs to people who combine AI tools, reliable data sources, and domain expertise. When those three line up, the speed of creation becomes extraordinary.&lt;/p&gt;

&lt;p&gt;Explore the code, contribute, or build your own version: &lt;a href="https://github.com/Kevinelectronics/finviz-clone-claude-code-eodhd" rel="noopener noreferrer"&gt;FinView on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Want the data layer behind FinView?&lt;/strong&gt;&lt;br&gt;
Get real-time and historical market data, fundamentals, and global coverage through one simple API.&lt;br&gt;
&lt;strong&gt;→ &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=finviz-alternative-claude-code-eodhd-api&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Start with EODHD&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>api</category>
      <category>claude</category>
      <category>webdev</category>
      <category>stocks</category>
    </item>
    <item>
      <title>The 10 Best Financial APIs for AI Coding Tools (2026)</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Fri, 19 Jun 2026 08:21:00 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/the-10-best-financial-apis-for-ai-coding-tools-2026-4lok</link>
      <guid>https://dev.to/kevin_menesesgonzlez/the-10-best-financial-apis-for-ai-coding-tools-2026-4lok</guid>
      <description>&lt;p&gt;Cursor can scaffold a fintech app in twenty minutes. Claude Code can wire the backend, write the tests, and ship a working build before lunch.&lt;/p&gt;

&lt;p&gt;None of that means the app is correct.&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building a portfolio tracker,&lt;/li&gt;
&lt;li&gt;vibe-coding a stock screener,&lt;/li&gt;
&lt;li&gt;or shipping a trading dashboard for a client,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the API you plug in decides whether the AI gets it right the first time, or quietly invents endpoints that don't exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your AI coding tool is only as good as the docs it's reading
&lt;/h2&gt;

&lt;p&gt;Here's what actually happens. You open Cursor, paste a financial API's docs link, and ask it to build a price-history endpoint. Half the time it works. The other half, it hallucinates a parameter that was deprecated two years ago, or guesses at a response shape that hasn't matched reality since the provider's last redesign.&lt;/p&gt;

&lt;p&gt;That's not a model problem.&lt;/p&gt;

&lt;p&gt;It's a documentation problem. Most financial data providers wrote their docs for a human skimming a browser tab, not for a model parsing structure. No &lt;code&gt;llms.txt&lt;/code&gt;. No machine-readable OpenAPI spec. No SDK that matches what's actually in the docs.&lt;/p&gt;

&lt;p&gt;Developers discover this the expensive way: after the AI ships broken code with confidence, and nobody catches it until the demo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coverage matters less than legibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In 2026, the financial APIs worth using with an AI coding tool aren't necessarily the ones with the most tickers. They're the ones whose documentation, specs, and SDKs are clean enough that Cursor, Claude Code, Windsurf, or Copilot can generate correct code against them on the first pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to check before you pick one
&lt;/h2&gt;

&lt;p&gt;Before wiring any financial API into an AI-assisted workflow, look for four things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Machine-readable docs&lt;/strong&gt; — an &lt;code&gt;llms.txt&lt;/code&gt; file, an OpenAPI 3.x spec, or both&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An official SDK&lt;/strong&gt; in your stack's language, not just community wrappers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A real free tier&lt;/strong&gt;, so the AI can be tested against live responses while you prototype&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictable pricing&lt;/strong&gt;, because AI coding tools tend to make you move fast, and fast means more API calls than you planned for&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use EODHD for most of this kind of work, mainly because its OpenAPI spec and AI Agent Skills are built for exactly this. 👉 &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-financial-apis-ai-coding-tools-2026&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Get an EODHD key here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are the ten that hold up.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-financial-apis-ai-coding-tools-2026&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;EODHD&lt;/a&gt; — Best all-around for AI-assisted building
&lt;/h2&gt;

&lt;p&gt;EODHD covers 60+ exchanges and 150,000+ tickers, with 30+ years of history on major markets, all returned as clean JSON.&lt;/p&gt;

&lt;p&gt;What makes it the strongest pick for coding with AI specifically is the sheer number of on-ramps: an official MCP server with 75 tools, an OpenAPI 3.1 spec covering 74 endpoints, AI Agent Skills built for Claude Code and Codex-style agents, and a ChatGPT assistant trained on its own documentation. When you ask Cursor or Claude Code to build against it, the model has a machine-readable spec to read instead of guessing from prose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Broadest AI on-ramp of any provider here, global coverage, fundamentals and technicals under one key, accessible pricing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Real-time runs over per-ticker WebSocket rather than ultra-low-latency feeds. US options is a paid add-on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier, then roughly €20–€100/month depending on real-time and intraday access; commercial plans from around €400/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Anyone building a fintech app end-to-end with an AI coding tool and wants one API instead of five.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-financial-apis-ai-coding-tools-2026&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Grab a free EODHD key and point your AI coding tool at it&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://massive.com/" rel="noopener noreferrer"&gt;Massive&lt;/a&gt; (formerly Polygon.io) — Best for real-time, latency-sensitive apps
&lt;/h2&gt;

&lt;p&gt;Polygon rebranded to Massive in 2026, though most developers still call it Polygon out of habit. The product underneath is unchanged: tick-by-tick trades, WebSocket streaming, and low-latency US equities and options data.&lt;/p&gt;

&lt;p&gt;Its MCP server takes an unusual approach. Instead of one tool per endpoint, it gives the model three composable tools, search, call, and query, that cover the entire API surface and stay in sync automatically as Massive ships new endpoints. For an AI coding tool exploring an API it's never seen, that's a meaningfully shorter learning curve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Real-time WebSockets, options with Greeks, a well-designed MCP that scales with the API instead of falling behind it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; US-centric. Real-time access sits on higher tiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier with delayed data; paid stock plans roughly $29–$199+/month, with real-time gated to higher tiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Trading dashboards and live-data apps where milliseconds matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://alpaca.markets/" rel="noopener noreferrer"&gt;Alpaca&lt;/a&gt; — Best for apps that need to act, not just read
&lt;/h2&gt;

&lt;p&gt;Alpaca is a self-clearing broker-dealer, which means it's the rare entry on this list where the AI-built app doesn't just display data, it can place trades.&lt;/p&gt;

&lt;p&gt;Alpaca has leaned hard into the coding-tool angle specifically. Its Trading MCP Server and a new Trading CLI are both built from its published OpenAPI specs and explicitly documented to work with Claude Code, Cursor, VS Code, Gemini CLI, and PyCharm. Account creation is free, there's no minimum deposit, and paper trading with $100K in simulated funds means an AI coding tool can build and test a full trading flow without touching real money.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Free brokerage account, paper trading out of the box, MCP and CLI built around AI coding workflows, equities/options/crypto in one API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Full real-time market coverage (beyond the free IEX feed) requires the paid Algo Trader Plus tier. It's brokerage-first, not a general research dataset.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free account and Basic market data; paid tier for full real-time stock and options coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Apps where the AI needs to read market data &lt;em&gt;and&lt;/em&gt; execute on it, with a safe paper-trading sandbox while you build.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. &lt;a href="https://site.financialmodelingprep.com/" rel="noopener noreferrer"&gt;Financial Modeling Prep&lt;/a&gt; — Best for fundamentals-heavy apps
&lt;/h2&gt;

&lt;p&gt;If your AI coding tool's job is reading balance sheets instead of chasing ticks, FMP is the deepest option here. It exposes income statements, ratios, DCF models, filings, transcripts, and institutional holdings across 100+ endpoints, in both REST and WebSocket form.&lt;/p&gt;

&lt;p&gt;FMP's documentation is consistently cited as one of the easier financial APIs to scaffold against, partly because the endpoint structure is predictable across asset classes once an AI coding tool learns the pattern from one or two examples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Deepest fundamentals and ratios, generous endpoint count, JSON and CSV both supported.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Real-time data, full global coverage, and earnings transcripts live behind the higher tiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free (250 calls/day), Starter around $19/month, Premium around $69/month, Ultimate around $139/month for global coverage and transcripts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Valuation tools, equity-research dashboards, and any app where the AI is reasoning about a company's financials.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a href="https://www.alphavantage.co/" rel="noopener noreferrer"&gt;Alpha Vantage&lt;/a&gt; — Best for learning the workflow
&lt;/h2&gt;

&lt;p&gt;Alpha Vantage shows up in nearly every roundup of AI-friendly financial APIs, and it earns the spot. It runs an official MCP server, covers 200,000+ tickers across 20+ exchanges, and ships a deep technical-indicator library so the AI doesn't have to compute RSI or MACD by hand.&lt;/p&gt;

&lt;p&gt;It's also become the default data backbone behind several open-source multi-agent trading frameworks, which means there's a large body of public code an AI coding tool has effectively already seen during training. That translates into fewer hallucinated calls when you ask it to wire Alpha Vantage into a new project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Official MCP, strong indicator library, huge base of public examples and documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; The free tier is heavily rate-limited and you'll hit the wall fast once you start building seriously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free key with strict limits; premium plans from roughly $50/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Learning the AI-coding-tool-plus-financial-API workflow before committing to a paid provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;a href="https://finnhub.io/" rel="noopener noreferrer"&gt;Finnhub&lt;/a&gt; — Best free tier
&lt;/h2&gt;

&lt;p&gt;Finnhub's free tier is genuinely usable, not a teaser. Sixty calls per minute covers prototyping comfortably, and it includes real-time US quotes, fundamentals, SEC filings, and news with sentiment scores across 60+ global exchanges.&lt;/p&gt;

&lt;p&gt;Where it gets interesting for an AI-assisted app is the alternative data: insider sentiment, earnings-call transcripts, lobbying records, and ESG scores, the kind of signal that usually sits behind an expensive institutional feed. There's no single official MCP server, but the docs are clean enough that Cursor or Claude Code can generate a working wrapper from the OpenAPI reference in a few minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Best free tier in this list, rich alternative data, global coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; No official MCP server, so you're either using a community one or writing your own thin wrapper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free (60 calls/minute); premium tiers roughly $12–$100/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Side projects and sentiment-driven apps that need to start free and scale gradually.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;a href="https://www.tiingo.com/" rel="noopener noreferrer"&gt;Tiingo&lt;/a&gt; — Best lightweight option
&lt;/h2&gt;

&lt;p&gt;Tiingo is the API to reach for when you don't need the firehose. It covers US equities, end-of-day and intraday pricing, fundamentals, crypto, forex, and financial news, with documentation simple enough that an AI coding tool rarely trips over it.&lt;/p&gt;

&lt;p&gt;It also ships an MCP server with prompt templates for repeatable analysis tasks, which is a nice touch for a provider this size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Clean, predictable docs, decent news coverage, inexpensive paid tiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Narrower than the all-rounders. No deep options or macro coverage, and real-time relies on IEX rather than the full US tape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier for prototyping; low-cost paid plans for higher limits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Lightweight US-equity apps and side projects where simplicity beats breadth.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. &lt;a href="https://twelvedata.com/" rel="noopener noreferrer"&gt;Twelve Data&lt;/a&gt; — Best for multi-asset, indicator-driven apps
&lt;/h2&gt;

&lt;p&gt;Twelve Data covers stocks, forex, crypto, ETFs, and indices from over 250 exchanges through one consistent API and WebSocket structure, with 100+ technical indicators built in.&lt;/p&gt;

&lt;p&gt;The part that matters for AI-assisted coding is consistency. Every endpoint shares the same logic and the same response shape, and an OpenAPI/Swagger spec is published directly for generating client code. That uniformity is exactly what reduces the odds of an AI coding tool inventing a parameter that doesn't exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Clean multi-asset coverage, 100+ indicators, consistent API and WebSocket design, published OpenAPI spec.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Paid tiers can feel pricier than alternatives offering broader datasets at a similar cost. Fundamentals are thinner than an all-in-one provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free Basic plan for US stocks, forex, and crypto; paid plans starting around $29/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Dashboards that mix asset classes and lean on technical indicators.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. &lt;a href="https://www.financialdatasets.ai/" rel="noopener noreferrer"&gt;Financial Datasets&lt;/a&gt; (financialdatasets.ai) — Best built-for-AI option
&lt;/h2&gt;

&lt;p&gt;Most providers on this list retrofitted AI support onto an API built for humans. Financial Datasets did the opposite: it was designed from the start as a stock market API for AI agents and LLM-powered tools.&lt;/p&gt;

&lt;p&gt;It covers 27,000+ tickers and 30+ years of history, including financial statements, equity prices, insider transactions, and full-text SEC filings an AI coding tool can pull directly into context. Five of the most common tickers (AAPL, GOOGL, MSFT, NVDA, TSLA) are free to query, which makes it unusually easy to prototype against before paying for full coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Purpose-built for AI/LLM consumption, full-text SEC filing access, generous free sandbox on major tickers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; Younger product than the established players, so the ecosystem of examples and community SDKs is smaller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free for five major tickers; paid plans for full 27,000+ ticker coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Agent-style apps that need to reason over filings and statements, not just prices.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. &lt;a href="https://intrinio.com/" rel="noopener noreferrer"&gt;Intrinio&lt;/a&gt; — Best when you outgrow the others
&lt;/h2&gt;

&lt;p&gt;Intrinio is the enterprise option here, and it's upfront about who it's for: fintechs and financial institutions that need licensed, audit-ready data and are willing to pay for it.&lt;/p&gt;

&lt;p&gt;What's notable is how directly its marketing addresses AI-assisted building. Intrinio normalizes its data specifically so it plugs into Claude, ChatGPT, and custom models without a transformation layer, and it ships SDKs in Python, Ruby, and JS with sandbox environments for testing. The honest gap: there's no first-party MCP server yet, so an AI coding tool building an agent-style integration needs a custom wrapper rather than a drop-in connection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Normalized, audit-ready data built for AI consumption, strong SDKs, broad asset-class coverage including options and ETFs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt; No free production plan, only a limited sandbox. No first-party MCP server. Pricing scales fast once you're past prototyping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free developer sandbox; production packages typically run from a few hundred to several thousand dollars per year depending on dataset.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Funded fintech teams that need licensed, compliance-ready data behind an AI-assisted product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Free tier&lt;/th&gt;
&lt;th&gt;AI on-ramp&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EODHD&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;MCP + OpenAPI + Agent Skills&lt;/td&gt;
&lt;td&gt;All-around fintech apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Massive&lt;/td&gt;
&lt;td&gt;Yes (delayed)&lt;/td&gt;
&lt;td&gt;MCP (search/call/query)&lt;/td&gt;
&lt;td&gt;Real-time trading dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alpaca&lt;/td&gt;
&lt;td&gt;Yes (paper trading)&lt;/td&gt;
&lt;td&gt;MCP + CLI&lt;/td&gt;
&lt;td&gt;Apps that place trades&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FMP&lt;/td&gt;
&lt;td&gt;Yes (250/day)&lt;/td&gt;
&lt;td&gt;OpenAPI, REST + WS&lt;/td&gt;
&lt;td&gt;Fundamentals &amp;amp; valuation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alpha Vantage&lt;/td&gt;
&lt;td&gt;Yes (limited)&lt;/td&gt;
&lt;td&gt;Official MCP&lt;/td&gt;
&lt;td&gt;Learning the workflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finnhub&lt;/td&gt;
&lt;td&gt;Yes (60/min)&lt;/td&gt;
&lt;td&gt;OpenAPI reference&lt;/td&gt;
&lt;td&gt;Sentiment &amp;amp; alt-data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tiingo&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;MCP with prompt templates&lt;/td&gt;
&lt;td&gt;Lightweight US-equity apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twelve Data&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;OpenAPI spec&lt;/td&gt;
&lt;td&gt;Multi-asset, indicator-driven apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Financial Datasets&lt;/td&gt;
&lt;td&gt;Yes (5 tickers)&lt;/td&gt;
&lt;td&gt;Built natively for LLMs&lt;/td&gt;
&lt;td&gt;Agent-style filing analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intrinio&lt;/td&gt;
&lt;td&gt;Sandbox only&lt;/td&gt;
&lt;td&gt;Normalized for Claude/ChatGPT&lt;/td&gt;
&lt;td&gt;Enterprise, compliance-ready apps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to pick yours
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;You're prototyping solo.&lt;/strong&gt; Start with &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-financial-apis-ai-coding-tools-2026&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;EODHD&lt;/a&gt; or &lt;a href="https://alpaca.markets/" rel="noopener noreferrer"&gt;Alpaca&lt;/a&gt;, both have real free tiers and AI on-ramps built specifically for coding tools, not retrofitted afterward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're building something fundamentals-heavy.&lt;/strong&gt; &lt;a href="https://site.financialmodelingprep.com/" rel="noopener noreferrer"&gt;FMP&lt;/a&gt; or EODHD. Both give an AI coding tool deep, structured financial statements to ground its output instead of inventing numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're building something that trades.&lt;/strong&gt; Alpaca for the brokerage layer, &lt;a href="https://massive.com/" rel="noopener noreferrer"&gt;Massive&lt;/a&gt; if you need lower-latency market data feeding into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wiring one in: what "AI-coding-tool-friendly" actually looks like
&lt;/h2&gt;

&lt;p&gt;The difference between a provider with good AI on-ramps and one without shows up the moment you ask Cursor or Claude Code to build something.&lt;/p&gt;

&lt;p&gt;Prompt: &lt;em&gt;"Build a Python function that pulls the last 30 days of daily closing prices for a ticker using EODHD's API and returns them as a list of (date, price) tuples."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because EODHD publishes an OpenAPI spec, the model reads structure instead of guessing from prose, and the output looks like this on the first try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_closing_prices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;today&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://eodhd.com/api/eod/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ticker&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.US&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fmt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No invented parameters. No guessed response shape. That's the entire point of choosing an API with machine-readable docs before you start vibe-coding around it.&lt;/p&gt;

&lt;p&gt;From here you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a portfolio tracker that refreshes on a schedule&lt;/li&gt;
&lt;li&gt;a screener that filters by price action across a watchlist&lt;/li&gt;
&lt;li&gt;a dashboard the AI extends every time you add a new data point&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Coverage matters less than legibility. The API your AI coding tool can read correctly beats the one with more tickers.&lt;/li&gt;
&lt;li&gt;Look for &lt;code&gt;llms.txt&lt;/code&gt;, an OpenAPI spec, and an official SDK before anything else.&lt;/li&gt;
&lt;li&gt;EODHD and Alpaca currently have the most coding-tool-native on-ramps (MCP, CLI, Agent Skills) of the ten covered here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;❓ &lt;strong&gt;What's the best financial API for AI coding tools like Cursor or Claude Code in 2026?&lt;/strong&gt;&lt;br&gt;
✅ It depends on what you're building. EODHD has the broadest AI on-ramp for general fintech apps. Alpaca is strongest if the app needs to place trades, not just display data. FMP wins for fundamentals-heavy dashboards.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Do I need an MCP server, or is a regular REST API enough?&lt;/strong&gt;&lt;br&gt;
✅ A REST API is enough if you're willing to let the AI read the OpenAPI spec and generate the wrapper itself, which works well with providers like FMP or Twelve Data. An MCP server removes that step entirely, which matters more as the app grows.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Which financial API has the best free tier for prototyping with AI?&lt;/strong&gt;&lt;br&gt;
✅ Finnhub (60 calls/minute) and EODHD both offer free tiers usable for real prototyping, not just a teaser. Alpaca's free paper-trading account is the best option if the app needs to simulate trades.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Can an AI-built app actually place trades, or only read data?&lt;/strong&gt;&lt;br&gt;
✅ Most of the APIs on this list are read-only. Alpaca is the exception: it's a real brokerage, so an AI-built app can place orders and manage positions through the same API it uses to read market data.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Why does documentation quality matter more than data coverage for AI coding tools?&lt;/strong&gt;&lt;br&gt;
✅ An AI coding tool generates code from what it can parse. A provider with a clean OpenAPI spec or &lt;code&gt;llms.txt&lt;/code&gt; gives the model structure to read instead of prose to guess from, which is the difference between correct code on the first try and a silent hallucination that breaks in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;The model isn't the bottleneck anymore. The documentation is.&lt;/p&gt;

&lt;p&gt;Pick the financial API whose docs your AI coding tool can actually read, and the difference shows up in every function it generates after that.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-financial-apis-ai-coding-tools-2026&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Start building with the EODHD API here&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>coding</category>
      <category>api</category>
      <category>stocks</category>
    </item>
    <item>
      <title>The 7 Best Stock Market APIs for AI Agents in 2026</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Mon, 08 Jun 2026 13:36:20 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/the-7-best-stock-market-apis-for-ai-agents-in-2026-25bj</link>
      <guid>https://dev.to/kevin_menesesgonzlez/the-7-best-stock-market-apis-for-ai-agents-in-2026-25bj</guid>
      <description>&lt;h1&gt;
  
  
  The 7 Best Stock Market APIs for AI Agents in 2026
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Meta: The 7 best stock market APIs for AI agents in 2026, compared by MCP support, data coverage, and pricing — so your Claude or LLM agent gets reliable data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your AI agent is only as smart as the data it can reach.&lt;/p&gt;

&lt;p&gt;You can hand it the best model on the market. You can write a perfect system prompt. But if it can't pull live, structured market data, it does the one thing a financial agent must never do: it guesses. And a financial agent that guesses is worse than no agent at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API you pick decides how dumb your agent is
&lt;/h2&gt;

&lt;p&gt;For years, choosing a stock market API came down to four things: coverage, latency, price, and documentation. Those still matter. But agents added a fifth question that quietly outranks the rest. Can the data plug into an agent at all, without you hand-wiring every endpoint?&lt;/p&gt;

&lt;p&gt;Most market APIs were never built for that. They were built for humans and dashboards. A developer reads the docs, writes a client, maps each response to a chart. An agent can't improvise that on the fly. It needs a standard way to discover tools and call them, or you end up gluing brittle wrappers together and hoping the model formats the request correctly.&lt;/p&gt;

&lt;p&gt;That gap is what Model Context Protocol closed. And it split the market into two camps.&lt;/p&gt;

&lt;p&gt;On one side, the AI-native providers shipping official MCP servers your agent connects to directly. On the other, the enterprise backbones that are broad and fast but expect you to bring your own orchestration. Both can be the right answer. It depends on what you're building.&lt;/p&gt;

&lt;p&gt;So the real question in 2026 isn't which API has the most data. Plenty have enough.&lt;/p&gt;

&lt;p&gt;It's which one your agent can actually use without you babysitting the integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I ranked these
&lt;/h2&gt;

&lt;p&gt;Five things, weighted for agents specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent-readiness.&lt;/strong&gt; Official MCP server, AI skills, or an OpenAPI spec the model can consume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured outputs.&lt;/strong&gt; Clean JSON the model can reason over without a parsing layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coverage.&lt;/strong&gt; Equities, fundamentals, news, options, global markets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time.&lt;/strong&gt; Whether the agent needs live ticks or end-of-day is enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price.&lt;/strong&gt; What it costs a solo builder versus a funded team.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the seven that hold up.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. EODHD — Best all-around for AI agents
&lt;/h2&gt;

&lt;p&gt;EODHD is the closest thing on this list to a single, agent-ready data layer you can build on without stitching five vendors together. It covers 60+ global exchanges, 120,000+ tickers, and 30+ years of history, returning clean JSON with precomputed technical indicators and a built-in screener.&lt;/p&gt;

&lt;p&gt;What puts it at number one for agents is the integration surface. EODHD ships an official MCP server with 75 tools that lets Claude, Cursor, and Windsurf query live data in conversation, plus AI Agent Skills with 72 endpoints for Claude Code and Codex, an OpenAPI 3.1 spec for custom GPTs and function calling, and a ChatGPT assistant trained on its docs. No other provider here exposes that many agent on-ramps at once.&lt;/p&gt;

&lt;p&gt;Pricing is bundled instead of per-dataset, which matters when an agent touches many data types in one loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Broadest agent toolkit (MCP + Skills + OpenAPI), global coverage, fundamentals and technicals under one key, accessible entry price.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Real-time runs over WebSocket per ticker rather than ultra-low-latency feeds, so it's not built for HFT. US options is a paid add-on.&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier, then €19.99/mo (EOD All World), €29.99/mo (+intraday and real-time), €99.99/mo (All-in-One). Commercial from €399/mo.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Solo builders and teams that want the widest agent-ready dataset under one subscription.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  🚀 Start with EODHD
&lt;/h3&gt;

&lt;p&gt;The broadest agent-ready data layer on this list — official MCP (75 tools), AI Skills, and OpenAPI, all under one key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-stock-market-apis-ai-agents-2026&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Get your free EODHD API key&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  2. Alpha Vantage — The default for AI-native research
&lt;/h2&gt;

&lt;p&gt;Alpha Vantage is the name that shows up in almost every "MCP for stock data" roundup, and for good reason. It runs an official MCP server at &lt;code&gt;mcp.alphavantage.co&lt;/code&gt;, covers 200,000+ tickers across 20+ exchanges, and ships a deep technical-indicator suite so your agent doesn't have to compute RSI or MACD itself.&lt;/p&gt;

&lt;p&gt;It's also the standard data backbone behind open-source agent frameworks like TradingAgents, which simulate a trading desk with multiple LLM analysts. If you're prototyping a multi-agent research system, Alpha Vantage is the path of least resistance.&lt;/p&gt;

&lt;p&gt;The catch is the free tier. It exists, which is great for a first build, but it's tightly rate-limited, and you'll hit the wall fast once an agent starts hammering it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Official MCP, strong technical indicators, huge ecosystem of docs and examples, AI-native positioning.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Free tier is heavily throttled. Coverage skews US-and-majors.&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free key with strict limits; premium plans from roughly $50/mo.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; AI-native research agents and anyone learning the MCP workflow.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Site:&lt;/strong&gt; &lt;a href="https://www.alphavantage.co" rel="noopener noreferrer"&gt;alphavantage.co&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Financial Modeling Prep — Best for fundamentals-heavy copilots
&lt;/h2&gt;

&lt;p&gt;If your agent's job is reading balance sheets, not chasing ticks, FMP is the strongest pick. Its MCP server is widely regarded as the king of fundamental analysis, exposing income statements, ratios, DCF models, filings, transcripts, and institutional holdings as agent-callable tools.&lt;/p&gt;

&lt;p&gt;FMP says its MCP integration gives agents access to tens of thousands of structured data points, which is exactly what a financial copilot needs to ground its answers instead of inventing them.&lt;/p&gt;

&lt;p&gt;It's also one of EODHD's few genuine rivals on breadth-per-dollar, so it's worth a hard look if fundamentals are your core use case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Deepest fundamentals and ratios, MCP-ready, generous endpoint count, clean statements data.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Real-time and global coverage live behind the higher tiers. Some datasets are gated.&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free (250 calls/day), Starter ~$19/mo, Premium ~$69/mo, Ultimate ~$139/mo (global + transcripts + 13F).&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Equity-research copilots and valuation agents.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Site:&lt;/strong&gt; &lt;a href="https://site.financialmodelingprep.com" rel="noopener noreferrer"&gt;financialmodelingprep.com&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Polygon.io (now Massive) — Best for real-time trading agents
&lt;/h2&gt;

&lt;p&gt;Polygon rebranded to Massive in 2026, but developers still call it Polygon. Whatever the name, it's the specialist for speed: tick-by-tick trades, WebSocket streaming, and low-latency US equity and options data.&lt;/p&gt;

&lt;p&gt;Its official MCP server is unusually smart. Rather than one tool per endpoint, it gives the model a few composable tools (search, call, query) that cover the entire API surface and stay in sync automatically. That's a clean design for agents that need to roam across many endpoints.&lt;/p&gt;

&lt;p&gt;If your agent reacts to intraday moves, this is your data feed. If it runs end-of-day screens, you're paying for latency you won't use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Real-time WebSockets, options with Greeks, well-designed MCP, trading-desk-grade infrastructure.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; US-centric. Real-time sits on higher tiers, and cost climbs with it.&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier with delayed data; paid stock plans roughly $29–$199+/mo, real-time on higher tiers.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Day-trading agents and live market dashboards where latency is the constraint.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Site:&lt;/strong&gt; &lt;a href="https://polygon.io" rel="noopener noreferrer"&gt;polygon.io&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Tradier — Best for agents that actually trade
&lt;/h2&gt;

&lt;p&gt;Most APIs on this list stop at reading data. Tradier goes further. It's a brokerage stack, so an agent can pull quotes and options chains &lt;em&gt;and&lt;/em&gt; place orders, check positions, and manage a portfolio through the same connection.&lt;/p&gt;

&lt;p&gt;Its docs are unusually forward-leaning for the agent era, with an &lt;code&gt;llms.txt&lt;/code&gt;, dedicated LLM resources, and an MCP section that lets connected AI tools access market data, account details, and trade execution. It also supports WebSocket streaming for event-driven agent loops.&lt;/p&gt;

&lt;p&gt;The trade-off is scope: it's US-brokerage-centric, not a global research dataset. Real-time data is tied to having a brokerage account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Read &lt;em&gt;and&lt;/em&gt; act capability, MCP with execution, streaming, strong fit for action-taking agents.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; US-only focus, narrower research data, real-time tied to brokerage access.&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free sandbox (delayed); real-time via brokerage account or a low-cost market-data add-on.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Trading copilots and semi-autonomous execution agents (with guardrails).&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Site:&lt;/strong&gt; &lt;a href="https://tradier.com" rel="noopener noreferrer"&gt;tradier.com&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  6. Finnhub — Best for alternative data and sentiment
&lt;/h2&gt;

&lt;p&gt;Finnhub punches above its price. The free tier is among the most generous in the category at 60 calls per minute, and it covers 60+ global exchanges, real-time US quotes, fundamentals, SEC filings, and news with sentiment scores.&lt;/p&gt;

&lt;p&gt;Where it stands out is alternative data: insider sentiment, earnings-call transcripts, lobbying records, FDA calendars, and ESG scores. Those signals usually live behind expensive institutional feeds. For an agent that reasons about &lt;em&gt;why&lt;/em&gt; a stock is moving, that's high-value context.&lt;/p&gt;

&lt;p&gt;There's no single official MCP server, but several solid community ones exist (real-time streaming, quotes, fundamentals), so wiring it into Claude is a short job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Best-in-class free tier, rich alternative data and sentiment, global coverage.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; MCP is community-built, not official. Premium needed for deeper international data.&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free (60 calls/min); Premium roughly $12–$100/mo by tier.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; News-and-sentiment agents and alt-data research workflows.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Site:&lt;/strong&gt; &lt;a href="https://finnhub.io" rel="noopener noreferrer"&gt;finnhub.io&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  7. Tiingo — Best lightweight option
&lt;/h2&gt;

&lt;p&gt;Tiingo is the clean, developer-friendly choice when you don't need the firehose. It does US equities, end-of-day and intraday pricing, fundamentals, crypto, forex, and genuinely good financial news, with a practical free tier for prototyping and an MCP server with prompt templates for repeatable analysis tasks.&lt;/p&gt;

&lt;p&gt;The honest limit: it's narrower than the all-rounders. No deep options, commodities, or macro coverage, and its real-time relies on IEX, which doesn't represent the full US tape.&lt;/p&gt;

&lt;p&gt;For a focused US-equity research agent or a side project, that's a fair trade for the simplicity and low price.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Clean data, strong news, MCP with prompt templates, low cost.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Narrow scope, IEX-based real-time, no broad options/macro.&lt;br&gt;
&lt;strong&gt;Pricing:&lt;/strong&gt; Free tier; low-cost paid plans for higher limits.&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Lightweight US-equity and news-driven agents.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Site:&lt;/strong&gt; &lt;a href="https://www.tiingo.com" rel="noopener noreferrer"&gt;tiingo.com&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Agent integration&lt;/th&gt;
&lt;th&gt;Coverage&lt;/th&gt;
&lt;th&gt;Real-time&lt;/th&gt;
&lt;th&gt;Free tier&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EODHD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Official MCP (75 tools) + Skills + OpenAPI&lt;/td&gt;
&lt;td&gt;Global, 60+ exchanges&lt;/td&gt;
&lt;td&gt;WebSocket&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;All-around agent data layer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alpha Vantage&lt;/td&gt;
&lt;td&gt;Official MCP&lt;/td&gt;
&lt;td&gt;US + majors&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Throttled&lt;/td&gt;
&lt;td&gt;AI-native research&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FMP&lt;/td&gt;
&lt;td&gt;MCP (deep fundamentals)&lt;/td&gt;
&lt;td&gt;US→global by tier&lt;/td&gt;
&lt;td&gt;Higher tiers&lt;/td&gt;
&lt;td&gt;250/day&lt;/td&gt;
&lt;td&gt;Fundamentals copilots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polygon / Massive&lt;/td&gt;
&lt;td&gt;Official MCP&lt;/td&gt;
&lt;td&gt;US&lt;/td&gt;
&lt;td&gt;Yes (low latency)&lt;/td&gt;
&lt;td&gt;Delayed&lt;/td&gt;
&lt;td&gt;Real-time trading agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tradier&lt;/td&gt;
&lt;td&gt;MCP + execution&lt;/td&gt;
&lt;td&gt;US brokerage&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Sandbox&lt;/td&gt;
&lt;td&gt;Agents that trade&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finnhub&lt;/td&gt;
&lt;td&gt;Community MCP&lt;/td&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;Yes (US)&lt;/td&gt;
&lt;td&gt;60/min&lt;/td&gt;
&lt;td&gt;Alt-data + sentiment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tiingo&lt;/td&gt;
&lt;td&gt;MCP&lt;/td&gt;
&lt;td&gt;US-focused&lt;/td&gt;
&lt;td&gt;IEX-based&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Lightweight research&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  How to pick yours
&lt;/h2&gt;

&lt;p&gt;Three honest profiles:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're a solo builder or prototyping.&lt;/strong&gt; Start with EODHD for the broadest agent-ready data under one key, or lean on Alpha Vantage's and Finnhub's free tiers while you experiment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're building a research or fundamentals copilot.&lt;/strong&gt; EODHD or FMP. Both give an agent deep, structured fundamentals it can ground its answers in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You're building a live trading or execution agent.&lt;/strong&gt; Polygon/Massive for the data feed, Tradier when the agent also needs to place orders.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wiring one into Claude in a few lines
&lt;/h2&gt;

&lt;p&gt;The reason MCP matters is that connecting a provider stops being a coding project. With EODHD's MCP server, you register it once and your agent can query live data in plain language:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Register the EODHD MCP server with Claude Code&lt;/span&gt;
claude mcp add eodhd &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;EODHD_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_api_key_here &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--&lt;/span&gt; &amp;lt;eodhd-mcp-server-command-from-their-docs&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you don't write endpoint calls. You ask. "Screen US tech stocks with positive EPS under a 50B market cap" becomes a tool call the agent makes on its own, against real data. If you want to see that exact pattern end to end, I walked through letting Claude run a screener and pick stocks in a separate piece.&lt;/p&gt;

&lt;p&gt;That's the whole shift. The model does the reasoning. The API tells it the truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;❓ &lt;strong&gt;What is the best stock market API for AI agents in 2026?&lt;/strong&gt;&lt;br&gt;
✅ It depends on the job. For the broadest agent-ready data under one subscription, EODHD is the strongest all-rounder thanks to its MCP server, AI skills, and OpenAPI support. For real-time trading agents, Polygon/Massive; for fundamentals copilots, FMP or EODHD.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Do I need an MCP server, or is a normal API enough?&lt;/strong&gt;&lt;br&gt;
✅ A normal REST API works if you're willing to write and maintain tool wrappers yourself. An MCP server removes that work: the agent discovers and calls tools through a standard interface, which is faster to build and far less brittle.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Which stock API has the best free tier for AI agents?&lt;/strong&gt;&lt;br&gt;
✅ Finnhub (60 calls/minute) and Alpha Vantage are the most common free starting points. EODHD and FMP also offer free tiers that are useful for prototyping before you scale up.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Can an AI agent place trades, or only read data?&lt;/strong&gt;&lt;br&gt;
✅ Most data APIs are read-only. Tradier is the exception here: its brokerage-connected MCP lets a guarded agent place orders and manage positions, not just retrieve quotes.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Do these APIs work with Claude, ChatGPT, and Cursor?&lt;/strong&gt;&lt;br&gt;
✅ Yes. Providers with MCP servers (EODHD, Alpha Vantage, Polygon, Tradier) connect to Claude, Cursor, and similar tools. EODHD also offers an OpenAPI spec for custom GPTs and a dedicated ChatGPT assistant.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;In 2026, the model is rarely the bottleneck. The data is.&lt;/p&gt;

&lt;p&gt;Pick the API your agent can actually reach, the one that hands it clean, structured, current market data through an interface it already understands. Get that right and the agent stops guessing and starts reasoning.&lt;/p&gt;

&lt;p&gt;If you want the widest agent-ready coverage with the least integration work, EODHD is where I'd start.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  🚀 Build your agent on EODHD
&lt;/h3&gt;

&lt;p&gt;Widest agent-ready coverage with the least integration work — MCP, AI Skills, OpenAPI, and a free tier to start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=best-stock-market-apis-ai-agents-2026&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Start building with EODHD&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>api</category>
      <category>stocks</category>
    </item>
    <item>
      <title>I Gave Claude a Stock Screener. Here's What It Picked</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Sun, 07 Jun 2026 11:21:57 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/i-gave-claude-a-stock-screener-heres-what-it-picked-1d7g</link>
      <guid>https://dev.to/kevin_menesesgonzlez/i-gave-claude-a-stock-screener-heres-what-it-picked-1d7g</guid>
      <description>&lt;p&gt;Most "AI picks stocks" demos are fiction.&lt;/p&gt;

&lt;p&gt;You ask a chatbot for undervalued companies, it hands you five tickers, and they sound reasonable. AAPL. MSFT. A bank you've heard of. It feels like analysis.&lt;/p&gt;

&lt;p&gt;It isn't.&lt;/p&gt;

&lt;p&gt;The model is reciting names from its training data. It has no idea what those companies trade at today, what their P/E is this quarter, or whether they're even still profitable. The numbers it quotes are frozen in time, and half of them are made up.&lt;/p&gt;

&lt;p&gt;So I ran a different experiment. I gave Claude a real stock screener as a tool, handed it an actual market goal, and let it do the filtering itself.&lt;/p&gt;

&lt;p&gt;This is what happened.&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building AI agents that touch financial data,&lt;/li&gt;
&lt;li&gt;automating your own stock research,&lt;/li&gt;
&lt;li&gt;or just curious whether an LLM can screen the market without hallucinating,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this one is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with letting an LLM pick stocks
&lt;/h2&gt;

&lt;p&gt;A language model is a text predictor. It is very good at sounding like a financial analyst and very bad at being one.&lt;/p&gt;

&lt;p&gt;Ask it for "the cheapest profitable semiconductor stocks" and it will confidently produce a list. But it has no live access to market caps, earnings, or valuations. It is pattern-matching against whatever it absorbed during training, which ended months ago.&lt;/p&gt;

&lt;p&gt;Developers discover this the hard way. The picks look fine until you check them and realize the "low P/E" stock the model loved is now trading at three times that, or split, or delisted.&lt;/p&gt;

&lt;p&gt;You can't fix this with a better prompt. The data simply isn't in the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude doesn't need to know the market. It needs a way to query it.
&lt;/h2&gt;

&lt;p&gt;That single shift changes the whole problem.&lt;/p&gt;

&lt;p&gt;The moment Claude can call a screener, it stops guessing and starts orchestrating. It decides &lt;em&gt;what&lt;/em&gt; to look for, the API decides &lt;em&gt;what's actually true&lt;/em&gt;, and Claude reasons over real results instead of inventing them.&lt;/p&gt;

&lt;p&gt;The model becomes the analyst. The API becomes the data desk.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: give Claude a screener API as a tool
&lt;/h2&gt;

&lt;p&gt;For the data layer I used the &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=ai-stock-screener-claude-eodhd&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;EODHD Screener API&lt;/a&gt;. It exposes the entire stock universe behind one endpoint and lets you filter it with simple conditions.&lt;/p&gt;

&lt;p&gt;You pass filters and a sort order, and you get structured JSON back. Each result carries fields you can actually screen on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;market capitalization&lt;/li&gt;
&lt;li&gt;earnings per share&lt;/li&gt;
&lt;li&gt;sector and exchange&lt;/li&gt;
&lt;li&gt;dividend yield&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No scraping. No unofficial endpoints that break on Mondays. A clean REST call that returns the same shape every time, which is exactly what you need when an LLM is going to consume the output.&lt;/p&gt;

&lt;p&gt;That last part matters more than it sounds. Tool use only works if the data coming back is predictable. A screener that returns clean, typed JSON is the difference between an agent that reasons and one that chokes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you want to follow along, the screener endpoint and filter fields are documented &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=ai-stock-screener-claude-eodhd&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wiring the EODHD screener into Claude
&lt;/h2&gt;

&lt;p&gt;The architecture is three pieces: a function that runs the screener, a tool definition that describes it to Claude, and a loop that lets Claude call it.&lt;/p&gt;

&lt;p&gt;Start with the function. This is the only part that talks to the market.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;EODHD_API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EODHD_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_screener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization.desc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://eodhd.com/api/screener&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;EODHD_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fmt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filters are just a list of &lt;code&gt;[field, operator, value]&lt;/code&gt; conditions. Profitable tech stocks above a billion in market cap is two lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;run_screener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sector&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Technology&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1_000_000_000&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_share&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;earnings_share.desc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now describe that function to Claude as a tool. The description is the part most people rush. Don't. This is how the model knows what it can ask for.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# reads ANTHROPIC_API_KEY from env
&lt;/span&gt;
&lt;span class="n"&gt;screener_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_screener&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Screen US stocks by fundamentals using a live market data API. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Returns matching tickers with fields like code, name, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization, earnings_share, sector, and dividend_yield.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_schema&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;array&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;List of [field, operator, value]. Fields include &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market_capitalization, earnings_share, sector, exchange, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dividend_yield. Operators: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;array&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;field.direction, e.g. &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;earnings_share.desc&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;integer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last piece is the loop. Give Claude a goal, let it request the screener, feed the real data back, and let it decide.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;goal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Find profitable, reasonably valued US technology stocks. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Profitable means positive earnings per share. Don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t limit yourself to &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mega-caps; include mid-caps. Return a shortlist of 5 and explain why &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;each one made the cut.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;screener_tool&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop_reason&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_use&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_use&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;run_screener&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_screener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_use_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the entire system. No vector database, no fine-tuning, no agent framework. One function, one tool, one loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here's what happened
&lt;/h2&gt;

&lt;p&gt;I gave Claude the goal above and watched.&lt;/p&gt;

&lt;p&gt;The first thing it did was not pick stocks. It picked &lt;em&gt;filters&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It translated "profitable, reasonably valued tech" into a concrete screen on its own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sector"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Technology"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"market_capitalization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2000000000&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"market_capitalization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50000000000&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"earnings_share"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the choices. It set a floor &lt;em&gt;and&lt;/em&gt; a ceiling on market cap to honor "not just mega-caps." It required positive EPS for "profitable." Nobody told it to do that. It reasoned from the goal to the query.&lt;/p&gt;

&lt;p&gt;Then it called the screener, got real tickers back, and narrowed the list with a second pass before writing up its shortlist.&lt;/p&gt;

&lt;p&gt;One thing to keep in mind: a screener reads the market as it is &lt;em&gt;today&lt;/em&gt;. The exact constituents shift every time you run it, as earnings update and caps move. So this is a representative run, not a fixed list. Run it tomorrow and the names will differ.&lt;/p&gt;

&lt;p&gt;Here is the shape of the shortlist it returned and the reasoning it attached to each:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ticker&lt;/th&gt;
&lt;th&gt;Why it made the cut (Claude's reasoning)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FTNT&lt;/td&gt;
&lt;td&gt;Positive EPS, sat cleanly inside the requested cap band, software margins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MPWR&lt;/td&gt;
&lt;td&gt;Strongest earnings_share in the filtered set; flagged as the highest-quality name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CDW&lt;/td&gt;
&lt;td&gt;Profitable, steadier business, included as the "lower-volatility" pick&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZS&lt;/td&gt;
&lt;td&gt;Met every filter but Claude caveated it as the most expensive of the five&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WDC&lt;/td&gt;
&lt;td&gt;Edge case Claude added with a warning that it's cyclical and EPS swings hard&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What stood out wasn't the picks. It was the honesty.&lt;/p&gt;

&lt;p&gt;Claude flagged its own limits without prompting. It noted that EPS alone doesn't mean a stock is cheap, that it had no forward estimates, and that this was a starting watchlist, not a buy signal.&lt;/p&gt;

&lt;p&gt;That's the correct answer. A screener narrows the universe. It does not tell you the future. The model understood the job better than most "AI stock picker" demos pretend to.&lt;/p&gt;

&lt;p&gt;Where it fell short: with only fundamental snapshot fields, it couldn't reason about momentum, debt, or recent news. Those need more endpoints. The screener is the front door, not the whole house.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The model orchestrates, the API decides.&lt;/strong&gt; Claude is good at turning a vague goal into a precise query. It is not a data source, and the moment you treat it like one, it hallucinates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean JSON is the unlock.&lt;/strong&gt; Tool use only works when the data coming back is predictable. The screener's structured response is what makes the loop reliable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducible beats vibes.&lt;/strong&gt; Run the same prompt twice and you get the same filters against the same live data. That's a system you can audit, not a magic trick.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;❓ &lt;strong&gt;Can AI actually pick stocks?&lt;/strong&gt;&lt;br&gt;
✅ Not on its own. A language model has no live market data and will invent figures if you let it. Connected to a screener API, it can translate a goal into real filters and reason over real results, which is a very different and far more reliable thing.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;What is the best stock screener API for Python?&lt;/strong&gt;&lt;br&gt;
✅ You want one that returns clean, structured JSON and lets you filter on fundamentals like market cap, EPS, and sector. EODHD's Screener API does this through a single REST endpoint, which makes it a good fit for feeding an LLM.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Do I need an agent framework to build this?&lt;/strong&gt;&lt;br&gt;
✅ No. The example above is plain Python: one function, one tool definition, one loop. Frameworks add structure when you have many tools, but a single screener doesn't need one.&lt;/p&gt;

&lt;p&gt;❓ &lt;strong&gt;Is this safe to trade on?&lt;/strong&gt;&lt;br&gt;
✅ Treat the output as a research shortlist, not a recommendation. A screener narrows thousands of stocks to a handful worth a closer look. The analysis after that is still on you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it yourself
&lt;/h2&gt;

&lt;p&gt;Get a free EODHD key and run the loop above:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://eodhd.com/?via=kmg&amp;amp;ref1=Meneses&amp;amp;utm_source=medium&amp;amp;utm_medium=post&amp;amp;utm_campaign=ai-stock-screener-claude-eodhd&amp;amp;utm_content=Meneses" rel="noopener noreferrer"&gt;Start with the EODHD Screener API here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a single endpoint to screen the full stock universe&lt;/li&gt;
&lt;li&gt;filters on market cap, EPS, sector, dividend yield, and more&lt;/li&gt;
&lt;li&gt;clean JSON that drops straight into a tool-use loop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point was never to let an AI gamble on tickers.&lt;/p&gt;

&lt;p&gt;It was to stop the model from guessing, and give it something true to work with.&lt;/p&gt;

&lt;p&gt;That's the whole trick.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>stocks</category>
      <category>data</category>
    </item>
    <item>
      <title>Automate Social Media With Python and the Zernio API</title>
      <dc:creator>Kevin Meneses González</dc:creator>
      <pubDate>Fri, 05 Jun 2026 10:08:50 +0000</pubDate>
      <link>https://dev.to/kevin_menesesgonzlez/automate-social-media-with-python-and-the-zernio-api-36mn</link>
      <guid>https://dev.to/kevin_menesesgonzlez/automate-social-media-with-python-and-the-zernio-api-36mn</guid>
      <description>&lt;p&gt;Most people think growing on social media is about better content.&lt;/p&gt;

&lt;p&gt;It's not. It's about showing up. Every day. Without missing a beat.&lt;/p&gt;

&lt;p&gt;The accounts that win aren't the ones with the smartest takes. They're the ones that posted while everyone else "didn't have time today."&lt;/p&gt;

&lt;p&gt;So the real question isn't &lt;em&gt;what do I post?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's &lt;em&gt;how do I post consistently without it eating my week?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a developer building in public,&lt;/li&gt;
&lt;li&gt;a founder running content for a SaaS,&lt;/li&gt;
&lt;li&gt;or anyone tired of copy-pasting the same post across five tabs,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem isn't ideas. It's friction.
&lt;/h2&gt;

&lt;p&gt;Here's what consistent posting actually looks like when you do it by hand.&lt;/p&gt;

&lt;p&gt;You write a tweet. You open Reddit, reformat it, pick a subreddit, post. You open LinkedIn, rewrite the tone, post. You remember you wanted to schedule it for tomorrow morning instead, so you don't post — you set a reminder. The reminder fires while you're in a meeting. You skip it.&lt;/p&gt;

&lt;p&gt;Multiply that by every day, across every platform.&lt;/p&gt;

&lt;p&gt;This is why most people quit. Not because they ran out of things to say. Because the &lt;em&gt;distribution&lt;/em&gt; is exhausting.&lt;/p&gt;

&lt;p&gt;And if you're a developer thinking "I'll just script it," you hit a second wall fast: every platform has its own API, its own OAuth dance, its own rate limits, its own media specs. Twitter's API works nothing like Reddit's, which works nothing like LinkedIn's.&lt;/p&gt;

&lt;p&gt;You wanted to automate posting. Instead you signed up to maintain five integrations forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reframe
&lt;/h2&gt;

&lt;p&gt;You don't have a content problem. You have a plumbing problem.&lt;/p&gt;

&lt;p&gt;The fix isn't more discipline. It's removing the manual step entirely — generate the content, schedule it once, and let an API fan it out across every platform.&lt;/p&gt;

&lt;p&gt;Two pieces make that possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A language model&lt;/strong&gt; to write fresh posts so you're not recycling the same three lines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One API that speaks to every platform&lt;/strong&gt;, so your code doesn't care whether it's posting to Twitter or Reddit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the first, GPT-4o-mini is cheap and good enough. For the second, I use &lt;strong&gt;Zernio&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Zernio
&lt;/h2&gt;

&lt;p&gt;Zernio is a unified REST API for social media publishing. One endpoint replaces the 15 separate integrations you'd otherwise build and babysit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One Bearer token, one JSON payload — posts to Twitter/X, Reddit, LinkedIn, Instagram, Facebook and 10+ more platforms.&lt;/li&gt;
&lt;li&gt;Schedule, publish now, or bulk-upload — the scheduling logic is built in, not something you write.&lt;/li&gt;
&lt;li&gt;No SDK. It's plain REST, so Python's &lt;code&gt;requests&lt;/code&gt; library is all you need.&lt;/li&gt;
&lt;li&gt;Free first 2 connected accounts, no credit card — enough to ship this whole project for free.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pay-per-account after the free tier (graduated: cheaper as you scale).&lt;/li&gt;
&lt;li&gt;One account per platform per profile, so multi-client agencies need multiple profiles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; developers who want to add scheduling and cross-posting to a script or product without becoming a full-time API maintenance engineer.&lt;/p&gt;

&lt;p&gt;That last point is the whole pitch. You're not paying for a feature you couldn't build. You're paying to never touch five OAuth flows again.&lt;/p&gt;

&lt;p&gt;👉 You can grab a free Zernio key here: &lt;strong&gt;&lt;a href="https://zernio.link/kevin-meneses" rel="noopener noreferrer"&gt;zernio.link/kevin-meneses&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the automation
&lt;/h2&gt;

&lt;p&gt;Here's the plan: a script that generates AI posts and schedules four of them across the coming week — two to Twitter, two to Reddit — in a single run.&lt;/p&gt;

&lt;p&gt;Set it up once. Run it Monday. Forget about it.&lt;/p&gt;

&lt;p&gt;The full project lives on GitHub if you'd rather clone and run it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Kevinelectronics/social-media-automation.git
&lt;span class="nb"&gt;cd &lt;/span&gt;social-media-automation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Install and configure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests python-dotenv openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file with two keys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;ZERNIO_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_zernio_api_key_here
&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_openai_api_key_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the Zernio key free at &lt;a href="https://zernio.link/kevin-meneses" rel="noopener noreferrer"&gt;zernio.link/kevin-meneses&lt;/a&gt;, and the OpenAI key at &lt;code&gt;platform.openai.com/api-keys&lt;/code&gt;. Then log in to Zernio, open &lt;strong&gt;Accounts&lt;/strong&gt;, and connect your Twitter and Reddit profiles.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Set up the clients
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timedelta&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;ZERNIO_BASE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://zernio.com/api/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ZERNIO_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;TOPICS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python automation tips&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;productivity for developers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipping side projects&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Fetch your connected accounts
&lt;/h3&gt;

&lt;p&gt;Zernio gives each connected profile an ID. You need those IDs to tell the API where to post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_accounts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ZERNIO_BASE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/accounts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;platform&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns a clean map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reddit   → 6a2135f22b2567671ac3e5e4
twitter  → 6a2136552b2567671ac3e855
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Generate the content
&lt;/h3&gt;

&lt;p&gt;One function for tweets, one for Reddit posts. The Reddit one asks GPT for structured JSON so we get a clean title and body.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_tweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write one punchy tweet about &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                       &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Max 280 characters. One emoji max, no hashtag spam.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_reddit_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write a Reddit post about &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                       &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Return JSON with keys &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; and &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;. No markdown.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="n"&gt;response_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json_object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Schedule a single post
&lt;/h3&gt;

&lt;p&gt;This is the core call. One payload shape, regardless of platform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;schedule_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subreddit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;platforms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;platform&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accountId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;publishNow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;scheduledFor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timezone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;America/New_York&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;subreddit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;platforms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subreddit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subreddit&lt;/span&gt;

    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ZERNIO_BASE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/posts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the entire integration. No OAuth handling in your code, no per-platform branching beyond a subreddit field. Zernio normalizes the rest.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Schedule the whole week
&lt;/h3&gt;

&lt;p&gt;Loop through four slots, spaced across seven days, alternating platforms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;schedule_week&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;twitter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reddit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;twitter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reddit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;day_offset&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;day_offset&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;hour&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;microsecond&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isoformat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;topic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOPICS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;twitter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_tweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;post_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;schedule_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;twitter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;twitter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_reddit_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;post_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;schedule_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reddit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reddit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;subreddit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;learnprogramming&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; | ID: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🔗 Connecting to Zernio...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_accounts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🤖 Generating content and scheduling posts...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;schedule_week&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;🎉 Done. Check your Zernio dashboard.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🔗 Connecting to Zernio...
🤖 Generating content and scheduling posts...

  ✅ twitter  | 2025-06-04T10:00:00 | ID: 6a2142f2d786bdfc96598f5b
  ✅ reddit   | 2025-06-06T10:00:00 | ID: 6a2143aad786bdfc96598f6c
  ✅ twitter  | 2025-06-08T10:00:00 | ID: 6a2144bbd786bdfc96598f7d
  ✅ reddit   | 2025-06-10T10:00:00 | ID: 6a2145ccd786bdfc96598f8e

🎉 Done. Check your Zernio dashboard.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four posts. A full week. One command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make it yours
&lt;/h2&gt;

&lt;p&gt;The script is a skeleton on purpose. Three things to change:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Topics.&lt;/strong&gt; Edit the &lt;code&gt;TOPICS&lt;/code&gt; list to your niche. Trading, design, devops, parenting — whatever you actually post about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frequency.&lt;/strong&gt; The &lt;code&gt;plan&lt;/code&gt; list controls how many posts go out and when. Add slots, change the hours, push it to daily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Platforms.&lt;/strong&gt; Zernio handles LinkedIn, Instagram and Facebook too. Add a line to the plan with &lt;code&gt;"linkedin"&lt;/code&gt; and the matching account ID, and the same &lt;code&gt;schedule_post&lt;/code&gt; function just works — no new integration.&lt;/p&gt;

&lt;p&gt;From this base you can build:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a content calendar that refills itself every Sunday,&lt;/li&gt;
&lt;li&gt;a product that lets &lt;em&gt;your&lt;/em&gt; users schedule across platforms,&lt;/li&gt;
&lt;li&gt;a cron job on a cheap VPS that runs the whole thing while you sleep.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Consistency beats brilliance on social media, and consistency is automatable.&lt;/li&gt;
&lt;li&gt;The hard part of automation isn't AI content — it's cross-platform plumbing.&lt;/li&gt;
&lt;li&gt;One unified API removes that plumbing, so a complete scheduler fits in ~80 lines of Python.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need a marketing team. You need a script and an API that does the boring part.&lt;/p&gt;

&lt;p&gt;The complete, runnable code is on GitHub: &lt;strong&gt;&lt;a href="https://github.com/Kevinelectronics/social-media-automation" rel="noopener noreferrer"&gt;github.com/Kevinelectronics/social-media-automation&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the Zernio API key
&lt;/h2&gt;

&lt;p&gt;To run this, you'll need a Zernio account. The free tier covers your first 2 connected accounts with full API access and no credit card — enough to ship this entire project for free.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://zernio.link/kevin-meneses" rel="noopener noreferrer"&gt;Get your free Zernio key here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Connect Twitter and Reddit, drop in your keys, and you'll have a week of posts scheduled before your coffee's cold.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;❓ Is there a free social media posting API?&lt;/strong&gt;&lt;br&gt;
✅ Yes. Zernio's free tier includes your first 2 connected accounts with unlimited posts and full REST API access, no credit card required. That's enough to build and run this Python automation end to end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ Can I schedule posts to multiple platforms with one API call?&lt;/strong&gt;&lt;br&gt;
✅ Yes. Zernio accepts a &lt;code&gt;platforms&lt;/code&gt; array in a single request, so one call can target Twitter, Reddit, LinkedIn and more at once. You send one JSON payload and it handles each platform's formatting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ Do I need an SDK to use Zernio with Python?&lt;/strong&gt;&lt;br&gt;
✅ No. Zernio is a plain REST API with Bearer authentication, so Python's built-in-feel &lt;code&gt;requests&lt;/code&gt; library is all you need. No vendor SDK to install or keep updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;❓ Which platforms does Zernio support?&lt;/strong&gt;&lt;br&gt;
✅ Twitter/X, Reddit, LinkedIn, Instagram, Facebook, and around ten more including YouTube, TikTok, Threads, Pinterest and Bluesky — all through the same endpoint.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Looking for technical content for your company? I can help — &lt;a href="https://www.linkedin.com/in/kevin-meneses-gonzalez/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · &lt;a href="mailto:kevinmenesesgonzalez@gmail.com"&gt;kevinmenesesgonzalez@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>api</category>
      <category>socialmedia</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
