the python code below is my trading strategy testing in the binance demo account rewrite it in a way to test it in the bingx demo account
import pandas as pd
import numpy as np
from dataclasses import dataclass
from typing import List, Optional, Dict

from binance.client import AsyncClient
from binance.enums import *
from binance.exceptions import BinanceAPIException, BinanceOrderException

import asyncio
import time
from datetime import datetime, timedelta

@dataclass
class StrategySettings:
    sensitivity: float = 18.0
    risk_percent: float = 1.0
    break_even_target: str = "1"  # Options: "1", "2", "3", "WITHOUT"
    tp1_percent: float = 1.0
    tp1_percent_fix: float = 40.0
    tp2_percent: float = 2.0
    tp2_percent_fix: float = 30.0
    tp3_percent: float = 3.0
    tp3_percent_fix: float = 20.0
    tp4_percent: float = 4.0
    tp4_percent_fix: float = 10.0
    fixed_stop: bool = False
    sl_percent: float = 0.0

@dataclass
class Trade:
    start_bar_index: int
    side: str  # "LONG" or "SHORT"
    entry_price: float
    sl_price: float
    tp1_price: float
    tp1_percent_fix: float
    tp2_price: float
    tp2_percent_fix: float
    tp3_price: float
    tp3_percent_fix: float
    tp4_price: float
    tp4_percent_fix: float
    break_even_price: float
    risk_percent: float
    open_date: pd.Timestamp
    close_date: Optional[pd.Timestamp] = None
    is_closed: bool = False
    sl_hit: bool = False
    tp1_hit: bool = False
    tp2_hit: bool = False
    tp3_hit: bool = False
    tp4_hit: bool = False
    can_break_even: bool = False
    profit: float = 0.0
    position_size_left: float = 100.0
    force_closed: bool = False
    order_id: Optional[int] = None  # Binance order ID
    quantity: float = 0.0           # Quantity traded

class TradingStrategy:
    def __init__(self, client: AsyncClient, symbol: str, settings: StrategySettings):
        self.client = client
        self.symbol = symbol
        self.settings = settings
        self.trades: List[Trade] = []
        self.total_profit = 0.0
        self.dep = settings.risk_percent * 100  # Initial deposit can be adjusted as needed
        self.trade_count = 0
        self.profit_trades = 0
        self.loss_trades = 0
        self.win_streak = 0
        self.loss_streak = 0
        self.current_win_streak = 0
        self.current_loss_streak = 0
        self.first_trade_date = None

        # Initialize data placeholders
        self.data = None

        # Initialize trend states
        self.is_long_trend = False
        self.is_short_trend = False
        self.last_trend = None  # Keeps track of the last trend to prevent rapid switching

        # Retrieve exchange info for symbol precision and lot size
        self.exchange_info = None
        self.lot_size = None
        self.tick_size = None
        self.initialized = False  # To check if exchange info and other initializations are done

    async def initialize(self):
        # Retrieve exchange info for symbol precision and lot size
        self.exchange_info = await self.client.get_symbol_info(self.symbol)
        # Extract lot size and tick size from the filters
        for filt in self.exchange_info['filters']:
            if filt['filterType'] == 'LOT_SIZE':
                self.lot_size = float(filt['stepSize'])
            if filt['filterType'] == 'PRICE_FILTER':
                self.tick_size = float(filt['tickSize'])
        self.initialized = True

    def round_step_size(self, quantity, step_size):
        precision = int(round(-np.log10(step_size), 0))
        return round(quantity, precision)

    def calc_rr(self, entry_price: float, sl_price: float, tp_price: float) -> float:
        if entry_price > sl_price:
            return (tp_price - entry_price) / (entry_price - sl_price)
        else:
            return (entry_price - tp_price) / (sl_price - entry_price)

    async def run_strategy(self):
        if not self.initialized:
            await self.initialize()
        # Fetch the latest data
        data = await self.get_live_data(limit=int(self.settings.sensitivity)+5)
        if data is None:
            return
        self.data = data
        # Only process the latest bar (since we're running continuously)
        idx = len(self.data) - 1
        current_bar = self.data.iloc[idx]
        close = current_bar['close']
        date = current_bar['datetime']
        trend_line = current_bar['trend_line']
        fib_236 = current_bar['fib_236']
        fib_786 = current_bar['fib_786']

        if not np.isnan(trend_line):
            can_long = close >= trend_line and close >= fib_236
            can_short = close <= trend_line and close <= fib_786

            # Prevent trend switching too frequently
            new_trend = None
            if can_long and self.last_trend != "LONG":
                new_trend = "LONG"
            elif can_short and self.last_trend != "SHORT":
                new_trend = "SHORT"

            # Update trend only if there's a clear change
            if new_trend:
                if new_trend == "LONG" and not self.is_short_trend:
                    self.is_long_trend = True
                    self.is_short_trend = False
                    self.last_trend = "LONG"
                elif new_trend == "SHORT" and not self.is_long_trend:
                    self.is_short_trend = True
                    self.is_long_trend = False
                    self.last_trend = "SHORT"

        # Manage existing trades
        await self.manage_trades(idx, current_bar)

        # Check for new trade entry
        await self.check_entry(idx, current_bar)

    async def manage_trades(self, idx, current_bar: pd.Series):
        for trade in self.trades:
            if not trade.is_closed:
                if trade.side == "LONG":
                    await self.manage_long_trade(trade, idx, current_bar)
                elif trade.side == "SHORT":
                    await self.manage_short_trade(trade, idx, current_bar)

    async def manage_long_trade(self, trade: Trade, idx: int, current_bar: pd.Series):
        date = current_bar['datetime']

        # Fetch current price
        current_price = await self.get_current_price()

        # Handle Take Profits and Stop Loss
        if not trade.tp1_hit and current_price >= trade.tp1_price:
            await self.hit_tp(trade, 'tp1', trade.tp1_price, self.settings.tp1_percent_fix, idx, date)

        if not trade.tp2_hit and current_price >= trade.tp2_price:
            await self.hit_tp(trade, 'tp2', trade.tp2_price, self.settings.tp2_percent_fix, idx, date)
            trade.can_break_even = True  # Enable BE once TP2 is hit

        if not trade.tp3_hit and current_price >= trade.tp3_price:
            await self.hit_tp(trade, 'tp3', trade.tp3_price, self.settings.tp3_percent_fix, idx, date)

        if not trade.tp4_hit and current_price >= trade.tp4_price:
            await self.hit_tp(trade, 'tp4', trade.tp4_price, self.settings.tp4_percent_fix, idx, date)
            trade.is_closed = True  # Close the trade after TP4
            await self.close_trade(trade)

        # Handle Stop Loss
        if current_price <= trade.sl_price and not trade.can_break_even:
            await self.hit_sl(trade, idx, date)

        # Handle Break-Even
        if trade.can_break_even and current_price <= trade.entry_price:
            await self.hit_be(trade, idx, date)

    async def manage_short_trade(self, trade: Trade, idx: int, current_bar: pd.Series):
        date = current_bar['datetime']

        # Fetch current price
        current_price = await self.get_current_price()

        # Handle Take Profits and Stop Loss
        if not trade.tp1_hit and current_price <= trade.tp1_price:
            await self.hit_tp(trade, 'tp1', trade.tp1_price, self.settings.tp1_percent_fix, idx, date)

        if not trade.tp2_hit and current_price <= trade.tp2_price:
            await self.hit_tp(trade, 'tp2', trade.tp2_price, self.settings.tp2_percent_fix, idx, date)
            trade.can_break_even = True  # Enable BE once TP2 is hit

        if not trade.tp3_hit and current_price <= trade.tp3_price:
            await self.hit_tp(trade, 'tp3', trade.tp3_price, self.settings.tp3_percent_fix, idx, date)

        if not trade.tp4_hit and current_price <= trade.tp4_price:
            await self.hit_tp(trade, 'tp4', trade.tp4_price, self.settings.tp4_percent_fix, idx, date)
            trade.is_closed = True  # Close the trade after TP4
            await self.close_trade(trade)

        # Handle Stop Loss
        if current_price >= trade.sl_price and not trade.can_break_even:
            await self.hit_sl(trade, idx, date)

        # Handle Break-Even
        if trade.can_break_even and current_price >= trade.entry_price:
            await self.hit_be(trade, idx, date)

    async def get_current_price(self):
        # Fetch current price from Binance
        ticker = await self.client.get_symbol_ticker(symbol=self.symbol)
        return float(ticker['price'])

    async def hit_tp(self, trade: Trade, tp_label: str, tp_price: float, tp_percent_fix: float, idx: int, date: pd.Timestamp):
        setattr(trade, f"{tp_label}_hit", True)
        trade.position_size_left -= tp_percent_fix
        profit = self.calc_rr(trade.entry_price, trade.sl_price, tp_price) * (tp_percent_fix / 100) * trade.risk_percent
        trade.profit += profit
        self.total_profit += profit
        print(f"{self.symbol} {tp_label.upper()} Hit on {date}: +{profit:.2f}%")

        # Close partial position on Binance
        quantity = trade.quantity * (tp_percent_fix / 100)
        quantity = self.round_step_size(quantity, self.lot_size)
        if quantity > 0:
            await self.place_order(
                side=SIDE_SELL if trade.side == "LONG" else SIDE_BUY,
                quantity=quantity,
                order_type=ORDER_TYPE_MARKET
            )

    async def hit_sl(self, trade: Trade, idx: int, date: pd.Timestamp):
        trade.sl_hit = True
        trade.is_closed = True
        trade.close_date = date
        trade.profit -= self.settings.risk_percent * (trade.position_size_left / 100)
        self.total_profit += trade.profit
        self.loss_trades += 1
        self.current_loss_streak += 1
        self.current_win_streak = 0
        if self.current_loss_streak > self.loss_streak:
            self.loss_streak = self.current_loss_streak
        print(f"{self.symbol} Stop Loss Hit on {date} for trade started on {trade.open_date}")

        # Close position on Binance
        await self.close_trade(trade)

    async def hit_be(self, trade: Trade, idx: int, date: pd.Timestamp):
        trade.is_closed = True
        trade.close_date = date
        # Assume no profit or loss on BE
        trade.profit += 0.0
        self.total_profit += trade.profit
        if trade.profit >= 0:
            self.profit_trades += 1
            self.current_win_streak += 1
            self.current_loss_streak = 0
            if self.current_win_streak > self.win_streak:
                self.win_streak = self.current_win_streak
        else:
            self.loss_trades += 1
            self.current_loss_streak += 1
            self.current_win_streak = 0
            if self.current_loss_streak > self.loss_streak:
                self.loss_streak = self.current_loss_streak
        print(f"{self.symbol} Break-Even triggered on {date} for trade started on {trade.open_date}")

        # Close position on Binance
        await self.close_trade(trade)

    async def check_entry(self, idx: int, current_bar: pd.Series):
        date = current_bar['datetime']

        # Prevent both long and short trades from being open simultaneously
        active_long = any(trade.side == "LONG" and not trade.is_closed for trade in self.trades)
        active_short = any(trade.side == "SHORT" and not trade.is_closed for trade in self.trades)

        # Long Entry Condition
        if self.is_long_trend and not active_long and not active_short:
            await self.open_trade(idx, current_bar, side="LONG")

        # Short Entry Condition
        elif self.is_short_trend and not active_short and not active_long:
            await self.open_trade(idx, current_bar, side="SHORT")

    async def open_trade(self, idx: int, current_bar: pd.Series, side: str):
        entry_price = current_bar['close']
        date = current_bar['datetime']

        if side == "LONG":
            if self.settings.fixed_stop:
                sl_price = entry_price * (1 - self.settings.sl_percent / 100)
            else:
                sl_price = current_bar['fib_786'] * (1 - self.settings.sl_percent / 100)
            tp1_price = entry_price * (1 + self.settings.tp1_percent / 100)
            tp2_price = entry_price * (1 + self.settings.tp2_percent / 100)
            tp3_price = entry_price * (1 + self.settings.tp3_percent / 100)
            tp4_price = entry_price * (1 + self.settings.tp4_percent / 100)
            # Determine break-even price based on target
            if self.settings.break_even_target == "1":
                break_even_price = tp1_price
            elif self.settings.break_even_target == "2":
                break_even_price = tp2_price
            elif self.settings.break_even_target == "3":
                break_even_price = tp3_price
            else:
                break_even_price = tp4_price
        else:  # SHORT
            if self.settings.fixed_stop:
                sl_price = entry_price * (1 + self.settings.sl_percent / 100)
            else:
                sl_price = current_bar['fib_236'] * (1 + self.settings.sl_percent / 100)
            tp1_price = entry_price * (1 - self.settings.tp1_percent / 100)
            tp2_price = entry_price * (1 - self.settings.tp2_percent / 100)
            tp3_price = entry_price * (1 - self.settings.tp3_percent / 100)
            tp4_price = entry_price * (1 - self.settings.tp4_percent / 100)
            # Determine break-even price based on target
            if self.settings.break_even_target == "1":
                break_even_price = tp1_price
            elif self.settings.break_even_target == "2":
                break_even_price = tp2_price
            elif self.settings.break_even_target == "3":
                break_even_price = tp3_price
            else:
                break_even_price = tp4_price

        # Calculate order quantity
        quantity = self.calculate_order_quantity(entry_price)
        if quantity <= 0:
            print(f"{self.symbol} Quantity is too small to place an order.")
            return

        # Place order on Binance Testnet
        order = await self.place_order(
            side=SIDE_BUY if side == "LONG" else SIDE_SELL,
            quantity=quantity,
            order_type=ORDER_TYPE_MARKET
        )

        if order:
            # Update trade information
            new_trade = Trade(
                start_bar_index=idx,
                side=side,
                entry_price=round(entry_price, 8),
                sl_price=round(sl_price, 8),
                tp1_price=round(tp1_price, 8),
                tp1_percent_fix=self.settings.tp1_percent_fix,
                tp2_price=round(tp2_price, 8),
                tp2_percent_fix=self.settings.tp2_percent_fix,
                tp3_price=round(tp3_price, 8),
                tp3_percent_fix=self.settings.tp3_percent_fix,
                tp4_price=round(tp4_price, 8),
                tp4_percent_fix=self.settings.tp4_percent_fix,
                break_even_price=round(break_even_price, 8),
                risk_percent=self.settings.risk_percent,
                open_date=date,
                order_id=order['orderId'],
                quantity=quantity
            )
            self.trades.append(new_trade)
            self.trade_count += 1
            if self.first_trade_date is None:
                self.first_trade_date = date
            print(f"{self.symbol} New {side} trade opened on {date} at Entry Price: {entry_price:.8f}")
        else:
            print(f"{self.symbol} Order failed and trade was not opened.")

    def calculate_order_quantity(self, price):
        # Calculate the quantity based on risk management
        # For simplicity, let's assume we use a fixed amount per trade
        risk_amount = self.dep * (self.settings.risk_percent / 100)
        quantity = risk_amount / price
        # Adjust quantity to match Binance's requirements
        quantity = self.round_step_size(quantity, self.lot_size)
        return quantity

    async def place_order(self, side, quantity, order_type=ORDER_TYPE_MARKET):
        try:
            print(f"{self.symbol} Placing {order_type} order for {quantity} as {side}")
            order = await self.client.create_order(
                symbol=self.symbol,
                side=side,
                type=order_type,
                quantity=quantity
            )
            print(f"{self.symbol} Order placed: {order}")
            return order
        except BinanceAPIException as e:
            # Error handling
            print(f"{self.symbol} Binance API Exception: {e}")
            return None
        except BinanceOrderException as e:
            # Error handling
            print(f"{self.symbol} Binance Order Exception: {e}")
            return None

    async def close_trade(self, trade: Trade):
        # Determine the side to close the trade
        side = SIDE_SELL if trade.side == "LONG" else SIDE_BUY
        quantity = trade.quantity * (trade.position_size_left / 100)
        quantity = self.round_step_size(quantity, self.lot_size)
        if quantity <= 0:
            print(f"{self.symbol} Quantity is too small to place an order.")
            return
        order = await self.place_order(
            side=side,
            quantity=quantity,
            order_type=ORDER_TYPE_MARKET
        )
        if order:
            trade.is_closed = True
            trade.close_date = pd.Timestamp.now()
            print(f"{self.symbol} Trade closed on {trade.close_date}")
        else:
            print(f"{self.symbol} Failed to close the trade.")

    def get_performance_summary(self):
        win_trades = [trade for trade in self.trades if trade.profit > 0]
        loss_trades = [trade for trade in self.trades if trade.profit <= 0]
        win_rate = (len(win_trades) / len(self.trades) * 100) if self.trades else 0
        avg_win = sum(trade.profit for trade in win_trades) / len(win_trades) if win_trades else 0
        avg_loss = sum(trade.profit for trade in loss_trades) / len(loss_trades) if loss_trades else 0

        return {
            "Symbol": self.symbol,
            "Total Trades": len(self.trades),
            "Total Profit (%)": round(self.total_profit, 2),
            "Win Rate (%)": round(win_rate, 2),
            "Average Profit per Win (%)": round(avg_win, 2),
            "Average Loss per Loss (%)": round(avg_loss, 2),
            "Current Deposit": round(self.dep, 2)
        }

    async def get_live_data(self, limit=500):
        try:
            # Fetch historical klines from Binance
            klines = await self.client.get_klines(symbol=self.symbol, interval=Client.KLINE_INTERVAL_5MINUTE, limit=limit)
            # Transform into DataFrame
            data = pd.DataFrame(klines, columns=[
                'open_time', 'open', 'high', 'low', 'close', 'volume',
                'close_time', 'qav', 'num_trades', 'taker_base_vol', 'taker_quote_vol', 'ignore'
            ])
            # Convert numeric columns
            for col in ['open', 'high', 'low', 'close', 'volume']:
                data[col] = data[col].astype(float)
            # Convert time columns
            data['open_time'] = pd.to_datetime(data['open_time'], unit='ms')
            data['close_time'] = pd.to_datetime(data['close_time'], unit='ms')
            data['datetime'] = data['close_time']
            data = data.reset_index(drop=False)
            # Ensure lowercase column names
            data.columns = [col.lower() for col in data.columns]

            # Calculate trend lines with Fibonacci levels
            data['high_line'] = data['high'].rolling(window=int(self.settings.sensitivity)).max()
            data['low_line'] = data['low'].rolling(window=int(self.settings.sensitivity)).min()
            data['channel_range'] = data['high_line'] - data['low_line']
            data['fib_236'] = data['high_line'] - data['channel_range'] * 0.236
            data['fib_382'] = data['high_line'] - data['channel_range'] * 0.382
            data['fib_5'] = data['high_line'] - data['channel_range'] * 0.5
            data['fib_618'] = data['high_line'] - data['channel_range'] * 0.618
            data['fib_786'] = data['high_line'] - data['channel_range'] * 0.786
            data['trend_line'] = data['fib_5']
            return data
        except Exception as e:
            print(f"{self.symbol} Error fetching live data: {e}")
            return None

# Main function
async def main():
    # Replace with your Binance Testnet API keys
    api_key = 'YOUR_TESTNET_API_KEY'
    api_secret = 'YOUR_TESTNET_SECRET_KEY'

    # For testnet
    testnet_api_url = 'https://testnet.binance.vision/'

    # Initialize Binance client
    client = await AsyncClient.create(api_key, api_secret, testnet=True)
    client.API_URL = testnet_api_url

    # List of symbols to trade
    symbols = ['BTCUSDT', 'ETHUSDT', 'DOGEUSDT']  # Add or remove symbols as needed

    # Initialize strategy settings
    settings = StrategySettings(
        sensitivity=17,
        risk_percent=2.5,
        break_even_target="2",
        tp1_percent=1.0,
        tp1_percent_fix=40.0,
        tp2_percent=2.0,
        tp2_percent_fix=30.0,
        tp3_percent=3.0,
        tp3_percent_fix=20.0,
        tp4_percent=4.0,
        tp4_percent_fix=10.0,
        fixed_stop=True,
        sl_percent=1.0
    )

    # Create a strategy instance for each symbol
    strategies: Dict[str, TradingStrategy] = {symbol: TradingStrategy(client, symbol, settings) for symbol in symbols}

    try:
        while True:
            # Record the start time
            start_time = datetime.utcnow()

            # Run the strategies for all symbols
            tasks = [strategy.run_strategy() for strategy in strategies.values()]
            await asyncio.gather(*tasks)

            # Record the end time
            end_time = datetime.utcnow()
            time_taken = (end_time - start_time).total_seconds()

            # Calculate time until the next 5-minute interval
            next_interval = (end_time + timedelta(minutes=5 - end_time.minute % 5)).replace(second=0, microsecond=0)
            sleep_time = (next_interval - end_time).total_seconds()
            sleep_time = sleep_time if sleep_time > 0 else 300  # Fallback to 5 minutes

            print(f"Time taken for strategy execution: {time_taken:.2f} seconds")
            print(f"Sleeping for {sleep_time:.2f} seconds until next interval.")

            # Sleep until the next interval
            await asyncio.sleep(sleep_time)
    except KeyboardInterrupt:
        print("Strategy stopped manually.")
    finally:
        # Close the client session
        await client.close_connection()

    # Print performance summary for each symbol
    print("\n=== Performance Summary ===")
    for strategy in strategies.values():
        summary = strategy.get_performance_summary()
        print(f"\nSymbol: {summary['Symbol']}")
        for key, value in summary.items():
            if key != 'Symbol':
                print(f"{key}: {value}")

# Entry point
if __name__ == "__main__":
    asyncio.run(main())