Data sourced from prediction-market-analysis.
Run notebooks/data.ipynb to produce the following in data/kalshi/processed/:
One row per market contract, a snapshot of each contract's final state.
ticker— unique market identifieryes_bid,yes_ask,no_bid,no_ask— bid/ask prices in centsyes_spread,no_spread— ask − bid for each sidelast_price— last traded priceopen_time,close_time— market open/close timestampsstatus,volume
One row per trade execution, the full tick-by-tick history of every transaction on Kalshi.
ticker— which market contract was tradedyes_price— execution price in cents (0–100);no_priceis dropped as it is always100 − yes_pricecount— number of contracts in the filltaker_side—"yes"or"no"created_time— trade timestampvolume— notional size in dollars (count × yes_price / 100)
Extends the filtered trade history with two EDA-derived columns used downstream by the model:
return_15min— absolute 15-minute backward return in cents (yes_price − yes_price_15m_ago)y— large-move label:+1for trades above the 75th-percentile return,-1for trades below the 25th percentile,0otherwise
Built after two filters: (1) trades before the first date with >10M aggregate daily volume are removed, and (2) trades where the base price 15 minutes ago was below 3 cents are dropped to avoid extreme-valuation noise.
A 3-block 1D CNN (JumpCNN) that predicts whether a 1-minute bar sits at the endpoint of a large forward price move. One model is trained per prediction horizon H ∈ {5, 15, 30, 60} minutes, with labels and thresholds computed separately for each horizon from the training-set return distribution.
Input:
| Block | Layers | Output shape |
|---|---|---|
| 1 |
Conv1d(F→64, k=3, p=1) → BN → ReLU × 2, MaxPool1d(2), Dropout(0.2)
|
|
| 2 |
Conv1d(64→128, k=3, p=1) → BN → ReLU × 2, MaxPool1d(2), Dropout(0.2)
|
|
| 3 |
Conv1d(128→256, k=3, p=1) → BN → ReLU, AdaptiveAvgPool1d(1)
|
|
| Head | Linear(256→1) |
- Load
trades_with_labels.parquet, keep only raw columns (ticker,created_time,yes_price,volume,count). - Filter tickers with fewer than
min_trades_per_ticker = 50trades. - Aggregate into 1-minute bars per ticker:
close(last price),volume(sum),n_trades(sum). - Build features — all causal (no lookahead):
| Feature | Description |
|---|---|
close_norm |
close / 100 |
ret_1 |
1-bar % return |
ret_5 |
5-bar % return |
log_volume |
log(1 + volume) |
hour_sin / hour_cos |
Cyclical hour-of-day encoding |
- Compute forward returns using real timestamps for each horizon H, with a tolerance window of
max(2, H × 0.5)minutes. Bars without a future observation within the tolerance are assignedNaN. - Split chronologically 70 / 15 / 15 (train / val / test) on global bar timestamps.
- Binarise labels: thresholds are the 10th and 90th percentiles of the training-set forward return distribution; the same fixed thresholds are applied to val and test. A bar is labeled
1(jump) if its forward return exceeds the upper threshold or falls below the lower threshold. - Save the processed dataset to
bars_clean.parquet(skip if the file already exists). - Train one
JumpCNNper horizon withBCEWithLogitsLoss+pos_weightfor class imbalance. Windows spanning more than 90 real minutes are excluded. Checkpoints are saved tocheckpoints/jump_cnn_{H}m.pt. - Threshold search on the validation set: find the lowest decision threshold that achieves at least 60% precision (
MIN_PRECISION_TARGET = 0.60). - Evaluate on the test set: AUC-PR, AUC-ROC, accuracy, balanced accuracy, F1, MCC, and a confusion matrix.
After training, the notebook computes:
- Gradient saliency maps averaged over the 200 most confident correct jump and no-jump predictions.
- Feature ablation: each feature is zeroed out one at a time to measure its contribution to the predicted jump probability.
Key finding: close_norm dominates — ablating it collapses predictions in ~99% of cases. Recent momentum features (ret_1, ret_5) contribute very little, suggesting the CNN is primarily learning a price-level heuristic rather than temporal patterns.
The bar construction (steps 1–4) is checkpointed to bars_clean.parquet. Subsequent runs load this file and skip straight to training. Delete the file to force a full rebuild.
- Windows longer than 90 real minutes are rejected so sparse tickers with large inactivity gaps don't produce misleading inputs.
- The flat-price pattern in illiquid markets inflates AUC: the CNN learns that any tick after a long quiet period is a jump. These windows should be filtered or discounted in the next milestone.
This milestone is delivered as a main Colab notebook plus large artifacts on Google Drive (parquet tables, trained checkpoints, caches). The notebook is self-documenting (table of contents, folder layout, and a TF setup cell).
Teaching staff — Drive is optional for review. You can read the submitted notebook (method, code, and saved outputs) without copying anything from Drive. Only download or copy the Drive project folder if you want to re-run cells; the bundle is larger than 10 GB.
Folder: project — Google Drive
Expected top-level contents: data/, models/ (under data/ as in the notebook), moe_cache/, notebooks/, and at the project root requirements.txt (and the main notebook under notebooks/).
- Default (read-only): Open
notebooks/cs1090b_ms4_main_group52.ipynbfrom the submission (e.g. GitHub preview, downloaded.ipynb, or Colab upload of the file alone). No Drive access required to see what we did. - Only if re-running: Open the Drive folder and copy the entire
projecttree into your own Google Drive (for example Organize → Add shortcut to Drive or duplicate intoMyDrive). Then open the notebook in Colab from that tree. - Run the TF setup cell near the top of the notebook (after the table of contents). It mounts Drive (on Colab), sets
PROJECT_ROOT, and installs fromrequirements.txtif that file sits next todata/andnotebooks/. - If your copy of
projectis not atMyDrive/CS1090B/project, editPROJECT_ROOTin that setup cell to the path of the folder that contains bothdata/andnotebooks/. - Run the rest top to bottom (for example Runtime → Run all). Do not run the other experimental notebooks in
notebooks/unless you intend to regenerate intermediates; the main notebook states this in its disclaimer.
- Drive holds everything needed to execute MS4 (data, checkpoints, caches, notebook,
requirements.txt). - GitHub (this repo or a small spin-off) is useful for version history and code review of the notebook and
requirements.txt. It is not required to reproduce runs if staff use Drive only.