Tutorials

Patterns and projections

Detect chart patterns and project their effect on future prices

Patterns help bring order to what may seem like chaos. They appear throughout nature—such as circles in road signs or rectangles in windows and doors. Just as children gradually learn to navigate an entirely unknown environment by recognizing regularities, participants in financial markets must also learn to operate within their complex, ever-changing surroundings. Much like children who rely on parents, teachers, or even Google for guidance, we have a valuable tool to aid our understanding: quantitative analysis.

In finance, patterns are distinctive formations formed by price movements on a chart and form the foundation of technical analysis. They can provide clues about what prices might do next, based on past behavior. For example, we can search for all previous occurrences of the same pattern we see today to analyze how events unfolded each time, enabling more nuanced trading decisions that consider multiple possibilities. Patterns are particularly valuable for identifying transition points between rising and falling trends, which is key to successful trade entries and exits. However, patterns do not guarantee future results, nor do they last forever. Unlike the real world, where structure and behavior tend to be consistent, financial markets are dominated by noise and false positives that arise from intense interactions among people, systems, and other entities. Discovering something that performs just slightly better than random in a specific market regime is already an accomplishment—an exciting game with probabilities.

Let's walk through a simple use case where we want to identify the Double Top pattern. We will start by pulling two years of daily BTCUSDT history as our baseline data:

from vectorbtpro import *

data = vbt.BinanceData.pull(
    "BTCUSDT",
    start="2020-06-01 UTC",
    end="2022-06-01 UTC"
)
data.plot().show()

A quick visual inspection suggests the most apparent occurrence of this pattern was between October and December 2021:

data_window = data.loc["2021-09-25":"2021-11-25"]
data_window.plot(plot_volume=False).show()

As humans, we can easily detect patterns visually in data. But how can we accomplish this programmatically, where everything is represented by numbers? It would be costly, unnecessary, and likely ineffective to train a DNN for such a simple task. Following the principle "the simpler the algorithm, the better" for noisy data, we should design an algorithm that tackles the problem using simple loops and basic math.

Since each pattern is matched against a single feature of the data, we will use the typical price:

price_window = data_window.hlc3
price_window.vbt.plot().show()

Next, let's design the pattern. Price patterns are identified using a series of lines or curves. For example, the "Double Top" pattern can be represented by the following array:

pattern = np.array([1, 2, 3, 2, 3, 2])
pd.Series(pattern).vbt.plot().show()

It is important to note that the length and absolute values in the pattern definition do not matter. Whether the pattern scales from 1 to 3 or 1 to 60, it will be stretched horizontally and vertically to align with the corresponding price data. What matters for computation is the relative positioning of each point. For instance, the first point 2 comes exactly in the middle between 1 and 3, meaning if the asset rises in price to match the second point, it should ideally make the same move to reach the first peak. Furthermore, since some values like 2 and 3 repeat, we do not expect the price at those points to deviate significantly, which helps define support and resistance levels.

Another key rule relates to the horizontal structure of the pattern: regardless of the value at any given point, the location (timing) of a point is always relative to its neighboring points. For example, if the first point was matched on 2020-01-01 and the second on 2020-01-03, the third point should be matched on 2020-01-06. If any part of the pattern takes longer to form, changing the horizontal structure, a match becomes less likely.

Interpolation

Once we have defined our pattern, we need to ensure that both the pattern and the price array are the same length. In image processing, increasing the size of an image involves reconstructing the image by interpolating new pixels, while reducing the size involves downsampling the existing pixels. In pattern processing, the approach is similar, but we work with one-dimensional arrays instead of two-dimensional ones. We also prefer interpolation (stretching) over downsampling (shrinking) to avoid losing information. This means that if the price array is shorter than the pattern, it should be stretched to match the pattern's length, rather than compressing the pattern to fit the price.

There are four main interpolation modes in pattern processing: linear, nearest neighbor, discrete, and mixed. All of these are implemented using the Numba-compiled function interp_resize_1d_nb, which takes an array, a target size, and an interpolation mode of type InterpMode. The implementation is very efficient: it iterates through the array only once and does not require creating extra arrays except for the final output.

Linear

Chart patterns are a fundamental aspect of technical analysis. With VBT's excellent performance, you can detect chart patterns in your data using traditional methods, without needing to rely on costly machine learning models.

✅ Learn how to detect chart patterns, analyze them both visually and technically, combine multiple patterns to identify convergence, divergence, and other complex events, and convert them into a format suitable for backtesting.

✅ Learn how to analyze and visualize the impact of events on price movement using projections. Just like Toggle, but with unlimited customization and analysis capabilities.

Topics

Copyright © 20212026 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.