"""Illustrative simulation: generate fictional OHLC prices and a trade ledger offline."""
import csv
from decimal import Decimal as D, ROUND_HALF_UP
from pathlib import Path
from datetime import date, timedelta
from random import Random

HERE = Path(__file__).resolve().parent
SIZE, FEE, SLIP = D("1"), D("0.001"), D("0.0005")
COLUMNS = "signal_date,trade_date,buy_price,sell_price,gross_units,fees_units,net_units".split(",")


def simulate(days):
    for previous, signal, trade in zip(days, days[1:], days[2:]):
        if D(signal["close"]) <= D(previous["high"]):
            continue
        buy = D(trade["open"]) * (1 + SLIP)
        sell = D(trade["close"]) * (1 - SLIP)
        gross = SIZE * (sell - buy)
        fees = SIZE * (buy + sell) * FEE
        yield (signal["date"], trade["date"], buy, sell, gross, fees, gross - fees)


def generate_prices():
    """One invented asset, starting at 100 units. No historical inputs or fitted parameters."""
    rng = Random(1741)
    close = 10_000  # integer hundredths of a fictional price unit
    for day in range(60):
        opening = close
        close = opening + rng.randint(-250, 250)
        high = max(opening, close) + rng.randint(1, 80)
        low = min(opening, close) - rng.randint(1, 80)
        label = (date(2030, 1, 1) + timedelta(days=day)).isoformat()
        yield [label, *(D(n) / 100 for n in (opening, high, low, close)), "synthetic"]


def run():
    with (HERE / "prices.csv").open("w", newline="") as f:
        writer = csv.writer(f)
        writer.writerow(["date", "open", "high", "low", "close", "data_type"])
        writer.writerows(generate_prices())
    with (HERE / "prices.csv").open() as f:
        trades = simulate(list(csv.DictReader(f)))
    with (HERE / "trades.csv").open("w", newline="") as f:
        writer = csv.writer(f)
        writer.writerow([*COLUMNS, "data_type"])
        for row in trades:
            writer.writerow([str(x.quantize(D("0.00000001"), rounding=ROUND_HALF_UP))
                             if isinstance(x, D) else x for x in row] + ["synthetic"])


if __name__ == "__main__":
    run()
