Experts: MQL5 Programming for Traders – Source Codes from the Book. Part 6 - page 2

 
Stanislav Korotky #:
Orders, deals, positions are not related to timeframes anyhow. You either misunderstood something or your wording is incorrect.
Am sorry I guess my choice of word is confusing by "timeframe" I mean "date range". Say I want to select Deals/Orders transacted within a given date range like say Deals from 2025-10-01 00:00:00 to 2025-10-22 23:59:59. 
 
pauldic #:
Am sorry I guess my choice of word is confusing by "timeframe" I mean "date range". Say I want to select Deals/Orders transacted within a given date range like say Deals from 2025-10-01 00:00:00 to 2025-10-22 23:59:59. 

If you want to analyze a subrange of a trading history, when it's more efficient to request only this part of the history before the filtering, without affecting the filtering code itself:

input datetime SubrangeFrom = 0;
input datetime SubrangeTo = 0;

...

{
   HistorySelect(SubrangeFrom, SubrangeTo);
   // ... filter code goes here as is
}

If, for some reason, you want to select a (more narrow) subrange within the global range which you applied with HistorySelect, then you still can do it in the filtering code like so:

{
      // some of these go here

      // HistorySelect(0, LONG_MAX);
      // HistorySelectByPosition(PositionID);
      ...
      DealTuple deals[];
      if(SubrangeFrom != SubrangeTo && SubrangeFrom < SubrangeTo)
      {
         filter.let(DEAL_TIME, SubrangeFrom - 1, IS::GREATER).let(DEAL_TIME, SubrangeTo + 1, IS::LESS);
      }
      filter.let(DEAL_POSITION_ID, PositionID).select(deals, true);
      ...
}

The highlighted in yellow line sets 2 conditions for the datetime range [SubrangeFrom, SubrangeTo] using additional qualificators IS::GREATER and IS::LESS (by default, they are not specified in other calls to let(), and then IS::EQUAL is normally used for single value fields).

I know only one reason to apply the subfilter by date range - it is for orders' setup time (ORDER_TIME_SETUP), because HistorySelect is applied to another datetime property of orders - namely order execution time (ORDER_TIME_DONE). Also it might be interesting to filter a subrange of active orders (not in the history), if there are many of them.

You can look at the MQL5/Scripts/MQL5Book/p6/TradeHistoryPrint.mq5 example script, as a starting point.
 
Stanislav Korotky #:

If you want to analyze a subrange of a trading history, when it's more efficient to request only this part of the history before the filtering, without affecting the filtering code itself:

If, for some reason, you want to select a (more narrow) subrange within the global range which you applied with HistorySelect, then you still can do it in the filtering code like so:

The highlighted in yellow line sets 2 conditions for the datetime range [SubrangeFrom, SubrangeTo] using additional qualificators IS::GREATER and IS::LESS (by default, they are not specified in other calls to let(), and then IS::EQUAL is normally used for single value fields).

I know only one reason to apply the subfilter by date range - it is for orders' setup time (ORDER_TIME_SETUP), because HistorySelect is applied to another datetime property of orders - namely order execution time (ORDER_TIME_DONE). Also it might be interesting to filter a subrange of active orders (not in the history), if there are many of them.

You can look at the MQL5/Scripts/MQL5Book/p6/TradeHistoryPrint.mq5 example script, as a starting point.
@Stanislav Korotky Thanks once again... It is a great starting point for me and will start working with it
 

Bugfix MQL5/Include/MQL5Book/TradeUtils.mqh.

   bool Equal(const double v1, const double v2)
   {
      return v1 == v2 || fabs(v1 - v2) < DBL_EPSILON * fmax(1.0, fmax(fabs(v1), fabs(v2)));
   }
Files:
TradeUtils.mqh  12 kb
 
pauldic #:

Use the CODE button (Alt-S) when inserting code.

A moderator formatted the incorrectly pasted code. Usually, such code is removed.

@Stanislav Korotky Please can you help look into this error, I believe it started after MT5 updates because I knew the code works in the previous months without any modifications.

parameter convertion type 'long[][2]' to 'string[][] &' is not allowed SymbolFilter.mqh 199 20

parameter convertion type 'double[][2]' to 'string[][] &' is not allowed TradeFilter.mqh 332 20
parameter convertion type 'long[][2]' to 'string[][] &' is not allowed TradeFilter.mqh 163 17


I suspect the code below will help to replicate the issue:


Hi @Paul Dick 

Try this https://www.mql5.com/en/code/57233 for sorting arrays

Introsort (Introspective sort) using Function Pointers
Introsort (Introspective sort) using Function Pointers
  • 2025.03.18
  • www.mql5.com
A hybrid sorting algorithm that provide fast performance for sorting arrays of simple types, structures or object pointers.
 

I am attaching an updated version of the calculation file of the customoptimisation criterion based on R2 - RSquared.mqh, in which the calculation for the case of variable lots has been corrected.

The quality of estimation has been significantly improved - judging by the table of optimisation results, the combination of recovery factor and Sharpe parameters has been obtained.

Example of use.

double OnTester()
{
   HistorySelect(0, LONG_MAX);
   
   #define  STAT_PROPS 5
   
   const ENUM_DEAL_PROPERTY_DOUBLE props[STAT_PROPS] =
   {
      DEAL_PROFIT, DEAL_SWAP, DEAL_COMMISSION, DEAL_FEE, DEAL_VOLUME
   };
   double expenses[][STAT_PROPS];
   ulong tickets[]; // used here only to match 'select' prototype, but useful for debug
   
   DealFilter filter;
   filter.let(DEAL_TYPE, (1 << DEAL_TYPE_BUY) | (1 << DEAL_TYPE_SELL), IS::OR_BITWISE)
      .let(DEAL_ENTRY, (1 << DEAL_ENTRY_OUT) | (1 << DEAL_ENTRY_INOUT) | (1 << DEAL_ENTRY_OUT_BY), IS::OR_BITWISE)
      .select(props, tickets, expenses);

   const int n = ArraySize(tickets);
   
   double balance[];
   double volumes[]; // take trade volumes into account for using R2 criterion
   
   ArrayResize(balance, n + 1);
   balance[0] = 0;
   ArrayResize(volumes, n + 1);
   volumes[0] = 0;
   
   for(int i = 0; i < n; ++i)
   {
      double result = 0;
      for(int j = 0; j < STAT_PROPS - 1; ++j)
      {
         result += expenses[i][j];
      }
      // use volumes as a model - more investments - more returns expected
      volumes[i + 1] = expenses[i][STAT_PROPS - 1] + volumes[i];
      balance[i + 1] = result + balance[i];
   }
   
   const double r2 = RSquaredTest(balance, volumes);
   
   #undef  STAT_PROPS
   
   return r2 * 100;
}
Files:
RSquared.mqh  4 kb
 

I've recently been learning Frame and I tested your code, FrameTransfer.mq5. This line is throwing an error in the current MT5 compiler. Please verify: #property tester_set "FrameTransfer.set" (invalid tester set file extension, '*.set' expected FrameTransfer.mq5)

It must be changed like this for it to compile successfully: #property tester_set "\\Presets\\FrameTransfer.set"

Even `#property tester_set "/Presets/FrameTransfer.set"` will fail.

Perhaps you could modify the description in the algorithm book:


 
hini #property tester_set "FrameTransfer.set" (invalid tester set file extension, '*.set' is expected FrameTransfer.mq5)

For successful compilation it should be changed as follows: #property tester_set "\\Presets\\FrameTransfer.set"

Even `#property tester_set "/Presets/FrameTransfer.set"` will fail.

Perhaps you could change the description in the algorithm book:


This is an obvious compiler bug - it gives the error: "invalid tester set file extension, '*.set' expected" to the code:

#property tester_set "FrameTransfer.set"

where the file has the required extension. The file location path has nothing to do with it.

The bug has been around for a long time, since at least 2024. Why MQ is not itching to fix it, I don't know.

As for the book edits, they are not needed in this case, but in any case the book is now fully under MQ's control.

 
Stanislav Korotky #:

This is an obvious compiler bug - it gives the error: "invalid tester set file extension, '*.set' expected" to the code:

where the file has the required extension. The file location path has nothing to do with it.

The bug has been around for a long time, since at least 2024. Why MQ is not itching to fix it, I don't know.

As for the book edits, they are not needed in this case, but in any case the book is now fully under MQ's control.

Confirmed and reported. Let see if it will be fixed.
 
Stanislav Korotky #:

This is an obvious compiler bug - it gives the error: "invalid tester set file extension, '*.set' expected" to the code:

Thank you, fixed!

To stay on your MetaEditor version add zero to the filename end: "myset.set\0"