prediction-market-agent-tooling 0.50.1__tar.gz → 0.51.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 (98) hide show
  1. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/PKG-INFO +1 -1
  2. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/deploy/agent.py +5 -0
  3. prediction_market_agent_tooling-0.51.1/prediction_market_agent_tooling/markets/metaculus/data_models.py +104 -0
  4. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +5 -6
  5. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/omen/data_models.py +21 -8
  6. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +4 -6
  7. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +6 -13
  8. prediction_market_agent_tooling-0.51.1/prediction_market_agent_tooling/tools/is_invalid.py +92 -0
  9. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/utils.py +3 -1
  10. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/pyproject.toml +1 -1
  11. prediction_market_agent_tooling-0.50.1/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -97
  12. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/LICENSE +0 -0
  13. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/README.md +0 -0
  14. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +0 -0
  15. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
  16. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  17. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
  18. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_agentresultmapping.abi.json +0 -0
  19. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  20. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  21. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  22. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  23. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  24. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  25. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  26. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  27. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
  28. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  29. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  30. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
  31. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  32. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/config.py +0 -0
  33. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  34. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/deploy/betting_strategy.py +0 -0
  35. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  36. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  37. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  38. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  39. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/gtypes.py +0 -0
  40. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
  41. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/jobs/jobs.py +0 -0
  42. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/jobs/jobs_models.py +0 -0
  43. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +0 -0
  44. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/loggers.py +0 -0
  45. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/agent_market.py +0 -0
  46. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  47. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/data_models.py +0 -0
  48. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  49. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  50. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  51. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  52. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  53. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/markets.py +0 -0
  54. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
  55. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  56. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/omen/omen.py +0 -0
  57. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
  58. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
  59. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
  60. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
  61. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
  62. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  63. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/monitor/markets/manifold.py +0 -0
  64. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/monitor/markets/metaculus.py +0 -0
  65. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/monitor/markets/omen.py +0 -0
  66. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -0
  67. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/monitor/monitor.py +0 -0
  68. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/monitor/monitor_app.py +0 -0
  69. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/monitor/monitor_settings.py +0 -0
  70. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/py.typed +0 -0
  71. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/balances.py +0 -0
  72. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
  73. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -0
  74. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -0
  75. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  76. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +0 -0
  77. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/cache.py +0 -0
  78. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/contract.py +0 -0
  79. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/costs.py +0 -0
  80. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/datetime_utc.py +0 -0
  81. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/gnosis_rpc.py +0 -0
  82. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/google.py +0 -0
  83. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
  84. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/httpx_cached_client.py +0 -0
  85. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  86. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  87. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +0 -0
  88. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/is_predictable.py +0 -0
  89. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
  90. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +0 -0
  91. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
  92. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  93. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/safe.py +0 -0
  94. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/singleton.py +0 -0
  95. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  96. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py +0 -0
  97. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.1}/prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py +0 -0
  98. {prediction_market_agent_tooling-0.50.1 → prediction_market_agent_tooling-0.51.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.50.1
3
+ Version: 0.51.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
@@ -66,6 +66,7 @@ from prediction_market_agent_tooling.monitor.monitor_app import (
66
66
  )
67
67
  from prediction_market_agent_tooling.tools.hexbytes_custom import HexBytes
68
68
  from prediction_market_agent_tooling.tools.ipfs.ipfs_handler import IPFSHandler
69
+ from prediction_market_agent_tooling.tools.is_invalid import is_invalid
69
70
  from prediction_market_agent_tooling.tools.is_predictable import is_predictable_binary
70
71
  from prediction_market_agent_tooling.tools.langfuse_ import langfuse_context, observe
71
72
  from prediction_market_agent_tooling.tools.utils import DatetimeUTC, utcnow
@@ -295,6 +296,7 @@ class DeployableTraderAgent(DeployableAgent):
295
296
  bet_on_n_markets_per_run: int = 1
296
297
  min_required_balance_to_operate: xDai | None = xdai_type(1)
297
298
  min_balance_to_keep_in_native_currency: xDai | None = xdai_type(0.1)
299
+ allow_invalid_questions: bool = False
298
300
 
299
301
  def __init__(
300
302
  self,
@@ -403,6 +405,9 @@ class DeployableTraderAgent(DeployableAgent):
403
405
  if not is_predictable_binary(market.question):
404
406
  return False
405
407
 
408
+ if not self.allow_invalid_questions and is_invalid(market.question):
409
+ return False
410
+
406
411
  return True
407
412
 
408
413
  def answer_binary_market(self, market: AgentMarket) -> ProbabilisticAnswer | None:
@@ -0,0 +1,104 @@
1
+ from enum import Enum
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from prediction_market_agent_tooling.gtypes import Probability
7
+ from prediction_market_agent_tooling.tools.utils import DatetimeUTC
8
+
9
+
10
+ class QuestionType(str, Enum):
11
+ binary = "binary"
12
+
13
+
14
+ class AggregationItem(BaseModel):
15
+ start_time: DatetimeUTC
16
+ end_time: DatetimeUTC | None
17
+ forecast_values: list[float] | None
18
+ forecaster_count: int
19
+ interval_lower_bounds: list[float] | None
20
+ centers: list[float] | None
21
+ interval_upper_bounds: list[float] | None
22
+ means: list[float] | None
23
+ histogram: list[float] | None
24
+
25
+
26
+ class Aggregation(BaseModel):
27
+ history: list[AggregationItem]
28
+ latest: AggregationItem | None
29
+ score_data: dict[str, Any]
30
+
31
+
32
+ class Aggregations(BaseModel):
33
+ recency_weighted: Aggregation
34
+ unweighted: Aggregation
35
+ single_aggregation: Aggregation
36
+ metaculus_prediction: Aggregation
37
+
38
+
39
+ class MyForecast(BaseModel):
40
+ start_time: DatetimeUTC
41
+ end_time: DatetimeUTC | None
42
+ forecast_values: list[float] | None
43
+ interval_lower_bounds: list[float] | None
44
+ centers: list[float] | None
45
+ interval_upper_bounds: list[float] | None
46
+
47
+
48
+ class MyAggregation(BaseModel):
49
+ history: list[MyForecast]
50
+ latest: MyForecast | None
51
+ score_data: dict[str, Any]
52
+
53
+
54
+ class Question(BaseModel):
55
+ aggregations: Aggregations
56
+ my_forecasts: MyAggregation
57
+ type: QuestionType
58
+ possibilities: dict[str, str] | None
59
+
60
+
61
+ class MetaculusQuestion(BaseModel):
62
+ id: int
63
+ author_id: int
64
+ author_username: str
65
+ title: str
66
+ created_at: DatetimeUTC
67
+ published_at: DatetimeUTC
68
+ scheduled_close_time: DatetimeUTC
69
+ scheduled_resolve_time: DatetimeUTC
70
+ user_permission: str
71
+ comment_count: int
72
+ question: Question
73
+ # TODO add the rest of the fields https://github.com/gnosis/prediction-market-agent-tooling/issues/301
74
+
75
+ @property
76
+ def page_url(self) -> str:
77
+ return f"https://www.metaculus.com/questions/{self.id}/"
78
+
79
+ @property
80
+ def p_yes(self) -> Probability:
81
+ if self.question.type != QuestionType.binary:
82
+ raise ValueError(f"Only binary markets can have p_yes.")
83
+ if (
84
+ self.question.aggregations.recency_weighted is None
85
+ or self.question.aggregations.recency_weighted.latest is None
86
+ or self.question.aggregations.recency_weighted.latest.forecast_values
87
+ is None
88
+ ):
89
+ # If no value is provided (i.e. the question is new and has not been answered yet), we default to 0.5.
90
+ return Probability(0.5)
91
+ if len(self.question.aggregations.recency_weighted.latest.forecast_values) != 2:
92
+ raise ValueError(
93
+ f"Invalid logic, assumed that binary markets will have two forecasts, got: {self.question.aggregations.recency_weighted.latest.forecast_values}"
94
+ )
95
+ # Experimentally figured out that they store "Yes" at index 1.
96
+ return Probability(
97
+ self.question.aggregations.recency_weighted.latest.forecast_values[1]
98
+ )
99
+
100
+
101
+ class MetaculusQuestions(BaseModel):
102
+ next: str | None
103
+ previous: str | None
104
+ results: list[MetaculusQuestion]
@@ -37,13 +37,12 @@ class MetaculusAgentMarket(AgentMarket):
37
37
  question=model.title,
38
38
  outcomes=[],
39
39
  resolution=None,
40
- current_p_yes=Probability(model.community_prediction.full.p_yes),
41
- created_time=model.created_time,
42
- close_time=model.close_time,
43
- url=model.url,
40
+ current_p_yes=model.p_yes,
41
+ created_time=model.created_at,
42
+ close_time=model.scheduled_close_time,
43
+ url=model.page_url,
44
44
  volume=None,
45
- have_predicted=model.my_predictions is not None
46
- and len(model.my_predictions.predictions) > 0,
45
+ have_predicted=model.question.my_forecasts.latest is not None,
47
46
  outcome_token_pool=None,
48
47
  )
49
48
 
@@ -352,25 +352,38 @@ class OmenMarket(BaseModel):
352
352
  def is_binary(self) -> bool:
353
353
  return len(self.outcomes) == 2
354
354
 
355
- @property
356
- def boolean_outcome(self) -> bool:
355
+ def boolean_outcome_from_answer(self, answer: HexBytes) -> bool:
357
356
  if not self.is_binary:
358
357
  raise ValueError(
359
358
  f"Market with title {self.title} is not binary, it has {len(self.outcomes)} outcomes."
360
359
  )
360
+ outcome: str = self.outcomes[answer.as_int()]
361
+ return get_boolean_outcome(outcome)
362
+
363
+ @property
364
+ def boolean_outcome(self) -> bool:
361
365
  if not self.is_resolved_with_valid_answer:
362
366
  raise ValueError(f"Bet with title {self.title} is not resolved.")
367
+ return self.boolean_outcome_from_answer(
368
+ check_not_none(
369
+ self.currentAnswer, "Can not be None if `is_resolved_with_valid_answer`"
370
+ )
371
+ )
363
372
 
364
- outcome: str = self.outcomes[check_not_none(self.answer_index)]
365
- return get_boolean_outcome(outcome)
373
+ def get_resolution_enum_from_answer(self, answer: HexBytes) -> Resolution:
374
+ if self.boolean_outcome_from_answer(answer):
375
+ return Resolution.YES
376
+ else:
377
+ return Resolution.NO
366
378
 
367
379
  def get_resolution_enum(self) -> t.Optional[Resolution]:
368
380
  if not self.is_resolved_with_valid_answer:
369
381
  return None
370
- if self.boolean_outcome:
371
- return Resolution.YES
372
- else:
373
- return Resolution.NO
382
+ return self.get_resolution_enum_from_answer(
383
+ check_not_none(
384
+ self.currentAnswer, "Can not be None if `is_resolved_with_valid_answer`"
385
+ )
386
+ )
374
387
 
375
388
  @property
376
389
  def url(self) -> str:
@@ -18,9 +18,6 @@ from prediction_market_agent_tooling.markets.omen.data_models import (
18
18
  OmenMarket,
19
19
  RealityQuestion,
20
20
  )
21
- from prediction_market_agent_tooling.markets.omen.omen import (
22
- OMEN_DEFAULT_REALITIO_BOND_VALUE,
23
- )
24
21
  from prediction_market_agent_tooling.markets.omen.omen_contracts import (
25
22
  OmenOracleContract,
26
23
  OmenRealitioContract,
@@ -121,6 +118,7 @@ def claim_bonds_on_realitio_question(
121
118
  def finalize_markets(
122
119
  api_keys: APIKeys,
123
120
  markets_with_resolutions: list[tuple[OmenMarket, Resolution | None]],
121
+ realitio_bond: xDai,
124
122
  wait_n_days_before_invalid: int = 30,
125
123
  web3: Web3 | None = None,
126
124
  ) -> list[HexAddress]:
@@ -140,7 +138,7 @@ def finalize_markets(
140
138
  omen_submit_invalid_answer_market_tx(
141
139
  api_keys,
142
140
  market,
143
- OMEN_DEFAULT_REALITIO_BOND_VALUE,
141
+ realitio_bond,
144
142
  web3=web3,
145
143
  )
146
144
 
@@ -155,7 +153,7 @@ def finalize_markets(
155
153
  api_keys,
156
154
  market,
157
155
  resolution,
158
- OMEN_DEFAULT_REALITIO_BOND_VALUE,
156
+ realitio_bond,
159
157
  web3=web3,
160
158
  )
161
159
  finalized_markets.append(market.id)
@@ -168,7 +166,7 @@ def finalize_markets(
168
166
  omen_submit_invalid_answer_market_tx(
169
167
  api_keys,
170
168
  market,
171
- OMEN_DEFAULT_REALITIO_BOND_VALUE,
169
+ realitio_bond,
172
170
  web3=web3,
173
171
  )
174
172
 
@@ -71,12 +71,17 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
71
71
  def __init__(self) -> None:
72
72
  self.sg = Subgrounds()
73
73
 
74
- # Patch the query_json method to retry on failure.
74
+ # Patch methods to retry on failure.
75
75
  self.sg.query_json = tenacity.retry(
76
76
  stop=tenacity.stop_after_attempt(3),
77
77
  wait=tenacity.wait_fixed(1),
78
78
  after=lambda x: logger.debug(f"query_json failed, {x.attempt_number=}."),
79
79
  )(self.sg.query_json)
80
+ self.sg.load_subgraph = tenacity.retry(
81
+ stop=tenacity.stop_after_attempt(3),
82
+ wait=tenacity.wait_fixed(1),
83
+ after=lambda x: logger.debug(f"load_subgraph failed, {x.attempt_number=}."),
84
+ )(self.sg.load_subgraph)
80
85
 
81
86
  keys = APIKeys()
82
87
 
@@ -221,7 +226,6 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
221
226
  opened_after: t.Optional[DatetimeUTC] = None,
222
227
  finalized_before: t.Optional[DatetimeUTC] = None,
223
228
  finalized_after: t.Optional[DatetimeUTC] = None,
224
- finalized: bool | None = None,
225
229
  resolved: bool | None = None,
226
230
  liquidity_bigger_than: Wei | None = None,
227
231
  condition_id_in: list[HexBytes] | None = None,
@@ -273,12 +277,6 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
273
277
  else:
274
278
  where_stms["resolutionTimestamp"] = None
275
279
 
276
- if finalized is not None:
277
- if finalized:
278
- where_stms["answerFinalizedTimestamp_not"] = None
279
- else:
280
- where_stms["answerFinalizedTimestamp"] = None
281
-
282
280
  if opened_after:
283
281
  where_stms["question_"]["openingTimestamp_gt"] = to_int_timestamp(
284
282
  opened_after
@@ -358,13 +356,11 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
358
356
  Simplified `get_omen_binary_markets` method, which allows to fetch markets based on the filter_by and sort_by values.
359
357
  """
360
358
  # These values need to be set according to the filter_by value, so they can not be passed as arguments.
361
- finalized: bool | None = None
362
359
  resolved: bool | None = None
363
360
  opened_after: DatetimeUTC | None = None
364
361
  liquidity_bigger_than: Wei | None = None
365
362
 
366
363
  if filter_by == FilterBy.RESOLVED:
367
- finalized = True
368
364
  resolved = True
369
365
  elif filter_by == FilterBy.OPEN:
370
366
  # We can not use `resolved=False` + `finalized=False` here,
@@ -381,7 +377,6 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
381
377
 
382
378
  return self.get_omen_binary_markets(
383
379
  limit=limit,
384
- finalized=finalized,
385
380
  resolved=resolved,
386
381
  opened_after=opened_after,
387
382
  liquidity_bigger_than=liquidity_bigger_than,
@@ -401,7 +396,6 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
401
396
  opened_after: t.Optional[DatetimeUTC] = None,
402
397
  finalized_before: t.Optional[DatetimeUTC] = None,
403
398
  finalized_after: t.Optional[DatetimeUTC] = None,
404
- finalized: bool | None = None,
405
399
  resolved: bool | None = None,
406
400
  creator: t.Optional[HexAddress] = None,
407
401
  creator_in: t.Optional[t.Sequence[HexAddress]] = None,
@@ -429,7 +423,6 @@ class OmenSubgraphHandler(metaclass=SingletonMeta):
429
423
  opened_after=opened_after,
430
424
  finalized_before=finalized_before,
431
425
  finalized_after=finalized_after,
432
- finalized=finalized,
433
426
  resolved=resolved,
434
427
  condition_id_in=condition_id_in,
435
428
  id_in=id_in,
@@ -0,0 +1,92 @@
1
+ import tenacity
2
+
3
+ from prediction_market_agent_tooling.config import APIKeys
4
+ from prediction_market_agent_tooling.loggers import logger
5
+ from prediction_market_agent_tooling.tools.cache import persistent_inmemory_cache
6
+ from prediction_market_agent_tooling.tools.is_predictable import (
7
+ parse_decision_yes_no_completion,
8
+ )
9
+ from prediction_market_agent_tooling.tools.langfuse_ import (
10
+ get_langfuse_langchain_config,
11
+ observe,
12
+ )
13
+ from prediction_market_agent_tooling.tools.utils import (
14
+ LLM_SEED,
15
+ LLM_SUPER_LOW_TEMPERATURE,
16
+ )
17
+
18
+ # I tried to make it return a JSON, but it didn't work well in combo with asking it to do chain of thought.
19
+ # Rules are almost copy-pasted from https://cdn.kleros.link/ipfs/QmZM12kkguXFk2C94ykrKpambt4iUVKsVsxGxDEdLS68ws/omen-rules.pdf,
20
+ # with some small prompting mods and I removed the point about "The outcome of the market must be known by its Resolution Date.", because that can not be verified before-hand.
21
+ # and also point about "in which none of the answers are valid will resolve as invalid" and "in which multiple answers are valid will resolve as invalid.", because before hand we can not know if one of the outcomes happened or not.
22
+ QUESTION_IS_INVALID_PROMPT = """Main signs about an invalid question (sometimes referred to as a "market"):
23
+ - The market's question is about immoral violence, death or assassination.
24
+ - The violent event can be caused by a single conscious being.
25
+ - The violent event is done illegally.
26
+ - The market should not directly incentivize immoral violent (such as murder, rape or unjust imprisonment) actions which could likely be performed by any participant.
27
+ - Invalid: Will Donald Trump be alive on the 01/12/2021? (Anyone could bet on “No” and kill him for a guaranteed profit. Anyone could bet on “Yes” to effectively put a bounty on his head).
28
+ - Invalid: Will Hera be a victim of swatting in 2020? (Anyone could falsely call the emergency services on him in order to win the bet)
29
+ - This does not prevent markets:
30
+ - Whose topics are violent events not caused by conscious beings.
31
+ - Valid: How many people will die from COVID19 in 2020? (Viruses don’t use prediction markets).
32
+ - Whose main source of uncertainty is not related to a potential violent action.
33
+ - Valid: Will Trump win the 2020 US presidential election? (The main source of uncertainty is the vote of US citizens, not a potential murder of a presidential candidate).
34
+ - Which could give an incentive only to specific participants to commit an immoral violent action, but are in practice unlikely.
35
+ - Valid: Will the US be engaged in a military conflict with a UN member state in 2021? (It’s unlikely for the US to declare war in order to win a bet on this market).
36
+ - Valid: Will Derek Chauvin go to jail for the murder of George Flyod? (It’s unlikely that the jurors would collude to make a wrong verdict in order to win this market).
37
+ - Questions with relative dates will resolve as invalid. Dates must be stated in absolute terms, not relative depending on the current time.
38
+ - Invalid: Who will be the president of the United States in 6 months? (“in 6 months depends on the current time”).
39
+ - Questions about moral values and not facts will be resolved as invalid.
40
+ - Invalid: “Is it ethical to eat meat?”.
41
+
42
+ Follow a chain of thought to evaluate if the question is invalid:
43
+
44
+ First, write the parts of the following question:
45
+
46
+ "{question}"
47
+
48
+ Then, write down what is the future event of the question, what it refers to and when that event will happen if the question contains it.
49
+
50
+ Then, explain why do you think it is or isn't invalid.
51
+
52
+ Finally, write your final decision, write `decision: ` followed by either "yes it is invalid" or "no it isn't invalid" about the question. Don't write anything else after that. You must include "yes" or "no".
53
+ """
54
+
55
+
56
+ @persistent_inmemory_cache
57
+ @tenacity.retry(stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_fixed(1))
58
+ @observe()
59
+ def is_invalid(
60
+ question: str,
61
+ engine: str = "gpt-4o",
62
+ temperature: float = LLM_SUPER_LOW_TEMPERATURE,
63
+ seed: int = LLM_SEED,
64
+ prompt_template: str = QUESTION_IS_INVALID_PROMPT,
65
+ max_tokens: int = 1024,
66
+ ) -> bool:
67
+ """
68
+ Evaluate if the question is actually answerable.
69
+ """
70
+ try:
71
+ from langchain.prompts import ChatPromptTemplate
72
+ from langchain_openai import ChatOpenAI
73
+ except ImportError:
74
+ logger.error("langchain not installed, skipping is_invalid")
75
+ return True
76
+
77
+ llm = ChatOpenAI(
78
+ model=engine,
79
+ temperature=temperature,
80
+ seed=seed,
81
+ api_key=APIKeys().openai_api_key_secretstr_v1,
82
+ )
83
+
84
+ prompt = ChatPromptTemplate.from_template(template=prompt_template)
85
+ messages = prompt.format_messages(question=question)
86
+ completion = str(
87
+ llm.invoke(
88
+ messages, max_tokens=max_tokens, config=get_langfuse_langchain_config()
89
+ ).content
90
+ )
91
+
92
+ return parse_decision_yes_no_completion(question, completion)
@@ -22,8 +22,10 @@ from prediction_market_agent_tooling.loggers import logger
22
22
  T = TypeVar("T")
23
23
 
24
24
  # t=0 is mathematically impossible and it's not clear how OpenAI (and others) handle it, as a result, even with t=0, gpt-4-turbo produces very different outputs,
25
- # it seems that using a very low temperature is the best way to have as consistent outputs as possible: https://community.openai.com/t/why-the-api-output-is-inconsistent-even-after-the-temperature-is-set-to-0/329541/12
25
+ # see this experiment to figure out if you should use LLM_SUPER_LOW_TEMPERATURE or just 0: https://github.com/gnosis/prediction-market-agent/pull/438.
26
26
  LLM_SUPER_LOW_TEMPERATURE = 0.00000001
27
+ # For consistent results, also include seed for models that supports it.
28
+ LLM_SEED = 0
27
29
 
28
30
 
29
31
  def check_not_none(
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "prediction-market-agent-tooling"
3
- version = "0.50.1"
3
+ version = "0.51.1"
4
4
  description = "Tools to benchmark, deploy and monitor prediction market agents."
5
5
  authors = ["Gnosis"]
6
6
  readme = "README.md"
@@ -1,97 +0,0 @@
1
- from enum import Enum
2
- from typing import Any
3
-
4
- from pydantic import BaseModel
5
-
6
- from prediction_market_agent_tooling.tools.utils import DatetimeUTC
7
-
8
-
9
- class QuestionType(str, Enum):
10
- forecast = "forecast"
11
- notebook = "notebook"
12
- discussion = "discussion"
13
- claim = "claim"
14
- group = "group"
15
- conditional_group = "conditional_group"
16
- multiple_choice = "multiple_choice"
17
-
18
-
19
- class CommunityPrediction(BaseModel):
20
- y: list[float]
21
- q1: float | None = None
22
- q2: float | None = None
23
- q3: float | None = None
24
-
25
- @property
26
- def p_yes(self) -> float:
27
- """
28
- q2 corresponds to the median, or 'second quartile' of the distribution.
29
-
30
- If no value is provided (i.e. the question is new and has not been
31
- answered yet), we default to 0.5.
32
- """
33
- return self.q2 if self.q2 is not None else 0.5
34
-
35
-
36
- class Prediction(BaseModel):
37
- t: DatetimeUTC
38
- x: float
39
-
40
-
41
- class UserPredictions(BaseModel):
42
- id: int
43
- predictions: list[Prediction]
44
- points_won: float | None = None
45
- user: int
46
- username: str
47
- question: int
48
-
49
-
50
- class CommunityPredictionStats(BaseModel):
51
- full: CommunityPrediction
52
- unweighted: CommunityPrediction
53
-
54
-
55
- class MetaculusQuestion(BaseModel):
56
- """
57
- https://www.metaculus.com/api2/schema/redoc/#tag/questions/operation/questions_retrieve
58
- """
59
-
60
- active_state: Any
61
- url: str
62
- page_url: str
63
- id: int
64
- author: int
65
- author_name: str
66
- author_id: int
67
- title: str
68
- title_short: str
69
- group_label: str | None = None
70
- resolution: int | None
71
- resolved_option: int | None
72
- created_time: DatetimeUTC
73
- publish_time: DatetimeUTC | None = None
74
- close_time: DatetimeUTC | None = None
75
- effected_close_time: DatetimeUTC | None
76
- resolve_time: DatetimeUTC | None = None
77
- possibilities: dict[Any, Any] | None = None
78
- scoring: dict[Any, Any] = {}
79
- type: QuestionType | None = None
80
- user_perms: Any
81
- weekly_movement: float | None
82
- weekly_movement_direction: int | None = None
83
- cp_reveal_time: DatetimeUTC | None = None
84
- edited_time: DatetimeUTC
85
- last_activity_time: DatetimeUTC
86
- activity: float
87
- comment_count: int
88
- votes: int
89
- community_prediction: CommunityPredictionStats
90
- my_predictions: UserPredictions | None = None
91
- # TODO add the rest of the fields https://github.com/gnosis/prediction-market-agent-tooling/issues/301
92
-
93
-
94
- class MetaculusQuestions(BaseModel):
95
- next: str | None
96
- previous: str | None
97
- results: list[MetaculusQuestion]