prediction-market-agent-tooling 0.67.4__tar.gz → 0.68.0__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 (136) hide show
  1. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/PKG-INFO +1 -1
  2. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/deploy/agent.py +2 -4
  3. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/deploy/betting_strategy.py +177 -49
  4. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +2 -2
  5. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/omen/data_models.py +6 -1
  6. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/omen/omen.py +43 -6
  7. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/seer/price_manager.py +68 -0
  8. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/seer/seer.py +11 -7
  9. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +2 -0
  10. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +2 -0
  11. prediction_market_agent_tooling-0.68.0/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +418 -0
  12. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +6 -1
  13. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +0 -3
  14. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/web3_utils.py +2 -0
  15. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/pyproject.toml +1 -1
  16. prediction_market_agent_tooling-0.67.4/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -150
  17. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/LICENSE +0 -0
  18. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/README.md +0 -0
  19. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/agentresultmapping.abi.json +0 -0
  20. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +0 -0
  21. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
  22. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/erc1155.abi.json +0 -0
  23. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  24. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
  25. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/erc721.abi.json +0 -0
  26. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/gvp2_settlement.abi.json +0 -0
  27. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  28. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  29. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  30. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  31. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  32. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  33. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  34. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  35. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/ownable.abi.json +0 -0
  36. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/ownable_erc721.abi.json +0 -0
  37. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
  38. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/seer_gnosis_router.abi.json +0 -0
  39. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/seer_market_factory.abi.json +0 -0
  40. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/abis/swapr_router.abi.json +0 -0
  41. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  42. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  43. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
  44. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  45. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/chains.py +0 -0
  46. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/config.py +0 -0
  47. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/data_download/langfuse_data_downloader.py +0 -0
  48. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  49. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  50. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  51. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  52. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  53. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/deploy/trade_interval.py +0 -0
  54. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/gtypes.py +0 -0
  55. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
  56. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/jobs/jobs_models.py +0 -0
  57. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/loggers.py +0 -0
  58. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/logprobs_parser.py +0 -0
  59. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/agent_market.py +0 -0
  60. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/base_subgraph_handler.py +0 -0
  61. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/blockchain_utils.py +0 -0
  62. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  63. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/data_models.py +0 -0
  64. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  65. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  66. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  67. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  68. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  69. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/market_fees.py +0 -0
  70. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/markets.py +0 -0
  71. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
  72. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
  73. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +0 -0
  74. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  75. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/omen/cow_contracts.py +0 -0
  76. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/omen/omen_constants.py +0 -0
  77. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
  78. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
  79. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +0 -0
  80. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
  81. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
  82. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
  83. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
  84. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/polymarket/polymarket_subgraph_handler.py +0 -0
  85. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  86. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/seer/data_models.py +0 -0
  87. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/seer/exceptions.py +0 -0
  88. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/seer/seer_contracts.py +0 -0
  89. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/markets/seer/swap_pool_handler.py +0 -0
  90. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/py.typed +0 -0
  91. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/_generic_value.py +0 -0
  92. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/balances.py +0 -0
  93. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  94. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/caches/db_cache.py +0 -0
  95. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/caches/inmemory_cache.py +0 -0
  96. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/caches/serializers.py +0 -0
  97. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/contract.py +0 -0
  98. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/costs.py +0 -0
  99. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/cow/cow_order.py +0 -0
  100. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/cow/models.py +0 -0
  101. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/cow/semaphore.py +0 -0
  102. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/custom_exceptions.py +0 -0
  103. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/datetime_utc.py +0 -0
  104. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/db/db_manager.py +0 -0
  105. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/google_utils.py +0 -0
  106. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
  107. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/httpx_cached_client.py +0 -0
  108. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  109. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  110. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +0 -0
  111. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/is_invalid.py +0 -0
  112. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
  113. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
  114. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
  115. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/omen/sell_positions.py +0 -0
  116. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  117. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/perplexity/perplexity_client.py +0 -0
  118. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/perplexity/perplexity_models.py +0 -0
  119. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/perplexity/perplexity_search.py +0 -0
  120. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py +0 -0
  121. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py +0 -0
  122. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py +0 -0
  123. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/rephrase.py +0 -0
  124. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/safe.py +0 -0
  125. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/singleton.py +0 -0
  126. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  127. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/tavily/tavily_models.py +0 -0
  128. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/tavily/tavily_search.py +0 -0
  129. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/tokens/auto_deposit.py +0 -0
  130. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +0 -0
  131. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/tokens/main_token.py +0 -0
  132. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/tokens/slippage.py +0 -0
  133. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/tokens/token_utils.py +0 -0
  134. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/tokens/usd.py +0 -0
  135. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/transaction_cache.py +0 -0
  136. {prediction_market_agent_tooling-0.67.4 → prediction_market_agent_tooling-0.68.0}/prediction_market_agent_tooling/tools/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.67.4
3
+ Version: 0.68.0
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.13
@@ -11,7 +11,7 @@ from pydantic_ai.exceptions import UnexpectedModelBehavior
11
11
  from prediction_market_agent_tooling.config import APIKeys
12
12
  from prediction_market_agent_tooling.deploy.betting_strategy import (
13
13
  BettingStrategy,
14
- MultiCategoricalMaxAccuracyBettingStrategy,
14
+ CategoricalMaxAccuracyBettingStrategy,
15
15
  TradeType,
16
16
  )
17
17
  from prediction_market_agent_tooling.deploy.trade_interval import (
@@ -662,9 +662,7 @@ class DeployableTraderAgent(DeployablePredictionAgent):
662
662
  Given the market and prediction, agent uses this method to calculate optimal outcome and bet size.
663
663
  """
664
664
  total_amount = self.get_total_amount_to_bet(market)
665
- return MultiCategoricalMaxAccuracyBettingStrategy(
666
- max_position_amount=total_amount
667
- )
665
+ return CategoricalMaxAccuracyBettingStrategy(max_position_amount=total_amount)
668
666
 
669
667
  def build_trades(
670
668
  self,
@@ -30,8 +30,13 @@ from prediction_market_agent_tooling.markets.omen.omen import (
30
30
  from prediction_market_agent_tooling.tools.betting_strategies.kelly_criterion import (
31
31
  get_kelly_bet_full,
32
32
  get_kelly_bet_simplified,
33
+ get_kelly_bets_categorical_full,
34
+ get_kelly_bets_categorical_simplified,
35
+ )
36
+ from prediction_market_agent_tooling.tools.betting_strategies.utils import (
37
+ BinaryKellyBet,
38
+ CategoricalKellyBet,
33
39
  )
34
- from prediction_market_agent_tooling.tools.betting_strategies.utils import SimpleBet
35
40
  from prediction_market_agent_tooling.tools.utils import check_not_none
36
41
 
37
42
 
@@ -245,7 +250,7 @@ class BettingStrategy(ABC):
245
250
  return trades
246
251
 
247
252
 
248
- class MultiCategoricalMaxAccuracyBettingStrategy(BettingStrategy):
253
+ class CategoricalMaxAccuracyBettingStrategy(BettingStrategy):
249
254
  def __init__(self, max_position_amount: USD, take_profit: bool = True):
250
255
  super().__init__(take_profit=take_profit)
251
256
  self.max_position_amount = max_position_amount
@@ -308,8 +313,11 @@ class MultiCategoricalMaxAccuracyBettingStrategy(BettingStrategy):
308
313
  )
309
314
  return trades
310
315
 
316
+ def __repr__(self) -> str:
317
+ return f"CategoricalMaxAccuracyBettingStrategy(max_position_amount={self.max_position_amount}, take_profit={self.take_profit})"
318
+
311
319
 
312
- class MaxExpectedValueBettingStrategy(MultiCategoricalMaxAccuracyBettingStrategy):
320
+ class MaxExpectedValueBettingStrategy(CategoricalMaxAccuracyBettingStrategy):
313
321
  @staticmethod
314
322
  def calculate_direction(
315
323
  market: AgentMarket, answer: CategoricalProbabilisticAnswer
@@ -350,49 +358,52 @@ class MaxExpectedValueBettingStrategy(MultiCategoricalMaxAccuracyBettingStrategy
350
358
 
351
359
  return best_outcome
352
360
 
361
+ def __repr__(self) -> str:
362
+ return f"MaxExpectedValueBettingStrategy(max_position_amount={self.max_position_amount}, take_profit={self.take_profit})"
363
+
353
364
 
354
- class KellyBettingStrategy(BettingStrategy):
365
+ class BinaryKellyBettingStrategy(BettingStrategy):
355
366
  def __init__(
356
367
  self,
357
368
  max_position_amount: USD,
358
369
  max_price_impact: float | None = None,
359
370
  take_profit: bool = True,
371
+ force_simplified_calculation: bool = False,
360
372
  ):
361
373
  super().__init__(take_profit=take_profit)
362
374
  self.max_position_amount = max_position_amount
363
375
  self.max_price_impact = max_price_impact
376
+ self.force_simplified_calculation = force_simplified_calculation
364
377
 
365
378
  @property
366
379
  def maximum_possible_bet_amount(self) -> USD:
367
380
  return self.max_position_amount
368
381
 
369
- @staticmethod
370
382
  def get_kelly_bet(
383
+ self,
371
384
  market: AgentMarket,
372
- max_bet_amount: USD,
373
385
  direction: OutcomeStr,
374
386
  other_direction: OutcomeStr,
375
387
  answer: CategoricalProbabilisticAnswer,
376
388
  override_p_yes: float | None = None,
377
- ) -> SimpleBet:
389
+ ) -> BinaryKellyBet:
390
+ if not market.is_binary:
391
+ raise ValueError("This strategy is usable only with binary markets.")
392
+
378
393
  estimated_p_yes = (
379
394
  answer.probability_for_market_outcome(direction)
380
395
  if not override_p_yes
381
396
  else override_p_yes
382
397
  )
383
398
 
384
- if not market.is_binary:
385
- # use Kelly simple, since Kelly full only supports 2 outcomes
386
-
399
+ if market.outcome_token_pool is None or self.force_simplified_calculation:
387
400
  kelly_bet = get_kelly_bet_simplified(
388
- max_bet=market.get_usd_in_token(max_bet_amount),
401
+ max_bet=market.get_usd_in_token(self.max_position_amount),
389
402
  market_p_yes=market.probability_for_market_outcome(direction),
390
403
  estimated_p_yes=estimated_p_yes,
391
404
  confidence=answer.confidence,
392
405
  )
393
406
  else:
394
- # We consider only binary markets, since the Kelly strategy is not yet implemented
395
- # for markets with more than 2 outcomes (https://github.com/gnosis/prediction-market-agent-tooling/issues/671).
396
407
  direction_to_bet_pool_size = market.get_outcome_token_pool_by_outcome(
397
408
  direction
398
409
  )
@@ -403,7 +414,7 @@ class KellyBettingStrategy(BettingStrategy):
403
414
  yes_outcome_pool_size=direction_to_bet_pool_size,
404
415
  no_outcome_pool_size=other_direction_pool_size,
405
416
  estimated_p_yes=estimated_p_yes,
406
- max_bet=market.get_usd_in_token(max_bet_amount),
417
+ max_bet=market.get_usd_in_token(self.max_position_amount),
407
418
  confidence=answer.confidence,
408
419
  fees=market.fees,
409
420
  )
@@ -416,7 +427,7 @@ class KellyBettingStrategy(BettingStrategy):
416
427
  market: AgentMarket,
417
428
  ) -> list[Trade]:
418
429
  # We consider the p_yes as the direction with highest probability.
419
- direction = MultiCategoricalMaxAccuracyBettingStrategy.calculate_direction(
430
+ direction = CategoricalMaxAccuracyBettingStrategy.calculate_direction(
420
431
  market, answer
421
432
  )
422
433
  # We get the first direction which is != direction.
@@ -426,7 +437,6 @@ class KellyBettingStrategy(BettingStrategy):
426
437
 
427
438
  kelly_bet = self.get_kelly_bet(
428
439
  market=market,
429
- max_bet_amount=self.max_position_amount,
430
440
  direction=direction,
431
441
  other_direction=other_direction,
432
442
  answer=answer,
@@ -436,7 +446,10 @@ class KellyBettingStrategy(BettingStrategy):
436
446
  if self.max_price_impact:
437
447
  # Adjust amount
438
448
  max_price_impact_bet_amount = self.calculate_bet_amount_for_price_impact(
439
- market, kelly_bet, direction=direction
449
+ market,
450
+ kelly_bet.size,
451
+ direction=direction,
452
+ max_price_impact=self.max_price_impact,
440
453
  )
441
454
 
442
455
  # We just don't want Kelly size to extrapolate price_impact - hence we take the min.
@@ -447,7 +460,9 @@ class KellyBettingStrategy(BettingStrategy):
447
460
  amounts = {
448
461
  bet_outcome: BettingStrategy.cap_to_profitable_bet_amount(
449
462
  market, market.get_token_in_usd(kelly_bet_size), bet_outcome
450
- ),
463
+ )
464
+ if kelly_bet_size > 0
465
+ else USD(0),
451
466
  }
452
467
  target_position = Position(market_id=market.id, amounts_current=amounts)
453
468
  trades = self._build_rebalance_trades_from_positions(
@@ -455,8 +470,8 @@ class KellyBettingStrategy(BettingStrategy):
455
470
  )
456
471
  return trades
457
472
 
473
+ @staticmethod
458
474
  def calculate_price_impact_for_bet_amount(
459
- self,
460
475
  outcome_idx: int,
461
476
  bet_amount: CollateralToken,
462
477
  pool_balances: list[OutcomeWei],
@@ -474,33 +489,43 @@ class KellyBettingStrategy(BettingStrategy):
474
489
  price_impact = (actual_price - expected_price) / expected_price
475
490
  return price_impact
476
491
 
492
+ @staticmethod
477
493
  def calculate_bet_amount_for_price_impact(
478
- self, market: AgentMarket, kelly_bet: SimpleBet, direction: OutcomeStr
494
+ market: AgentMarket,
495
+ kelly_bet_size: CollateralToken,
496
+ direction: OutcomeStr,
497
+ max_price_impact: float,
479
498
  ) -> CollateralToken:
480
499
  def calculate_price_impact_deviation_from_target_price_impact(
481
500
  bet_amount_collateral: float, # Needs to be float because it's used in minimize_scalar internally.
482
501
  ) -> float:
483
502
  outcome_idx = market.get_outcome_index(direction)
484
- price_impact = self.calculate_price_impact_for_bet_amount(
485
- outcome_idx=outcome_idx,
486
- bet_amount=CollateralToken(bet_amount_collateral),
487
- pool_balances=pool_balances,
488
- fees=market.fees,
503
+ price_impact = (
504
+ BinaryKellyBettingStrategy.calculate_price_impact_for_bet_amount(
505
+ outcome_idx=outcome_idx,
506
+ bet_amount=CollateralToken(bet_amount_collateral),
507
+ pool_balances=pool_balances,
508
+ fees=market.fees,
509
+ )
489
510
  )
490
511
  # We return abs for the algorithm to converge to 0 instead of the min (and possibly negative) value.
491
-
492
- max_price_impact = check_not_none(self.max_price_impact)
493
512
  return abs(price_impact - max_price_impact)
494
513
 
495
514
  if not market.outcome_token_pool:
496
515
  logger.warning(
497
516
  "Market outcome_token_pool is None, cannot calculate bet amount"
498
517
  )
499
- return kelly_bet.size
518
+ return kelly_bet_size
500
519
 
501
- pool_balances = [i.as_outcome_wei for i in market.outcome_token_pool.values()]
520
+ filtered_pool = {
521
+ outcome: pool_value
522
+ for outcome, pool_value in market.outcome_token_pool.items()
523
+ if INVALID_OUTCOME_LOWERCASE_IDENTIFIER not in outcome.lower()
524
+ }
525
+
526
+ pool_balances = [i.as_outcome_wei for i in filtered_pool.values()]
502
527
  # stay float for compatibility with `minimize_scalar`
503
- total_pool_balance = sum([i.value for i in market.outcome_token_pool.values()])
528
+ total_pool_balance = sum([i.value for i in filtered_pool.values()])
504
529
 
505
530
  # The bounds below have been found to work heuristically.
506
531
  optimized_bet_amount = minimize_scalar(
@@ -513,7 +538,7 @@ class KellyBettingStrategy(BettingStrategy):
513
538
  return CollateralToken(optimized_bet_amount.x)
514
539
 
515
540
  def __repr__(self) -> str:
516
- return f"{self.__class__.__name__}(max_bet_amount={self.max_position_amount}, max_price_impact={self.max_price_impact})"
541
+ return f"{self.__class__.__name__}(max_position_amount={self.max_position_amount}, max_price_impact={self.max_price_impact}, take_profit={self.take_profit}, force_simplified_calculation={self.force_simplified_calculation})"
517
542
 
518
543
 
519
544
  class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
@@ -529,40 +554,29 @@ class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
529
554
  def maximum_possible_bet_amount(self) -> USD:
530
555
  return self.max_position_amount
531
556
 
532
- def adjust_bet_amount(
533
- self, existing_position: ExistingPosition | None, market: AgentMarket
534
- ) -> USD:
535
- existing_position_total_amount = (
536
- existing_position.total_amount_current if existing_position else USD(0)
537
- )
538
- return self.max_position_amount + existing_position_total_amount
539
-
540
557
  def calculate_trades(
541
558
  self,
542
559
  existing_position: ExistingPosition | None,
543
560
  answer: CategoricalProbabilisticAnswer,
544
561
  market: AgentMarket,
545
562
  ) -> list[Trade]:
546
- adjusted_bet_amount_usd = self.adjust_bet_amount(existing_position, market)
547
-
548
563
  outcome = get_most_probable_outcome(answer.probabilities)
549
564
 
550
- direction = MultiCategoricalMaxAccuracyBettingStrategy.calculate_direction(
565
+ direction = CategoricalMaxAccuracyBettingStrategy.calculate_direction(
551
566
  market, answer
552
567
  )
553
568
  # We get the first direction which is != direction.
554
- other_direction = (
555
- MultiCategoricalMaxAccuracyBettingStrategy.get_other_direction(
556
- outcomes=market.outcomes, direction=direction
557
- )
569
+ other_direction = CategoricalMaxAccuracyBettingStrategy.get_other_direction(
570
+ outcomes=market.outcomes, direction=direction
558
571
  )
559
572
 
560
573
  # We ignore the direction nudge given by Kelly, hence we assume we have a perfect prediction.
561
574
  estimated_p_yes = 1.0
562
575
 
563
- kelly_bet = KellyBettingStrategy.get_kelly_bet(
576
+ kelly_bet = BinaryKellyBettingStrategy(
577
+ max_position_amount=self.max_position_amount
578
+ ).get_kelly_bet(
564
579
  market=market,
565
- max_bet_amount=adjusted_bet_amount_usd,
566
580
  direction=direction,
567
581
  other_direction=other_direction,
568
582
  answer=answer,
@@ -584,4 +598,118 @@ class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
584
598
  return trades
585
599
 
586
600
  def __repr__(self) -> str:
587
- return f"{self.__class__.__name__}(max_bet_amount={self.max_position_amount})"
601
+ return f"{self.__class__.__name__}(max_position_amount={self.max_position_amount}, take_profit={self.take_profit})"
602
+
603
+
604
+ class CategoricalKellyBettingStrategy(BettingStrategy):
605
+ def __init__(
606
+ self,
607
+ max_position_amount: USD,
608
+ max_price_impact: float | None,
609
+ allow_multiple_bets: bool,
610
+ allow_shorting: bool,
611
+ multicategorical: bool,
612
+ take_profit: bool = True,
613
+ force_simplified_calculation: bool = False,
614
+ ):
615
+ super().__init__(take_profit=take_profit)
616
+ self.max_position_amount = max_position_amount
617
+ self.max_price_impact = max_price_impact
618
+ self.allow_multiple_bets = allow_multiple_bets
619
+ self.allow_shorting = allow_shorting
620
+ self.multicategorical = multicategorical
621
+ self.force_simplified_calculation = force_simplified_calculation
622
+
623
+ @property
624
+ def maximum_possible_bet_amount(self) -> USD:
625
+ return self.max_position_amount
626
+
627
+ def get_kelly_bets(
628
+ self,
629
+ market: AgentMarket,
630
+ max_bet_amount: USD,
631
+ answer: CategoricalProbabilisticAnswer,
632
+ ) -> list[CategoricalKellyBet]:
633
+ max_bet = market.get_usd_in_token(max_bet_amount)
634
+
635
+ if market.outcome_token_pool is None or self.force_simplified_calculation:
636
+ kelly_bets = get_kelly_bets_categorical_simplified(
637
+ market_probabilities=[market.probabilities[o] for o in market.outcomes],
638
+ estimated_probabilities=[
639
+ answer.probability_for_market_outcome(o) for o in market.outcomes
640
+ ],
641
+ confidence=answer.confidence,
642
+ max_bet=max_bet,
643
+ fees=market.fees,
644
+ allow_multiple_bets=self.allow_multiple_bets,
645
+ allow_shorting=self.allow_shorting,
646
+ )
647
+
648
+ else:
649
+ kelly_bets = get_kelly_bets_categorical_full(
650
+ outcome_pool_sizes=[
651
+ market.outcome_token_pool[o] for o in market.outcomes
652
+ ],
653
+ estimated_probabilities=[
654
+ answer.probability_for_market_outcome(o) for o in market.outcomes
655
+ ],
656
+ confidence=answer.confidence,
657
+ max_bet=max_bet,
658
+ fees=market.fees,
659
+ allow_multiple_bets=self.allow_multiple_bets,
660
+ allow_shorting=self.allow_shorting,
661
+ multicategorical=self.multicategorical,
662
+ )
663
+
664
+ return kelly_bets
665
+
666
+ def calculate_trades(
667
+ self,
668
+ existing_position: ExistingPosition | None,
669
+ answer: CategoricalProbabilisticAnswer,
670
+ market: AgentMarket,
671
+ ) -> list[Trade]:
672
+ kelly_bets = self.get_kelly_bets(
673
+ market=market,
674
+ max_bet_amount=self.max_position_amount,
675
+ answer=answer,
676
+ )
677
+
678
+ # TODO: Allow shorting in BettingStrategy._build_rebalance_trades_from_positions.
679
+ # In binary implementation, we simply flip the direction in case of negative bet, for categorical outcome, we need to implement shorting.
680
+ kelly_bets = [bet for bet in kelly_bets if bet.size > 0]
681
+ if not kelly_bets:
682
+ return []
683
+
684
+ # TODO: Allow betting on multiple outcomes.
685
+ # Categorical kelly could suggest to bet on multiple outcomes, but we only consider the first one for now (limitation of BettingStrategy `trades` creation).
686
+ # Also, this could maybe work for multi-categorical markets as well, but it wasn't benchmarked for it.
687
+ best_kelly_bet = max(kelly_bets, key=lambda x: abs(x.size))
688
+
689
+ if self.max_price_impact:
690
+ # Adjust amount
691
+ max_price_impact_bet_amount = (
692
+ BinaryKellyBettingStrategy.calculate_bet_amount_for_price_impact(
693
+ market,
694
+ best_kelly_bet.size,
695
+ direction=market.get_outcome_str(best_kelly_bet.index),
696
+ max_price_impact=self.max_price_impact,
697
+ )
698
+ )
699
+ # We just don't want Kelly size to extrapolate price_impact - hence we take the min.
700
+ best_kelly_bet.size = min(best_kelly_bet.size, max_price_impact_bet_amount)
701
+
702
+ amounts = {
703
+ market.outcomes[best_kelly_bet.index]: market.get_token_in_usd(
704
+ best_kelly_bet.size
705
+ ),
706
+ }
707
+ target_position = Position(market_id=market.id, amounts_current=amounts)
708
+ trades = self._build_rebalance_trades_from_positions(
709
+ existing_position, target_position, market=market
710
+ )
711
+
712
+ return trades
713
+
714
+ def __repr__(self) -> str:
715
+ return f"{self.__class__.__name__}(max_position_amount={self.max_position_amount}, max_price_impact={self.max_price_impact}, allow_multiple_bets={self.allow_multiple_bets}, allow_shorting={self.allow_shorting}, take_profit={self.take_profit}, force_simplified_calculation={self.force_simplified_calculation})"
@@ -2,7 +2,7 @@ import typing as t
2
2
 
3
3
  from prediction_market_agent_tooling.config import APIKeys
4
4
  from prediction_market_agent_tooling.deploy.betting_strategy import (
5
- KellyBettingStrategy,
5
+ BinaryKellyBettingStrategy,
6
6
  TradeType,
7
7
  )
8
8
  from prediction_market_agent_tooling.gtypes import USD
@@ -93,7 +93,7 @@ class OmenJobAgentMarket(OmenAgentMarket, JobAgentMarket):
93
93
 
94
94
  def get_job_trade(self, max_bond: USD, result: str) -> Trade:
95
95
  # 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.
96
- strategy = KellyBettingStrategy(max_position_amount=max_bond)
96
+ strategy = BinaryKellyBettingStrategy(max_position_amount=max_bond)
97
97
  required_trades = strategy.calculate_trades(
98
98
  existing_position=None,
99
99
  answer=self.get_job_answer(result),
@@ -601,7 +601,12 @@ class OmenBet(BaseModel):
601
601
  created_time=self.creation_datetime,
602
602
  market_question=self.title,
603
603
  market_id=self.fpmm.id,
604
- market_outcome=self.fpmm.outcomes[self.outcomeIndex],
604
+ market_outcome=self.fpmm.outcomes[
605
+ check_not_none(
606
+ self.fpmm.answer_index,
607
+ "Should not be None if `is_resolved_with_valid_answer`.",
608
+ )
609
+ ],
605
610
  resolved_time=check_not_none(self.fpmm.finalized_datetime),
606
611
  profit=self.get_profit(),
607
612
  )
@@ -3,6 +3,7 @@ from collections import defaultdict
3
3
  from datetime import timedelta
4
4
 
5
5
  import tenacity
6
+ from pydantic import BaseModel
6
7
  from tqdm import tqdm
7
8
  from web3 import Web3
8
9
 
@@ -1323,20 +1324,34 @@ def send_keeping_token_to_eoa_xdai(
1323
1324
  )
1324
1325
 
1325
1326
 
1326
- def get_buy_outcome_token_amount(
1327
+ class BuyOutcomeResult(BaseModel):
1328
+ outcome_tokens_received: OutcomeToken
1329
+ new_pool_balances: list[OutcomeToken]
1330
+
1331
+
1332
+ def calculate_buy_outcome_token(
1327
1333
  investment_amount: CollateralToken,
1328
1334
  outcome_index: int,
1329
1335
  pool_balances: list[OutcomeToken],
1330
1336
  fees: MarketFees,
1331
- ) -> OutcomeToken:
1337
+ ) -> BuyOutcomeResult:
1332
1338
  """
1333
1339
  Calculates the amount of outcome tokens received for a given investment
1340
+ and returns the new pool balances after the purchase.
1334
1341
 
1335
1342
  Taken from https://github.com/gnosis/conditional-tokens-market-makers/blob/6814c0247c745680bb13298d4f0dd7f5b574d0db/contracts/FixedProductMarketMaker.sol#L264
1336
1343
  """
1337
1344
  if outcome_index >= len(pool_balances):
1338
1345
  raise ValueError("invalid outcome index")
1339
1346
 
1347
+ new_pool_balances = pool_balances.copy()
1348
+
1349
+ if investment_amount == 0:
1350
+ return BuyOutcomeResult(
1351
+ outcome_tokens_received=OutcomeToken(0),
1352
+ new_pool_balances=new_pool_balances,
1353
+ )
1354
+
1340
1355
  investment_amount_minus_fees = fees.get_after_fees(investment_amount)
1341
1356
  investment_amount_minus_fees_as_ot = OutcomeToken(
1342
1357
  investment_amount_minus_fees.value
@@ -1348,17 +1363,39 @@ def get_buy_outcome_token_amount(
1348
1363
  # Calculate the ending balance considering all other outcomes
1349
1364
  for i, pool_balance in enumerate(pool_balances):
1350
1365
  if i != outcome_index:
1351
- denominator = pool_balance + investment_amount_minus_fees_as_ot
1366
+ new_pool_balances[i] = pool_balance + investment_amount_minus_fees_as_ot
1352
1367
  ending_outcome_balance = OutcomeToken(
1353
- (ending_outcome_balance * pool_balance / denominator)
1368
+ (ending_outcome_balance * pool_balance / new_pool_balances[i])
1354
1369
  )
1355
1370
 
1371
+ # Update the bought outcome's pool balance
1372
+ new_pool_balances[outcome_index] = ending_outcome_balance
1373
+
1356
1374
  if ending_outcome_balance <= 0:
1357
1375
  raise ValueError("must have non-zero balances")
1358
1376
 
1359
- result = (
1377
+ outcome_tokens_received = (
1360
1378
  buy_token_pool_balance
1361
1379
  + investment_amount_minus_fees_as_ot
1362
1380
  - ending_outcome_balance
1363
1381
  )
1364
- return result
1382
+
1383
+ return BuyOutcomeResult(
1384
+ outcome_tokens_received=outcome_tokens_received,
1385
+ new_pool_balances=new_pool_balances,
1386
+ )
1387
+
1388
+
1389
+ def get_buy_outcome_token_amount(
1390
+ investment_amount: CollateralToken,
1391
+ outcome_index: int,
1392
+ pool_balances: list[OutcomeToken],
1393
+ fees: MarketFees,
1394
+ ) -> OutcomeToken:
1395
+ result = calculate_buy_outcome_token(
1396
+ investment_amount=investment_amount,
1397
+ outcome_index=outcome_index,
1398
+ pool_balances=pool_balances,
1399
+ fees=fees,
1400
+ )
1401
+ return result.outcome_tokens_received
@@ -2,11 +2,15 @@ from cachetools import TTLCache, cached
2
2
  from pydantic import BaseModel
3
3
  from web3 import Web3
4
4
 
5
+ from prediction_market_agent_tooling.deploy.constants import (
6
+ INVALID_OUTCOME_LOWERCASE_IDENTIFIER,
7
+ )
5
8
  from prediction_market_agent_tooling.gtypes import (
6
9
  ChecksumAddress,
7
10
  CollateralToken,
8
11
  HexAddress,
9
12
  OutcomeStr,
13
+ OutcomeToken,
10
14
  Probability,
11
15
  )
12
16
  from prediction_market_agent_tooling.loggers import logger
@@ -182,3 +186,67 @@ class PriceManager:
182
186
  normalized_prices[outcome] = new_price
183
187
 
184
188
  return normalized_prices
189
+
190
+ def build_initial_probs_from_pool(
191
+ self, model: SeerMarket, wrapped_tokens: list[ChecksumAddress]
192
+ ) -> tuple[dict[OutcomeStr, Probability], dict[OutcomeStr, OutcomeToken]]:
193
+ """
194
+ Builds a map of outcome to probability and outcome token pool.
195
+ """
196
+ probability_map = {}
197
+ outcome_token_pool = {}
198
+ wrapped_tokens_with_supply = [
199
+ (
200
+ token,
201
+ SeerSubgraphHandler().get_pool_by_token(
202
+ token, model.collateral_token_contract_address_checksummed
203
+ ),
204
+ )
205
+ for token in wrapped_tokens
206
+ ]
207
+ wrapped_tokens_with_supply = [
208
+ (token, pool)
209
+ for token, pool in wrapped_tokens_with_supply
210
+ if pool is not None
211
+ ]
212
+
213
+ for token, pool in wrapped_tokens_with_supply:
214
+ if pool is None or pool.token1.id is None or pool.token0.id is None:
215
+ continue
216
+ if HexBytes(token) == HexBytes(pool.token1.id):
217
+ outcome_token_pool[
218
+ OutcomeStr(model.outcomes[wrapped_tokens.index(token)])
219
+ ] = (
220
+ OutcomeToken(pool.totalValueLockedToken0)
221
+ if pool.totalValueLockedToken0 is not None
222
+ else OutcomeToken(0)
223
+ )
224
+ probability_map[
225
+ OutcomeStr(model.outcomes[wrapped_tokens.index(token)])
226
+ ] = Probability(pool.token0Price.value)
227
+ else:
228
+ outcome_token_pool[
229
+ OutcomeStr(model.outcomes[wrapped_tokens.index(token)])
230
+ ] = (
231
+ OutcomeToken(pool.totalValueLockedToken1)
232
+ if pool.totalValueLockedToken1 is not None
233
+ else OutcomeToken(0)
234
+ )
235
+ probability_map[
236
+ OutcomeStr(model.outcomes[wrapped_tokens.index(token)])
237
+ ] = Probability(pool.token1Price.value)
238
+
239
+ for outcome in model.outcomes:
240
+ if outcome not in outcome_token_pool:
241
+ outcome_token_pool[outcome] = OutcomeToken(0)
242
+ logger.warning(
243
+ f"Outcome {outcome} not found in outcome_token_pool for market {self.seer_market.url}."
244
+ )
245
+ if outcome not in probability_map:
246
+ if INVALID_OUTCOME_LOWERCASE_IDENTIFIER not in outcome.lower():
247
+ raise PriceCalculationError(
248
+ f"Couldn't get probability for {outcome} for market {self.seer_market.url}."
249
+ )
250
+ else:
251
+ probability_map[outcome] = Probability(0)
252
+ return probability_map, outcome_token_pool
@@ -411,10 +411,14 @@ class SeerAgentMarket(AgentMarket):
411
411
  must_have_prices: bool,
412
412
  ) -> t.Optional["SeerAgentMarket"]:
413
413
  price_manager = PriceManager(seer_market=model, seer_subgraph=seer_subgraph)
414
-
415
- probability_map = {}
414
+ wrapped_tokens = [Web3.to_checksum_address(i) for i in model.wrapped_tokens]
416
415
  try:
417
- probability_map = price_manager.build_probability_map()
416
+ (
417
+ probability_map,
418
+ outcome_token_pool,
419
+ ) = price_manager.build_initial_probs_from_pool(
420
+ model=model, wrapped_tokens=wrapped_tokens
421
+ )
418
422
  except PriceCalculationError as e:
419
423
  logger.info(
420
424
  f"Error when calculating probabilities for market {model.id.hex()} - {e}"
@@ -437,9 +441,9 @@ class SeerAgentMarket(AgentMarket):
437
441
  condition_id=model.condition_id,
438
442
  url=model.url,
439
443
  close_time=model.close_time,
440
- wrapped_tokens=[Web3.to_checksum_address(i) for i in model.wrapped_tokens],
444
+ wrapped_tokens=wrapped_tokens,
441
445
  fees=MarketFees.get_zero_fees(),
442
- outcome_token_pool=None,
446
+ outcome_token_pool=outcome_token_pool,
443
447
  outcomes_supply=model.outcomes_supply,
444
448
  resolution=resolution,
445
449
  volume=None,
@@ -633,9 +637,9 @@ class SeerAgentMarket(AgentMarket):
633
637
  amount_wei=amount_wei,
634
638
  web3=web3,
635
639
  )
636
- swap_pool_tx_hash = tx_receipt["transactionHash"].hex()
640
+ swap_pool_tx_hash = tx_receipt["transactionHash"]
637
641
  logger.info(f"TxHash is {swap_pool_tx_hash=}.")
638
- return swap_pool_tx_hash
642
+ return swap_pool_tx_hash.hex()
639
643
 
640
644
  def place_bet(
641
645
  self,
@@ -352,6 +352,8 @@ class SeerSubgraphHandler(BaseSubgraphHandler):
352
352
  pools_field.token1.id,
353
353
  pools_field.token1.name,
354
354
  pools_field.token1.symbol,
355
+ pools_field.totalValueLockedToken0,
356
+ pools_field.totalValueLockedToken1,
355
357
  ]
356
358
  return fields
357
359