can you please add optimization gui elemnts and operation to this app for optimizing the indicator periods and threshold vaes and equity as explained in documentation : DOCUMENTATION: 
Backtesting

Let's see how our strategy performs on historical Google data. The Backtest instance is initialized with OHLC data and a strategy class (see API reference for additional options), and we begin with 10,000 units of cash and set broker's commission to realistic 0.2%.

from backtesting import Backtest

bt = Backtest(GOOG, SmaCross, cash=10_000, commission=.002)
stats = bt.run()
stats

Start                     2004-08-19 00:00:00
End                       2013-03-01 00:00:00
Duration                   3116 days 00:00:00
Exposure Time [%]                       97.07
Equity Final [$]                     68221.97
Equity Peak [$]                      68991.22
Return [%]                             582.22
Buy & Hold Return [%]                  703.46
Return (Ann.) [%]                       25.27
Volatility (Ann.) [%]                   38.38
Sharpe Ratio                             0.66
Sortino Ratio                            1.29
Calmar Ratio                             0.76
Max. Drawdown [%]                      -33.08
Avg. Drawdown [%]                       -5.58
Max. Drawdown Duration      688 days 00:00:00
Avg. Drawdown Duration       41 days 00:00:00
# Trades                                   94
Win Rate [%]                            54.26
Best Trade [%]                          57.12
Worst Trade [%]                        -16.63
Avg. Trade [%]                           2.07
Max. Trade Duration         121 days 00:00:00
Avg. Trade Duration          33 days 00:00:00
Profit Factor                            2.19
Expectancy [%]                           2.61
SQN                                      1.99
_strategy                            SmaCross
_equity_curve                          Equ...
_trades                       Size  EntryB...
dtype: object

Backtest.run() method returns a pandas Series of simulation results and statistics associated with our strategy. We see that this simple strategy makes almost 600% return in the period of 9 years, with maximum drawdown 33%, and with longest drawdown period spanning almost two years ...

Backtest.plot() method provides the same insights in a more visual form.

bt.plot()

Row(
id = '1450', …)
Optimization

We hard-coded the two lag parameters (n1 and n2) into our strategy above. However, the strategy may work better with 15–30 or some other cross-over. We declared the parameters as optimizable by making them class variables.

We optimize the two parameters by calling Backtest.optimize() method with each parameter a keyword argument pointing to its pool of possible values to test. Parameter n1 is tested for values in range between 5 and 30 and parameter n2 for values between 10 and 70, respectively. Some combinations of values of the two parameters are invalid, i.e. n1 should not be larger than or equal to n2. We limit admissible parameter combinations with an ad hoc constraint function, which takes in the parameters and returns True (i.e. admissible) whenever n1 is less than n2. Additionally, we search for such parameter combination that maximizes return over the observed period. We could instead choose to optimize any other key from the returned stats series.

%%time

stats = bt.optimize(n1=range(5, 30, 5),
                    n2=range(10, 70, 5),
                    maximize='Equity Final [$]',
                    constraint=lambda param: param.n1 < param.n2)
stats

CPU times: user 177 ms, sys: 16.1 ms, total: 193 ms
Wall time: 2.41 s

Start                     2004-08-19 00:00:00
End                       2013-03-01 00:00:00
Duration                   3116 days 00:00:00
Exposure Time [%]                       99.07
Equity Final [$]                    103949.43
Equity Peak [$]                     108327.72
Return [%]                             939.49
Buy & Hold Return [%]                  703.46
Return (Ann.) [%]                       31.61
Volatility (Ann.) [%]                   44.74
Sharpe Ratio                             0.71
Sortino Ratio                            1.49
Calmar Ratio                             0.72
Max. Drawdown [%]                      -44.00
Avg. Drawdown [%]                       -6.14
Max. Drawdown Duration      690 days 00:00:00
Avg. Drawdown Duration       43 days 00:00:00
# Trades                                  153
Win Rate [%]                            51.63
Best Trade [%]                          61.56
Worst Trade [%]                        -19.78
Avg. Trade [%]                           1.55
Max. Trade Duration          83 days 00:00:00
Avg. Trade Duration          21 days 00:00:00
Profit Factor                            1.98
Expectancy [%]                           1.98
SQN                                      1.60
_strategy                 SmaCross(n1=10,n...
_equity_curve                           Eq...
_trades                        Size  Entry...
dtype: object

We can look into stats['_strategy'] to access the Strategy instance and its optimal parameter values (10 and 15).

stats._strategy

<Strategy SmaCross(n1=10,n2=15)>

bt.plot(plot_volume=False, plot_pl=False)

Row(
id = '2059', …)

Strategy optimization managed to up its initial performance on in-sample data by almost 50% and even beat simple buy & hold. In real life optimization, however, do take steps to avoid overfitting.
Trade data

In addition to backtest statistics returned by Backtest.run() shown above, you can look into individual trade returns and the changing equity curve and drawdown by inspecting the last few, internal keys in the result series.

stats.tail()

Expectancy [%]                                                 1.98
SQN                                                            1.60
_strategy                                     SmaCross(n1=10,n2=15)
_equity_curve                   Equity  DrawdownPct DrawdownDura...
_trades                Size  EntryBar  ExitBar  EntryPrice  Exit...
dtype: object

The columns should be self-explanatory.

stats['_equity_curve']  # Contains equity/drawdown curves. DrawdownDuration is only defined at ends of DD periods.

	Equity 	DrawdownPct 	DrawdownDuration
2004-08-19 	10000.00 	0.00 	NaT
2004-08-20 	10000.00 	0.00 	NaT
2004-08-23 	10000.00 	0.00 	NaT
2004-08-24 	10000.00 	0.00 	NaT
2004-08-25 	10000.00 	0.00 	NaT
... 	... 	... 	...
2013-02-25 	103035.53 	0.05 	NaT
2013-02-26 	102952.33 	0.05 	NaT
2013-02-27 	104206.83 	0.04 	NaT
2013-02-28 	104391.43 	0.04 	NaT
2013-03-01 	103949.43 	0.04 	533 days

2148 rows × 3 columns

stats['_trades']  # Contains individual trade data

	Size 	EntryBar 	ExitBar 	EntryPrice 	ExitPrice 	PnL 	ReturnPct 	EntryTime 	ExitTime 	Duration
0 	87 	20 	60 	114.65 	185.23 	6140.56 	0.62 	2004-09-17 	2004-11-12 	56 days
1 	-87 	60 	69 	184.86 	175.80 	788.18 	0.05 	2004-11-12 	2004-11-26 	14 days
2 	96 	69 	71 	176.15 	180.71 	437.61 	0.03 	2004-11-26 	2004-11-30 	4 days
3 	-96 	71 	75 	180.35 	179.13 	116.98 	0.01 	2004-11-30 	2004-12-06 	6 days
4 	97 	75 	82 	179.49 	177.99 	-145.33 	-0.01 	2004-12-06 	2004-12-15 	9 days
... 	... 	... 	... 	... 	... 	... 	... 	... 	... 	...
148 	139 	2085 	2111 	689.16 	735.54 	6447.44 	0.07 	2012-11-29 	2013-01-08 	40 days
149 	-139 	2111 	2113 	734.07 	742.83 	-1217.79 	-0.01 	2013-01-08 	2013-01-10 	2 days
150 	136 	2113 	2121 	744.32 	735.99 	-1132.29 	-0.01 	2013-01-10 	2013-01-23 	13 days
151 	-136 	2121 	2127 	734.52 	750.51 	-2174.91 	-0.02 	2013-01-23 	2013-01-31 	8 days
152 	130 	2127 	2147 	752.01 	797.80 	5952.57 	0.06 	2013-01-31 	2013-03-01 	29 days

153 rows × 10 columns

Learn more by exploring further examples or find more framework options in the full API reference.
CODE TO EXTEND : import tkinter as tk
from tkinter import ttk
import pandas as pd
import ccxt
from ta.momentum import RSIIndicator, StochasticOscillator
from ta.volatility import BollingerBands
from ta.trend import MACD
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import pandas as pd
import ccxt
from ta.momentum import RSIIndicator, StochasticOscillator
from ta.volatility import BollingerBands
from ta.trend import MACD
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

class TradingStrategy(Strategy):
    params = {
        'rsi_length': 30,       
        'macd_fast': 12,
        'macd_slow': 26,
        'bollinger_bands_window': 20,
        'stochastic_oscillator_window': 14,
        'rsi_threshold_buy' : 50,
        'rsi_threshold_sell' : 50,
        'macd_threshold_buy' : 50,
        'macd_threshold_sell' : 50,
        'bollinger_bands_threshold_buy' : 50,
        'bollinger_bands_threshold_sell' : 50, #10
        'stochastic_oscillator_window_buy' :50,
        'stochastic_oscillator_window_sell' :50, #12
        'rsi_include' : True,
        'macd_include' : True,
        'bollinger_bands_include' : True,
        'stochastic_oscillator_include' : True,
        
        
    }

    def init(self):
        # Convert data columns to pandas.Series
        close_series = pd.Series(self.data['Close'])
        high_series = pd.Series(self.data['High'])
        low_series = pd.Series(self.data['Low'])

        # RSI Indicator
        self.rsi = self.I(lambda x: RSIIndicator(x, window=self.params[0][1]).rsi(), close_series)
        
        # MACD
        self.macd = self.I(lambda x: MACD(x, window_slow=self.params[1][1], window_fast=self.params[2][1]).macd(), close_series)
        
        # Bollinger Bands
        self.bollinger_bands = self.I(lambda x: BollingerBands(x, window=self.params[3][1]).bollinger_mavg(), close_series)
        print(self.bollinger_bands)
        
        
        # Stochastic Oscillator
        self.stochastic_oscillator = self.I(
            lambda h, l, c: StochasticOscillator(
                high=h, low=l, close=c, window=self.params[4][1]
            ).stoch(),
            high_series, low_series, close_series
        )

    def next(self):
    	if ( self.params[13][1] ) :
    		if self.rsi > self.params[5][1]:
    			self.buy()
    		elif self.rsi < self.params[6][1]:
    			self.sell()
    	if ( self.params[14][1] ):
    		if self.macd >  self.params[7][1]:
    			self.buy()
    		elif self.macd < self.params[8][1]:
    			self.sell()
    	if ( self.params[15][1] ) :
    		if self.bollinger_bands >  self.params[9][1] :
    			self.buy()
    		elif self.bollinger_bands <  self.params[10][1] :
    			self.sell()
    	if ( self.params[16][1] ) :
    		if self.stochastic_oscillator >  self.params[11][1]:
    			self.buy()
    		elif self.stochastic_oscillator <  self.params[12][1]:
    			self.sell()

class GUI:
     def __init__(self, root):
        self.root = root
        self.root.title("Trading Strategy GUI")
        self.root.geometry("800x800")  # Adjusted size to accommodate more widgets

        # Ticker Entry
        self.ticker_label = tk.Label(root, text="Ticker:")
        self.ticker_label.pack()
        self.ticker_entry = tk.Entry(root)
        self.ticker_entry.insert(0, 'PEPE/USDT')
        self.ticker_entry.pack()

        # RSI Length
        self.rsi_length_label = tk.Label(root, text="RSI length:")
        self.rsi_length_label.pack()
        self.rsi_length_entry = tk.Entry(root)
        self.rsi_length_entry.insert(0, '30')
        self.rsi_length_entry.pack()

        # RSI Thresholds
        self.rsi_threshold_buy_label = tk.Label(root, text="RSI Threshold Buy:")
        self.rsi_threshold_buy_label.pack()
        self.rsi_threshold_buy_entry = tk.Entry(root)
        self.rsi_threshold_buy_entry.insert(0, '50')
        self.rsi_threshold_buy_entry.pack()

        self.rsi_threshold_sell_label = tk.Label(root, text="RSI Threshold Sell:")
        self.rsi_threshold_sell_label.pack()
        self.rsi_threshold_sell_entry = tk.Entry(root)
        self.rsi_threshold_sell_entry.insert(0, '50')
        self.rsi_threshold_sell_entry.pack()

        # RSI Include Checkbox
        self.rsi_include = tk.BooleanVar(value=True)
        self.rsi_include_checkbox = tk.Checkbutton(root, text="Include RSI", variable=self.rsi_include)
        self.rsi_include_checkbox.pack()

        # MACD Fast and Slow
        self.macd_fast_label = tk.Label(root, text="MACD Fast:")
        self.macd_fast_label.pack()
        self.macd_fast_entry = tk.Entry(root)
        self.macd_fast_entry.insert(0, '12')
        self.macd_fast_entry.pack()

        self.macd_slow_label = tk.Label(root, text="MACD Slow:")
        self.macd_slow_label.pack()
        self.macd_slow_entry = tk.Entry(root)
        self.macd_slow_entry.insert(0, '26')
        self.macd_slow_entry.pack()

        # MACD Thresholds
        self.macd_threshold_buy_label = tk.Label(root, text="MACD Threshold Buy:")
        self.macd_threshold_buy_label.pack()
        self.macd_threshold_buy_entry = tk.Entry(root)
        self.macd_threshold_buy_entry.insert(0, '50')
        self.macd_threshold_buy_entry.pack()

        self.macd_threshold_sell_label = tk.Label(root, text="MACD Threshold Sell:")
        self.macd_threshold_sell_label.pack()
        self.macd_threshold_sell_entry = tk.Entry(root)
        self.macd_threshold_sell_entry.insert(0, '50')
        self.macd_threshold_sell_entry.pack()

        # MACD Include Checkbox
        self.macd_include = tk.BooleanVar(value=True)
        self.macd_include_checkbox = tk.Checkbutton(root, text="Include MACD", variable=self.macd_include)
        self.macd_include_checkbox.pack()

        # Bollinger Bands Window
        self.bollinger_bands_window_label = tk.Label(root, text="Bollinger Bands Window:")
        self.bollinger_bands_window_label.pack()
        self.bollinger_bands_window_entry = tk.Entry(root)
        self.bollinger_bands_window_entry.insert(0, '20')
        self.bollinger_bands_window_entry.pack()

        # Bollinger Bands Thresholds
        self.bollinger_bands_threshold_buy_label = tk.Label(root, text="Bollinger Bands Threshold Buy:")
        self.bollinger_bands_threshold_buy_label.pack()
        self.bollinger_bands_threshold_buy_entry = tk.Entry(root)
        self.bollinger_bands_threshold_buy_entry.insert(0, '50')
        self.bollinger_bands_threshold_buy_entry.pack()

        self.bollinger_bands_threshold_sell_label = tk.Label(root, text="Bollinger Bands Threshold Sell:")
        self.bollinger_bands_threshold_sell_label.pack()
        self.bollinger_bands_threshold_sell_entry = tk.Entry(root)
        self.bollinger_bands_threshold_sell_entry.insert(0, '50')
        self.bollinger_bands_threshold_sell_entry.pack()

        # Bollinger Bands Include Checkbox
        self.bollinger_bands_include = tk.BooleanVar(value=True)
        self.bollinger_bands_include_checkbox = tk.Checkbutton(root, text="Include Bollinger Bands", variable=self.bollinger_bands_include)
        self.bollinger_bands_include_checkbox.pack()

        # Stochastic Oscillator Window
        self.stochastic_oscillator_window_label = tk.Label(root, text="Stochastic Oscillator Window:")
        self.stochastic_oscillator_window_label.pack()
        self.stochastic_oscillator_window_entry = tk.Entry(root)
        self.stochastic_oscillator_window_entry.insert(0, '14')
        self.stochastic_oscillator_window_entry.pack()

        # Stochastic Oscillator Thresholds
        self.stochastic_oscillator_window_buy_label = tk.Label(root, text="Stochastic Oscillator Threshold Buy:")
        self.stochastic_oscillator_window_buy_label.pack()
        self.stochastic_oscillator_window_buy_entry = tk.Entry(root)
        self.stochastic_oscillator_window_buy_entry.insert(0, '50')
        self.stochastic_oscillator_window_buy_entry.pack()

        self.stochastic_oscillator_window_sell_label = tk.Label(root, text="Stochastic Oscillator Threshold Sell:")
        self.stochastic_oscillator_window_sell_label.pack()
        self.stochastic_oscillator_window_sell_entry = tk.Entry(root)
        self.stochastic_oscillator_window_sell_entry.insert(0, '50')
        self.stochastic_oscillator_window_sell_entry.pack()

        # Stochastic Oscillator Include Checkbox
        self.stochastic_oscillator_include = tk.BooleanVar(value=True)
        self.stochastic_oscillator_include_checkbox = tk.Checkbutton(root, text="Include Stochastic Oscillator", variable=self.stochastic_oscillator_include)
        self.stochastic_oscillator_include_checkbox.pack()

        # Backtest and Plot Buttons
        self.backtest_button = tk.Button(root, text="Backtest", command=self.backtest)
        self.backtest_button.pack()

      
     def backtest(self):
        ticker = self.ticker_entry.get()
        exchange = ccxt.binance()
        data = exchange.fetch_ohlcv(ticker, timeframe='1m', since=1609459200000, limit=10000)
        df = pd.DataFrame(data, columns=['timestamp', 'Open', 'High', 'Low', 'Close', 'Volume'])
        #df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
        df.set_index('timestamp', inplace=True)
        strategy = TradingStrategy
        strategy.params = ( ('rsi_length', int(self.rsi_length_entry.get()) ),
            ('macd_fast', int(self.macd_fast_entry.get())),
            ('macd_slow', int(self.macd_slow_entry.get())),
            ('bollinger_bands_window', int(self.bollinger_bands_window_entry.get())),
            ('stochastic_oscillator_window', int(self.stochastic_oscillator_window_entry.get())),
            ('rsi_threshold_buy', float(self.rsi_threshold_buy_entry.get())),
            ('rsi_threshold_sell', float(self.rsi_threshold_sell_entry.get())),
            ('macd_threshold_buy', float(self.macd_threshold_buy_entry.get())),
            ('macd_threshold_sell', float(self.macd_threshold_sell_entry.get())),
            ('bollinger_bands_threshold_buy', float(self.bollinger_bands_threshold_buy_entry.get())),
            ('bollinger_bands_threshold_sell', float(self.bollinger_bands_threshold_sell_entry.get())),
            ('stochastic_oscillator_window_buy', float(self.stochastic_oscillator_window_buy_entry.get())),
            ('stochastic_oscillator_window_sell', float(self.stochastic_oscillator_window_sell_entry.get())),
            ('rsi_include', self.rsi_include.get()),
            ('macd_include', self.macd_include.get()),
            ('bollinger_bands_include', self.bollinger_bands_include.get()),
            ('stochastic_oscillator_include', self.stochastic_oscillator_include.get()),
        )
        print("---------------------")
        print(strategy.params)
        self.backtest = Backtest(df, strategy, cash=1000000, commission=.02)

        self.stats = self.backtest.run()
        fig, ax = plt.subplots(figsize=(16, 8))
        #ax.plot(self.backtest._data.index, self.backtest._data['Close'], label='Close Price')
        ax.plot(self.backtest._results['_equity_curve']['Equity'])
        ax.set_ylabel('Price')
        ax.set_title('Backtest Results')
        ax.legend()
        plt.show()
        #ax.set_ylim(bottom=0, top=500000)  # Adjust the top limit as needed
        print( self.stats)

        #fig, ax = plt.subplots(figsize=(8, 6))
    # def plot(self):
       # fig, ax = plt.subplots(figsize=(8, 6))
       # equity_curve = self.backtest._results['_equity_curve']
       # equity_curve = equity_curve[equity_curve.notnull()] # remove NaT values
       # ax.plot(equity_curve)
      #  ax.set_xlabel('Time')
     #   ax.set_ylabel('Equity')
     #   ax.set_title('Equity Curve')
     #   canvas = FigureCanvasTkAgg(fig, self.root)
     #   canvas.get_tk_widget().pack()
    #    canvas.draw()

        # Embed the plot into the Tkinter window
#        canvas = FigureCanvasTkAgg(fig, self.root)
 #       canvas.get_tk_widget().pack()
  #      canvas.draw()
   #     plt.show()

if __name__ == "__main__":
    root = tk.Tk()
    gui = GUI(root)
    root.mainloop()