prediction-market-agent-tooling 0.56.3__tar.gz → 0.57.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/PKG-INFO +1 -1
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/config.py +29 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/deploy/agent.py +67 -40
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/data_models.py +21 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -1
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/omen/data_models.py +4 -7
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +8 -4
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/polymarket/utils.py +1 -1
- prediction_market_agent_tooling-0.57.0/prediction_market_agent_tooling/monitor/financial_metrics/financial_metrics.py +66 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/contract.py +3 -7
- prediction_market_agent_tooling-0.56.3/prediction_market_agent_tooling/tools/google.py → prediction_market_agent_tooling-0.57.0/prediction_market_agent_tooling/tools/google_utils.py +28 -1
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +1 -1
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/is_invalid.py +1 -1
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/is_predictable.py +8 -3
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +1 -0
- prediction_market_agent_tooling-0.57.0/prediction_market_agent_tooling/tools/transaction_cache.py +48 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/utils.py +1 -23
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/web3_utils.py +5 -1
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/pyproject.toml +2 -1
- prediction_market_agent_tooling-0.56.3/prediction_market_agent_tooling/tools/gnosis_rpc.py +0 -6
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/LICENSE +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/README.md +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_agentresultmapping.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/deploy/betting_strategy.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/deploy/constants.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/deploy/trade_interval.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/gtypes.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/jobs/jobs_models.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/loggers.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/agent_market.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/base_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/categorize.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/market_fees.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/markets.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/omen/omen.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/polymarket/api.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/seer/data_models.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/markets/seer/seer_subgraph_handler.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/monitor/markets/manifold.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/monitor/markets/metaculus.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/monitor/markets/omen.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/monitor/monitor.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/monitor/monitor_app.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/monitor/monitor_settings.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/py.typed +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/balances.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/caches/db_cache.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/caches/inmemory_cache.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/costs.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/custom_exceptions.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/datetime_utc.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/httpx_cached_client.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/relevant_news_analysis/data_models.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_analysis.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/relevant_news_analysis/relevant_news_cache.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/safe.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/singleton.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/tavily/tavily_models.py +0 -0
- {prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/prediction_market_agent_tooling/tools/tavily/tavily_search.py +0 -0
@@ -1,5 +1,6 @@
|
|
1
1
|
import typing as t
|
2
2
|
|
3
|
+
from pydantic import Field
|
3
4
|
from pydantic.types import SecretStr
|
4
5
|
from pydantic.v1.types import SecretStr as SecretStrV1
|
5
6
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
@@ -7,6 +8,7 @@ from safe_eth.eth import EthereumClient
|
|
7
8
|
from safe_eth.safe.safe import SafeV141
|
8
9
|
|
9
10
|
from prediction_market_agent_tooling.gtypes import (
|
11
|
+
ChainID,
|
10
12
|
ChecksumAddress,
|
11
13
|
PrivateKey,
|
12
14
|
secretstr_to_v1_secretstr,
|
@@ -203,3 +205,30 @@ class APIKeys(BaseSettings):
|
|
203
205
|
s = SafeV141(self.SAFE_ADDRESS, ethereum_client)
|
204
206
|
public_key_from_signer = private_key_to_public_key(self.bet_from_private_key)
|
205
207
|
return s.retrieve_is_owner(public_key_from_signer)
|
208
|
+
|
209
|
+
|
210
|
+
class RPCConfig(BaseSettings):
|
211
|
+
model_config = SettingsConfigDict(
|
212
|
+
env_file=".env", env_file_encoding="utf-8", extra="ignore"
|
213
|
+
)
|
214
|
+
|
215
|
+
GNOSIS_RPC_URL: str = Field(default="https://rpc.gnosischain.com")
|
216
|
+
CHAIN_ID: ChainID = Field(default=ChainID(100))
|
217
|
+
|
218
|
+
@property
|
219
|
+
def gnosis_rpc_url(self) -> str:
|
220
|
+
return check_not_none(
|
221
|
+
self.GNOSIS_RPC_URL, "GNOSIS_RPC_URL missing in the environment."
|
222
|
+
)
|
223
|
+
|
224
|
+
@property
|
225
|
+
def chain_id(self) -> ChainID:
|
226
|
+
return check_not_none(self.CHAIN_ID, "CHAIN_ID missing in the environment.")
|
227
|
+
|
228
|
+
|
229
|
+
class CloudCredentials(BaseSettings):
|
230
|
+
model_config = SettingsConfigDict(
|
231
|
+
env_file=".env", env_file_encoding="utf-8", extra="ignore"
|
232
|
+
)
|
233
|
+
|
234
|
+
GOOGLE_APPLICATION_CREDENTIALS: t.Optional[str] = None
|
@@ -8,8 +8,7 @@ from datetime import timedelta
|
|
8
8
|
from enum import Enum
|
9
9
|
from functools import cached_property
|
10
10
|
|
11
|
-
from pydantic import
|
12
|
-
from typing_extensions import Annotated
|
11
|
+
from pydantic import computed_field
|
13
12
|
|
14
13
|
from prediction_market_agent_tooling.config import APIKeys
|
15
14
|
from prediction_market_agent_tooling.deploy.betting_strategy import (
|
@@ -69,27 +68,6 @@ from prediction_market_agent_tooling.tools.langfuse_ import langfuse_context, ob
|
|
69
68
|
from prediction_market_agent_tooling.tools.utils import DatetimeUTC, utcnow
|
70
69
|
|
71
70
|
MAX_AVAILABLE_MARKETS = 20
|
72
|
-
TRADER_TAG = "trader"
|
73
|
-
|
74
|
-
|
75
|
-
def to_boolean_outcome(value: str | bool) -> bool:
|
76
|
-
if isinstance(value, bool):
|
77
|
-
return value
|
78
|
-
|
79
|
-
elif isinstance(value, str):
|
80
|
-
value = value.lower().strip()
|
81
|
-
|
82
|
-
if value in {"true", "yes", "y", "1"}:
|
83
|
-
return True
|
84
|
-
|
85
|
-
elif value in {"false", "no", "n", "0"}:
|
86
|
-
return False
|
87
|
-
|
88
|
-
else:
|
89
|
-
raise ValueError(f"Expected a boolean string, but got {value}")
|
90
|
-
|
91
|
-
else:
|
92
|
-
raise ValueError(f"Expected a boolean or a string, but got {value}")
|
93
71
|
|
94
72
|
|
95
73
|
def initialize_langfuse(enable_langfuse: bool) -> None:
|
@@ -107,15 +85,21 @@ def initialize_langfuse(enable_langfuse: bool) -> None:
|
|
107
85
|
langfuse_context.configure(enabled=enable_langfuse)
|
108
86
|
|
109
87
|
|
110
|
-
Decision = Annotated[bool, BeforeValidator(to_boolean_outcome)]
|
111
|
-
|
112
|
-
|
113
88
|
class AnsweredEnum(str, Enum):
|
114
89
|
ANSWERED = "answered"
|
115
90
|
NOT_ANSWERED = "not_answered"
|
116
91
|
|
117
92
|
|
93
|
+
class AgentTagEnum(str, Enum):
|
94
|
+
PREDICTOR = "predictor"
|
95
|
+
TRADER = "trader"
|
96
|
+
|
97
|
+
|
118
98
|
class DeployableAgent:
|
99
|
+
"""
|
100
|
+
Subclass this class to create agent with standardized interface.
|
101
|
+
"""
|
102
|
+
|
119
103
|
def __init__(
|
120
104
|
self,
|
121
105
|
enable_langfuse: bool = APIKeys().default_enable_langfuse,
|
@@ -176,20 +160,25 @@ class DeployableAgent:
|
|
176
160
|
)
|
177
161
|
|
178
162
|
def load(self) -> None:
|
179
|
-
|
163
|
+
"""
|
164
|
+
Implement this method to load arbitrary instances needed across the whole run of the agent.
|
165
|
+
|
166
|
+
Do not customize __init__ method.
|
167
|
+
"""
|
180
168
|
|
181
169
|
def deploy_local(
|
182
170
|
self,
|
183
171
|
market_type: MarketType,
|
184
172
|
sleep_time: float,
|
185
|
-
|
173
|
+
run_time: float | None,
|
186
174
|
) -> None:
|
175
|
+
"""
|
176
|
+
Run the agent in the forever cycle every `sleep_time` seconds, until the `run_time` is met.
|
177
|
+
"""
|
187
178
|
start_time = time.time()
|
188
|
-
while
|
179
|
+
while run_time is None or time.time() - start_time < run_time:
|
189
180
|
self.run(market_type=market_type)
|
190
181
|
time.sleep(sleep_time)
|
191
|
-
if time.time() - start_time > timeout:
|
192
|
-
break
|
193
182
|
|
194
183
|
def deploy_gcp(
|
195
184
|
self,
|
@@ -205,6 +194,9 @@ class DeployableAgent:
|
|
205
194
|
start_time: DatetimeUTC | None = None,
|
206
195
|
timeout: int = 180,
|
207
196
|
) -> None:
|
197
|
+
"""
|
198
|
+
Deploy the agent as GCP Function.
|
199
|
+
"""
|
208
200
|
path_to_agent_file = os.path.relpath(inspect.getfile(self.__class__))
|
209
201
|
|
210
202
|
entrypoint_function_name = "main"
|
@@ -271,6 +263,9 @@ def {entrypoint_function_name}(request) -> str:
|
|
271
263
|
schedule_deployed_gcp_function(fname, cron_schedule=cron_schedule)
|
272
264
|
|
273
265
|
def run(self, market_type: MarketType) -> None:
|
266
|
+
"""
|
267
|
+
Run single iteration of the agent.
|
268
|
+
"""
|
274
269
|
raise NotImplementedError("This method must be implemented by the subclass.")
|
275
270
|
|
276
271
|
def get_gcloud_fname(self, market_type: MarketType) -> str:
|
@@ -278,6 +273,14 @@ def {entrypoint_function_name}(request) -> str:
|
|
278
273
|
|
279
274
|
|
280
275
|
class DeployablePredictionAgent(DeployableAgent):
|
276
|
+
"""
|
277
|
+
Subclass this class to create your own prediction market agent.
|
278
|
+
|
279
|
+
The agent will process markets and make predictions.
|
280
|
+
"""
|
281
|
+
|
282
|
+
AGENT_TAG: AgentTagEnum = AgentTagEnum.PREDICTOR
|
283
|
+
|
281
284
|
bet_on_n_markets_per_run: int = 1
|
282
285
|
|
283
286
|
# Agent behaviour when fetching markets
|
@@ -297,10 +300,10 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
297
300
|
def __init__(
|
298
301
|
self,
|
299
302
|
enable_langfuse: bool = APIKeys().default_enable_langfuse,
|
300
|
-
|
303
|
+
store_predictions: bool = True,
|
301
304
|
) -> None:
|
302
305
|
super().__init__(enable_langfuse=enable_langfuse)
|
303
|
-
self.
|
306
|
+
self.store_predictions = store_predictions
|
304
307
|
|
305
308
|
def initialize_langfuse(self) -> None:
|
306
309
|
super().initialize_langfuse()
|
@@ -328,7 +331,7 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
328
331
|
) -> None:
|
329
332
|
self.langfuse_update_current_trace(
|
330
333
|
tags=[
|
331
|
-
|
334
|
+
self.AGENT_TAG,
|
332
335
|
(
|
333
336
|
AnsweredEnum.ANSWERED
|
334
337
|
if processed_market is not None
|
@@ -386,6 +389,9 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
386
389
|
self,
|
387
390
|
market_type: MarketType,
|
388
391
|
) -> t.Sequence[AgentMarket]:
|
392
|
+
"""
|
393
|
+
Override this method to customize what markets will fetch for processing.
|
394
|
+
"""
|
389
395
|
cls = market_type.market_class
|
390
396
|
# Fetch the soonest closing markets to choose from
|
391
397
|
available_markets = cls.get_binary_markets(
|
@@ -399,6 +405,9 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
399
405
|
def before_process_market(
|
400
406
|
self, market_type: MarketType, market: AgentMarket
|
401
407
|
) -> None:
|
408
|
+
"""
|
409
|
+
Executed before processing of each market.
|
410
|
+
"""
|
402
411
|
api_keys = APIKeys()
|
403
412
|
|
404
413
|
if market_type.is_blockchain_market:
|
@@ -442,19 +451,22 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
442
451
|
market: AgentMarket,
|
443
452
|
processed_market: ProcessedMarket | None,
|
444
453
|
) -> None:
|
454
|
+
"""
|
455
|
+
Executed after processing of each market.
|
456
|
+
"""
|
445
457
|
keys = APIKeys()
|
446
|
-
if self.
|
458
|
+
if self.store_predictions:
|
447
459
|
market.store_prediction(
|
448
460
|
processed_market=processed_market, keys=keys, agent_name=self.agent_name
|
449
461
|
)
|
450
462
|
else:
|
451
463
|
logger.info(
|
452
|
-
f"Prediction {processed_market} not stored because {self.
|
464
|
+
f"Prediction {processed_market} not stored because {self.store_predictions=}."
|
453
465
|
)
|
454
466
|
|
455
467
|
def before_process_markets(self, market_type: MarketType) -> None:
|
456
468
|
"""
|
457
|
-
|
469
|
+
Executed before market processing loop starts.
|
458
470
|
"""
|
459
471
|
api_keys = APIKeys()
|
460
472
|
self.check_min_required_balance_to_operate(market_type)
|
@@ -485,7 +497,9 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
485
497
|
logger.info("All markets processed.")
|
486
498
|
|
487
499
|
def after_process_markets(self, market_type: MarketType) -> None:
|
488
|
-
"
|
500
|
+
"""
|
501
|
+
Executed after market processing loop ends.
|
502
|
+
"""
|
489
503
|
|
490
504
|
def run(self, market_type: MarketType) -> None:
|
491
505
|
if market_type not in self.supported_markets:
|
@@ -498,6 +512,14 @@ class DeployablePredictionAgent(DeployableAgent):
|
|
498
512
|
|
499
513
|
|
500
514
|
class DeployableTraderAgent(DeployablePredictionAgent):
|
515
|
+
"""
|
516
|
+
Subclass this class to create your own prediction market trading agent.
|
517
|
+
|
518
|
+
The agent will process markets, make predictions and place trades (bets) based off these predictions.
|
519
|
+
"""
|
520
|
+
|
521
|
+
AGENT_TAG: AgentTagEnum = AgentTagEnum.TRADER
|
522
|
+
|
501
523
|
# These markets require place of bet, not just predictions.
|
502
524
|
supported_markets: t.Sequence[MarketType] = [
|
503
525
|
MarketType.OMEN,
|
@@ -508,12 +530,12 @@ class DeployableTraderAgent(DeployablePredictionAgent):
|
|
508
530
|
def __init__(
|
509
531
|
self,
|
510
532
|
enable_langfuse: bool = APIKeys().default_enable_langfuse,
|
511
|
-
|
533
|
+
store_predictions: bool = True,
|
512
534
|
store_trades: bool = True,
|
513
535
|
place_trades: bool = True,
|
514
536
|
) -> None:
|
515
537
|
super().__init__(
|
516
|
-
enable_langfuse=enable_langfuse,
|
538
|
+
enable_langfuse=enable_langfuse, store_predictions=store_predictions
|
517
539
|
)
|
518
540
|
self.store_trades = store_trades
|
519
541
|
self.place_trades = place_trades
|
@@ -537,6 +559,11 @@ class DeployableTraderAgent(DeployablePredictionAgent):
|
|
537
559
|
)
|
538
560
|
|
539
561
|
def get_betting_strategy(self, market: AgentMarket) -> BettingStrategy:
|
562
|
+
"""
|
563
|
+
Override this method to customize betting strategy of your agent.
|
564
|
+
|
565
|
+
Given the market and prediction, agent uses this method to calculate optimal outcome and bet size.
|
566
|
+
"""
|
540
567
|
user_id = market.get_user_id(api_keys=APIKeys())
|
541
568
|
|
542
569
|
total_amount = market.get_tiny_bet_amount().amount
|
@@ -140,3 +140,24 @@ class PlacedTrade(Trade):
|
|
140
140
|
amount=trade.amount,
|
141
141
|
id=id,
|
142
142
|
)
|
143
|
+
|
144
|
+
|
145
|
+
class SimulationDetail(BaseModel):
|
146
|
+
strategy: str
|
147
|
+
url: str
|
148
|
+
market_p_yes: float
|
149
|
+
agent_p_yes: float
|
150
|
+
agent_conf: float
|
151
|
+
org_bet: float
|
152
|
+
sim_bet: float
|
153
|
+
org_dir: bool
|
154
|
+
sim_dir: bool
|
155
|
+
org_profit: float
|
156
|
+
sim_profit: float
|
157
|
+
timestamp: DatetimeUTC
|
158
|
+
|
159
|
+
|
160
|
+
class SharpeOutput(BaseModel):
|
161
|
+
annualized_volatility: float
|
162
|
+
mean_daily_return: float
|
163
|
+
annualized_sharpe_ratio: float
|
@@ -531,7 +531,6 @@ class OmenBet(BaseModel):
|
|
531
531
|
if self.boolean_outcome == self.fpmm.boolean_outcome
|
532
532
|
else -bet_amount_xdai
|
533
533
|
)
|
534
|
-
profit -= wei_to_xdai(self.feeAmount)
|
535
534
|
return ProfitAmount(
|
536
535
|
amount=profit,
|
537
536
|
currency=Currency.xDai,
|
@@ -539,9 +538,8 @@ class OmenBet(BaseModel):
|
|
539
538
|
|
540
539
|
def to_bet(self) -> Bet:
|
541
540
|
return Bet(
|
542
|
-
id=str(
|
543
|
-
|
544
|
-
), # Use the transaction hash instead of the bet id - both are valid, but we return the transaction hash from the trade functions, so be consistent here.
|
541
|
+
id=str(self.transactionHash),
|
542
|
+
# Use the transaction hash instead of the bet id - both are valid, but we return the transaction hash from the trade functions, so be consistent here.
|
545
543
|
amount=BetAmount(amount=self.collateralAmountUSD, currency=Currency.xDai),
|
546
544
|
outcome=self.boolean_outcome,
|
547
545
|
created_time=self.creation_datetime,
|
@@ -556,9 +554,8 @@ class OmenBet(BaseModel):
|
|
556
554
|
)
|
557
555
|
|
558
556
|
return ResolvedBet(
|
559
|
-
id=
|
560
|
-
|
561
|
-
), # Use the transaction hash instead of the bet id - both are valid, but we return the transaction hash from the trade functions, so be consistent here.
|
557
|
+
id=self.transactionHash.hex(),
|
558
|
+
# Use the transaction hash instead of the bet id - both are valid, but we return the transaction hash from the trade functions, so be consistent here.
|
562
559
|
amount=BetAmount(amount=self.collateralAmountUSD, currency=Currency.xDai),
|
563
560
|
outcome=self.boolean_outcome,
|
564
561
|
created_time=self.creation_datetime,
|
@@ -435,10 +435,14 @@ class OmenSubgraphHandler(BaseSubgraphHandler):
|
|
435
435
|
omen_markets = self.do_query(fields=fields, pydantic_model=OmenMarket)
|
436
436
|
return omen_markets
|
437
437
|
|
438
|
-
def get_omen_market_by_market_id(
|
439
|
-
|
440
|
-
|
441
|
-
)
|
438
|
+
def get_omen_market_by_market_id(
|
439
|
+
self, market_id: HexAddress, block_number: int | None = None
|
440
|
+
) -> OmenMarket:
|
441
|
+
query_filters: dict[str, t.Any] = {"id": market_id.lower()}
|
442
|
+
if block_number:
|
443
|
+
query_filters["block"] = {"number": block_number}
|
444
|
+
|
445
|
+
markets = self.trades_subgraph.Query.fixedProductMarketMaker(**query_filters)
|
442
446
|
|
443
447
|
fields = self._get_fields_for_markets(markets)
|
444
448
|
omen_markets = self.do_query(fields=fields, pydantic_model=OmenMarket)
|
@@ -3,7 +3,7 @@ from prediction_market_agent_tooling.markets.markets import MarketType
|
|
3
3
|
from prediction_market_agent_tooling.markets.polymarket.data_models_web import (
|
4
4
|
PolymarketFullMarket,
|
5
5
|
)
|
6
|
-
from prediction_market_agent_tooling.tools.
|
6
|
+
from prediction_market_agent_tooling.tools.google_utils import search_google
|
7
7
|
|
8
8
|
|
9
9
|
def find_resolution_on_polymarket(question: str) -> Resolution | None:
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import pandas as pd
|
3
|
+
|
4
|
+
from prediction_market_agent_tooling.markets.data_models import (
|
5
|
+
SharpeOutput,
|
6
|
+
SimulationDetail,
|
7
|
+
)
|
8
|
+
|
9
|
+
|
10
|
+
class SharpeRatioCalculator:
|
11
|
+
def __init__(
|
12
|
+
self, details: list[SimulationDetail], risk_free_rate: float = 0.0
|
13
|
+
) -> None:
|
14
|
+
self.details = details
|
15
|
+
self.df = pd.DataFrame([d.model_dump() for d in self.details])
|
16
|
+
self.risk_free_rate = risk_free_rate
|
17
|
+
|
18
|
+
def __has_df_valid_columns_else_exception(
|
19
|
+
self, required_columns: list[str]
|
20
|
+
) -> None:
|
21
|
+
if not set(required_columns).issubset(self.df.columns):
|
22
|
+
raise ValueError("Dataframe doesn't contain all the required columns.")
|
23
|
+
|
24
|
+
def prepare_wallet_daily_balance_df(
|
25
|
+
self, timestamp_col_name: str, profit_col_name: str
|
26
|
+
) -> pd.DataFrame:
|
27
|
+
self.__has_df_valid_columns_else_exception(
|
28
|
+
[timestamp_col_name, profit_col_name]
|
29
|
+
)
|
30
|
+
df = self.df.copy()
|
31
|
+
df[timestamp_col_name] = pd.to_datetime(df[timestamp_col_name])
|
32
|
+
df.sort_values(timestamp_col_name, ascending=True, inplace=True)
|
33
|
+
|
34
|
+
df["profit_cumsum"] = df[profit_col_name].cumsum()
|
35
|
+
df["profit_cumsum"] = df["profit_cumsum"] + 50
|
36
|
+
|
37
|
+
df = df.drop_duplicates(subset=timestamp_col_name, keep="last")
|
38
|
+
df.set_index(timestamp_col_name, inplace=True)
|
39
|
+
# We generate a new Dataframe with daily wallet balances, derived by the final wallet balance
|
40
|
+
# from the previous day.
|
41
|
+
wallet_balance_daily_df = df[["profit_cumsum"]].resample("D").ffill()
|
42
|
+
wallet_balance_daily_df.dropna(inplace=True)
|
43
|
+
wallet_balance_daily_df["returns"] = wallet_balance_daily_df[
|
44
|
+
"profit_cumsum"
|
45
|
+
].pct_change()
|
46
|
+
return wallet_balance_daily_df
|
47
|
+
|
48
|
+
def calculate_annual_sharpe_ratio(
|
49
|
+
self, timestamp_col_name: str = "timestamp", profit_col_name: str = "sim_profit"
|
50
|
+
) -> SharpeOutput:
|
51
|
+
wallet_daily_balance_df = self.prepare_wallet_daily_balance_df(
|
52
|
+
timestamp_col_name=timestamp_col_name, profit_col_name=profit_col_name
|
53
|
+
)
|
54
|
+
|
55
|
+
daily_volatility = wallet_daily_balance_df["returns"].std()
|
56
|
+
annualized_volatility = daily_volatility * np.sqrt(365)
|
57
|
+
mean_daily_return = wallet_daily_balance_df["returns"].mean()
|
58
|
+
daily_sharpe_ratio = (
|
59
|
+
mean_daily_return - self.risk_free_rate
|
60
|
+
) / daily_volatility
|
61
|
+
annualized_sharpe_ratio = daily_sharpe_ratio * np.sqrt(365)
|
62
|
+
return SharpeOutput(
|
63
|
+
annualized_volatility=annualized_volatility,
|
64
|
+
mean_daily_return=mean_daily_return,
|
65
|
+
annualized_sharpe_ratio=annualized_sharpe_ratio,
|
66
|
+
)
|
@@ -8,7 +8,7 @@ from pydantic import BaseModel, field_validator
|
|
8
8
|
from web3 import Web3
|
9
9
|
from web3.contract.contract import Contract as Web3Contract
|
10
10
|
|
11
|
-
from prediction_market_agent_tooling.config import APIKeys
|
11
|
+
from prediction_market_agent_tooling.config import APIKeys, RPCConfig
|
12
12
|
from prediction_market_agent_tooling.gtypes import (
|
13
13
|
ABI,
|
14
14
|
ChainID,
|
@@ -18,10 +18,6 @@ from prediction_market_agent_tooling.gtypes import (
|
|
18
18
|
TxReceipt,
|
19
19
|
Wei,
|
20
20
|
)
|
21
|
-
from prediction_market_agent_tooling.tools.gnosis_rpc import (
|
22
|
-
GNOSIS_NETWORK_ID,
|
23
|
-
GNOSIS_RPC_URL,
|
24
|
-
)
|
25
21
|
from prediction_market_agent_tooling.tools.utils import DatetimeUTC, should_not_happen
|
26
22
|
from prediction_market_agent_tooling.tools.web3_utils import (
|
27
23
|
call_function_on_contract,
|
@@ -391,8 +387,8 @@ class ContractOnGnosisChain(ContractBaseClass):
|
|
391
387
|
Contract base class with Gnosis Chain configuration.
|
392
388
|
"""
|
393
389
|
|
394
|
-
CHAIN_ID =
|
395
|
-
CHAIN_RPC_URL =
|
390
|
+
CHAIN_ID = RPCConfig().chain_id
|
391
|
+
CHAIN_RPC_URL = RPCConfig().gnosis_rpc_url
|
396
392
|
|
397
393
|
|
398
394
|
class ContractProxyOnGnosisChain(ContractProxyBaseClass, ContractOnGnosisChain):
|
@@ -1,10 +1,14 @@
|
|
1
|
+
import json
|
1
2
|
import typing as t
|
2
3
|
from datetime import timedelta
|
3
4
|
|
4
5
|
import tenacity
|
6
|
+
from google.cloud import secretmanager
|
5
7
|
from googleapiclient.discovery import build
|
8
|
+
from pydantic import SecretStr
|
6
9
|
|
7
|
-
from prediction_market_agent_tooling.config import APIKeys
|
10
|
+
from prediction_market_agent_tooling.config import APIKeys, CloudCredentials
|
11
|
+
from prediction_market_agent_tooling.gtypes import PrivateKey
|
8
12
|
from prediction_market_agent_tooling.loggers import logger
|
9
13
|
from prediction_market_agent_tooling.tools.caches.db_cache import db_cache
|
10
14
|
|
@@ -51,3 +55,26 @@ def search_google(
|
|
51
55
|
)
|
52
56
|
except KeyError as e:
|
53
57
|
raise ValueError(f"Can not parse results: {search}") from e
|
58
|
+
|
59
|
+
|
60
|
+
def get_private_key_from_gcp_secret(
|
61
|
+
secret_id: str,
|
62
|
+
project_id: str = "582587111398", # Gnosis AI default project_id
|
63
|
+
version_id: str = "latest",
|
64
|
+
) -> PrivateKey:
|
65
|
+
# If credentials filename specified, use that, else read using default credentials path.
|
66
|
+
google_application_credentials_filename = (
|
67
|
+
CloudCredentials().GOOGLE_APPLICATION_CREDENTIALS
|
68
|
+
)
|
69
|
+
if google_application_credentials_filename is not None:
|
70
|
+
# mypy interprets incorrectly that from_service_account_json requires further args.
|
71
|
+
client = secretmanager.SecretManagerServiceClient.from_service_account_json(filename=google_application_credentials_filename) # type: ignore [call-arg]
|
72
|
+
else:
|
73
|
+
client = secretmanager.SecretManagerServiceClient()
|
74
|
+
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
|
75
|
+
response = client.access_secret_version(request={"name": name})
|
76
|
+
secret_payload = response.payload.data.decode("UTF-8")
|
77
|
+
secret_json = json.loads(secret_payload)
|
78
|
+
if "private_key" not in secret_json:
|
79
|
+
raise ValueError(f"Private key not found in gcp secret {secret_id}")
|
80
|
+
return PrivateKey(SecretStr(secret_json["private_key"]))
|
@@ -17,7 +17,7 @@ def rewrite_question_into_image_generation_prompt(question: str) -> str:
|
|
17
17
|
"openai not installed, please install extras `langchain` to use this function."
|
18
18
|
)
|
19
19
|
llm = ChatOpenAI(
|
20
|
-
model="gpt-
|
20
|
+
model="gpt-4o-2024-08-06",
|
21
21
|
temperature=0.0,
|
22
22
|
api_key=APIKeys().openai_api_key_secretstr_v1,
|
23
23
|
)
|
@@ -60,7 +60,7 @@ Finally, write your final decision, write `decision: ` followed by either "yes i
|
|
60
60
|
@db_cache
|
61
61
|
def is_invalid(
|
62
62
|
question: str,
|
63
|
-
engine: str = "gpt-4o",
|
63
|
+
engine: str = "gpt-4o-2024-08-06",
|
64
64
|
temperature: float = LLM_SUPER_LOW_TEMPERATURE,
|
65
65
|
seed: int = LLM_SEED,
|
66
66
|
prompt_template: str = QUESTION_IS_INVALID_PROMPT,
|
@@ -7,7 +7,10 @@ from prediction_market_agent_tooling.tools.langfuse_ import (
|
|
7
7
|
get_langfuse_langchain_config,
|
8
8
|
observe,
|
9
9
|
)
|
10
|
-
from prediction_market_agent_tooling.tools.utils import
|
10
|
+
from prediction_market_agent_tooling.tools.utils import (
|
11
|
+
LLM_SEED,
|
12
|
+
LLM_SUPER_LOW_TEMPERATURE,
|
13
|
+
)
|
11
14
|
|
12
15
|
# I tried to make it return a JSON, but it didn't work well in combo with asking it to do chain of thought.
|
13
16
|
QUESTION_IS_PREDICTABLE_BINARY_PROMPT = """Main signs about a fully qualified question (sometimes referred to as a "market"):
|
@@ -81,7 +84,7 @@ Finally, write your final decision, write `decision: ` followed by either "yes i
|
|
81
84
|
@db_cache
|
82
85
|
def is_predictable_binary(
|
83
86
|
question: str,
|
84
|
-
engine: str = "gpt-
|
87
|
+
engine: str = "gpt-4o-2024-08-06",
|
85
88
|
prompt_template: str = QUESTION_IS_PREDICTABLE_BINARY_PROMPT,
|
86
89
|
max_tokens: int = 1024,
|
87
90
|
) -> bool:
|
@@ -98,6 +101,7 @@ def is_predictable_binary(
|
|
98
101
|
llm = ChatOpenAI(
|
99
102
|
model=engine,
|
100
103
|
temperature=LLM_SUPER_LOW_TEMPERATURE,
|
104
|
+
seed=LLM_SEED,
|
101
105
|
api_key=APIKeys().openai_api_key_secretstr_v1,
|
102
106
|
)
|
103
107
|
|
@@ -118,7 +122,7 @@ def is_predictable_binary(
|
|
118
122
|
def is_predictable_without_description(
|
119
123
|
question: str,
|
120
124
|
description: str,
|
121
|
-
engine: str = "gpt-
|
125
|
+
engine: str = "gpt-4o-2024-08-06",
|
122
126
|
prompt_template: str = QUESTION_IS_PREDICTABLE_WITHOUT_DESCRIPTION_PROMPT,
|
123
127
|
max_tokens: int = 1024,
|
124
128
|
) -> bool:
|
@@ -137,6 +141,7 @@ def is_predictable_without_description(
|
|
137
141
|
llm = ChatOpenAI(
|
138
142
|
model=engine,
|
139
143
|
temperature=LLM_SUPER_LOW_TEMPERATURE,
|
144
|
+
seed=LLM_SEED,
|
140
145
|
api_key=APIKeys().openai_api_key_secretstr_v1,
|
141
146
|
)
|
142
147
|
|
prediction_market_agent_tooling-0.57.0/prediction_market_agent_tooling/tools/transaction_cache.py
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
import diskcache as dc
|
2
|
+
import tenacity
|
3
|
+
from eth_typing import HexStr
|
4
|
+
from tenacity import wait_exponential
|
5
|
+
from web3 import Web3
|
6
|
+
|
7
|
+
from prediction_market_agent_tooling.loggers import logger
|
8
|
+
|
9
|
+
|
10
|
+
class TransactionBlockCache:
|
11
|
+
def __init__(self, web3: Web3):
|
12
|
+
self.block_number_cache = dc.Cache("block_cache_dir")
|
13
|
+
self.block_timestamp_cache = dc.Cache("timestamp_cache_dir")
|
14
|
+
self.web3 = web3
|
15
|
+
|
16
|
+
@tenacity.retry(
|
17
|
+
wait=wait_exponential(multiplier=1, min=1, max=4),
|
18
|
+
stop=tenacity.stop_after_attempt(7),
|
19
|
+
after=lambda x: logger.debug(f"fetch tx failed, {x.attempt_number=}."),
|
20
|
+
)
|
21
|
+
def fetch_block_number(self, transaction_hash: str) -> int:
|
22
|
+
tx = self.web3.eth.get_transaction(HexStr(transaction_hash))
|
23
|
+
return tx["blockNumber"]
|
24
|
+
|
25
|
+
@tenacity.retry(
|
26
|
+
wait=wait_exponential(multiplier=1, min=1, max=4),
|
27
|
+
stop=tenacity.stop_after_attempt(7),
|
28
|
+
after=lambda x: logger.debug(f"fetch tx failed, {x.attempt_number=}."),
|
29
|
+
)
|
30
|
+
def fetch_block_timestamp(self, block_number: int) -> int:
|
31
|
+
block = self.web3.eth.get_block(block_number)
|
32
|
+
return block["timestamp"]
|
33
|
+
|
34
|
+
def get_block_number(self, tx_hash: str) -> int:
|
35
|
+
if tx_hash in self.block_number_cache:
|
36
|
+
return int(self.block_number_cache[tx_hash])
|
37
|
+
|
38
|
+
block_number = self.fetch_block_number(tx_hash)
|
39
|
+
self.block_number_cache[tx_hash] = block_number
|
40
|
+
return block_number
|
41
|
+
|
42
|
+
def get_block_timestamp(self, block_number: int) -> int:
|
43
|
+
if block_number in self.block_timestamp_cache:
|
44
|
+
return int(self.block_timestamp_cache[block_number])
|
45
|
+
|
46
|
+
block_timestamp = self.fetch_block_timestamp(block_number)
|
47
|
+
self.block_timestamp_cache[block_number] = block_timestamp
|
48
|
+
return block_timestamp
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import json
|
2
1
|
import os
|
3
2
|
import subprocess
|
4
3
|
from datetime import datetime
|
@@ -6,17 +5,11 @@ from typing import Any, NoReturn, Optional, Type, TypeVar
|
|
6
5
|
|
7
6
|
import pytz
|
8
7
|
import requests
|
9
|
-
from google.cloud import secretmanager
|
10
8
|
from pydantic import BaseModel, ValidationError
|
11
9
|
from scipy.optimize import newton
|
12
10
|
from scipy.stats import entropy
|
13
11
|
|
14
|
-
from prediction_market_agent_tooling.gtypes import
|
15
|
-
DatetimeUTC,
|
16
|
-
PrivateKey,
|
17
|
-
Probability,
|
18
|
-
SecretStr,
|
19
|
-
)
|
12
|
+
from prediction_market_agent_tooling.gtypes import DatetimeUTC, Probability, SecretStr
|
20
13
|
from prediction_market_agent_tooling.loggers import logger
|
21
14
|
from prediction_market_agent_tooling.markets.market_fees import MarketFees
|
22
15
|
|
@@ -214,18 +207,3 @@ def calculate_sell_amount_in_collateral(
|
|
214
207
|
|
215
208
|
amount_to_sell = newton(f, 0)
|
216
209
|
return float(amount_to_sell) * 0.999999 # Avoid rounding errors
|
217
|
-
|
218
|
-
|
219
|
-
def get_private_key_from_gcp_secret(
|
220
|
-
secret_id: str,
|
221
|
-
project_id: str = "582587111398", # Gnosis AI default project_id
|
222
|
-
version_id: str = "latest",
|
223
|
-
) -> PrivateKey:
|
224
|
-
client = secretmanager.SecretManagerServiceClient()
|
225
|
-
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
|
226
|
-
response = client.access_secret_version(request={"name": name})
|
227
|
-
secret_payload = response.payload.data.decode("UTF-8")
|
228
|
-
secret_json = json.loads(secret_payload)
|
229
|
-
if "private_key" not in secret_json:
|
230
|
-
raise ValueError(f"Private key not found in gcp secret {secret_id}")
|
231
|
-
return PrivateKey(SecretStr(secret_json["private_key"]))
|
@@ -263,7 +263,11 @@ def send_function_on_contract_tx_using_safe(
|
|
263
263
|
)
|
264
264
|
safe_tx.sign(from_private_key.get_secret_value())
|
265
265
|
safe_tx.call() # simulate call
|
266
|
-
|
266
|
+
eoa_nonce = web3.eth.get_transaction_count(eoa_public_key)
|
267
|
+
tx_hash, tx = safe_tx.execute(
|
268
|
+
from_private_key.get_secret_value(),
|
269
|
+
tx_nonce=eoa_nonce,
|
270
|
+
)
|
267
271
|
receipt_tx = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=timeout)
|
268
272
|
check_tx_receipt(receipt_tx)
|
269
273
|
return receipt_tx
|
{prediction_market_agent_tooling-0.56.3 → prediction_market_agent_tooling-0.57.0}/pyproject.toml
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "prediction-market-agent-tooling"
|
3
|
-
version = "0.
|
3
|
+
version = "0.57.0"
|
4
4
|
description = "Tools to benchmark, deploy and monitor prediction market agents."
|
5
5
|
authors = ["Gnosis"]
|
6
6
|
readme = "README.md"
|
@@ -65,6 +65,7 @@ mypy = "^1.11.1"
|
|
65
65
|
black = "^23.12.1"
|
66
66
|
ape-foundry = "^0.8.2"
|
67
67
|
eth-ape = "^0.8.10,<0.8.17" # 0.8.17 doesn't work with the current configuration and needs a fix, see https://github.com/gnosis/prediction-market-agent-tooling/issues/518.
|
68
|
+
diskcache = "^5.6.3"
|
68
69
|
|
69
70
|
[build-system]
|
70
71
|
requires = ["poetry-core"]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|