DEV Community

Eric Khoo
Eric Khoo

Posted on

How I built a serverless ETF backtest bot with GitHub Actions and Telegram

TL;DR: I built a small, open-source Telegram bot that tracks major ETFs (CSPX, QQQM), calculates Trend/Momentum scores, and shows historical win rates for current market structures — using only free serverless tools.


The problem: "Is now a good time?"

If you’ve ever dollar-cost averaged into ETFs, you’ve probably asked yourself this question at some point.

The market is up — should I wait for a pullback?
The market is down — is this a buying opportunity or a falling knife?

I couldn’t find a tool that gave me a data-backed answer without requiring a Bloomberg terminal or a PhD in finance. So I built one.


The solution: A bot that shows historical probabilities

Instead of telling me what might happen, the bot tells me what historically happened when the market looked like this.

Here’s what a daily update looks like:

📜 Historical Match: 138 occurrences
  • Next 90d: Win 84.1% | Avg +5.9% | MaxDD -18.4%
  • Next 180d: Win 76.1% | Avg +9.1% | MaxDD -18.0%
Enter fullscreen mode Exit fullscreen mode

That’s not a prediction. That’s data.


How it works (the 30-second version)

  1. Every trading day, the bot fetches 15 years of historical data for CSPX and QQQM.

  2. It calculates MA50, MA200, and RSI (14).

  3. It combines those into two composite scores:

Trend Score (0–100) – measures structural health
Momentum Score (0–100) – measures short-term strength

It scans the entire 15-year history for structurally similar periods (within ±8 points on both scores).

It calculates forward returns for those matched periods — 90 days and 180 days out.


The tech stack (all free, all serverless)

Component | Tool
Data source | Yahoo Finance (via yfinance)
Calculation engine | Python (pandas, matplotlib)
Scheduling & execution | GitHub Actions (cron + on-demand)
API gateway | Cloudflare Workers
Delivery | Telegram Bot API
Source code | GitHub (MIT license)

The entire pipeline costs $0/month to run. GitHub Actions provides free compute, Cloudflare Workers provides free API routing, and Telegram provides free delivery.


The core logic: Trend Score explained

I wanted a scoring system that was simple enough to explain but robust enough to be useful.

The Trend Score is calculated as follows:

  • Start at 50 (neutral)

  • If price > MA200 → +20 points, plus bonus for distance above

  • If price > MA50 → +10 points

  • If MA50 > MA200 (golden cross) → +5 points

  • Vice versa for bearish conditions

This gives a score from 0 to 100 that reflects how “bullish” or “bearish” the current structure is.


The historical backtest: how the probability is calculated

This is the part that took the most thought.

For every trading day in the last 15 years, I calculate the Trend and Momentum scores. I then find all days where both scores are within ±8 points of today’s values.

Those days become the historical match set. For each matched day, I calculate:

  • The price 90 days later

  • The price 180 days later

  • The return percentage

  • The max drawdown during that period

The results are aggregated and displayed as:

  • Win rate (% of positive returns)

  • Average return

  • Maximum drawdown

This is not a backtest of a trading strategy — it’s a structural similarity analysis.


One design decision I’m proud of

I didn’t optimize the parameters.

The tolerance (±8 points) and the indicator set (MA50, MA200, RSI) were chosen before running the backtest. I didn’t tweak them to make the numbers look better.

This means the results are honest. They might not be perfect, but they’re not fabricated either.


What’s next

  • More assets — I’m planning to add more ETFs, and eventually individual stocks.

  • More indicators — I may add volatility (ATR) and participation (volume) to the scoring.

  • Public dashboard — a simple web view of the daily analysis.


Try it yourself

The bot is free and open source.

If you’re a developer, you can fork the repo and adapt it to your own assets. If you’re an investor, just join the channel and check the daily update.


Feedback welcome

If you have thoughts on:

  • The scoring methodology

  • What assets to add next

  • How to improve the historical backtest

I’d genuinely appreciate hearing from you.

Built by Eric Khoo. Not financial advice — just data.

Top comments (0)