Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Improving Random Python Internet Study Notes

Every now and then, samples withbacktrader code pop up in theInternet. There are several in what it looks to me to be Chinese. The latestone is here:

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

In the__init__ method of the strategy inside the study notes we find thefollowing

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 thenext method of the strategy, the following are the logicdecisions 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 sellif (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, whichwill also add to readability, maintainability and tweaking (if needed be)

Instead of having those comparison of moving averages (current point0 andprevious point-1) followed by some divisions, let’s look at how to have itprecalculated 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.buy_sig = ma1_pct > ma2_pct  # buy signal    self.sell_sig = ma1_pct <= ma2_pct  # sell signal

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

def next(self):    ...    # Not yet ... we MIGHT BUY if ...    if self.buy_sig:    ...    ...    # Already in the market ... we might sell    if self.sell_sig:    ...

Notice that we don’t even have to useself.buy_sig[0], because the booleantest make withif self.buy_sig is already translated by thebacktradermachinery to a check for[0]

Imho, a much cleaner approach in which defining the logic in__init__ withstandard 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-inPercentChange indicator (akaPctChange)

See:backtrader documentation - Indicator Reference

As the name suggests it does already calculate the percentage change over agiven 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    self.buy_sig = ma1_pct > ma2_pct  # buy signal    self.sell_sig = ma1_pct <= ma2_pct  # sell signal

It doesn’t make much of a difference in this case, but it may for sure save youfrom lots of trouble if the calculations are larger and more complex.

Happybacktrading!


[8]ページ先頭

©2009-2025 Movatter.jp