#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""V3 黄金双模式 — 与TDX公式逐位对齐的Python实现
融合：V1(多方/空方力度) × V2(波动率状态机+吸货线+二段式卖点) + ATR吊灯止损
"""
import numpy as np
import pandas as pd

def _ema(X, N):
    out = np.empty_like(X, dtype=np.float64)
    out[0] = X[0]
    m = 2.0 / (N + 1)
    for i in range(1, len(X)):
        out[i] = X[i] * m + out[i - 1] * (1 - m)
    return out

def _sma(X, N, M):
    out = np.empty_like(X, dtype=np.float64)
    out[0] = X[0]
    for i in range(1, len(X)):
        out[i] = (X[i] * M + out[i - 1] * (N - M)) / N
    return out

def _rmin(X, N):
    return pd.Series(X).rolling(N, min_periods=1).min().values

def _rmax(X, N):
    return pd.Series(X).rolling(N, min_periods=1).max().values

def _cross_up(A, B):
    out = np.zeros(len(A), dtype=bool)
    out[1:] = (A[1:] >= B[1:]) & (A[:-1] < B[:-1])
    return out

def _cross_dn(A, B):
    out = np.zeros(len(A), dtype=bool)
    out[1:] = (A[1:] <= B[1:]) & (A[:-1] > B[:-1])
    return out

def _barslast(x):
    out = np.full(len(x), 999999.0)
    last = -1
    for i in range(len(x)):
        if x[i]:
            last = i
        if last >= 0:
            out[i] = i - last
    return out

def _ref(X, k):
    out = X.copy()
    if k > 0:
        out[k:] = X[:-k]
        out[:k] = X[0]
    return out

def _filter_signal(sig, n=3):
    """FILTER近似: 信号触发后n根K线内不重复"""
    out = sig.copy()
    cooldown = 0
    for i in range(len(out)):
        if cooldown > 0:
            out[i] = False
            cooldown -= 1
        elif out[i]:
            cooldown = n
    return out


def compute_v3(C, H, L, O):
    """V3黄金双模式信号计算
    返回 dict(buy, tp_warn, sell, trail_stop, C7, C9, low_vol, buy_mode)
    buy_mode: 'bottom'=抄底买, 'trend'=趋势买
    """
    n = len(C)
    ar = np.arange(n)

    # ===== 1. 波动率与状态机 (V2) =====
    GATE = 3.5
    SB = 120

    B1 = np.minimum(C, O)
    B2 = np.where(B1 > 0, (B1 - L) / L * 100, 0)
    B3 = np.where(ar > 0, (C - _ref(C, 1)) / _ref(C, 1) * 100, 0)
    B4 = np.where(ar > 0, (O - _ref(C, 1)) / _ref(C, 1) * 100, 0)
    B5 = np.where(O > 0, (C - O) / O * 100, 0)
    B6 = np.maximum(C, O)
    B7 = np.where(B6 > 0, (H - B6) / B6 * 100, 0)
    C2 = np.maximum(np.maximum(np.maximum(np.maximum(B3, B4), B5),
                                np.maximum(B7, B2)),
                    np.maximum(B7 + B2, np.maximum(B5 + B7, B5 + B2))) * 1.2

    AVGVOL = np.where(ar < 20,
                       np.cumsum(C2) / (ar + 1),
                       pd.Series(C2).rolling(20, min_periods=1).mean().values)

    UP_T = GATE + 0.5
    DN_T = GATE
    BU = _barslast(AVGVOL > UP_T)
    BD = _barslast(AVGVOL < DN_T)
    st_low = BU >= BD
    enough = ar >= SB
    low_vol = np.where(enough, st_low, AVGVOL < GATE)

    # ===== 2. 吸货线 (V2) =====
    pL = np.roll(L, 1)
    pL[0] = L[0]
    A2 = _sma(np.abs(L - pL), 3, 1)
    A3 = _sma(np.maximum(L - pL, 0), 3, 1)
    A4 = np.where(A3 > 0.000001, A2 / A3 * 100, 100)
    A5 = _ema(A4 * 10, 3)
    A6 = np.where(low_vol, _rmin(L, 26), _rmin(L, 21))
    A7 = np.where(low_vol, _rmax(A5, 26), _rmax(A5, 21))
    A8 = np.where(L <= A6, (A5 + A7 * 2) / 2, 0)
    xihuo_line = np.minimum(_ema(A8, 3) / 618.0, 25)

    # ===== 3. 摆动主图 C7/C9 (V2) =====
    C5 = (2 * C + H + L) / 4
    RLL = _rmin(L, 34)
    RHL = _rmax(H, 34)
    RGL = RHL - RLL
    RSVL = np.where(RGL > 0.000001, (C5 - RLL) / np.where(RGL <= 0, 1, RGL) * 100, 50)
    C7L = np.where(RGL > 0.000001, _ema(RSVL, 13), 50)

    RL2 = _rmin(L, 21)
    RH2 = _rmax(H, 21)
    RG2 = RH2 - RL2
    RSVH = np.where(RG2 > 0.000001, (C5 - RL2) / np.where(RG2 <= 0, 1, RG2) * 100, 50)
    C7H = np.where(RG2 > 0.000001, _ema(RSVH, 11), 50)

    C7 = np.where(low_vol, C7L, C7H)
    C9 = _ema(0.667 * _ref(C7, 1) + 0.333 * C7, 2)

    # ===== 4. 力度线 (V1新增) =====
    # 空方力度
    HH55 = _rmax(H, 55)
    LL55 = _rmin(L, 55)
    R55 = HH55 - LL55
    bear_str = np.where(R55 > 0.000001, 100 * (HH55 - C) / R55, 50)

    # 多方力度: 3*SMA(rsv27,5,1) - 2*SMA(SMA(rsv27,5,1),3,1)
    HH27 = _rmax(H, 27)
    LL27 = _rmin(L, 27)
    R27 = HH27 - LL27
    rsv27 = np.where(R27 > 0.000001, (C - LL27) / np.where(R27 <= 0, 1, R27) * 100, 50)
    sma1 = _sma(rsv27, 5, 1)
    sma2 = _sma(sma1, 3, 1)
    bull_str = 3 * sma1 - 2 * sma2

    strong_trend = bear_str <= 35

    # ===== 5. ATR与吊灯止损 (V3新增) =====
    TR1 = np.maximum(np.maximum(H - L, np.abs(H - _ref(C, 1))), np.abs(L - _ref(C, 1)))
    ATR14 = _sma(TR1, 14, 1)
    trail_line = _rmax(H, 15) - 3 * ATR14

    # ===== 6. 买点 (V3双模式) =====
    xih_active = (xihuo_line > 0.001) | (_ref(xihuo_line, 1) > 0.001) | (_ref(xihuo_line, 2) > 0.001)
    VT = np.where(low_vol, 2.5, 3.5)
    vol_pass = C2 >= VT

    # 抄底买: 吸货+C7上穿C9+波动达标+非强趋势+空方力度<=92
    bottom_buy = xih_active & _cross_up(C7, C9) & vol_pass & (~strong_trend) & (bear_str <= 92)

    # 趋势买: 多方力度上穿40 + 强趋势 + C7>C9
    trend_buy = _cross_up(bull_str, np.full(n, 40.0)) & strong_trend & (C7 > C9)

    # 合并 + FILTER(3根冷却)
    raw_buy = bottom_buy | trend_buy
    buy = _filter_signal(raw_buy, 3)

    # 买点模式标记
    buy_mode = np.where(bottom_buy, 'bottom', np.where(trend_buy, 'trend', ''))

    # ===== 7. 卖点 T/S (V3优化) =====
    H13 = _rmax(H, 13)
    H11 = _rmax(H, 11)
    C13 = _rmax(C7, 13)
    C11 = _rmax(C7, 11)

    pnh = np.where(low_vol,
                    (H == H13) & (_ref(H, 1) < _ref(H13, 1)),
                    (H == H11) & (_ref(H, 1) < _ref(H11, 1)))
    inh = np.where(low_vol, C7 < _ref(C13, 1), C7 < _ref(C11, 1))
    top_div = pnh & inh & (C7 > 65)

    golden_tp = ((C - _rmin(L, 20)) / np.where(_rmax(H, 20) - _rmin(L, 20) > 0.000001,
                  _rmax(H, 20) - _rmin(L, 20), 1)) >= np.where(low_vol, 0.618, 0.5)

    # 止盈预警: (黄金位+顶背离) OR (C7>80/83且回落)
    tp_warn = (golden_tp & top_div) | ((C7 > np.where(low_vol, 80, 83)) & (_ref(C7, 1) > C7))

    # 终卖: C9下穿C7, C7>55/60
    death_cross_sell = _cross_dn(C9, C7) & (C7 > np.where(low_vol, 60, 55))

    # V3新增: 卖出时排除强趋势区
    sell_signal = death_cross_sell | (tp_warn & (~strong_trend))

    # 吊灯止损: 收盘跌破吊灯线无条件清仓
    trail_stop = C < trail_line

    # 最终卖出 = sell_signal | trail_stop
    sell = sell_signal | trail_stop

    return dict(
        buy=buy, tp_warn=tp_warn, sell=sell,
        trail_stop=trail_stop, sell_signal=sell_signal,
        C7=C7, C9=C9, low_vol=low_vol, C2=C2,
        buy_mode=buy_mode,
        bear_str=bear_str, bull_str=bull_str,
        strong_trend=strong_trend, ATR14=ATR14, trail_line=trail_line,
    )
