Getting Started =============== Coin-test is a backtesting library designed for cryptocurrency trading. It supports trading strategies across multiple currencies and advanced configurations of tests, including cron-based scheduled execution of strategies, synthetic data generation, slippage modeling, and trading fees. View `example analysis HTML report `_ Quick Start ----------- Coin-test runs on Python 3.10 or higher. Install the package via pip: .. code-block:: pip3 install coin-test To run a backtest, import the coin-test library. Then define your data source, strategy, and test settings to run the analysis. .. code-block:: python import datetime as dt import coin_test import pandas as pd from coin_test.backtest import Portfolio, Strategy, MarketTradeRequest from coin_test.data import BinanceDataset, FillProcessor, GarchDatasetGenerator from coin_test.util import AssetPair, Money, Side Then, define the assets to trade and your starting portfolio. .. code-block:: python # Define assets traded and an initial portfolio eth, usdt = eth_usdt = AssetPair.from_str("ETH", "USDT") portfolio = Portfolio(base_currency=usdt, assets={eth: Money(eth, 0), usdt: Money(usdt, 10000)}) Next, import daily historical data from Binance for the backtest and fill gaps. .. code-block:: python # Download the last 150 days of data freq ='d' dataset = BinanceDataset("ETH/USDT Daily Data", eth_usdt, freq=freq, start=dt.datetime.today()-dt.timedelta(days=150)) dataset.process([FillProcessor(freq)]) Now we wish to generate synthetic data to allow backtesting on a variety of future market conditions. The existing data is split into a train/test split and then fed to a GARCH statistical model to generate new data. .. code-block:: python # Split the data into train test split train, test = dataset.split(percent=0.75) # Generate 30 synthetic datasets 90 days long and package them for backtesting datasets = GarchDatasetGenerator(train).generate(timedelta=pd.Timedelta(days=90), n=30) datasets = [[d] for d in datasets] # Package the datasets for backtesting To implement a custom strategy, extend the ``Strategy`` class. Each strategy should have * a schedule, which is a cron string representing when this strategy is run * a lookback, which is how much data is accessed in the strategy * a ``__call__`` method, which returns a list of TradeRequest objects representing trades the strategy wants to make. A code example for implementing ``MACD_discrete_days`` strategy is shown below. .. code-block:: python class MACD_discrete_days(Strategy): def __init__(self, asset_pair) -> None: """Initialize a MACD object. This strategy uses a 26, 12, 9 standard EMACD calculation to generate buy sell signals. Made to be used with Hour data""" super().__init__( name="MACD_Discrete_day", asset_pairs=[asset_pair], schedule="0 9 * * *", lookback=dt.timedelta(days=26), ) self.perc = .98 self.invested = False def __call__(self, time, portfolio, lookback_data): """Execute strategy.""" asset_ticker, base_ticker = asset_pair = self.asset_pairs[0] data = lookback_data[asset_pair]["Close"] macd, signal, fast_ma, slow_ma = macd_indicator(data, 12, 26, 9) if signal < macd and not self.invested: self.invested =True return [MarketTradeRequest( asset_pair, Side.BUY, notional=portfolio.available_assets(base_ticker).qty * self.perc, )] elif signal > macd and self.invested: self.invested = False return [MarketTradeRequest( asset_pair, Side.SELL, qty=portfolio.available_assets(asset_ticker).qty * self.perc, )] else: return [] To run the backtest, create a portfolio with starting values of assets and call the ``run`` method. This package supports testing multiple strategies at once. See our `user guide in docs `_ for more advanced features and customization options. .. code-block:: python # Package the strategies before backtesting strategies = [[MACD_discrete_days(eth_usdt)]] # Run the backtest and generate the report results = coin_test.run(datasets, strategies, portfolio, backtest_length=pd.Timedelta(days=90), n_parallel=8) `Check out the report generated by this example! `_