prediction-market-agent-tooling 0.56.0.dev1863__tar.gz → 0.56.1__tar.gz

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 (107) hide show
  1. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/PKG-INFO +1 -1
  2. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/deploy/agent.py +23 -12
  3. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/jobs/jobs_models.py +27 -2
  4. prediction_market_agent_tooling-0.56.1/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +140 -0
  5. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/agent_market.py +8 -2
  6. prediction_market_agent_tooling-0.56.1/prediction_market_agent_tooling/markets/base_subgraph_handler.py +51 -0
  7. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/markets.py +12 -0
  8. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +1 -1
  9. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/omen/data_models.py +11 -2
  10. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/omen/omen.py +16 -9
  11. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +29 -51
  12. prediction_market_agent_tooling-0.56.1/prediction_market_agent_tooling/markets/seer/data_models.py +27 -0
  13. prediction_market_agent_tooling-0.56.1/prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +142 -0
  14. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/caches/db_cache.py +30 -62
  15. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/is_invalid.py +1 -1
  16. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/utils.py +2 -0
  17. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/pyproject.toml +1 -1
  18. prediction_market_agent_tooling-0.56.0.dev1863/prediction_market_agent_tooling/jobs/jobs.py +0 -45
  19. prediction_market_agent_tooling-0.56.0.dev1863/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +0 -114
  20. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/LICENSE +0 -0
  21. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/README.md +0 -0
  22. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +0 -0
  23. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
  24. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  25. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
  26. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_agentresultmapping.abi.json +0 -0
  27. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  28. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  29. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  30. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  31. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  32. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  33. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  34. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  35. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
  36. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  37. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  38. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
  39. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  40. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/config.py +0 -0
  41. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  42. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/deploy/betting_strategy.py +0 -0
  43. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  44. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  45. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  46. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  47. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/deploy/trade_interval.py +0 -0
  48. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/gtypes.py +0 -0
  49. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
  50. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/loggers.py +0 -0
  51. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  52. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/data_models.py +0 -0
  53. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  54. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  55. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  56. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  57. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  58. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/market_fees.py +0 -0
  59. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
  60. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
  61. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  62. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
  63. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
  64. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
  65. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
  66. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
  67. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
  68. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  69. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/monitor/markets/manifold.py +0 -0
  70. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/monitor/markets/metaculus.py +0 -0
  71. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/monitor/markets/omen.py +0 -0
  72. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -0
  73. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/monitor/monitor.py +0 -0
  74. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/monitor/monitor_app.py +0 -0
  75. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/monitor/monitor_settings.py +0 -0
  76. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/py.typed +0 -0
  77. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/balances.py +0 -0
  78. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
  79. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -0
  80. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -0
  81. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  82. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +0 -0
  83. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/caches/inmemory_cache.py +0 -0
  84. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/contract.py +0 -0
  85. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/costs.py +0 -0
  86. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/datetime_utc.py +0 -0
  87. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/gnosis_rpc.py +0 -0
  88. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/google.py +0 -0
  89. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
  90. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/httpx_cached_client.py +0 -0
  91. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  92. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  93. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +0 -0
  94. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
  95. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
  96. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +0 -0
  97. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
  98. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  99. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py +0 -0
  100. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py +0 -0
  101. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py +0 -0
  102. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/safe.py +0 -0
  103. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/singleton.py +0 -0
  104. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  105. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/tavily/tavily_models.py +0 -0
  106. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/tavily/tavily_search.py +0 -0
  107. {prediction_market_agent_tooling-0.56.0.dev1863 → prediction_market_agent_tooling-0.56.1}/prediction_market_agent_tooling/tools/web3_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.56.0.dev1863
3
+ Version: 0.56.1
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -153,10 +153,10 @@ class DeployableAgent:
153
153
  input=input,
154
154
  output=output,
155
155
  user_id=user_id or getpass.getuser(),
156
- session_id=session_id
157
- or self.session_id, # All traces within a single run execution will be grouped under a single session.
158
- version=version
159
- or APIKeys().LANGFUSE_DEPLOYMENT_VERSION, # Optionally, mark the current deployment with version (e.g. add git commit hash during docker building).
156
+ session_id=session_id or self.session_id,
157
+ # All traces within a single run execution will be grouped under a single session.
158
+ version=version or APIKeys().LANGFUSE_DEPLOYMENT_VERSION,
159
+ # Optionally, mark the current deployment with version (e.g. add git commit hash during docker building).
160
160
  release=release,
161
161
  metadata=metadata,
162
162
  tags=tags,
@@ -342,6 +342,10 @@ class DeployablePredictionAgent(DeployableAgent):
342
342
  ]
343
343
  )
344
344
 
345
+ @property
346
+ def agent_name(self) -> str:
347
+ return self.__class__.__name__
348
+
345
349
  def check_min_required_balance_to_operate(self, market_type: MarketType) -> None:
346
350
  api_keys = APIKeys()
347
351
 
@@ -444,7 +448,9 @@ class DeployablePredictionAgent(DeployableAgent):
444
448
  ) -> None:
445
449
  keys = APIKeys()
446
450
  if self.store_prediction:
447
- market.store_prediction(processed_market=processed_market, keys=keys)
451
+ market.store_prediction(
452
+ processed_market=processed_market, keys=keys, agent_name=self.agent_name
453
+ )
448
454
  else:
449
455
  logger.info(
450
456
  f"Prediction {processed_market} not stored because {self.store_prediction=}."
@@ -519,7 +525,6 @@ class DeployableTraderAgent(DeployablePredictionAgent):
519
525
  def initialize_langfuse(self) -> None:
520
526
  super().initialize_langfuse()
521
527
  # Auto-observe all the methods where it makes sense, so that subclassses don't need to do it manually.
522
- self.get_betting_strategy = observe()(self.get_betting_strategy) # type: ignore[method-assign]
523
528
  self.build_trades = observe()(self.build_trades) # type: ignore[method-assign]
524
529
 
525
530
  def check_min_required_balance_to_trade(self, market: AgentMarket) -> None:
@@ -555,16 +560,18 @@ class DeployableTraderAgent(DeployablePredictionAgent):
555
560
  BettingStrategy.assert_trades_currency_match_markets(market, trades)
556
561
  return trades
557
562
 
563
+ def before_process_market(
564
+ self, market_type: MarketType, market: AgentMarket
565
+ ) -> None:
566
+ super().before_process_market(market_type, market)
567
+ self.check_min_required_balance_to_trade(market)
568
+
558
569
  def process_market(
559
570
  self,
560
571
  market_type: MarketType,
561
572
  market: AgentMarket,
562
573
  verify_market: bool = True,
563
574
  ) -> ProcessedTradedMarket | None:
564
- self.check_min_required_balance_to_trade(
565
- market
566
- ) # Do this as part of `process_market` because it observes some methods --> To keep everything traced under the `process_market`.
567
-
568
575
  processed_market = super().process_market(market_type, market, verify_market)
569
576
  if processed_market is None:
570
577
  return None
@@ -612,10 +619,14 @@ class DeployableTraderAgent(DeployablePredictionAgent):
612
619
  processed_market: ProcessedMarket | None,
613
620
  ) -> None:
614
621
  api_keys = APIKeys()
615
- super().after_process_market(market_type, market, processed_market)
622
+ super().after_process_market(
623
+ market_type,
624
+ market,
625
+ processed_market,
626
+ )
616
627
  if isinstance(processed_market, ProcessedTradedMarket):
617
628
  if self.store_trades:
618
- market.store_trades(processed_market, api_keys)
629
+ market.store_trades(processed_market, api_keys, self.agent_name)
619
630
  else:
620
631
  logger.info(
621
632
  f"Trades {processed_market.trades} not stored because {self.store_trades=}."
@@ -3,7 +3,12 @@ from abc import ABC, abstractmethod
3
3
 
4
4
  from pydantic import BaseModel
5
5
 
6
- from prediction_market_agent_tooling.markets.agent_market import AgentMarket
6
+ from prediction_market_agent_tooling.deploy.betting_strategy import ProbabilisticAnswer
7
+ from prediction_market_agent_tooling.gtypes import Probability
8
+ from prediction_market_agent_tooling.markets.agent_market import (
9
+ AgentMarket,
10
+ ProcessedTradedMarket,
11
+ )
7
12
  from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
8
13
  FilterBy,
9
14
  SortBy,
@@ -39,10 +44,24 @@ class JobAgentMarket(AgentMarket, ABC):
39
44
  @classmethod
40
45
  @abstractmethod
41
46
  def get_jobs(
42
- cls, limit: int | None, filter_by: FilterBy, sort_by: SortBy
47
+ cls,
48
+ limit: int | None,
49
+ filter_by: FilterBy = FilterBy.OPEN,
50
+ sort_by: SortBy = SortBy.CLOSING_SOONEST,
43
51
  ) -> t.Sequence["JobAgentMarket"]:
44
52
  """Get all available jobs."""
45
53
 
54
+ @staticmethod
55
+ @abstractmethod
56
+ def get_job(id: str) -> "JobAgentMarket":
57
+ """Get a single job by its id."""
58
+
59
+ @abstractmethod
60
+ def submit_job_result(
61
+ self, agent_name: str, max_bond: float, result: str
62
+ ) -> ProcessedTradedMarket:
63
+ """Submit the completed result for this job."""
64
+
46
65
  def to_simple_job(self, max_bond: float) -> SimpleJob:
47
66
  return SimpleJob(
48
67
  id=self.id,
@@ -51,3 +70,9 @@ class JobAgentMarket(AgentMarket, ABC):
51
70
  currency=self.currency.value,
52
71
  deadline=self.deadline,
53
72
  )
73
+
74
+ def get_job_answer(self, result: str) -> ProbabilisticAnswer:
75
+ # Just return 100% yes with 100% confidence, because we assume the job is completed correctly.
76
+ return ProbabilisticAnswer(
77
+ p_yes=Probability(1.0), confidence=1.0, reasoning=result
78
+ )
@@ -0,0 +1,140 @@
1
+ import typing as t
2
+
3
+ from prediction_market_agent_tooling.config import APIKeys
4
+ from prediction_market_agent_tooling.deploy.betting_strategy import (
5
+ Currency,
6
+ KellyBettingStrategy,
7
+ TradeType,
8
+ )
9
+ from prediction_market_agent_tooling.jobs.jobs_models import JobAgentMarket
10
+ from prediction_market_agent_tooling.markets.agent_market import ProcessedTradedMarket
11
+ from prediction_market_agent_tooling.markets.data_models import PlacedTrade, Trade
12
+ from prediction_market_agent_tooling.markets.omen.omen import (
13
+ BetAmount,
14
+ OmenAgentMarket,
15
+ OmenMarket,
16
+ )
17
+ from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
18
+ FilterBy,
19
+ OmenSubgraphHandler,
20
+ SortBy,
21
+ )
22
+ from prediction_market_agent_tooling.tools.utils import DatetimeUTC
23
+
24
+
25
+ class OmenJobAgentMarket(OmenAgentMarket, JobAgentMarket):
26
+ CATEGORY = "jobs"
27
+
28
+ @property
29
+ def job(self) -> str:
30
+ """Omen market's have only question, so that's where the job description is."""
31
+ return self.question
32
+
33
+ @property
34
+ def deadline(self) -> DatetimeUTC:
35
+ return self.close_time
36
+
37
+ def get_reward(self, max_bond: float) -> float:
38
+ trade = self.get_job_trade(
39
+ max_bond,
40
+ result="", # Pass empty result, as we are computing only potential reward at this point.
41
+ )
42
+ reward = (
43
+ self.get_buy_token_amount(
44
+ bet_amount=BetAmount(
45
+ amount=trade.amount.amount, currency=trade.amount.currency
46
+ ),
47
+ direction=trade.outcome,
48
+ ).amount
49
+ - trade.amount.amount
50
+ )
51
+ return reward
52
+
53
+ @classmethod
54
+ def get_jobs(
55
+ cls,
56
+ limit: int | None,
57
+ filter_by: FilterBy = FilterBy.OPEN,
58
+ sort_by: SortBy = SortBy.CLOSING_SOONEST,
59
+ ) -> t.Sequence["OmenJobAgentMarket"]:
60
+ markets = OmenSubgraphHandler().get_omen_binary_markets_simple(
61
+ limit=limit,
62
+ filter_by=filter_by,
63
+ sort_by=sort_by,
64
+ category=cls.CATEGORY,
65
+ )
66
+ return [OmenJobAgentMarket.from_omen_market(market) for market in markets]
67
+
68
+ @staticmethod
69
+ def get_job(id: str) -> "OmenJobAgentMarket":
70
+ return OmenJobAgentMarket.from_omen_agent_market(
71
+ OmenJobAgentMarket.get_binary_market(id=id)
72
+ )
73
+
74
+ def submit_job_result(
75
+ self, agent_name: str, max_bond: float, result: str
76
+ ) -> ProcessedTradedMarket:
77
+ if not APIKeys().enable_ipfs_upload:
78
+ raise RuntimeError(
79
+ f"ENABLE_IPFS_UPLOAD must be set to True to upload job results."
80
+ )
81
+
82
+ trade = self.get_job_trade(max_bond, result)
83
+ buy_id = self.buy_tokens(outcome=trade.outcome, amount=trade.amount)
84
+
85
+ processed_traded_market = ProcessedTradedMarket(
86
+ answer=self.get_job_answer(result),
87
+ trades=[PlacedTrade.from_trade(trade, id=buy_id)],
88
+ )
89
+
90
+ keys = APIKeys()
91
+ self.store_trades(processed_traded_market, keys, agent_name)
92
+
93
+ return processed_traded_market
94
+
95
+ def get_job_trade(self, max_bond: float, result: str) -> Trade:
96
+ # 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.
97
+ strategy = KellyBettingStrategy(max_bet_amount=max_bond)
98
+ required_trades = strategy.calculate_trades(
99
+ existing_position=None,
100
+ answer=self.get_job_answer(result),
101
+ market=self,
102
+ )
103
+ assert (
104
+ len(required_trades) == 1
105
+ ), f"Shouldn't process same job twice: {required_trades}"
106
+ trade = required_trades[0]
107
+ assert trade.trade_type == TradeType.BUY, "Should only buy on job markets."
108
+ assert trade.outcome, "Should buy only YES on job markets."
109
+ assert (
110
+ trade.amount.currency == Currency.xDai
111
+ ), "Should work only on real-money markets."
112
+ return required_trades[0]
113
+
114
+ @staticmethod
115
+ def from_omen_market(market: OmenMarket) -> "OmenJobAgentMarket":
116
+ return OmenJobAgentMarket.from_omen_agent_market(
117
+ OmenAgentMarket.from_data_model(market)
118
+ )
119
+
120
+ @staticmethod
121
+ def from_omen_agent_market(market: OmenAgentMarket) -> "OmenJobAgentMarket":
122
+ return OmenJobAgentMarket(
123
+ id=market.id,
124
+ question=market.question,
125
+ description=market.description,
126
+ outcomes=market.outcomes,
127
+ outcome_token_pool=market.outcome_token_pool,
128
+ resolution=market.resolution,
129
+ created_time=market.created_time,
130
+ close_time=market.close_time,
131
+ current_p_yes=market.current_p_yes,
132
+ url=market.url,
133
+ volume=market.volume,
134
+ creator=market.creator,
135
+ collateral_token_contract_address_checksummed=market.collateral_token_contract_address_checksummed,
136
+ market_maker_contract_address_checksummed=market.market_maker_contract_address_checksummed,
137
+ condition=market.condition,
138
+ finalized_time=market.finalized_time,
139
+ fees=market.fees,
140
+ )
@@ -231,7 +231,10 @@ class AgentMarket(BaseModel):
231
231
  raise NotImplementedError("Subclasses must implement this method")
232
232
 
233
233
  def store_prediction(
234
- self, processed_market: ProcessedMarket | None, keys: APIKeys
234
+ self,
235
+ processed_market: ProcessedMarket | None,
236
+ keys: APIKeys,
237
+ agent_name: str,
235
238
  ) -> None:
236
239
  """
237
240
  If market allows to upload predictions somewhere, implement it in this method.
@@ -239,7 +242,10 @@ class AgentMarket(BaseModel):
239
242
  raise NotImplementedError("Subclasses must implement this method")
240
243
 
241
244
  def store_trades(
242
- self, traded_market: ProcessedTradedMarket | None, keys: APIKeys
245
+ self,
246
+ traded_market: ProcessedTradedMarket | None,
247
+ keys: APIKeys,
248
+ agent_name: str,
243
249
  ) -> None:
244
250
  """
245
251
  If market allows to upload trades somewhere, implement it in this method.
@@ -0,0 +1,51 @@
1
+ import typing as t
2
+
3
+ import tenacity
4
+ from pydantic import BaseModel
5
+ from subgrounds import FieldPath, Subgrounds
6
+
7
+ from prediction_market_agent_tooling.config import APIKeys
8
+ from prediction_market_agent_tooling.loggers import logger
9
+ from prediction_market_agent_tooling.tools.singleton import SingletonMeta
10
+
11
+ T = t.TypeVar("T", bound=BaseModel)
12
+
13
+
14
+ class BaseSubgraphHandler(metaclass=SingletonMeta):
15
+ def __init__(self) -> None:
16
+ self.sg = Subgrounds()
17
+ # Patch methods to retry on failure.
18
+ self.sg.query_json = tenacity.retry(
19
+ stop=tenacity.stop_after_attempt(3),
20
+ wait=tenacity.wait_fixed(1),
21
+ after=lambda x: logger.debug(f"query_json failed, {x.attempt_number=}."),
22
+ )(self.sg.query_json)
23
+ self.sg.load_subgraph = tenacity.retry(
24
+ stop=tenacity.stop_after_attempt(3),
25
+ wait=tenacity.wait_fixed(1),
26
+ after=lambda x: logger.debug(f"load_subgraph failed, {x.attempt_number=}."),
27
+ )(self.sg.load_subgraph)
28
+
29
+ self.keys = APIKeys()
30
+
31
+ def _parse_items_from_json(
32
+ self, result: list[dict[str, t.Any]]
33
+ ) -> list[dict[str, t.Any]]:
34
+ """subgrounds return a weird key as a dict key"""
35
+ items = []
36
+ for result_chunk in result:
37
+ for k, v in result_chunk.items():
38
+ # subgrounds might pack all items as a list, indexed by a key, or pack it as a dictionary (if one single element)
39
+ if v is None:
40
+ continue
41
+ elif isinstance(v, dict):
42
+ items.extend([v])
43
+ else:
44
+ items.extend(v)
45
+ return items
46
+
47
+ def do_query(self, fields: list[FieldPath], pydantic_model: t.Type[T]) -> list[T]:
48
+ result = self.sg.query_json(fields)
49
+ items = self._parse_items_from_json(result)
50
+ models = [pydantic_model.model_validate(i) for i in items]
51
+ return models
@@ -3,6 +3,8 @@ from datetime import timedelta
3
3
  from enum import Enum
4
4
 
5
5
  from prediction_market_agent_tooling.config import APIKeys
6
+ from prediction_market_agent_tooling.jobs.jobs_models import JobAgentMarket
7
+ from prediction_market_agent_tooling.jobs.omen.omen_jobs import OmenJobAgentMarket
6
8
  from prediction_market_agent_tooling.markets.agent_market import (
7
9
  AgentMarket,
8
10
  FilterBy,
@@ -46,6 +48,12 @@ class MarketType(str, Enum):
46
48
  raise ValueError(f"Unknown market type: {self}")
47
49
  return MARKET_TYPE_TO_AGENT_MARKET[self]
48
50
 
51
+ @property
52
+ def job_class(self) -> type[JobAgentMarket]:
53
+ if self not in JOB_MARKET_TYPE_TO_JOB_AGENT_MARKET:
54
+ raise ValueError(f"Unknown market type: {self}")
55
+ return JOB_MARKET_TYPE_TO_JOB_AGENT_MARKET[self]
56
+
49
57
  @property
50
58
  def is_blockchain_market(self) -> bool:
51
59
  return self in [MarketType.OMEN, MarketType.POLYMARKET]
@@ -58,6 +66,10 @@ MARKET_TYPE_TO_AGENT_MARKET: dict[MarketType, type[AgentMarket]] = {
58
66
  MarketType.METACULUS: MetaculusAgentMarket,
59
67
  }
60
68
 
69
+ JOB_MARKET_TYPE_TO_JOB_AGENT_MARKET: dict[MarketType, type[JobAgentMarket]] = {
70
+ MarketType.OMEN: OmenJobAgentMarket,
71
+ }
72
+
61
73
 
62
74
  def get_binary_markets(
63
75
  limit: int,
@@ -107,7 +107,7 @@ class MetaculusAgentMarket(AgentMarket):
107
107
  return [MetaculusAgentMarket.from_data_model(q) for q in all_questions[:limit]]
108
108
 
109
109
  def store_prediction(
110
- self, processed_market: ProcessedMarket | None, keys: APIKeys
110
+ self, processed_market: ProcessedMarket | None, keys: APIKeys, agent_name: str
111
111
  ) -> None:
112
112
  if processed_market is not None:
113
113
  make_prediction(self.id, processed_market.answer.p_yes)
@@ -24,6 +24,7 @@ from prediction_market_agent_tooling.markets.data_models import (
24
24
  ResolvedBet,
25
25
  )
26
26
  from prediction_market_agent_tooling.tools.utils import (
27
+ BPS_CONSTANT,
27
28
  DatetimeUTC,
28
29
  check_not_none,
29
30
  should_not_happen,
@@ -502,7 +503,7 @@ class OmenBet(BaseModel):
502
503
  feeAmount: Wei
503
504
  outcomeIndex: int
504
505
  outcomeTokensTraded: Wei
505
- transactionHash: HexAddress
506
+ transactionHash: HexBytes
506
507
  fpmm: OmenMarket
507
508
 
508
509
  @property
@@ -785,6 +786,14 @@ class ContractPrediction(BaseModel):
785
786
  tx_hashes: list[HexBytes] = Field(..., alias="txHashes")
786
787
  estimated_probability_bps: int = Field(..., alias="estimatedProbabilityBps")
787
788
 
789
+ @property
790
+ def estimated_probability(self) -> Probability:
791
+ return Probability(self.estimated_probability_bps / BPS_CONSTANT)
792
+
793
+ @property
794
+ def boolean_outcome(self) -> bool:
795
+ return self.estimated_probability > 0.5
796
+
788
797
  @computed_field # type: ignore[prop-decorator] # Mypy issue: https://github.com/python/mypy/issues/14461
789
798
  @property
790
799
  def publisher_checksummed(self) -> ChecksumAddress:
@@ -798,7 +807,7 @@ class ContractPrediction(BaseModel):
798
807
 
799
808
  class IPFSAgentResult(BaseModel):
800
809
  reasoning: str
801
-
810
+ agent_name: str
802
811
  model_config = ConfigDict(
803
812
  extra="forbid",
804
813
  )
@@ -78,6 +78,7 @@ from prediction_market_agent_tooling.tools.contract import (
78
78
  from prediction_market_agent_tooling.tools.hexbytes_custom import HexBytes
79
79
  from prediction_market_agent_tooling.tools.ipfs.ipfs_handler import IPFSHandler
80
80
  from prediction_market_agent_tooling.tools.utils import (
81
+ BPS_CONSTANT,
81
82
  DatetimeUTC,
82
83
  calculate_sell_amount_in_collateral,
83
84
  check_not_none,
@@ -413,17 +414,21 @@ class OmenAgentMarket(AgentMarket):
413
414
  @staticmethod
414
415
  def verify_operational_balance(api_keys: APIKeys) -> bool:
415
416
  return get_total_balance(
416
- api_keys.public_key, # Use `public_key`, not `bet_from_address` because transaction costs are paid from the EOA wallet.
417
+ api_keys.public_key,
418
+ # Use `public_key`, not `bet_from_address` because transaction costs are paid from the EOA wallet.
417
419
  sum_wxdai=False,
418
420
  ) > xdai_type(0.001)
419
421
 
420
422
  def store_prediction(
421
- self, processed_market: ProcessedMarket | None, keys: APIKeys
423
+ self, processed_market: ProcessedMarket | None, keys: APIKeys, agent_name: str
422
424
  ) -> None:
423
425
  """On Omen, we have to store predictions along with trades, see `store_trades`."""
424
426
 
425
427
  def store_trades(
426
- self, traded_market: ProcessedTradedMarket | None, keys: APIKeys
428
+ self,
429
+ traded_market: ProcessedTradedMarket | None,
430
+ keys: APIKeys,
431
+ agent_name: str,
427
432
  ) -> None:
428
433
  if traded_market is None:
429
434
  logger.warning(f"No prediction for market {self.id}, not storing anything.")
@@ -437,7 +442,7 @@ class OmenAgentMarket(AgentMarket):
437
442
  if keys.enable_ipfs_upload:
438
443
  logger.info("Storing prediction on IPFS.")
439
444
  ipfs_hash = IPFSHandler(keys).store_agent_result(
440
- IPFSAgentResult(reasoning=reasoning)
445
+ IPFSAgentResult(reasoning=reasoning, agent_name=agent_name)
441
446
  )
442
447
  ipfs_hash_decoded = ipfscidv0_to_byte32(ipfs_hash)
443
448
 
@@ -448,7 +453,7 @@ class OmenAgentMarket(AgentMarket):
448
453
  publisher=keys.public_key,
449
454
  ipfs_hash=ipfs_hash_decoded,
450
455
  tx_hashes=tx_hashes,
451
- estimated_probability_bps=int(traded_market.answer.p_yes * 10000),
456
+ estimated_probability_bps=int(traded_market.answer.p_yes * BPS_CONSTANT),
452
457
  )
453
458
  tx_receipt = OmenAgentResultMappingContract().add_prediction(
454
459
  api_keys=keys,
@@ -1237,12 +1242,12 @@ def redeem_from_all_user_positions(
1237
1242
 
1238
1243
  if not conditional_token_contract.is_condition_resolved(condition_id):
1239
1244
  logger.info(
1240
- f"[{index+1} / {len(user_positions)}] Skipping redeem, {user_position.id=} isn't resolved yet."
1245
+ f"[{index + 1} / {len(user_positions)}] Skipping redeem, {user_position.id=} isn't resolved yet."
1241
1246
  )
1242
1247
  continue
1243
1248
 
1244
1249
  logger.info(
1245
- f"[{index+1} / {len(user_positions)}] Processing redeem from {user_position.id=}."
1250
+ f"[{index + 1} / {len(user_positions)}] Processing redeem from {user_position.id=}."
1246
1251
  )
1247
1252
 
1248
1253
  original_balances = get_balances(public_key, web3)
@@ -1263,9 +1268,11 @@ def redeem_from_all_user_positions(
1263
1268
  def get_binary_market_p_yes_history(market: OmenAgentMarket) -> list[Probability]:
1264
1269
  history: list[Probability] = []
1265
1270
  trades = sorted(
1266
- OmenSubgraphHandler().get_trades( # We need to look at price both after buying or selling, so get trades, not bets.
1271
+ OmenSubgraphHandler().get_trades(
1272
+ # We need to look at price both after buying or selling, so get trades, not bets.
1267
1273
  market_id=market.market_maker_contract_address_checksummed,
1268
- end_time=market.close_time, # Even after market is closed, there can be many `Sell` trades which will converge the probability to the true one.
1274
+ end_time=market.close_time,
1275
+ # Even after market is closed, there can be many `Sell` trades which will converge the probability to the true one.
1269
1276
  ),
1270
1277
  key=lambda x: x.creation_datetime,
1271
1278
  )