import sys, random, math
out = sys.argv[1]
SANS = "Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif"
MONO = "JetBrains Mono, ui-monospace, Menlo, monospace"
BG="#0b0c10"; CARD="#111319"; LINE="#262a33"; INK="#e9eaee"; DIM="#9a9ca8"; FAINT="#656874"
ACC="#7c84ff"; ACC2="#aeb3ff"; UP="#2ebd85"; DOWN="#f0616d"; WARN="#e8a849"; NIGHT="#151a3a"; DAY="#2a2414"
def svg(w,h,body): return f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {w} {h}" width="{w}" height="{h}" font-family="{SANS}">\n<rect width="{w}" height="{h}" rx="14" fill="{BG}"/>\n{body}\n</svg>\n'
def t(x,y,s,size=14,fill=INK,anchor="start",weight=400,font=None,extra=""):
    f = f' font-family="{font}"' if font else ""
    return f'<text x="{x}" y="{y}" font-size="{size}" fill="{fill}" text-anchor="{anchor}" font-weight="{weight}"{f} {extra}>{s}</text>'

# 1. Timeline: one round trip, ET clock
W,H=960,300
x0,x1=60,900
# 09:30 day1 -> 09:30 day2 = 24h
def X(h): return x0+(h-9.5)/24*(x1-x0)
b=[]
b.append(t(40,42,"One round trip of the overnight hold",18,INK,weight=600))
b.append(t(40,66,"New York time. The strategy holds only while the exchange is shut.",13,DIM))
y=130; hh=56
b.append(f'<rect x="{X(9.5)}" y="{y}" width="{X(16)-X(9.5)}" height="{hh}" rx="8" fill="{DAY}" stroke="#5a4a22"/>')
b.append(f'<rect x="{X(16)}" y="{y}" width="{X(33.5)-X(16)}" height="{hh}" rx="8" fill="{NIGHT}" stroke="#2f3a7a"/>')
b.append(t((X(9.5)+X(16))/2,y+34,"Session (flat)",14,"#e8c77a","middle",600))
b.append(t((X(16)+X(33.5))/2,y+34,"Exchange shut: holding the token",14,ACC2,"middle",600))
for h,l in [(9.5,"09:30"),(12,"12:00"),(16,"16:00"),(20,"20:00"),(24,"00:00"),(28,"04:00"),(33.5,"09:30")]:
    b.append(f'<line x1="{X(h)}" x2="{X(h)}" y1="{y+hh}" y2="{y+hh+8}" stroke="{FAINT}"/>')
    b.append(t(X(h),y+hh+26,l,12,DIM,"middle",font=MONO))
b.append(t(X(9.5),y+hh+46,"day 1",11,FAINT,"middle"))
b.append(t(X(33.5),y+hh+46,"next trading day",11,FAINT,"end"))
# buy marker at 15:50
bx=X(15+50/60); sx=X(33.5)
for x,c,lab,sub,anc in [(bx,UP,"BUY 15:50","signal on the 15:45 bar","end"),(sx,DOWN,"SELL 09:30","first bar of the next session","end")]:
    b.append(f'<line x1="{x}" x2="{x}" y1="{y-30}" y2="{y+hh}" stroke="{c}" stroke-width="2"/>')
    b.append(f'<circle cx="{x}" cy="{y-30}" r="5" fill="{c}"/>')
    b.append(t(x-10,y-40,lab,13,c,anc,700,MONO))
    b.append(t(x-10,y-24,sub,11,DIM,anc))
b.append(t(40,262,"entryMinutes = 15 on 5-minute bars: the 15:45 bar triggers the buy and it fills at 15:50.",12,FAINT,font=MONO))
open(f"{out}/round-trip.svg","w").write(svg(W,282,"\n".join(b)))

# 2. Calendar: Thanksgiving week 2026
W,H=960,380
b=[t(40,42,"Thanksgiving week 2026, as nyseClose() sees it",18,INK,weight=600),
   t(40,66,"A strategy that assumes every weekday closes at 16:00 gets two days wrong.",13,DIM)]
days=[("Mon 23 Nov","16:00",16),("Tue 24 Nov","16:00",16),("Wed 25 Nov","16:00",16),("Thu 26 Nov","closed",None),("Fri 27 Nov","13:00",13)]
# hours 9..17 horizontally
gx0,gx1=200,900
def HX(h): return gx0+(h-9)/(17-9)*(gx1-gx0)
for h in range(9,18):
    b.append(f'<line x1="{HX(h)}" x2="{HX(h)}" y1="96" y2="320" stroke="{LINE}"/>')
    b.append(t(HX(h),340,f"{h:02d}:00",11,FAINT,"middle",font=MONO))
for i,(d,lab,c) in enumerate(days):
    yy=104+i*42
    b.append(t(40,yy+22,d,14,INK,weight=500))
    if c is None:
        b.append(f'<rect x="{HX(9.5)}" y="{yy+4}" width="{HX(16)-HX(9.5)}" height="26" rx="6" fill="none" stroke="{FAINT}" stroke-dasharray="5 5"/>')
        b.append(t((HX(9.5)+HX(16))/2,yy+22,"Thanksgiving: no session",13,DIM,"middle"))
    else:
        col = UP if c==16 else WARN
        b.append(f'<rect x="{HX(9.5)}" y="{yy+4}" width="{HX(c)-HX(9.5)}" height="26" rx="6" fill="{col}" fill-opacity="0.22" stroke="{col}" stroke-opacity="0.6"/>')
        b.append(t(HX(c)+8,yy+22,f"close {lab}" + ("  (early close)" if c==13 else ""),12,col,font=MONO))
# naive marker on Friday at 16:00
yy=104+4*42
b.append(f'<line x1="{HX(16)}" x2="{HX(16)}" y1="{yy-2}" y2="{yy+36}" stroke="{DOWN}" stroke-width="2" stroke-dasharray="4 3"/>')
b.append(t(HX(16)-8,yy+50,"a naive 16:00 exit: 3 hours after the real close",11.5,DOWN,"end"))
open(f"{out}/thanksgiving-week.svg","w").write(svg(W,H,"\n".join(b)))

# 3. Fees bar chart (numbers from the backtest in the post)
W,H=960,392
b=[t(40,42,"The same 30 round trips at two fee levels",18,INK,weight=600),
   t(40,66,"Return after fees, $1,000 a trade, SPY/USDG pool, 10 Sep to 22 Oct 2026.",13,DIM)]
rows=[("Overnight","0.005%",0.30),("Intraday","0.005%",0.26),("Overnight","0.3%",-15.73),("Intraday","0.3%",-16.03)]
zx=470; scale=(900-zx)/17  # px per %
# axis
b.append(f'<line x1="{zx}" x2="{zx}" y1="96" y2="330" stroke="{FAINT}"/>')
for v in [-15,-10,-5,0]:
    x=zx+v*scale*1.0 if v>=0 else zx+v*( (zx-60-150)/17)
for i,(name,fee,v) in enumerate(rows):
    yy=110+i*52 + (16 if i>=2 else 0)
    b.append(t(40,yy+22,name,14,INK,weight=500))
    b.append(t(150,yy+22,f"fee {fee}",12,DIM,font=MONO))
    if v>=0:
        w=v*120
        b.append(f'<rect x="{zx}" y="{yy+4}" width="{w}" height="28" rx="4" fill="{UP}"/>')
        b.append(t(zx+w+8,yy+23,f"+{v:.2f}%",13,UP,weight=600,font=MONO))
    else:
        w=-v*(zx-260)/17
        b.append(f'<rect x="{zx-w}" y="{yy+4}" width="{w}" height="28" rx="4" fill="{DOWN}"/>')
        b.append(t(zx+10,yy+23,f"−{-v:.2f}%",13,DOWN,weight=600,font=MONO))
b.append(t(40,350,"Overnight fees paid: $2.95 at 0.005%, $165.60 at 0.3%.",12.5,DIM,font=MONO))
b.append(t(40,370,"Gains are drawn at a larger scale than losses so both stay readable.",11,FAINT))
open(f"{out}/fees.svg","w").write(svg(W,H,"\n".join(b)))

# 4. News mood gate
W,H=960,330
b=[t(40,42,"How the news gate decides each evening",18,INK,weight=600),
   t(40,66,"The us-news-mood feed runs every weekday at 15:30 New York, before the strategy's buy window.",13,DIM)]
boxes=[("GDELT news index","headlines since the","previous rating",ACC2),
       ("Language model","rates the evening","1 bearish … 99 bullish",ACC2),
       ("Feed history","rating + headlines","+ model, stored",ACC2),
       ("Strategy at 15:45","mood ≥ minMood?","buy · else skip",UP)]
bw,bh,gap=190,110,36; bx0=40
for i,(h1,l1,l2,c) in enumerate(boxes):
    x=bx0+i*(bw+gap); y=110
    b.append(f'<rect x="{x}" y="{y}" width="{bw}" height="{bh}" rx="12" fill="{CARD}" stroke="{c}" stroke-opacity="0.45"/>')
    b.append(t(x+16,y+34,h1,15,INK,weight=600))
    b.append(t(x+16,y+62,l1,12.5,DIM))
    b.append(t(x+16,y+82,l2,12.5,DIM))
    if i<3:
        ax=x+bw+4
        b.append(f'<path d="M{ax} {y+bh/2} h{gap-10}" stroke="{FAINT}" stroke-width="2"/><path d="M{ax+gap-10} {y+bh/2-5} l8 5 l-8 5z" fill="{FAINT}"/>')
b.append(t(40,262,"Presets",12,FAINT,weight=600))
for i,(n,v) in enumerate([("always","0"),("neutral or better","40"),("bullish only","61")]):
    x=110+i*250
    b.append(f'<rect x="{x}" y="246" width="232" height="24" rx="12" fill="{ACC}" fill-opacity="0.12" stroke="{ACC}" stroke-opacity="0.35"/>')
    b.append(t(x+14,263,f"{n}: minMood {v}",12,ACC2,font=MONO))
b.append(t(40,306,"A backtest reads the stored history, so it sees exactly what a live run would have seen that day.",12,FAINT))
open(f"{out}/news-gate.svg","w").write(svg(W,H,"\n".join(b)))
