prediction-market-agent-tooling 0.66.5__tar.gz → 0.67.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/PKG-INFO +1 -1
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/deploy/agent.py +23 -5
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/agent_market.py +9 -2
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/manifold/manifold.py +3 -2
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/markets.py +5 -5
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +3 -1
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/omen/omen.py +5 -2
- prediction_market_agent_tooling-0.67.1/prediction_market_agent_tooling/markets/polymarket/api.py +123 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/polymarket/data_models.py +60 -14
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -54
- prediction_market_agent_tooling-0.67.1/prediction_market_agent_tooling/markets/polymarket/polymarket.py +173 -0
- prediction_market_agent_tooling-0.67.1/prediction_market_agent_tooling/markets/polymarket/polymarket_subgraph_handler.py +49 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -21
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/seer/price_manager.py +65 -46
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/seer/seer.py +70 -90
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +48 -35
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/seer/swap_pool_handler.py +11 -1
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/cow/cow_order.py +26 -11
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/cow/models.py +4 -2
- prediction_market_agent_tooling-0.67.1/prediction_market_agent_tooling/tools/httpx_cached_client.py +21 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/tokens/auto_deposit.py +7 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/tokens/auto_withdraw.py +8 -0
- prediction_market_agent_tooling-0.67.1/prediction_market_agent_tooling/tools/tokens/slippage.py +21 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/utils.py +5 -2
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/pyproject.toml +1 -1
- prediction_market_agent_tooling-0.66.5/prediction_market_agent_tooling/markets/polymarket/api.py +0 -140
- prediction_market_agent_tooling-0.66.5/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -90
- prediction_market_agent_tooling-0.66.5/prediction_market_agent_tooling/tools/httpx_cached_client.py +0 -14
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/README.md +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/agentresultmapping.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/erc721.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/gvp2_settlement.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/ownable.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/ownable_erc721.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/seer_gnosis_router.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/seer_market_factory.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/abis/swapr_router.abi.json +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/chains.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/config.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/data_download/langfuse_data_downloader.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/deploy/betting_strategy.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/deploy/constants.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/deploy/trade_interval.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/gtypes.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/jobs/jobs_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/loggers.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/logprobs_parser.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/base_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/blockchain_utils.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/categorize.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/data_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/market_fees.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/omen/cow_contracts.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/omen/data_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/omen/omen_constants.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/seer/data_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/seer/exceptions.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/seer/seer_contracts.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/markets/seer/subgraph_data_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/py.typed +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/_generic_value.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/balances.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/caches/db_cache.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/caches/inmemory_cache.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/caches/serializers.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/contract.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/costs.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/cow/semaphore.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/custom_exceptions.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/datetime_utc.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/db/db_manager.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/google_utils.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/is_invalid.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/omen/sell_positions.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/perplexity/perplexity_client.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/perplexity/perplexity_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/perplexity/perplexity_search.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/safe.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/singleton.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/tavily/tavily_models.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/tavily/tavily_search.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/tokens/main_token.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/tokens/token_utils.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/tokens/usd.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/transaction_cache.py +0 -0
- {prediction_market_agent_tooling-0.66.5 → prediction_market_agent_tooling-0.67.1}/prediction_market_agent_tooling/tools/web3_utils.py +0 -0
@@ -19,9 +19,11 @@ from prediction_market_agent_tooling.deploy.trade_interval import (
|
|
19
19
|
)
|
20
20
|
from prediction_market_agent_tooling.gtypes import USD, OutcomeToken, xDai
|
21
21
|
from prediction_market_agent_tooling.loggers import logger
|
22
|
+
from prediction_market_agent_tooling.markets.agent_market import AgentMarket, FilterBy
|
23
|
+
from prediction_market_agent_tooling.markets.agent_market import (
|
24
|
+
MarketType as AgentMarketType,
|
25
|
+
)
|
22
26
|
from prediction_market_agent_tooling.markets.agent_market import (
|
23
|
-
AgentMarket,
|
24
|
-
FilterBy,
|
25
27
|
ProcessedMarket,
|
26
28
|
ProcessedTradedMarket,
|
27
29
|
SortBy,
|
@@ -335,6 +337,15 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
335
337
|
return True
|
336
338
|
return False
|
337
339
|
|
340
|
+
@property
|
341
|
+
def agent_market_type(self) -> AgentMarketType:
|
342
|
+
if self.fetch_scalar_markets:
|
343
|
+
return AgentMarketType.SCALAR
|
344
|
+
elif self.fetch_categorical_markets:
|
345
|
+
return AgentMarketType.CATEGORICAL
|
346
|
+
else:
|
347
|
+
return AgentMarketType.BINARY
|
348
|
+
|
338
349
|
def get_markets(
|
339
350
|
self,
|
340
351
|
market_type: MarketType,
|
@@ -343,14 +354,16 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
343
354
|
Override this method to customize what markets will fetch for processing.
|
344
355
|
"""
|
345
356
|
cls = market_type.market_class
|
357
|
+
|
358
|
+
agent_market_type = self.agent_market_type
|
359
|
+
|
346
360
|
# Fetch the soonest closing markets to choose from
|
347
361
|
available_markets = cls.get_markets(
|
348
362
|
limit=self.n_markets_to_fetch,
|
349
363
|
sort_by=self.get_markets_sort_by,
|
350
364
|
filter_by=self.get_markets_filter_by,
|
351
365
|
created_after=self.trade_on_markets_created_after,
|
352
|
-
|
353
|
-
fetch_scalar_markets=self.fetch_scalar_markets,
|
366
|
+
market_type=agent_market_type,
|
354
367
|
)
|
355
368
|
return available_markets
|
356
369
|
|
@@ -628,7 +641,12 @@ class DeployableTraderAgent(DeployablePredictionAgent):
|
|
628
641
|
api_keys = APIKeys()
|
629
642
|
user_id = market.get_user_id(api_keys=api_keys)
|
630
643
|
|
631
|
-
|
644
|
+
try:
|
645
|
+
existing_position = market.get_position(user_id=user_id)
|
646
|
+
except Exception as e:
|
647
|
+
logger.warning(f"Could not get position for user {user_id}, exception {e}")
|
648
|
+
return None
|
649
|
+
|
632
650
|
trades = self.build_trades(
|
633
651
|
market=market,
|
634
652
|
answer=processed_market.answer,
|
@@ -64,6 +64,13 @@ class FilterBy(str, Enum):
|
|
64
64
|
NONE = "none"
|
65
65
|
|
66
66
|
|
67
|
+
class MarketType(str, Enum):
|
68
|
+
ALL = "all"
|
69
|
+
CATEGORICAL = "categorical"
|
70
|
+
SCALAR = "scalar"
|
71
|
+
BINARY = "binary"
|
72
|
+
|
73
|
+
|
67
74
|
class AgentMarket(BaseModel):
|
68
75
|
"""
|
69
76
|
Common market class that can be created from vendor specific markets.
|
@@ -369,8 +376,8 @@ class AgentMarket(BaseModel):
|
|
369
376
|
filter_by: FilterBy = FilterBy.OPEN,
|
370
377
|
created_after: t.Optional[DatetimeUTC] = None,
|
371
378
|
excluded_questions: set[str] | None = None,
|
372
|
-
|
373
|
-
|
379
|
+
market_type: MarketType = MarketType.ALL,
|
380
|
+
include_conditional_markets: bool = False,
|
374
381
|
) -> t.Sequence["AgentMarket"]:
|
375
382
|
raise NotImplementedError("Subclasses must implement this method")
|
376
383
|
|
@@ -12,6 +12,7 @@ from prediction_market_agent_tooling.markets.agent_market import (
|
|
12
12
|
AgentMarket,
|
13
13
|
FilterBy,
|
14
14
|
MarketFees,
|
15
|
+
MarketType,
|
15
16
|
SortBy,
|
16
17
|
)
|
17
18
|
from prediction_market_agent_tooling.markets.manifold.api import (
|
@@ -110,8 +111,8 @@ class ManifoldAgentMarket(AgentMarket):
|
|
110
111
|
filter_by: FilterBy = FilterBy.OPEN,
|
111
112
|
created_after: t.Optional[DatetimeUTC] = None,
|
112
113
|
excluded_questions: set[str] | None = None,
|
113
|
-
|
114
|
-
|
114
|
+
market_type: MarketType = MarketType.ALL,
|
115
|
+
include_conditional_markets: bool = False,
|
115
116
|
) -> t.Sequence["ManifoldAgentMarket"]:
|
116
117
|
sort: t.Literal["newest", "close-date"] | None
|
117
118
|
if sort_by == SortBy.CLOSING_SOONEST:
|
@@ -3,11 +3,11 @@ from enum import Enum
|
|
3
3
|
|
4
4
|
from prediction_market_agent_tooling.jobs.jobs_models import JobAgentMarket
|
5
5
|
from prediction_market_agent_tooling.jobs.omen.omen_jobs import OmenJobAgentMarket
|
6
|
+
from prediction_market_agent_tooling.markets.agent_market import AgentMarket, FilterBy
|
6
7
|
from prediction_market_agent_tooling.markets.agent_market import (
|
7
|
-
|
8
|
-
FilterBy,
|
9
|
-
SortBy,
|
8
|
+
MarketType as AgentMarketType,
|
10
9
|
)
|
10
|
+
from prediction_market_agent_tooling.markets.agent_market import SortBy
|
11
11
|
from prediction_market_agent_tooling.markets.manifold.manifold import (
|
12
12
|
ManifoldAgentMarket,
|
13
13
|
)
|
@@ -68,7 +68,7 @@ def get_binary_markets(
|
|
68
68
|
sort_by: SortBy = SortBy.NONE,
|
69
69
|
excluded_questions: set[str] | None = None,
|
70
70
|
created_after: DatetimeUTC | None = None,
|
71
|
-
|
71
|
+
agent_market_type: AgentMarketType = AgentMarketType.BINARY,
|
72
72
|
) -> t.Sequence[AgentMarket]:
|
73
73
|
agent_market_class = MARKET_TYPE_TO_AGENT_MARKET[market_type]
|
74
74
|
markets = agent_market_class.get_markets(
|
@@ -77,6 +77,6 @@ def get_binary_markets(
|
|
77
77
|
filter_by=filter_by,
|
78
78
|
created_after=created_after,
|
79
79
|
excluded_questions=excluded_questions,
|
80
|
-
|
80
|
+
market_type=agent_market_type,
|
81
81
|
)
|
82
82
|
return markets
|
@@ -9,6 +9,7 @@ from prediction_market_agent_tooling.markets.agent_market import (
|
|
9
9
|
AgentMarket,
|
10
10
|
FilterBy,
|
11
11
|
MarketFees,
|
12
|
+
MarketType,
|
12
13
|
ProcessedMarket,
|
13
14
|
SortBy,
|
14
15
|
)
|
@@ -72,8 +73,9 @@ class MetaculusAgentMarket(AgentMarket):
|
|
72
73
|
filter_by: FilterBy = FilterBy.OPEN,
|
73
74
|
created_after: t.Optional[DatetimeUTC] = None,
|
74
75
|
excluded_questions: set[str] | None = None,
|
76
|
+
market_type: MarketType = MarketType.ALL,
|
77
|
+
include_conditional_markets: bool = False,
|
75
78
|
tournament_id: int | None = None,
|
76
|
-
fetch_scalar_markets: bool = False,
|
77
79
|
) -> t.Sequence["MetaculusAgentMarket"]:
|
78
80
|
order_by: str | None
|
79
81
|
if sort_by == SortBy.NONE:
|
@@ -25,6 +25,7 @@ from prediction_market_agent_tooling.markets.agent_market import (
|
|
25
25
|
AgentMarket,
|
26
26
|
FilterBy,
|
27
27
|
MarketFees,
|
28
|
+
MarketType,
|
28
29
|
ProcessedMarket,
|
29
30
|
ProcessedTradedMarket,
|
30
31
|
SortBy,
|
@@ -379,9 +380,11 @@ class OmenAgentMarket(AgentMarket):
|
|
379
380
|
filter_by: FilterBy = FilterBy.OPEN,
|
380
381
|
created_after: t.Optional[DatetimeUTC] = None,
|
381
382
|
excluded_questions: set[str] | None = None,
|
382
|
-
|
383
|
-
|
383
|
+
market_type: MarketType = MarketType.ALL,
|
384
|
+
include_conditional_markets: bool = False,
|
384
385
|
) -> t.Sequence["OmenAgentMarket"]:
|
386
|
+
fetch_categorical_markets = market_type == MarketType.CATEGORICAL
|
387
|
+
|
385
388
|
return [
|
386
389
|
OmenAgentMarket.from_data_model(m)
|
387
390
|
for m in OmenSubgraphHandler().get_omen_markets_simple(
|
prediction_market_agent_tooling-0.67.1/prediction_market_agent_tooling/markets/polymarket/api.py
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
import typing as t
|
2
|
+
from enum import Enum
|
3
|
+
from urllib.parse import urljoin
|
4
|
+
|
5
|
+
import httpx
|
6
|
+
import tenacity
|
7
|
+
|
8
|
+
from prediction_market_agent_tooling.loggers import logger
|
9
|
+
from prediction_market_agent_tooling.markets.polymarket.data_models import (
|
10
|
+
POLYMARKET_FALSE_OUTCOME,
|
11
|
+
POLYMARKET_TRUE_OUTCOME,
|
12
|
+
PolymarketGammaResponse,
|
13
|
+
PolymarketGammaResponseDataItem,
|
14
|
+
)
|
15
|
+
from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC
|
16
|
+
from prediction_market_agent_tooling.tools.httpx_cached_client import HttpxCachedClient
|
17
|
+
from prediction_market_agent_tooling.tools.utils import response_to_model
|
18
|
+
|
19
|
+
MARKETS_LIMIT = 100 # Polymarket will only return up to 100 markets
|
20
|
+
POLYMARKET_GAMMA_API_BASE_URL = "https://gamma-api.polymarket.com/"
|
21
|
+
|
22
|
+
|
23
|
+
class PolymarketOrderByEnum(str, Enum):
|
24
|
+
LIQUIDITY = "liquidity"
|
25
|
+
START_DATE = "startDate"
|
26
|
+
END_DATE = "endDate"
|
27
|
+
VOLUME_24HR = "volume24hr"
|
28
|
+
|
29
|
+
|
30
|
+
@tenacity.retry(
|
31
|
+
stop=tenacity.stop_after_attempt(2),
|
32
|
+
wait=tenacity.wait_fixed(1),
|
33
|
+
after=lambda x: logger.debug(
|
34
|
+
f"get_polymarkets_with_pagination failed, {x.attempt_number=}."
|
35
|
+
),
|
36
|
+
)
|
37
|
+
def get_polymarkets_with_pagination(
|
38
|
+
limit: int,
|
39
|
+
created_after: t.Optional[DatetimeUTC] = None,
|
40
|
+
active: bool | None = None,
|
41
|
+
closed: bool | None = None,
|
42
|
+
excluded_questions: set[str] | None = None,
|
43
|
+
only_binary: bool = True,
|
44
|
+
archived: bool = False,
|
45
|
+
ascending: bool = False,
|
46
|
+
order_by: PolymarketOrderByEnum = PolymarketOrderByEnum.VOLUME_24HR,
|
47
|
+
) -> list[PolymarketGammaResponseDataItem]:
|
48
|
+
"""
|
49
|
+
Binary markets have len(model.markets) == 1.
|
50
|
+
Categorical markets have len(model.markets) > 1
|
51
|
+
"""
|
52
|
+
client: httpx.Client = HttpxCachedClient(ttl=60).get_client()
|
53
|
+
all_markets: list[PolymarketGammaResponseDataItem] = []
|
54
|
+
offset = 0
|
55
|
+
remaining = limit
|
56
|
+
|
57
|
+
while remaining > 0:
|
58
|
+
# Calculate how many items to request in this batch (up to MARKETS_LIMIT or remaining)
|
59
|
+
# By default we fetch many markets because not possible to filter by binary/categorical
|
60
|
+
batch_size = MARKETS_LIMIT
|
61
|
+
|
62
|
+
# Build query parameters, excluding None values
|
63
|
+
params = {
|
64
|
+
"limit": batch_size,
|
65
|
+
"active": str(active).lower() if active is not None else None,
|
66
|
+
"archived": str(archived).lower(),
|
67
|
+
"closed": str(closed).lower() if closed is not None else None,
|
68
|
+
"order": order_by.value,
|
69
|
+
"ascending": str(ascending).lower(),
|
70
|
+
"offset": offset,
|
71
|
+
}
|
72
|
+
params_not_none = {k: v for k, v in params.items() if v is not None}
|
73
|
+
url = urljoin(
|
74
|
+
POLYMARKET_GAMMA_API_BASE_URL,
|
75
|
+
f"events/pagination",
|
76
|
+
)
|
77
|
+
|
78
|
+
r = client.get(url, params=params_not_none)
|
79
|
+
r.raise_for_status()
|
80
|
+
|
81
|
+
market_response = response_to_model(r, PolymarketGammaResponse)
|
82
|
+
|
83
|
+
markets_to_add = []
|
84
|
+
for m in market_response.data:
|
85
|
+
if excluded_questions and m.title in excluded_questions:
|
86
|
+
continue
|
87
|
+
|
88
|
+
sorted_outcome_list = sorted(m.markets[0].outcomes_list)
|
89
|
+
if only_binary:
|
90
|
+
# We keep markets that are only Yes,No
|
91
|
+
if len(m.markets) > 1 or sorted_outcome_list != [
|
92
|
+
POLYMARKET_FALSE_OUTCOME,
|
93
|
+
POLYMARKET_TRUE_OUTCOME,
|
94
|
+
]:
|
95
|
+
continue
|
96
|
+
|
97
|
+
if created_after and created_after > m.startDate:
|
98
|
+
continue
|
99
|
+
|
100
|
+
markets_to_add.append(m)
|
101
|
+
|
102
|
+
if only_binary:
|
103
|
+
markets_to_add = [
|
104
|
+
market for market in market_response.data if len(market.markets) == 1
|
105
|
+
]
|
106
|
+
|
107
|
+
# Add the markets from this batch to our results
|
108
|
+
all_markets.extend(markets_to_add)
|
109
|
+
|
110
|
+
# Update counters
|
111
|
+
offset += len(market_response.data)
|
112
|
+
remaining -= len(markets_to_add)
|
113
|
+
|
114
|
+
# Stop if we've reached our limit or there are no more results
|
115
|
+
if (
|
116
|
+
remaining <= 0
|
117
|
+
or not market_response.pagination.hasMore
|
118
|
+
or len(market_response.data) == 0
|
119
|
+
):
|
120
|
+
break
|
121
|
+
|
122
|
+
# Return exactly the number of items requested (in case we got more due to batch size)
|
123
|
+
return all_markets[:limit]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import json
|
2
|
+
|
1
3
|
from pydantic import BaseModel
|
2
4
|
|
3
5
|
from prediction_market_agent_tooling.gtypes import USDC, OutcomeStr, Probability
|
@@ -5,9 +7,9 @@ from prediction_market_agent_tooling.markets.data_models import Resolution
|
|
5
7
|
from prediction_market_agent_tooling.markets.polymarket.data_models_web import (
|
6
8
|
POLYMARKET_FALSE_OUTCOME,
|
7
9
|
POLYMARKET_TRUE_OUTCOME,
|
8
|
-
PolymarketFullMarket,
|
9
10
|
construct_polymarket_url,
|
10
11
|
)
|
12
|
+
from prediction_market_agent_tooling.tools.hexbytes_custom import HexBytes
|
11
13
|
from prediction_market_agent_tooling.tools.utils import DatetimeUTC
|
12
14
|
|
13
15
|
|
@@ -26,6 +28,63 @@ class PolymarketToken(BaseModel):
|
|
26
28
|
winner: bool
|
27
29
|
|
28
30
|
|
31
|
+
class PolymarketGammaMarket(BaseModel):
|
32
|
+
conditionId: HexBytes
|
33
|
+
outcomes: str
|
34
|
+
outcomePrices: str | None = None
|
35
|
+
marketMakerAddress: str
|
36
|
+
createdAt: DatetimeUTC
|
37
|
+
updatedAt: DatetimeUTC | None = None
|
38
|
+
archived: bool
|
39
|
+
questionId: str | None = None
|
40
|
+
clobTokenIds: str | None = None # int-encoded hex
|
41
|
+
|
42
|
+
@property
|
43
|
+
def outcomes_list(self) -> list[OutcomeStr]:
|
44
|
+
return [OutcomeStr(i) for i in json.loads(self.outcomes)]
|
45
|
+
|
46
|
+
@property
|
47
|
+
def outcome_prices(self) -> list[float] | None:
|
48
|
+
if not self.outcomePrices:
|
49
|
+
return None
|
50
|
+
return [float(i) for i in json.loads(self.outcomePrices)]
|
51
|
+
|
52
|
+
|
53
|
+
class PolymarketGammaTag(BaseModel):
|
54
|
+
label: str
|
55
|
+
slug: str
|
56
|
+
|
57
|
+
|
58
|
+
class PolymarketGammaResponseDataItem(BaseModel):
|
59
|
+
id: str
|
60
|
+
slug: str
|
61
|
+
volume: float | None = None
|
62
|
+
startDate: DatetimeUTC
|
63
|
+
endDate: DatetimeUTC | None = None
|
64
|
+
liquidity: float | None = None
|
65
|
+
liquidityClob: float | None = None
|
66
|
+
title: str
|
67
|
+
description: str
|
68
|
+
archived: bool
|
69
|
+
closed: bool
|
70
|
+
active: bool
|
71
|
+
markets: list[PolymarketGammaMarket]
|
72
|
+
tags: list[PolymarketGammaTag]
|
73
|
+
|
74
|
+
@property
|
75
|
+
def url(self) -> str:
|
76
|
+
return construct_polymarket_url(self.slug)
|
77
|
+
|
78
|
+
|
79
|
+
class PolymarketGammaPagination(BaseModel):
|
80
|
+
hasMore: bool
|
81
|
+
|
82
|
+
|
83
|
+
class PolymarketGammaResponse(BaseModel):
|
84
|
+
data: list[PolymarketGammaResponseDataItem]
|
85
|
+
pagination: PolymarketGammaPagination
|
86
|
+
|
87
|
+
|
29
88
|
class PolymarketMarket(BaseModel):
|
30
89
|
enable_order_book: bool
|
31
90
|
active: bool
|
@@ -89,19 +148,6 @@ class PolymarketMarket(BaseModel):
|
|
89
148
|
f"Should not happen, invalid winner tokens: {winner_tokens}"
|
90
149
|
)
|
91
150
|
|
92
|
-
def fetch_full_market(self) -> PolymarketFullMarket | None:
|
93
|
-
return PolymarketFullMarket.fetch_from_url(self.url)
|
94
|
-
|
95
|
-
def fetch_if_its_a_main_market(self) -> bool:
|
96
|
-
# On Polymarket, there are markets that are actually a group of multiple Yes/No markets, for example https://polymarket.com/event/presidential-election-winner-2024.
|
97
|
-
# But API returns them individually, and then we receive questions such as "Will any other Republican Politician win the 2024 US Presidential Election?",
|
98
|
-
# which are naturally unpredictable without futher details.
|
99
|
-
# This is a heuristic to filter them out.
|
100
|
-
# Warning: This is a very slow operation, as it requires fetching the website. Use it only when necessary.
|
101
|
-
full_market = self.fetch_full_market()
|
102
|
-
# `full_market` can be None, if this class come from a multiple Yes/No market, becase then, the constructed URL is invalid (and there is now way to construct an valid one from the data we have).
|
103
|
-
return full_market is not None and full_market.is_main_market
|
104
|
-
|
105
151
|
|
106
152
|
class MarketsEndpointResponse(BaseModel):
|
107
153
|
limit: int
|
@@ -5,14 +5,11 @@ Keep in mind that not all fields were used so far, so there might be some bugs.
|
|
5
5
|
These models are based on what Polymarket's website returns in the response, and `prediction_market_agent_tooling/markets/polymarket/data_models.py` are based on what their API returns.
|
6
6
|
"""
|
7
7
|
|
8
|
-
import json
|
9
8
|
import typing as t
|
10
9
|
|
11
|
-
import requests
|
12
10
|
from pydantic import BaseModel, field_validator
|
13
11
|
|
14
12
|
from prediction_market_agent_tooling.gtypes import USDC, HexAddress, OutcomeStr
|
15
|
-
from prediction_market_agent_tooling.loggers import logger
|
16
13
|
from prediction_market_agent_tooling.markets.data_models import Resolution
|
17
14
|
from prediction_market_agent_tooling.tools.utils import DatetimeUTC
|
18
15
|
|
@@ -293,57 +290,6 @@ class PolymarketFullMarket(BaseModel):
|
|
293
290
|
)
|
294
291
|
return self.markets[0]
|
295
292
|
|
296
|
-
@staticmethod
|
297
|
-
def fetch_from_url(url: str) -> "PolymarketFullMarket | None":
|
298
|
-
"""
|
299
|
-
Get the full market data from the Polymarket website.
|
300
|
-
|
301
|
-
Returns None if this market's url returns "Oops...we didn't forecast this", see `check_if_its_a_main_market` method for more details.
|
302
|
-
|
303
|
-
Warning: This is a very slow operation, as it requires fetching the website. Use it only when necessary.
|
304
|
-
"""
|
305
|
-
logger.info(f"Fetching full market from {url}")
|
306
|
-
|
307
|
-
# Fetch the website as a normal browser would.
|
308
|
-
headers = {
|
309
|
-
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
|
310
|
-
}
|
311
|
-
content = requests.get(url, headers=headers).text
|
312
|
-
|
313
|
-
# Find the JSON with the data within the content.
|
314
|
-
start_tag = """<script id="__NEXT_DATA__" type="application/json" crossorigin="anonymous">"""
|
315
|
-
start_idx = content.find(start_tag) + len(start_tag)
|
316
|
-
end_idx = content.find("</script>", start_idx)
|
317
|
-
response_data = content[start_idx:end_idx]
|
318
|
-
|
319
|
-
# Parsing.
|
320
|
-
response_dict = json.loads(response_data)
|
321
|
-
response_model = PolymarketWebResponse.model_validate(response_dict)
|
322
|
-
|
323
|
-
full_market_queries = [
|
324
|
-
q
|
325
|
-
for q in response_model.props.pageProps.dehydratedState.queries
|
326
|
-
if isinstance(q.state.data, PolymarketFullMarket)
|
327
|
-
]
|
328
|
-
|
329
|
-
# We expect either 0 markets (if it doesn't exist) or 1 market.
|
330
|
-
if len(full_market_queries) not in (0, 1):
|
331
|
-
raise ValueError(
|
332
|
-
f"Unexpected number of queries in the response, please check it out and modify the code accordingly: `{response_dict}`"
|
333
|
-
)
|
334
|
-
|
335
|
-
# It will be `PolymarketFullMarket` thanks to the filter above.
|
336
|
-
market = (
|
337
|
-
t.cast(PolymarketFullMarket, full_market_queries[0].state.data)
|
338
|
-
if full_market_queries
|
339
|
-
else None
|
340
|
-
)
|
341
|
-
|
342
|
-
if market is None:
|
343
|
-
logger.warning(f"No polymarket found for {url}")
|
344
|
-
|
345
|
-
return market
|
346
|
-
|
347
293
|
|
348
294
|
class PriceSide(BaseModel):
|
349
295
|
price: USDC
|
@@ -0,0 +1,173 @@
|
|
1
|
+
import typing as t
|
2
|
+
|
3
|
+
from prediction_market_agent_tooling.gtypes import (
|
4
|
+
USD,
|
5
|
+
CollateralToken,
|
6
|
+
HexBytes,
|
7
|
+
OutcomeStr,
|
8
|
+
Probability,
|
9
|
+
)
|
10
|
+
from prediction_market_agent_tooling.markets.agent_market import (
|
11
|
+
AgentMarket,
|
12
|
+
FilterBy,
|
13
|
+
MarketFees,
|
14
|
+
MarketType,
|
15
|
+
SortBy,
|
16
|
+
)
|
17
|
+
from prediction_market_agent_tooling.markets.data_models import Resolution
|
18
|
+
from prediction_market_agent_tooling.markets.polymarket.api import (
|
19
|
+
PolymarketOrderByEnum,
|
20
|
+
get_polymarkets_with_pagination,
|
21
|
+
)
|
22
|
+
from prediction_market_agent_tooling.markets.polymarket.data_models import (
|
23
|
+
PolymarketGammaResponseDataItem,
|
24
|
+
)
|
25
|
+
from prediction_market_agent_tooling.markets.polymarket.data_models_web import (
|
26
|
+
POLYMARKET_BASE_URL,
|
27
|
+
)
|
28
|
+
from prediction_market_agent_tooling.markets.polymarket.polymarket_subgraph_handler import (
|
29
|
+
ConditionSubgraphModel,
|
30
|
+
PolymarketSubgraphHandler,
|
31
|
+
)
|
32
|
+
from prediction_market_agent_tooling.tools.datetime_utc import DatetimeUTC
|
33
|
+
|
34
|
+
|
35
|
+
class PolymarketAgentMarket(AgentMarket):
|
36
|
+
"""
|
37
|
+
Polymarket's market class that can be used by agents to make predictions.
|
38
|
+
"""
|
39
|
+
|
40
|
+
base_url: t.ClassVar[str] = POLYMARKET_BASE_URL
|
41
|
+
|
42
|
+
# Based on https://docs.polymarket.com/#fees, there are currently no fees, except for transactions fees.
|
43
|
+
# However they do have `maker_fee_base_rate` and `taker_fee_base_rate`, but impossible to test out our implementation without them actually taking the fees.
|
44
|
+
# But then in the new subgraph API, they have `fee: BigInt! (Percentage fee of trades taken by market maker. A 2% fee is represented as 2*10^16)`.
|
45
|
+
# TODO: Check out the fees while integrating the subgraph API or if we implement placing of bets on Polymarket.
|
46
|
+
fees: MarketFees = MarketFees.get_zero_fees()
|
47
|
+
|
48
|
+
@staticmethod
|
49
|
+
def build_resolution_from_condition(
|
50
|
+
condition_id: HexBytes,
|
51
|
+
condition_model_dict: dict[HexBytes, ConditionSubgraphModel],
|
52
|
+
outcomes: list[OutcomeStr],
|
53
|
+
) -> Resolution | None:
|
54
|
+
condition_model = condition_model_dict.get(condition_id)
|
55
|
+
if (
|
56
|
+
not condition_model
|
57
|
+
or condition_model.resolutionTimestamp is None
|
58
|
+
or not condition_model.payoutNumerators
|
59
|
+
or not condition_model.payoutDenominator
|
60
|
+
):
|
61
|
+
return None
|
62
|
+
|
63
|
+
# Currently we only support binary markets, hence we throw an error if we get something else.
|
64
|
+
payout_numerator_indices_gt_0 = [
|
65
|
+
idx
|
66
|
+
for idx, value in enumerate(condition_model.payoutNumerators)
|
67
|
+
if value > 0
|
68
|
+
]
|
69
|
+
# For a binary market, there should be exactly one payout numerator greater than 0.
|
70
|
+
if len(payout_numerator_indices_gt_0) != 1:
|
71
|
+
raise ValueError(
|
72
|
+
f"Only binary markets are supported. Got payout numerators: {condition_model.payoutNumerators}"
|
73
|
+
)
|
74
|
+
|
75
|
+
# we return the only payout numerator greater than 0 as resolution
|
76
|
+
resolved_outcome = outcomes[payout_numerator_indices_gt_0[0]]
|
77
|
+
return Resolution.from_answer(resolved_outcome)
|
78
|
+
|
79
|
+
@staticmethod
|
80
|
+
def from_data_model(
|
81
|
+
model: PolymarketGammaResponseDataItem,
|
82
|
+
condition_model_dict: dict[HexBytes, ConditionSubgraphModel],
|
83
|
+
) -> "PolymarketAgentMarket":
|
84
|
+
# If len(model.markets) > 0, this denotes a categorical market.
|
85
|
+
|
86
|
+
outcomes = model.markets[0].outcomes_list
|
87
|
+
outcome_prices = model.markets[0].outcome_prices
|
88
|
+
if not outcome_prices:
|
89
|
+
# We give random prices
|
90
|
+
outcome_prices = [0.5, 0.5]
|
91
|
+
probabilities = {o: Probability(op) for o, op in zip(outcomes, outcome_prices)}
|
92
|
+
|
93
|
+
resolution = PolymarketAgentMarket.build_resolution_from_condition(
|
94
|
+
condition_id=model.markets[0].conditionId,
|
95
|
+
condition_model_dict=condition_model_dict,
|
96
|
+
outcomes=outcomes,
|
97
|
+
)
|
98
|
+
|
99
|
+
return PolymarketAgentMarket(
|
100
|
+
id=model.id,
|
101
|
+
question=model.title,
|
102
|
+
description=model.description,
|
103
|
+
outcomes=outcomes,
|
104
|
+
resolution=resolution,
|
105
|
+
created_time=model.startDate,
|
106
|
+
close_time=model.endDate,
|
107
|
+
url=model.url,
|
108
|
+
volume=CollateralToken(model.volume) if model.volume else None,
|
109
|
+
outcome_token_pool=None,
|
110
|
+
probabilities=probabilities,
|
111
|
+
)
|
112
|
+
|
113
|
+
def get_tiny_bet_amount(self) -> CollateralToken:
|
114
|
+
raise NotImplementedError("TODO: Implement to allow betting on Polymarket.")
|
115
|
+
|
116
|
+
def place_bet(self, outcome: OutcomeStr, amount: USD) -> str:
|
117
|
+
raise NotImplementedError("TODO: Implement to allow betting on Polymarket.")
|
118
|
+
|
119
|
+
@staticmethod
|
120
|
+
def get_markets(
|
121
|
+
limit: int,
|
122
|
+
sort_by: SortBy = SortBy.NONE,
|
123
|
+
filter_by: FilterBy = FilterBy.OPEN,
|
124
|
+
created_after: t.Optional[DatetimeUTC] = None,
|
125
|
+
excluded_questions: set[str] | None = None,
|
126
|
+
market_type: MarketType = MarketType.ALL,
|
127
|
+
include_conditional_markets: bool = False,
|
128
|
+
) -> t.Sequence["PolymarketAgentMarket"]:
|
129
|
+
closed: bool | None
|
130
|
+
|
131
|
+
if filter_by == FilterBy.OPEN:
|
132
|
+
closed = False
|
133
|
+
elif filter_by == FilterBy.RESOLVED:
|
134
|
+
closed = True
|
135
|
+
elif filter_by == FilterBy.NONE:
|
136
|
+
closed = None
|
137
|
+
else:
|
138
|
+
raise ValueError(f"Unknown filter_by: {filter_by}")
|
139
|
+
|
140
|
+
ascending: bool = False # default value
|
141
|
+
match sort_by:
|
142
|
+
case SortBy.NEWEST:
|
143
|
+
order_by = PolymarketOrderByEnum.START_DATE
|
144
|
+
case SortBy.CLOSING_SOONEST:
|
145
|
+
ascending = True
|
146
|
+
order_by = PolymarketOrderByEnum.END_DATE
|
147
|
+
case SortBy.HIGHEST_LIQUIDITY:
|
148
|
+
order_by = PolymarketOrderByEnum.LIQUIDITY
|
149
|
+
case SortBy.NONE:
|
150
|
+
order_by = PolymarketOrderByEnum.VOLUME_24HR
|
151
|
+
case _:
|
152
|
+
raise ValueError(f"Unknown sort_by: {sort_by}")
|
153
|
+
|
154
|
+
# closed markets also have property active=True, hence ignoring active.
|
155
|
+
markets = get_polymarkets_with_pagination(
|
156
|
+
limit=limit,
|
157
|
+
closed=closed,
|
158
|
+
order_by=order_by,
|
159
|
+
ascending=ascending,
|
160
|
+
created_after=created_after,
|
161
|
+
excluded_questions=excluded_questions,
|
162
|
+
only_binary=market_type is not MarketType.CATEGORICAL,
|
163
|
+
)
|
164
|
+
|
165
|
+
condition_models = PolymarketSubgraphHandler().get_conditions(
|
166
|
+
condition_ids=[market.markets[0].conditionId for market in markets]
|
167
|
+
)
|
168
|
+
condition_models_dict = {c.id: c for c in condition_models}
|
169
|
+
|
170
|
+
return [
|
171
|
+
PolymarketAgentMarket.from_data_model(m, condition_models_dict)
|
172
|
+
for m in markets
|
173
|
+
]
|