MQL5: MAX TRADES , RISK BASED LOTSIZE implementation

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

//|                                       SachinMarketingProject.mq5 |

//|                                  Copyright 2025, MetaQuotes Ltd. |

//|                                             https://www.mql5.com |

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

#property copyright "Copyright 2025, MetaQuotes Ltd."

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

#property version   "1.00"

#include <Trade\Trade.mqh>

CTrade trade;

input int MagicNumber=12345;

input double lotsize=3;

input string INFO1="Moving Average settings";

input int MA_Period=20;

input ENUM_MA_METHOD Ma_Type=0;

input double TargetMul=1;

input double riskpercentage=1;

input int MaxTradesPerDay = 0;   

// 0 = unlimited

int trades_today = 0;            // counter for today's trades

datetime last_reset_time = 0;    // to track day reset


int MyDigits;

double MyPoint;

bool BUY=false,SELL=false;

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

//| Expert initialization function                                   |

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

int OnInit()

  {

//---

   int Digits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);

   double Point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);



   if(Digits == 5)

      MyDigits = 4;

   else

      if(Digits == 3)

         MyDigits = 2;

      else

         MyDigits = Digits;


   if(Point == 0.00001)

      MyPoint = 0.0001; // 6 digits

   else

      if(Point == 0.001)

         MyPoint = 0.01; // 3 digits (for Yen based pairs)

      else

         MyPoint = Point; // Normal



//---

   return(INIT_SUCCEEDED);

  }

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

//| Utility functions for highs/lows                                 |

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



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

//|                                                                  |

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


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

//|                                                                  |

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

void ResetDailyCounter()

  {

   MqlDateTime mt;

   TimeToStruct(TimeCurrent(), mt);

   mt.hour = 0;

   mt.min = 0;

   mt.sec = 0;

   datetime start_of_day = StructToTime(mt);


   if(last_reset_time < start_of_day)   // new day has started

     {

      trades_today = 0;

      last_reset_time = TimeCurrent();

      Print("✅ New day detected — trade counter reset to 0.");

     }

  }



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

//|                                                                  |

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

double GetLowest(double a, double b, double c)

  {

   double minVal = a;

   if(b < minVal)

      minVal = b;

   if(c < minVal)

      minVal = c;

   return minVal;

  }


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

//|                                                                  |

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

double GetHighest(double a, double b, double c)

  {

   double maxVal = a;

   if(b > maxVal)

      maxVal = b;

   if(c > maxVal)

      maxVal = c;

   return maxVal;

  }


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

//| Expert deinitialization function                                 |

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

void OnDeinit(const int reason)

  {

//---


  }

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

//| Expert tick function                                             |

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

//---

// ─────────────────────────────────────────────────────────────────────────────

// Risk-based position sizing for MT5 (XAUUSD-ready)

// Inputs: risk_pct (e.g., 1.0 for 1%), entry_price, stop_price

// Returns: normalized lots (0.0 if risk too small for broker's min lot)

// ─────────────────────────────────────────────────────────────────────────────

/*

double CalcLotsByRisk(double slPoints ){

   double risk = AccountInfoDouble(ACCOUNT_BALANCE) * riskpercentage / 100;


   double ticksize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);

   double tickvalue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);

   double lotstep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);


   double moneyPerLotstep = slPoints / ticksize * tickvalue * lotstep;

   double lots = MathFloor(risk / moneyPerLotstep / lotstep) * lotstep;


   double minvolume = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN);

   double maxvolume = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MAX);


   if(maxvolume!=0) lots = MathMin(lots, maxvolume);

   if(minvolume!=0) lots = MathMax(lots, minvolume);


   lots = NormalizeDouble(lots, 2);

   return lots;

}

*/


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

//|                                                                  |

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

double calculate_lot(double ep, double sl,double contractSize)

  {

   double accountBal=AccountInfoDouble(ACCOUNT_BALANCE);

   double riskval= accountBal* riskpercentage* 0.01;


   Print("account bal: "+accountBal);

   Print("riskval: "+riskval);

   double diff_ep_sl=MathAbs(ep-sl);

   Print("diff_ep_sl: "+diff_ep_sl);

   diff_ep_sl=diff_ep_sl*contractSize;


   Print("diff_ep_sl * 100: "+diff_ep_sl);


   lots=riskval/diff_ep_sl;


   lots= NormalizeDouble(lots, 2);


   Print("lots : "+lots);

   return lots;



  }



double o1,o2,o3,h1,h2,h3,l1,l2,l3,c1,c2,c3,ma,MA_BUFF[],ltp;

double sll,tgt,dist;

string Trade=NULL;

double lots;



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

//|                                                                  |

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

void OnTick()

  {

   ResetDailyCounter();

   ma= iMA(Symbol(),PERIOD_CURRENT,MA_Period,0,Ma_Type,PRICE_CLOSE);

   ArraySetAsSeries(MA_BUFF,true);

   CopyBuffer(ma,0,0,5,MA_BUFF);



   o1=iOpen(Symbol(),PERIOD_CURRENT,1);

   o2=iOpen(Symbol(),PERIOD_CURRENT,2);

   o3=iOpen(Symbol(),PERIOD_CURRENT,3);


   h1=iHigh(Symbol(),PERIOD_CURRENT,1);

   h2=iHigh(Symbol(),PERIOD_CURRENT,2);

   h3=iHigh(Symbol(),PERIOD_CURRENT,3);


   l1=iLow(Symbol(),PERIOD_CURRENT,1);

   l2=iLow(Symbol(),PERIOD_CURRENT,2);

   l3=iLow(Symbol(),PERIOD_CURRENT,3);


   c1=iClose(Symbol(),PERIOD_CURRENT,1);

   c2=iClose(Symbol(),PERIOD_CURRENT,2);

   c3=iClose(Symbol(),PERIOD_CURRENT,3);

   ltp=iClose(Symbol(),PERIOD_CURRENT,0);


   if(c1>MA_BUFF[1] && c2>MA_BUFF[2] &&c3>MA_BUFF[3]&&ltp>=h1 &&c1>o1&&c2>o2&&c3>o3&&BUY==false)

     {



      Trade="BUY";

      BUY=true;

      SELL=false;

      Alert("BUY @ "+Symbol());

      trade.SetExpertMagicNumber(MagicNumber);

      //change it to lowest amont 3

      //sll=l3;

      sll= GetLowest(l1, l2, l3);

      dist=NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_ASK),_Digits)-sll;

      tgt=dist*TargetMul;

      tgt=NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_ASK),_Digits)+tgt;

      double diff=NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_BID),_Digits)-sll;

      Alert(diff);

      // lots=CalcLotsByRisk(diff);

      if(MaxTradesPerDay > 0 && trades_today >= MaxTradesPerDay)

        {

         PrintFormat("⚠️ Trade limit reached (%d/%d). Skipping new trade.",

                     trades_today, MaxTradesPerDay);

         return; // skip trade entry

        }

      lots=calculate_lot(NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_ASK),_Digits),sll,100);

      trade.Buy(lots,Symbol(),NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_ASK),_Digits),sll,tgt,"ThinkStak Ea");

      trades_today++;

     }


   if(c1<MA_BUFF[1] && c2<MA_BUFF[2] &&c3<MA_BUFF[3]&&ltp<=l1 &&c1<o1&&c2<o2&&c3<o3&&SELL==false)

     {

      Trade="SELL";

      BUY=false;

      SELL=true;

      Alert("SELL @ "+Symbol());

      trade.SetExpertMagicNumber(MagicNumber);

      // sll=h3;

      sll=GetHighest(h1,h2,h3);

      dist=sll-NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_BID),_Digits);

      tgt=dist*TargetMul;

      tgt=NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_BID),_Digits)-tgt;

      double diff=sll-NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_BID),_Digits);

      Alert(diff);

      // lots=CalcLotsByRisk(diff);

      if(MaxTradesPerDay > 0 && trades_today >= MaxTradesPerDay)

        {

         PrintFormat("⚠️ Trade limit reached (%d/%d). Skipping new trade.",

                     trades_today, MaxTradesPerDay);

         return; // skip trade entry

        }

      lots=calculate_lot(NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_BID),_Digits),sll,100);

      trade.Sell(lots,Symbol(),NormalizeDouble(SymbolInfoDouble(Symbol(),SYMBOL_BID),_Digits),sll,tgt,"ThinkStak Ea");

      trades_today++;

     }



  }

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


Comments

Popular posts from this blog

MQL5 : Add time to current time in mins

MQL5 : Get current trading session