long and short strategy with macd indicator in Backtrader

I just switched from Matlab to python and evening newer to the backtrader library for backtestingtrading strategies. My questions might seem obvious .
My trouble seems similar to this : hypertext transfer protocol : //community.backtrader.com/topic/2857/wanted-exit-long-and-open-short-on-the-same-bar-and-vice-versa
and this : hypertext transfer protocol : //community.backtrader.com/topic/2797/self-close-does-not-clear-position The code downstairs is a simple MACD scheme. here is the code :

# -*- coding: utf-8 -*-
"""

"""

import backtrader as bt
import argparse
import backtrader.feeds as btFeeds
import numpy as np
import yfinance as yf
import pandas as pd
import talib



class SimpleMACDStrat(bt.Strategy):
    
    def __init__(self):
        #Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close
        self.order = None

    def log(self, txt, dt=None):
        dt = dt or self.datas[0].datetime.date(0)
        print(f'{dt.isoformat()} {txt}')
        #Print date and close
        
    
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return

        # Check if an order has been completed
        # Attention: broker could reject order if not enough cash
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log('LONG EXECUTED, %.2f' % order.executed.price)
                
            elif order.issell():
                self.log('SELL EXECUTED, %.2f' % order.executed.price)

            self.bar_executed = len(self)

        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')

        # Write down: no pending order
        self.order = None
        

    def next(self):
        self.log("Close: '{0}'" .format(self.data.adj_close[0]))
        print('%f %f %f %f %f %f %f %f %f %f %f %f %f' % (self.data.Indexx[0],self.data.open[0],
                                                 self.data.high[0],self.data.low[0],
                               self.data.close[0],self.data.adj_close[0],
                               self.data.volume[0],self.data.EMA_100[0], 
                               self.data.RSI[0], self.data.CCI[0],
                               self.data.MACD_macd[0],self.data.MACD_sign[0],self.data.MACD_hist[0]))

        if self.order:
            return
        
        if self.data.MACD_hist[0]>0:
            if self.position.size<0 and self.data.MACD_hist[-1]<0  :
                     self.close()
                     self.log('CLOSE SHORT POSITION, %.2f' % self.dataclose[0])
       
            elif self.position.size==0:
                    self.order=self.buy()
                    self.log('OPEN LONG POSITION, %.2f' % self.dataclose[0])
                    
                
        elif self.data.MACD_hist[0]<0:
            if self.position.size>0 and self.data.MACD_hist[-1]>0:
                     self.order=self.close()
                     self.log('CLOSE LONG POSITION, %.2f' % self.dataclose[0])
                            
            elif self.position.size==0:
                    self.order=self.sell()
                    self.log('OPEN SHORT POSITION, %.2f' % self.dataclose[0])
        print('')
        


class BasicIndicatorsFeeded(btFeeds.PandasData):
    lines = ('Indexx', 'adj_close', 'EMA_100', 'RSI', 'CCI', 'MACD_macd', 'MACD_sign', 'MACD_hist',)

    params = ( ('Indexx', 0), ('adj_close', 5), ('volume', 6), 
              ('EMA_100', 7), ('RSI', 8), ('CCI', 9),
              ('MACD_macd', 10), ('MACD_sign', 11), ('MACD_hist', 12),)







if __name__ == '__main__':
    
    cerebro = bt.Cerebro()
    
    #Add data feed to Cerebro
    data1 = yf.download("AAPL",start="2021-08-09", end="2021-12-21",group_by="ticker")
    data1.insert(0,'Indexx',' ')
    data1['Indexx']=range(len(data1))
    data1['EMA_100']=talib.EMA(data1['Adj Close'],100)
    data1['RSI']=talib.RSI(data1['Adj Close'],14)
    data1['CCI']=talib.CCI(data1['High'], data1['Low'], data1['Adj Close'], timeperiod=14)
    data1['MACD_macd']=talib.MACD(data1['Adj Close'], fastperiod=12, slowperiod=26, signalperiod=9)[0]
    data1['MACD_sign']=talib.MACD(data1['Adj Close'], fastperiod=12, slowperiod=26, signalperiod=9)[1]
    data1['MACD_hist']=talib.MACD(data1['Adj Close'], fastperiod=12, slowperiod=26, signalperiod=9)[2]
   # data1['Long_position']
    # Run Cerebro Engine
    cerebro.broker.setcash(8000000000)
    start_portfolio_value = cerebro.broker.getvalue()
    cerebro.addstrategy(SimpleMACDStrat)
    
    data = BasicIndicatorsFeeded(dataname=data1)
    cerebro.adddata(data)
   
    cerebro.run()
    cerebro.plot()
   # print(data1)
    print('-------------------')
    #print('%f' %data)
    # print(data)
    end_portfolio_value = cerebro.broker.getvalue()
    pnl = end_portfolio_value - start_portfolio_value
    print(f'Starting Portfolio Value: {start_portfolio_value:2f}')
    print(f'Final Portfolio Value: {end_portfolio_value:2f}')
    print(f'PnL: {pnl:.2f}')

here are the results :

results
On 2021-11-10, macd_hist goes from postive to negative. We are expecting that the future day ( 2021-11-11 ) :
a ) the long put is closed and justly after and
bel ) a unretentive position is opened
1 ) We see that a ) is actually closed the same day. Is n’t it supposed to happen the next ?
2 ) besides a sell is executed the day after, which is not supposed to happen.

Any suggestion for 1 ) and 2 ) would be more then welcome. Thanks .
abbe
EDIT :
Btw, I ‘m aware the mind can be coded that way ( only def adjacent ) :

    def next(self):
        #print('%f' % (self.datas[0].Indexxx[0])
        self.log("Close: '{0}'" .format(self.data.adj_close[0]))
        print('%f %f %f %f %f %f %f %f %f %f %f %f %f' % (self.data.Indexx[0],self.data.open[0],
                                                 self.data.high[0],self.data.low[0],
                               self.data.close[0],self.data.adj_close[0],
                               self.data.volume[0],self.data.EMA_100[0], 
                               self.data.RSI[0], self.data.CCI[0],
                               self.data.MACD_macd[0],self.data.MACD_sign[0],self.data.MACD_hist[0]))
        if self.order:
            return
 

        print(self.position)
        if self.data.MACD_hist[0]>0 and self.data.MACD_hist[-1]<0:
                     self.order=self.buy()
                     self.log('CLOSE SHORT POSITION and open long, %.2f' % self.dataclose[0])
                
                
        if self.data.MACD_hist[0]<0 and self.data.MACD_hist[-1]>0:

                     self.order=self.sell()
                     self.log('CLOSE LONG POSITION and open short, %.2f' % self.dataclose[0])
                
        print('')

But I in truth want to separate the

self.close()

and for exemplify the

self.buy()

That would allow me subsequently to use different conditions for closing a placement and opening one .
Thanks a fortune for any inputs, ideas, remarks .
abbe

source : https://coinselected
Category : coin 4u

Leave a Reply

Your email address will not be published.