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% (367973 of 367973) |################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (40502 of 40502) |##################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (14648104 of 14648104) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 1/7 1s
100% (14648104 of 14648104) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 2/7 2s
100% (14648100 of 14648100) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 3/7 3s
100% (14648072 of 14648072) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 4/7 4s
100% (14647992 of 14647992) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 5/7 5s
100% (14647992 of 14647992) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 6/7 7s
100% (3588140 of 3588140) |##############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 7/7 7s
Data loaded 7s
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
2024-09-04 59.314591 0.000717 0.241497 -0.150600 -0.378042 1.013586 0.244778 1.0 218.0 0.168097 11.680150
2024-09-05 59.090863 -0.003772 0.241474 -0.153804 -0.378042 1.012399 0.244468 1.0 218.0 0.168062 11.680150
2024-09-06 58.766421 -0.005491 0.241453 -0.158450 -0.378042 1.010727 0.244043 1.0 218.0 0.168028 11.680150
2024-09-09 59.129089 0.006171 0.241430 -0.153257 -0.378042 1.012282 0.244395 1.0 218.0 0.167995 11.680150
2024-09-10 59.084880 -0.000748 0.241405 -0.153890 -0.378042 1.011942 0.244287 1.0 218.0 0.167980 11.694732
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 - 2024-09-10
Sharpe Ratio = 1.0119415494402122
Ok.
Check correlation.
WARNING! Can't calculate correlation.
Correlation check failed.
Write output: /root/fractions.nc.gz
In [5]:
weights
Out[5]:
<xarray.DataArray (time: 4703, asset: 256)>
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.34615385, 0.        , ..., 0.        , 0.        ,
        0.        ]])
Coordinates:
  * time     (time) datetime64[ns] 2006-01-03 2006-01-04 ... 2024-09-10
  * asset    (asset) <U10 'NAS:AAL' 'NAS:AAPL' ... 'NYS:RHT' 'NYS:TEVA'
In [6]:
data
Out[6]:
<xarray.DataArray 'stocks_nasdaq100' (field: 9, time: 4955, asset: 256)>
array([[[     nan,   1.1568,      nan, ...,  12.08  ,  13.41  ,
          29.81  ],
        [     nan,   1.1393,      nan, ...,  12.49  ,  13.05  ,
          29.2   ],
        [     nan,   1.1511,      nan, ...,  12.11  ,  12.6   ,
          27.97  ],
        ...,
        [ 10.78  , 223.95  , 116.37  , ...,  44.76  ,      nan,
          18.51  ],
        [ 10.85  , 220.82  , 115.11  , ...,  44.51  ,      nan,
          18.09  ],
        [ 11.21  , 218.92  , 117.01  , ...,  45.5   ,      nan,
          17.88  ]],

       [[     nan,   1.1179,      nan, ...,  11.9   ,  13.03  ,
          29.06  ],
        [     nan,   1.1245,      nan, ...,  11.97  ,  12.54  ,
          28.02  ],
        [     nan,   1.1438,      nan, ...,  11.97  ,  12.25  ,
          27.31  ],
...
        [  1.    ,   1.    ,   1.    , ...,   1.    ,      nan,
           1.    ],
        [  1.    ,   1.    ,   1.    , ...,   1.    ,      nan,
           1.    ],
        [  1.    ,   1.    ,   1.    , ...,   1.    ,      nan,
           1.    ]],

       [[     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.    ],
        [  0.    ,   1.    ,   1.    , ...,   0.    ,      nan,
           0.    ]]])
Coordinates:
  * time     (time) datetime64[ns] 2005-01-03 2005-01-04 ... 2024-09-10
  * asset    (asset) <U10 'NAS:AAL' 'NAS:AAPL' ... 'NYS:RHT' 'NYS:TEVA'
  * field    (field) object 'open' 'low' 'high' ... 'split_cumprod' 'is_liquid'