# app/src/trading/market_analysis/indicators.py

from __future__ import annotations

from src.integrations.exchange.models import Kline


def ema(values: list[float], period: int) -> float | None:
    if period <= 0 or len(values) < period:
        return None

    multiplier = 2 / (period + 1)
    current = sum(values[:period]) / period

    for value in values[period:]:
        current = (value - current) * multiplier + current

    return current


def atr(candles: list[Kline], period: int = 14) -> float | None:
    if period <= 0 or len(candles) < period + 1:
        return None

    true_ranges: list[float] = []

    for previous, current in zip(candles, candles[1:]):
        high_low = current.high_price - current.low_price
        high_close = abs(current.high_price - previous.close_price)
        low_close = abs(current.low_price - previous.close_price)

        true_ranges.append(max(high_low, high_close, low_close))

    if len(true_ranges) < period:
        return None

    recent = true_ranges[-period:]
    return sum(recent) / period


def rsi(values: list[float], period: int = 14) -> float | None:
    if period <= 0 or len(values) < period + 1:
        return None

    gains: list[float] = []
    losses: list[float] = []

    recent = values[-(period + 1):]

    for previous, current in zip(recent, recent[1:]):
        change = current - previous

        if change > 0:
            gains.append(change)
            losses.append(0.0)
        else:
            gains.append(0.0)
            losses.append(abs(change))

    average_gain = sum(gains) / period
    average_loss = sum(losses) / period

    if average_loss == 0:
        return 100.0

    rs = average_gain / average_loss
    return 100 - (100 / (1 + rs))