prediction-market-agent-tooling 0.48.4__py3-none-any.whl → 0.48.6__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/benchmark/agents.py +0 -2
- prediction_market_agent_tooling/benchmark/utils.py +5 -3
- prediction_market_agent_tooling/deploy/agent.py +35 -27
- prediction_market_agent_tooling/deploy/agent_example.py +5 -6
- prediction_market_agent_tooling/deploy/betting_strategy.py +62 -0
- prediction_market_agent_tooling/markets/data_models.py +40 -3
- prediction_market_agent_tooling/markets/omen/data_models.py +43 -3
- prediction_market_agent_tooling/monitor/monitor_app.py +9 -8
- prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +6 -13
- prediction_market_agent_tooling/tools/is_predictable.py +1 -1
- prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py +1 -3
- prediction_market_agent_tooling/tools/web3_utils.py +5 -10
- {prediction_market_agent_tooling-0.48.4.dist-info → prediction_market_agent_tooling-0.48.6.dist-info}/METADATA +1 -1
- {prediction_market_agent_tooling-0.48.4.dist-info → prediction_market_agent_tooling-0.48.6.dist-info}/RECORD +17 -16
- {prediction_market_agent_tooling-0.48.4.dist-info → prediction_market_agent_tooling-0.48.6.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.48.4.dist-info → prediction_market_agent_tooling-0.48.6.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.48.4.dist-info → prediction_market_agent_tooling-0.48.6.dist-info}/entry_points.txt +0 -0
@@ -87,7 +87,6 @@ class RandomAgent(AbstractBenchmarkedAgent):
|
|
87
87
|
p_yes, confidence = random.random(), random.random()
|
88
88
|
return Prediction(
|
89
89
|
outcome_prediction=OutcomePrediction(
|
90
|
-
decision=p_yes > 0.5,
|
91
90
|
p_yes=Probability(p_yes),
|
92
91
|
confidence=confidence,
|
93
92
|
info_utility=None,
|
@@ -111,7 +110,6 @@ class FixedAgent(AbstractBenchmarkedAgent):
|
|
111
110
|
p_yes, confidence = 1.0 if self.fixed_answer else 0.0, 1.0
|
112
111
|
return Prediction(
|
113
112
|
outcome_prediction=OutcomePrediction(
|
114
|
-
decision=self.fixed_answer,
|
115
113
|
p_yes=Probability(p_yes),
|
116
114
|
confidence=confidence,
|
117
115
|
info_utility=None,
|
@@ -3,11 +3,13 @@ import typing as t
|
|
3
3
|
|
4
4
|
from pydantic import BaseModel
|
5
5
|
|
6
|
-
from prediction_market_agent_tooling.
|
7
|
-
|
6
|
+
from prediction_market_agent_tooling.markets.data_models import (
|
7
|
+
ProbabilisticAnswer,
|
8
|
+
Resolution,
|
9
|
+
)
|
8
10
|
|
9
11
|
|
10
|
-
class OutcomePrediction(
|
12
|
+
class OutcomePrediction(ProbabilisticAnswer):
|
11
13
|
info_utility: t.Optional[float]
|
12
14
|
|
13
15
|
@property
|
@@ -12,6 +12,10 @@ from pydantic import BaseModel, BeforeValidator, computed_field
|
|
12
12
|
from typing_extensions import Annotated
|
13
13
|
|
14
14
|
from prediction_market_agent_tooling.config import APIKeys
|
15
|
+
from prediction_market_agent_tooling.deploy.betting_strategy import (
|
16
|
+
BettingStrategy,
|
17
|
+
MaxAccuracyBettingStrategy,
|
18
|
+
)
|
15
19
|
from prediction_market_agent_tooling.deploy.constants import (
|
16
20
|
MARKET_TYPE_KEY,
|
17
21
|
REPOSITORY_KEY,
|
@@ -25,14 +29,19 @@ from prediction_market_agent_tooling.deploy.gcp.utils import (
|
|
25
29
|
gcp_function_is_active,
|
26
30
|
gcp_resolve_api_keys_secrets,
|
27
31
|
)
|
28
|
-
from prediction_market_agent_tooling.gtypes import
|
32
|
+
from prediction_market_agent_tooling.gtypes import xDai, xdai_type
|
29
33
|
from prediction_market_agent_tooling.loggers import logger
|
30
34
|
from prediction_market_agent_tooling.markets.agent_market import (
|
31
35
|
AgentMarket,
|
32
36
|
FilterBy,
|
33
37
|
SortBy,
|
34
38
|
)
|
35
|
-
from prediction_market_agent_tooling.markets.data_models import
|
39
|
+
from prediction_market_agent_tooling.markets.data_models import (
|
40
|
+
BetAmount,
|
41
|
+
ProbabilisticAnswer,
|
42
|
+
TokenAmount,
|
43
|
+
TokenAmountAndDirection,
|
44
|
+
)
|
36
45
|
from prediction_market_agent_tooling.markets.markets import (
|
37
46
|
MarketType,
|
38
47
|
have_bet_on_market_since,
|
@@ -95,19 +104,8 @@ class OutOfFundsError(ValueError):
|
|
95
104
|
pass
|
96
105
|
|
97
106
|
|
98
|
-
class Answer(BaseModel):
|
99
|
-
decision: Decision # Warning: p_yes > 0.5 doesn't necessarily mean decision is True! For example, if our p_yes is 55%, but market's p_yes is 80%, then it might be profitable to bet on False.
|
100
|
-
p_yes: Probability
|
101
|
-
confidence: float
|
102
|
-
reasoning: str | None = None
|
103
|
-
|
104
|
-
@property
|
105
|
-
def p_no(self) -> Probability:
|
106
|
-
return Probability(1 - self.p_yes)
|
107
|
-
|
108
|
-
|
109
107
|
class ProcessedMarket(BaseModel):
|
110
|
-
answer:
|
108
|
+
answer: ProbabilisticAnswer
|
111
109
|
amount: BetAmount
|
112
110
|
|
113
111
|
|
@@ -280,6 +278,7 @@ class DeployableTraderAgent(DeployableAgent):
|
|
280
278
|
bet_on_n_markets_per_run: int = 1
|
281
279
|
min_required_balance_to_operate: xDai | None = xdai_type(1)
|
282
280
|
min_balance_to_keep_in_native_currency: xDai | None = xdai_type(0.1)
|
281
|
+
strategy: BettingStrategy = MaxAccuracyBettingStrategy()
|
283
282
|
|
284
283
|
def __init__(
|
285
284
|
self,
|
@@ -295,7 +294,7 @@ class DeployableTraderAgent(DeployableAgent):
|
|
295
294
|
self.have_bet_on_market_since = observe()(self.have_bet_on_market_since) # type: ignore[method-assign]
|
296
295
|
self.verify_market = observe()(self.verify_market) # type: ignore[method-assign]
|
297
296
|
self.answer_binary_market = observe()(self.answer_binary_market) # type: ignore[method-assign]
|
298
|
-
self.
|
297
|
+
self.calculate_bet_amount_and_direction = observe()(self.calculate_bet_amount_and_direction) # type: ignore[method-assign]
|
299
298
|
self.process_market = observe()(self.process_market) # type: ignore[method-assign]
|
300
299
|
|
301
300
|
def update_langfuse_trace_by_market(
|
@@ -311,6 +310,18 @@ class DeployableTraderAgent(DeployableAgent):
|
|
311
310
|
},
|
312
311
|
)
|
313
312
|
|
313
|
+
def calculate_bet_amount_and_direction(
|
314
|
+
self, answer: ProbabilisticAnswer, market: AgentMarket
|
315
|
+
) -> TokenAmountAndDirection:
|
316
|
+
amount_and_direction = self.strategy.calculate_bet_amount_and_direction(
|
317
|
+
answer, market
|
318
|
+
)
|
319
|
+
if amount_and_direction.currency != market.currency:
|
320
|
+
raise ValueError(
|
321
|
+
f"Currency mismatch. Strategy yields {amount_and_direction.currency}, market has currency {market.currency}"
|
322
|
+
)
|
323
|
+
return amount_and_direction
|
324
|
+
|
314
325
|
def update_langfuse_trace_by_processed_market(
|
315
326
|
self, market_type: MarketType, processed_market: ProcessedMarket | None
|
316
327
|
) -> None:
|
@@ -360,18 +371,12 @@ class DeployableTraderAgent(DeployableAgent):
|
|
360
371
|
|
361
372
|
return True
|
362
373
|
|
363
|
-
def answer_binary_market(self, market: AgentMarket) ->
|
374
|
+
def answer_binary_market(self, market: AgentMarket) -> ProbabilisticAnswer | None:
|
364
375
|
"""
|
365
376
|
Answer the binary market. This method must be implemented by the subclass.
|
366
377
|
"""
|
367
378
|
raise NotImplementedError("This method must be implemented by the subclass")
|
368
379
|
|
369
|
-
def calculate_bet_amount(self, answer: Answer, market: AgentMarket) -> BetAmount:
|
370
|
-
"""
|
371
|
-
Calculate the bet amount. By default, it returns the minimum bet amount.
|
372
|
-
"""
|
373
|
-
return market.get_tiny_bet_amount()
|
374
|
-
|
375
380
|
def get_markets(
|
376
381
|
self,
|
377
382
|
market_type: MarketType,
|
@@ -408,22 +413,25 @@ class DeployableTraderAgent(DeployableAgent):
|
|
408
413
|
self.update_langfuse_trace_by_processed_market(market_type, None)
|
409
414
|
return None
|
410
415
|
|
411
|
-
|
416
|
+
amount_and_direction = self.calculate_bet_amount_and_direction(answer, market)
|
412
417
|
|
413
418
|
if self.place_bet:
|
414
419
|
logger.info(
|
415
|
-
f"Placing bet on {market} with
|
420
|
+
f"Placing bet on {market} with direction {amount_and_direction.direction} and amount {amount_and_direction.amount}"
|
416
421
|
)
|
417
422
|
market.place_bet(
|
418
|
-
amount=
|
419
|
-
|
423
|
+
amount=TokenAmount(
|
424
|
+
amount=amount_and_direction.amount,
|
425
|
+
currency=amount_and_direction.currency,
|
426
|
+
),
|
427
|
+
outcome=amount_and_direction.direction,
|
420
428
|
)
|
421
429
|
|
422
430
|
self.after_process_market(market_type, market)
|
423
431
|
|
424
432
|
processed_market = ProcessedMarket(
|
425
433
|
answer=answer,
|
426
|
-
amount=
|
434
|
+
amount=amount_and_direction,
|
427
435
|
)
|
428
436
|
self.update_langfuse_trace_by_processed_market(market_type, processed_market)
|
429
437
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import random
|
2
2
|
|
3
3
|
from prediction_market_agent_tooling.deploy.agent import (
|
4
|
-
Answer,
|
5
4
|
DeployableTraderAgent,
|
6
|
-
|
5
|
+
ProbabilisticAnswer,
|
7
6
|
)
|
7
|
+
from prediction_market_agent_tooling.gtypes import Probability
|
8
8
|
from prediction_market_agent_tooling.markets.agent_market import AgentMarket
|
9
9
|
from prediction_market_agent_tooling.markets.markets import MarketType
|
10
10
|
|
@@ -13,10 +13,9 @@ class DeployableCoinFlipAgent(DeployableTraderAgent):
|
|
13
13
|
def verify_market(self, market_type: MarketType, market: AgentMarket) -> bool:
|
14
14
|
return True
|
15
15
|
|
16
|
-
def answer_binary_market(self, market: AgentMarket) ->
|
16
|
+
def answer_binary_market(self, market: AgentMarket) -> ProbabilisticAnswer | None:
|
17
17
|
decision = random.choice([True, False])
|
18
|
-
return
|
19
|
-
decision=decision,
|
18
|
+
return ProbabilisticAnswer(
|
20
19
|
p_yes=Probability(float(decision)),
|
21
20
|
confidence=0.5,
|
22
21
|
reasoning="I flipped a coin to decide.",
|
@@ -24,5 +23,5 @@ class DeployableCoinFlipAgent(DeployableTraderAgent):
|
|
24
23
|
|
25
24
|
|
26
25
|
class DeployableAlwaysRaiseAgent(DeployableTraderAgent):
|
27
|
-
def answer_binary_market(self, market: AgentMarket) ->
|
26
|
+
def answer_binary_market(self, market: AgentMarket) -> ProbabilisticAnswer | None:
|
28
27
|
raise RuntimeError("I always raise!")
|
@@ -0,0 +1,62 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
from prediction_market_agent_tooling.markets.agent_market import AgentMarket
|
4
|
+
from prediction_market_agent_tooling.markets.data_models import (
|
5
|
+
ProbabilisticAnswer,
|
6
|
+
TokenAmountAndDirection,
|
7
|
+
)
|
8
|
+
from prediction_market_agent_tooling.tools.betting_strategies.kelly_criterion import (
|
9
|
+
get_kelly_bet,
|
10
|
+
)
|
11
|
+
|
12
|
+
|
13
|
+
class BettingStrategy(ABC):
|
14
|
+
@abstractmethod
|
15
|
+
def calculate_bet_amount_and_direction(
|
16
|
+
self, answer: ProbabilisticAnswer, market: AgentMarket
|
17
|
+
) -> TokenAmountAndDirection:
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
class MaxAccuracyBettingStrategy(BettingStrategy):
|
22
|
+
def __init__(self, bet_amount: float | None = None):
|
23
|
+
self.bet_amount = bet_amount
|
24
|
+
|
25
|
+
@staticmethod
|
26
|
+
def calculate_direction(market_p_yes: float, estimate_p_yes: float) -> bool:
|
27
|
+
# If estimate_p_yes >= market.current_p_yes, then bet TRUE, else bet FALSE.
|
28
|
+
# This is equivalent to saying EXPECTED_VALUE = (estimate_p_yes * num_tokens_obtained_by_betting_yes) -
|
29
|
+
# ((1 - estimate_p_yes) * num_tokens_obtained_by_betting_no) >= 0
|
30
|
+
return estimate_p_yes >= market_p_yes
|
31
|
+
|
32
|
+
def calculate_bet_amount_and_direction(
|
33
|
+
self, answer: ProbabilisticAnswer, market: AgentMarket
|
34
|
+
) -> TokenAmountAndDirection:
|
35
|
+
bet_amount = (
|
36
|
+
market.get_tiny_bet_amount().amount
|
37
|
+
if self.bet_amount is None
|
38
|
+
else self.bet_amount
|
39
|
+
)
|
40
|
+
direction = self.calculate_direction(market.current_p_yes, answer.p_yes)
|
41
|
+
return TokenAmountAndDirection(
|
42
|
+
amount=bet_amount,
|
43
|
+
currency=market.currency,
|
44
|
+
direction=direction,
|
45
|
+
)
|
46
|
+
|
47
|
+
|
48
|
+
class KellyBettingStrategy(BettingStrategy):
|
49
|
+
def __init__(self, max_bet_amount: float = 10):
|
50
|
+
self.max_bet_amount = max_bet_amount
|
51
|
+
|
52
|
+
def calculate_bet_amount_and_direction(
|
53
|
+
self, answer: ProbabilisticAnswer, market: AgentMarket
|
54
|
+
) -> TokenAmountAndDirection:
|
55
|
+
kelly_bet = get_kelly_bet(
|
56
|
+
self.max_bet_amount, market.current_p_yes, answer.p_yes, answer.confidence
|
57
|
+
)
|
58
|
+
return TokenAmountAndDirection(
|
59
|
+
amount=kelly_bet.size,
|
60
|
+
currency=market.currency,
|
61
|
+
direction=kelly_bet.direction,
|
62
|
+
)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from enum import Enum
|
3
|
-
from typing import TypeAlias
|
3
|
+
from typing import Annotated, TypeAlias
|
4
4
|
|
5
|
-
from pydantic import BaseModel, computed_field
|
5
|
+
from pydantic import BaseModel, BeforeValidator, computed_field
|
6
6
|
|
7
|
-
from prediction_market_agent_tooling.gtypes import OutcomeStr
|
7
|
+
from prediction_market_agent_tooling.gtypes import OutcomeStr, Probability
|
8
8
|
|
9
9
|
|
10
10
|
class Currency(str, Enum):
|
@@ -57,6 +57,43 @@ class ResolvedBet(Bet):
|
|
57
57
|
return f"Resolved bet for market {self.market_id} for question {self.market_question} created at {self.created_time}: {self.amount} on {self.outcome}. Bet was resolved at {self.resolved_time} and was {'correct' if self.is_correct else 'incorrect'}. Profit was {self.profit}"
|
58
58
|
|
59
59
|
|
60
|
+
class TokenAmountAndDirection(TokenAmount):
|
61
|
+
direction: bool
|
62
|
+
|
63
|
+
|
64
|
+
def to_boolean_outcome(value: str | bool) -> bool:
|
65
|
+
if isinstance(value, bool):
|
66
|
+
return value
|
67
|
+
|
68
|
+
elif isinstance(value, str):
|
69
|
+
value = value.lower().strip()
|
70
|
+
|
71
|
+
if value in {"true", "yes", "y", "1"}:
|
72
|
+
return True
|
73
|
+
|
74
|
+
elif value in {"false", "no", "n", "0"}:
|
75
|
+
return False
|
76
|
+
|
77
|
+
else:
|
78
|
+
raise ValueError(f"Expected a boolean string, but got {value}")
|
79
|
+
|
80
|
+
else:
|
81
|
+
raise ValueError(f"Expected a boolean or a string, but got {value}")
|
82
|
+
|
83
|
+
|
84
|
+
Decision = Annotated[bool, BeforeValidator(to_boolean_outcome)]
|
85
|
+
|
86
|
+
|
87
|
+
class ProbabilisticAnswer(BaseModel):
|
88
|
+
p_yes: Probability
|
89
|
+
confidence: float
|
90
|
+
reasoning: str | None = None
|
91
|
+
|
92
|
+
@property
|
93
|
+
def p_no(self) -> Probability:
|
94
|
+
return Probability(1 - self.p_yes)
|
95
|
+
|
96
|
+
|
60
97
|
class Position(BaseModel):
|
61
98
|
market_id: str
|
62
99
|
amounts: dict[OutcomeStr, TokenAmount]
|
@@ -77,6 +77,10 @@ class Question(BaseModel):
|
|
77
77
|
def opening_datetime(self) -> datetime:
|
78
78
|
return datetime.fromtimestamp(self.openingTimestamp)
|
79
79
|
|
80
|
+
@property
|
81
|
+
def has_answer(self) -> bool:
|
82
|
+
return self.currentAnswer is not None
|
83
|
+
|
80
84
|
@property
|
81
85
|
def outcome_index(self) -> int | None:
|
82
86
|
return (
|
@@ -88,6 +92,34 @@ class Question(BaseModel):
|
|
88
92
|
else None
|
89
93
|
)
|
90
94
|
|
95
|
+
@property
|
96
|
+
def is_binary(self) -> bool:
|
97
|
+
return len(self.outcomes) == 2
|
98
|
+
|
99
|
+
@property
|
100
|
+
def has_valid_answer(self) -> bool:
|
101
|
+
return self.outcome_index is not None and self.outcome_index != INVALID_ANSWER
|
102
|
+
|
103
|
+
@property
|
104
|
+
def boolean_outcome(self) -> bool:
|
105
|
+
if not self.is_binary:
|
106
|
+
raise ValueError(
|
107
|
+
f"Question with title {self.title} is not binary, it has {len(self.outcomes)} outcomes."
|
108
|
+
)
|
109
|
+
|
110
|
+
if not self.has_answer:
|
111
|
+
raise ValueError(f"Question with title {self.title} is not answered.")
|
112
|
+
|
113
|
+
outcome_index = check_not_none(self.outcome_index)
|
114
|
+
|
115
|
+
if not self.has_valid_answer:
|
116
|
+
raise ValueError(
|
117
|
+
f"Question with title {self.title} has invalid answer {outcome_index}."
|
118
|
+
)
|
119
|
+
|
120
|
+
outcome: str = self.outcomes[outcome_index]
|
121
|
+
return get_boolean_outcome(outcome)
|
122
|
+
|
91
123
|
|
92
124
|
class OmenPosition(BaseModel):
|
93
125
|
id: HexBytes
|
@@ -132,7 +164,15 @@ class OmenUserPosition(BaseModel):
|
|
132
164
|
|
133
165
|
class OmenMarket(BaseModel):
|
134
166
|
"""
|
135
|
-
https://
|
167
|
+
https://presagio.pages.dev
|
168
|
+
|
169
|
+
An Omen market goes through the following stages:
|
170
|
+
|
171
|
+
1. creation - can add liquidty immediately, and trade immediately if there is liquidity
|
172
|
+
2. closing - market is closed, and a question is simultaneously opened for answers on Reality
|
173
|
+
3. finalizing - the question is finalized on reality (including any disputes)
|
174
|
+
4. resolving - a manual step required by calling the Omen oracle contract
|
175
|
+
5. redeeming - a user withdraws collateral tokens from the market
|
136
176
|
"""
|
137
177
|
|
138
178
|
BET_AMOUNT_CURRENCY: t.ClassVar[Currency] = Currency.xDai
|
@@ -347,7 +387,7 @@ class OmenBet(BaseModel):
|
|
347
387
|
collateralAmountUSD: USD
|
348
388
|
feeAmount: Wei
|
349
389
|
outcomeIndex: int
|
350
|
-
outcomeTokensTraded:
|
390
|
+
outcomeTokensTraded: Wei
|
351
391
|
transactionHash: HexAddress
|
352
392
|
fpmm: OmenMarket
|
353
393
|
|
@@ -372,7 +412,7 @@ class OmenBet(BaseModel):
|
|
372
412
|
def get_profit(self) -> ProfitAmount:
|
373
413
|
bet_amount_xdai = wei_to_xdai(self.collateralAmount)
|
374
414
|
profit = (
|
375
|
-
wei_to_xdai(
|
415
|
+
wei_to_xdai(self.outcomeTokensTraded) - bet_amount_xdai
|
376
416
|
if self.boolean_outcome == self.fpmm.boolean_outcome
|
377
417
|
else -bet_amount_xdai
|
378
418
|
)
|
@@ -135,15 +135,16 @@ def monitor_app(
|
|
135
135
|
)
|
136
136
|
|
137
137
|
st.header("Market Info")
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
if st.checkbox("Show Market Info"):
|
139
|
+
with st.spinner("Loading markets"):
|
140
|
+
open_markets, resolved_markets = get_open_and_resolved_markets(
|
141
|
+
start_time=oldest_start_time, market_type=market_type
|
142
|
+
)
|
143
|
+
(
|
144
|
+
monitor_market(open_markets=open_markets, resolved_markets=resolved_markets)
|
145
|
+
if open_markets and resolved_markets
|
146
|
+
else st.warning("No market data found.")
|
141
147
|
)
|
142
|
-
(
|
143
|
-
monitor_market(open_markets=open_markets, resolved_markets=resolved_markets)
|
144
|
-
if open_markets and resolved_markets
|
145
|
-
else st.warning("No market data found.")
|
146
|
-
)
|
147
148
|
|
148
149
|
st.header("Agent Info")
|
149
150
|
if st.button("Export agents"):
|
@@ -1,23 +1,16 @@
|
|
1
|
-
from enum import Enum
|
2
|
-
|
3
1
|
from pydantic import BaseModel
|
4
2
|
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
def check_is_valid_probability(probability: float) -> None:
|
5
|
+
if not 0 <= probability <= 1:
|
6
|
+
raise ValueError("Probability must be between 0 and 1")
|
9
7
|
|
10
8
|
|
11
9
|
class KellyBet(BaseModel):
|
12
|
-
direction:
|
10
|
+
direction: bool
|
13
11
|
size: float
|
14
12
|
|
15
13
|
|
16
|
-
def check_is_valid_probability(probability: float) -> None:
|
17
|
-
if not 0 <= probability <= 1:
|
18
|
-
raise ValueError("Probability must be between 0 and 1")
|
19
|
-
|
20
|
-
|
21
14
|
def get_kelly_bet(
|
22
15
|
max_bet: float,
|
23
16
|
market_p_yes: float,
|
@@ -47,10 +40,10 @@ def get_kelly_bet(
|
|
47
40
|
check_is_valid_probability(confidence)
|
48
41
|
|
49
42
|
if estimated_p_yes > market_p_yes:
|
50
|
-
bet_direction =
|
43
|
+
bet_direction = True
|
51
44
|
market_prob = market_p_yes
|
52
45
|
else:
|
53
|
-
bet_direction =
|
46
|
+
bet_direction = False
|
54
47
|
market_prob = 1 - market_p_yes
|
55
48
|
|
56
49
|
# Handle the case where market_prob is 0
|
@@ -60,9 +60,7 @@ def tavily_search(
|
|
60
60
|
return response_parsed
|
61
61
|
|
62
62
|
|
63
|
-
@tenacity.retry(
|
64
|
-
stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(1), reraise=True
|
65
|
-
)
|
63
|
+
@tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(1))
|
66
64
|
def _tavily_search(
|
67
65
|
query: str,
|
68
66
|
search_depth: t.Literal["basic", "advanced"],
|
@@ -28,6 +28,7 @@ from prediction_market_agent_tooling.loggers import logger
|
|
28
28
|
ONE_NONCE = Nonce(1)
|
29
29
|
ONE_XDAI = xdai_type(1)
|
30
30
|
ZERO_BYTES = HexBytes(HASH_ZERO)
|
31
|
+
NOT_REVERTED_ICASE_REGEX_PATTERN = "(?i)(?!.*reverted.*)"
|
31
32
|
|
32
33
|
|
33
34
|
def private_key_to_public_key(private_key: SecretStr) -> ChecksumAddress:
|
@@ -154,11 +155,8 @@ def _prepare_tx_params(
|
|
154
155
|
|
155
156
|
|
156
157
|
@tenacity.retry(
|
157
|
-
#
|
158
|
-
|
159
|
-
retry=tenacity.retry_if_exception_message(
|
160
|
-
match="(.*wrong transaction nonce.*)|(.*Invalid.*)|(.*OldNonce.*)"
|
161
|
-
),
|
158
|
+
# Don't retry on `reverted` messages, as they would always fail again.
|
159
|
+
retry=tenacity.retry_if_exception_message(match=NOT_REVERTED_ICASE_REGEX_PATTERN),
|
162
160
|
wait=tenacity.wait_chain(*[tenacity.wait_fixed(n) for n in range(1, 10)]),
|
163
161
|
stop=tenacity.stop_after_attempt(9),
|
164
162
|
after=lambda x: logger.debug(
|
@@ -194,11 +192,8 @@ def send_function_on_contract_tx(
|
|
194
192
|
|
195
193
|
|
196
194
|
@tenacity.retry(
|
197
|
-
#
|
198
|
-
|
199
|
-
retry=tenacity.retry_if_exception_message(
|
200
|
-
match="(.*wrong transaction nonce.*)|(.*Invalid.*)|(.*OldNonce.*)"
|
201
|
-
),
|
195
|
+
# Don't retry on `reverted` messages, as they would always fail again.
|
196
|
+
retry=tenacity.retry_if_exception_message(match=NOT_REVERTED_ICASE_REGEX_PATTERN),
|
202
197
|
wait=tenacity.wait_chain(*[tenacity.wait_fixed(n) for n in range(1, 10)]),
|
203
198
|
stop=tenacity.stop_after_attempt(9),
|
204
199
|
after=lambda x: logger.debug(
|
@@ -11,12 +11,13 @@ prediction_market_agent_tooling/abis/omen_realitio.abi.json,sha256=7HmFkBF_rq83U
|
|
11
11
|
prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json,sha256=u1-3B8FB3Ys9KVJCH-lw9ArkicdxbNMf34dV-VEGMMU,930
|
12
12
|
prediction_market_agent_tooling/abis/proxy.abi.json,sha256=h24GXZ6Q0bSZlwh7zOv0EiDvbqUz_PHtWfKHTyPJ1w4,644
|
13
13
|
prediction_market_agent_tooling/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
-
prediction_market_agent_tooling/benchmark/agents.py,sha256=
|
14
|
+
prediction_market_agent_tooling/benchmark/agents.py,sha256=BwE3U11tQq0rfOJBn-Xn5ZgN1DTXBEehvmdZx6A7DuE,3918
|
15
15
|
prediction_market_agent_tooling/benchmark/benchmark.py,sha256=xiHKzZx5GHSsDerFHMZ9j_LXAXnSaITSvv67iPe3MEU,21095
|
16
|
-
prediction_market_agent_tooling/benchmark/utils.py,sha256=
|
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=
|
19
|
-
prediction_market_agent_tooling/deploy/agent_example.py,sha256=
|
18
|
+
prediction_market_agent_tooling/deploy/agent.py,sha256=MdNiUG2y-E6S_Hc7d31ISIPF7e18-2bmO8SULg7RDd4,17760
|
19
|
+
prediction_market_agent_tooling/deploy/agent_example.py,sha256=dIIdZashExWk9tOdyDjw87AuUcGyM7jYxNChYrVK2dM,1001
|
20
|
+
prediction_market_agent_tooling/deploy/betting_strategy.py,sha256=nJizN4d_jsw5WA8uukaKModVezAgVwoLrCOXsaBOwXo,2223
|
20
21
|
prediction_market_agent_tooling/deploy/constants.py,sha256=M5ty8URipYMGe_G-RzxRydK3AFL6CyvmqCraJUrLBnE,82
|
21
22
|
prediction_market_agent_tooling/deploy/gcp/deploy.py,sha256=CYUgnfy-9XVk04kkxA_5yp0GE9Mw5caYqlFUZQ2j3ks,3739
|
22
23
|
prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py,sha256=qYIHRxQLac3yxtZ8ChikiPG9O1aUQucHW0muTSm1nto,2627
|
@@ -25,7 +26,7 @@ prediction_market_agent_tooling/gtypes.py,sha256=ezM2iAycTRJ0uHKK03s0z76a8YFSF43
|
|
25
26
|
prediction_market_agent_tooling/loggers.py,sha256=JiBTgvb34O9dKHYKZyQ0UzojPUy6KSFQSTfbBIXopSY,3721
|
26
27
|
prediction_market_agent_tooling/markets/agent_market.py,sha256=BELq6x3F4xLZwi0XmoN84RA7ttRQIclyHL2CY6a4Ixc,8409
|
27
28
|
prediction_market_agent_tooling/markets/categorize.py,sha256=jsoHWvZk9pU6n17oWSCcCxNNYVwlb_NXsZxKRI7vmsk,1301
|
28
|
-
prediction_market_agent_tooling/markets/data_models.py,sha256=
|
29
|
+
prediction_market_agent_tooling/markets/data_models.py,sha256=8OZmP493O3HfiJWnfYXd7xMbxdQ8vmypghbu1hOvRQQ,2983
|
29
30
|
prediction_market_agent_tooling/markets/manifold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
31
|
prediction_market_agent_tooling/markets/manifold/api.py,sha256=AC2zmkzpBU3P4kyybs7CgPbDg4hLAx3GY5mjgDi7qDo,7221
|
31
32
|
prediction_market_agent_tooling/markets/manifold/data_models.py,sha256=jHqOzOiN21wYvDNyh4VtbGtj4adWr6vA4liOQmh24cc,6239
|
@@ -36,7 +37,7 @@ prediction_market_agent_tooling/markets/metaculus/api.py,sha256=gvPQVAM5NlCyWzEM
|
|
36
37
|
prediction_market_agent_tooling/markets/metaculus/data_models.py,sha256=6TBy17xntdLBR61QCE5wddwTa_k2D0D8ZgK6p7sGUuc,2448
|
37
38
|
prediction_market_agent_tooling/markets/metaculus/metaculus.py,sha256=uNF7LP4evvubk818g2zbX1VlnFxeUQOkNgx_e_LwaJA,3416
|
38
39
|
prediction_market_agent_tooling/markets/omen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
|
-
prediction_market_agent_tooling/markets/omen/data_models.py,sha256=
|
40
|
+
prediction_market_agent_tooling/markets/omen/data_models.py,sha256=z-J8cmmHIzyArj8OvNPSX4sfxFpBvr1FGGzzveEsmwo,16067
|
40
41
|
prediction_market_agent_tooling/markets/omen/omen.py,sha256=fL8Lk1H0guwNBcgvT8Ymy3jRewbWLbJ9m8br4HN7vPg,40014
|
41
42
|
prediction_market_agent_tooling/markets/omen/omen_contracts.py,sha256=DWJk7GZgw_UxxFxdVeDJTcskWlJ8AchN0QaXWZrrh4E,23633
|
42
43
|
prediction_market_agent_tooling/markets/omen/omen_resolving.py,sha256=8uHWH1nMYiop4wOhSSoz3tdaexa-qb6KX10SiyaYYhA,10981
|
@@ -51,11 +52,11 @@ prediction_market_agent_tooling/monitor/markets/metaculus.py,sha256=S8zeDVN2aA6y
|
|
51
52
|
prediction_market_agent_tooling/monitor/markets/omen.py,sha256=jOLPnIbDU9syjnYtHfOb2xa6-Ize3vbplgh-8WWkuT4,3323
|
52
53
|
prediction_market_agent_tooling/monitor/markets/polymarket.py,sha256=I9z9aO1wncyGI3a09ihrw17JkeBKjAuMmC0I9pl_9o4,1781
|
53
54
|
prediction_market_agent_tooling/monitor/monitor.py,sha256=snMSPmoHFV7QchqsFBaNkOEQhHJshF1qmIGPuID1giQ,14579
|
54
|
-
prediction_market_agent_tooling/monitor/monitor_app.py,sha256=
|
55
|
+
prediction_market_agent_tooling/monitor/monitor_app.py,sha256=1e4LuzhAVjb7cPS6rGPZuZHMwMiNOeRhSxG8AVG-e0o,4839
|
55
56
|
prediction_market_agent_tooling/monitor/monitor_settings.py,sha256=Xiozs3AsufuJ04JOe1vjUri-IAMWHjjmc2ugGGiHNH4,947
|
56
57
|
prediction_market_agent_tooling/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
58
|
prediction_market_agent_tooling/tools/balances.py,sha256=nR8_dSfbm3yTOOmMAwhGlurftEiNo1w1WIVzbskjdmM,837
|
58
|
-
prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py,sha256=
|
59
|
+
prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py,sha256=IoLx8fIOqjC9d2gSWIc5Y-3wlukib6cuJaJzguHqNbU,1835
|
59
60
|
prediction_market_agent_tooling/tools/betting_strategies/market_moving.py,sha256=wtrHVQRuA0uDx06z0OxQLYbswuOpHQ1UyCWwLCrD_oM,4400
|
60
61
|
prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py,sha256=-FUSuQQgjcWSSnoFxnlAyTeilY6raJABJVM2QKkFqAY,438
|
61
62
|
prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py,sha256=THMXwFlskvzbjnX_OiYtDSzI8XVFyULWfP2525_9UGc,429
|
@@ -67,18 +68,18 @@ prediction_market_agent_tooling/tools/google.py,sha256=SfVDxb3oEOUK8mpd0l3mTX9yb
|
|
67
68
|
prediction_market_agent_tooling/tools/hexbytes_custom.py,sha256=Bp94qgPjvjWf1Vb4lNzGFDXRdThw1rJ91vL6r2PWq5E,2096
|
68
69
|
prediction_market_agent_tooling/tools/image_gen/image_gen.py,sha256=HzRwBx62hOXBOmrtpkXaP9Qq1Ku03uUGdREocyjLQ_k,1266
|
69
70
|
prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py,sha256=8A3U2uxsCsOfLjru-6R_PPIAuiKY4qFkWp_GSBPV6-s,1280
|
70
|
-
prediction_market_agent_tooling/tools/is_predictable.py,sha256=
|
71
|
+
prediction_market_agent_tooling/tools/is_predictable.py,sha256=GqBgp4aHbY97PdprKfCHV-lJy2bbGIrd9yCtkqg6gEc,6558
|
71
72
|
prediction_market_agent_tooling/tools/langfuse_.py,sha256=jI_4ROxqo41CCnWGS1vN_AeDVhRzLMaQLxH3kxDu3L8,1153
|
72
73
|
prediction_market_agent_tooling/tools/parallelism.py,sha256=Rz8QdVUWX8KCbr8UZfaC_b1GBWIb3bXwITUumuvBJ60,1633
|
73
74
|
prediction_market_agent_tooling/tools/safe.py,sha256=h0xOO0eNtitClf0fPkn-0oTc6A_bflDTee98V_aiV-A,5195
|
74
75
|
prediction_market_agent_tooling/tools/singleton.py,sha256=CiIELUiI-OeS7U7eeHEt0rnVhtQGzwoUdAgn_7u_GBM,729
|
75
76
|
prediction_market_agent_tooling/tools/streamlit_user_login.py,sha256=NXEqfjT9Lc9QtliwSGRASIz1opjQ7Btme43H4qJbzgE,3010
|
76
77
|
prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py,sha256=dr-N-G67f4au6s5xLwZPNbKhe4BFaEuYpQTn0KZ4EKg,4377
|
77
|
-
prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py,sha256=
|
78
|
+
prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py,sha256=eln3BygdfsDf8WOlSQPL7qH946QnGnThRkazRZKBA8o,3194
|
78
79
|
prediction_market_agent_tooling/tools/utils.py,sha256=JE9YWtPPhnTgLiOyGAZDNG5K8nCwUY9IZEuAlm9UcxA,6611
|
79
|
-
prediction_market_agent_tooling/tools/web3_utils.py,sha256=
|
80
|
-
prediction_market_agent_tooling-0.48.
|
81
|
-
prediction_market_agent_tooling-0.48.
|
82
|
-
prediction_market_agent_tooling-0.48.
|
83
|
-
prediction_market_agent_tooling-0.48.
|
84
|
-
prediction_market_agent_tooling-0.48.
|
80
|
+
prediction_market_agent_tooling/tools/web3_utils.py,sha256=euq_MH-LhTowACq42colks2IXxZQjqjuisYl91EYZtU,10440
|
81
|
+
prediction_market_agent_tooling-0.48.6.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
|
82
|
+
prediction_market_agent_tooling-0.48.6.dist-info/METADATA,sha256=TF3DLH3Qpryr7ZBkTAfhaeSoH8m2RMgJbc9FHxs-9E4,7810
|
83
|
+
prediction_market_agent_tooling-0.48.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
84
|
+
prediction_market_agent_tooling-0.48.6.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
|
85
|
+
prediction_market_agent_tooling-0.48.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|