strategy

Technical Analysis using trix, ema

Predicting stocks using technical indicators (trix, ema)

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


This template shows you the basic steps for taking part to the NASDAQ-100 Stock Long-Short contest.

In [1]:
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 multi_trix_v3(data, params):
    s_ = qnta.trix(data.sel(field='high'), params[0])
    w_1 = s_.shift(time=params[1]) > s_.shift(time=params[2])
    w_2 = s_.shift(time=params[3]) > s_.shift(time=params[4])
    weights = (w_1 * w_2) * data.sel(field="is_liquid")
    return weights.fillna(0)


def multi_ema_v3(data, params):
    s_ = qnta.ema(data.sel(field='high'), params[0])
    w_1 = s_.shift(time=params[1]) > s_.shift(time=params[2])
    w_2 = s_.shift(time=params[3]) > s_.shift(time=params[4])
    weights = (w_1 * w_2) * data.sel(field="is_liquid")
    return weights.fillna(0)


def multi_ema_v4(data, params):
    s_ = qnta.trix(data.sel(field='high'), 30)
    w_1 = s_.shift(time=params[0]) > s_.shift(time=params[1])
    s_ = qnta.ema(data.sel(field='high'), params[2])
    w_2 = s_.shift(time=params[3]) > s_.shift(time=params[4])
    weights = (w_1 * w_2) * data.sel(field="is_liquid")
    return weights.fillna(0)


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

weights_1 = multi_trix_v3(data, [87, 135, 108, 13, 114])
weights_2 = multi_trix_v3(data, [89, 8, 101, 148, 36])
weights_3 = multi_trix_v3(data, [196, 125, 76, 12, 192])
weights_4 = multi_ema_v3(data, [69, 47, 57, 7, 41])

weights_f = (weights_1 + weights_2) * weights_3 * weights_4

weights_5 = multi_trix_v3(data, [89, 139, 22, 8, 112])
weights_6 = multi_trix_v3(data, [92, 139, 20, 10, 110])
weights_7 = multi_ema_v4(data, [13, 134, 42, 66, 133])

weights_t = (weights_5 + weights_6) * weights_7 + weights_3

weights_all = 4 * weights_f + weights_t
100% (364802 of 364802) |################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (38058 of 38058) |##################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (14589748 of 14589748) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 1/6 1s
ERROR:root:download error: data
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/qnt/data/common.py", line 79, in request_with_retry
    with urllib.request.urlopen(req, timeout=TIMEOUT) as response:
  File "/usr/local/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.7/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/local/lib/python3.7/urllib/request.py", line 641, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/local/lib/python3.7/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
ERROR:root:download error: data
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/qnt/data/common.py", line 79, in request_with_retry
    with urllib.request.urlopen(req, timeout=TIMEOUT) as response:
  File "/usr/local/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.7/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/local/lib/python3.7/urllib/request.py", line 641, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/local/lib/python3.7/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
ERROR:root:download error: data
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/qnt/data/common.py", line 79, in request_with_retry
    with urllib.request.urlopen(req, timeout=TIMEOUT) as response:
  File "/usr/local/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.7/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/local/lib/python3.7/urllib/request.py", line 641, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/local/lib/python3.7/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
ERROR:root:download error: data
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/qnt/data/common.py", line 79, in request_with_retry
    with urllib.request.urlopen(req, timeout=TIMEOUT) as response:
  File "/usr/local/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.7/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/local/lib/python3.7/urllib/request.py", line 641, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/local/lib/python3.7/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
ERROR:root:download error: data
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/qnt/data/common.py", line 79, in request_with_retry
    with urllib.request.urlopen(req, timeout=TIMEOUT) as response:
  File "/usr/local/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.7/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/local/lib/python3.7/urllib/request.py", line 641, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/local/lib/python3.7/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
ERROR:root:download error: data
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/qnt/data/common.py", line 79, in request_with_retry
    with urllib.request.urlopen(req, timeout=TIMEOUT) as response:
  File "/usr/local/lib/python3.7/urllib/request.py", line 222, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.7/urllib/request.py", line 531, in open
    response = meth(req, response)
  File "/usr/local/lib/python3.7/urllib/request.py", line 641, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/local/lib/python3.7/urllib/request.py", line 569, in error
    return self._call_chain(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 503, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.7/urllib/request.py", line 649, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
100% (14592844 of 14592844) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 2/6 9s
100% (14586616 of 14586616) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 3/6 10s
100% (14586532 of 14586532) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 4/6 12s
100% (14586532 of 14586532) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 5/6 13s
100% (9843808 of 9843808) |##############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 6/6 14s
Data loaded 15s
In [2]:
def get_enough_bid_for(weights_):
    time_traded = weights_.time[abs(weights_).fillna(0).sum('asset') > 0]
    is_strategy_traded = len(time_traded)
    if is_strategy_traded:
        return xr.where(weights_.time < time_traded.min(), data.sel(field="is_liquid"), weights_)
    return weights_


weights_new = get_enough_bid_for(weights_all)
weights_new = weights_new.sel(time=slice("2006-01-01",None))

weights = qnout.clean(output=weights_new, data=data, kind="stocks_nasdaq100")
Output cleaning...
fix uniq
ffill if the current price is None...
Check liquidity...
Ok.
Check missed dates...
Ok.
Normalization...
Output cleaning is complete.
In [3]:
def print_statistic(data, weights_all):
    import qnt.stats as qnstats

    stats = qnstats.calc_stat(data, weights_all)
    display(stats.to_pandas().tail(5))
    # graph
    performance = stats.to_pandas()["equity"]
    import qnt.graph as qngraph

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

print_statistic(data, weights)
field equity relative_return volatility underwater max_drawdown sharpe_ratio mean_return bias instruments avg_turnover avg_holding_time
time
2023-09-07 58.195159 -0.001861 0.243315 -0.161846 -0.378936 1.063225 0.258698 1.0 212.0 0.170881 11.393912
2023-09-08 58.099162 -0.001650 0.243288 -0.163229 -0.378936 1.062590 0.258516 1.0 212.0 0.170844 11.393912
2023-09-11 58.542635 0.007633 0.243266 -0.156841 -0.378936 1.064647 0.258992 1.0 212.0 0.170807 11.393912
2023-09-12 58.269490 -0.004666 0.243243 -0.160775 -0.378936 1.063113 0.258594 1.0 212.0 0.170841 11.393387
2023-09-13 58.269490 0.000000 0.243215 -0.160775 -0.378936 1.062965 0.258529 0.0 212.0 0.170802 11.417058
In [4]:
weights = weights.sel(time=slice("2006-01-01",None))

qnout.check(weights, data, "stocks_nasdaq100")
qnout.write(weights) # to participate in the competition
Check liquidity...
Ok.
Check missed dates...
Ok.
Check the sharpe ratio...
Period: 2006-01-01 - 2023-09-13
Sharpe Ratio = 1.0629647513153482
Ok.
Check correlation.

Ok. This strategy does not correlate with other strategies.
Write output: /root/fractions.nc.gz
In [5]:
weights
Out[5]:
<xarray.DataArray (time: 4455, asset: 244)>
array([[0.        , 0.01123596, 0.        , ..., 0.        , 0.01123596,
        0.01123596],
       [0.        , 0.01190476, 0.        , ..., 0.        , 0.01190476,
        0.01190476],
       [0.        , 0.01190476, 0.        , ..., 0.        , 0.01190476,
        0.01190476],
       ...,
       [0.        , 0.        , 0.        , ..., 0.        , 0.        ,
        0.        ],
       [0.        , 0.        , 0.        , ..., 0.        , 0.        ,
        0.        ],
       [0.        , 0.        , 0.        , ..., 0.        , 0.        ,
        0.        ]])
Coordinates:
  * time     (time) datetime64[ns] 2006-01-03 2006-01-04 ... 2023-09-13
  * asset    (asset) <U10 'NAS:AAL' 'NAS:AAPL' ... 'NYS:RHT' 'NYS:TEVA'
In [6]:
data
Out[6]:
<xarray.DataArray 'stocks_nasdaq100' (field: 9, time: 4707, asset: 244)>
array([[[     nan,   1.1582,      nan, ...,  11.6   ,  13.41  ,
          29.81  ],
        [     nan,   1.1384,      nan, ...,  11.99  ,  13.05  ,
          29.2   ],
        [     nan,   1.1518,      nan, ...,  11.63  ,  12.6   ,
          27.97  ],
        ...,
        [ 14.02  , 180.07  , 146.22  , ...,  41.96  ,      nan,
           9.74  ],
        [ 14.19  , 179.49  , 146.88  , ...,  42.29  ,      nan,
          10.05  ],
        [     nan,      nan, 146.    , ...,  41.69  ,      nan,
              nan]],

       [[     nan,   1.1179,      nan, ...,  11.42  ,  13.03  ,
          29.06  ],
        [     nan,   1.1245,      nan, ...,  11.49  ,  12.54  ,
          28.02  ],
        [     nan,   1.1437,      nan, ...,  11.49  ,  12.25  ,
          27.31  ],
...
        [  1.    ,   1.    ,   1.    , ...,   1.    ,      nan,
           1.    ],
        [  1.    ,   1.    ,   1.    , ...,   1.    ,      nan,
           1.    ],
        [     nan,      nan,   1.    , ...,   1.    ,      nan,
              nan]],

       [[     nan,   1.    ,      nan, ...,   0.    ,   0.    ,
           1.    ],
        [     nan,   1.    ,      nan, ...,   0.    ,   0.    ,
           1.    ],
        [     nan,   1.    ,      nan, ...,   0.    ,   0.    ,
           1.    ],
        ...,
        [  0.    ,   1.    ,   1.    , ...,   0.    ,      nan,
           0.    ],
        [  0.    ,   1.    ,   1.    , ...,   0.    ,      nan,
           0.    ],
        [     nan,      nan,   1.    , ...,   0.    ,      nan,
              nan]]])
Coordinates:
  * time     (time) datetime64[ns] 2005-01-03 2005-01-04 ... 2023-09-13
  * asset    (asset) <U10 'NAS:AAL' 'NAS:AAPL' ... 'NYS:RHT' 'NYS:TEVA'
  * field    (field) object 'open' 'low' 'high' ... 'split_cumprod' 'is_liquid'