Backtest your Trading Systems with Python — Strategies Development
We’ve seen previously how you can extract data and create the most simple strategy using backtrader (if you’ve missed this story: Backtest your Trading Systems with Python — Introduction). We will now see how to develop complex strategies.
Strategy’s skeleton
Below is the skeleton of any strategy:
import backtrader as btclass MyStrategy(bt.Strategy):
params = (
)
def __init__(self):
pass
def log(self, msg, dt=None):
pass def next(self):
pass
def notify_order(self, order):
pass
def notify_trade(self, trade):
pass- params: strategy’s parameters.
- init: strategy’s constructor, useful for indicator’s initialization.
- log: method you can use to display text.
- next: method executed for each iteration.
- notify_order: method executed when an order is created or updated.
- notify_trade: method executed when a trade is created or updated.
Indicators
Maybe you want to use indicators in your strategies. Gratefully, backtrader has some basic indicators available such as RSI, MACD, EMA, etc… If you want custom indicators you can develop yours, but we’ll see that later.
You need first to import the indicators you want to use, for example, an EMA.
from backtrader.indicators import ExponentialMovingAverage as EMAThen, you can initialize them in your strategy’s constructor:
def __init__(self):
self.ema = EMA(period=10)As you can see, we can specify parameters for indicators.
Then, if we need the value of our ema in the next method of our strategy, we can get it the same way as we get the close price. We want to get the ema line of our ema attribute:
ema_now = self.ema.ema[0]If we want the ema one bar earlier:
ema_earlier = self.ema.ema[-1]For a full indicators reference, check https://www.backtrader.com/docu/indautoref/.
Parameters
It’s useful to parameterize our strategies, either for optimization or just for trying things. We can specify parameters in the params attribute.
class MyStrategy(bt.Strategy):
params = (
('ema_period', 10),
)A parameter is a tuple whose first element is the parameter’s name, and the second element is a default value.
Then we can access our parameter anywhere in our strategy using self.p:
def __init__(self):
self.ema = EMA(period=self.p.ema_period)We specify the value of a parameter when initializing our strategy:
cerebro.addstrategy(MyStrategy, ema_period=10)Rules
To define our strategy’s rules, we use the next method.
def next(self):
if self.datas[0].close[0] < self.ema.ema[0]:
# do somethingOrders
To deal with orders, we first have to initialize an empty list in our strategy’s constructor:
def __init__(self):
self.orders_ref = list()Now, we have to implement notify_order :
def notify_order(self, order):
if not order.alive() and order.ref in self.orders_ref:
self.orders_ref.remove(order.ref)This way, when an order is created or updated, we check if the order is still alive. If he’s not, we remove it.
Then, we have to create orders when our strategy’s signals are triggered. To make things easy, we will begin with just a simple buy order:
def next(self):
if self.datas[0].close[0] < self.ema[0]:
orders = [self.buy()]
self.orders_ref = [order.ref for order in orders if order]
if self.datas[0].close[0] > self.ema[0]:
self.close()We use self.buy() to buy and self.sell() to sell. self.close() closes our orders.
If we want to make things more complex, we can use OCO orders:
orders = self.buy_bracket(price=ACTUAL_PRICE, stopprice=stop_price, limitprice=take_profit_price)
We can also use stop or limit orders:
orders = [self.buy(), self.sell(exectype=bt.Order.Stop, price=stop_price)]
# or
orders = [self.buy(), self.sell(exectype=bt.Order.Limit, price=take_profit_price)]Mixing everything
Now, we can complete our strategy’s skeleton using everything we know:
class MyStrategy(bt.Strategy):
params = (
('ema_period', 10),
)
def __init__(self):
self.ema = EMA(period=self.p.ema_period)
def log(self, msg, dt=None):
print("{} - {}".format(dt or self.datas[0].datetime.date(0), msg))
def next(self):
self.log('{} - {} {} @ {}'.format(self.datas[0].datetime.date(0), self.datas[0].close[0], self.datas[0]._name, self.ema[0]))
if self.datas[0].close[0] < self.ema[0]:
orders = [self.buy()]
self.orders_ref = [order.ref for order in orders if order]
if self.datas[0].close[0] > self.ema[0]:
self.close()
def notify_order(self, order):
self.log('{} - {} {} @ {}'.format(order.data._name, order.size, order.data._name, order.price))
if not order.alive() and order.ref in self.orders_ref:
self.orders_ref.remove(order.ref)
def notify_trade(self, trade):
self.log('{} - {} {} @ {}'.format(trade.dt.date(0), trade.size, trade.data._name, trade.price))And we can run our strategy:
btc_eur = yf.Ticker("BTC-EUR")
data = btc_eur.history()
pandas_data = btfeeds.PandasData(dataname=data)
cerebro.adddata(pandas_data)
cerebro.addstrategy(MyStrategy, ema_period=200)cerebro.run()Your strategy will be backtested and you should see some data getting logged.
Then?
Then, nothing happens because we don’t use any analyzer. We’ll see in the next story how to use them to analyze your strategy’s results. In the meantime, you can add a line for cerebro.plot()after cerebro.run() . It will display your strategy’s chart.
Be sure to follow me so you don’t miss the next story about Backtesting your Trading Systems with Python!
Edit: find the next story here: https://readmedium.com/backtest-your-trading-systems-with-python-analysis-of-the-results-467a82b26ef5
You can also explore the other stories mixing Python and trading here: Improve your Trading with Python
To explore more of my Python stories, click here!
If you liked the story, don’t forget to clap and maybe follow me if you want to explore more of my content :)
You can also subscribe to me via email to be notified every time I publish a new story, just click here!
If you’re not subscribed to medium yet and wish to support me or get access to all my stories, you can use my link:
A Message from InsiderFinance

Thanks for being a part of our community! Before you go:
- 👏 Clap for the story and follow the author 👉
- 📰 View more content in the InsiderFinance Wire
- 📚 Take our FREE Masterclass
- 📈 Discover Powerful Trading Tools





