Optimize your Trading System with Quantiacs

May, 07 2020

The Quantiacs toolbox allows you to modify your trading system with minimal effort. You are able to run your strategy on an array of different parameters, and evaluate different versions of the same system.

Parametric scans are integral for Quants: they allow finding optimal parameters which maximize key figures like the Sharpe ratio, and studying the stability of the trading system when parameters are changed.

Let us have a look at the full strategy again:

import numpy

def myTradingSystem(DATE, OPEN, HIGH, LOW, CLOSE, VOL, exposure, equity, settings):
    '''This system uses trend following techniques to allocate capital into the desired equities.'''

    nMarkets= CLOSE.shape[1]
    perL= 200
    perS= 40
    smaLong  = numpy.nansum(CLOSE[-perL:, :], axis=0)/perL
    smaRecent= numpy.nansum(CLOSE[-perS:, :], axis=0)/perS
    longEquity= smaRecent > smaLong
    shortEquity= ~longEquity
    pos= numpy.zeros(nMarkets)
    pos[longEquity]= 1
    pos[shortEquity]= -1
    weights = pos/numpy.nansum(abs(pos))
    return weights, settings

def mySettings():

    '''Define your trading system settings here.'''
    settings= {}
    # selected Futures contracts
    settings['markets']= ['CASH', 'F_AD', 'F_BO', 'F_BP', 'F_C']
    settings['beginInSample']= '20120506'
    settings['endInSample']  = '20150506'
    settings['lookback']= 504
    settings['budget']  = 10**6
    settings['slippage']= 0.05
    return settings

if __name__ == "__main__":
    import quantiacsToolbox
    results = quantiacsToolbox.runts(__file__)

There are only two steps to run a parametric scan.

Step 1: Add the range of parameters to scan by replacing the lines where parameters are defined:

    perL = 200
    perS = 40

with:

    perL = 200 #%[100:10:200]#
    perS = 40  #%[40:10:100]#

Now, the system will be evaluated for several configurations obtained by varying the variable ‘perL’ between 100 and 200 using a step of 10 days, and the variable ‘perS’ between 40 and 100 using a step of 10 days.

Step 2: Change final call. Instead of calling the function ‘runts’, we will call the function ‘optimize’ as shown:

if __name__ == "__main__":
    import quantiacsToolbox
    #results = quantiacsToolbox.runts(__file__)
    quantiacsToolbox.optimize(__file__)

Finally, the results of the optimizer will be visualized in a graphical user interface, showing the dependency of the Sharpe Ratio values on the lookback parameters.

The Full Code

The full optimization code is given by:

import numpy

def myTradingSystem(DATE, OPEN, HIGH, LOW, CLOSE, VOL, exposure, equity, settings):
    '''This system uses trend following techniques to allocate capital into the desired equities.'''

    nMarkets= CLOSE.shape[1]
    perL= 200 #%[100:10:200]#
    perS= 40  #%[40:10:100]#
    smaLong  = numpy.nansum(CLOSE[-perL:, :], axis=0)/perL
    smaRecent= numpy.nansum(CLOSE[-perS:, :], axis=0)/perS
    longEquity= smaRecent > smaLong
    shortEquity= ~longEquity
    pos= numpy.zeros(nMarkets)
    pos[longEquity]= 1
    pos[shortEquity]= -1
    weights = pos/numpy.nansum(abs(pos))
    return weights, settings

def mySettings():
    '''Define your trading system settings here.'''

    settings= {}
    # selected Futures contracts
    settings['markets']= ['CASH', 'F_AD', 'F_BO', 'F_BP', 'F_C']
    settings['beginInSample']= '20120506'
    settings['endInSample']  = '20150506'
    settings['lookback']= 504
    settings['budget']  = 10**6
    settings['slippage']= 0.05
    return settings

if __name__ == "__main__":
    import quantiacsToolbox
    #results = quantiacsToolbox.runts(__file__)
    quantiacsToolbox.optimize(__file__)