Библиотеки: MultiTester - страница 3

 
Edgar:

Если имеется в виду, как смотреть результаты оптимизации, то я говорил о программном чтении результатов из кэша.

Другое имел в виду. Но чтение кеша возможно. Надо написать только.

 

Крутая вещь!!!

Прикрутил к ней ещё Циклы - получилось именно то, чего мне очень не хватало )))

#include <fxsaber\MultiTester\MultiTester.mqh> // Множественные прогоны/оптимизации в Тестере.

enum CyclNum
{
   n01   = 1,     // 1
   n02,           // 2
   n03,           // 3
   n04,           // 4
   n05,           // 5
   n06,           // 6
   n07,           // 7
   n08,           // 8
   n09,           // 9
   n10,           // 0
};
sinput bool Period_M1 = false;         // Включить M1
sinput bool Period_M5 = false;         // Включить M5
sinput bool Period_M15 = false;        // Включить M15
sinput bool OnlyCustomSymbols = false; // Только кастомные символы
sinput CyclNum number_cycles  = n06;   // Количество циклов

// Эта функция отвечает за формирование списка заданий.
void SetTesterSettings()
{
   for(int n = 0; n < number_cycles; n++)
   {
      // Перебираем все символы из Обзора рынка.
      for (int i = SymbolsTotal(true) - 1; i >= 0; i--)
      {

Спасибо!

 
Сергей Таболин:

Прикрутил к ней ещё Циклы - получилось именно то, чего мне очень не хватало )))

Нужны функции-кнопкодавилок в Тестере. Тогда автоматизация была бы совсем иного уровня.

 

Я добавил несколько функций для нужных мне контролов (Depo, Currency, Leverage, OptimizationType, BarsType, Criteria). Но ещё не проверял. После могу опубликовать.

Хотел реализовать управление агентами. Например, можно кликнуть на списке агентов, нажать HOME, и выбирать с VK_DOWN каждый агент. Но не знаю, как вызвать контекстное меню для выбранной строки. А там бы нажимать 'd'/'e' для disable/enable.

Подскажет кто?

Ещё сложней - включать/выключать облако (отключать перед оптимизацией по тикам или кроссов). Если даже попасть в контекстное меню, нельзя четко включить/выключить, можно только перекинуть. Узнать текущее состояние программно нельзя. Можно прочитать из журнала терминала "2019.07.31 19:27:35.664 Tester Cloud servers using switch off". Кажется, программно читать журнал тоже нельзя, надо искать в файле журнала.

Есть ещё шанс на недокументированные команды WinAPI. Возможно, кто-то из программистов на C++ умеет найти?

 

Столкнулся с проблемой отключения электричества. Теперь не знаю какой объём оптимизации пройден (((

Появится время, попробую прикрутить проверку на % от общей оптимизации и отработанных символов. Надеюсь автор не против? ))) Или он сам пожелает это сделать? 

 
Сергей Таболин:

Столкнулся с проблемой отключения электричества. Теперь не знаю какой объём оптимизации пройден (((

MultiTester свои шаги отражает в логах. Если терминал логи сохранил, то там все видно будет.

Более того, оптимизационные кеши 100% сохранились. Так что по ним сразу будет видно, что выполнилось.

 
Edgar:

Я добавил несколько функций для нужных мне контролов (Depo, Currency, Leverage, OptimizationType, BarsType, Criteria). Но ещё не проверял. После могу опубликовать.

Перед тем, как решать частные задачи, хорошо бы прописать сценарии использования их решений.

 
fxsaber:

Перед тем, как решать частные задачи, хорошо бы прописать сценарии использования их решений.

Свой сценарий я описывал на предыдущей странице.

Кликер не заменит всего, это один из нескольких инструментов, необходимых для автоматизации оптимизации. Позволяет делать всë в пределах одного терминала, не запуская дополнительного. Добавлю фреймы для анализа результатов (для того же годна Ваша новая библиотека чтения кэша оптимизации), функции для управления входными переменными, SQLITE для хранения состояний и статистики. И можно писать сценарии интеллектуальной оптимизации. Универсальности не достичь, для каждого эксперта свой сценарий. Причëм его приходится создавать вручную, и только потом многократно применять.

Фреймы уже добавил. С SQLITE опыт имел. 

Я просто расширил Вашу либу для своих нужд. Уверен, Вы сами планировали, но я не стал ждать. Это единственная технология из вышеперечисленных, по которым у меня не было готового решения. Кстати, я проверил свои дополнения, они работают. Вопросы по управлению агентами пока актуальны. Spy++ может помочь в отлавливании сообщений опытному системщику, мне было слабо, надо знать что фильтровать. Надеюсь, народ подтянется. Тема всплывает с 2008 года.

 
Edgar:

Вот как бы я хотел улучшить еë. Мой типичный сценарий оптимизации:

Для OHLC провести N генетических проходов. Из каждого взять лучший результат по кастомному критерию.

Провести медленную оптимизацию по каждой группе параметров (в каждой по 2-3 взаимозависимых параметра).

Повторять итеративно медленные оптимизации для каждой группы, пока не достигнут оптимум (параметры перестали плавать).

Переключить на реальные тики, провести так же медленные оптимизации.

Переключить на другой символ, повторить всë.

Передо мной такой задачи не стоит. Конечно, хорошо будет, если автоматизация и это будет позволять.

Сам стремлюсь к выработке критерия робастости ТС через показатели автооптимизации. Очень его не хватает для большей объективности при исследованиях.

Схему автооптимизатора придумал полностью, технических препятствий уже нет для реализации.

Библу точно нужно дополнять функционалом. Так что предлагайте свои реализации.

 
enum eOptType   { eOptOff, eOptSlow, eOptGen, eOptAllSym };
enum eBars      { eBarsEvery, eBarsReal, eBarsOHLC, eBarsOpen, eBarsMath };
enum eCriteria  { eCritBal, eCritPF, eCritEPO, eCritDD, eCritRF, eCritSR, eCritCust };



class MTTESTER {
public:

        static bool 
        SetOptType(eOptType opt) {
                const bool rc = MTTESTER::IsReady();
                if (rc) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x28FB };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_HOME, 0);
                        for (int i = 0; i < opt; i++)
                                user32::SendMessageW(Handle, WM_KEYDOWN, VK_DOWN, 0);
                }
                return rc;
        }



        static bool 
        SetBars(eBars type) {
                const bool rc = MTTESTER::IsReady();
                if (rc) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x2913 };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_HOME, 0);
                        for (int i = 0; i < type; i++)
                                user32::SendMessageW(Handle, WM_KEYDOWN, VK_DOWN, 0);
                }
                return rc;
        }



        static bool 
        SetCriteria(eCriteria type) {
                const bool Res = MTTESTER::IsReady();
                if (Res) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x290B };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_HOME, 0);
                        for (int i = 0; i < type; i++)
                                user32::SendMessageW(Handle, WM_KEYDOWN, VK_DOWN, 0);
                }
                return Res;
        }



        static bool 
        SetCurrency(const string name) {
                const bool Res = MTTESTER::IsReady();
                if (Res) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x293F, 0x03E9 };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_LBUTTONDOWN, 0, 0);
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_DELETE, 0);
                        char Chars[];
                        const int Size = ::StringToCharArray(name, Chars);
                        for (int i = 0; i < Size; i++)
                                user32::SendMessageW(Handle, WM_CHAR, Chars[i], 0);
                }
                return Res;
        }



        static bool 
        SetDepo(const long depo) {
                const bool Res = MTTESTER::IsReady();
                if (Res) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x28F9, 0x03E9 };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_LBUTTONDOWN, 0, 0);
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_DELETE, 0);
                        string s = IntegerToString(depo);
                        char Chars[];
                        const int Size = ::StringToCharArray(s, Chars);
                        for (int i = 0; i < Size; i++)
                                user32::SendMessageW(Handle, WM_CHAR, Chars[i], 0);
                }
                return Res;
        }



        static bool 
        SetLeverage(const long leverage) {
                const bool Res = MTTESTER::IsReady();
                if (Res) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x28E9, 0x03E9 };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_LBUTTONDOWN, 0, 0);
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_DELETE, 0);
                        string s = "1:" + IntegerToString(leverage);
                        char Chars[];
                        const int Size = ::StringToCharArray(s, Chars);
                        for (int i = 0; i < Size; i++)
                                user32::SendMessageW(Handle, WM_CHAR, Chars[i], 0);
                }
                return Res;
        }
Причина обращения: