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).
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.
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.
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.
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.
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.
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.