@@ -350,78 +350,84 @@ def display_strategy_analysis(strategy):
350350_cleanup_managers = {}
351351_cleanup_initiated = False
352352
353+
353354def _emergency_cleanup (signum = None , frame = None ):
354355 """Emergency cleanup function called on signal interruption."""
355356 global _cleanup_initiated
356357 if _cleanup_initiated :
357358 print ("\n 🚨 Already cleaning up, please wait..." )
358359 return
359-
360+
360361 _cleanup_initiated = True
361-
362+
362363 if signum :
363364 signal_name = signal .Signals (signum ).name
364365 print (f"\n 🚨 Received { signal_name } signal - initiating emergency cleanup!" )
365366 else :
366367 print ("\n 🚨 Initiating emergency cleanup!" )
367-
368+
368369 if _cleanup_managers :
369370 print ("⚠️ Emergency position and order cleanup in progress..." )
370-
371+
371372 try :
372373 order_manager = _cleanup_managers .get ("order_manager" )
373374 position_manager = _cleanup_managers .get ("position_manager" )
374375 data_manager = _cleanup_managers .get ("data_manager" )
375-
376+
376377 if order_manager and position_manager :
377378 # Get current state
378379 positions = position_manager .get_all_positions ()
379380 orders = order_manager .search_open_orders ()
380-
381+
381382 if positions or orders :
382- print (f"🚫 Emergency: Cancelling { len (orders )} orders and closing { len (positions )} positions..." )
383-
383+ print (
384+ f"🚫 Emergency: Cancelling { len (orders )} orders and closing { len (positions )} positions..."
385+ )
386+
384387 # Cancel all orders immediately
385388 for order in orders :
386389 try :
387390 order_manager .cancel_order (order .id )
388391 print (f" ✅ Cancelled order { order .id } " )
389392 except :
390393 print (f" ❌ Failed to cancel order { order .id } " )
391-
394+
392395 # Close all positions with market orders
393396 for pos in positions :
394397 try :
395398 close_side = 1 if pos .type == 1 else 0
396399 close_response = order_manager .place_market_order (
397400 contract_id = pos .contractId ,
398401 side = close_side ,
399- size = pos .size
402+ size = pos .size ,
400403 )
401404 if close_response .success :
402- print (f" ✅ Emergency close order: { close_response .order_id } " )
405+ print (
406+ f" ✅ Emergency close order: { close_response .order_id } "
407+ )
403408 except :
404409 print (f" ❌ Failed to close position { pos .contractId } " )
405-
410+
406411 print ("⏳ Waiting 3 seconds for emergency orders to process..." )
407412 time .sleep (3 )
408413 else :
409414 print ("✅ No positions or orders to clean up" )
410-
415+
411416 # Stop data feed
412417 if data_manager :
413418 try :
414419 data_manager .stop_realtime_feed ()
415420 print ("🧹 Real-time feed stopped" )
416421 except :
417422 pass
418-
423+
419424 except Exception as e :
420425 print (f"❌ Emergency cleanup error: { e } " )
421-
426+
422427 print ("🚨 Emergency cleanup completed - check your trading platform!" )
423428 sys .exit (1 )
424429
430+
425431def wait_for_user_confirmation (message : str ) -> bool :
426432 """Wait for user confirmation before proceeding."""
427433 print (f"\n ⚠️ { message } " )
@@ -437,11 +443,11 @@ def wait_for_user_confirmation(message: str) -> bool:
437443def main ():
438444 """Demonstrate multi-timeframe trading strategy."""
439445 global _cleanup_managers
440-
446+
441447 # Register signal handlers for emergency cleanup
442- signal .signal (signal .SIGINT , _emergency_cleanup ) # Ctrl+C
448+ signal .signal (signal .SIGINT , _emergency_cleanup ) # Ctrl+C
443449 signal .signal (signal .SIGTERM , _emergency_cleanup ) # Termination signal
444-
450+
445451 logger = setup_logging (level = "INFO" )
446452 print ("🚀 Multi-Timeframe Trading Strategy Example" )
447453 print ("=" * 60 )
@@ -491,7 +497,7 @@ def main():
491497 data_manager = trading_suite ["data_manager" ]
492498 order_manager = trading_suite ["order_manager" ]
493499 position_manager = trading_suite ["position_manager" ]
494-
500+
495501 # Store managers for emergency cleanup
496502 _cleanup_managers ["data_manager" ] = data_manager
497503 _cleanup_managers ["order_manager" ] = order_manager
@@ -653,12 +659,14 @@ def main():
653659 print (" Position Details:" )
654660 for pos in final_positions :
655661 direction = "LONG" if pos .type == 1 else "SHORT"
656-
662+
657663 # Get current price for P&L calculation
658664 try :
659665 current_price = data_manager .get_current_price ()
660666 if current_price :
661- pnl_info = position_manager .calculate_position_pnl (pos , current_price )
667+ pnl_info = position_manager .calculate_position_pnl (
668+ pos , current_price
669+ )
662670 pnl = pnl_info .get ("unrealized_pnl" , 0 ) if pnl_info else 0
663671 print (
664672 f" { pos .contractId } : { direction } { pos .size } @ ${ pos .averagePrice :.2f} (P&L: ${ pnl :+.2f} )"
@@ -714,25 +722,31 @@ def main():
714722 finally :
715723 # Comprehensive cleanup - close positions and cancel orders
716724 cleanup_performed = False
717-
725+
718726 if "order_manager" in locals () and "position_manager" in locals ():
719727 try :
720728 print ("\n " + "=" * 50 )
721729 print ("🧹 STRATEGY CLEANUP" )
722730 print ("=" * 50 )
723-
731+
724732 # Get current positions and orders
725733 final_positions = position_manager .get_all_positions ()
726734 final_orders = order_manager .search_open_orders ()
727-
735+
728736 if final_positions or final_orders :
729- print (f"⚠️ Found { len (final_positions )} open positions and { len (final_orders )} open orders" )
730- print (" For safety, all positions and orders should be closed when exiting." )
731-
737+ print (
738+ f"⚠️ Found { len (final_positions )} open positions and { len (final_orders )} open orders"
739+ )
740+ print (
741+ " For safety, all positions and orders should be closed when exiting."
742+ )
743+
732744 # Ask for user confirmation to close everything
733- if wait_for_user_confirmation ("Close all positions and cancel all orders?" ):
745+ if wait_for_user_confirmation (
746+ "Close all positions and cancel all orders?"
747+ ):
734748 cleanup_performed = True
735-
749+
736750 # Cancel all open orders first
737751 if final_orders :
738752 print (f"\n 🚫 Cancelling { len (final_orders )} open orders..." )
@@ -743,74 +757,104 @@ def main():
743757 cancelled_count += 1
744758 print (f" ✅ Cancelled order { order .id } " )
745759 else :
746- print (f" ❌ Failed to cancel order { order .id } " )
760+ print (
761+ f" ❌ Failed to cancel order { order .id } "
762+ )
747763 except Exception as e :
748- print (f" ❌ Error cancelling order { order .id } : { e } " )
749-
750- print (f" 📊 Successfully cancelled { cancelled_count } /{ len (final_orders )} orders" )
751-
764+ print (
765+ f" ❌ Error cancelling order { order .id } : { e } "
766+ )
767+
768+ print (
769+ f" 📊 Successfully cancelled { cancelled_count } /{ len (final_orders )} orders"
770+ )
771+
752772 # Close all open positions
753773 if final_positions :
754- print (f"\n 📤 Closing { len (final_positions )} open positions..." )
774+ print (
775+ f"\n 📤 Closing { len (final_positions )} open positions..."
776+ )
755777 closed_count = 0
756-
778+
757779 for pos in final_positions :
758780 try :
759781 direction = "LONG" if pos .type == 1 else "SHORT"
760- print (f" 🎯 Closing { direction } { pos .size } { pos .contractId } @ ${ pos .averagePrice :.2f} " )
761-
782+ print (
783+ f" 🎯 Closing { direction } { pos .size } { pos .contractId } @ ${ pos .averagePrice :.2f} "
784+ )
785+
762786 # Get current market price for market order
763- current_price = data_manager .get_current_price () if "data_manager" in locals () else None
764-
787+ current_price = (
788+ data_manager .get_current_price ()
789+ if "data_manager" in locals ()
790+ else None
791+ )
792+
765793 # Close position with market order (opposite side)
766- close_side = 1 if pos .type == 1 else 0 # Opposite of position type
767-
794+ close_side = (
795+ 1 if pos .type == 1 else 0
796+ ) # Opposite of position type
797+
768798 close_response = order_manager .place_market_order (
769799 contract_id = pos .contractId ,
770800 side = close_side ,
771- size = pos .size
801+ size = pos .size ,
772802 )
773-
803+
774804 if close_response .success :
775805 closed_count += 1
776- print (f" ✅ Close order placed: { close_response .order_id } " )
806+ print (
807+ f" ✅ Close order placed: { close_response .order_id } "
808+ )
777809 else :
778- print (f" ❌ Failed to place close order: { close_response .error_message } " )
779-
810+ print (
811+ f" ❌ Failed to place close order: { close_response .error_message } "
812+ )
813+
780814 except Exception as e :
781- print (f" ❌ Error closing position { pos .contractId } : { e } " )
782-
783- print (f" 📊 Successfully placed { closed_count } /{ len (final_positions )} close orders" )
784-
815+ print (
816+ f" ❌ Error closing position { pos .contractId } : { e } "
817+ )
818+
819+ print (
820+ f" 📊 Successfully placed { closed_count } /{ len (final_positions )} close orders"
821+ )
822+
785823 # Give orders time to fill
786824 if closed_count > 0 :
787825 print (" ⏳ Waiting 5 seconds for orders to fill..." )
788826 time .sleep (5 )
789-
827+
790828 # Check final status
791- remaining_positions = position_manager .get_all_positions ()
829+ remaining_positions = (
830+ position_manager .get_all_positions ()
831+ )
792832 if remaining_positions :
793- print (f" ⚠️ { len (remaining_positions )} positions still open - monitor manually" )
833+ print (
834+ f" ⚠️ { len (remaining_positions )} positions still open - monitor manually"
835+ )
794836 else :
795837 print (" ✅ All positions successfully closed" )
796838 else :
797- print (" ℹ️ Cleanup skipped by user - positions and orders remain open" )
839+ print (
840+ " ℹ️ Cleanup skipped by user - positions and orders remain open"
841+ )
798842 print (" ⚠️ IMPORTANT: Monitor your positions manually!" )
799843 else :
800844 print ("✅ No open positions or orders to clean up" )
801845 cleanup_performed = True
802-
846+
803847 except Exception as e :
804848 print (f"❌ Error during cleanup: { e } " )
805-
849+
806850 # Stop real-time feed
807851 if "data_manager" in locals ():
808852 try :
809853 data_manager .stop_realtime_feed ()
810854 print ("\n 🧹 Real-time feed stopped" )
811855 except Exception as e :
812856 print (f"⚠️ Feed stop warning: { e } " )
813-
857+
814858 # Final safety message
815859 if not cleanup_performed :
816860 print ("\n " + "⚠️ " * 20 )
0 commit comments