prediction-market-agent-tooling 0.67.3__tar.gz → 0.67.4.dev992__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 (137) hide show
  1. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/PKG-INFO +1 -1
  2. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/deploy/agent.py +2 -4
  3. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/deploy/betting_strategy.py +169 -49
  4. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +2 -2
  5. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/agent_market.py +17 -0
  6. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/blockchain_utils.py +5 -3
  7. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/data_models.py +23 -3
  8. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/omen/data_models.py +6 -1
  9. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/omen/omen.py +43 -6
  10. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/polymarket/api.py +9 -3
  11. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/polymarket/data_models.py +5 -3
  12. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +15 -7
  13. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/seer/seer.py +11 -2
  14. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/seer/swap_pool_handler.py +4 -1
  15. prediction_market_agent_tooling-0.67.4.dev992/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +418 -0
  16. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +6 -1
  17. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/hexbytes_custom.py +9 -0
  18. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/httpx_cached_client.py +5 -3
  19. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +4 -3
  20. prediction_market_agent_tooling-0.67.4.dev992/prediction_market_agent_tooling/tools/singleton.py +28 -0
  21. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/pyproject.toml +1 -1
  22. prediction_market_agent_tooling-0.67.3/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -150
  23. prediction_market_agent_tooling-0.67.3/prediction_market_agent_tooling/tools/singleton.py +0 -23
  24. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/LICENSE +0 -0
  25. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/README.md +0 -0
  26. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/agentresultmapping.abi.json +0 -0
  27. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +0 -0
  28. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
  29. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/erc1155.abi.json +0 -0
  30. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  31. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
  32. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/erc721.abi.json +0 -0
  33. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/gvp2_settlement.abi.json +0 -0
  34. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  35. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  36. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  37. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  38. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  39. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  40. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  41. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  42. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/ownable.abi.json +0 -0
  43. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/ownable_erc721.abi.json +0 -0
  44. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
  45. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/seer_gnosis_router.abi.json +0 -0
  46. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/seer_market_factory.abi.json +0 -0
  47. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/abis/swapr_router.abi.json +0 -0
  48. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  49. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  50. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
  51. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  52. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/chains.py +0 -0
  53. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/config.py +0 -0
  54. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/data_download/langfuse_data_downloader.py +0 -0
  55. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  56. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  57. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  58. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  59. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  60. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/deploy/trade_interval.py +0 -0
  61. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/gtypes.py +0 -0
  62. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
  63. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/jobs/jobs_models.py +0 -0
  64. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/loggers.py +0 -0
  65. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/logprobs_parser.py +0 -0
  66. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/base_subgraph_handler.py +0 -0
  67. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  68. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  69. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  70. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  71. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  72. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  73. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/market_fees.py +0 -0
  74. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/markets.py +0 -0
  75. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
  76. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
  77. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +0 -0
  78. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  79. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/omen/cow_contracts.py +0 -0
  80. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/omen/omen_constants.py +0 -0
  81. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
  82. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
  83. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +0 -0
  84. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
  85. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/polymarket/polymarket_subgraph_handler.py +0 -0
  86. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  87. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/seer/data_models.py +0 -0
  88. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/seer/exceptions.py +0 -0
  89. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/seer/price_manager.py +0 -0
  90. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/seer/seer_contracts.py +0 -0
  91. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +0 -0
  92. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +0 -0
  93. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/py.typed +0 -0
  94. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/_generic_value.py +0 -0
  95. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/balances.py +0 -0
  96. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  97. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/caches/db_cache.py +0 -0
  98. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/caches/inmemory_cache.py +0 -0
  99. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/caches/serializers.py +0 -0
  100. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/contract.py +0 -0
  101. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/costs.py +0 -0
  102. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/cow/cow_order.py +0 -0
  103. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/cow/models.py +0 -0
  104. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/cow/semaphore.py +0 -0
  105. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/custom_exceptions.py +0 -0
  106. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/datetime_utc.py +0 -0
  107. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/db/db_manager.py +0 -0
  108. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/google_utils.py +0 -0
  109. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  110. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  111. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +0 -0
  112. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/is_invalid.py +0 -0
  113. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
  114. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
  115. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
  116. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/omen/sell_positions.py +0 -0
  117. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  118. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/perplexity/perplexity_client.py +0 -0
  119. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/perplexity/perplexity_models.py +0 -0
  120. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/perplexity/perplexity_search.py +0 -0
  121. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py +0 -0
  122. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py +0 -0
  123. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py +0 -0
  124. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/rephrase.py +0 -0
  125. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/safe.py +0 -0
  126. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  127. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/tavily/tavily_models.py +0 -0
  128. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/tavily/tavily_search.py +0 -0
  129. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/tokens/auto_deposit.py +0 -0
  130. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +0 -0
  131. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/tokens/main_token.py +0 -0
  132. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/tokens/slippage.py +0 -0
  133. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/tokens/token_utils.py +0 -0
  134. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/tokens/usd.py +0 -0
  135. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/transaction_cache.py +0 -0
  136. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/utils.py +0 -0
  137. {prediction_market_agent_tooling-0.67.3 → prediction_market_agent_tooling-0.67.4.dev992}/prediction_market_agent_tooling/tools/web3_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.3
3
+ Version: 0.67.4.dev992
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,49 @@ 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:
378
390
  estimated_p_yes = (
379
391
  answer.probability_for_market_outcome(direction)
380
392
  if not override_p_yes
381
393
  else override_p_yes
382
394
  )
383
395
 
384
- if not market.is_binary:
385
- # use Kelly simple, since Kelly full only supports 2 outcomes
386
-
396
+ if market.outcome_token_pool is None or self.force_simplified_calculation:
387
397
  kelly_bet = get_kelly_bet_simplified(
388
- max_bet=market.get_usd_in_token(max_bet_amount),
398
+ max_bet=market.get_usd_in_token(self.max_position_amount),
389
399
  market_p_yes=market.probability_for_market_outcome(direction),
390
400
  estimated_p_yes=estimated_p_yes,
391
401
  confidence=answer.confidence,
392
402
  )
393
403
  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
404
  direction_to_bet_pool_size = market.get_outcome_token_pool_by_outcome(
397
405
  direction
398
406
  )
@@ -403,7 +411,7 @@ class KellyBettingStrategy(BettingStrategy):
403
411
  yes_outcome_pool_size=direction_to_bet_pool_size,
404
412
  no_outcome_pool_size=other_direction_pool_size,
405
413
  estimated_p_yes=estimated_p_yes,
406
- max_bet=market.get_usd_in_token(max_bet_amount),
414
+ max_bet=market.get_usd_in_token(self.max_position_amount),
407
415
  confidence=answer.confidence,
408
416
  fees=market.fees,
409
417
  )
@@ -416,7 +424,7 @@ class KellyBettingStrategy(BettingStrategy):
416
424
  market: AgentMarket,
417
425
  ) -> list[Trade]:
418
426
  # We consider the p_yes as the direction with highest probability.
419
- direction = MultiCategoricalMaxAccuracyBettingStrategy.calculate_direction(
427
+ direction = CategoricalMaxAccuracyBettingStrategy.calculate_direction(
420
428
  market, answer
421
429
  )
422
430
  # We get the first direction which is != direction.
@@ -426,7 +434,6 @@ class KellyBettingStrategy(BettingStrategy):
426
434
 
427
435
  kelly_bet = self.get_kelly_bet(
428
436
  market=market,
429
- max_bet_amount=self.max_position_amount,
430
437
  direction=direction,
431
438
  other_direction=other_direction,
432
439
  answer=answer,
@@ -436,15 +443,21 @@ class KellyBettingStrategy(BettingStrategy):
436
443
  if self.max_price_impact:
437
444
  # Adjust amount
438
445
  max_price_impact_bet_amount = self.calculate_bet_amount_for_price_impact(
439
- market, kelly_bet, direction=direction
446
+ market,
447
+ kelly_bet.size,
448
+ direction=direction,
449
+ max_price_impact=self.max_price_impact,
440
450
  )
441
451
 
442
452
  # We just don't want Kelly size to extrapolate price_impact - hence we take the min.
443
453
  kelly_bet_size = min(kelly_bet.size, max_price_impact_bet_amount)
444
454
 
445
455
  bet_outcome = direction if kelly_bet.direction else other_direction
456
+
446
457
  amounts = {
447
- bet_outcome: market.get_token_in_usd(kelly_bet_size),
458
+ bet_outcome: BettingStrategy.cap_to_profitable_bet_amount(
459
+ market, market.get_token_in_usd(kelly_bet_size), bet_outcome
460
+ ),
448
461
  }
449
462
  target_position = Position(market_id=market.id, amounts_current=amounts)
450
463
  trades = self._build_rebalance_trades_from_positions(
@@ -452,8 +465,8 @@ class KellyBettingStrategy(BettingStrategy):
452
465
  )
453
466
  return trades
454
467
 
468
+ @staticmethod
455
469
  def calculate_price_impact_for_bet_amount(
456
- self,
457
470
  outcome_idx: int,
458
471
  bet_amount: CollateralToken,
459
472
  pool_balances: list[OutcomeWei],
@@ -471,29 +484,33 @@ class KellyBettingStrategy(BettingStrategy):
471
484
  price_impact = (actual_price - expected_price) / expected_price
472
485
  return price_impact
473
486
 
487
+ @staticmethod
474
488
  def calculate_bet_amount_for_price_impact(
475
- self, market: AgentMarket, kelly_bet: SimpleBet, direction: OutcomeStr
489
+ market: AgentMarket,
490
+ kelly_bet_size: CollateralToken,
491
+ direction: OutcomeStr,
492
+ max_price_impact: float,
476
493
  ) -> CollateralToken:
477
494
  def calculate_price_impact_deviation_from_target_price_impact(
478
- bet_amount_usd: float, # Needs to be float because it's used in minimize_scalar internally.
495
+ bet_amount_collateral: float, # Needs to be float because it's used in minimize_scalar internally.
479
496
  ) -> float:
480
497
  outcome_idx = market.get_outcome_index(direction)
481
- price_impact = self.calculate_price_impact_for_bet_amount(
482
- outcome_idx=outcome_idx,
483
- bet_amount=market.get_usd_in_token(USD(bet_amount_usd)),
484
- pool_balances=pool_balances,
485
- fees=market.fees,
498
+ price_impact = (
499
+ BinaryKellyBettingStrategy.calculate_price_impact_for_bet_amount(
500
+ outcome_idx=outcome_idx,
501
+ bet_amount=CollateralToken(bet_amount_collateral),
502
+ pool_balances=pool_balances,
503
+ fees=market.fees,
504
+ )
486
505
  )
487
506
  # We return abs for the algorithm to converge to 0 instead of the min (and possibly negative) value.
488
-
489
- max_price_impact = check_not_none(self.max_price_impact)
490
507
  return abs(price_impact - max_price_impact)
491
508
 
492
509
  if not market.outcome_token_pool:
493
510
  logger.warning(
494
511
  "Market outcome_token_pool is None, cannot calculate bet amount"
495
512
  )
496
- return kelly_bet.size
513
+ return kelly_bet_size
497
514
 
498
515
  pool_balances = [i.as_outcome_wei for i in market.outcome_token_pool.values()]
499
516
  # stay float for compatibility with `minimize_scalar`
@@ -504,13 +521,13 @@ class KellyBettingStrategy(BettingStrategy):
504
521
  calculate_price_impact_deviation_from_target_price_impact,
505
522
  bounds=(0, 1000 * total_pool_balance),
506
523
  method="bounded",
507
- tol=1e-11,
524
+ tol=1e-13,
508
525
  options={"maxiter": 10000},
509
526
  )
510
527
  return CollateralToken(optimized_bet_amount.x)
511
528
 
512
529
  def __repr__(self) -> str:
513
- return f"{self.__class__.__name__}(max_bet_amount={self.max_position_amount}, max_price_impact={self.max_price_impact})"
530
+ 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})"
514
531
 
515
532
 
516
533
  class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
@@ -526,40 +543,29 @@ class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
526
543
  def maximum_possible_bet_amount(self) -> USD:
527
544
  return self.max_position_amount
528
545
 
529
- def adjust_bet_amount(
530
- self, existing_position: ExistingPosition | None, market: AgentMarket
531
- ) -> USD:
532
- existing_position_total_amount = (
533
- existing_position.total_amount_current if existing_position else USD(0)
534
- )
535
- return self.max_position_amount + existing_position_total_amount
536
-
537
546
  def calculate_trades(
538
547
  self,
539
548
  existing_position: ExistingPosition | None,
540
549
  answer: CategoricalProbabilisticAnswer,
541
550
  market: AgentMarket,
542
551
  ) -> list[Trade]:
543
- adjusted_bet_amount_usd = self.adjust_bet_amount(existing_position, market)
544
-
545
552
  outcome = get_most_probable_outcome(answer.probabilities)
546
553
 
547
- direction = MultiCategoricalMaxAccuracyBettingStrategy.calculate_direction(
554
+ direction = CategoricalMaxAccuracyBettingStrategy.calculate_direction(
548
555
  market, answer
549
556
  )
550
557
  # We get the first direction which is != direction.
551
- other_direction = (
552
- MultiCategoricalMaxAccuracyBettingStrategy.get_other_direction(
553
- outcomes=market.outcomes, direction=direction
554
- )
558
+ other_direction = CategoricalMaxAccuracyBettingStrategy.get_other_direction(
559
+ outcomes=market.outcomes, direction=direction
555
560
  )
556
561
 
557
562
  # We ignore the direction nudge given by Kelly, hence we assume we have a perfect prediction.
558
563
  estimated_p_yes = 1.0
559
564
 
560
- kelly_bet = KellyBettingStrategy.get_kelly_bet(
565
+ kelly_bet = BinaryKellyBettingStrategy(
566
+ max_position_amount=self.max_position_amount
567
+ ).get_kelly_bet(
561
568
  market=market,
562
- max_bet_amount=adjusted_bet_amount_usd,
563
569
  direction=direction,
564
570
  other_direction=other_direction,
565
571
  answer=answer,
@@ -581,4 +587,118 @@ class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
581
587
  return trades
582
588
 
583
589
  def __repr__(self) -> str:
584
- return f"{self.__class__.__name__}(max_bet_amount={self.max_position_amount})"
590
+ return f"{self.__class__.__name__}(max_position_amount={self.max_position_amount}, take_profit={self.take_profit})"
591
+
592
+
593
+ class CategoricalKellyBettingStrategy(BettingStrategy):
594
+ def __init__(
595
+ self,
596
+ max_position_amount: USD,
597
+ max_price_impact: float | None,
598
+ allow_multiple_bets: bool,
599
+ allow_shorting: bool,
600
+ multicategorical: bool,
601
+ take_profit: bool = True,
602
+ force_simplified_calculation: bool = False,
603
+ ):
604
+ super().__init__(take_profit=take_profit)
605
+ self.max_position_amount = max_position_amount
606
+ self.max_price_impact = max_price_impact
607
+ self.allow_multiple_bets = allow_multiple_bets
608
+ self.allow_shorting = allow_shorting
609
+ self.multicategorical = multicategorical
610
+ self.force_simplified_calculation = force_simplified_calculation
611
+
612
+ @property
613
+ def maximum_possible_bet_amount(self) -> USD:
614
+ return self.max_position_amount
615
+
616
+ def get_kelly_bets(
617
+ self,
618
+ market: AgentMarket,
619
+ max_bet_amount: USD,
620
+ answer: CategoricalProbabilisticAnswer,
621
+ ) -> list[CategoricalKellyBet]:
622
+ max_bet = market.get_usd_in_token(max_bet_amount)
623
+
624
+ if market.outcome_token_pool is None or self.force_simplified_calculation:
625
+ kelly_bets = get_kelly_bets_categorical_simplified(
626
+ market_probabilities=[market.probabilities[o] for o in market.outcomes],
627
+ estimated_probabilities=[
628
+ answer.probability_for_market_outcome(o) for o in market.outcomes
629
+ ],
630
+ confidence=answer.confidence,
631
+ max_bet=max_bet,
632
+ fees=market.fees,
633
+ allow_multiple_bets=self.allow_multiple_bets,
634
+ allow_shorting=self.allow_shorting,
635
+ )
636
+
637
+ else:
638
+ kelly_bets = get_kelly_bets_categorical_full(
639
+ outcome_pool_sizes=[
640
+ market.outcome_token_pool[o] for o in market.outcomes
641
+ ],
642
+ estimated_probabilities=[
643
+ answer.probability_for_market_outcome(o) for o in market.outcomes
644
+ ],
645
+ confidence=answer.confidence,
646
+ max_bet=max_bet,
647
+ fees=market.fees,
648
+ allow_multiple_bets=self.allow_multiple_bets,
649
+ allow_shorting=self.allow_shorting,
650
+ multicategorical=self.multicategorical,
651
+ )
652
+
653
+ return kelly_bets
654
+
655
+ def calculate_trades(
656
+ self,
657
+ existing_position: ExistingPosition | None,
658
+ answer: CategoricalProbabilisticAnswer,
659
+ market: AgentMarket,
660
+ ) -> list[Trade]:
661
+ kelly_bets = self.get_kelly_bets(
662
+ market=market,
663
+ max_bet_amount=self.max_position_amount,
664
+ answer=answer,
665
+ )
666
+
667
+ # TODO: Allow shorting in BettingStrategy._build_rebalance_trades_from_positions.
668
+ # In binary implementation, we simply flip the direction in case of negative bet, for categorical outcome, we need to implement shorting.
669
+ kelly_bets = [bet for bet in kelly_bets if bet.size > 0]
670
+ if not kelly_bets:
671
+ return []
672
+
673
+ # TODO: Allow betting on multiple outcomes.
674
+ # Categorical kelly could suggest to bet on multiple outcomes, but we only consider the first one for now (limitation of BettingStrategy `trades` creation).
675
+ # Also, this could maybe work for multi-categorical markets as well, but it wasn't benchmarked for it.
676
+ best_kelly_bet = max(kelly_bets, key=lambda x: abs(x.size))
677
+
678
+ if self.max_price_impact:
679
+ # Adjust amount
680
+ max_price_impact_bet_amount = (
681
+ BinaryKellyBettingStrategy.calculate_bet_amount_for_price_impact(
682
+ market,
683
+ best_kelly_bet.size,
684
+ direction=market.get_outcome_str(best_kelly_bet.index),
685
+ max_price_impact=self.max_price_impact,
686
+ )
687
+ )
688
+ # We just don't want Kelly size to extrapolate price_impact - hence we take the min.
689
+ best_kelly_bet.size = min(best_kelly_bet.size, max_price_impact_bet_amount)
690
+
691
+ amounts = {
692
+ market.outcomes[best_kelly_bet.index]: market.get_token_in_usd(
693
+ best_kelly_bet.size
694
+ ),
695
+ }
696
+ target_position = Position(market_id=market.id, amounts_current=amounts)
697
+ trades = self._build_rebalance_trades_from_positions(
698
+ existing_position, target_position, market=market
699
+ )
700
+
701
+ return trades
702
+
703
+ def __repr__(self) -> str:
704
+ 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),
@@ -153,6 +153,23 @@ class AgentMarket(BaseModel):
153
153
  if "fees" not in data and "fee" in data:
154
154
  data["fees"] = MarketFees(absolute=0.0, bet_proportion=data["fee"])
155
155
  del data["fee"]
156
+ # Backward compatibility for older `AgentMarket` without `probabilities`.
157
+ if "probabilities" not in data and "current_p_yes" in data:
158
+ yes_outcome = data["outcomes"][
159
+ [o.lower() for o in data["outcomes"]].index(
160
+ YES_OUTCOME_LOWERCASE_IDENTIFIER
161
+ )
162
+ ]
163
+ no_outcome = data["outcomes"][
164
+ [o.lower() for o in data["outcomes"]].index(
165
+ NO_OUTCOME_LOWERCASE_IDENTIFIER
166
+ )
167
+ ]
168
+ data["probabilities"] = {
169
+ yes_outcome: data["current_p_yes"],
170
+ no_outcome: 1 - data["current_p_yes"],
171
+ }
172
+ del data["current_p_yes"]
156
173
  return data
157
174
 
158
175
  def market_outcome_for_probability_key(
@@ -37,6 +37,10 @@ def store_trades(
37
37
  logger.warning(f"No prediction for market {market_id}, not storing anything.")
38
38
  return None
39
39
 
40
+ logger.info(
41
+ f"Storing trades for market {market_id}, with outcomes {outcomes}, {traded_market=}."
42
+ )
43
+
40
44
  probabilities = traded_market.answer.probabilities
41
45
  if not probabilities:
42
46
  logger.info("Skipping this since no probabilities available.")
@@ -56,9 +60,7 @@ def store_trades(
56
60
  ipfs_hash_decoded = ipfscidv0_to_byte32(ipfs_hash)
57
61
 
58
62
  # tx_hashes must be list of bytes32 (see Solidity contract).
59
- tx_hashes = [
60
- HexBytes(HexStr(i.id)) for i in traded_market.trades if i.id is not None
61
- ]
63
+ tx_hashes = [HexBytes(HexStr(i.id)) for i in traded_market.trades]
62
64
 
63
65
  # Dune dashboard expects the probs to be in the same order as on the market.
64
66
  probabilities_converted = [
@@ -1,7 +1,7 @@
1
1
  from enum import Enum
2
- from typing import Annotated, Sequence
2
+ from typing import Annotated, Any, Sequence
3
3
 
4
- from pydantic import BaseModel, BeforeValidator, computed_field
4
+ from pydantic import BaseModel, BeforeValidator, computed_field, model_validator
5
5
 
6
6
  from prediction_market_agent_tooling.deploy.constants import (
7
7
  DOWN_OUTCOME_LOWERCASE_IDENTIFIER,
@@ -157,6 +157,15 @@ class CategoricalProbabilisticAnswer(BaseModel):
157
157
  confidence: float
158
158
  reasoning: str | None = None
159
159
 
160
+ @model_validator(mode="before")
161
+ @classmethod
162
+ def _model_validator(cls, data: Any) -> Any:
163
+ if "p_yes" in data:
164
+ return CategoricalProbabilisticAnswer.from_probabilistic_answer(
165
+ ProbabilisticAnswer.model_validate(data)
166
+ ).model_dump()
167
+ return data
168
+
160
169
  @property
161
170
  def probable_resolution(self) -> Resolution:
162
171
  most_likely_outcome = max(
@@ -290,9 +299,20 @@ class Trade(BaseModel):
290
299
  outcome: OutcomeStr
291
300
  amount: USD
292
301
 
302
+ @model_validator(mode="before")
303
+ @classmethod
304
+ def _model_validator(cls, data: Any) -> Any:
305
+ if isinstance(data["outcome"], bool):
306
+ data["outcome"] = (
307
+ YES_OUTCOME_LOWERCASE_IDENTIFIER
308
+ if data["outcome"]
309
+ else NO_OUTCOME_LOWERCASE_IDENTIFIER
310
+ )
311
+ return data
312
+
293
313
 
294
314
  class PlacedTrade(Trade):
295
- id: str | None = None
315
+ id: str
296
316
 
297
317
  @staticmethod
298
318
  def from_trade(trade: Trade, id: str) -> "PlacedTrade":
@@ -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
@@ -1,4 +1,5 @@
1
1
  import typing as t
2
+ from datetime import timedelta
2
3
  from enum import Enum
3
4
  from urllib.parse import urljoin
4
5
 
@@ -49,7 +50,7 @@ def get_polymarkets_with_pagination(
49
50
  Binary markets have len(model.markets) == 1.
50
51
  Categorical markets have len(model.markets) > 1
51
52
  """
52
- client: httpx.Client = HttpxCachedClient(ttl=60).get_client()
53
+ client: httpx.Client = HttpxCachedClient(ttl=timedelta(seconds=60)).get_client()
53
54
  all_markets: list[PolymarketGammaResponseDataItem] = []
54
55
  offset = 0
55
56
  remaining = limit
@@ -82,6 +83,9 @@ def get_polymarkets_with_pagination(
82
83
 
83
84
  markets_to_add = []
84
85
  for m in market_response.data:
86
+ # Some Polymarket markets are missing the markets field
87
+ if m.markets is None:
88
+ continue
85
89
  if excluded_questions and m.title in excluded_questions:
86
90
  continue
87
91
 
@@ -94,14 +98,16 @@ def get_polymarkets_with_pagination(
94
98
  ]:
95
99
  continue
96
100
 
97
- if created_after and created_after > m.startDate:
101
+ if not m.startDate or (created_after and created_after > m.startDate):
98
102
  continue
99
103
 
100
104
  markets_to_add.append(m)
101
105
 
102
106
  if only_binary:
103
107
  markets_to_add = [
104
- market for market in market_response.data if len(market.markets) == 1
108
+ market
109
+ for market in markets_to_add
110
+ if market.markets is not None and len(market.markets) == 1
105
111
  ]
106
112
 
107
113
  # Add the markets from this batch to our results