prediction-market-agent-tooling 0.64.12.dev660__py3-none-any.whl → 0.65.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.
Files changed (51) hide show
  1. prediction_market_agent_tooling/benchmark/agents.py +19 -16
  2. prediction_market_agent_tooling/benchmark/benchmark.py +94 -84
  3. prediction_market_agent_tooling/benchmark/utils.py +8 -9
  4. prediction_market_agent_tooling/deploy/agent.py +85 -125
  5. prediction_market_agent_tooling/deploy/agent_example.py +20 -10
  6. prediction_market_agent_tooling/deploy/betting_strategy.py +222 -96
  7. prediction_market_agent_tooling/deploy/constants.py +4 -0
  8. prediction_market_agent_tooling/jobs/jobs_models.py +15 -4
  9. prediction_market_agent_tooling/jobs/omen/omen_jobs.py +3 -3
  10. prediction_market_agent_tooling/markets/agent_market.py +145 -50
  11. prediction_market_agent_tooling/markets/blockchain_utils.py +10 -1
  12. prediction_market_agent_tooling/markets/data_models.py +83 -17
  13. prediction_market_agent_tooling/markets/manifold/api.py +18 -7
  14. prediction_market_agent_tooling/markets/manifold/data_models.py +23 -16
  15. prediction_market_agent_tooling/markets/manifold/manifold.py +18 -18
  16. prediction_market_agent_tooling/markets/manifold/utils.py +7 -12
  17. prediction_market_agent_tooling/markets/markets.py +2 -1
  18. prediction_market_agent_tooling/markets/metaculus/metaculus.py +29 -4
  19. prediction_market_agent_tooling/markets/omen/data_models.py +17 -32
  20. prediction_market_agent_tooling/markets/omen/omen.py +65 -108
  21. prediction_market_agent_tooling/markets/omen/omen_contracts.py +2 -5
  22. prediction_market_agent_tooling/markets/omen/omen_resolving.py +13 -13
  23. prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +18 -12
  24. prediction_market_agent_tooling/markets/polymarket/data_models.py +7 -3
  25. prediction_market_agent_tooling/markets/polymarket/data_models_web.py +7 -3
  26. prediction_market_agent_tooling/markets/polymarket/polymarket.py +5 -4
  27. prediction_market_agent_tooling/markets/seer/data_models.py +0 -83
  28. prediction_market_agent_tooling/markets/seer/price_manager.py +44 -30
  29. prediction_market_agent_tooling/markets/seer/seer.py +105 -105
  30. prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +34 -41
  31. prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +1 -1
  32. prediction_market_agent_tooling/tools/cow/cow_order.py +10 -3
  33. prediction_market_agent_tooling/tools/is_predictable.py +2 -3
  34. prediction_market_agent_tooling/tools/langfuse_client_utils.py +4 -4
  35. prediction_market_agent_tooling/tools/omen/sell_positions.py +3 -2
  36. prediction_market_agent_tooling/tools/utils.py +26 -13
  37. {prediction_market_agent_tooling-0.64.12.dev660.dist-info → prediction_market_agent_tooling-0.65.0.dist-info}/METADATA +2 -2
  38. {prediction_market_agent_tooling-0.64.12.dev660.dist-info → prediction_market_agent_tooling-0.65.0.dist-info}/RECORD +41 -51
  39. prediction_market_agent_tooling/monitor/financial_metrics/financial_metrics.py +0 -68
  40. prediction_market_agent_tooling/monitor/markets/manifold.py +0 -90
  41. prediction_market_agent_tooling/monitor/markets/metaculus.py +0 -43
  42. prediction_market_agent_tooling/monitor/markets/omen.py +0 -88
  43. prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -49
  44. prediction_market_agent_tooling/monitor/monitor.py +0 -406
  45. prediction_market_agent_tooling/monitor/monitor_app.py +0 -149
  46. prediction_market_agent_tooling/monitor/monitor_settings.py +0 -27
  47. prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -146
  48. prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -12
  49. {prediction_market_agent_tooling-0.64.12.dev660.dist-info → prediction_market_agent_tooling-0.65.0.dist-info}/LICENSE +0 -0
  50. {prediction_market_agent_tooling-0.64.12.dev660.dist-info → prediction_market_agent_tooling-0.65.0.dist-info}/WHEEL +0 -0
  51. {prediction_market_agent_tooling-0.64.12.dev660.dist-info → prediction_market_agent_tooling-0.65.0.dist-info}/entry_points.txt +0 -0
@@ -1,149 +0,0 @@
1
- import typing as t
2
- from datetime import datetime, timedelta
3
-
4
- import streamlit as st
5
-
6
- from prediction_market_agent_tooling.markets.agent_market import (
7
- AgentMarket,
8
- FilterBy,
9
- SortBy,
10
- )
11
- from prediction_market_agent_tooling.markets.markets import MarketType
12
- from prediction_market_agent_tooling.monitor.markets.manifold import (
13
- DeployedManifoldAgent,
14
- )
15
- from prediction_market_agent_tooling.monitor.markets.metaculus import (
16
- DeployedMetaculusAgent,
17
- )
18
- from prediction_market_agent_tooling.monitor.markets.omen import DeployedOmenAgent
19
- from prediction_market_agent_tooling.monitor.markets.polymarket import (
20
- DeployedPolymarketAgent,
21
- )
22
- from prediction_market_agent_tooling.monitor.monitor import (
23
- DeployedAgent,
24
- monitor_agent,
25
- monitor_market,
26
- )
27
- from prediction_market_agent_tooling.monitor.monitor_settings import MonitorSettings
28
- from prediction_market_agent_tooling.tools.utils import (
29
- DatetimeUTC,
30
- check_not_none,
31
- utc_datetime,
32
- utcnow,
33
- )
34
-
35
- MAX_MONITOR_MARKETS = 1000
36
-
37
- MARKET_TYPE_TO_DEPLOYED_AGENT: dict[MarketType, type[DeployedAgent]] = {
38
- MarketType.MANIFOLD: DeployedManifoldAgent,
39
- MarketType.OMEN: DeployedOmenAgent,
40
- MarketType.POLYMARKET: DeployedPolymarketAgent,
41
- MarketType.METACULUS: DeployedMetaculusAgent,
42
- }
43
-
44
-
45
- def get_deployed_agents(
46
- market_type: MarketType,
47
- settings: MonitorSettings,
48
- start_time: DatetimeUTC | None,
49
- ) -> list[DeployedAgent]:
50
- cls = MARKET_TYPE_TO_DEPLOYED_AGENT.get(market_type)
51
- if cls is None:
52
- raise ValueError(f"Unknown market type: {market_type}")
53
-
54
- agents: list[DeployedAgent] = []
55
-
56
- if settings.LOAD_FROM_GCF:
57
- agents.extend(cls.from_all_gcp_functions())
58
-
59
- if settings.LOAD_FROM_GCK:
60
- agents.extend(
61
- cls.from_all_gcp_cronjobs(namespace=settings.LOAD_FROM_GCK_NAMESPACE)
62
- )
63
-
64
- match market_type:
65
- case MarketType.MANIFOLD:
66
- agents += settings.MANIFOLD_AGENTS
67
- case MarketType.OMEN:
68
- agents += settings.OMEN_AGENTS
69
- case MarketType.POLYMARKET:
70
- agents += settings.POLYMARKET_AGENTS
71
- case _:
72
- raise ValueError(f"Unknown market type: {market_type}")
73
-
74
- return agents
75
-
76
-
77
- def get_open_and_resolved_markets(
78
- start_time: DatetimeUTC,
79
- market_type: MarketType,
80
- ) -> tuple[t.Sequence[AgentMarket], t.Sequence[AgentMarket]]:
81
- cls = market_type.market_class
82
- open_markets = cls.get_binary_markets(
83
- limit=MAX_MONITOR_MARKETS,
84
- sort_by=SortBy.NEWEST,
85
- created_after=start_time,
86
- filter_by=FilterBy.OPEN,
87
- )
88
- resolved_markets = cls.get_binary_markets(
89
- limit=MAX_MONITOR_MARKETS,
90
- sort_by=SortBy.NEWEST,
91
- created_after=start_time,
92
- filter_by=FilterBy.RESOLVED,
93
- )
94
- resolved_markets = [m for m in resolved_markets if m.has_successful_resolution()]
95
- return open_markets, resolved_markets
96
-
97
-
98
- def monitor_app(
99
- enabled_market_types: list[MarketType],
100
- ) -> None:
101
- settings = MonitorSettings()
102
- market_type: MarketType = check_not_none(
103
- st.selectbox(label="Market type", options=enabled_market_types, index=0)
104
- )
105
- start_time: DatetimeUTC | None = (
106
- DatetimeUTC.from_datetime(
107
- datetime.combine(
108
- st.date_input(
109
- "Start time",
110
- value=utcnow() - timedelta(weeks=settings.PAST_N_WEEKS),
111
- ),
112
- datetime.min.time(),
113
- )
114
- )
115
- if settings.has_manual_agents
116
- else None
117
- )
118
-
119
- with st.spinner("Loading agents"):
120
- agents: list[DeployedAgent] = get_deployed_agents(
121
- market_type=market_type,
122
- settings=settings,
123
- start_time=start_time,
124
- )
125
-
126
- oldest_start_time = (
127
- min(agent.start_time for agent in agents)
128
- if agents
129
- else utc_datetime(2020, 1, 1)
130
- )
131
-
132
- st.header("Market Info")
133
- if st.checkbox("Show Market Info"):
134
- with st.spinner("Loading markets"):
135
- open_markets, resolved_markets = get_open_and_resolved_markets(
136
- start_time=oldest_start_time, market_type=market_type
137
- )
138
- (
139
- monitor_market(open_markets=open_markets, resolved_markets=resolved_markets)
140
- if open_markets and resolved_markets
141
- else st.warning("No market data found.")
142
- )
143
-
144
- st.header("Agent Info")
145
- if st.button("Export agents"):
146
- st.text("[" + ",".join(a.model_dump_json() for a in agents) + "]")
147
- for agent in agents:
148
- with st.expander(f"Agent: '{agent.name}'"):
149
- monitor_agent(agent)
@@ -1,27 +0,0 @@
1
- from pydantic_settings import BaseSettings, SettingsConfigDict
2
-
3
- from prediction_market_agent_tooling.monitor.markets.manifold import (
4
- DeployedManifoldAgent,
5
- )
6
- from prediction_market_agent_tooling.monitor.markets.omen import DeployedOmenAgent
7
- from prediction_market_agent_tooling.monitor.markets.polymarket import (
8
- DeployedPolymarketAgent,
9
- )
10
-
11
-
12
- class MonitorSettings(BaseSettings):
13
- model_config = SettingsConfigDict(
14
- env_file=".env.monitor", env_file_encoding="utf-8", extra="ignore"
15
- )
16
-
17
- LOAD_FROM_GCF: bool = False
18
- LOAD_FROM_GCK: bool = False
19
- LOAD_FROM_GCK_NAMESPACE: str = "agents"
20
- MANIFOLD_AGENTS: list[DeployedManifoldAgent] = []
21
- OMEN_AGENTS: list[DeployedOmenAgent] = []
22
- POLYMARKET_AGENTS: list[DeployedPolymarketAgent] = []
23
- PAST_N_WEEKS: int = 1
24
-
25
- @property
26
- def has_manual_agents(self) -> bool:
27
- return bool(self.MANIFOLD_AGENTS or self.OMEN_AGENTS or self.POLYMARKET_AGENTS)
@@ -1,146 +0,0 @@
1
- from functools import reduce
2
-
3
- import numpy as np
4
-
5
- from prediction_market_agent_tooling.gtypes import (
6
- CollateralToken,
7
- OutcomeToken,
8
- Probability,
9
- )
10
- from prediction_market_agent_tooling.markets.omen.omen import (
11
- MarketFees,
12
- OmenAgentMarket,
13
- )
14
- from prediction_market_agent_tooling.tools.betting_strategies.utils import SimpleBet
15
- from prediction_market_agent_tooling.tools.utils import check_not_none
16
-
17
-
18
- def get_market_moving_bet(
19
- yes_outcome_pool_size: OutcomeToken,
20
- no_outcome_pool_size: OutcomeToken,
21
- market_p_yes: float,
22
- target_p_yes: float,
23
- fees: MarketFees,
24
- max_iters: int = 100,
25
- ) -> SimpleBet:
26
- """
27
- Implements a binary search to determine the bet that will move the market's
28
- `p_yes` to that of the target.
29
-
30
- Consider a binary fixed-product market containing `x` and `y` tokens.
31
- A trader wishes to acquire `x` tokens by betting an amount `d0`.
32
-
33
- The calculation to determine the number of `x` tokens he acquires, denoted
34
- by `dx`, is:
35
-
36
- a_x * a_y = fixed_product
37
- na_x = a_x + d0
38
- na_y = a_y + d0
39
- na_x * na_y = new_product
40
- (na_x - dx) * na_y = fixed_product
41
- (na_x * na_y) - (dx * na_y) = fixed_product
42
- new_product - fixed_product = dx * na_y
43
- dx = (new_product - fixed_product) / na_y
44
- """
45
- fixed_product = yes_outcome_pool_size * no_outcome_pool_size
46
- bet_direction: bool = target_p_yes > market_p_yes
47
-
48
- min_bet_amount = CollateralToken(0.0)
49
- max_bet_amount = (
50
- yes_outcome_pool_size + no_outcome_pool_size
51
- ).as_token * 100 # TODO set a better upper bound
52
-
53
- # Binary search for the optimal bet amount
54
- for _ in range(max_iters):
55
- bet_amount = (min_bet_amount + max_bet_amount) / 2
56
- amounts_diff = fees.get_after_fees(bet_amount)
57
- amounts_diff_as_ot = OutcomeToken.from_token(amounts_diff)
58
-
59
- # Initial new amounts are old amounts + equal new amounts for each outcome
60
- yes_outcome_new_pool_size = yes_outcome_pool_size + amounts_diff_as_ot
61
- no_outcome_new_pool_size = no_outcome_pool_size + amounts_diff_as_ot
62
- new_amounts: dict[bool, OutcomeToken] = {
63
- True: yes_outcome_new_pool_size,
64
- False: no_outcome_new_pool_size,
65
- }
66
-
67
- # Now give away tokens at `bet_outcome_index` to restore invariant
68
- new_product = yes_outcome_new_pool_size * no_outcome_new_pool_size
69
- dx = (new_product - fixed_product) / new_amounts[not bet_direction]
70
- new_amounts[bet_direction] -= OutcomeToken(dx)
71
-
72
- # Check that the invariant is restored
73
- assert np.isclose(
74
- reduce(lambda x, y: x * y.value, list(new_amounts.values()), 1.0),
75
- float(fixed_product),
76
- )
77
-
78
- new_p_yes = Probability(
79
- (
80
- new_amounts[False]
81
- / sum(list(new_amounts.values()), start=OutcomeToken(0))
82
- )
83
- )
84
- if abs(target_p_yes - new_p_yes) < 1e-6:
85
- break
86
- elif new_p_yes > target_p_yes:
87
- if bet_direction:
88
- max_bet_amount = bet_amount
89
- else:
90
- min_bet_amount = bet_amount
91
- else:
92
- if bet_direction:
93
- min_bet_amount = bet_amount
94
- else:
95
- max_bet_amount = bet_amount
96
-
97
- return SimpleBet(direction=bet_direction, size=bet_amount)
98
-
99
-
100
- def _sanity_check_omen_market_moving_bet(
101
- bet_to_check: SimpleBet, market: OmenAgentMarket, target_p_yes: float
102
- ) -> None:
103
- """
104
- A util function for checking that a bet moves the market to the target_p_yes
105
- by calling the market's calcBuyAmount method from the smart contract, and
106
- using the adjusted outcome pool sizes to calculate the new p_yes.
107
- """
108
- buy_amount_ = market.get_contract().calcBuyAmount(
109
- investment_amount=bet_to_check.size.as_wei,
110
- outcome_index=market.get_outcome_index(
111
- market.get_outcome_str_from_bool(bet_to_check.direction)
112
- ),
113
- )
114
- buy_amount = buy_amount_.as_outcome_token
115
-
116
- outcome_token_pool = check_not_none(market.outcome_token_pool)
117
- yes_outcome_pool_size = outcome_token_pool[market.get_outcome_str_from_bool(True)]
118
- no_outcome_pool_size = outcome_token_pool[market.get_outcome_str_from_bool(False)]
119
- market_const = yes_outcome_pool_size.value * no_outcome_pool_size.value
120
-
121
- bet_to_check_size_after_fees = market.fees.get_after_fees(bet_to_check.size).value
122
-
123
- # When you buy 'yes' tokens, you add your bet size to the both pools, then
124
- # subtract `buy_amount` from the 'yes' pool. And vice versa for 'no' tokens.
125
- new_yes_outcome_pool_size = (
126
- yes_outcome_pool_size.value
127
- + bet_to_check_size_after_fees
128
- - float(bet_to_check.direction) * buy_amount.value
129
- )
130
- new_no_outcome_pool_size = (
131
- no_outcome_pool_size.value
132
- + bet_to_check_size_after_fees
133
- - float(not bet_to_check.direction) * buy_amount.value
134
- )
135
- new_market_const = new_yes_outcome_pool_size * new_no_outcome_pool_size
136
- # Check the invariant is restored
137
- assert np.isclose(new_market_const, market_const)
138
-
139
- # Now check that the market's new p_yes is equal to the target_p_yes
140
- new_p_yes = new_no_outcome_pool_size / (
141
- new_yes_outcome_pool_size + new_no_outcome_pool_size
142
- )
143
- if not np.isclose(new_p_yes, target_p_yes, atol=0.01):
144
- raise ValueError(
145
- f"Bet does not move market to target_p_yes {target_p_yes=}. Got {new_p_yes=}"
146
- )
@@ -1,12 +0,0 @@
1
- from prediction_market_agent_tooling.markets.agent_market import AgentMarket
2
-
3
-
4
- def minimum_bet_to_win(
5
- answer: bool, amount_to_win: float, market: AgentMarket
6
- ) -> float:
7
- """
8
- Estimates the minimum bet amount to win the given amount based on the current market price.
9
- """
10
- share_price = market.current_p_yes if answer else market.current_p_no
11
- bet_amount = amount_to_win / (1 / share_price - 1)
12
- return bet_amount