Skip to content

main loop (_run_trading_session) can cause endless loop without sleep(1) #1145

Description

@SherlockLaw

Name: lumibot
Version: 4.5.66

hey guys.
I have run a strategy,CPU occupied was pretty high after the network crashed. so I found these codes with problems,if this function return early,then the sleep(1) will not be executed,which happend in my situation. I wrap this method for myself with a sleep if anyone interest
here is the source code
`
def _run_trading_session(self):

    has_data_source = getattr(self.broker, "data_source", None) is not None
    market_name = getattr(self.broker, "market", None)
    is_continuous_market = market_name and self._is_continuous_market(market_name)

    # Process pandas daily and get out.
    if self._is_pandas_daily_data_source():
        self._process_pandas_daily_data()
        return

    # Set up market session and determine time_to_close
    if not is_continuous_market:
        # Set up market session and check if we should continue
        if not self._setup_market_session(has_data_source):
            return                    # **happends here**-----------------------------------------
        time_to_close = self._ensure_progress_inside_open_session(self.broker.get_time_to_close())
    else:
        time_to_close = float("inf")

    if not self.strategy.is_backtesting:
        # Start APScheduler for the trading session.
        self._setup_live_trading_scheduler()

        # Calculate if we should stop based on market timing
        should_we_stop = self._calculate_should_we_stop()

        # Clean up any existing check_queue thread before starting new one
        if hasattr(self, 'check_queue_thread') and self.check_queue_thread is not None:
            if self.check_queue_thread.is_alive():
                self.check_queue_stop_event.set()
                self.check_queue_thread.join(timeout=5.0)
        
        # Reset the stop event for the new thread
        self.check_queue_stop_event.clear()
        
        # Start the check_queue thread which will run continuously in the background, checking if any items have
        # been added to the queue and executing them.
        self.check_queue_thread = Thread(target=self.check_queue)
        self.check_queue_thread.start()

        next_run_time = self.get_next_ap_scheduler_run_time()
        if next_run_time is not None:
            # Format the date to be used in the log message.
            dt_str = next_run_time.strftime("%Y-%m-%d %I:%M:%S %p %Z")
            self.strategy.log_message(f"Strategy will check in again at: {dt_str}", color="blue")

        # Loop until the strategy should stop.
        loop_count = 0
        while True:
            loop_count += 1

            # Log every 60 iterations (roughly every minute) to track loop activity
            if loop_count % 60 == 1:
                self.strategy.logger.debug(f"Main loop iteration #{loop_count} - Market closed status check")

            # Send data to cloud every minute FIRST - regardless of market status
            should_send_cloud_update = (not hasattr(self, '_last_updated_cloud')) or ((datetime.now() - self._last_updated_cloud) >= timedelta(minutes=1))
            if should_send_cloud_update:
                time_since_last = "never" if not hasattr(self, '_last_updated_cloud') else str(datetime.now() - self._last_updated_cloud)
                self.strategy.logger.debug(f"Sending cloud update (last update: {time_since_last} ago)")
                self.strategy.send_update_to_cloud()
                self._last_updated_cloud = datetime.now()

            # Get the current jobs from the scheduler (may be None if gracefully exited previously)
            if self.scheduler is None:
                self.strategy.log_message("⚠️ Scheduler is None, attempting to recreate", color="yellow")
                # Attempt to re-create and start the scheduler
                self._setup_live_trading_scheduler()

            jobs = self.scheduler.get_jobs() if self.scheduler is not None else []

            # Log scheduler status every minute
            if loop_count % 60 == 1:
                self.strategy.logger.debug(f"Scheduler jobs: {len(jobs)} active")

            # Check if we should continue trading loop
            should_continue = self._should_continue_trading_loop(jobs, is_continuous_market, should_we_stop)
            if not should_continue:
                self.strategy.logger.debug(f"Trading loop should stop: jobs={len(jobs)}, continuous={is_continuous_market}, should_stop={should_we_stop}")
                break

            # Handle LifeCycle methods
            self._handle_lifecycle_methods()

            time.sleep(1)  # Sleep to save CPU`

Another problem in other function, may cause the same.but I dont know if I should open extra issues.
please fix it. thank you for runing this project

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions