0% found this document useful (0 votes)
276 views11 pages

mt4_capfree_ea

The document is an MQL4 script for a trading expert advisor (EA) named MR CAPFREE, designed for automated trading in financial markets. It includes various settings for trade management, money management, and order handling, such as lot size calculation, trading hours, and stop-loss configurations. The script initializes parameters, tracks market spreads, and manages open and pending orders based on defined trading strategies and conditions.

Uploaded by

mayurparitx
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
276 views11 pages

mt4_capfree_ea

The document is an MQL4 script for a trading expert advisor (EA) named MR CAPFREE, designed for automated trading in financial markets. It includes various settings for trade management, money management, and order handling, such as lot size calculation, trading hours, and stop-loss configurations. The script initializes parameters, tracks market spreads, and manages open and pending orders based on defined trading strategies and conditions.

Uploaded by

mayurparitx
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 11

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

//| MR CAPFREE.mq4 |
//| Copyright 2025, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict

// Enum for lot type calculation


enum enumLotType
{
Fixed_Lots = 0,
Pct_of_Balance = 1,
Pct_of_Equity = 2,
Pct_of_Free_Margin = 3
};

//--- Input Parameters


input string GeneralSettings = "=================="; // GENERAL SETTINGS
input int InpMagic = 12345; // Magic Number
input int Slippage = 1; // Slippage

input string TimeSettings = "=================="; // Time Settings


input int StartHour = 16; // START TRADING HOUR
input int EndHour = 22; // End Trading Hour
input int Secs = 60; // ORDER MODIFICATIONS (Should
be same as TF)

input string MoneyManagement = "=================="; // MONEY MANAGEMENT


input enumLotType LotType = Fixed_Lots; // Type of Lotsize calculation
input double FixedLot = 0.01; // Fixed Lots
input double RiskPercent = 0.5; // Risk per MM

input string TradeSettings = "=================="; // TRADE SETTINGS IN POINTS


input double Delta = 0.5; // ORDER DISTANCE
input double MaxDistance = 7; // THETA (Max order distance)
input double Stop = 10; // Stop Loss Size
input double MaxTrailing = 4; // COS (start of trailing
stop)
input int MaxSpread = 20; // Max spread Limit

//--- Global Variables


double DeltaX = 0;
double MinOrderDistance = 0.5;
double MaxTrailingLimit = 7.5;
double OrderModificationFactor = 3;
int TickCounter = 0;
double PriceToPipRatio = 0;

double BaseTrailingStop = 0;
double TrailingStopBuffer = 0;
double TrailingStopIncrement = 0;
double TrailingStopThreshold = 0;
long AccountLeverageValue = 0;

double LotStepSize = 0;
double MaxLotSize = 0;
double MinLotSize = 0;
double MarginPerMinLot = 0;
double MinStopDistance = 0;

int BrokerStopLevel = 0;
double MinFreezeDistance = 0;
int BrokerFreezeLevel = 0;
double CurrentSpread = 0;
double AverageSpread = 0;

int EAModeFlag = 0;
int SpreadArraySize = 0;
int DefaultSpreadPeriod = 30;
double MaxAllowedSpread = 0;
double CalculatedLotSize = 0;

double CommissionPerPip = 0;
int SpreadMultiplier = 0;
double AdjustedOrderDistance = 0;
double MinOrderModification = 0;
double TrailingStopActive = 0;

double TrailingStopMax = 0;
double MaxOrderPlacementDistance = 0;
double OrderPlacementStep = 0;
double CalculatedStopLoss = 0;

double CurrentBuySL = 0;
string OrderCommentText = "Gasper";
int LastBuyOrderTime = 0;
double CurrentSellSL = 0;
int LastSellOrderTime = 0;
int OrderCheckFrequency = 2;
int SpreadCalculationMethod = 1;
bool EnableTrading = false;

double SpreadHistoryArray[];
int LastOrderTime = 0;
int MinOrderInterval = 0;

//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Set chart properties
ChartSetInteger(0, CHART_SHOW_GRID, false);

// Initialize variables
DeltaX = Delta;
if(MinOrderDistance > Delta)
{
DeltaX = MinOrderDistance + 0.1;
}
if(MaxTrailing > MaxTrailingLimit)
{
MaxTrailingLimit = MaxTrailing + 0.1;
}
if(OrderModificationFactor < 1)
{
OrderModificationFactor = 1;
}

TickCounter = 0;
PriceToPipRatio = 0;
BaseTrailingStop = TrailingStopBuffer;
TrailingStopIncrement = TrailingStopThreshold;
AccountLeverageValue = AccountLeverage();

// Get symbol properties


LotStepSize = MarketInfo(Symbol(), MODE_LOTSTEP);
MaxLotSize = MarketInfo(Symbol(), MODE_MAXLOT);
MinLotSize = MarketInfo(Symbol(), MODE_MINLOT);
MarginPerMinLot = MarketInfo(Symbol(), MODE_MARGINREQUIRED) * MinLotSize;

// Get broker restrictions


BrokerStopLevel = (int)MarketInfo(Symbol(), MODE_STOPLEVEL);
MinStopDistance = 0;
if(BrokerStopLevel > 0)
MinStopDistance = (BrokerStopLevel + 1) * Point;

BrokerFreezeLevel = (int)MarketInfo(Symbol(), MODE_FREEZELEVEL);


MinFreezeDistance = 0;
if(BrokerFreezeLevel > 0)
MinFreezeDistance = (BrokerFreezeLevel + 1) * Point;

if(BrokerStopLevel > 0 || BrokerFreezeLevel > 0)


{
Comment("WARNING: Broker is not suitable, the stoplevel is greater than
zero");
}

// Initialize spread tracking


double ask = Ask;
double bid = Bid;
CurrentSpread = NormalizeDouble(ask - bid, Digits);
AverageSpread = CurrentSpread;

SpreadArraySize = (EAModeFlag == 0) ? DefaultSpreadPeriod : 3;


ArrayResize(SpreadHistoryArray, SpreadArraySize);
ArrayInitialize(SpreadHistoryArray, CurrentSpread);

MaxAllowedSpread = NormalizeDouble(MaxSpread * Point, Digits);

Print("MR CAPFREE EA initialized successfully");


return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Comment("");
}

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
int CurrentTime = (int)TimeCurrent();
int PendingBuyCount = 0;
int PendingSellCount = 0;
int OpenBuyCount = 0;
int OpenSellCount = 0;
int TotalBuyCount = 0;
int TotalSellCount = 0;

double BuyOrdersPriceSum = 0;
double BuyOrdersLotSum = 0;
double SellOrdersPriceSum = 0;
double SellOrdersLotSum = 0;
double AverageBuyPrice = 0;
double AverageSellPrice = 0;
double LowestBuyPrice = 99999;
double HighestSellPrice = 0;

TickCounter++;

// Calculate price to pip ratio from history (MT4 version)


if(PriceToPipRatio == 0)
{
for(int i = OrdersHistoryTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if(OrderSymbol() != Symbol()) continue;
if(OrderProfit() == 0) continue;
if(OrderType() > 1) continue; // Only BUY/SELL orders

double entryPrice = OrderOpenPrice();


double exitPrice = OrderClosePrice();
double profit = OrderProfit();
double commission = OrderCommission();

if(exitPrice != entryPrice)
{
PriceToPipRatio = MathAbs(profit / (exitPrice - entryPrice));
CommissionPerPip = commission / PriceToPipRatio;
break;
}
}
}
}

// Update spread history


double ask = Ask;
double bid = Bid;
double newSpread = NormalizeDouble(ask - bid, Digits);

// Shift array and add new spread


for(int i = 0; i < SpreadArraySize - 1; i++)
{
SpreadHistoryArray[i] = SpreadHistoryArray[i + 1];
}
SpreadHistoryArray[SpreadArraySize - 1] = newSpread;
// Calculate average spread
double sum = 0;
for(int i = 0; i < SpreadArraySize; i++)
{
sum += SpreadHistoryArray[i];
}
CurrentSpread = sum / SpreadArraySize;

// Calculate average spread including commission


AverageSpread = MathMax(SpreadMultiplier * Point, CurrentSpread +
CommissionPerPip);

// Calculate order distances


AdjustedOrderDistance = MathMax(AverageSpread * Delta, MinStopDistance);
MinOrderModification = MathMax(AverageSpread * MinOrderDistance,
MinFreezeDistance);

// Calculate trailing stop values


TrailingStopActive = AverageSpread * MaxTrailing;
TrailingStopMax = AverageSpread * MaxTrailingLimit;
MaxOrderPlacementDistance = AverageSpread * MaxDistance;
OrderPlacementStep = MinOrderModification / OrderModificationFactor;
CalculatedStopLoss = MathMax(AverageSpread * Stop, MinStopDistance);

// Count open positions


for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == InpMagic)
{
double price = OrderOpenPrice();
double lots = OrderLots();
double sl = OrderStopLoss();

if(OrderType() == OP_BUY)
{
OpenBuyCount++;
if(sl == 0 || (sl > 0 && sl < price)) TotalBuyCount++;
CurrentBuySL = sl;
BuyOrdersPriceSum += price * lots;
BuyOrdersLotSum += lots;
if(price < LowestBuyPrice) LowestBuyPrice = price;
}
else if(OrderType() == OP_SELL)
{
OpenSellCount++;
if(sl == 0 || (sl > 0 && sl > price)) TotalSellCount++;
CurrentSellSL = sl;
SellOrdersPriceSum += price * lots;
SellOrdersLotSum += lots;
if(price > HighestSellPrice) HighestSellPrice = price;
}
else if(OrderType() == OP_BUYSTOP)
{
PendingBuyCount++;
TotalBuyCount++;
}
else if(OrderType() == OP_SELLSTOP)
{
PendingSellCount++;
TotalSellCount++;
}
}
}
}

// Calculate average prices


if(BuyOrdersLotSum > 0)
{
AverageBuyPrice = NormalizeDouble(BuyOrdersPriceSum / BuyOrdersLotSum,
Digits);
}
if(SellOrdersLotSum > 0)
{
AverageSellPrice = NormalizeDouble(SellOrdersPriceSum / SellOrdersLotSum,
Digits);
}

// Get broker time


datetime brokerTime = TimeCurrent();
int hour = TimeHour(brokerTime);

// Process pending orders


for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != InpMagic) continue;

int ticket = OrderTicket();


int type = OrderType();
double openPrice = OrderOpenPrice();
double sl = OrderStopLoss();
double tp = OrderTakeProfit();
double lots = OrderLots();

// Process buy stop orders


if(type == OP_BUYSTOP)
{
bool allowTrade = (hour >= StartHour && hour <= EndHour);
if(AverageSpread > MaxAllowedSpread || !allowTrade)
{
OrderDelete(ticket);
continue;
}

int timeDiff = CurrentTime - LastBuyOrderTime;


bool needsModification = (timeDiff > Secs) ||
(TickCounter % OrderCheckFrequency == 0 &&
((OpenBuyCount < 1 && (openPrice - Ask) <
MinOrderModification) ||
(openPrice - Ask) < OrderPlacementStep ||
(openPrice - Ask) > MaxOrderPlacementDistance));

if(needsModification)
{
double distance = AdjustedOrderDistance;
if(OpenBuyCount > 0) distance /= OrderModificationFactor;
distance = MathMax(distance, MinStopDistance);

double modifiedPrice = NormalizeDouble(Ask + distance, Digits);


double modifiedSl = (OpenBuyCount > 0) ? CurrentBuySL :
NormalizeDouble(modifiedPrice - CalculatedStopLoss, Digits);

if((OpenBuyCount == 0 || modifiedPrice > AverageBuyPrice) &&


modifiedPrice != openPrice &&
(openPrice - Ask) > MinFreezeDistance)
{
OrderModify(ticket, modifiedPrice, modifiedSl, tp, 0);
LastBuyOrderTime = CurrentTime;
}
}
}

// Process sell stop orders


else if(type == OP_SELLSTOP)
{
bool allowTrade = (hour >= StartHour && hour <= EndHour);
if(AverageSpread > MaxAllowedSpread || !allowTrade)
{
OrderDelete(ticket);
continue;
}

int timeDiff = CurrentTime - LastSellOrderTime;


bool needsModification = (timeDiff > Secs) ||
(TickCounter % OrderCheckFrequency == 0 &&
((OpenSellCount < 1 && (Bid - openPrice) <
MinOrderModification) ||
(Bid - openPrice) < OrderPlacementStep ||
(Bid - openPrice) > MaxOrderPlacementDistance));

if(needsModification)
{
double distance = AdjustedOrderDistance;
if(OpenSellCount > 0) distance /= OrderModificationFactor;
distance = MathMax(distance, MinStopDistance);

double modifiedPrice = NormalizeDouble(Bid - distance, Digits);


double modifiedSl = (OpenSellCount > 0) ? CurrentSellSL :
NormalizeDouble(modifiedPrice + CalculatedStopLoss, Digits);

if((OpenSellCount == 0 || modifiedPrice < AverageSellPrice) &&


modifiedPrice != openPrice &&
(Bid - openPrice) > MinFreezeDistance)
{
OrderModify(ticket, modifiedPrice, modifiedSl, tp, 0);
LastSellOrderTime = CurrentTime;
}
}
}
}

// Process open positions for trailing stops


for(int i = 0; i < OrdersTotal(); i++)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != InpMagic) continue;
if(OrderType() > 1) continue; // Skip pending orders

int ticket = OrderTicket();


int type = OrderType();
double openPrice = OrderOpenPrice();
double sl = OrderStopLoss();
double tp = OrderTakeProfit();

// Process Buy Positions


if(type == OP_BUY)
{
double priceMove = MathMax(Bid - openPrice + CommissionPerPip, 0);
double trailDist = CalculateTrailingStop(priceMove, MinStopDistance,
TrailingStopActive, BaseTrailingStop, TrailingStopMax);

double modifiedSl = NormalizeDouble(Bid - trailDist, Digits);


double triggerLevel = openPrice + CommissionPerPip +
TrailingStopIncrement;

if((Bid - triggerLevel) > trailDist &&


(sl == 0 || (Bid - sl) > trailDist) &&
modifiedSl != sl)
{
OrderModify(ticket, openPrice, modifiedSl, tp, 0);
}
}

// Process Sell Positions


else if(type == OP_SELL)
{
double priceMove = MathMax(openPrice - Ask - CommissionPerPip, 0);
double trailDist = CalculateTrailingStop(priceMove, MinStopDistance,
TrailingStopActive, BaseTrailingStop, TrailingStopMax);

double modifiedSl = NormalizeDouble(Ask + trailDist, Digits);


double triggerLevel = openPrice - CommissionPerPip -
TrailingStopIncrement;

if((triggerLevel - Ask) > trailDist &&


(sl == 0 || (sl - Ask) > trailDist) &&
modifiedSl != sl)
{
OrderModify(ticket, openPrice, modifiedSl, tp, 0);
}
}
}

// Place new buy stop order if needed


if(((OrderModificationFactor > 1 && TotalBuyCount < 1) || OpenBuyCount < 1) &&
PendingBuyCount < 1)
{
bool spreadOK = (AverageSpread <= MaxAllowedSpread);
bool timeOK = (hour >= StartHour && hour <= EndHour);

if(spreadOK && timeOK && (CurrentTime - LastOrderTime) > MinOrderInterval &&


EAModeFlag == 0)
{
// Calculate lot size
if(LotType == Fixed_Lots)
{
CalculatedLotSize = MathCeil(FixedLot / LotStepSize) * LotStepSize;
CalculatedLotSize = MathMax(CalculatedLotSize, MinLotSize);
}
else if(LotType > Fixed_Lots)
{
CalculatedLotSize = CalcLots(CalculatedStopLoss);
}

// Check margin requirement


double marginRequired = MarketInfo(Symbol(), MODE_MARGINREQUIRED) *
CalculatedLotSize;
if(AccountFreeMargin() > marginRequired)
{
double orderDist = MathMax(MathMax(AdjustedOrderDistance,
MinFreezeDistance), MinStopDistance);
double orderPrice = NormalizeDouble(Ask + orderDist, Digits);
double orderSL = (OpenBuyCount > 0) ? CurrentBuySL :
NormalizeDouble(orderPrice - CalculatedStopLoss, Digits);

int result = OrderSend(Symbol(), OP_BUYSTOP, CalculatedLotSize,


orderPrice, Slippage, orderSL, 0, OrderCommentText, InpMagic);
if(result > 0)
{
LastBuyOrderTime = CurrentTime;
LastOrderTime = CurrentTime;
}
}
}
}

// Place new sell stop order if needed


if(((OrderModificationFactor > 1 && TotalSellCount < 1) || OpenSellCount < 1) &&
PendingSellCount < 1)
{
bool spreadOK = (AverageSpread <= MaxAllowedSpread);
bool timeOK = (hour >= StartHour && hour <= EndHour);

if(spreadOK && timeOK && (CurrentTime - LastOrderTime) > MinOrderInterval &&


EAModeFlag == 0)
{
// Calculate lot size
if(LotType == Fixed_Lots)
{
CalculatedLotSize = MathCeil(FixedLot / LotStepSize) * LotStepSize;
CalculatedLotSize = MathMax(CalculatedLotSize, MinLotSize);
}
else if(LotType > Fixed_Lots)
{
CalculatedLotSize = CalcLots(CalculatedStopLoss);
}

// Check margin requirement


double marginRequired = MarketInfo(Symbol(), MODE_MARGINREQUIRED) *
CalculatedLotSize;
if(AccountFreeMargin() > marginRequired)
{
double orderDist = MathMax(MathMax(AdjustedOrderDistance,
MinFreezeDistance), MinStopDistance);
double orderPrice = NormalizeDouble(Bid - orderDist, Digits);
double orderSL = (OpenSellCount > 0) ? CurrentSellSL :
NormalizeDouble(orderPrice + CalculatedStopLoss, Digits);

int result = OrderSend(Symbol(), OP_SELLSTOP, CalculatedLotSize,


orderPrice, Slippage, orderSL, 0, OrderCommentText, InpMagic);
if(result > 0)
{
LastSellOrderTime = CurrentTime;
LastOrderTime = CurrentTime;
}
}
}
}
}

//+------------------------------------------------------------------+
//| Calculate trailing stop distance |
//+------------------------------------------------------------------+
double CalculateTrailingStop(double priceMove, double minDist, double activeDist,
double baseDist, double maxDist)
{
if(maxDist == 0) return MathMax(activeDist, minDist);

double ratio = priceMove / maxDist;


double dynamicDist = (activeDist - baseDist) * ratio + baseDist;
return MathMax(MathMax(dynamicDist, activeDist), minDist);
}

//+------------------------------------------------------------------+
//| Calculate lot size based on risk management |
//+------------------------------------------------------------------+
double CalcLots(double slPoints)
{
double lots = MarketInfo(Symbol(), MODE_MINLOT);

double AccountBalance = AccountBalance();


double EquityBalance = AccountEquity();
double FreeMargin = AccountFreeMargin();

double risk = 0;
switch(LotType)
{
case Fixed_Lots:
lots = FixedLot;
return lots;
case Pct_of_Balance:
risk = AccountBalance * RiskPercent / 100;
break;
case Pct_of_Equity:
risk = EquityBalance * RiskPercent / 100;
break;
case Pct_of_Free_Margin:
risk = FreeMargin * RiskPercent / 100;
break;
}
double tickSize = MarketInfo(Symbol(), MODE_TICKSIZE);
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);

if(tickSize > 0 && tickValue > 0)


{
double moneyPerLotStep = slPoints / tickSize * tickValue * lotStep;
if(moneyPerLotStep > 0)
lots = MathFloor(risk / moneyPerLotStep) * lotStep;
}

// Apply limits
double minVolume = MarketInfo(Symbol(), MODE_MINLOT);
double maxVolume = MarketInfo(Symbol(), MODE_MAXLOT);

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


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

lots = NormalizeDouble(lots, 2);

return lots;
}

You might also like