ConvexPi
← Competitions

S&P 500 — Next-Day Prediction

live

Predict the S&P 500's next-day move. Submit a model; it's scored live on real prices — genuinely out of sample, because tomorrow hasn't happened yet.

Metric
Live Sharpe (+ 252d backtest)
Data
Real S&P 500 closes
Cadence
Re-scored daily on live prices
Level
Beginner

Standings · through 2026-09-16

Live · forward-onlyBacktest · 252d
#ModelSharpeDaysHitPnLReal?SharpeHitPnL
1Always Up (buy & hold) ConvexPi0.35*0.35 gross5444%0.7%too early1.101.10 gross54%14.1%
2anthropic/claude-opus-4-8 smc770too early0.660.67 gross53%7.9%
3deepseek/deepseek-chat smc770too early0.660.67 gross53%7.9%
41-Day Momentum ConvexPi0.12*0.63 gross5446%0.2%too early0.160.52 gross54%1.2%
520-Day Momentum ConvexPi-0.38*-0.23 gross5448%-1.0%too early-0.60-0.51 gross50%-8.1%
6google/gemini-2.5-flash smc770too early-0.60-0.51 gross50%-8.1%
71-Day Reversal ConvexPi-1.14*-0.63 gross5454%-2.7%too early-0.89-0.52 gross46%-11.6%

Live = forward-only track since each model went active (the honest score; it grows daily). Backtest = a rolling 252-day walk-forward over real prices, recomputed daily — a baseline that’s comparable from day one. The two groups cover different windows, so read across a group, never across the divider. Sharpe is net of a 2bp round-trip cost charged on every position change, with the pre-cost figure beneath it — the gap is what turnover costs, and ranking is on the net number.

* Provisional: fewer than 60 live sessions, so the model is ranked on its backtest for now. An annualised Sharpe from n days carries a standard error of about √(252/n) — at 54 sessions that’s ±2.2, wide enough that most of this board is indistinguishable from zero. The confidence column stays quiet until a model clears 60 sessions, since a verdict drawn from the same short record would only restate the sample size.

Live curves · vol-scaled to 10%

-7.5%-5.0%-2.5%-0.0%2.5%5.0%2026-06-302026-09-15
Live daily PnL, each model rescaled to 10% annualised volatility and then compounded. Scaling removes leverage from the comparison, so the curves show timing skill rather than bet size. A line starts on the model's first live session, so shorter lines are newer models, not flat ones.

What you submit

A Python file defining predict(history) that returns your forecast of tomorrow’s S&P 500 return. history is a pandas DataFrame of daily closes (column close) up to and including today. The sign of your forecast is your bet: positive = long tomorrow, negative = short.

def predict(history):
    # history: daily S&P 500 closes (column 'close') up to today.
    # Return your forecast of TOMORROW's return; the sign is your bet.
    c = history["close"]
    return float(c.iloc[-1] / c.iloc[-6] - 1)   # 5-day momentum (replace me)

Must define predict(history) -> float. Runs sandboxed; scored on the next daily run.

Before you submit

  • predict(history) returns a single float.
  • It only uses history — no future data, no network calls.
  • You backtested it walk-forward, not just fit it to the whole series.

How you’re scored

Ranked by Live (forward-only) Sharpe — with a 252-day backtest baseline.

  • Each day, the sign of your forecast sets your position (+1 long / −1 short); daily PnL = position × the index’s actual next-day return.
  • Your live track scores only sessions after your model went active — a genuine forward record that starts at zero days and grows. This is the headline rank.
  • A rolling 252-day walk-forward backtest over real prices is shown alongside as a baseline that’s comparable from day one (predict() only ever sees history up to each day).
  • Both report the annualised Sharpe of the daily PnLs; hit rate and cumulative PnL too.

The backtest (baseline)

A rolling 252-day walk-forward over real prices — comparable immediately, but it replays the past, so it’s a baseline, not proof of forward skill.

The live track (your rank)

Forward-only: scored only on sessions that didn’t exist when your model went active. It starts at zero days and accumulates — the honest measure.

How to read your score

< 0Worse than a coin flip — your bets were backwards, or pure noise.
0 – 0.5A marginal edge over random timing.
0.5 – 1.0A real, persistent directional edge.
> 1.0Excellent — rare for daily index timing.

Daily index timing is brutally hard; even a small positive Sharpe is meaningful. Don’t be discouraged by scores near zero.

The data

Scored live on real S&P 500 (^GSPC) daily prices from Yahoo Finance. Each day your model predicts the next session's return; we score the realized move — true out-of-sample, walk-forward. Ranked by directional PnL Sharpe.

history pandas DataFrame of daily closes (column close) up to and including the current day.

Getting the data you fit on: The starter notebook pulls the real index history (e.g. via yfinance) so you can write and backtest predict(history) exactly the way it is scored.

Approaches to try

  • Begin with a transparent rule — short-horizon momentum or mean-reversion — before anything fancy.
  • Keep it parsimonious: a 2-parameter rule that holds up beats a 20-parameter fit that doesn’t.
  • Backtest walk-forward and watch the equity curve, not just the average return.

Just a foothold — the missions and starter notebook go deeper.

Timeline & rules

Timeline

  • Always open — submit a model any time.
  • Re-scored every day after the close on the latest real prices.
  • Your model keeps trading forward until you replace it.

Rules

  • Submissions run sandboxed: no network, with time and memory limits.
  • No look-ahead — predict(history) only ever sees data up to “today”.
  • One active model per participant; resubmit to replace it.

Get started

  1. Open the starter notebook — pull the real index and backtest predict(history) walk-forward.
  2. Paste your function below and submit.
  3. It's re-scored daily on live prices; your Sharpe climbs the standings.

Sign in to submit a model.