From very simple single pair models to multi-pair / multi-model trading systems

From very simple single pair models to multi-pair / multi-model trading systems

At fxcryptobots.com, our trading automation journey began with single-pair models — simple but effective systems built around core technical indicators such as EMA and ATR. Over time, these evolved into powerful multi-pair, multi-model architectures capable of monitoring hundreds of cryptocurrencies, analyzing market conditions, and executing trades autonomously.

Below is a simplified version of one of our Binance Spot trading modules. This script continuously checks multiple pairs, determines trend direction using the EMA(50/200) crossover, and dynamically calculates position size based on market volatility (ATR). It demonstrates how a compact model can still operate fully autonomously within a defined rule set.

⚠️ Important Notice: This bot directly manages open positions. It should not be used simultaneously with other bots or manual trading on the same account, as it may close or reverse positions according to its own model logic. Although this version is designed for Binance Spot, it can easily be adapted for Binance Futures or any CCXT-supported exchange.

Example: Binance Spot Trading Bot (Python)


import ccxt
from datetime import datetime
import talib
import time
import pandas as pd
import traceback

LOG_FILE = "errorlog.txt"

def log_error(msg):
    """Append error message with UTC timestamp to log file"""
    now = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
    with open(LOG_FILE, "a", encoding="utf-8") as f:
        f.write(f"[{now}] {msg}\n")

def TheBinanceBotCode(dry_run=True, account_type="spot"):
    """
    dry_run=True → simulate only (no real orders)
    account_type → 'spot' or 'futures'
    """

    binance = ccxt.binance({
        'apiKey': 'YOUR_API_KEY',
        'secret': 'YOUR_SECRET_KEY',
        'enableRateLimit': True,
        'options': {'defaultType': account_type}
    })

    symbols = ["BTC/USDT", "ETH/USDT", "BNB/USDT"]

    try:
        balance_info = binance.fetch_balance()['info']
    except Exception as e:
        err = f"Balance fetch error: {e}"
        print("⚠️", err)
        log_error(err)
        return

    if account_type == "futures":
        balance = float(balance_info.get('totalWalletBalance', 0))
        positions = balance_info.get('positions', [])
    else:
        balance = binance.fetch_balance()['free'].get('USDT', 0)
        positions = []

    print(f"=== Total Balance: {balance:.2f} USDT ===")

    for symbol in symbols:
        try:
            ohlcv = binance.fetch_ohlcv(symbol=symbol, timeframe='5m', limit=500)
            df = pd.DataFrame(ohlcv, columns=['Time', 'Open', 'High', 'Low', 'Close', 'Volume'])
            df['Time'] = pd.to_datetime(df['Time'], unit='ms')
            df.set_index('Time', inplace=True)

            ema50 = talib.EMA(df['Close'], timeperiod=50)
            ema200 = talib.EMA(df['Close'], timeperiod=200)
            atr10 = talib.ATR(df['High'], df['Low'], df['Close'], timeperiod=10)

            ema50_last = ema50.iloc[-1]
            ema200_last = ema200.iloc[-1]
            atr10_last = atr10.iloc[-1]

            buy = ema50_last > ema200_last
            sell = ema50_last < ema200_last

            unit_risk_percent = 1
            risk_per_point = atr10_last * 10
            amount = balance * unit_risk_percent / 100 / risk_per_point

            decimals = binance.load_markets()[symbol]['precision']['amount']
            amount = round(amount, decimals)

            position_amt = 0
            print(f"\n🔹 {symbol}")
            print(f"EMA50={ema50_last:.2f}, EMA200={ema200_last:.2f}, ATR10={atr10_last:.4f}")
            print(f"New trade size={amount:.4f}")

            if dry_run:
                print("Dry-run mode: no orders will be sent.")
                if buy: print("→ Long signal")
                elif sell: print("→ Short signal")
                continue

            price = None
            params = {}

            if buy:
                binance.create_order(symbol, 'market', 'buy', amount, price, params)
                print("✅ Buy order executed")
            elif sell:
                binance.create_order(symbol, 'market', 'sell', amount, price, params)
                print("✅ Sell order executed")

        except Exception as e:
            tb = traceback.format_exc()
            err = f"{symbol} error: {e}\n{tb}"
            print("⚠️", err)
            log_error(err)
            continue


def TheBinanceBotRunner():
    """Main runner — keeps bot alive and restarts automatically on errors."""
    while True:
        try:
            now = datetime.utcnow()
            print(f"🕒 {now.strftime('%H:%M:%S')} - waiting for 5-minute bar close...")
            if now.second > 30 and now.minute % 5 == 4:
                print("⏱ Period close: checking signals...")
                TheBinanceBotCode(dry_run=True, account_type="spot")
                time.sleep(60)
            time.sleep(1)
        except Exception as e:
            tb = traceback.format_exc()
            err = f"Runner error: {e}\n{tb}"
            print("🚨 Critical error. Restarting bot...")
            log_error(err)
            time.sleep(10)  # wait before restart

if __name__ == "__main__":
    TheBinanceBotRunner()
  

From Simple Frameworks to Advanced Multi-Model Systems

This compact example illustrates the fundamental principles behind our multi-model trading systems — modular, exchange-agnostic, and risk-aware. Even though it’s a simplified version, it already shows the key building blocks of a professional automated trading infrastructure.

Our advanced internal systems extend these foundations with layered signal filtering, multi-timeframe validation, and comprehensive trade management — running simultaneously across Spot and Futures environments. They operate with monitoring dashboards, performance tracking, and coordinated decision logic between models.

Possible Enhancements and Next Steps

The example above represents a minimal, educational implementation. In production environments, several enhancements can be introduced to improve resilience, performance, and scalability:

Each of these enhancements is already part of our internal multi-model framework — a coordinated ecosystem capable of running dozens of models across all Binance pairs, sharing signals, managing exposure, and optimizing performance in real time.

➡️ In the next section, we’ll present this multi-strategy coordination layer in detail — how different models interact, how capital is distributed dynamically, and how our dashboards visualize every trade, risk parameter, and trade outcome in a unified environment.

The Role of Backtesting and Model Integration

No trading system should ever go live without extensive backtesting. The equity curve below represents the combined outcome of dozens of independent models, each executed through AmiBroker’s portfolio-level testing environment and controlled programmatically via Python automation scripts. Using this setup, we were able to run multiple large-scale portfolio backtests in sequence — each covering all Binance Futures pairs — and then merge their equity results directly inside AmiBroker using Python integration.

In addition, commission and slippage costs were explicitly incorporated into the backtest execution prices, ensuring that the simulated performance remains fully aligned with live-trading conditions. Every segment, drawdown, and plateau in this equity curve therefore reflects not only model logic, but also realistic execution behavior and transaction costs — delivering a one-to-one correspondence with real trading results.

Portfolio Equity Backtest

As shown above, managing performance degradation is one of the most critical aspects of multi-model systems. While a single strategy may perform well under certain conditions, large-scale portfolios of automated models require active supervision and internal coordination to sustain long-term profitability. This means tracking not only live trades, but also signal drift, execution latency, and slippage behavior across multiple environments.

In production, each model runs independently while sharing a unified capital base. Their individual positions are not stored on Binance but rather tracked in dedicated databases or structured files. This enables our framework to:

Such architecture allows the system to run dozens of strategies simultaneously on a single account without losing transparency or control. It forms the foundation of our ongoing model supervision process — ensuring that every strategy operates within defined risk parameters while contributing positively to the portfolio as a whole.

The examples below illustrate live trading outputs at different update intervals — a 15-minute Positions Report providing real-time exposure tracking, and an hourly Trade Stats report summarizing system-wide performance.

For readers who wish to explore detailed examples, here are a few sample reports — each opens in a new tab:

These tools represent the operational layer of our ecosystem — transforming raw model data into actionable insights. Together with our multi-model trading framework, they form a complete infrastructure for building, testing, executing, and continuously improving automated trading systems across hundreds of markets.