Rules & FAQ
How the Arena works
The contract your submission must follow, how scoring works, and the limits that keep every run fair and reproducible.
What do I submit?
A single ZIP with two mandatory files: solution/solution.py, which defines a StrategyModel class with a predict(data_point) method, and solution/train.py, the pipeline that produced everything solution.py loads. Extra files (weights, helpers) are fine inside the ZIP; no other entry point is read. An upload missing either file is rejected at once.
What changed in round 2?
New data: the kit ships a fresh dataset and every model is scored on its hidden test set, so download the new kit from the Task page before you train. Now required: solution/train.py next to solution.py, the pipeline that rebuilds your artifacts from this round's train.parquet, so that finalists' solutions can be retrained. The rules themselves are unchanged: no information from the future at step t, everything inside the ZIP. Round-1 submissions no longer rank. The deadline is 30 September 2026 at 23:59 MSK; the Leaderboard shows the countdown.
What data do I get?
One file, datasets/train.parquet in the starter kit: a continuous, chronological series of 200 ms steps with the 70 feature columns and the realised PnL of every action at each step (the answers). There is no separate validation file; hold out the later rows yourself. The public test set is the period that follows the training data; the private set is a further period after that. Both stay hidden and reach your model only as features streamed into the sandbox.
How is my submission scored?
Your model runs offline in a sandbox. The scoring worker streams the hidden test set into it one step at a time (features only, never the answers, and never a step ahead of the one being predicted) and your model returns one action per step. The worker then re-derives your non-overlapping trades and sums their PnL in basis points; that total is your score.
What must train.py do?
Rebuild every artifact solution.py loads. Command line: python solution/train.py --train <train.parquet> --output <dir>. Write the artifacts into --output under the same relative paths solution.py reads next to itself, so --output solution/ yields a ready-to-zip tree. Do your own model selection inside it (hold out the later rows of train.parquet if you need to), read nothing but --train, and seed everything. A model with no learned parameters still ships a train.py; it may simply write nothing.
Will my train.py be re-run?
It may be: the organizers can retrain any finalist. They run train.py in the same offline image with this round's train.parquet as the only input, overlay its output onto your solution/ and score the result, within a budget of 4 vCPU, 32 GB RAM and 6 hours. That is why the pipeline may depend on nothing else. A retrained model whose behaviour cannot be explained by the shipped one is a discrepancy and grounds for disqualification.
What may my model use at step t?
Only what exists at t: the steps it has already seen (up to and including t) and artifacts derived solely from this round's training data. Pre-saved future data (answers, lookups keyed by time or row, anything about the test period) is forbidden. Rolling statistics computed inside predict() over past steps are fine. The sandbox enforces the mechanics: one step at a time, no access to the test file. The retrain and the review of the finalists enforce the rest; breaking the rule is grounds for disqualification.
Can I use round-1 data, other market data or pretrained weights?
No. Every learned artifact must come out of your train.py run on this round's train.parquet, because that is the only file the retrain sees: round-1 parquets, outside market data and weights trained elsewhere cannot be reproduced there and are not allowed. Your code is not data: feature engineering, model architecture and domain knowledge are what the contest is about.
What does predict() return?
Return None when data_point.need_prediction is False (a step locked by an open trade, or a warm-up step). Otherwise return a length-1 numeric array whose rounded value is the action, an integer 0..9. Action 0 stays flat; 1..9 open a position and lock the next 3000 steps.
How do I test locally?
Run the kit's validate.py on rows your model did not fit on: python validate.py --data datasets/train.parquet --from-row <first hold-out row> --solution solution/solution.py. It streams the features step by step, applies the same warm-up and lockout and prints the total PnL: the math the server runs, on rows of your choosing. Expect the absolute number to differ from the leaderboard, which is a different period and length; use the local score to compare your own models, not to predict the leaderboard. The kit README gives the row for the baseline's 20 % hold-out.
What are the runtime limits?
Each submission runs on 1 vCPU / 16 GB RAM with no internet and a 60-minute wall-clock limit, on Python 3.13 with the fixed runner ML dependency set preinstalled, including PyTorch, TensorFlow, JAX, XGBoost, LightGBM and CatBoost (the kit's requirements.txt lists it). Nothing can be installed or downloaded at runtime. The submission directory is read-only; write temporary files, caches or extracted model artifacts under /scratch or use Python tempfile.
Can I ship a saved model?
Yes. Put model files inside the ZIP and load them from solution.py; your train.py must be able to reproduce them. For portable artifacts, prefer ONNX. If you ship sklearn joblib/pickle artifacts, create them in the same runner environment; Python pickle does not guarantee compatibility across sklearn versions inside a range.
Will my score be reproducible?
Yes. The runner fixes PYTHONHASHSEED and seeds random/numpy before your model runs, so a deterministic model scores identically on resubmit. Seed any other libraries you use; validate.py applies the same seed, so a local run is repeatable too.
How many submissions can I make?
Up to 5 per day, with at most 1 queued or running at once. Score locally with validate.py before spending a slot.
Which score decides the winners?
The live leaderboard shows the public score, computed on the hidden public test set. The final ranking uses the private score, computed the same way on a separate, later period that is never published, so it cannot be probed or overfitted.
Which of my submissions is scored privately?
Exactly one: the submission you mark as your final pick on the Submissions tab. You can change it any time until the deadline. If you never pick one, your best-scoring public submission is used automatically, so you are never left out of the final ranking.
I submitted before the reopen. Do those submissions count?
No. The contest reopened on a fresh dataset as a new round. Earlier submissions stay in your history (marked with their round) but are not on the leaderboard and cannot be your final pick. Upload again, with train.py, to compete in the current round.
Still stuck?
Read the full task description on the Task page, or ask in the community chat linked from About.