33Order and Position Tracking Demo
44
55This demo script demonstrates the automatic order cleanup functionality when positions are closed,
6- using proper async components (AsyncOrderManager, AsyncPositionManager, AsyncRealtimeDataManager ).
6+ using proper components (OrderManager, PositionManager, RealtimeDataManager ).
77
88It creates a bracket order and monitors positions and orders in real-time, showing how the system
99automatically cancels remaining orders when a position is closed (either by stop loss, take profit,
1010or manual closure from the broker).
1111
1212Features demonstrated:
13- - Proper async components for all operations
13+ - Proper components for all operations
1414- Automatic order cleanup when positions close
1515- Non-blocking real-time monitoring with clear status updates
16- - Proper async cleanup on exit (cancels open orders and closes positions)
16+ - Proper cleanup on exit (cancels open orders and closes positions)
1717- Concurrent operations for improved performance
1818
1919Usage:
3535from datetime import datetime
3636
3737from project_x_py import ProjectX , create_trading_suite
38+ from project_x_py .models import BracketOrderResponse , Order , Position
3839
3940
4041class OrderPositionDemo :
@@ -113,6 +114,10 @@ async def create_demo_bracket_order(self) -> bool:
113114 account_id = account_info .id ,
114115 )
115116
117+ if not isinstance (bracket_response , BracketOrderResponse ):
118+ print (f"❌ Unexpected bracket order type: { type (bracket_response )} " )
119+ return False
120+
116121 if bracket_response and bracket_response .success :
117122 print ("✅ Bracket order created successfully!" )
118123 print (f" Entry Order ID: { bracket_response .entry_order_id } " )
@@ -171,6 +176,8 @@ async def display_status(self):
171176 if positions :
172177 print ("\n 🏦 Position Details:" )
173178 for pos in positions :
179+ if not isinstance (pos , Position ):
180+ continue
174181 direction = (
175182 "LONG"
176183 if pos .type == 1
@@ -200,6 +207,9 @@ async def display_status(self):
200207 if orders :
201208 print ("\n 📝 Order Details:" )
202209 for order in orders :
210+ if not isinstance (order , Order ):
211+ print (f" ❌ Unexpected order type: { type (order )} " )
212+ continue
203213 order_type = "UNKNOWN"
204214 if hasattr (order , "type" ):
205215 order_type = order .type
@@ -303,13 +313,20 @@ async def cleanup_all_positions_and_orders(self):
303313 print (f"📋 Cancelling { len (orders )} open orders..." )
304314 cancel_tasks = []
305315 for order in orders :
316+ if not isinstance (order , Order ):
317+ continue
306318 cancel_tasks .append (
307319 self .suite ["order_manager" ].cancel_order (order .id )
308320 )
309321
310322 # Wait for all cancellations to complete
311- results = await asyncio .gather (* cancel_tasks , return_exceptions = True )
312- for order , result in zip (orders , results , strict = False ):
323+ cancel_results : list [Order | BaseException ] = await asyncio .gather (
324+ * cancel_tasks , return_exceptions = True
325+ )
326+ for order , result in zip (orders , cancel_results , strict = False ):
327+ if not isinstance (order , Order ):
328+ print (f" ❌ Unexpected order type: { type (order )} " )
329+ continue
313330 if isinstance (result , Exception ):
314331 print (f" ❌ Error cancelling order { order .id } : { result } " )
315332 elif result :
@@ -318,7 +335,9 @@ async def cleanup_all_positions_and_orders(self):
318335 print (f" ⚠️ Failed to cancel order { order .id } " )
319336
320337 # Close all open positions
321- positions = await self .suite ["position_manager" ].get_all_positions ()
338+ positions : list [Position ] = await self .suite [
339+ "position_manager"
340+ ].get_all_positions ()
322341 if positions :
323342 print (f"🏦 Closing { len (positions )} open positions..." )
324343 close_tasks = []
@@ -330,7 +349,9 @@ async def cleanup_all_positions_and_orders(self):
330349 )
331350
332351 # Wait for all positions to close
333- results = await asyncio .gather (* close_tasks , return_exceptions = True )
352+ results : list [Position | BaseException ] = await asyncio .gather (
353+ * close_tasks , return_exceptions = True
354+ )
334355 for position , result in zip (positions , results , strict = False ):
335356 if isinstance (result , Exception ):
336357 print (
@@ -355,7 +376,7 @@ async def cleanup_all_positions_and_orders(self):
355376 print (f"❌ Error during cleanup: { e } " )
356377
357378 async def run (self , client : ProjectX ):
358- """Main async demo execution."""
379+ """Main demo execution."""
359380 self .setup_signal_handlers ()
360381 self .client = client
361382
@@ -376,9 +397,9 @@ async def run(self, client: ProjectX):
376397 print (f"❌ Failed to authenticate: { e } " )
377398 return False
378399
379- # Create async trading suite
400+ # Create trading suite
380401 try :
381- print ("\n 🔧 Setting up async trading suite..." )
402+ print ("\n 🔧 Setting up trading suite..." )
382403 jwt_token = self .client .session_token
383404 self .suite = await create_trading_suite (
384405 instrument = "MNQ" ,
@@ -388,10 +409,10 @@ async def run(self, client: ProjectX):
388409 timeframes = ["5min" ], # Minimal timeframes for demo
389410 )
390411
391- print ("✅ Async trading suite created with automatic order cleanup enabled" )
412+ print ("✅ Trading suite created with automatic order cleanup enabled" )
392413
393414 except Exception as e :
394- print (f"❌ Failed to create async trading suite: { e } " )
415+ print (f"❌ Failed to create trading suite: { e } " )
395416 return False
396417
397418 # Connect real-time client and initialize data feed
@@ -442,7 +463,7 @@ async def run(self, client: ProjectX):
442463
443464
444465async def main ():
445- """Main async entry point."""
466+ """Main entry point."""
446467 demo = OrderPositionDemo ()
447468 try :
448469 async with ProjectX .from_env () as client :
0 commit comments