Любой вопрос новичка, чтоб не захламлять форум. Профи, не проходите мимо. Без вас никуда - 6. - страница 103

 
hoz:

Если 7.43 и не ложился.. Значится, предположу, что пишется грааль!

Не, зачем так ругаться :)) Грааль мне Юсуф наворожил. Сижу на чемоданах, жду манну небесную, на Мальдивы поеду :))

 
artmedia70:
Ну так показывайте чего вы там понаделали... Телепатов тут нет - в отпуске они.

extern string time1 = "n";// 
extern string time2="m";
extern double lot=0.2;// объявили лот
extern int slippage=2;// объявили макс отклонение от цены





int start()
{
double max;// максимальная цена 6-ти свечей
double min;// минимальная цена 6-ти свечей
int hour1 = TimeHour(StrToTime(time1)); // время часы
int minute1 = TimeMinute(StrToTime(time1));// время минуты


if (hour1 == TimeHour(TimeCurrent()) && minute1 == TimeMinute(TimeCurrent()))// если время подошло то
{
min=Low[iLowest(Symbol(),0,MODE_LOW,6,1)]; // вычисляем минимальную цену последних 6 свечей
max=High[iHighest(Symbol(),0,MODE_HIGH,6,1)]; // вычисляем максимальную цену последних 6 свечей
double volum=max-min;// общий объем локалки последних 6 свечей М5
 int ticket1=-1;
 int ticket2=-1;
if ((volum<=0.0018)==true)// если объем свечей меньше или равно z пунктов 

if (ticket1<0)
{ 
OrderSend ( Symbol (), OP_BUYSTOP, lot,max+Point,3,min-Point,max+0.0022, NULL,0,time2, Red);
Alert(GetLastError());
}
if(ticket2<0)
{
OrderSend( Symbol (), OP_SELLSTOP, lot,min-Point,3,max+Point,min-0.0022, NULL,0,time2, Yellow);
Alert(GetLastError());
}


return;


if (OrderSelect(1,SELECT_BY_POS,MODE_HISTORY)) ///если первый открытый ордер закрылся с профитом 
if(OrderProfit()>0)
{
OrderDelete(OrderTicket());// удаляем второй отложенный
}

}



bool closeorder;//определим переменную закрытия ордеров
closeorder=true;

if (closeorder==true)// вечернее закрытие всех отложенных ордеров, и рыночных позиций
{
int hour2 = TimeHour(StrToTime(time2));// вычисляем время закрытия ордеров
int minute2 = TimeMinute(StrToTime(time2));

if (hour2 == TimeHour(TimeCurrent()) && minute2 == TimeMinute(TimeCurrent()))// если время ***
{// определяем количество открытых позиций, и отложенных ордеров
for(int i=OrdersTotal()-1; i>=0; i--)
 if (OrderSelect(1,SELECT_BY_POS,MODE_TRADES))break; //определяем место где будем искать ( рабочие позиции)
if (OrderType()==OP_BUY ) OrderClose (OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),slippage);// Закрытие ордера бай если такой есть
if (OrderType()==OP_SELL) OrderClose (OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),slippage);//Закрытие ордера селл если такой есть
if (OrderType()==OP_BUYSTOP)
{ 
OrderDelete(OrderTicket()); //удаляем отложенный байстоп
}                    
if(OrderType()==OP_SELLSTOP)
{ 
OrderDelete(OrderTicket()); //удаляем отложенный sellstop
}                    

Кинул общий код советника, чтобы было более понятно что он должен делать..Знаю что в коде безобразие, но пока по другому не научился=)))
Скажу еще раз где он тупит
открытие отложенника: открывает или один отложенник без противоположного, или целую кучу отложенников в одном направлении.
Удаление ордеров: удаляет через раз, иногда нормально без проблем вечером в четко указанное время, а иногда через день, или совсем не закрывает..

Ну а условие :
Если первый открытый отложенный закрывается с профитом, то второй удаляем сразу же - тоже сомневаюсь что правильно написал, но проверить не могу в работе, так как не хочет открывать две противоположных позиции=(((((
 
artmedia70:
При поиске последнего закрытого, сначала нужно найти самый последний закрытый, а вот проверку его на закрытие по тейку нужно вынести за пределы цикла, иначе он каждый закрытый ордер проверяет на закрытие по тейку и, если да, то запоминает время первого, который в цикле попался, закрытый по тейку, а не самого последнего.


Ну это уже оптимизация кода. Результат то от этого не изменится, как я вижу. Просто дольше будет просчёт. Я всё же поправил код, но работает так же..

//+-------------------------------------------------------------------------------------+
//| Получаем состояние последней позиции (Открыта или закрыта)                          |
//+-------------------------------------------------------------------------------------+
datetime GetLastOrderState()
{
   datetime lastOrderCloseTime = -1,               // Время закрытия последнего открытого ордера
            lastOOTMarket = -1,          // Время открытия последнего открытого ордера рыночного
            lastOOTHist = -1;            // Время открытия последнего открытого ордера из истории
   
   for (int i=OrdersHistoryTotal()-1; i>=0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      if (OrderMagicNumber() != i_magic) continue;
      if (OrderSymbol() != Symbol()) continue;
      if (OrderType() > 1) continue;               // Все удалённые отложки нас не интересуют..
  
      if (lastOrderCloseTime < OrderCloseTime())   // Находим время закрытия..
          lastOrderCloseTime = OrderCloseTime();   // ..последней закрытой позиции в истории
      Comment("Время закрытия последнего ордера в истории lastOrderCloseTime = ", lastOrderCloseTime);
   }

   if (MathAbs(OrderTakeProfit() - OrderOpenPrice()) < i_tp * pt) return(0);
      Comment("OrderTakeProfit() - OrderOpenPrice() < i_tp * pt = ", MathAbs(OrderTakeProfit() - OrderOpenPrice()) < i_tp * pt);
   lastOOTHist = OrderOpenTime();   // Тогда время открытия последней закрытой позиции из истории
      Comment("Время закрытия последнего ордера в истории lastOOTHist = ", lastOOTHist);
   
      Comment("Время открытия последнего открытого ордера = ", lastOOTHist);
  
   for (int h=OrdersTotal()-1; i>=0; i--)
   {   
      if (!OrderSelect(h, SELECT_BY_POS, MODE_TRADES)) continue;
      if (OrderMagicNumber() != i_magic) continue;
      if (OrderSymbol() != Symbol()) continue;
      {
         if (lastOOTMarket < OrderOpenTime())
             lastOOTMarket = OrderOpenTime();
  
         if (lastOOTMarket < lastOOTHist)      // Если время открытия последнего открытого ордера (рыночного) ниже последнего открытого ордера из истории..
             lastOrderCloseTime = OrderCloseTime(); // Значит это искомый ордер
      }
   }

   Comment("Время закрытия последнего открытого ордера = ", lastOrderCloseTime);
   return (lastOrderCloseTime);
}

Всё же есть какой-то косяк в ней как-будто.

 
ex1m:

Кинул общий код советника, чтобы было более понятно что он должен делать..Знаю что в коде безобразие, но пока по другому не научился=)))
Скажу еще раз где он тупит
открытие отложенника: открывает или один отложенник без противоположного, или целую кучу отложенников в одном направлении.
Удаление ордеров: удаляет через раз, иногда нормально без проблем вечером в четко указанное время, а иногда через день, или совсем не закрывает..

Ну а условие :
Если первый открытый отложенный закрывается с профитом, то второй удаляем сразу же - тоже сомневаюсь что правильно написал, но проверить не могу в работе, так как не хочет открывать две противоположных позиции=(((((



Отвечу вопросом на вопрос. Это что за такое:

if ((volum<=0.0018)==true)// если объем свечей меньше или равно z пунктов 

Расшифруй мне, я не понял :)

Проверки на открытие позиции должны быть после попытки открыть позицию. Т.е.

if (ticket1<0)

Помещаешь после посыла ордера.

Что бы открыть отложку, нужно чтоб цена были выше или ниже Аска или Бида соответственно. Для бая так:

 if (OOP > Ask)
 
hoz:


Ну это уже оптимизация кода. Результат то от этого не изменится, как я вижу. Просто дольше будет просчёт. Я всё же поправил код, но работает так же..

Всё же есть какой-то косяк в ней как-будто.

Нет, это как раз не оптимизация кода. Это как раз поиск именно последнего. Как только завершили перебор всех закрытых ордеров и нашли из них самый последний закрытый, только после этого нужно его проверить на закрытие по тейку и, если да, закрыт по тейку, только тогда имеет смысл продолжать поиск остального.

Если же проверку на закрытие по тейку поместить внутрь цикла, то что мы получим? Получим ошибку логики:
Допустим, выбрали ордер, который был закрыт год назад. Его время в любом случае будет больше -1, значит проверили его на закрытие по тейку (ведь в коде внутри цикла стоит эта проверка). Ага, закрылся по тейку... Что делает дальше ваша функция? Правильно - продолжает работать с этим, год назад закрытым по тейку ордером. Ща погляжу, где там ещё ошибки. Только домой приехал...

 

Было написано: 2. Если последняя открытая позиция закроется по тейку, то закрываем всё!

Ну вот, значит как-то так:

//-----------------------------------------------------------------------------------------------+
bool isCloseByTakeLastOpenPos (string sy, int mn, int delta) {
   datetime t=0;
   int   i, k, j=-1;
   
// Сначала определим, что последняя закрытая позиция была закрыта по тейку (в пределах дельты)
   k=OrdersHistoryTotal()-1;
   for(i=k; i>=0; i--) {
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) {
         if (OrderMagicNumber()!=mn)   continue;
         if (OrderSymbol()!=sy)        continue;
         if (OrderType()>1)            continue;            // Сначала забыл вписать, подправил
         if (t<OrderCloseTime()) {t=OrderCloseTime(); j=i;}
         }
      }  
   // Нашли последнюю. Проверим её закрытие по тейку
   if (OrderSelect(j,SELECT_BY_POS,MODE_HISTORY)) {                      
      if (OrderProfit()+OrderSwap()+OrderCommission()<=0)   return(false);          // Закрыта с убытком или в ноль
      if (MathAbs(OrderTakeProfit()-OrderClosePrice())>delta*Point) return(false);  // закрыта в профите, но не в пределах дельты
      else t=OrderOpenTime();    // Если последняя закрытая была закрыта по тейку (в пределах дельты), запомним время её открытия
      }
   else {Print("FUNC isCloseByTakeLastOpenPos : не удалось выбрать ордер в истории");return(false);}
// Здесь мы имеем последнюю закрытую позицию в профите и закрытую по тейку (в пределах дельты), ищем дальше
   k=OrdersTotal()-1;
   for(i=k; i>=0; i--) {
      if (OrderSelect(i,SELECT_BY_POS)) {
         if (OrderMagicNumber()!=mn)   continue;
         if (OrderSymbol()!=sy)        continue;
         if (OrderType()>1)            continue;
         if (t<OrderOpenTime()) return(false);  // Выбранная рыночная позиция открыта позже закрытой по тейку
         }
      else {Print("FUNC isCloseByTakeLastOpenPos : не удалось выбрать рыночный ордер");return(false);}
      }
   return(true);  // Найденная закрытая по тейку позиция была открыта позже всех, возвращаем её время открытия
}
//-----------------------------------------------------------------------------------------------+

В функцию передаём символ, по которому хотим проверить, магик и дельту (расстояние в пунктах == разница между тейком ордера и ценой его закрытия), вот так например:

   if (isCloseByTakeLastOpenPos (Symbol(), Magic, 5)) { // Если последняя открытая была закрыта по тейку ...
      // ... тут обрабатываем эту ситуёвину
      }
   else {   // Иначе ...
      // тут обрабатываем, если последняя закрытая была открыта не последней или ...
      // ... последняя закрытая была закрыта с убытком или в профите, но за пределами дельты
      }

Функцию не проверял, писал на коленке. Так что поиск ошибок - за вами.

Можно сделать её int и использовать коды возврата. Например, если искомой позиции нет или есть, но закрыта в убытке вернуть -1,
если есть и закрыта с профитом, но не в пределах дельты, то вернуть 0;
если есть и закрыта с профитом и по тейку (в пределах дельты), то вернуть 1...

Простор для фантазии огромен...

 
artmedia70:

Если же проверку на закрытие по тейку поместить внутрь цикла, то что мы получим? Получим ошибку логики:

Допустим, выбрали ордер, который был закрыт год назад. Его время в любом случае будет больше -1, значит проверили его на закрытие по тейку (ведь в коде внутри цикла стоит эта проверка). Ага, закрылся по тейку..


Так если цикл по всем ордерам, то по-любому цикл прошерстит все ордера. Будет сравниваться время закрытия каждого ордера, с предыдущим выбранным. Только тут выходит косяк с производительностью. Т.к. тейкпрофит будет проверяться в цикле постоянно, у каждой закрытой позиции, а не только у последней. Ведь так !?
 
PapaYozh:

Так.

Но есть Open[], с ценой открытия.


Понял, благодарю :)
 
hoz:

Так если цикл по всем ордерам, то по-любому цикл прошерстит все ордера. Будет сравниваться время закрытия каждого ордера, с предыдущим выбранным. Только тут выходит косяк с производительностью. Т.к. тейкпрофит будет проверяться в цикле постоянно, у каждой закрытой позиции, а не только у последней. Ведь так !?
Я уже написал пример функции.
 
hoz:

Так если цикл по всем ордерам, то по-любому цикл прошерстит все ордера. Будет сравниваться время закрытия каждого ордера, с предыдущим выбранным. Только тут выходит косяк с производительностью. Т.к. тейкпрофит будет проверяться в цикле постоянно, у каждой закрытой позиции, а не только у последней. Ведь так !?

Вот косяк:

   for (int i=OrdersHistoryTotal()-1; i>=0; i--)
   {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      if (OrderMagicNumber() != i_magic) continue;
      if (OrderSymbol() != Symbol()) continue;
      if (OrderType() > 1) continue;               // Все удалённые отложки нас не интересуют.. 
  
      if (lastOrderCloseTime < OrderCloseTime())   // Находим время закрытия..
          lastOrderCloseTime = OrderCloseTime();   // ..последней закрытой позиции в истории
      
      if (MathAbs(OrderTakeProfit() - OrderOpenPrice()) < i_tp * pt) return(0); // ЗДЕСЬ ВЫХОДИМ ПРИ ПЕРВОМ ВСТРЕЧНОМ
      
      lastOOTHist = OrderOpenTime();   // Тогда время открытия последней закрытой позиции из истории
   }
Причина обращения: