"""
Hurst/VPIN integration module — provides compact signal generators
for live trading, paper trading, and backtesting.

Live: feeds price tick stream into Hurst dollar bars.
Paper/Backtest: feeds real trade data.
"""

import math, time, numpy as np
from collections import deque


# ═══════════════════════════════════════════════════════════
# 1. Hurst Exponent — R/S on log returns
# ═══════════════════════════════════════════════════════════
def _hurst_rs(returns: list) -> float:
    """R/S estimate from log returns. Returns 0.20–0.80."""
    n = len(returns)
    if n < 32:
        return 0.50
    max_lag = min(n // 2, 64)
    lags = []; rs = []
    for lag in range(4, max_lag):
        segs = n // lag
        if segs < 2: continue
        vals = []
        for s in range(segs):
            seg = returns[s*lag:(s+1)*lag]
            mean = np.mean(seg)
            dev = np.cumsum(seg - mean)
            r = float(np.max(dev) - np.min(dev))
            sd = float(np.std(seg, ddof=1))
            if sd > 1e-12:
                vals.append(r / sd)
        if vals:
            lags.append(np.log(lag))
            rs.append(np.log(np.mean(vals)))
    if len(lags) < 4:
        return 0.50
    slope = float(np.polyfit(lags, rs, 1)[0])
    return max(0.20, min(0.80, slope))


# ═══════════════════════════════════════════════════════════
# 2. Dollar Bar Builder (notional-based)
# ═══════════════════════════════════════════════════════════
class DollarBar:
    def __init__(self, threshold: float = 10000.0):
        self.threshold = threshold
        self.vol = 0.0
        self.buy_vol = 0.0
        self.sell_vol = 0.0
        self.close = 0.0

    def add(self, price: float, notional: float, is_buy: bool):
        self.vol += notional
        if is_buy:
            self.buy_vol += notional
        else:
            self.sell_vol += notional
        self.close = price

    @property
    def ready(self) -> bool:
        return self.vol >= self.threshold

    def emit(self) -> dict:
        total = self.buy_vol + self.sell_vol
        data = {
            "close": self.close,
            "vpin": abs(self.buy_vol - self.sell_vol) / total if total > 1 else 0.0,
            "direction": (self.buy_vol - self.sell_vol) / total if total > 1 else 0.0,
        }
        self.vol = 0.0; self.buy_vol = 0.0; self.sell_vol = 0.0
        return data


# ═══════════════════════════════════════════════════════════
# 3. Hurst/VPIN Signal (price-tick mode for live trading)
# ═══════════════════════════════════════════════════════════
class HurstVPINLive:
    """Lightweight Hurst/VPIN for live price tick stream.
    
    Uses notional bars ($10K) from mid-price changes.
    Each tick adds notional ≈ price * |Δprice| * 100 as volume proxy.
    """
    def __init__(self, threshold: float = 10000.0,
                 hurst_window: int = 128,
                 vpin_window: int = 50,
                 hurst_entry: float = 0.55,
                 vpin_threshold: float = 0.25):
        self.threshold = threshold
        self.vpin_window = vpin_window
        self.hurst_entry = hurst_entry
        self.vpin_threshold = vpin_threshold

        self.bar = DollarBar(threshold)
        self.vpin_buf = deque(maxlen=vpin_window)
        self.vpin_dir_buf = deque(maxlen=vpin_window)
        self.returns = deque(maxlen=hurst_window)
        self.last_close = 0.0
        self.last_price = 0.0

    def feed_price(self, price: float):
        """Feed a mid-price tick. Returns signal dict or None."""
        if self.last_price <= 0:
            self.last_price = price
            return None

        delta = price - self.last_price
        is_buy = delta > 0
        notional = price * abs(delta) * 100  # volume proxy
        self.last_price = price

        self.bar.add(price, notional, is_buy)
        if not self.bar.ready:
            return None

        bar_data = self.bar.emit()

        # VPIN
        self.vpin_buf.append(bar_data["vpin"])
        self.vpin_dir_buf.append(bar_data["direction"])
        vpin = float(np.mean(self.vpin_buf)) if len(self.vpin_buf) >= self.vpin_window else 0.0
        direction = float(np.mean(self.vpin_dir_buf)) if len(self.vpin_dir_buf) >= self.vpin_window else 0.0

        # Hurst
        if self.last_close > 0:
            self.returns.append(math.log(bar_data["close"] / self.last_close))
        self.last_close = bar_data["close"]

        hurst = _hurst_rs(list(self.returns)) if len(self.returns) >= 64 else 0.50

        # Signal
        trending = hurst >= self.hurst_entry
        high_vpin = vpin >= self.vpin_threshold

        if trending and high_vpin:
            if direction > 0.02:
                return {"signal": "BUY", "hurst": round(hurst, 3), "vpin": round(vpin, 3), "direction": round(direction, 3)}
            elif direction < -0.02:
                return {"signal": "SELL", "hurst": round(hurst, 3), "vpin": round(vpin, 3), "direction": round(direction, 3)}

        return None


# ═══════════════════════════════════════════════════════════
# 4. Hurst/VPIN for backtest (full trade data)
# ═══════════════════════════════════════════════════════════
from strategies.hurst_vpin import run_hurst_vpin, HurstVPINSignal

# Expose for easy import
def hurst_vpin_backtest(trades, capital=100.0, size=0.00024):
    return run_hurst_vpin(trades, starting_capital=capital, size=size)
