Navigation

    Quantiacs Community

    • Register
    • Login
    • Search
    • Categories
    • News
    • Recent
    • Tags
    • Popular
    • Users
    • Groups

    Optimizing and Monitoring a Trading System with Quantiacs

    News and Feature Releases
    1
    1
    618
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • news-quantiacs
      news-quantiacs last edited by support

      *This article was published on Medium: check it out here.

      In this article we describe the implementation of a new tool we released for the Quantiacs Python toolbox: a fast optimizer for testing the robustness of a trading system.*

      As Donald Knuth pointed out, “Premature optimization is the root of all evil.” This is a famous saying among software developers and it is true also in the context of trading system development.

      jefferson-santos-9SoCnyQmkzI-unsplash (1).jpg
      Photo by Jefferson Santos on Unsplash

      It is very tempting to write an algorithm, a simple trend-following strategy or a more refined machine-learning based system, and then to search for optimal parameters or hyperparameters which are going to maximize a given score function, normally the Sharpe ratio.

      As optimal parameters are maximizing the chosen score function in the past, and financial data are very noisy, the usual result of parameter optimization is overfitting: the trading system works so well with past data that it becomes useless for predicting future market moves.

      The problem of inflating the simulated performance of a trading system extends beyond backtest optimizers: for example, developers tend to focus and report only on positive outcomes out of all the models they try, an issue known as selection bias. For a detailed description of these problems we refer to the 2014 article by Marcos Lopez de Prado.

      Nevertheless, optimizers rely on a basic functionality which can be used for testing the robustness of a trading system: a grid scan of the system over possible combinations of the parameters. The results of the scan can be used to visualize and test how much the performance of the trading system is sensitive to the parameter choice. A robust system will have a good Sharpe ratio for a wide range of the independent parameters.

      Trading System Optimization with Quantiacs

      You can find our optimizer in the Examples section of the Development area of your account:

      Screenshot from 2021-03-16 11-04-37.png

      For running the example, simply click on the Clone button and work in your favourite environment, Jupyter Notebook or JupyterLab. Alternatively you can download locally the Quantiacs toolbox and take advantage of parallelization on your own machine.

      Let us analyze the code. First of all we import the needed libraries:

      import qnt.data as qndata
      import qnt.ta as qnta
      import qnt.output as qnout
      import qnt.stats as qns
      import qnt.log as qnlog
      import qnt.optimizer as qnop
      import qnt.backtester as qnbt
      
      import xarray as xr
      

      In addition to the Quantiacs library, freely available at our GitHub page, we import xarray for quick processing of multi-dimensional data structures.

      Next we define a simple trading rule based on two parameters. The strategy is going long only when the rate of change in the last "roc_period" trading days (in this case 10) of the linear-weighted moving average over the last "wma_period" trading days (in this case 20) is positive:

      def single_pass_strategy(data, wma_period=20, roc_period=10):
          wma = qnta.lwma(data.sel(field='close'), wma_period)
          sroc = qnta.roc(wma, roc_period)
          weights = xr.where(sroc > 0, 1, 0)
          weights = weights / len(data.asset)
          with qnlog.Settings(info=False, err=False):
              weights = qnout.clean(weights, data, debug=False)
          return weights
      

      The strategy returns allocation weights (fraction of capital to be invested) for every day. We check the performance of this strategy with the chosen parameters:

      data = qndata.futures.load_data(min_date='2004-01-01')
      single_pass_output = single_pass_strategy(data)
      single_pass_stat = qns.calc_stat(data,\
          single_pass_output.sel(time=slice('2006-01-01', None)))
      display(single_pass_stat.to_pandas().tail())
      

      The code returns the values of the relevant statistical indicators, including the Sharpe ratio, in a table, since beginning of the in-sample period:

      Screenshot from 2021-03-16 11-16-21.png

      Next we run the optimization code, which performs a scan over a predefined range of parameter values: the user can choose for each parameter the starting value, the final one and the step:

      data = qndata.futures.load_data(min_date='2004-01-01')
      
      result = qnop.optimize_strategy(
          data,
          single_pass_strategy,
          qnop.full_range_args_generator(
              wma_period=range(10, 150, 5), # min, max, step
              roc_period=range(5, 100, 5)   # min, max, step
          ),
          workers=1 # you can set more workers on your PC
      )
      
      qnop.build_plot(result)
      
      print("---")
      print("Best iteration:")
      display(result['best_iteration'])
      

      The code returns an interactive plot where one can analyze the dependence of the key statistical indicators on the parameters. In this plot we display the two independent parameters on the x and y axis, the Sharpe ratio value on he z axis and use different colors according to the maximum drawdown.

      Screenshot from 2021-03-16 11-19-23.png

      As a reference, we display the optimal values of the parameters which maximize the Sharpe ratio (beware of overfitting!):

      Screenshot from 2021-03-16 11-20-50.png

      A robust trading system will have a smooth dependence of the Sharpe ratio on the parameter values, ideally with good values larger than 1 for a wide choice of the parameters. An overfitted system will display typically a Sharpe ratio peak for a particular choice of the independent parameters.

      Do you have questions or suggestions? Post them in our Forum or write us to info@quantiacs.com!

      You can try the optimizer on Quantiacs. The code can be found in the Examples section of the Development area of your account. Or you can download the full code from our GitHub repository.

      1 Reply Last reply Reply Quote 0
      • First post
        Last post
      Powered by NodeBB | Contributors
      • Documentation
      • About
      • Career
      • My account
      • Privacy policy
      • Terms and Conditions
      • Cookies policy
      Home
      Copyright © 2014 - 2021 Quantiacs LLC.
      Powered by NodeBB | Contributors