Notebook

Q18 Technical Analysis using Index Data

This strategy uses the SP500 index data and technical indicators to trade NASDAQ stocks.

You can clone and edit this example there (tab Examples).


Predicting stocks from the NASDAQ 100 index using the SPX index and technical analysis indicators

In [ ]:
from IPython.display import display
import xarray as xr
import qnt.data as qndata
import qnt.output as qnout
import qnt.ta as qnta
import qnt.stats as qns


def get_SPX(market_data):
    index_name = 'SPX'
    index_data = qndata.index.load_data(assets=[index_name], min_date='2005-01-01', forward_order=True)
    spx_data = index_data.sel(asset=index_name)
    spx_data = xr.align(spx_data, market_data.isel(field=0), join='right')[0]
    return spx_data


def get_strategy_1(data, spx, params):
    def get_trix(prices, index, periods):
        result = prices.copy(True)
        t = qnta.trix(index, periods)
        for a in prices.asset.values:
            result.loc[{"asset": a}] = t
        return result

    trix = get_trix(data.sel(field='close'), spx, 40)

    strategy_1 = trix.shift(time=params[0]) < trix.shift(time=params[1])
    strategy_2 = trix.shift(time=params[2]) > trix.shift(time=params[3])

    weights = strategy_1 * strategy_2 * data.sel(field="is_liquid")
    return weights.fillna(0)


def get_strategy_2(data, spx, params):
    def get_rsi(prices, index, periods):
        result = prices.copy(True)
        r = qnta.rsi(index, periods)
        for a in prices.asset.values:
            result.loc[{"asset": a}] = r
        return result

    rsi = get_rsi(data.sel(field='close'), spx, 40)

    strategy_1 = rsi.shift(time=params[0]) < rsi.shift(time=params[1])
    strategy_2 = rsi.shift(time=params[2]) > rsi.shift(time=params[3])

    weights = strategy_1 * strategy_2 * data.sel(field="is_liquid")
    return weights.fillna(0)


def get_strategy_3(data, spx, params):
    def get_roc(prices, index, periods):
        result = prices.copy(True)
        r = qnta.roc(index, periods)
        for a in prices.asset.values:
            result.loc[{"asset": a}] = r
        return result

    roc = get_roc(data.sel(field='close'), spx, 15)

    strategy_1 = roc.shift(time=params[0]) < roc.shift(time=params[1])
    strategy_2 = roc.shift(time=params[2]) > roc.shift(time=params[3])

    weights = strategy_1 * strategy_2 * data.sel(field="is_liquid")
    return weights.fillna(0)


data = qndata.stocks.load_ndx_data(min_date="2005-01-01")
spx = get_SPX(data)

weights_1_1 = get_strategy_1(data, spx, [142, 54, 132, 63])  # 1.0330127484868614 Sharpe Ratio
weights_1_2 = get_strategy_1(data, spx, [166, 75, 46, 24])  # 0.9591131817092265 Sharpe Ratio
weights_2 = get_strategy_2(data, spx, [159, 78, 77, 167])  # 0.8568070000760702 Sharpe Ratio
weights_3 = get_strategy_3(data, spx, [10, 27, 29, 41])  # 0.835419 Sharpe Ratio

weights_all = weights_1_1 + weights_1_2 + weights_2 + weights_3
weights = qnout.clean(output=weights_all, data=data, kind="stocks_nasdaq100")


def print_statistic(data, weights_all):
    import plotly.graph_objs as go
    import qnt.stats as qnstats

    stats = qnstats.calc_stat(data, weights_all)
    display(stats.to_pandas().tail(5))

    equity_curve = stats.loc[:, "equity"]
    fig = go.Figure(data=[
        go.Scatter(
            x=equity_curve.time.to_pandas(),
            y=equity_curve,
            hovertext="Equity curve",
        )
    ])
    fig.update_yaxes(fixedrange=False)
    fig.show()


print_statistic(data, weights)
In [ ]:
qnout.check(weights, data, "stocks_nasdaq100")
qnout.write(weights)

Example of a strategy using technical analysis indicators

The example of a strategy with a sharpe ratio of 0.9615 trading 215 financial instruments

The strategy use sma, ema, adl (Advance–Decline line)

from IPython.display import display
import xarray as xr
import qnt.data as qndata
import qnt.output as qnout
import qnt.ta as qnta
import qnt.stats as qns

data = qndata.stocks.load_ndx_data(min_date="2005-01-01")


def get_strategy_1(data, params):
    buy = 1
    not_trade = 0
    close = data.sel(field="close")

    strategy_1 = xr.where(qnta.sma(close, params[1]) > qnta.sma(close, params[0]), buy, not_trade)
    strategy_2 = xr.where(qnta.ema(close, params[2]) > qnta.ema(close, params[3]), buy, not_trade)

    weights = strategy_1 * strategy_2 * data.sel(field="is_liquid")
    weights = weights / 100.0
    return weights.fillna(0)


def get_strategy_2(data, params):
    buy = 1
    not_trade = 0
    close = data.sel(field="close") * data.sel(field="is_liquid")

    adl = qnta.ad_line(close) * 1.0
    adl_dif = adl.shift(time=params[0]) - adl.shift(time=params[1])
    positive_trend = adl_dif > 0
    strategy_1 = xr.where(positive_trend, buy, not_trade)

    weights = strategy_1 * data.sel(field="is_liquid")
    return weights.fillna(0)


weights_1 = get_strategy_1(data, [25, 40, 12, 132])  # 0.6108887689714039 Sharpe Ratio
weights_2 = get_strategy_2(data, [34, 183])  # 0.6012686822757577

weights_all = 2 * weights_1 * weights_2 - weights_1
weights = qnout.clean(output=weights_all, data=data, kind="stocks_nasdaq100")  # 0.9615

# qnout.check(weights, data, "stocks_nasdaq100")
qnout.write(weights)