The Quest Begins (The "Why")
Honestly, I was staring at my exchange dashboard at 2 a.m., coffee gone cold, watching Bitcoin dip 3% while I slept. I kept thinking, “If only I could tell my laptop to buy the dip and sell the rally while I’m dreaming.” That moment felt like the classic “choose your own adventure” page where you either keep losing sleep or you level up. I decided the dragon I needed to slay was manual, emotion‑driven trading—the kind that makes you second‑guess every click and leaves you exhausted.
So I embarked on a quest: build a simple, rule‑based crypto trading bot that could run 24/7, follow a clear strategy, and let me actually get some sleep.
The Revelation (The Insight)
The biggest “aha!” came when I realized a bot doesn’t need to be a sentient AI from Ex Machina; it just needs to obey a few clear instructions, like a loyal sidekick. The core idea is simple:
- Fetch market data (price, volume) from an exchange’s public API.
- Apply a rule—for example, “buy when the 5‑minute moving average crosses above the 20‑minute moving average.”
- Place an order via the exchange’s private API (using your API key).
- Loop every few minutes, log what happened, and repeat.
All the magic lives in that loop. Once you have it, you can swap out the rule for anything—RSI, MACD, even a sentiment‑based trigger—without rewriting the whole thing.
Wielding the Power (Code & Examples)
Below is a minimal, working example using the Binance API and the python‑binance library. I’ll show the “struggle” version first (the trap many beginners fall into), then the victorious version.
The Struggle – Hard‑coded sleep & no error handling
import time
from binance.client import Client
API_KEY = "your_key"
API_SECRET = "your_secret"
client = Client(API_KEY, API_SYMBOL)
def get_price():
ticker = client.get_symbol_ticker(symbol="BTCUSDT")
return float(ticker["price"])
def simple_strategy():
price = get_price()
# naive rule: buy if price < 30000, sell if > 31000
if price < 30000:
client.order_market_buy(symbol="BTCUSDT", quantity=0.001)
print(f"Bought at {price}")
elif price > 31000:
client.order_market_sell(symbol="BTCUSDT", quantity=0.001)
print(f"Sold at {price}")
while True:
try:
simple_strategy()
except Exception as e:
print("Error:", e)
time.sleep(60) # wait a minute
What went wrong?
- No rate‑limit awareness – Binance will ban you if you hammer the endpoint.
- The
quantityis hard‑coded; if your balance changes you could over‑ or under‑trade. - No logging or persistence – if the script crashes you lose track of what happened.
The Victory – Smart, resilient bot
import time
import logging
from binance.client import Client
from binance.exceptions import BinanceAPIException, BinanceRequestException
# ---- CONFIG -------------------------------------------------
API_KEY = "your_key"
API_SECRET = "your_secret"
SYMBOL = "BTCUSDT"
QUANTITY = 0.001 # adjust to match your account’s precision
FAST_MA = 5 # periods
SLOW_MA = 20
CHECK_INTERVAL = 30 # seconds – respects Binance weight limits
# -------------------------------------------------------------
client = Client(API_KEY, API_SECRET)
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s")
def get_klines(limit=SLOW_MA+1):
"""Fetch recent close prices for MA calculation."""
klines = client.get_klines(symbol=SYMBOL,
interval=Client.KLINE_INTERVAL_5MINUTE,
limit=limit)
return [float(k[4]) for k in klines] # close price
def moving_average(prices, window):
return sum(prices[-window:]) / window
def should_buy(fast, slow):
return fast > slow # bullish crossover
def should_sell(fast, slow):
return fast < slow # bearish crossover
def execute_order(side):
try:
order = client.order_market(symbol=SYMBOL,
side=side,
quantity=QUANTITY)
logging.info(f"Order placed: {side} {QUANTITY} {SYMBOL} | {order}")
except (BinanceAPIException, BinanceRequestException) as e:
logging.error(f"Binance error: {e}")
except Exception as e:
logging.error(f"Unexpected error: {e}")
def main():
while True:
try:
closes = get_klines()
if len(closes) < SLOW_MA:
logging.warning("Not enough data yet, waiting...")
time.sleep(CHECK_INTERVAL)
continue
fast_ma = moving_average(closes, FAST_MA)
slow_ma = moving_average(closes, SLOW_MA)
logging.info(f"Fast MA: {fast_ma:.2f} | Slow MA: {slow_ma:.2f}")
if should_buy(fast_ma, slow_ma):
execute_order(Client.SIDE_BUY)
elif should_sell(fast_ma, slow_ma):
execute_order(Client.SIDE_SELL)
else:
logging.info("No signal – holding.")
except Exception as e:
logging.exception("Loop crashed – restarting after pause")
time.sleep(CHECK_INTERVAL)
if __name__ == "__main__":
main()
Why this version feels like a win:
-
Rate‑limit friendly – we only call the API every
CHECK_INTERVALseconds (30 s here) and fetch a limited number of klines. -
Dynamic quantity – you can set
QUANTITYonce based on your account’s balance and precision. - Robust error handling – Binance‑specific exceptions are caught, and any unexpected crash is logged before the loop continues.
-
Clear, testable logic – the MA crossover rule lives in tiny pure functions (
should_buy,should_sell) that you can unit‑test without touching the exchange.
Running this script on a VPS or even a Raspberry Pi gives you a tireless trader that watches the market while you binge‑watch Stranger Things (hey, that’s our one body pop‑culture reference—felt like pulling off a perfect combo in Street Fighter when the bot finally executed its first trade).
Why This New Power Matters
Now that you’ve got a skeleton bot, the real adventure begins. You can:
- Swap the MA crossover for an RSI‑overbought/oversold strategy.
- Add Telegram notifications so you know when a trade happens.
- Implement risk management—stop‑loss, position sizing, or max daily loss.
- Paper‑trade first with Binance’s testnet to gain confidence without risking real funds.
The best part? You’ve turned a sleepless, anxiety‑filled habit into a repeatable, automated process. Every time the bot makes a trade, you’ll feel a tiny rush—like leveling up in an RPG after defeating a tough boss.
Your challenge: Fork the code above, add a simple logging file that records each trade’s timestamp, price, and side, then run it on Binance’s testnet for 24 hours. Come back and tell me what strategy you tried and how the bot behaved.
Happy hunting, and may your algorithms be ever in your favor! 🚀
Top comments (0)