Libraries: MT4Orders QuickReport - page 4

 
Forester #:

It turned out that the MQ tester transfers the deleted limit orders to the archive with a delay:

Please provide data for reproduction.
 
Forester #:

I changed to highchart. It turned out to be better: google.charts froze at 700,000 deals, while highchart displayed them without special brakes and was able to zoom in to individual deals.

Is it correct that in the current implementation highcharts requires to be online?
 
fxsaber #:
Please provide data for reproduction.
 // difference from - connect virtual tester via SelectByIndex() instead of #define VIRTUAL_TESTER
 
 #include <MT4Orders.mqh>

#define  REPORT_TESTER             // The tester will automatically record reports
//#define  REPORT_BROWSER            // Creating a report with browser startup - requires DLL permission.
#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 ){//check for complete closure
           OrderClose(OrderTicket(), OrderLots(), (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//check full closure - it works
         }
         
         //check partial closing on different ticks
         if(Magic == 1002 ){
           double Lots = OrderLots();
           if(Lots==10){//primary lot - close 25%
               double LotsDel1=NormalizeDouble(Lots/4, 2);// close 25% of the original lot
               OrderClose(OrderTicket(), LotsDel1, (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//check partial closure
           }else{ // close the balance on the next tick
              OrderClose(OrderTicket(), Lots, (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//check for complete closure
           }
         }
            
         //check partial closing of OrderClose() on the same tick. It doesn't work in virtual tester - it pushes through many orders with 1/2 lot. 
         //Because after the first OrderSend a new ticket will be created and the old ticket will not be found at the second OrderSend, as a result the 3rd ticket will be created.
         if(Magic == 1003 ){
           double Lots = OrderLots();
           double LotsDel1=NormalizeDouble(Lots/3, 2);// close 33% of the original lot
           OrderClose(OrderTicket(), LotsDel1,                         (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//check partial closure
           OrderClose(OrderTicket(), NormalizeDouble(Lots-LotsDel1,2), (OrderType()==OP_BUY ? Tick.bid : Tick.ask), 0 ) ;//check the full closing of the balance on the same tick - there is a failure here
         }
         
         if(Magic == 1004 ){
           //OrderCloseBy(); //check it out
         }
         if(Magic == 1005 ){
            OrderDelete(OrderTicket());
         }

      }
     
    if(TimeHour(TimeCurrent())<23 && TimeHour(TimeCurrent())>0 ){return;} // perform operations from 0 to 1 and from 23 to 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);
      
    }  
//check limit orders with TP=SL=open price.
    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);

//check closing of limit orders 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);
      

//common orders with TP/SL = Offset Will not be modified, triggered by TP/SL
    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);//TP/SL at the spread boundary 
    OrderSend(Symb, OP_SELL, 10, Tick.bid, 0, Tick.ask, Tick.ask,  NULL, 1000);//TP/SL at the spread boundary 
  
//check if OrderClose() is completely closed
    OrderSend(Symb, OP_BUY,  10, Tick.ask, 0, 0, 0,  NULL, 1001);
    OrderSend(Symb, OP_SELL, 10, Tick.bid, 0, 0, 0,  NULL, 1001);


    //check partial closure 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);// 

  }
}

Server: MetaQuotes-Demo Hedge

Deal with ticket 99 on the second page.

 

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

More than 5.4 million lines can be uploaded to a file, but Firefox browser can't process any more.

When loading this report, the browser used about 6GB of memory (processed about 1 minute), then freed it, after which the report is displayed on the page: (Report uses 5-6GB from 80-100k rows)

I wonder how it is with other browsers.

Forum on trading, automated trading systems and testing trading strategies

Bugs, bugs, questions

fxsaber, 2023.10.18 15:00

Rating of the fastest browsers when opening large html-tables - steutments. Summary result for a table with 35K rows.

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

My unequivocal choice is MyPal.

 
fxsaber #:
Am I correct in understanding that the current implementation requires you to be online for highcharts to work?

Yes. Or if JS files are downloaded earlier, they are taken from the cache.
Stored for 1 month: downloaded on 8 January, deleted on 8 February


I wanted to quickly add their code to the file, but there are thousands of quotes, automatically changed to \"". But an error pops up. It didn't work quickly.
 
Forester #:

I wanted to quickly add their code to the file, but there are thousands of quotes, I automatically changed it to \"". But an error pops up. I couldn't do it quickly.

Quick version.

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 is at the top, Report is at the bottom. The second one makes colour highlighting only for triggered levels. Due to this there is an understanding that SL or TP was triggered. I would add it to QuickReport.

 
fxsaber #:

QuickReport is at the top, Report is at the bottom. The second one makes colour highlighting only for triggered levels. Due to this there is an understanding that SL or TP was triggered. I would add it to QuickReport.

Both TP and SL would be highlighted, since both are set at the same price. The case is rare (only for extreme state test), but for accuracy I added code to detect and highlight even in it.

Forester #:
I wanted to quickly add their code to the file, but there are thousands of quotes, I automatically changed it to \"". But an error pops up. It didn't work quickly.

I changed my mind about adding the code to the file because it requires a licence. Read more here https://shop.highcharts.com/
I set google.charts by default, if someone needs Highcharts and has rights to use it, they can include it through:

// 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 licence. https://shop.highcharts.com/
 
Forester #:

Both TP and SL were highlighted, since both are set to the same price. The case is rare (only for the test of extreme states), but for accuracy I added code for detection and highlighting even in it.

An interesting case that revealed another difference from the MQ Tester.


This is Virtual.


And this is MQ-Tester.

Virtual has closed both positions on SL, MQ has closed both positions on SL, MQ has closed both positions on SL, MQ has closed both positions on SL. Virtual had the priority for SL-closing specially prescribed. MQ - unknown.

 
fxsaber #:

An interesting case that brought out another difference from the MQ Tester.

This is Virtual.

And this is MQ-Tester.

Virtual closed both positions by SL, MQ - in a different way. The priority for SL-closing was specially prescribed for Virtual. MQ - unknown.

Yeah, I noticed that too. Maybe MQ depends on the direction of buy|sell, what will work first.