|
8 | 8 |
|
9 | 9 | import numerapi |
10 | 10 |
|
11 | | -napi = numerapi.NumerAPI() |
| 11 | +DEFAULT_TOURNAMENT = 8 |
| 12 | + |
| 13 | + |
| 14 | +def _get_api(tournament: int): |
| 15 | + """ |
| 16 | + Return the correct API implementation for a tournament. |
| 17 | +
|
| 18 | + Classic (and any tournament other than Signals/Crypto) uses NumerAPI, |
| 19 | + Signals (11) uses SignalsAPI, and Crypto (12) uses CryptoAPI. |
| 20 | + """ |
| 21 | + if tournament == 11: |
| 22 | + return numerapi.SignalsAPI() |
| 23 | + if tournament == 12: |
| 24 | + return numerapi.CryptoAPI() |
| 25 | + api = numerapi.NumerAPI() |
| 26 | + api.tournament_id = tournament |
| 27 | + return api |
| 28 | + |
| 29 | + |
| 30 | +def _require_method(api, method_name: str, command_name: str): |
| 31 | + """Ensure the requested command is supported for the selected tournament.""" |
| 32 | + if not hasattr(api, method_name): |
| 33 | + raise click.ClickException( |
| 34 | + f"The '{command_name}' command is not available for tournament " |
| 35 | + f"{api.tournament_id}.") |
| 36 | + return getattr(api, method_name) |
| 37 | + |
| 38 | + |
| 39 | +def tournament_option(func): |
| 40 | + """Reusable Click option for selecting a tournament.""" |
| 41 | + return click.option( |
| 42 | + '--tournament', |
| 43 | + type=int, |
| 44 | + default=DEFAULT_TOURNAMENT, |
| 45 | + show_default=True, |
| 46 | + help="Tournament to target (8 classic, 11 signals, 12 crypto).", |
| 47 | + )(func) |
12 | 48 |
|
13 | 49 |
|
14 | 50 | class CommonJSONEncoder(json.JSONEncoder): |
@@ -38,159 +74,192 @@ def cli(): |
38 | 74 |
|
39 | 75 |
|
40 | 76 | @cli.command() |
41 | | -@click.option('--round_num', |
42 | | - help='round you are interested in.defaults to the current round') |
43 | | -def list_datasets(round_num): |
| 77 | +@click.option( |
| 78 | + '--round_num', type=int, |
| 79 | + help='round you are interested in. defaults to the current round') |
| 80 | +@tournament_option |
| 81 | +def list_datasets(round_num, tournament): |
44 | 82 | """List of available data files""" |
45 | | - click.echo(prettify(napi.list_datasets(round_num=round_num))) |
| 83 | + api = _get_api(tournament) |
| 84 | + click.echo(prettify(api.list_datasets(round_num=round_num))) |
46 | 85 |
|
47 | 86 |
|
48 | 87 | @cli.command() |
49 | 88 | @click.option( |
50 | | - '--round_num', |
51 | | - help='round you are interested in.defaults to the current round') |
| 89 | + '--round_num', type=int, |
| 90 | + help='round you are interested in. defaults to the current round') |
52 | 91 | @click.option( |
53 | | - '--filename', help='file to be downloaded') |
| 92 | + '--filename', default="numerai_live_data.parquet", show_default=True, |
| 93 | + help='file to be downloaded') |
54 | 94 | @click.option( |
55 | 95 | '--dest_path', |
56 | | - help='complate destination path, defaults to the name of the source file') |
| 96 | + help='complete destination path, defaults to the name of the source file') |
| 97 | +@tournament_option |
57 | 98 | def download_dataset(round_num, filename="numerai_live_data.parquet", |
58 | | - dest_path=None): |
| 99 | + dest_path=None, tournament=DEFAULT_TOURNAMENT): |
59 | 100 | """Download specified file for the given round""" |
60 | 101 | click.echo("WARNING to download the old data use `download-dataset-old`") |
61 | | - click.echo(napi.download_dataset( |
| 102 | + api = _get_api(tournament) |
| 103 | + click.echo(api.download_dataset( |
62 | 104 | round_num=round_num, filename=filename, dest_path=dest_path)) |
63 | 105 |
|
64 | 106 |
|
65 | 107 | @cli.command() |
66 | | -@click.option('--tournament', default=8, |
67 | | - help='The ID of the tournament, defaults to 8') |
68 | | -def competitions(tournament=8): |
| 108 | +@tournament_option |
| 109 | +def competitions(tournament=DEFAULT_TOURNAMENT): |
69 | 110 | """Retrieves information about all competitions""" |
70 | | - click.echo(prettify(napi.get_competitions(tournament=tournament))) |
| 111 | + api = _get_api(tournament) |
| 112 | + method = _require_method(api, 'get_competitions', 'competitions') |
| 113 | + click.echo(prettify(method(tournament=tournament))) |
71 | 114 |
|
72 | 115 |
|
73 | 116 | @cli.command() |
74 | | -@click.option('--tournament', default=8, |
75 | | - help='The ID of the tournament, defaults to 8') |
76 | | -def current_round(tournament=8): |
| 117 | +@tournament_option |
| 118 | +def current_round(tournament=DEFAULT_TOURNAMENT): |
77 | 119 | """Get number of the current active round.""" |
78 | | - click.echo(napi.get_current_round(tournament=tournament)) |
| 120 | + api = _get_api(tournament) |
| 121 | + click.echo(api.get_current_round(tournament=tournament)) |
79 | 122 |
|
80 | 123 |
|
81 | 124 | @cli.command() |
82 | 125 | @click.option('--limit', default=20, |
83 | 126 | help='Number of items to return, defaults to 20') |
84 | 127 | @click.option('--offset', default=0, |
85 | 128 | help='Number of items to skip, defaults to 0') |
86 | | -def leaderboard(limit=20, offset=0): |
| 129 | +@tournament_option |
| 130 | +def leaderboard(limit=20, offset=0, tournament=DEFAULT_TOURNAMENT): |
87 | 131 | """Get the leaderboard.""" |
88 | | - click.echo(prettify(napi.get_leaderboard(limit=limit, offset=offset))) |
| 132 | + api = _get_api(tournament) |
| 133 | + method = _require_method(api, 'get_leaderboard', 'leaderboard') |
| 134 | + click.echo(prettify(method(limit=limit, offset=offset))) |
89 | 135 |
|
90 | 136 |
|
91 | 137 | @cli.command() |
92 | | -@click.option('--tournament', type=int, default=None, |
93 | | - help='filter by ID of the tournament, defaults to None') |
94 | 138 | @click.option('--round_num', type=int, default=None, |
95 | 139 | help='filter by round number, defaults to None') |
96 | 140 | @click.option( |
97 | 141 | '--model_id', type=str, default=None, |
98 | 142 | help="An account model UUID (required for accounts with multiple models") |
| 143 | +@tournament_option |
99 | 144 | def submission_filenames(round_num, tournament, model_id): |
100 | 145 | """Get filenames of your submissions""" |
| 146 | + api = _get_api(tournament) |
| 147 | + method = _require_method( |
| 148 | + api, 'get_submission_filenames', 'submission-filenames') |
101 | 149 | click.echo(prettify( |
102 | | - napi.get_submission_filenames(tournament, round_num, model_id))) |
| 150 | + method(tournament=tournament, round_num=round_num, model_id=model_id))) |
103 | 151 |
|
104 | 152 |
|
105 | 153 | @cli.command() |
106 | 154 | @click.option('--hours', default=12, |
107 | 155 | help='timeframe to consider, defaults to 12') |
108 | | -def check_new_round(hours=12): |
| 156 | +@tournament_option |
| 157 | +def check_new_round(hours=12, tournament=DEFAULT_TOURNAMENT): |
109 | 158 | """Check if a new round has started within the last `hours`.""" |
110 | | - click.echo(int(napi.check_new_round(hours=hours))) |
| 159 | + api = _get_api(tournament) |
| 160 | + click.echo(int(api.check_new_round(hours=hours))) |
111 | 161 |
|
112 | 162 |
|
113 | 163 | @cli.command() |
114 | | -def account(): |
| 164 | +@tournament_option |
| 165 | +def account(tournament=DEFAULT_TOURNAMENT): |
115 | 166 | """Get all information about your account!""" |
116 | | - click.echo(prettify(napi.get_account())) |
| 167 | + api = _get_api(tournament) |
| 168 | + click.echo(prettify(api.get_account())) |
117 | 169 |
|
118 | 170 |
|
119 | 171 | @cli.command() |
120 | | -@click.option('--tournament', default=8, |
121 | | - help='The ID of the tournament, defaults to 8') |
122 | | -def models(tournament): |
| 172 | +@tournament_option |
| 173 | +def models(tournament=DEFAULT_TOURNAMENT): |
123 | 174 | """Get map of account models!""" |
124 | | - click.echo(prettify(napi.get_models(tournament))) |
| 175 | + api = _get_api(tournament) |
| 176 | + click.echo(prettify(api.get_models(tournament))) |
125 | 177 |
|
126 | 178 |
|
127 | 179 | @cli.command() |
128 | 180 | @click.argument("username") |
129 | | -def profile(username): |
| 181 | +@tournament_option |
| 182 | +def profile(username, tournament=DEFAULT_TOURNAMENT): |
130 | 183 | """Fetch the public profile of a user.""" |
131 | | - click.echo(prettify(napi.public_user_profile(username))) |
| 184 | + api = _get_api(tournament) |
| 185 | + method = _require_method(api, 'public_user_profile', 'profile') |
| 186 | + click.echo(prettify(method(username))) |
132 | 187 |
|
133 | 188 |
|
134 | 189 | @cli.command() |
135 | 190 | @click.argument("username") |
136 | | -def daily_model_performances(username): |
| 191 | +@tournament_option |
| 192 | +def daily_model_performances(username, tournament=DEFAULT_TOURNAMENT): |
137 | 193 | """Fetch daily performance of a model.""" |
138 | | - click.echo(prettify(napi.daily_model_performances(username))) |
| 194 | + api = _get_api(tournament) |
| 195 | + method = _require_method( |
| 196 | + api, 'daily_model_performances', 'daily-model-performances') |
| 197 | + click.echo(prettify(method(username))) |
139 | 198 |
|
140 | 199 |
|
141 | 200 | @cli.command() |
142 | | -def transactions(): |
| 201 | +@tournament_option |
| 202 | +def transactions(tournament=DEFAULT_TOURNAMENT): |
143 | 203 | """List all your deposits and withdrawals.""" |
144 | | - click.echo(prettify(napi.wallet_transactions())) |
| 204 | + api = _get_api(tournament) |
| 205 | + click.echo(prettify(api.wallet_transactions())) |
145 | 206 |
|
146 | 207 |
|
147 | 208 | @cli.command() |
148 | | -@click.option('--tournament', default=8, |
149 | | - help='The ID of the tournament, defaults to 8') |
150 | 209 | @click.option( |
151 | 210 | '--model_id', type=str, default=None, |
152 | 211 | help="An account model UUID (required for accounts with multiple models") |
153 | 212 | @click.argument('path', type=click.Path(exists=True)) |
154 | | -def submit(path, tournament, model_id): |
| 213 | +@tournament_option |
| 214 | +def submit(path, model_id, tournament=DEFAULT_TOURNAMENT): |
155 | 215 | """Upload predictions from file.""" |
156 | | - click.echo(napi.upload_predictions( |
157 | | - path, tournament, model_id)) |
| 216 | + api = _get_api(tournament) |
| 217 | + click.echo(api.upload_predictions(path, model_id=model_id)) |
158 | 218 |
|
159 | 219 |
|
160 | 220 | @cli.command() |
161 | 221 | @click.argument("username") |
162 | | -def stake_get(username): |
| 222 | +@tournament_option |
| 223 | +def stake_get(username, tournament=DEFAULT_TOURNAMENT): |
163 | 224 | """Get stake value of a user.""" |
164 | | - click.echo(napi.stake_get(username)) |
| 225 | + api = _get_api(tournament) |
| 226 | + method = _require_method(api, 'stake_get', 'stake-get') |
| 227 | + click.echo(method(username)) |
165 | 228 |
|
166 | 229 |
|
167 | 230 | @cli.command() |
168 | 231 | @click.option( |
169 | 232 | '--model_id', type=str, default=None, |
170 | 233 | help="An account model UUID (required for accounts with multiple models") |
171 | | -def stake_drain(model_id): |
| 234 | +@tournament_option |
| 235 | +def stake_drain(model_id, tournament=DEFAULT_TOURNAMENT): |
172 | 236 | """Completely remove your stake.""" |
173 | | - click.echo(napi.stake_drain(model_id)) |
| 237 | + api = _get_api(tournament) |
| 238 | + click.echo(api.stake_drain(model_id)) |
174 | 239 |
|
175 | 240 |
|
176 | 241 | @cli.command() |
177 | 242 | @click.argument("nmr") |
178 | 243 | @click.option( |
179 | 244 | '--model_id', type=str, default=None, |
180 | 245 | help="An account model UUID (required for accounts with multiple models") |
181 | | -def stake_decrease(nmr, model_id): |
| 246 | +@tournament_option |
| 247 | +def stake_decrease(nmr, model_id, tournament=DEFAULT_TOURNAMENT): |
182 | 248 | """Decrease your stake by `value` NMR.""" |
183 | | - click.echo(napi.stake_decrease(nmr, model_id)) |
| 249 | + api = _get_api(tournament) |
| 250 | + click.echo(api.stake_decrease(nmr, model_id)) |
184 | 251 |
|
185 | 252 |
|
186 | 253 | @cli.command() |
187 | 254 | @click.argument("nmr") |
188 | 255 | @click.option( |
189 | 256 | '--model_id', type=str, default=None, |
190 | 257 | help="An account model UUID (required for accounts with multiple models") |
191 | | -def stake_increase(nmr, model_id): |
| 258 | +@tournament_option |
| 259 | +def stake_increase(nmr, model_id, tournament=DEFAULT_TOURNAMENT): |
192 | 260 | """Increase your stake by `value` NMR.""" |
193 | | - click.echo(napi.stake_increase(nmr, model_id)) |
| 261 | + api = _get_api(tournament) |
| 262 | + click.echo(api.stake_increase(nmr, model_id)) |
194 | 263 |
|
195 | 264 |
|
196 | 265 | @cli.command() |
|
0 commit comments