Как только Эквити оторвался от депозита на установленную нами сумму, все закрывается.Заметьте ни намека в большую или меньшую сторону.
if(CurrentnEQ-CurrentnPR >= Equity_RollbackUp || CurrentnEQ-CurrentnPR <= — Equity_RollbackDown)
Вы чего написали, вы хотя чуть -чуть вдумываетесь в смысл написанного.Методом тыка хороший советник не получиться.
//************************************************************************************************/
bool TrailingEquity()
{
if(Equity_Rollback == 0) // Если трал эквити не разрешeн
return(false); // выходим
double CurrentnEQ = AccountEquity() ; // Текущий эквити меняется с каждым тиком
// --------- Этап 1 - ожидание начала цикла для получения стартового эквити ---------
if(b+s == 0) // Если нет ордеров (начало очередного этапа)
{
CloseEQ = AccountEquity(); // Запоминаем эквити на начало цикла, пока не появится хоть один ордер.
return (false); // Трал эквити еще не закончил свою работу.
}
// ------------------------- Этап 2 - работа трала эквити -----------------------------
if(b+s > 0) // Если появился ордер (начало очередного этапа)
{
if(TrailEQ == false) // Если трал эквити еще не начался, то следим за эквити.
{ //
if(CurrentnEQ >= CloseEQ + Equity_Rollback) // Если текущий эквити оторвался в + от стартового на дистанцию трала и более
{
CloseEQ = CurrentnEQ - Equity_Rollback; // Запоминаем эквити для закрытия всего, который будем подтягивать за растущим эквити.
TrailEQ = true; // Флаг начала трэйлинга подняли. Заработал трал эквити.
Alert ("Сработал Трэйлинг эквити");
return (false); // Трал начал работу, но не выполнил еще свою функцию.
} // Просто передаем слежение за эквити дальнейшему алгоритму на последующих тиках
}
if(TrailEQ == true) // Если трал запущен и уже тралит эквити.
{
if(CurrentnEQ > CloseEQ + Equity_Rollback) // Если текущий эквити отрывается дальше в + от эквити для закрытия CloseEQ
CloseEQ = CurrentnEQ - Equity_Rollback; // Каждый раз величиваем уровень эквити для закрытия CloseEQ
//--- Если текущий эквити падает, эквити на закрытие остается на месте.
if(CurrentnEQ <= CloseEQ) // Если текущий эквити упал до уровня срабатывания трала
{
TrailEQ = false; // Флаг начала трэйлинга снимаем.
Alert ("Сигнал на защиту Эквити");
return (true); // Функция сработала.
}
}
}
return (false); // Иначе трал трудится
}
//************************************************************************************************/
void CloseAll()
{
int nn = 0,OMN,OT,Ticket,j;
int total = OrdersTotal();
double profits = 0;
while(true)
{
for (j = total-1; j >= 0; j--)
{
if (OrderSelect(j, SELECT_BY_POS))
{
OT = OrderType();
OMN = OrderMagicNumber();
Ticket = OrderTicket();
if (OT==OP_BUY)
if (OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),Slippage,Blue))
profits+=OrderProfit();
//---
if (OT==OP_SELL)
if (OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),Slippage,Red))
profits+=OrderProfit();
}
}
int n=0;
for (j = 0; j < OrdersTotal(); j++)
if (OrderSelect(j, SELECT_BY_POS))
{
OT = OrderType();
n++;
}
if (n==0) break;
nn++;
if (nn>10)
Alert(Symbol()," Не удалось закрыть все сделки, осталось еще ",n);
Sleep(1000);
RefreshRates();
}
Alert(Symbol()," Закрыли все сделки ");
}
//************************************************************************************************/
//--- Выставляем ТР крайним ордерам OP_SELL в безубыток + ----
if(s>=CountAverage)
{
if(CloseOrder==FullAwerage) // Закрываем оба ордера
if(tk==SelPriceMaxTic || tk==SelPriceMinTic)
if(Ask>AverageSelPrice && tp!=AverageSelPrice)
if(!OrderModify(tk,op,OrderStopLoss(),AverageSelPrice,0,clrRed))
Print("OrderModify error №6 #",GetLastError());
//---
if(CloseOrder==NoClose) // Закрываем только убыточный ордер
if(tk==SelPriceMaxTic)
if(Ask>AverageSelPrice && tp!=AverageSelPrice)
if(!OrderModify(tk,op,OrderStopLoss(),AverageSelPrice,0,clrRed))
Print("OrderModify error №7 #",GetLastError());
//---
if(CloseOrder==StartClose && Ask<=AverageSelPrice)
{
if(tk==SelPriceMaxTic) // Профитному оставляем стартовый лот
if(!OrderClose(tk,NormalizeDouble(SelPriceMaxLot-StartLots,2),Ask,Slippage,clrBlue))
Print("OrderModify error №3 #",GetLastError());
if(tk==SelPriceMinTic) // А убыточный закрываем весь
if(!OrderClose(tk,lt,Ask,Slippage,clrBlue))
Print("OrderModify error №3 #",GetLastError());
}
//---
if(CloseOrder==StartStart && Ask<=AverageBuyPrice)
{
if(tk==SelPriceMaxTic) // От профитномого убавлем стартовый лот
if(!OrderClose(tk,StartLots,Ask,Slippage,clrBlue))
Print("OrderModify error №3 #",GetLastError());
if(tk==SelPriceMinTic) // Убыточный закрываем весь
if(!OrderClose(tk,lt,Ask,Slippage,clrBlue))
Print("OrderModify error №3 #",GetLastError());
}
}
}
//-------- Восстановление ТР не крайним ордерам OP_SELL ---------
if(tk != SelPriceMinTic && tk != SelPriceMaxTic)
if(tp!= NormalizeDouble (op - TakeProfit * Point(), Digits()))
if(!OrderModify(tk, op, OrderStopLoss(), NormalizeDouble (op - TakeProfit * Point(), Digits()), 0, clrRed))
Print("OrderModify error №8 #", GetLastError());
} // End OP_SELL
}
//************************************************************************************************/
//* ФУНКЦИИ */
//************************************************************************************************/
double GetLotPersent() //Функция возвращает значение лотов,
{
double lots,MD,MinLots,MaxLots, LotSize;
int lotsdigit=0; //вычисляется путем:Свободные средства*Risk
MinLots = NormalizeDouble(MarketInfo(Symbol(),MODE_MINLOT),2);
MaxLots = NormalizeDouble(MarketInfo(Symbol(),MODE_MAXLOT),2);
LotSize = MarketInfo(Symbol(), MODE_LOTSIZE); //поделить на стоимость одного лота
MD = NormalizeDouble(MarketInfo(Symbol(), MODE_LOTSTEP), 2);
//А также вычисляем колличество знаков
if(MD==0.01)
lotsdigit=2; //присваивает значения максимума лотов
if(MD==0.1)
lotsdigit=1; //присваивает значения максимума лотов
if(MM)
lots=NormalizeDouble((AccountFreeMargin()*Risk/LotSize),lotsdigit);
else
lots=StartLots;
if(lots < MinLots)
lots = MinLots;
if(lots > MaxLots)
lots = MaxLots;
return(NormalizeDouble(lots,lotsdigit));
}
//************************************************************************************************/
bool CheckVolumeValue(double volume)
{
//--- минимально допустимый объем для торговых операций
double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
if(volume<min_volume)
return(false);
//--- максимально допустимый объем для торговых операций
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
if(volume>max_volume)
return(false);
//--- получим минимальную градацию объема
double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
int ratio=(int)MathRound(volume/volume_step);
if(MathAbs(ratio*volume_step-volume)>0.0000001)
return(false);
return(true);
}
//************************************************************************************************/
//************************** Определение средней цены между крайними ордерами + Минимальный профит **************************
double AverageBuyPrice=0,AverageSelPrice=0;
if(b>=CountAverage)
AverageBuyPrice = NormalizeDouble((BuyPriceMax*BuyPriceMaxLot+BuyPriceMin*BuyPriceMinLot)
/(BuyPriceMaxLot+BuyPriceMinLot)+MinimalProfit*Point(),Digits());
if(s>=CountAverage)
AverageSelPrice = NormalizeDouble((SelPriceMax*SelPriceMaxLot+SelPriceMin*SelPriceMinLot)
/(SelPriceMaxLot+SelPriceMinLot)-MinimalProfit*Point(),Digits());
//*********************************** Определение лотов на покупку и продажу ************************************************
double BuyLot = 0, SelLot = 0;
//---------------- Если ММ не разрешeн ----------------
if(!MM)
{
if(b==0)
BuyLot = StartLots;
else
BuyLot = NormalizeDouble(MathCeil((BuyPriceMinLot * CoeffLots)*100)/100,2);
//---
if(s==0)
SelLot = StartLots;
else
SelLot = NormalizeDouble(MathCeil((SelPriceMaxLot * CoeffLots)*100)/100,2);
}
//---------------- Если ММ разрешeн ----------------
if(MM)
{
if(BuyPriceMinLot == 0 || b==0)
BuyLot = GetLotPersent();
else
BuyLot = NormalizeDouble(MathCeil((BuyPriceMinLot * CoeffLots)*100)/100,2);
//---
if(SelPriceMaxLot == 0 || s==0)
SelLot = GetLotPersent();
else
SelLot = NormalizeDouble(MathCeil((SelPriceMaxLot * CoeffLots)*100)/100,2);
}
//--- Проверка лотов на превышение максимально нами разрешенного ---
if(BuyLot>MaximalLots)
BuyLot=NormalizeDouble(MaximalLots,2);
if(SelLot>MaximalLots)
SelLot=NormalizeDouble(MaximalLots,2);
//--- Проверка лотов на валидность---
if(!CheckVolumeValue(BuyLot) || !CheckVolumeValue(SelLot))
return;
//************************** Открытие ордеров ******************************
SignalB = false; SignalS = false;
if(OpenOrder == NoBars)
{
SignalB = true;
SignalS = true;
}
if(OpenOrder == OutOpen)
{
if(Open[0]<Open[1] && Bid>Open[1])
SignalB = true;
if(Open[0]>Open[1] && Bid<Open[1])
SignalS = true;
}
if(OpenOrder == cCloseOut)
{
if(Open[1]<Open[2] && Close[1]>High[2])
SignalB = true;
if(Open[1]>Open[2] && Close[1]<Low[2])
SignalS = true;
}
if((b==0) || (b>0 && SignalB && (BuyPriceMin-Ask)>(PointOrderStep*Point())))
if(OrderSend(Symbol(),OP_BUY,NormalizeDouble(BuyLot,2),NormalizeDouble(Ask,Digits()),Slippage,0,0,"",MagicNumber,0,clrBlue)<0)
Print("Order Buy Send error #",GetLastError());
if((s==0) || (s>0 && SignalS && (Bid-SelPriceMax)>(PointOrderStep*Point())))
if(OrderSend(Symbol(),OP_SELL,NormalizeDouble(SelLot,2),NormalizeDouble(Bid,Digits()),Slippage,0,0,"",MagicNumber,0,clrRed)<0)
Print("Order Sell Send error #",GetLastError());
//********************** Сопровождение ордеров в цикле **********************
for(int i=OrdersTotal()-1;i>=0;i--)
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
if(OrderMagicNumber()==MagicNumber)
if(OrderSymbol()==Symbol())
{
op=NormalizeDouble(OrderOpenPrice(),Digits());
tp=NormalizeDouble(OrderTakeProfit(),Digits());
lt=NormalizeDouble(OrderLots(),2);
tk=OrderTicket();
sl=OrderStopLoss();
if(OrderType()==OP_BUY && b==1 && tp==0)
{
//--- Выставляем SL и ТР стартовым ордерам OP_BUY ---------
if(b==1 && tp==0)
{
sl=0; tp=0;
if(StopLoss>0)
sl=NormalizeDouble(Ask-StopLoss*Point(),Digits());
if(TakeProfit>0)
tp=NormalizeDouble(Ask+TakeProfit*Point(),Digits());
if(!OrderModify(tk,op,sl,tp,0,clrBlue))
Print("OrderModify error №1 #",GetLastError());
}
//--- Выставляем ТР крайних ордеров OP_BUY в безубыток + --------
if(b>=CountAverage)
{
if(CloseOrder==FullAwerage)
if(tk==BuyPriceMaxTic || tk==BuyPriceMinTic)
if(Bid<=AverageBuyPrice && tp!=AverageBuyPrice)
if(!OrderModify(tk,op,OrderStopLoss(),AverageBuyPrice,0,clrBlue))
Print("OrderModify error №2 #",GetLastError());
//---
if(CloseOrder==NoClose)
if(tk==BuyPriceMinTic)
if(Bid<=AverageBuyPrice && tp!=AverageBuyPrice)
if(!OrderModify(tk,op,OrderStopLoss(),AverageBuyPrice,0,clrBlue))
Print("OrderModify error №3 #",GetLastError());
//---
if(CloseOrder==StartClose && Bid>=AverageBuyPrice)
{
if(tk==BuyPriceMinTic) // Профитному оставляем стартовый лот
if(!OrderClose(tk,NormalizeDouble(BuyPriceMinLot-StartLots,2),Bid,Slippage,clrBlue))
Print("OrderModify error №3 #",GetLastError());
if(tk==BuyPriceMaxTic) // Убыточный закрываем весь
if(!OrderClose(tk,lt,Bid,Slippage,clrBlue))
Print("OrderModify error №3 #",GetLastError());
}
//---
if(CloseOrder==StartStart && Bid>=AverageBuyPrice)
{
if(tk==BuyPriceMinTic) // От профитномого сокращаем стартовый лот
if(!OrderClose(tk,StartLots,Bid,Slippage,clrBlue))
Print("OrderModify error №3 #",GetLastError());
if(tk==BuyPriceMaxTic) // Убыточный закрываем весь
if(!OrderClose(tk,lt,Bid,Slippage,clrBlue))
Print("OrderModify error №3 #",GetLastError());
}
}
//--------- Восстановление ТР не крайним ордерам OP_BUY --------------
if(tk != BuyPriceMinTic && tk != BuyPriceMaxTic)
if(tp!= NormalizeDouble (op + TakeProfit * Point(), Digits()))
if(!OrderModify(tk, op, OrderStopLoss(), NormalizeDouble (op + TakeProfit * Point(), Digits()), 0, clrBlue))
Print("OrderModify error №4 #", GetLastError());
} // End OP_BUY
//---------------------------------------------------------------------
if(OrderType()==OP_SELL)
{
// Выставляем SL и ТР стартовым ордерам OP_SELL
if(s==1 && tp==0)
{
sl=0; tp=0;
if(StopLoss>0)
sl=NormalizeDouble(Bid+StopLoss*Point(),Digits());
if(TakeProfit>0)
tp=NormalizeDouble(Bid-TakeProfit*Point(),Digits());
if(!OrderModify(tk,op,sl,tp,0,clrRed))
Print("OrderModify error №5 #",GetLastError());
}
//+------------------------------------------------------------------+
//| KAE Grid.mq4 |
//| Copyright 2025 |
//| kvashnin007@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025"
#property version "1.4"
#property strict
//************************************************************************************************/
//* */
//************************************************************************************************/
enum ENUM_OO // Вариант открытия ордеров
{
NoBars = 0, // No Bars - Открываем ордера при их отсутствии, не глядя на бар
OutOpen = 1, // Out Open - Открываем ордера при их отсутствии, если цена пробила цену открытия предыдущей свечи
cCloseOut = 2 // Out High Low - Открываем ордера при их отсутствии, если свеча закрыласьза екстремум предыдущей свечи
};
enum ENUM_ST // Вариант сокращения ордеров
{
FullAwerage = 0, // FullAwerage - Сокращает весь ордер на весь ордер в плюс MinimalProfit
StartClose = 1, // Start Close - Оставляет StartLots от плюсового ордера, закрывает минусовой
StartStart = 2, // Start Start - Сокращает StartLots от плюсового ордера, закрывает минусовой
NoClose = 3 // No Close - Закрывает только убыточный ордер
};
//************************************************************************************************/
input bool MM = false; // Мани Менеджмент
input double Risk = 0.5; // Риск на сделку % в процентах от свободной маржи.
input double StartLots = 0.03; // Start lot
input double CoeffLots = 2.0; // Увеличение лота
input double MaximalLots = 2.56; // Maximal Lots
//---
input double Equity_Rollback = 12.7; // Текущая прибыль (в $) всех ордеров, с которой тралим EQUITY
input ENUM_OO OpenOrder = NoBars; // Type Open orders
input ENUM_ST CloseOrder = FullAwerage; // Type Close orders
input int CountAverage = 2; // Минимальное количество ордеров для сокращения
input int StopLoss = 0; // Stop Loss (in pips)
input int TakeProfit = 390; // Take Profit (in pips)
input int PointOrderStep = 270; // Point order step (in pips)
input int MinimalProfit = 70; // Minimal profit for close grid (in pips)
//---
input int MagicNumber = 1961; // Magic Number (in number)
input int Slippage = 30; // Slippage (in pips)
//-------------------------------------------------------------------------------------------------
double Equiti=0;
double Balans=0;
double ProfitBuy = 0, ProfitSell = 0, ProfitFull = 0, NewEQ = 0;
bool TrailEQ = false; // Флаг начала работы трала эквити
//---
double BuyPriceMax=0,BuyPriceMin=0,BuyPriceMaxLot=0,BuyPriceMinLot=0,
SelPriceMin=0,SelPriceMax=0,SelPriceMinLot=0,SelPriceMaxLot=0;
int BuyPriceMaxTic=0,BuyPriceMinTic=0,SelPriceMaxTic=0,SelPriceMinTic=0;
double op=0,lt=0,tp=0,sl=0;
int tk=0,b=0,s=0;
bool SignalB, SignalS; // Сигналы-разрешение на открытие ордеров.
double CloseEQ; // Эквити, при откате до которого выключаем свет.
//************************************************************************************************/
int OnInit()
{
return(INIT_SUCCEEDED);
}
//************************************************************************************************/
void OnDeinit(const int reason){}
//************************************************************************************************/
void OnTick()
{ // --- Обнуляем переменные ---
BuyPriceMax=0;BuyPriceMin=0;BuyPriceMaxLot=0;BuyPriceMinLot=0;
SelPriceMin=0;SelPriceMax=0;SelPriceMinLot=0;SelPriceMaxLot=0;
BuyPriceMaxTic=0;BuyPriceMinTic=0;SelPriceMaxTic=0;SelPriceMinTic=0;
op=0;lt=0;tp=0;sl=0;
ProfitBuy=0;ProfitSell=0;ProfitFull=0;
tk=0;b=0;s=0;
//*********************************** Цикл сбора данный о крайних ордерах *****************************************
for(int i=OrdersTotal()-1;i>=0;i--)
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
if(OrderMagicNumber()==MagicNumber)
if (OrderSymbol()==Symbol())
{
op=NormalizeDouble(OrderOpenPrice(),Digits());
lt=NormalizeDouble(OrderLots(),2);
tk=OrderTicket();
if(OrderType()==OP_BUY)
{
b++;
if(op>BuyPriceMax || BuyPriceMax==0)
{
BuyPriceMax = op;
BuyPriceMaxLot = lt;
BuyPriceMaxTic = tk;
}
if(op<BuyPriceMin || BuyPriceMin==0)
{
BuyPriceMin = op;
BuyPriceMinLot = lt;
BuyPriceMinTic = tk;
}
}
// ===
if(OrderType()==OP_SELL)
{
s++;
if(op>SelPriceMax || SelPriceMax==0)
{
SelPriceMax = op;
SelPriceMaxLot = lt;
SelPriceMaxTic = tk;
}
if(op<SelPriceMin || SelPriceMin==0)
{
SelPriceMin = op;
SelPriceMinLot = lt;
SelPriceMinTic = tk;
}
}
}
//---------- Трейлинг Equiti --------------
if(Equity_Rollback >0 && TrailingEquity() == true)
CloseAll();
<code> //************************************************************************************************/ bool TrailingEquity1() { double CurrentnEQ = AccountEquity() ; // Текущий эквити меняется с каждым тиком. double CurrentnPR = AccountBalance() ; // Текущий депозит меняется с каждым закрытием ордеров // или их открытием за счет спреда и комиссии. if(CurrentnEQ-CurrentnPR >= Equity_RollbackUp || CurrentnEQ-CurrentnPR <= - Equity_RollbackDown) { CloseAll(); Print ("Сигнал на защиту Эквити"); return (true); // Трал дает сигнал об окончании работы } return (false); // Иначе трал еще трудится } //************************************************************************************************/ </code>
<code> //************************************************************************************************/ bool TrailingEquity2() { if(Equity_Rollback == 0) // Если трал эквити не разрешeн return(false); // выходим double CurrentnEQ = AccountEquity() ; // Текущий эквити меняется с каждым тиком double CurrentnPR = AccountProfit() ; // Текущий профит меняется с каждым тиком if(CurrentnEQ-CurrentnPR <= Equity_Rollback) { // CloseAll(); Print ("Сигнал на защиту Эквити"); return (true); // Трал дает сигнал об окончании работы } return (false); // Иначе трал еще трудится } //************************************************************************************************/ </code>
<code> input double Equity_Rollback = 12.7; // Текущая прибыль (в $) всех ордеров, с которой тралим EQUITY //************************************************************************************************/ bool TrailingEquity() { if(Equity_Rollback == 0) // Если трал эквити не разрешeн return(false); // выходим double CurrentnEQ = AccountEquity() ; // Текущий эквити меняется с каждым тиком // --------- Этап 1 - ожидание начала цикла для получения стартового эквити --------- if(b+s == 0) // Если нет ордеров (начало очередного этапа) { CloseEQ = AccountEquity(); // Запоминаем эквити на начало цикла, пока не появится хоть один ордер. return (false); // Трал эквити еще не закончил свою работу. } // ------------------------- Этап 2 - работа трала эквити ----------------------------- if(b+s > 0) // Если появился ордер (начало очередного этапа) { if(TrailEQ == false) // Если трал эквити еще не начался, то следим за эквити. { // if(CurrentnEQ >= CloseEQ + Equity_Rollback) // Если текущий эквити оторвался в + от стартового на дистанцию трала и более { CloseEQ = CurrentnEQ - Equity_Rollback; // Запоминаем эквити для закрытия всего, который будем подтягивать за растущим эквити. TrailEQ = true; // Флаг начала трэйлинга подняли. Заработал трал эквити. Alert ("Сработал Трэйлинг эквити"); return (false); // Трал начал работу, но не выполнил еще свою функцию. } // Просто передаем слежение за эквити дальнейшему алгоритму на последующих тиках } if(TrailEQ == true) // Если трал запущен и уже тралит эквити. { if(CurrentnEQ > CloseEQ + Equity_Rollback) // Если текущий эквити отрывается дальше в + от эквити для закрытия CloseEQ CloseEQ = CurrentnEQ - Equity_Rollback; // Каждый раз величиваем уровень эквити для закрытия CloseEQ //--- Если текущий эквити падает, эквити на закрытие остается на месте. if(CurrentnEQ <= CloseEQ) // Если текущий эквити упал до уровня срабатывания трала { TrailEQ = false; // Флаг начала трэйлинга снимаем. Alert ("Сигнал на защиту Эквити"); return (true); // Функция сработала. } } } return (false); // Иначе трал еще трудится } //************************************************************************************************/ </code>
из-за спреда и комиссии минимальный профит может оказаться и убыточным. Немного, но…
Можно перейти на профиты ордеров. Когда общий профит будет больше чем…
Так. Мысль после тестирования настигла. Это не критично, но все таки.
kvashnin007