prediction-market-agent-tooling 0.48.17__py3-none-any.whl → 0.49.0__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.
Files changed (22) hide show
  1. prediction_market_agent_tooling/deploy/agent.py +25 -8
  2. prediction_market_agent_tooling/deploy/betting_strategy.py +64 -27
  3. prediction_market_agent_tooling/jobs/omen/omen_jobs.py +2 -1
  4. prediction_market_agent_tooling/markets/agent_market.py +11 -3
  5. prediction_market_agent_tooling/markets/data_models.py +14 -0
  6. prediction_market_agent_tooling/markets/manifold/api.py +3 -1
  7. prediction_market_agent_tooling/markets/manifold/manifold.py +7 -2
  8. prediction_market_agent_tooling/markets/metaculus/metaculus.py +5 -0
  9. prediction_market_agent_tooling/markets/omen/data_models.py +7 -1
  10. prediction_market_agent_tooling/markets/omen/omen.py +34 -18
  11. prediction_market_agent_tooling/markets/omen/omen_resolving.py +3 -1
  12. prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +20 -2
  13. prediction_market_agent_tooling/markets/polymarket/polymarket.py +1 -1
  14. prediction_market_agent_tooling/monitor/markets/polymarket.py +4 -0
  15. prediction_market_agent_tooling/tools/langfuse_client_utils.py +5 -5
  16. prediction_market_agent_tooling/tools/omen/reality_accuracy.py +74 -0
  17. prediction_market_agent_tooling/tools/utils.py +18 -0
  18. {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.49.0.dist-info}/METADATA +1 -1
  19. {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.49.0.dist-info}/RECORD +22 -21
  20. {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.49.0.dist-info}/LICENSE +0 -0
  21. {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.49.0.dist-info}/WHEEL +0 -0
  22. {prediction_market_agent_tooling-0.48.17.dist-info → prediction_market_agent_tooling-0.49.0.dist-info}/entry_points.txt +0 -0
@@ -38,6 +38,7 @@ from prediction_market_agent_tooling.markets.agent_market import (
38
38
  SortBy,
39
39
  )
40
40
  from prediction_market_agent_tooling.markets.data_models import (
41
+ PlacedTrade,
41
42
  Position,
42
43
  ProbabilisticAnswer,
43
44
  Trade,
@@ -110,7 +111,7 @@ class OutOfFundsError(ValueError):
110
111
 
111
112
  class ProcessedMarket(BaseModel):
112
113
  answer: ProbabilisticAnswer
113
- trades: list[Trade]
114
+ trades: list[PlacedTrade]
114
115
 
115
116
 
116
117
  class AnsweredEnum(str, Enum):
@@ -282,8 +283,6 @@ class DeployableTraderAgent(DeployableAgent):
282
283
  bet_on_n_markets_per_run: int = 1
283
284
  min_required_balance_to_operate: xDai | None = xdai_type(1)
284
285
  min_balance_to_keep_in_native_currency: xDai | None = xdai_type(0.1)
285
- strategy: BettingStrategy = MaxAccuracyBettingStrategy()
286
- allow_opposite_bets: bool = False
287
286
 
288
287
  def __init__(
289
288
  self,
@@ -293,6 +292,15 @@ class DeployableTraderAgent(DeployableAgent):
293
292
  super().__init__(enable_langfuse=enable_langfuse)
294
293
  self.place_bet = place_bet
295
294
 
295
+ def get_betting_strategy(self, market: AgentMarket) -> BettingStrategy:
296
+ user_id = market.get_user_id(api_keys=APIKeys())
297
+
298
+ total_amount = market.get_user_balance(user_id=user_id) * 0.1
299
+ if existing_position := market.get_position(user_id=user_id):
300
+ total_amount += existing_position.total_amount.amount
301
+
302
+ return MaxAccuracyBettingStrategy(bet_amount=total_amount)
303
+
296
304
  def initialize_langfuse(self) -> None:
297
305
  super().initialize_langfuse()
298
306
  # Auto-observe all the methods where it makes sense, so that subclassses don't need to do it manually.
@@ -411,7 +419,8 @@ class DeployableTraderAgent(DeployableAgent):
411
419
  answer: ProbabilisticAnswer,
412
420
  existing_position: Position | None,
413
421
  ) -> list[Trade]:
414
- trades = self.strategy.calculate_trades(existing_position, answer, market)
422
+ strategy = self.get_betting_strategy(market=market)
423
+ trades = strategy.calculate_trades(existing_position, answer, market)
415
424
  BettingStrategy.assert_trades_currency_match_markets(market, trades)
416
425
  return trades
417
426
 
@@ -444,24 +453,32 @@ class DeployableTraderAgent(DeployableAgent):
444
453
 
445
454
  existing_position = market.get_position(user_id=APIKeys().bet_from_address)
446
455
  trades = self.build_trades(
447
- market=market, answer=answer, existing_position=existing_position
456
+ market=market,
457
+ answer=answer,
458
+ existing_position=existing_position,
448
459
  )
449
460
 
461
+ placed_trades = []
450
462
  if self.place_bet:
451
463
  for trade in trades:
452
464
  logger.info(f"Executing trade {trade}")
453
465
 
454
466
  match trade.trade_type:
455
467
  case TradeType.BUY:
456
- market.buy_tokens(outcome=trade.outcome, amount=trade.amount)
468
+ id = market.buy_tokens(
469
+ outcome=trade.outcome, amount=trade.amount
470
+ )
457
471
  case TradeType.SELL:
458
- market.sell_tokens(outcome=trade.outcome, amount=trade.amount)
472
+ id = market.sell_tokens(
473
+ outcome=trade.outcome, amount=trade.amount
474
+ )
459
475
  case _:
460
476
  raise ValueError(f"Unexpected trade type {trade.trade_type}.")
477
+ placed_trades.append(PlacedTrade.from_trade(trade, id))
461
478
 
462
479
  self.after_process_market(market_type, market)
463
480
 
464
- processed_market = ProcessedMarket(answer=answer, trades=trades)
481
+ processed_market = ProcessedMarket(answer=answer, trades=placed_trades)
465
482
  self.update_langfuse_trace_by_processed_market(market_type, processed_market)
466
483
 
467
484
  logger.info(f"Processed market {market.question=} from {market.url=}.")
@@ -30,12 +30,6 @@ class BettingStrategy(ABC):
30
30
  def build_zero_token_amount(self, currency: Currency) -> TokenAmount:
31
31
  return TokenAmount(amount=0, currency=currency)
32
32
 
33
- @abstractmethod
34
- def adjust_bet_amount(
35
- self, existing_position: Position | None, market: AgentMarket
36
- ) -> float:
37
- pass
38
-
39
33
  @staticmethod
40
34
  def assert_trades_currency_match_markets(
41
35
  market: AgentMarket, trades: list[Trade]
@@ -99,20 +93,7 @@ class BettingStrategy(ABC):
99
93
 
100
94
 
101
95
  class MaxAccuracyBettingStrategy(BettingStrategy):
102
- def adjust_bet_amount(
103
- self, existing_position: Position | None, market: AgentMarket
104
- ) -> float:
105
- existing_position_total_amount = (
106
- existing_position.total_amount.amount if existing_position else 0
107
- )
108
- bet_amount = (
109
- market.get_tiny_bet_amount().amount
110
- if self.bet_amount is None
111
- else self.bet_amount
112
- )
113
- return bet_amount + existing_position_total_amount
114
-
115
- def __init__(self, bet_amount: float | None = None):
96
+ def __init__(self, bet_amount: float):
116
97
  self.bet_amount = bet_amount
117
98
 
118
99
  def calculate_trades(
@@ -121,13 +102,11 @@ class MaxAccuracyBettingStrategy(BettingStrategy):
121
102
  answer: ProbabilisticAnswer,
122
103
  market: AgentMarket,
123
104
  ) -> list[Trade]:
124
- adjusted_bet_amount = self.adjust_bet_amount(existing_position, market)
125
-
126
105
  direction = self.calculate_direction(market.current_p_yes, answer.p_yes)
127
106
 
128
107
  amounts = {
129
108
  market.get_outcome_str_from_bool(direction): TokenAmount(
130
- amount=adjusted_bet_amount,
109
+ amount=self.bet_amount,
131
110
  currency=market.currency,
132
111
  ),
133
112
  }
@@ -141,6 +120,9 @@ class MaxAccuracyBettingStrategy(BettingStrategy):
141
120
  def calculate_direction(market_p_yes: float, estimate_p_yes: float) -> bool:
142
121
  return estimate_p_yes >= 0.5
143
122
 
123
+ def __repr__(self) -> str:
124
+ return f"{self.__class__.__name__}(bet_amount={self.bet_amount})"
125
+
144
126
 
145
127
  class MaxExpectedValueBettingStrategy(MaxAccuracyBettingStrategy):
146
128
  @staticmethod
@@ -152,6 +134,53 @@ class MaxExpectedValueBettingStrategy(MaxAccuracyBettingStrategy):
152
134
 
153
135
 
154
136
  class KellyBettingStrategy(BettingStrategy):
137
+ def __init__(self, max_bet_amount: float):
138
+ self.max_bet_amount = max_bet_amount
139
+
140
+ def calculate_trades(
141
+ self,
142
+ existing_position: Position | None,
143
+ answer: ProbabilisticAnswer,
144
+ market: AgentMarket,
145
+ ) -> list[Trade]:
146
+ outcome_token_pool = check_not_none(market.outcome_token_pool)
147
+ kelly_bet = (
148
+ get_kelly_bet_full(
149
+ yes_outcome_pool_size=outcome_token_pool[
150
+ market.get_outcome_str_from_bool(True)
151
+ ],
152
+ no_outcome_pool_size=outcome_token_pool[
153
+ market.get_outcome_str_from_bool(False)
154
+ ],
155
+ estimated_p_yes=answer.p_yes,
156
+ max_bet=self.max_bet_amount,
157
+ confidence=answer.confidence,
158
+ )
159
+ if market.has_token_pool()
160
+ else get_kelly_bet_simplified(
161
+ self.max_bet_amount,
162
+ market.current_p_yes,
163
+ answer.p_yes,
164
+ answer.confidence,
165
+ )
166
+ )
167
+
168
+ amounts = {
169
+ market.get_outcome_str_from_bool(kelly_bet.direction): TokenAmount(
170
+ amount=kelly_bet.size, currency=market.currency
171
+ ),
172
+ }
173
+ target_position = Position(market_id=market.id, amounts=amounts)
174
+ trades = self._build_rebalance_trades_from_positions(
175
+ existing_position, target_position, market=market
176
+ )
177
+ return trades
178
+
179
+ def __repr__(self) -> str:
180
+ return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount})"
181
+
182
+
183
+ class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
155
184
  def __init__(self, max_bet_amount: float = 10):
156
185
  self.max_bet_amount = max_bet_amount
157
186
 
@@ -171,6 +200,11 @@ class KellyBettingStrategy(BettingStrategy):
171
200
  ) -> list[Trade]:
172
201
  adjusted_bet_amount = self.adjust_bet_amount(existing_position, market)
173
202
  outcome_token_pool = check_not_none(market.outcome_token_pool)
203
+
204
+ # Fixed direction of bet, only use Kelly to adjust the bet size based on market's outcome pool size.
205
+ estimated_p_yes = float(answer.p_yes > 0.5)
206
+ confidence = 1.0
207
+
174
208
  kelly_bet = (
175
209
  get_kelly_bet_full(
176
210
  yes_outcome_pool_size=outcome_token_pool[
@@ -179,16 +213,16 @@ class KellyBettingStrategy(BettingStrategy):
179
213
  no_outcome_pool_size=outcome_token_pool[
180
214
  market.get_outcome_str_from_bool(False)
181
215
  ],
182
- estimated_p_yes=answer.p_yes,
216
+ estimated_p_yes=estimated_p_yes,
183
217
  max_bet=adjusted_bet_amount,
184
- confidence=answer.confidence,
218
+ confidence=confidence,
185
219
  )
186
220
  if market.has_token_pool()
187
221
  else get_kelly_bet_simplified(
188
222
  adjusted_bet_amount,
189
223
  market.current_p_yes,
190
- answer.p_yes,
191
- answer.confidence,
224
+ estimated_p_yes,
225
+ confidence,
192
226
  )
193
227
  )
194
228
 
@@ -202,3 +236,6 @@ class KellyBettingStrategy(BettingStrategy):
202
236
  existing_position, target_position, market=market
203
237
  )
204
238
  return trades
239
+
240
+ def __repr__(self) -> str:
241
+ return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount})"
@@ -83,7 +83,8 @@ def compute_job_reward(
83
83
  market: OmenAgentMarket, max_bond: float, web3: Web3 | None = None
84
84
  ) -> float:
85
85
  # Because jobs are powered by prediction markets, potentional reward depends on job's liquidity and our will to bond (bet) our xDai into our job completion.
86
- required_trades = KellyBettingStrategy(max_bet_amount=max_bond).calculate_trades(
86
+ strategy = KellyBettingStrategy(max_bet_amount=max_bond)
87
+ required_trades = strategy.calculate_trades(
87
88
  existing_position=None,
88
89
  # We assume that we finish the job and so the probability of the market happening will be 100%.
89
90
  answer=ProbabilisticAnswer(p_yes=Probability(1.0), confidence=1.0),
@@ -166,13 +166,13 @@ class AgentMarket(BaseModel):
166
166
  def liquidate_existing_positions(self, outcome: bool) -> None:
167
167
  raise NotImplementedError("Subclasses must implement this method")
168
168
 
169
- def place_bet(self, outcome: bool, amount: BetAmount) -> None:
169
+ def place_bet(self, outcome: bool, amount: BetAmount) -> str:
170
170
  raise NotImplementedError("Subclasses must implement this method")
171
171
 
172
- def buy_tokens(self, outcome: bool, amount: TokenAmount) -> None:
172
+ def buy_tokens(self, outcome: bool, amount: TokenAmount) -> str:
173
173
  return self.place_bet(outcome=outcome, amount=amount)
174
174
 
175
- def sell_tokens(self, outcome: bool, amount: TokenAmount) -> None:
175
+ def sell_tokens(self, outcome: bool, amount: TokenAmount) -> str:
176
176
  raise NotImplementedError("Subclasses must implement this method")
177
177
 
178
178
  @staticmethod
@@ -281,3 +281,11 @@ class AgentMarket(BaseModel):
281
281
  raise ValueError("Outcome token pool is not available.")
282
282
 
283
283
  return self.outcome_token_pool[outcome]
284
+
285
+ @staticmethod
286
+ def get_user_balance(user_id: str) -> float:
287
+ raise NotImplementedError("Subclasses must implement this method")
288
+
289
+ @staticmethod
290
+ def get_user_id(api_keys: APIKeys) -> str:
291
+ raise NotImplementedError("Subclasses must implement this method")
@@ -37,6 +37,7 @@ ProfitAmount: TypeAlias = TokenAmount
37
37
 
38
38
 
39
39
  class Bet(BaseModel):
40
+ id: str
40
41
  amount: BetAmount
41
42
  outcome: bool
42
43
  created_time: datetime
@@ -126,3 +127,16 @@ class Trade(BaseModel):
126
127
  trade_type: TradeType
127
128
  outcome: bool
128
129
  amount: TokenAmount
130
+
131
+
132
+ class PlacedTrade(Trade):
133
+ id: str
134
+
135
+ @staticmethod
136
+ def from_trade(trade: Trade, id: str) -> "PlacedTrade":
137
+ return PlacedTrade(
138
+ trade_type=trade.trade_type,
139
+ outcome=trade.outcome,
140
+ amount=trade.amount,
141
+ id=id,
142
+ )
@@ -110,7 +110,7 @@ def get_one_manifold_binary_market() -> ManifoldMarket:
110
110
  )
111
111
  def place_bet(
112
112
  amount: Mana, market_id: str, outcome: bool, manifold_api_key: SecretStr
113
- ) -> None:
113
+ ) -> ManifoldBet:
114
114
  outcome_str = "YES" if outcome else "NO"
115
115
  url = f"{MANIFOLD_API_BASE_URL}/v0/bet"
116
116
  params = {
@@ -131,6 +131,7 @@ def place_bet(
131
131
  raise RuntimeError(
132
132
  f"Placing bet failed: {response.status_code} {response.reason} {response.text}"
133
133
  )
134
+ return ManifoldBet.model_validate(data)
134
135
  else:
135
136
  raise Exception(
136
137
  f"Placing bet failed: {response.status_code} {response.reason} {response.text}"
@@ -209,6 +210,7 @@ def manifold_to_generic_resolved_bet(
209
210
 
210
211
  market_outcome = market.get_resolved_boolean_outcome()
211
212
  return ResolvedBet(
213
+ id=bet.id,
212
214
  amount=BetAmount(amount=bet.amount, currency=Currency.Mana),
213
215
  outcome=bet.get_resolved_boolean_outcome(),
214
216
  created_time=bet.createdTime,
@@ -49,15 +49,16 @@ class ManifoldAgentMarket(AgentMarket):
49
49
  # Manifold lowest bet is 1 Mana, so we need to ceil the result.
50
50
  return mana_type(ceil(minimum_bet_to_win(answer, amount_to_win, self)))
51
51
 
52
- def place_bet(self, outcome: bool, amount: BetAmount) -> None:
52
+ def place_bet(self, outcome: bool, amount: BetAmount) -> str:
53
53
  if amount.currency != self.currency:
54
54
  raise ValueError(f"Manifold bets are made in Mana. Got {amount.currency}.")
55
- place_bet(
55
+ bet = place_bet(
56
56
  amount=Mana(amount.amount),
57
57
  market_id=self.id,
58
58
  outcome=outcome,
59
59
  manifold_api_key=APIKeys().manifold_api_key,
60
60
  )
61
+ return bet.id
61
62
 
62
63
  @staticmethod
63
64
  def from_data_model(model: FullManifoldMarket) -> "ManifoldAgentMarket":
@@ -119,3 +120,7 @@ class ManifoldAgentMarket(AgentMarket):
119
120
  @classmethod
120
121
  def get_user_url(cls, keys: APIKeys) -> str:
121
122
  return get_authenticated_user(keys.manifold_api_key.get_secret_value()).url
123
+
124
+ @staticmethod
125
+ def get_user_id(api_keys: APIKeys) -> str:
126
+ return api_keys.manifold_user_id
@@ -1,6 +1,7 @@
1
1
  import typing as t
2
2
  from datetime import datetime
3
3
 
4
+ from prediction_market_agent_tooling.config import APIKeys
4
5
  from prediction_market_agent_tooling.gtypes import Probability
5
6
  from prediction_market_agent_tooling.markets.agent_market import (
6
7
  AgentMarket,
@@ -104,3 +105,7 @@ class MetaculusAgentMarket(AgentMarket):
104
105
  def submit_prediction(self, p_yes: Probability, reasoning: str) -> None:
105
106
  make_prediction(self.id, p_yes)
106
107
  post_question_comment(self.id, reasoning)
108
+
109
+ @staticmethod
110
+ def get_user_id(api_keys: APIKeys) -> str:
111
+ return str(api_keys.metaculus_user_id)
@@ -382,7 +382,7 @@ class OmenBetCreator(BaseModel):
382
382
 
383
383
 
384
384
  class OmenBet(BaseModel):
385
- id: HexAddress
385
+ id: HexAddress # A concatenation of: FPMM contract ID, trader ID and nonce. See https://github.com/protofire/omen-subgraph/blob/f92bbfb6fa31ed9cd5985c416a26a2f640837d8b/src/FixedProductMarketMakerMapping.ts#L109
386
386
  title: str
387
387
  collateralToken: HexAddress
388
388
  outcomeTokenMarginalPrice: xDai
@@ -431,6 +431,9 @@ class OmenBet(BaseModel):
431
431
 
432
432
  def to_bet(self) -> Bet:
433
433
  return Bet(
434
+ id=str(
435
+ self.transactionHash
436
+ ), # Use the transaction hash instead of the bet id - both are valid, but we return the transaction hash from the trade functions, so be consistent here.
434
437
  amount=BetAmount(amount=self.collateralAmountUSD, currency=Currency.xDai),
435
438
  outcome=self.boolean_outcome,
436
439
  created_time=self.creation_datetime,
@@ -445,6 +448,9 @@ class OmenBet(BaseModel):
445
448
  )
446
449
 
447
450
  return ResolvedBet(
451
+ id=str(
452
+ self.transactionHash
453
+ ), # Use the transaction hash instead of the bet id - both are valid, but we return the transaction hash from the trade functions, so be consistent here.
448
454
  amount=BetAmount(amount=self.collateralAmountUSD, currency=Currency.xDai),
449
455
  outcome=self.boolean_outcome,
450
456
  created_time=self.creation_datetime,
@@ -189,7 +189,7 @@ class OmenAgentMarket(AgentMarket):
189
189
  omen_auto_deposit: bool = True,
190
190
  web3: Web3 | None = None,
191
191
  api_keys: APIKeys | None = None,
192
- ) -> None:
192
+ ) -> str:
193
193
  if not self.can_be_traded():
194
194
  raise ValueError(
195
195
  f"Market {self.id} is not open for trading. Cannot place bet."
@@ -197,7 +197,7 @@ class OmenAgentMarket(AgentMarket):
197
197
  if amount.currency != self.currency:
198
198
  raise ValueError(f"Omen bets are made in xDai. Got {amount.currency}.")
199
199
  amount_xdai = xDai(amount.amount)
200
- binary_omen_buy_outcome_tx(
200
+ return binary_omen_buy_outcome_tx(
201
201
  api_keys=api_keys if api_keys is not None else APIKeys(),
202
202
  amount=amount_xdai,
203
203
  market=self,
@@ -212,7 +212,7 @@ class OmenAgentMarket(AgentMarket):
212
212
  amount: TokenAmount,
213
213
  web3: Web3 | None = None,
214
214
  api_keys: APIKeys | None = None,
215
- ) -> None:
215
+ ) -> str:
216
216
  return self.place_bet(
217
217
  outcome=outcome,
218
218
  amount=amount,
@@ -245,7 +245,7 @@ class OmenAgentMarket(AgentMarket):
245
245
  auto_withdraw: bool = False,
246
246
  api_keys: APIKeys | None = None,
247
247
  web3: Web3 | None = None,
248
- ) -> None:
248
+ ) -> str:
249
249
  if not self.can_be_traded():
250
250
  raise ValueError(
251
251
  f"Market {self.id} is not open for trading. Cannot sell tokens."
@@ -258,7 +258,7 @@ class OmenAgentMarket(AgentMarket):
258
258
  outcome=outcome,
259
259
  web3=web3,
260
260
  )
261
- binary_omen_sell_outcome_tx(
261
+ return binary_omen_sell_outcome_tx(
262
262
  amount=collateral,
263
263
  api_keys=api_keys if api_keys is not None else APIKeys(),
264
264
  market=self,
@@ -633,6 +633,14 @@ class OmenAgentMarket(AgentMarket):
633
633
  )
634
634
  return Probability(new_p_yes)
635
635
 
636
+ @staticmethod
637
+ def get_user_balance(user_id: str) -> float:
638
+ return float(get_balances(Web3.to_checksum_address(user_id)).total)
639
+
640
+ @staticmethod
641
+ def get_user_id(api_keys: APIKeys) -> str:
642
+ return api_keys.bet_from_address
643
+
636
644
 
637
645
  def get_omen_user_url(address: ChecksumAddress) -> str:
638
646
  return f"https://gnosisscan.io/address/{address}"
@@ -659,7 +667,7 @@ def omen_buy_outcome_tx(
659
667
  outcome: str,
660
668
  auto_deposit: bool,
661
669
  web3: Web3 | None = None,
662
- ) -> None:
670
+ ) -> str:
663
671
  """
664
672
  Bets the given amount of xDai for the given outcome in the given market.
665
673
  """
@@ -695,7 +703,7 @@ def omen_buy_outcome_tx(
695
703
  )
696
704
 
697
705
  # Buy shares using the deposited xDai in the collateral token.
698
- market_contract.buy(
706
+ tx_receipt = market_contract.buy(
699
707
  api_keys=api_keys,
700
708
  amount_wei=amount_wei_to_buy,
701
709
  outcome_index=outcome_index,
@@ -703,6 +711,8 @@ def omen_buy_outcome_tx(
703
711
  web3=web3,
704
712
  )
705
713
 
714
+ return tx_receipt["transactionHash"].hex()
715
+
706
716
 
707
717
  def binary_omen_buy_outcome_tx(
708
718
  api_keys: APIKeys,
@@ -711,8 +721,8 @@ def binary_omen_buy_outcome_tx(
711
721
  binary_outcome: bool,
712
722
  auto_deposit: bool,
713
723
  web3: Web3 | None = None,
714
- ) -> None:
715
- omen_buy_outcome_tx(
724
+ ) -> str:
725
+ return omen_buy_outcome_tx(
716
726
  api_keys=api_keys,
717
727
  amount=amount,
718
728
  market=market,
@@ -729,7 +739,7 @@ def omen_sell_outcome_tx(
729
739
  outcome: str,
730
740
  auto_withdraw: bool,
731
741
  web3: Web3 | None = None,
732
- ) -> None:
742
+ ) -> str:
733
743
  """
734
744
  Sells the given xDai value of shares corresponding to the given outcome in
735
745
  the given market.
@@ -770,7 +780,7 @@ def omen_sell_outcome_tx(
770
780
  web3=web3,
771
781
  )
772
782
  # Sell the shares.
773
- market_contract.sell(
783
+ tx_receipt = market_contract.sell(
774
784
  api_keys,
775
785
  amount_wei,
776
786
  outcome_index,
@@ -792,6 +802,8 @@ def omen_sell_outcome_tx(
792
802
  web3,
793
803
  )
794
804
 
805
+ return tx_receipt["transactionHash"].hex()
806
+
795
807
 
796
808
  def binary_omen_sell_outcome_tx(
797
809
  api_keys: APIKeys,
@@ -800,8 +812,8 @@ def binary_omen_sell_outcome_tx(
800
812
  binary_outcome: bool,
801
813
  auto_withdraw: bool,
802
814
  web3: Web3 | None = None,
803
- ) -> None:
804
- omen_sell_outcome_tx(
815
+ ) -> str:
816
+ return omen_sell_outcome_tx(
805
817
  api_keys=api_keys,
806
818
  amount=amount,
807
819
  market=market,
@@ -930,7 +942,7 @@ def omen_fund_market_tx(
930
942
  web3: Web3 | None = None,
931
943
  ) -> None:
932
944
  market_contract = market.get_contract()
933
- collateral_token_contract = market_contract.get_collateral_token_contract()
945
+ collateral_token_contract = market_contract.get_collateral_token_contract(web3=web3)
934
946
 
935
947
  amount_to_fund = collateral_token_contract.get_in_shares(funds, web3)
936
948
 
@@ -1048,8 +1060,12 @@ def omen_remove_fund_market_tx(
1048
1060
  """
1049
1061
  from_address = api_keys.bet_from_address
1050
1062
  market_contract = market.get_contract()
1051
- market_collateral_token_contract = market_contract.get_collateral_token_contract()
1052
- original_balance = market_collateral_token_contract.balanceOf(from_address)
1063
+ market_collateral_token_contract = market_contract.get_collateral_token_contract(
1064
+ web3=web3
1065
+ )
1066
+ original_balance = market_collateral_token_contract.balanceOf(
1067
+ from_address, web3=web3
1068
+ )
1053
1069
 
1054
1070
  total_shares = market_contract.balanceOf(from_address, web3=web3)
1055
1071
  if total_shares == 0:
@@ -1084,11 +1100,11 @@ def omen_remove_fund_market_tx(
1084
1100
  web3=web3,
1085
1101
  )
1086
1102
 
1087
- new_balance = market_collateral_token_contract.balanceOf(from_address)
1103
+ new_balance = market_collateral_token_contract.balanceOf(from_address, web3=web3)
1088
1104
 
1089
1105
  logger.debug(f"Result from merge positions {result}")
1090
1106
  logger.info(
1091
- f"Withdrawn {new_balance - original_balance} {market_collateral_token_contract.symbol_cached()} from liquidity at {market.url=}."
1107
+ f"Withdrawn {new_balance - original_balance} {market_collateral_token_contract.symbol_cached(web3=web3)} from liquidity at {market.url=}."
1092
1108
  )
1093
1109
 
1094
1110
 
@@ -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(question_id=question.questionId)
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(where=where_stms)
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(where=where_stms)
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)
@@ -46,7 +46,7 @@ class PolymarketAgentMarket(AgentMarket):
46
46
  def get_tiny_bet_amount(cls) -> BetAmount:
47
47
  raise NotImplementedError("TODO: Implement to allow betting on Polymarket.")
48
48
 
49
- def place_bet(self, outcome: bool, amount: BetAmount) -> None:
49
+ def place_bet(self, outcome: bool, amount: BetAmount) -> str:
50
50
  raise NotImplementedError("TODO: Implement to allow betting on Polymarket.")
51
51
 
52
52
  @staticmethod
@@ -43,3 +43,7 @@ class DeployedPolymarketAgent(DeployedAgent):
43
43
  == MarketType.POLYMARKET.value,
44
44
  ) -> t.Sequence["DeployedPolymarketAgent"]:
45
45
  return super().from_all_gcp_functions(filter_=filter_)
46
+
47
+ @staticmethod
48
+ def get_user_id(api_keys: APIKeys) -> str:
49
+ return api_keys.bet_from_address
@@ -7,9 +7,9 @@ from langfuse.client import TraceWithDetails
7
7
  from pydantic import BaseModel
8
8
 
9
9
  from prediction_market_agent_tooling.markets.data_models import (
10
+ PlacedTrade,
10
11
  ProbabilisticAnswer,
11
12
  ResolvedBet,
12
- Trade,
13
13
  TradeType,
14
14
  )
15
15
  from prediction_market_agent_tooling.markets.omen.omen import OmenAgentMarket
@@ -20,10 +20,10 @@ class ProcessMarketTrace(BaseModel):
20
20
  timestamp: datetime
21
21
  market: OmenAgentMarket
22
22
  answer: ProbabilisticAnswer
23
- trades: list[Trade]
23
+ trades: list[PlacedTrade]
24
24
 
25
25
  @property
26
- def buy_trade(self) -> Trade:
26
+ def buy_trade(self) -> PlacedTrade:
27
27
  buy_trades = [t for t in self.trades if t.trade_type == TradeType.BUY]
28
28
  if len(buy_trades) == 1:
29
29
  return buy_trades[0]
@@ -107,10 +107,10 @@ def trace_to_answer(trace: TraceWithDetails) -> ProbabilisticAnswer:
107
107
  return ProbabilisticAnswer.model_validate(trace.output["answer"])
108
108
 
109
109
 
110
- def trace_to_trades(trace: TraceWithDetails) -> list[Trade]:
110
+ def trace_to_trades(trace: TraceWithDetails) -> list[PlacedTrade]:
111
111
  assert trace.output is not None, "Trace output is None"
112
112
  assert trace.output["trades"] is not None, "Trace output trades is None"
113
- return [Trade.model_validate(t) for t in trace.output["trades"]]
113
+ return [PlacedTrade.model_validate(t) for t in trace.output["trades"]]
114
114
 
115
115
 
116
116
  def get_closest_datetime_from_list(
@@ -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"]))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.48.17
3
+ Version: 0.49.0
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -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=xT0L1BLU89t7lfBcbbqojcH_4H7ElnXKMQB2wjFxwos,19112
18
+ prediction_market_agent_tooling/deploy/agent.py,sha256=QiGREI3YDafVP6kA7H6ejSTxMGBUEG-iYibda43k7vY,19749
19
19
  prediction_market_agent_tooling/deploy/agent_example.py,sha256=dIIdZashExWk9tOdyDjw87AuUcGyM7jYxNChYrVK2dM,1001
20
- prediction_market_agent_tooling/deploy/betting_strategy.py,sha256=edatJ7temvl9TBTy05JjtFCAlaoVXCfLOQlYWJ61wvw,7636
20
+ prediction_market_agent_tooling/deploy/betting_strategy.py,sha256=eCmKpi3EJxFNbPiT7zDYRxJrP76mj0idvSlzin1wtWg,8990
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
@@ -26,35 +26,35 @@ prediction_market_agent_tooling/gtypes.py,sha256=O77co9-GWmHJo_NyBzRVkli5L1xqweI
26
26
  prediction_market_agent_tooling/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  prediction_market_agent_tooling/jobs/jobs.py,sha256=I07yh0GJ-xhlvQaOUQB8xlSnihhcbU2c7DZ4ZND14c0,1246
28
28
  prediction_market_agent_tooling/jobs/jobs_models.py,sha256=8JS9n_EVgmNzqRg1YUjopPVZRjqFneVYCKnX4UEFy3I,1326
29
- prediction_market_agent_tooling/jobs/omen/omen_jobs.py,sha256=EAzo63vhSt1P7ddoDubdmvgzFf-ieQRTDCRLzYkH3js,3922
29
+ prediction_market_agent_tooling/jobs/omen/omen_jobs.py,sha256=Mr6fZqfOs4tzGYsp7g0ygolYjQaFCLG7ljP1mKs71ng,3946
30
30
  prediction_market_agent_tooling/loggers.py,sha256=Am6HHXRNO545BO3l7Ue9Wb2TkYE1OK8KKhGbI3XypVU,3751
31
- prediction_market_agent_tooling/markets/agent_market.py,sha256=nVJO1MY7_l-YP1Q7-mGLtRgIHK8M-yt3Ht1yyQPwImM,10176
31
+ prediction_market_agent_tooling/markets/agent_market.py,sha256=OmnoGgcH_jnYb-y7vG5XH9bEwb0VdCrBqfHAxLd7eIw,10457
32
32
  prediction_market_agent_tooling/markets/categorize.py,sha256=jsoHWvZk9pU6n17oWSCcCxNNYVwlb_NXsZxKRI7vmsk,1301
33
- prediction_market_agent_tooling/markets/data_models.py,sha256=vaJ049j2Anf5sZWjNflsCEag-Y0G1mTu6bCWT74HxqM,3266
33
+ prediction_market_agent_tooling/markets/data_models.py,sha256=DoSWVrHgzrEbEELSZ19hK38ckBShJLobmp6IetZaL8E,3563
34
34
  prediction_market_agent_tooling/markets/manifold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- prediction_market_agent_tooling/markets/manifold/api.py,sha256=AC2zmkzpBU3P4kyybs7CgPbDg4hLAx3GY5mjgDi7qDo,7221
35
+ prediction_market_agent_tooling/markets/manifold/api.py,sha256=pliGOyehEcApj1l6OaoVDeuGrws8AN2bymiTuP1y4t0,7295
36
36
  prediction_market_agent_tooling/markets/manifold/data_models.py,sha256=2Rh3j9SM2om-q61Mbxm_UjOzXfxnoej-f_Vyx0LMMfE,6467
37
- prediction_market_agent_tooling/markets/manifold/manifold.py,sha256=t_FyV7jBMSIV_MA_EWih3SpvChxpmBey5g8HYQrYde0,4316
37
+ prediction_market_agent_tooling/markets/manifold/manifold.py,sha256=e4T6IAxV2OfIHsPMOTqSpfTRfLZ7CxegAYbCLc35Os8,4450
38
38
  prediction_market_agent_tooling/markets/manifold/utils.py,sha256=cPPFWXm3vCYH1jy7_ctJZuQH9ZDaPL4_AgAYzGWkoow,513
39
39
  prediction_market_agent_tooling/markets/markets.py,sha256=EN0MgOBBk2ASSVTfqlk0MrsHxg3CVRyQl23jtzfeEi8,3222
40
40
  prediction_market_agent_tooling/markets/metaculus/api.py,sha256=gvPQVAM5NlCyWzEMt4WML9saRBsK9eiHAZP6jwirVqc,2750
41
41
  prediction_market_agent_tooling/markets/metaculus/data_models.py,sha256=6TBy17xntdLBR61QCE5wddwTa_k2D0D8ZgK6p7sGUuc,2448
42
- prediction_market_agent_tooling/markets/metaculus/metaculus.py,sha256=1aaainHlMExDSp6nfKY31iATQsaJx1LdYp9p2PkQVAs,3453
42
+ prediction_market_agent_tooling/markets/metaculus/metaculus.py,sha256=vvdN2DbOeSPyvCIzZyZmrAqAnmWqwCJgQ5bb5zRBlL4,3625
43
43
  prediction_market_agent_tooling/markets/omen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
- prediction_market_agent_tooling/markets/omen/data_models.py,sha256=PQyoENpXkhu5TXZhbUdDvKLsb2sQt8rwryPTVQ9fIeM,17029
45
- prediction_market_agent_tooling/markets/omen/omen.py,sha256=TGXthQITMoYvx1iK388nHbv8U0DQeX_jyHb-OEinvfg,46676
44
+ prediction_market_agent_tooling/markets/omen/data_models.py,sha256=B5EfIkq_ezfGiGFbWXPbtVTUDAsrcQ0DM9lmcLXzoHw,17675
45
+ prediction_market_agent_tooling/markets/omen/omen.py,sha256=euiia_WHnHeAEPEh0WeHLleKVl6Yp289oKyQZDGMTZo,47147
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=Awaw1r32IBAClCktrXbYJ24RNyLDWcLb8RqAx6FGSkI,9529
48
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=W3JIq3NDGoJuHZlPtv2Gv_EmCtYVwsgZwClSY-RloZw,30219
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
52
- prediction_market_agent_tooling/markets/polymarket/polymarket.py,sha256=wQ_jzwuPNB-u2eB7okw2I6qbvNZbUT0qH4pAIKXHBkI,2774
52
+ prediction_market_agent_tooling/markets/polymarket/polymarket.py,sha256=SONMs6gFAR_j8xgVK8MmQDTrFx64_JCi5IfVr52EeKE,2773
53
53
  prediction_market_agent_tooling/markets/polymarket/utils.py,sha256=m4JG6WULh5epCJt4XBMHg0ae5NoVhqlOvAl0A7DR9iM,2023
54
54
  prediction_market_agent_tooling/monitor/markets/manifold.py,sha256=GdYpgRX1GahDi-75Mr53jgtEg6nWcs_rHDUkg4o_7dQ,3352
55
55
  prediction_market_agent_tooling/monitor/markets/metaculus.py,sha256=S8zeDVN2aA6yvQykQNPb8GUGohczfJuCYt9Ds9ESCzs,1473
56
56
  prediction_market_agent_tooling/monitor/markets/omen.py,sha256=jOLPnIbDU9syjnYtHfOb2xa6-Ize3vbplgh-8WWkuT4,3323
57
- prediction_market_agent_tooling/monitor/markets/polymarket.py,sha256=I9z9aO1wncyGI3a09ihrw17JkeBKjAuMmC0I9pl_9o4,1781
57
+ prediction_market_agent_tooling/monitor/markets/polymarket.py,sha256=y7HVAEzeybfphB_VZPZpmAsQqjxPUM1uM7ZttQ56mm8,1888
58
58
  prediction_market_agent_tooling/monitor/monitor.py,sha256=tvYzHJg8Nau4vGWVTngjUAcM26LcH3Emss76351xl2o,14636
59
59
  prediction_market_agent_tooling/monitor/monitor_app.py,sha256=1e4LuzhAVjb7cPS6rGPZuZHMwMiNOeRhSxG8AVG-e0o,4839
60
60
  prediction_market_agent_tooling/monitor/monitor_settings.py,sha256=Xiozs3AsufuJ04JOe1vjUri-IAMWHjjmc2ugGGiHNH4,947
@@ -75,17 +75,18 @@ prediction_market_agent_tooling/tools/image_gen/image_gen.py,sha256=HzRwBx62hOXB
75
75
  prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py,sha256=8A3U2uxsCsOfLjru-6R_PPIAuiKY4qFkWp_GSBPV6-s,1280
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
- prediction_market_agent_tooling/tools/langfuse_client_utils.py,sha256=HZ8PN__CahMeNLaEx4v9esOqow6XEeezuYOOZD9-Ol8,4741
78
+ prediction_market_agent_tooling/tools/langfuse_client_utils.py,sha256=PcBi9CSEkyjdSKU8AoGvC2guBsCrUzFNw9BhMkm-vvI,4771
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=JE9YWtPPhnTgLiOyGAZDNG5K8nCwUY9IZEuAlm9UcxA,6611
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.17.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
88
- prediction_market_agent_tooling-0.48.17.dist-info/METADATA,sha256=sAyQzhlLTgPYGu4SF0z2dfSpSkZeJkZJYStbvagwh18,7848
89
- prediction_market_agent_tooling-0.48.17.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
90
- prediction_market_agent_tooling-0.48.17.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
91
- prediction_market_agent_tooling-0.48.17.dist-info/RECORD,,
88
+ prediction_market_agent_tooling-0.49.0.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
89
+ prediction_market_agent_tooling-0.49.0.dist-info/METADATA,sha256=DjQQylYgmiw5_M2v-5BHozKAUGyX8Ykmpr1WlWyyiKE,7847
90
+ prediction_market_agent_tooling-0.49.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
91
+ prediction_market_agent_tooling-0.49.0.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
92
+ prediction_market_agent_tooling-0.49.0.dist-info/RECORD,,