Skip to main content

A simple quant strategy creation and backtesting package.

Project description

Quantex

Quantex is a Python library for writing trading strategies and replaying them on historical market data.

It gives you a small set of building blocks:

The project is intentionally small. It does not try to be a full research platform, portfolio database, or live-trading engine. Instead, it focuses on a straightforward workflow: load historical bars, define strategy logic, simulate orders, and inspect the results.

Installation

Quantex requires Python 3.10 or newer and is published as quantex.

pip install quantex

What the library actually does

At runtime, a typical Quantex workflow looks like this:

  1. Create a strategy class by inheriting from Strategy.
  2. In Strategy.init(), attach one or more data sources with Strategy.add_data().
  3. Still in Strategy.init(), build indicator arrays with the built-in indicator catalog on self.ta or the package-level indicators, then register them with Strategy.Indicator().
  4. In Strategy.next(), read the current bar through properties such as DataSource.COpen and DataSource.CClose, then place orders through the broker stored in Strategy.positions.
  5. Run the strategy with SimpleBacktester.run().
  6. Inspect the returned BacktestReport, including BacktestReport.total_return, BacktestReport.periods_per_year, BacktestReport.plot(), and the printable summary from BacktestReport.__str__().

Usage

The example below assumes no prior knowledge of the library.

1. Prepare a data file

Quantex expects historical bar data with these columns:

  • Open
  • High
  • Low
  • Close
  • Volume

The first column in a CSV file is typically the timestamp index used by CSVDataSource.

Example:

Date,Open,High,Low,Close,Volume
2024-01-01,100,101,99,100.5,1500
2024-01-02,100.5,102,100,101.8,1700
2024-01-03,101.8,103,101,102.6,1650

2. Write a strategy

from quantex import Strategy, CSVDataSource, SimpleBacktester
import pandas as pd


class MovingAverageCross(Strategy):
    def __init__(self, fast_period=5, slow_period=20):
        super().__init__()
        self.fast_period = fast_period
        self.slow_period = slow_period

    def init(self):
        data = CSVDataSource("data.csv")
        self.add_data(data, "TEST")

        close = self.data["TEST"].Close
        self.fast_ma = self.Indicator(self.ta.sma(close, self.fast_period))
        self.slow_ma = self.Indicator(self.ta.sma(close, self.slow_period))

    def next(self):
        if len(self.fast_ma) < 2 or len(self.slow_ma) < 2:
            return

        broker = self.positions["TEST"]

        crossed_up = self.fast_ma[-2] <= self.slow_ma[-2] and self.fast_ma[-1] > self.slow_ma[-1]
        crossed_down = self.fast_ma[-2] >= self.slow_ma[-2] and self.fast_ma[-1] < self.slow_ma[-1]

        if crossed_up and broker.is_closed():
            broker.buy(quantity=1.0)
        elif crossed_down and broker.is_long():
            broker.close()

3. Run a backtest

strategy = MovingAverageCross(fast_period=5, slow_period=20)
backtester = SimpleBacktester(strategy, cash=10_000)
report = backtester.run()

print(report)
report.plot()

4. Understand what happens during the backtest

When you call SimpleBacktester.run():

5. Understand order sizing

Order sizing in Quantex is simple but important:

  • Broker.buy() treats quantity as a fraction of available cash unless you pass amount
  • Broker.sell() uses the same sizing calculation and can open or increase a short position
  • Broker.close() places a market order that offsets the current position

Because of this design, buy(0.5) means “use roughly half of the broker cash for this symbol”, not “buy half a share”.

Core concepts

Strategy

Your strategy is a class that implements two methods:

Data sources

DataSource wraps a pandas DataFrame and exposes both full history and current-bar values.

Indicators

Strategy now exposes a built-in technical analysis catalog at self.ta, and the package exports the same catalog as quantex.indicators.

Included indicators cover trend, momentum, volatility, volume, and more advanced studies, including:

  • moving averages: sma, ema, wma, dema, tema, kama
  • momentum and oscillators: rsi, stochastic_oscillator, cci, williams_r, roc, momentum, trix, fisher_transform, ultimate_oscillator
  • volatility and channels: atr, bollinger_bands, keltner_channels, donchian_channels, volatility
  • volume and trend strength: obv, mfi, adx, aroon, vortex
  • advanced and research-oriented tools: ichimoku_cloud, zscore, sharpe_ratio, sortino_ratio, hurst_exponent, linear_regression_slope

Strategy.Indicator() still wraps each NumPy array in TimeNDArray, which only exposes data up to the current bar.

Example:

from quantex import Strategy, CSVDataSource, SimpleBacktester


class MacdTrendStrategy(Strategy):
    def init(self):
        self.add_data(CSVDataSource("data.csv"), "TEST")
        close = self.data["TEST"].Close

        self.ema_20 = self.Indicator(self.ta.ema(close, 20))
        self.rsi_14 = self.Indicator(self.ta.rsi(close, 14))
        macd_line, macd_signal, _ = self.ta.macd(close)
        self.macd_line = self.Indicator(macd_line)
        self.macd_signal = self.Indicator(macd_signal)

Broker and orders

Each call to Strategy.add_data() also creates a Broker for that symbol.

Supported order behavior in the current codebase:

  • market orders and limit orders via OrderType
  • pending, active, and complete order states via OrderStatus
  • optional stop-loss and take-profit triggers stored on Order
  • percentage or cash commissions via CommissionType

Optimization

SimpleBacktester.optimize() runs a grid search over every parameter combination you provide.

SimpleBacktester.optimize_parallel() does the same work in multiple processes, then re-runs the best parameter set locally to produce a full BacktestReport.

Minimal example:

params = {
    "fast_period": range(5, 11),
    "slow_period": range(15, 31, 5),
}

best_params, best_report, results = backtester.optimize(
    params,
    constraint=lambda p: p["fast_period"] < p["slow_period"],
)

print(best_params)
print(best_report)
print(results.head())

Documentation

Project documentation is built with MkDocs. The main docs entry point is docs/index.md, and usage guides live under docs/usage/.

Published documentation: https://dangreen07.github.io/quantex/

Development

The package metadata and dependencies are defined in pyproject.toml.

Typical local workflow:

poetry install
poetry run pytest
poetry run pre-commit install

Tests in tests/test_backtester.py, tests/test_broker.py, tests/test_datasource.py, and tests/test_strategy.py are useful references for the library's current behavior.

License

See LICENSE.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

quantex-0.3.1.tar.gz (33.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

quantex-0.3.1-py3-none-any.whl (33.4 kB view details)

Uploaded Python 3

File details

Details for the file quantex-0.3.1.tar.gz.

File metadata

  • Download URL: quantex-0.3.1.tar.gz
  • Upload date:
  • Size: 33.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.13.1 Windows/11

File hashes

Hashes for quantex-0.3.1.tar.gz
Algorithm Hash digest
SHA256 6bf3951c78b4bcd4aca5e93702b745db93b77891a5472dced5642a32ca6eb7c5
MD5 cedfb84d1259f8a46707b0d7943fe5a9
BLAKE2b-256 c8d85dab6c2bd2912caf8df26c52819eac6a9189d5b3138bb32553c284cc5248

See more details on using hashes here.

File details

Details for the file quantex-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: quantex-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 33.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.13.1 Windows/11

File hashes

Hashes for quantex-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4c22a9e6ae97b5af6e338b7eb35c7e7ce5a1540f5320fd5329026449d59e1d4b
MD5 5e3cc1fa8d5d4f5e4560f30b7bde950a
BLAKE2b-256 f9f4286d09e17e34693040f503a321fe86b3655e15fdb684ac9e9fc1bb74ccd3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page