Issuer repurchase windows

Buyback edition — last week's paper plus this week's repurchase calendar.

Internet of Events — dated windows, then a scored hold versus sitting in the market. This is not millions of dates per race. Tape

Who this is for

Desks that follow issuer repurchase windows

Same Moneyball method as the weekly grid: measured windows, paper book, no invented tape. This book is only repurchase calendars — not earnings prints, not the weekly mix, not the watch overlay SKU.

Calendar
MONEYBALL
10 Instances Analog event date: Feb. 12, 2010

Cyber Moneyball

Calendar · 2020 Finance Edition analog · not live tape

Asset Holding Period (Days)

1 Trading Day Hold [Purchased at Open to Sold at Close] (10 Instances)

-1Feb 11, 2010
Event Date Feb 12, 2010
0Feb 12, 2010
Asset Purchased at Open Feb 12, 2010
+1Feb 16, 2010
Asset Sold at Close Feb 16, 2010
+2Feb 17, 2010
+3Feb 18, 2010
Pattern History Percent Change Feb 11, 2010 Feb 12, 2010 Feb 16, 2010 Feb 17, 2010 Feb 18, 2010
Win Rate Percent of instances Feb 11, 2010 Feb 12, 2010 Feb 16, 2010 Feb 17, 2010 Feb 18, 2010

Why this window

Tape not hydrated · refusing simulated exceptionalism

Not analog

The band, the names, and the cadence come from measured hold returns on the dated tape. Adding names is their prices summed, not an equal-weight mix. Equal-weight is the sleeve. We do not paint analog Sharpe as a live fact.

Event Basket Sleeve

Tape not hydrated · refusing simulated Sharpe / vs-SPY

Not analog

Sleeve numbers come from SPY (and the names in the basket) daily closes on the dated tape. Fair comparison (exposure-window parity): SPY is in the market only on the same session days as the sleeve. Always-in: SPY buy-and-hold every session from first date to last. Walk-forward is past instances, then later instances. This card does not paint 1.41 / 1.48 as a live fact.

Outperformers
Stock Market Direction Median Return Avg. Return
Names and numbers fill from the live event-date tape when it is on — never a 2020 PDF name list. SPY is the always-in and exposure-parity benchmark when the tape is live.
Object contract

This is the 2020 Finance Edition object (Event Date, Purchased at Close, Sold at Close, Pattern History, Win Rate). When the Internet of Events tape is live, those four slots fill from measured hold returns and win rate on that series — they are not frozen 2010 museum numbers. Sleeve Sharpe / vs-the-market fill from daily closes or we refuse to invent them. This week's grid is scored from historical dates on each event series. Notes never change the ranking. This is not millions of dates per race.

The object above is the house-measured season-end disclosure windows — same sleeve as weekly (QQQ, IWM, SPYG vs SPY). Period grain, not issuer execution days. Live MBBB-* issues hydrate when the mothership archive has them. Analog never invents a repurchase calendar. Weekly grid · Earnings book · Watch overlay

" ); } function renderWeeklyEvent(ev) { const hp = ev.holding_period || {}; const inst = ev.historical_instances || 0; const spec = specFromHp(hp, inst, ev.event_date); const labels = axisLabelsFromSpec(spec); const kind = classifyEventGraphic(ev.category, ev.event_name); const retPad = padSeries(hp.per_bar_avg_returns || [], labels.length); const wrPad = padSeries(hp.per_bar_win_rates || [], labels.length); let html = '
'; html += '
' + identityMarkHtml(kind) + 'MONEYBALL
' + inst + " Instances" + esc(ev.event_date || "") + " · " + esc(ev.category || "") + "
"; html += "

" + esc(ev.event_name || "") + "

"; html += holdingBarHtml(spec); html += patternHistorySvg(labels, hp.per_bar_avg_returns || []); html += winRateSvg(labels, hp.per_bar_win_rates || []); html += unmeasuredNoteHtml(retPad.measured.concat(wrPad.measured)); html += explorerHtml(ev.explorer); var insight = ev.event_insight || (ev.basket_sleeve && ev.basket_sleeve.insight); if (insight) html += eventInsightHtml(insight); if (ev.basket_sleeve) html += basketSleeveHtml(ev.basket_sleeve); html += outperformersTable(ev.outperformers || [], ev.benchmark); return html + "
"; } function renderQuantCard(card) { const inst = card.instance_count || 0; const hp = { per_bar_avg_returns: card.per_bar_avg_returns || [], per_bar_win_rates: card.per_bar_win_rates || [], optimal_hold_bars: card.hold_bars || 1, }; const spec = specFromHp(hp, inst, card.event_date); const labels = axisLabelsFromSpec(spec); const rows = (card.top_symbols || []).map(function (s) { return { symbol: s.symbol, name: s.symbol, market_direction_pct: (s.terminal_win_rate || 0) * 100, median_return_pct: s.terminal_avg_pct, avg_return_pct: s.terminal_avg_pct, }; }); let html = '
'; html += '
' + identityMarkHtml(classifyEventGraphic("", card.event_name || "")) + 'MONEYBALL
'; html += "

" + esc(card.event_name || "") + "

"; var scoreMeta = ""; if (card.identity_plane === "presidential_action") { scoreMeta = "vendor " + (card.vendor_coverage_score != null ? Number(card.vendor_coverage_score).toFixed(2) : "—") + " (coverage, not Q01)"; } else if (card.allocation_eligible && card.moneyball_score != null) { scoreMeta = "Q01 mb " + Number(card.moneyball_score).toFixed(2) + " allocation"; } else if (card.vendor_coverage_score != null) { scoreMeta = "vendor " + Number(card.vendor_coverage_score).toFixed(2) + " (coverage, not Q01)"; } else if (card.moneyball_score != null && Number(card.moneyball_score) > 0) { scoreMeta = "Q01 mb " + Number(card.moneyball_score).toFixed(2); } html += '

' + esc(card.event_date || "") + (scoreMeta ? " · " + esc(scoreMeta) : "") + " · pool " + esc(card.precedent_pool_key || "") + " · N=" + inst + "

"; html += holdingBarHtml(spec); html += patternHistorySvg(labels, hp.per_bar_avg_returns || []); html += winRateSvg(labels, hp.per_bar_win_rates || []); html += unmeasuredNoteHtml( padSeries(hp.per_bar_avg_returns || [], labels.length).measured.concat( padSeries(hp.per_bar_win_rates || [], labels.length).measured ) ); html += explorerHtml(card.explorer); html += outperformersTable(rows, null); return html + "
"; } function fmtPct2(v) { if (v == null || Number.isNaN(Number(v))) return "—"; const n = Number(v); const sign = n > 0 ? "+" : ""; return sign + n.toFixed(2) + "%"; } function fmtPx(v) { if (v == null || Number.isNaN(Number(v))) return "—"; return Number(v).toFixed(2); } function readOverlayTape() { const el = document.getElementById("mb-overlay-tape"); if (!el) return null; try { return JSON.parse(el.textContent || ""); } catch (err) { return null; } } function overlayGeometry(n) { const w = 640; const h = 286; const padL = 72; const padR = 16; const padT = 44; const padB = 78; const plotW = w - padL - padR; const plotH = h - padT - padB; function xAt(i) { if (n <= 1) return padL + plotW / 2; return padL + (i / (n - 1)) * plotW; } function yAt(v, minY, span) { return padT + ((minY + span - v) / span) * plotH; } return { w: w, h: h, padL: padL, padR: padR, padT: padT, padB: padB, plotW: plotW, plotH: plotH, xAt: xAt, yAt: yAt }; } function polylinePts(series, g, minY, span) { const pts = []; for (let i = 0; i < series.length; i += 1) { pts.push(g.xAt(i).toFixed(1) + "," + g.yAt(series[i], minY, span).toFixed(1)); } return pts.join(" "); } function tradeDetailHtml(tape, trade, idx) { if (!trade) { return ( '

Hover or click a shaded window, or a ledger row, for day-by-day closes between entry and exit.

' ); } const legs = trade.legs || []; const sleeveS = trade.sessions || []; const spyS = trade.spy_sessions || []; const nSess = Math.max( sleeveS.length, spyS.length, legs.reduce(function (m, leg) { return Math.max(m, (leg.sessions || []).length); }, 0) ); const headSyms = (tape.trade_symbols || []).slice(); let head = "DateSession" + headSyms .map(function (s) { return "" + esc(s) + "" + esc(s) + " close"; }) .join("") + "SleeveSPYSPY close"; const body = []; for (let i = 0; i < nSess; i += 1) { const s0 = sleeveS[i] || {}; const spy = spyS[i] || {}; const cells = headSyms .map(function (sym) { const leg = legs.filter(function (l) { return l.symbol === sym; })[0]; const sess = ((leg && leg.sessions) || [])[i] || {}; const daily = i === 0 ? "0.00% (entry)" : fmtPct2(sess.daily_pct); return ( '' + daily + '' + fmtPx(sess.close) + "" ); }) .join(""); const sleeveDaily = i === 0 ? "0.00% (entry)" : fmtPct2(s0.daily_pct); const spyDaily = i === 0 ? "0.00% (entry)" : fmtPct2(spy.daily_pct); body.push( "" + esc(s0.date || spy.date || "") + '' + String(i) + "" + cells + '' + sleeveDaily + '' + spyDaily + '' + fmtPx(spy.close) + "" ); } const names = (tape.trade_symbols || []).join(" · "); const corridor = readCorridorTape(); const path = ((corridor && corridor.paths) || []).filter(function (p) { return p && p.event_date === trade.event_date; })[0]; const mfeLine = path ? "MFE " + fmtPct2(path.mfe_terminal) + "MAE " + fmtPct2(path.mae_terminal) + "" : ""; return ( '
' + "

Trade " + String(idx + 1) + " · " + esc(trade.event_date || "") + "

" + '

' + esc(trade.buy_date || "") + " → " + esc(trade.sell_date || "") + " · close-to-close · " + esc(names) + " equal-weight vs SPY same window

" + '

' + "Sleeve " + fmtPct2(trade.return_pct) + "SPY " + fmtPct2(trade.spy_return_pct) + "" + mfeLine + "

" + '
' + head + "" + body.join("") + "
" + '

' + esc(tape.hold_rule || "Close-to-close. Entry session daily is 0% at the entry close.") + "

" ); } function tradesAtIndex(tape, i) { const hits = []; (tape.trades || []).forEach(function (t, idx) { const a = t.buy_i; const b = t.sell_i; if (typeof a === "number" && typeof b === "number" && i >= a && i <= b) { hits.push(idx); } }); if (!hits.length) return []; hits.sort(function (a, b) { const ta = tape.trades[a]; const tb = tape.trades[b]; const wa = (ta.sell_i || 0) - (ta.buy_i || 0); const wb = (tb.sell_i || 0) - (tb.buy_i || 0); if (wa !== wb) return wa - wb; return b - a; }); return hits; } function mountOneOverlay(root, tape, shared) { const dates = tape.dates || []; const eventPct = tape.event_pct || []; const always = tape.always_in_pct || []; const spyEvt = tape.spy_event_pct || []; const n = Math.min(dates.length, eventPct.length, always.length); if (n < 2) return; const ys = eventPct.slice(0, n).concat(always.slice(0, n), spyEvt.slice(0, n)); const ysc = ticksForBaseline(ys, 6); const minY = ysc.min; const span = Math.max(ysc.max - ysc.min, 1e-12); const g = overlayGeometry(n); const f = { w: g.w, h: g.h, padL: g.padL, padR: g.padR, padT: g.padT, padB: g.padB, plotW: g.plotW, plotH: g.plotH }; const xsc = emptyX(Math.max(n - 1, 1)); const yearLabs = []; let prevY = ""; for (let i = 0; i < n; i += 1) { const y = String(dates[i] || "").slice(0, 4); if (y && y !== prevY) { yearLabs.push( '' + esc(y) + "" ); prevY = y; } } const bands = (tape.trades || []) .map(function (t, idx) { if (typeof t.buy_i !== "number" || typeof t.sell_i !== "number") return ""; const x0 = g.xAt(Math.max(0, t.buy_i)); const x1 = g.xAt(Math.min(n - 1, t.sell_i)); const w = Math.max(x1 - x0, 1.2); return ( '' ); }) .join(""); let isMark = ""; const isEnd = tape.is_end_date || ""; const isI = dates.indexOf(isEnd); if (isI >= 0) { const ix = g.xAt(isI); isMark = '' + 'IS'; } const names = (tape.trade_symbols || []).join(" · "); const svg = '' + 'Always in the market vs event windows' + 'Cumulative close-to-close % · ' + esc(names) + " trades · SPY benchmark · hover a window" + axisLayer(f, xsc, ysc, "", "", "%") + isMark + bands + '' + '' + '' + '' + '' + '' + 'Event windows only (flat when out)' + 'SPY same windows' + 'Always in the market (every session)' + yearLabs.join("") + ""; const mount = root.querySelector(".mb-overlay-mount"); const detail = root.querySelector(".mb-trade-window"); if (!mount || !detail) return; mount.innerHTML = '
' + svg + '

Navy is equal-weight ' + esc(names) + " on event holds (flat when out). Gold is SPY on the same hold days — the in-sample comparison. Grey is SPY always-in every session. Shaded bands are trade date windows.

"; const svgEl = mount.querySelector("svg"); const cursor = svgEl.querySelector(".mb-overlay-cursor"); const readout = svgEl.querySelector(".mb-overlay-readout"); const hit = svgEl.querySelector(".mb-overlay-hit"); function indexFromEvent(evt) { const pt = svgEl.createSVGPoint(); pt.x = evt.clientX; pt.y = evt.clientY; const ctm = svgEl.getScreenCTM(); if (!ctm) return -1; const loc = pt.matrixTransform(ctm.inverse()); const t = (loc.x - g.padL) / g.plotW; if (t < -0.02 || t > 1.02) return -1; return Math.max(0, Math.min(n - 1, Math.round(t * (n - 1)))); } function paintBands(active) { svgEl.querySelectorAll(".mb-trade-band").forEach(function (el) { const on = Number(el.getAttribute("data-trade-i")) === active; el.setAttribute("opacity", on ? "0.28" : "0.10"); }); } function showTrade(idx, pin) { const trade = tape.trades[idx]; detail.hidden = false; detail.innerHTML = tradeDetailHtml(tape, trade, idx); paintBands(idx); if (pin) shared.pinned = idx; document.querySelectorAll(".mb-instance-ledger tbody tr").forEach(function (tr) { tr.classList.toggle("is-on", Number(tr.getAttribute("data-trade-i")) === idx); }); if (shared.paintCorridor) shared.paintCorridor(idx); } function onMove(evt) { const i = indexFromEvent(evt); if (i < 0) return; const x = g.xAt(i); cursor.setAttribute("x1", x.toFixed(1)); cursor.setAttribute("x2", x.toFixed(1)); cursor.setAttribute("opacity", "0.55"); const hits = tradesAtIndex(tape, i); const inM = (tape.in_market || [])[i] ? "in window" : "cash / out"; readout.textContent = dates[i] + " · sleeve " + fmtPct2(eventPct[i]) + " · SPY window " + fmtPct2(spyEvt[i]) + " · always-in " + fmtPct2(always[i]) + " · " + inM; if (shared.pinned == null && hits.length) showTrade(hits[0], false); } function onLeave() { cursor.setAttribute("opacity", "0"); if (shared.pinned == null) { paintBands(-1); detail.hidden = true; document.querySelectorAll(".mb-instance-ledger tbody tr").forEach(function (tr) { tr.classList.remove("is-on"); }); } } function onClick(evt) { const i = indexFromEvent(evt); if (i < 0) return; const hits = tradesAtIndex(tape, i); if (!hits.length) { shared.pinned = null; onLeave(); return; } showTrade(hits[0], true); } hit.addEventListener("mousemove", onMove); hit.addEventListener("mouseleave", onLeave); hit.addEventListener("click", onClick); root._mbShowTrade = showTrade; } function bindOverlayKeys(shared, tape) { if (document.documentElement.getAttribute("data-mb-overlay-keys") === "1") return; document.documentElement.setAttribute("data-mb-overlay-keys", "1"); document.addEventListener("keydown", function (ev) { const n = ((tape && tape.trades) || []).length; if (!n) return; const t = ev.target; if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.tagName === "SELECT" || t.isContentEditable)) { return; } if (ev.key === "Escape") { shared.pinned = null; document.querySelectorAll("[data-mb-overlay]").forEach(function (root) { const detail = root.querySelector(".mb-trade-window"); if (detail) { detail.hidden = true; detail.innerHTML = ""; } }); document.querySelectorAll(".mb-instance-ledger tbody tr").forEach(function (tr) { tr.classList.remove("is-on"); }); if (shared.paintCorridor) shared.paintCorridor(-1); return; } if (ev.key !== "ArrowLeft" && ev.key !== "ArrowRight" && ev.key !== "Home" && ev.key !== "End") { return; } ev.preventDefault(); let idx = shared.pinned == null ? 0 : shared.pinned; if (ev.key === "ArrowLeft") idx = Math.max(0, idx - 1); else if (ev.key === "ArrowRight") idx = Math.min(n - 1, idx + 1); else if (ev.key === "Home") idx = 0; else idx = n - 1; shared.pinned = idx; document.querySelectorAll("[data-mb-overlay]").forEach(function (root) { if (root._mbShowTrade) root._mbShowTrade(idx, true); }); if (shared.paintCorridor) shared.paintCorridor(idx); const row = document.querySelector('.mb-instance-ledger tbody tr[data-trade-i="' + idx + '"]'); if (row && row.scrollIntoView) row.scrollIntoView({ block: "nearest" }); }); } function readCorridorTape() { const el = document.getElementById("mb-corridor-tape"); if (!el) return null; try { return JSON.parse(el.textContent || ""); } catch (err) { return null; } } function mountCorridorTape(shared) { const tape = readCorridorTape(); const svg = document.querySelector(".mb-corridor-svg"); if (!tape || !svg) return; const plot = tape.plot || {}; const padL = Number(plot.pad_l || 72); const padR = Number(plot.pad_r || 16); const padT = Number(plot.pad_t || 40); const w = Number(plot.w || 640); const h = Number(plot.h || 292); const plotW = w - padL - padR; const plotH = h - padT - Number(plot.pad_b || 56); const minY = Number(plot.min_y != null ? plot.min_y : -1); const maxY = Number(plot.max_y != null ? plot.max_y : 1); const span = Math.max(maxY - minY, 0.5); const n = (tape.avg || []).length; function xAt(i) { if (n <= 1) return padL + plotW / 2; return padL + (i / (n - 1)) * plotW; } function yAt(v) { return padT + ((maxY - v) / span) * plotH; } function paint(idx) { const sel = svg.querySelector(".mb-corridor-sel"); const readout = svg.querySelector(".mb-corridor-readout"); const path = (tape.paths || [])[idx]; svg.querySelectorAll(".mb-corridor-dot").forEach(function (el) { const on = Number(el.getAttribute("data-trade-i")) === idx; el.setAttribute("opacity", on ? "0.95" : "0.28"); el.setAttribute("r", on ? "3.4" : "2.4"); }); if (!sel) return; if (!path) { sel.setAttribute("opacity", "0"); if (readout) readout.textContent = ""; return; } const series = path.close_pct || []; const pts = []; for (let i = 0; i < Math.min(series.length, n); i += 1) { pts.push(xAt(i).toFixed(1) + "," + yAt(series[i]).toFixed(1)); } sel.setAttribute("points", pts.join(" ")); sel.setAttribute("opacity", "1"); if (readout) { readout.textContent = (path.event_date || "") + " · sleeve " + fmtPct2(path.terminal_pct) + " · MFE " + fmtPct2(path.mfe_terminal) + " · MAE " + fmtPct2(path.mae_terminal); } } shared.paintCorridor = paint; svg.querySelectorAll(".mb-corridor-dot").forEach(function (el) { el.style.cursor = "pointer"; el.addEventListener("click", function (evt) { evt.stopPropagation(); const idx = Number(el.getAttribute("data-trade-i")); if (Number.isNaN(idx)) return; shared.pinned = idx; document.querySelectorAll("[data-mb-overlay]").forEach(function (root) { if (root._mbShowTrade) root._mbShowTrade(idx, true); }); paint(idx); }); }); const hit = svg.querySelector(".mb-corridor-hit"); if (hit) { hit.addEventListener("mousemove", function (evt) { const pt = svg.createSVGPoint(); pt.x = evt.clientX; pt.y = evt.clientY; const ctm = svg.getScreenCTM(); if (!ctm) return; const loc = pt.matrixTransform(ctm.inverse()); const t = (loc.x - padL) / plotW; if (t < -0.02 || t > 1.02 || n < 2) return; const bar = Math.max(0, Math.min(n - 1, Math.round(t * (n - 1)))); const readout = svg.querySelector(".mb-corridor-readout"); if (!readout || shared.pinned != null) return; const lab = bar === 0 ? "T0" : "T+" + bar; readout.textContent = lab + " · avg " + fmtPct2((tape.avg || [])[bar]) + " · MFE " + fmtPct2((tape.mfe || [])[bar]) + " · MAE " + fmtPct2((tape.mae || [])[bar]) + " · SPY " + fmtPct2((tape.spy || [])[bar]); }); } } function bindPatternBars(shared) { document.querySelectorAll(".mb-pattern-bar[data-trade-i], .mb-pattern-hit[data-trade-i]").forEach(function (el) { el.style.cursor = "pointer"; el.addEventListener("click", function () { const idx = Number(el.getAttribute("data-trade-i")); if (Number.isNaN(idx)) return; shared.pinned = idx; document.querySelectorAll("[data-mb-overlay]").forEach(function (root) { if (root._mbShowTrade) root._mbShowTrade(idx, true); }); if (shared.paintCorridor) shared.paintCorridor(idx); }); }); } function bindYearCharts(shared) { let tip = document.querySelector(".mb-chart-tip"); if (!tip) { tip = document.createElement("div"); tip.className = "mb-chart-tip"; tip.hidden = true; document.body.appendChild(tip); } let yearOn = ""; function showTip(html, evt) { if (!html) { tip.hidden = true; return; } tip.innerHTML = html; tip.hidden = false; const x = Math.min(window.innerWidth - 220, (evt && evt.clientX ? evt.clientX : 0) + 12); const y = Math.min(window.innerHeight - 72, (evt && evt.clientY ? evt.clientY : 0) + 14); tip.style.left = x + "px"; tip.style.top = y + "px"; } function hideTip() { tip.hidden = true; } function yearOf(el) { return (el.getAttribute("data-year") || "").slice(0, 4); } function paintYear(year) { yearOn = year || ""; if (shared) shared.yearOn = yearOn; document.querySelectorAll(".mb-year-bar, .mb-year-hit, .mb-year-lab").forEach(function (el) { const on = yearOn && yearOf(el) === yearOn; el.classList.toggle("is-on", on); el.classList.toggle("is-dim", !!yearOn && !on); }); document.querySelectorAll(".mb-pattern-bar, .mb-pattern-hit").forEach(function (el) { const on = yearOn && yearOf(el) === yearOn; el.classList.toggle("is-dim", !!yearOn && !on); if (el.classList.contains("mb-pattern-bar")) { el.classList.toggle("is-on", on); } }); let nShow = 0; document.querySelectorAll(".mb-instance-ledger tbody tr[data-trade-i]").forEach(function (tr) { const match = !yearOn || yearOf(tr) === yearOn; tr.classList.toggle("is-year-off", !match); if (match) nShow += 1; }); const host = document.querySelector(".mb-year-filter"); if (host) { if (!yearOn) { host.hidden = true; host.textContent = ""; } else { host.hidden = false; host.innerHTML = "Showing " + esc(yearOn) + " · " + nShow + " session" + (nShow === 1 ? "" : "s") + ' '; const btn = host.querySelector(".mb-year-clear"); if (btn) { btn.addEventListener("click", function (evt) { evt.preventDefault(); paintYear(""); }); } } } } shared.setYearFilter = function (year, toggle) { const next = String(year || "").slice(0, 4); if (toggle && next && next === yearOn) paintYear(""); else paintYear(next); }; function yearTip(el) { const y = yearOf(el); if (!y) return ""; const n = el.getAttribute("data-n"); const wins = el.getAttribute("data-wins"); const rate = Number(el.getAttribute("data-rate")); const avg = Number(el.getAttribute("data-avg")); let line = esc(y); if (n != null && n !== "") { line += " · " + esc(String(wins || "0")) + "/" + esc(String(n)) + " wins"; } if (!Number.isNaN(rate) && el.getAttribute("data-rate") != null) { line += " · " + Math.round(rate * 100) + "% win"; } if (!Number.isNaN(avg) && el.getAttribute("data-avg") != null) { line += " · avg " + fmtPct(avg); } return line + "
Click to filter the instance report"; } function patternTip(el) { const date = el.getAttribute("data-date") || ""; const ret = Number(el.getAttribute("data-ret")); const win = el.getAttribute("data-win") === "1"; const y = yearOf(el); return ( esc(date || y) + " · sleeve " + fmtPct(ret) + " · " + (win ? "W" : "L") + "
Click for the hold path · click the year to filter" ); } document.querySelectorAll(".mb-year-bar, .mb-year-hit, .mb-year-lab").forEach(function (el) { el.addEventListener("mousemove", function (evt) { showTip(yearTip(el), evt); }); el.addEventListener("mouseleave", hideTip); el.addEventListener("click", function (evt) { evt.preventDefault(); evt.stopPropagation(); shared.setYearFilter(yearOf(el), true); }); }); document.querySelectorAll(".mb-pattern-bar, .mb-pattern-hit").forEach(function (el) { el.addEventListener("mousemove", function (evt) { showTip(patternTip(el), evt); }); el.addEventListener("mouseleave", hideTip); }); document.querySelectorAll(".mb-year-chart").forEach(function (svg) { svg.addEventListener("keydown", function (evt) { if (evt.key !== "ArrowLeft" && evt.key !== "ArrowRight" && evt.key !== "Escape") return; const years = []; svg.querySelectorAll(".mb-year-lab[data-year], .mb-pattern-bar[data-year]").forEach(function (el) { const y = yearOf(el); if (y && years.indexOf(y) < 0) years.push(y); }); if (evt.key === "Escape") { paintYear(""); evt.preventDefault(); return; } if (!years.length) return; let i = years.indexOf(yearOn); if (evt.key === "ArrowRight") i = i < 0 ? 0 : Math.min(years.length - 1, i + 1); else i = i < 0 ? years.length - 1 : Math.max(0, i - 1); paintYear(years[i]); evt.preventDefault(); }); }); } function bindHistAndSeason(shared) { function applyLedger() { const year = shared.yearOn || ""; const season = shared.seasonOn || ""; const lo = shared.binLo; const hi = shared.binHi; document.querySelectorAll(".mb-instance-ledger tbody tr[data-trade-i]").forEach(function (tr) { const y = (tr.getAttribute("data-year") || "").slice(0, 4); const s = tr.getAttribute("data-season") || ""; const ret = Number(tr.getAttribute("data-ret")); let on = true; if (year && y !== year) on = false; if (season && s !== season) on = false; if (lo != null && hi != null && Number.isFinite(ret) && (ret < lo || ret > hi)) on = false; tr.classList.toggle("is-year-off", !on); }); } function paintHist() { document.querySelectorAll(".mb-hist-bar, .mb-hist-hit").forEach(function (el) { const lo = Number(el.getAttribute("data-lo")); const hi = Number(el.getAttribute("data-hi")); const on = shared.binLo === lo && shared.binHi === hi; el.classList.toggle("is-on", on); }); } function histTip(el) { const lo = Number(el.getAttribute("data-lo")); const hi = Number(el.getAttribute("data-hi")); const c = el.getAttribute("data-count") || "0"; const mid = Number(el.getAttribute("data-mid")); return ( "T+1 close " + (Number.isFinite(lo) ? lo.toFixed(1) : "—") + " to " + (Number.isFinite(hi) ? hi.toFixed(1) : "—") + "% · n=" + esc(String(c)) + (Number.isFinite(mid) ? " · mid " + mid.toFixed(1) + "%" : "") + "
Click to filter the instance report" ); } document.querySelectorAll(".mb-hist-bar, .mb-hist-hit").forEach(function (el) { el.style.cursor = "pointer"; el.addEventListener("mousemove", function (evt) { const tip = document.querySelector(".mb-chart-tip"); if (!tip) return; tip.innerHTML = histTip(el); tip.hidden = false; tip.style.left = Math.min(window.innerWidth - 220, evt.clientX + 12) + "px"; tip.style.top = Math.min(window.innerHeight - 72, evt.clientY + 14) + "px"; }); el.addEventListener("mouseleave", function () { const tip = document.querySelector(".mb-chart-tip"); if (tip) tip.hidden = true; }); el.addEventListener("click", function () { const nextLo = Number(el.getAttribute("data-lo")); const nextHi = Number(el.getAttribute("data-hi")); if (shared.binLo === nextLo && shared.binHi === nextHi) { shared.binLo = null; shared.binHi = null; } else { shared.binLo = nextLo; shared.binHi = nextHi; } paintHist(); applyLedger(); }); }); document.querySelectorAll(".mb-season-table tbody tr[data-season]").forEach(function (tr) { tr.style.cursor = "pointer"; tr.addEventListener("click", function () { const s = tr.getAttribute("data-season") || ""; shared.seasonOn = shared.seasonOn === s ? "" : s; applyLedger(); }); }); } function numArr(fields, key) { const v = fields && fields[key]; return Array.isArray(v) ? v.map(Number) : []; } function axisLabel(axes, id) { for (let i = 0; i < (axes || []).length; i += 1) { if (axes[i].id === id) return axes[i].label || id; } return id; } function axisKind(axes, id) { for (let i = 0; i < (axes || []).length; i += 1) { if (axes[i].id === id) return axes[i].kind || "num"; } if (id === "symbol" || id === "year" || id === "season" || id === "instance-index") return "cat"; return "num"; } function niceNum(span, round) { if (!Number.isFinite(span) || span <= 0) return 1; const exp = Math.floor(Math.log10(span)); const f = span / Math.pow(10, exp); let nf; if (round) { if (f < 1.5) nf = 1; else if (f < 3) nf = 2; else if (f < 7) nf = 5; else nf = 10; } else if (f <= 1) nf = 1; else if (f <= 2) nf = 2; else if (f <= 5) nf = 5; else nf = 10; return nf * Math.pow(10, exp); } function niceTicks(lo, hi, maxTicks) { if (!Number.isFinite(lo)) lo = 0; if (!Number.isFinite(hi)) hi = 1; if (lo > hi) { const t = lo; lo = hi; hi = t; } if (Math.abs(hi - lo) < 1e-12) { const pad = Math.abs(lo) < 1e-9 ? 1 : Math.abs(lo) * 0.12; lo -= pad; hi += pad; } maxTicks = Math.max(maxTicks || 5, 2); const span = niceNum(hi - lo, false); const step = Math.max(niceNum(span / (maxTicks - 1), true), 1e-12); const niceLo = Math.floor(lo / step) * step; let niceHi = Math.ceil(hi / step) * step; const ticks = []; let v = niceLo; let n = 0; while (v <= niceHi + step * 0.5 && n < 24) { ticks.push(Math.abs(v) < step * 1e-9 ? 0 : v); v += step; n += 1; } if (ticks.length < 2) ticks.push(niceLo, niceHi); if (Math.abs(niceHi - niceLo) < 1e-12) niceHi = niceLo + step; return { min: niceLo, max: niceHi, ticks: ticks }; } function integerish(vals) { if (!vals.length) return false; const min = Math.min.apply(null, vals); const max = Math.max.apply(null, vals); return vals.every(function (v) { return Math.abs(v - Math.round(v)) < 1e-6; }) && max - min <= 16; } function emptyX(n) { return { min: 0, max: Math.max(n, 1), ticks: [] }; } function percentScale() { return { min: 0, max: 100, ticks: [0, 25, 50, 75, 100] }; } function ticksForBaseline(vals, maxTicks) { const finite = (vals || []).filter(Number.isFinite); if (!finite.length) return ticksForValues([0], maxTicks); const hasZero = finite.some(function (v) { return v === 0; }); return ticksForValues(hasZero ? finite : finite.concat([0]), maxTicks); } function ticksForValues(vals, maxTicks) { const finite = (vals || []).filter(Number.isFinite); if (!finite.length) return { min: 0, max: 1, ticks: [0, 1] }; let lo = Math.min.apply(null, finite); let hi = Math.max.apply(null, finite); if (integerish(finite)) { const ilo = Math.floor(lo); const ihi = Math.ceil(hi); const ticks = []; for (let i = ilo; i <= ihi; i += 1) ticks.push(i); return { min: ilo - 0.35, max: ihi + 0.35, ticks: ticks }; } if (lo < 0 && hi > 0) { /* crosses origin */ } else if (lo >= 0 && lo <= Math.abs(hi - lo) * 0.18) lo = 0; else if (hi <= 0 && Math.abs(hi) <= Math.abs(hi - lo) * 0.18) hi = 0; return niceTicks(lo, hi, maxTicks || 5); } function fmtTick(v) { if (!Number.isFinite(v)) return "—"; if (Math.abs(v - Math.round(v)) < 1e-8) return String(Math.round(v)); if (Math.abs(v) >= 100) return v.toFixed(0); if (Math.abs(v) >= 10) return v.toFixed(1); return String(Number(v.toFixed(2))); } function axisLayer(f, xsc, ysc, xlab, ylab, ySuffix) { ySuffix = ySuffix || ""; const xr = f.w - f.padR; const yb = f.padT + f.plotH; function sx(v) { return f.padL + ((v - xsc.min) / Math.max(Math.abs(xsc.max - xsc.min), 1e-12)) * f.plotW; } function sy(v) { return f.padT + f.plotH - ((v - ysc.min) / Math.max(Math.abs(ysc.max - ysc.min), 1e-12)) * f.plotH; } let out = ''; (ysc.ticks || []).forEach(function (t) { const yy = sy(t); out += ''; out += '' + esc(fmtTick(t) + ySuffix) + ""; }); (xsc.ticks || []).forEach(function (t) { const xx = sx(t); out += ''; out += '' + esc(fmtTick(t)) + ""; }); if (xsc.min < 0 && xsc.max > 0) { const zx = sx(0); out += ''; } if (ysc.min < 0 && ysc.max > 0) { const zy = sy(0); out += ''; } out += ''; out += ''; if (xlab) { out += '' + esc(xlab) + ""; } if (ylab) { const yn = Math.max(f.padT - 6, 22); out += '' + esc(ylab) + ""; } return out; } function histogramSvg(diag) { const counts = diag.hist_counts || []; const mids = diag.hist_mids || []; if (!counts.length || !mids.length) return ""; const hn = counts.length; const f = { w: 640, h: 220, padL: 56, padR: 14, padT: 36, padB: 46 }; f.plotW = f.w - f.padL - f.padR; f.plotH = f.h - f.padT - f.padB; const peak = Math.max.apply(null, counts.concat([1])); let ysc = niceTicks(0, peak, 4); ysc.min = 0; if (ysc.ticks.indexOf(0) < 0) ysc.ticks.unshift(0); const edges = diag.hist_edges || []; const xLo = edges.length ? Number(edges[0]) : Number(mids[0]); const xHi = edges.length ? Number(edges[edges.length - 1]) : Number(mids[mids.length - 1]); const xsc = ticksForValues([xLo, xHi], 6); const bw = f.plotW / hn; let bars = ""; let hits = ""; for (let i = 0; i < hn; i += 1) { const bh = (counts[i] / peak) * f.plotH * 0.92; const x = f.padL + i * bw + bw * 0.12; const y = f.padT + f.plotH - Math.max(bh, 1); const mid = Number(mids[i] || 0); const lo = Number(edges[i] != null ? edges[i] : mid); const hi = Number(edges[i + 1] != null ? edges[i + 1] : mid); const sign = mid >= 0 ? "mb-sign-pos" : "mb-sign-neg"; const meta = 'data-lo="' + lo.toFixed(4) + '" data-hi="' + hi.toFixed(4) + '" data-count="' + counts[i] + '" data-mid="' + mid.toFixed(4) + '"'; bars += ''; hits += ''; } const title = "Terminal distribution · T+1 close %"; return '
' + esc(title) + "" + axisLayer(f, xsc, ysc, "T+1 close %", "Count") + bars + hits + "
"; } function fillAxisSelect(sel, axes, current, prefer) { if (!sel) return; const groups = {}; (axes || []).forEach(function (a) { const fam = a.family || "core"; if (!groups[fam]) groups[fam] = []; groups[fam].push(a); }); sel.innerHTML = ""; Object.keys(groups).forEach(function (fam) { const og = document.createElement("optgroup"); og.label = fam; groups[fam].forEach(function (a) { const opt = document.createElement("option"); opt.value = a.id; opt.textContent = a.label || a.id; og.appendChild(opt); }); sel.appendChild(og); }); const want = current || prefer || ""; if (want) { sel.value = want; if (sel.value !== want) { const opt = sel.querySelector('option[value="' + want.replace(/"/g, "") + '"]'); if (opt) opt.selected = true; } } } function svgScatter(points, xlab, ylab) { const f = { w: 640, h: 300, padL: 72, padR: 16, padT: 36, padB: 48 }; f.plotW = f.w - f.padL - f.padR; f.plotH = f.h - f.padT - f.padB; const xs = points.map(function (p) { return p.x; }).filter(Number.isFinite); const ys = points.map(function (p) { return p.y; }).filter(Number.isFinite); const xsc = ticksForValues(xs, 5); const ysc = ticksForValues(ys, 5); function sx(v) { return f.padL + ((v - xsc.min) / Math.max(Math.abs(xsc.max - xsc.min), 1e-12)) * f.plotW; } function sy(v) { return f.padT + f.plotH - ((v - ysc.min) / Math.max(Math.abs(ysc.max - ysc.min), 1e-12)) * f.plotH; } let groups = {}; points.forEach(function (p) { const k = p.series_key || p.sym || ""; if (!groups[k]) groups[k] = []; groups[k].push(p); }); let lines = ""; Object.keys(groups).forEach(function (k) { const pts = groups[k].filter(function (p) { return Number.isFinite(p.x) && Number.isFinite(p.y); }) .sort(function (a, b) { return a.x - b.x; }); if (pts.length < 2) return; const cls = pts.some(function (p) { return p.primary; }) ? "mb-ex-line is-primary" : "mb-ex-line is-overlay"; const poly = pts.map(function (p) { return sx(p.x).toFixed(1) + "," + sy(p.y).toFixed(1); }).join(" "); lines += ''; }); let dots = ""; let hits = ""; points.forEach(function (p) { if (!Number.isFinite(p.x) || !Number.isFinite(p.y)) return; const cls = p.primary ? "mb-ex-pt is-primary" : "mb-ex-pt is-overlay"; const r = p.primary ? 6.2 : 5.2; const meta = 'data-bar="' + (p.bar != null ? p.bar : "") + '" data-trade-i="' + (p.i != null ? p.i : "") + '" data-sym="' + esc(p.sym || "") + '" data-x="' + p.x + '" data-y="' + p.y + '"'; const cx = sx(p.x).toFixed(1); const cy = sy(p.y).toFixed(1); dots += ''; hits += ''; }); const title = xlab + " versus " + ylab; const legend = 'Sleeve' + 'Names · SPY'; return ( '' + esc(title) + "" + axisLayer(f, xsc, ysc, xlab, ylab) + lines + dots + legend + hits + "" ); } function svgBars(rows, ylab) { const n = Math.max(rows.length, 1); const f = { w: 640, h: 280, padL: 56, padR: 14, padT: 36, padB: 52 }; f.plotW = f.w - f.padL - f.padR; f.plotH = f.h - f.padT - f.padB; const bw = f.plotW / n; const vals = rows.map(function (r) { return Number(r.y) || 0; }); const ysc = ticksForValues(vals, 5); const xsc = { min: 0, max: n, ticks: [] }; function sx(i) { return f.padL + (i + 0.5) * bw; } function sy(v) { return f.padT + f.plotH - ((v - ysc.min) / Math.max(Math.abs(ysc.max - ysc.min), 1e-12)) * f.plotH; } const zeroY = ysc.min < 0 && ysc.max > 0 ? sy(0) : f.padT + f.plotH; const bars = rows.map(function (r, i) { const yv = Number(r.y) || 0; const y1 = sy(yv); const y0 = zeroY; const top = Math.min(y0, y1); const bh = Math.max(Math.abs(y1 - y0), 1); const sign = yv >= 0 ? "mb-sign-pos" : "mb-sign-neg"; return ( '' ); }).join(""); const labs = rows.map(function (r, i) { return ( '' + esc(String(r.label || "").slice(0, 10)) + "" ); }).join(""); const title = ylab + " by group"; return ( '' + esc(title) + "" + axisLayer(f, xsc, ysc, "", ylab) + bars + labs + "" ); } function drawExplore(root, tape) { const xSel = root.querySelector(".mb-ex-x"); const ySel = root.querySelector(".mb-ex-y"); const subSel = root.querySelector(".mb-ex-subset"); const plot = root.querySelector(".mb-explore-plot"); if (!plot) return; const xId = (xSel && xSel.value) || tape.default_x || "holding-days"; const yId = (ySel && ySel.value) || tape.default_y || "profit-factor"; const subset = (subSel && subSel.value) || "range"; const axes = tape.axes || []; const series = tape.series || []; const exitI = Number(tape.exit_i || 0); if (axisKind(axes, xId) === "cat") { let rows = []; if (xId === "symbol") { rows = (tape.names || []).map(function (n) { let y = Number(n.avg || 0); series.forEach(function (s) { if (s.symbol === n.symbol) { const arr = numArr(s.fields, yId); if (arr.length) y = arr[Math.min(exitI, arr.length - 1)]; } }); if (yId.indexOf("sharpe") >= 0 && n.sharpe) y = Number(n.sharpe); return { label: n.symbol, y: y }; }); } else if (xId === "year" || xId === "season") { const bag = {}; (tape.sessions || []).forEach(function (s) { const k = xId === "year" ? s.year : s.season; if (!k) return; if (!bag[k]) bag[k] = []; bag[k].push(Number(s.ret || 0)); }); rows = Object.keys(bag).map(function (k) { const xs = bag[k]; return { label: k, y: xs.reduce(function (a, b) { return a + b; }, 0) / xs.length }; }); } else { const evo = tape.evolution || {}; const ys = evo[yId] || evo["evolution-average-return-by-instance"] || []; const dates = evo["evolution-instance-dates"] || []; const additive = String(yId).indexOf("evolution-additive-") === 0; const additiveMean = additive && String(yId).indexOf("-mean-") >= 0; const from = additive && !additiveMean ? Number(evo["evolution-additive-defined-from"] || 3) : 1; rows = ys.map(function (v, i) { const k = i + 1; if (k < from) return null; const d = dates[i] ? String(dates[i]) : ""; return { label: additive ? ("1–" + k) : String(k), y: Number(v), date: d }; }).filter(function (r) { return r && Number.isFinite(r.y); }); } plot.innerHTML = svgBars(rows, axisLabel(axes, yId)); } else { const points = []; series.forEach(function (s) { const xs = numArr(s.fields, xId); const ys = numArr(s.fields, yId); const n = Math.min(xs.length, ys.length); let lo = 0; let hi = n; if (subset === "range") hi = Math.min(n, exitI + 1); if (subset === "exit") { lo = Math.min(exitI, Math.max(n - 1, 0)); hi = lo + 1; } for (let i = lo; i < hi; i += 1) { points.push({ x: xs[i], y: ys[i], bar: i, sym: s.symbol, primary: !!s.primary, exitOnly: subset === "exit" }); } }); plot.innerHTML = svgScatter(points, axisLabel(axes, xId), axisLabel(axes, yId)); } const mega = root.querySelector(".mb-mega-host"); if (mega) { const primary = series.filter(function (s) { return s.primary; })[0] || series[0]; const fields = (primary && primary.fields) || {}; const hd = numArr(fields, "holding-days"); const keys = ["returns-average", "sharpe-ratio", "profit-factor", "higher-percent", "returns-sd", "long-sortino-ratio"]; let head = "Day"; keys.forEach(function (k) { head += '' + esc(axisLabel(axes, k)) + ""; }); let body = ""; hd.forEach(function (d, i) { body += '' + d + ""; keys.forEach(function (k) { const v = numArr(fields, k)[i]; body += '' + (Number.isFinite(v) ? Number(v).toFixed(3) : "—") + ""; }); body += ""; }); mega.innerHTML = '
' + head + "" + body + "
"; mega.querySelectorAll(".mb-mega-row").forEach(function (tr) { tr.style.cursor = "pointer"; tr.addEventListener("click", function () { if (subSel) subSel.value = "exit"; if (xSel) xSel.value = "holding-days"; drawExplore(root, tape); }); }); } const evoHost = root.querySelector(".mb-evo-host"); if (evoHost) { const evo = tape.evolution || {}; const ys = evo["evolution-additive-sharpe-by-instance"] || []; const dates = evo["evolution-instance-dates"] || []; const from = Number(evo["evolution-additive-defined-from"] || 3); const pts = ys.map(function (v, i) { const k = i + 1; const d = dates[i] ? String(dates[i]) : ""; return { x: k, y: Number(v), i: i, primary: true, bar: k, series_key: "evolution-additive", sym: d ? ("1–" + k + " · " + d) : ("1–" + k) }; }).filter(function (p) { return p.x >= from && Number.isFinite(p.y); }); evoHost.innerHTML = svgScatter(pts, "Instance #", "Evolution Sharpe (1…n)"); const sum = root.querySelector(".mb-evo-summary"); if (sum) { const s = evo["evolution-summary"] || {}; const n = s.total_instances || ys.length; sum.textContent = n + " instances · Sharpe of 1–k at each k (defined from k=" + from + ")"; } } const freq = root.querySelector(".mb-freq-host"); if (freq) { const primary = series.filter(function (s) { return s.primary; })[0] || series[0]; const fields = (primary && primary.fields) || {}; const hd = numArr(fields, "holding-days"); const hi = numArr(fields, "higher-percent"); const lo = numArr(fields, "lower-percent"); const ptsH = hd.map(function (d, i) { return { x: d, y: hi[i], primary: true, bar: i }; }); const ptsL = hd.map(function (d, i) { return { x: d, y: lo[i], primary: false, bar: i }; }); freq.innerHTML = svgScatter(ptsH.concat(ptsL), "Holding days", "Higher % (navy) · Lower % (gold)"); } function ensureTip() { let tip = document.querySelector(".mb-chart-tip"); if (!tip) { tip = document.createElement("div"); tip.className = "mb-chart-tip"; tip.hidden = true; document.body.appendChild(tip); } return tip; } function bindMarks(host) { if (!host) return; host.querySelectorAll(".mb-ex-pt, .mb-ex-bar, .mb-ex-hit").forEach(function (el) { el.style.cursor = "pointer"; el.addEventListener("mousemove", function (evt) { const tip = ensureTip(); const lab = el.getAttribute("data-sym") || el.getAttribute("data-bar") || ""; const xv = el.getAttribute("data-x"); const yv = el.getAttribute("data-y"); let html = esc(lab); if (xv != null && xv !== "") html += "
x " + esc(xv); if (yv != null && yv !== "") html += " · y " + esc(yv); const bar = el.getAttribute("data-bar"); const lab0 = el.getAttribute("data-sym") || ""; const evoPt = (host.classList && host.classList.contains("mb-evo-host")) || lab0.indexOf("1–") === 0; if (bar != null && bar !== "" && !evoPt) html += "
hold day " + esc(bar); if (evoPt) { html += "
Click to pin instance " + esc(bar || lab0); } else if (el.getAttribute("data-trade-i") != null && el.getAttribute("data-trade-i") !== "") { html += "
Click to pin trade window"; } else { html += "
Click to highlight hold-day row"; } tip.innerHTML = html; tip.hidden = false; tip.style.left = Math.min(window.innerWidth - 220, evt.clientX + 12) + "px"; tip.style.top = Math.min(window.innerHeight - 72, evt.clientY + 14) + "px"; }); el.addEventListener("mouseleave", function () { const tip = document.querySelector(".mb-chart-tip"); if (tip) tip.hidden = true; }); el.addEventListener("click", function () { const idx = Number(el.getAttribute("data-trade-i")); document.querySelectorAll("[data-mb-overlay]").forEach(function (node) { if (node._mbShowTrade && Number.isFinite(idx)) node._mbShowTrade(idx, true); }); const bar = el.getAttribute("data-bar"); const lab0 = el.getAttribute("data-sym") || ""; const evoPt = (host.classList && host.classList.contains("mb-evo-host")) || lab0.indexOf("1–") === 0; if (!evoPt) { root.querySelectorAll(".mb-mega-row").forEach(function (tr) { tr.classList.toggle("is-on", bar != null && tr.getAttribute("data-bar") === bar); }); } host.querySelectorAll(".mb-ex-pt, .mb-ex-bar").forEach(function (pt) { pt.classList.toggle("is-on", pt.getAttribute("data-bar") === bar && pt.getAttribute("data-sym") === el.getAttribute("data-sym")); }); }); }); } bindMarks(plot); bindMarks(root.querySelector(".mb-evo-host")); bindMarks(root.querySelector(".mb-freq-host")); } function mountExploreAll() { document.querySelectorAll("[data-mb-explore]").forEach(function (root) { if (root._mbExploreOn) return; const node = root.querySelector(".mb-explore-tape"); if (!node) return; let tape; try { tape = JSON.parse(node.textContent || "{}"); } catch (e) { return; } root._mbExploreOn = true; fillAxisSelect(root.querySelector(".mb-ex-x"), tape.axes, tape.default_x, "holding-days"); fillAxisSelect(root.querySelector(".mb-ex-y"), tape.axes, tape.default_y, "profit-factor"); ["mb-ex-x", "mb-ex-y", "mb-ex-subset"].forEach(function (cls) { const el = root.querySelector("." + cls); if (el) el.addEventListener("change", function () { drawExplore(root, tape); }); }); drawExplore(root, tape); }); } var overlayMounted = false; function mountOverlayTape() { if (overlayMounted) return; overlayMounted = true; const tape = readOverlayTape(); const shared = { pinned: null }; if (tape && tape.dates && tape.trades) { document.querySelectorAll("[data-mb-overlay]").forEach(function (root) { mountOneOverlay(root, tape, shared); }); bindOverlayKeys(shared, tape); } mountCorridorTape(shared); bindPatternBars(shared); bindYearCharts(shared); bindHistAndSeason(shared); mountExploreAll(); document.querySelectorAll(".mb-instance-ledger tbody tr[data-trade-i]").forEach(function (tr) { tr.addEventListener("click", function () { const idx = Number(tr.getAttribute("data-trade-i")); if (Number.isNaN(idx)) return; shared.pinned = idx; document.querySelectorAll("[data-mb-overlay]").forEach(function (root) { if (root._mbShowTrade) root._mbShowTrade(idx, true); }); if (shared.paintCorridor) shared.paintCorridor(idx); tr.scrollIntoView({ block: "nearest" }); }); }); } global.mbFinance = { esc: esc, arrowPct: arrowPct, holdingBarHtml: holdingBarHtml, specFromHp: specFromHp, outperformersTable: outperformersTable, patternHistorySvg: patternHistorySvg, winRateSvg: winRateSvg, identityMarkHtml: identityMarkHtml, classifyEventGraphic: classifyEventGraphic, basketSleeveHtml: basketSleeveHtml, renderWeeklyEvent: renderWeeklyEvent, renderQuantCard: renderQuantCard, mountExploreAll: mountExploreAll, mountOverlayTape: mountOverlayTape, mountCorridorTape: mountCorridorTape, }; if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", mountOverlayTape); } else { mountOverlayTape(); } })(window); const API = '/api/v10/moneyball/buyback-edition/latest'; (function () { var q = new URLSearchParams(location.search); var status = document.getElementById('status'); if (q.get('checkout') === 'success') status.className = 'ok', status.textContent = 'Checkout complete. Buyback edition uses its own Stripe Price.'; if (q.get('checkout') === 'cancel') status.className = 'err', status.textContent = 'Checkout canceled. Price is still the buyback edition Price.'; document.getElementById('pay').addEventListener('submit', async function (ev) { ev.preventDefault(); status.className = ''; status.textContent = 'Opening Stripe…'; try { var resp = await fetch('/api/v10/moneyball/public/checkout-buyback', { method: 'POST', headers: { 'content-type': 'application/json', accept: 'application/json' }, body: JSON.stringify({ customer_email: document.getElementById('email').value }) }); var body = {}; try { body = await resp.json(); } catch (e) { status.className = 'err'; status.textContent = 'Checkout needs the live API.'; return; } if (!resp.ok) { status.className = 'err'; status.textContent = body.error || ('Checkout failed ' + resp.status); return; } if (body.checkout_url) { location.href = body.checkout_url; return; } status.className = 'err'; status.textContent = 'Checkout session missing URL'; } catch (e) { status.className = 'err'; status.textContent = String(e); } }); })();