Trailing Bar Entry EA - page 3

 
BenLinus: What I asked for is a way to exit the caller from inside a function.

What you asked for is something to give to your CEO to get your boss (and you) fired. Doesn't work in SW.

Once you return, your 'boss' is in charge. You can't force your 'boss' to do anything.

 
WHRoeder:

What you asked for is something to give to your CEO to get your boss (and you) fired. Doesn't work in SW.

Once you return, your 'boss' is in charge. You can't force your 'boss' to do anything.


Lol.

It is conceivable at least. For example, I could give the CEO spoofed evidence that we are both involved in some questionable activities.We will both be fired.

 

Anyway,

I worked something out:

I replaced all occurrences of OrderSelect() in start() with

        if (!OrderSelectAlert(index, select, pool=MODE_TRADES))   //order is now selected as a side effect
                return(0);

Where, OrderSelectAlert() is defined as follows:

bool OrderSelectAlert(int index, int select, int pool=MODE_TRADES) {
        if (OrderSelect(index, select, pool))   return(true);
        else{
                if(Closing_Alert_Made) return(false);   //This is a global variable in customs.mqh initialized to 0
                //order was not made and an alert was shown. start() should skip
                Alert("Ticket was not found.");
                Closing_Alert_Made = true;
                return(false);
        }
}


I don't know if this is good design. If ever I become a better, more experienced programmer I might know.

 
double NormalizePrice(double p, string pair=""){
        // https://forum.mql4.com/43064#515262 zzuegg reports for non-currency DE30:
        // MarketInfo(chart.symbol,MODE_TICKSIZE) returns 0.5
        // MarketInfo(chart.symbol,MODE_DIGITS) return 1
        // Point = 0.1
        // Prices to open must be a multiple of ticksize 
    if (pair == "") pair = Symbol();
    double ts = MarketInfo(pair, MODE_TICKSIZE);

    return( MathRound(p/ts) * ts );
}
Added missing semicolon (red)
 
William Roeder:

RaptorUK knows I disagree with that. NormalizeDouble is NEVER needed. It's a kludge, don't use it. It's use is always wrong.

  1. Normallizing Price for pending orders must be a multiple of ticksize, metals are multiple of 0.25 not a power of ten.
  2. For TP/SL those are levels, once the market reaches the level, they become a market order. No normalize needed.
  3. Normallizing lotsize must be a multiple of lotstep. Is lotstep a multiple of ten on all brokers?
  4. Comparing doubles, normalize is unnecessary. All that does is hide the fundamental problem, floating point round off. The == operand. - MQL4 forum


double NormalizeLots(double lots, string pair=""){
    if (pair == "") pair = Symbol();
    double  lotStep     = MarketInfo(pair, MODE_LOTSTEP),
            minLot      = MarketInfo(pair, MODE_MINLOT);
    lots            = MathRound(lots/ls) * ls;
    if (lots < minLot) lots = 0;    // or minLot
    return(lots);
}

Doesn't compile. ls variable should be lotStep?

 
First Last: Doesn't compile. ls variable should be lotStep?

obviously.

 
William Roeder:

RaptorUK knows I disagree with that. NormalizeDouble is NEVER needed. It's a kludge, don't use it. It's use is always wrong.

  1. Normallizing Price for pending orders must be a multiple of ticksize, metals are multiple of 0.25 not a power of ten.
  2. For TP/SL those are levels, once the market reaches the level, they become a market order. No normalize needed.
  3. Normallizing lotsize must be a multiple of lotstep. Is lotstep a multiple of ten on all brokers?
  4. Comparing doubles, normalize is unnecessary. All that does is hide the fundamental problem, floating point round off. The == operand. - MQL4 forum


Hi William

Hope you can help me to identify the problem in the code. When I normalize the volume, I get 0.0 as normalized volume (highlighted in Red below). Attached is my code.

HS 0 19:22:49.168 Core 1 2021.01.04 08:00:00   InpPrice 0.89563 InpSL 0.89529 InpRPTrade 0.05

EI 0 19:22:49.168 Core 1 2021.01.04 08:00:00   Tick Value (ExRate) 1.36832

IR 0 19:22:49.168 Core 1 2021.01.04 08:00:00   FxCTrade::Get_OptimumVolume: Optimum Lot before Normalization 2.149479

KS 0 19:22:49.168 Core 1 2021.01.04 08:00:00   FxCTrade::Get_OptimumVolume: SL Pips 3.4 SL CDeposit 1.0 SL CQuote 0.730823

PN 0 19:22:49.168 Core 1 2021.01.04 08:00:00   FxCTrade::Get_OptimumVolume: VolumeSTEP 0.01 VolumeMin 0.01 VolumeOptimum 2.149479 Normalize Lot 0.0

//+----------------------------------------------------------------------------------------------------------+
//| METHOD:       Get_OptimumVolume()
//| APPLICATION:  to calculate 'optimum lot size' within Risk Per Trade percentage
//+----------------------------------------------------------------------------------------------------------+
double FxCTrade::Get_OptimumVolume(const double entryPrice,const double SL,const double riskPerTrade)
  {
    Print("InpPrice ",entryPrice," InpSL ",SL," InpRPTrade ",riskPerTrade);
  //+--------------------------------------------------------------------------------------------------------+
  //| CapitalToRisk for Position is Minimum of Account 'Balance' OR 'Equity'
  //+--------------------------------------------------------------------------------------------------------+
    double acctEquity    = AccountInfoDouble(ACCOUNT_EQUITY);
    double acctBalance   = AccountInfoDouble(ACCOUNT_BALANCE);
    double capitalToRisk = MathMin(acctEquity,acctBalance);   // Risk Minimum of Equity or Balance
    //Print("Equity Bal ",acctEquity," Account Bal ",acctBalance);
  //+--------------------------------------------------------------------------------------------------------+
  //| Get lot size conditions from the Broker
  //| Deposit Currency is Currency in which, the account operates
  //| EURUSD Pair: EUR is Base Currency USD is Quote Currency
  //| GBPEUR Pair: GBP is Base Currency EUR is Quote Currency
  //+--------------------------------------------------------------------------------------------------------+
    double optimumLot   = NULL;
    double contractSize = FxSymbol.TradeContractSize();   // Maximum Trade contract size
    double volumeMax    = FxSymbol.VolumeMax();           // Maximal volume for a deal
    double volumeMin    = FxSymbol.VolumeMin();           // Minimal volume for a deal
    double volumeStep   = FxSymbol.VolumeStep();          // Minimal volume change step for deal execution
    double tickValue    = FxSymbol.TickValue();           // ExRate of Quote Currency in Deposit Currency
    //Print("Std Lot ",contractSize," Max Lot ",volumeMax," Min Lot ",volumeMin," Lot Step ",volumeStep);
    Print("Tick Value (ExRate) ",tickValue);
  //+--------------------------------------------------------------------------------------------------------+
  //| Calculate Stop Loss in Pips of Base Currency
  //+--------------------------------------------------------------------------------------------------------+
    int    sl_Points   = FxSymbol.Get_Points(entryPrice - SL);  // SL in (int)Points as 255
    double sl_Pips     = FxSymbol.Get_Pips(sl_Points);          // SL in Pisp as 25.5
    double sl_CDeposit = (capitalToRisk * (riskPerTrade/100)) ; // Max SL in Deposit Currency
    double sl_CQuote   = (sl_CDeposit / tickValue);             // Max SL in Quote Curency
    // Check for Zero Divide & optimum lot size >= MinLot size of Broker
    double normalizeLot = 0;
    if(sl_Pips != 0)
      {
        optimumLot = (sl_CQuote / sl_Pips) / contractSize;
        Print(__FUNCTION__,": Optimum Lot before Normalization ",optimumLot);
        // NORMALIZE 'lotsize' must be a multiple of lotstep. NormalizeToDouble() not work correctly
        normalizeLot = MathRound(optimumLot / volumeStep) * volumeStep;
        Print(__FUNCTION__,": SL Pips ",sl_Pips," SL CDeposit ",sl_CDeposit," SL CQuote ",sl_CQuote);
        Print(__FUNCTION__,": VolumeSTEP ",volumeStep," VolumeMin ",volumeMin," VolumeOptimum ",optimumLot,
                           " Normalize Lot ",normalizeLot);
        if(normalizeLot < volumeMin)
          normalizeLot = volumeMin;        // Calculated lot size >= Minimum lot size allowed by the Broker
        if(normalizeLot > volumeMax)
          normalizeLot = volumeMax;        // Calculated lot size <= Maximum lot size allowed by the Broker
      }
    return(normalizeLot);
  } // END of Get_OptimumVolume()
 
William Roeder #:
double NormalizePrice(double p, string pair=""){         // https://forum.mql4.com/43064#515262 zzuegg reports for non-currency DE30:         // MarketInfo(chart.symbol,MODE_TICKSIZE) returns 0.5         // MarketInfo(chart.symbol,MODE_DIGITS) return 1         // Point = 0.1         // Prices to open must be a multiple of ticksize     if (pair == "") pair = Symbol();     double ts = MarketInfo(pair, MODE_TICKSIZE)     return( MathRound(p/ts) * ts );

Seeing this coded out makes so much sense now. Thank you for this William! I have been fighting this very issue!