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]&<p>=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]&<p<=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
Post a Comment