Investment Studio > Views > System > Optimization
System Parameters can be automatically optimized with respect to some user-defined performance measure, e.g. final portfolio NAV. This basically involves running the trading system repeatedly, each time with a different parameter value, and keeping track of which value yields the best result.
The range of values to explore [Low, High] is specified individually for each parameter in the Parameters grid, along with the number of equally spaced Steps in which this range is to be traversed. Optimization is possible only if at least one parameter has a non-trivial range (High > Low, Steps > 1) and is not Locked.
To start optimizing, click Optimize
in the Parameters section's pop-up menu or click
in
its toolbar. This opens the Optimizer window:

| Enter an expression for the performance measure
which you want to either minimize or maximize (known as
the "objective function") in the Objective
box. Click the spin button in the Objective box for a
list of recently used objective functions. You can use all the symbols
available in the Symbols section to create your objective
function.
Consider for instance the expression in the screenshot above, portfolio_nav(portfolio, to_date) In the Objective box, this works just fine, since the expression in the Objective box is computed only after the system has finished executing and the portfolio has been updated accordingly. But if you had defined a symbol _final_nav = portfolio_nav(portfolio, to_date) in the Symbols grid, it would have been computed at the beginning of the run and then never again, since both arguments (portfolio, to_date) remain the same throughout system execution. Using _final_nav as your objective function would therefore have yielded misleading results! Also note that final
portfolio NAV may not be the most adequate performance
measure, since it doesn't take into account how much risk
was incurred to achieve that NAV. Two popular risk-adjusted
performance measures which address this problem are the
Sharpe ratio and the Treynor ratio:
where the "risk-free" return is typically taken to be the return on US Treasury bills, a money market account or similar "safe" asset. While it's possible to compute average returns using the XIRR function, it is not necessary to do so for the purpose of optimization. Instead, define symbols _initial_nav = portfolio_nav(portfolio, from_date) _rfdc = asset_quotes(riskfree, "c", from_date, to_date) _risk_free_return = index(array(_rfdc), _rfdc_n, 2) / index(array(_rfdc), 1, 2) (where riskfree stands for the asset symbol of your risk-free asset; substitute the appropriate actual symbol) and then compute the numerator (in the Objective box - see notes above!) as portfolio_nav(portfolio, to_date) - _initial_nav * _risk_free_return The standard deviation of (daily) portfolio returns can be computed as stdev(subarray(roc(portfolio_quotes(portfolio, "c", from_date, to_date), 1), 1, 0, 2, 0)) while the portfolio's Beta is given by ba(asset_quotes(market, "c", from_date, to_date), portfolio_quotes(portfolio, from_date, to_date)) where market stands for the asset symbol of a market proxy (typically an index like the S&P 500 or the Russell 3000). The optimal portfolio according to the Sharpe measure can therefore be found by maximizing the objective function (portfolio_nav(portfolio, to_date) - _initial_nav * _risk_free_return) / stdev(subarray(roc(portfolio_quotes(portfolio, from_date, to_date), 1), 1, 0, 2, 0)) while the optimal portfolio according to the Treynor measure can be found by maximizing the objective function (portfolio_nav(portfolio, to_date) - _initial_nav * _risk_free_return) / ba(asset_quotes(market, "c", from_date, to_date), portfolio_quotes(portfolio, from_date, to_date)) |
|||||||||||||||||||||||
| The controls in the top row of the Test
qoutes box determine the date range over which
the system is optimized. They are analogous to the date
range controls in the Rules section. The
rationale for having two separate sets of date range
controls is that sound trading system development always
involves the use of at least two non-overlapping date (and
data) ranges: one used for optimization, the other for
verification of the optimized system. The system should
display similar behaviour (number of transactions per
time unit, average portfolio return, drawdown,
distribution of gains and losses) over both date ranges.
Without such verification there is an overwhelming risk
of over-fitting, i.e. of creating a system that performs
perfectly over the optimization range, but lousy at all
other times.
|
|||||||||||||||||||||||
| The controls in the second row of the Test
qoutes box have no effect unless Shuffle
is checked. When Shuffle is checked, the optimizer does not use quotes in the selected date range "as is". Instead, before the system is executed, the quotes in the selected range are converted to daily relative moves which are then randomly reshuffled and converted back to quotes. The result is a set of quotes which, while fictitious, have the same distribution of daily moves, the same starting point and the same end point (and therefore the same overall trend) as the original quotes. All assets and currency quotes are reshuffled together (i.e. all asset and currency moves from day X are relocated to the same day Y) so as to also preserve any cross-correlations between quotes. Quotes are reshuffled every time the optimizer takes a new step through parameter space, i.e. every time a parameter value is updated. If a value > 1 has been set in the "x" (times) box,
reshuffling and system execution are also iterated the specified number of times for each set of parameter values, whereafter the set's "official" objective function value is computed from the "x" individual results, using the method specified to the right of the "x" box:
The purpose of all this
tribulation is to avoid the common trap of overfitting
the system to a particular sequence of market events
which are not likely to ever repeat again in the same
order.
It should be noted that while random shuffling is close in spirit to Monte Carlo optimization, it skips a crucial step necessary to qualify as such. In Monte Carlo methods, a postulated distribution of price moves (e.g. a log-normal distribution) is fitted to the historical quotes, whereafter the fictitious prices are obtained from the fitted distribution rather than directly from the historical data. This extra step can be argued to make Monte Carlo methods more "general" in nature, by better insulating the fictitious quotes from peculiarities of the available historical data; but this insulation is achieved at the cost of postulating a particular underlying distribution, essentially as a matter of faith. Generally speaking, the more historical data you have at your disposal, the better it will reflect the actual distribution, whatever its nature. On the other hand, old data may have been collected under market conditions so different from current ones as to have limited predictive value. |
|||||||||||||||||||||||
| Click Execute to start
the optimization process. This button is enabled only if
optimization is not already underway, if an Objective
function has been provided, and if Shuffle
is unchecked or a number of iterations > 0 has been
specified. Once clicked, the Execute button stays grayed out until all parameter values in the specified range have been stepped through or Stop (6) is clicked. Execution progress and estimated time left (ETA = hours:minutes:seconds left) are displayed next to the button (5); extrema and the latest parameter set evaluated so far are displayed in the result grid below the button (7). |
|||||||||||||||||||||||
| The result grid can be
navigated as usual (with scroll bars, mouse, arrow keys
etc.) but is read-only. The top data row displays the largest (Max), smallest (Min) and latest (Last) objective function value ("<OBJECTIVE>") found during the latest optimization run. The rows below it display the corresponding parameter values. For instance, in the screenshot below, |

| the highlighted value (23.9200...) is the
smallest objective function value found so far; its
coordinates in parameter space are _min_af = 0.384454545...
and _max_af = 0.001. To transfer a set of parameter values (whether Max, Min or Last) from the result grid to the corresponding Value fields in the System view's Parameters grid, select a cell in the desired column, then click OK (12). |
|
| If Log is checked, every
point in parameter space reported under Last in the
result grid (7) during the optimization run will also be
written to the CSV (Comma Separated Value) file specified
in the log file box (9). Any data previously in the file
will be overwritten. The file path can be typed into the
box, or you can click Symbolic directory names can be used in the file path (e.g. "<TEMP>", as in the screenshot above) and will be automatically substituted for actual directory paths wherever possible. The first row in the CSV file created by the optimizer is a header describing the contents of each column (<OBJECTIVE> value in the first column, symbol names in the rest). Each subsequent row describes a point in parameter space. All values are written in general floating point format (using a decimal period) and can be read using common spreadsheets and charting software. |
|
| Click Minimize to reduce Investment Studio to an icon on the Windows task bar during lengthy optimization runs. | |
| Click OK to close the
optimizer windows and transfer all parameter values from
the selected column (Max,
Min or Last) in the
result grid (7) to the coresponding Value
fields in the System view's Parameters grid. Click
|