numerapi 2.19.1__tar.gz → 2.20.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: numerapi
3
- Version: 2.19.1
3
+ Version: 2.20.1
4
4
  Summary: Automatically download and upload data for the Numerai machine learning competition
5
5
  Home-page: https://github.com/uuazed/numerapi
6
6
  Maintainer: uuazed
@@ -168,5 +168,3 @@ Each command has it's own help page, for example:
168
168
 
169
169
  Checkout the [detailed API docs](http://numerapi.readthedocs.io/en/latest/api/numerapi.html#module-numerapi.numerapi)
170
170
  to learn about all available methods, parameters and returned values.
171
-
172
-
@@ -46,12 +46,10 @@ class Api:
46
46
  self.tournament_id = 0
47
47
  self.global_data_dir = "."
48
48
 
49
- def _login(self, public_id=None, secret_key=None):
49
+ def _login(self, public_id: str | None = None, secret_key: str | None = None) -> None:
50
50
  # check env variables if not set
51
- if not public_id:
52
- public_id = os.getenv("NUMERAI_PUBLIC_ID")
53
- if not secret_key:
54
- secret_key = os.getenv("NUMERAI_SECRET_KEY")
51
+ if not public_id or not secret_key:
52
+ public_id, secret_key = utils.load_secrets()
55
53
 
56
54
  if public_id and secret_key:
57
55
  self.token = (public_id, secret_key)
@@ -76,7 +74,7 @@ class Api:
76
74
 
77
75
  def raw_query(self, query: str, variables: Dict = None,
78
76
  authorization: bool = False,
79
- retries: int = 3, delay: int = 5, backoff: int = 2):
77
+ *, retries: int = 3, delay: int = 5, backoff: int = 2):
80
78
  """Send a raw request to the Numerai's GraphQL API.
81
79
 
82
80
  This function allows to build your own queries and fetch results from
@@ -391,15 +389,6 @@ class Api:
391
389
  round_num = data["number"]
392
390
  return round_num
393
391
 
394
- def get_account_transactions(self) -> List:
395
- """Get all your account deposits and withdrawals.
396
-
397
- DEPRECATED - please use `wallet_transactions` instead"
398
- """
399
- self.logger.warning(
400
- "DEPRECATED - please use `wallet_transactions` instead")
401
- return self.wallet_transactions()
402
-
403
392
  def set_bio(self, model_id: str, bio: str) -> bool:
404
393
  """Set bio field for a model id.
405
394
 
@@ -573,7 +562,6 @@ class Api:
573
562
  Args:
574
563
  file_path (str): CSV file with predictions that will get uploaded
575
564
  tournament (int): ID of the tournament (optional, defaults to None)
576
- -- DEPRECATED there is only one tournament nowadays
577
565
  model_id (str): Target model UUID (required for accounts with
578
566
  multiple models)
579
567
  df (pandas.DataFrame): pandas DataFrame to upload, if function is
@@ -939,129 +927,12 @@ class Api:
939
927
  def round_model_performances(self, username: str) -> List[Dict]:
940
928
  """Fetch round model performance of a user.
941
929
 
942
- Args:
943
- username (str)
944
-
945
- Returns:
946
- list of dicts: list of round model performance entries
947
-
948
- For each entry in the list, there is a dict with the following
949
- content:
950
-
951
- * corr (`float`)
952
- * corr20V2 (`float` or None)
953
- * corr20V2Percentile (`float` or None)
954
- * corr20d (`float` or None)
955
- * corr20dPercentile (`float` or None)
956
- * corrMultiplier (`float`)
957
- * corrPercentile (`float`)
958
- * corrWMetamodel (`float`)
959
- * tc (`float`)
960
- * tcPercentile (`float`)
961
- * tcMultiplier (`float`)
962
- * ic (`float`)
963
- * icPercentile (`float`)
964
- * fnc (`float`)
965
- * fncPercentile (`float`)
966
- * fncV3 (`float`)
967
- * fncV3Percentile (`float`)
968
- * mmc (`float`)
969
- * mmc20d (`float` or None)
970
- * mmc20dPercentile (`float` or None)
971
- * mmcMultiplier (`float`)
972
- * mmcPercentile (`float`)
973
- * payout (`Decimal`)
974
- * roundNumber (`int`)
975
- * roundOpenTime (`datetime`)
976
- * roundPayoutFactor (`Decimal`)
977
- * roundResolveTime (`datetime`)
978
- * roundResolved (`bool`)
979
- * roundTarget (`str` or None)
980
- * selectedStakeValue (`Decimal`)
981
-
982
- Example:
983
- >>> api = NumerAPI()
984
- >>> api.round_model_performances("uuazed")
985
- [{'corr': -0.01296840448965,
986
- 'corr20V2': None,
987
- 'corr20V2Percentile': None,
988
- 'corr20d': None,
989
- 'corr20dPercentile': None,
990
- 'corrMultiplier': 1.0,
991
- 'corrPercentile': 0.0411107104219257,
992
- 'corrWMetamodel': 0.51542251407092,
993
- 'tc': 0.1415973344,
994
- 'tcPercentile': 0.115398485394879,
995
- 'ic': 0.1415973344,
996
- 'icPercentile': 0.115398485394879,
997
- 'fnc': 0.000437631996046271,
998
- 'fncPercentile': 0.115398485394879,
999
- 'fncV3': 0.000437631996046271,
1000
- 'fncV3Percentile': 0.115398485394879,
1001
- 'mmc': -0.0152125841680981,
1002
- 'mmc20d': None,
1003
- 'mmc20dPercentile': None,
1004
- ...
1005
- ]
930
+ DEPRECATED - please use `round_model_performances_v2` instead
1006
931
  """
1007
- if self.tournament_id == 8:
1008
- endpoint = "v3UserProfile"
1009
- elif self.tournament_id == 11:
1010
- endpoint = "v2SignalsProfile"
1011
- else:
1012
- raise ValueError("round_model_performances is not available for ",
1013
- f"tournament {self.tournament_id}")
1014
932
  self.logger.warning(
1015
- "Deprecated soon. Checkout round_model_performances_v2.")
1016
- query = f"""
1017
- query($username: String!) {{
1018
- {endpoint}(modelName: $username) {{
1019
- roundModelPerformances {{
1020
- corr
1021
- corr20V2
1022
- corr20V2Percentile
1023
- corr20d
1024
- corr20dPercentile
1025
- corrMultiplier
1026
- corrPercentile
1027
- corrWMetamodel
1028
- tc
1029
- tcPercentile
1030
- ic
1031
- icPercentile
1032
- fnc
1033
- fncPercentile
1034
- fncV3
1035
- fncV3Percentile
1036
- mmc
1037
- mmc20d
1038
- mmc20dPercentile
1039
- mmcMultiplier
1040
- mmcPercentile
1041
- payout
1042
- roundNumber
1043
- roundOpenTime
1044
- roundPayoutFactor
1045
- roundResolveTime
1046
- roundResolved
1047
- roundTarget
1048
- selectedStakeValue
1049
- tcMultiplier
1050
- }}
1051
- }}
1052
- }}
1053
- """
1054
- arguments = {'username': username}
1055
- data = self.raw_query(query, arguments)['data'][endpoint]
1056
- performances = data['roundModelPerformances']
1057
- # convert strings to python objects
1058
- for perf in performances:
1059
- utils.replace(perf, "roundOpenTime", utils.parse_datetime_string)
1060
- utils.replace(perf, "roundResolveTime", utils.parse_datetime_string)
1061
- utils.replace(perf, "payout", utils.parse_float_string)
1062
- utils.replace(perf, "roundPayoutFactor", utils.parse_float_string)
1063
- utils.replace(perf, "selectedStakeValue", utils.parse_float_string)
1064
- return performances
933
+ "Deprecated. Checkout round_model_performances_v2.")
934
+ return self.round_model_performances_v2(username)
935
+
1065
936
 
1066
937
  def stake_change(self, nmr, action: str = "decrease",
1067
938
  model_id: str = None) -> Dict:
@@ -1196,7 +1067,6 @@ class Api:
1196
1067
  model_id (str): Target model UUID (required for accounts with
1197
1068
  multiple models)
1198
1069
  tournament (int): ID of the tournament (optional, defaults to 8)
1199
- -- DEPRECATED there is only one tournament nowadays
1200
1070
 
1201
1071
  Returns:
1202
1072
  dict: stake information with the following content:
@@ -1240,7 +1110,7 @@ class Api:
1240
1110
  arguments = {'tournament': self.tournament_id}
1241
1111
  # in some period in between rounds, "number: 0" returns Value error -
1242
1112
  # "Current round not open for submissions", because there is no active
1243
- # round. This is catched by the try / except.
1113
+ # round. This is caught by the try / except.
1244
1114
  try:
1245
1115
  raw = self.raw_query(query, arguments)['data']['rounds'][0]
1246
1116
  except ValueError:
@@ -1259,7 +1129,6 @@ class Api:
1259
1129
  Args:
1260
1130
  hours (int, optional): timeframe to consider, defaults to 12
1261
1131
  tournament (int): ID of the tournament (optional)
1262
- -- DEPRECATED this is now automatically filled
1263
1132
 
1264
1133
  Returns:
1265
1134
  bool: True if a new round has started, False otherwise.
@@ -1281,7 +1150,7 @@ class Api:
1281
1150
  arguments = {'tournament': tournament}
1282
1151
  # in some period in between rounds, "number: 0" returns Value error -
1283
1152
  # "Current round not open for submissions", because there is no active
1284
- # round. This is catched by the try / except.
1153
+ # round. This is caught by the try / except.
1285
1154
  try:
1286
1155
  raw = self.raw_query(query, arguments)['data']['rounds'][0]
1287
1156
  except ValueError:
@@ -112,15 +112,6 @@ def check_new_round(hours=12, tournament=8):
112
112
  click.echo(int(napi.check_new_round(hours=hours, tournament=tournament)))
113
113
 
114
114
 
115
- @cli.command()
116
- @click.option(
117
- '--model_id', type=str, default=None,
118
- help="An account model UUID (required for accounts with multiple models")
119
- def user(model_id):
120
- """Get all information about you! DEPRECATED - use account"""
121
- click.echo(prettify(napi.get_user(model_id)))
122
-
123
-
124
115
  @cli.command()
125
116
  def account():
126
117
  """Get all information about your account!"""
@@ -1,3 +1,5 @@
1
+ """API for Numerai Crypto"""
2
+
1
3
  from numerapi import base_api
2
4
 
3
5
  class CryptoAPI(base_api.Api):
@@ -28,7 +28,6 @@ class NumerAPI(base_api.Api):
28
28
 
29
29
  Args:
30
30
  tournament (int, optional): ID of the tournament, defaults to 8
31
- -- DEPRECATED there is only one tournament nowadays
32
31
 
33
32
  Returns:
34
33
  list of dicts: list of rounds
@@ -81,7 +80,6 @@ class NumerAPI(base_api.Api):
81
80
 
82
81
  Args:
83
82
  tournament (int): optionally filter by ID of the tournament
84
- -- DEPRECATED there is only one tournament nowadays
85
83
  round_num (int): optionally filter round number
86
84
  model_id (str): Target model UUID (required for accounts with
87
85
  multiple models)
@@ -134,112 +132,6 @@ class NumerAPI(base_api.Api):
134
132
  filenames.sort(key=lambda f: (f['round_num'], f['tournament']))
135
133
  return filenames
136
134
 
137
- def get_user(self, model_id: str = None) -> Dict:
138
- """Get all information about you! DEPRECATED
139
-
140
- Args:
141
- model_id (str): Target model UUID (required for accounts with
142
- multiple models)
143
-
144
- Returns:
145
- dict: user information including the following fields:
146
-
147
- * assignedEthAddress (`str`)
148
- * availableNmr (`decimal.Decimal`)
149
- * availableUsd (`decimal.Decimal`)
150
- * banned (`bool`)
151
- * email (`str`)
152
- * id (`str`)
153
- * insertedAt (`datetime`)
154
- * mfaEnabled (`bool`)
155
- * status (`str`)
156
- * username (`str`)
157
- * country (`str)
158
- * apiTokens (`list`) each with the following fields:
159
- * name (`str`)
160
- * public_id (`str`)
161
- * scopes (`list of str`)
162
- * v2Stake
163
- * status (`str`)
164
- * txHash (`str`)
165
-
166
- Example:
167
- >>> api = NumerAPI(secret_key="..", public_id="..")
168
- >>> model = api.get_models()['uuazed']
169
- >>> api.get_user(model)
170
- {'apiTokens': [
171
- {'name': 'tokenname',
172
- 'public_id': 'BLABLA',
173
- 'scopes': ['upload_submission', 'stake', ..]
174
- }, ..],
175
- 'assignedEthAddress': '0x0000000000000000000000000001',
176
- 'availableNmr': Decimal('99.01'),
177
- 'availableUsd': Decimal('9.47'),
178
- 'banned': False,
179
- 'email': 'username@example.com',
180
- 'country': 'US',
181
- 'id': '1234-ABC..',
182
- 'insertedAt': datetime.datetime(2018, 1, 1, 2, 16, 48),
183
- 'mfaEnabled': False,
184
- 'status': 'VERIFIED',
185
- 'username': 'cool username',
186
- 'v2Stake': None
187
- }
188
- """
189
- self.logger.warning("Method get_user is DEPRECATED, use get_account")
190
- query = """
191
- query($modelId: String) {
192
- user(modelId: $modelId) {
193
- username
194
- banned
195
- assignedEthAddress
196
- availableNmr
197
- availableUsd
198
- email
199
- id
200
- mfaEnabled
201
- status
202
- country
203
- insertedAt
204
- apiTokens {
205
- name
206
- public_id
207
- scopes
208
- }
209
- v2Stake {
210
- status
211
- txHash
212
- }
213
- }
214
- }
215
- """
216
- arguments = {'modelId': model_id}
217
- data = self.raw_query(
218
- query, arguments, authorization=True)['data']['user']
219
- # convert strings to python objects
220
- utils.replace(data, "insertedAt", utils.parse_datetime_string)
221
- utils.replace(data, "availableUsd", utils.parse_float_string)
222
- utils.replace(data, "availableNmr", utils.parse_float_string)
223
- return data
224
-
225
- def submission_status(self, model_id: str = None) -> None:
226
- """submission status of the last submission associated with the account
227
-
228
- DEPRECATED numerai no longer provides this data. This will be removed
229
- in one of the next versions
230
-
231
- Args:
232
- model_id (str): Target model UUID (required for accounts with
233
- multiple models)
234
-
235
- Example:
236
- >>> napi = NumerAPI(secret_key="..", public_id="..")
237
- >>> model_id = napi.get_models()['uuazed']
238
- >>> napi.submission_status(model_id)
239
- """
240
- _ = model_id
241
- self.logger.warning("Method submission_status is DEPRECATED and will be removed soon.")
242
-
243
135
  def get_leaderboard(self, limit: int = 50, offset: int = 0) -> List[Dict]:
244
136
  """Get the current model leaderboard
245
137
 
@@ -423,12 +315,6 @@ class NumerAPI(base_api.Api):
423
315
  utils.replace(data, "startDate", utils.parse_datetime_string)
424
316
  return data
425
317
 
426
- def daily_user_performances(self, username: str) -> List[Dict]:
427
- """DEPRECATED"""
428
- self.logger.warning("Method daily_user_performances is DEPRECATED, "
429
- "use daily_model_performances")
430
- return self.daily_model_performances(username)
431
-
432
318
  def daily_model_performances(self, username: str) -> List[Dict]:
433
319
  """Fetch daily performance of a user.
434
320
 
@@ -151,23 +151,6 @@ class SignalsAPI(base_api.Api):
151
151
  create = self.raw_query(create_query, arguments, authorization=True)
152
152
  return create['data']['createSignalsSubmission']['id']
153
153
 
154
- def submission_status(self, model_id: str = None) -> None:
155
- """submission status of the last submission associated with the account
156
-
157
- DEPRECATED numerai no longer provides this data. This will be removed
158
- in one of the next versions
159
-
160
- Args:
161
- model_id (str)
162
-
163
- Example:
164
- >>> api = SignalsAPI(secret_key="..", public_id="..")
165
- >>> model_id = api.get_models()['uuazed']
166
- >>> api.submission_status(model_id)
167
- """
168
- _ = model_id
169
- self.logger.warning("Method submission_status is DEPRECATED and will be removed soon.")
170
-
171
154
  def public_user_profile(self, username: str) -> Dict:
172
155
  """Fetch the public Numerai Signals profile of a user.
173
156
 
@@ -301,12 +284,6 @@ class SignalsAPI(base_api.Api):
301
284
  path = self.download_dataset("signals/v1.0/live.parquet")
302
285
  return pd.read_parquet(path).numerai_ticker.tolist()
303
286
 
304
- def download_validation_data(self) -> None:
305
- """download CSV file with historical targets and ticker universe
306
- """
307
- self.logger.warning("'download_validation_data' is DEPRECATED.")
308
- self.logger.warning("Please use 'download_dataset' and 'list_datasets'")
309
-
310
287
  def stake_get(self, username) -> decimal.Decimal:
311
288
  """get current stake for a given users
312
289
 
@@ -16,6 +16,21 @@ import tqdm
16
16
  logger = logging.getLogger(__name__)
17
17
 
18
18
 
19
+ def load_secrets() -> tuple:
20
+ """load secrets from environment variables or dotenv file"""
21
+
22
+ try:
23
+ from dotenv import load_dotenv # pylint: disable-msg=import-outside-toplevel
24
+ load_dotenv()
25
+ except ImportError:
26
+ pass
27
+
28
+ public_id = os.getenv("NUMERAI_PUBLIC_ID")
29
+ secret_key = os.getenv("NUMERAI_SECRET_KEY")
30
+
31
+ return public_id, secret_key
32
+
33
+
19
34
  def parse_datetime_string(string: str) -> Optional[datetime.datetime]:
20
35
  """try to parse string to datetime object"""
21
36
  if string is None:
@@ -91,7 +106,7 @@ def download_file(url: str, dest_path: str, show_progress_bars: bool = True):
91
106
 
92
107
 
93
108
  def post_with_err_handling(url: str, body: str, headers: Dict,
94
- timeout: Optional[int] = None,
109
+ *, timeout: Optional[int] = None,
95
110
  retries: int = 3, delay: int = 1, backoff: int = 2
96
111
  ) -> Dict:
97
112
  """send `post` request and handle (some) errors that might occur"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: numerapi
3
- Version: 2.19.1
3
+ Version: 2.20.1
4
4
  Summary: Automatically download and upload data for the Numerai machine learning competition
5
5
  Home-page: https://github.com/uuazed/numerapi
6
6
  Maintainer: uuazed
@@ -168,5 +168,3 @@ Each command has it's own help page, for example:
168
168
 
169
169
  Checkout the [detailed API docs](http://numerapi.readthedocs.io/en/latest/api/numerapi.html#module-numerapi.numerapi)
170
170
  to learn about all available methods, parameters and returned values.
171
-
172
-
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  numerapi = numerapi.cli:cli
3
-
@@ -6,7 +6,7 @@ def load(path):
6
6
  return open(path, 'r').read()
7
7
 
8
8
 
9
- numerapi_version = '2.19.1'
9
+ numerapi_version = '2.20.1'
10
10
 
11
11
 
12
12
  classifiers = [
File without changes
File without changes
File without changes