Documentation

Portfolio

Simulate trading activity and analyze portfolio performance

A portfolio refers to any combination of financial assets held by a trader. In VBT, a "portfolio" is a multidimensional structure designed to simulate and track multiple independent as well as dependent portfolio instances. The primary function of a portfolio is to apply trading logic to a set of inputs and simulate a realistic trading environment, known as "simulation". The outputs of this simulation are orders and other information that users can use to assess the portfolio's performance, a process also referred to as "reconstruction" or "post-analysis". Both phases are isolated, which allows for a variety of interesting use cases in quantitative analysis and data science.

The main class for simulating and analyzing portfolios (that is, actual backtesting) is Portfolio. This is a standard Python class that subclasses Analyzable and provides access to a variety of Numba-compiled functions. It is structured similarly to other analyzable classes, featuring diverse class methods for instantiation from different types of inputs (such as Portfolio.from_signals, which accepts signals). This stateful class can wrap and index any Pandas-like objects it contains, compute metrics, and display (sub-)plots for quick introspection of the stored data.

Simulation

So, what is a simulation? It is simply a sophisticated loop! 🍩

A typical simulation in VBT takes some inputs (such as signals), gradually iterates over their rows (representing time steps in the real world) using a for-loop, and at each row runs the trading logic by issuing and executing orders. It then updates the current state of the trading environment, such as the cash balance and position size. This process mirrors how we would approach algorithmic trading in reality: at each minute, hour, or day (each row), we decide what to do (the trading logic) and place an order if we wish to change our market position.

Now, let's discuss execution. The core of VBT's backtesting engine is entirely Numba-compiled for optimal performance. The engine's functionality is distributed across many functions within the portfolio.nb sub-package, covering everything from core order execution commands to the calculation of P&L in trade records. It is important to note that these functions are not intended for direct use (unless specifically required); instead, they are called by Python functions higher in the stack. These higher-level functions handle proper pre-processing of input data and post-processing of output data.

In the following sections, we will discuss order execution and processing, and we will gradually implement a collection of simple pipelines to better illustrate various simulation concepts.

Primitive commands

Keep in mind that VBT is an exceptionally raw backtester: its primary commands are "buy" 🟢 and "sell" 🔴. This means that any strategy that can be expressed as a set of these commands is supported out of the box. It also means that more complex orders, such as limit and stop-loss orders, must be implemented manually. In contrast to other backtesting frameworks, where processing is monolithic and functionality is written in an object-oriented manner, Numba forces VBT to implement most functionality in a procedural way.

Even though Numba supports OOP by compiling Python classes with @jitclass, they are treated as functions, must be statically typed, and have performance drawbacks that prevent us from adopting them at this time.

Functions related to order execution are primarily found in portfolio.nb.core. The functions implementing our two primary commands are buy_nb and sell_nb. In addition to the requested size and price of an order, the main input for each of these functions is the current account state of type AccountState. This includes the cash balance, position size, and other details about the current environment. Whenever we buy or sell, the function creates and returns a new state of the same type. It also returns an order result of type OrderResult, which includes the filled size, slippage-adjusted price, transaction fee, order side, status information indicating whether the order succeeded or failed, and helpful details about any failure.

Buying

The buy operation consists of two distinct actions: "long-buy," implemented by long_buy_nb, and "short-buy," implemented by short_buy_nb. The first opens or increases a long position, while the second reduces a short position. By chaining these two actions, we can reverse a short position, which is handled automatically by buy_nb. This function checks the current position (if any) and calls the appropriate function.

Suppose we have $100 available and want to buy 1 share at a price of $15:

Portfolio modeling connects trading rules with a realistic simulation state and reconstructs the result into orders, trades, positions, drawdowns, returns, and other analysis objects. This section explains that lifecycle and the main simulation interfaces.

Topics

Copyright © 2021–2026 Oleg Polakow. All rights reserved.

Site content and documentation are provided for using and evaluating VectorBT PRO and for educational purposes. Any other use, including building or supporting competing products or services, requires prior written consent.