import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Fetch historical data for IBEX index
ticker = '^IBEX'
data = yf.download(ticker, start='2023-01-01')

# Convert data to lowercase if MultiIndex
if isinstance(data.columns, pd.MultiIndex):
    data.columns = data.columns.get_level_values(0)

# Parameters
length = 70
mult = 1.2
timeframes = ["5", "15", "60", "240", "1D"]
green = '#00ffbb'
red = '#ff1100'
gray = '#808080'

# Calculate lag
lag = (length - 1) // 2

# Calculate ZLEMA
def ema(data, period):
    alpha = 2 / (period + 1)
    ema_values = np.zeros_like(data)
    ema_values[0] = data[0]
    for i in range(1, len(data)):
        ema_values[i] = alpha * data[i] + (1 - alpha) * ema_values[i - 1]
    return ema_values

# Ensure src has enough data points
if len(data) < length:
    raise ValueError("Data length is less than the specified length for calculations.")

# Calculate the source series with lag
src = data['Close'].values
src_with_lag = src + (src - np.roll(src, lag))
src_with_lag[:lag] = src[:lag]  # Fill initial NaN values

# Calculate ZLEMA and store in the DataFrame
data['ZLEMA'] = ema(src_with_lag, length)

# Calculate Volatility
def atr(data, period):
    high = data['High']
    low = data['Low']
    close = data['Close']
    tr = np.maximum(high - low, np.abs(high - np.roll(close, 1)))
    tr = np.maximum(tr, np.abs(low - np.roll(close, 1)))
    atr_values = ema(tr, period)
    return atr_values

volatility = atr(data, length) * mult

# Calculate Trend
data['Trend'] = np.where(data['Close'] > data['ZLEMA'] + volatility, 1, 
                        np.where(data['Close'] < data['ZLEMA'] - volatility, -1, 0))

# Calculate ZLEMA Color
data['ZLEMA_Color'] = np.where(data['Trend'] == 1, green, 
                              np.where(data['Trend'] == -1, red, gray))

# Calculate Upper and Lower Bands
upper = data['ZLEMA'] + volatility
lower = data['ZLEMA'] - volatility

# Update Upper_Band and Lower_Band in the DataFrame
data['Upper_Band'] = upper
data['Lower_Band'] = lower

# Debugging intermediate results
print("First few rows of the DataFrame with calculations:")
print(data.head(20))

# Optional: Plotting the results using matplotlib
plt.figure(figsize=(14, 7))
plt.plot(data.index, data['Close'], label='Close Price', color='blue')
plt.plot(data.index, data['ZLEMA'], label='ZLEMA', color='orange')

# Fill between Upper and Lower Bands
plt.fill_between(data.index, data['Upper_Band'], data['Lower_Band'], color=gray, alpha=0.3, label='Volatility Bands')

# Plot Bullish and Bearish Entries
bullish_entries = (data['Trend'] == 1) & (data['Trend'].shift() == 0)
bearish_entries = (data['Trend'] == -1) & (data['Trend'].shift() == 0)

plt.scatter(data.index[bullish_entries], data['Lower_Band'][bullish_entries], marker='^', color=green, label='Bullish Entry', s=50)
plt.scatter(data.index[bearish_entries], data['Upper_Band'][bearish_entries], marker='v', color=red, label='Bearish Entry', s=50)

plt.title('Zero Lag Trend Signals (MTF) [AlgoAlpha] - IBEX')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.grid(True)
plt.show()

Fix the trend calculation cause is always 0 and that's not the expected value