Tester MT5 - страница 2

 
Vasily Temchenko:

Освоил МТ5, написал советник с графическим интерфейсом, радостно запустил тестер и...
... и очень, очень огорчился - в визуальном режиме Не Работает Графика, только вывод объектов с тем статусом, который им был присвоен при создании, управление графическими объектами недоступно - линии не выделяются, кнопки не нажимаются, данные в окна не вводятся. Облом...

Надеюсь что не нашел нужный выключатель. Если это так - подскажите, плз. В противном случае непонятно ЗАЧЕМ это сделано. Если в МТ4, используя бот с графическим интерфейсом в визуальном режиме тестера, я мог отрабатывать стратегии изменяя в ходе теста настройки эксперта, то в МТ5 подобная отработка невозможна - только через оптимизацию, что есть не самый оптимальный вариант - требует много времени, нет визуального контроля. Кроме того многие начинающие (использовавшие в МТ4 мои боты с графическим интерфейсом) говорили спасибо за возможность быстрого обучения торговле в тестере.

Не знаю какие плюсы разработчики в этом нашли, но огромный минус очевиден - экспертом нельзя управлять в тестере.

Кнопки нормально нажимаются, а вот линии и правда не не выделить и не переместить, сам страдаю. Вот класс CTradeButtons из живого проекта, рисует 4 кнопки, работает в MQL4/5 тестере.

#include <AvLib-4-5\TradeButtons.mqh>
CTradeButtons   TrButtons;

int OnInit()
{
    Print("UninitializeReason() from OnInit = ", UninitializeReason());
    if(LastDeinitReason==REASON_CHARTCHANGE || LastDeinitReason==REASON_TEMPLATE)
    {
        LastDeinitReason = 0;
        return(INIT_SUCCEEDED);
    }
    if(LastDeinitReason==REASON_PARAMETERS)
    {
        InitParams();
        return(INIT_SUCCEEDED);                              
    }
    TrButtons.DeleteButtons();
    ChartRedraw();
    TrButtons.CreateButtons();
    #ifndef BUTTONS_IS_VISIBLE
        TrButtons.SetVisible(false);
    #endif    
    LastDeinitReason = 0;
    return(INIT_SUCCEEDED);
} 

void OnDeinit(const int reason)
{
//    Print("UninitializeReason() from OnDeinit = ", UninitializeReason());
  //  Print("reason = ", reason);
    LastDeinitReason = reason;
    if(reason==REASON_CHARTCHANGE || reason==REASON_TEMPLATE || reason==REASON_PARAMETERS)
        return;
} 

//+------------------------------------------------------------------+
//|                                                 TradeButtons.mqh |
//|                                               Alexey Volchanskiy |
//|                                          http://forexscalping.ru |
//+------------------------------------------------------------------+
#property copyright "Alexey Volchanskiy"
#property link      "http://forexscalping.ru"
#property strict

#include <Controls\WndObj.mqh>
//#include <Controls\BmpButton.mqh>
#include <Controls\Button.mqh>
#include <Controls\Panel.mqh>
#include <Arrays\ArrayObj.mqh>

string  BtnName[BTN_ROWS][BTN_COLS]     = {{"btnSellEnable", "btnBuyEnable"}, {"btnCloseLoss", "btnCloseProfit"}};
string  BtnText[BTN_ROWS][BTN_COLS]     = {{"Sell enable", "Buy enable"}, {"Close loss", "Close profit"}};
int     XYCoord[BTN_ROWS][BTN_COLS][4]  = {{{20,50,100,75}, {110,50,190,75}}, {{20,85,100,110}, {110,85,190,110}}};
color   BtnColor[BTN_ROWS][BTN_COLS][2] = {{{clrLime,clrRed}, {clrLime,clrRed}}, {{clrLime,clrRed}, {clrLime,clrRed}}};
color   BtnTextColor[BTN_ROWS][BTN_COLS][2] = {{{clrBlack,clrLinen}, {clrBlack,clrLinen}}, {{clrBlack,clrLinen}, {clrBlack,clrLinen}}};


class CTradeButtons : CObject
{
protected:
    CButton*    ArrButtons[BTN_ROWS][BTN_COLS];
    color       m_buttonColor;
    color       m_buttonsBorderColor;
    color       m_fontColor;
    int         m_fontSize;
    string      m_fontName;
    bool        m_visible;
    //const string    BtnName[BTN_ROWS][BTN_COLS];
    //const string  BtnName[BTN_ROWS][BTN_COLS] = {{"btnSellEnable", "btnBuyEnable"}, {"btnCloseLoss", "btnCloseProfit"}};
public:
    CTradeButtons()
    {
        /*BtnName[0][0] = "btnSellEnable";
        BtnName[0][1] = "btnBuyEnable";
        BtnName[1][0] = "btnCloseLoss";
        BtnName[1][1] = "btnCloseProfit";*/
    }
    
    ~CTradeButtons() { DeleteButtons(); }
    
    void SetVisible(bool visible)
    {
        CButton *btn;
        m_visible = visible;
        for(int nrow = 0; nrow < BTN_ROWS; nrow++)
            for(int ncol = 0; ncol < BTN_COLS; ncol++)
            {
                btn = ArrButtons[nrow][ncol];
                btn.Visible(visible);
            }    
        ChartRedraw();
    }
    
    void SetParams(color buttonColor, color buttonsBorderColor, color fontColor, int fontSize, string fontName, bool visible)
    {
        m_buttonColor = buttonColor;
        m_buttonsBorderColor = buttonsBorderColor;
        m_fontColor = fontColor;
        m_fontSize = fontSize;
        m_fontName = fontName;
        m_visible = visible;
        DeleteButtons();
        CreateButtons();
    }
    
    bool GetPressedState(int row, int col)
    {
        CButton *btn = ArrButtons[row][col];//.Pressed();
        return true;
    }
/*    bool GetPressedState(int row, int col)
    {
        return ArrButtons[row][col].Pressed();
    }*/


    bool GetPressedState(string name, bool& state)
    {
        for(int row = 0; row < BTN_ROWS; row++)
            for(int col = 0; col < BTN_COLS; col++)
            {
                if(StringFind(name, BtnName[row][col]) != -1)
                {
                    state = ArrButtons[row][col].Pressed();
                    if(state)
                    {
                        ArrButtons[row][col].ColorBackground(BtnColor[row][col][1]);
                        ArrButtons[row][col].Color(BtnTextColor[row][col][1]);
                    }    
                    else 
                    {   
                        ArrButtons[row][col].ColorBackground(BtnColor[row][col][0]);
                        ArrButtons[row][col].Color(BtnTextColor[row][col][0]);
                    }    
                    return true; // кнопка нашлась
                }    
            }
        return false; //не нашлась    
    }

    void SetPressedState(int row, int col, bool state)
    {
        ArrButtons[row][col].Pressed(state);
    }

    void SetPressedState(string name, bool state)
    {
        for(int row = 0; row < BTN_ROWS; row++)
            for(int col = 0; col < BTN_COLS; col++)
            {
                if(StringFind(name, BtnName[row][col]) != -1)
                {
                    ArrButtons[row][col].Pressed(state);
                    if(state)
                    {
                        ArrButtons[row][col].ColorBackground(BtnColor[row][col][1]);
                        ArrButtons[row][col].Color(BtnTextColor[row][col][1]);
                    }    
                    else 
                    {   
                        ArrButtons[row][col].ColorBackground(BtnColor[row][col][0]);
                        ArrButtons[row][col].Color(BtnTextColor[row][col][0]);
                    }    
                    return; // кнопка нашлась
                }    
            }
    }
    
    void DeleteButtons()
    {
        for(int row = 0; row <  BTN_ROWS; row++)
            for(int col = 0; col < BTN_COLS; col++)
            {
                CButton* btn = ArrButtons[row][col];
                if(CheckPointer(btn) == POINTER_DYNAMIC)
                    delete btn;
            }
        ObjectsDeleteAll(0, "btn");    
        ChartRedraw();
    }
    
    CButton* CreateButton(string bname, int x1, int y1, int x2, int y2, color bcolor, string btext, string font, int fontSize,// bool visible,
                        color colorBackground, color colorBorder, long chart = 0, int subwin = 0)
    {
        CButton* btn = new CButton();
        btn.Create(chart, bname, subwin, x1, y1, x2, y2);
        btn.Color(bcolor);
        btn.Text(btext);
        btn.Font(font);
        btn.FontSize(fontSize);
//        btn.Visible(m_visible);
        btn.ColorBackground(colorBackground);
        btn.ColorBorder(colorBorder);   
        return btn;
    }
    
    void CreateButtons()
    {
        for(int nrow = 0; nrow < BTN_ROWS; nrow++)
            for(int ncol = 0; ncol < BTN_COLS; ncol++)
            {
                CButton* btn = CreateButton(BtnName[nrow][ncol], XYCoord[nrow][ncol][0], XYCoord[nrow][ncol][1], XYCoord[nrow][ncol][2], XYCoord[nrow][ncol][3], 
                    clrBlack, BtnText[nrow][ncol], "Arial Rounded MT Bold", 10, BtnColor[nrow][ncol][0], clrBeige);
                if(CheckPointer(btn) == POINTER_DYNAMIC)    
                    ArrButtons[nrow][ncol] = btn;  
                else      
                    ArrButtons[nrow][ncol] = NULL;  
            }
        ChartRedraw();
    }
};
 
Vasily Temchenko:
"Тестер - это модуль для отлаживания ТС" - совершенно верно. Но как раз эту возможность и урезали.
"А эксперта - разумнее отлаживать в отладчике" - если речь об отладке кода - да, верно, если речь о настройке ТС - абсолютно не согласен. В визуальном режиме, имея возможность управлять тестером в МТ4 через графический интерфейс робота я мог осознанно настраивать торговые параметры. 90% работы по настройке ТС делалось именно таким образом. В оптимизаторе производилась всего лишь небольшая доводка.

Согласен на 100%. Мне абсолютно непонятно, зачем испортили тестер в этом плане по сравнению с МТ4. Как всегда, MQ одно лечат, другое калечат. В стиле MS (вспоминаем загубленный Skype).

 
Alexey Volchanskiy:

Кнопки нормально нажимаются ... Вот класс CTradeButtons из живого проекта, рисует 4 кнопки, работает в MQL4/5 тестере.

Спасибо огромное за подсказку. Если в таком варианте нажимаются - уже хорошо.

Я кнопки рисовал по старинке, как в МТ4. На живом графике работают без проблем - уже неделю торгую этим ботом. Но если  нарисованные по CTradeButtons будут работать и в тестере - придется переделать.
Надеюсь что и с окнами ввода то же самое. Придется опять учить буквы... А так не хотелось ;)

 
Vasily Temchenko:

По твоей логике пользователи (они же покупатели) должны приспосабливаться к плохому качеству продукта? Тем более зная что качество ухудшено намерено - в предыдущей партии товара (МТ4) ЭТО качество было.
Круто!
Такой товар будет иметь спрос только в монопольных условиях.  Как только появится достойный конкурентный продукт, пользователи очень быстро проголосуют ногами в его сторону.
Впрочем уже давно голосуют. Несмотря на форсированные попытки продвижения МТ5 наиболее используемым терминалом, тем не менее, остается МТ4.
Метаквот (как и кто бы то ни было другой) не сумел переплюнуть свою же разработку. Впрочем это и неудивительно - МТ4 почти идеальный продукт, в нем все на месте. А МТ5 и недоделан и неудобен. Плюсов не вижу никаких.

Увы, ты не прав.

Уже давно большинство заказов во Фрилансе идет на кроссплатформенный код, чтобы эксперты работали на обоих системах. Да и все опытные программисты из форума - имеют кроссплатформенные библиотеки. Что говорит о том, что МТ5 реально востребованный продукт. Причем, главное его преимущество именно в его тестере, который, и в самом деле, не дает двигать нарисованные объекты мышкой, как тебе вздумается.

Так что монополия остается, с закономерным диктатом монополиста.

 

Кнопки нажимаются.

А вот введение значений в поле Edit и работа с линиями - действительно не работает и это небольшая проблема. (+- в помощь)

Хотя если посмотреть с другой стороны - нужно делать свои функции, специально разработанные для тестера. Если этот советник будет работать в тестере. 

Но проблема только в линиях, как я посмотрю..

 
Vladislav Andruschenko:

Кнопки нажимаются.

А вот введение значений в поле Edit и работа с линиями - действительно не работает и это небольшая проблема. (+- в помощь)

Хотя если посмотреть с другой стороны - нужно делать свои функции, специально разработанные для тестера. Если этот советник будет работать в тестере. 

Но проблема только в линиях, как я посмотрю..

Да, верно, нажимаются, спасибо за подсказку, по кнопкам уже подсказали выше. Но, если невозможно оживить Edit и выделить/передвинуть мышой линию (виртуальный ордер), то не стоит и кнопки в тестере  делать нажимающимися - толку с этого ноль если нельзя вводить данные и управлять виртуальными ордерами, сойдет как есть. Просто нужно поставить жирный крест на возможности управления роботом в тестере. Жаль, конечно, но с берданкой против танка не попрешь... Наши вопли, похоже, никому не интересны, Метаквоту плевать на подобные "мелочи", реального конкурента у них действительно нет (заставил бы прислушаться к мнению потребителя) и вряд ли появится в ближайшем обозримом будущем.

Спасибо всем за отклик и помощь.

 
Vasily Temchenko:

Да, верно, нажимаются, спасибо за подсказку, по кнопкам уже подсказали выше. Но, если невозможно оживить Edit и выделить/передвинуть мышой линию (виртуальный ордер), то не стоит и кнопки в тестере  делать нажимающимися - толку с этого ноль если нельзя вводить данные и управлять виртуальными ордерами, сойдет как есть. Просто нужно поставить жирный крест на возможности управления роботом в тестере. Жаль, конечно, но с берданкой против танка не попрешь... Наши вопли, похоже, никому не интересны, Метаквоту плевать на подобные "мелочи", реального конкурента у них действительно нет (заставил бы прислушаться к мнению потребителя) и вряд ли появится в ближайшем обозримом будущем.

Спасибо всем за отклик и помощь.


я же и говорил. Смотря для каких целей. 

для поля EDIT есть кнопки +- их сделать не проблема.

А вот насчет линий - тут без вариантов (или варианты есть, но я их не рассматривал за ненадобностью?)

кнопки нажимаются, этого достаточно. 

Я не спорю - управление графиком в полном объеме для тестера стратегий НЕОБХОДИМАЯ функция. Это избавит от многих костылей. 

 
Vladislav Andruschenko:

для поля EDIT есть кнопки +- их сделать не проблема.

Нет, это не решение. Нельзя загромождать интерфейс, он и без того прилично пригружен - см. скриншот выше. Я ни в коем случае не вывожу на графический интерфейс то без чего можно обойтись. Только важные элементы оперативного управления и самую необходимую инфу. Чем больше полей/кнопок, тем хуже - если интерфейс загроможден, то данные плохо воспринимаются, человек не робот.

Тем более что если нет возможности организовать управление в полном объеме, то и огород городить не имеет смысла. "Умерла, так умерла"... Просто добавлю в функцию обработки событий графики запрет на работу в тестере - хоть какая-то польза - тестер быстрее работать будет. На реале работает, ну и ладно... бум ждать шестую версию ;)

 
Vasily Temchenko:

Нет, это не решение. Нельзя загромождать интерфейс, он и без того прилично пригружен - см. скриншот выше. Я ни в коем случае не вывожу на графический интерфейс то без чего можно обойтись. Только важные элементы оперативного управления и самую необходимую инфу. Чем больше полей/кнопок, тем хуже - если интерфейс загроможден, то данные плохо воспринимаются, человек не робот.

Тем более что если нет возможности организовать управление в полном объеме, то и огород городить не имеет смысла. "Умерла, так умерла"... Просто добавлю в функцию обработки событий графики запрет на работу в тестере - хоть какая-то польза - тестер быстрее работать будет. На реале работает, ну и ладно... бум ждать шестую версию ;)

MetaTrader X с встроенной памятью на 256 gb 
 
Vladislav Andruschenko:
MetaTrader X с встроенной памятью на 256 gb 
Аппаратный терминал преллагаете сделать? 
Причина обращения: