strategy

Q18 Quick Start Strategy

This template shows how to make a submission to the Q18 Nasdaq-100 contest and contains some useful code snippets.

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


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

Please note that:

  • Your trading algorithm can open short and long positions.

  • At each point in time your algorithm can trade all or a subset of the stocks which at that point of time are or were part of the NASDAQ-100 stock index. Note that the composition of this set changes in time, and Quantiacs provides you with an appropriate filter function for selecting them.

  • The Sharpe ratio of your system since January 1st, 2006, has to be larger than 1.

  • Your system cannot be a copy of the current examples. We run a correlation filter on the submissions and detect duplicates.

More details on the rules can be found here.

Need help? Check the Documentation and find solutions/report problems in the Forum section.

More help with Jupyter? Check the official Jupyter page.

Once you are done, click on Submit to the contest and take part to our competitions.

API reference:

  • data: check how to work with data;

  • backtesting: read how to run the simulation and check the results.

Need to use the optimizer function to automate tedious tasks?

  • optimization: read more on our article.
In [1]:
%%javascript
window.IPython && (IPython.OutputArea.prototype._should_scroll = function(lines) { return false; })
// disable widget scrolling
In [2]:
import xarray as xr

import qnt.ta as qnta
import qnt.backtester as qnbt
import qnt.data as qndata



def load_data(period):
    return qndata.stocks_load_ndx_data(tail=period)



def strategy(data):
    close     = data.sel(field="close")
    is_liquid = data.sel(field="is_liquid") # this field tags NASDAQ-100 stocks
    sma_slow  = qnta.sma(close, 200).isel(time=-1)
    sma_fast  = qnta.sma(close, 20).isel(time=-1)
    weights   = xr.where(sma_slow < sma_fast, 1, -1) # 1 - long position (**buy**), -1 - short position (**sell**)
    weights   = weights * is_liquid  # trade only NASDAQ-100 stocks
    weights   = weights / 100.0
    return weights



weights = qnbt.backtest(
    competition_type = "stocks_nasdaq100",
    load_data        = load_data,
    lookback_period  = 365*4,
    start_date       = "2006-01-01",
    strategy         = strategy,
    analyze          = True,
    build_plots      = True
)
Run last pass...
Load data...
100% (31314 of 31314) |##################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (19727 of 19727) |##################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (10457432 of 10457432) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 1/1 2s
Data loaded 2s
Run strategy...
Load data for cleanup...
100% (417364 of 417364) |################| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 1/1 2s
Data loaded 2s
Output cleaning...
fix uniq
ffill if the current price is None...
Check liquidity...
Ok.
Check missed dates...
Ok.
Normalization...
Output cleaning is complete.
Write result...
Write output: /root/fractions.nc.gz
---
Run first pass...
Load data...
100% (14535 of 14535) |##################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (7628792 of 7628792) |##############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 1/1 1s
Data loaded 1s
Run strategy...
---
Load full data...
100% (34173 of 34173) |##################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (14862360 of 14862360) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 1/7 1s
100% (14862360 of 14862360) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 2/7 1s
100% (14862332 of 14862332) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 3/7 2s
100% (14862252 of 14862252) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 4/7 3s
100% (14885324 of 14885324) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 5/7 4s
100% (15107472 of 15107472) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 6/7 5s
100% (2247380 of 2247380) |##############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 7/7 5s
Data loaded 5s
---
Run iterations...

100% (4228 of 4228) |####################| Elapsed Time: 0:03:09 Time:  0:03:09
Merge outputs...
Load data for cleanup and analysis...
100% (35337 of 35337) |##################| Elapsed Time: 0:00:00 Time:  0:00:00
100% (14601000 of 14601000) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 1/7 1s
100% (14601000 of 14601000) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 2/7 2s
100% (14600972 of 14600972) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 3/7 3s
100% (14600896 of 14600896) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 4/7 4s
100% (14626204 of 14626204) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 5/7 5s
100% (14626204 of 14626204) |############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 6/7 6s
100% (8000784 of 8000784) |##############| Elapsed Time: 0:00:00 Time:  0:00:00
fetched chunk 7/7 7s
Data loaded 7s
Output cleaning...
fix uniq
ffill if the current price is None...
Check liquidity...
Ok.
Check missed dates...
Ok.
Normalization...
Output cleaning is complete.
Write result...
Write output: /root/fractions.nc.gz
---
Analyze results...
Check...
Check liquidity...
Ok.
Check missed dates...
Ok.
Check the sharpe ratio...
Period: 2006-01-01 - 2022-06-16
Sharpe Ratio = 0.050513380697975875
ERROR! The Sharpe Ratio is too low. 0.050513380697975875 < 1
Improve the strategy and make sure that the in-sample Sharpe Ratio more than 1.
Check correlation.

Ok. This strategy does not correlate with other strategies.
---
Align...
Calc global stats...
---
Calc stats per asset...
Build plots...
---
Output:
asset NAS:AAL NAS:AAPL NAS:ABNB NAS:ADBE NAS:ADCT NAS:ADI NAS:ADP NAS:ADSK NAS:AEP NAS:AKAM
time
2022-06-03 -0.0 -0.008475 -0.008475 -0.008475 0.0 -0.008475 -0.008475 -0.008475 0.008475 -0.0
2022-06-06 -0.0 -0.008475 -0.008475 -0.008475 0.0 -0.008475 -0.008475 -0.008475 0.008475 -0.0
2022-06-07 -0.0 -0.008475 -0.008475 -0.008475 0.0 -0.008475 -0.008475 -0.008475 0.008475 -0.0
2022-06-08 -0.0 -0.008475 -0.008475 -0.008475 0.0 -0.008475 -0.008475 -0.008475 0.008475 -0.0
2022-06-09 -0.0 -0.008403 -0.008403 -0.008403 0.0 -0.008403 -0.008403 -0.008403 0.008403 -0.0
2022-06-10 -0.0 -0.008403 -0.008403 -0.008403 0.0 -0.008403 -0.008403 -0.008403 0.008403 -0.0
2022-06-13 -0.0 -0.008403 -0.008403 -0.008403 0.0 -0.008403 -0.008403 -0.008403 0.008403 -0.0
2022-06-14 -0.0 -0.008403 -0.008403 -0.008403 0.0 -0.008403 -0.008403 -0.008403 0.008403 -0.0
2022-06-15 -0.0 -0.008403 -0.008403 -0.008403 0.0 -0.008403 -0.008403 -0.008403 0.008403 -0.0
2022-06-16 -0.0 -0.008403 -0.008403 -0.008403 0.0 -0.008403 -0.008403 -0.008403 0.008403 -0.0
Stats:
field equity relative_return volatility underwater max_drawdown sharpe_ratio mean_return bias instruments avg_turnover avg_holding_time
time
2022-06-03 1.041811 0.014427 0.131682 -0.191308 -0.399356 0.018945 0.002495 -0.491525 227.0 0.030935 99.607283
2022-06-06 1.038814 -0.002877 0.131668 -0.193635 -0.399356 0.017608 0.002318 -0.474576 227.0 0.030931 99.607283
2022-06-07 1.030980 -0.007541 0.131666 -0.199715 -0.399356 0.014102 0.001857 -0.457627 227.0 0.030939 99.695373
2022-06-08 1.033529 0.002472 0.131651 -0.197737 -0.399356 0.015242 0.002007 -0.457627 227.0 0.030939 99.703118
2022-06-09 1.048846 0.014820 0.131686 -0.185847 -0.399356 0.022040 0.002902 -0.478992 228.0 0.030937 99.703118
2022-06-10 1.075849 0.025745 0.131823 -0.164887 -0.399356 0.033771 0.004452 -0.478992 228.0 0.030948 99.725203
2022-06-13 1.104886 0.026990 0.131974 -0.142347 -0.399356 0.046046 0.006077 -0.478992 228.0 0.030955 99.725203
2022-06-14 1.103115 -0.001603 0.131959 -0.143722 -0.399356 0.045298 0.005978 -0.478992 228.0 0.030951 99.725203
2022-06-15 1.086516 -0.015047 0.131996 -0.156606 -0.399356 0.038262 0.005050 -0.529412 228.0 0.030948 99.725203
2022-06-16 1.115839 0.026988 0.132147 -0.133845 -0.399356 0.050513 0.006675 -0.529412 228.0 0.030960 103.962713