# Improving Random Python Internet Study Notes

Every now and then, samples with backtrader code pop up in the Internet. There are several in what it looks to me to be Chinese. The latest one is here:

The title is: backtrader-学习笔记2, which apparently (thanks Google) translates to backtrader- study notes 2. If those are study notes, let’s try to improve the code there where it can really be improved and in my personal opinion there where backtrader shines the most.

In the `__init__` method of the strategy inside the study notes we find the following

```def __init__(self):
...
self.ma1 = bt.indicators.SMA(self.datas[0],
period=self.p.period
)
self.ma2 = bt.indicators.SMA(self.datas[1],
period=self.p.period
)
```

Nothing to argue here (style is something very personal, I won’t touch that)

And in the `next` method of the strategy, the following are the logic decisions for buying and selling.

```...
# Not yet ... we MIGHT BUY if ...
if (self.ma1[0]-self.ma1[-1])/self.ma1[-1]>(self.ma2[0]-self.ma2[-1])/self.ma2[-1]:
...
```

and

```...
# Already in the market ... we might sell
if (self.ma1[0]-self.ma1[-1])/self.ma1[-1]<=(self.ma2[0]-self.ma2[-1])/self.ma2[-1]:
...
```

These two logic blocks is what one can actually make a lot more better, which will also add to readability, maintainability and tweaking (if needed be)

Instead of having those comparison of moving averages (current point `0` and previous point `-1`) followed by some divisions, let’s look at how to have it precalculated for us.

Let’s tweak `__init__`

```def __init__(self):
...

# Let's create the moving averages as before
ma1 = bt.ind.SMA(self.data0, period=self.p.period)
ma2 = bt.ind.SMA(self.data1, period=self.p.period)

# Use line delay notation (-x) to get a ref to the -1 point
ma1_pct = ma1 / ma1(-1) - 1.0  # The ma1 percentage part
ma2_pct = ma2 / ma2(-1) - 1.0  # The ma2 percentage part

self.sell_sig = ma1_pct <= ma2_pct  # sell signal
```

And we can now take that to the `next` method and do the following:

```def next(self):
...
# Not yet ... we MIGHT BUY if ...
...

...
# Already in the market ... we might sell
if self.sell_sig:
...
```

Notice that we don’t even have to use `self.buy_sig[0]`, because the boolean test make with `if self.buy_sig` is already translated by the backtrader machinery to a check for `[0]`

Imho, a much cleaner approach in which defining the logic in `__init__` with standard arithmetic and logical operations (and using the line delay notation `(-x)`) makes the code much better.

In any case and for closing note, one could have also tried to use the built-in `PercentChange` indicator (aka `PctChange`)

As the name suggests it does already calculate the percentage change over a given period of bars. The code in `__init__` would now look like this

```def __init__(self):
...

# Let's create the moving averages as before
ma1 = bt.ind.SMA(self.data0, period=self.p.period)
ma2 = bt.ind.SMA(self.data1, period=self.p.period)

ma1_pct = bt.ind.PctChange(ma1, period=1)  # The ma1 percentage part
ma2_pct = bt.ind.PctChange(ma2, period=1)  # The ma2 percentage part