Skip to content

Commit 8c5aa98

Browse files
authored
Merge pull request #69 from TexasCoding/v3.5.7_examples_documentation
v3.5.7: Fix Decimal JSON serialization in order placement
2 parents 33f8ab1 + 24a0613 commit 8c5aa98

File tree

22 files changed

+406
-47
lines changed

22 files changed

+406
-47
lines changed

.secrets.baseline

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@
133133
"filename": "CHANGELOG.md",
134134
"hashed_secret": "89a6cfe2a229151e8055abee107d45ed087bbb4f",
135135
"is_verified": false,
136-
"line_number": 2183
136+
"line_number": 2198
137137
}
138138
],
139139
"README.md": [
@@ -325,5 +325,5 @@
325325
}
326326
]
327327
},
328-
"generated_at": "2025-09-02T01:57:55Z"
328+
"generated_at": "2025-09-02T03:30:00Z"
329329
}

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- Migration guides will be provided for all breaking changes
1515
- Semantic versioning (MAJOR.MINOR.PATCH) is strictly followed
1616

17+
## [3.5.7] - 2025-02-02
18+
19+
### 🐛 Fixed
20+
21+
**Order Placement**:
22+
- **Decimal Serialization**: Fixed JSON serialization error when placing orders with Decimal prices
23+
- **API Compatibility**: Ensured all price values are properly converted to float for API requests
24+
- **Price Precision**: Maintained internal Decimal precision while ensuring JSON compatibility
25+
26+
### 📚 Documentation
27+
28+
**Examples**:
29+
- **Quick Start Example**: Fixed and verified the quick_start.py example in Documentation_Examples
30+
- **Order Placement**: Ensured all documentation examples work with the fixed serialization
31+
1732
## [3.5.6] - 2025-02-02
1833

1934
### 🐛 Fixed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ A **high-performance async Python SDK** for the [ProjectX Trading Platform](http
2828

2929
This Python SDK acts as a bridge between your trading strategies and the ProjectX platform, handling all the complex API interactions, data processing, and real-time connectivity.
3030

31-
## 🚀 v3.5.6 - Event System & Bracket Order Enhancements
31+
## 🚀 v3.5.7 - Order Placement Serialization Fix
3232

33-
**Latest Version**: v3.5.6 - Critical fixes for multi-instrument event handling and automatic price alignment for bracket orders, ensuring robust real-time trading operations.
33+
**Latest Version**: v3.5.7 - Fixed JSON serialization error when placing orders with Decimal prices, ensuring all price values are properly converted for API requests while maintaining internal precision.
3434

3535
**Key Improvements**:
3636
- 🔄 **Event Forwarding**: Fixed multi-instrument event propagation with proper bus forwarding
@@ -39,7 +39,7 @@ This Python SDK acts as a bridge between your trading strategies and the Project
3939
- 🛡️ **Improved Reliability**: 30+ test fixes ensuring production stability
4040
-**Real-time Fixes**: Corrected bar data access in streaming examples
4141

42-
See [CHANGELOG.md](CHANGELOG.md) for complete v3.5.6 fixes and previous version features.
42+
See [CHANGELOG.md](CHANGELOG.md) for complete v3.5.7 fixes and previous version features.
4343

4444
### 📦 Production Stability Guarantee
4545

docs/changelog.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,36 @@ All notable changes to the ProjectX Python SDK will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [3.5.7] - 2025-02-02
9+
10+
### 🐛 Fixed
11+
12+
**Order Placement**:
13+
- **Decimal Serialization**: Fixed JSON serialization error when placing orders with Decimal prices
14+
- **API Compatibility**: Ensured all price values are properly converted to float for API requests
15+
- **Price Precision**: Maintained internal Decimal precision while ensuring JSON compatibility
16+
17+
### 📚 Documentation
18+
19+
**Examples**:
20+
- **Quick Start Example**: Fixed and verified the quick_start.py example in Documentation_Examples
21+
- **Order Placement**: Ensured all documentation examples work with the fixed serialization
22+
23+
## [3.5.6] - 2025-02-02
24+
25+
### 🐛 Fixed
26+
27+
**Multi-Instrument Event System**:
28+
- **Event Forwarding**: Implemented event forwarding from instrument-specific EventBuses to suite-level EventBus
29+
- **InstrumentContext Methods**: Added `on()`, `once()`, `off()`, and `wait_for()` methods that delegate to event_bus
30+
- **Event Propagation**: Fixed broken event system that prevented `mnq_context.wait_for(EventType.NEW_BAR)` from working
31+
- **Multi-Instrument Support**: Events now properly flow from individual instruments to the suite level
32+
33+
**Bracket Order Improvements**:
34+
- **Automatic Price Alignment**: Changed validation from failing to auto-aligning prices to tick size
35+
- **Smart Adjustment**: Orders with misaligned prices are now automatically corrected instead of rejected
36+
- **Better UX**: Improved user experience by handling price alignment transparently
37+
838
## [3.4.0] - 2025-08-28
939

1040
### 🚀 New Feature: ETH vs RTH Trading Sessions (Experimental)

docs/examples/advanced.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Advanced Trading Examples
22

3-
This page demonstrates sophisticated trading strategies and advanced features of the ProjectX Python SDK v3.5.6. These examples include order placement with automatic price alignment, risk management, and complex event-driven trading systems with proper multi-instrument event forwarding.
3+
This page demonstrates sophisticated trading strategies and advanced features of the ProjectX Python SDK v3.5.7. These examples include order placement with automatic price alignment, risk management, and complex event-driven trading systems with proper multi-instrument event forwarding.
44

55
!!! warning "Live Trading Alert"
66
**These examples place REAL ORDERS on the market!**

docs/examples/realtime.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Real-time Data Processing Examples
22

3-
This page demonstrates how to work with real-time market data streams using the ProjectX Python SDK v3.5.6. Learn to handle WebSocket data, process multiple timeframes, and build real-time trading systems with the enhanced event system.
3+
This page demonstrates how to work with real-time market data streams using the ProjectX Python SDK v3.5.7. Learn to handle WebSocket data, process multiple timeframes, and build real-time trading systems with the enhanced event system.
44

55
## Prerequisites
66

docs/getting-started/quickstart.md

Lines changed: 80 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,32 @@
11
# Quick Start
22

3-
This guide will help you get started with the ProjectX Python SDK.
3+
This guide will help you get started with the ProjectX Python SDK. Some examples will place live trades and orders. Please use with caution!!
44

55
## Basic Setup
66

77
### Single Instrument (Traditional)
88

99
```python
1010
import asyncio
11+
1112
from project_x_py import TradingSuite
1213

14+
1315
async def main():
1416
# Create a trading suite for single instrument
1517
suite = await TradingSuite.create(
1618
instruments=["MNQ"], # List notation (recommended)
1719
timeframes=["1min", "5min"],
1820
features=["orderbook"], # Optional features
19-
initial_days=5 # Historical data to load
21+
initial_days=5, # Historical data to load
2022
)
2123

2224
# Access the instrument context
2325
mnq = suite["MNQ"]
2426

27+
if suite.client.account_info is None:
28+
raise Exception("Account info is None")
29+
2530
# Everything is now connected and ready
2631
print(f"Connected to: {suite.client.account_info.name}")
2732

@@ -32,19 +37,25 @@ async def main():
3237
# Clean shutdown
3338
await suite.disconnect()
3439

40+
3541
# Run the async function
3642
asyncio.run(main())
3743
```
3844

3945
### Multi-Instrument Setup (v3.5.0)
4046

4147
```python
48+
import asyncio
49+
50+
from project_x_py import TradingSuite
51+
52+
4253
async def multi_instrument_setup():
4354
# Create suite for multiple instruments
4455
suite = await TradingSuite.create(
4556
instruments=["MNQ", "ES", "MGC"], # Multiple futures
4657
timeframes=["1min", "5min"],
47-
features=["orderbook", "risk_manager"]
58+
features=["orderbook", "risk_manager"],
4859
)
4960

5061
print(f"Managing {len(suite)} instruments: {list(suite.keys())}")
@@ -56,6 +67,7 @@ async def multi_instrument_setup():
5667

5768
await suite.disconnect()
5869

70+
5971
asyncio.run(multi_instrument_setup())
6072
```
6173

@@ -64,6 +76,11 @@ asyncio.run(multi_instrument_setup())
6476
### Single Instrument Trading
6577

6678
```python
79+
import asyncio
80+
81+
from project_x_py import TradingSuite
82+
83+
6784
async def trading_example():
6885
suite = await TradingSuite.create(["MNQ"]) # List notation
6986
mnq = suite["MNQ"] # Get instrument context
@@ -72,31 +89,38 @@ async def trading_example():
7289
order = await mnq.orders.place_market_order(
7390
contract_id=mnq.instrument_info.id,
7491
side=0, # 0=Buy, 1=Sell
75-
size=1
92+
size=1,
7693
)
77-
print(f"Order placed: {order.order_id}")
94+
print(f"Order placed: {order.orderId}")
7895

7996
# Check position
8097
position = await mnq.positions.get_position("MNQ")
8198
if position:
82-
print(f"Position: {position.net_position} @ ${position.average_price:,.2f}")
99+
print(f"Position: {position.size} @ ${position.averagePrice:,.2f}")
83100

84101
# Place a stop loss
85-
if position and position.net_position > 0:
102+
if position and position.size > 0:
86103
stop_order = await mnq.orders.place_stop_order(
87104
contract_id=mnq.instrument_info.id,
88105
side=1, # Sell
89-
size=position.net_position,
90-
stop_price=position.average_price - 20 # 20 points below entry
106+
size=position.size,
107+
stop_price=position.averagePrice - 20, # 20 points below entry
91108
)
92-
print(f"Stop loss placed: {stop_order.order_id}")
109+
print(f"Stop loss placed: {stop_order.orderId}")
93110

94111
await suite.disconnect()
112+
113+
asyncio.run(trading_example())
95114
```
96115

97116
### Multi-Instrument Pairs Trading
98117

99118
```python
119+
import asyncio
120+
121+
from project_x_py import TradingSuite
122+
123+
100124
async def pairs_trading_example():
101125
suite = await TradingSuite.create(["ES", "MNQ"]) # S&P 500 vs NASDAQ
102126

@@ -107,6 +131,9 @@ async def pairs_trading_example():
107131
es_price = await es_context.data.get_current_price()
108132
mnq_price = await mnq_context.data.get_current_price()
109133

134+
if es_price is None or mnq_price is None:
135+
raise Exception("No price data available")
136+
110137
# Calculate spread (normalize by contract values)
111138
spread = (es_price * 50) - (mnq_price * 20)
112139
print(f"ES/MNQ Spread: ${spread:.2f}")
@@ -115,42 +142,54 @@ async def pairs_trading_example():
115142
if spread > 500: # ES expensive relative to MNQ
116143
await es_context.orders.place_market_order(
117144
contract_id=es_context.instrument_info.id,
118-
side=1, size=1 # Sell ES
145+
side=1,
146+
size=1, # Sell ES
119147
)
120148
await mnq_context.orders.place_market_order(
121149
contract_id=mnq_context.instrument_info.id,
122-
side=0, size=1 # Buy MNQ
150+
side=0,
151+
size=1, # Buy MNQ
123152
)
124153
print("Executed pairs trade: Short ES, Long MNQ")
125154

126155
await suite.disconnect()
156+
157+
158+
asyncio.run(pairs_trading_example())
127159
```
128160

129161
## Real-time Data Streaming
130162

131163
### Single Instrument Streaming
132164

133165
```python
134-
from project_x_py import EventType
166+
import asyncio
167+
168+
from project_x_py import EventType, TradingSuite
169+
from project_x_py.event_bus import Event
170+
135171

136172
async def stream_data():
137-
suite = await TradingSuite.create(
138-
["MNQ"],
139-
timeframes=["1min", "5min"]
140-
)
173+
suite = await TradingSuite.create(["MNQ"], timeframes=["15sec", "1min"])
141174

142175
mnq = suite["MNQ"]
143176

144177
# Register event handlers
145-
async def on_new_bar(event):
178+
async def on_new_bar(event: Event):
146179
data = event.data
147-
timeframe = data.get('timeframe')
148-
bar = data.get('data')
180+
timeframe = data.get("timeframe")
181+
bar = data.get("data")
149182
if bar:
150-
print(f"MNQ New {timeframe} bar: ${bar['close']:,.2f} Vol: {bar['volume']:,}")
183+
print(
184+
f"MNQ New {timeframe} bar: ${bar['close']:,.2f} Vol: {bar['volume']:,}"
185+
)
151186

152-
async def on_quote(event):
187+
async def on_quote(event: Event):
153188
quote = event.data
189+
190+
if quote["bid"] is None or quote["ask"] is None:
191+
return
192+
154193
print(f"MNQ Quote: Bid ${quote['bid']:,.2f} Ask ${quote['ask']:,.2f}")
155194

156195
# Subscribe to events for MNQ
@@ -161,25 +200,36 @@ async def stream_data():
161200
await asyncio.sleep(30)
162201

163202
await suite.disconnect()
203+
204+
205+
asyncio.run(stream_data())
164206
```
165207

166208
### Multi-Instrument Streaming
167209

168210
```python
211+
import asyncio
212+
213+
from project_x_py import EventType, TradingSuite
214+
from project_x_py.event_bus import Event
215+
216+
169217
async def multi_stream_data():
170218
suite = await TradingSuite.create(
171219
["MNQ", "ES", "MGC"],
172-
timeframes=["1min", "5min"]
220+
timeframes=["15sec", "1min"],
173221
)
174222

175223
# Register handlers for each instrument
176224
for symbol, context in suite.items():
225+
177226
async def make_handler(sym):
178-
async def on_new_bar(event):
227+
async def on_new_bar(event: Event):
179228
data = event.data
180-
if data.get('timeframe') == '5min':
181-
bar = data.get('data')
182-
print(f"{sym} 5min: ${bar['close']:,.2f}")
229+
if data.get("timeframe") == "1min":
230+
bar = data.get("data")
231+
print(f"{sym} 1min: ${bar['close']:,.2f}")
232+
183233
return on_new_bar
184234

185235
handler = await make_handler(symbol)
@@ -188,6 +238,9 @@ async def multi_stream_data():
188238
# Stream all instruments simultaneously
189239
await asyncio.sleep(30)
190240
await suite.disconnect()
241+
242+
243+
asyncio.run(multi_stream_data())
191244
```
192245

193246
## Next Steps

docs/guide/realtime.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Real-time Data Guide
22

3-
This guide covers comprehensive real-time data streaming using ProjectX Python SDK v3.5.6+. All real-time operations are fully asynchronous and provide high-performance WebSocket connectivity with automatic reconnection, memory management, and enhanced event forwarding for multi-instrument support.
3+
This guide covers comprehensive real-time data streaming using ProjectX Python SDK v3.5.7+. All real-time operations are fully asynchronous and provide high-performance WebSocket connectivity with automatic reconnection, memory management, and enhanced event forwarding for multi-instrument support.
44

55
## Overview
66

0 commit comments

Comments
 (0)