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 demonstrates predicting the stock market using SPX index data to develop 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
)