prediction-market-agent-tooling 0.48.18__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.
@@ -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,7 +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
286
 
287
287
  def __init__(
288
288
  self,
@@ -292,6 +292,15 @@ class DeployableTraderAgent(DeployableAgent):
292
292
  super().__init__(enable_langfuse=enable_langfuse)
293
293
  self.place_bet = place_bet
294
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
+
295
304
  def initialize_langfuse(self) -> None:
296
305
  super().initialize_langfuse()
297
306
  # Auto-observe all the methods where it makes sense, so that subclassses don't need to do it manually.
@@ -410,7 +419,8 @@ class DeployableTraderAgent(DeployableAgent):
410
419
  answer: ProbabilisticAnswer,
411
420
  existing_position: Position | None,
412
421
  ) -> list[Trade]:
413
- 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)
414
424
  BettingStrategy.assert_trades_currency_match_markets(market, trades)
415
425
  return trades
416
426
 
@@ -443,24 +453,32 @@ class DeployableTraderAgent(DeployableAgent):
443
453
 
444
454
  existing_position = market.get_position(user_id=APIKeys().bet_from_address)
445
455
  trades = self.build_trades(
446
- market=market, answer=answer, existing_position=existing_position
456
+ market=market,
457
+ answer=answer,
458
+ existing_position=existing_position,
447
459
  )
448
460
 
461
+ placed_trades = []
449
462
  if self.place_bet:
450
463
  for trade in trades:
451
464
  logger.info(f"Executing trade {trade}")
452
465
 
453
466
  match trade.trade_type:
454
467
  case TradeType.BUY:
455
- market.buy_tokens(outcome=trade.outcome, amount=trade.amount)
468
+ id = market.buy_tokens(
469
+ outcome=trade.outcome, amount=trade.amount
470
+ )
456
471
  case TradeType.SELL:
457
- market.sell_tokens(outcome=trade.outcome, amount=trade.amount)
472
+ id = market.sell_tokens(
473
+ outcome=trade.outcome, amount=trade.amount
474
+ )
458
475
  case _:
459
476
  raise ValueError(f"Unexpected trade type {trade.trade_type}.")
477
+ placed_trades.append(PlacedTrade.from_trade(trade, id))
460
478
 
461
479
  self.after_process_market(market_type, market)
462
480
 
463
- processed_market = ProcessedMarket(answer=answer, trades=trades)
481
+ processed_market = ProcessedMarket(answer=answer, trades=placed_trades)
464
482
  self.update_langfuse_trace_by_processed_market(market_type, processed_market)
465
483
 
466
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
  }
@@ -155,24 +134,15 @@ class MaxExpectedValueBettingStrategy(MaxAccuracyBettingStrategy):
155
134
 
156
135
 
157
136
  class KellyBettingStrategy(BettingStrategy):
158
- def __init__(self, max_bet_amount: float = 10):
137
+ def __init__(self, max_bet_amount: float):
159
138
  self.max_bet_amount = max_bet_amount
160
139
 
161
- def adjust_bet_amount(
162
- self, existing_position: Position | None, market: AgentMarket
163
- ) -> float:
164
- existing_position_total_amount = (
165
- existing_position.total_amount.amount if existing_position else 0
166
- )
167
- return self.max_bet_amount + existing_position_total_amount
168
-
169
140
  def calculate_trades(
170
141
  self,
171
142
  existing_position: Position | None,
172
143
  answer: ProbabilisticAnswer,
173
144
  market: AgentMarket,
174
145
  ) -> list[Trade]:
175
- adjusted_bet_amount = self.adjust_bet_amount(existing_position, market)
176
146
  outcome_token_pool = check_not_none(market.outcome_token_pool)
177
147
  kelly_bet = (
178
148
  get_kelly_bet_full(
@@ -183,12 +153,12 @@ class KellyBettingStrategy(BettingStrategy):
183
153
  market.get_outcome_str_from_bool(False)
184
154
  ],
185
155
  estimated_p_yes=answer.p_yes,
186
- max_bet=adjusted_bet_amount,
156
+ max_bet=self.max_bet_amount,
187
157
  confidence=answer.confidence,
188
158
  )
189
159
  if market.has_token_pool()
190
160
  else get_kelly_bet_simplified(
191
- adjusted_bet_amount,
161
+ self.max_bet_amount,
192
162
  market.current_p_yes,
193
163
  answer.p_yes,
194
164
  answer.confidence,
@@ -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
 
@@ -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(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.48.18
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=Pgl6M5d0COjKtIpKNjickAhnvRJVQo-oYIGNTT7n7DY,19074
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=SHDdgjlkjj0fAD4XUqVimOcqVHv9_JywR4BT68_srLM,10091
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
47
  prediction_market_agent_tooling/markets/omen/omen_resolving.py,sha256=udzte2jD33tONHPfMGhQbkAlHePRuw5iF8YXy71P8qo,9555
48
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,7 +75,7 @@ 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
79
  prediction_market_agent_tooling/tools/omen/reality_accuracy.py,sha256=M1SF7iSW1gVlQSTskdVFTn09uPLST23YeipVIWj54io,2236
80
80
  prediction_market_agent_tooling/tools/parallelism.py,sha256=6Gou0hbjtMZrYvxjTDFUDZuxmE2nqZVbb6hkg1hF82A,1022
81
81
  prediction_market_agent_tooling/tools/safe.py,sha256=h0xOO0eNtitClf0fPkn-0oTc6A_bflDTee98V_aiV-A,5195
@@ -85,8 +85,8 @@ prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py,sha256=Uq2
85
85
  prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py,sha256=xrtQH9v5pXycBRyc5j45pWqkSffkoc9efNIU1_G633Q,3706
86
86
  prediction_market_agent_tooling/tools/utils.py,sha256=uItjuwR5ZB6Qy7mmc5Dzx7fa2lkLO7oHhk2nzJMrIVo,7341
87
87
  prediction_market_agent_tooling/tools/web3_utils.py,sha256=IZDxHhUJH5RsaRkK9DW6z1RYdk2cz5RqLMZG3T6Gv1U,11602
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,,
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,,