prediction-market-agent-tooling 0.39.0__py3-none-any.whl → 0.39.2__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.
@@ -114,6 +114,20 @@ class AgentMarket(BaseModel):
114
114
  """
115
115
  raise NotImplementedError("Subclasses must implement this method")
116
116
 
117
+ def get_last_trade_yes_outcome_price(self) -> float | None:
118
+ # Price on prediction markets are, by definition, equal to the probability of an outcome.
119
+ # Just making it explicit in this function.
120
+ if last_trade_p_yes := self.get_last_trade_p_yes():
121
+ return float(last_trade_p_yes)
122
+ return None
123
+
124
+ def get_last_trade_no_outcome_price(self) -> float | None:
125
+ # Price on prediction markets are, by definition, equal to the probability of an outcome.
126
+ # Just making it explicit in this function.
127
+ if last_trade_p_no := self.get_last_trade_p_no():
128
+ return float(last_trade_p_no)
129
+ return None
130
+
117
131
  def get_bet_amount(self, amount: float) -> BetAmount:
118
132
  return BetAmount(amount=amount, currency=self.currency)
119
133
 
@@ -185,11 +199,23 @@ class AgentMarket(BaseModel):
185
199
  raise NotImplementedError("Subclasses must implement this method")
186
200
 
187
201
  @classmethod
188
- def get_positions(cls, user_id: str, liquid_only: bool = False) -> list[Position]:
202
+ def get_positions(
203
+ cls, user_id: str, liquid_only: bool = False, larger_than: float = 0
204
+ ) -> list[Position]:
189
205
  """
190
206
  Get all non-zero positions a user has in any market.
191
207
 
192
208
  If `liquid_only` is True, only return positions that can be sold.
209
+
210
+ If `larger_than` is not None, only return positions with a larger number
211
+ of tokens than this amount.
212
+ """
213
+ raise NotImplementedError("Subclasses must implement this method")
214
+
215
+ @classmethod
216
+ def get_positions_value(cls, positions: list[Position]) -> BetAmount:
217
+ """
218
+ Get the total value of all positions held by a user.
193
219
  """
194
220
  raise NotImplementedError("Subclasses must implement this method")
195
221
 
@@ -50,6 +50,13 @@ class Position(BaseModel):
50
50
  market_id: str
51
51
  amounts: dict[OutcomeStr, TokenAmount]
52
52
 
53
+ @property
54
+ def total_amount(self) -> TokenAmount:
55
+ return TokenAmount(
56
+ amount=sum(amount.amount for amount in self.amounts.values()),
57
+ currency=self.amounts[next(iter(self.amounts.keys()))].currency,
58
+ )
59
+
53
60
  def __str__(self) -> str:
54
61
  amounts_str = ", ".join(
55
62
  f"{amount.amount} '{outcome}' tokens"
@@ -367,11 +367,16 @@ class OmenAgentMarket(AgentMarket):
367
367
  )
368
368
 
369
369
  @classmethod
370
- def get_positions(cls, user_id: str, liquid_only: bool = False) -> list[Position]:
370
+ def get_positions(
371
+ cls,
372
+ user_id: str,
373
+ liquid_only: bool = False,
374
+ larger_than: float = 0,
375
+ ) -> list[Position]:
371
376
  sgh = OmenSubgraphHandler()
372
377
  omen_positions = sgh.get_user_positions(
373
378
  better_address=Web3.to_checksum_address(user_id),
374
- total_balance_bigger_than=wei_type(0),
379
+ total_balance_bigger_than=xdai_to_wei(xDai(larger_than)),
375
380
  )
376
381
 
377
382
  # Sort positions and corresponding markets by condition_id
@@ -421,6 +426,67 @@ class OmenAgentMarket(AgentMarket):
421
426
 
422
427
  return positions
423
428
 
429
+ @classmethod
430
+ def get_positions_value(cls, positions: list[Position]) -> BetAmount:
431
+ # Two dicts to map from market ids to (1) positions and (2) market.
432
+ market_ids_positions = {p.market_id: p for p in positions}
433
+ # Check there is only one position per market.
434
+ if len(set(market_ids_positions.keys())) != len(positions):
435
+ raise ValueError(
436
+ f"Markets for positions ({market_ids_positions.keys()}) are not unique."
437
+ )
438
+ markets: list[OmenAgentMarket] = [
439
+ OmenAgentMarket.from_data_model(m)
440
+ for m in OmenSubgraphHandler().get_omen_binary_markets(
441
+ limit=sys.maxsize, id_in=list(market_ids_positions.keys())
442
+ )
443
+ ]
444
+ market_ids_markets = {m.id: m for m in markets}
445
+
446
+ # Validate that dict keys are the same.
447
+ if set(market_ids_positions.keys()) != set(market_ids_markets.keys()):
448
+ raise ValueError(
449
+ f"Market ids in {market_ids_positions.keys()} are not the same as in {market_ids_markets.keys()}"
450
+ )
451
+
452
+ # Initialise position value.
453
+ total_position_value = 0.0
454
+
455
+ for market_id in market_ids_positions.keys():
456
+ position = market_ids_positions[market_id]
457
+ market = market_ids_markets[market_id]
458
+
459
+ yes_tokens = 0.0
460
+ no_tokens = 0.0
461
+ if OMEN_TRUE_OUTCOME in position.amounts:
462
+ yes_tokens = position.amounts[OutcomeStr(OMEN_TRUE_OUTCOME)].amount
463
+ if OMEN_FALSE_OUTCOME in position.amounts:
464
+ no_tokens = position.amounts[OutcomeStr(OMEN_FALSE_OUTCOME)].amount
465
+
466
+ # Account for the value of positions in resolved markets
467
+ if market.is_resolved() and market.has_successful_resolution():
468
+ valued_tokens = yes_tokens if market.boolean_outcome else no_tokens
469
+ total_position_value += valued_tokens
470
+
471
+ # Or if the market is open and trading, get the value of the position
472
+ elif market.can_be_traded():
473
+ total_position_value += yes_tokens * market.yes_outcome_price
474
+ total_position_value += no_tokens * market.no_outcome_price
475
+
476
+ # Or if the market is still open but not trading, estimate the value
477
+ # of the position
478
+ else:
479
+ if yes_tokens:
480
+ yes_price = check_not_none(
481
+ market.get_last_trade_yes_outcome_price()
482
+ )
483
+ total_position_value += yes_tokens * yes_price
484
+ if no_tokens:
485
+ no_price = check_not_none(market.get_last_trade_no_outcome_price())
486
+ total_position_value += no_tokens * no_price
487
+
488
+ return BetAmount(amount=total_position_value, currency=Currency.xDai)
489
+
424
490
  @classmethod
425
491
  def get_user_url(cls, keys: APIKeys) -> str:
426
492
  return f"https://gnosisscan.io/address/{keys.bet_from_address}"
@@ -166,6 +166,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
166
166
  resolved: bool | None = None,
167
167
  liquidity_bigger_than: Wei | None = None,
168
168
  condition_id_in: list[HexBytes] | None = None,
169
+ id_in: list[str] | None = None,
169
170
  excluded_questions: set[str] | None = None,
170
171
  ) -> dict[str, t.Any]:
171
172
  where_stms: dict[str, t.Any] = {
@@ -193,6 +194,9 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
193
194
  if condition_id_in is not None:
194
195
  where_stms["condition_"]["id_in"] = [x.hex() for x in condition_id_in]
195
196
 
197
+ if id_in is not None:
198
+ where_stms["id_in"] = id_in
199
+
196
200
  if resolved is not None:
197
201
  if resolved:
198
202
  where_stms["resolutionTimestamp_not"] = None
@@ -308,6 +312,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
308
312
  creator: t.Optional[HexAddress] = None,
309
313
  liquidity_bigger_than: Wei | None = None,
310
314
  condition_id_in: list[HexBytes] | None = None,
315
+ id_in: list[str] | None = None,
311
316
  excluded_questions: set[str] | None = None, # question titles
312
317
  sort_by_field: FieldPath | None = None,
313
318
  sort_direction: str | None = None,
@@ -326,6 +331,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
326
331
  finalized=finalized,
327
332
  resolved=resolved,
328
333
  condition_id_in=condition_id_in,
334
+ id_in=id_in,
329
335
  excluded_questions=excluded_questions,
330
336
  liquidity_bigger_than=liquidity_bigger_than,
331
337
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.39.0
3
+ Version: 0.39.2
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -21,9 +21,9 @@ prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py,sha256=qYIHRxQLa
21
21
  prediction_market_agent_tooling/deploy/gcp/utils.py,sha256=oyW0jgrUT2Tr49c7GlpcMsYNQjoCSOcWis3q-MmVAhU,6089
22
22
  prediction_market_agent_tooling/gtypes.py,sha256=lbV2nsPyhMIRI9olx0_6A06jwTWKYBPGMxyiGVFysag,2467
23
23
  prediction_market_agent_tooling/loggers.py,sha256=ua9rynYmsbOJZjxPIFxRBooomeN08zuLSJ7lxZMDS7w,3133
24
- prediction_market_agent_tooling/markets/agent_market.py,sha256=SMvkXct_RgHXqF-fVq3ooTIQ_99MG77kVlvS3rM8Ozo,7019
24
+ prediction_market_agent_tooling/markets/agent_market.py,sha256=ZpBpNLqY2QXTAdmkCr8-L3yjN70H_y-KiCptx3OFQgM,8099
25
25
  prediction_market_agent_tooling/markets/categorize.py,sha256=yTd-lDMPW4ESDSzmxeLLBuzLX0FggOF7Vbswh7295o0,941
26
- prediction_market_agent_tooling/markets/data_models.py,sha256=uODY3aoFp8YYeLAUcrzMk1yU8pIKsTLobB9xIEGTmKs,1170
26
+ prediction_market_agent_tooling/markets/data_models.py,sha256=6J8tyq-ZJI2HknqJolDCMfWXVXZsdBq3EhVQeIiT6bY,1418
27
27
  prediction_market_agent_tooling/markets/manifold/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  prediction_market_agent_tooling/markets/manifold/api.py,sha256=m6qOzDiyQfxj62Eo_SzzQLkX4ijpi8KtQKGd4CpKAsk,7307
29
29
  prediction_market_agent_tooling/markets/manifold/data_models.py,sha256=Iw-ajDPYhtfcTfN45nJN_kZShfWcWe9mgzexSWnQCCQ,5295
@@ -32,10 +32,10 @@ prediction_market_agent_tooling/markets/manifold/utils.py,sha256=cPPFWXm3vCYH1jy
32
32
  prediction_market_agent_tooling/markets/markets.py,sha256=w05Oo7yCA2axpCw69Q9y4i9Gcdpht0u5bZGbWqld3rU,2964
33
33
  prediction_market_agent_tooling/markets/omen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  prediction_market_agent_tooling/markets/omen/data_models.py,sha256=EXtjmcujx68Xu50BVkYXvLuf_Asx5o65RvFS3ZS6HGs,14405
35
- prediction_market_agent_tooling/markets/omen/omen.py,sha256=fS19WoDG_N8WIa5FY-YRF21Np46y6d93QBJOpNKXi7Q,33939
35
+ prediction_market_agent_tooling/markets/omen/omen.py,sha256=dMun3MvkvEVrBmN2NwCCb1Uq3kd9nePe1FhFBgHHcj0,36868
36
36
  prediction_market_agent_tooling/markets/omen/omen_contracts.py,sha256=-EEmN4vA8Fn52ewqQ7ZXZAFnfP4EQ4YISkeDHb9oeLk,21722
37
37
  prediction_market_agent_tooling/markets/omen/omen_resolving.py,sha256=g77QsQ5WnSI2rzBlX87L_EhWMwobkyXyfRhHQmpAdzo,9012
38
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=2y89FJlDrJ_hpeNTFZU1W30xCpt8QXjssEW8bNZnEpU,23596
38
+ prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=6TC-uTq6DEQdXkbsZ0jI-g9zbqoO7UT3RCLFN1mQtAk,23772
39
39
  prediction_market_agent_tooling/markets/polymarket/api.py,sha256=HXmA1akA0qDj0m3e-GEvWG8x75pm6BX4H7YJPQcST7I,4767
40
40
  prediction_market_agent_tooling/markets/polymarket/data_models.py,sha256=9CJzakyEcsn6DQBK2nOXjOMzTZBLAmK_KqevXvW17DI,4292
41
41
  prediction_market_agent_tooling/markets/polymarket/data_models_web.py,sha256=f8SRQy0Rn-gIHSEMrJJAI8H3J7l8lzOLj3aCMe0vJv8,11324
@@ -69,8 +69,8 @@ prediction_market_agent_tooling/tools/singleton.py,sha256=CiIELUiI-OeS7U7eeHEt0r
69
69
  prediction_market_agent_tooling/tools/streamlit_user_login.py,sha256=NXEqfjT9Lc9QtliwSGRASIz1opjQ7Btme43H4qJbzgE,3010
70
70
  prediction_market_agent_tooling/tools/utils.py,sha256=-G22UEbCRm59bm1RWFdeF55hRsaxgwZVAHvK32-Ye1g,6190
71
71
  prediction_market_agent_tooling/tools/web3_utils.py,sha256=nKRHmdLnWSKd3wpo-cysXGvhhrJ2Yf69sN2FFQfSt6s,10578
72
- prediction_market_agent_tooling-0.39.0.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
73
- prediction_market_agent_tooling-0.39.0.dist-info/METADATA,sha256=Jzdbs7Vpcixk6fiZ3ap_BN5U_GN_yHpSMOAz9__IO8g,7634
74
- prediction_market_agent_tooling-0.39.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
75
- prediction_market_agent_tooling-0.39.0.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
76
- prediction_market_agent_tooling-0.39.0.dist-info/RECORD,,
72
+ prediction_market_agent_tooling-0.39.2.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
73
+ prediction_market_agent_tooling-0.39.2.dist-info/METADATA,sha256=_3lt-n5ktkIsCSzP3YGNfj7X3OrNTqUJKhNILaTqA-4,7634
74
+ prediction_market_agent_tooling-0.39.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
75
+ prediction_market_agent_tooling-0.39.2.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
76
+ prediction_market_agent_tooling-0.39.2.dist-info/RECORD,,