prediction-market-agent-tooling 0.48.17__py3-none-any.whl → 0.48.18__py3-none-any.whl
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.
- prediction_market_agent_tooling/deploy/agent.py +0 -1
- prediction_market_agent_tooling/deploy/betting_strategy.py +67 -0
- prediction_market_agent_tooling/markets/omen/omen_resolving.py +3 -1
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +20 -2
- prediction_market_agent_tooling/tools/omen/reality_accuracy.py +74 -0
- prediction_market_agent_tooling/tools/utils.py +18 -0
- {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.48.18.dist-info}/METADATA +1 -1
- {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.48.18.dist-info}/RECORD +11 -10
- {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.48.18.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.48.18.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.48.18.dist-info}/entry_points.txt +0 -0
@@ -283,7 +283,6 @@ class DeployableTraderAgent(DeployableAgent):
|
|
283
283
|
min_required_balance_to_operate: xDai | None = xdai_type(1)
|
284
284
|
min_balance_to_keep_in_native_currency: xDai | None = xdai_type(0.1)
|
285
285
|
strategy: BettingStrategy = MaxAccuracyBettingStrategy()
|
286
|
-
allow_opposite_bets: bool = False
|
287
286
|
|
288
287
|
def __init__(
|
289
288
|
self,
|
@@ -141,6 +141,9 @@ class MaxAccuracyBettingStrategy(BettingStrategy):
|
|
141
141
|
def calculate_direction(market_p_yes: float, estimate_p_yes: float) -> bool:
|
142
142
|
return estimate_p_yes >= 0.5
|
143
143
|
|
144
|
+
def __repr__(self) -> str:
|
145
|
+
return f"{self.__class__.__name__}(bet_amount={self.bet_amount})"
|
146
|
+
|
144
147
|
|
145
148
|
class MaxExpectedValueBettingStrategy(MaxAccuracyBettingStrategy):
|
146
149
|
@staticmethod
|
@@ -202,3 +205,67 @@ class KellyBettingStrategy(BettingStrategy):
|
|
202
205
|
existing_position, target_position, market=market
|
203
206
|
)
|
204
207
|
return trades
|
208
|
+
|
209
|
+
def __repr__(self) -> str:
|
210
|
+
return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount})"
|
211
|
+
|
212
|
+
|
213
|
+
class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
|
214
|
+
def __init__(self, max_bet_amount: float = 10):
|
215
|
+
self.max_bet_amount = max_bet_amount
|
216
|
+
|
217
|
+
def adjust_bet_amount(
|
218
|
+
self, existing_position: Position | None, market: AgentMarket
|
219
|
+
) -> float:
|
220
|
+
existing_position_total_amount = (
|
221
|
+
existing_position.total_amount.amount if existing_position else 0
|
222
|
+
)
|
223
|
+
return self.max_bet_amount + existing_position_total_amount
|
224
|
+
|
225
|
+
def calculate_trades(
|
226
|
+
self,
|
227
|
+
existing_position: Position | None,
|
228
|
+
answer: ProbabilisticAnswer,
|
229
|
+
market: AgentMarket,
|
230
|
+
) -> list[Trade]:
|
231
|
+
adjusted_bet_amount = self.adjust_bet_amount(existing_position, market)
|
232
|
+
outcome_token_pool = check_not_none(market.outcome_token_pool)
|
233
|
+
|
234
|
+
# Fixed direction of bet, only use Kelly to adjust the bet size based on market's outcome pool size.
|
235
|
+
estimated_p_yes = float(answer.p_yes > 0.5)
|
236
|
+
confidence = 1.0
|
237
|
+
|
238
|
+
kelly_bet = (
|
239
|
+
get_kelly_bet_full(
|
240
|
+
yes_outcome_pool_size=outcome_token_pool[
|
241
|
+
market.get_outcome_str_from_bool(True)
|
242
|
+
],
|
243
|
+
no_outcome_pool_size=outcome_token_pool[
|
244
|
+
market.get_outcome_str_from_bool(False)
|
245
|
+
],
|
246
|
+
estimated_p_yes=estimated_p_yes,
|
247
|
+
max_bet=adjusted_bet_amount,
|
248
|
+
confidence=confidence,
|
249
|
+
)
|
250
|
+
if market.has_token_pool()
|
251
|
+
else get_kelly_bet_simplified(
|
252
|
+
adjusted_bet_amount,
|
253
|
+
market.current_p_yes,
|
254
|
+
estimated_p_yes,
|
255
|
+
confidence,
|
256
|
+
)
|
257
|
+
)
|
258
|
+
|
259
|
+
amounts = {
|
260
|
+
market.get_outcome_str_from_bool(kelly_bet.direction): TokenAmount(
|
261
|
+
amount=kelly_bet.size, currency=market.currency
|
262
|
+
),
|
263
|
+
}
|
264
|
+
target_position = Position(market_id=market.id, amounts=amounts)
|
265
|
+
trades = self._build_rebalance_trades_from_positions(
|
266
|
+
existing_position, target_position, market=market
|
267
|
+
)
|
268
|
+
return trades
|
269
|
+
|
270
|
+
def __repr__(self) -> str:
|
271
|
+
return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount})"
|
@@ -66,7 +66,9 @@ def claim_bonds_on_realitio_question(
|
|
66
66
|
realitio_contract = OmenRealitioContract()
|
67
67
|
|
68
68
|
# Get all answers for the question.
|
69
|
-
responses = OmenSubgraphHandler().get_responses(
|
69
|
+
responses = OmenSubgraphHandler().get_responses(
|
70
|
+
limit=None, question_id=question.questionId
|
71
|
+
)
|
70
72
|
|
71
73
|
# They need to be processed in order.
|
72
74
|
responses = sorted(responses, key=lambda x: x.timestamp)
|
@@ -677,6 +677,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
|
|
677
677
|
|
678
678
|
def get_questions(
|
679
679
|
self,
|
680
|
+
limit: int | None,
|
680
681
|
user: HexAddress | None = None,
|
681
682
|
claimed: bool | None = None,
|
682
683
|
current_answer_before: datetime | None = None,
|
@@ -694,7 +695,12 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
|
|
694
695
|
id_in=id_in,
|
695
696
|
question_id_in=question_id_in,
|
696
697
|
)
|
697
|
-
questions = self.realityeth_subgraph.Query.questions(
|
698
|
+
questions = self.realityeth_subgraph.Query.questions(
|
699
|
+
first=(
|
700
|
+
limit if limit else sys.maxsize
|
701
|
+
), # if not limit, we fetch all possible
|
702
|
+
where=where_stms,
|
703
|
+
)
|
698
704
|
fields = self._get_fields_for_reality_questions(questions)
|
699
705
|
result = self.sg.query_json(fields)
|
700
706
|
items = self._parse_items_from_json(result)
|
@@ -715,10 +721,14 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
|
|
715
721
|
|
716
722
|
def get_responses(
|
717
723
|
self,
|
724
|
+
limit: int | None,
|
718
725
|
user: HexAddress | None = None,
|
719
726
|
question_id: HexBytes | None = None,
|
720
727
|
question_claimed: bool | None = None,
|
721
728
|
question_finalized_before: datetime | None = None,
|
729
|
+
question_finalized_after: datetime | None = None,
|
730
|
+
question_current_answer_before: datetime | None = None,
|
731
|
+
question_id_in: list[HexBytes] | None = None,
|
722
732
|
) -> list[RealityResponse]:
|
723
733
|
where_stms: dict[str, t.Any] = {}
|
724
734
|
|
@@ -729,9 +739,17 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
|
|
729
739
|
question_id=question_id,
|
730
740
|
claimed=question_claimed,
|
731
741
|
finalized_before=question_finalized_before,
|
742
|
+
finalized_after=question_finalized_after,
|
743
|
+
current_answer_before=question_current_answer_before,
|
744
|
+
question_id_in=question_id_in,
|
732
745
|
)
|
733
746
|
|
734
|
-
responses = self.realityeth_subgraph.Query.responses(
|
747
|
+
responses = self.realityeth_subgraph.Query.responses(
|
748
|
+
first=(
|
749
|
+
limit if limit else sys.maxsize
|
750
|
+
), # if not limit, we fetch all possible
|
751
|
+
where=where_stms,
|
752
|
+
)
|
735
753
|
fields = self._get_fields_for_responses(responses)
|
736
754
|
result = self.sg.query_json(fields)
|
737
755
|
items = self._parse_items_from_json(result)
|
@@ -0,0 +1,74 @@
|
|
1
|
+
from datetime import timedelta
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
|
5
|
+
from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
|
6
|
+
ChecksumAddress,
|
7
|
+
OmenSubgraphHandler,
|
8
|
+
RealityResponse,
|
9
|
+
)
|
10
|
+
from prediction_market_agent_tooling.tools.utils import utcnow
|
11
|
+
|
12
|
+
|
13
|
+
class RealityAccuracyReport(BaseModel):
|
14
|
+
total: int
|
15
|
+
correct: int
|
16
|
+
|
17
|
+
@property
|
18
|
+
def accuracy(self) -> float:
|
19
|
+
return self.correct / self.total
|
20
|
+
|
21
|
+
|
22
|
+
def reality_accuracy(user: ChecksumAddress, since: timedelta) -> RealityAccuracyReport:
|
23
|
+
now = utcnow()
|
24
|
+
start_from = now - since
|
25
|
+
|
26
|
+
# Get all question ids where we placed the higher bond.
|
27
|
+
user_responses = OmenSubgraphHandler().get_responses(
|
28
|
+
limit=None,
|
29
|
+
user=user,
|
30
|
+
question_finalized_before=now,
|
31
|
+
question_finalized_after=start_from,
|
32
|
+
)
|
33
|
+
unique_question_ids = set(r.question.questionId for r in user_responses)
|
34
|
+
|
35
|
+
# Get all responses for these questions (including not ours)
|
36
|
+
question_to_responses = {
|
37
|
+
question_id: OmenSubgraphHandler().get_responses(
|
38
|
+
limit=None, question_id=question_id
|
39
|
+
)
|
40
|
+
for question_id in unique_question_ids
|
41
|
+
}
|
42
|
+
|
43
|
+
total = 0
|
44
|
+
correct = 0
|
45
|
+
|
46
|
+
for question_id, responses in question_to_responses.items():
|
47
|
+
is_correct = user_was_correct(user, responses)
|
48
|
+
assert (
|
49
|
+
is_correct is not None
|
50
|
+
), f"All these questions should be challenged by provided user: {responses[0].question.url}"
|
51
|
+
|
52
|
+
total += 1
|
53
|
+
correct += int(is_correct)
|
54
|
+
|
55
|
+
return RealityAccuracyReport(total=total, correct=correct)
|
56
|
+
|
57
|
+
|
58
|
+
def user_was_correct(
|
59
|
+
user: ChecksumAddress, responses: list[RealityResponse]
|
60
|
+
) -> bool | None:
|
61
|
+
sorted_responses = sorted(responses, key=lambda r: r.timestamp)
|
62
|
+
users_sorted_responses = [r for r in sorted_responses if r.user_checksummed == user]
|
63
|
+
|
64
|
+
if not users_sorted_responses:
|
65
|
+
return None
|
66
|
+
|
67
|
+
# Find the user's last response
|
68
|
+
users_last_response = users_sorted_responses[-1]
|
69
|
+
|
70
|
+
# Last response is the final one (if market is finalized)
|
71
|
+
actual_resolution = sorted_responses[-1]
|
72
|
+
|
73
|
+
# Compare the user's last answer with the actual resolution
|
74
|
+
return users_last_response.answer == actual_resolution.answer
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import json
|
1
2
|
import os
|
2
3
|
import subprocess
|
3
4
|
import typing as t
|
@@ -6,12 +7,14 @@ from typing import Any, NoReturn, Optional, Type, TypeVar, cast
|
|
6
7
|
|
7
8
|
import pytz
|
8
9
|
import requests
|
10
|
+
from google.cloud import secretmanager
|
9
11
|
from pydantic import BaseModel, ValidationError
|
10
12
|
from scipy.optimize import newton
|
11
13
|
from scipy.stats import entropy
|
12
14
|
|
13
15
|
from prediction_market_agent_tooling.gtypes import (
|
14
16
|
DatetimeWithTimezone,
|
17
|
+
PrivateKey,
|
15
18
|
Probability,
|
16
19
|
SecretStr,
|
17
20
|
)
|
@@ -210,3 +213,18 @@ def calculate_sell_amount_in_collateral(
|
|
210
213
|
|
211
214
|
amount_to_sell = newton(f, 0)
|
212
215
|
return float(amount_to_sell) * 0.999999 # Avoid rounding errors
|
216
|
+
|
217
|
+
|
218
|
+
def get_private_key_from_gcp_secret(
|
219
|
+
secret_id: str,
|
220
|
+
project_id: str = "582587111398", # Gnosis AI default project_id
|
221
|
+
version_id: str = "latest",
|
222
|
+
) -> PrivateKey:
|
223
|
+
client = secretmanager.SecretManagerServiceClient()
|
224
|
+
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
|
225
|
+
response = client.access_secret_version(request={"name": name})
|
226
|
+
secret_payload = response.payload.data.decode("UTF-8")
|
227
|
+
secret_json = json.loads(secret_payload)
|
228
|
+
if "private_key" not in secret_json:
|
229
|
+
raise ValueError(f"Private key not found in gcp secret {secret_id}")
|
230
|
+
return PrivateKey(SecretStr(secret_json["private_key"]))
|
@@ -15,9 +15,9 @@ prediction_market_agent_tooling/benchmark/agents.py,sha256=BwE3U11tQq0rfOJBn-Xn5
|
|
15
15
|
prediction_market_agent_tooling/benchmark/benchmark.py,sha256=xiHKzZx5GHSsDerFHMZ9j_LXAXnSaITSvv67iPe3MEU,21095
|
16
16
|
prediction_market_agent_tooling/benchmark/utils.py,sha256=D0MfUkVZllmvcU0VOurk9tcKT7JTtwwOp-63zuCBVuc,2880
|
17
17
|
prediction_market_agent_tooling/config.py,sha256=9h68Nb9O1YZabZqtOBrH1S-4U5aIdLKfVYLSKspfUeA,6008
|
18
|
-
prediction_market_agent_tooling/deploy/agent.py,sha256=
|
18
|
+
prediction_market_agent_tooling/deploy/agent.py,sha256=Pgl6M5d0COjKtIpKNjickAhnvRJVQo-oYIGNTT7n7DY,19074
|
19
19
|
prediction_market_agent_tooling/deploy/agent_example.py,sha256=dIIdZashExWk9tOdyDjw87AuUcGyM7jYxNChYrVK2dM,1001
|
20
|
-
prediction_market_agent_tooling/deploy/betting_strategy.py,sha256=
|
20
|
+
prediction_market_agent_tooling/deploy/betting_strategy.py,sha256=SHDdgjlkjj0fAD4XUqVimOcqVHv9_JywR4BT68_srLM,10091
|
21
21
|
prediction_market_agent_tooling/deploy/constants.py,sha256=M5ty8URipYMGe_G-RzxRydK3AFL6CyvmqCraJUrLBnE,82
|
22
22
|
prediction_market_agent_tooling/deploy/gcp/deploy.py,sha256=CYUgnfy-9XVk04kkxA_5yp0GE9Mw5caYqlFUZQ2j3ks,3739
|
23
23
|
prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py,sha256=qYIHRxQLac3yxtZ8ChikiPG9O1aUQucHW0muTSm1nto,2627
|
@@ -44,8 +44,8 @@ prediction_market_agent_tooling/markets/omen/__init__.py,sha256=47DEQpj8HBSa-_TI
|
|
44
44
|
prediction_market_agent_tooling/markets/omen/data_models.py,sha256=PQyoENpXkhu5TXZhbUdDvKLsb2sQt8rwryPTVQ9fIeM,17029
|
45
45
|
prediction_market_agent_tooling/markets/omen/omen.py,sha256=TGXthQITMoYvx1iK388nHbv8U0DQeX_jyHb-OEinvfg,46676
|
46
46
|
prediction_market_agent_tooling/markets/omen/omen_contracts.py,sha256=MfaWfDDfEzHYVAbeT3Dgtl8KG7XsqEpdY3m3-rsOPwo,23588
|
47
|
-
prediction_market_agent_tooling/markets/omen/omen_resolving.py,sha256=
|
48
|
-
prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=
|
47
|
+
prediction_market_agent_tooling/markets/omen/omen_resolving.py,sha256=udzte2jD33tONHPfMGhQbkAlHePRuw5iF8YXy71P8qo,9555
|
48
|
+
prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=2K-B5rnT05oC0K1YbrB0cKXOz3wjagoDLXQ9fxBTlBs,30902
|
49
49
|
prediction_market_agent_tooling/markets/polymarket/api.py,sha256=HXmA1akA0qDj0m3e-GEvWG8x75pm6BX4H7YJPQcST7I,4767
|
50
50
|
prediction_market_agent_tooling/markets/polymarket/data_models.py,sha256=9CJzakyEcsn6DQBK2nOXjOMzTZBLAmK_KqevXvW17DI,4292
|
51
51
|
prediction_market_agent_tooling/markets/polymarket/data_models_web.py,sha256=IPsFT3FX9Ge5l5zR1nBd2w-sd5ue7oR8PJSW710vFWY,12479
|
@@ -76,16 +76,17 @@ prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py,sha256=8
|
|
76
76
|
prediction_market_agent_tooling/tools/is_predictable.py,sha256=QapzvJVgUZdhucgmxhzWAQ885BwSwvYUi0SG8mkLQMQ,6738
|
77
77
|
prediction_market_agent_tooling/tools/langfuse_.py,sha256=jI_4ROxqo41CCnWGS1vN_AeDVhRzLMaQLxH3kxDu3L8,1153
|
78
78
|
prediction_market_agent_tooling/tools/langfuse_client_utils.py,sha256=HZ8PN__CahMeNLaEx4v9esOqow6XEeezuYOOZD9-Ol8,4741
|
79
|
+
prediction_market_agent_tooling/tools/omen/reality_accuracy.py,sha256=M1SF7iSW1gVlQSTskdVFTn09uPLST23YeipVIWj54io,2236
|
79
80
|
prediction_market_agent_tooling/tools/parallelism.py,sha256=6Gou0hbjtMZrYvxjTDFUDZuxmE2nqZVbb6hkg1hF82A,1022
|
80
81
|
prediction_market_agent_tooling/tools/safe.py,sha256=h0xOO0eNtitClf0fPkn-0oTc6A_bflDTee98V_aiV-A,5195
|
81
82
|
prediction_market_agent_tooling/tools/singleton.py,sha256=CiIELUiI-OeS7U7eeHEt0rnVhtQGzwoUdAgn_7u_GBM,729
|
82
83
|
prediction_market_agent_tooling/tools/streamlit_user_login.py,sha256=NXEqfjT9Lc9QtliwSGRASIz1opjQ7Btme43H4qJbzgE,3010
|
83
84
|
prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py,sha256=Uq2iyDygVRxp6qHAnz9t5c1uTLGV2RPQE15sVJFLds8,6341
|
84
85
|
prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py,sha256=xrtQH9v5pXycBRyc5j45pWqkSffkoc9efNIU1_G633Q,3706
|
85
|
-
prediction_market_agent_tooling/tools/utils.py,sha256=
|
86
|
+
prediction_market_agent_tooling/tools/utils.py,sha256=uItjuwR5ZB6Qy7mmc5Dzx7fa2lkLO7oHhk2nzJMrIVo,7341
|
86
87
|
prediction_market_agent_tooling/tools/web3_utils.py,sha256=IZDxHhUJH5RsaRkK9DW6z1RYdk2cz5RqLMZG3T6Gv1U,11602
|
87
|
-
prediction_market_agent_tooling-0.48.
|
88
|
-
prediction_market_agent_tooling-0.48.
|
89
|
-
prediction_market_agent_tooling-0.48.
|
90
|
-
prediction_market_agent_tooling-0.48.
|
91
|
-
prediction_market_agent_tooling-0.48.
|
88
|
+
prediction_market_agent_tooling-0.48.18.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
|
89
|
+
prediction_market_agent_tooling-0.48.18.dist-info/METADATA,sha256=-IlB5IPMIotI_oqEi8oeSMN3xSveBEbghH3S5SoAuw4,7848
|
90
|
+
prediction_market_agent_tooling-0.48.18.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
91
|
+
prediction_market_agent_tooling-0.48.18.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
|
92
|
+
prediction_market_agent_tooling-0.48.18.dist-info/RECORD,,
|
File without changes
|
File without changes
|