"""
Symbol parameter auto-calibration.
When a new trading symbol is detected, this module:
  1. Looks up category defaults via classify_symbol()
  2. After 120 bars, recalibrates spread/pip from actual market data
  3. Writes calibrated values to effective_params.json
"""
import json, pathlib, os

def calibrate_symbol_params(symbol: str, save: bool = True) -> dict:
    """Get or calibrate trading parameters for a symbol."""
    from src.symbol_resolver import classify_symbol
    meta = classify_symbol(symbol)

    # Per-category ATR floor (minimum ATR to allow trading, in price units)
    # Derived from typical price * typical daily range % * M5 fraction
    _atr_floor_by_category = {
        "metal": 1.0,     # XAUUSD M5 ~1-5 ATR
        "forex": 0.0002,  # EURUSD M5 ~0.0002-0.0010 ATR
        "crypto": 5.0,    # BTCUSD M5 ~50-500 ATR; floor=5 filters extreme low-vol only
        "index": 2.0,     # US30 M5 ~5-30 ATR
        "commodity": 0.5,
    }

    params = {
        "symbol": str(symbol).strip().upper(),
        "category": meta["category_cn"],
        "pip_size": meta["pip_size"],
        "spread_kill_initial": meta["typical_spread"],
        "max_position_size_initial": _default_lot_for_category(meta["category"]),
        "atr_floor": _atr_floor_by_category.get(meta["category"], 1.0),
    }

    if save:
        appdata = pathlib.Path(os.environ.get("APPDATA","")) / "GoldAutoTrade"
        ep_path = appdata / "config" / "effective_params.json"
        ep = {}
        if ep_path.exists():
            try: ep = json.loads(ep_path.read_text(encoding="utf-8"))
            except: pass
        ep.setdefault("per_symbol", {})[params["symbol"]] = params
        ep_path.parent.mkdir(parents=True, exist_ok=True)
        ep_path.write_text(json.dumps(ep, indent=2, ensure_ascii=False), encoding="utf-8")
    return params

def recalibrate_from_bars(symbol: str, bars: list) -> dict:
    """Recalibrate spread and ATR from actual market bars."""
    if len(bars) < 20:
        return calibrate_symbol_params(symbol)
    spreads = [abs(float(b.get("spread",0))) for b in bars[-120:] if b.get("spread")]
    if not spreads:
        return calibrate_symbol_params(symbol)
    spreads.sort()
    p90_spread = spreads[int(len(spreads) * 0.9)]
    calibrated_spread = max(int(p90_spread * 3), 1)

    params = calibrate_symbol_params(symbol, save=False)
    params["spread_kill_calibrated"] = calibrated_spread
    params["calibrated_at_bars"] = len(bars)

    appdata = pathlib.Path(os.environ.get("APPDATA","")) / "GoldAutoTrade"
    ep_path = appdata / "config" / "effective_params.json"
    ep = {}
    if ep_path.exists():
        try: ep = json.loads(ep_path.read_text(encoding="utf-8"))
        except: pass
    ep.setdefault("per_symbol", {})[params["symbol"]] = params
    ep_path.write_text(json.dumps(ep, indent=2, ensure_ascii=False), encoding="utf-8")
    return params

def _default_lot_for_category(cat: str) -> float:
    return {"metal": 0.05, "forex": 0.10, "crypto": 0.005, "index": 0.05, "commodity": 0.05}.get(cat, 0.05)
