Libraries: Virtual - page 8

 

After language changes over the last year, my version of Virtual stopped working. I switched back to yours.
But I really missed a commission that would take into account price changes. Especially for crypto, where the price changes many times during testing.
In my old version was accurate, but slow calculation with string operations and querying prices by instrument. Probably from this slowdown you didn't want to add it to your own.

This time I made a simple and fast calculation for instruments like EURUSD, AUDUSD ... with USD deposit currency and for all crypto, there all to USDT. I.e. if quote currency == account currency, the calculation will be correct.

#define COMMISSION_TO_PRICE 2 // умножить полученную комиссию на цену, например для EURUSD *=1.12345; 1 - комиссия берется только при входе, 2 - комиссия берется 2 раза и при входе и при выходе

The commission is simply multiplied by OpenPrice or ClosePrice. For instruments like USDJPY or if the deposit currency is not USD(T), the option can be disabled, as it will not be accurate (like your current option).

#ifdef  ORDER_COMMISSION
 this.Commission = this.Lots * (ORDER_COMMISSION);
 #ifdef  COMMISSION_TO_PRICE
   this.Commission *= this.OpenPrice + (COMMISSION_TO_PRICE==2 ? this.ClosePrice : 0.0);
 #endif // COMMISSION_TO_PRICE
#endif// ORDER_COMMISSION

Here is what I got on EURUSD:

DC:
Virtual c * per price
Virtual without * on price

As you can see, with the added option the commission differs only by 18 cents for 140 trades. And without it by 42 dollars. Of course, you can select in your variant the average multiplier not 4, but 4.305 for example (average commission for the test), but it will have to be done manually for each instrument and recompile.

The edits are not big, I hope you will want to add this option to the library code. Or maybe you will think of something more universal.


Files:
Order.mqh  36 kb
 
Forester deposit currency USD and for all crypto, there all to USDT. I.e. if the quote currency == account currency, the calculation will be correct.

In fact, this formula always works.

Commission = 0.002%; // per side.

OrderCommission = (OrderOpenPrice + OrderClosePrice) * Commission * OrderLots * TickValue / TickSize;

Of course, you can choose in your variant the average multiplier not 4, but 4.305 for example (average commission for the test), but it will have to be done manually for each instrument and recompile.

Another variant.

input double inCommission = 0;
// .....
#define  ORDER_COMMISSION inCommission // OrderCommission() = OrderLots() * (ORDER_COMMISSION)), including the dynamic option.

Edits are not big, I hope you will want to add this variant to the library code. Or maybe you will think of something more universal.

Totally agree that the edit is useful and should be made. It should be checked for partial close (OrderClose not for the whole lot) and CloseBy. To check it, it is enough to write a script where two differently directed positions are opened on the same tick and a partial and CloseBy-close are made at once. I am not ready to do it myself yet. If you provide such a script with correct results, I will make your corrections faster.

 
fxsaber #:

In fact, this formula works all the time.

It's easier for you, you're always on top of things. I don't do it all the time. For the first time since July, I decided to test something again....

About
OrderClosePrice
- there are probably some brokerage centres that take commission only at opening - for them it is better not to take it into account. For pipsing the difference will be small, but for big targets it will be noticeable.
 
fxsaber #:
Totally agree that the edit is useful and should be made. It is necessary to check for partial closing (OrderClose not for the whole lot) and CloseBy. To check it, it is enough to write a script where two differently directed positions are opened on the same tick and a partial and CloseBy-close are made at once. I am not ready to do it myself yet. If you send me such a script with a correct result, I will make your corrections faster.
I tested what is commented out there and I left it as a working version. But now I've forgotten everything. CloseBy - I don't use it, I usually have simpler ideas. I don't have time for it either. As long as there is enthusiasm, I will do strategy.
 

Virtual adds a commission to non-performing limits:


Apparently we need to do a type check
 
Forester #:

Virtual adds a commission to unexecuted limits:

Apparently we need to do a type check
#define ORDER_COMMISSION -5 // OrderCommission() = OrderLots() * (ORDER_COMMISSION)), including the dynamic option.
#include <fxsaber\Virtual\Virtual.mqh> // https://www.mql5.com/en/code/22577

void OnStart()
{
  if (VIRTUAL::SelectByHandle(VIRTUAL::Create()))
  {
    VIRTUAL::NewTick();
    
    OrderDelete(OrderSend(_Symbol, OP_BUYLIMIT, 1, 0.01, 0, 0, 0));
    
    Print(VIRTUAL::ToString(1));
  }
}


Result.

#2 2025.11.25 19:23:11.105 buy limit 1.00 EURGBP.pro 0.01000 0.00000 0.00000 2025.11.25 19:23:11.105 0.87715 0.00 0.00 0.00 0 - 00:00:00


It works correctly. Apparently, these edits require additional checking.

 
fxsaber #:

It works correctly. Apparently, these edits require additional verification.

You are right.

In ToClose() I added calculation of commissions outside if (this.IsPosition()){

Fixed it, attached the file

Files:
Order.mqh  37 kb