How I built a fully autonomous investment advisory bot in Python — for $0/month. No auto-trading. No paid APIs. Just a system that removes the information barrier between you and better decisions.
Codebase
~800 lines of Python
Monthly Cost
$0 — all free tools
Optimised Sharpe
2.23 (hedge-fund level)
Cloud Usage
~110 mins/month (free tier)
Most retail investors operate on instinct. They concentrate in a handful of tickers, never measure whether those instincts are working, and react emotionally when prices move. I wanted a system that applies the same analytical rigour used by quant funds — at zero cost. Here is the full architecture.
The Full Architecture
Eight layers. Each does exactly one job. Swap any layer without touching the rest.
Layer 1: Data → yfinance (free) + Broker API
Layer 2: Backtest → quantstats tearsheets vs SPY
Layer 3: Optimise → Riskfolio-Lib (4 methods)
Layer 4: Dip signals → 5-signal watchlist engine
Layer 5: Rules alerts → concentration, stop-loss, drift
Layer 6: Delivery → Telegram daily digest
Layer 7: Cloud → GitHub Actions (free tier)
Layer 8: Memory → advice_journal.csv
Step 1 — Measure First, Build Second
1
Generate a tearsheet before writing a single alert
The first script I wrote wasn’t an alert engine — it was a performance analyser. Using quantstats and yfinance, I generated an HTML tearsheet comparing my portfolio against SPY.
import quantstats as qs
qs.reports.html(portfolio_returns, benchmark='SPY', output='tearsheet.html')
Key metrics: Sharpe ratio, Max Drawdown, Calmar ratio, rolling beta. A portfolio that returned 46% but with −40% max drawdown is not beating the market — it’s leveraged to luck.
Run this baseline first. Everything else is built on top of it.
Step 2 — Optimise Mathematically
2
Same tickers. Four different weight strategies.
Riskfolio-Lib computes optimal weights across four methods. The difference is dramatic:
| Method |
CAGR |
Sharpe |
Max Drawdown |
| Max Sharpe (Markowitz) |
26.35% |
2.23 |
−10.21% |
| Risk Parity |
17.26% |
1.63 |
−10.66% |
| Min Risk |
9.13% |
1.22 |
−7.76% |
| Unoptimised original |
46.77% |
1.15 |
−40.44% |
The unoptimised version had a 40% max drawdown — concentration masquerading as skill. The optimiser runs monthly on GitHub Actions and auto-commits fresh target weights.
Step 3 — The 5-Signal Dip-Buy Engine
3
Score every stock across five independent signals
Score = number of signals fired simultaneously:
- Price < 50-day MA by a configurable threshold (e.g. −5%)
- Price < 200-day MA — deeper correction signal
- RSI(14) < 40 — technically oversold
- Price > 15% below 6-month high — significant drawdown
- Price < your average cost basis — natural averaging-down trigger
3–5 signals = STRONG BUY · 2 = BUY · 1 = MILD DIP
Multi-signal filtering eliminates the false positives that plague single-indicator systems.
Step 4 — Cover the Full AI Supply Chain
4
If you’re bullish on AI, own every layer of it
| Layer |
Tickers |
Why |
| Chip designers |
NVDA, AMD |
AI training & inference |
| AI networking |
AVGO |
Data centre infrastructure |
| Foundry |
TSM |
~90% of advanced chip manufacturing |
| Equipment |
ASML |
Only EUV lithography maker on Earth |
| Diversified |
SMH ETF |
Top 25 semiconductor names in one ticker |
One sector. Multiple moats. Far lower concentration risk than going all-in on a single name.
Step 5 — The Daily Rules Engine
5
Alert before problems become disasters
Five rules checked every morning:
RULES = {
"max_single_position_pct": 15.0, # alert if any stock > 15%
"max_sector_pct": 40.0, # alert if any sector > 40%
"stop_loss_pct": -30.0, # alert if any position < -30%
"min_position_value": 200.0, # alert if position < $200
"drift_threshold_pct": 5.0, # alert if drift from target > 5%
}
The Telegram digest every morning:
Portfolio Advisory — 2026-05-14
BUY-THE-DIP ALERTS
*** MSFT $408 — Below 200d MA, RSI 38, -20% off 6m high
Suggest +$500 (current 14% → cap 15%)
** META $603 — Below 200d MA, -18% off high
Critical Alerts
[CONCENTRATION] TSLA is 62.1% — REDUCE
Rebalance Suggestions
AAPL: 3.2% vs target 12.0% — ADD 8.8%
Arrives in Telegram every weekday morning before you open your broker.
Step 6 — The Advice Journal
6
Log every alert. Measure the outcome 30 days later.
Every alert is stored with the price at alert time:
date, ticker, alert_type, score, price_now, suggested,
notes, your_action, price_30d, return_30d
One command backfills the outcome column after 30 days:
python journal.py --backfill # fetches price 30 days after alert
python journal.py --summary # win rate, avg return by alert type
Without this, there is no feedback loop. The journal is what turns an alert tool into an advisory system that improves over time.
Step 7 — Free Cloud Deployment
7
Two GitHub Actions workflows power everything
| Workflow |
Schedule |
Job |
Runtime |
| advisor.yml |
Weekdays 13:30 UTC |
Sync → signals → Telegram → commit journal |
~40s |
| optimize.yml |
1st of month |
Re-optimise → commit new target weights |
~3 min |
on:
schedule:
- cron: '30 13 * * 1-5' # weekdays at market open
permissions:
contents: write # needed to commit the journal back
GitHub free tier = 2,000 mins/month. This system uses ~110.
Step 8 — Design Principles
8
The decisions that prevent the system from hurting you
| Principle |
Reason |
| Advisory-only, no auto-trading |
Human error-correction loop is preserved |
| Read-only API keys |
Worst-case breach = data exposure, not account drain |
| [skip ci] on bot commits |
Prevents the journal commit re-triggering the workflow |
| Separate daily / monthly workflows |
Daily: 15s install. Monthly: 3-min Riskfolio install |
| Measure first, build second |
You need the honest baseline before any alerts are useful |
Step 9 — DCA + Dip, No Forced Selling
9
Diversify by adding, not by selling winners
- Keep your conviction positions
- Let their weight dilute naturally as you add to others on dips
- Only add when signals fire — not on emotion
- Set a hard position cap per stock (e.g. max 12%)
The portfolio diversifies over time without a single forced sell decision.
The One Principle That Matters
“Build the measurement system first. Act on the data second. Build more features third.”
Most people skip straight to step three.
Build Your Own — Start With This Prompt
Open Claude, Claude Code, or Codex. Paste the prompt below, fill in your details, and it will guide you through building the full system step by step.
I want to build a Python-based investment advisory bot. Here is what it should do:
1. Pull portfolio data from [my broker API / a CSV export of my positions]
2. Generate a performance tearsheet comparing my portfolio vs SPY using quantstats
3. Optimise portfolio weights using Riskfolio-Lib across four methods:
Max Sharpe, Risk Parity, Min Risk, and Hierarchical Risk Parity
4. Run a 5-signal dip-buy scanner across a watchlist of stocks:
- Price below 50-day moving average by a configurable threshold
- Price below 200-day moving average
- RSI(14) below 40 (oversold)
- Price more than 15% below 6-month high
- Price below my average cost basis
5. Fire daily rules alerts for: concentration limits, stop-loss triggers,
sector exposure, and drift from target weights
6. Deliver a daily advisory digest to Telegram
7. Log every alert to advice_journal.csv and backfill 30-day price outcomes
8. Run automatically on GitHub Actions on a weekday schedule
The system must be advisory-only — it should never place trades automatically.
My setup:
- OS: [Windows / Mac / Linux]
- Broker: [eToro / Interactive Brokers / Alpaca / I will use a CSV export]
- Python experience: [beginner / intermediate]
My current portfolio tickers and approximate weights:
[e.g. NVDA 30%, AAPL 20%, MSFT 15%, TSLA 10%, cash 25%]
Start with Step 1: help me generate a quantstats tearsheet from my portfolio.
Ask me anything you need to get started.
Not sure which AI to use? Claude Code (claude.ai/code) works best for this — it can read and write files directly on your machine, run Python scripts, and iterate on the code with you in real time.
Common Questions
01Do I need a paid broker or API?
No. The data layer runs entirely on yfinance — free, no API key required. A broker API is only needed if you want live position sync. All advisory logic, optimisation, and Telegram delivery work with just yfinance and a manual CSV export of your positions.
02Does this work with eToro?
Yes. eToro launched public APIs in October 2025 at api-portal.etoro.com, including official support for AI Agent Portfolios. This system stays advisory-only by design, but the data sync layer can connect to the eToro API once you have access.
03Will this guarantee strong returns?
No — any system claiming guaranteed returns is misleading you. This is a decision-support tool. It removes emotional noise, enforces discipline, and surfaces information you would otherwise miss. Returns depend on your ticker selection and market conditions, not the bot.
04How long does setup take?
The core system runs in a weekend. GitHub Actions deployment takes a few more hours. Budget a full week if you want live broker sync and a fully tuned watchlist. Using the prompt above with Claude Code will significantly speed up each step.
05What Python level do I need?
Comfortable beginner. You need to install packages, run scripts, and edit a config file. You do not need to understand the mathematics inside Riskfolio-Lib — the library handles it. If you can write a basic function and read a DataFrame, you are ready to start.