project-x-py 0.2.0__py3-none-any.whl

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.
@@ -0,0 +1,550 @@
1
+ """
2
+ ProjectX API Client for TopStepX Futures Trading
3
+
4
+ A comprehensive Python client for the ProjectX Gateway API, providing access to:
5
+ - Market data retrieval
6
+ - Account management
7
+ - Order placement, modification, and cancellation
8
+ - Position management
9
+ - Trade history and analysis
10
+ - Real-time data streams
11
+
12
+ Author: TexasCoding
13
+ Date: June 2025
14
+ """
15
+
16
+ from typing import Any, Optional
17
+
18
+ __version__ = "0.2.0"
19
+ __author__ = "TexasCoding"
20
+
21
+ # Core client classes
22
+ from .client import ProjectX
23
+
24
+ # Configuration management
25
+ from .config import (
26
+ ConfigManager,
27
+ check_environment,
28
+ create_config_template,
29
+ load_default_config,
30
+ )
31
+
32
+ # Exceptions
33
+ from .exceptions import (
34
+ ProjectXAuthenticationError,
35
+ ProjectXConnectionError,
36
+ ProjectXDataError,
37
+ ProjectXError,
38
+ ProjectXInstrumentError,
39
+ ProjectXOrderError,
40
+ ProjectXPositionError,
41
+ ProjectXRateLimitError,
42
+ ProjectXServerError,
43
+ )
44
+
45
+ # Data models
46
+ from .models import (
47
+ Account,
48
+ BracketOrderResponse,
49
+ # Trading entities
50
+ Instrument,
51
+ Order,
52
+ OrderPlaceResponse,
53
+ Position,
54
+ # Configuration
55
+ ProjectXConfig,
56
+ Trade,
57
+ )
58
+ from .order_manager import OrderManager
59
+ from .orderbook import OrderBook
60
+ from .position_manager import PositionManager
61
+ from .realtime import ProjectXRealtimeClient
62
+ from .realtime_data_manager import ProjectXRealtimeDataManager
63
+
64
+ # Utility functions
65
+ # Convenience imports for backward compatibility
66
+ from .utils import (
67
+ RateLimiter,
68
+ # Enhanced data analysis and indicators
69
+ analyze_bid_ask_spread,
70
+ calculate_adx,
71
+ calculate_atr,
72
+ calculate_bollinger_bands,
73
+ calculate_commodity_channel_index,
74
+ calculate_correlation_matrix,
75
+ calculate_ema,
76
+ calculate_macd,
77
+ calculate_max_drawdown,
78
+ calculate_portfolio_metrics,
79
+ calculate_position_sizing,
80
+ calculate_position_value,
81
+ calculate_risk_reward_ratio,
82
+ calculate_rsi,
83
+ calculate_sharpe_ratio,
84
+ # Technical analysis helpers
85
+ calculate_sma,
86
+ calculate_stochastic,
87
+ calculate_tick_value,
88
+ calculate_volatility_metrics,
89
+ calculate_volume_profile,
90
+ calculate_williams_r,
91
+ convert_timeframe_to_seconds,
92
+ create_data_snapshot,
93
+ detect_candlestick_patterns,
94
+ detect_chart_patterns,
95
+ extract_symbol_from_contract_id,
96
+ find_support_resistance_levels,
97
+ format_price,
98
+ format_volume,
99
+ get_env_var,
100
+ get_market_session_info,
101
+ get_polars_last_value as _get_polars_last_value,
102
+ get_polars_rows as _get_polars_rows,
103
+ is_market_hours,
104
+ round_to_tick_size,
105
+ setup_logging,
106
+ # New utility functions for developers
107
+ validate_contract_id,
108
+ )
109
+
110
+ # Public API - these are the main classes users should import
111
+ __all__ = [
112
+ "Account",
113
+ "BracketOrderResponse",
114
+ "ConfigManager",
115
+ "Instrument",
116
+ "Order",
117
+ "OrderBook",
118
+ "OrderManager",
119
+ "OrderPlaceResponse",
120
+ "Position",
121
+ "PositionManager",
122
+ "ProjectX",
123
+ "ProjectXAuthenticationError",
124
+ "ProjectXConfig",
125
+ "ProjectXConnectionError",
126
+ "ProjectXDataError",
127
+ "ProjectXError",
128
+ "ProjectXInstrumentError",
129
+ "ProjectXOrderError",
130
+ "ProjectXPositionError",
131
+ "ProjectXRateLimitError",
132
+ "ProjectXRealtimeClient",
133
+ "ProjectXRealtimeDataManager",
134
+ "ProjectXServerError",
135
+ "RateLimiter",
136
+ "Trade",
137
+ # Enhanced technical analysis and trading utilities
138
+ "analyze_bid_ask_spread",
139
+ "calculate_adx",
140
+ "calculate_atr",
141
+ "calculate_bollinger_bands",
142
+ "calculate_commodity_channel_index",
143
+ "calculate_correlation_matrix",
144
+ "calculate_ema",
145
+ "calculate_macd",
146
+ "calculate_max_drawdown",
147
+ "calculate_portfolio_metrics",
148
+ "calculate_position_sizing",
149
+ "calculate_position_value",
150
+ "calculate_risk_reward_ratio",
151
+ "calculate_rsi",
152
+ "calculate_sharpe_ratio",
153
+ "calculate_sma",
154
+ "calculate_stochastic",
155
+ "calculate_tick_value",
156
+ "calculate_volatility_metrics",
157
+ "calculate_volume_profile",
158
+ "calculate_williams_r",
159
+ "check_environment",
160
+ "convert_timeframe_to_seconds",
161
+ "create_config_template",
162
+ "create_data_manager",
163
+ "create_data_snapshot",
164
+ "create_order_manager",
165
+ "create_orderbook",
166
+ "create_position_manager",
167
+ "create_realtime_client",
168
+ "create_trading_suite",
169
+ "detect_candlestick_patterns",
170
+ "detect_chart_patterns",
171
+ "extract_symbol_from_contract_id",
172
+ "find_support_resistance_levels",
173
+ "format_price",
174
+ "format_volume",
175
+ "get_env_var",
176
+ "get_market_session_info",
177
+ "is_market_hours",
178
+ "load_default_config",
179
+ "round_to_tick_size",
180
+ "setup_logging",
181
+ "validate_contract_id",
182
+ ]
183
+
184
+
185
+ def get_version() -> str:
186
+ """Get the current version of the ProjectX package."""
187
+ return __version__
188
+
189
+
190
+ def quick_start() -> dict:
191
+ """
192
+ Get quick start information for the ProjectX package.
193
+
194
+ Returns:
195
+ Dict with setup instructions and examples
196
+ """
197
+ return {
198
+ "version": __version__,
199
+ "setup_instructions": [
200
+ "1. Set environment variables:",
201
+ " export PROJECT_X_API_KEY='your_api_key'",
202
+ " export PROJECT_X_USERNAME='your_username'",
203
+ "",
204
+ "2. Basic usage:",
205
+ " from project_x_py import ProjectX",
206
+ " client = ProjectX.from_env()",
207
+ " instruments = client.search_instruments('MGC')",
208
+ " data = client.get_data('MGC', days=5)",
209
+ ],
210
+ "examples": {
211
+ "basic_client": "client = ProjectX.from_env()",
212
+ "get_instruments": "instruments = client.search_instruments('MGC')",
213
+ "get_data": "data = client.get_data('MGC', days=5, interval=15)",
214
+ "place_order": "response = client.place_market_order('CONTRACT_ID', 0, 1)",
215
+ "get_positions": "positions = client.search_open_positions()",
216
+ },
217
+ "documentation": "https://github.com/your-repo/project-x-py",
218
+ "support": "Create an issue at https://github.com/your-repo/project-x-py/issues",
219
+ }
220
+
221
+
222
+ def check_setup() -> dict:
223
+ """
224
+ Check if the ProjectX package is properly set up.
225
+
226
+ Returns:
227
+ Dict with setup status and recommendations
228
+ """
229
+ try:
230
+ from .config import check_environment
231
+
232
+ env_status = check_environment()
233
+
234
+ status = {
235
+ "environment_configured": env_status["auth_configured"],
236
+ "config_file_exists": env_status["config_file_exists"],
237
+ "issues": [],
238
+ "recommendations": [],
239
+ }
240
+
241
+ if not env_status["auth_configured"]:
242
+ status["issues"].append("Missing required environment variables")
243
+ status["recommendations"].extend(
244
+ [
245
+ "Set PROJECT_X_API_KEY environment variable",
246
+ "Set PROJECT_X_USERNAME environment variable",
247
+ ]
248
+ )
249
+
250
+ if env_status["missing_required"]:
251
+ status["missing_variables"] = env_status["missing_required"]
252
+
253
+ if env_status["environment_overrides"]:
254
+ status["environment_overrides"] = env_status["environment_overrides"]
255
+
256
+ if not status["issues"]:
257
+ status["status"] = "Ready to use"
258
+ else:
259
+ status["status"] = "Setup required"
260
+
261
+ return status
262
+
263
+ except Exception as e:
264
+ return {
265
+ "status": "Error checking setup",
266
+ "error": str(e),
267
+ "recommendations": [
268
+ "Ensure all dependencies are installed",
269
+ "Check package installation",
270
+ ],
271
+ }
272
+
273
+
274
+ # Package-level convenience functions
275
+ def create_client(
276
+ username: str | None = None,
277
+ api_key: str | None = None,
278
+ config: ProjectXConfig | None = None,
279
+ account_name: str | None = None,
280
+ ) -> ProjectX:
281
+ """
282
+ Create a ProjectX client with flexible initialization.
283
+
284
+ Args:
285
+ username: Username (uses env var if None)
286
+ api_key: API key (uses env var if None)
287
+ config: Configuration object (uses defaults if None)
288
+ account_name: Optional account name to select specific account
289
+
290
+ Returns:
291
+ ProjectX client instance
292
+
293
+ Example:
294
+ >>> # Using environment variables
295
+ >>> client = create_client()
296
+ >>> # Using explicit credentials
297
+ >>> client = create_client("username", "api_key")
298
+ >>> # Using specific account
299
+ >>> client = create_client(account_name="Main Trading Account")
300
+ """
301
+ if username is None or api_key is None:
302
+ return ProjectX.from_env(config=config, account_name=account_name)
303
+ else:
304
+ return ProjectX(
305
+ username=username, api_key=api_key, config=config, account_name=account_name
306
+ )
307
+
308
+
309
+ def create_realtime_client(
310
+ jwt_token: str, account_id: str, config: ProjectXConfig | None = None
311
+ ) -> ProjectXRealtimeClient:
312
+ """
313
+ Create a ProjectX real-time client.
314
+
315
+ Args:
316
+ jwt_token: JWT authentication token
317
+ account_id: Account ID for subscriptions
318
+ config: Configuration object (uses defaults if None)
319
+
320
+ Returns:
321
+ ProjectXRealtimeClient instance
322
+ """
323
+ if config is None:
324
+ config = load_default_config()
325
+
326
+ return ProjectXRealtimeClient(
327
+ jwt_token=jwt_token,
328
+ account_id=account_id,
329
+ user_hub_url=config.user_hub_url,
330
+ market_hub_url=config.market_hub_url,
331
+ )
332
+
333
+
334
+ def create_data_manager(
335
+ instrument: str,
336
+ project_x: ProjectX,
337
+ realtime_client: ProjectXRealtimeClient,
338
+ timeframes: list[str] | None = None,
339
+ config: ProjectXConfig | None = None,
340
+ ) -> ProjectXRealtimeDataManager:
341
+ """
342
+ Create a ProjectX real-time OHLCV data manager with dependency injection.
343
+
344
+ Args:
345
+ instrument: Trading instrument symbol
346
+ project_x: ProjectX client instance
347
+ realtime_client: ProjectXRealtimeClient instance for real-time data
348
+ timeframes: List of timeframes to track (default: ["5min"])
349
+ config: Configuration object (uses defaults if None)
350
+
351
+ Returns:
352
+ ProjectXRealtimeDataManager instance
353
+ """
354
+ if timeframes is None:
355
+ timeframes = ["5min"]
356
+
357
+ if config is None:
358
+ config = load_default_config()
359
+
360
+ return ProjectXRealtimeDataManager(
361
+ instrument=instrument,
362
+ project_x=project_x,
363
+ realtime_client=realtime_client,
364
+ timeframes=timeframes,
365
+ timezone=config.timezone,
366
+ )
367
+
368
+
369
+ def create_orderbook(
370
+ instrument: str,
371
+ config: ProjectXConfig | None = None,
372
+ ) -> "OrderBook":
373
+ """
374
+ Create a ProjectX OrderBook for advanced market depth analysis.
375
+
376
+ Args:
377
+ instrument: Trading instrument symbol
378
+ config: Configuration object (uses defaults if None)
379
+
380
+ Returns:
381
+ OrderBook instance
382
+ """
383
+ if config is None:
384
+ config = load_default_config()
385
+
386
+ return OrderBook(
387
+ instrument=instrument,
388
+ timezone=config.timezone,
389
+ )
390
+
391
+
392
+ def create_order_manager(
393
+ project_x: ProjectX,
394
+ realtime_client: ProjectXRealtimeClient | None = None,
395
+ ) -> OrderManager:
396
+ """
397
+ Create a ProjectX OrderManager for comprehensive order operations.
398
+
399
+ Args:
400
+ project_x: ProjectX client instance
401
+ realtime_client: Optional ProjectXRealtimeClient for real-time order tracking
402
+
403
+ Returns:
404
+ OrderManager instance
405
+
406
+ Example:
407
+ >>> order_manager = create_order_manager(project_x, realtime_client)
408
+ >>> order_manager.initialize()
409
+ >>> # Place orders
410
+ >>> response = order_manager.place_market_order("MGC", 0, 1)
411
+ >>> bracket = order_manager.place_bracket_order(
412
+ ... "MGC", 0, 1, 2045.0, 2040.0, 2055.0
413
+ ... )
414
+ >>> # Manage orders
415
+ >>> orders = order_manager.search_open_orders()
416
+ >>> order_manager.cancel_order(order_id)
417
+ """
418
+ order_manager = OrderManager(project_x)
419
+ order_manager.initialize(realtime_client=realtime_client)
420
+ return order_manager
421
+
422
+
423
+ def create_position_manager(
424
+ project_x: ProjectX,
425
+ realtime_client: ProjectXRealtimeClient | None = None,
426
+ ) -> PositionManager:
427
+ """
428
+ Create a ProjectX PositionManager for comprehensive position operations.
429
+
430
+ Args:
431
+ project_x: ProjectX client instance
432
+ realtime_client: Optional ProjectXRealtimeClient for real-time position tracking
433
+
434
+ Returns:
435
+ PositionManager instance
436
+
437
+ Example:
438
+ >>> position_manager = create_position_manager(project_x, realtime_client)
439
+ >>> position_manager.initialize()
440
+ >>> # Get positions
441
+ >>> positions = position_manager.get_all_positions()
442
+ >>> mgc_position = position_manager.get_position("MGC")
443
+ >>> # Portfolio analytics
444
+ >>> pnl = position_manager.get_portfolio_pnl()
445
+ >>> risk = position_manager.get_risk_metrics()
446
+ >>> # Position monitoring
447
+ >>> position_manager.add_position_alert("MGC", max_loss=-500.0)
448
+ >>> position_manager.start_monitoring()
449
+ """
450
+ position_manager = PositionManager(project_x)
451
+ position_manager.initialize(realtime_client=realtime_client)
452
+ return position_manager
453
+
454
+
455
+ def create_trading_suite(
456
+ instrument: str,
457
+ project_x: ProjectX,
458
+ jwt_token: str,
459
+ account_id: str,
460
+ timeframes: list[str] | None = None,
461
+ config: ProjectXConfig | None = None,
462
+ ) -> dict[str, Any]:
463
+ """
464
+ Create a complete trading suite with optimized architecture.
465
+
466
+ This factory function sets up:
467
+ - Single ProjectXRealtimeClient for WebSocket connection
468
+ - ProjectXRealtimeDataManager for OHLCV data
469
+ - OrderBook for market depth analysis
470
+ - OrderManager for comprehensive order operations
471
+ - PositionManager for position tracking and risk management
472
+ - Proper dependency injection and connection sharing
473
+
474
+ Args:
475
+ instrument: Trading instrument symbol
476
+ project_x: ProjectX client instance
477
+ jwt_token: JWT token for WebSocket authentication
478
+ account_id: Account ID for real-time subscriptions
479
+ timeframes: List of timeframes to track (default: ["5min"])
480
+ config: Configuration object (uses defaults if None)
481
+
482
+ Returns:
483
+ dict: {"realtime_client": client, "data_manager": manager, "orderbook": orderbook, "order_manager": order_manager, "position_manager": position_manager}
484
+
485
+ Example:
486
+ >>> suite = create_trading_suite(
487
+ ... "MGC", project_x, jwt_token, account_id, ["5sec", "1min", "5min"]
488
+ ... )
489
+ >>> # Connect once
490
+ >>> suite["realtime_client"].connect()
491
+ >>> # Initialize components
492
+ >>> suite["data_manager"].initialize(initial_days=30)
493
+ >>> suite["data_manager"].start_realtime_feed()
494
+ >>> # Place orders
495
+ >>> bracket = suite["order_manager"].place_bracket_order(
496
+ ... "MGC", 0, 1, 2045.0, 2040.0, 2055.0
497
+ ... )
498
+ >>> # Monitor positions
499
+ >>> suite["position_manager"].add_position_alert("MGC", max_loss=-500.0)
500
+ >>> suite["position_manager"].start_monitoring()
501
+ >>> # Access data
502
+ >>> ohlcv_data = suite["data_manager"].get_data("5min")
503
+ >>> orderbook_snapshot = suite["orderbook"].get_orderbook_snapshot()
504
+ >>> portfolio_pnl = suite["position_manager"].get_portfolio_pnl()
505
+ """
506
+ if timeframes is None:
507
+ timeframes = ["5min"]
508
+
509
+ if config is None:
510
+ config = load_default_config()
511
+
512
+ # Create single realtime client (shared connection)
513
+ realtime_client = ProjectXRealtimeClient(
514
+ jwt_token=jwt_token,
515
+ account_id=account_id,
516
+ user_hub_url=config.user_hub_url,
517
+ market_hub_url=config.market_hub_url,
518
+ )
519
+
520
+ # Create OHLCV data manager with dependency injection
521
+ data_manager = ProjectXRealtimeDataManager(
522
+ instrument=instrument,
523
+ project_x=project_x,
524
+ realtime_client=realtime_client,
525
+ timeframes=timeframes,
526
+ timezone=config.timezone,
527
+ )
528
+
529
+ # Create separate orderbook for market depth analysis
530
+ orderbook = OrderBook(
531
+ instrument=instrument,
532
+ timezone=config.timezone,
533
+ )
534
+
535
+ # Create order manager for comprehensive order operations
536
+ order_manager = OrderManager(project_x)
537
+ order_manager.initialize(realtime_client=realtime_client)
538
+
539
+ # Create position manager for position tracking and risk management
540
+ position_manager = PositionManager(project_x)
541
+ position_manager.initialize(realtime_client=realtime_client)
542
+
543
+ return {
544
+ "realtime_client": realtime_client,
545
+ "data_manager": data_manager,
546
+ "orderbook": orderbook,
547
+ "order_manager": order_manager,
548
+ "position_manager": position_manager,
549
+ "config": config,
550
+ }