clodds 1.5.1 → 1.5.2
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.
- package/dist/acp/identity.js +21 -13
- package/dist/acp/identity.js.map +1 -1
- package/dist/acp/persistence.js +9 -7
- package/dist/acp/persistence.js.map +1 -1
- package/dist/acp/registry.js +7 -3
- package/dist/acp/registry.js.map +1 -1
- package/dist/agents/handlers/agentbets.js.map +1 -1
- package/dist/agents/handlers/paper-trading.js +1 -1
- package/dist/agents/handlers/paper-trading.js.map +1 -1
- package/dist/agents/handlers/predictfun.js +4 -2
- package/dist/agents/handlers/predictfun.js.map +1 -1
- package/dist/agents/index.js +5 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/alerts/index.js +5 -5
- package/dist/alerts/index.js.map +1 -1
- package/dist/alerts/realtime.js +8 -0
- package/dist/alerts/realtime.js.map +1 -1
- package/dist/api/apikeys.js +1 -1
- package/dist/api/compute/code.js +4 -1
- package/dist/api/compute/code.js.map +1 -1
- package/dist/api/compute/data.js +8 -2
- package/dist/api/compute/data.js.map +1 -1
- package/dist/api/compute/gateway.js +14 -9
- package/dist/api/compute/gateway.js.map +1 -1
- package/dist/api/compute/llm.js +14 -10
- package/dist/api/compute/llm.js.map +1 -1
- package/dist/api/compute/storage.js +6 -2
- package/dist/api/compute/storage.js.map +1 -1
- package/dist/api/compute/trade.js +6 -5
- package/dist/api/compute/trade.js.map +1 -1
- package/dist/api/compute/web.js +5 -0
- package/dist/api/compute/web.js.map +1 -1
- package/dist/api/fees.js +5 -1
- package/dist/api/fees.js.map +1 -1
- package/dist/api/gateway.js +35 -7
- package/dist/api/gateway.js.map +1 -1
- package/dist/api/jobs.js +15 -6
- package/dist/api/jobs.js.map +1 -1
- package/dist/api/middleware.js +12 -3
- package/dist/api/middleware.js.map +1 -1
- package/dist/api/sdk.js +1 -1
- package/dist/api/server.js +16 -7
- package/dist/api/server.js.map +1 -1
- package/dist/arbitrage/index.js +14 -4
- package/dist/arbitrage/index.js.map +1 -1
- package/dist/auth/copilot.js +3 -3
- package/dist/auth/copilot.js.map +1 -1
- package/dist/auth/google.js +6 -2
- package/dist/auth/google.js.map +1 -1
- package/dist/auth/oauth.js +18 -11
- package/dist/auth/oauth.js.map +1 -1
- package/dist/auth/qwen.js +4 -4
- package/dist/auth/qwen.js.map +1 -1
- package/dist/auto-reply/index.js +18 -4
- package/dist/auto-reply/index.js.map +1 -1
- package/dist/automation/cron.js +10 -3
- package/dist/automation/cron.js.map +1 -1
- package/dist/automation/webhooks.js +13 -2
- package/dist/automation/webhooks.js.map +1 -1
- package/dist/bankr/client.js +3 -3
- package/dist/base/provider.js +16 -2
- package/dist/base/provider.js.map +1 -1
- package/dist/bin/worker.js +4 -4
- package/dist/bin/worker.js.map +1 -1
- package/dist/bittensor/chutes.js +1 -1
- package/dist/bittensor/chutes.js.map +1 -1
- package/dist/bittensor/python-runner.js +5 -1
- package/dist/bittensor/python-runner.js.map +1 -1
- package/dist/bittensor/service.js +1 -1
- package/dist/bittensor/service.js.map +1 -1
- package/dist/browser/index.js +40 -16
- package/dist/browser/index.js.map +1 -1
- package/dist/cache/index.d.ts +2 -0
- package/dist/cache/index.js +30 -5
- package/dist/cache/index.js.map +1 -1
- package/dist/canvas/index.js +56 -27
- package/dist/canvas/index.js.map +1 -1
- package/dist/channels/googlechat/index.js +3 -0
- package/dist/channels/googlechat/index.js.map +1 -1
- package/dist/channels/imessage/index.js +6 -0
- package/dist/channels/imessage/index.js.map +1 -1
- package/dist/channels/index.js +7 -2
- package/dist/channels/index.js.map +1 -1
- package/dist/channels/line/index.d.ts +1 -1
- package/dist/channels/line/index.js +4 -2
- package/dist/channels/line/index.js.map +1 -1
- package/dist/channels/mattermost/index.js +5 -0
- package/dist/channels/mattermost/index.js.map +1 -1
- package/dist/channels/nostr/index.js +10 -2
- package/dist/channels/nostr/index.js.map +1 -1
- package/dist/channels/teams/index.js +20 -3
- package/dist/channels/teams/index.js.map +1 -1
- package/dist/channels/telegram/index.js +20 -3
- package/dist/channels/telegram/index.js.map +1 -1
- package/dist/channels/tlon/index.js +6 -1
- package/dist/channels/tlon/index.js.map +1 -1
- package/dist/channels/voice/index.js +16 -0
- package/dist/channels/voice/index.js.map +1 -1
- package/dist/channels/webchat/index.js +6 -1
- package/dist/channels/webchat/index.js.map +1 -1
- package/dist/channels/zalo/index.js +4 -2
- package/dist/channels/zalo/index.js.map +1 -1
- package/dist/cli/commands/doctor.js +2 -2
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/index.js +54 -24
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/onboard.js +12 -11
- package/dist/cli/commands/onboard.js.map +1 -1
- package/dist/cli/commands/skills.js +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/secure.js +11 -5
- package/dist/cli/secure.js.map +1 -1
- package/dist/commands/registry.js +17 -9
- package/dist/commands/registry.js.map +1 -1
- package/dist/config/index.js +42 -32
- package/dist/config/index.js.map +1 -1
- package/dist/credentials/index.js +7 -6
- package/dist/credentials/index.js.map +1 -1
- package/dist/cron/index.js +15 -1
- package/dist/cron/index.js.map +1 -1
- package/dist/db/index.d.ts +12 -4
- package/dist/db/index.js +8 -6
- package/dist/db/index.js.map +1 -1
- package/dist/docker/index.d.ts +0 -10
- package/dist/docker/index.js +52 -57
- package/dist/docker/index.js.map +1 -1
- package/dist/doctor/index.js +16 -7
- package/dist/doctor/index.js.map +1 -1
- package/dist/embeddings/index.js +42 -8
- package/dist/embeddings/index.js.map +1 -1
- package/dist/evm/contracts.js +8 -1
- package/dist/evm/contracts.js.map +1 -1
- package/dist/evm/odos.js +1 -1
- package/dist/evm/odos.js.map +1 -1
- package/dist/evm/oneinch.js +7 -4
- package/dist/evm/oneinch.js.map +1 -1
- package/dist/evm/pancakeswap.js +1 -1
- package/dist/evm/pancakeswap.js.map +1 -1
- package/dist/evm/transfers.js +10 -5
- package/dist/evm/transfers.js.map +1 -1
- package/dist/evm/uniswap.js +1 -1
- package/dist/evm/uniswap.js.map +1 -1
- package/dist/evm/virtuals.js +7 -2
- package/dist/evm/virtuals.js.map +1 -1
- package/dist/exchanges/binance-futures/index.js +24 -21
- package/dist/exchanges/binance-futures/index.js.map +1 -1
- package/dist/exchanges/bybit/index.js +17 -14
- package/dist/exchanges/bybit/index.js.map +1 -1
- package/dist/exchanges/hyperliquid/index.js +28 -20
- package/dist/exchanges/hyperliquid/index.js.map +1 -1
- package/dist/exchanges/lighter/index.js +4 -4
- package/dist/exchanges/mexc/index.js +15 -15
- package/dist/exchanges/mexc/index.js.map +1 -1
- package/dist/exchanges/opinion/index.js +7 -7
- package/dist/exchanges/opinion/index.js.map +1 -1
- package/dist/exchanges/predictfun/index.js +1 -1
- package/dist/execution/index.js +93 -87
- package/dist/execution/index.js.map +1 -1
- package/dist/extensions/copilot-proxy/index.js +13 -7
- package/dist/extensions/copilot-proxy/index.js.map +1 -1
- package/dist/extensions/diagnostics-otel/index.js +8 -0
- package/dist/extensions/diagnostics-otel/index.js.map +1 -1
- package/dist/extensions/google-auth/index.js +4 -1
- package/dist/extensions/google-auth/index.js.map +1 -1
- package/dist/extensions/llm-task/index.js +28 -10
- package/dist/extensions/llm-task/index.js.map +1 -1
- package/dist/extensions/lobster/index.js +27 -8
- package/dist/extensions/lobster/index.js.map +1 -1
- package/dist/extensions/memory-lancedb/index.js +16 -6
- package/dist/extensions/memory-lancedb/index.js.map +1 -1
- package/dist/extensions/open-prose/index.js +1 -1
- package/dist/extensions/task-runner/index.js +12 -5
- package/dist/extensions/task-runner/index.js.map +1 -1
- package/dist/farcaster/client.js +7 -7
- package/dist/feeds/agentbets/index.d.ts +1 -1
- package/dist/feeds/betfair/index.js +12 -6
- package/dist/feeds/betfair/index.js.map +1 -1
- package/dist/feeds/crypto/index.js +38 -30
- package/dist/feeds/crypto/index.js.map +1 -1
- package/dist/feeds/drift/trading.js +4 -4
- package/dist/feeds/external/index.js +3 -0
- package/dist/feeds/external/index.js.map +1 -1
- package/dist/feeds/fred/index.js.map +1 -1
- package/dist/feeds/hedgehog/index.js +10 -2
- package/dist/feeds/hedgehog/index.js.map +1 -1
- package/dist/feeds/manifold/index.js +1 -1
- package/dist/feeds/metaculus/index.js +2 -2
- package/dist/feeds/opinion/index.js +2 -2
- package/dist/feeds/polymarket/index.js +7 -1
- package/dist/feeds/polymarket/index.js.map +1 -1
- package/dist/feeds/polymarket/whale-tracker.js.map +1 -1
- package/dist/feeds/predictfun/index.js +2 -2
- package/dist/feeds/smarkets/index.js +12 -6
- package/dist/feeds/smarkets/index.js.map +1 -1
- package/dist/gateway/feeds-routes.d.ts +8 -7
- package/dist/gateway/feeds-routes.js.map +1 -1
- package/dist/gateway/index.js +28 -6
- package/dist/gateway/index.js.map +1 -1
- package/dist/history/index.js +8 -4
- package/dist/history/index.js.map +1 -1
- package/dist/hooks/index.js +14 -5
- package/dist/hooks/index.js.map +1 -1
- package/dist/i18n/index.js +2 -1
- package/dist/i18n/index.js.map +1 -1
- package/dist/identity/erc8004.js +13 -3
- package/dist/identity/erc8004.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/infra/index.d.ts +1 -1
- package/dist/infra/index.js +39 -26
- package/dist/infra/index.js.map +1 -1
- package/dist/ledger/hooks.js +26 -18
- package/dist/ledger/hooks.js.map +1 -1
- package/dist/ledger/storage.js +23 -13
- package/dist/ledger/storage.js.map +1 -1
- package/dist/link-understanding/index.js +26 -2
- package/dist/link-understanding/index.js.map +1 -1
- package/dist/logging/index.js +31 -4
- package/dist/logging/index.js.map +1 -1
- package/dist/macos/index.d.ts +1 -1
- package/dist/macos/index.js +41 -36
- package/dist/macos/index.js.map +1 -1
- package/dist/markdown/index.js +25 -8
- package/dist/markdown/index.js.map +1 -1
- package/dist/market-index/index.js +8 -6
- package/dist/market-index/index.js.map +1 -1
- package/dist/mcp/index.js +67 -10
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.js +21 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/media/index.js +17 -15
- package/dist/media/index.js.map +1 -1
- package/dist/memory/context.js +17 -9
- package/dist/memory/context.js.map +1 -1
- package/dist/memory/index.js +6 -5
- package/dist/memory/index.js.map +1 -1
- package/dist/ml-pipeline/collector.js +14 -3
- package/dist/ml-pipeline/collector.js.map +1 -1
- package/dist/ml-pipeline/trainer.js +1 -1
- package/dist/ml-pipeline/trainer.js.map +1 -1
- package/dist/monitoring/health.js +15 -3
- package/dist/monitoring/health.js.map +1 -1
- package/dist/monitoring/metrics.js +2 -2
- package/dist/nodes/index.js +40 -25
- package/dist/nodes/index.js.map +1 -1
- package/dist/opportunity/combinatorial.js +4 -1
- package/dist/opportunity/combinatorial.js.map +1 -1
- package/dist/opportunity/correlation.js +2 -2
- package/dist/opportunity/executor.js +14 -5
- package/dist/opportunity/executor.js.map +1 -1
- package/dist/opportunity/risk.js +3 -1
- package/dist/opportunity/risk.js.map +1 -1
- package/dist/opportunity/scoring.js +3 -1
- package/dist/opportunity/scoring.js.map +1 -1
- package/dist/pairing/index.js +8 -4
- package/dist/pairing/index.js.map +1 -1
- package/dist/payments/x402/evm.js +4 -4
- package/dist/payments/x402/index.js +26 -7
- package/dist/payments/x402/index.js.map +1 -1
- package/dist/payments/x402/solana.js +3 -3
- package/dist/percolator/feed.js +1 -1
- package/dist/percolator/feed.js.map +1 -1
- package/dist/permissions/index.d.ts +2 -0
- package/dist/permissions/index.js +22 -12
- package/dist/permissions/index.js.map +1 -1
- package/dist/plugins/index.d.ts +3 -1
- package/dist/plugins/index.js +18 -6
- package/dist/plugins/index.js.map +1 -1
- package/dist/portfolio/index.js +16 -15
- package/dist/portfolio/index.js.map +1 -1
- package/dist/presence/index.js +17 -5
- package/dist/presence/index.js.map +1 -1
- package/dist/process/index.js +40 -14
- package/dist/process/index.js.map +1 -1
- package/dist/providers/discovery.js +34 -28
- package/dist/providers/discovery.js.map +1 -1
- package/dist/providers/health.js +7 -4
- package/dist/providers/health.js.map +1 -1
- package/dist/providers/index.js +36 -33
- package/dist/providers/index.js.map +1 -1
- package/dist/queue/index.js +1 -1
- package/dist/remote/index.d.ts +0 -5
- package/dist/remote/index.js +41 -9
- package/dist/remote/index.js.map +1 -1
- package/dist/risk/circuit-breaker.js +13 -5
- package/dist/risk/circuit-breaker.js.map +1 -1
- package/dist/risk/engine.js +2 -2
- package/dist/risk/volatility.js +1 -1
- package/dist/risk/volatility.js.map +1 -1
- package/dist/routing/index.js +5 -2
- package/dist/routing/index.js.map +1 -1
- package/dist/search/index.js +7 -5
- package/dist/search/index.js.map +1 -1
- package/dist/security/address-checker.js +40 -19
- package/dist/security/address-checker.js.map +1 -1
- package/dist/security/code-scanner.js +7 -5
- package/dist/security/code-scanner.js.map +1 -1
- package/dist/security/index.d.ts +3 -0
- package/dist/security/index.js +19 -7
- package/dist/security/index.js.map +1 -1
- package/dist/security/tx-validator.js +2 -2
- package/dist/security/tx-validator.js.map +1 -1
- package/dist/services/feature-engineering/rolling-window.d.ts +7 -0
- package/dist/services/feature-engineering/rolling-window.js +23 -0
- package/dist/services/feature-engineering/rolling-window.js.map +1 -1
- package/dist/services/feature-engineering/thresholds.js +2 -2
- package/dist/services/feature-engineering/thresholds.js.map +1 -1
- package/dist/services/tick-recorder/index.js +13 -1
- package/dist/services/tick-recorder/index.js.map +1 -1
- package/dist/services/tick-recorder/queries.js +11 -7
- package/dist/services/tick-recorder/queries.js.map +1 -1
- package/dist/services/tick-streamer/index.js +6 -2
- package/dist/services/tick-streamer/index.js.map +1 -1
- package/dist/session/index.d.ts +1 -1
- package/dist/session/index.js +31 -6
- package/dist/session/index.js.map +1 -1
- package/dist/sessions/index.js +76 -52
- package/dist/sessions/index.js.map +1 -1
- package/dist/signal-router/router.js +8 -1
- package/dist/signal-router/router.js.map +1 -1
- package/dist/skills/bundled/agentbets/index.js.map +1 -1
- package/dist/skills/bundled/auto-reply/SKILL.md +19 -16
- package/dist/skills/bundled/automation/SKILL.md +33 -215
- package/dist/skills/bundled/backtest/SKILL.md +2 -1
- package/dist/skills/bundled/credentials/SKILL.md +2 -1
- package/dist/skills/bundled/edge/SKILL.md +6 -3
- package/dist/skills/bundled/sandbox/SKILL.md +29 -240
- package/dist/skills/bundled/trading-kalshi/SKILL.md +65 -586
- package/dist/skills/bundled/usage/SKILL.md +8 -18
- package/dist/skills/bundled/webhooks/SKILL.md +31 -279
- package/dist/skills/bundled/whale-tracking/SKILL.md +24 -22
- package/dist/solana/copytrade.js +5 -5
- package/dist/solana/drift.js +2 -2
- package/dist/solana/drift.js.map +1 -1
- package/dist/solana/meteora-dbc.d.ts +2 -2
- package/dist/solana/pumpapi.js +4 -0
- package/dist/solana/pumpapi.js.map +1 -1
- package/dist/solana/raydium.js +46 -10
- package/dist/solana/raydium.js.map +1 -1
- package/dist/solana/swarm-copytrade.js +2 -2
- package/dist/solana/wallet.js +12 -3
- package/dist/solana/wallet.js.map +1 -1
- package/dist/strategies/crypto-hft/index.js +2 -0
- package/dist/strategies/crypto-hft/index.js.map +1 -1
- package/dist/strategies/crypto-hft/positions.js +11 -3
- package/dist/strategies/crypto-hft/positions.js.map +1 -1
- package/dist/strategies/crypto-hft/presets.js +2 -1
- package/dist/strategies/crypto-hft/presets.js.map +1 -1
- package/dist/strategies/crypto-hft/strategies.js +4 -3
- package/dist/strategies/crypto-hft/strategies.js.map +1 -1
- package/dist/strategies/hft-divergence/detector.js +5 -1
- package/dist/strategies/hft-divergence/detector.js.map +1 -1
- package/dist/strategies/hft-divergence/position-manager.js +13 -1
- package/dist/strategies/hft-divergence/position-manager.js.map +1 -1
- package/dist/strategies/hft-divergence/strategy.js +3 -1
- package/dist/strategies/hft-divergence/strategy.js.map +1 -1
- package/dist/streaming/index.js +21 -5
- package/dist/streaming/index.js.map +1 -1
- package/dist/tailscale/index.d.ts +0 -4
- package/dist/tailscale/index.js +5 -8
- package/dist/tailscale/index.js.map +1 -1
- package/dist/telemetry/index.d.ts +1 -0
- package/dist/telemetry/index.js +49 -6
- package/dist/telemetry/index.js.map +1 -1
- package/dist/tools/canvas.js +32 -8
- package/dist/tools/canvas.js.map +1 -1
- package/dist/tools/exec.js +32 -2
- package/dist/tools/exec.js.map +1 -1
- package/dist/tools/image.js +19 -0
- package/dist/tools/image.js.map +1 -1
- package/dist/tools/sql.js +4 -1
- package/dist/tools/sql.js.map +1 -1
- package/dist/tools/transcription.js +13 -0
- package/dist/tools/transcription.js.map +1 -1
- package/dist/tools/web-fetch.js +14 -0
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-search.js +14 -0
- package/dist/tools/web-search.js.map +1 -1
- package/dist/trading/backtest.js +3 -3
- package/dist/trading/backtest.js.map +1 -1
- package/dist/trading/bots/index.d.ts +9 -1
- package/dist/trading/bots/index.js +4 -0
- package/dist/trading/bots/index.js.map +1 -1
- package/dist/trading/devtools.js +1 -1
- package/dist/trading/devtools.js.map +1 -1
- package/dist/trading/futures/index.js +5 -5
- package/dist/trading/index.js +1 -1
- package/dist/trading/index.js.map +1 -1
- package/dist/trading/logger.js +27 -20
- package/dist/trading/logger.js.map +1 -1
- package/dist/trading/safety.d.ts +2 -0
- package/dist/trading/safety.js +12 -2
- package/dist/trading/safety.js.map +1 -1
- package/dist/trading/stream.js +1 -1
- package/dist/trading/stream.js.map +1 -1
- package/dist/trading/tracking.d.ts +1 -1
- package/dist/trading/tracking.js.map +1 -1
- package/dist/utils/config.js +4 -3
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/http.js +15 -1
- package/dist/utils/http.js.map +1 -1
- package/dist/utils/kelly.js +14 -5
- package/dist/utils/kelly.js.map +1 -1
- package/dist/utils/rate-limiter.js +25 -10
- package/dist/utils/rate-limiter.js.map +1 -1
- package/dist/voice/index.d.ts +5 -1
- package/dist/voice/index.js +65 -25
- package/dist/voice/index.js.map +1 -1
- package/dist/weather/edge.js +4 -2
- package/dist/weather/edge.js.map +1 -1
- package/dist/weather/markets.d.ts +1 -0
- package/dist/weather/markets.js +17 -8
- package/dist/weather/markets.js.map +1 -1
- package/dist/weather/noaa.d.ts +2 -0
- package/dist/weather/noaa.js +22 -5
- package/dist/weather/noaa.js.map +1 -1
- package/dist/web/index.d.ts +3 -0
- package/dist/web/index.js +60 -12
- package/dist/web/index.js.map +1 -1
- package/dist/wizard/index.js +13 -14
- package/dist/wizard/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,629 +1,108 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: trading-kalshi
|
|
3
|
-
description: "
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- KALSHI_EMAIL
|
|
8
|
-
- KALSHI_PASSWORD
|
|
3
|
+
description: "Kalshi trading - search markets, place orders, stream prices, advanced order types"
|
|
4
|
+
commands:
|
|
5
|
+
- /kalshi
|
|
6
|
+
- /trading-kalshi
|
|
9
7
|
---
|
|
10
8
|
|
|
11
|
-
# Kalshi Trading
|
|
9
|
+
# Kalshi Trading
|
|
12
10
|
|
|
13
|
-
Full access to Kalshi
|
|
14
|
-
|
|
15
|
-
**Docs**: https://docs.kalshi.com/welcome
|
|
16
|
-
**Discord**: #dev channel for support
|
|
11
|
+
Full access to Kalshi prediction markets: search, trade, stream real-time data, and use advanced order types (TWAP, bracket, trigger).
|
|
17
12
|
|
|
18
13
|
## Required Environment Variables
|
|
19
14
|
|
|
20
15
|
```bash
|
|
21
|
-
|
|
22
|
-
|
|
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"
|
|
16
|
+
KALSHI_API_KEY_ID=your_api_key_id
|
|
17
|
+
KALSHI_PRIVATE_KEY=your_private_key_pem_contents
|
|
18
|
+
# OR
|
|
19
|
+
KALSHI_PRIVATE_KEY_PATH=/path/to/private_key.pem
|
|
42
20
|
```
|
|
43
21
|
|
|
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
|
|
22
|
+
Authentication uses RSA key-pair signing (not email/password). Generate an API key from the Kalshi dashboard.
|
|
56
23
|
|
|
57
|
-
|
|
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
|
-
```
|
|
24
|
+
Optional:
|
|
137
25
|
|
|
138
|
-
|
|
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")
|
|
26
|
+
```bash
|
|
27
|
+
DRY_RUN=true # Simulate trades without executing
|
|
261
28
|
```
|
|
262
29
|
|
|
263
|
-
|
|
30
|
+
## Commands
|
|
264
31
|
|
|
265
|
-
|
|
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()
|
|
32
|
+
### Market Data
|
|
274
33
|
|
|
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
34
|
```
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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()
|
|
35
|
+
/kalshi search <query> - Search markets
|
|
36
|
+
/kalshi market <ticker> - Market details
|
|
37
|
+
/kalshi book <ticker> - View orderbook (REST snapshot)
|
|
38
|
+
/kalshi events [query] - Browse events
|
|
39
|
+
/kalshi event <event-ticker> - Event details + markets
|
|
298
40
|
```
|
|
299
41
|
|
|
300
|
-
###
|
|
42
|
+
### Trading
|
|
301
43
|
|
|
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
44
|
```
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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"])
|
|
45
|
+
/kalshi buy <ticker> <contracts> <price> - Buy YES contracts
|
|
46
|
+
/kalshi sell <ticker> <contracts> <price> - Sell YES contracts
|
|
47
|
+
/kalshi orders - View open orders
|
|
48
|
+
/kalshi cancel <order-id> - Cancel an order
|
|
49
|
+
/kalshi cancel all - Cancel all orders
|
|
50
|
+
/kalshi balance - Account balance
|
|
334
51
|
```
|
|
335
52
|
|
|
336
|
-
###
|
|
53
|
+
### Advanced Orders
|
|
337
54
|
|
|
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
55
|
```
|
|
56
|
+
/kalshi twap <buy|sell> <ticker> <total> <price> [slices] [interval-sec]
|
|
57
|
+
/kalshi twap status - Active TWAP progress
|
|
58
|
+
/kalshi twap cancel <id> - Cancel TWAP
|
|
369
59
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
-
}
|
|
60
|
+
/kalshi bracket <ticker> <size> <tp> <sl> - Set take-profit / stop-loss
|
|
61
|
+
/kalshi bracket status - Active brackets
|
|
62
|
+
/kalshi bracket cancel <id> - Cancel bracket
|
|
387
63
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
64
|
+
/kalshi trigger buy <ticker> <size> <price> [limit] - Buy when price drops
|
|
65
|
+
/kalshi trigger sell <ticker> <size> <price> [limit] - Sell when price rises
|
|
66
|
+
/kalshi trigger list - Active triggers
|
|
67
|
+
/kalshi trigger cancel <id> - Cancel trigger
|
|
391
68
|
```
|
|
392
69
|
|
|
393
|
-
###
|
|
70
|
+
### Real-Time Streaming (WebSocket)
|
|
394
71
|
|
|
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
72
|
```
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
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']}¢")
|
|
73
|
+
/kalshi stream <ticker> [channels] - Start streaming (ticker,trade,orderbook)
|
|
74
|
+
/kalshi stream-fills - Stream your order fills
|
|
75
|
+
/kalshi streams - List active streams
|
|
76
|
+
/kalshi unstream <ticker> - Stop streaming a market
|
|
77
|
+
/kalshi unstream-fills - Stop fill notifications
|
|
78
|
+
/kalshi realtime-book <ticker> - Get real-time orderbook from stream
|
|
439
79
|
```
|
|
440
80
|
|
|
441
|
-
###
|
|
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", [])
|
|
81
|
+
### Cross-Platform
|
|
451
82
|
|
|
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
83
|
```
|
|
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')}")
|
|
84
|
+
/kalshi route <ticker> <buy|sell> <size> - Compare prices across platforms
|
|
85
|
+
/kalshi circuit - Circuit breaker status
|
|
471
86
|
```
|
|
472
87
|
|
|
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
|
|
88
|
+
## Examples
|
|
482
89
|
|
|
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
90
|
```
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
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)
|
|
91
|
+
/kalshi search bitcoin
|
|
92
|
+
/kalshi market KXBTC-24JAN01
|
|
93
|
+
/kalshi book KXBTC-24JAN01
|
|
94
|
+
/kalshi buy KXBTC-24JAN01 10 0.65
|
|
95
|
+
/kalshi sell KXBTC-24JAN01 5 0.70
|
|
96
|
+
/kalshi stream KXBTC-24JAN01 ticker,trade
|
|
97
|
+
/kalshi twap buy KXBTC-24JAN01 50 0.60 10 30
|
|
98
|
+
/kalshi bracket KXBTC-24JAN01 10 0.80 0.40
|
|
99
|
+
/kalshi trigger buy KXBTC-24JAN01 10 45
|
|
602
100
|
```
|
|
603
101
|
|
|
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
|
|
102
|
+
## Notes
|
|
629
103
|
|
|
104
|
+
- Prices are in decimal format for commands (0.65 = 65 cents)
|
|
105
|
+
- Trigger prices are in cents (45 = 45 cents)
|
|
106
|
+
- Contracts pay $1 if correct; cost is the price
|
|
107
|
+
- Circuit breaker integration blocks trades when risk limits are hit
|
|
108
|
+
- Trigger orders poll every 5 seconds
|