Skip to content
All library documents

Backtesting an ETHUSDT EMA Crossover on Binance Trade Ticks

Code NautilusTrader

Summary

This example shows how to set up a crypto strategy backtest using Binance ETHUSDT trade ticks. It loads trade data from a CSV, registers the instrument and a cash account, and configures a maker taker fee model with equal stated rates. The example strategy is an EMA crossover with fast and slow periods of 10 and 20, operating on internally aggregated 250 tick bars and using a trade size of 0.10 ETH.

After the engine runs, it prints account, order fill, and position reports, then resets and disposes of the engine. The document demonstrates backtest wiring and the choice of tick based bars, but it does not define the crossover signal itself, report results, or discuss data quality, slippage, or parameter selection. It is therefore a reproducible setup example rather than evidence that the strategy is profitable or robust.

Key ideas

  • The example backtests an ETHUSDT strategy using Binance trade tick data.
  • Trade ticks are aggregated into 250 tick bars for the strategy.
  • The EMA crossover configuration uses fast and slow periods of 10 and 20.
  • The simulated account is cash based and includes a stated maker taker fee model.
  • The script prints account, fill, and position reports, but provides no performance findings.

Tags

Full text
# crypto_ema_cross_ethusdt_trade_ticks.py


```py
#!/usr/bin/env python3
# -------------------------------------------------------------------------------------------------
#  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
#  https://nautechsystems.io
#
#  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
#  You may not use this file except in compliance with the License.
#  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
# -------------------------------------------------------------------------------------------------
"""
Example of crypto ema cross ethusdt trade ticks.
"""

import sys
from decimal import Decimal
from pathlib import Path

import pandas as pd

from nautilus_trader.adapters.binance import BINANCE_VENUE
from nautilus_trader.backtest import BacktestEngine
from nautilus_trader.config import BacktestEngineConfig
from nautilus_trader.config import RiskEngineConfig
from nautilus_trader.execution import MakerTakerFeeModel
from nautilus_trader.model import AccountType
from nautilus_trader.model import BarType
from nautilus_trader.model import Currency
from nautilus_trader.model import Money
from nautilus_trader.model import OmsType
from nautilus_trader.model import TraderId
from nautilus_trader.testkit.providers import TestDataProvider
from nautilus_trader.testkit.providers import TestInstrumentProvider


sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "docs" / "tutorials"))

from ema_cross import EMACross
from ema_cross import EMACrossConfig


if __name__ == "__main__":
    engine = BacktestEngine(
        BacktestEngineConfig(
            trader_id=TraderId.from_str("BACKTESTER-001"),
            risk_engine=RiskEngineConfig(bypass=True),
        ),
    )

    ETH = Currency.from_str("ETH")
    USDT = Currency.from_str("USDT")
    engine.add_venue(
        venue=BINANCE_VENUE,
        oms_type=OmsType.NETTING,
        account_type=AccountType.CASH,
        base_currency=None,
        starting_balances=[Money(1_000_000, USDT), Money(10, ETH)],
        fee_model=MakerTakerFeeModel(
            maker_rate=Decimal("0.0001"),
            taker_rate=Decimal("0.0001"),
        ),
    )

    ETHUSDT_BINANCE = TestInstrumentProvider.ethusdt_binance()
    engine.add_instrument(ETHUSDT_BINANCE)

    ticks = TestDataProvider.trades_from_binance_csv(
        instrument=ETHUSDT_BINANCE,
        csv_name="binance/ethusdt-trades.csv",
    )
    engine.add_data(ticks)

    strategy = EMACross(
        EMACrossConfig(
            instrument_id=ETHUSDT_BINANCE.id,
            bar_type=BarType.from_str("ETHUSDT.BINANCE-250-TICK-LAST-INTERNAL"),
            trade_size=Decimal("0.10"),
            fast_ema_period=10,
            slow_ema_period=20,
        ),
    )
    engine.add_strategy(strategy)
    engine.run()

    with pd.option_context(
        "display.max_rows",
        100,
        "display.max_columns",
        None,
        "display.width",
        300,
    ):
        print(engine.generate_account_report(BINANCE_VENUE))
        print(engine.generate_order_fills_report())
        print(engine.generate_positions_report())

    engine.reset()
    engine.dispose()

```

Shown in full with attribution under the source's licence. Licence: LGPL-3.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.