Track Your Performance
This tutorial shows how to retrieve and analyze your submission history programmaticaly, track scores over time, and identify your best-performing strategies.
In [ ]:
Copied!
%pip install crowdcent-challenge altair polars
import crowdcent_challenge as cc
import polars as pl
import altair as alt
%pip install crowdcent-challenge altair polars
import crowdcent_challenge as cc
import polars as pl
import altair as alt
For this tutorial, you will need:
- CrowdCent account: register for free
- CrowdCent API Key: generate an API key from your user profile
- Some scored submissions: Submit predictions and wait for scoring
Load API key¶
In [2]:
Copied!
CROWDCENT_API_KEY = "API_KEY_HERE"
CROWDCENT_API_KEY = "API_KEY_HERE"
Initialize the client¶
In [ ]:
Copied!
client = cc.ChallengeClient(
challenge_slug="hyperliquid-ranking",
api_key=CROWDCENT_API_KEY
)
client = cc.ChallengeClient(
challenge_slug="hyperliquid-ranking",
api_key=CROWDCENT_API_KEY
)
2025-12-30 15:08:08,401 - INFO - ChallengeClient initialized for 'hyperliquid-ranking' at URL: https://crowdcent.com/api
Get Performance History¶
Use get_performance() to retrieve all your scored submissions as a list of dicts:
In [4]:
Copied!
history = client.get_performance()
history_df = pl.DataFrame(history).with_columns(
pl.col("release_date").str.to_date(),
pl.col("submitted_at").str.to_datetime(),
)
history_df
history = client.get_performance()
history_df = pl.DataFrame(history).with_columns(
pl.col("release_date").str.to_date(),
pl.col("submitted_at").str.to_datetime(),
)
history_df
2025-12-30 15:08:08,479 - INFO - Fetching submission history for 'hyperliquid-ranking'... 2025-12-30 15:08:10,410 - INFO - Loaded 949 scored submissions.
Out[4]:
shape: (949, 14)
| id | slot | release_date | submitted_at | status | score_ndcg@40_10d | score_ndcg@40_30d | score_spearman_10d | score_spearman_30d | percentile_ndcg@40_10d | percentile_ndcg@40_30d | percentile_spearman_10d | percentile_spearman_30d | composite_percentile |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| i64 | i64 | date | datetime[μs, UTC] | str | f64 | f64 | f64 | f64 | f64 | f64 | f64 | f64 | f64 |
| 5880 | 5 | 2025-12-28 | 2025-12-28 14:44:37.055198 UTC | "pending" | 0.337716 | 0.340841 | -0.533123 | -0.523227 | 8.108108 | 8.108108 | 10.810811 | 10.810811 | 9.459459 |
| 5879 | 4 | 2025-12-28 | 2025-12-28 14:44:36.327841 UTC | "pending" | 0.421611 | 0.419226 | -0.417002 | -0.384453 | 62.162162 | 48.648649 | 70.27027 | 62.162162 | 60.810811 |
| 5878 | 3 | 2025-12-28 | 2025-12-28 14:44:35.920831 UTC | "pending" | 0.385517 | 0.388523 | -0.499784 | -0.464013 | 16.216216 | 18.918919 | 27.027027 | 35.135135 | 24.324324 |
| 5877 | 2 | 2025-12-28 | 2025-12-28 14:44:34.445854 UTC | "pending" | 0.452958 | 0.423994 | -0.47497 | -0.469166 | 81.081081 | 54.054054 | 59.459459 | 29.72973 | 56.081081 |
| 5876 | 1 | 2025-12-28 | 2025-12-28 14:44:34.074837 UTC | "pending" | 0.414794 | 0.492791 | -0.415315 | -0.242053 | 56.756757 | 89.189189 | 72.972973 | 83.783784 | 75.675676 |
| … | … | … | … | … | … | … | … | … | … | … | … | … | … |
| 14 | 2 | 2025-06-06 | 2025-06-06 16:04:20.309350 UTC | "evaluated" | 0.647897 | 0.63497 | 0.145175 | 0.133588 | 66.666667 | 66.666667 | 66.666667 | 66.666667 | null |
| 13 | 1 | 2025-06-06 | 2025-06-06 16:04:19.820281 UTC | "evaluated" | 0.647897 | 0.63497 | 0.145175 | 0.133588 | 66.666667 | 66.666667 | 66.666667 | 66.666667 | null |
| 12 | 2 | 2025-06-05 | 2025-06-05 15:06:38.631117 UTC | "evaluated" | 0.540538 | 0.651426 | 0.004378 | 0.119459 | 66.666667 | 66.666667 | 66.666667 | 66.666667 | null |
| 11 | 3 | 2025-06-05 | 2025-06-05 15:04:02.653942 UTC | "evaluated" | 0.55855 | 0.690496 | 0.051245 | 0.227518 | 100.0 | 100.0 | 100.0 | 100.0 | null |
| 10 | 1 | 2025-06-05 | 2025-06-05 14:37:09.450635 UTC | "evaluated" | 0.540538 | 0.651426 | 0.004378 | 0.119459 | 66.666667 | 66.666667 | 66.666667 | 66.666667 | null |
Each dict includes:
id,slot,release_date,submitted_at,status— submission metadatascore_*keys — raw metric scores (e.g.,score_spearman_10d)percentile_*keys — your percentile rank vs other participantscomposite_percentile— overall ranking (if available)
Analyze Performance by Slot¶
If you're using multiple slots for different strategies, compare them:
In [5]:
Copied!
# Average percentile by slot
slot_performance = (
history_df.group_by("slot")
.agg(
pl.col("composite_percentile").mean().alias("avg_percentile"),
pl.col("composite_percentile").std().alias("std_percentile"),
pl.col("composite_percentile").count().alias("submissions"),
)
.sort("avg_percentile", descending=True)
)
slot_performance
# Average percentile by slot
slot_performance = (
history_df.group_by("slot")
.agg(
pl.col("composite_percentile").mean().alias("avg_percentile"),
pl.col("composite_percentile").std().alias("std_percentile"),
pl.col("composite_percentile").count().alias("submissions"),
)
.sort("avg_percentile", descending=True)
)
slot_performance
Out[5]:
shape: (5, 4)
| slot | avg_percentile | std_percentile | submissions |
|---|---|---|---|
| i64 | f64 | f64 | u32 |
| 3 | 68.601376 | 20.018743 | 181 |
| 4 | 67.555864 | 22.640585 | 181 |
| 5 | 62.624793 | 26.325876 | 168 |
| 2 | 53.486718 | 21.407269 | 194 |
| 1 | 42.384833 | 21.720835 | 194 |
Visualize Performance Over Time¶
Plot your percentile trajectory with a moving average:
In [6]:
Copied!
window_size = 5
# Add rolling averages for percentile metrics
history_df = history_df.sort("release_date").with_columns(
[
pl.col("composite_percentile")
.rolling_mean(window_size=window_size)
.over("slot")
.alias(f"composite_percentile_ma{window_size}"),
]
)
window_size = 5
# Add rolling averages for percentile metrics
history_df = history_df.sort("release_date").with_columns(
[
pl.col("composite_percentile")
.rolling_mean(window_size=window_size)
.over("slot")
.alias(f"composite_percentile_ma{window_size}"),
]
)
In [7]:
Copied!
chart = (
alt.Chart(history_df)
.mark_line(point=True)
.encode(
x=alt.X("release_date:T", title="Inference Period"),
y=alt.Y("composite_percentile_ma5:Q", title="Percentile"),
color=alt.Color("slot:N", title="Slot"),
tooltip=["release_date", "slot", "composite_percentile"],
)
.properties(title="Performance Over Time", width=600, height=300)
)
chart
chart = (
alt.Chart(history_df)
.mark_line(point=True)
.encode(
x=alt.X("release_date:T", title="Inference Period"),
y=alt.Y("composite_percentile_ma5:Q", title="Percentile"),
color=alt.Color("slot:N", title="Slot"),
tooltip=["release_date", "slot", "composite_percentile"],
)
.properties(title="Performance Over Time", width=600, height=300)
)
chart
Out[7]: