For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Problem with crossovers



  • I have an EMA set to 8 periods and another at 21 periods. I have setup a log that records the date at which the crossovers happened.

    The issue is sometimes it gives the correct date of crossover and sometimes it give a wrong date (off by one day). Can this be rectified?? Or is there a way to get the correct date of crossover??

    Help will be appreciated.



  • Can you please provide your logging code? Thanks.



  • Please provide script and outputs confirming behavior described.



  • @run-out same time :)



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


  • That's just the log to print. Where to you capture the crossover and send it to the log?



  • This is the entire next function that I have in place.
    I save the date of the crossovers in the crossovers list.
    Then I compare the dates stored in the crossovers list with the plot and some dates stored are on point but some dates gets registered as a crossover at the date of next candlestick.

        def next(self):
            self.index.append(bt.num2date(self.data.datetime[0]).date())
            self.equity.append(cerebro.broker.getvalue())
            self.print_signal()
            if self.altering_params['entry_condition'] == 'Open':
                # price_array = self.data.Open
                price_array = self.datas[0].open
            elif self.altering_params['entry_condition'] == 'High':
                # price_array = self.data.High
                price_array = self.datas[0].high
            elif self.altering_params['entry_condition'] == 'Low':
                # price_array = self.data.Low
                price_array = self.datas[0].low
            elif self.altering_params['entry_condition'] == 'Close':
                # price_array = self.data.Close
                price_array = self.datas[0].close
    
            try:
                self.recentLow = min(self.data.low.get(size=self.LookBack+1)[:self.LookBack])
                self.lows.append(self.recentLow)
                self.recentHigh = max(self.data.high.get(size=self.LookBack+1)[:self.LookBack])
                self.highs.append(self.recentHigh)
    
            except Exception as e:
                print(e)
    
            if cerebro.broker.getvalue() < self.maintanance_margin:
                pass
            # pending opening orders do nothing
            # if len(self.o_li) > 0:
            #     return
            if self.crossover == 1:
                if self.buy_sell_request_made and exit_at_crossover:
                    self.close()
                price = price_array[0]
                for low in self.lows[::-1]:
                    if price > low:
                        stop_loss = low
                        break
                print("------------------------------")
                print(" FAST MA CROSSES OVER SLOW MA ")
                print("------------------------------")
                self.crossovers.append(self.datetime.date())
                take_profit = price + self.altering_params['pips_profit_loss']/10000
                # for order in self.pending_orders:
                #     self.cancel(order)
                # self.pending_orders = []
                if not exit_at_crossover:
                    self.long_buy_order = self.buy_bracket(
                        exectype=bt.Order.Stop,
                        price=price,
                        stopprice=stop_loss,
                        stopexec=bt.Order.Stop,
                        limitprice=take_profit,
                        limitexec=bt.Order.Limit)
                else:
                    self.long_buy_order = self.buy(
                        exectype=bt.Order.Stop,
                        price=price)
                self.buy_sell_request_made = True
                if isinstance(self.long_buy_order,list):
                    self.pending_orders = self.pending_orders + self.long_buy_order
                    self.log(
                        "LONG BUY at market {}: Oref {} / Buy at {} / Stop loss at {} / Take Profit at {}".format(
                            self.datetime.date(),
                            self.long_buy_order[0].ref,
                            price,
                            stop_loss,
                            take_profit
                        ))
                else:
                    self.pending_orders.append(self.long_buy_order)
                    self.log(
                    "LONG BUY at market {}: Oref {} / Buy at {} / Stop loss at {} / Take Profit at {}".format(
                        self.datetime.date(),
                        self.long_buy_order.ref,
                        price,
                        stop_loss,
                        take_profit
                    ))
                # Store orders in a list
    
            else:
                pass
    
            if self.crossover == -1:
                if self.buy_sell_request_made and exit_at_crossover:
                    self.close()
                price = price_array[0]
                # price = self.data.Close[-1]
                for high in self.highs[::-1]:
                    if price < high:
                        stop_loss = high
                        break
                print("------------------------------")
                print(" SLOW MA CROSSES OVER FAST MA ")
                print("------------------------------")
                self.crossovers.append(self.datetime.date())
                take_profit = price - self.altering_params['pips_profit_loss']/10000
                # for order in self.pending_orders:
                #     self.cancel(order)
                # self.pending_orders = []
                if not exit_at_crossover:
                    self.short_sell_order = self.sell_bracket(
                        exectype=bt.Order.Stop,
                        price=price,
                        stopprice=stop_loss,
                        stopexec=bt.Order.Stop,
                        limitprice=take_profit,
                        limitexec=bt.Order.Limit
                    )
                else:
                    self.short_sell_order = self.sell(
                        exectype=bt.Order.Stop,
                        price=price
                    )
                if isinstance(self.short_sell_order,list):
                    self.pending_orders = self.pending_orders + self.short_sell_order
                    self.log(
                        "SHORT SELL at market {}: Oref {} / Sell at {} / Stop Loss at {} / Take Profit at {}".format(
                            self.datetime.date(),
                            self.short_sell_order[0].ref,
                            price,
                            stop_loss,
                            take_profit
                        )
                    )
                else:
                    self.pending_orders.append(self.short_sell_order)
                    self.log(
                        "SHORT SELL at market {}: Oref {} / Sell at {} / Stop Loss at {} / Take Profit at {}".format(
                            self.datetime.date(),
                            self.short_sell_order.ref,
                            price,
                            stop_loss,
                            take_profit
                        )
                    )
                self.trades_occured = True
    
                # Store orders in a list
    
            else:
                pass
    

    I might sound foolish but I have a theory to what might be happening.

    I think the crossover in backtrader works like this - if the crossover has occurred at or before the horizontal center of the candlestick then the date is right on point , but if the crossover has occurred after the horizontal center and before the end of a particular candlestick then it considers the next date as the Crossover date.



  • Thank you for posting the extra code. Could you also post the self.crossover creation you made? Thanks.



  • [datetime.date(1991, 10, 30), datetime.date(1992, 1, 15), datetime.date(1992, 2, 5), datetime.date(1992, 2, 11), datetime.date(1992, 3, 30), datetime.date(1992, 4, 15), datetime.date(1992, 5, 4), datetime.date(1992, 9, 13), datetime.date(1992, 9, 29), datetime.date(1992, 10, 8), datetime.date(1992, 12, 13), datetime.date(1993, 1, 3), datetime.date(1993, 1, 24), datetime.date(1993, 1, 31), datetime.date(1993, 2, 23), datetime.date(1993, 2, 24), datetime.date(1993, 3, 22), datetime.date(1993, 5, 11), datetime.date(1993, 5, 30), datetime.date(1993, 6, 3), datetime.date(1993, 8, 8), datetime.date(1993, 8, 9), datetime.date(1993, 8, 15), datetime.date(1993, 10, 18), datetime.date(1994, 2, 15), datetime.date(1994, 4, 5), datetime.date(1994, 4, 20), datetime.date(1994, 6, 6), datetime.date(1994, 6, 12), datetime.date(1994, 7, 27), datetime.date(1994, 8, 10), datetime.date(1994, 8, 29), datetime.date(1994, 9, 4), datetime.date(1994, 11, 9), datetime.date(1995, 1, 8), datetime.date(1995, 5, 10), datetime.date(1995, 5, 28), datetime.date(1995, 6, 5), datetime.date(1995, 6, 8), datetime.date(1995, 7, 11), datetime.date(1995, 7, 12), datetime.date(1995, 7, 16), datetime.date(1995, 7, 18), datetime.date(1995, 8, 3), datetime.date(1995, 9, 20), datetime.date(1995, 11, 12), datetime.date(1995, 11, 13), datetime.date(1995, 11, 26), datetime.date(1996, 2, 15), datetime.date(1996, 3, 3), datetime.date(1996, 6, 12), datetime.date(1996, 9, 5), datetime.date(1996, 10, 27), datetime.date(1996, 11, 26), datetime.date(1997, 3, 26), datetime.date(1997, 4, 6), datetime.date(1997, 5, 8), datetime.date(1997, 6, 1), datetime.date(1997, 8, 24), datetime.date(1997, 10, 21), datetime.date(1997, 10, 26), datetime.date(1997, 11, 24), datetime.date(1998, 1, 26), datetime.date(1998, 1, 28), datetime.date(1998, 2, 4), datetime.date(1998, 2, 5), datetime.date(1998, 2, 23), datetime.date(1998, 2, 24), datetime.date(1998, 3, 3), datetime.date(1998, 3, 30), datetime.date(1998, 4, 8), datetime.date(1998, 6, 9), datetime.date(1998, 7, 15), datetime.date(1998, 8, 13), datetime.date(1998, 8, 27), datetime.date(1998, 10, 29), datetime.date(1998, 12, 7), datetime.date(1999, 1, 8), datetime.date(1999, 5, 7), datetime.date(1999, 5, 14), datetime.date(1999, 7, 21), datetime.date(1999, 8, 18), datetime.date(1999, 8, 19), datetime.date(1999, 8, 23), datetime.date(1999, 9, 2), datetime.date(1999, 9, 10), datetime.date(1999, 9, 29), datetime.date(1999, 10, 27), datetime.date(2000, 1, 3), datetime.date(2000, 1, 17), datetime.date(2000, 2, 22), datetime.date(2000, 2, 25), datetime.date(2000, 3, 26), datetime.date(2000, 3, 28), datetime.date(2000, 5, 26), datetime.date(2000, 6, 25), datetime.date(2000, 6, 29), datetime.date(2000, 7, 13), datetime.date(2000, 9, 27), datetime.date(2000, 10, 6), datetime.date(2000, 11, 3), datetime.date(2000, 11, 17), datetime.date(2000, 11, 30), datetime.date(2001, 1, 24), datetime.date(2001, 2, 4), datetime.date(2001, 2, 7), datetime.date(2001, 3, 2), datetime.date(2001, 3, 14), datetime.date(2001, 4, 22), datetime.date(2001, 4, 30), datetime.date(2001, 6, 26), datetime.date(2001, 6, 28), datetime.date(2001, 7, 15), datetime.date(2001, 9, 5), datetime.date(2001, 9, 11), datetime.date(2001, 10, 11), datetime.date(2001, 12, 2), datetime.date(2001, 12, 24), datetime.date(2002, 1, 2), datetime.date(2002, 1, 15), datetime.date(2002, 2, 19), datetime.date(2002, 2, 20), datetime.date(2002, 2, 24), datetime.date(2002, 2, 25), datetime.date(2002, 3, 7), datetime.date(2002, 3, 28), datetime.date(2002, 4, 3), datetime.date(2002, 7, 30), datetime.date(2002, 8, 30), datetime.date(2002, 9, 10), datetime.date(2002, 9, 24), datetime.date(2002, 9, 25), datetime.date(2002, 9, 29), datetime.date(2002, 10, 17), datetime.date(2002, 10, 30), datetime.date(2002, 11, 25), datetime.date(2002, 12, 6), datetime.date(2003, 3, 17), datetime.date(2003, 3, 31), datetime.date(2003, 4, 6), datetime.date(2003, 4, 14), datetime.date(2003, 6, 22), datetime.date(2003, 7, 25), datetime.date(2003, 7, 31), datetime.date(2003, 9, 9), datetime.date(2003, 10, 31), datetime.date(2003, 11, 14), datetime.date(2004, 1, 19), datetime.date(2004, 1, 21), datetime.date(2004, 1, 26), datetime.date(2004, 1, 27), datetime.date(2004, 1, 28), datetime.date(2004, 2, 6), datetime.date(2004, 2, 23), datetime.date(2004, 5, 5), datetime.date(2004, 5, 9), datetime.date(2004, 5, 21), datetime.date(2004, 6, 13), datetime.date(2004, 6, 24), datetime.date(2004, 7, 23), datetime.date(2004, 8, 9), datetime.date(2004, 8, 24), datetime.date(2004, 9, 10), datetime.date(2005, 1, 6), datetime.date(2005, 2, 18), datetime.date(2005, 3, 22), datetime.date(2005, 4, 20), datetime.date(2005, 4, 28), datetime.date(2005, 7, 20), datetime.date(2005, 7, 26), datetime.date(2005, 7, 28), datetime.date(2005, 8, 21), datetime.date(2005, 8, 26), datetime.date(2005, 8, 30), datetime.date(2005, 8, 31), datetime.date(2005, 9, 14), datetime.date(2005, 10, 27), datetime.date(2005, 10, 31), datetime.date(2005, 12, 12), datetime.date(2005, 12, 28), datetime.date(2006, 1, 3), datetime.date(2006, 2, 3), datetime.date(2006, 3, 3), datetime.date(2006, 3, 9), datetime.date(2006, 3, 14), datetime.date(2006, 6, 9), datetime.date(2006, 7, 2), datetime.date(2006, 7, 16), datetime.date(2006, 7, 28), datetime.date(2006, 9, 8), datetime.date(2006, 9, 24), datetime.date(2006, 9, 26), datetime.date(2006, 10, 27), datetime.date(2006, 12, 26), datetime.date(2006, 12, 29), datetime.date(2007, 1, 5), datetime.date(2007, 2, 8), datetime.date(2007, 5, 10), datetime.date(2007, 5, 15), datetime.date(2007, 5, 16), datetime.date(2007, 6, 24), datetime.date(2007, 8, 1), datetime.date(2007, 8, 3), datetime.date(2007, 8, 12), datetime.date(2007, 8, 29), datetime.date(2007, 12, 7), datetime.date(2007, 12, 12), datetime.date(2007, 12, 13), datetime.date(2007, 12, 30), datetime.date(2008, 1, 21), datetime.date(2008, 1, 25), datetime.date(2008, 2, 7), datetime.date(2008, 2, 19), datetime.date(2008, 4, 27), datetime.date(2008, 5, 21), datetime.date(2008, 6, 1), datetime.date(2008, 6, 8), datetime.date(2008, 6, 10), datetime.date(2008, 6, 25), datetime.date(2008, 7, 25), datetime.date(2008, 9, 22), datetime.date(2008, 9, 30), datetime.date(2008, 11, 26), datetime.date(2008, 11, 30), datetime.date(2008, 12, 8), datetime.date(2009, 1, 9), datetime.date(2009, 3, 12), datetime.date(2009, 4, 12), datetime.date(2009, 4, 13), datetime.date(2009, 4, 15), datetime.date(2009, 5, 1), datetime.date(2009, 6, 18), datetime.date(2009, 6, 19), datetime.date(2009, 6, 22), datetime.date(2009, 6, 23), datetime.date(2009, 7, 7), datetime.date(2009, 7, 15), datetime.date(2009, 8, 17), datetime.date(2009, 8, 20), datetime.date(2009, 11, 1), datetime.date(2009, 11, 6), datetime.date(2009, 12, 7), datetime.date(2010, 1, 14), datetime.date(2010, 1, 15), datetime.date(2010, 3, 12), datetime.date(2010, 3, 19), datetime.date(2010, 4, 12), datetime.date(2010, 4, 20), datetime.date(2010, 6, 18), datetime.date(2010, 6, 30), datetime.date(2010, 7, 1), datetime.date(2010, 8, 13), datetime.date(2010, 9, 5), datetime.date(2010, 9, 7), datetime.date(2010, 9, 14), datetime.date(2010, 11, 10), datetime.date(2010, 12, 31), datetime.date(2011, 1, 6), datetime.date(2011, 1, 14), datetime.date(2011, 2, 15), datetime.date(2011, 2, 17), datetime.date(2011, 5, 9), datetime.date(2011, 6, 1), datetime.date(2011, 6, 15), datetime.date(2011, 6, 30), datetime.date(2011, 7, 8), datetime.date(2011, 7, 24), datetime.date(2011, 8, 2), datetime.date(2011, 8, 3), datetime.date(2011, 8, 4), datetime.date(2011, 8, 15), datetime.date(2011, 9, 2), datetime.date(2011, 10, 13), datetime.date(2011, 11, 7), datetime.date(2011, 11, 8), datetime.date(2011, 11, 9), datetime.date(2012, 1, 23), datetime.date(2012, 3, 6), datetime.date(2012, 3, 22), datetime.date(2012, 4, 5), datetime.date(2012, 4, 24), datetime.date(2012, 5, 4), datetime.date(2012, 6, 17), datetime.date(2012, 6, 24), datetime.date(2012, 7, 3), datetime.date(2012, 7, 4), datetime.date(2012, 8, 5), datetime.date(2012, 10, 28), datetime.date(2012, 11, 23), datetime.date(2013, 1, 6), datetime.date(2013, 1, 10), datetime.date(2013, 2, 14), datetime.date(2013, 4, 8), datetime.date(2013, 5, 12), datetime.date(2013, 6, 2), datetime.date(2013, 6, 25), datetime.date(2013, 7, 16), datetime.date(2013, 8, 30), datetime.date(2013, 9, 13), datetime.date(2013, 11, 3), datetime.date(2013, 11, 26), datetime.date(2014, 1, 5), datetime.date(2014, 1, 26), datetime.date(2014, 1, 30), datetime.date(2014, 2, 11), datetime.date(2014, 3, 27), datetime.date(2014, 4, 10), datetime.date(2014, 5, 11), datetime.date(2014, 6, 27), datetime.date(2014, 7, 7), datetime.date(2014, 7, 9), datetime.date(2014, 7, 10), datetime.date(2014, 10, 19), datetime.date(2014, 10, 22), datetime.date(2014, 12, 16), datetime.date(2014, 12, 17), datetime.date(2015, 4, 5), datetime.date(2015, 4, 8), datetime.date(2015, 4, 24), datetime.date(2015, 5, 24), datetime.date(2015, 6, 4), datetime.date(2015, 6, 28), datetime.date(2015, 8, 11), datetime.date(2015, 9, 7), datetime.date(2015, 9, 9), datetime.date(2015, 9, 22), datetime.date(2015, 10, 8), datetime.date(2015, 10, 22), datetime.date(2015, 12, 4), datetime.date(2016, 1, 4), datetime.date(2016, 1, 10), datetime.date(2016, 1, 12), datetime.date(2016, 1, 15), datetime.date(2016, 1, 22), datetime.date(2016, 1, 28), datetime.date(2016, 1, 29), datetime.date(2016, 2, 2), datetime.date(2016, 2, 24), datetime.date(2016, 3, 10), datetime.date(2016, 4, 22), datetime.date(2016, 4, 28), datetime.date(2016, 5, 15), datetime.date(2016, 6, 5), datetime.date(2016, 6, 16), datetime.date(2016, 6, 19), datetime.date(2016, 6, 24), datetime.date(2016, 7, 31), datetime.date(2016, 8, 31), datetime.date(2016, 9, 7), datetime.date(2016, 9, 18), datetime.date(2016, 9, 25), datetime.date(2016, 10, 6), datetime.date(2016, 11, 3), datetime.date(2016, 11, 9), datetime.date(2017, 1, 8), datetime.date(2017, 2, 12), datetime.date(2017, 3, 12), datetime.date(2017, 4, 3), datetime.date(2017, 4, 20), datetime.date(2017, 6, 20), datetime.date(2017, 6, 25), datetime.date(2017, 9, 25), datetime.date(2017, 11, 15), datetime.date(2017, 12, 10), datetime.date(2017, 12, 20), datetime.date(2018, 2, 25), datetime.date(2018, 3, 6), datetime.date(2018, 3, 16), datetime.date(2018, 3, 25), datetime.date(2018, 4, 1), datetime.date(2018, 4, 11), datetime.date(2018, 4, 22), datetime.date(2018, 7, 6), datetime.date(2018, 7, 18), datetime.date(2018, 7, 20), datetime.date(2018, 7, 26), datetime.date(2018, 8, 24), datetime.date(2018, 10, 1), datetime.date(2018, 12, 7), datetime.date(2018, 12, 11), datetime.date(2018, 12, 20), datetime.date(2019, 1, 18), datetime.date(2019, 1, 29), datetime.date(2019, 2, 7), datetime.date(2019, 2, 26), datetime.date(2019, 3, 5), datetime.date(2019, 3, 19), datetime.date(2019, 3, 26), datetime.date(2019, 4, 14), datetime.date(2019, 4, 19), datetime.date(2019, 5, 12), datetime.date(2019, 5, 15), datetime.date(2019, 6, 4), datetime.date(2019, 6, 19), datetime.date(2019, 6, 20), datetime.date(2019, 7, 5), datetime.date(2019, 8, 11), datetime.date(2019, 8, 14), datetime.date(2019, 10, 11), datetime.date(2019, 11, 8), datetime.date(2019, 12, 4), datetime.date(2020, 1, 14), datetime.date(2020, 1, 15), datetime.date(2020, 1, 17), datetime.date(2020, 2, 28), datetime.date(2020, 3, 18), datetime.date(2020, 3, 30), datetime.date(2020, 4, 1), datetime.date(2020, 5, 1), datetime.date(2020, 5, 6), datetime.date(2020, 5, 19)]
    


  • @run-out I am using EURUSD data from 01-10-1991 to current. I would like to send you the csv file that I am using but cant find a way how to send it here.



  • I have also added a log to record the date at which the next() is called and found that next is called first at 30-10-1991 and hence missing the first 29 candles. Is there something that I am doing wrong.

    Also the plot shows that the first crossover occurs at 29-10-1991 and the first recorded candlestick is at 30-10-1991.



  • @Sajil-Thamban said in Problem with crossovers:

    I have also added a log to record the date at which the next() is called and found that next is called first at 30-10-1991 and hence missing the first 29 candles. Is there something that I am doing wrong.

    Also the plot shows that the first crossover occurs at 29-10-1991 and the first recorded candlestick is at 30-10-1991.

    Sorry its not missing 29 candlesticks but the candlesticks between 01-10-1991 - 29-10-1991



  • plot.png [0_1595496036203_EURUSDMTONE.csv](Uploading 100%)





  • Correct Crossovers
    plot1.png



  • Sorry to be a pain, but the one line I was looking for starts with :

    bt.ind.CrossOver()
    


  • @run-out

    self.ema_fast = bt.indicators.ExponentialMovingAverage(self.data, period=self.p.pfast)
         
    self.ema_slow = bt.indicators.ExponentialMovingAverage(self.data, period=self.p.pslow)
    


  • And this is the crossover

    self.crossover = bt.ind.CrossOver(self.ema_fast, self.ema_slow)
    




  • @Sajil-Thamban post full script which generates issues, not pieces here and there, outputs that prove issues. After that I can take a look and try to help you.


Log in to reply
 

});