Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions numerapi/signalsapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,18 +284,29 @@ def ticker_universe(self) -> List[str]:
path = self.download_dataset("signals/v1.0/live.parquet")
return pd.read_parquet(path).numerai_ticker.tolist()

def stake_get(self, username) -> decimal.Decimal:
"""get current stake for a given users
def stake_get(self, username) -> decimal.Decimal | None:
"""get current stake for a given user

Args:
username (str)

Returns:
decimal.Decimal: current stake
decimal.Decimal or None: current stake, or None if the model has
no stake

Example:
>>> SignalsAPI().stake_get("uuazed")
Decimal('14.63')
"""
data = self.public_user_profile(username)
return data['totalStake']
query = """
query($model_name: String!
$tournament: Int) {
v3UserProfile(model_name: $model_name
tournament: $tournament) {
Comment on lines +304 to +305

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Query the Signals profile endpoint

In a SignalsAPI call, the username identifies a Signals model; this class and the changelog map Signals profiles to v2SignalsProfile, while v3UserProfile is the Classic profile endpoint. For Signals-only model names this call will not find the model, and for names shared across tournaments it can return the Classic stake instead, so SignalsAPI().stake_get(...) still gives users the wrong result. Use the Signals profile stake field (nmrStaked) instead.

Useful? React with 👍 / 👎.

stakeValue
}
}
"""
arguments = {'model_name': username, 'tournament': self.tournament_id}
data = self.raw_query(query, arguments)['data']['v3UserProfile']
return utils.parse_float_string(data['stakeValue'])
24 changes: 24 additions & 0 deletions tests/test_signalsapi.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import decimal
from unittest.mock import patch

import pytest
import responses

Expand All @@ -13,6 +16,27 @@ def api_fixture():
return api


@patch("numerapi.signalsapi.SignalsAPI.raw_query")
def test_stake_get(mocked, api):
mocked.return_value = {"data": {"v3UserProfile": {"stakeValue": "14.63"}}}

stake = api.stake_get("uuazed")

assert stake == decimal.Decimal("14.63")
args, _ = mocked.call_args
# current stake lives in `stakeValue`; `totalStake` no longer exists
assert "stakeValue" in args[0]
assert "totalStake" not in args[0]
assert args[1]["tournament"] == api.tournament_id == 11


@patch("numerapi.signalsapi.SignalsAPI.raw_query")
def test_stake_get_no_stake(mocked, api):
# a model with no stake returns null -> None, not a KeyError
mocked.return_value = {"data": {"v3UserProfile": {"stakeValue": None}}}
assert api.stake_get("uuazed") is None


@pytest.mark.live_api
def test_get_leaderboard(api):
lb = api.get_leaderboard(1)
Expand Down