Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [0.3.0] - 2026-02-28

### Added

Expand Down Expand Up @@ -86,6 +86,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New `UserOrders` WebSocket channel for real-time order update notifications
(`UserOrderData`, `UserOrderEventType`). Requires authentication, supports
optional `market_tickers` filtering.
- `QuoteExecuted` variant on `CommunicationData` enum for WebSocket quote
execution notifications (`QuoteExecutedData` with `quote_id`, `rfq_id`,
`order_id`, `client_order_id`, `executed_ts`). Previously, quote execution
events on the `communications` channel were silently dropped.
- `subaccount` filter on `ListRfqsParams` for per-subaccount RFQ queries.
- `subaccount` filter on `GetOrderGroupsParams` for per-subaccount order group
queries. New `get_order_group_for_subaccount()` method on `KalshiClient`.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "kalshi-trade-rs"
version = "0.2.0"
version = "0.3.0"
edition = "2024"
authors = ["pbeets"]
description = "Rust client for the Kalshi trading API and WebSocket streams"
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ An unofficial Rust client library for the [Kalshi](https://kalshi.com) predictio

## Key Features

- **REST Client**: Full coverage of 84 Kalshi API endpoints including portfolio management, order operations, market data, exchange status, historical data, and RFQ (Request for Quote) communications
- **REST Client**: Full coverage of 86 Kalshi API endpoints including portfolio management, order operations, market data, exchange status, historical data, and RFQ (Request for Quote) communications
- **WebSocket Streaming**: 10 real-time channels — ticker, trade, orderbook, fill, order updates, position, RFQ/quote, order groups, market lifecycle, and multivariate
- **Batch Operations**: Rate-limited `BatchManager` with automatic chunking, retry, and per-order subaccount support
- **Orderbook Aggregation**: Live orderbook state from WebSocket delta streams with gap detection
Expand All @@ -22,7 +22,7 @@ Add to your `Cargo.toml`:

```toml
[dependencies]
kalshi-trade-rs = "0.2.0"
kalshi-trade-rs = "0.3.0"
```

Configure environment variables:
Expand Down Expand Up @@ -122,7 +122,7 @@ Stream RFQ events via WebSocket:

```rust
handle.subscribe(Channel::Communications, &[]).await?;
// Receive: RfqCreated, RfqDeleted, QuoteCreated, QuoteAccepted
// Receive: RfqCreated, RfqDeleted, QuoteCreated, QuoteAccepted, QuoteExecuted
```

See [`examples/rfq_verify.rs`](examples/rfq_verify.rs) for a complete verification example.
Expand All @@ -144,7 +144,7 @@ let client = KalshiStreamClient::connect_with_strategy(&config, ConnectStrategy:

## Examples

See the [`examples/`](examples/) directory for 24 working examples:
See the [`examples/`](examples/) directory for 25 working examples:

### REST API

Expand Down Expand Up @@ -176,6 +176,7 @@ See the [`examples/`](examples/) directory for 24 working examples:
| `stream_reconnect` | Reconnection with resubscription |
| `stream_firehose` | High-volume streaming pattern |
| `stream_lifecycle` | Market lifecycle events |
| `stream_user_orders` | Real-time order update notifications |
| `multi_channel_subscribe` | Multi-channel subscription management |
| `orderbook_aggregator` | Live orderbook state from delta streams |
| `test_auth` | Basic authentication verification |
Expand Down
7 changes: 7 additions & 0 deletions examples/rfq_verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
//! - `CommunicationData::RfqDeleted` - RFQ cancelled
//! - `CommunicationData::QuoteCreated` - Quote submitted
//! - `CommunicationData::QuoteAccepted` - Quote accepted (trade executing)
//! - `CommunicationData::QuoteExecuted` - Quote fully executed

use std::time::Duration;

Expand Down Expand Up @@ -227,6 +228,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
quote.quote_id, quote.accepted_side
);
}
CommunicationData::QuoteExecuted(quote) => {
println!(
" [QUOTE EXECUTED] {} for RFQ {}",
quote.quote_id, quote.rfq_id
);
}
}
}
StreamMessage::Closed { reason } => {
Expand Down
2 changes: 1 addition & 1 deletion src/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Complete reference for all Kalshi REST API endpoints supported by this library.

| Status | Method | Endpoint | Rust Function | Notes |
|--------|--------|----------|---------------|-------|
| ✅ | POST | `/portfolio/order_groups` | `create_order_group()` | |
| ✅ | POST | `/portfolio/order_groups/create` | `create_order_group()` | |
| ✅ | GET | `/portfolio/order_groups/{id}` | `get_order_group()` | |
| ✅ | GET | `/portfolio/order_groups` | `list_order_groups()` | |
| ✅ | DELETE | `/portfolio/order_groups/{id}` | `delete_order_group()` | Cancels all orders in group |
Expand Down
1 change: 0 additions & 1 deletion src/models/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,6 @@ impl GetMultivariateEventsParams {
self
}

/// Set the pagination cursor for fetching subsequent pages.
#[must_use]
pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
self.cursor = Some(cursor.into());
Expand Down
2 changes: 0 additions & 2 deletions src/models/fcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ impl GetFcmOrdersParams {
}
}

/// Set the pagination cursor.
#[must_use]
pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
self.cursor = Some(cursor.into());
Expand Down Expand Up @@ -275,7 +274,6 @@ impl GetFcmPositionsParams {
Ok(self)
}

/// Set the pagination cursor.
#[must_use]
pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
self.cursor = Some(cursor.into());
Expand Down
1 change: 0 additions & 1 deletion src/models/incentive_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ impl GetIncentiveProgramsParams {
self
}

/// Set the pagination cursor.
#[must_use]
pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
self.cursor = Some(cursor.into());
Expand Down
1 change: 0 additions & 1 deletion src/models/milestone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ impl GetMilestonesParams {
self
}

/// Set the pagination cursor.
#[must_use]
pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
self.cursor = Some(cursor.into());
Expand Down
7 changes: 7 additions & 0 deletions src/models/series.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,21 +106,28 @@ pub struct Series {
#[serde(default)]
pub status: Option<String>,
/// Tags associated with this series.
#[serde(default)]
pub tags: Vec<String>,
/// Settlement sources for this series.
#[serde(default)]
pub settlement_sources: Vec<super::event::SettlementSource>,
/// URL to the contract for this series.
#[serde(default)]
pub contract_url: String,
/// URL to the contract terms for this series.
#[serde(default)]
pub contract_terms_url: String,
/// Product metadata for this series.
#[serde(default)]
pub product_metadata: Option<serde_json::Value>,
/// Fee type for this series.
#[serde(default)]
pub fee_type: String,
/// Fee multiplier for this series.
#[serde(default)]
pub fee_multiplier: f64,
/// Additional trading prohibitions.
#[serde(default)]
pub additional_prohibitions: Vec<String>,
/// Total contracts traded across all events in this series.
/// Only present when `include_volume=true` in the request.
Expand Down
1 change: 0 additions & 1 deletion src/models/structured_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ impl GetStructuredTargetsParams {
self
}

/// Set the pagination cursor.
#[must_use]
pub fn cursor(mut self, cursor: impl Into<String>) -> Self {
self.cursor = Some(cursor.into());
Expand Down
6 changes: 3 additions & 3 deletions src/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@ pub use command::{CommunicationsSharding, SubscribeOptions, SubscribeResult, Uns
pub use message::{
Action, CommunicationData, FillData, MarketLifecycleData, MarketLifecycleEventType,
MarketPositionData, MultivariateLookupData, MveLeg, OrderGroupEventType, OrderGroupUpdateData,
OrderbookDeltaData, OrderbookSnapshotData, PriceLevel, QuoteAcceptedData, QuoteData, RfqData,
RfqDeletedData, Side, StreamMessage, StreamUpdate, TickerData, TradeData, UserOrderData,
UserOrderEventType,
OrderbookDeltaData, OrderbookSnapshotData, PriceLevel, QuoteAcceptedData, QuoteData,
QuoteExecutedData, RfqData, RfqDeletedData, Side, StreamMessage, StreamUpdate, TickerData,
TradeData, UserOrderData, UserOrderEventType,
};

/// Connection strategy for the WebSocket client.
Expand Down
7 changes: 0 additions & 7 deletions src/ws/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,4 @@ mod tests {
assert_eq!(sharding.shard_factor, Some(4));
assert_eq!(sharding.shard_key, Some(2));
}

#[test]
fn test_communications_sharding_default() {
let sharding = CommunicationsSharding::default();
assert_eq!(sharding.shard_factor, None);
assert_eq!(sharding.shard_key, None);
}
}
Loading