> For the complete documentation index, see [llms.txt](https://docs.everesteer.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.everesteer.ai/submissions/tournament-submissions.md).

# Tournament submissions

The exact contract for a Himalayas round submission.

## Recommended: auto-submit

**Set up auto-submit and let the platform submit for you.** Upload your model as a `.pkl` and enable it; the platform runs it against every open round and writes the submission, so you never miss a round.

```python
client.create_model(name="my-model-v1")
client.upload_model("my-model-v1", "model.pkl", python_version="3.11")
client.set_auto_submit(model_id="my-model-v1", enabled=True)
```

Then check `get_models`: `lane_active` is `true` when the model will run, and `lane_note` says why when it will not. Full contract: [Model upload (.pkl)](/submissions/model-upload-pkl.md). Also put the model on the historical leaderboard with `submit_validation_diagnostics`.

Everything below is the **manual fallback**: submitting predictions yourself each round.

## Manual submission (fallback)

Submit predictions for the current round of the Himalayas Futures tournament. Each round covers one exped (a single as-of day), and your submission must cover every instrument in that round's universe.

## Prerequisites

**Create the model first.** Every model must be registered before it can receive predictions. Call `create_model(name=...)` once per model. A submit against a model name that does not exist returns 404 with `Model not found`. The platform never auto-creates a model.

```python
client.create_model(name="my-model-v1")
```

## The instrument set

The round's instrument set is the source of truth for which ids to predict on. Fetch it once per round:

```bash
curl -H "X-API-Key: $EIQ_API_KEY" \
  https://api.everesteer.ai/api/v1/futures/rounds/current/instruments
```

`GET /api/v1/futures/rounds/current/instruments` returns the round's `exped`, the exact list of `instrument_ids` your submission must cover, their `count`, and a `data_datestamp` you can use to bind your predictions to a specific snapshot. The `live` split the round serves carries the same ids, so predicting on every row of `download_dataset(split="live")` covers the set. The `is_accepting_submissions` field is advisory: it replays the open-window gate at read time. The server gate is the stored `[open_at, close_at)` interval.

## Submit body (v2, preferred)

`POST /api/v1/futures/submit/v2` accepts a JSON body with these fields:

```json
{
  "model_id": "my-model-v1",
  "exped": "exped_0850",
  "data_datestamp": 20260909,
  "predictions": [
    {
      "instrument_id": "559073fecf705ae5",
      "prediction": 0.73
    }
  ]
}
```

| Field            | Type    | Required | Description                                                                                                                           |
| ---------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `model_id`       | string  | Yes      | The model name you registered with `create_model`.                                                                                    |
| `exped`          | string  | Yes      | The round's exped, from `GET /api/v1/futures/rounds/current/instruments`.                                                             |
| `data_datestamp` | integer | No       | YYYYMMDD snapshot binding. If sent and the server's snapshot has rotated, the submit returns 400 with the current expected datestamp. |
| `predictions`    | array   | Yes      | One entry per instrument, each with `instrument_id` and `prediction`.                                                                 |

### Prediction rules

* **One entry per instrument\_id.** Every id from the instrument set must appear exactly once. Duplicates are rejected with 400. Missing or extra ids are also rejected.
* **Value in \[0, 1].** Each prediction must be a finite number between 0 and 1 inclusive. The response returns 422 for out-of-range values.
* **Accuracy is rank-based.** Scoring is by CORR, AIMC, and NCORR, all of which are rank-based. Rescaling your signal into \[0, 1] does not affect your score.

```python
submission = client.submit_futures_predictions(
    model_id="my-model-v1",
    predictions={row["id"]: pred for row, pred in zip(live_df.itertuples(), my_preds)},
    exped=instruments["exped"],
)
```

### Response

A successful submit returns 201 with:

| Field              | Type           | Description                                                                                                                                                                                                                               |
| ------------------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `submission_id`    | string         | Unique identifier for this submission record.                                                                                                                                                                                             |
| `model_id`         | string         | The model that submitted.                                                                                                                                                                                                                 |
| `exped`            | string         | The round exped.                                                                                                                                                                                                                          |
| `instrument_count` | integer        | Number of predictions accepted.                                                                                                                                                                                                           |
| `submitted_at`     | string         | ISO timestamp of the submission.                                                                                                                                                                                                          |
| `late`             | boolean        | True if accepted outside the `[open_at, close_at)` window. Read `scored` to know whether it counts. A late submission may create a model's entry for the exped, or revise that model's own late entry, but never replaces an on-time one. |
| `scored`           | boolean        | False when the submission was sent while no round was open. It is kept on file but never scored and earns no payout. Resubmit while a round is open to enter it.                                                                          |
| `note`             | string or null | A plain explanation when `scored` is false.                                                                                                                                                                                               |
| `replaced`         | boolean        | True if this call overwrote an existing submission for the same model and exped. The status is 201 either way; read this field to distinguish.                                                                                            |

### Replacement semantics

**You may resubmit for the same model and exped while the submission window is open.** Only the final version before close is scored. The `replaced` field is true when the call overwrites an earlier entry. Once the window closes, the entry is final.

## Pre-flight validation

`POST /api/v1/futures/predictions/validate` checks your payload shape, target names, coverage and range without consuming a submission slot or writing anything. It returns 200 with `valid: true` or a 400/422 describing the first error.

```python
issues = client.validate_submission(predictions={...})
```

## Batch submit

`POST /api/v1/futures/submit/batch` submits predictions for several models in one call (MCP tool `submit_futures_predictions_batch`). Up to 25 items are accepted, each with its own `model_id` and `predictions` list in the v2 shape. Each item is independent: a refused item reports its reason in `items` while the rest still write.

**Always read `all_succeeded`.** The response is 207 when any item failed. A partial failure is never a full batch success.

| Field           | Type    | Description                                                                                            |
| --------------- | ------- | ------------------------------------------------------------------------------------------------------ |
| `accepted`      | integer | Number of items accepted.                                                                              |
| `failed`        | integer | Number of items refused.                                                                               |
| `all_succeeded` | boolean | True only when every item was accepted.                                                                |
| `items`         | array   | Per-item outcomes with `status` (`accepted` or `error`), `submission_id`, `error`, and `error_status`. |

## Submission status

`GET /api/v1/submissions` returns your own submissions per (round, model). Fields include `submitted`, `accepted`, `coverage_pct`, `submitted_at`, and `n_predictions`.

```python
status = client.get_submission_status(round="exped_0850", model_id="my-model-v1")
```

## The deprecated v1 route

`POST /api/v1/futures/submit` (v1, per-target) is deprecated. It accepts the same contract but uses a `predictions` dict keyed by target name. Do not use it for new code. The v2 endpoint is the preferred entry point.

## Status codes on this path

| Code | Meaning                                                                                                                            |
| ---- | ---------------------------------------------------------------------------------------------------------------------------------- |
| 201  | Submission accepted (new or replacement).                                                                                          |
| 400  | Wrong exped, duplicate instrument\_ids, missing ids, or stale `data_datestamp`.                                                    |
| 404  | Model not found. Create it first with `create_model`.                                                                              |
| 422  | Prediction value outside \[0, 1] or other validation error.                                                                        |
| 409  | The round's window has closed and the existing entry may not be replaced, or an automated submission would overwrite a manual one. |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.everesteer.ai/submissions/tournament-submissions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
