prediction-market-agent-tooling 0.49.1__py3-none-any.whl → 0.50.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 (43) hide show
  1. prediction_market_agent_tooling/benchmark/agents.py +6 -6
  2. prediction_market_agent_tooling/deploy/agent.py +5 -5
  3. prediction_market_agent_tooling/deploy/betting_strategy.py +83 -3
  4. prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +3 -4
  5. prediction_market_agent_tooling/gtypes.py +3 -2
  6. prediction_market_agent_tooling/jobs/jobs_models.py +3 -3
  7. prediction_market_agent_tooling/jobs/omen/omen_jobs.py +2 -2
  8. prediction_market_agent_tooling/markets/agent_market.py +13 -17
  9. prediction_market_agent_tooling/markets/data_models.py +3 -3
  10. prediction_market_agent_tooling/markets/manifold/api.py +6 -6
  11. prediction_market_agent_tooling/markets/manifold/data_models.py +13 -23
  12. prediction_market_agent_tooling/markets/manifold/manifold.py +2 -2
  13. prediction_market_agent_tooling/markets/markets.py +7 -3
  14. prediction_market_agent_tooling/markets/metaculus/api.py +2 -3
  15. prediction_market_agent_tooling/markets/metaculus/data_models.py +11 -10
  16. prediction_market_agent_tooling/markets/metaculus/metaculus.py +2 -2
  17. prediction_market_agent_tooling/markets/omen/data_models.py +35 -22
  18. prediction_market_agent_tooling/markets/omen/omen.py +13 -9
  19. prediction_market_agent_tooling/markets/omen/omen_contracts.py +4 -2
  20. prediction_market_agent_tooling/markets/omen/omen_resolving.py +3 -4
  21. prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +46 -33
  22. prediction_market_agent_tooling/markets/polymarket/api.py +1 -1
  23. prediction_market_agent_tooling/markets/polymarket/data_models.py +5 -6
  24. prediction_market_agent_tooling/markets/polymarket/data_models_web.py +14 -14
  25. prediction_market_agent_tooling/markets/polymarket/polymarket.py +2 -2
  26. prediction_market_agent_tooling/monitor/markets/manifold.py +2 -2
  27. prediction_market_agent_tooling/monitor/markets/metaculus.py +2 -2
  28. prediction_market_agent_tooling/monitor/markets/omen.py +2 -2
  29. prediction_market_agent_tooling/monitor/markets/polymarket.py +2 -2
  30. prediction_market_agent_tooling/monitor/monitor.py +5 -15
  31. prediction_market_agent_tooling/monitor/monitor_app.py +7 -8
  32. prediction_market_agent_tooling/tools/contract.py +3 -7
  33. prediction_market_agent_tooling/tools/datetime_utc.py +74 -0
  34. prediction_market_agent_tooling/tools/httpx_cached_client.py +11 -0
  35. prediction_market_agent_tooling/tools/is_predictable.py +1 -1
  36. prediction_market_agent_tooling/tools/langfuse_client_utils.py +16 -11
  37. prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py +5 -5
  38. prediction_market_agent_tooling/tools/utils.py +28 -52
  39. {prediction_market_agent_tooling-0.49.1.dist-info → prediction_market_agent_tooling-0.50.0.dist-info}/METADATA +5 -2
  40. {prediction_market_agent_tooling-0.49.1.dist-info → prediction_market_agent_tooling-0.50.0.dist-info}/RECORD +43 -41
  41. {prediction_market_agent_tooling-0.49.1.dist-info → prediction_market_agent_tooling-0.50.0.dist-info}/LICENSE +0 -0
  42. {prediction_market_agent_tooling-0.49.1.dist-info → prediction_market_agent_tooling-0.50.0.dist-info}/WHEEL +0 -0
  43. {prediction_market_agent_tooling-0.49.1.dist-info → prediction_market_agent_tooling-0.50.0.dist-info}/entry_points.txt +0 -0
@@ -1,9 +1,10 @@
1
- from datetime import datetime
2
1
  from enum import Enum
3
2
  from typing import Any
4
3
 
5
4
  from pydantic import BaseModel
6
5
 
6
+ from prediction_market_agent_tooling.tools.utils import DatetimeUTC
7
+
7
8
 
8
9
  class QuestionType(str, Enum):
9
10
  forecast = "forecast"
@@ -33,7 +34,7 @@ class CommunityPrediction(BaseModel):
33
34
 
34
35
 
35
36
  class Prediction(BaseModel):
36
- t: datetime
37
+ t: DatetimeUTC
37
38
  x: float
38
39
 
39
40
 
@@ -68,20 +69,20 @@ class MetaculusQuestion(BaseModel):
68
69
  group_label: str | None = None
69
70
  resolution: int | None
70
71
  resolved_option: int | None
71
- created_time: datetime
72
- publish_time: datetime | None = None
73
- close_time: datetime | None = None
74
- effected_close_time: datetime | None
75
- resolve_time: datetime | None = None
72
+ created_time: DatetimeUTC
73
+ publish_time: DatetimeUTC | None = None
74
+ close_time: DatetimeUTC | None = None
75
+ effected_close_time: DatetimeUTC | None
76
+ resolve_time: DatetimeUTC | None = None
76
77
  possibilities: dict[Any, Any] | None = None
77
78
  scoring: dict[Any, Any] = {}
78
79
  type: QuestionType | None = None
79
80
  user_perms: Any
80
81
  weekly_movement: float | None
81
82
  weekly_movement_direction: int | None = None
82
- cp_reveal_time: datetime | None = None
83
- edited_time: datetime
84
- last_activity_time: datetime
83
+ cp_reveal_time: DatetimeUTC | None = None
84
+ edited_time: DatetimeUTC
85
+ last_activity_time: DatetimeUTC
85
86
  activity: float
86
87
  comment_count: int
87
88
  votes: int
@@ -1,5 +1,4 @@
1
1
  import typing as t
2
- from datetime import datetime
3
2
 
4
3
  from prediction_market_agent_tooling.config import APIKeys
5
4
  from prediction_market_agent_tooling.gtypes import Probability
@@ -17,6 +16,7 @@ from prediction_market_agent_tooling.markets.metaculus.api import (
17
16
  from prediction_market_agent_tooling.markets.metaculus.data_models import (
18
17
  MetaculusQuestion,
19
18
  )
19
+ from prediction_market_agent_tooling.tools.utils import DatetimeUTC
20
20
 
21
21
 
22
22
  class MetaculusAgentMarket(AgentMarket):
@@ -52,7 +52,7 @@ class MetaculusAgentMarket(AgentMarket):
52
52
  limit: int,
53
53
  sort_by: SortBy = SortBy.NONE,
54
54
  filter_by: FilterBy = FilterBy.OPEN,
55
- created_after: t.Optional[datetime] = None,
55
+ created_after: t.Optional[DatetimeUTC] = None,
56
56
  excluded_questions: set[str] | None = None,
57
57
  tournament_id: int | None = None,
58
58
  ) -> t.Sequence["MetaculusAgentMarket"]:
@@ -1,7 +1,5 @@
1
1
  import typing as t
2
- from datetime import datetime
3
2
 
4
- import pytz
5
3
  from pydantic import BaseModel, ConfigDict, Field, computed_field
6
4
  from web3 import Web3
7
5
 
@@ -26,6 +24,7 @@ from prediction_market_agent_tooling.markets.data_models import (
26
24
  ResolvedBet,
27
25
  )
28
26
  from prediction_market_agent_tooling.tools.utils import (
27
+ DatetimeUTC,
29
28
  check_not_none,
30
29
  should_not_happen,
31
30
  )
@@ -71,7 +70,7 @@ class Question(BaseModel):
71
70
  outcomes: list[str]
72
71
  isPendingArbitration: bool
73
72
  openingTimestamp: int
74
- answerFinalizedTimestamp: t.Optional[datetime] = None
73
+ answerFinalizedTimestamp: t.Optional[DatetimeUTC] = None
75
74
  currentAnswer: t.Optional[str] = None
76
75
 
77
76
  @property
@@ -84,8 +83,8 @@ class Question(BaseModel):
84
83
  return len(self.outcomes)
85
84
 
86
85
  @property
87
- def opening_datetime(self) -> datetime:
88
- return datetime.fromtimestamp(self.openingTimestamp)
86
+ def opening_datetime(self) -> DatetimeUTC:
87
+ return DatetimeUTC.to_datetime_utc(self.openingTimestamp)
89
88
 
90
89
  @property
91
90
  def has_answer(self) -> bool:
@@ -218,11 +217,11 @@ class OmenMarket(BaseModel):
218
217
  return self.question.openingTimestamp
219
218
 
220
219
  @property
221
- def opening_datetime(self) -> datetime:
222
- return datetime.fromtimestamp(self.openingTimestamp, tz=pytz.UTC)
220
+ def opening_datetime(self) -> DatetimeUTC:
221
+ return DatetimeUTC.to_datetime_utc(self.openingTimestamp)
223
222
 
224
223
  @property
225
- def close_time(self) -> datetime:
224
+ def close_time(self) -> DatetimeUTC:
226
225
  # Opening of the Reality's question is close time for the market,
227
226
  # however, market is usually "closed" even sooner by removing all the liquidity.
228
227
  return self.opening_datetime
@@ -257,13 +256,13 @@ class OmenMarket(BaseModel):
257
256
  return self.title
258
257
 
259
258
  @property
260
- def creation_datetime(self) -> datetime:
261
- return datetime.fromtimestamp(self.creationTimestamp)
259
+ def creation_datetime(self) -> DatetimeUTC:
260
+ return DatetimeUTC.to_datetime_utc(self.creationTimestamp)
262
261
 
263
262
  @property
264
- def finalized_datetime(self) -> datetime | None:
263
+ def finalized_datetime(self) -> DatetimeUTC | None:
265
264
  return (
266
- datetime.fromtimestamp(self.answerFinalizedTimestamp)
265
+ DatetimeUTC.to_datetime_utc(self.answerFinalizedTimestamp)
267
266
  if self.answerFinalizedTimestamp is not None
268
267
  else None
269
268
  )
@@ -490,8 +489,8 @@ class OmenBet(BaseModel):
490
489
  fpmm: OmenMarket
491
490
 
492
491
  @property
493
- def creation_datetime(self) -> datetime:
494
- return datetime.fromtimestamp(self.creationTimestamp, tz=pytz.UTC)
492
+ def creation_datetime(self) -> DatetimeUTC:
493
+ return DatetimeUTC.to_datetime_utc(self.creationTimestamp)
495
494
 
496
495
  @property
497
496
  def boolean_outcome(self) -> bool:
@@ -548,9 +547,7 @@ class OmenBet(BaseModel):
548
547
  market_question=self.title,
549
548
  market_id=self.fpmm.id,
550
549
  market_outcome=self.fpmm.boolean_outcome,
551
- resolved_time=datetime.fromtimestamp(
552
- check_not_none(self.fpmm.answerFinalizedTimestamp)
553
- ),
550
+ resolved_time=check_not_none(self.fpmm.finalized_datetime),
554
551
  profit=self.get_profit(),
555
552
  )
556
553
 
@@ -571,11 +568,23 @@ class RealityQuestion(BaseModel):
571
568
  id: str
572
569
  user: HexAddress
573
570
  historyHash: HexBytes | None
574
- updatedTimestamp: datetime
571
+ updatedTimestamp: int
575
572
  contentHash: HexBytes
576
573
  questionId: HexBytes
577
- answerFinalizedTimestamp: datetime
578
- currentScheduledFinalizationTimestamp: datetime
574
+ answerFinalizedTimestamp: int
575
+ currentScheduledFinalizationTimestamp: int
576
+
577
+ @property
578
+ def updated_datetime(self) -> DatetimeUTC:
579
+ return DatetimeUTC.to_datetime_utc(self.updatedTimestamp)
580
+
581
+ @property
582
+ def answer_finalized_datetime(self) -> DatetimeUTC:
583
+ return DatetimeUTC.to_datetime_utc(self.answerFinalizedTimestamp)
584
+
585
+ @property
586
+ def current_scheduled_finalization_datetime(self) -> DatetimeUTC:
587
+ return DatetimeUTC.to_datetime_utc(self.currentScheduledFinalizationTimestamp)
579
588
 
580
589
  @property
581
590
  def url(self) -> str:
@@ -584,13 +593,17 @@ class RealityQuestion(BaseModel):
584
593
 
585
594
  class RealityAnswer(BaseModel):
586
595
  id: str
587
- timestamp: datetime
596
+ timestamp: int
588
597
  answer: HexBytes
589
598
  lastBond: Wei
590
599
  bondAggregate: Wei
591
600
  question: RealityQuestion
592
601
  createdBlock: int
593
602
 
603
+ @property
604
+ def timestamp_datetime(self) -> DatetimeUTC:
605
+ return DatetimeUTC.to_datetime_utc(self.timestamp)
606
+
594
607
 
595
608
  class RealityResponse(BaseModel):
596
609
  """
@@ -598,7 +611,7 @@ class RealityResponse(BaseModel):
598
611
  """
599
612
 
600
613
  id: str
601
- timestamp: datetime
614
+ timestamp: int
602
615
  answer: HexBytes
603
616
  isUnrevealed: bool
604
617
  isCommitment: bool
@@ -1,6 +1,6 @@
1
1
  import sys
2
2
  import typing as t
3
- from datetime import datetime, timedelta
3
+ from datetime import timedelta
4
4
 
5
5
  import tenacity
6
6
  from web3 import Web3
@@ -47,6 +47,7 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
47
47
  )
48
48
  from prediction_market_agent_tooling.markets.omen.omen_contracts import (
49
49
  OMEN_DEFAULT_MARKET_FEE_PERC,
50
+ REALITY_DEFAULT_FINALIZATION_TIMEOUT,
50
51
  Arbitrator,
51
52
  OmenConditionalTokenContract,
52
53
  OmenFixedProductMarketMakerContract,
@@ -69,6 +70,7 @@ from prediction_market_agent_tooling.tools.contract import (
69
70
  )
70
71
  from prediction_market_agent_tooling.tools.hexbytes_custom import HexBytes
71
72
  from prediction_market_agent_tooling.tools.utils import (
73
+ DatetimeUTC,
72
74
  calculate_sell_amount_in_collateral,
73
75
  check_not_none,
74
76
  )
@@ -96,9 +98,9 @@ class OmenAgentMarket(AgentMarket):
96
98
  collateral_token_contract_address_checksummed: ChecksumAddress
97
99
  market_maker_contract_address_checksummed: ChecksumAddress
98
100
  condition: Condition
99
- finalized_time: datetime | None
100
- created_time: datetime
101
- close_time: datetime
101
+ finalized_time: DatetimeUTC | None
102
+ created_time: DatetimeUTC
103
+ close_time: DatetimeUTC
102
104
  fee: float # proportion, from 0 to 1
103
105
 
104
106
  _binary_market_p_yes_history: list[Probability] | None = None
@@ -362,7 +364,7 @@ class OmenAgentMarket(AgentMarket):
362
364
  limit: int,
363
365
  sort_by: SortBy,
364
366
  filter_by: FilterBy = FilterBy.OPEN,
365
- created_after: t.Optional[datetime] = None,
367
+ created_after: t.Optional[DatetimeUTC] = None,
366
368
  excluded_questions: set[str] | None = None,
367
369
  ) -> t.Sequence["OmenAgentMarket"]:
368
370
  return [
@@ -386,7 +388,7 @@ class OmenAgentMarket(AgentMarket):
386
388
 
387
389
  @staticmethod
388
390
  def get_bets_made_since(
389
- better_address: ChecksumAddress, start_time: datetime
391
+ better_address: ChecksumAddress, start_time: DatetimeUTC
390
392
  ) -> list[Bet]:
391
393
  bets = OmenSubgraphHandler().get_bets(
392
394
  better_address=better_address, start_time=start_time
@@ -396,7 +398,9 @@ class OmenAgentMarket(AgentMarket):
396
398
 
397
399
  @staticmethod
398
400
  def get_resolved_bets_made_since(
399
- better_address: ChecksumAddress, start_time: datetime, end_time: datetime | None
401
+ better_address: ChecksumAddress,
402
+ start_time: DatetimeUTC,
403
+ end_time: DatetimeUTC | None,
400
404
  ) -> list[ResolvedBet]:
401
405
  subgraph_handler = OmenSubgraphHandler()
402
406
  bets = subgraph_handler.get_resolved_bets_with_valid_answer(
@@ -835,12 +839,12 @@ def omen_create_market_tx(
835
839
  api_keys: APIKeys,
836
840
  initial_funds: xDai,
837
841
  question: str,
838
- closing_time: datetime,
842
+ closing_time: DatetimeUTC,
839
843
  category: str,
840
844
  language: str,
841
845
  outcomes: list[str],
842
846
  auto_deposit: bool,
843
- finalization_timeout: timedelta = timedelta(days=1),
847
+ finalization_timeout: timedelta = REALITY_DEFAULT_FINALIZATION_TIMEOUT,
844
848
  fee_perc: float = OMEN_DEFAULT_MARKET_FEE_PERC,
845
849
  distribution_hint: list[OmenOutcomeToken] | None = None,
846
850
  collateral_token_address: ChecksumAddress = WrappedxDaiContract().address,
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import random
3
3
  import typing as t
4
- from datetime import datetime, timedelta
4
+ from datetime import timedelta
5
5
  from enum import Enum
6
6
 
7
7
  from web3 import Web3
@@ -40,6 +40,7 @@ from prediction_market_agent_tooling.tools.contract import (
40
40
  init_collateral_token_contract,
41
41
  to_gnosis_chain_contract,
42
42
  )
43
+ from prediction_market_agent_tooling.tools.utils import DatetimeUTC
43
44
  from prediction_market_agent_tooling.tools.web3_utils import (
44
45
  ZERO_BYTES,
45
46
  byte32_to_ipfscidv0,
@@ -431,6 +432,7 @@ class sDaiContract(ContractERC4626OnGnosisChain):
431
432
 
432
433
 
433
434
  OMEN_DEFAULT_MARKET_FEE_PERC = 0.02 # 2% fee from the buying shares amount.
435
+ REALITY_DEFAULT_FINALIZATION_TIMEOUT = timedelta(days=3)
434
436
 
435
437
 
436
438
  class OmenFixedProductMarketMakerFactoryContract(ContractOnGnosisChain):
@@ -574,7 +576,7 @@ class OmenRealitioContract(ContractOnGnosisChain):
574
576
  outcomes: list[str],
575
577
  language: str,
576
578
  arbitrator: Arbitrator,
577
- opening: datetime,
579
+ opening: DatetimeUTC,
578
580
  timeout: timedelta,
579
581
  nonce: int | None = None,
580
582
  tx_params: t.Optional[TxParams] = None,
@@ -1,5 +1,3 @@
1
- from datetime import datetime
2
-
3
1
  from web3 import Web3
4
2
 
5
3
  from prediction_market_agent_tooling.config import APIKeys
@@ -33,6 +31,7 @@ from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
33
31
  from prediction_market_agent_tooling.markets.polymarket.utils import (
34
32
  find_resolution_on_polymarket,
35
33
  )
34
+ from prediction_market_agent_tooling.tools.utils import utcnow
36
35
  from prediction_market_agent_tooling.tools.web3_utils import ZERO_BYTES, xdai_to_wei
37
36
 
38
37
 
@@ -131,7 +130,7 @@ def finalize_markets(
131
130
  logger.info(
132
131
  f"[{idx+1} / {len(markets_with_resolutions)}] Looking into {market.url=} {market.question_title=}"
133
132
  )
134
- closed_before_days = (datetime.now() - market.close_time).days
133
+ closed_before_days = (utcnow() - market.close_time).days
135
134
 
136
135
  if resolution is None:
137
136
  if closed_before_days > wait_n_days_before_invalid:
@@ -240,7 +239,7 @@ def omen_resolve_market_tx(
240
239
  web3: Web3 | None = None,
241
240
  ) -> None:
242
241
  """
243
- Market can be resolved 24h after last answer was submitted via `omen_submit_answer_market_tx`.
242
+ Market can be resolved after the answer if finalized on Reality.
244
243
  """
245
244
  oracle_contract = OmenOracleContract()
246
245
  oracle_contract.resolve(
@@ -1,6 +1,5 @@
1
1
  import sys
2
2
  import typing as t
3
- from datetime import datetime
4
3
 
5
4
  import requests
6
5
  import tenacity
@@ -35,7 +34,11 @@ from prediction_market_agent_tooling.markets.omen.omen_contracts import (
35
34
  sDaiContract,
36
35
  )
37
36
  from prediction_market_agent_tooling.tools.singleton import SingletonMeta
38
- from prediction_market_agent_tooling.tools.utils import to_int_timestamp, utcnow
37
+ from prediction_market_agent_tooling.tools.utils import (
38
+ DatetimeUTC,
39
+ to_int_timestamp,
40
+ utcnow,
41
+ )
39
42
  from prediction_market_agent_tooling.tools.web3_utils import (
40
43
  ZERO_BYTES,
41
44
  byte32_to_ipfscidv0,
@@ -213,11 +216,11 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
213
216
  creator: t.Optional[HexAddress] = None,
214
217
  creator_in: t.Optional[t.Sequence[HexAddress]] = None,
215
218
  outcomes: list[str] = OMEN_BINARY_MARKET_OUTCOMES,
216
- created_after: t.Optional[datetime] = None,
217
- opened_before: t.Optional[datetime] = None,
218
- opened_after: t.Optional[datetime] = None,
219
- finalized_before: t.Optional[datetime] = None,
220
- finalized_after: t.Optional[datetime] = None,
219
+ created_after: t.Optional[DatetimeUTC] = None,
220
+ opened_before: t.Optional[DatetimeUTC] = None,
221
+ opened_after: t.Optional[DatetimeUTC] = None,
222
+ finalized_before: t.Optional[DatetimeUTC] = None,
223
+ finalized_after: t.Optional[DatetimeUTC] = None,
221
224
  finalized: bool | None = None,
222
225
  resolved: bool | None = None,
223
226
  liquidity_bigger_than: Wei | None = None,
@@ -319,6 +322,16 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
319
322
  sort_by_field = (
320
323
  self.trades_subgraph.FixedProductMarketMaker.openingTimestamp
321
324
  )
325
+ case SortBy.HIGHEST_LIQUIDITY:
326
+ sort_direction = "desc"
327
+ sort_by_field = (
328
+ self.trades_subgraph.FixedProductMarketMaker.liquidityMeasure
329
+ )
330
+ case SortBy.LOWEST_LIQUIDITY:
331
+ sort_direction = "asc"
332
+ sort_by_field = (
333
+ self.trades_subgraph.FixedProductMarketMaker.liquidityMeasure
334
+ )
322
335
  case SortBy.NONE:
323
336
  sort_direction = None
324
337
  sort_by_field = None
@@ -334,7 +347,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
334
347
  filter_by: FilterBy,
335
348
  sort_by: SortBy,
336
349
  # Additional filters, these can not be modified by the enums above.
337
- created_after: datetime | None = None,
350
+ created_after: DatetimeUTC | None = None,
338
351
  excluded_questions: set[str] | None = None, # question titles
339
352
  collateral_token_address_in: (
340
353
  tuple[ChecksumAddress, ...] | None
@@ -347,7 +360,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
347
360
  # These values need to be set according to the filter_by value, so they can not be passed as arguments.
348
361
  finalized: bool | None = None
349
362
  resolved: bool | None = None
350
- opened_after: datetime | None = None
363
+ opened_after: DatetimeUTC | None = None
351
364
  liquidity_bigger_than: Wei | None = None
352
365
 
353
366
  if filter_by == FilterBy.RESOLVED:
@@ -383,11 +396,11 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
383
396
  def get_omen_binary_markets(
384
397
  self,
385
398
  limit: t.Optional[int],
386
- created_after: t.Optional[datetime] = None,
387
- opened_before: t.Optional[datetime] = None,
388
- opened_after: t.Optional[datetime] = None,
389
- finalized_before: t.Optional[datetime] = None,
390
- finalized_after: t.Optional[datetime] = None,
399
+ created_after: t.Optional[DatetimeUTC] = None,
400
+ opened_before: t.Optional[DatetimeUTC] = None,
401
+ opened_after: t.Optional[DatetimeUTC] = None,
402
+ finalized_before: t.Optional[DatetimeUTC] = None,
403
+ finalized_after: t.Optional[DatetimeUTC] = None,
391
404
  finalized: bool | None = None,
392
405
  resolved: bool | None = None,
393
406
  creator: t.Optional[HexAddress] = None,
@@ -544,12 +557,12 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
544
557
  def get_trades(
545
558
  self,
546
559
  better_address: ChecksumAddress | None = None,
547
- start_time: datetime | None = None,
548
- end_time: t.Optional[datetime] = None,
560
+ start_time: DatetimeUTC | None = None,
561
+ end_time: t.Optional[DatetimeUTC] = None,
549
562
  market_id: t.Optional[ChecksumAddress] = None,
550
563
  filter_by_answer_finalized_not_null: bool = False,
551
564
  type_: t.Literal["Buy", "Sell"] | None = None,
552
- market_opening_after: datetime | None = None,
565
+ market_opening_after: DatetimeUTC | None = None,
553
566
  collateral_amount_more_than: Wei | None = None,
554
567
  ) -> list[OmenBet]:
555
568
  if not end_time:
@@ -587,11 +600,11 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
587
600
  def get_bets(
588
601
  self,
589
602
  better_address: ChecksumAddress | None = None,
590
- start_time: datetime | None = None,
591
- end_time: t.Optional[datetime] = None,
603
+ start_time: DatetimeUTC | None = None,
604
+ end_time: t.Optional[DatetimeUTC] = None,
592
605
  market_id: t.Optional[ChecksumAddress] = None,
593
606
  filter_by_answer_finalized_not_null: bool = False,
594
- market_opening_after: datetime | None = None,
607
+ market_opening_after: DatetimeUTC | None = None,
595
608
  collateral_amount_more_than: Wei | None = None,
596
609
  ) -> list[OmenBet]:
597
610
  return self.get_trades(
@@ -608,8 +621,8 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
608
621
  def get_resolved_bets(
609
622
  self,
610
623
  better_address: ChecksumAddress,
611
- start_time: datetime,
612
- end_time: t.Optional[datetime] = None,
624
+ start_time: DatetimeUTC,
625
+ end_time: t.Optional[DatetimeUTC] = None,
613
626
  market_id: t.Optional[ChecksumAddress] = None,
614
627
  ) -> list[OmenBet]:
615
628
  omen_bets = self.get_bets(
@@ -624,8 +637,8 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
624
637
  def get_resolved_bets_with_valid_answer(
625
638
  self,
626
639
  better_address: ChecksumAddress,
627
- start_time: datetime,
628
- end_time: t.Optional[datetime] = None,
640
+ start_time: DatetimeUTC,
641
+ end_time: t.Optional[DatetimeUTC] = None,
629
642
  market_id: t.Optional[ChecksumAddress] = None,
630
643
  ) -> list[OmenBet]:
631
644
  bets = self.get_resolved_bets(
@@ -640,9 +653,9 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
640
653
  def get_reality_question_filters(
641
654
  user: HexAddress | None = None,
642
655
  claimed: bool | None = None,
643
- current_answer_before: datetime | None = None,
644
- finalized_before: datetime | None = None,
645
- finalized_after: datetime | None = None,
656
+ current_answer_before: DatetimeUTC | None = None,
657
+ finalized_before: DatetimeUTC | None = None,
658
+ finalized_after: DatetimeUTC | None = None,
646
659
  id_in: list[str] | None = None,
647
660
  question_id: HexBytes | None = None,
648
661
  question_id_in: list[HexBytes] | None = None,
@@ -689,9 +702,9 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
689
702
  limit: int | None,
690
703
  user: HexAddress | None = None,
691
704
  claimed: bool | None = None,
692
- current_answer_before: datetime | None = None,
693
- finalized_before: datetime | None = None,
694
- finalized_after: datetime | None = None,
705
+ current_answer_before: DatetimeUTC | None = None,
706
+ finalized_before: DatetimeUTC | None = None,
707
+ finalized_after: DatetimeUTC | None = None,
695
708
  id_in: list[str] | None = None,
696
709
  question_id_in: list[HexBytes] | None = None,
697
710
  ) -> list[RealityQuestion]:
@@ -734,9 +747,9 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
734
747
  user: HexAddress | None = None,
735
748
  question_id: HexBytes | None = None,
736
749
  question_claimed: bool | None = None,
737
- question_finalized_before: datetime | None = None,
738
- question_finalized_after: datetime | None = None,
739
- question_current_answer_before: datetime | None = None,
750
+ question_finalized_before: DatetimeUTC | None = None,
751
+ question_finalized_after: DatetimeUTC | None = None,
752
+ question_current_answer_before: DatetimeUTC | None = None,
740
753
  question_id_in: list[HexBytes] | None = None,
741
754
  ) -> list[RealityResponse]:
742
755
  where_stms: dict[str, t.Any] = {}
@@ -2,8 +2,8 @@ import typing as t
2
2
 
3
3
  import requests
4
4
  import tenacity
5
- from loguru import logger
6
5
 
6
+ from prediction_market_agent_tooling.loggers import logger
7
7
  from prediction_market_agent_tooling.markets.polymarket.data_models import (
8
8
  POLYMARKET_FALSE_OUTCOME,
9
9
  POLYMARKET_TRUE_OUTCOME,
@@ -1,5 +1,3 @@
1
- from datetime import datetime
2
-
3
1
  from pydantic import BaseModel
4
2
 
5
3
  from prediction_market_agent_tooling.gtypes import USDC, Probability, usdc_type
@@ -10,13 +8,14 @@ from prediction_market_agent_tooling.markets.polymarket.data_models_web import (
10
8
  PolymarketFullMarket,
11
9
  construct_polymarket_url,
12
10
  )
11
+ from prediction_market_agent_tooling.tools.utils import DatetimeUTC
13
12
 
14
13
 
15
14
  class PolymarketRewards(BaseModel):
16
15
  min_size: int
17
16
  max_spread: float | None
18
- event_start_date: datetime | None = None
19
- event_end_date: datetime | None = None
17
+ event_start_date: DatetimeUTC | None = None
18
+ event_end_date: DatetimeUTC | None = None
20
19
  in_game_multiplier: int | None = None
21
20
  reward_epoch: int | None = None
22
21
 
@@ -39,8 +38,8 @@ class PolymarketMarket(BaseModel):
39
38
  question: str
40
39
  description: str
41
40
  market_slug: str
42
- end_date_iso: datetime | None
43
- game_start_time: datetime | None
41
+ end_date_iso: DatetimeUTC | None
42
+ game_start_time: DatetimeUTC | None
44
43
  seconds_delay: int
45
44
  fpmm: str
46
45
  maker_base_fee: int
@@ -7,7 +7,6 @@ These models are based on what Polymarket's website returns in the response, and
7
7
 
8
8
  import json
9
9
  import typing as t
10
- from datetime import datetime
11
10
 
12
11
  import requests
13
12
  from pydantic import BaseModel, field_validator
@@ -15,6 +14,7 @@ from pydantic import BaseModel, field_validator
15
14
  from prediction_market_agent_tooling.gtypes import USDC, HexAddress
16
15
  from prediction_market_agent_tooling.loggers import logger
17
16
  from prediction_market_agent_tooling.markets.data_models import Resolution
17
+ from prediction_market_agent_tooling.tools.utils import DatetimeUTC
18
18
 
19
19
  POLYMARKET_BASE_URL = "https://polymarket.com"
20
20
  POLYMARKET_TRUE_OUTCOME = "Yes"
@@ -38,7 +38,7 @@ class Event(BaseModel):
38
38
 
39
39
 
40
40
  class Event1(BaseModel):
41
- startDate: datetime | None = None
41
+ startDate: DatetimeUTC | None = None
42
42
  slug: str
43
43
 
44
44
 
@@ -60,7 +60,7 @@ class Market1(BaseModel):
60
60
  class ResolutionData(BaseModel):
61
61
  id: str
62
62
  author: str
63
- lastUpdateTimestamp: datetime
63
+ lastUpdateTimestamp: int
64
64
  status: str
65
65
  wasDisputed: bool
66
66
  price: str
@@ -79,13 +79,13 @@ class Market(BaseModel):
79
79
  slug: str
80
80
  twitterCardImage: t.Any | None = None
81
81
  resolutionSource: str | None = None
82
- endDate: datetime
82
+ endDate: DatetimeUTC
83
83
  category: t.Any | None = None
84
84
  ammType: t.Any | None = None
85
85
  description: str
86
86
  liquidity: str | None = None
87
- startDate: datetime | None = None
88
- createdAt: datetime
87
+ startDate: DatetimeUTC | None = None
88
+ createdAt: DatetimeUTC
89
89
  xAxisValue: t.Any | None = None
90
90
  yAxisValue: t.Any | None = None
91
91
  denominationToken: t.Any | None = None
@@ -106,7 +106,7 @@ class Market(BaseModel):
106
106
  upperBoundDate: t.Any | None = None
107
107
  closed: bool
108
108
  marketMakerAddress: HexAddress
109
- closedTime: datetime | None = None
109
+ closedTime: DatetimeUTC | None = None
110
110
  wideFormat: bool | None = None
111
111
  new: bool | None = None
112
112
  sentDiscord: t.Any | None = None
@@ -129,9 +129,9 @@ class Market(BaseModel):
129
129
  curationOrder: t.Any | None = None
130
130
  volumeNum: USDC | None = None
131
131
  liquidityNum: float | None = None
132
- endDateIso: datetime | None = None
133
- startDateIso: datetime | None = None
134
- umaEndDateIso: datetime | None = None
132
+ endDateIso: DatetimeUTC | None = None
133
+ startDateIso: DatetimeUTC | None = None
134
+ umaEndDateIso: DatetimeUTC | None = None
135
135
  commentsEnabled: bool | None = None
136
136
  disqusThread: t.Any | None = None
137
137
  gameStartTime: t.Any | None = None
@@ -236,8 +236,8 @@ class PolymarketFullMarket(BaseModel):
236
236
  description: str
237
237
  commentCount: int | None = None
238
238
  resolutionSource: str | None = None
239
- startDate: datetime | None = None
240
- endDate: datetime
239
+ startDate: DatetimeUTC | None = None
240
+ endDate: DatetimeUTC
241
241
  image: str | None = None
242
242
  icon: str | None = None
243
243
  featuredImage: str | None = None
@@ -253,10 +253,10 @@ class PolymarketFullMarket(BaseModel):
253
253
  competitive: float | None = None
254
254
  openInterest: int | None = None
255
255
  sortBy: str | None = None
256
- createdAt: datetime
256
+ createdAt: DatetimeUTC
257
257
  commentsEnabled: bool | None = None
258
258
  disqusThread: t.Any | None = None
259
- updatedAt: datetime
259
+ updatedAt: DatetimeUTC
260
260
  enableOrderBook: bool | None = None
261
261
  liquidityAmm: float | None = None
262
262
  liquidityClob: float | None = None