Indexes

Quantiacs provides up-to-date daily data for various stock market indices:


import qnt.data as qndata

index_data = qndata.index.load_data(min_date='2005-01-01')

['BKX', 'CELS', 'COMP', 'INDU', 'IXNDX', 'KRX', 'NBI',
 'NDX', 'NDXE', 'NDXT', 'NDXX', 'OEX', 'QNET', 'RUA',
 'RUI', 'RUT', 'SOX', 'SPX']
Number ID Name
1 SPX S&P 500
2 INDU Dow Industrials
3 NDX NASDAQ-100 Index
4 RUI Russell 1000
5 RUT Russell 2000
6 RUA Russell 3000
7 OEX S&P 100
8 COMP NASDAQ Composite Index
9 SOX PHLX Semiconductor Sector
10 NBI NASDAQ Biotechnology
11 BKX KBW Bank Index
12 KRX KBW Regional Banking Index
13 IXNDX NASDAQ-100
14 NDXT NASDAQ-100 Technology Sector Index
15 NDXX NASDAQ-100 Ex-Tech Sector Index
16 NDXE The NASDAQ-100 Equal Weighted Index
17 CELS NASDAQ Clean Edge Green Energy Index
18 QNET NASDAQ Internet Index

Examples

This example predicts stock market movements with SPX index data to build a trading strategy.

Single pass version for faster development

# import os
# os.environ['API_KEY'] = "{your_api_key_here}"  # you may need it for local development

# Import necessary libraries
import xarray as xr
import numpy as np
import qnt.data as qndata  # Load and manipulate data
import qnt.output as qnout  # Manage output
import qnt.stats as qnstats  # Statistical functions for analysis
import qnt.graph as qngraph  # Graphical tools
import qnt.ta as qnta  # Indicators library
import qnt.backtester as qnbt  # backtester
import qnt.exposure as qnexp


def strategy(data):
    close_stocks = data["stocks"].sel(field="close")
    close_spx = data["spx"]

    # Generate buy signal if 20-day SMA < 50-day SMA, otherwise hold (0) or sell (-1)
    accuracy = 0.00001  # to avoid floating point errors
    weights_stocks = xr.where(qnta.sma(close_stocks, 20) < qnta.sma(close_stocks, 50) + accuracy, 1, 0)
    weights_spx = xr.where(qnta.sma(close_spx, 20) < qnta.sma(close_spx, 60) + accuracy, 1, 0)
    weights = (weights_stocks + weights_spx) / 2

    # Apply liquidity filter
    is_liquid = data["stocks"].sel(field="is_liquid")
    weights = weights * is_liquid

    # Normalize positions and cut big positions
    weights_sum = abs(weights).sum('asset')
    weights = xr.where(weights_sum > 1, weights / weights_sum, weights)
    weights = qnexp.cut_big_positions(weights=weights, max_weight=0.049)

    return weights


min_date = "2005-06-01"

stocks = qndata.stocks.load_ndx_data(min_date=min_date)


def get_spx(stocks, min_date):
    index_data = qndata.index.load_data(assets=['SPX'], min_date=min_date)
    spx = index_data.sel(asset='SPX')
    # Align stocks and SPX data based on common time indices
    common_times = stocks.time.values
    spx = spx.sel(time=common_times)
    return spx


data_mix = {
    "stocks": stocks,
    "spx": get_spx(stocks, min_date)
}

weights = strategy(data_mix)

# Calc stats
stats = qnstats.calc_stat(stocks, weights.sel(time=slice("2005-12-30", None)))
display(stats.to_pandas().tail())

# Graph
performance = stats.to_pandas()["equity"]
import qnt.graph as qngraph

qngraph.make_plot_filled(performance.index, performance, name="PnL (Equity)", type="log")

weights = weights.sel(time=slice("2005-12-30", None))

qnout.check(weights, stocks, "stocks_nasdaq100", check_correlation=False)
qnout.write(weights)  # to participate in the competition

Multi-pass version

# import os
# os.environ['API_KEY'] = "{your_api_key_here}"  # you may need it for local development

# Import necessary libraries
import xarray as xr
import numpy as np
import qnt.data as qndata  # Load and manipulate data
import qnt.output as qnout  # Manage output
import qnt.stats as qnstats  # Statistical functions for analysis
import qnt.graph as qngraph  # Graphical tools
import qnt.ta as qnta  # Indicators library
import qnt.backtester as qnbt  # backtester
import qnt.exposure as qnexp


def load_data(period):
    """
    period (int): Number of days of data to load.
    """
    stocks = qndata.stocks.load_ndx_data(tail=period)
    index_data = qndata.index.load_data(assets=['SPX'], tail=period)
    spx = index_data.sel(asset='SPX')
    # Align stocks and SPX data based on common time indices
    common_times = stocks.time.values
    spx = spx.sel(time=common_times)
    return {"stocks": stocks, "spx": spx}, stocks.time.values


def window(data, max_date: np.datetime64, lookback_period: int):
    min_date = max_date - np.timedelta64(lookback_period, "D")
    return {
        "stocks": data["stocks"].sel(time=slice(min_date, max_date)),
        "spx": data["spx"].sel(time=slice(min_date, max_date))
    }


def strategy(data):
    close_stocks = data["stocks"].sel(field="close")
    close_spx = data["spx"]

    # Generate buy signal if 20-day SMA < 50-day SMA, otherwise hold (0) or sell (-1)
    accuracy = 0.00001  # to avoid floating point errors
    weights_stocks = xr.where(qnta.sma(close_stocks, 20) < qnta.sma(close_stocks, 50) + accuracy, 1, 0)
    weights_spx = xr.where(qnta.sma(close_spx, 20) < qnta.sma(close_spx, 60) + accuracy, 1, 0)
    weights = (weights_stocks + weights_spx) / 2

    # Apply liquidity filter
    is_liquid = data["stocks"].sel(field="is_liquid")
    weights = weights * is_liquid

    # Normalize positions and cut big positions
    weights_sum = abs(weights).sum('asset')
    weights = xr.where(weights_sum > 1, weights / weights_sum, weights)
    weights = qnexp.cut_big_positions(weights=weights, max_weight=0.049)

    return weights


# Multi-pass version
# Run backtest
weights_backtest = qnbt.backtest(
    competition_type="stocks_nasdaq100",
    load_data=load_data,
    lookback_period=120,
    start_date="2005-12-30",
    strategy=strategy,
    window=window,
    check_correlation=False
)