// Вариант через макросы, #define iInput01 Amount #define iInput02 Count #define iInput03 Period #define dInput01 Koef #define dInput02 Log #define bInput01 Flag // но лучше через копирование mqh-файла и соответствующую замену в одно действие для каждого входного. #include <fxsaber\Input_Struct\Input_Struct.mqh> // https://www.mql5.com/ru/code/47932 #include <fxsaber\MultiTester\MTTester.mqh> // https://www.mql5.com/ru/code/26132 INPUT_STRUCT inInputs; MACROS_INPUT(int, Amount, 1); // Parameter Amount MACROS_INPUT(int, Count, 2); // Parameter Count MACROS_INPUT(int, Period, 3); // Parameter Period MACROS_INPUT(double, Koef, 4.56); // Parameter Koef MACROS_INPUT(double, Log, 7.89); // Parameter Log MACROS_INPUT(bool, Flag, true); // Parameter Flag // ФФ для штатного Оптимизатора - пример. double OnTester() { return(MathSin(inInputs.Amount) * MathSin(inInputs.Count) * MathSin(inInputs.Period) * MathSin(inInputs.Koef) * MathSin(inInputs.Log) * (inInputs.Flag ? 1 : -1)); } int OnInit() { const bool IsTester = MQLInfoInteger(MQL_TESTER); if (!IsTester) { string Settings; double ArgBest[]; double BestResult; if (!MTTESTER::GetSettings2(Settings) || ((Settings = StringSubstr(Settings, StringFind(Settings, "[TesterInputs]"))) == NULL) || (inInputs.FromString(Settings) != inInputs.GetAmount())) MessageBox("Поместите этот советник в Тестер и\nнастройте там входные параметры!" + "\n\nЗатем запустите его снова в Терминале."); else if (!OptimizationMode(Settings, BestResult, ArgBest)) Print("\nError optimization!"); else { inInputs = ArgBest; Print("\nBestResult = " + (string)BestResult + ": " + inInputs.ToString()); } } return(!IsTester); } // ФФ для кастомного Оптимизатора. double FitnessFunction( const double &Arg[] ) { inInputs = Arg; return(OnTester()); } // Режим запуска кастомного Оптимизатора. bool OptimizationMode( const string Settings, double &Res, double &ArgBest[] ) { INPUT_STRUCT InputsDefault; INPUT_STRUCT InputsStart; INPUT_STRUCT InputsStep; INPUT_STRUCT InputsStop; INPUT_STRUCT InputsEnable; InputsDefault.FromString(Settings); InputsStart.FromString(Settings, 1); InputsStep.FromString(Settings, 2); InputsStop.FromString(Settings, 3); InputsEnable.FromString(Settings, 4); Print("\nНастройки оптимизации на языке именованных входных параметров:"); Print("InputDefault: " + InputsDefault.ToString()); Print("InputsStart: " + InputsStart.ToString()); Print("InputsStep: " + InputsStep.ToString()); Print("InputsStop: " + InputsStop.ToString()); Print("InputsEnable: " + InputsEnable.ToString()); double ArgDefault[]; double ArgStart[]; double ArgStep[]; double ArgStop[]; double ArgEnable[]; InputsDefault.ToArray(ArgDefault); InputsStart.ToArray(ArgStart); InputsStep.ToArray(ArgStep); InputsStop.ToArray(ArgStop); InputsEnable.ToArray(ArgEnable); Print("\nНастройки оптимизации на языке кастомного алгоритма оптимизации ФФ:"); Print("ArgDefault:"); ArrayPrint(ArgDefault); Print("ArgStart:"); ArrayPrint(ArgStart); Print("ArgStep:"); ArrayPrint(ArgStep); Print("ArgStop:"); ArrayPrint(ArgStop); Print("ArgEnable:"); ArrayPrint(ArgEnable); return(Optimization(FitnessFunction, Res, ArgBest, ArgDefault, ArgStart, ArgStep, ArgStop, ArgEnable)); } typedef double (*TFitnessFunction)( const double &Arg[] ); // Кастомный Оптимизатор. bool Optimization( const TFitnessFunction FF, double &Res, double &ArgBest[], // Res = FF(ArgBest) const double &ArgDefault[], const double &ArgStart[], const double &ArgStep[], const double &ArgStop[], const double &ArgEnable[]) { // На основе Arg-данных алгоритм оптимизации должен создавать Arg[] для расчета FF(Arg). return(false); // false - в случае неудачи. }
- Открываем этот советник в Тестере и настраиваем значения оптимизируемых параметров.
- Либо запускаем советник в Тестере - получаем результат штатного Оптимизатора.
- Либо запускаем советник в Терминале - получаем результат кастомного Оптимизатора. Входные подхватятся из п.1.
Для авторов кастомных оптимизаторов следующий скрин объяснит, как добавить свой алгоритм оптимизации.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2024.01.19 18:16
// Кастомный Оптимизатор. bool Optimization( const TFitnessFunction FF, double &Res, double &ArgBest[], // Res = FF(ArgBest) const double &ArgDefault[], const double &ArgStart[], const double &ArgStep[], const double &ArgStop[], const double &ArgEnable[] );
#define vector vect #include <ParticleSwarm.mqh> // https://www.mql5.com/en/blogs/post/683577 #undef vector class FF_Functor : public Functor { public: static TFitnessFunction FF; virtual double calculate( const double &Arg[] ) { return(FF_Functor::FF(Arg)); } }; static TFitnessFunction FF_Functor::FF = NULL; #define PSO_CYCLES 10 // Кастомный Оптимизатор. bool Optimization( const TFitnessFunction FF, double &Res, double &ArgBest[], // Res = FF(ArgBest) const double &ArgDefault[], const double &ArgStart[], const double &ArgStep[], const double &ArgStop[], const double &ArgEnable[] ) { double Max[]; double Min[]; double Step[]; const int Size = ArraySize(ArgDefault); ArrayResize(Max, Size); ArrayResize(Min, Size); ArrayResize(Step, Size); for (uint i = Size; (bool)i--;) { Min[i] = ArgEnable[i] ? ArgStart[i] : ArgDefault[i]; Max[i] = ArgEnable[i] ? ArgStop[i] : ArgDefault[i]; Step[i] = ArgEnable[i] ? ArgStep[i] : 0; } Swarm swarm(Size, Max, Min, Step); FF_Functor FFObject; FF_Functor::FF = FF; Res = swarm.optimize(FFObject, PSO_CYCLES); swarm.getSolution(ArgBest); return(true); // false - в случае неудачи. }
На этих настройках
такой результат.
Штатный ГА был повержен на этом запуске. Скорее всего, это ни о чем не говорит, т.к. ФФ сомнительная.
Факт - сценарий использования данной библиотеки входных параметров для легкого подключения кастомных алгоритмов оптимизации является рабочим.
- 2016.11.21
- www.mql5.com
Памятка.
#define iInput01 Amount #define dInput01 Koef #include <fxsaber\Input_Struct\Input_Struct.mqh> // https://www.mql5.com/ru/code/47932 #define TOSTRING(A) #A + " = " + (string)(A) + " " void OnStart() { INPUT_STRUCT Input; // Задание через массив. const double Array[] = {1, 2}; Input = Array; // Input.FromArray(Array); // Вывод в строку. Print(Input[]); // Amount = 1, Koef = 2.0 Print(TOSTRING(Input.Amount) + TOSTRING(Input.Koef)); // Input.Amount = 1 Input.Koef = 2.0 // Задание через строку. Input = "Amount = 3"; // Input.FromString("Amount = 3"); Print(Input[]); // Amount = 3, Koef = 2.0 // Вывод в строку - расширенный вариант. Print(Input + Input); // Amount = 3, Koef = 2.0, Amount = 3, Koef = 2.0 Print(Input + "Hello!"); // Amount = 3, Koef = 2.0, Hello! Print(Input["SL = 1.5, Koef = 3.42, Hello!, Amount = 1"]); // Amount = 1, Koef = 3.42, SL = 1.5, Hello! // Вывод в массив. double Array2[]; Input.ToArray(Array2); ArrayPrint(Array2); // 3.00000 2.00000 // Задание через строку - расширенный вариант. Input.FromString("Amount=4||5||2||10||N", 0); Print(Input[]); // Amount = 4, Koef = 2.0 Input.FromString("Amount=4||5||2||10||N", 1); Print(Input[]); // Amount = 5, Koef = 2.0 Input.FromString("Amount=4||5||2||10||N", 2); Print(Input[]); // Amount = 2, Koef = 2.0 Input.FromString("Amount=4||5||2||10||N", 3); Print(Input[]); // Amount = 10, Koef = 2.0 Input.FromString("Amount=4||5||2||10||N", 4); Print(Input[]); // Amount = 0, Koef = 2.0 Input.FromString("Amount=4||5||2||10||Y", 4); Print(Input[]); // Amount = 1, Koef = 2.0 // Вывод в строку по маске. bool Mask1[] = {true, true}; Print(Input[Mask1]); // Amount = 1, Koef = 2.0 bool Mask2[] = {true, false}; Print(Input[Mask2]); // Amount = 1 bool Mask3[] = {false, true}; Print(Input[Mask3]); // Koef = 2.0 }
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2024.02.06 23:49
По входным хороший пример получился.
Каждый входной параметр нужно прописать пять-шесть раз.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2024.02.12 02:09
Текущие результаты своей работы с инпутами снова (в приложении) применил к коду из данной статьи.
Удалось добиться единоразового прописывания в коде входных.
Пример того, как достаточно только один раз в коде прописать входные, а дальше готовы и соответствующие input-переменные и прием/передача их через строки в файлы/ООП.
Значительно расширил возможности библиотеки.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
fxsaber, 2024.02.12 17:33
Добавил group, string-инпуты и кое-что по мелочи для удобства на будущее.
#define TYPENAME_INPUT StrategyInput #define MACROS_MULTI \ INPUT(symbol, string, "EURGBP") \ // Торговый инструмент (символ) INPUT(timeframe, ENUM_TIMEFRAMES, PERIOD_H1) \ // Период графика (таймфрейм) GROUP("=== Параметры управление капиталом") \ INPUT(fixedLot, double, 0.01) // Размер открываемых позиций (фиксированный)
#define TYPENAME_INPUT SimpleVolumesStrategyInput #define MACROS_MULTI \ GROUP("=== Параметры сигнала к открытию") \ INPUT(signalPeriod, int, 13) \ // Количество свечей для усреднения объемов INPUT(signalDeviation, double, 0.3) \ // Относ. откл. от среднего для открытия первого ордера INPUT(signaAddlDeviation, double, 1) \ // Относ. откл. от среднего для открытия второго и последующих ордеров GROUP("=== Параметры отложенных ордеров") \ INPUT(openDistance, int, 0) \ // Расстояние от цены до отлож. ордера INPUT(stopLevel, double, 10500) \ // Stop Loss (в пунктах) INPUT(takeLevel, double, 465) \ // Take Profit (в пунктах) INPUT(ordersExpiration, int, 1000) \ // Время истечения отложенных ордеров (в минутах) GROUP("=== Параметры управление капиталом") \ INPUT(maxCountOfOrders, int, 3) // Макс. количество одновременно отрытых ордеров
Нетривиальный код библиотеки и простое ее использование.
#property script_show_inputs #define iInput01 Amount #define dInput01 Koef #include <fxsaber\Input_Struct\Input_Struct.mqh> // https://www.mql5.com/ru/code/47932 // Задали инпут-переменные. MACROS_INPUTS(int, Amount, 1); MACROS_INPUTS(double, Koef, 2); void OnStart() { Print(inInputsAll); // Все input-переменные в одной строке. }
Amount = 123, Koef = 4.567
Полноценный пример использования этой возможности здесь.
Бывают ситуации, когда при считывании сета не задано какое-то поле. Например, сеты давно были записаны. А позже был добавлен новый инпут. И, соответственно, он оказался не прописан в старых сохраненных сетах.
В подобных ситуациях пригодится Default-метод для задания новому полю значения по умолчанию.
#property script_show_inputs #define iInput01 Amount #define dInput01 Koef #define INPUT_STRUCT_ADDON // Полная автоматизация input-переменных. #include <fxsaber\Input_Struct\Input_Struct.mqh> // https://www.mql5.com/ru/code/47932 void OnStart() { Print(inINPUT_STRUCT[]); // Автоматически созданный объект структуры с соответствующими инпутами. inINPUT_STRUCT.Default(); // Прописали значения input-переменных, что прописаны в коде. Print(inINPUT_STRUCT[]); }
Результат.
Amount = 123, Koef = 4.567 Amount = 1, Koef = 2.0
Потому что при задании input-переменных в коде были указаны такие значения.
#define TYPENAME_INPUT INPUT_STRUCT #define MACROS_MULTI \ INPUT(Amount, int, 1) \ INPUT(Koef, double, 2)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Input_Struct:
Структура входных параметров
Автор: fxsaber