Okay, here's the explanation of the MQL4 script's logic, written for a non-programmer audience:
This script is designed to automate trading in the MetaTrader platform based on Fibonacci pivot levels. It's like having a robot assistant that watches the market for you and places trades according to a specific plan. Here's a breakdown of what it does:
-
Setup and Configuration:
- When you start the script, it first gathers information about the current market conditions for the specific currency pair you're trading (e.g., EUR/USD). This includes things like the minimum price change, the spread (the difference between the buying and selling price), and the minimum and maximum trade sizes allowed.
- It checks if the trade size you've set in the script's settings is valid. If the size is too small or too large, the script will stop and tell you to correct the setting.
- Then it also look at past trades to ensure the script can be restarted properly
- It checks for errors that might prevent trade execution and it will stop until the error is fixed.
-
Calculating Support and Resistance Levels:
- The core of this script revolves around identifying potential support and resistance levels using a Fibonacci-based approach.
- The script looks at the high, low, and closing price of the previous day to determine the day's volatility.
- It calculates a "Pivot Point" (the typical price of a day) based on yesterday's high, low, and closing prices.
- Using this Pivot Point, the script calculates several support and resistance levels by applying the Fibonacci ratios that you specify as percentages in the script's settings. These levels are essentially price points where the script anticipates the price might find support (bounce upwards) or encounter resistance (struggle to move higher).
-
Trading Logic:
- The script runs every time a new price quote comes in.
- It verifies that today the currency hasnt already been trade.
- The main logic is to close every trade order and place pending orders.
- Pending Orders: Based on the calculated support and resistance levels, the script automatically places "pending orders".
- A "Buy Stop" order is placed above the first calculated resistance level (Res1). This order is triggered if the price rises to that level, anticipating that the price will continue to rise further.
- A "Sell Stop" order is placed below the first calculated support level (Supp1). This order is triggered if the price falls to that level, anticipating that the price will continue to fall further.
- The script calculates where to place the "stop loss" and "take profit" levels for these orders. These are safety measures to limit potential losses and secure profits.
- The script ensures it's not trying to place orders too close to the current price (within a certain "stop level").
- Order Management: The script also includes functionality to manage existing trades:
- If a trade goes far enough into profit, the script can move the stop loss to the breakeven point.
- It also has the capacity to do a partial trade exit on the Fibonacci levels.
- It also include basic error management and logs.
-
Important Considerations:
- Parameters: The script relies heavily on the input parameters you set. These parameters (like the Fibonacci percentages) determine where the support and resistance levels are placed, and thus, the entry and exit points for trades.
- Sound Alerts: The script can play a sound when it opens a new trade, letting you know it's taken action.
- Magic Number: The "Magic Number" is a unique identifier for the trades placed by this script. This allows the script to manage its own trades without interfering with other automated trading systems you might be using.
In essence, this script automates a trading strategy based on Fibonacci pivot levels. It calculates potential support and resistance areas, places pending orders, manages existing trades, and includes basic error handling and alerts. It does not guarantee profits, and you need to understand the underlying strategy and adjust the settings to suit your trading style and risk tolerance.
//+-------------------------------------------------------------------------------------+
//| FiboPivot_Expert.mq4 |
//| Scriptong |
//| |
//+-------------------------------------------------------------------------------------+
#property copyright "Scriptong"
#property link "scriptong@mail.ru"
//---- input parameters
extern double Lots = 0.1; // Îáúåì îòêðûâàåìîé ïîçèöèè
extern string A1 = "Óðîâíè ñîïðîòèâëåíèÿ è ïîääåðæêè â ïðîöåíòàõ";
extern double Resistance3=138.2; // Ñàìîå âûñîêîå ìîïðîòèâëåíèå
extern double Resistance2=100.0; // Ñðåäíåå ñîïðîòèâëåíèå
extern double Resistance1=61.8; // Ñàìîå íèçêîå ñîïðîòèâëåíèå
extern double Support1=61.8; // Ñàìàÿ âûñîêàÿ ïîääåðæêà
extern double Support2=100.0; // Ñðåäíÿÿ ïîääåðæêà
extern double Support3=138.2; // Ñàìàÿ íèçêàÿ ïîääåðæêà
extern string A2 = "=====================================";
extern string OpenOrderSound = "ok.wav"; // Çâóê äëÿ îòêðûòèÿ ïîçèöèè
extern int MagicNumber = 17589 ; // Ìàãèê ïîçèöèé ñîâåòíèêà
bool Activate, FreeMarginAlert, FatalError;
double Tick, Spread, StopLevel, MinLot, MaxLot, LotStep, Res1, Res2, Res3, Supp1, Supp2,
Supp3, Pivot;
datetime LastSell, LastBuy;
int TypeOrder, LastType, TicketOrder;
//+-------------------------------------------------------------------------------------+
//| Ôóíêöèÿ èíèöèàëèçàöèè ýêñïåðòà |
//+-------------------------------------------------------------------------------------+
int init()
{
//----
Activate = False;
// - 1 - == Ñáîð èíôîðìàöèè îá óñëîâèÿõ òîðãîâëè ========================================
Tick = MarketInfo(Symbol(), MODE_TICKSIZE); // ìèíèìàëüíûé òèê
Spread = ND(MarketInfo(Symbol(), MODE_SPREAD)*Point); // òåêùèé ñïðýä
StopLevel = ND(MarketInfo(Symbol(), MODE_STOPLEVEL)*Point); // òåêóùèé óðîâåíü ñòîïîâ
MinLot = MarketInfo(Symbol(), MODE_MINLOT); // ìèíèìàëüíûé ðàçðåøåííûé îáúåì ñäåëêè
MaxLot = MarketInfo(Symbol(), MODE_MAXLOT); // ìàêñèìàëüíûé ðàçðåøåííûé îáúåì ñäåëêè
LotStep = MarketInfo(Symbol(), MODE_LOTSTEP); // øàã ïðèðàùåíèÿ îáúåìà ñäåëêè
// - 1 - == Îêîí÷àíèå áëîêà =============================================================
// - 2 - == Ïðèâåäåíèå îáúåìà ñäåëêè ê äîïóñòèìîìó è ïðîâåðêà êîððåêòíîñòè îáúåìà =======
Lots = MathRound(Lots/LotStep)*LotStep; // îêðóãëåíèå îáúåìà äî áëèæàéøåãî äîïóñòèìîãî
if(Lots < MinLot || Lots > MaxLot) // îáúåì ñäåëêè íå ìåíüøå MinLot è íå áîëüøå MaxLot
{
Comment("Ïàðàìåòðîì Lots áûë çàäàí íåïðàâèëüíûé îáúåì ñäåëêè! Ñîâåòíèê îòêëþ÷åí!");
return(0);
}
// - 2 - == Îêîí÷àíèå áëîêà =============================================================
// - 3 - == Îáíîâëåíèå èñòîðè÷åñêèõ äàííûõ ==============================================
Comment("Ïîäîæäèòå, ïðîèçâîäèòñÿ çàïðîñ èñòîðè÷åñêèõ äàííûõ...");
int P = 0;
while(P < 120)
{
datetime NowDay = iTime(Symbol(), PERIOD_D1, 0);
if (GetLastError() != 4066) break;
Sleep(1000);
P++;
}
Comment("");
// - 3 - == Îêîí÷àíèå áëîêà =============================================================
// - 4 - == Ñáîð ñâåäåíèé îá èñòîðè ñäåëîê äî ñòàðòà ñîâåòíèêà ==========================
LastSell = 0;
LastBuy = 0;
for (int i = 0; i < OrdersTotal(); i++)
if (OrderSelect(i, SELECT_BY_POS))
if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if (OrderType() == OP_BUY && OrderOpenTime() >= NowDay)
LastBuy = NowDay;
if (OrderType() == OP_SELL && OrderOpenTime() >= NowDay)
LastSell = NowDay;
}
for (i = 0; i < OrdersHistoryTotal(); i++)
if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
{
if (OrderType() == OP_BUY && OrderOpenTime() >= NowDay)
LastBuy = NowDay;
if (OrderType() == OP_SELL && OrderOpenTime() >= NowDay)
LastSell = NowDay;
}
// - 4 - == Îêîí÷àíèå áëîêà =============================================================
Activate = True; // Âñå ïðîâåðêè óñïåøíî çàâåðøåíû, âîçâîäèì ôëàã àêòèâèçàöèè ýêñïåðòà
//----
return(0);
}
//+-------------------------------------------------------------------------------------+
//| Ôóíêöèÿ äåèíèöèàëèçàöèè ýêñïåðòà |
//+-------------------------------------------------------------------------------------+
int deinit()
{
//----
Comment("");
//----
return(0);
}
//+-------------------------------------------------------------------------------------+
//| Ïðèâåäåíèå çíà÷åíèé ê òî÷íîñòè îäíîãî ïóíêòà |
//+-------------------------------------------------------------------------------------+
double ND(double A)
{
return(NormalizeDouble(A, Digits));
}
//+-------------------------------------------------------------------------------------+
//| Ðàñøèôðîâêà ñîîáùåíèÿ îá îøèáêå |
//+-------------------------------------------------------------------------------------+
string ErrorToString(int Error)
{
switch(Error)
{
case 2: return("çàôèêñèðîâàíà îáùàÿ îøèáêà, îáðàòèòåñü â òåõïîääåðæêó.");
case 5: return("ó âàñ ñòàðàÿ âåðñèÿ òåðìèíàëà, îáíîâèòå åå.");
case 6: return("íåò ñâÿçè ñ ñåðâåðîì, ïîïðîáóéòå ïåðåçàãðóçèòü òåðìèíàë.");
case 64: return("ñ÷åò çàáëîêèðîâàí, îáðàòèòåñü â òåõïîääåðæêó.");
case 132: return("ðûíîê çàêðûò.");
case 133: return("òîðãîâëÿ çàïðåùåíà.");
case 149: return("çàïðåùåíî ëîêèðîâàíèå.");
}
}
//+-------------------------------------------------------------------------------------+
//| Îòêðûòèå ïîçèöèè |
//| Âîçâðàùàåò: |
//| True - Ïîçèöèÿ îòêðûòà óñïåøíî |
//| False - Îøèáêà îòêðûòèÿ |
//+-------------------------------------------------------------------------------------+
bool OpenOrder(int Type, double Price, double SL, double TP)
{
// Áëîê ïðîâåðêè äîñòàòî÷íîñòè ñâîáîäíûõ ñðåäñòâ
if(AccountFreeMarginCheck(Symbol(), OP_BUY, Lots) <= 0 || GetLastError() == 134)
{
if(!FreeMarginAlert)
{
Print("Íåäîñòàòî÷íî ñðåäñòâ äëÿ îòêðûòèÿ ïîçèöèè. Free Margin = ",
AccountFreeMargin());
FreeMarginAlert = True;
}
return(False);
}
FreeMarginAlert = False;
// ---------------------------------------------
switch (Type)
{
case OP_BUY: string S = "BUY"; break;
case OP_SELL: S = "SELL"; break;
case OP_BUYSTOP: S = "BUYSTOP"; break;
case OP_SELLSTOP: S = "SELLSTOP"; break;
case OP_BUYLIMIT: S = "BUYLIMIT"; break;
case OP_SELLLIMIT: S = "SELLLIMIT"; break;
}
if(WaitForTradeContext()) // îæèäàíèå îñâîáîæäåíèÿ òîðãîâîãî ïîòîêà
{
Comment("Îòïðàâëåí çàïðîñ íà îòêðûòèå îðäåðà ", S, " ...");
int ticket=OrderSend(Symbol(), Type, Lots, Price, 0,
SL, TP, NULL, MagicNumber, 0, CLR_NONE); // îòêðûòèå ïîçèöèè
// Ïîïûòêà îòêðûòèÿ ïîçèöèè çàâåðøèëàñü íåóäà÷åé
if(ticket<0)
{
int Error = GetLastError();
if(Error == 2 || Error == 5 || Error == 6 || Error == 64
|| Error == 132 || Error == 133 || Error == 149) // ñïèñîê ôàòàëüíûõ îøèáîê
{
Comment("Ôàòàëüíàÿ îøèáêà ïðè îòêðûòèè ïîçèöèè ò. ê. "+
ErrorToString(Error)+" Ñîâåòíèê îòêëþ÷åí!");
FatalError = True;
}
else
Comment("Îøèáêà îòêðûòèÿ ïîçèöèè ", S, ": ", Error); // íåôàòàëüíàÿ îøèáêà
return(False);
}
// ---------------------------------------------
// Óäà÷íîå îòêðûòèå ïîçèöèè
Comment("Ïîçèöèÿ ", S, " îòêðûòà óñïåøíî!");
PlaySound(OpenOrderSound);
return(True);
// ------------------------
}
else
{
Comment("Âðåìÿ îæèäàíèÿ îñâîáîæäåíèÿ òîðãîâîãî ïîòîêà èñòåêëî!");
return(False);
}
}
//+-------------------------------------------------------------------------------------+
//| Îæèäàíèå òîðãîâîãî ïîòîêà. Åñëè ïîòîê ñâîáîäåí, òî ðåçóëüòàò True, èíà÷å - False |
//+-------------------------------------------------------------------------------------+
bool WaitForTradeContext()
{
int P = 0;
// öèêë "ïîêà"
while(IsTradeContextBusy() && P < 5)
{
P++;
Sleep(1000);
}
// -------------
if(P == 5)
return(False);
return(True);
}
//+-------------------------------------------------------------------------------------+
//| Ðàñ÷åò óðîâíåé ïîääåðæêè/ñîïðîòèâëåíèÿ |
//+-------------------------------------------------------------------------------------+
void GetSignal()
{
// - 1 - == Ðàñ÷åò óðîâíåé ñîïðîòèâëåíèÿ è ïîääåðæêè äëÿ òåêóùåãî äíÿ ===================
double HighDay = iHigh(Symbol(), PERIOD_D1, 1); // Ìàêñèìóì ïðåäûäóùåãî äíÿ
double LowDay = iLow(Symbol(), PERIOD_D1, 1); // Ìèíèìóì ïðåäûäóùåãî äíÿ
double CloseDay = iClose(Symbol(), PERIOD_D1, 1); // Çàêðûòèå ïðåäûäóùåãî äíÿ
double Width = HighDay - LowDay; // Âîëàòèëüíîñòü â÷åðàøíåãî äíÿ
Pivot = (HighDay+LowDay+CloseDay)/3; //Ñòàíäàðòíûé Pivot - òèïè÷íàÿ öåíà äíÿ
Res1 = Pivot + Width*(Resistance1/100.0); // Ïåðâîå ñîïðîòèâëåíèå
Res2 = Pivot + Width*(Resistance2/100.0); // Âòîðîå ñîïðîòèâëåíèå
Res3 = Pivot + Width*(Resistance3/100.0); // Òðåòüå ñîïðîòèâëåíèå
Supp1 = Pivot - Width*(Support1/100.0); // Ïåðâàÿ ïîääåðæêà
Supp2 = Pivot - Width*(Support2/100.0); // Âòîðàÿ ïîääåðæêà
Supp3 = Pivot - Width*(Support3/100.0); // Òðåòüÿ ïîääåðæêà
// - 1 - == Îêîí÷àíèå áëîêà =============================================================
}
//+-------------------------------------------------------------------------------------+
//| Çàêðûâàåò âñå ïîçèöèè. Åñëè çàêðûòü íå óäàëîñü, òî âîçâðàùàåò False. |
//|  ñëó÷àå óñïåõà True. |
//+-------------------------------------------------------------------------------------+
bool CloseAll()
{
for (int i = OrdersTotal()-1; i >= 0; i--)
if (OrderSelect(i, SELECT_BY_POS))
if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
if (OrderOpenTime() < iTime(Symbol(), PERIOD_D1, 0))
if (WaitForTradeContext())
{
if (OrderType() < 2) // Åñëè íàøëè ïîçèöèþ
{
RefreshRates();
if (OrderType() == OP_BUY)
double Pr = ND(Bid);
else
Pr = ND(Ask);
if (!OrderClose(OrderTicket(), OrderLots(), Pr, 3)) // òî ïûòàåìñÿ çàêðûòü
return(False); // íå óäàëîñü çàêðûòü - âåðíåì False
}
else
if (!OrderDelete(OrderTicket()))
return(False);
}
else
return(False); //âåðíåì False, åñëè íå äîæäàëèñü îñâîáîæäåíèÿ òîðãîâîãî ïîòîêà
return(True); // åñëè âñå ÎÊ, òî âåðíåì 0
}
//+-------------------------------------------------------------------------------------+
//| Ïîèñê ïåðâè÷íîé ïîçèöèè è óäàëåíèå ñîîòâåòñòâóþùåãî åé îòëîæåííèêà, åñëè ïîçèöèè íåò|
//+-------------------------------------------------------------------------------------+
void PartiallyClose()
{
for (int i = OrdersTotal()-1; i >= 0; i--)
if (OrderSelect(i, SELECT_BY_POS))
if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber
&& OrderType() < 2) // ïîèñê ñðàáîòàâøåãî îðäåðà
{
if (StringFind(OrderComment(), "from #", 0) < 0)
{ // Öåíà äîñòèãëà óðîâíÿ âòîðîãî ñîïðîòèâëåíèÿ èëè ïîääåðæêè
if ((OrderType() == OP_BUY && ND(Bid) >= ND(Res2)) ||
(OrderType() == OP_SELL && ND(Bid) <= ND(Supp2)))
{ // Ïðîèçâîäèì ÷àñòè÷íîå çàêðûòèå
double LotsClose = MathMax(MinLot, // Ðàñ÷åò çàêðûâàåìîãî îáúåìà
MathRound((OrderLots()/2)/LotStep)*LotStep);
if (WaitForTradeContext())
if (!OrderClose(OrderTicket(), LotsClose, IF(OrderType() == OP_BUY,
ND(Bid), ND(Ask)), 3))
return;
}
}
else
{ // Ïåðåíîñ ñòîïà â áåçóáûòîê
bool Res = False;
if (OrderType() == OP_BUY)
if (ND(OrderStopLoss()) < ND(OrderOpenPrice()) &&
ND(Bid - OrderOpenPrice()) > StopLevel)
Res = True;
if (OrderType() == OP_SELL)
if (ND(OrderStopLoss()) > ND(OrderOpenPrice()) &&
ND(OrderOpenPrice() - Ask) > StopLevel)
Res = True;
if (Res)
if (WaitForTradeContext())
if (!OrderModify(OrderTicket(), 0, ND(OrderOpenPrice()),
OrderTakeProfit(), 0))
return;
}
}
}
//+-------------------------------------------------------------------------------------+
//| Çàìåíà ñòàíäàðòíîãî áëîêà "if-else" |
//+-------------------------------------------------------------------------------------+
double IF(bool Condition, double IfTrue, double IfFalse)
{
if (Condition) return(IfTrue); // Åñëè óñëîâèå èñòèííî, òî âîçâðàùàåì çíà÷åíèå IfTrue
else return(IfFalse); // Åñëè óñëîâèå ëîæíî, òî âîçâðàùàåì çíà÷åíèå IfFalse
}
//+-------------------------------------------------------------------------------------+
//| Ôóíêöèÿ START ýêñïåðòà |
//+-------------------------------------------------------------------------------------+
int start()
{
// - 1 - == Ðàçðåøåíî ëè ñîâåòíèêó ðàáîòàòü? ===========================================
if (!Activate || FatalError) // Îòêëþ÷àåòñÿ ðàáîòà ñîâåòíèêà, åñëè ôóíêöèÿ
return(0); // init çàâåðøèëàñü ñ îøèáêîé èëè èìåëà ìåñòî ôàòàëüíàÿ îøèáêà
// - 1 - == Îêîí÷àíèå áëîêà ============================================================
// - 2 - == ×àñòè÷íîå çàêðûòèå ïîçèöèè è ïðåíîñ ñòîïà â áåçóáûòîê =======================
PartiallyClose();
// - 2 - == Îêîí÷àíèå áëîêà ============================================================
// - 3 - == Êîíòðîëü îòêðûòèÿ íîâîãî äíÿ ===============================================
datetime NowDay = iTime(Symbol(), PERIOD_D1, 0);
if (LastBuy == NowDay && LastSell == NowDay) //Åñëè îòêðûâàëèñü ñåãîäíÿ, òî áîëüøå íå
return(0); // ðàáîòàåì
// - 3 - == Îêîí÷àíèå áëîêà ============================================================
// - 4 - == Ñáîð èíôîðìàöèè îá óñëîâèÿõ òîðãîâëè ========================================
Spread = ND(MarketInfo(Symbol(), MODE_SPREAD)*Point); // òåêùèé ñïðýä
StopLevel = ND(MarketInfo(Symbol(), MODE_STOPLEVEL)*Point); // òåêóùèé óðîâåíü ñòîïîâ
// - 4 - == Îêîí÷àíèå áëîêà ============================================================
// - 5 - == Ðàñ÷åò òåêóùåãî ñèãíàëà =====================================================
GetSignal();
// - 5 - == Îêîí÷àíèå áëîêà ============================================================
// - 6 - == Óñòàíîâêà îðäåðà BuyStop ====================================================
double Price = ND(Res1 + Spread);
bool Res = CloseAll(); // Çàêðûòü âñå ïîçèöèè è óäàëèòü âñå îðäåðà
RefreshRates();
if (Res && Ask < Price && LastBuy < NowDay) // åñëè íåò îòêðûòûõ ïîçèöèé è öåíà íå
{ // ïðîáèëà ïåðâîå ñîïðîòèâëåíèå
double TP = ND(IF(Res3 - Price > StopLevel, Res3, Price + StopLevel));
double SL = ND(IF(Price - Pivot - Tick > StopLevel+Spread, Pivot - Tick,
Price - StopLevel - Spread));
if (ND(Price - Ask) <= StopLevel) // Åñëè íåâîçìîæíî îòëîæèòü îðäåð, òî æäåì
return(0); // ñëåäóþùåãî òèêà
if (!OpenOrder(OP_BUYSTOP, Price, SL, TP)) // åñëè íå óäàëîñü óñòàíîâèòü îðäåð
return(0); // òî ïîïðîáóåì ñî ñëåäóþùèì òèêîì
LastBuy = NowDay;
}
if (!Res) return(0); //çàêðûòü âñå ïîçèöèè íå âûøëî, æäåì äî ñëåäóþùåãî òèêà
// - 6 - == Îêîí÷àíèå áëîêà ============================================================
// - 7 - == Óñòàíîâêà îðäåðà SellStop ===================================================
Price = ND(Supp1);
if (Bid > Price && LastSell < NowDay) // åñëè íåò îòêðûòûõ ïîçèöèé è öåíà íå ïðîáèëà
{ // ïåðâóþ ïîääåðæêó
TP = ND(IF(Price - Supp3 + Spread > StopLevel, Supp3 + Spread,
Price - StopLevel));
SL = ND(IF(Pivot + Tick - Price > StopLevel, Pivot + Spread + Tick,
Price + StopLevel + Spread));
if (ND(Bid - Price) <= StopLevel) // Åñëè íåâîçìîæíî îòëîæèòü îðäåð, òî æäåì
return(0); // ñëåäóþùåãî òèêà
if (!OpenOrder(OP_SELLSTOP, Price, SL, TP)) // åñëè íå óäàëîñü óñòàíîâèòü îðäåð
return(0); // òî ïîïðîáóåì ñî ñëåäóþùèì òèêîì
LastSell = NowDay;
}
// - 7 - == Îêîí÷àíèå áëîêà ============================================================
return(0);
}
//+------------------------------------------------------------------+
Comments