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
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Old implementations are removed when improved
- Clean, modern code architecture is prioritized

## [2.0.8] - 2025-08-03

### Added
- **🚀 Enhanced Factory Functions**: Dramatically simplified trading suite setup
- `create_initialized_trading_suite()`: One-line setup with everything connected and ready
- Enhanced `create_trading_suite()` with auto-initialization options:
- `auto_connect`: Automatically connect realtime client and subscribe to user updates
- `auto_subscribe`: Automatically subscribe to market data and start feeds
- `initial_days`: Configurable historical data loading (default: 5)
- Reduces boilerplate code by ~95% for most use cases
- Still allows full manual control when needed

### Examples
- **12_simplified_strategy.py**: Demonstrates the new simplified setup approach
- **13_factory_comparison.py**: Shows the difference between old manual setup and new auto-initialization

### Improved
- **📖 Documentation**: Updated README with comprehensive factory function documentation
- **🎯 Developer Experience**: Trading strategies can now focus on logic instead of setup boilerplate
- **🔄 Flexibility**: Three levels of initialization control:
1. `create_initialized_trading_suite()` - Everything automatic
2. `create_trading_suite(..., auto_connect=True, auto_subscribe=True)` - Configurable automation
3. `create_trading_suite(..., auto_connect=False, auto_subscribe=False)` - Full manual control

### Technical Details
- Factory functions now handle all initialization steps:
- WebSocket connection and user update subscription
- Historical data loading
- Instrument search and contract resolution
- Market data subscription
- Real-time feed initialization
- OrderBook initialization (if enabled)
- All initialization is properly sequenced to avoid race conditions
- Error handling ensures clear feedback if initialization fails

## [2.0.7] - 2025-08-03

### Added
Expand Down
160 changes: 146 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,37 +128,117 @@ if __name__ == "__main__":
asyncio.run(main())
```

### Real-time Trading Suite
### Trading Suite (NEW in v2.0.8)

The easiest way to get started with a complete trading setup:

```python
import asyncio
from project_x_py import ProjectX, create_trading_suite

async def on_tick(tick_data):
print(f"Price: ${tick_data['price']}")
from project_x_py import ProjectX, create_initialized_trading_suite

async def main():
async with ProjectX.from_env() as client:
await client.authenticate()

# Create complete trading suite
suite = await create_trading_suite(
# One line creates and initializes everything!
suite = await create_initialized_trading_suite(
instrument="MNQ",
project_x=client,
timeframes=["1min", "5min", "15min"]
timeframes=["5min", "15min", "1hr"],
initial_days=5
)

# Connect real-time services
await suite["realtime_client"].connect()
await suite["data_manager"].initialize(initial_days=5)
# Everything is ready to use:
# ✅ Realtime client connected
# ✅ Historical data loaded
# ✅ Market data streaming
# ✅ All components initialized

# Subscribe to real-time data
# Access components
data = await suite["data_manager"].get_data("5min")
orderbook = suite["orderbook"]
order_manager = suite["order_manager"]
position_manager = suite["position_manager"]

# Your trading logic here...

if __name__ == "__main__":
asyncio.run(main())
```

### Factory Functions (v2.0.8+)

The SDK provides powerful factory functions to simplify setup:

#### create_initialized_trading_suite
The simplest way to get a fully initialized trading environment:

```python
suite = await create_initialized_trading_suite(
instrument="MNQ",
project_x=client,
timeframes=["5min", "15min", "1hr"], # Optional, defaults to ["5min"]
enable_orderbook=True, # Optional, defaults to True
initial_days=5 # Optional, defaults to 5
)
# Everything is connected and ready!
```

#### create_trading_suite
For more control over initialization:

```python
suite = await create_trading_suite(
instrument="MNQ",
project_x=client,
timeframes=["5min", "15min"],
auto_connect=True, # Auto-connect realtime client (default: True)
auto_subscribe=True, # Auto-subscribe to market data (default: True)
initial_days=5 # Historical data to load
)
```

#### Manual Setup (Full Control)
If you need complete control:

```python
suite = await create_trading_suite(
instrument="MNQ",
project_x=client,
auto_connect=False,
auto_subscribe=False
)
# Now manually connect and subscribe as needed
await suite["realtime_client"].connect()
await suite["data_manager"].initialize()
# ... etc
```

### Real-time Trading Example

```python
import asyncio
from project_x_py import ProjectX, create_initialized_trading_suite

async def on_tick(tick_data):
print(f"Price: ${tick_data['price']}")

async def main():
async with ProjectX.from_env() as client:
await client.authenticate()

# Create fully initialized trading suite
suite = await create_initialized_trading_suite("MNQ", client)

# Add callbacks
suite["data_manager"].add_tick_callback(on_tick)
await suite["data_manager"].start_realtime_feed()

# Get current price
current_price = await suite["data_manager"].get_current_price()

# Place a bracket order
response = await suite["order_manager"].place_bracket_order(
contract_id=instrument.id,
contract_id=suite["instrument_info"].id,
side=0, # Buy
size=1,
entry_price=current_price,
Expand Down Expand Up @@ -284,6 +364,8 @@ The `examples/` directory contains comprehensive async examples:
7. **07_technical_indicators.py** - Using indicators with async data
8. **08_order_and_position_tracking.py** - Integrated async monitoring
9. **09_get_check_available_instruments.py** - Interactive async instrument search
10. **12_simplified_strategy.py** - NEW: Simplified strategy using auto-initialization
11. **13_factory_comparison.py** - NEW: Comparison of factory function approaches

## 🔧 Configuration

Expand Down Expand Up @@ -366,6 +448,56 @@ async def place_order(self, ...):
# Method implementation
```

## 🔧 Troubleshooting

### Common Issues with Factory Functions

#### JWT Token Not Available
```python
# Error: "JWT token is required but not available from client"
# Solution: Ensure client is authenticated before creating suite
async with ProjectX.from_env() as client:
await client.authenticate() # Don't forget this!
suite = await create_initialized_trading_suite("MNQ", client)
```

#### Instrument Not Found
```python
# Error: "Instrument MNQ not found"
# Solution: Verify instrument symbol is correct
# Common symbols: "MNQ", "MES", "MGC", "ES", "NQ"
```

#### Connection Timeouts
```python
# If initialization times out, try manual setup with error handling:
try:
suite = await create_trading_suite(
instrument="MNQ",
project_x=client,
auto_connect=False
)
await suite["realtime_client"].connect()
except Exception as e:
print(f"Connection failed: {e}")
```

#### Memory Issues with Long-Running Strategies
```python
# The suite automatically manages memory, but for long-running strategies:
# 1. Use reasonable initial_days (3-7 is usually sufficient)
# 2. The data manager automatically maintains sliding windows
# 3. OrderBook has built-in memory limits
```

#### Rate Limiting
```python
# The SDK handles rate limiting automatically, but if you encounter issues:
# 1. Reduce concurrent API calls
# 2. Add delays between operations
# 3. Use batch operations where available
```

## 🤝 Contributing

We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
project = "project-x-py"
copyright = "2025, Jeff West"
author = "Jeff West"
release = "2.0.7"
version = "2.0.7"
release = "2.0.8"
version = "2.0.8"

# -- General configuration ---------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion examples/06_multi_timeframe_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ def signal_handler(signum, frame):
instruments = await client.search_instruments("MNQ")
if instruments:
await suite["realtime_client"].subscribe_market_data(
[instruments[0].activeContract]
[instruments[0].id]
)
await suite["data_manager"].start_realtime_feed()

Expand Down
Loading
Loading