Библиотеки: MT4Orders QuickReport - страница 4

 
Forester #:

Оказалось, что тестер MQ переносит в архив удаляемые лимитные ордера с опозданием:

Просьба предоставить данные для воспроизведения.
 
Forester #:

Поменял на highchart. Он оказался лучше: google.charts зависал при 700 000 сделках, а highchart отобразил их без особых тормозов и смог увеличить до отдельных сделок.

Правильно ли понимаю, что в текущей реализации для работы highcharts требуется быть онлайн?
 
fxsaber #:
Просьба предоставить данные для воспроизведения.
 // отличие от  - подключаем вирт тестер через SelectByIndex(), а не #define VIRTUAL_TESTER
 
 #include <MT4Orders.mqh>

#define REPORT_TESTER             // В тестере будут автоматически записываться отчеты
//#define REPORT_BROWSER            // Создание отчета с запуском браузера - требует разрешения DLL.
#include <MT4Orders_QuickReport.mqh>//

input int inAmount = 10;
input int inOffset = 5;
input int inRange = 0;

bool OrdersBuy[];
bool OrdersSell[];
bool OrdersBuyStop[];
bool OrdersSellStop[];

void OnInit()
{
  ArrayResize(OrdersBuy, inAmount + 1);
  ArrayResize(OrdersSell, inAmount + 1);
  ArrayResize(OrdersBuyStop, inAmount + 1);
  ArrayResize(OrdersSellStop, inAmount + 1);
}

void OnTick()
{

   strategy ();

}

double OnTester() { 
QuickReport("report_0", true, 0);
   return(AccountInfoDouble(ACCOUNT_BALANCE)); 
}

void OnDeinit(const int  reason ){
   Print("OnDeinit main");

}


int TimeHour     ( datetime time ){return((int)((time / 3600) % 24));}//current hour in day. 3600 sec in hour

void strategy (){
  string Symb = _Symbol;
  MqlTick Tick;
  
  if (SymbolInfoTick(Symb, Tick))
  {    
    double sl, tp, point = SymbolInfoDouble(Symb, SYMBOL_POINT);
    const double Offset = inOffset * point;

    ArrayInitialize(OrdersBuy, false);
    ArrayInitialize(OrdersSell, false);
    ArrayInitialize(OrdersBuyStop, false);
    ArrayInitialize(OrdersSellStop, false);

    for (uint i = OrdersTotal(); (bool)i--;)
      if (OrderSelect(i, SELECT_BY_POS))         
      {
        ulong Magic = OrderMagicNumber();
        if(Magic > 0 && Magic < 100 ){
           switch (OrderType())
           {
             case OP_BUY:
               OrderModify(OrderTicket(), OrderOpenPrice(), 0, Tick.bid + Magic * Offset, 0);
               OrdersBuy[Magic] = true;
               
               break;
             case OP_SELL:
               OrderModify(OrderTicket(), OrderOpenPrice(), 0, Tick.ask - Magic * Offset, 0);
               OrdersSell[Magic] = true;
               
               break;
             case OP_BUYLIMIT:
               OrderModify(OrderTicket(), Tick.ask - Magic * Offset, 0, 0, 0);
               OrdersBuy[Magic] = true;
               
               break;
             case OP_SELLLIMIT:          
               OrderModify(OrderTicket(), Tick.bid + Magic * Offset, 0, 0, 0);
               OrdersSell[Magic] = true;
               
               break;
           }
         }
         
        if(Magic > 100 && Magic < 200 ){
           Magic = Magic - 100;
           switch (OrderType())
           { 
             case OP_BUY:
               OrderModify(OrderTicket(), OrderOpenPrice(), 0, Tick.bid + Magic * Offset, 0);
               OrdersBuyStop[Magic] = true;
               
               break;
             case OP_SELL:
               OrderModify(OrderTicket(), OrderOpenPrice(), 0, Tick.ask - Magic * Offset, 0);
               OrdersSellStop[Magic] = true;
               
               break;
             case OP_BUYSTOP:
               OrderModify(OrderTicket(), Tick.ask + Magic * Offset, 0, 0, 0);
               OrdersBuyStop[Magic] = true;
               
               break;
             case OP_SELLSTOP:          
               OrderModify(OrderTicket(), Tick.bid - Magic * Offset, 0, 0, 0);
               OrdersSellStop[Magic] = true;
               
               break;
           }
           
         }
         if(Magic == 1001 ){//проверка полного закрытия
           OrderClose(OrderTicket(), OrderLots(), (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//проверка полного закрытия - работает
         }
         
         //проверка частичного закрытия на разных тиках
         if(Magic == 1002 ){
           double Lots = OrderLots();
           if(Lots==10){//первичный лот - закрыть 25%
               double LotsDel1=NormalizeDouble(Lots/4, 2);// закрыть 25% от первоначального лота
               OrderClose(OrderTicket(), LotsDel1, (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//проверка частичного закрытия
           }else{ //остаток закрыть на следущем тике
              OrderClose(OrderTicket(), Lots, (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//проверка полного закрытия
           }
         }
            
         //проверка частичного закрытия OrderClose() на том же самом тике. В вирт.  тестере не работает - продит множество ордеров с 1/2 лота. 
         //Т.к. после первого OrderSend остатку создастся новый тикет и старый тикет не будет найден при втором OrderSend, в итоге создастся 3-й тикет.
         if(Magic == 1003 ){
           double Lots = OrderLots();
           double LotsDel1=NormalizeDouble(Lots/3, 2);// закрыть 33% от первоначального лота
           OrderClose(OrderTicket(), LotsDel1,                         (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//проверка частичного закрытия
           OrderClose(OrderTicket(), NormalizeDouble(Lots-LotsDel1,2), (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//проверка полного закрытия остатка на том же тике - тут сбой
         }
         
         if(Magic == 1004 ){
           //OrderCloseBy(); //проверить бы
         }
         if(Magic == 1005 ){
            OrderDelete(OrderTicket());
         }

      }
     
    if(TimeHour(TimeCurrent())<23 && TimeHour(TimeCurrent())>0 ){return;} //совершаем операции с 0 до 1 и с 23 до 0
 
    for (int i = 1; i <= inAmount; i++)
    {
      if (!OrdersBuy[i])
        OrderSend(Symb, OP_BUYLIMIT, 10, Tick.ask - i * Offset, 0, 0, 0, NULL, i);

      if (!OrdersSell[i])
        OrderSend(Symb, OP_SELLLIMIT, 10, Tick.bid + i * Offset, 0, 0, 0, NULL, i);
      // 
      if (!OrdersBuyStop[i])
        OrderSend(Symb, OP_BUYSTOP, 10, Tick.ask + i * Offset, 0, 0, 0, NULL, i+100);

      if (!OrdersSellStop[i])
        OrderSend(Symb, OP_SELLSTOP, 10, Tick.bid - i * Offset, 0, 0, 0, NULL, i+100);
      
    }  
//проверка лимитных ордеров с ТП=СЛ=цене открытия.
    OrderSend(Symb, OP_BUYLIMIT, 11,  Tick.ask -  Offset, 0,Tick.ask -  Offset, Tick.ask -  Offset, NULL, 1100);
    OrderSend(Symb, OP_SELLLIMIT, 11, Tick.bid +  Offset, 0,Tick.bid +  Offset, Tick.bid +  Offset, NULL, 1100);

//проверка закрытия лимитных ордеров OrderDelete()
    OrderSend(Symb, OP_BUYLIMIT, 12,  Tick.ask -  Offset, 0,Tick.ask -  Offset, Tick.ask -  Offset, NULL, 1005);
    OrderSend(Symb, OP_SELLLIMIT, 12, Tick.bid +  Offset, 0,Tick.bid +  Offset, Tick.bid +  Offset, NULL, 1005);
      

//обычные ордера с ТП/СЛ = Offset Не будут модифицироваться, сработают по ТП/СЛ
    sl=Tick.bid-Offset; tp=Tick.ask+Offset;
    OrderSend(Symb, OP_BUY,  0.01, Tick.ask, 0, sl, tp,  NULL, 1000);//
    sl=Tick.ask+Offset; tp=Tick.bid-Offset;
    OrderSend(Symb, OP_SELL, 0.1, Tick.bid, 0, sl, tp,  NULL, 1000);//

//проверка ТП/СЛ на границе спреда. В виртуальном тестере - ок. У тестера MQ бывают сбои на 1-х сделках теста https://www.mql5.com/ru/forum/455977/page36#comment_51246904&nbsp;&nbsp; и   https://www.mql5.com/ru/forum/455977/page36#comment_51248196
    OrderSend(Symb, OP_BUY,  10, Tick.ask, 0, Tick.bid, Tick.bid,  NULL, 1000);//ТП/СЛ на границе спреда 
    OrderSend(Symb, OP_SELL, 10, Tick.bid, 0, Tick.ask, Tick.ask,  NULL, 1000);//ТП/СЛ на границе спреда 
  
//проверка полного закрытия OrderClose()
    OrderSend(Symb, OP_BUY,  10, Tick.ask, 0, 0, 0,  NULL, 1001);
    OrderSend(Symb, OP_SELL, 10, Tick.bid, 0, 0, 0,  NULL, 1001);


    //проверка частичного закрытия OrderClose() 
    sl=Tick.bid-Offset; tp=Tick.ask+Offset;
    OrderSend(Symb, OP_BUY,  10, Tick.ask, 0, 0, 0,  NULL, 1002);
    sl=Tick.ask+Offset; tp=Tick.bid-Offset;
    OrderSend(Symb, OP_SELL, 10, Tick.bid, 0, 0, 0,  NULL, 1002);// 

  }
}

Сервер:  MetaQuotes-Demo Hedge

Сделка с тикетом 99 на второй странице.

 

Этот отчет показал Firefox. Chrome зависает, ему нужны файлы поменьше.

Больше 5.4 млн строк можно выгрузить в файл, но броузер Firefox больше уже не может обработать.

При загрузке этого отчета броузер задействовал около 6Гб памяти (обрабатывал около 1 минуты), потом освободил, после чего отчет отобразился на странице: (Report задействует 5-6 Гб от 80-100 тыс строк)

Интересно, как с другими браузерами.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

fxsaber, 2023.10.18 15:00

Рейтинг самых быстрых браузеров при открытии больших html-таблиц - стейтментов. Сводный результат для таблицы на 35К строк.

Browser LengthTime (sec)
MyPal 24
Basilisk 35
PaleMoon 50
K-Meleon 52
Thorium 55

Мой однозначный выбор - MyPal.

 
fxsaber #:
Правильно ли понимаю, что в текущей реализации для работы highcharts требуется быть онлайн?

Да. Или если файлы JS скачаны ранее, то берутся они из кеша.
Хранятся 1 месяц: 8 января скачано, удалится 8 февраля


Хотел по быстрому добавить их код в файл, но там тысячи кавычек, автоматом поменял на \". Но выскакивает ошибка. По быстрому не получилось.
 
Forester #:

Хотел по быстрому добавить их код в файл, но там тысячи кавычек, автоматом поменял на \". Но выскакивает ошибка. По быстрому не получилось.

Быстрый вариант.

Scripts: Balance Graph HTML - How to generate various variants of the Balance Graph.
Scripts: Balance Graph HTML - How to generate various variants of the Balance Graph.
  • 2019.04.09
  • www.mql5.com
But has no possibility of further modification. For example, if you need to get graphs of profits, commissions, turnover, etc. Where can i generate various variants of the graph. I pasted your html code into my library
 

QuickReport - наверху, Report - внизу. Второй цветовую подстветку делает только для сработавших уровней. За счет этого есть понимание, что сработал SL или TP. В QuickReport добавить бы.

 
fxsaber #:

QuickReport - наверху, Report - внизу. Второй цветовую подстветку делает только для сработавших уровней. За счет этого есть понимание, что сработал SL или TP. В QuickReport добавить бы.

Подсвечивало и ТП и СЛ, т.к. оба установлены в одну цену. Случай редкий (только для теста крайних состояний), но для точности добавил код для определения и подсветки даже в нем.

Forester #:
Хотел по быстрому добавить их код в файл, но там тысячи кавычек, автоматом поменял на \". Но выскакивает ошибка. По быстрому не получилось.

Добавлять код в файл передумал, т.к. он требует лицензии. Подробнее тут https://shop.highcharts.com/
Поставил по умолчанию google.charts, если кому то нужно Highcharts и имеются права на его использование могут его включать через:

// By default MT4Orders_QuickReport use free google.charts, but you can use highcharts if you have rights.
// #define USE_highcharts // You can download and try out all Highcharts products for free. Once your project/product is ready for launch, purchase a commercial license. https://shop.highcharts.com/
 
Forester #:

Подсвечивало и ТП и СЛ, т.к. оба установлены в одну цену. Случай редкий (только для теста крайних состояний), но для точности добавил код для определения и подсветки даже в нем.

Интересный случай, который выявил еще одно различие от MQ-Тестера.


Это Virtual.


А это MQ-Тестер.

Virtual закрыл обе позиции по SL, MQ - в разнобой. У Virtual приоритет на SL-закрытие специально был прописан. MQ - неизвестно.

 
fxsaber #:

Интересный случай, который выявил еще одно различие от MQ-Тестера.

Это Virtual.

А это MQ-Тестер.

Virtual закрыл обе позиции по SL, MQ - в разнобой. У Virtual приоритет на SL-закрытие специально был прописан. MQ - неизвестно.

Да, тоже заметил. Может MQ от направления buy|sell зависит, что первым сработает.