[*********************100%***********************]  1 of 1 completed
Traceback (most recent call last):
  File "c:\Users\Adrian\Desktop\Trader_1.py", line 181, in <module>
    result = cerebro.run()
             ^^^^^^^^^^^^^
  File "C:\Users\Adrian\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\cerebro.py", line 1127, in run
    runstrat = self.runstrategies(iterstrat)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Adrian\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\cerebro.py", line 1217, in runstrategies
    strat = stratcls(*sargs, **skwargs)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Adrian\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\metabase.py", line 88, in __call__
    _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Adrian\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\metabase.py", line 78, in doinit
    _obj.__init__(*args, **kwargs)
  File "c:\Users\Adrian\Desktop\Trader_1.py", line 115, in __init__
    (self.data0 / self.data1).rolling(window=self.params.lookback).mean() - 1.0
                  ^^^^^^^^^^
  File "C:\Users\Adrian\AppData\Local\Programs\Python\Python311\Lib\site-packages\backtrader\lineseries.py", line 461, in __getattr__
    return getattr(self.lines, name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Lines_LineSeries_LineIterator_DataAccessor_Strateg' object has no attribute 'data1'

import backtrader as bt
import pandas as pd
import yfinance as yf
import requests

# setup bot
token = ''

def send_message(text):
    chat_id = ''
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    params = {
        "chat_id": chat_id,
        "text": text,
    }
    resp = requests.get(url, params=params)
    resp.raise_for_status()




class MovingAverageStrategy(bt.Strategy):
    params = (('fast_ma', 20), ('slow_ma', 50))
    
    def __init__(self):
        self.fast_ma = bt.indicators.SMA(self.data, period=self.params.fast_ma)
        self.slow_ma = bt.indicators.SMA(self.data, period=self.params.slow_ma)
        self.crossover = bt.indicators.CrossOver(self.fast_ma, self.slow_ma)
        
    def next(self):
        if not self.position:
            if self.crossover > 0:
                self.buy()
        elif self.crossover < 0:
            self.sell()

class MomentumStrategy(bt.Strategy):
    params = (('period', 14), ('mom', 10))
    
    def __init__(self):
        self.mom = bt.indicators.Momentum(self.data, period=self.params.period)
        
    def next(self):
        if not self.position:
            if self.mom > self.params.mom:
                self.buy()
        elif self.mom < self.params.mom:
            self.sell()

class MeanReversionStrategy(bt.Strategy):
    params = (('period', 20), ('devfactor', 2))

    def __init__(self):
        self.zscore = ZScore(period=self.params.period)

    def next(self):
        if not self.position:
            if self.zscore < -1.0:
                self.buy()
        elif self.zscore > 1.0:
            self.sell()

# Trend Following Strategy
class TrendFollowingStrategy(bt.Strategy):
    params = (
        ('fast_ma_period', 50),
        ('slow_ma_period', 200),
    )

    def __init__(self):
        self.fast_ma = bt.indicators.SimpleMovingAverage(
            self.data, period=self.params.fast_ma_period
        )
        self.slow_ma = bt.indicators.SimpleMovingAverage(
            self.data, period=self.params.slow_ma_period
        )

    def next(self):
        if self.position.size == 0 and self.fast_ma[-1] > self.slow_ma[-1]:
            self.buy()
        elif self.position.size > 0 and self.fast_ma[-1] < self.slow_ma[-1]:
            self.close()
        elif self.position.size < 0 and self.fast_ma[-1] > self.slow_ma[-1]:
            self.close()
# Breakout Startegy
class BreakoutStrategy(bt.Strategy):
    params = (
        ('atr_period', 14),
        ('breakout_multiplier', 1.5),
    )

    def __init__(self):
        self.atr = bt.indicators.AverageTrueRange(
            self.data, period=self.params.atr_period
        )

    def next(self):
        if self.position.size == 0 and self.data.close[-1] > (
            self.data.close[-2] + (self.atr[-1] * self.params.breakout_multiplier)
        ):
            self.buy()
        elif self.position.size > 0 and self.data.close[-1] < self.data.close[0]:
            self.close()

# Pairs Trading Strategy
class PairsTradingStrategy(bt.Strategy):
    params = (
        ('lookback', 20),
        ('entry_threshold', 2.0),
        ('exit_threshold', 0.5),
    )

    def __init__(self):
        self.zscore = self.indicators.zscore = (
            (self.data0 / self.data1).rolling(window=self.params.lookback).mean() - 1.0
        ) / (self.data0 / self.data1).rolling(window=self.params.lookback).std()
        self.long_entry = self.params.entry_threshold
        self.long_exit = self.params.exit_threshold
        self.short_entry = -self.params.entry_threshold
        self.short_exit = -self.params.exit_threshold

    def next(self):
        if self.position.size == 0:
            if self.zscore[-1] > self.long_entry:
                self.buy(data=self.data0)
                self.sell(data=self.data1)
            elif self.zscore[-1] < self.short_entry:
                self.sell(data=self.data0)
                self.buy(data=self.data1)
        elif self.position.size > 0:
            if self.zscore[-1] < self.long_exit:
                self.close()
        elif self.position.size < 0:
            if self.zscore[-1] > self.short_exit:
                self.close()
class ZScore(bt.Indicator):
    lines = ('zscore',)
    params = (('period', 20),)

    def __init__(self):
        self.bband = bt.indicators.BollingerBands(self.data, period=self.params.period)
        self.stddev = bt.indicators.StandardDeviation(self.data, period=self.params.period)

    def next(self):
        self.lines.zscore[0] = (self.data[0] - self.bband.lines.mid[0]) / self.stddev[0]



if __name__ == '__main__':
    # Download historical price data for MSFT from Yahoo Finance
    tickers = ['MSFT', 'AAPL', 'GOOGL', 'TSLA',]

    for ticker in tickers:
        try:
            data = yf.download(ticker, start='2010-01-01', end='2023-03-28', auto_adjust=True, ignore_tz=True)
            if data.empty:
                raise ValueError(f"No data found for {ticker} in the specified date range.")
            # Convert data to backtrader format
            data = bt.feeds.PandasData(dataname=data)
            strategies = [MovingAverageStrategy, MomentumStrategy, MeanReversionStrategy, TrendFollowingStrategy, BreakoutStrategy, PairsTradingStrategy]


            for strategy in strategies:
                # Create a cerebro instance
                cerebro = bt.Cerebro()

                # Add the data feed
                cerebro.adddata(data)

                # Add the strategy
                cerebro.addstrategy(strategy)

                # Set up the cash and commission
                cerebro.broker.setcash(10000)
                cerebro.broker.setcommission(commission=0.001)

                # Add a fixed stake sizer
                cerebro.addsizer(bt.sizers.FixedSize, stake=1)

                # Run the backtest
                result = cerebro.run()
        except ValueError as e:
            print(e)
            continue

    

    

        # Print the result
        print(strategy.__name__)
        print('Total profit:', result[0].broker.getvalue() - 10000)
        print('Return on investment:', (result[0].broker.getvalue() - 10000) / 10000 * 100, '%')
        print('')

        
        # Print the result
        print('Moving Average Crossover Strategy')
        print('Total profit:', result[0].broker.getvalue() - cerebro.broker.getcash())
        print('Return on investment:', (result[0].broker.getvalue() - cerebro.broker.getcash()) / cerebro.broker.getcash() * 100, '%')
        print('')
        
        print('Momentum Trading Strategy')
        print('Total profit:', result[0].broker.getvalue() - cerebro.broker.getcash())
        print('Return on investment:', (result[0].broker.getvalue() - cerebro.broker.getcash()) / cerebro.broker.getcash() * 100, '%')
        print('')
        
        print('Mean Reversion Trading Strategy')
        print('Total profit:', result[0].broker.getvalue() - cerebro.broker.getcash())
        print('Return on investment:', (result[0].broker.getvalue() - cerebro.broker.getcash()) / cerebro.broker.getcash() * 100, '%')
        print('')