prediction-market-agent-tooling 0.49.0__tar.gz → 0.49.2__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 (95) hide show
  1. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/PKG-INFO +3 -1
  2. prediction_market_agent_tooling-0.49.2/prediction_market_agent_tooling/abis/debuggingcontract.abi.json +29 -0
  3. prediction_market_agent_tooling-0.49.2/prediction_market_agent_tooling/abis/omen_agentresultmapping.abi.json +171 -0
  4. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/benchmark/benchmark.py +0 -93
  5. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/config.py +16 -0
  6. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/deploy/agent.py +62 -7
  7. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/deploy/betting_strategy.py +83 -3
  8. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/agent_market.py +5 -3
  9. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/data_models.py +1 -1
  10. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/metaculus/metaculus.py +1 -1
  11. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/omen/data_models.py +240 -5
  12. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/omen/omen.py +44 -25
  13. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/omen/omen_contracts.py +180 -33
  14. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/omen/omen_resolving.py +1 -1
  15. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py +45 -0
  16. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/polymarket/api.py +1 -1
  17. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/monitor/monitor.py +3 -3
  18. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/monitor/monitor_app.py +2 -2
  19. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/contract.py +50 -1
  20. prediction_market_agent_tooling-0.49.2/prediction_market_agent_tooling/tools/httpx_cached_client.py +11 -0
  21. prediction_market_agent_tooling-0.49.2/prediction_market_agent_tooling/tools/ipfs/ipfs_handler.py +33 -0
  22. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/is_predictable.py +1 -1
  23. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/langfuse_client_utils.py +23 -8
  24. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py +1 -1
  25. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/utils.py +28 -4
  26. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/web3_utils.py +7 -0
  27. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/pyproject.toml +3 -1
  28. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/LICENSE +0 -0
  29. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/README.md +0 -0
  30. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/depositablewrapper_erc20.abi.json +0 -0
  31. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/erc20.abi.json +0 -0
  32. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/erc4626.abi.json +0 -0
  33. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/omen_dxdao.abi.json +0 -0
  34. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/omen_fpmm.abi.json +0 -0
  35. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/omen_fpmm_conditionaltokens.abi.json +0 -0
  36. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/omen_fpmm_factory.abi.json +0 -0
  37. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/omen_kleros.abi.json +0 -0
  38. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/omen_oracle.abi.json +0 -0
  39. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/omen_realitio.abi.json +0 -0
  40. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/omen_thumbnailmapping.abi.json +0 -0
  41. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/abis/proxy.abi.json +0 -0
  42. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/benchmark/__init__.py +0 -0
  43. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/benchmark/agents.py +0 -0
  44. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/benchmark/utils.py +0 -0
  45. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/deploy/agent_example.py +0 -0
  46. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/deploy/constants.py +0 -0
  47. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/deploy/gcp/deploy.py +0 -0
  48. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/deploy/gcp/kubernetes_models.py +0 -0
  49. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/deploy/gcp/utils.py +0 -0
  50. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/gtypes.py +0 -0
  51. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/jobs/__init__.py +0 -0
  52. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/jobs/jobs.py +0 -0
  53. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/jobs/jobs_models.py +0 -0
  54. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/jobs/omen/omen_jobs.py +0 -0
  55. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/loggers.py +0 -0
  56. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/categorize.py +0 -0
  57. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/manifold/__init__.py +0 -0
  58. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/manifold/api.py +0 -0
  59. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/manifold/data_models.py +0 -0
  60. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/manifold/manifold.py +0 -0
  61. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/manifold/utils.py +0 -0
  62. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/markets.py +0 -0
  63. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/metaculus/api.py +0 -0
  64. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/metaculus/data_models.py +0 -0
  65. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/omen/__init__.py +0 -0
  66. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/polymarket/data_models.py +0 -0
  67. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/polymarket/data_models_web.py +0 -0
  68. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/polymarket/polymarket.py +0 -0
  69. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/markets/polymarket/utils.py +0 -0
  70. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/monitor/markets/manifold.py +0 -0
  71. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/monitor/markets/metaculus.py +0 -0
  72. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/monitor/markets/omen.py +0 -0
  73. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/monitor/markets/polymarket.py +0 -0
  74. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/monitor/monitor_settings.py +0 -0
  75. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/py.typed +0 -0
  76. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/balances.py +0 -0
  77. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/betting_strategies/kelly_criterion.py +0 -0
  78. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/betting_strategies/market_moving.py +0 -0
  79. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/betting_strategies/minimum_bet_to_win.py +0 -0
  80. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/betting_strategies/stretch_bet_between.py +0 -0
  81. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/betting_strategies/utils.py +0 -0
  82. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/cache.py +0 -0
  83. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/costs.py +0 -0
  84. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/gnosis_rpc.py +0 -0
  85. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/google.py +0 -0
  86. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/hexbytes_custom.py +0 -0
  87. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/image_gen/image_gen.py +0 -0
  88. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/image_gen/market_thumbnail_gen.py +0 -0
  89. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/langfuse_.py +0 -0
  90. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/omen/reality_accuracy.py +0 -0
  91. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/parallelism.py +0 -0
  92. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/safe.py +0 -0
  93. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/singleton.py +0 -0
  94. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/streamlit_user_login.py +0 -0
  95. {prediction_market_agent_tooling-0.49.0 → prediction_market_agent_tooling-0.49.2}/prediction_market_agent_tooling/tools/tavily_storage/tavily_storage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prediction-market-agent-tooling
3
- Version: 0.49.0
3
+ Version: 0.49.2
4
4
  Summary: Tools to benchmark, deploy and monitor prediction market agents.
5
5
  Author: Gnosis
6
6
  Requires-Python: >=3.10,<3.12
@@ -20,6 +20,7 @@ Requires-Dist: google-api-python-client (==2.95.0) ; extra == "google"
20
20
  Requires-Dist: google-cloud-functions (>=1.16.0,<2.0.0)
21
21
  Requires-Dist: google-cloud-resource-manager (>=1.12.0,<2.0.0)
22
22
  Requires-Dist: google-cloud-secret-manager (>=2.18.2,<3.0.0)
23
+ Requires-Dist: hishel (>=0.0.31,<0.0.32)
23
24
  Requires-Dist: isort (>=5.13.2,<6.0.0)
24
25
  Requires-Dist: langchain (>=0.2.6,<0.3.0) ; extra == "langchain"
25
26
  Requires-Dist: langchain-community (>=0.0.19)
@@ -29,6 +30,7 @@ Requires-Dist: loguru (>=0.7.2,<0.8.0)
29
30
  Requires-Dist: loky (>=3.4.1,<4.0.0)
30
31
  Requires-Dist: numpy (>=1.26.4,<2.0.0)
31
32
  Requires-Dist: openai (>=1.0.0,<2.0.0) ; extra == "openai"
33
+ Requires-Dist: pinatapy-vourhey (>=0.2.0,<0.3.0)
32
34
  Requires-Dist: prompt-toolkit (>=3.0.43,<4.0.0)
33
35
  Requires-Dist: psycopg2-binary (>=2.9.9,<3.0.0)
34
36
  Requires-Dist: pydantic (>=2.6.1,<3.0.0)
@@ -0,0 +1,29 @@
1
+ [
2
+ {
3
+ "constant": false,
4
+ "inputs": [],
5
+ "name": "inc",
6
+ "outputs": [],
7
+ "payable": false,
8
+ "stateMutability": "nonpayable",
9
+ "type": "function"
10
+ },
11
+ {
12
+ "constant": true,
13
+ "inputs": [],
14
+ "name": "counter",
15
+ "outputs": [{ "name": "", "type": "uint256" }],
16
+ "payable": false,
17
+ "stateMutability": "view",
18
+ "type": "function"
19
+ },
20
+ {
21
+ "constant": true,
22
+ "inputs": [],
23
+ "name": "getNow",
24
+ "outputs": [{ "name": "", "type": "uint32" }],
25
+ "payable": false,
26
+ "stateMutability": "view",
27
+ "type": "function"
28
+ }
29
+ ]
@@ -0,0 +1,171 @@
1
+ [
2
+ {
3
+ "type": "constructor",
4
+ "inputs": [],
5
+ "stateMutability": "nonpayable"
6
+ },
7
+ {
8
+ "type": "function",
9
+ "name": "addPrediction",
10
+ "inputs": [
11
+ {
12
+ "name": "marketAddress",
13
+ "type": "address",
14
+ "internalType": "address"
15
+ },
16
+ {
17
+ "name": "prediction",
18
+ "type": "tuple",
19
+ "internalType": "struct Prediction",
20
+ "components": [
21
+ {
22
+ "name": "publisherAddress",
23
+ "type": "address",
24
+ "internalType": "address"
25
+ },
26
+ {
27
+ "name": "ipfsHash",
28
+ "type": "bytes32",
29
+ "internalType": "bytes32"
30
+ },
31
+ {
32
+ "name": "txHashes",
33
+ "type": "bytes32[]",
34
+ "internalType": "bytes32[]"
35
+ },
36
+ {
37
+ "name": "estimatedProbabilityBps",
38
+ "type": "uint16",
39
+ "internalType": "uint16"
40
+ }
41
+ ]
42
+ }
43
+ ],
44
+ "outputs": [],
45
+ "stateMutability": "nonpayable"
46
+ },
47
+ {
48
+ "type": "function",
49
+ "name": "getPredictionByIndex",
50
+ "inputs": [
51
+ {
52
+ "name": "marketAddress",
53
+ "type": "address",
54
+ "internalType": "address"
55
+ },
56
+ {
57
+ "name": "index",
58
+ "type": "uint256",
59
+ "internalType": "uint256"
60
+ }
61
+ ],
62
+ "outputs": [
63
+ {
64
+ "name": "",
65
+ "type": "tuple",
66
+ "internalType": "struct Prediction",
67
+ "components": [
68
+ {
69
+ "name": "publisherAddress",
70
+ "type": "address",
71
+ "internalType": "address"
72
+ },
73
+ {
74
+ "name": "ipfsHash",
75
+ "type": "bytes32",
76
+ "internalType": "bytes32"
77
+ },
78
+ {
79
+ "name": "txHashes",
80
+ "type": "bytes32[]",
81
+ "internalType": "bytes32[]"
82
+ },
83
+ {
84
+ "name": "estimatedProbabilityBps",
85
+ "type": "uint16",
86
+ "internalType": "uint16"
87
+ }
88
+ ]
89
+ }
90
+ ],
91
+ "stateMutability": "view"
92
+ },
93
+ {
94
+ "type": "function",
95
+ "name": "getPredictions",
96
+ "inputs": [
97
+ {
98
+ "name": "marketAddress",
99
+ "type": "address",
100
+ "internalType": "address"
101
+ }
102
+ ],
103
+ "outputs": [
104
+ {
105
+ "name": "",
106
+ "type": "tuple[]",
107
+ "internalType": "struct Prediction[]",
108
+ "components": [
109
+ {
110
+ "name": "publisherAddress",
111
+ "type": "address",
112
+ "internalType": "address"
113
+ },
114
+ {
115
+ "name": "ipfsHash",
116
+ "type": "bytes32",
117
+ "internalType": "bytes32"
118
+ },
119
+ {
120
+ "name": "txHashes",
121
+ "type": "bytes32[]",
122
+ "internalType": "bytes32[]"
123
+ },
124
+ {
125
+ "name": "estimatedProbabilityBps",
126
+ "type": "uint16",
127
+ "internalType": "uint16"
128
+ }
129
+ ]
130
+ }
131
+ ],
132
+ "stateMutability": "view"
133
+ },
134
+ {
135
+ "type": "event",
136
+ "name": "PredictionAdded",
137
+ "inputs": [
138
+ {
139
+ "name": "marketAddress",
140
+ "type": "address",
141
+ "indexed": true,
142
+ "internalType": "address"
143
+ },
144
+ {
145
+ "name": "estimatedProbabilityBps",
146
+ "type": "uint16",
147
+ "indexed": false,
148
+ "internalType": "uint16"
149
+ },
150
+ {
151
+ "name": "publisherAddress",
152
+ "type": "address",
153
+ "indexed": true,
154
+ "internalType": "address"
155
+ },
156
+ {
157
+ "name": "txHashes",
158
+ "type": "bytes32[]",
159
+ "indexed": false,
160
+ "internalType": "bytes32[]"
161
+ },
162
+ {
163
+ "name": "ipfsHash",
164
+ "type": "bytes32",
165
+ "indexed": false,
166
+ "internalType": "bytes32"
167
+ }
168
+ ],
169
+ "anonymous": false
170
+ }
171
+ ]
@@ -1,7 +1,6 @@
1
1
  import concurrent.futures
2
2
  import os
3
3
  import typing as t
4
- from collections import defaultdict
5
4
 
6
5
  import numpy as np
7
6
  import pandas as pd
@@ -436,92 +435,6 @@ class Benchmarker:
436
435
  ],
437
436
  }
438
437
 
439
- def calculate_expected_returns(
440
- self, prediction: Prediction, market: AgentMarket
441
- ) -> float | None:
442
- """
443
- The expected value if betting on a binary market in its initialized state of 50:50 'yes' and 'no' shares, with the assumption that the correct `p_yes` is that of the market.
444
- """
445
- if not prediction.is_answered:
446
- return None
447
-
448
- # TODO: Add support for different bet sizes -- if we bet a low amount (such as <10 units), the real shares will be very close to that we calculate below (bet_units / share_price),
449
- # but if one bets a lot, it will change the share price along the way, and so he/she receives less than `bet_units / share_price`, but it's more complicated to calculate.
450
- bet_units = 10 # Assuming the agent always bet 10 units per market.
451
-
452
- assert prediction.outcome_prediction is not None
453
- # Assume that market starts at 50/50 and so the price is 0.5 at the time we are buying it,
454
- # we can't use {yes,no}_outcome_price atm, because it would just cancel out to EV = 0.0,
455
- # as it's the same as the probability.
456
- yes_shares = (
457
- bet_units / 0.5 # market.yes_outcome_price
458
- if prediction.outcome_prediction.probable_resolution == Resolution.YES
459
- and market.yes_outcome_price > 0
460
- else 0
461
- )
462
- no_shares = (
463
- bet_units / 0.5 # market.no_outcome_price
464
- if prediction.outcome_prediction.probable_resolution == Resolution.NO
465
- and market.no_outcome_price > 0
466
- else 0
467
- )
468
-
469
- # If we don't bet, we don't have any expected returns.
470
- if yes_shares == 0 and no_shares == 0:
471
- return None
472
-
473
- expected_value = (
474
- yes_shares * market.current_p_yes
475
- + no_shares * (1 - market.current_p_yes)
476
- - bet_units
477
- )
478
- expected_returns_perc = 100 * expected_value / bet_units
479
-
480
- return expected_returns_perc
481
-
482
- def compute_expected_returns_summary(
483
- self,
484
- ) -> t.Tuple[dict[str, list[str | float]], dict[str, list[str | float | None]]]:
485
- overall_summary: dict[str, list[str | float]] = defaultdict(list)
486
-
487
- for agent in self.registered_agents:
488
- expected_returns = []
489
-
490
- for market in self.markets:
491
- if (
492
- prediction := self.get_prediction(agent.agent_name, market.question)
493
- ).is_answered and (
494
- expected_return := self.calculate_expected_returns(
495
- prediction, market
496
- )
497
- ) is not None:
498
- expected_returns.append(expected_return)
499
-
500
- overall_summary["Agent"].append(agent.agent_name)
501
- overall_summary["Mean expected returns"].append(
502
- float(np.mean(expected_returns))
503
- )
504
- overall_summary["Median expected returns"].append(
505
- float(np.median(expected_returns))
506
- )
507
- overall_summary["Total expected returns"].append(
508
- float(np.sum(expected_returns))
509
- )
510
-
511
- per_market: dict[str, list[str | float | None]] = defaultdict(list)
512
-
513
- for market in self.markets:
514
- per_market["Market Question"].append(market.question)
515
-
516
- for agent in self.registered_agents:
517
- per_market[agent.agent_name].append(
518
- self.calculate_expected_returns(
519
- self.get_prediction(agent.agent_name, market.question), market
520
- )
521
- )
522
-
523
- return dict(overall_summary), dict(per_market)
524
-
525
438
  def generate_markdown_report(self) -> str:
526
439
  md = "# Comparison Report\n\n"
527
440
  md += "## Market Results\n\n"
@@ -533,10 +446,4 @@ class Benchmarker:
533
446
  md += "\n\n"
534
447
  md += "### Markets\n\n"
535
448
  md += pd.DataFrame(self.get_markets_summary()).to_markdown(index=False)
536
- md += "\n\n"
537
- md += "### Expected value\n\n"
538
- overall_summary, per_market = self.compute_expected_returns_summary()
539
- md += pd.DataFrame(overall_summary).to_markdown(index=False)
540
- md += "\n\n"
541
- md += pd.DataFrame(per_market).to_markdown(index=False)
542
449
  return md
@@ -35,6 +35,7 @@ class APIKeys(BaseSettings):
35
35
  SAFE_ADDRESS: t.Optional[ChecksumAddress] = None
36
36
  OPENAI_API_KEY: t.Optional[SecretStr] = None
37
37
  GRAPH_API_KEY: t.Optional[SecretStr] = None
38
+ TENDERLY_FORK_RPC: t.Optional[str] = None
38
39
 
39
40
  GOOGLE_SEARCH_API_KEY: t.Optional[SecretStr] = None
40
41
  GOOGLE_SEARCH_ENGINE_ID: t.Optional[SecretStr] = None
@@ -44,6 +45,9 @@ class APIKeys(BaseSettings):
44
45
  LANGFUSE_HOST: t.Optional[str] = None
45
46
  LANGFUSE_DEPLOYMENT_VERSION: t.Optional[str] = None
46
47
 
48
+ PINATA_API_KEY: t.Optional[SecretStr] = None
49
+ PINATA_API_SECRET: t.Optional[SecretStr] = None
50
+
47
51
  TAVILY_API_KEY: t.Optional[SecretStr] = None
48
52
 
49
53
  SQLALCHEMY_DB_URL: t.Optional[SecretStr] = None
@@ -147,6 +151,18 @@ class APIKeys(BaseSettings):
147
151
  and self.LANGFUSE_HOST is not None
148
152
  )
149
153
 
154
+ @property
155
+ def pinata_api_key(self) -> SecretStr:
156
+ return check_not_none(
157
+ self.PINATA_API_KEY, "PINATA_API_KEY missing in the environment."
158
+ )
159
+
160
+ @property
161
+ def pinata_api_secret(self) -> SecretStr:
162
+ return check_not_none(
163
+ self.PINATA_API_SECRET, "PINATA_API_SECRET missing in the environment."
164
+ )
165
+
150
166
  @property
151
167
  def tavily_api_key(self) -> SecretStr:
152
168
  return check_not_none(
@@ -10,6 +10,7 @@ from functools import cached_property
10
10
 
11
11
  from pydantic import BaseModel, BeforeValidator, computed_field
12
12
  from typing_extensions import Annotated
13
+ from web3 import Web3
13
14
 
14
15
  from prediction_market_agent_tooling.config import APIKeys
15
16
  from prediction_market_agent_tooling.deploy.betting_strategy import (
@@ -30,7 +31,7 @@ from prediction_market_agent_tooling.deploy.gcp.utils import (
30
31
  gcp_function_is_active,
31
32
  gcp_resolve_api_keys_secrets,
32
33
  )
33
- from prediction_market_agent_tooling.gtypes import xDai, xdai_type
34
+ from prediction_market_agent_tooling.gtypes import HexStr, xDai, xdai_type
34
35
  from prediction_market_agent_tooling.loggers import logger
35
36
  from prediction_market_agent_tooling.markets.agent_market import (
36
37
  AgentMarket,
@@ -47,17 +48,27 @@ from prediction_market_agent_tooling.markets.markets import (
47
48
  MarketType,
48
49
  have_bet_on_market_since,
49
50
  )
51
+ from prediction_market_agent_tooling.markets.omen.data_models import (
52
+ ContractPrediction,
53
+ IPFSAgentResult,
54
+ )
50
55
  from prediction_market_agent_tooling.markets.omen.omen import (
51
56
  is_minimum_required_balance,
52
57
  redeem_from_all_user_positions,
53
58
  withdraw_wxdai_to_xdai_to_keep_balance,
54
59
  )
60
+ from prediction_market_agent_tooling.markets.omen.omen_contracts import (
61
+ OmenAgentResultMappingContract,
62
+ )
55
63
  from prediction_market_agent_tooling.monitor.monitor_app import (
56
64
  MARKET_TYPE_TO_DEPLOYED_AGENT,
57
65
  )
66
+ from prediction_market_agent_tooling.tools.hexbytes_custom import HexBytes
67
+ from prediction_market_agent_tooling.tools.ipfs.ipfs_handler import IPFSHandler
58
68
  from prediction_market_agent_tooling.tools.is_predictable import is_predictable_binary
59
69
  from prediction_market_agent_tooling.tools.langfuse_ import langfuse_context, observe
60
70
  from prediction_market_agent_tooling.tools.utils import DatetimeWithTimezone, utcnow
71
+ from prediction_market_agent_tooling.tools.web3_utils import ipfscidv0_to_byte32
61
72
 
62
73
  MAX_AVAILABLE_MARKETS = 20
63
74
  TRADER_TAG = "trader"
@@ -291,11 +302,12 @@ class DeployableTraderAgent(DeployableAgent):
291
302
  ) -> None:
292
303
  super().__init__(enable_langfuse=enable_langfuse)
293
304
  self.place_bet = place_bet
305
+ self.ipfs_handler = IPFSHandler(APIKeys())
294
306
 
295
307
  def get_betting_strategy(self, market: AgentMarket) -> BettingStrategy:
296
308
  user_id = market.get_user_id(api_keys=APIKeys())
297
309
 
298
- total_amount = market.get_user_balance(user_id=user_id) * 0.1
310
+ total_amount = market.get_tiny_bet_amount().amount
299
311
  if existing_position := market.get_position(user_id=user_id):
300
312
  total_amount += existing_position.total_amount.amount
301
313
 
@@ -461,7 +473,7 @@ class DeployableTraderAgent(DeployableAgent):
461
473
  placed_trades = []
462
474
  if self.place_bet:
463
475
  for trade in trades:
464
- logger.info(f"Executing trade {trade}")
476
+ logger.info(f"Executing trade {trade} on market {market.id}")
465
477
 
466
478
  match trade.trade_type:
467
479
  case TradeType.BUY:
@@ -476,18 +488,61 @@ class DeployableTraderAgent(DeployableAgent):
476
488
  raise ValueError(f"Unexpected trade type {trade.trade_type}.")
477
489
  placed_trades.append(PlacedTrade.from_trade(trade, id))
478
490
 
479
- self.after_process_market(market_type, market)
480
-
481
491
  processed_market = ProcessedMarket(answer=answer, trades=placed_trades)
482
492
  self.update_langfuse_trace_by_processed_market(market_type, processed_market)
483
493
 
494
+ self.after_process_market(
495
+ market_type, market, processed_market=processed_market
496
+ )
497
+
484
498
  logger.info(f"Processed market {market.question=} from {market.url=}.")
485
499
  return processed_market
486
500
 
487
501
  def after_process_market(
488
- self, market_type: MarketType, market: AgentMarket
502
+ self,
503
+ market_type: MarketType,
504
+ market: AgentMarket,
505
+ processed_market: ProcessedMarket,
489
506
  ) -> None:
490
- pass
507
+ if market_type != MarketType.OMEN:
508
+ logger.info(
509
+ f"Skipping after_process_market since market_type {market_type} != OMEN"
510
+ )
511
+ return
512
+ keys = APIKeys()
513
+ self.store_prediction(
514
+ market_id=market.id, processed_market=processed_market, keys=keys
515
+ )
516
+
517
+ def store_prediction(
518
+ self, market_id: str, processed_market: ProcessedMarket, keys: APIKeys
519
+ ) -> None:
520
+ reasoning = (
521
+ processed_market.answer.reasoning
522
+ if processed_market.answer.reasoning
523
+ else ""
524
+ )
525
+ ipfs_hash = self.ipfs_handler.store_agent_result(
526
+ IPFSAgentResult(reasoning=reasoning)
527
+ )
528
+
529
+ tx_hashes = [
530
+ HexBytes(HexStr(i.id)) for i in processed_market.trades if i.id is not None
531
+ ]
532
+ prediction = ContractPrediction(
533
+ publisher=keys.public_key,
534
+ ipfs_hash=ipfscidv0_to_byte32(ipfs_hash),
535
+ tx_hashes=tx_hashes,
536
+ estimated_probability_bps=int(processed_market.answer.p_yes * 10000),
537
+ )
538
+ tx_receipt = OmenAgentResultMappingContract().add_prediction(
539
+ api_keys=keys,
540
+ market_address=Web3.to_checksum_address(market_id),
541
+ prediction=prediction,
542
+ )
543
+ logger.info(
544
+ f"Added prediction to market {market_id}. - receipt {tx_receipt['transactionHash'].hex()}."
545
+ )
491
546
 
492
547
  def before_process_markets(self, market_type: MarketType) -> None:
493
548
  """
@@ -1,5 +1,9 @@
1
1
  from abc import ABC, abstractmethod
2
2
 
3
+ from scipy.optimize import minimize_scalar
4
+
5
+ from prediction_market_agent_tooling.gtypes import xDai
6
+ from prediction_market_agent_tooling.loggers import logger
3
7
  from prediction_market_agent_tooling.markets.agent_market import AgentMarket
4
8
  from prediction_market_agent_tooling.markets.data_models import (
5
9
  Currency,
@@ -10,10 +14,14 @@ from prediction_market_agent_tooling.markets.data_models import (
10
14
  TradeType,
11
15
  )
12
16
  from prediction_market_agent_tooling.markets.omen.data_models import get_boolean_outcome
17
+ from prediction_market_agent_tooling.markets.omen.omen import (
18
+ get_buy_outcome_token_amount,
19
+ )
13
20
  from prediction_market_agent_tooling.tools.betting_strategies.kelly_criterion import (
14
21
  get_kelly_bet_full,
15
22
  get_kelly_bet_simplified,
16
23
  )
24
+ from prediction_market_agent_tooling.tools.betting_strategies.utils import SimpleBet
17
25
  from prediction_market_agent_tooling.tools.utils import check_not_none
18
26
 
19
27
 
@@ -134,8 +142,9 @@ class MaxExpectedValueBettingStrategy(MaxAccuracyBettingStrategy):
134
142
 
135
143
 
136
144
  class KellyBettingStrategy(BettingStrategy):
137
- def __init__(self, max_bet_amount: float):
145
+ def __init__(self, max_bet_amount: float, max_price_impact: float | None = None):
138
146
  self.max_bet_amount = max_bet_amount
147
+ self.max_price_impact = max_price_impact
139
148
 
140
149
  def calculate_trades(
141
150
  self,
@@ -165,9 +174,19 @@ class KellyBettingStrategy(BettingStrategy):
165
174
  )
166
175
  )
167
176
 
177
+ kelly_bet_size = kelly_bet.size
178
+ if self.max_price_impact:
179
+ # Adjust amount
180
+ max_price_impact_bet_amount = self.calculate_bet_amount_for_price_impact(
181
+ market, kelly_bet, 0
182
+ )
183
+
184
+ # We just don't want Kelly size to extrapolate price_impact - hence we take the min.
185
+ kelly_bet_size = min(kelly_bet.size, max_price_impact_bet_amount)
186
+
168
187
  amounts = {
169
188
  market.get_outcome_str_from_bool(kelly_bet.direction): TokenAmount(
170
- amount=kelly_bet.size, currency=market.currency
189
+ amount=kelly_bet_size, currency=market.currency
171
190
  ),
172
191
  }
173
192
  target_position = Position(market_id=market.id, amounts=amounts)
@@ -176,8 +195,69 @@ class KellyBettingStrategy(BettingStrategy):
176
195
  )
177
196
  return trades
178
197
 
198
+ def calculate_price_impact_for_bet_amount(
199
+ self, buy_direction: bool, bet_amount: float, yes: float, no: float, fee: float
200
+ ) -> float:
201
+ total_outcome_tokens = yes + no
202
+ expected_price = (
203
+ no / total_outcome_tokens if buy_direction else yes / total_outcome_tokens
204
+ )
205
+
206
+ tokens_to_buy = get_buy_outcome_token_amount(
207
+ bet_amount, buy_direction, yes, no, fee
208
+ )
209
+
210
+ actual_price = bet_amount / tokens_to_buy
211
+ # price_impact should always be > 0
212
+ price_impact = (actual_price - expected_price) / expected_price
213
+ return price_impact
214
+
215
+ def calculate_bet_amount_for_price_impact(
216
+ self,
217
+ market: AgentMarket,
218
+ kelly_bet: SimpleBet,
219
+ fee: float,
220
+ ) -> float:
221
+ def calculate_price_impact_deviation_from_target_price_impact(
222
+ bet_amount: xDai,
223
+ ) -> float:
224
+ price_impact = self.calculate_price_impact_for_bet_amount(
225
+ kelly_bet.direction,
226
+ bet_amount,
227
+ yes_outcome_pool_size,
228
+ no_outcome_pool_size,
229
+ fee,
230
+ )
231
+ # We return abs for the algorithm to converge to 0 instead of the min (and possibly negative) value.
232
+
233
+ max_price_impact = check_not_none(self.max_price_impact)
234
+ return abs(price_impact - max_price_impact)
235
+
236
+ if not market.outcome_token_pool:
237
+ logger.warning(
238
+ "Market outcome_token_pool is None, cannot calculate bet amount"
239
+ )
240
+ return kelly_bet.size
241
+
242
+ yes_outcome_pool_size = market.outcome_token_pool[
243
+ market.get_outcome_str_from_bool(True)
244
+ ]
245
+ no_outcome_pool_size = market.outcome_token_pool[
246
+ market.get_outcome_str_from_bool(False)
247
+ ]
248
+
249
+ # The bounds below have been found to work heuristically.
250
+ optimized_bet_amount = minimize_scalar(
251
+ calculate_price_impact_deviation_from_target_price_impact,
252
+ bounds=(0, 1000 * (yes_outcome_pool_size + no_outcome_pool_size)),
253
+ method="bounded",
254
+ tol=1e-11,
255
+ options={"maxiter": 10000},
256
+ )
257
+ return float(optimized_bet_amount.x)
258
+
179
259
  def __repr__(self) -> str:
180
- return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount})"
260
+ return f"{self.__class__.__name__}(max_bet_amount={self.max_bet_amount}, max_price_impact={self.max_price_impact})"
181
261
 
182
262
 
183
263
  class MaxAccuracyWithKellyScaledBetsStrategy(BettingStrategy):
@@ -18,8 +18,8 @@ from prediction_market_agent_tooling.markets.data_models import (
18
18
  TokenAmount,
19
19
  )
20
20
  from prediction_market_agent_tooling.tools.utils import (
21
- add_utc_timezone_validator,
22
21
  check_not_none,
22
+ convert_to_utc_datetime,
23
23
  should_not_happen,
24
24
  utcnow,
25
25
  )
@@ -28,6 +28,8 @@ from prediction_market_agent_tooling.tools.utils import (
28
28
  class SortBy(str, Enum):
29
29
  CLOSING_SOONEST = "closing-soonest"
30
30
  NEWEST = "newest"
31
+ HIGHEST_LIQUIDITY = "highest_liquidity"
32
+ LOWEST_LIQUIDITY = "lowest_liquidity"
31
33
  NONE = "none"
32
34
 
33
35
 
@@ -61,10 +63,10 @@ class AgentMarket(BaseModel):
61
63
  volume: float | None # Should be in currency of `currency` above.
62
64
 
63
65
  _add_timezone_validator_created_time = field_validator("created_time")(
64
- add_utc_timezone_validator
66
+ convert_to_utc_datetime
65
67
  )
66
68
  _add_timezone_validator_close_time = field_validator("close_time")(
67
- add_utc_timezone_validator
69
+ convert_to_utc_datetime
68
70
  )
69
71
 
70
72
  @field_validator("outcome_token_pool")
@@ -130,7 +130,7 @@ class Trade(BaseModel):
130
130
 
131
131
 
132
132
  class PlacedTrade(Trade):
133
- id: str
133
+ id: str | None = None
134
134
 
135
135
  @staticmethod
136
136
  def from_trade(trade: Trade, id: str) -> "PlacedTrade":
@@ -100,7 +100,7 @@ class MetaculusAgentMarket(AgentMarket):
100
100
 
101
101
  if len(all_questions) >= limit:
102
102
  break
103
- return [MetaculusAgentMarket.from_data_model(q) for q in all_questions]
103
+ return [MetaculusAgentMarket.from_data_model(q) for q in all_questions[:limit]]
104
104
 
105
105
  def submit_prediction(self, p_yes: Probability, reasoning: str) -> None:
106
106
  make_prediction(self.id, p_yes)