prediction-market-agent-tooling 0.15.1__py3-none-any.whl → 0.17.0__py3-none-any.whl

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.
@@ -6,6 +6,7 @@ from prediction_market_agent_tooling.benchmark.utils import (
6
6
  OutcomePrediction,
7
7
  Prediction,
8
8
  )
9
+ from prediction_market_agent_tooling.gtypes import Probability
9
10
 
10
11
 
11
12
  class AbstractBenchmarkedAgent:
@@ -86,7 +87,8 @@ class RandomAgent(AbstractBenchmarkedAgent):
86
87
  p_yes, confidence = random.random(), random.random()
87
88
  return Prediction(
88
89
  outcome_prediction=OutcomePrediction(
89
- p_yes=p_yes,
90
+ decision=p_yes > 0.5,
91
+ p_yes=Probability(p_yes),
90
92
  confidence=confidence,
91
93
  info_utility=None,
92
94
  ),
@@ -109,7 +111,8 @@ class FixedAgent(AbstractBenchmarkedAgent):
109
111
  p_yes, confidence = 1.0 if self.fixed_answer else 0.0, 1.0
110
112
  return Prediction(
111
113
  outcome_prediction=OutcomePrediction(
112
- p_yes=p_yes,
114
+ decision=self.fixed_answer,
115
+ p_yes=Probability(p_yes),
113
116
  confidence=confidence,
114
117
  info_utility=None,
115
118
  ),
@@ -3,12 +3,11 @@ import typing as t
3
3
 
4
4
  from pydantic import BaseModel
5
5
 
6
+ from prediction_market_agent_tooling.deploy.agent import Answer
6
7
  from prediction_market_agent_tooling.markets.data_models import Resolution
7
8
 
8
9
 
9
- class OutcomePrediction(BaseModel):
10
- p_yes: float
11
- confidence: float
10
+ class OutcomePrediction(Answer):
12
11
  info_utility: t.Optional[float]
13
12
 
14
13
  @property
@@ -6,6 +6,8 @@ import typing as t
6
6
  from datetime import datetime
7
7
 
8
8
  from loguru import logger
9
+ from pydantic import BaseModel, BeforeValidator
10
+ from typing_extensions import Annotated
9
11
 
10
12
  from prediction_market_agent_tooling.config import APIKeys, PrivateCredentials
11
13
  from prediction_market_agent_tooling.deploy.constants import (
@@ -21,6 +23,7 @@ from prediction_market_agent_tooling.deploy.gcp.utils import (
21
23
  gcp_function_is_active,
22
24
  gcp_resolve_api_keys_secrets,
23
25
  )
26
+ from prediction_market_agent_tooling.gtypes import Probability
24
27
  from prediction_market_agent_tooling.markets.agent_market import (
25
28
  AgentMarket,
26
29
  FilterBy,
@@ -39,6 +42,40 @@ from prediction_market_agent_tooling.tools.utils import DatetimeWithTimezone, ut
39
42
  MAX_AVAILABLE_MARKETS = 20
40
43
 
41
44
 
45
+ def to_boolean_outcome(value: str | bool) -> bool:
46
+ if isinstance(value, bool):
47
+ return value
48
+
49
+ elif isinstance(value, str):
50
+ value = value.lower().strip()
51
+
52
+ if value in {"true", "yes", "y", "1"}:
53
+ return True
54
+
55
+ elif value in {"false", "no", "n", "0"}:
56
+ return False
57
+
58
+ else:
59
+ raise ValueError(f"Expected a boolean string, but got {value}")
60
+
61
+ else:
62
+ raise ValueError(f"Expected a boolean or a string, but got {value}")
63
+
64
+
65
+ Decision = Annotated[bool, BeforeValidator(to_boolean_outcome)]
66
+
67
+
68
+ class Answer(BaseModel):
69
+ decision: Decision # Warning: p_yes > 0.5 doesn't necessarily mean decision is True! For example, if our p_yes is 55%, but market's p_yes is 80%, then it might be profitable to bet on False.
70
+ p_yes: Probability
71
+ confidence: float
72
+ reasoning: str | None = None
73
+
74
+ @property
75
+ def p_no(self) -> Probability:
76
+ return Probability(1 - self.p_yes)
77
+
78
+
42
79
  class DeployableAgent:
43
80
  def __init__(self) -> None:
44
81
  self.load()
@@ -58,7 +95,7 @@ class DeployableAgent:
58
95
  """
59
96
  return markets[:1]
60
97
 
61
- def answer_binary_market(self, market: AgentMarket) -> bool | None:
98
+ def answer_binary_market(self, market: AgentMarket) -> Answer | None:
62
99
  """
63
100
  Answer the binary market. This method must be implemented by the subclass.
64
101
  """
@@ -157,7 +194,7 @@ def {entrypoint_function_name}(request) -> str:
157
194
  if cron_schedule:
158
195
  schedule_deployed_gcp_function(fname, cron_schedule=cron_schedule)
159
196
 
160
- def calculate_bet_amount(self, answer: bool, market: AgentMarket) -> BetAmount:
197
+ def calculate_bet_amount(self, answer: Answer, market: AgentMarket) -> BetAmount:
161
198
  """
162
199
  Calculate the bet amount. By default, it returns the minimum bet amount.
163
200
  """
@@ -205,7 +242,7 @@ def {entrypoint_function_name}(request) -> str:
205
242
  )
206
243
  market.place_bet(
207
244
  amount=amount,
208
- outcome=result,
245
+ outcome=result.decision,
209
246
  )
210
247
 
211
248
  def after(self, market_type: MarketType) -> None:
@@ -1,7 +1,11 @@
1
1
  import random
2
2
  import typing as t
3
3
 
4
- from prediction_market_agent_tooling.deploy.agent import DeployableAgent
4
+ from prediction_market_agent_tooling.deploy.agent import (
5
+ Answer,
6
+ DeployableAgent,
7
+ Probability,
8
+ )
5
9
  from prediction_market_agent_tooling.markets.agent_market import AgentMarket
6
10
 
7
11
 
@@ -9,10 +13,16 @@ class DeployableCoinFlipAgent(DeployableAgent):
9
13
  def pick_markets(self, markets: t.Sequence[AgentMarket]) -> t.Sequence[AgentMarket]:
10
14
  return random.sample(markets, 1)
11
15
 
12
- def answer_binary_market(self, market: AgentMarket) -> bool | None:
13
- return random.choice([True, False])
16
+ def answer_binary_market(self, market: AgentMarket) -> Answer | None:
17
+ decision = random.choice([True, False])
18
+ return Answer(
19
+ decision=decision,
20
+ p_yes=Probability(float(decision)),
21
+ confidence=0.5,
22
+ reasoning="I flipped a coin to decide.",
23
+ )
14
24
 
15
25
 
16
26
  class DeployableAlwaysRaiseAgent(DeployableAgent):
17
- def answer_binary_market(self, market: AgentMarket) -> bool | None:
27
+ def answer_binary_market(self, market: AgentMarket) -> Answer | None:
18
28
  raise RuntimeError("I always raise!")
@@ -1,7 +1,4 @@
1
- from datetime import timedelta
2
-
3
1
  from loguru import logger
4
- from pydantic import BaseModel
5
2
  from web3 import Web3
6
3
 
7
4
  from prediction_market_agent_tooling.config import PrivateCredentials
@@ -34,81 +31,10 @@ from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
34
31
  from prediction_market_agent_tooling.markets.polymarket.utils import (
35
32
  find_resolution_on_polymarket,
36
33
  )
37
- from prediction_market_agent_tooling.tools.balances import get_balances
38
- from prediction_market_agent_tooling.tools.utils import utcnow
39
34
  from prediction_market_agent_tooling.tools.web3_utils import ZERO_BYTES, xdai_to_wei
40
35
 
41
36
 
42
- class FinalizeAndResolveResult(BaseModel):
43
- finalized: list[HexAddress]
44
- resolved: list[HexAddress]
45
- claimed_question_ids: list[HexBytes]
46
-
47
-
48
- def omen_finalize_and_resolve_and_claim_back_all_markets_based_on_others_tx(
49
- private_credentials: PrivateCredentials,
50
- ) -> FinalizeAndResolveResult:
51
- public_key = private_credentials.public_key
52
- balances_start = get_balances(public_key)
53
- logger.info(f"{balances_start=}")
54
-
55
- # Just to be friendly with timezones.
56
- before = utcnow() - timedelta(hours=8)
57
-
58
- # Fetch markets created by us that are already open, but no answer was submitted yet.
59
- created_opened_markets = OmenSubgraphHandler().get_omen_binary_markets(
60
- limit=None,
61
- creator=public_key,
62
- opened_before=before,
63
- finalized=False,
64
- )
65
- # Finalize them (set answer on Realitio).
66
- finalized_markets = finalize_markets(
67
- private_credentials,
68
- created_opened_markets,
69
- )
70
- balances_after_finalization = get_balances(public_key)
71
- logger.info(f"{balances_after_finalization=}")
72
-
73
- # Fetch markets created by us that are already open, and we already submitted an answer more than a day ago, but they aren't resolved yet.
74
- created_finalized_markets = OmenSubgraphHandler().get_omen_binary_markets(
75
- limit=None,
76
- creator=public_key,
77
- finalized_before=before - timedelta(hours=24),
78
- resolved=False,
79
- )
80
- # Resolve them (resolve them on Oracle).
81
- resolved_markets = resolve_markets(
82
- private_credentials,
83
- created_finalized_markets,
84
- )
85
- balances_after_resolution = get_balances(public_key)
86
- logger.info(f"{balances_after_resolution=}")
87
-
88
- # Fetch questions that are already finalised (last answer is older than 24 hours), but we didn't claim the bonded xDai yet.
89
- created_not_claimed_questions: list[
90
- RealityQuestion
91
- ] = OmenSubgraphHandler().get_questions(
92
- user=public_key,
93
- claimed=False,
94
- current_answer_before=before - timedelta(hours=24),
95
- )
96
- claimed_question_ids = claim_bonds_on_realitio_quetions(
97
- private_credentials,
98
- created_not_claimed_questions,
99
- auto_withdraw=True,
100
- )
101
- balances_after_claiming = get_balances(public_key)
102
- logger.info(f"{balances_after_claiming=}")
103
-
104
- return FinalizeAndResolveResult(
105
- finalized=finalized_markets,
106
- resolved=resolved_markets,
107
- claimed_question_ids=claimed_question_ids,
108
- )
109
-
110
-
111
- def claim_bonds_on_realitio_quetions(
37
+ def claim_bonds_on_realitio_questions(
112
38
  private_credentials: PrivateCredentials,
113
39
  questions: list[RealityQuestion],
114
40
  auto_withdraw: bool,
@@ -194,18 +120,17 @@ def claim_bonds_on_realitio_question(
194
120
 
195
121
  def finalize_markets(
196
122
  private_credentials: PrivateCredentials,
197
- markets: list[OmenMarket],
123
+ markets_with_resolutions: list[tuple[OmenMarket, Resolution | None]],
198
124
  ) -> list[HexAddress]:
199
125
  finalized_markets: list[HexAddress] = []
200
126
 
201
- for idx, market in enumerate(markets):
127
+ for idx, (market, resolution) in enumerate(markets_with_resolutions):
202
128
  logger.info(
203
- f"[{idx+1} / {len(markets)}] Looking into {market.url=} {market.question_title=}"
129
+ f"[{idx+1} / {len(markets_with_resolutions)}] Looking into {market.url=} {market.question_title=}"
204
130
  )
205
- resolution = find_resolution_on_other_markets(market)
206
131
 
207
132
  if resolution is None:
208
- logger.error(f"No resolution found for {market.url=}")
133
+ logger.error(f"No resolution provided for {market.url=}")
209
134
 
210
135
  elif resolution in (Resolution.YES, Resolution.NO):
211
136
  logger.info(f"Found resolution {resolution.value=} for {market.url=}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.15.1
3
+ Version: 0.17.0
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -8,12 +8,12 @@ prediction_market_agent_tooling/abis/omen_oracle.abi.json,sha256=YPZ-FLvd4PA9pYd
8
8
  prediction_market_agent_tooling/abis/omen_realitio.abi.json,sha256=7HmFkBF_rq83UTaH2kRRsEfc_WZuf4n-qvkB4nhvweo,15953
9
9
  prediction_market_agent_tooling/abis/wxdai.abi.json,sha256=m3qC06Yug-pToI0lSFe1f8e6gKMIulnV3MA2K0X51hI,6055
10
10
  prediction_market_agent_tooling/benchmark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- prediction_market_agent_tooling/benchmark/agents.py,sha256=HtZGjY0En7lmUaLyynZSNO_YjsCg-hlRi6YQ4ZGQyHc,3829
11
+ prediction_market_agent_tooling/benchmark/agents.py,sha256=HPIFJvackW110ch3UkktbxhU48gMRVo4gQse84Klhdc,4000
12
12
  prediction_market_agent_tooling/benchmark/benchmark.py,sha256=xiHKzZx5GHSsDerFHMZ9j_LXAXnSaITSvv67iPe3MEU,21095
13
- prediction_market_agent_tooling/benchmark/utils.py,sha256=mRHhkS-_TrDSh4uyz-d36bKlJdwDk1w6gyfzXUc2Mrs,2875
13
+ prediction_market_agent_tooling/benchmark/utils.py,sha256=iS1BzyXcCMfMm1Rx--1QCH0pHvBTblTndcDQFbTUJ2s,2897
14
14
  prediction_market_agent_tooling/config.py,sha256=Cvl9RWlOEPRzdSE7-ChTyKSMNTgNoOYmtJ0lT5yDqpE,3570
15
- prediction_market_agent_tooling/deploy/agent.py,sha256=ju-BDe8Ek1mTLWMoIyp_LLcNt2KhxgITa0O8OtgW_ko,7788
16
- prediction_market_agent_tooling/deploy/agent_example.py,sha256=vwswPCOutCG9vIqJT5lBcI1FZy3QRkNyVbNIJdn6wvk,652
15
+ prediction_market_agent_tooling/deploy/agent.py,sha256=hpk2VvRBHU1d7_tcYaZg5V3bvhehl7ZgUjn3jc6iAMY,8916
16
+ prediction_market_agent_tooling/deploy/agent_example.py,sha256=KaTJm43cwbBZR2BmTEyB1ohChAqwYlBUqaaVumsWQe4,891
17
17
  prediction_market_agent_tooling/deploy/constants.py,sha256=M5ty8URipYMGe_G-RzxRydK3AFL6CyvmqCraJUrLBnE,82
18
18
  prediction_market_agent_tooling/deploy/gcp/deploy.py,sha256=CYUgnfy-9XVk04kkxA_5yp0GE9Mw5caYqlFUZQ2j3ks,3739
19
19
  prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py,sha256=qYIHRxQLac3yxtZ8ChikiPG9O1aUQucHW0muTSm1nto,2627
@@ -32,8 +32,7 @@ prediction_market_agent_tooling/markets/omen/__init__.py,sha256=47DEQpj8HBSa-_TI
32
32
  prediction_market_agent_tooling/markets/omen/data_models.py,sha256=g6A_DQ54m-_3XQO02AM4NliDycsgYvg8hgpt8Dri5cg,14111
33
33
  prediction_market_agent_tooling/markets/omen/omen.py,sha256=aZhz2dRFYuAP2h1TlrPWN4lIuOrSvvCjXV-3WcP3TG4,31392
34
34
  prediction_market_agent_tooling/markets/omen/omen_contracts.py,sha256=vblZAS_aWTSB6I5LDx_E7hg5gyvocs1I9qxSfxM8YfM,19733
35
- prediction_market_agent_tooling/markets/omen/omen_replicate.py,sha256=1Yp8vpuZS15kIMPKqMxH0vrvXOsStI4KVA2DrS4V134,7409
36
- prediction_market_agent_tooling/markets/omen/omen_resolve_replicated.py,sha256=v6fRGv3Loy5PARoRyyAiCNY2TvKGE-Jxr27-1i-D40A,11356
35
+ prediction_market_agent_tooling/markets/omen/omen_resolving.py,sha256=OXgcdXN4mFw9kjhtcTWZ7O3RdHYJdq2aAA52dzj-MqQ,8726
37
36
  prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py,sha256=F2JyAYqCR4REOnFB2cngbngh7ib7SMt0VtFw7mGt2Yc,22266
38
37
  prediction_market_agent_tooling/markets/polymarket/api.py,sha256=p1JkqL9kF8C04qbmqFzF0hgtzD5kN3yup2hYOjxazQ4,4188
39
38
  prediction_market_agent_tooling/markets/polymarket/data_models.py,sha256=srTl8-0FM76AGLRDWzjLpf46ikWloaBCgkn0XqZoKCI,4248
@@ -64,8 +63,8 @@ prediction_market_agent_tooling/tools/safe.py,sha256=gNgcY6ugckx3DbupR8VBezDgh1d
64
63
  prediction_market_agent_tooling/tools/singleton.py,sha256=CiIELUiI-OeS7U7eeHEt0rnVhtQGzwoUdAgn_7u_GBM,729
65
64
  prediction_market_agent_tooling/tools/utils.py,sha256=6MRfLr5xGPEQGobLz_eCsE_p-XaAeOCcmygwgNCIvqE,5044
66
65
  prediction_market_agent_tooling/tools/web3_utils.py,sha256=tl_uN-SpKK4nXpqlSozefzMXpbAe9rFzaCB9IQ0QJxY,8335
67
- prediction_market_agent_tooling-0.15.1.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
68
- prediction_market_agent_tooling-0.15.1.dist-info/METADATA,sha256=3PCBmKISvfL0pfNUibhzvXD59uu4YEv4pxH536xdviw,5468
69
- prediction_market_agent_tooling-0.15.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
70
- prediction_market_agent_tooling-0.15.1.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
71
- prediction_market_agent_tooling-0.15.1.dist-info/RECORD,,
66
+ prediction_market_agent_tooling-0.17.0.dist-info/LICENSE,sha256=6or154nLLU6bELzjh0mCreFjt0m2v72zLi3yHE0QbeE,7650
67
+ prediction_market_agent_tooling-0.17.0.dist-info/METADATA,sha256=Z-mAb4_umw_MR5dyNTEybglqltb3DTvvmOufBifARTk,5468
68
+ prediction_market_agent_tooling-0.17.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
69
+ prediction_market_agent_tooling-0.17.0.dist-info/entry_points.txt,sha256=m8PukHbeH5g0IAAmOf_1Ahm-sGAMdhSSRQmwtpmi2s8,81
70
+ prediction_market_agent_tooling-0.17.0.dist-info/RECORD,,
@@ -1,184 +0,0 @@
1
- from datetime import datetime, timedelta
2
-
3
- from loguru import logger
4
-
5
- from prediction_market_agent_tooling.config import PrivateCredentials
6
- from prediction_market_agent_tooling.gtypes import ChecksumAddress, wei_type, xDai
7
- from prediction_market_agent_tooling.markets.agent_market import FilterBy, SortBy
8
- from prediction_market_agent_tooling.markets.categorize import infer_category
9
- from prediction_market_agent_tooling.markets.markets import (
10
- MarketType,
11
- get_binary_markets,
12
- )
13
- from prediction_market_agent_tooling.markets.omen.data_models import (
14
- OMEN_FALSE_OUTCOME,
15
- OMEN_TRUE_OUTCOME,
16
- )
17
- from prediction_market_agent_tooling.markets.omen.omen import (
18
- OMEN_DEFAULT_MARKET_FEE,
19
- OmenAgentMarket,
20
- omen_create_market_tx,
21
- omen_remove_fund_market_tx,
22
- )
23
- from prediction_market_agent_tooling.markets.omen.omen_subgraph_handler import (
24
- OmenSubgraphHandler,
25
- )
26
- from prediction_market_agent_tooling.tools.is_predictable import is_predictable_binary
27
- from prediction_market_agent_tooling.tools.utils import utcnow
28
-
29
- # According to Omen's recommendation, closing time of the market should be at least 6 days after the outcome is known.
30
- # That is because at the closing time, the question will open on Realitio, and we don't want it to be resolved as unknown/invalid.
31
- # All replicated markets that close at N, needs to have closing time on Realition N + `EXTEND_CLOSING_TIME_DELTA`.
32
- EXTEND_CLOSING_TIME_DELTA = timedelta(days=6)
33
-
34
-
35
- def omen_replicate_from_tx(
36
- private_credentials: PrivateCredentials,
37
- market_type: MarketType,
38
- n_to_replicate: int,
39
- initial_funds: xDai,
40
- close_time_before: datetime | None = None,
41
- auto_deposit: bool = False,
42
- ) -> list[ChecksumAddress]:
43
- from_address = private_credentials.public_key
44
- already_created_markets = OmenSubgraphHandler().get_omen_binary_markets(
45
- limit=None,
46
- creator=from_address,
47
- )
48
-
49
- markets = get_binary_markets(
50
- # Polymarket is slow to get, so take only 10 candidates for him.
51
- 10 if market_type == MarketType.POLYMARKET else 100,
52
- market_type,
53
- filter_by=FilterBy.OPEN,
54
- sort_by=SortBy.NONE,
55
- excluded_questions=set(m.question_title for m in already_created_markets),
56
- )
57
- markets_sorted = sorted(
58
- markets,
59
- key=lambda m: m.volume or 0,
60
- reverse=True,
61
- )
62
- markets_to_replicate = [
63
- m
64
- for m in markets_sorted
65
- if close_time_before is None
66
- or (m.close_time is not None and m.close_time <= close_time_before)
67
- ]
68
- if not markets_to_replicate:
69
- logger.info(f"No markets found for {market_type}")
70
- return []
71
-
72
- logger.info(f"Found {len(markets_to_replicate)} markets to replicate.")
73
-
74
- # Get a set of possible categories from existing markets (but created by anyone, not just your agent)
75
- existing_categories = set(
76
- m.category
77
- for m in OmenSubgraphHandler().get_omen_binary_markets_simple(
78
- limit=1000,
79
- sort_by=SortBy.NEWEST,
80
- filter_by=FilterBy.NONE,
81
- )
82
- )
83
-
84
- created_addresses: list[ChecksumAddress] = []
85
-
86
- for market in markets_to_replicate:
87
- if market.close_time is None:
88
- logger.info(
89
- f"Skipping `{market.question}` because it's missing the closing time."
90
- )
91
- continue
92
-
93
- safe_closing_time = market.close_time + EXTEND_CLOSING_TIME_DELTA
94
- # Force at least 48 hours of time where the resolution is unknown.
95
- soonest_allowed_resolution_known_time = utcnow() + timedelta(hours=48)
96
- if market.close_time <= soonest_allowed_resolution_known_time:
97
- logger.info(
98
- f"Skipping `{market.question}` because it closes sooner than {soonest_allowed_resolution_known_time}."
99
- )
100
- continue
101
-
102
- # Do as the last step, becuase it calls OpenAI (costly & slow).
103
- if not is_predictable_binary(market.question):
104
- logger.info(
105
- f"Skipping `{market.question}` because it seems to not be predictable."
106
- )
107
- continue
108
-
109
- category = infer_category(market.question, existing_categories)
110
- # Realitio will allow new categories or misformated categories, so double check that the LLM got it right.
111
- if category not in existing_categories:
112
- logger.info(
113
- f"Error: LLM went rouge. Skipping `{market.question}` because the category `{category}` is not in the existing categories {existing_categories}."
114
- )
115
- continue
116
-
117
- market_address = omen_create_market_tx(
118
- private_credentials=private_credentials,
119
- initial_funds=initial_funds,
120
- fee=OMEN_DEFAULT_MARKET_FEE,
121
- question=market.question,
122
- closing_time=safe_closing_time,
123
- category=category,
124
- language="en",
125
- outcomes=[OMEN_TRUE_OUTCOME, OMEN_FALSE_OUTCOME],
126
- auto_deposit=auto_deposit,
127
- )
128
- created_addresses.append(market_address)
129
- logger.info(
130
- f"Created `https://aiomen.eth.limo/#/{market_address}` for `{market.question}` in category {category} out of {market.url}."
131
- )
132
-
133
- if len(created_addresses) >= n_to_replicate:
134
- logger.info(
135
- f"Replicated {len(created_addresses)} from {market_type}, breaking."
136
- )
137
- break
138
-
139
- return created_addresses
140
-
141
-
142
- def omen_unfund_replicated_known_markets_tx(
143
- private_credentials: PrivateCredentials,
144
- saturation_above_threshold: float | None = None,
145
- ) -> None:
146
- from_address = private_credentials.public_key
147
-
148
- now = utcnow()
149
- # We want to unfund markets ~1 day before the resolution should be known.
150
- # That is, if the original market would be closing now, but we added `EXTEND_CLOSING_TIME_DELTA` to it,
151
- # we want to unfund any market that closes sooner than NOW + `EXTEND_CLOSING_TIME_DELTA` - 1 day.
152
- opened_before = now + EXTEND_CLOSING_TIME_DELTA - timedelta(days=1)
153
-
154
- # Fetch markets that we created, are soon to be known,
155
- # and still have liquidity in them (we didn't withdraw it yet).
156
- markets = OmenSubgraphHandler().get_omen_binary_markets(
157
- limit=None,
158
- creator=from_address,
159
- opened_before=opened_before,
160
- liquidity_bigger_than=wei_type(0),
161
- )
162
-
163
- for idx, market in enumerate(markets):
164
- # Optionally, if `saturation_above_threshold` is provided, skip markets that are not saturated to leave some free money motivation for agents.
165
- if (
166
- saturation_above_threshold is not None
167
- and not market.is_resolved
168
- and not (
169
- market.current_p_yes > saturation_above_threshold
170
- or market.current_p_no > saturation_above_threshold
171
- )
172
- ):
173
- logger.info(
174
- f"[{idx+1}/{len(markets)}] Skipping unfunding of `{market.liquidityParameter=} {market.question=} {market.url=}`, because it's not saturated yet, `{market.current_p_yes=}`."
175
- )
176
- continue
177
- logger.info(
178
- f"[{idx+1}/{len(markets)}] Unfunding market `{market.liquidityParameter=} {market.question=} {market.url=}`."
179
- )
180
- omen_remove_fund_market_tx(
181
- private_credentials=private_credentials,
182
- market=OmenAgentMarket.from_data_model(market),
183
- shares=None,
184
- )