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,629 @@
1
+ ---
2
+ name: trading-kalshi
3
+ description: "Execute trades on Kalshi - full REST API access for markets, orders, positions, balance"
4
+ emoji: "📈"
5
+ gates:
6
+ envs:
7
+ - KALSHI_EMAIL
8
+ - KALSHI_PASSWORD
9
+ ---
10
+
11
+ # Kalshi Trading - Complete API Reference
12
+
13
+ Full access to Kalshi's CFTC-regulated prediction market via their REST API.
14
+
15
+ **Docs**: https://docs.kalshi.com/welcome
16
+ **Discord**: #dev channel for support
17
+
18
+ ## Required Environment Variables
19
+
20
+ ```bash
21
+ KALSHI_EMAIL=your@email.com
22
+ KALSHI_PASSWORD=your_password
23
+ ```
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install requests
29
+ # Optional: pip install kalshi-python # Official SDK
30
+ ```
31
+
32
+ ---
33
+
34
+ ## API Base URLs
35
+
36
+ ```python
37
+ # Production
38
+ BASE_URL = "https://trading-api.kalshi.com/trade-api/v2"
39
+
40
+ # Demo/Sandbox (for testing)
41
+ DEMO_URL = "https://demo-api.kalshi.co/trade-api/v2"
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Authentication
47
+
48
+ Kalshi uses email/password login returning a bearer token valid for 30 minutes.
49
+
50
+ ### Login & Token Management
51
+
52
+ ```python
53
+ import os
54
+ import time
55
+ import requests
56
+
57
+ BASE_URL = "https://trading-api.kalshi.com/trade-api/v2"
58
+
59
+ class KalshiClient:
60
+ def __init__(self):
61
+ self.email = os.getenv("KALSHI_EMAIL")
62
+ self.password = os.getenv("KALSHI_PASSWORD")
63
+ self.token = None
64
+ self.token_expiry = 0
65
+ self.member_id = None
66
+
67
+ def _ensure_auth(self):
68
+ """Refresh token if expired (30 min lifetime)"""
69
+ if time.time() > self.token_expiry - 60:
70
+ self._login()
71
+
72
+ def _login(self):
73
+ """POST /login - Get new auth token"""
74
+ r = requests.post(f"{BASE_URL}/login", json={
75
+ "email": self.email,
76
+ "password": self.password
77
+ })
78
+ r.raise_for_status()
79
+ data = r.json()
80
+ self.token = data["token"]
81
+ self.member_id = data.get("member_id")
82
+ self.token_expiry = time.time() + 29 * 60 # Refresh at 29 mins
83
+ return data
84
+
85
+ def _headers(self):
86
+ """Get auth headers for requests"""
87
+ self._ensure_auth()
88
+ return {
89
+ "Authorization": f"Bearer {self.token}",
90
+ "Content-Type": "application/json"
91
+ }
92
+
93
+ def logout(self):
94
+ """POST /logout - Invalidate current token"""
95
+ r = requests.post(f"{BASE_URL}/logout", headers=self._headers())
96
+ self.token = None
97
+ self.token_expiry = 0
98
+ return r.status_code == 200
99
+
100
+ # Initialize
101
+ client = KalshiClient()
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Market Data Endpoints
107
+
108
+ ### Get Markets
109
+
110
+ ```python
111
+ def get_markets(
112
+ status: str = "open", # "open", "closed", "settled"
113
+ series_ticker: str = None, # Filter by series
114
+ limit: int = 100,
115
+ cursor: str = None # For pagination
116
+ ):
117
+ """GET /markets - List markets"""
118
+ params = {"status": status, "limit": limit}
119
+ if series_ticker:
120
+ params["series_ticker"] = series_ticker
121
+ if cursor:
122
+ params["cursor"] = cursor
123
+
124
+ r = requests.get(f"{BASE_URL}/markets", headers=client._headers(), params=params)
125
+ r.raise_for_status()
126
+ data = r.json()
127
+ return {
128
+ "markets": data.get("markets", []),
129
+ "cursor": data.get("cursor") # Use for pagination
130
+ }
131
+
132
+ # Examples
133
+ markets = get_markets(series_ticker="INXD") # S&P 500 daily
134
+ markets = get_markets(series_ticker="FED") # Fed rate decisions
135
+ markets = get_markets(series_ticker="KXBTC") # Bitcoin price
136
+ ```
137
+
138
+ ### Get Single Market
139
+
140
+ ```python
141
+ def get_market(ticker: str):
142
+ """GET /markets/{ticker} - Single market details"""
143
+ r = requests.get(f"{BASE_URL}/markets/{ticker}", headers=client._headers())
144
+ r.raise_for_status()
145
+ return r.json()["market"]
146
+
147
+ market = get_market("INXD-24JAN10-T5805")
148
+ # Returns: ticker, title, subtitle, status, yes_bid, yes_ask,
149
+ # no_bid, no_ask, volume, open_interest, close_time, result
150
+ ```
151
+
152
+ ### Get Market Orderbook
153
+
154
+ ```python
155
+ def get_orderbook(ticker: str, depth: int = 10):
156
+ """GET /markets/{ticker}/orderbook - Full orderbook"""
157
+ r = requests.get(f"{BASE_URL}/markets/{ticker}/orderbook",
158
+ headers=client._headers(),
159
+ params={"depth": depth})
160
+ r.raise_for_status()
161
+ data = r.json()["orderbook"]
162
+
163
+ # data["yes"] = list of [price, size] for YES side
164
+ # data["no"] = list of [price, size] for NO side
165
+ return data
166
+
167
+ book = get_orderbook("INXD-24JAN10-T5805")
168
+ print(f"Yes bids: {book['yes']}") # [[45, 100], [44, 200], ...]
169
+ print(f"No asks: {book['no']}")
170
+ ```
171
+
172
+ ### Get Market History/Trades
173
+
174
+ ```python
175
+ def get_market_history(ticker: str, limit: int = 100):
176
+ """GET /markets/{ticker}/history - Trade history"""
177
+ r = requests.get(f"{BASE_URL}/markets/{ticker}/history",
178
+ headers=client._headers(),
179
+ params={"limit": limit})
180
+ r.raise_for_status()
181
+ return r.json().get("history", [])
182
+
183
+ trades = get_market_history("INXD-24JAN10-T5805")
184
+ for t in trades:
185
+ print(f"{t['created_time']}: {t['count']} @ {t['yes_price']}¢")
186
+ ```
187
+
188
+ ### Get Series/Events
189
+
190
+ ```python
191
+ def get_series():
192
+ """GET /series - List all series (categories)"""
193
+ r = requests.get(f"{BASE_URL}/series", headers=client._headers())
194
+ r.raise_for_status()
195
+ return r.json().get("series", [])
196
+
197
+ def get_events(series_ticker: str = None):
198
+ """GET /events - List events"""
199
+ params = {}
200
+ if series_ticker:
201
+ params["series_ticker"] = series_ticker
202
+ r = requests.get(f"{BASE_URL}/events", headers=client._headers(), params=params)
203
+ r.raise_for_status()
204
+ return r.json().get("events", [])
205
+
206
+ series = get_series()
207
+ events = get_events("FED")
208
+ ```
209
+
210
+ ---
211
+
212
+ ## Order Management
213
+
214
+ ### Place Order
215
+
216
+ ```python
217
+ def place_order(
218
+ ticker: str,
219
+ side: str, # "yes" or "no"
220
+ action: str, # "buy" or "sell"
221
+ count: int, # Number of contracts
222
+ price: int = None, # Price in cents (1-99), None for market
223
+ order_type: str = "limit", # "limit" or "market"
224
+ expiration_ts: int = None, # Optional: GTD expiration timestamp
225
+ client_order_id: str = None # Optional: Your reference ID
226
+ ):
227
+ """POST /portfolio/orders - Place an order"""
228
+ payload = {
229
+ "ticker": ticker,
230
+ "side": side.lower(),
231
+ "action": action.lower(),
232
+ "count": count,
233
+ "type": order_type
234
+ }
235
+
236
+ if order_type == "limit" and price:
237
+ # yes_price is always from YES perspective
238
+ payload["yes_price"] = price if side.lower() == "yes" else (100 - price)
239
+
240
+ if expiration_ts:
241
+ payload["expiration_ts"] = expiration_ts
242
+
243
+ if client_order_id:
244
+ payload["client_order_id"] = client_order_id
245
+
246
+ r = requests.post(f"{BASE_URL}/portfolio/orders",
247
+ headers=client._headers(),
248
+ json=payload)
249
+ r.raise_for_status()
250
+ return r.json()
251
+
252
+ # Examples
253
+ # Buy 10 YES at 45 cents
254
+ result = place_order("INXD-24JAN10-T5805", "yes", "buy", 10, 45)
255
+
256
+ # Sell 5 NO at 30 cents (equivalent to YES at 70 cents)
257
+ result = place_order("INXD-24JAN10-T5805", "no", "sell", 5, 30)
258
+
259
+ # Market order (immediate fill)
260
+ result = place_order("INXD-24JAN10-T5805", "yes", "buy", 10, order_type="market")
261
+ ```
262
+
263
+ ### Batch Create Orders
264
+
265
+ ```python
266
+ def batch_create_orders(orders: list):
267
+ """POST /portfolio/orders/batched - Create multiple orders"""
268
+ payload = {"orders": orders}
269
+ r = requests.post(f"{BASE_URL}/portfolio/orders/batched",
270
+ headers=client._headers(),
271
+ json=payload)
272
+ r.raise_for_status()
273
+ return r.json()
274
+
275
+ orders = [
276
+ {"ticker": "INXD-24JAN10-T5805", "side": "yes", "action": "buy", "count": 5, "type": "limit", "yes_price": 40},
277
+ {"ticker": "INXD-24JAN10-T5805", "side": "yes", "action": "buy", "count": 5, "type": "limit", "yes_price": 42},
278
+ ]
279
+ results = batch_create_orders(orders)
280
+ ```
281
+
282
+ ### Amend Order
283
+
284
+ ```python
285
+ def amend_order(order_id: str, count: int = None, price: int = None):
286
+ """POST /portfolio/orders/{order_id}/amend - Modify order"""
287
+ payload = {}
288
+ if count:
289
+ payload["count"] = count
290
+ if price:
291
+ payload["yes_price"] = price
292
+
293
+ r = requests.post(f"{BASE_URL}/portfolio/orders/{order_id}/amend",
294
+ headers=client._headers(),
295
+ json=payload)
296
+ r.raise_for_status()
297
+ return r.json()
298
+ ```
299
+
300
+ ### Decrease Order Size
301
+
302
+ ```python
303
+ def decrease_order(order_id: str, reduce_by: int):
304
+ """POST /portfolio/orders/{order_id}/decrease - Reduce order size"""
305
+ r = requests.post(f"{BASE_URL}/portfolio/orders/{order_id}/decrease",
306
+ headers=client._headers(),
307
+ json={"reduce_by": reduce_by})
308
+ r.raise_for_status()
309
+ return r.json()
310
+ ```
311
+
312
+ ### Cancel Order
313
+
314
+ ```python
315
+ def cancel_order(order_id: str):
316
+ """DELETE /portfolio/orders/{order_id} - Cancel single order"""
317
+ r = requests.delete(f"{BASE_URL}/portfolio/orders/{order_id}",
318
+ headers=client._headers())
319
+ return r.status_code in [200, 204]
320
+
321
+ def batch_cancel_orders(order_ids: list):
322
+ """DELETE /portfolio/orders/batched - Cancel multiple orders"""
323
+ r = requests.delete(f"{BASE_URL}/portfolio/orders/batched",
324
+ headers=client._headers(),
325
+ json={"order_ids": order_ids})
326
+ r.raise_for_status()
327
+ return r.json()
328
+
329
+ # Cancel specific order
330
+ cancel_order("abc123-order-id")
331
+
332
+ # Cancel multiple
333
+ batch_cancel_orders(["order-1", "order-2", "order-3"])
334
+ ```
335
+
336
+ ### Get Orders
337
+
338
+ ```python
339
+ def get_orders(
340
+ ticker: str = None,
341
+ status: str = None, # "resting", "canceled", "executed", "pending"
342
+ limit: int = 100
343
+ ):
344
+ """GET /portfolio/orders - List orders"""
345
+ params = {"limit": limit}
346
+ if ticker:
347
+ params["ticker"] = ticker
348
+ if status:
349
+ params["status"] = status
350
+
351
+ r = requests.get(f"{BASE_URL}/portfolio/orders",
352
+ headers=client._headers(),
353
+ params=params)
354
+ r.raise_for_status()
355
+ return r.json().get("orders", [])
356
+
357
+ def get_order(order_id: str):
358
+ """GET /portfolio/orders/{order_id} - Single order"""
359
+ r = requests.get(f"{BASE_URL}/portfolio/orders/{order_id}",
360
+ headers=client._headers())
361
+ r.raise_for_status()
362
+ return r.json()["order"]
363
+
364
+ # Get all open orders
365
+ orders = get_orders(status="resting")
366
+ for o in orders:
367
+ print(f"{o['order_id']}: {o['action']} {o['side']} {o['remaining_count']} @ {o['yes_price']}¢")
368
+ ```
369
+
370
+ ---
371
+
372
+ ## Portfolio Management
373
+
374
+ ### Get Balance
375
+
376
+ ```python
377
+ def get_balance():
378
+ """GET /portfolio/balance - Account balance"""
379
+ r = requests.get(f"{BASE_URL}/portfolio/balance", headers=client._headers())
380
+ r.raise_for_status()
381
+ data = r.json()
382
+
383
+ return {
384
+ "balance": data.get("balance", 0) / 100, # Available in dollars
385
+ "portfolio_value": data.get("portfolio_value", 0) / 100
386
+ }
387
+
388
+ bal = get_balance()
389
+ print(f"Available: ${bal['balance']:.2f}")
390
+ print(f"Portfolio: ${bal['portfolio_value']:.2f}")
391
+ ```
392
+
393
+ ### Get Positions
394
+
395
+ ```python
396
+ def get_positions(limit: int = 100):
397
+ """GET /portfolio/positions - Current positions"""
398
+ r = requests.get(f"{BASE_URL}/portfolio/positions",
399
+ headers=client._headers(),
400
+ params={"limit": limit})
401
+ r.raise_for_status()
402
+ return r.json().get("market_positions", [])
403
+
404
+ positions = get_positions()
405
+ for p in positions:
406
+ if p.get("position", 0) != 0:
407
+ print(f"{p['ticker']}: {p['position']} contracts @ avg {p['average_price']}¢")
408
+ print(f" Realized P&L: ${p.get('realized_pnl', 0) / 100:.2f}")
409
+ ```
410
+
411
+ ### Get Fills (Trade History)
412
+
413
+ ```python
414
+ def get_fills(
415
+ ticker: str = None,
416
+ limit: int = 100,
417
+ cursor: str = None
418
+ ):
419
+ """GET /portfolio/fills - Executed trades"""
420
+ params = {"limit": limit}
421
+ if ticker:
422
+ params["ticker"] = ticker
423
+ if cursor:
424
+ params["cursor"] = cursor
425
+
426
+ r = requests.get(f"{BASE_URL}/portfolio/fills",
427
+ headers=client._headers(),
428
+ params=params)
429
+ r.raise_for_status()
430
+ data = r.json()
431
+ return {
432
+ "fills": data.get("fills", []),
433
+ "cursor": data.get("cursor")
434
+ }
435
+
436
+ fills = get_fills()
437
+ for f in fills["fills"]:
438
+ print(f"{f['created_time']}: {f['action']} {f['side']} {f['count']} @ {f['price']}¢")
439
+ ```
440
+
441
+ ### Get Settlements
442
+
443
+ ```python
444
+ def get_settlements(limit: int = 100):
445
+ """GET /portfolio/settlements - Settlement history"""
446
+ r = requests.get(f"{BASE_URL}/portfolio/settlements",
447
+ headers=client._headers(),
448
+ params={"limit": limit})
449
+ r.raise_for_status()
450
+ return r.json().get("settlements", [])
451
+
452
+ settlements = get_settlements()
453
+ for s in settlements:
454
+ print(f"{s['ticker']}: Settled at {s['settlement_value']}¢, P&L: ${s['revenue'] / 100:.2f}")
455
+ ```
456
+
457
+ ---
458
+
459
+ ## Exchange Status
460
+
461
+ ```python
462
+ def get_exchange_status():
463
+ """GET /exchange/status - Exchange operational status"""
464
+ r = requests.get(f"{BASE_URL}/exchange/status", headers=client._headers())
465
+ r.raise_for_status()
466
+ return r.json()
467
+
468
+ status = get_exchange_status()
469
+ print(f"Trading: {status.get('trading_active')}")
470
+ print(f"Exchange open: {status.get('exchange_active')}")
471
+ ```
472
+
473
+ ---
474
+
475
+ ## WebSocket (Real-time Data)
476
+
477
+ For real-time updates, use WebSocket after REST authentication:
478
+
479
+ ```python
480
+ import websocket
481
+ import json
482
+
483
+ def on_message(ws, message):
484
+ data = json.loads(message)
485
+ print(f"Update: {data}")
486
+
487
+ def on_open(ws):
488
+ # Subscribe to orderbook updates
489
+ ws.send(json.dumps({
490
+ "type": "subscribe",
491
+ "channel": "orderbook",
492
+ "ticker": "INXD-24JAN10-T5805"
493
+ }))
494
+
495
+ # Connect with auth token
496
+ ws = websocket.WebSocketApp(
497
+ f"wss://trading-api.kalshi.com/trade-api/ws/v2?token={client.token}",
498
+ on_message=on_message,
499
+ on_open=on_open
500
+ )
501
+ ws.run_forever()
502
+ ```
503
+
504
+ ---
505
+
506
+ ## Complete Trading Bot
507
+
508
+ ```python
509
+ #!/usr/bin/env python3
510
+ """
511
+ Production Kalshi trading bot
512
+ """
513
+
514
+ import os
515
+ import time
516
+ import requests
517
+
518
+ BASE_URL = "https://trading-api.kalshi.com/trade-api/v2"
519
+
520
+ class KalshiBot:
521
+ def __init__(self):
522
+ self.email = os.getenv("KALSHI_EMAIL")
523
+ self.password = os.getenv("KALSHI_PASSWORD")
524
+ self.token = None
525
+ self.token_expiry = 0
526
+
527
+ def _auth(self):
528
+ if time.time() > self.token_expiry - 60:
529
+ r = requests.post(f"{BASE_URL}/login", json={
530
+ "email": self.email, "password": self.password
531
+ })
532
+ r.raise_for_status()
533
+ self.token = r.json()["token"]
534
+ self.token_expiry = time.time() + 29 * 60
535
+
536
+ def _h(self):
537
+ self._auth()
538
+ return {"Authorization": f"Bearer {self.token}", "Content-Type": "application/json"}
539
+
540
+ def get_market(self, ticker):
541
+ r = requests.get(f"{BASE_URL}/markets/{ticker}", headers=self._h())
542
+ r.raise_for_status()
543
+ return r.json()["market"]
544
+
545
+ def get_positions(self):
546
+ r = requests.get(f"{BASE_URL}/portfolio/positions", headers=self._h())
547
+ r.raise_for_status()
548
+ return {p["ticker"]: p for p in r.json().get("market_positions", [])}
549
+
550
+ def get_balance(self):
551
+ r = requests.get(f"{BASE_URL}/portfolio/balance", headers=self._h())
552
+ r.raise_for_status()
553
+ return r.json().get("balance", 0) / 100
554
+
555
+ def buy(self, ticker, side, count, price):
556
+ payload = {
557
+ "ticker": ticker, "side": side, "action": "buy",
558
+ "count": count, "type": "limit",
559
+ "yes_price": price if side == "yes" else (100 - price)
560
+ }
561
+ r = requests.post(f"{BASE_URL}/portfolio/orders", headers=self._h(), json=payload)
562
+ return r.json() if r.status_code == 200 else {"error": r.text}
563
+
564
+ def sell(self, ticker, side, count, price):
565
+ payload = {
566
+ "ticker": ticker, "side": side, "action": "sell",
567
+ "count": count, "type": "limit",
568
+ "yes_price": price if side == "yes" else (100 - price)
569
+ }
570
+ r = requests.post(f"{BASE_URL}/portfolio/orders", headers=self._h(), json=payload)
571
+ return r.json() if r.status_code == 200 else {"error": r.text}
572
+
573
+ # Run
574
+ bot = KalshiBot()
575
+ TICKER = "INXD-24JAN10-T5805"
576
+
577
+ while True:
578
+ try:
579
+ market = bot.get_market(TICKER)
580
+ positions = bot.get_positions()
581
+ balance = bot.get_balance()
582
+
583
+ yes_bid = market["yes_bid"]
584
+ yes_ask = market["yes_ask"]
585
+ pos = positions.get(TICKER, {}).get("position", 0)
586
+
587
+ print(f"Balance: ${balance:.2f}, Position: {pos}, Price: {yes_bid}/{yes_ask}")
588
+
589
+ # Trading logic
590
+ if yes_ask < 40 and pos < 10 and balance > 5:
591
+ print(f"BUYING at {yes_ask}")
592
+ bot.buy(TICKER, "yes", 5, yes_ask)
593
+ elif yes_bid > 60 and pos > 0:
594
+ print(f"SELLING at {yes_bid}")
595
+ bot.sell(TICKER, "yes", pos, yes_bid)
596
+
597
+ time.sleep(10)
598
+
599
+ except Exception as e:
600
+ print(f"Error: {e}")
601
+ time.sleep(30)
602
+ ```
603
+
604
+ ---
605
+
606
+ ## Popular Market Series
607
+
608
+ | Series | Description | Example Ticker |
609
+ |--------|-------------|----------------|
610
+ | FED | Fed rate decisions | FED-24MAR-T525 |
611
+ | INXD | S&P 500 daily close | INXD-24JAN10-T5805 |
612
+ | KXBTC | Bitcoin price brackets | KXBTC-24JAN-T45000 |
613
+ | KXETH | Ethereum price | KXETH-24JAN-T2500 |
614
+ | CPI | Inflation data | CPI-24JAN-T3.5 |
615
+ | GDP | GDP growth | GDP-24Q1-T2.0 |
616
+ | NFP | Non-farm payrolls | NFP-24JAN-T200K |
617
+
618
+ ---
619
+
620
+ ## Key Notes
621
+
622
+ 1. **Prices in CENTS** - 45 means $0.45 per contract
623
+ 2. **Contracts pay $1 if correct** - Cost is the price, profit is $1 - price
624
+ 3. **No trading fees** - Only spread matters
625
+ 4. **Token expires in 30 min** - Auto-refresh before expiry
626
+ 5. **US residents only** - KYC verification required
627
+ 6. **Rate limits exist** - Implement exponential backoff on 429 errors
628
+ 7. **Max position limits** - Varies by market, check market details
629
+