clodds 1.2.9 → 1.3.0

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 (226) hide show
  1. package/dist/skills/bundled/acp/SKILL.md +188 -0
  2. package/dist/skills/bundled/acp/index.d.ts +0 -3
  3. package/dist/skills/bundled/acp/index.js +1 -1
  4. package/dist/skills/bundled/acp/index.js.map +1 -1
  5. package/dist/skills/bundled/agentbets/SKILL.md +19 -0
  6. package/dist/skills/bundled/ai-strategy/SKILL.md +111 -0
  7. package/dist/skills/bundled/ai-strategy/index.js +1 -1
  8. package/dist/skills/bundled/ai-strategy/index.js.map +1 -1
  9. package/dist/skills/bundled/alerts/SKILL.md +87 -0
  10. package/dist/skills/bundled/analytics/SKILL.md +252 -0
  11. package/dist/skills/bundled/analytics/index.js +2 -2
  12. package/dist/skills/bundled/analytics/index.js.map +1 -1
  13. package/dist/skills/bundled/arbitrage/SKILL.md +287 -0
  14. package/dist/skills/bundled/auto-reply/SKILL.md +285 -0
  15. package/dist/skills/bundled/auto-reply/index.js +2 -2
  16. package/dist/skills/bundled/auto-reply/index.js.map +1 -1
  17. package/dist/skills/bundled/automation/SKILL.md +242 -0
  18. package/dist/skills/bundled/automation/index.js +2 -2
  19. package/dist/skills/bundled/automation/index.js.map +1 -1
  20. package/dist/skills/bundled/backtest/SKILL.md +225 -0
  21. package/dist/skills/bundled/bags/SKILL.md +131 -0
  22. package/dist/skills/bundled/bankr/SKILL.md +114 -0
  23. package/dist/skills/bundled/betfair/SKILL.md +113 -0
  24. package/dist/skills/bundled/binance-futures/SKILL.md +84 -0
  25. package/dist/skills/bundled/binance-futures/index.d.ts +0 -3
  26. package/dist/skills/bundled/binance-futures/index.js +1 -2
  27. package/dist/skills/bundled/binance-futures/index.js.map +1 -1
  28. package/dist/skills/bundled/botchan/SKILL.md +66 -0
  29. package/dist/skills/bundled/botchan/index.d.ts +0 -3
  30. package/dist/skills/bundled/botchan/index.js +0 -1
  31. package/dist/skills/bundled/botchan/index.js.map +1 -1
  32. package/dist/skills/bundled/bridge/SKILL.md +215 -0
  33. package/dist/skills/bundled/bybit-futures/SKILL.md +84 -0
  34. package/dist/skills/bundled/bybit-futures/index.d.ts +0 -3
  35. package/dist/skills/bundled/bybit-futures/index.js +0 -1
  36. package/dist/skills/bundled/bybit-futures/index.js.map +1 -1
  37. package/dist/skills/bundled/clanker/SKILL.md +125 -0
  38. package/dist/skills/bundled/clanker/index.d.ts +0 -3
  39. package/dist/skills/bundled/clanker/index.js +0 -1
  40. package/dist/skills/bundled/clanker/index.js.map +1 -1
  41. package/dist/skills/bundled/copy-trading/SKILL.md +285 -0
  42. package/dist/skills/bundled/copy-trading/index.js +2 -2
  43. package/dist/skills/bundled/copy-trading/index.js.map +1 -1
  44. package/dist/skills/bundled/copy-trading-solana/SKILL.md +66 -0
  45. package/dist/skills/bundled/credentials/SKILL.md +261 -0
  46. package/dist/skills/bundled/crypto-hft/SKILL.md +121 -0
  47. package/dist/skills/bundled/dca/SKILL.md +27 -0
  48. package/dist/skills/bundled/dex/SKILL.md +87 -0
  49. package/dist/skills/bundled/divergence/SKILL.md +83 -0
  50. package/dist/skills/bundled/doctor/SKILL.md +267 -0
  51. package/dist/skills/bundled/doctor/index.js +2 -8
  52. package/dist/skills/bundled/doctor/index.js.map +1 -1
  53. package/dist/skills/bundled/drift/SKILL.md +53 -0
  54. package/dist/skills/bundled/drift-sdk/SKILL.md +103 -0
  55. package/dist/skills/bundled/drift-sdk/index.d.ts +0 -3
  56. package/dist/skills/bundled/drift-sdk/index.js +0 -1
  57. package/dist/skills/bundled/drift-sdk/index.js.map +1 -1
  58. package/dist/skills/bundled/edge/SKILL.md +84 -0
  59. package/dist/skills/bundled/embeddings/SKILL.md +244 -0
  60. package/dist/skills/bundled/endaoment/SKILL.md +65 -0
  61. package/dist/skills/bundled/endaoment/index.d.ts +0 -3
  62. package/dist/skills/bundled/endaoment/index.js +0 -1
  63. package/dist/skills/bundled/endaoment/index.js.map +1 -1
  64. package/dist/skills/bundled/ens/SKILL.md +63 -0
  65. package/dist/skills/bundled/ens/index.d.ts +0 -3
  66. package/dist/skills/bundled/ens/index.js +0 -1
  67. package/dist/skills/bundled/ens/index.js.map +1 -1
  68. package/dist/skills/bundled/erc8004/SKILL.md +79 -0
  69. package/dist/skills/bundled/erc8004/index.d.ts +0 -3
  70. package/dist/skills/bundled/erc8004/index.js +0 -1
  71. package/dist/skills/bundled/erc8004/index.js.map +1 -1
  72. package/dist/skills/bundled/execution/SKILL.md +278 -0
  73. package/dist/skills/bundled/farcaster/SKILL.md +80 -0
  74. package/dist/skills/bundled/features/SKILL.md +20 -0
  75. package/dist/skills/bundled/feeds/SKILL.md +288 -0
  76. package/dist/skills/bundled/harden/SKILL.md +74 -0
  77. package/dist/skills/bundled/history/SKILL.md +257 -0
  78. package/dist/skills/bundled/hyperliquid/SKILL.md +200 -0
  79. package/dist/skills/bundled/hyperliquid/index.d.ts +0 -3
  80. package/dist/skills/bundled/hyperliquid/index.js +0 -1
  81. package/dist/skills/bundled/hyperliquid/index.js.map +1 -1
  82. package/dist/skills/bundled/identity/SKILL.md +228 -0
  83. package/dist/skills/bundled/identity/index.js +2 -2
  84. package/dist/skills/bundled/identity/index.js.map +1 -1
  85. package/dist/skills/bundled/integrations/SKILL.md +321 -0
  86. package/dist/skills/bundled/integrations/index.js +2 -2
  87. package/dist/skills/bundled/integrations/index.js.map +1 -1
  88. package/dist/skills/bundled/jupiter/SKILL.md +163 -0
  89. package/dist/skills/bundled/kamino/SKILL.md +69 -0
  90. package/dist/skills/bundled/ledger/SKILL.md +20 -0
  91. package/dist/skills/bundled/lighter/SKILL.md +83 -0
  92. package/dist/skills/bundled/lighter/index.d.ts +0 -3
  93. package/dist/skills/bundled/lighter/index.js +0 -1
  94. package/dist/skills/bundled/lighter/index.js.map +1 -1
  95. package/dist/skills/bundled/marginfi/SKILL.md +62 -0
  96. package/dist/skills/bundled/market-index/SKILL.md +242 -0
  97. package/dist/skills/bundled/market-index/index.js +1 -3
  98. package/dist/skills/bundled/market-index/index.js.map +1 -1
  99. package/dist/skills/bundled/markets/SKILL.md +49 -0
  100. package/dist/skills/bundled/mcp/SKILL.md +235 -0
  101. package/dist/skills/bundled/mcp/index.js +1 -3
  102. package/dist/skills/bundled/mcp/index.js.map +1 -1
  103. package/dist/skills/bundled/memory/SKILL.md +209 -0
  104. package/dist/skills/bundled/metaculus/SKILL.md +62 -0
  105. package/dist/skills/bundled/meteora/SKILL.md +28 -0
  106. package/dist/skills/bundled/meteora-dbc/SKILL.md +25 -0
  107. package/dist/skills/bundled/metrics/SKILL.md +338 -0
  108. package/dist/skills/bundled/mev/SKILL.md +239 -0
  109. package/dist/skills/bundled/mev/index.js +2 -2
  110. package/dist/skills/bundled/mev/index.js.map +1 -1
  111. package/dist/skills/bundled/mexc-futures/SKILL.md +86 -0
  112. package/dist/skills/bundled/mexc-futures/index.d.ts +0 -3
  113. package/dist/skills/bundled/mexc-futures/index.js +0 -1
  114. package/dist/skills/bundled/mexc-futures/index.js.map +1 -1
  115. package/dist/skills/bundled/mm/SKILL.md +142 -0
  116. package/dist/skills/bundled/monitoring/SKILL.md +249 -0
  117. package/dist/skills/bundled/news/SKILL.md +95 -0
  118. package/dist/skills/bundled/onchainkit/SKILL.md +83 -0
  119. package/dist/skills/bundled/opinion/SKILL.md +87 -0
  120. package/dist/skills/bundled/opportunity/SKILL.md +308 -0
  121. package/dist/skills/bundled/orca/SKILL.md +28 -0
  122. package/dist/skills/bundled/pairing/SKILL.md +275 -0
  123. package/dist/skills/bundled/pancakeswap/SKILL.md +93 -0
  124. package/dist/skills/bundled/pancakeswap/index.d.ts +0 -3
  125. package/dist/skills/bundled/pancakeswap/index.js +0 -1
  126. package/dist/skills/bundled/pancakeswap/index.js.map +1 -1
  127. package/dist/skills/bundled/percolator/SKILL.md +22 -0
  128. package/dist/skills/bundled/permissions/SKILL.md +269 -0
  129. package/dist/skills/bundled/permissions/index.js +2 -2
  130. package/dist/skills/bundled/permissions/index.js.map +1 -1
  131. package/dist/skills/bundled/plugins/SKILL.md +263 -0
  132. package/dist/skills/bundled/plugins/index.js +2 -2
  133. package/dist/skills/bundled/plugins/index.js.map +1 -1
  134. package/dist/skills/bundled/portfolio/SKILL.md +161 -0
  135. package/dist/skills/bundled/portfolio/index.js +1 -1
  136. package/dist/skills/bundled/portfolio/index.js.map +1 -1
  137. package/dist/skills/bundled/portfolio-sync/SKILL.md +466 -0
  138. package/dist/skills/bundled/positions/SKILL.md +262 -0
  139. package/dist/skills/bundled/predictfun/SKILL.md +109 -0
  140. package/dist/skills/bundled/predictfun/index.js +1 -1
  141. package/dist/skills/bundled/predictfun/index.js.map +1 -1
  142. package/dist/skills/bundled/predictit/SKILL.md +66 -0
  143. package/dist/skills/bundled/presence/SKILL.md +217 -0
  144. package/dist/skills/bundled/presence/index.js +2 -2
  145. package/dist/skills/bundled/presence/index.js.map +1 -1
  146. package/dist/skills/bundled/processes/SKILL.md +254 -0
  147. package/dist/skills/bundled/pump-swarm/SKILL.md +309 -0
  148. package/dist/skills/bundled/pumpfun/SKILL.md +145 -0
  149. package/dist/skills/bundled/qmd/SKILL.md +129 -0
  150. package/dist/skills/bundled/qrcoin/SKILL.md +60 -0
  151. package/dist/skills/bundled/qrcoin/index.d.ts +0 -3
  152. package/dist/skills/bundled/qrcoin/index.js +0 -1
  153. package/dist/skills/bundled/qrcoin/index.js.map +1 -1
  154. package/dist/skills/bundled/raydium/SKILL.md +198 -0
  155. package/dist/skills/bundled/remote/SKILL.md +201 -0
  156. package/dist/skills/bundled/research/SKILL.md +83 -0
  157. package/dist/skills/bundled/research/index.js +2 -2
  158. package/dist/skills/bundled/research/index.js.map +1 -1
  159. package/dist/skills/bundled/risk/SKILL.md +323 -0
  160. package/dist/skills/bundled/router/SKILL.md +233 -0
  161. package/dist/skills/bundled/routing/SKILL.md +258 -0
  162. package/dist/skills/bundled/sandbox/SKILL.md +257 -0
  163. package/dist/skills/bundled/search-config/SKILL.md +257 -0
  164. package/dist/skills/bundled/search-config/index.js +2 -2
  165. package/dist/skills/bundled/search-config/index.js.map +1 -1
  166. package/dist/skills/bundled/sessions/SKILL.md +251 -0
  167. package/dist/skills/bundled/sessions/index.js +1 -1
  168. package/dist/skills/bundled/sessions/index.js.map +1 -1
  169. package/dist/skills/bundled/setup/SKILL.md +53 -0
  170. package/dist/skills/bundled/shield/SKILL.md +21 -0
  171. package/dist/skills/bundled/signals/SKILL.md +106 -0
  172. package/dist/skills/bundled/signals/index.d.ts +0 -3
  173. package/dist/skills/bundled/signals/index.js +3 -4
  174. package/dist/skills/bundled/signals/index.js.map +1 -1
  175. package/dist/skills/bundled/sizing/SKILL.md +238 -0
  176. package/dist/skills/bundled/slippage/SKILL.md +306 -0
  177. package/dist/skills/bundled/smarkets/SKILL.md +107 -0
  178. package/dist/skills/bundled/solend/SKILL.md +63 -0
  179. package/dist/skills/bundled/strategy/SKILL.md +266 -0
  180. package/dist/skills/bundled/streaming/SKILL.md +150 -0
  181. package/dist/skills/bundled/streaming/index.js +2 -2
  182. package/dist/skills/bundled/streaming/index.js.map +1 -1
  183. package/dist/skills/bundled/tailscale/SKILL.md +249 -0
  184. package/dist/skills/bundled/tailscale/index.js +2 -2
  185. package/dist/skills/bundled/tailscale/index.js.map +1 -1
  186. package/dist/skills/bundled/ticks/SKILL.md +61 -0
  187. package/dist/skills/bundled/token-security/SKILL.md +18 -0
  188. package/dist/skills/bundled/trading-evm/SKILL.md +329 -0
  189. package/dist/skills/bundled/trading-futures/SKILL.md +865 -0
  190. package/dist/skills/bundled/trading-kalshi/SKILL.md +629 -0
  191. package/dist/skills/bundled/trading-manifold/SKILL.md +387 -0
  192. package/dist/skills/bundled/trading-polymarket/SKILL.md +1080 -0
  193. package/dist/skills/bundled/trading-solana/SKILL.md +418 -0
  194. package/dist/skills/bundled/trading-system/SKILL.md +290 -0
  195. package/dist/skills/bundled/triggers/SKILL.md +433 -0
  196. package/dist/skills/bundled/tts/SKILL.md +220 -0
  197. package/dist/skills/bundled/tweet-ideas/SKILL.md +77 -0
  198. package/dist/skills/bundled/usage/SKILL.md +239 -0
  199. package/dist/skills/bundled/usage/index.js +2 -2
  200. package/dist/skills/bundled/usage/index.js.map +1 -1
  201. package/dist/skills/bundled/veil/SKILL.md +76 -0
  202. package/dist/skills/bundled/veil/index.d.ts +0 -3
  203. package/dist/skills/bundled/veil/index.js +0 -1
  204. package/dist/skills/bundled/veil/index.js.map +1 -1
  205. package/dist/skills/bundled/verify/SKILL.md +199 -0
  206. package/dist/skills/bundled/verify/index.d.ts +0 -3
  207. package/dist/skills/bundled/verify/index.js +0 -1
  208. package/dist/skills/bundled/verify/index.js.map +1 -1
  209. package/dist/skills/bundled/virtuals/SKILL.md +82 -0
  210. package/dist/skills/bundled/voice/SKILL.md +217 -0
  211. package/dist/skills/bundled/voice/index.js +2 -2
  212. package/dist/skills/bundled/voice/index.js.map +1 -1
  213. package/dist/skills/bundled/weather/SKILL.md +80 -0
  214. package/dist/skills/bundled/webhooks/SKILL.md +297 -0
  215. package/dist/skills/bundled/webhooks/index.js +2 -2
  216. package/dist/skills/bundled/webhooks/index.js.map +1 -1
  217. package/dist/skills/bundled/whale-tracking/SKILL.md +287 -0
  218. package/dist/skills/bundled/whale-tracking/index.js +2 -2
  219. package/dist/skills/bundled/whale-tracking/index.js.map +1 -1
  220. package/dist/skills/bundled/yoink/SKILL.md +54 -0
  221. package/dist/skills/bundled/yoink/index.d.ts +0 -3
  222. package/dist/skills/bundled/yoink/index.js +0 -1
  223. package/dist/skills/bundled/yoink/index.js.map +1 -1
  224. package/dist/skills/executor.js +5 -3
  225. package/dist/skills/executor.js.map +1 -1
  226. package/package.json +2 -2
@@ -0,0 +1,466 @@
1
+ ---
2
+ name: portfolio-sync
3
+ description: "Sync portfolio positions from Polymarket, Kalshi, and Manifold"
4
+ emoji: "📁"
5
+ ---
6
+
7
+ # Portfolio Sync Skill
8
+
9
+ Real methods to fetch and sync positions from each prediction market platform.
10
+
11
+ ## Polymarket Position Sync
12
+
13
+ Polymarket positions are held as ERC-1155 tokens on Polygon. Query on-chain balances.
14
+
15
+ ```python
16
+ import os
17
+ import requests
18
+
19
+ WALLET = os.getenv("POLY_FUNDER_ADDRESS")
20
+ CTF_CONTRACT = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" # Conditional Token Framework
21
+
22
+ def get_polymarket_positions(token_ids: list[str]) -> dict:
23
+ """
24
+ Get balances for specific token IDs
25
+
26
+ Args:
27
+ token_ids: List of token IDs to check (from market data)
28
+
29
+ Returns:
30
+ Dict of token_id -> balance in shares
31
+ """
32
+ positions = {}
33
+
34
+ for token_id in token_ids:
35
+ token_int = int(token_id)
36
+
37
+ # ERC-1155 balanceOf call
38
+ data = f"0x00fdd58e000000000000000000000000{WALLET[2:].lower()}{token_int:064x}"
39
+
40
+ r = requests.post("https://polygon-rpc.com/", json={
41
+ "jsonrpc": "2.0",
42
+ "method": "eth_call",
43
+ "params": [{"to": CTF_CONTRACT, "data": data}, "latest"],
44
+ "id": 1
45
+ })
46
+
47
+ result = r.json().get("result", "0x0")
48
+ balance = int(result, 16) / 1e6 # Raw to shares
49
+
50
+ if balance > 0:
51
+ positions[token_id] = balance
52
+
53
+ return positions
54
+
55
+ # Example: Check positions for BTC 15-min market
56
+ btc_tokens = [
57
+ "21742633143463906290569050155826241533067272736897614950488156847949938836455", # YES
58
+ "48331043336612883890938759509493159234755048973500640148014422747788308965745" # NO
59
+ ]
60
+
61
+ positions = get_polymarket_positions(btc_tokens)
62
+ for token_id, balance in positions.items():
63
+ print(f"Token {token_id[:20]}...: {balance} shares")
64
+ ```
65
+
66
+ ### Get All Polymarket Positions (via Gamma API)
67
+
68
+ ```python
69
+ def get_all_polymarket_positions(wallet: str):
70
+ """Get all positions for a wallet via Gamma API"""
71
+ url = f"https://gamma-api.polymarket.com/positions?user={wallet.lower()}"
72
+ r = requests.get(url)
73
+
74
+ if r.status_code != 200:
75
+ return []
76
+
77
+ positions = r.json()
78
+
79
+ result = []
80
+ for p in positions:
81
+ result.append({
82
+ "market_id": p.get("conditionId"),
83
+ "market_question": p.get("title", "Unknown"),
84
+ "token_id": p.get("tokenId"),
85
+ "outcome": p.get("outcome"),
86
+ "size": float(p.get("size", 0)),
87
+ "avg_price": float(p.get("avgPrice", 0)),
88
+ "current_price": float(p.get("currentPrice", 0)),
89
+ "pnl": float(p.get("pnl", 0)),
90
+ "value": float(p.get("value", 0))
91
+ })
92
+
93
+ return result
94
+
95
+ positions = get_all_polymarket_positions(WALLET)
96
+ for p in positions:
97
+ print(f"{p['market_question'][:40]}")
98
+ print(f" {p['outcome']}: {p['size']} shares @ {p['avg_price']:.2f} -> {p['current_price']:.2f}")
99
+ print(f" PnL: ${p['pnl']:.2f}")
100
+ ```
101
+
102
+ ### Get USDC Balance
103
+
104
+ ```python
105
+ def get_usdc_balance(wallet: str) -> float:
106
+ """Get USDC balance on Polygon"""
107
+ USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" # USDC on Polygon
108
+
109
+ # ERC-20 balanceOf
110
+ data = f"0x70a08231000000000000000000000000{wallet[2:].lower()}"
111
+
112
+ r = requests.post("https://polygon-rpc.com/", json={
113
+ "jsonrpc": "2.0",
114
+ "method": "eth_call",
115
+ "params": [{"to": USDC, "data": data}, "latest"],
116
+ "id": 1
117
+ })
118
+
119
+ result = r.json().get("result", "0x0")
120
+ balance = int(result, 16) / 1e6 # USDC has 6 decimals
121
+
122
+ return balance
123
+
124
+ usdc = get_usdc_balance(WALLET)
125
+ print(f"USDC Balance: ${usdc:.2f}")
126
+ ```
127
+
128
+ ## Kalshi Position Sync
129
+
130
+ ```python
131
+ import requests
132
+ import time
133
+
134
+ BASE_URL = "https://trading-api.kalshi.com/trade-api/v2"
135
+
136
+ class KalshiSync:
137
+ def __init__(self, email: str, password: str):
138
+ self.email = email
139
+ self.password = password
140
+ self.token = None
141
+ self.token_expiry = 0
142
+
143
+ def _auth(self):
144
+ if time.time() > self.token_expiry - 60:
145
+ r = requests.post(f"{BASE_URL}/login", json={
146
+ "email": self.email,
147
+ "password": self.password
148
+ })
149
+ r.raise_for_status()
150
+ self.token = r.json()["token"]
151
+ self.token_expiry = time.time() + 29 * 60
152
+
153
+ def _headers(self):
154
+ self._auth()
155
+ return {"Authorization": f"Bearer {self.token}"}
156
+
157
+ def get_positions(self):
158
+ """Get all Kalshi positions"""
159
+ r = requests.get(f"{BASE_URL}/portfolio/positions", headers=self._headers())
160
+ r.raise_for_status()
161
+
162
+ positions = []
163
+ for p in r.json().get("market_positions", []):
164
+ # Get market details
165
+ market = requests.get(
166
+ f"{BASE_URL}/markets/{p['ticker']}",
167
+ headers=self._headers()
168
+ ).json().get("market", {})
169
+
170
+ positions.append({
171
+ "market_id": p["ticker"],
172
+ "market_question": market.get("title", p["ticker"]),
173
+ "side": "YES" if p.get("position", 0) > 0 else "NO",
174
+ "size": abs(p.get("position", 0)),
175
+ "avg_price": p.get("average_price", 0) / 100,
176
+ "current_price": market.get("yes_bid", 50) / 100,
177
+ "value": abs(p.get("position", 0)) * market.get("yes_bid", 50) / 100,
178
+ "pnl": p.get("realized_pnl", 0) / 100
179
+ })
180
+
181
+ return positions
182
+
183
+ def get_balance(self):
184
+ """Get Kalshi balance"""
185
+ r = requests.get(f"{BASE_URL}/portfolio/balance", headers=self._headers())
186
+ r.raise_for_status()
187
+ data = r.json()
188
+ return {
189
+ "available": data.get("balance", 0) / 100,
190
+ "portfolio_value": data.get("portfolio_value", 0) / 100
191
+ }
192
+
193
+ # Usage
194
+ sync = KalshiSync(os.getenv("KALSHI_EMAIL"), os.getenv("KALSHI_PASSWORD"))
195
+
196
+ positions = sync.get_positions()
197
+ for p in positions:
198
+ print(f"{p['market_question'][:40]}")
199
+ print(f" {p['side']}: {p['size']} @ {p['avg_price']:.2f} -> {p['current_price']:.2f}")
200
+
201
+ balance = sync.get_balance()
202
+ print(f"\nAvailable: ${balance['available']:.2f}")
203
+ print(f"Portfolio: ${balance['portfolio_value']:.2f}")
204
+ ```
205
+
206
+ ## Manifold Position Sync
207
+
208
+ ```python
209
+ import requests
210
+
211
+ API_URL = "https://api.manifold.markets/v0"
212
+ API_KEY = os.getenv("MANIFOLD_API_KEY")
213
+
214
+ def get_manifold_positions():
215
+ """Get all Manifold positions"""
216
+ headers = {"Authorization": f"Key {API_KEY}"}
217
+
218
+ # Get user profile
219
+ r = requests.get(f"{API_URL}/me", headers=headers)
220
+ r.raise_for_status()
221
+ user = r.json()
222
+ user_id = user["id"]
223
+ balance = user.get("balance", 0)
224
+
225
+ # Get all bets
226
+ r = requests.get(f"{API_URL}/bets", headers=headers, params={"userId": user_id, "limit": 1000})
227
+ bets = r.json()
228
+
229
+ # Aggregate positions by market
230
+ markets = {}
231
+ for bet in bets:
232
+ if bet.get("isSold") or bet.get("isCancelled"):
233
+ continue
234
+
235
+ mid = bet["contractId"]
236
+ if mid not in markets:
237
+ markets[mid] = {
238
+ "yes_shares": 0,
239
+ "no_shares": 0,
240
+ "invested": 0,
241
+ "question": bet.get("contractQuestion", "Unknown")
242
+ }
243
+
244
+ if bet["outcome"] == "YES":
245
+ markets[mid]["yes_shares"] += bet.get("shares", 0)
246
+ else:
247
+ markets[mid]["no_shares"] += bet.get("shares", 0)
248
+
249
+ markets[mid]["invested"] += bet["amount"]
250
+
251
+ # Get current prices
252
+ positions = []
253
+ for mid, data in markets.items():
254
+ if data["yes_shares"] == 0 and data["no_shares"] == 0:
255
+ continue
256
+
257
+ # Fetch current market price
258
+ r = requests.get(f"{API_URL}/market/{mid}")
259
+ if r.status_code == 200:
260
+ market = r.json()
261
+ prob = market.get("probability", 0.5)
262
+
263
+ yes_value = data["yes_shares"] * prob
264
+ no_value = data["no_shares"] * (1 - prob)
265
+ total_value = yes_value + no_value
266
+ pnl = total_value - data["invested"]
267
+
268
+ positions.append({
269
+ "market_id": mid,
270
+ "market_question": data["question"],
271
+ "yes_shares": data["yes_shares"],
272
+ "no_shares": data["no_shares"],
273
+ "invested": data["invested"],
274
+ "current_value": total_value,
275
+ "probability": prob,
276
+ "pnl": pnl,
277
+ "url": market.get("url", "")
278
+ })
279
+
280
+ return positions, balance
281
+
282
+ positions, balance = get_manifold_positions()
283
+ print(f"Mana Balance: {balance}")
284
+
285
+ for p in positions:
286
+ print(f"\n{p['market_question'][:50]}")
287
+ print(f" YES: {p['yes_shares']:.1f} shares, NO: {p['no_shares']:.1f} shares")
288
+ print(f" Value: {p['current_value']:.0f}M, PnL: {p['pnl']:+.0f}M")
289
+ ```
290
+
291
+ ## Unified Portfolio Sync
292
+
293
+ ```python
294
+ #!/usr/bin/env python3
295
+ """
296
+ Sync portfolio from all prediction markets
297
+ """
298
+
299
+ import os
300
+ from dataclasses import dataclass
301
+ from typing import List
302
+
303
+ @dataclass
304
+ class Position:
305
+ platform: str
306
+ market_id: str
307
+ market_question: str
308
+ side: str
309
+ size: float
310
+ avg_price: float
311
+ current_price: float
312
+ value: float
313
+ pnl: float
314
+ pnl_pct: float
315
+
316
+ def sync_all_portfolios() -> List[Position]:
317
+ """Sync positions from all platforms"""
318
+ all_positions = []
319
+
320
+ # Polymarket
321
+ if os.getenv("POLY_FUNDER_ADDRESS"):
322
+ poly_positions = get_all_polymarket_positions(os.getenv("POLY_FUNDER_ADDRESS"))
323
+ for p in poly_positions:
324
+ avg = p["avg_price"] or 0.01
325
+ pnl_pct = ((p["current_price"] - avg) / avg * 100) if avg > 0 else 0
326
+
327
+ all_positions.append(Position(
328
+ platform="polymarket",
329
+ market_id=p["market_id"],
330
+ market_question=p["market_question"],
331
+ side=p["outcome"],
332
+ size=p["size"],
333
+ avg_price=avg,
334
+ current_price=p["current_price"],
335
+ value=p["value"],
336
+ pnl=p["pnl"],
337
+ pnl_pct=pnl_pct
338
+ ))
339
+
340
+ # Kalshi
341
+ if os.getenv("KALSHI_EMAIL"):
342
+ kalshi = KalshiSync(os.getenv("KALSHI_EMAIL"), os.getenv("KALSHI_PASSWORD"))
343
+ kalshi_positions = kalshi.get_positions()
344
+ for p in kalshi_positions:
345
+ avg = p["avg_price"] or 0.01
346
+ pnl_pct = ((p["current_price"] - avg) / avg * 100) if avg > 0 else 0
347
+
348
+ all_positions.append(Position(
349
+ platform="kalshi",
350
+ market_id=p["market_id"],
351
+ market_question=p["market_question"],
352
+ side=p["side"],
353
+ size=p["size"],
354
+ avg_price=avg,
355
+ current_price=p["current_price"],
356
+ value=p["value"],
357
+ pnl=p["pnl"],
358
+ pnl_pct=pnl_pct
359
+ ))
360
+
361
+ # Manifold
362
+ if os.getenv("MANIFOLD_API_KEY"):
363
+ mani_positions, _ = get_manifold_positions()
364
+ for p in mani_positions:
365
+ invested = p["invested"] or 1
366
+ pnl_pct = (p["pnl"] / invested * 100) if invested > 0 else 0
367
+
368
+ # Add YES position
369
+ if p["yes_shares"] > 0:
370
+ all_positions.append(Position(
371
+ platform="manifold",
372
+ market_id=p["market_id"],
373
+ market_question=p["market_question"],
374
+ side="YES",
375
+ size=p["yes_shares"],
376
+ avg_price=0, # Manifold doesn't track this
377
+ current_price=p["probability"],
378
+ value=p["yes_shares"] * p["probability"],
379
+ pnl=p["pnl"] / 2, # Split PnL
380
+ pnl_pct=pnl_pct
381
+ ))
382
+
383
+ # Add NO position
384
+ if p["no_shares"] > 0:
385
+ all_positions.append(Position(
386
+ platform="manifold",
387
+ market_id=p["market_id"],
388
+ market_question=p["market_question"],
389
+ side="NO",
390
+ size=p["no_shares"],
391
+ avg_price=0,
392
+ current_price=1 - p["probability"],
393
+ value=p["no_shares"] * (1 - p["probability"]),
394
+ pnl=p["pnl"] / 2,
395
+ pnl_pct=pnl_pct
396
+ ))
397
+
398
+ return all_positions
399
+
400
+ # Run sync
401
+ positions = sync_all_portfolios()
402
+
403
+ # Print summary
404
+ total_value = sum(p.value for p in positions)
405
+ total_pnl = sum(p.pnl for p in positions)
406
+
407
+ print(f"\n{'='*60}")
408
+ print(f"PORTFOLIO SUMMARY")
409
+ print(f"{'='*60}")
410
+ print(f"Total Value: ${total_value:.2f}")
411
+ print(f"Total PnL: ${total_pnl:+.2f}")
412
+ print(f"{'='*60}")
413
+
414
+ for platform in ["polymarket", "kalshi", "manifold"]:
415
+ plat_positions = [p for p in positions if p.platform == platform]
416
+ if plat_positions:
417
+ plat_value = sum(p.value for p in plat_positions)
418
+ plat_pnl = sum(p.pnl for p in plat_positions)
419
+ print(f"\n{platform.upper()}: ${plat_value:.2f} (PnL: ${plat_pnl:+.2f})")
420
+
421
+ for p in plat_positions:
422
+ print(f" {p.market_question[:35]}")
423
+ print(f" {p.side}: {p.size:.1f} @ {p.avg_price:.2f} -> {p.current_price:.2f}")
424
+ print(f" Value: ${p.value:.2f}, PnL: ${p.pnl:+.2f} ({p.pnl_pct:+.1f}%)")
425
+ ```
426
+
427
+ ## Cron Job for Auto-Sync
428
+
429
+ ```python
430
+ #!/usr/bin/env python3
431
+ """
432
+ Run every hour to sync positions to database
433
+ """
434
+
435
+ import sqlite3
436
+ from datetime import datetime
437
+
438
+ def sync_to_db():
439
+ """Sync all positions to SQLite"""
440
+ conn = sqlite3.connect("~/.clodds/clodds.db")
441
+ positions = sync_all_portfolios()
442
+
443
+ for p in positions:
444
+ conn.execute("""
445
+ INSERT OR REPLACE INTO positions
446
+ (platform, market_id, market_question, side, size, avg_price, current_price, value, pnl, updated_at)
447
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
448
+ """, (
449
+ p.platform, p.market_id, p.market_question, p.side,
450
+ p.size, p.avg_price, p.current_price, p.value, p.pnl,
451
+ datetime.now().isoformat()
452
+ ))
453
+
454
+ conn.commit()
455
+ conn.close()
456
+ print(f"Synced {len(positions)} positions at {datetime.now()}")
457
+
458
+ if __name__ == "__main__":
459
+ sync_to_db()
460
+ ```
461
+
462
+ Add to crontab:
463
+ ```bash
464
+ # Sync every hour
465
+ 0 * * * * cd /path/to/clodds && python3 -c "from skills.portfolio_sync import sync_to_db; sync_to_db()"
466
+ ```