"""Invented prices for teaching timing and costs, not historical market evidence.

Run with Python 3: python strategies-momentum-example.py
No external packages, market downloads, API keys or file inputs are required.
Each split starts and ends flat. The three-session rule is fixed in advance.
"""

PRICES = [
    100, 101, 103, 102, 105, 107, 106, 108, 110, 109,
    108, 106, 107, 105, 104, 103, 102, 104, 106, 105,
    108, 110, 112, 111, 113, 115, 114, 116, 118, 117,
    115, 112, 109, 110, 107, 105, 104, 106, 108, 107,
    105, 103, 101, 102, 100, 98, 99, 97, 95, 96,
]


def backtest(start, end, cost_bps, mode="momentum", window=3):
    """Return compounded return, signed max drawdown and turnover units.

    At close i-1, use prices no later than i-2 to choose weight for i-1 -> i.
    Charge proportional equity costs before each position change and at exit.
    Target weights are exclusively 0 or 1; flat cash has zero interest.
    """
    if mode not in {"momentum", "buyhold"}:
        raise ValueError("unknown mode")
    if not (window >= 1 and start >= window + 2 and start < end <= len(PRICES)):
        raise ValueError("invalid bounds or insufficient signal history")
    if not (0 <= cost_bps < 10_000):
        raise ValueError("cost must be between 0 and 10,000 basis points")
    previous = turnover = 0
    returns = []
    cost = cost_bps / 10_000
    for i in range(start, end):
        weight = 1 if mode == "buyhold" else int(
            PRICES[i - 2] > PRICES[i - 2 - window]
        )
        change = abs(weight - previous)
        asset_return = PRICES[i] / PRICES[i - 1] - 1
        factor = (1 - cost * change) * (1 + weight * asset_return)
        returns.append(factor - 1)
        turnover += change
        previous = weight
    returns[-1] = (1 + returns[-1]) * (1 - cost * previous) - 1
    turnover += previous
    wealth = peak = 1.0
    drawdown = 0.0
    for ret in returns:
        wealth *= 1 + ret
        peak = max(peak, wealth)
        drawdown = min(drawdown, wealth / peak - 1)
    return wealth - 1, drawdown, turnover


def main():
    print("SYNTHETIC TEACHING DATA; NO HISTORICAL PERFORMANCE CLAIM")
    print("split        model     bps    return   max_dd turnover")
    for label, start, end in [("development", 5, 30), ("heldout", 30, 50)]:
        for mode, bps in [("momentum", 0), ("momentum", 10),
                          ("momentum", 50), ("buyhold", 10)]:
            ret, dd, turnover = backtest(start, end, bps, mode)
            print(f"{label:12} {mode:9} {bps:3} {ret:9.2%} {dd:8.2%} {turnover:8}")
    print("\nWindow sensitivity: diagnostics, not a new model selection")
    for window in [2, 3, 4, 5]:
        ret, dd, turnover = backtest(30, 50, 10, window=window)
        print(f"window={window}: return={ret:.2%}, max_dd={dd:.2%}, turnover={turnover}")


if __name__ == "__main__":
    main()
