0

i'm trying to convert this strategy from pinescript to python but im getting enormous output value when i backtest it, someone can find if there's something wrong? thank tou

class WaveTrendStrategy(bt.Strategy):
    
    def __init__(self) :
        n1 = 21
        n2 = 14
        obLevel1 = 60
        obLevel1 = 60
        obLevel2 = 53
        osLevel1 = -60
        osLevel2 = -53
        hlc3 = (self.data.high+self.data.low+self.data.close)/3
        ap = hlc3 
        esa = bt.ind.EMA(ap,period=n1)
        d = bt.ind.EMA(abs(ap - esa), period=n1)
        ci = (ap - esa) / (0.015 * d)
        tci = bt.ind.EMA(ci, period=n2)
        wt1 = tci
        wt2 = bt.ind.SMA(wt1,period=4)
        self.longCondition  = bt.ind.CrossUp(wt2,osLevel2)
        self.shortCondition = bt.ind.CrossDown(wt2,obLevel2)
        
        
    def next(self):
        if self.longCondition:
                self.buy()
        
        elif self.shortCondition:
            self.sell()
run-out
  • 3,114
  • 1
  • 9
  • 25
  • Try some of the approaches in the [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) article? – Jiří Baum May 14 '21 at 13:16
  • BTW, we can't debug the code, because we don't know what's in `bt.Strategy` and we don't know what was in the pine script strategy. As it is, it looks like `self.data` should give an error (it's not defined at that point), unless the rest of the program does things to define it. – Jiří Baum May 14 '21 at 13:20
  • The backtrader code looks fine at least programatically. Give the value expected, and what you are getting, otherwise very difficult for the people to help. Moreover it majorly depends on the input dataset, there might be a real huge open position that lead to enormous amounts – Siva Kumar Sunku May 14 '21 at 13:33

1 Answers1

0

I'm not sure why you are having problems. I've copied your code and it's running fine. Perhaps your data feed has someting wrong?

The only thing I added in was assuming you wanted to go long AND short. Your current code goes either long to flat, or short to flat. I've added in a close trade before the short/long trades.

if self.getposition().size != 0:
                self.close()

Here's your code just added to my shell. Have a look and run this. It works of yfinance so will go around any data issues. Let us know if you still have problems.

import datetime
import backtrader as bt

class WaveTrendStrategy(bt.Strategy):

    def log(self, txt, dt=None):
        """ Logging function fot this strategy"""
        dt = dt or self.data.datetime[0]
        if isinstance(dt, float):
            dt = bt.num2date(dt)
        print("%s, %s" % (dt.date(), txt))

    def print_signal(self):
        self.log(
            f"o {self.datas[0].open[0]:7.2f} "
            f"h {self.datas[0].high[0]:7.2f} "
            f"l {self.datas[0].low[0]:7.2f} "
            f"c {self.datas[0].close[0]:7.2f} "
            f"v {self.datas[0].volume[0]:7.0f} "
            # f"rsi {self.rsi[0]:5.0f}"
        )

    def notify_order(self, order):
        """ Triggered upon changes to orders. """

        # Suppress notification if it is just a submitted order.
        if order.status == order.Submitted:
            return

        # Print out the date, security name, order number and status.
        dt, dn = self.datetime.date(), order.data._name
        type = "Buy" if order.isbuy() else "Sell"
        self.log(
            f"{order.data._name:<6} Order: {order.ref:3d}\tType: {type:<5}\tStatus"
            f" {order.getstatusname():<8} \t"
            f"Size: {order.created.size:9.4f} Price: {order.created.price:9.4f} "
            f"Position: {self.getposition(order.data).size}"
        )
        if order.status == order.Margin:
            return

        # Check if an order has been completed
        if order.status in [order.Completed]:
            self.log(
                f"{order.data._name:<6} {('BUY' if order.isbuy() else 'SELL'):<5} "
                # f"EXECUTED for: {dn} "
                f"Price: {order.executed.price:6.2f} "
                f"Cost: {order.executed.value:6.2f} "
                f"Comm: {order.executed.comm:4.2f} "
                f"Size: {order.created.size:9.4f} "
            )

    def notify_trade(self, trade):
        """Provides notification of closed trades."""
        if trade.isclosed:
            self.log(
                "{} Closed: PnL Gross {}, Net {},".format(
                    trade.data._name,
                    round(trade.pnl, 2),
                    round(trade.pnlcomm, 1),
                )
            )

    def __init__(self):
        n1 = 21
        n2 = 14
        obLevel1 = 60
        obLevel1 = 60
        obLevel2 = 53
        osLevel1 = -60
        osLevel2 = -53
        hlc3 = (self.data.high + self.data.low + self.data.close) / 3
        ap = hlc3
        esa = bt.ind.EMA(ap, period=n1)
        d = bt.ind.EMA(abs(ap - esa), period=n1)
        ci = (ap - esa) / (0.015 * d)
        tci = bt.ind.EMA(ci, period=n2)
        wt1 = tci
        wt2 = bt.ind.SMA(wt1, period=4)
        self.longCondition = bt.ind.CrossUp(wt2, osLevel2)
        self.shortCondition = bt.ind.CrossDown(wt2, obLevel2)

    def next(self):
        # Print OHLCV
        self.print_signal()

        if self.longCondition:
            if self.getposition().size != 0:
                self.close()
            self.buy()

        elif self.shortCondition:
            if self.getposition().size != 0:
                self.close()
            self.sell()



if __name__ == "__main__":

    cerebro = bt.Cerebro()

    data = bt.feeds.YahooFinanceData(
        dataname="FB",
        timeframe=bt.TimeFrame.Days,
        fromdate=datetime.datetime(2018, 1, 1),
        todate=datetime.datetime(2021, 4, 1),
        reverse=False,
    )

    cerebro.adddata(data, name="FB")

    cerebro.addstrategy(WaveTrendStrategy)

    # Execute
    cerebro.run()
    print(f"Final Value: {cerebro.broker.getvalue():5.2f}")

    cerebro.plot()

run-out
  • 3,114
  • 1
  • 9
  • 25