Getting Started

This guide will help you get started with backtesting trading strategies using QTrade.

Strategy

Let’s create a simple SMA strategy to backtest. Our custome strategy need inherit from qtrade.Strategy and implement init() and next() method

from qtrade.backtest import Strategy

class SMAStrategy(Strategy):

    def init(self):
        return super().init()

    def on_bar_close(self):
        if self.data.SMA3[-2] < self.data.SMA10[-2] and \
            self.data.SMA3[-1] > self.data.SMA10[-1]:
            self.buy()
        if self.data.SMA10[-2] > self.data.SMA10[-2] and \
            self.data.SMA10[-1] < self.data.SMA10[-1]:
            self.close()

Data

For simplicity, the QTrade library does not provide a data processing component. Users need to prepare OHLC data as a pandas.DataFrame with the required columns: Open, High, Low, Close, and optionally Volume. The dataframe should also include any indicators that will be used.

In this guide, we’ll use yfinance to obtain the data:

$ pip install yfinance
import yfinance as yf

# Download gold data with daily intervals
data = yf.download(
    "GC=F", 
    start="2023-01-01", 
    end="2024-01-01", 
    interval="1d", 
    multi_level_index=False
)
data['SMA3'] = data['Close'].rolling(3).mean()
data['SMA10'] = data['Close'].rolling(10).mean()

Backtest

Now let’s backtest our stratgy on prepared data.


from qtrade.backtest import Backtest

bt = Backtest(
    data=data,
    strategy_class=SMAStrategy,
    cash=10000,
)
bt.run()

# Show backtest results
bt.show_stats()
Start                         : 2023-01-03 00:00:00
End                           : 2023-12-29 00:00:00
Duration                      : 360 days 00:00:00
Start Value                   : 5000.0
End Value                     : 5504.3994140625
Total Return [%]              : 10.08798828125
Total Commission Cost[%]      : 0
Buy & Hold Return [%]         : 12.10523221626531
Return (Ann.) [%]             : 18.074280342264217
Volatility (Ann.) [%]         : 7.44
Max Drawdown [%]              : -3.8180767955781354
Max Drawdown Duration         : 186 days 00:00:00
Total Trades                  : 14
Win Rate [%]                  : 42.857142857142854
Best Trade [%]                : 239.0
Worst Trade [%]               : -58.0
Avg Winning Trade [%]         : 126.69986979166667
Avg Losing Trade [%]          : -31.9749755859375
Avg Winning Trade Duration    : 21 days 00:00:00
Avg Losing Trade Duration     : 4 days 15:00:00
Profit Factor                 : 2.9718522251363866
Expectancy                    : 36.028529575892854
Sharpe Ratio                  : 2.271145457445316
Sortino Ratio                 : 2.6654676881799224
Calmar Ratio                  : 4.733870299098423
Omega Ratio                   : 1.7873724100138564

Plot

Qtrade uses Bokeh to plot result charts. You can generate a plot of your backtest results with the following command:

bt.plot()

Trades

You can also check all trades by using the following commands:

trade_details = bt.get_trade_history()
print(trade_details)
    Type  Size  Entry Price   Exit Price Entry Time  Exit Date      Profit   Tag Exit Reason Duration
0   Long   2.0  1833.500000  1812.699951 2023-03-02 2023-03-08  -41.600098  None      signal   6 days
1   Long   2.0  1862.000000  2007.400024 2023-03-10 2023-04-18  290.800049  None      signal  39 days
2   Long   2.0  2014.300049  2014.500000 2023-05-02 2023-05-12    0.399902  None      signal  10 days
3   Long   2.0  1978.000000  1965.500000 2023-06-01 2023-06-06  -25.000000  None      signal   5 days
4   Long   2.0  1963.599976  1962.199951 2023-06-08 2023-06-09   -2.800049  None      signal   1 days
5   Long   2.0  1955.300049  1944.599976 2023-06-12 2023-06-13  -21.400146  None      signal   1 days
6   Long   2.0  1958.400024  1935.500000 2023-06-16 2023-06-20  -45.800049  None      signal   4 days
7   Long   2.0  1919.599976  1962.099976 2023-07-05 2023-07-25   85.000000  None      signal  20 days
8   Long   2.0  1918.500000  1917.500000 2023-08-23 2023-09-07   -2.000000  None      signal  15 days
9   Long   2.0  1931.500000  1916.599976 2023-09-18 2023-09-25  -29.800049  None      signal   7 days
10  Long   2.0  1861.000000  1985.599976 2023-10-10 2023-11-02  249.199951  None      signal  23 days
11  Long   2.0  1991.500000  1966.800049 2023-11-03 2023-11-07  -49.399902  None      signal   4 days
12  Long   2.0  1983.900024  2030.500000 2023-11-16 2023-12-06   93.199951  None      signal  20 days
13  Long   2.0  2021.099976  2062.399902 2023-12-15 2023-12-29   82.599854  None         end  14 days