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