To build a crypto trading or analysis bot with Claude Code, run Claude Code on a VDS (a virtual dedicated server) and let it write, test and run the code on that server. Claude Code is Anthropic's coding agent. It reads your project, edits files and runs commands, while the model itself runs in Anthropic's cloud. The server gives the bot what a laptop can't: it runs all day, it has a fixed IPv4 address that exchanges can whitelist, and it has enough CPU cores to test strategies quickly. You don't need to trust a bot with your money to get value from this. The safest start is a bot that only watches the market and sends you Telegram alerts, while you keep the buy and sell buttons.
Key facts, checked on 9 October 2026:
- Claude Code is included in Claude's paid plans, from Pro ($20 a month) up to Max ($100 or $200), and with API billing. It needs Debian 10+ or Ubuntu 20.04+ and 4 GB of RAM (Claude Code docs). We installed version 2.1.295 on Debian 13.
- Freqtrade 2026.9 is a free, open-source trading bot under GPLv3. It starts in dry-run mode, so every trade is simulated until you change that (freqtrade.io).
- Exchanges limit API access per IP address. Binance allows 6,000 request weight per minute per IP, then answers with 429 errors and can ban the IP for up to 3 days (Binance API docs). A Binance key without an IP restriction can only read, not trade.
- In the EU, MiCA rules apply in full since the transition period ended on 1 July 2026. Kraken, Coinbase, Bitstamp, Bybit EU, OKX and Bitvavo are in ESMA's register of licensed providers; Binance is not.
- Regulators warn about "AI trading bot" promises. The CFTC's advisory is titled "AI Won't Turn Trading Bots into Money Machines". This article is about tools and testing, not financial advice.
What Claude Code does in this setup, and what it doesn't
Claude Code is a programmer that sits in your terminal. You describe what you want in plain words. It reads the files, writes a strategy or a script, runs the backtest, reads the result and fixes what broke. On a server that means you can say "add RSI to this strategy, backtest it on the last four months and compare it with simply holding the coins" and come back to a finished answer.
What it doesn't do is know where the price goes next. It works with the same public data you have. Its value is speed: an idea you would spend an evening coding is tested in minutes, and most ideas fail that test. That alone saves money. Our own first test below is a good example.
Why a VDS and not your laptop
- It never sleeps. A bot or an alert script on a laptop stops when the lid closes. A server keeps running, and Claude Code sessions survive in tmux when you disconnect.
- One fixed IPv4 address. Exchanges let you lock an API key to an IP address, and some require it. Binance only enables trading on keys with an IP restriction, and Bybit expires keys without a bound IP after 90 days (Bybit docs). A server's address doesn't change; a home connection's often does.
- CPU cores for testing. Strategy optimisation runs hundreds of backtests. In our lab, 200 rounds of Freqtrade's hyperopt took 573 seconds with 2 workers and 205 seconds with 8, about 2.8 times faster on the same 8-core machine.
- Your keys stay off your personal computer. The machine you browse and open email on is the machine most likely to be compromised.
- A /48 of IPv6 for data collection. Every RS Computers server in Amsterdam and Dublin comes with its own /48 IPv6 prefix, which is 65,536 subnets of /64 each. More on how to use it below.
Where the server is matters more than you think
Most exchanges decide what you may use from your verified residence. Some also look at where the API request comes from:
- Binance: Freqtrade's exchange notes say Binance restricts API access by the server's country and name the Netherlands. Binance also stopped serving Dutch residents in July 2023, and it is not in ESMA's MiCA register. If Binance is your exchange, an Amsterdam server is the wrong choice.
- Bybit: its API returns 403 to requests from the US and mainland China (Bybit API guide).
- Kraken: it bases restrictions on your verified residency (Kraken support). Its EU entity is licensed by the Central Bank of Ireland.
| Exchange (EU entity) | MiCA licence from | Freqtrade support |
|---|---|---|
| Kraken | Ireland, June 2025 | Supported (spot; history needs trade downloads) |
| OKX (MyOKX EEA) | Malta, January 2025 | Supported (spot) |
| Bybit EU | Austria, May 2025 | Supported (spot) |
| Gate EU | Malta, September 2025 | Supported (spot) |
| Bitvavo | Netherlands, June 2025 | Listed, not officially supported |
| Coinbase | Luxembourg, June 2025 | Listed, missing some features |
Licence dates come from ESMA's interim MiCA register (updated 30 September 2026). Freqtrade's status comes from its own list-exchanges command, version 2026.9. In Kosovo, the Law on Crypto-Assets (No. 08/L-295, published November 2024) puts the Central Bank of Kosovo in charge of licensing crypto operators. Check your own exchange's terms before you choose a city.
Step 1: prepare the server
We used Debian 13. Log in as root and install the tools, then create a normal user for the bot work. Claude Code and the bots should never run as root:
# as root
apt update
apt install -y sudo curl git tmux docker.io docker-compose python3-venv cron
useradd -m -s /bin/bash -G sudo,docker bot
passwd bot
Type a long password twice. From now on, connect as that user with ssh bot@YOUR_SERVER_IP. docker compose version should print 2.26 or later.
Step 2: install Claude Code and sign in over SSH
# as the bot user
curl -fsSL https://claude.ai/install.sh | bash
exit
The installer puts Claude Code in ~/.local/bin. On Debian that folder joins your PATH at the next login, which is why the last line logs you out. Connect again and check the installation:
# as the bot user, after logging in again
claude --version
claude doctor
We got 2.1.295 (Claude Code) and "No installation issues found". Now start a tmux session, so Claude Code keeps working when your SSH connection drops, and run it:
# as the bot user
tmux new -s claude
claude
On a server without a browser, Claude Code prints a sign-in link. Press c to copy it, open it on your own computer or phone, sign in with your Claude account, and paste the code shown back into the terminal. To leave Claude Code running, press Ctrl+B, then D. tmux attach -t claude brings you back to it later.
Step 3: lock your keys away before Claude Code sees the project
Claude Code reads files to do its work, so decide now what it may not read. Create a project folder with a settings file:
# as the bot user
mkdir -p ~/bot-project/.claude && cd ~/bot-project
cat > .claude/settings.json <<'EOF'
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./secrets/**)",
"Read(~/.alerts.env)"
],
"disableBypassPermissionsMode": "disable"
}
}
EOF
claude doctor
If the file has a typo, claude doctor prints Invalid settings and the file's name, as it did when we broke it on purpose. The deny rules stop Claude Code's own tools from reading your key files. The last setting turns off the mode that skips every permission question. Anthropic's permissions documentation recommends that mode only for isolated containers.
The documentation is also clear about a limit: deny rules cover Claude Code's built-in tools and common shell commands, not a script that opens the file itself. For a stronger fence, install the sandbox tools with sudo apt install bubblewrap socat (bubblewrap 0.12.0 on Debian 13) and turn the sandbox on with /sandbox inside Claude Code. Then follow the exchange-side rules, which matter even more:
- Read-only keys for analysis. A bot that only watches needs no trading permission at all.
- Never enable withdrawals. Kraken's API key guide notes that a trading key almost certainly doesn't need the Withdraw Funds permission.
- Lock every key to the server's IPv4 address. A stolen key is useless from anywhere else.
- Use a sub-account holding only the money the bot may lose.
Step 4: a trading bot in dry-run with Freqtrade
Freqtrade handles the hard parts: exchange connections, order handling, backtesting and a test mode. Get it running before you involve Claude Code:
# as the bot user
mkdir ~/ft_userdata && cd ~/ft_userdata
curl -fsSL https://raw.githubusercontent.com/freqtrade/freqtrade/stable/docker-compose.yml -o docker-compose.yml
docker compose pull
docker compose run --rm freqtrade create-userdir --userdir user_data
The last command creates user_data with a sample strategy in it. Freqtrade's new-config command asks questions to build a configuration. This minimal one does the same job; save it as user_data/config.json with nano:
{
"max_open_trades": 3,
"stake_currency": "EUR",
"stake_amount": 100,
"tradable_balance_ratio": 0.99,
"fiat_display_currency": "EUR",
"dry_run": true,
"dry_run_wallet": 1000,
"cancel_open_orders_on_exit": false,
"trading_mode": "spot",
"entry_pricing": { "price_side": "same", "use_order_book": true, "order_book_top": 1 },
"exit_pricing": { "price_side": "same", "use_order_book": true, "order_book_top": 1 },
"exchange": {
"name": "myokx",
"key": "",
"secret": "",
"pair_whitelist": ["BTC/EUR", "ETH/EUR", "SOL/EUR"]
},
"pairlists": [{ "method": "StaticPairList" }],
"bot_name": "lab-bot",
"initial_state": "running",
"internals": { "process_throttle_secs": 5 }
}
"dry_run": true with a pretend wallet of 1,000 EUR means nothing real happens. The key fields stay empty, because downloading prices and simulating trades needs no account. We used OKX's EEA exchange (myokx) because it serves EUR pairs and gives long price histories. Now download four months of candles and backtest the sample strategy:
# as the bot user, in ~/ft_userdata
docker compose run --rm freqtrade download-data --config user_data/config.json --timeframes 1h 5m --days 120
docker compose run --rm freqtrade backtesting --config user_data/config.json --strategy SampleStrategy --timerange 20260611-
The download took 41 seconds for three pairs. The backtest took 14 seconds and printed a long table. These were the lines that mattered:
| Result, 11 June to 9 October 2026 | Value |
|---|---|
| Trades | 100, of which 91 winners |
| Bot's total profit | +2.95% (29.45 EUR on 1,000) |
| Market change (holding the three coins) | +53.32% |
| Worst single trade | -10.27% |
| Mean profit p-value | 0.25 (not statistically meaningful) |
A 91% win rate sounds great until you read the line below it: simply holding the coins did eighteen times better. This is why backtesting comes first. A bot that looks busy and wins most trades can still lose against doing nothing.
When you want the simulated bot to run around the clock, start it in the background with docker compose up -d. Its log shows Dry run is enabled. All trades are simulated. and a heartbeat every minute (docker compose logs --tail 20 freqtrade). Freqtrade's web interface, FreqUI, should stay on 127.0.0.1 as in the downloaded file. The REST API docs strongly recommend not exposing it to the internet, so reach it through an SSH tunnel.
Step 5: put Claude Code to work
Give Claude Code the project rules first. A CLAUDE.md file in the project folder is read at the start of every session:
# as the bot user
cat > ~/ft_userdata/CLAUDE.md <<'EOF'
# Rules for this project
- This is a Freqtrade project run with docker compose. Strategies live in user_data/strategies.
- Never set dry_run to false and never add API keys. A human does that.
- Every strategy change ends with a backtest. Report total profit, max drawdown,
number of trades and the "Market change" line side by side.
- Optimise on one period and confirm on a later period the optimiser never saw.
- Explain each entry and exit rule in plain words in the strategy file.
EOF
Claude Code treats CLAUDE.md as guidance, not as a lock, which is why the settings file from step 3 does the hard blocking. Then start Claude Code in that folder and ask for real work. These are the kinds of requests it handles well:
- "Read
user_data/strategies/sample_strategy.pyand explain every entry and exit condition in plain English." - "Write a new strategy that buys when the 1-hour EMA 20 crosses above EMA 50 and RSI is below 65, with a 6% stop-loss. Backtest it from 20260611 and compare it with SampleStrategy and with the market change."
- "Run hyperopt for 200 epochs with 8 workers on the buy and sell spaces using data until 20260901, then backtest the best parameters on September and October only."
- "The backtest shows most losses on SOL/EUR. Find out why and suggest one change. Don't apply it yet."
The last request shows a good habit: ask for analysis first, then approve changes. In normal mode Claude Code asks before it edits a file or runs a command, so you see each step. As the third request shows, keep testing periods apart. A strategy tuned on the same data it is judged on looks far better than it will trade.
Check on it from your phone
Claude Code's Remote Control connects a session running on your server to the Claude app on your phone or to claude.ai. Inside tmux, run claude remote-control and open the link or QR code it shows. It works with Pro, Max, Team and Enterprise sign-ins, not with API keys, and it uses outbound HTTPS only, so no port on the server needs to be opened. A long backtest can finish while you are away, and you read the result on your phone.
Not ready to automate? Let the bot watch and tell you
Many people don't want software placing orders, and that is a reasonable position. A watcher bot gives you most of the benefit with none of that risk. It checks prices and news every few minutes and sends a Telegram message when something needs your attention:
- a coin moves more than 5% in 24 hours,
- RSI says a coin is stretched (below 30 or above 70),
- a headline mentions a hack, an exploit, a delisting, halted withdrawals, a stablecoin losing its peg, or a lawsuit.
You decide what, if anything, to do. This is a script of the kind Claude Code writes in a few minutes when you describe the alerts you want. It reads public data only and never trades:
# as the bot user
mkdir -p ~/analysis && cd ~/analysis
python3 -m venv .venv
. .venv/bin/activate
pip install ccxt
nano alerts.py
Paste this, then save with Ctrl+O, Enter and Ctrl+X:
#!/usr/bin/env python3
"""Alert bot: watches prices, RSI and headlines, and sends a Telegram message. It never trades."""
import json
import os
import pathlib
import time
import urllib.parse
import urllib.request
import xml.etree.ElementTree as ET
import ccxt
PAIRS = ["BTC/EUR", "ETH/EUR", "SOL/EUR"]
MOVE_ALERT = 5.0 # alert when the price moves more than this many % in 24 hours
RSI_LOW, RSI_HIGH = 30, 70 # alert when RSI leaves this range
FEEDS = ["https://cointelegraph.com/rss"]
WORDS = ["hack", "exploit", "delist", "halt", "outage", "depeg", "insolven", "freeze", "lawsuit", "sec "]
SEEN = pathlib.Path.home() / ".alerts-seen.json"
def rsi(closes, period=14):
gains = losses = 0.0
for prev, cur in zip(closes[-period - 1:-1], closes[-period:]):
gains += max(cur - prev, 0)
losses += max(prev - cur, 0)
return 100.0 if losses == 0 else 100 - 100 / (1 + gains / losses)
def market_alerts(seen):
exchange = ccxt.myokx()
today = time.strftime("%Y-%m-%d")
found = []
for pair in PAIRS:
closes = [c[4] for c in exchange.fetch_ohlcv(pair, timeframe="1h", limit=100)]
change = (closes[-1] / closes[-25] - 1) * 100
value = rsi(closes)
key = f"{today} {pair}" # one market alert per pair per day
if key not in seen and (abs(change) >= MOVE_ALERT or not RSI_LOW <= value <= RSI_HIGH):
found.append(f"{pair}: {closes[-1]:.2f} EUR, 24h {change:+.1f}%, RSI {value:.0f}")
seen.add(key)
return found
def news_alerts(seen):
found = []
for url in FEEDS:
req = urllib.request.Request(url, headers={"User-Agent": "alert-bot/1.0"})
root = ET.fromstring(urllib.request.urlopen(req, timeout=15).read())
for item in root.iter("item"):
title = (item.findtext("title") or "").strip()
if title and title not in seen and any(w in title.lower() + " " for w in WORDS):
found.append(f"{title}\n{item.findtext('link')}")
seen.add(title)
return found
def send(text):
token, chat = os.environ.get("TG_TOKEN"), os.environ.get("TG_CHAT")
if not token or not chat:
print(text)
return
data = urllib.parse.urlencode({"chat_id": chat, "text": text[:4000]}).encode()
urllib.request.urlopen(f"https://api.telegram.org/bot{token}/sendMessage", data=data, timeout=15)
seen = set(json.loads(SEEN.read_text())) if SEEN.exists() else set()
lines = market_alerts(seen) + news_alerts(seen)
if lines:
send("Market watch\n\n" + "\n\n".join(lines))
SEEN.write_text(json.dumps(sorted(seen)[-1000:]))
Run it once with python alerts.py. Without a Telegram token it prints instead of sending. Our first run printed SOL/EUR: 97.44 EUR, 24h -5.9%, RSI 34; a second run printed nothing, because each alert is sent once per pair per day and each headline only once. The RSI here uses simple averages, so it can differ slightly from your exchange's chart.
To receive the messages, create a bot with @BotFather in Telegram and find your chat ID; our Telegram bot hosting guide shows both steps. Put the two values in a private file and schedule the script every 15 minutes:
# as the bot user
cat > ~/.alerts.env <<'EOF'
export TG_TOKEN="YOUR_BOT_TOKEN"
export TG_CHAT="YOUR_CHAT_ID"
EOF
chmod 600 ~/.alerts.env
( crontab -l 2>/dev/null; echo '*/15 * * * * . $HOME/.alerts.env; $HOME/analysis/.venv/bin/python $HOME/analysis/alerts.py >> $HOME/alerts.log 2>&1' ) | crontab -
crontab -l
If ~/alerts.log shows HTTP Error 401: Unauthorized, the token is wrong. The alert file is also one of the paths blocked in step 3, so Claude Code won't read the token while it improves the script.
Freqtrade can do a middle step too. Add "telegram": {"enabled": true, "token": "...", "chat_id": "..."} to the config and keep "dry_run": true. The bot then messages you every simulated entry and exit, and you can decide whether to copy them by hand. With a wrong token, its log says the token "was rejected by the server", which tells you what to fix.
Exchange API limits, and how to stay inside them
Every exchange limits how often a bot may call its API. The limits are counted per IP address, and going over has consequences:
- Binance: 6,000 request weight per minute and 10 orders per second, counted per IP rather than per key. Going over returns 429 errors, and continuing after that brings an IP ban from 2 minutes up to 3 days. Live values are in
/api/v3/exchangeInfo. - Bybit: keys without a bound IP stop working after 90 days.
- Kraken: its spot API returns only the last 720 candles, so long histories come from trade downloads, which are slower.
Practical rules that keep a bot healthy:
- One bot, one key, one IPv4 address. Two bots on the same address share one limit and can get each other banned.
- Use websockets for live prices instead of polling every second. Freqtrade and CCXT handle this for you.
- Collect history once and store it. Freqtrade's downloaded files are reused by every later backtest.
- Don't spread requests over many addresses to dodge a limit. Exchanges treat that as abuse, and it is the quickest way to lose an account.
Using your /48 of IPv6 for news and data
An RS Computers server in Amsterdam or Dublin comes with a whole /48 of IPv6, not a single address. That is useful for the data side of a bot. When we checked today, Cointelegraph, CoinGecko's API, Reddit, Google News and the SEC's website all had IPv6 addresses. The trading APIs of Kraken, Bybit and Binance had IPv4 addresses only.
That leads to a clean split. Trade over your fixed IPv4, the address you whitelist on the exchange. Collect news and data over IPv6, from an address that never touches an exchange key. A busy news collector then never shares an address with the key that can trade. You can also give each data job its own address, which makes logs and blocklists easy to read. Show your prefix and add a second address from it:
# as the bot user
ip -br link
ip -6 addr show dev eth0 scope global
sudo ip -6 addr add 2001:db8:abcd::10/48 dev eth0
curl -6 --interface 2001:db8:abcd::10 https://api64.ipify.org
Replace eth0 with your interface name from the first line, and 2001:db8:abcd with the first three groups of your own prefix. The last command prints the new address. On our Amsterdam test server, a news feed fetched that way answered 200 from the extra address. An address added like this lasts until the next reboot. Be a polite client on every address: respect each site's limits and terms, and prefer official APIs and RSS feeds to scraping.
Which plan: sizing for backtests, not for Claude Code
Claude Code itself is light, because the model runs at Anthropic. What needs the server's power is your own work: backtests and optimisation use every core you give them, price history fills disk, and every bot and database holds memory.
| Plan | Good for |
|---|---|
| VDS Small (4 vCPU, 8 GB, 240 GB NVMe) | Claude Code, an alert bot and one dry-run Freqtrade bot, with short backtests. |
| VDS Medium (8 vCPU, 16 GB, 480 GB NVMe) | Regular hyperopt runs with 8 workers, several bots side by side, a database of collected prices and news. |
| VDS Large (16 vCPU, 32 GB, 960 GB NVMe) | Optimising many pairs and timeframes at once, Freqtrade's machine learning add-on FreqAI, or several people's projects on one server. |
All VDS plans run on KVM with a 10 Gb/s port, unmetered traffic, a fixed IPv4 address and IPv6. Prices are on the plans page, and you can move up a plan later with a short reboot. Our measurement gives a feel for the difference: the same 200-round hyperopt took 9.5 minutes with 2 workers and under 3.5 minutes with 8. For servers in Amsterdam, Dublin or Prishtina, see VPS in the Netherlands, VPS in Ireland and VPS in Kosovo.
Honest limits, and the scams to avoid
- No tool predicts prices. The CFTC's advisory says "AI technology can't predict the future or sudden market changes". ESMA's March 2025 warning reminds investors that public AI tools are not authorised or supervised by financial regulators.
- "AI bot" schemes are a known fraud. The UK FCA's warning list names many unauthorised "AI trader" and "crypto bot" firms. Anyone who sells a bot with a promised monthly return is selling the promise, not the bot.
- Reported volume isn't always real. An academic study of crypto wash trading (Cong and others) found it averaged over 70% of reported volume on unregulated exchanges, which is one more reason to stay with licensed venues.
- Backtests flatter. Real trading adds fees, slippage, outages and markets that change their character. Run any strategy in dry-run for weeks before real money, then start small.
Frequently asked questions
Can Claude Code trade crypto for me?
Claude Code writes and runs code; it is not a trading service. It can build, test and improve a bot such as Freqtrade on your server, but the bot follows the rules you approve, and no tool can promise profits. Keep it in dry-run until the backtests and weeks of simulated trading convince you.
Do I need a large server to run Claude Code?
No. Claude Code needs about 4 GB of RAM, because the model runs in Anthropic's cloud. A bigger VDS pays off for backtests and optimisation: in our test, 8 workers finished the same job about 2.8 times faster than 2.
How do I connect Claude Code to my server?
Install it on the server over SSH with the official installer, sign in by copying the link it prints to your own browser, and run it inside tmux so it keeps working when you disconnect. Remote Control then lets you follow the session from the Claude app on your phone.
Can I use Binance from a server in the Netherlands?
Freqtrade's exchange notes say Binance restricts API access by the server's country and name the Netherlands, and Binance doesn't serve Dutch residents. Use an exchange licensed under MiCA for EU customers, such as Kraken, OKX, Bybit EU or Bitvavo, and check its terms for your country.
Why do exchanges want an IP whitelist on API keys?
A key locked to your server's IP address is useless to anyone who steals it. Binance only allows trading on keys with an IP restriction, and Bybit expires keys without one after 90 days, so a server with a fixed IPv4 address makes this easy.
Can a bot just send me alerts instead of trading?
Yes, and it is the safest way to start. A small script checks prices, RSI and headlines every 15 minutes and sends a Telegram message when a coin moves sharply or the news mentions a hack, a delisting or halted withdrawals. You decide what to do.
Our short version
Put Claude Code on a VDS as a normal user, block it from reading your key files, and start with Freqtrade in dry-run and an alert bot that only watches. Let Claude Code write and test strategies, always against simply holding the coins, and keep trading keys locked to the server's IPv4 with withdrawals off. To get a server for it, pick a VDS on the plans page or message us on Telegram, and we will help you choose a city that works with your exchange.