"""TRACK D — ROBUST WALK-FORWARD TREND PORTFOLIO (BTC+ETH), vol-targeted + leverage.

Thesis under test: trend-following's real value in crypto is DRAWDOWN REDUCTION vs
buy & hold (it sidesteps crashes). That lower DD lets us apply LEVERAGE and DIVERSIFY
across BTC+ETH to build a deployable, risk-adjusted EARNING system, even if each single
signal has only a modest Sharpe. Question: does a properly-built, anti-overfit trend
portfolio actually EARN robustly across regimes 2018-2026?

METHOD (strict, honest):
  * NO LOOK-AHEAD. We build equity directly from a TARGET-POSITION series.
      - target[i] is decided using ONLY data <= close[i].
      - target[i] is HELD during the next bar (close[i] -> close[i+1]).
      - bar return r[t] = close[t]/close[t-1] - 1  (uses close[t], close[t-1]; both <= t).
      - pnl on bar t = target[t-1] * r[t]            (shift positions by 1 -> no leakage).
      - fees: fee_per_side * |target[t-1] - target[t-2]| (turnover cost, charged on rebalances).
    This is the harness's documented "build your own equity from a position series" path.
  * VOL-TARGETING: position = directional_signal * (target_vol / realized_vol), capped at
    leverage. realized_vol uses past returns only (rolling std up to close[i]). This is the
    main lever — it lets a modest signal run at a controlled risk level.
  * WALK-FORWARD / MULTI-REGIME: per-year returns for ALL years 2018-2026. Plus an explicit
    EARLY (2018-2021) tune / LATE (2022-2026) confirm split. ONE robust param set, both assets.
  * PORTFOLIO: equal-weight BTC+ETH sleeves, rebalanced each bar. Report combined Sharpe/DD/CAGR.
  * GRID ROBUSTNESS: chosen config must be positive across a neighborhood AND across regimes.
  * FEE & LEVERAGE SWEEP: fee/side 0.0005..0.002 (0.10..0.40% RT); leverage cap 1x..3x.

Run:  uv run python scripts/research/trackD_trendport.py
"""
from __future__ import annotations

import sys
from pathlib import Path

import numpy as np
import pandas as pd

sys.path.insert(0, str(Path(__file__).resolve().parents[2]))

from src.backtest.harness import load

ASSETS = ["BTC", "ETH"]
TF = "1h"
BARS_PER_YEAR = 24 * 365.25          # 1h bars
FEE_SIDE = 0.0005                    # 0.05% per side = 0.10% round trip (Deribit taker)

# horizons in 1h bars ~ 1 / 3 / 6 "months" (30d months)
H1, H3, H6 = 30 * 24, 90 * 24, 180 * 24


# ---------------------------------------------------------------------------
# Core building blocks (all <= close[i])
# ---------------------------------------------------------------------------
def simple_returns(c: np.ndarray) -> np.ndarray:
    r = np.zeros(len(c))
    r[1:] = c[1:] / c[:-1] - 1.0
    return r


def realized_vol(r: np.ndarray, win: int) -> np.ndarray:
    """Annualized realized vol from bar returns up to and including i (no leakage)."""
    vol = pd.Series(r).rolling(win, min_periods=win // 2).std().values
    return vol * np.sqrt(BARS_PER_YEAR)


def sig_tsmom_blend(c: np.ndarray, horizons=(H1, H3, H6)) -> np.ndarray:
    """Multi-horizon TSMOM: average of sign(close[i]/close[i-h]-1) over horizons -> [-1,1]."""
    n = len(c)
    acc = np.zeros(n)
    cnt = np.zeros(n)
    for h in horizons:
        s = np.full(n, np.nan)
        s[h:] = np.sign(c[h:] / c[:-h] - 1.0)
        valid = np.isfinite(s)
        acc[valid] += s[valid]
        cnt[valid] += 1
    out = np.zeros(n)
    nz = cnt > 0
    out[nz] = acc[nz] / cnt[nz]
    return out


def sig_ma_slope(c: np.ndarray, span: int, slope_win: int = 24) -> np.ndarray:
    """Sign of the slope of an EMA: ema[i] vs ema[i-slope_win]. -> {-1,0,+1}."""
    ema = pd.Series(c).ewm(span=span, adjust=False).mean().values
    n = len(c)
    out = np.zeros(n)
    out[slope_win:] = np.sign(ema[slope_win:] - ema[:-slope_win])
    return out


def sig_donchian_state(c, h, l, n_break: int, n_exit: int) -> np.ndarray:
    """Donchian breakout with trailing (channel) stop, returns a stateful {-1,0,+1} series.
    Long when close[i] > prior n_break high; exit/flip via prior n_exit low channel (trailing).
    Detection uses prior-window extremes EXCLUDING current bar (shift 1) and close[i] -> honest."""
    hh = pd.Series(h).rolling(n_break).max().shift(1).values
    ll = pd.Series(l).rolling(n_break).min().shift(1).values
    xh = pd.Series(h).rolling(n_exit).max().shift(1).values   # trailing exit for shorts
    xl = pd.Series(l).rolling(n_exit).min().shift(1).values   # trailing exit for longs
    n = len(c)
    state = np.zeros(n)
    pos = 0
    for i in range(n):
        if not np.isfinite(hh[i]):
            state[i] = 0
            continue
        if pos == 1:
            if c[i] < xl[i]:
                pos = 0
        elif pos == -1:
            if c[i] > xh[i]:
                pos = 0
        if pos == 0:
            if c[i] > hh[i]:
                pos = 1
            elif c[i] < ll[i]:
                pos = -1
        state[i] = pos
    return state


# ---------------------------------------------------------------------------
# Position construction (vol-targeting + leverage cap + long/flat option)
# ---------------------------------------------------------------------------
def build_target(direction: np.ndarray, vol: np.ndarray, target_vol: float,
                 leverage: float, long_only: bool) -> np.ndarray:
    """target[i] = direction[i] * (target_vol / vol[i]), clipped to [-leverage, leverage].
    direction[i] in [-1,1]; vol[i] annualized realized vol (<= close[i]). long_only clips <0 to 0."""
    d = direction.copy()
    if long_only:
        d = np.clip(d, 0, None)
    scal = np.where((vol > 0) & np.isfinite(vol), target_vol / vol, 0.0)
    tgt = d * scal
    tgt = np.clip(tgt, -leverage, leverage)
    tgt[~np.isfinite(tgt)] = 0.0
    return tgt


def equity_from_target(target: np.ndarray, r: np.ndarray, fee_side: float):
    """Build equity from a target-position series with NO look-ahead.
    pos held during bar t = target[t-1]; pnl[t] = target[t-1]*r[t]; fee on turnover."""
    n = len(target)
    pos_held = np.zeros(n)
    pos_held[1:] = target[:-1]                # held during bar t = decided at close[t-1]
    gross = pos_held * r
    turn = np.abs(np.diff(pos_held, prepend=0.0))
    net = gross - fee_side * turn
    net[0] = 0.0
    net = np.clip(net, -0.99, None)           # cannot lose more than capital on a bar
    equity = np.cumprod(1.0 + net)
    return equity, net


# ---------------------------------------------------------------------------
# Metrics
# ---------------------------------------------------------------------------
def metrics(equity: np.ndarray, net: np.ndarray, ts: pd.Series) -> dict:
    rr = net[np.isfinite(net)]
    sharpe = float(np.mean(rr) / np.std(rr) * np.sqrt(BARS_PER_YEAR)) if np.std(rr) > 0 else 0.0
    peak = np.maximum.accumulate(equity)
    dd = float(np.max((peak - equity) / peak))
    span_days = (ts.iloc[-1] - ts.iloc[0]).total_seconds() / 86400
    years = span_days / 365.25
    total = equity[-1] / equity[0]
    cagr = total ** (1 / years) - 1 if years > 0 and total > 0 else -1.0
    eq_s = pd.Series(equity, index=ts)
    yearly = {}
    for y, g in eq_s.groupby(eq_s.index.year):
        if len(g) > 1 and g.iloc[0] > 0:
            yearly[int(y)] = float(g.iloc[-1] / g.iloc[0] - 1)
    daily_2k = (2000 * total - 2000) / span_days if span_days > 0 else 0.0
    return dict(sharpe=sharpe, max_dd=dd, cagr=cagr, total=total - 1,
                yearly=yearly, daily_2k=daily_2k, vol_ann=float(np.std(rr) * np.sqrt(BARS_PER_YEAR)))


def avg_gross(target: np.ndarray) -> float:
    """Average absolute position = average gross leverage actually deployed."""
    t = target[np.isfinite(target)]
    return float(np.mean(np.abs(t))) if len(t) else 0.0


def fmt(m, label):
    return (f"  {label:<34s} ret={m['total']*100:>+9.0f}% CAGR={m['cagr']*100:>+6.1f}% "
            f"Sh={m['sharpe']:>5.2f} DD={m['max_dd']*100:>4.1f}% volA={m['vol_ann']*100:>4.0f}% "
            f"€/d(2k)={m['daily_2k']:>+7.2f}")


# ---------------------------------------------------------------------------
# Strategy assembly
# ---------------------------------------------------------------------------
def make_direction(df: pd.DataFrame, kind: str, params: dict) -> np.ndarray:
    c = df["close"].values.astype(float)
    if kind == "TSMOM":
        return sig_tsmom_blend(c, params.get("horizons", (H1, H3, H6)))
    if kind == "MASLOPE":
        return sig_ma_slope(c, params["span"], params.get("slope_win", 24))
    if kind == "DONCHIAN":
        h = df["high"].values.astype(float)
        l = df["low"].values.astype(float)
        return sig_donchian_state(c, h, l, params["n_break"], params["n_exit"])
    raise ValueError(kind)


def run_asset(df, kind, params, target_vol, leverage, long_only, fee_side=FEE_SIDE):
    c = df["close"].values.astype(float)
    r = simple_returns(c)
    vol = realized_vol(r, params.get("vol_win", 30 * 24))
    direction = make_direction(df, kind, params)
    tgt = build_target(direction, vol, target_vol, leverage, long_only)
    equity, net = equity_from_target(tgt, r, fee_side)
    ts = df["datetime"]
    m = metrics(equity, net, ts)
    m["target"] = tgt
    m["net"] = net
    m["ts"] = ts
    m["equity"] = equity
    return m


def buy_hold(df):
    c = df["close"].values.astype(float)
    r = simple_returns(c)
    equity = np.cumprod(1.0 + np.clip(r, -0.99, None))
    return metrics(equity, r, df["datetime"])


# ---------------------------------------------------------------------------
# Portfolio (equal-weight BTC+ETH, rebalanced each bar on common timestamps)
# ---------------------------------------------------------------------------
def portfolio(net_btc_df, net_eth_df, w=(0.5, 0.5)):
    """Combine two per-bar net-return series aligned on common timestamps."""
    a = pd.Series(net_btc_df["net"], index=net_btc_df["ts"].values)
    b = pd.Series(net_eth_df["net"], index=net_eth_df["ts"].values)
    j = pd.concat([a.rename("a"), b.rename("b")], axis=1, join="inner").fillna(0.0)
    combo = w[0] * j["a"].values + w[1] * j["b"].values
    equity = np.cumprod(1.0 + np.clip(combo, -0.99, None))
    ts = pd.Series(pd.to_datetime(j.index))
    return metrics(equity, combo, ts)


# ---------------------------------------------------------------------------
# Reporting helpers
# ---------------------------------------------------------------------------
ALL_YEARS = list(range(2018, 2027))


def print_yearly_row(label, m):
    cells = []
    for y in ALL_YEARS:
        v = m["yearly"].get(y)
        cells.append("   .   " if v is None else f"{v*100:>+6.0f}%")
    print(f"  {label:<26s} " + " ".join(cells))


def yearly_header():
    print(f"  {'config':<26s} " + " ".join(f"{y:>7d}" for y in ALL_YEARS))


# ---------------------------------------------------------------------------
# Experiments
# ---------------------------------------------------------------------------
def main():
    pd.set_option("display.width", 220)
    dfs = {a: load(a, TF) for a in ASSETS}

    print("=" * 130)
    print("# TRACK D — VOL-TARGETED TREND PORTFOLIO (BTC+ETH, 1h, Deribit certified)")
    print("# Equity built from target-position series; positions shifted +1 bar (no look-ahead);")
    print("# fee = 0.05%/side (0.10% RT) on turnover. Vol-targeting scales by inverse realized vol.")
    print("=" * 130)

    print("\n# BUY & HOLD BENCHMARK (the DD/return bar trend must beat on risk-adjusted basis)")
    yearly_header()
    bh = {}
    for a in ASSETS:
        bh[a] = buy_hold(dfs[a])
        print(fmt(bh[a], f"B&H {a}"))
        print_yearly_row(f"B&H {a} yearly", bh[a])
    bh_port = portfolio({"net": simple_returns(dfs["BTC"]["close"].values), "ts": dfs["BTC"]["datetime"]},
                        {"net": simple_returns(dfs["ETH"]["close"].values), "ts": dfs["ETH"]["datetime"]})
    print(fmt(bh_port, "B&H 50/50 BTC+ETH"))
    print_yearly_row("B&H port yearly", bh_port)

    # ----------------------------------------------------------------------
    # 1. BROAD SCAN: strategies x vol-target x leverage x long-only, per asset & portfolio
    # ----------------------------------------------------------------------
    print("\n" + "=" * 130)
    print("# 1) BROAD SCAN — per-asset & 50/50 portfolio, vol-target=20%, leverage cap 2x")
    print("#    (TSMOM 1-3-6m blend / MA-slope / Donchian-trailing; long-short vs long-flat)")
    print("=" * 130)

    strat_defs = [
        ("TSMOM", dict(horizons=(H1, H3, H6), vol_win=30 * 24)),
        ("MASLOPE", dict(span=200, slope_win=48, vol_win=30 * 24)),
        ("DONCHIAN", dict(n_break=200, n_exit=100, vol_win=30 * 24)),
    ]
    for long_only in (False, True):
        mode = "LONG-FLAT" if long_only else "LONG-SHORT"
        print(f"\n  --- {mode} ---")
        for kind, params in strat_defs:
            sleeves = {}
            for a in ASSETS:
                m = run_asset(dfs[a], kind, params, target_vol=0.20, leverage=2.0, long_only=long_only)
                sleeves[a] = m
                print(fmt(m, f"{kind} {a}"))
            port = portfolio(sleeves["BTC"], sleeves["ETH"])
            print(fmt(port, f"{kind} PORTFOLIO 50/50"))
            print_yearly_row(f"{kind} port yearly", port)

    # ----------------------------------------------------------------------
    # 2. GRID ROBUSTNESS on the portfolio: vol-target x leverage x vol-window
    #    using the multi-horizon TSMOM blend (the most diversified trend signal)
    # ----------------------------------------------------------------------
    print("\n" + "=" * 130)
    print("# 2) GRID ROBUSTNESS — TSMOM 1-3-6m blend, 50/50 portfolio (LONG-SHORT)")
    print("#    Sweep target-vol x leverage-cap. A real config is positive across the neighborhood.")
    print("=" * 130)
    hdr = "  " + "tvol\\lev".ljust(8) + "".join(f"{lev:.0f}x".rjust(26) for lev in (1.0, 1.5, 2.0, 3.0))
    print(hdr)
    grid = {}
    for tvol in (0.10, 0.15, 0.20, 0.30, 0.40):
        row = f"  {tvol*100:>6.0f}%   "
        for lev in (1.0, 1.5, 2.0, 3.0):
            sleeves = {}
            for a in ASSETS:
                sleeves[a] = run_asset(dfs[a], "TSMOM",
                                       dict(horizons=(H1, H3, H6), vol_win=30 * 24),
                                       target_vol=tvol, leverage=lev, long_only=False)
            port = portfolio(sleeves["BTC"], sleeves["ETH"])
            grid[(tvol, lev)] = port
            row += f"  Sh{port['sharpe']:>4.2f} DD{port['max_dd']*100:>3.0f} C{port['cagr']*100:>+4.0f}"
        print(row)

    # ----------------------------------------------------------------------
    # 3. HORIZON-SET robustness (is the 1-3-6m blend a plateau or a lucky combo?)
    # ----------------------------------------------------------------------
    print("\n" + "=" * 130)
    print("# 3) HORIZON-SET ROBUSTNESS — TSMOM blend, portfolio, tvol=20% lev=2x (LONG-SHORT)")
    print("=" * 130)
    horizon_sets = {
        "1m only": (H1,), "3m only": (H3,), "6m only": (H6,),
        "1-3m": (H1, H3), "3-6m": (H3, H6), "1-3-6m": (H1, H3, H6),
        "1-2-4m": (30 * 24, 60 * 24, 120 * 24), "2-4-8m": (60 * 24, 120 * 24, 240 * 24),
    }
    yearly_header()
    for name, hs in horizon_sets.items():
        sleeves = {a: run_asset(dfs[a], "TSMOM", dict(horizons=hs, vol_win=30 * 24),
                                target_vol=0.20, leverage=2.0, long_only=False) for a in ASSETS}
        port = portfolio(sleeves["BTC"], sleeves["ETH"])
        print(fmt(port, f"TSMOM {name}"))
    print()
    for name, hs in horizon_sets.items():
        sleeves = {a: run_asset(dfs[a], "TSMOM", dict(horizons=hs, vol_win=30 * 24),
                                target_vol=0.20, leverage=2.0, long_only=False) for a in ASSETS}
        port = portfolio(sleeves["BTC"], sleeves["ETH"])
        print_yearly_row(f"{name}", port)

    # ----------------------------------------------------------------------
    # 4. WALK-FORWARD: EARLY (<=2021) tune / LATE (>=2022) confirm
    #    Same single param set for BOTH assets; we just split the equity by date.
    # ----------------------------------------------------------------------
    print("\n" + "=" * 130)
    print("# 4) WALK-FORWARD — split portfolio equity into EARLY (2018-2021) vs LATE (2022-2026)")
    print("#    One param set, both assets. Both halves must earn for the edge to be regime-robust.")
    print("=" * 130)
    cfg = dict(kind="TSMOM", params=dict(horizons=(H1, H3, H6), vol_win=30 * 24),
               target_vol=0.20, leverage=2.0, long_only=False)
    sleeves = {a: run_asset(dfs[a], cfg["kind"], cfg["params"], cfg["target_vol"],
                            cfg["leverage"], cfg["long_only"]) for a in ASSETS}
    a = pd.Series(sleeves["BTC"]["net"], index=sleeves["BTC"]["ts"].values)
    b = pd.Series(sleeves["ETH"]["net"], index=sleeves["ETH"]["ts"].values)
    j = pd.concat([a.rename("a"), b.rename("b")], axis=1, join="inner").fillna(0.0)
    combo = 0.5 * j["a"].values + 0.5 * j["b"].values
    idx = pd.to_datetime(j.index)
    for lab, mask in (("EARLY 2018-2021", idx.year <= 2021), ("LATE 2022-2026", idx.year >= 2022)):
        sub = combo[mask]
        eq = np.cumprod(1.0 + np.clip(sub, -0.99, None))
        m = metrics(eq, sub, pd.Series(idx[mask]))
        print(fmt(m, lab))
        print_yearly_row(f"{lab} yearly", m)

    # ----------------------------------------------------------------------
    # 5. FEE & LEVERAGE SWEEP on the headline portfolio config
    # ----------------------------------------------------------------------
    print("\n" + "=" * 130)
    print("# 5) FEE & LEVERAGE SWEEP — TSMOM 1-3-6m blend portfolio, tvol=20%")
    print("=" * 130)
    print("  fee sweep (leverage cap 2x):")
    for fee in (0.0005, 0.00075, 0.001, 0.0015, 0.002):
        sleeves = {a: run_asset(dfs[a], "TSMOM", dict(horizons=(H1, H3, H6), vol_win=30 * 24),
                                target_vol=0.20, leverage=2.0, long_only=False, fee_side=fee)
                   for a in ASSETS}
        port = portfolio(sleeves["BTC"], sleeves["ETH"])
        print(fmt(port, f"fee/side={fee:.5f} (RT={2*fee*100:.2f}%)"))
    print("  leverage sweep (fee 0.05%/side):")
    for lev in (1.0, 1.5, 2.0, 2.5, 3.0):
        sleeves = {a: run_asset(dfs[a], "TSMOM", dict(horizons=(H1, H3, H6), vol_win=30 * 24),
                                target_vol=0.20, leverage=lev, long_only=False)
                   for a in ASSETS}
        port = portfolio(sleeves["BTC"], sleeves["ETH"])
        print(fmt(port, f"leverage cap={lev:.1f}x"))

    # ----------------------------------------------------------------------
    # 6. HEADLINE ROBUST CONFIG — full per-year table + sleeves + portfolio
    # ----------------------------------------------------------------------
    print("\n" + "=" * 130)
    print("# 6) HEADLINE ROBUST CONFIG: TSMOM 1-3-6m blend, vol-target 20%, leverage cap 2x, LONG-SHORT")
    print("=" * 130)
    yearly_header()
    sleeves = {a: run_asset(dfs[a], "TSMOM", dict(horizons=(H1, H3, H6), vol_win=30 * 24),
                            target_vol=0.20, leverage=2.0, long_only=False) for a in ASSETS}
    for a in ASSETS:
        print(fmt(sleeves[a], f"sleeve {a}"))
        print_yearly_row(f"sleeve {a} yearly", sleeves[a])
    port = portfolio(sleeves["BTC"], sleeves["ETH"])
    print(fmt(port, "PORTFOLIO 50/50"))
    print_yearly_row("PORTFOLIO yearly", port)

    # also long-flat headline (deployable variant — no shorts/funding complexity)
    print()
    sleeves_lf = {a: run_asset(dfs[a], "TSMOM", dict(horizons=(H1, H3, H6), vol_win=30 * 24),
                               target_vol=0.20, leverage=2.0, long_only=True) for a in ASSETS}
    port_lf = portfolio(sleeves_lf["BTC"], sleeves_lf["ETH"])
    print(fmt(port_lf, "PORTFOLIO 50/50 LONG-FLAT"))
    print_yearly_row("PORTFOLIO LF yearly", port_lf)

    # ----------------------------------------------------------------------
    # 7. €/DAY ON 2000 — what leverage gets us toward 50/day, and the DD it costs
    # ----------------------------------------------------------------------
    print("\n" + "=" * 130)
    print("# 7) PATH TO ~50 EUR/day on 2000 — the REAL lever is TARGET-VOL, not the leverage cap.")
    print("#    At tvol=20%% on 60-80%% crypto vol, positions stay sub-1x: the leverage cap NEVER binds.")
    print("#    To deploy real leverage you raise target-vol; Sharpe is ~constant, DD scales ~linearly.")
    print("#    'avg gross' = mean |position| = leverage actually used.  (cap fixed at 3x here)")
    print("=" * 130)
    print(f"  {'target_vol':<12s}{'avgGross':>10s}{'CAGR':>9s}{'Sharpe':>9s}{'maxDD':>8s}"
          f"{'€/day(2k,avg)':>16s}{'final/2k':>12s}")
    for tvol in (0.20, 0.40, 0.60, 0.80, 1.00):
        sleeves = {a: run_asset(dfs[a], "TSMOM", dict(horizons=(H1, H3, H6), vol_win=30 * 24),
                                target_vol=tvol, leverage=3.0, long_only=False) for a in ASSETS}
        port = portfolio(sleeves["BTC"], sleeves["ETH"])
        ag = 0.5 * (avg_gross(sleeves["BTC"]["target"]) + avg_gross(sleeves["ETH"]["target"]))
        print(f"  {tvol*100:>8.0f}%   {ag:>9.2f}x{port['cagr']*100:>+8.1f}%{port['sharpe']:>9.2f}"
              f"{port['max_dd']*100:>7.1f}%{port['daily_2k']:>+16.2f}{(1+port['total']):>12.1f}x")
    # steady-state €/day at current capital under headline CAGR
    print("\n  Steady-state €/day implied by headline CAGR (NOT path-dependent), at various capital:")
    sleeves = {a: run_asset(dfs[a], "TSMOM", dict(horizons=(H1, H3, H6), vol_win=30 * 24),
                            target_vol=0.20, leverage=2.0, long_only=False) for a in ASSETS}
    port = portfolio(sleeves["BTC"], sleeves["ETH"])
    g = port["cagr"]
    daily_rate = (1 + g) ** (1 / 365.25) - 1
    for cap in (2000, 5000, 10000, 50000, 100000):
        print(f"    capital={cap:>7d}  ~€/day = {cap*daily_rate:>+8.2f}  (CAGR={g*100:+.1f}%)")
    need = 50.0 / daily_rate if daily_rate > 0 else float("inf")
    print(f"\n  To average ~50 EUR/day at this CAGR you'd need ~{need:,.0f} capital "
          f"(at leverage 2x, maxDD~{port['max_dd']*100:.0f}%).")

    print("\nDONE. See the report/diary for the honest verdict.")


if __name__ == "__main__":
    main()
