You do not need a data science PhD to ship a working crypto trading bot. You need an API that returns pre-computed indicators, a few lines of Python, and a clear entry rule. This tutorial walks you through building a BTCUSDT bot in twenty minutes using APIndicators and the Binance Futures testnet.
By the end you will have a script that fetches RSI and EMA signals every ten minutes, decides whether to enter a long position, and logs every decision to disk. No machine learning, no backtest framework, no indicator implementation. Just working code.
What You Need Before Starting
- Python 3.10 or newer
- A free APIndicators account (sign up at apindicators.com/pricing)
- Binance Futures testnet API keys (optional, only if you want to place simulated orders)
- The
requestslibrary
Install the one dependency:
pip install requests
That is it. No pandas, no TA-Lib, no scipy. The whole point of using an indicator API is that you skip the setup hell.
Step 1: Grab Your API Key
After signing up, head to the dashboard and create an API key. APIndicators uses simple bearer tokens. Export it as an environment variable so you do not accidentally commit it:
export APINDICATORS_API_KEY="your_key_here"
Step 2: Fetch Indicators for BTCUSDT
APIndicators exposes 50+ technical indicators via a single endpoint per pair. Here is how you pull the latest RSI, EMA, and MACD values for BTCUSDT on the 1-hour timeframe:
import os
import requests
API_KEY = os.environ["APINDICATORS_API_KEY"]
BASE_URL = "https://api.apindicators.com/v1"
def get_indicators(symbol, interval="1h"):
url = f"{BASE_URL}/pairs/{symbol}/indicators"
headers = {"Authorization": f"Bearer {API_KEY}"}
params = {"interval": interval}
response = requests.get(url, headers=headers, params=params, timeout=10)
response.raise_for_status()
return response.json()
data = get_indicators("BTCUSDT")
print(f"RSI: {data['rsi_14']}")
print(f"EMA 20: {data['ema_20']}")
print(f"EMA 50: {data['ema_50']}")
print(f"Close: {data['close']}")
One HTTP call, fifty indicators, zero calculation on your side. The response includes RSI, MACD, Bollinger Bands, ATR, OBV, Stochastic, ADX, EMAs, VWAP, and dozens more.
Step 3: Define Your Strategy
We will use a classic setup: enter long when RSI crosses above 30 (oversold recovery) AND the 20 EMA is above the 50 EMA (uptrend confirmation). This is not a magic strategy, but it demonstrates the pattern.
def should_enter_long(data):
rsi = data["rsi_14"]
ema_20 = data["ema_20"]
ema_50 = data["ema_50"]
oversold_recovery = 30 < rsi < 45
uptrend = ema_20 > ema_50
return oversold_recovery and uptrend
def should_exit_long(data):
rsi = data["rsi_14"]
return rsi > 70
Two functions. One for entry, one for exit. Every serious bot starts here and adds complexity only when the simple version is proven to work.
Step 4: Wire Up the Main Loop
Run the strategy every ten minutes. Track one open position at a time.
import time
import logging
from datetime import datetime
logging.basicConfig(
filename="bot.log",
level=logging.INFO,
format="%(asctime)s - %(message)s"
)
position = None
def run_strategy():
global position
data = get_indicators("BTCUSDT")
price = data["close"]
if position is None and should_enter_long(data):
position = {"entry_price": price, "entry_time": datetime.utcnow()}
logging.info(f"ENTER LONG at {price} | RSI={data['rsi_14']}")
elif position is not None and should_exit_long(data):
pnl_pct = (price - position["entry_price"]) / position["entry_price"] * 100
logging.info(f"EXIT at {price} | PnL={pnl_pct:.2f}%")
position = None
else:
logging.info(f"HOLD | price={price} | RSI={data['rsi_14']}")
while True:
try:
run_strategy()
except Exception as e:
logging.error(f"Strategy error: {e}")
time.sleep(600)
That is a complete paper-trading bot. It logs every decision to bot.log, handles errors without crashing, and sleeps between checks.
Step 5: Add Webhook Alerts (Optional)
Instead of polling every ten minutes, APIndicators can push signals to you via HMAC-signed webhooks. Register a webhook URL in your dashboard and handle incoming signals with Flask:
from flask import Flask, request, abort
import hmac
import hashlib
import os
app = Flask(__name__)
WEBHOOK_SECRET = os.environ["APINDICATORS_WEBHOOK_SECRET"].encode()
@app.route("/webhook", methods=["POST"])
def webhook():
signature = request.headers.get("X-Signature", "")
body = request.get_data()
expected = hmac.new(WEBHOOK_SECRET, body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, expected):
abort(401)
payload = request.json
if payload["signal"] == "BUY" and payload["confidence"] >= 0.80:
print(f"Trade signal: BUY {payload['symbol']} at {payload['price']}")
return {"ok": True}
if __name__ == "__main__":
app.run(port=5000)
Webhooks eliminate polling entirely. You only react when a qualifying signal fires.
What to Do Next
This bot does not place real orders. When you are ready, plug in the Binance Futures API (or your exchange of choice) to actually execute trades. Before that, run this exact script for at least two weeks of paper trading and track the win rate.
Three concrete next steps:
- Add a stop loss. Exit if price drops 1.5% below entry.
- Track win rate per day and alert yourself if it drops below 45%.
- Scale to multiple pairs by looping over the top 20 most liquid contracts.
Full API docs are at apindicators.com/docs. The free tier includes enough requests to run this bot on three pairs at 10-minute intervals. Ready to ship? Grab your API key and go.