Projects

Debugging

Introduction

Debugging is the process of systematically using a tool to find and fix errors in software. Errors can cause unintended trades, unexpected algorithm crashes, and faulty risk management logic. We use a debugging tool step through code line-by-line, and inspect the variables to understand the internal state of the program. You have many tools to debug your algorithm, including our built-in debugger, logging statements, charting, and the Object Store.

Coding Errors

Coding errors are errors that cause your projects to not build, throw exceptions, or behave unexpectedly. There are generally 3 types of coding errors: build, runtime, and logic errors. Each type of error occurs for different reasons.

Build Errors

Build errors occur when the interpreter's syntax check fails. An example code snippet that produces a build error is the following:

var a = 1;
if (a = 2) {}
a = 1
if a = 2:
    pass

If build errors occur in your project, you can not use the debugger, logging statements, or custom charts to debug the issue. You're notified of build errors in the following ways:

  • The line where the error occurs is underlined in red.
  • The Problems panel at the bottom of the IDE displays the errors.
  • The Explorer panel highlights the editors, files, and outlines in red where the error occurs.

Runtime Errors

Runtime Errors, also called exceptions, occur when the interpreter’s syntax checks pass but an error occurs during execution. An example code snippet that produces a runtime error is the following:

var a = new List<int>() {1};
var b = a[1];
a = [1]
a[1]

If runtime errors occur in your project, a stack trace of the error is added to the Cloud Terminal and the log file. For example, the snippet above produces the following error message:

Runtime Error: IndexError : list index out of range
  at OnData
    a[1]
===
   at Python.Runtime.PyObject.Invoke(PyTuple args in main.py: line 17
     (Open Stack Trace)
Runtime Error: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index') in Main.cs:line 24 (Open Stack Trace)

The stack trace from the build error identifies the line of code where the error occurs. If the error doesn't reference your project files, it's an issue with Lean or another library. To view more information about the error, click (Open Stack Trace).

Logic Errors

Logic errors occur when your algorithm behaves in an unexpected or unintended manner. These types of errors don't halt the program execution, so they are difficult to diagnose. An example code snippet that produces a logic error is the following:

var average = x + y / 2.0; // instead of (x + y) / 2.0
average = x + y / 2 # instead of (x + y) / 2

To resolve logic errors, carefully trace your algorithm. You may use the Loglog method and Debugdebug method methods or the built-in debugger.

Debugger

The debugger is a built-in tool to help you debug coding errors while backtesting. The debugger enables you to slow down the code execution, step through the program line-by-line, and inspect the variables to understand the internal state of the program. For more information about the backtesting debugger, see Backtest Debugging.

Logging Statements

Algorithms can record string messages ('log statements') to a file for analysis after a backtest is complete, or as a live algorithm is running. These records can assist in debugging logical flow errors in the project code. Consider adding them in the code block of an if statement to signify an error has been caught.

It's good practice to add logging statements to live algorithms so you can understand its behavior and keep records to compare against backtest results. If you don't add logging statements to a live algorithm and the algorithm doesn't trade as you expect, it's difficult to evaluate the underlying problem.

Log

Log statements are added to the log file while your algorithm continues executing. Logging dataset information is not permitted. Use Loglog method statements to debug your backtests and live trading algorithms.

Log length is capped by organization tier. If your organization hits the daily limit, contact us.

If you log the same content multiple times, only the first instance is added to the log file. To bypass this rate-limit, add a timestamp to your log messages.

For live trading, the log files of each cloud project can store up to 100,000 lines for up to one year. If you log more than 100,000 lines or some lines become older than one year, we remove the oldest lines in the files so your project stays within the quota.

To record the algorithm state when the algorithm stops executing, add log statements to the OnEndOfAlgorithmon_end_of_algorithm event handler.

Log("My log message");
self.log("My log message")

Debug

Debug statements are the same as log statements, but Debugdebug method statements are orange in the Cloud Terminal. Use these statements when you want to give more attention to a message in the Cloud Terminal. Debug messages can be up to 200 characters in length. If you send multiple debug statements within 1 second, your messages are rate-limited to avoid crashing your browser.

Debug("My debug message");
self.debug("My debug message")

Error

Error statements are the same as log statements, but Errorerror method statements are displayed in red text in the Cloud Terminal. Use these statements when you want to give the most attention to a message in the Cloud Terminal. Error statements are rate-limited like debug statements.

Error("My error message");
self.error("My error message")

Quit

Quit statements cause your project to stop running and may log some data to the log file and Cloud Terminal. These statements are orange in the Cloud Terminal. When you call the Quitquit method method, the program continues executing until the end of the method definition. If you want to quit execution immediately, return after you call Quitquit method.

Quit("My quit message");
self.quit("My quit message")

Charting

You can use the IDE charting capabilities to plot values over time when debugging. To add data points to a custom chart, call the Plotplot method with a chart name, series name, and value. For a full example, see Charting.

// Add data points to a custom chart.
Plot("Chart Name", "Series Name", value);
# Add data points to a custom chart.
self.plot("Chart Name", "Series Name", value)

If you run your algorithm in QuantConnect Cloud, we limit the number of points a chart can have to 4,000 because intensive charting generates hundreds of megabytes (200MB) of data, which is too much to stream online or display in a web browser. If you exceed the limit, the following error message is thrown:

Exceeded maximum data points per series, chart update skipped.

Object Store

The Object Store is a key-value data store for low-latency information storage and retrieval. During a backtest, you can build large objects you’d like to analyze and write them for later analysis. This workflow can be helpful when the objects are large and plotting is impossible or when you want to perform analysis across many backtests.

// Save the key-value pair in the Object Store.
ObjectStore.Save("key", value);
# Save the key-value pair in the Object Store.
self.object_store.save("key", value)

For more information about the Object Store, see Object Store. For a specific example of saving indicator values during a backtest into the Object Store and then plotting them in the Research Environment, see Example for Plotting.

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: