Помогите с кодом пожалуйста...

Моргана

Активный участник
Как прописать в коде, чтобы лот после убыточной сделки увеличивался в зависимости от величины этого убытка? У меня ТР стабильный, а убытки разные - могут быть -100, могут -30 или например -560 и т.д. А прибыль всегда одна и та же. Соответственно в коде прописала:
lot=NormalizeDouble(OrderProfit()/Profit,1);
где OrderProfit это отрицательный результат, Profit - значение моей стабильной прибыли на одну сделку.
В общем здесь вопросов нет, всё работает как надо...
Проблема такая: как сделать чтобы при череде убытков (2 и больше) он суммировал эти отрицательные значения и в конце концов увеличивал лот соответственно так чтобы прибыльная сделка после этой череды покрыла все эти убытки? :question:
Подскажите пожалуйста, буду очень благодарна!
 

cmillion

Гуру форума
Находим последний закрывшийся ордер:
PHP:
Expand Collapse Copy
if(сделка закрылась)
{
   double Loss;
   int i=OrdersHistoryTotal()-1;
   if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
   {                                     
      if (OrderProfit()<0) Loss+=OrderProfit();
      else Loss=0;
   }
}

Loss - общий убыток на данный момент

А теперь вычисляем лот для покрытия убытка в зависимости от накопленного Lossa как отношение Lossa к требуемому профиту.
 

machzelet

Почетный гражданин
Раз уж тема с криком о помощи существует, продолжу...
Прошу помочь с написанием кода для интегрированного стоп-лосса.

Идея такова:
Стоп-лосс рассчитавыется формулой в процентном соотношении максимально допустимого убытка от депозита с учетом валютного коэффициента (на один пипс) и величины тогруемого лота (аля ММ).

Пример:
StopLoss = (Депозит * Процент риска) / (Коэфф. валюты * Коэфф. лота)

Допустим:
Депозит = 356 у.е.
Процент риска = 30 (максимальный убыток, который мы готовы понести за одну сделку)
Коэфф. валюты = 37 (скажем, если счет не долларовый, а в шекелях, то на паре евро-бакса один пипс равен 0.37 шекеля * 100)
Коэфф. лота = 3 (при лоте 0,03 * 100)

Итак, StopLoss = (356 * 30) / (37 * 3) = 96,216216216216216216216216216216
Берем только целое число и получаем наш стоп-лосс равный 96 пипсам.

Буду очень благодарен за помощь.
 

machzelet

Почетный гражданин
cmillion, спасибо ))
Теперь возникла другая проблема - хочу добавить в советник функцию определения последней сделки закрытой по стоп-лоссу, чтобы с ее помощью высчитать размер следующей сделки. Только вот никак не могу найти функцию, которая определяет последнюю сделку, которая закрылась по стоп-лоссу (((
Вроде бы эта - OrderStopLoss(), но что в скобках прописать, чтобы советник определил?

Вообще, то что мне нужно, следующее:
kLots = величина последней стоповой сделки * коэффициент валюты / тейк профит (в пипсах)

Не поможете с этим?
Заранее благодарен.
 

cmillion

Гуру форума
cmillion, спасибо ))
Теперь возникла другая проблема - хочу добавить в советник функцию определения последней сделки закрытой по стоп-лоссу, чтобы с ее помощью высчитать размер следующей сделки. Только вот никак не могу найти функцию, которая определяет последнюю сделку, которая закрылась по стоп-лоссу (((
Вроде бы эта - OrderStopLoss(), но что в скобках прописать, чтобы советник определил?

Вообще, то что мне нужно, следующее:
kLots = величина последней стоповой сделки * коэффициент валюты / тейк профит (в пипсах)

Не поможете с этим?
Заранее благодарен.

OrderStopLoss( ) Возвращает значение цены закрытия позиции при достижении уровня убыточности (stop loss) для текущего выбранного ордера.

Вот индикатор, он сигналит при закрытии ордера и показывает по какому стопу ордер закрылся.
PHP:
Expand Collapse Copy
//+------------------------------------------------------------------+
//|                                              AlertCloseOrder.mq4 |
//|                               Copyright © 2010, Vladimir Hlystov |
//|                                         http://cmillion.narod.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010, Vladimir Hlystov"
#property link      "http://cmillion.narod.ru"
#property indicator_chart_window
int Orders;
//+------------------------------------------------------------------+
int start()
  {
   if (Orders>OrdersTotal()) AlertOrder();
   Orders=OrdersTotal();
   return(0);
  }
//+------------------------------------------------------------------+
void AlertOrder()
{
   string txt;
   double OCP;
   int i=OrdersHistoryTotal()-1;
   if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
   {                                     
      OCP=OrderClosePrice();
      if (OCP==OrderStopLoss()  ) txt="SL";
      if (OCP==OrderTakeProfit()) txt="TP";
      Alert("Ордер N ",OrderTicket()," закрыт по ",txt," ",
      DoubleToStr(OCP,Digits)," прибыль ",DoubleToStr(OrderProfit(),2));
}  }
//+------------------------------------------------------------------+

Если добавить в него пару строк, то получится то, что Вам нужно.
Удачи!
 

machzelet

Почетный гражданин
Ой, плин, торможу!
Мне нужно именно то, что просит девушка в первом посте, только не сумма лоссов, а после каждой сделки, закрытой по лосю, чтоб высчитывался лот, необходимый для покрытия лося. Профит у мну тоже стабильный.
 

machzelet

Почетный гражданин
cmillion,
Можете, пожалуйста, глянуть, что я не так делаю? Уже голову сломал над этим кодом ((
Цель - после закрытия ордера по стоп-лоссу, открылся ордер с увеличенным лотом в противоположную сторону, а в сторону стоп-лосса открылся ордер с нормальным лотом.
Что-то код совсем не хочет признавать ордера закрывшиеся по стоп-лоссу.
Заранее благодарю.
С уважением, Евгений.
 

cmillion

Гуру форума
cmillion,
Можете, пожалуйста, глянуть, что я не так делаю? Уже голову сломал над этим кодом ((
Цель - после закрытия ордера по стоп-лоссу, открылся ордер с увеличенным лотом в противоположную сторону, а в сторону стоп-лосса открылся ордер с нормальным лотом.
Что-то код совсем не хочет признавать ордера закрывшиеся по стоп-лоссу.
Заранее благодарю.
С уважением, Евгений.

Мне к сожалению некогда посмотреть, но Вы можете посмотреть мои советники, например _http://codebase.mql4.com/ru/6341 Советник из 10 строк "Неваляшка" В нем Вы возможно найти ответ на свой вопрос.
Если не найдете, пишите [email protected]


Удачи!
 

ale002

::: __,,,^._.^,,,__ :::
machzelet, попробуйте эту функцию использовать


Код:
Expand Collapse Copy
int GetChainLength (int iMagicNumber = 0, int iOrderType = -1, string sSymbol = "", bool bSkipOne = false) {
	//	Функция определяет длину серии закрытых с прибылью (или убытком) ордеров в истории (начиная с последнего по времени)
	// 	Если iOrderType = OP_BUY - считаем ордера на покупку
	// 	Если iOrderType = OP_SELL - считаем ордера на продажу
	// 	Если iOrderType = -1 или не указан вообще - считаем серию независимо от направления ордера
	// 	Если iOrderType = 2 - смотрим тип последнего закрытого ордера, т.е. если последний был ордером на продажу - считаем ордера на продажу и наоборот
	//		Если это серия прибыльных ордеров - функция возвращает положительное число, для убыточных - отрицательное
	int
		iChainLength = 0, // счётчик серии
		iProfit = 0 // переменная для определения прибыльная это или убыточная серия
	;
	for(int iOrder = OrdersHistoryTotal(); iOrder > 0; iOrder--) { // пробег по истории от последнего (по времени закрытия) к первому
		if(OrderSelect(iOrder, SELECT_BY_POS, MODE_HISTORY)) {
			if(
				(sSymbol == "" || OrderSymbol() == sSymbol) // если пара не задана или совпадает с искомой
				&& (iMagicNumber == 0 || OrderMagicNumber() == iMagicNumber) // и мэджик не задан или совпадает с искомым
				&& OrderType() < 2 // и это был ордер BUY или SELL
			) {
				if(iOrderType == 2) iOrderType = OrderType(); // если тип ордеров = "по последнему" - дальше будем считать, что ищем именно этот тип ордеров
				if(!bSkipOne) { // если пропускать этот ордер не нужно
					if(iProfit == 0) { // если это первый ордер серии - определим прибыльна она или убыточна
						if(OrderProfit() < 0) iProfit = -1; // серия убыточна
						else iProfit = 1; // серия не убыточна
					}
					if(
						(iOrderType == -1 || iOrderType == OrderType()) // это тот тип ордеров, которые считаем
						&& ( // и это тот тип прибыли или убытка, которые считаем
							(OrderProfit() < 0 && iProfit < 0)
							|| (OrderProfit() >= 0 && iProfit > 0)
						)) {
							iChainLength += iProfit; // увеличим (для убыточной серии) или уменьшим (для прибыльной) счётчик серии
						}
					else return(iChainLength); // если не совпала прибыльность или тип ордера - значит серия закончилась, заканчиваем и подсчёт, возвращаем результат
				}
				else bSkipOne = false; // следующий пропускать не нужно
			}
		}
	}
	// если работа функции дошла до этой строки - история закончилась
	return(iChainLength); // возвращаем счётчик
}

Вот для образца кусок кода из моего советника, где она вызывается:

Код:
Expand Collapse Copy
dLotVolume = glo.dFixedLots;
if(glo.sProfitFactor != "" || glo.sLossFactor != "") { // если заданы множители лотов для прибыльных или убыточных серий
iChainLength = GetChainLength(glo.iMagicNumber); // посчитаем длину серии закрытых ордеров
if(iChainLength > 0 && iChainLength < ArraySize(glo.adProfitFactor)) dLotVolume = glo.dFixedLots * glo.adProfitFactor[iChainLength - 1]; // лот с учётом длины серии прибыльных сделок
if(iChainLength < 0 && -iChainLength < ArraySize(glo.adLossFactor)) dLotVolume = glo.dFixedLots * glo.adLossFactor[-iChainLength - 1]; // лот с учётом длины серии убыточных сделок
}
dLotVolume = GetLotVolume(sSymbol, dLotVolume); // уточним допустимый размер лота

GetLotVolume - это др функция, котор приводит рассчитанный лот в соотв с требованиями брокера. В вашем советнике её сильно упрощённый аналог - CalculateMM()
 

machzelet

Почетный гражданин
ale002, спасибо... но мне нужно нечто иное.
Меня интересует функция, проверяющая последний закрывшийся ордер. И если последний ордер закрыт по стоп-лоссу, то выполняются действия Х. Если последний ордер закрыт по профиту, то выполняются действия У.
Довольно просто, но почему-то у мну не получается вызвать функцию последнего закрывшегося ордера.

double OCP;
int i=OrdersTotal()-1;
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
{
OCP=OrderClosePrice();
if (OCP==OrderStopLoss()) k=x*y;
if (OCP==OrderTakeProfit()) k=x/y;

В таком виде советник не желает принимать функцию, он просто напросто не предпринимает никаких действий.

Вот и хотелось бы подсказки, что я делаю не так.
 

cmillion

Гуру форума
ale002, спасибо... но мне нужно нечто иное.
Меня интересует функция, проверяющая последний закрывшийся ордер. И если последний ордер закрыт по стоп-лоссу, то выполняются действия Х. Если последний ордер закрыт по профиту, то выполняются действия У.
Довольно просто, но почему-то у мну не получается вызвать функцию последнего закрывшегося ордера.

double OCP;
int i=OrdersTotal()-1;
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
{
OCP=OrderClosePrice();
if (OCP==OrderStopLoss()) k=x*y;
if (OCP==OrderTakeProfit()) k=x/y;

В таком виде советник не желает принимать функцию, он просто напросто не предпринимает никаких действий.

Вот и хотелось бы подсказки, что я делаю не так.

Для вызова этой функции, Вам необходимо определить, что ордер закрылся. Например так:
PHP:
Expand Collapse Copy
int Orders;
//+------------------------------------------------------------------+
int start()
  {
   if (Orders>OrdersTotal()) ВАША_ФУНКЦИЯ();
   Orders=OrdersTotal();
   return(0);
  }
 

machzelet

Почетный гражданин
Вот кусок кода, где идет сравнение - закрылся ордер по профиту или по стоп-лоссу. Далее идет переход к функции set_kLots_sell или set_kLots_buy, если сравнение верно.

Код:
Expand Collapse Copy
for (int i=OrdersTotal()-1; i>=0; i--)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) break;
      if (OrderSymbol()!=Symbol()) continue;
      if (OrderType()!=OP_BUY && OrderType()!=OP_SELL) continue;
      if (OrderProfit()>0) continue;
         {
         OCP=OrderClosePrice();
         if (OrderType()==OP_BUY)
            { if (OCP==OrderStopLoss()) set_kLots_sell=1; }
         if (OrderType()==OP_SELL)
            { if (OCP==OrderStopLoss()) set_kLots_buy =1; }
         }
      }

Или так тоже пробовал...

Код:
Expand Collapse Copy
for (int i=OrdersTotal()-1; i>=0; i--)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) break;
      if (OrderSymbol()!=Symbol()) continue;
      if (OrderType()!=OP_BUY && OrderType()!=OP_SELL) continue;
      if (OrderProfit()>0) continue;
         {
         if (OrderType()==OP_BUY) set_kLots_sell=1;
         if (OrderType()==OP_SELL) set_kLots_buy =1;
         }
      }

Но ни так ни сяк не выходит. Знаю, что мну сейчас закидают шапками и помидорами, но я чайник и только учусь. Очень надеюсь на вашу помощь.
 

cmillion

Гуру форума
Но ни так ни сяк не выходит.

PHP:
Expand Collapse Copy
int Orders;
//+------------------------------------------------------------------+
int start()
  {
   string tip;
   if (Orders>OrdersTotal()) tip=LastOrder();
   Orders=OrdersTotal();
   if (tip=="SL")
   {
      Comment("Ордер закрылся по SL");
   }
   if (tip=="TP")
   {
      Comment("Ордер закрылся по TP");
   }
   return(0);
  }
//+------------------------------------------------------------------+
string LastOrder()
{
   double OCP;
   int i=OrdersHistoryTotal()-1;
   if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
   {                                     
      OCP=OrderClosePrice();
      if (OCP==OrderStopLoss()  ) return("SL");
      if (OCP==OrderTakeProfit()) return("TP");
   }  
   return("");
}
//+------------------------------------------------------------------+
 

machzelet

Почетный гражданин
Ребят, простите, но "моя твоя не понимать". ((
Решил привести наглядный пример "что, где и куда".
Вот полный код советника:

Код:
Expand Collapse Copy
extern int StartHour=15;               // Время открытия ордеров
extern int TimeZone=0;                 // Временная зона
extern int OrderExpirationDays=3;      // Срок жизни ордера в днях, если он не закрылся по стопу или профиту
extern int TakeProfit=14;              // Желаемая прибыль
extern int CurrencyFactor=37;          // Валютный коэффициент
extern double Lots=0.01;               // Величина лота
extern double RiskPercentLoss=30;      // Процент максимального убытка от депозита на один ордер
extern bool RiskMM=true;               // Мани Менеджмент
extern double RiskPercentMM=10;        // Процент риска


int set_buy=0;
int set_sell=0;
int StopLoss, LotFactor;
double kLots;

void start()
   {
   if (Bars<100 || IsTradeAllowed()==false) return;
   if (TimeZone<-23 || TimeZone>23) return;
   TestOrderExpirationDays();
   int hour=Hour()-TimeZone;
   if (DayOfWeek()>=1 && DayOfWeek()<=5 && hour==StartHour)
      {
      if (set_buy==0 && TotalBuy()==0) { if (OpenBuy()>0) {set_buy=1; return;} }
      if (set_sell==0 && TotalSell()==0) { if (OpenSell()>0) {set_sell=1; return;} }
      }
   else
      {
      set_buy=0;
      set_sell=0;
      }
   }

void TestOrderExpirationDays()
   {   
   if(RiskMM)CalculateMM();   
   int set_double_buy =0;
   int set_double_sell=0;
   int ticket, slippage;
   double loss, profit;
   
   for (int i=OrdersTotal()-1; i>=0; i--)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderSymbol()!=Symbol()) continue;
      if (OrderType()!=OP_BUY && OrderType()!=OP_SELL) continue;
      [COLOR="Red"]if (CurTime()-OrderOpenTime()<=86400*OrderExpirationDays) continue;
         {
         if (OrderType()==OP_BUY )
            { if (OrderClose(OrderTicket(),OrderLots(),Bid,slippage)) set_double_buy=1; }
         if (OrderType()==OP_SELL)
            { if (OrderClose(OrderTicket(),OrderLots(),Ask,slippage)) set_double_sell=1; }
         }[/COLOR]
      }
      
      kLots=(Lots*RiskPercentMM)/3;
      LotFactor=Lots*100;
      StopLoss=(AccountBalance()*RiskPercentLoss)/(CurrencyFactor*LotFactor);
     

     
      
   [COLOR="Blue"]if (set_double_buy>0)
      {
      slippage=2;
      loss=0; if (StopLoss>0) loss=Ask-StopLoss*Point;
      profit=0; if (TakeProfit>0) profit=Ask+TakeProfit*Point;
      ticket=OrderSend(Symbol(),OP_BUY,kLots*Lots,Ask,slippage,loss,profit,"",0,0);
      if (ticket>0) set_buy=0;
      else Print("Open a order failed with error #",GetLastError());
      }
   if (set_double_sell>0)
      {
      slippage=2;
      loss=0; if (StopLoss>0) loss=Bid+StopLoss*Point;
      profit=0; if (TakeProfit>0) profit=Bid-TakeProfit*Point;
      ticket=OrderSend(Symbol(),OP_SELL,kLots*Lots,Bid,slippage,loss,profit,"",0,0);
      if (ticket>0) set_sell=0;
      else Print("Open a order failed with error #",GetLastError());
      }[/COLOR]
   }

   int OpenBuy()
   {
   int slippage=2;
   double loss=0; if (StopLoss>0) loss=Ask-StopLoss*Point;
   double profit=0; if (TakeProfit>0) profit=Ask+TakeProfit*Point;
   int ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,slippage,loss,profit,"",0,0);
   if (ticket==0) Print("Open a order failed with error #",GetLastError());
   return (ticket);
   }

   int OpenSell()
   {
   int slippage=2;
   double loss=0; if (StopLoss>0) loss=Bid+StopLoss*Point;
   double profit=0; if (TakeProfit>0) profit=Bid-TakeProfit*Point;
   int ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,slippage,loss,profit,"",0,0);
   if (ticket==0) Print("Open a order failed with error #",GetLastError());
   return (ticket);
   }

   int TotalBuy()
   {
   int count=0;
   for (int i=0; i<OrdersTotal(); i++)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderSymbol()==Symbol() && OrderType()==OP_BUY) count++;
      }
   return (count);
   }

   int TotalSell()
   {
   int count=0;
   for (int i=0; i<OrdersTotal(); i++)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if (OrderSymbol()==Symbol() && OrderType()==OP_SELL) count++;
      }
   return (count);
   }



//+------------------------------------------------------------------+
//| Money Management                                                 |
//+------------------------------------------------------------------+

void CalculateMM()
{
   double MinLots=MarketInfo(Symbol(),MODE_MINLOT);
   double MaxLots=MarketInfo(Symbol(),MODE_MAXLOT);
   Lots=AccountFreeMargin()/100000*RiskPercentMM;
   Lots=MathMin(MaxLots,MathMax(MinLots,Lots));
   if(MinLots<0.1)Lots=NormalizeDouble(Lots,2);
   else
   {
     if(MinLots<1)Lots=NormalizeDouble(Lots,1);
     else Lots=NormalizeDouble(Lots,0);
   }
   if(Lots<MinLots)Lots=MinLots;
   if(Lots>MaxLots)Lots=MaxLots;
   return(0);
}

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

Красным выделен кусок, который проверяет время открытия ордера и по истечении 3 дней закрывает его, если тот не закрылся по профиту. После чего переходит к куску кода синего цвета.

Моя цель - заменить красный кусок кода на проверку закрытия ордера по стоп-лоссу, и если ордер действительно закрылся по стоп-лоссу, а не по профиту, тогда перейти к куску кода синего цвета.

Я перепробовал массу разных вариантов, но советник категорически отказывается замечать кусок кода синего цвета.
То есть, вместо открытия нового ордера в сторону стоп-лосса с увеличеным лотом он продолжает открывать ордера с нормальным лотом. ((

Помогите, плиз, домучать.
 

cmillion

Гуру форума
Ребят, простите, но "моя твоя не понимать". ((
Помогите, плиз, домучать.

У Вас принципиально не правильная постановка задачи.
Если Вы хотите при закрытии ордера открывать ордер в ту или иную сторону, в зависимости от закрытия по СЛ или ТП, то Вам не надо закрывать ордера принудительно по времени, т.к. они будут закрыты по текушей цене, а не по стопам.
Далее, если Вы все же закрываете ордера принудительно, то необходимо определить с прибылью или с убытком они закрылись и от этого назначать переменным set_double_buy и set_double_sell их значения. Например:
PHP:
Expand Collapse Copy
if (OrderType()==OP_BUY )
{
   if (OrderProfit()>0) set_double_buy=1; 
   else set_double_buy=0;
   OrderClose(OrderTicket(),OrderLots(),Bid,slippage)
}
Если Вы все же хотите анализировать уже закрытые ордера, то воспользуйтесь текстом программы из моего предыдущего поста.
Удачи!
 
Верх