How to use extern variables and optimization

This guide describes the NQuotes support of input variables and extern variables and expert advisor optimization (see Client Terminal / Auto Trading / Expert Optimization in the MT4 help).

Quick steps

  1. Declare variables in a .NET EA class.
  2. Declare input and extern variables in MQL.
  3. Call nquotes_set_property_X function from MQL "init" function for each variable.
  4. Compile and run the modified mq4 file.

These steps need to be done only once when you add or remove an input or extern variable.

There's a sample project in "%TERMINAL_DATA_PATH%\MQL4\Projects\nquotes\MovingAverageCustom" folder. Build the project to get a EA DLL - "MovingAverageCustom.dll". The project folder also contains an MQL file - "MovingAverageCustom.mq4". Copy it to "%TERMINAL_DATA_PATH%\MQL4\Experts". Open and compile it with MetaEditor, and then run it as a normal MQL expert advisor in the MT4 terminal.

Step 1: Declare variables in .NET

You have 2 possibilities for input or extern variables declaration in C#: use class fields or properties. If you choose to use a field, you can initialize it with a default value. If you choose to use a property, you can assign a default value in the class' parameterless constructor. It's important to mark the declarations as "public".

This is how you declare a field:

public double MaximumRisk = 0.02;

This is how you declare a property:

public double MaximumRisk { get; set; }

Then you are ready to build an expert advisor DLL.

Step 2: Declare input and extern variables in MQL

First find an MQL file to use. You can use a default MQL EA file - "%TERMINAL_DATA_PATH%\MQL4\Experts\nquotes.mq4", but it's better to create a separate "MyExpert.mq4" EA file from "MyExpertTemplate.mq4" as described in the expert name customization how-to.

Declaring input and extern variables is done as usual. For example:

input double MaximumRisk = 0.02;

See input variables documentation or extern variables documentation for more examples.

Step 3: Call nquotes_set_property_X

There's a family of nquotes_set_property_X MQL functions for each data type. The functions are provided by "nquoteslib.ex4". For example, nquotes_set_property_double function should be used for an input variable of type "double". See documentation on nquotes_set_property_X functions. Those functions must be called for each variable from MQL "init" function after a call to nquotes_setup function, but before a call to nquotes_init function. For example:

int init()
{
	nquotes_setup(NULL, NULL);  // this line must go first
	nquotes_set_property_double("MaximumRisk", MaximumRisk);
	return (nquotes_init());    // this line must go last
}

The first parameter to nquotes_set_property_double is the name of the C# property declared at step 1, and the second parameter is the input variable declared at step 2.

Step 4: Running optimization

  1. Open the terminal, then View - Strategy Tester menu.
  2. Choose the "MyExpert" expert advisor from the list and set "Optimization" checkbox.
  3. Click on "expert properties" button and configure the ranges and initial values of your input and extern parameters, which will be passed to the expert during optimization.
  4. Set the date range for the test and other parameters. Click "Start".

During the optimization your EA will be created and called multiple times with different input/extern parameter values. With NQuotes it's possible to debug and see what's happening by following the code execution.

Tips for running the optimization faster

Strategy testing runs thousands of ticks every second. In order to make it faster it's important to reduce the number of MQL calls.

Sometimes it's possible to cache the MQL data that you need. For example the "Symbol" function returns a value that is always the same after you attach your expert advisor to a chart. You can cache it into some class field in the "init" method and reuse the value.

Working with MQL arrays might be slow. This can be optimized by using the "ArrayCopy" function. For example if you need the last 10 Open prices, you can copy Open[0]...Open[9] values using a single call to "ArrayCopy", and then iterate through the resulting .NET array without additional MQL calls. If you are working with "Open" it's also possible to use the "ArrayCopySeries" function.

Sometimes it's possible to prepare the data in MQL, and pass it at the beginning of the "start" and "init" functions from MQL using the NQuotes MQL API - nquotes_set_property_X.

The indicator sample has an example of how to pass the data from MQL to C# and back in an efficient way.