An autonomous, self-hosted crypto trading bot with an LLM for a brain. You give it a small stake on Kraken and an API key for the LLM of your choice; it manages the money on its own schedule, keeps a full written diary of every thought, and pushes you a daily digest. Your only control is the halt button β by design.
β οΈ This is an experiment, not a product. An LLM has no proven trading edge. Magpie is built for people who want to watch an AI manage a toy stake with real rails around it β not for money you can't afford to lose. Expect anything from slow bleed to pleasant surprise. The house always takes 0.4% a trade.
π New to this, or on Windows? Jump to the step-by-step Windows guide β install to uninstall, no coding needed.
Dashboard a few months in, trading the top-5 alt universe (simulated preview data β a fresh install starts humbler).
Four sleeves, each an independent sub-portfolio with its own books, its own mandate, and its own decision cadence:
| Sleeve | Horizon | Decides | Funded by |
|---|---|---|---|
| swing | ~1β3 days | every 6 h | β of the stake |
| fortnight | 1β2 weeks | daily | β of the stake |
| quarter | weeksβ3 months | Mondays | β of the stake |
| vault | a year+ | 1st of month | profits only |
Each decision cycle, the engine builds a context pack β that sleeve's holdings, market data with computed indicators (EMA 20/50/200, RSI, multi-horizon returns), its own recent decision history, and a fee reminder β and asks its LLM for a strict-JSON decision: buy / sell / hold, pair, fraction, confidence, reasoning.
The validation layer is the real boundary: only whitelisted pairs, spot only, long only, exchange minimums enforced, balances reconciled β and any malformed, out-of-universe or errored answer resolves to HOLD. The model's words never touch the exchange; only validated orders do.
The vault starts empty. Whenever an active sleeve's value exceeds its high-water mark, half of the realised profit (EUR actually banked, not paper gains) is skimmed into the vault, and the mark ratchets up. The vault accumulates long-term positions out of house winnings only β losing sleeves are never refilled from it.
It learns from itself. Once a month it re-reads its own diary β every decision, what it reasoned at the time, and what actually happened β and writes itself a lessons note that is injected into all future prompts. The only memory it carries forward is the one it earns.
It trades like a local. Orders go in as post-only limits at the touch (maker fee ~0.25%) with a patient window before falling back to market (~0.40%) β a guaranteed saving on every fill that patience can win. Decisions see daily and 4-hour indicators, the live spread, and the Crypto Fear & Greed index; the slow sleeves think with a stronger model than the fast ones.
It keeps score against a hodler. From its first sight of capital it tracks a phantom buy-and-hold portfolio of the same money (topped up in lockstep) β the dashboard and daily digest always show whether the AI is beating doing nothing, and the monthly self-review is confronted with the number. Closed trades are FIFO-paired into round trips (win rate, average win/loss, hold time), and a nightly reconciliation keeps the virtual sleeve books honest against real exchange balances.
Top-ups: deposit more EUR to the exchange whenever you like. The bot notices the surplus at its next cycle, splits it equally across the three active sleeves, and raises their high-water marks so fresh cash is never mistaken for profit.
Magpie isn't wed to one model. LLM_PROVIDER chooses who makes the call:
| Provider | LLM_PROVIDER |
API key from |
|---|---|---|
| Gemini (Google) β default | gemini |
aistudio.google.com |
| OpenAI (ChatGPT) | openai |
platform.openai.com |
| Anthropic (Claude) | anthropic |
console.anthropic.com |
| Perplexity | perplexity |
perplexity.ai β API |
| Grok (xAI) | grok |
x.ai |
| DeepSeek | deepseek |
platform.deepseek.com |
| GitHub Models (Copilot) | github |
github.com personal access token |
| OpenRouter β one key, any model above and more | openrouter |
openrouter.ai |
Each provider uses its own key β set the one for the brain you pick. The prompt
and the strict-JSON safety layer are identical whichever model answers, so a
model that formats badly simply resolves to HOLD. LLM_MODEL / LLM_MODEL_DEEP
override the per-provider default models (the deep one runs the slow sleeves and
the monthly self-review; the fast one runs the rest). Switch live from the
settings page β dropdown, key, Test active brain, save; no restart.
A paid ChatGPT / Perplexity / Copilot subscription is not an API key β each needs a developer key from the provider's platform, billed per token. Gemini's free tier is enough to run Magpie outright.
- The API key cannot withdraw. Create it with query + trade permissions only.
Worst-case compromise of the box = bad trades, never stolen funds. (The repo's
verification snippet in
docs/probes this.) - It can never deposit β there is no payment integration. The stake you fund is the ceiling.
- Spot only, long only, whitelisted pairs only β no leverage, no derivatives, no liquidations.
- Kill switch:
POST /api/halt(or the big red button on the dashboard) stops all ordering untilPOST /api/resume. - Total auditability: every prompt sent to the model and every raw response is stored. The dashboard diary shows what it saw, what it thought, and what it did β for every cent that moves.
There is deliberately no auto-stop-loss and no position cap β the operator takes the risk knowingly and holds the halt button. Add your own guardrails if that's not your temperament.
You need: Docker, a dedicated Kraken account that holds only the money you want Magpie to manage, a trade-only API key (see above), and an API key for one supported LLM β Gemini is the default and its free tier is plenty to start (the bot makes only a handful of calls a day). See The brain for the alternatives.
β οΈ Use an empty Kraken account. On its first live cycle Magpie treats the entire balance of the account as its starting stake and splits it across the sleeves, and its nightly reconciliation pulls any coin sitting on the account into its own books. So fund a fresh account with nothing else in it β just the stake you're giving Magpie. Don't point it at an account holding coins or cash you don't want it trading.
cp .env.example .env # fill in your Kraken + LLM keys; leave TRADING_ENABLED=false
docker compose up -d --build
The bot starts in paper mode: identical code path, live market data,
simulated fills against a pretend stake. Watch the diary at http://<host>:8000
until you trust it, then set TRADING_ENABLED=true and recreate the container.
At its first live cycle it treats your entire exchange EUR balance as the opening
top-up and splits it across the sleeves.
Schedule the heartbeat (systemd timer or cron):
0 0,6,12,18 * * * curl -s -X POST http://localhost:8000/api/cycle
5 18 * * * curl -s -X POST http://localhost:8000/api/digest
45 5 * * * curl -s -X POST http://localhost:8000/api/reconcile
30 5 1 * * curl -s -X POST http://localhost:8000/api/review
The cycle endpoint is safe to call at any hour β sleeve cadences are gated internally (fortnight only acts on the 06:00 call, quarter on Monday's, the vault on the 1st of the month).
Magpie runs anywhere Docker does. On Windows β or if you're not very technical β follow the complete step-by-step Windows guide: install, run, schedule, go live, update and uninstall, all click-by-click with no coding.
GET /healthβ liveness, mode, halt state, last decisionGET /api/stateβ full portfolio, sleeve breakdown, decision diary, skimsPOST /api/cycleβ run a decision tickPOST /api/digestβ push the daily summaryPOST /api/reviewβ run the monthly self-review (writes the lessons note)POST /api/reconcileβ absorb drift between the sleeve books and exchange realityGET /settingsβ a page to enter/change keys and Home Assistant details (secrets masked; test buttons for each integration). Web-entered settings persist and override the env.POST /api/halt/POST /api/resumeβ the only human controlsPOST /api/topup?amount=β paper mode only; live deposits are auto-detected
Base currency. Magpie trades against and values everything in one currency β EUR by default, or USD, GBP, etc. It's a one-time choice at initial setup (Settings β Base currency): the moment you set it β and automatically once the bot has traded β it locks permanently, because switching it on a funded account would leave your holdings and exchange balance in the wrong currency. Choose it before funding.
Timezone. Set TIMEZONE (an IANA name like America/New_York, default
Europe/Dublin) β or pick it on the settings page β so the daily 06:00, Monday
and 1st-of-month decision slots run on your local clock. It's safe to change
anytime; align it with the schedule you set below.
Everything else is env vars β see .env.example. Notables:
LLM_PROVIDER (which brain; default gemini) and its matching API key,
LLM_MODEL / LLM_MODEL_DEEP (optional model overrides), PAIRS (the base
tradeable universe, default BTC/EUR + ETH/EUR), and SKIM_FRACTION (profit share
skimmed to the vault, default 0.5).
Magpie can push every event β trades, top-ups, the daily digest, error alerts and
the monthly self-review β to as many channels as you like. Set the ones you want
(in .env or on the settings page); each fires only when its keys are present, and
every alert fans out to all configured channels at once:
| Channel | Config |
|---|---|
| Home Assistant push | HA_URL + HA_TOKEN + HA_NOTIFY_SERVICE |
| Pushover | PUSHOVER_TOKEN + PUSHOVER_USER |
| Pushbullet | PUSHBULLET_TOKEN |
| Discord (rich embed) | DISCORD_WEBHOOK_URL |
| Telegram | TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID |
| ntfy | NTFY_TOPIC (+ NTFY_SERVER, default ntfy.sh) |
HA_NOTIFY_CLICK_URL (e.g. your dashboard URL) becomes the tap-to-open link on
every channel that supports it, and the settings page's Test button sends a
test to all configured channels at once. Configure nothing and Magpie just runs
quietly β one channel failing never blocks the others.
With DYNAMIC_UNIVERSE=true, the tradeable set is your base pairs plus the
top-DYNAMIC_TOP_N (default 5) altcoins by market cap that trade against EUR
on Kraken β stablecoins and wrapped/staked tokens excluded. It refreshes on a
weekly timer (POST /api/universe/refresh) and pushes a heads-up when the set
changes.
It never strands a position, and never churns fees on a ranking reshuffle: a
held coin that slips out of the top-DYNAMIC_TOP_N stays sellable at the bot's
own discretion, and only once it falls past DYNAMIC_SELL_FLOOR_N (default 10)
is it force-sold at the weekly refresh β the band between the two is a grace
zone the model manages itself. Base pairs are never auto-sold, and sub-β¬1 dust
is left in place. GET /api/universe shows the current set.
Pin your own coins. Beyond the base pairs and the auto-tracked alts, add any
coin that trades against EUR on Kraken from the settings page's Custom coins
card (or MANUAL_PAIRS / POST /api/pairs/add {symbol}). Each is validated
against Kraken before it's saved, is always tradeable regardless of the rankings,
and β because you chose it deliberately β is exempt from the sell floor.
Set DASHBOARD_PASSWORD (env or the settings page's Security card) to require a
password for the dashboard, portfolio view and controls. It's a single-password
cookie login; the health check and the timer-triggered action endpoints stay
open (they expose no data). Leave it blank to run open on a trusted LAN or behind
your own reverse-proxy auth.
Two-factor (TOTP). Once a password is set, turn on 2FA from the Security card: scan the QR into Google Authenticator / Authy / 1Password, confirm a code, and every login then needs the 6-digit code as well as the password. It's standard TOTP, verified at login before the session cookie is issued.
Enabling 2FA hands you 10 single-use backup codes (shown once, stored hashed).
Any one works in the login's code field in place of your authenticator and is then
spent β the way back in if you lose your phone. Regenerate the set anytime from the
Security card (needs a current code). If you lose the authenticator and the codes,
the last resort clears it from the container:
docker exec magpie sqlite3 /data/magpie.db "DELETE FROM settings WHERE key IN ('totp_enabled','totp_secret','totp_backup_codes')".
MIT Β© 2026 Colm Finn.
Built by Colm Finn. The magpie trades alone; the consequences are its keeper's.