Okay, here's a breakdown of what this MetaTrader script does, explained in plain language for someone who isn't a programmer:
Overall Goal:
This script is designed to automatically trade on the Forex market using a "grid" strategy. A grid strategy involves placing buy and sell orders at different price levels, creating a "grid" of potential trades. The script aims to make a profit by opening and closing trades within this grid. It's designed to be reactive, meaning it responds to price movements rather than trying to predict them.
Here's how it works, step by step:
-
Initial Setup (init function):
- This part is run once when the script starts. In this particular script, it doesn't do anything, it simply returns 0.
-
Core Trading Logic (start function):
-
Checks if enough time has passed. It only executes the rest of the code if at least 10 seconds have passed since the last trade.
-
Remember key account numbers. It keeps track of the highest amount of margin used, the largest floating loss on the account, and the lowest free margin so that it can reference those numbers later and report them.
-
End-of-Day Closing:
- At 11 PM GMT, it automatically closes all open trades and deletes any pending orders. This is a safety feature to avoid holding positions overnight or over the weekend.
- The script uses a flag called EOD_close to keep track of whether it has already closed the positions. The EOD_close flag is reset if the time is no longer >= 23 (11 PM).
-
Analyzing Current Trades:
- It counts how many buy and sell trades are currently open.
- It calculates the average opening price for all buy trades and the average opening price for all sell trades.
- It calculates the overall profit or loss (PL) of all trades in the account.
-
Setting a Profit Target:
-
The script calculates a "Profit Target," which is the amount of profit it wants to achieve before closing all trades.
-
The way it calculates the profit target depends on whether there are more buy trades or more sell trades.
-
The higher the Profit Target is, the more profit the script has to make before it will close all of its orders.
-
The Profit Target will only increase if the the script closes the "edges" of the grid due to order limits (see below).
-
-
Closing Trades to Achieve Profit (CloseAll Logic):
-
If the current profit exceeds the "Profit Target," the script tries to close all open positions.
-
It uses a switch (
CloseSwitch) to ensure this closing process happens only once per profit target. -
When closing trades, the script might try to close buy orders first or sell orders first depending on which type of order has the highest number.
-
There is logic to handle positive and negative slippage when closing trades.
-
-
Opening New Trades (If Not Closing):
-
The script only opens new trades if the
CloseAllswitch is off, indicating that it's not currently in the process of closing everything. -
The first time the script runs, if there are no buy trades, it opens a buy trade. If there are no sell trades, it opens a sell trade. This starts the grid.
-
Identifying the Grid Edges: The script finds the highest buy order and the lowest sell order to define the edges of the grid.
-
Limiting Grid Size:
-
The script can limit the maximum number of orders open at once by checking if the number of total orders has gone over a maximum order size.
-
If the number of open orders goes over the maximum order size, then the script will close the oldest order.
-
If the last order was a buy, it closes the highest buy order. If the last order was a sell, it closes the lowest sell order.
-
-
Expanding the Grid:
- The script determines whether it's appropriate to open new buy or sell orders based on the current price, the presence of existing orders, the current profit level, and the balance between the number of buy and sell trades.
- If the script determines that it should open additional trades based on the current price, the script will check to make sure there's enough free margin.
-
For all open order actions, the script will set the last trade was buy/sell order flags to the appropriate value.
-
-
In essence, this script is designed to:
- Automatically create a grid of buy and sell orders around the current market price.
- Manage these orders to try and profit from small price fluctuations.
- Close all orders when a specific profit target is reached.
- Restart the process by creating a new grid.
Important Considerations (not part of the script's logic, but important for users):
- Risk: Grid trading can be risky, especially in volatile markets. If the price moves strongly in one direction, the grid can accumulate losses.
- Customization: The script has several adjustable parameters ("extern" variables) that a user can change to customize the strategy, such as lot size, profit targets, maximum trades, and slippage. The user will need to set those values at a number that doesn't deplete their margin!
I hope this explanation is helpful!
/*-----------------------------+
| |
| Shared by www.Aptrafx.com |
| |
+------------------------------*/
//+------------------------------------------------------------------+
//| GridMaster_03.mq4 |
// Name := GridMaster_03
// Author := Copyright © 2005, Lifestatic, pip_seeker, autofx
// Link := http://autoforex.biz
// Notes:= This is a pure, 100% REACTIVE strategy, with no attempt at
// all to predict, anticipate or define a statistical edge.
// It limits grid size by keeping edges trimmed. This version
// (03) increases the profit target whenever an edge is trimmed.
// The ProfitIncrease input is used to indicate how much to
// increase the profit target. The MaxProfitExit input is used
// to limit the profit target to the defined value. This version
// also closes everything out once a day at 23:00 GMT.
//+------------------------------------------------------------------+
extern double Lots = 1.0;
int StopLoss = 0;
int TakeProfit = 0;
// extern int Trailing_Stop = 0;
// inputs;
extern int ProfitEntry = 5; // Open new trades if TotalProfit less than this value
extern int ProfitExit = 100; // Stop opening new trades and start closing them all if TotalProfit greater than this value
extern int ProfitIncrease = 50; // Dollar amount to increase profit target each time an edge is trimmed
extern int MaxProfitExit = 500; // Maximum profit target
extern int MaxTrades = 50; // Number of Total Orders allowed
extern int BalanceDelta = 20; // Number of trades by which buys can exceed sells and vice versa
extern int BucksPerPip = 1;
extern int dFreeMargin = 1500; // Least amount of acount margin to allow
extern int Slippage = 2; // Permitted slippage for order entry
extern int log = 0; // Record for troubleshooting
extern string Version = "1.1";
int MAGICGT = 20060912;
int i, TotalOrders;
int total, count;
double ProfitTarget;
int NumBuys,NumSells;
double CumulativeBuyPrice,CumulativeSellPrice,ExitPrice;
double BuyPL,SellPL,OverallPL;
double HighestSell,LowestBuy,HighestBuy,LowestSell;
double BuyNewLevel,SellNewLevel;
bool CloseAll;
bool EOD_close = false;
double LargestMarginUsed,LargestFloatingLoss;
bool CloseSwitch,CloseSellFirst,CloseBuyFirst;
double LowestFreeMargin;
datetime TimeClock,TimeMin;
datetime LastTradeTime;
double safety, target;
bool LastTradeWasBuy,LastTradeWasSell;
int init()
{
return(0);
}
int start()
{
// Presets;
if ((CurTime() - LastTradeTime) < 10) return(0);
if (AccountMargin() > LargestMarginUsed) LargestMarginUsed = AccountMargin();
if (AccountProfit() < LargestFloatingLoss) LargestFloatingLoss = AccountProfit();
if (LowestFreeMargin == 0) LowestFreeMargin = AccountFreeMargin();
if (AccountFreeMargin() < LowestFreeMargin) LowestFreeMargin = AccountFreeMargin();
// check for end of trading day closeout
if ((Hour() >= 23) && (EOD_close == false))
{
Print("Deleting Pending Orders");
total=OrdersTotal();
for(count=0; count<total; count++)
{
if(OrderSelect(count, SELECT_BY_POS, MODE_TRADES) == false) continue;
if(OrderSymbol() != Symbol()) continue; // ignore trades other than the chart
if (log>0) Print("count ", count, " ticket ", OrderTicket(), " type ", OrderType());
if (log>0) Print("Symbol ", Symbol(), " OrderSymbol ", OrderSymbol());
if(OrderType()==OP_SELLLIMIT) OrderDelete(OrderTicket());
if(OrderType()==OP_BUYLIMIT) OrderDelete(OrderTicket());
if(OrderType()==OP_SELLSTOP) OrderDelete(OrderTicket());
if(OrderType()==OP_BUYSTOP) OrderDelete(OrderTicket());
}
Print("Closing Open Positions");
total=OrdersTotal();
for(count=0; count<total; count++)
{
if(OrderSelect(count, SELECT_BY_POS, MODE_TRADES) == false) continue;
if(OrderSymbol() != Symbol()) continue; // ignore trades other than the chart
if (log>0) Print("count ", count, " ticket ", OrderTicket(), " type ", OrderType());
if (log>0) Print("Symbol ", Symbol(), " OrderSymbol ", OrderSymbol());
if(OrderType()==OP_SELL) if (!OrderClose(OrderTicket(), OrderLots(), Ask, 3, Red))
Print ("Close error ", GetLastError());
if(OrderType()==OP_BUY) if (!OrderClose(OrderTicket(), OrderLots(), Bid, 3, Red))
Print ("Close error ", GetLastError());
}
EOD_close = true; // flag that we have cleared the board
}
// Reset the End Of Day semaphore
if ((Hour() < 23) && (EOD_close == true)) EOD_close = false;
NumBuys = 0;
NumSells = 0;
CumulativeBuyPrice = 0.0;
CumulativeSellPrice = 0.0;
OverallPL = 0.0;
TotalOrders = OrdersTotal();
for (i=0; i<TotalOrders; i++)
{
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if ((OrderSymbol() == Symbol()) && (OrderType() == OP_BUY))
{
NumBuys++;
CumulativeBuyPrice += OrderOpenPrice();
}
if ((OrderSymbol() == Symbol()) && (OrderType() == OP_SELL))
{
NumSells++;
CumulativeSellPrice += OrderOpenPrice();
}
}
}
if ((NumBuys > NumSells) && (NumSells > 0))
{
ExitPrice = CumulativeBuyPrice/NumBuys;
while (OverallPL < ProfitTarget)
{
BuyPL = ((BucksPerPip*NumBuys)/Point)*(ExitPrice - CumulativeBuyPrice/NumBuys);
SellPL = ((BucksPerPip*NumSells)/Point)*(CumulativeSellPrice/NumSells - ExitPrice);
ExitPrice += Point;
OverallPL = BuyPL + SellPL;
}
if (ProfitTarget < ProfitExit) ProfitTarget = ProfitExit;
Comment("Buy trades: ",NumBuys,", Sell trades: ",NumSells,
"\nLargest Margin Used: ", LargestMarginUsed,", Largest Floating Loss: ", LargestFloatingLoss,", Lowest Free Margin: ", LowestFreeMargin,
"\nBalance: ", AccountBalance(),", Equity: ", AccountEquity(),", AccountProfit: ", AccountProfit(),
"\nHighestSell: ", HighestSell,", LowestBuy: ", LowestBuy,
"\nHighestBuy: ",HighestBuy,", LowestSell: ", LowestSell,
"\nGridSize: ", (HighestBuy-LowestSell)/Point," pips",
"\nDollar Target: ", ProfitTarget,
"\nLong Target: ", ExitPrice,
"\n",(ExitPrice-Bid)/Point," pips from target");
}
else
if ((NumSells > NumBuys) && (NumBuys > 0))
{
ExitPrice = CumulativeSellPrice/NumSells;
while (OverallPL < ProfitTarget)
{
BuyPL = ((BucksPerPip*NumBuys)/Point)*(ExitPrice - CumulativeBuyPrice/NumBuys);
SellPL = ((BucksPerPip*NumSells)/Point)*(CumulativeSellPrice/NumSells - ExitPrice);
ExitPrice -= Point;
OverallPL = BuyPL + SellPL;
}
if (ProfitTarget < ProfitExit) ProfitTarget = ProfitExit;
Comment("Buy trades: ",NumBuys,", Sell trades: ",NumSells,
"\nLargest Margin Used: ", LargestMarginUsed,", Largest Floating Loss: ", LargestFloatingLoss,", Lowest Free Margin: ", LowestFreeMargin,
"\nBalance: ", AccountBalance(),", Equity: ", AccountEquity(),", TotalProfit: ", AccountProfit(),
"\nHighestSell: ", HighestSell,", LowestBuy: ", LowestBuy,
"\nHighestBuy: ",HighestBuy,", LowestSell: ", LowestSell,
"\nGridSize: ", (HighestBuy-LowestSell)/Point," pips",
"\nDollar Target: ", ProfitTarget,
"\nLong Target: ", ExitPrice,
"\n",(ExitPrice-Bid)/Point," pips from target");
}
if ((CloseBuyFirst == 1) || (CloseSellFirst == 1))
{
if (NumBuys == 0) CloseBuyFirst = 0;
if (NumSells == 0) CloseSellFirst = 0;
}
// if Profit is positive, close all open positions;
if ((AccountProfit() > ProfitTarget) && (CloseSwitch == 0))
{
CloseAll = 1;
CloseSwitch = 1;
if (NumBuys > NumSells) CloseSellFirst = 1;
if (NumSells > NumBuys) CloseBuyFirst = 1;
}
if (TotalOrders == 0)
{
CloseAll = 0;
CloseSwitch = 0;
ProfitTarget = ProfitExit;
}
if (CloseAll == 1)
{
TotalOrders = OrdersTotal();
for (i=0; i<TotalOrders; i++)
{
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (((OrderSymbol() == Symbol()) && (OrderType() == OP_BUY) && (CloseBuyFirst == 1)) ||
((CloseBuyFirst == 0) && (CloseSellFirst == 0)))
{
if ((Bid-OrderOpenPrice()) < 0)
{
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, LawnGreen);
return(0);
}
if ((Bid-OrderOpenPrice()) > 0)
{
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Gold);
return(0);
}
}
if (((OrderSymbol() == Symbol()) && (OrderType() == OP_SELL) && (CloseSellFirst == 1)) ||
((CloseBuyFirst == 0) && (CloseSellFirst == 0)))
{
if ((OrderOpenPrice()-Ask) < 0)
{
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, HotPink);
return(0);
}
if ((OrderOpenPrice()-Ask) > 0)
{
OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Gold);
return(0);
}
}
} // if OrderSelect()
} // for i=0 to OrdersTotal()
} // if CloseAll == 1
if (CloseAll == 0) // If closing switch is set to 0, we can open new orders and adjust TPs/SLs
{
// Open First Trades;
if ((NumBuys == 0) && (AccountFreeMargin() > dFreeMargin))
{
if (StopLoss == 0) safety = 0;
else safety = Bid - (StopLoss * Point);
if (TakeProfit == 0) target = 0;
else target = Ask + (TakeProfit * Point);
if(log>0) Print("SL ", StopLoss, " safety ", safety, " TP ", TakeProfit, " target ", target );
OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, safety, target, "", MAGICGT, 0, Blue);
LastTradeWasBuy = true;
LastTradeWasSell = false;
return(0);
}
if ((NumSells == 0) && (AccountFreeMargin() > dFreeMargin))
{
if (StopLoss == 0) safety = 0;
else safety = Ask + (StopLoss * Point);
if (TakeProfit == 0) target = 0;
else target = Bid - (TakeProfit * Point);
if(log>0) Print("SL ", StopLoss, " safety ", safety, " TP ", TakeProfit, " target ", target );
OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, safety, target, "", MAGICGT, 0, Red);
LastTradeWasSell = true;
LastTradeWasBuy = false;
return(0);
}
////////////////////////////////////////////////////////
// Determine Highest Buy and Lowest Sell;
////////////////////////////////////////////////////////
LowestBuy = 1000;
HighestSell = 0;
HighestBuy = 0;
LowestSell = 1000;
for (i=0; i<TotalOrders; i++)
{
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol() == Symbol())
{
if (OrderType() == OP_BUY)
{
if (OrderOpenPrice() < LowestBuy) LowestBuy = OrderOpenPrice();
if (OrderOpenPrice() > HighestBuy) HighestBuy = OrderOpenPrice();
}
if (OrderType() == OP_SELL)
{
if (OrderOpenPrice() < LowestSell) LowestSell = OrderOpenPrice();
if (OrderOpenPrice() > HighestSell) HighestSell = OrderOpenPrice();
}
}
}
} // for i = 0 to TotalOrders-1
/////////////////////////////////////////
// If TotalOrders > MaxTrades, Close Highest Buy If Last Trade Was A Sell
// Or Close Lowest Sell If Last Trade Was A Buy
//////////////////////////////////////////
for (i=0; i<TotalOrders; i++)
{
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if ((LastTradeWasSell == true) &&
(TotalOrders > MaxTrades) &&
(OrderSymbol() == Symbol()) &&
(OrderType() == OP_BUY) &&
(OrderOpenPrice() == HighestBuy))
{
ProfitTarget += ProfitIncrease;
if (ProfitTarget > MaxProfitExit) ProfitTarget = MaxProfitExit;
OrderClose( OrderTicket(), OrderLots(), Bid, Slippage, Violet);
return(0);
}
if ((LastTradeWasBuy == true) &&
(TotalOrders > MaxTrades) &&
(OrderSymbol() == Symbol()) &&
(OrderType() == OP_SELL) &&
(OrderOpenPrice() == LowestSell))
{
ProfitTarget += ProfitIncrease;
if (ProfitTarget > MaxProfitExit) ProfitTarget = MaxProfitExit;
OrderClose( OrderTicket(), OrderLots(), Ask, Slippage, Violet);
return(0);
}
} // if OrderSelect()
} // for i = 0 to OrdersTotal()-1
// BuyNewLevel, SellNewLevel;
BuyNewLevel = 0;
SellNewLevel = 0;
for (i=0; i<TotalOrders; i++)
{
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol() == Symbol())
{
if ((OrderType() == OP_BUY) && (OrderOpenPrice() == Ask)) BuyNewLevel = 1;
if ((OrderType() == OP_SELL) && (OrderOpenPrice() == Bid)) SellNewLevel = 1;
}
}
} // for i = 0 to OrdersTotal-1
////////////////////////////////////////////////////////
// Open additional trades on a grid
////////////////////////////////////////////////////////
if ((Ask > LowestBuy) && (BuyNewLevel == 0) && (AccountProfit() < ProfitEntry) &&
(NumBuys <= NumSells+BalanceDelta))
{
if (AccountFreeMargin() < dFreeMargin) return(0);
LastTradeWasBuy = true;
LastTradeWasSell = false;
if (StopLoss == 0) safety = 0;
else safety = Bid - (StopLoss * Point);
if (TakeProfit == 0) target = 0;
else target = Ask + (TakeProfit * Point);
if(log>0) Print("SL ", StopLoss, " safety ", safety, " TP ", TakeProfit, " target ", target );
OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, safety, target, "", MAGICGT, 0, Blue);
return(0);
}
if ((Bid < HighestSell) && (SellNewLevel == 0) && (AccountProfit() < ProfitEntry) &&
(NumSells <= NumBuys+BalanceDelta))
{
if (AccountFreeMargin() < dFreeMargin) return(0);
LastTradeWasSell = true;
LastTradeWasBuy = false;
if (StopLoss == 0) safety = 0;
else safety = Ask + (StopLoss * Point);
if (TakeProfit == 0) target = 0;
else target = Bid - (TakeProfit * Point);
if(log>0) Print("SL ", StopLoss, " safety ", safety, " TP ", TakeProfit, " target ", target );
OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, safety, target, "", MAGICGT, 0, Red);
return(0);
}
} // if CloseAll == 0
} // start()
// end EA
Comments