Questions from Beginners MQL5 MT5 MetaTrader 5 - page 1415

 
Thanks for the information. In The checks a trading robot must pass a method "CheckMoneyForTrade" is mentioned, which checks whether the margin to be used for the trade is greater than the free margin (ACCOUNT_FREE_MARGIN). If I have understood you correctly, then you should also check whether the funds used also exceed a certain percentage of the account balance, i.e. something like:
 if (freeMargin - tradeMargin < balance * 0.9) return false;

Whereby you can of course change the 0.9 to (1 - maxRisk) and implement a "Maximum Risk in %" property that can be set by the user.

P.S. Do you use the first name or the last name here in the forum?
 
Benjamin Fotteler #:
Thanks for the information. In The checks a trading robot must pass a method "CheckMoneyForTrade" is mentioned, which checks whether the margin to be used for the trade is greater than the free margin (ACCOUNT_FREE_MARGIN). If I have understood you correctly, then you should also check whether the funds used also exceed a certain percentage of the account balance, i.e. something like:

Whereby you can of course change the 0.9 to (1 - maxRisk) and implement a "Maximum Risk in %" property that can be set by the user.

P.S. Are we on first-name terms or first-name terms here in the forum?

Everyone stumbles over the lot size and there is a lot of code and comments here!

I have now puzzled together what William Roeder wrote for MT5, that would be the untested(!!) function:
(https://www.mql5.com/en/forum/133792/page3#comment_3405179 & https://www.mql5.com/en/forum/390088#comment_28092477)

double lotsz (double risk, double sl, ENUM_ORDER_TYPE ordDir, string sym="", double CommissionPerLot=0) {
   MqlTick mqTick;
   if (sym == "") sym = _Symbol;
   double deltaValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
   SymbolInfoTick(sym,mqTick); 
   double diff = (ordDir==ORDER_TYPE_BUY) ? mqTick.ask - sl : ( (ordDir==ORDER_TYPE_SELL) ? sl - mqTick.bid : -1.0 );
   if (diff<0.0) return(0.0);
   double lts = ( (AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk/100) / (diff * deltaValue + CommissionPerLot) );
   return( fmin(fmax(SymbolInfoDouble(sym,SYMBOL_VOLUME_MIN),lts),SymbolInfoDouble(sym,SYMBOL_VOLUME_MAX)));
}
// use: lotsz(5, sl)

Please let me know if you find a mistake!

Since most people here are somehow anonymous with their nicknames or first names and that used to be even more the case, the "Du" has become naturalised.

Why is there NO Complete EA within the Code-Base? - When does the market close or open?
Why is there NO Complete EA within the Code-Base? - When does the market close or open?
  • 2011.08.20
  • www.mql5.com
I wanted to close all orders before end of the week (market close friday,) to prevent loss should the market gap over the week end, by passing the sl. ) so the question is when does the market close (or open. For example info on opened charts and history data, time info (like gmt, timezone, dst), market open, close info
 

Thanks for the code. The only thing missing was the adaptation to a valid intermediate lot size:

double lotsz (double risk, double sl, ENUM_ORDER_TYPE ordDir, string sym="", double CommissionPerLot=0) {
   MqlTick mqTick;
   if (sym == "") sym = _Symbol;
   double deltaValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
   SymbolInfoTick(sym,mqTick); 
   double diff = (ordDir==ORDER_TYPE_BUY) ? mqTick.ask - sl : ( (ordDir==ORDER_TYPE_SELL) ? sl - mqTick.bid : -1.0 );
   if (diff<0.0) return(0.0);
   double lts = ( (AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk/100) / (diff * deltaValue + CommissionPerLot) );
   lts = ( fmin(fmax(SymbolInfoDouble(sym,SYMBOL_VOLUME_MIN),lts),SymbolInfoDouble(sym,SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return ((int)MathRound(lts/stepSize)*stepSize);
}
// use: lotsz(5, sl)

I have another question: If I calculate the loss of a stopped out trade with TICK_VALUE or with deltaValue as above, the result is always slightly different from the MQL5 internal calculation:

double price=(ordDir==ORDER_TYPE_BUY) ? mqTick.ask : ((ordDir==ORDER_TYPE_SELL) ? mqTick.bid : mqTick.last);
double loss;
OrderCalcProfit(ordDir, sym, 1, price, sl, loss)

Is this because the loss/gain per tick is different for a EUR account and for market price 1.0 and market price 1.2? Because if I enter, for example, "price + 0.1" instead of price and "sl + 0.1" instead of sl in the code below, then the tick distance (diff) is the same, but the respective results output by OrderCalcProfit are different. And when I look at the profits/losses I get from the manual trades, the latter seems to be confirmed.

If I am right, then the following code would be more accurate:

double lotsz (double risk, double entry, double sl, ENUM_ORDER_TYPE ordDir, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   double loss;
   OrderCalcProfit(ordDir, sym, 1, entry, sl, loss);
   double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / -loss);
   lts = (fmin(fmax(SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN), lts), SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return ((int)MathRound(lts / stepSize) * stepSize);
}
// use: lotsz(5, ask, sl)
P.S. Thanks again for the basic idea: tying the risk factor not to the balance but to the free margin clearly makes sense.
 

The following code was created according to mql 5's own expert parabolic sar. Can I reverse the operation of the buy signal and the sell signal here? That is, when the buy signal comes, I want it to open sales instead of buying. can anyone help?




#property copyright "Copyright 2022, MetaQuotes Ltd."

#property link "https://www.mql5.com"

#property version "1.00"

//+------------------------------------------------------------------+

//| Include |

//+------------------------------------------------------------------+

#include <Expert\Expert.mqh>

//--- available signals

#include <Expert\Signal\SignalSAR.mqh>

//--- available trailing

#include <Expert\Trailing\TrailingNone.mqh>

//--- available money management

#include <Expert\Money\Money\MoneyFixedLot.mqh>

//+------------------------------------------------------------------+

//| Inputs |

//+------------------------------------------------------------------+

//--- inputs for expert

input string Expert_Title ="sar"; // Document name

ulong Expert_MagicNumber =13831; //

bool Expert_EveryTick =false; //

//--- inputs for main signal

input int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100]

input int Signal_ThresholdClose=10; // Signal threshold value to close [0...100]

input double Signal_PriceLevel =0.0; // Price level to execute a deal

input int Signal_Expiration =4; // Expiration of pending orders (in bars)

input double Signal_SAR_Step =0.02; // Parabolic SAR(0.02,0.2) Speed increment

input double Signal_SAR_Maximum =0.2; // Parabolic SAR(0.02,0.2) Maximum rate

input double Signal_SAR_Weight =1.0; // Parabolic SAR(0.02,0.2) Weight [0....1.0]

//--- inputs for money

input double Money_FixLot_Percent =10.0; // Percent

input double Money_FixLot_Lots =0.1; // Fixed volume

//+------------------------------------------------------------------+

//| Global expert object |

//+------------------------------------------------------------------+

CExpert ExtExpert;

//+------------------------------------------------------------------+

//| Initialisation function of the expert |

//+------------------------------------------------------------------+

int OnInit()

{

//--- Initialising expert

if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber))

{

//----- failed

printf(__FUNCTION__+": error initialising expert");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Creating signal

CExpertSignal *signal=new CExpertSignal;

if(signal==NULL)

{

//----- failed

printf(__FUNCTION__+": error creating signal");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//---

ExtExpert.InitSignal(signal);

signal.ThresholdOpen(Signal_ThresholdOpen);

signal.ThresholdClose(Signal_ThresholdClose);

signal.PriceLevel(Signal_PriceLevel);

signal.Expiration(Signal_Expiration);

//--- Creating filter CSignalSAR

CSignalSAR *filter0=new CSignalSAR;

if(filter0==NULL)

{

//----- failed

printf(__FUNCTION__+": error creating filter0");

ExtExpert.Deinit();

return(INIT_FAILED);

}

signal.AddFilter(filter0);

//--- Set filter parameters

filter0.Step(Signal_SAR_Step);

filter0.Maximum(Signal_SAR_Maximum);

filter0.Weight(Signal_SAR_Weight);

//--- Creation of trailing object

CTrailingNone *trailing=new CTrailingNone;

if(trailing==NULL)

{

//----- failed

printf(__FUNCTION__+": error creating trailing");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Add trailing to expert (will be deleted automatically))

if(!ExtExpert.InitTrailing(trailing))

{

//----- failed

printf(__FUNCTION__+": error initialising trailing");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Set trailing parameters

//--- Creation of money object

CMoneyFixedLot *money=new CMoneyFixedLot;

if(money==NULL)

{

//----- failed

printf(__FUNCTION__+": error creating money");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Add money to expert (will be deleted automatically))

if(!ExtExpert.InitMoney(money))

{

//----- failed

printf(__FUNCTION__+": error initialising money");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Set money parameters

money.Percent(Money_FixLot_Percent);

money.Lots(Money_FixLot_Lots);

//--- Check all trading objects parameters

if(!ExtExpert.ValidationSettings())

{

//----- failed

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- Tuning of all necessary indicators

if(!ExtExpert.InitIndicators())

{

//----- failed

printf(__FUNCTION__+": error initialising indicators");

ExtExpert.Deinit();

return(INIT_FAILED);

}

//--- ok

return(INIT_SUCCEEDED);

}

//+------------------------------------------------------------------+

//| Deinitialisation function of the expert |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

ExtExpert.Deinit();

}

//+------------------------------------------------------------------+

//| "Tick" event handler function |

//+------------------------------------------------------------------+

void OnTick()

{

ExtExpert.OnTick();

}

//+------------------------------------------------------------------+

//| "Trade" event handler function |

//+------------------------------------------------------------------+

void OnTrade()

{

ExtExpert.OnTrade();

}

//+------------------------------------------------------------------+

//| "Timer" event handler function |

//+------------------------------------------------------------------+

void OnTimer()

{

ExtExpert.OnTimer();

}

//+------------------------------------------------------------------+


 
Interesting suggestion, I'll have a look at it. The OrderCalcProfit() function only exists in MT5 and the ideas for lot calculation date back to MT4 times...
 
I can't open my session in the app to see how much money I have
 

I have now had time to work out your solution. It is more accurate (while the other is more cautious as commission is taken into account?) and it is apparently less error-prone, as can be seen with gold and silver on the demo account at MQ - with Roboforex it is, as expected, somewhat more cautious than your solution:

MetaQuotes demo account (b. 3369 Beta channel)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   XAUUSD  in: 1717.65000 sl:1717.15000  diff:0.50000  delta:10.00000  delta:*diff:5.00000  tVal:0.10000  tSz:0.01000
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   XAGUSD  in: 18.45100 sl:18.40100  diff:0.05000  delta:500.00000  delta:*diff:25.00000  tVal:0.50000  tSz:0.00100
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   EURUSD  in: 1.02185 sl:1.02235  diff:0.00050  delta:97861.72139  delta:*diff:48.93086  tVal:0.97862  tSz:0.00001
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  XAUUSD  BU  in: 1717.65000  sl: 1717.15000  lotsC: 71.3100 (-3489.26)  lotsB: 10.2000 (-499.09)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  XAGUSD  BU  in: 18.45100  sl: 18.40100  lotsC: 18.4900 (-4523.66)  lotsB: 2.0400 (-499.09)
2022.07.25 17:43:42.645 test_MM-functions (EURUSD,M1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 9983.40 EUR:  EURUSD  SE  in: 1.02185  sl: 1.02235  lotsC: 9.8000 (-479.29)  lotsB: 10.2100 (-499.34)


RoboForex Demo account (b. 3320 release channel)
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   XAUUSD  in: 1717.10000 sl:1717.15000  diff:0.05000  delta:100.00000  delta:*diff:5.00000  tVal:0.10000  tSz:0.00100
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   XAGUSD  in: 18.43400 sl:18.43350  diff:0.00050  delta:5000.00000  delta:*diff:2.50000  tVal:0.05000  tSz:0.00001
2022.07.25 17:46:22.772 test_MM-functions (EURUSD,D1)   EURUSD  in: 1.02186 sl:1.02236  diff:0.00050  delta:100000.00000  delta:*diff:50.00000  tVal:1.00000  tSz:0.00001
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  XAUUSD  SE  in: 1717.10000  sl: 1717.15000  lotsC: 38.2000 (-191.00)  lotsB: 53.4900 (-267.45)
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  XAGUSD  BU  in: 18.43400  sl: 18.43350  lotsC: 59.4300 (-148.57)  lotsB: 106.9700 (-267.42)
2022.07.25 17:46:22.773 test_MM-functions (EURUSD,D1)   Set: Risk: 5.0 %, dSL: 50  Com/Lot: 2.00  Free: 5348.69 USD:  EURUSD  SE  in: 1.02186  sl: 1.02236  lotsC: 5.1400 (-257.00)  lotsB: 5.3500 (-267.50)

On the MQ account, the lot sizes would be far too high.

Here is my script for comparing the two methods:

//+------------------------------------------------------------------+
//|                                            test_MM-functions.mq5 |
//|                                                            Calli |
//|                              https://www.mql5.com/de/users/gooly |
//+------------------------------------------------------------------+
#property copyright "Calli"
#property link      "https://www.mql5.com/de/users/gooly"
#property version   "1.00"
#property script_show_inputs
//--- input parameters
input double   risk_perCent   = 5.0;   // risk of capital in % on free_margin
input double   diff_sl        = 50;    // diff sl in points from entry
input double   CommPerLot     = 2.00;  

string Com = "",Syms[] = {"XAUUSD", "XAGUSD", "EURUSD" }; //,"AUDUSD","GBPCHF","GBPUSD", "EURCAD", "USDCAD", "USDRUB", "GBPJPY", "USDJPY"};

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
#define  forEach(TYPE, VAR, ARRAY) \
                TYPE VAR=NULL; \
                for(int i##VAR=0;  i##VAR<ArraySize(ARRAY)&&((VAR=ARRAY[i##VAR])!=NULL||true);  i##VAR++)

void OnStart()
  {
//---
   MqlTick mqTick;
   forEach(string, sym, Syms){
      
      double pnt = SymbolInfoDouble(sym,SYMBOL_POINT);
      ENUM_ORDER_TYPE ord = GetMicrosecondCount()%2==0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL; // randomly buy or sell
      SymbolInfoTick(sym,mqTick); 
      double entry = (ord==ORDER_TYPE_BUY) ? mqTick.ask : mqTick.bid,
             sl    = (ord==ORDER_TYPE_BUY) ? entry - diff_sl*pnt : entry + diff_sl*pnt,
             lossC = 0.0, lossB = 0.0,
             lotsC = lotszC(risk_perCent, entry, sl, sym, CommPerLot), 
             lotsB = lotszB(risk_perCent, entry, sl, sym, CommPerLot);
      
      if (!OrderCalcProfit(ord, sym, lotsC, entry, sl, lossC) ) 
         Print("chk OrderCalcProfit(",EnumToString(ord),", ",sym,", lot: ",lotsC,", in: ",DoubleToString(entry,6),", out: ",DoubleToString(sl,6),", lossC) => err: ",_LastError," lossC: ",lossC);
             
      if (!OrderCalcProfit(ord, sym, lotsB, entry, sl, lossB) ) 
         Print("chk OrderCalcProfit(",EnumToString(ord),", ",sym,", lot: ",lotsC,", in: ",DoubleToString(entry,6),", out: ",DoubleToString(sl,6),", lossC) => err: ",_LastError," lossC: ",lossC);
             
      string res = StringFormat("Set: Risk: %.1f %%, dSL: %.0f  Com/Lot: %.2f  Free: %.2f %s:  %s  %s  in: %.5f  sl: %.5f  lotsC: %.4f (%+.2f)  lotsB: %.4f (%+.2f)",
                                 risk_perCent, diff_sl, CommPerLot,
                                 AccountInfoDouble(ACCOUNT_MARGIN_FREE),AccountInfoString(ACCOUNT_CURRENCY),
                                 sym, (ord==ORDER_TYPE_BUY ? "BU" : "SE"), entry, sl, lotsC, lossC, lotsB, lossB );
      Com = Com + res+"\n";
   }
   Comment(Com);
   //Print(Com);
  }
//+------------------------------------------------------------------+
double lotszC (double risk, double entry, double sl, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   double deltaValue = SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE);
   ENUM_ORDER_TYPE ordDir = entry > sl ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   double diff = fabs (entry - sl); 
   Print(sym,"  in: ",DoubleToString(entry,5)," sl:",DoubleToString(sl,5),"  diff:",DoubleToString(diff,5),
         "  delta:",DoubleToString(deltaValue,5),"  delta:*diff:",DoubleToString(deltaValue*diff,5),
         "  tVal:",DoubleToString(SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_VALUE),5),"  tSz:",
         DoubleToString(SymbolInfoDouble(sym, SYMBOL_TRADE_TICK_SIZE),5));
   double lts = ( (AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk/100) / (diff * deltaValue + CommissionPerLot) );
   lts = ( fmin(fmax(SymbolInfoDouble(sym,SYMBOL_VOLUME_MIN),lts),SymbolInfoDouble(sym,SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return (MathRound(lts/stepSize)*stepSize);
}

double lotszB (double risk, double entry, double sl, string sym="", double CommissionPerLot=0) {
   if (sym == "") sym = _Symbol;
   ENUM_ORDER_TYPE ordDir = entry > sl ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
   double loss;
   if (!OrderCalcProfit(ordDir, sym, 1, entry, sl, loss)) return(-1.0);
   double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / -loss);
   lts = (fmin(fmax(SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN), lts), SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX)));
   double stepSize = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
   return (MathRound(lts / stepSize) * stepSize);
}

I derived the direction from in > sl (buy) or in < sl (sell). Then there would be no problems with the pending orders

 

Thank you for your tests. Yes, if you compare the results with each other, you can see on the one hand the consistency of OrderCalcProfit and on the other hand, at least for EURUSD and RoboForex, that the results differ by approximately "Lot size * CommissionPerLot". This could be added:

if (!OrderCalcProfit(ordDir, sym, 1, entry, sl, loss)) return(-1.0);
double lts = ((AccountInfoDouble(ACCOUNT_MARGIN_FREE) * risk * 0.01) / (-loss + CommissionPerLot);
If I used the forum search correctly, there is no way to query the "CommissionPerLot" value directly using MQL5, is there?
 
Benjamin Fotteler #:


If I have used the forum search correctly, then there is no way to query the "CommissionPerLot" value directly using MQL5, is there?

Yes, not directly in the terminal, but request it from the broker or in the trading history: DEAL_COMMISSION.

Dokumentation zu MQL5: Konstanten, Enumerationen und Strukturen / Handelskonstanten / Eigenschaften der Deals
Dokumentation zu MQL5: Konstanten, Enumerationen und Strukturen / Handelskonstanten / Eigenschaften der Deals
  • www.mql5.com
Eigenschaften der Deals - Handelskonstanten - Konstanten, Enumerationen und Strukturen - Nachschlagewerk MQL5 - Nachschlagewerk über die Sprache des algothitmischen/automatischen Handels für MetaTrader 5
 



Dear members~.


I am trying to count candles. please help~~


int Barcount;

if(Barcount != Bars)

{ Barcount
Barcount = Bars;
pt = pt + 1;
}

Print("pt=",pt) ;


int OT,SHi;

if(OrderSelect(ticket,SELECT_BY_TICKET)==true)

{ }

OT = OrderOpenTime();

}

SHi = iBarShift(Symbol(),0,OT);

Print("SHi=",SHi);

Reason: