import pandas as pd
import numpy as np
import pandas_ta as ta

# Read the CSV file
df = pd.read_csv("Data/BTCUSDT_5m.csv")

df = df[["Open Time", "Open", "High", "Low", "Close", "Volume"]]
df = df.rename(columns={"Open Time": "Datetime"})
df = df.set_index(pd.DatetimeIndex(df["Datetime"]))

# Drop the 'Datetime' column
df = df.drop(columns=["Datetime"])

# Convert to all values to log values
df["Log_Open"] = np.log(df["Open"])
df["Log_High"] = np.log(df["High"])
df["Log_Low"] = np.log(df["Low"])
df["Log_Close"] = np.log(df["Close"])

# Calculate ATR
df["ATR"] = ta.atr(high=df.Log_High, low=df.Log_Low, close=df.Log_Close, length=16)
df.dropna(inplace=True)

df["+4ATR"] = df.Log_Close + 4 * df.ATR
df["-1ATR"] = df.Log_Close - df.ATR


# --- Backtesting Function ---
def backtest_strategy(df, risk_percentage):
    """
    Backtests the described trading strategy.

    Args:
      df: DataFrame containing price data and calculated indicators.
      risk_percentage: Percentage of capital to risk on each trade (e.g., 0.02 for 2%).

    Returns:
      pandas.DataFrame: DataFrame with backtesting results including trade details.
    """

    # Initialize variables
    initial_capital = 10000  # Starting capital (example)
    capital = initial_capital
    position_size = 0
    open_trades = []
    trade_history = []

    # Iterate through each row (bar) of the DataFrame
    for i in range(len(df)):
        # Randomly decide if opening a new trade (simulating random entry)
        if np.random.rand() < 0.10:  # Adjust probability for trade frequency
            # Calculate position size based on risk and ATR
            entry_price = df["Close"].iloc[i]
            stop_loss_price = np.exp(df["-1ATR"].iloc[i])
            take_profit_price = np.exp(df["+4ATR"].iloc[i])
            risk_per_share = (entry_price - stop_loss_price) / entry_price
            #   position_size = (risk_percentage * capital) / risk_per_share
            position_size = (risk_percentage) / risk_per_share

            # Open the trade and store details
            open_trades.append(
                {
                    "Entry Time": df.index[i],
                    "Entry Price": entry_price,
                    "Position Size": position_size,
                    "Stop Loss": stop_loss_price,
                    "Take Profit": take_profit_price,
                }
            )

        # Check for open trades and process exits
        for trade in open_trades:
            # Check for stop loss hit
            if df["Close"].iloc[i] <= trade["Stop Loss"]:
                capital += (
                    (df["Close"].iloc[i] - trade["Entry Price"])
                    / trade["Entry Price"]
                    * trade["Position Size"]
                )
                trade["Exit Time"] = df.index[i]
                trade["Exit Price"] = df["Close"].iloc[i]
                trade["Profit"] = (
                    (df["Close"].iloc[i] - trade["Entry Price"])
                    / trade["Entry Price"]
                    * trade["Position Size"]
                )
                trade_history.append(trade)
                open_trades.remove(trade)

            # Check for take profit hit
            elif df["Close"].iloc[i] >= trade["Take Profit"]:
                capital += (
                    (df["Close"].iloc[i] - trade["Entry Price"])
                    / trade["Entry Price"]
                    * trade["Position Size"]
                )
                trade["Exit Time"] = df.index[i]
                trade["Exit Price"] = df["Close"].iloc[i]
                trade["Profit"] = (
                    (df["Close"].iloc[i] - trade["Entry Price"])
                    / trade["Entry Price"]
                    * trade["Position Size"]
                )
                trade_history.append(trade)
                open_trades.remove(trade)

    # Create a DataFrame from the trade history
    trade_df = pd.DataFrame(trade_history)

    return trade_df


# # --- Run the Backtest ---
# results_df = backtest_strategy(
#     df.copy(), risk_percentage=1
# )  # Use a copy of the DataFrame

# # print(results_df)

# # --- Analyze and Visualize Results (Example) ---
# print("Total Trades:", len(results_df))
# print("Profitable Trades:", len(results_df[results_df["Profit"] > 0]))
# print("Losing Trades:", len(results_df[results_df["Profit"] < 0]))
# print("Total Profit:", results_df["Profit"].sum())


total_profits = []
for i in range(30):
    results_df = backtest_strategy(df.copy(), risk_percentage=1)
    total_profits.append(results_df["Profit"].sum())

print("Mean total profit: ", np.array(total_profits).mean())
print("Std total profit: ", np.array(total_profits).std())


I made some statistical analysis, and on the data I should have a 76% of take profits and 24% of stop losses, and with a 1:4 ratio I should be profitable. Improve the logic of this code, because with the current backtests I don't see results aligned with the statistical analysis.