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.
- prediction_market_agent_tooling/markets/agent_market.py +27 -1
- prediction_market_agent_tooling/markets/data_models.py +7 -0
- prediction_market_agent_tooling/markets/omen/omen.py +68 -2
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +6 -0
- {prediction_market_agent_tooling-0.39.0.dist-info → prediction_market_agent_tooling-0.39.2.dist-info}/METADATA +1 -1
- {prediction_market_agent_tooling-0.39.0.dist-info → prediction_market_agent_tooling-0.39.2.dist-info}/RECORD +9 -9
- {prediction_market_agent_tooling-0.39.0.dist-info → prediction_market_agent_tooling-0.39.2.dist-info}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.39.0.dist-info → prediction_market_agent_tooling-0.39.2.dist-info}/WHEEL +0 -0
- {prediction_market_agent_tooling-0.39.0.dist-info → prediction_market_agent_tooling-0.39.2.dist-info}/entry_points.txt +0 -0
@@ -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(
|
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(
|
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=
|
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
|
)
|
@@ -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=
|
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=
|
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=
|
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=
|
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.
|
73
|
-
prediction_market_agent_tooling-0.39.
|
74
|
-
prediction_market_agent_tooling-0.39.
|
75
|
-
prediction_market_agent_tooling-0.39.
|
76
|
-
prediction_market_agent_tooling-0.39.
|
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,,
|
File without changes
|
File without changes
|