prediction-market-agent-tooling 0.40.0__tar.gz → 0.41.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/PKG-INFO +1 -1
  2. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/config.py +14 -0
  3. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/markets.py +5 -0
  4. prediction_market_agent_tooling-0.41.1/prediction_market_agent_tooling/markets/metaculus/api.py +95 -0
  5. prediction_market_agent_tooling-0.41.1/prediction_market_agent_tooling/markets/metaculus/data_models.py +96 -0
  6. prediction_market_agent_tooling-0.41.1/prediction_market_agent_tooling/markets/metaculus/metaculus.py +102 -0
  7. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/omen/omen.py +5 -1
  8. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +1 -4
  9. prediction_market_agent_tooling-0.41.1/prediction_market_agent_tooling/monitor/markets/metaculus.py +43 -0
  10. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/monitor/monitor_app.py +4 -0
  11. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/pyproject.toml +1 -1
  12. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/LICENSE +0 -0
  13. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/README.md +0 -0
  14. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  15. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  16. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  17. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  18. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  19. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  20. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  21. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  22. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  23. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/abis/wxdai.abi.json +0 -0
  24. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  25. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  26. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
  27. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  28. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/deploy/agent.py +0 -0
  29. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  30. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  31. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  32. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  33. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  34. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/gtypes.py +0 -0
  35. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/loggers.py +0 -0
  36. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/agent_market.py +0 -0
  37. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  38. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/data_models.py +0 -0
  39. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  40. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  41. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  42. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  43. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  44. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  45. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/omen/data_models.py +0 -0
  46. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
  47. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
  48. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
  49. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
  50. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
  51. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
  52. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  53. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/monitor/langfuse/langfuse_wrapper.py +0 -0
  54. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/monitor/markets/manifold.py +0 -0
  55. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/monitor/markets/omen.py +0 -0
  56. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -0
  57. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/monitor/monitor.py +0 -0
  58. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/monitor/monitor_settings.py +0 -0
  59. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/py.typed +0 -0
  60. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/balances.py +0 -0
  61. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
  62. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -0
  63. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -0
  64. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  65. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/cache.py +0 -0
  66. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/contract.py +0 -0
  67. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/costs.py +0 -0
  68. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/gnosis_rpc.py +0 -0
  69. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/google.py +0 -0
  70. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
  71. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  72. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  73. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
  74. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  75. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/safe.py +0 -0
  76. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/singleton.py +0 -0
  77. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  78. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/utils.py +0 -0
  79. {prediction_market_agent_tooling-0.40.0 → prediction_market_agent_tooling-0.41.1}/prediction_market_agent_tooling/tools/web3_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.40.0
3
+ Version: 0.41.1
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -24,6 +24,8 @@ class APIKeys(BaseSettings):
24
24
  )
25
25
 
26
26
  MANIFOLD_API_KEY: t.Optional[SecretStr] = None
27
+ METACULUS_API_KEY: t.Optional[SecretStr] = None
28
+ METACULUS_USER_ID: t.Optional[int] = None
27
29
  BET_FROM_PRIVATE_KEY: t.Optional[PrivateKey] = None
28
30
  SAFE_ADDRESS: t.Optional[ChecksumAddress] = None
29
31
  OPENAI_API_KEY: t.Optional[SecretStr] = None
@@ -51,6 +53,18 @@ class APIKeys(BaseSettings):
51
53
  self.MANIFOLD_API_KEY, "MANIFOLD_API_KEY missing in the environment."
52
54
  )
53
55
 
56
+ @property
57
+ def metaculus_api_key(self) -> SecretStr:
58
+ return check_not_none(
59
+ self.METACULUS_API_KEY, "METACULUS_API_KEY missing in the environment."
60
+ )
61
+
62
+ @property
63
+ def metaculus_user_id(self) -> int:
64
+ return check_not_none(
65
+ self.METACULUS_USER_ID, "METACULUS_USER_ID missing in the environment."
66
+ )
67
+
54
68
  @property
55
69
  def bet_from_private_key(self) -> PrivateKey:
56
70
  return check_not_none(
@@ -16,6 +16,9 @@ from prediction_market_agent_tooling.markets.manifold.api import (
16
16
  from prediction_market_agent_tooling.markets.manifold.manifold import (
17
17
  ManifoldAgentMarket,
18
18
  )
19
+ from prediction_market_agent_tooling.markets.metaculus.metaculus import (
20
+ MetaculusAgentMarket,
21
+ )
19
22
  from prediction_market_agent_tooling.markets.omen.omen import OmenAgentMarket
20
23
  from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
21
24
  OmenSubgraphHandler,
@@ -30,6 +33,7 @@ class MarketType(str, Enum):
30
33
  MANIFOLD = "manifold"
31
34
  OMEN = "omen"
32
35
  POLYMARKET = "polymarket"
36
+ METACULUS = "metaculus"
33
37
 
34
38
  @property
35
39
  def market_class(self) -> type[AgentMarket]:
@@ -42,6 +46,7 @@ MARKET_TYPE_TO_AGENT_MARKET: dict[MarketType, type[AgentMarket]] = {
42
46
  MarketType.MANIFOLD: ManifoldAgentMarket,
43
47
  MarketType.OMEN: OmenAgentMarket,
44
48
  MarketType.POLYMARKET: PolymarketAgentMarket,
49
+ MarketType.METACULUS: MetaculusAgentMarket,
45
50
  }
46
51
 
47
52
 
@@ -0,0 +1,95 @@
1
+ from datetime import datetime
2
+ from typing import Union
3
+
4
+ import requests
5
+
6
+ from prediction_market_agent_tooling.config import APIKeys
7
+ from prediction_market_agent_tooling.gtypes import Probability
8
+ from prediction_market_agent_tooling.markets.metaculus.data_models import (
9
+ MetaculusQuestion,
10
+ MetaculusQuestions,
11
+ )
12
+ from prediction_market_agent_tooling.tools.utils import response_to_model
13
+
14
+ METACULUS_API_BASE_URL = "https://www.metaculus.com/api2"
15
+
16
+
17
+ def get_auth_headers() -> dict[str, str]:
18
+ return {"Authorization": f"Token {APIKeys().metaculus_api_key.get_secret_value()}"}
19
+
20
+
21
+ def post_question_comment(question_id: str, comment_text: str) -> None:
22
+ """
23
+ Post a comment on the question page as the bot user.
24
+ """
25
+
26
+ response = requests.post(
27
+ f"{METACULUS_API_BASE_URL}/comments/",
28
+ json={
29
+ "comment_text": comment_text,
30
+ "submit_type": "N",
31
+ "include_latest_prediction": True,
32
+ "question": question_id,
33
+ },
34
+ headers=get_auth_headers(),
35
+ )
36
+ response.raise_for_status()
37
+
38
+
39
+ def make_prediction(question_id: str, p_yes: Probability) -> None:
40
+ """
41
+ Make a prediction for a question.
42
+ """
43
+ url = f"{METACULUS_API_BASE_URL}/questions/{question_id}/predict/"
44
+ response = requests.post(
45
+ url,
46
+ json={"prediction": p_yes},
47
+ headers=get_auth_headers(),
48
+ )
49
+ response.raise_for_status()
50
+
51
+
52
+ def get_question(question_id: str) -> MetaculusQuestion:
53
+ """
54
+ Get all details about a specific question.
55
+ """
56
+ url = f"{METACULUS_API_BASE_URL}/questions/{question_id}/"
57
+ return response_to_model(
58
+ response=requests.get(url, headers=get_auth_headers()),
59
+ model=MetaculusQuestion,
60
+ )
61
+
62
+
63
+ def get_questions(
64
+ limit: int,
65
+ order_by: str | None = None,
66
+ offset: int = 0,
67
+ tournament_id: int | None = None,
68
+ created_after: datetime | None = None,
69
+ status: str | None = None,
70
+ ) -> list[MetaculusQuestion]:
71
+ """
72
+ List detailed metaculus questions (i.e. markets)
73
+ """
74
+ url_params: dict[str, Union[int, str]] = {
75
+ "limit": limit,
76
+ "offset": offset,
77
+ "has_group": "false",
78
+ "forecast_type": "binary",
79
+ "type": "forecast",
80
+ "include_description": "true",
81
+ }
82
+ if order_by:
83
+ url_params["order_by"] = order_by
84
+ if tournament_id:
85
+ url_params["project"] = tournament_id
86
+ if created_after:
87
+ url_params["created_time__gt"] = created_after.isoformat()
88
+ if status:
89
+ url_params["status"] = status
90
+
91
+ url = f"{METACULUS_API_BASE_URL}/questions/"
92
+ return response_to_model(
93
+ response=requests.get(url, headers=get_auth_headers(), params=url_params),
94
+ model=MetaculusQuestions,
95
+ ).results
@@ -0,0 +1,96 @@
1
+ from datetime import datetime
2
+ from enum import Enum
3
+ from typing import Any
4
+
5
+ from pydantic import BaseModel
6
+
7
+
8
+ class QuestionType(str, Enum):
9
+ forecast = "forecast"
10
+ notebook = "notebook"
11
+ discussion = "discussion"
12
+ claim = "claim"
13
+ group = "group"
14
+ conditional_group = "conditional_group"
15
+ multiple_choice = "multiple_choice"
16
+
17
+
18
+ class CommunityPrediction(BaseModel):
19
+ y: list[float]
20
+ q1: float | None = None
21
+ q2: float | None = None
22
+ q3: float | None = None
23
+
24
+ @property
25
+ def p_yes(self) -> float:
26
+ """
27
+ q2 corresponds to the median, or 'second quartile' of the distribution.
28
+
29
+ If no value is provided (i.e. the question is new and has not been
30
+ answered yet), we default to 0.5.
31
+ """
32
+ return self.q2 if self.q2 is not None else 0.5
33
+
34
+
35
+ class Prediction(BaseModel):
36
+ t: datetime
37
+ x: float
38
+
39
+
40
+ class UserPredictions(BaseModel):
41
+ id: int
42
+ predictions: list[Prediction]
43
+ points_won: float | None = None
44
+ user: int
45
+ username: str
46
+ question: int
47
+
48
+
49
+ class CommunityPredictionStats(BaseModel):
50
+ full: CommunityPrediction
51
+ unweighted: CommunityPrediction
52
+
53
+
54
+ class MetaculusQuestion(BaseModel):
55
+ """
56
+ https://www.metaculus.com/api2/schema/redoc/#tag/questions/operation/questions_retrieve
57
+ """
58
+
59
+ active_state: Any
60
+ url: str
61
+ page_url: str
62
+ id: int
63
+ author: int
64
+ author_name: str
65
+ author_id: int
66
+ title: str
67
+ title_short: str
68
+ group_label: str | None = None
69
+ resolution: int | None
70
+ resolved_option: int | None
71
+ created_time: datetime
72
+ publish_time: datetime | None = None
73
+ close_time: datetime | None = None
74
+ effected_close_time: datetime | None
75
+ resolve_time: datetime | None = None
76
+ possibilities: dict[Any, Any] | None = None
77
+ scoring: dict[Any, Any] = {}
78
+ type: QuestionType | None = None
79
+ user_perms: Any
80
+ weekly_movement: float | None
81
+ weekly_movement_direction: int | None = None
82
+ cp_reveal_time: datetime | None = None
83
+ edited_time: datetime
84
+ last_activity_time: datetime
85
+ activity: float
86
+ comment_count: int
87
+ votes: int
88
+ community_prediction: CommunityPredictionStats
89
+ my_predictions: UserPredictions | None = None
90
+ # TODO add the rest of the fields https://github.com/gnosis/prediction-market-agent-tooling/issues/301
91
+
92
+
93
+ class MetaculusQuestions(BaseModel):
94
+ next: str | None
95
+ previous: str | None
96
+ results: list[MetaculusQuestion]
@@ -0,0 +1,102 @@
1
+ import typing as t
2
+ from datetime import datetime
3
+
4
+ from prediction_market_agent_tooling.gtypes import Probability
5
+ from prediction_market_agent_tooling.markets.agent_market import (
6
+ AgentMarket,
7
+ FilterBy,
8
+ SortBy,
9
+ )
10
+ from prediction_market_agent_tooling.markets.metaculus.api import (
11
+ METACULUS_API_BASE_URL,
12
+ get_questions,
13
+ make_prediction,
14
+ post_question_comment,
15
+ )
16
+ from prediction_market_agent_tooling.markets.metaculus.data_models import (
17
+ MetaculusQuestion,
18
+ )
19
+
20
+
21
+ class MetaculusAgentMarket(AgentMarket):
22
+ """
23
+ Metaculus' market class that can be used by agents to make predictions.
24
+ """
25
+
26
+ have_predicted: bool
27
+ base_url: t.ClassVar[str] = METACULUS_API_BASE_URL
28
+
29
+ @staticmethod
30
+ def from_data_model(model: MetaculusQuestion) -> "MetaculusAgentMarket":
31
+ return MetaculusAgentMarket(
32
+ id=str(model.id),
33
+ question=model.title,
34
+ outcomes=[],
35
+ resolution=None,
36
+ current_p_yes=Probability(model.community_prediction.full.p_yes),
37
+ created_time=model.created_time,
38
+ close_time=model.close_time,
39
+ url=model.url,
40
+ volume=None,
41
+ have_predicted=model.my_predictions is not None
42
+ and len(model.my_predictions.predictions) > 0,
43
+ )
44
+
45
+ @staticmethod
46
+ def get_binary_markets(
47
+ limit: int,
48
+ sort_by: SortBy = SortBy.NONE,
49
+ filter_by: FilterBy = FilterBy.OPEN,
50
+ created_after: t.Optional[datetime] = None,
51
+ excluded_questions: set[str] | None = None,
52
+ tournament_id: int | None = None,
53
+ ) -> t.Sequence["MetaculusAgentMarket"]:
54
+ order_by: str | None
55
+ if sort_by == SortBy.NONE:
56
+ order_by = None
57
+ elif sort_by == SortBy.CLOSING_SOONEST:
58
+ order_by = "-close_time"
59
+ elif sort_by == SortBy.NEWEST:
60
+ order_by = "-created_time"
61
+ else:
62
+ raise ValueError(f"Unknown sort_by: {sort_by}")
63
+
64
+ status: str | None
65
+ if filter_by == FilterBy.OPEN:
66
+ status = "open"
67
+ elif filter_by == FilterBy.RESOLVED:
68
+ status = "resolved"
69
+ elif filter_by == FilterBy.NONE:
70
+ status = None
71
+ else:
72
+ raise ValueError(f"Unknown filter_by: {filter_by}")
73
+
74
+ if excluded_questions:
75
+ raise NotImplementedError(
76
+ "Excluded questions are not suppoerted for Metaculus markets yet."
77
+ )
78
+
79
+ offset = 0
80
+ question_page_size = 500
81
+ all_questions = []
82
+ while True:
83
+ questions = get_questions(
84
+ limit=question_page_size,
85
+ offset=offset,
86
+ order_by=order_by,
87
+ created_after=created_after,
88
+ status=status,
89
+ tournament_id=tournament_id,
90
+ )
91
+ if not questions:
92
+ break
93
+ all_questions.extend(questions)
94
+ offset += question_page_size
95
+
96
+ if len(all_questions) >= limit:
97
+ break
98
+ return [MetaculusAgentMarket.from_data_model(q) for q in all_questions]
99
+
100
+ def submit_prediction(self, p_yes: Probability, reasoning: str) -> None:
101
+ make_prediction(self.id, p_yes)
102
+ post_question_comment(self.id, reasoning)
@@ -489,7 +489,11 @@ class OmenAgentMarket(AgentMarket):
489
489
 
490
490
  @classmethod
491
491
  def get_user_url(cls, keys: APIKeys) -> str:
492
- return f"https://gnosisscan.io/address/{keys.bet_from_address}"
492
+ return get_omen_user_url(keys.bet_from_address)
493
+
494
+
495
+ def get_omen_user_url(address: ChecksumAddress) -> str:
496
+ return f"https://gnosisscan.io/address/{address}"
493
497
 
494
498
 
495
499
  def pick_binary_market(
@@ -45,10 +45,7 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
45
45
 
46
46
  REALITYETH_GRAPH_URL = "https://gateway-arbitrum.network.thegraph.com/api/{graph_api_key}/subgraphs/id/E7ymrCnNcQdAAgLbdFWzGE5mvr5Mb5T9VfT43FqA7bNh"
47
47
 
48
- # TODO: Switch to arbitrum subgraph once it's published.
49
- OMEN_IMAGE_MAPPING_GRAPH_URL = (
50
- "https://api.studio.thegraph.com/query/63564/omen-thumbnailmapping/v0.0.3"
51
- )
48
+ OMEN_IMAGE_MAPPING_GRAPH_URL = "https://gateway-arbitrum.network.thegraph.com/api/{graph_api_key}/subgraphs/id/EWN14ciGK53PpUiKSm7kMWQ6G4iz3tDrRLyZ1iXMQEdu"
52
49
 
53
50
  INVALID_ANSWER = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
54
51
 
@@ -0,0 +1,43 @@
1
+ import typing as t
2
+
3
+ from google.cloud.functions_v2.types.functions import Function
4
+
5
+ from prediction_market_agent_tooling.config import APIKeys
6
+ from prediction_market_agent_tooling.deploy.constants import MARKET_TYPE_KEY
7
+ from prediction_market_agent_tooling.gtypes import DatetimeWithTimezone
8
+ from prediction_market_agent_tooling.markets.data_models import ResolvedBet
9
+ from prediction_market_agent_tooling.markets.markets import MarketType
10
+ from prediction_market_agent_tooling.monitor.monitor import DeployedAgent
11
+
12
+
13
+ class DeployedMetaculusAgent(DeployedAgent):
14
+ user: int
15
+
16
+ @property
17
+ def public_id(self) -> str:
18
+ return str(self.user)
19
+
20
+ def get_resolved_bets(self) -> list[ResolvedBet]:
21
+ raise NotImplementedError("TODO: Implement to allow betting on Metaculus.")
22
+
23
+ @staticmethod
24
+ def from_api_keys(
25
+ name: str,
26
+ start_time: DatetimeWithTimezone,
27
+ api_keys: APIKeys,
28
+ ) -> "DeployedMetaculusAgent":
29
+ return DeployedMetaculusAgent(
30
+ name=name,
31
+ start_time=start_time,
32
+ user=api_keys.metaculus_user_id,
33
+ )
34
+
35
+ @classmethod
36
+ def from_all_gcp_functions(
37
+ cls: t.Type["DeployedMetaculusAgent"],
38
+ filter_: t.Callable[[Function], bool] = lambda function: function.labels[
39
+ MARKET_TYPE_KEY
40
+ ]
41
+ == MarketType.METACULUS.value,
42
+ ) -> t.Sequence["DeployedMetaculusAgent"]:
43
+ return super().from_all_gcp_functions(filter_=filter_)
@@ -13,6 +13,9 @@ from prediction_market_agent_tooling.markets.markets import MarketType
13
13
  from prediction_market_agent_tooling.monitor.markets.manifold import (
14
14
  DeployedManifoldAgent,
15
15
  )
16
+ from prediction_market_agent_tooling.monitor.markets.metaculus import (
17
+ DeployedMetaculusAgent,
18
+ )
16
19
  from prediction_market_agent_tooling.monitor.markets.omen import DeployedOmenAgent
17
20
  from prediction_market_agent_tooling.monitor.markets.polymarket import (
18
21
  DeployedPolymarketAgent,
@@ -36,6 +39,7 @@ MARKET_TYPE_TO_DEPLOYED_AGENT: dict[MarketType, type[DeployedAgent]] = {
36
39
  MarketType.MANIFOLD: DeployedManifoldAgent,
37
40
  MarketType.OMEN: DeployedOmenAgent,
38
41
  MarketType.POLYMARKET: DeployedPolymarketAgent,
42
+ MarketType.METACULUS: DeployedMetaculusAgent,
39
43
  }
40
44
 
41
45
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "prediction-market-agent-tooling"
3
- version = "0.40.0"
3
+ version = "0.41.1"
4
4
  description = "Tools to benchmark, deploy and monitor prediction market agents."
5
5
  authors = ["Gnosis"]
6
6
  readme = "README.md"