Обучение языку MQL4 под MetaTrader 4📌

От xbms, 13 апреля, 2013 в Уголок Программиста

#5976

@Владимир Стариков  понятно. криво написанная панель.  

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

#5977

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

Спойлер

datetime FindLastTimeBuy()
  {
   datetime otime,time_buy=D'1980.07.19 12:30:27';
   for(int m=OrdersTotal()-1; m>=0;m--)
     {
      if(OrderSelect(m,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic_buy)
           {
            if(OrderType()==OP_BUY)
              {
               otime=OrderOpenTime();
               if(otime>time_buy)
                 {
                  time_buy=otime;
                 }
              }
           }
        }
     }
   return(time_buy);
  }

И я так понимаю последнее значение у цикла попадет в переменную time_buy ? Но мне кажется наверное надо не с конца цикл прогонять а с начала тогда.

#5978
10 часов назад, diodio сказал:

мне интересно в каком формате записать первоначальную дату для сравнения.

можно  начальное значение значение time_buy задать = 0. Если ордер BUY есть в рынке, то его время в любом случае будет >0.
Только нужно будет обрабатывать нулевое значение, которое вернет Ваша функция в случае, если ордеров БАЙ в рынке нет.
Направление сканирования рыночных ордеров значение не имеет.

 

 

#5979

Всем привет, скажите правильно ли я заполнил массив:

Спойлер

//+---------------------Профит уже закрытых ордеров на продажу----------------------+
void OrderProfitSellClose()
  {
   int counter=0,size=OrdersHistoryTotal();
   ArrayResize(cSellProfitClose,size);
   for(int i=OrdersHistoryTotal()-1; i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
        {
         if(OrderSymbol()==Symbol()&& OrderMagicNumber()==Magic_sell)
           {
            if(OrderType()==OP_SELL)
              {
               cSellProfitClose=OrderProfit()+OrderCommission()+OrderSwap();
               counter++;
              }
           }
        }
     }
   ArrayResize(cSellProfitClose,counter);
   return;
  }

Должно получиться что в каждой ячейке массива cSellProfitClose будет лежать какая-то цифра. Массив динамический, ну это уже понятно.

Далее я например хочу суммировать эти данные с этого массива путем перебора через цикл:

Спойлер

for(int z=ArraySize(cSellProfitClose)-1;  z>=0; z--)
           {
               SellProfitClose+=cSellProfitClose[z];
           }

Верно иду?

Кстати usver73 спасибо.

#5980
2 часа назад, diodio сказал:

Верно иду?

в тестере не проверял, но по теории все верно,раз нет ошибок

#5981
16 часов назад, diodio сказал:

Верно иду?

А я не понял смысла всех телодвижений...
 

 cSellProfitClose=OrderProfit()+OrderCommission()+OrderSwap();

будет ошибка- нет cSellProfitClose[]  c индексом массива.
Далее: массиву определяется размер в количестве ордеров в истории, а после выборки всех СЕЛЛ- ордеров идет резайз, причем скорее всего в меньшую сторону..
Какую часть массива эта команда обрежет?
тогда уж так:
 

ArrayResize(cSellProfitClose,counter+1);              
cSellProfitClose[counter]=OrderProfit()+OrderCommission()+OrderSwap();
counter++;

И вообще- в чем смысл иметь массив из определенных исторических ордеров? Если целей несколько, то, наверно, имеет смысл их копировать в массив. А если цель одна- посчитать профит, так это лучше сразу делать в цикле по истории.. ИМХО.

#5982
7 часов назад, usver73 сказал:

А я не понял смысла всех телодвижений...

Хотелось бы посмотреть как будет вести себя сов при определенном условии. А условие такое, должен закрывать просадочные ордера путем встречной сетки, которая набирает профит. Ну и исходя из этого я решил все запихнуть в массивы. Причем просадочные ордера какой-либо сетки закрываться должны отталкиваясь от последнего выставленного ордера этой просадочной сетки, ну т.е. сейчас немного подробнее, допустим просадка сетки по бай, и она тянется уже длительное время, в то время как селл зарабатывает, вот мы и берем весь профит селл закрытых ордеров, которые открылись после последнего открытого ордера на бай и сравниваем этот профит с суммой просадки и начинаем частично закрывать просадку. 

Вот такое условие идет:

Спойлер

LastTimeBuy = FindLastTimeBuy();
         OrderProfitSellClose();// Профит уже закрытых ордеров на продажу
         OrderTimeSell(); // Время открытия ордеров на продажу

         for(int z=ArraySize(cTimeSellOpen)-1; z>=0;z--)
           {
            if(cTimeSellOpen[z] > LastTimeBuy)
              {
               SellProfitClose+=cSellProfitClose[z];
              }
           }
         OrderProfitBuy(); // Профит еще не закрытых ордеров на покупку
         for(int t=ArraySize(cBuyProfitOpen)-1; t>=0;t--)
           {
            BuyProfitOpen+=cBuyProfitOpen[t];
            if(MathAbs(BuyProfitOpen) <= SellProfitClose)
              {
               if(OrderType() == OP_BUY)
                  bool close_profit_buy = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage);
              }
           }

//------------------ФУНКЦИИ---------------------------------

 

//+---------------------Функция находит последнее время ордера который выставился на покупку но еще сетка не закрыта--------------------+
datetime FindLastTimeBuy()
  {
   datetime otime,time_buy=0;
   for(int m=OrdersTotal()-1; m>=0;m--)
     {
      if(OrderSelect(m,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic_buy)
           {
            if(OrderType()==OP_BUY)
              {
               otime=OrderOpenTime();
               if(otime>time_buy)
                 {
                  time_buy=otime;
                 }
              }
           }
        }
     }
   return(time_buy);
  }

//+---------------------Профит уже закрытых ордеров на продажу----------------------+
void OrderProfitSellClose()
  {
   int counter=0,size=OrdersHistoryTotal();
   ArrayResize(cSellProfitClose,size);
   for(int i=OrdersHistoryTotal()-1; i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
        {
         if(OrderSymbol()==Symbol()&& OrderMagicNumber()==Magic_sell)
           {
            if(OrderType()==OP_SELL)
              {
               cSellProfitClose=OrderProfit();
               counter++;
              }
           }
        }
     }
   ArrayResize(cSellProfitClose,counter);
   return;
  }

 

//+---------------------Время открытия ордеров на продажу----------------------+
void OrderTimeSell()
  {
   int counter=0,size=OrdersTotal();
   ArrayResize(cTimeSellOpen,size);
   for(int i=OrdersTotal()-1; i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
        {
         if(OrderSymbol()==Symbol()&& OrderMagicNumber()==Magic_sell)
           {
            if(OrderType()==OP_SELL)
              {
               cTimeSellOpen=OrderOpenTime();
               counter++;
              }
           }
        }
     }
   ArrayResize(cTimeSellOpen,counter);
   return;
  }

 

//+---------------------Профит еще не закрытых ордеров на покупку----------------------+
void OrderProfitBuy()
  {
   int counter=0,size=OrdersHistoryTotal();
   ArrayResize(cBuyProfitOpen,size);
   for(int i=OrdersTotal()-1; i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
        {
         if(OrderSymbol()==Symbol()&& OrderMagicNumber()==Magic_buy)
           {
            if(OrderType()==OP_BUY)
              {
               cBuyProfitOpen=OrderProfit()+OrderCommission()+OrderSwap();
               counter++;
              }
           }
        }
     }
   ArrayResize(cBuyProfitOpen,counter);
   return;
  }

Сделал условие по времени открытия. Здесь на этом моменте решил проверить работоспособность и не сработало. Далее поставлю условие на участие определенных ордеров в закрытии, но это будет после. Хотя бы это должно работать, смысл пока идти дальше нет. Ну и где ошибка?)

#5983
Только что, diodio сказал:

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

Давайте разделим задачу на чисто код и логику.
Во-первых- Вы не объявляете массивы (хотя, возможно, они на глобальном уровне объявлены).
Во-вторых, когда Вы пишете в них информацию, то пишете с ошибкой синтаксиса- должно быть указание на ИНДЕКС массива в [] после имени.
В третьих- если Вам нужно одно значение- сумма профита исторических ордеров, время последнего ордера и т.д., то массивы вообще не нужны- объявляете переменную нужного типа и в цикле либо к ней прибавляете (расчет профита), либо проверяете ее значение (время крайнего ордера)..

По логике:
Если Вы все таки хотите решить несколько задач, связанных, например, с историческими ордерами, то логично в массивы писать ВСЮ нужную информацию (профит, время открытия/закрытия, цены открытия/закрытия и т.п). Тогда нужно объявлять структуру (F1) и объявлять, соответственно, массив структур.

#5984
9 минут назад, diodio сказал:

OrderProfitSellClose();// Профит уже закрытых ордеров на продажу

Функция не возвращает значение. Предполагаем, что внутри нее происходят вычисления и результат присваивается некоей переменной, объявленной на глобальном уровне..
Но по факту Вы получите значение первого(?) по времени закрытого СЕЛЛ ордера. 
Про массив я писал.
Про СУММУ СЕЛЛ ордеров вроде тоже.
Еще момент- у Вас нет ограничения по глубине истории, т.е. в данной реализации Вы будете считать ВСЮ историю закрытых СЕЛЛ ордеров.

16 минут назад, diodio сказал:

 OrderTimeSell(); // Время открытия ордеров на продажу

Та же фигня- Вы получите время первого закрытого ордера СЕЛЛ.

#5985

@diodio Вам @usver73 намекает, что решать такую задачу (непростую) и одновременно заниматься обслуживанием массива не очень разумно, тем более значения профита/убытка меняется на каждом тике и всё-равно нужно гонять цикл пересчёта ордеров, точного совпадения убытка и профита ордеров не будет, надо учитывать нереализованный профит при их совместном закрытии и т.д. - куча проблем, но есть и положительный момент - опыт Вы получите бесценный...

От Вас нужно чёткое понимание зачем (это делать, ведь просадка это бензин сетки) и как (алгоритм).

Много лет назад мне тоже это показалось ценной идеей и алгоритм был такой (насколько помню):

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

Делал это однократно, т.к. больше профита не хватало... 

#5986

Всем привет.

22 часа назад, usver73 сказал:

Во-первых- Вы не объявляете массивы (хотя, возможно, они на глобальном уровне объявлены).

По поводу массивов, они объявлены на глобальном уровне:

Спойлер

datetime cTimeBuyOpen[100], cTimeSellOpen[100], cTimeSellClose[100],cTimeBuyClose[100];
double   cBuyProfitOpen[100], cSellProfitOpen[100],cBuyProfitClose[100], cSellProfitClose[100];

Я даже им размер поставил.

 

22 часа назад, usver73 сказал:

Во-вторых, когда Вы пишете в них информацию, то пишете с ошибкой синтаксиса- должно быть указание на ИНДЕКС массива в [] после имени.

Далее я заполняю, их через цикл в функции: cSellProfitClose(i)=OrderProfit(); я тут поставил круглые скобки

где i и является тем индексом которая присутствует в цикле и в номере ячейки массива.

 

22 часа назад, usver73 сказал:

Но по факту Вы получите значение первого(?) по времени закрытого СЕЛЛ ордера. 

Я по факту хочу просто заполнить массив в самой функции путем цикла. Мне не нужно значение первого там или последнего ордера. 

Заполнен массив, который объявлен на глобальном уровне, далее я его кручу как хочу. Или я чего-то уже не понимаю. Разве не так заполняются массивы как я показал?

Ну и собственно к чему все эти движения?! Массивы были нужны для того чтоб я в них мог менять значения, а именно те значения, которые участвовали в переборе и закрывались допустим всей суммой просадку. Если говорить по-простому, то я хочу обнулить эти значения, не все, а только те, которые помогли закрыть просадку. Хотел это сделать вот таким путём:

Спойлер

for(int z=0; z < ArraySize(cTicketSellClose); z++)
                    {
                     if(cTicketSellClose[z] > LastTicketBuy)
                               
                        for(int b=0; b < ArraySize(cSellProfitClose); b++)
                          {
                           cSellProfitClose=+SellProfitClose;

                           OrderProfitBuy(cBuyProfitOpen); // Профит еще не закрытых ордеров на покупку
                           for(int t=0; t < ArraySize(cBuyProfitOpen); t++)
                             {
                              cBuyProfitOpen[t]=+BuyProfitOpen;
                              if(MathAbs(BuyProfitOpen) <= SellProfitClose)
                                {
                                 if(OrderType() == OP_BUY)
                                    bool close_profit_buy = OrderClose(OrderTicket(), OrderLots(), Bid, Slippage);
                                 for(int n=0; n < b; n++)
                                   {
                                    cSellProfitClose[n] = 0;
                                   }
                                    ArrayCopy(cSellProfitClose,cSellProfitClose,0,WHOLE_ARRAY);
                                    ArrayResize(cSellProfitClose, ArraySize(cSellProfitClose));
                                }
                             }
                          }
                       }

 

Изменено 24 июня, 2020 пользователем diodio

#5987
В 24.06.2020 в 21:23, diodio сказал:

Далее я заполняю, их через цикл в функции: cSellProfitClose(i)=OrderProfit(); я тут поставил круглые скобки

где i и является тем индексом которая присутствует в цикле и в номере ячейки массива.

Блин, или я чего-то не знаю, либо Вы не читаете, то, что пишут... Почему КРУГЛЫЕ скобки в массиве cSellProfitClose(i)?
Далее по функции OrderProfitSellClose();// Профит уже закрытых ордеров на продажу:
 

Спойлер

//+---------------------Профит уже закрытых ордеров на продажу----------------------+
void OrderProfitSellClose()
  {
   int counter=0,size=OrdersHistoryTotal();
   ArrayResize(cSellProfitClose,size); // устанавливаем размер массива по количеству ордеров в истории, допустим 1000
   for(int i=OrdersHistoryTotal()-1; i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
        {
         if(OrderSymbol()==Symbol()&& OrderMagicNumber()==Magic_sell)
           {
            if(OrderType()==OP_SELL)
              {
               cSellProfitClose=OrderProfit(); // если здесь будет исправлена ошибка и будет записано cSellProfitClose[i], то массив будет заполняться с "дырками"
               counter++;
              }
           }
        }
     }
   ArrayResize(cSellProfitClose,counter); // здесь мы обрежем примерно половину массива
   return;
  }

 

Про синтаксическую ошибку написал в комментарии.
По логике: Вы сканируете всю историю и выбираете только СЕЛЛ ордера. Но значения профита в массив пишутся не подряд, а так, как ордера СЕЛЛ в истории записаны. Будет примерно так:
1.0$
0.5$
0.0$
0.0$
-0.3$  и т.д.
т.е. там, где 0.0$ скорее всего были БАЙ-ордера.
Далее Вы уменьшаете размер массива до количества найденных СЕЛЛ ордеров. В примере- 3 шт.
В остатке массив будет содержать:
1.0$
0.5$
0.0$
Дальше вся Ваша логика летит в топку. Как сделать правильно- я писал ранее..
По вопросу, который осветил 0ll :
Сканировать на каждом тике (или с каким-то периодом- не важно) историю, да еще раздельно для БАЙ и СЕЛЛ как-то... неразумно. Терем просто умрет на каком-то этапе
Если количество ордеров в рынке конечно (даже если это сетка), то в истории их будет со временем ооочень много.. 
И нафига Вам ВСЕ исторические ордера? Скорее всего нужны последние сетки или еще-что-то.

if(cTicketSellClose[z] > LastTicketBuy)

 

Изменено 28 июня, 2020 пользователем usver73

#5989

Здравствуйте!

 

Осваиваю программирование на MQL4, пока дилетант. Написал несложный советник, прогнал в тестере.

Проблема такая - каждый новый бар (на Д1) советник должен открывать новые отложенные ордера. И в тестере все хорошо на истории, открывает.

А в реале приходится перезапускать терминал. После перезапуска сразу открывает, а просто при появлении новой свечки - нет.

Не могу понять, в чем может быть проблема. Счет - Альпари PRO.ecn

#5990
В 01.07.2020 в 20:42, Ill333 сказал:

И в тестере все хорошо на истории, открывает.

А в реале приходится перезапускать терминал.

Нужно вести лог при помощи Print(...), так можно будет понять что происходит.

#5991

Ребят, пишу советник на базе индикатора ТМА, уже тестирую простенький. Но есть еще задумка заложить в советник элементы теории вероятности.

Не получается создать цикл, уже всю голову сломал.

 

Суть такова:

 

Параметры:

 

extern int    Lot             = 10;  // Объем лота в % от депозита
extern double Factor          = 2.0; // Множитель при успешной сделке
extern int    Attempt         = 3;   // Количество попыток

 

1. Первая сделка (попытка) выполняется с базовым лотом (Lot)

2. Если попытка 1 закрывается по ТР, то попытка 2 открывается с лотом рассчитанным по формуле (лот первой сделки * на множитель). Если сделка один закрывается по SL,, то цикл останавливается и начинается заново и сделка открывается с базовым лотом (Lot)

3. Аналогично,

 

После отработки цикла, все начинается заново исходя из полученного баланса.

 

Таким образом у нас есть 10 попыток, чтобы поймать 3 последовательно успешные сделки. В таком случае если депозит 100, то расчет в трех попытках такой 10+20+40. Если цикл отработал на пример на 4 попытке, то баланс составляет 100-30+70 = 140.

 

Вот мой пример, но что то он считает не так(

 

if (Attempt > 1)
       { 
        for (int i = Attempt; i >= 1; i--)
         {
           if (i == Attempt)
             { 
               OpenOrder(Lots);
             }
           if (i < Attempt && LastOrderProfit() > 0)
             { 
               double OLot = LastOrderLot() * Factor;

               OLot = NormalizeDouble(OLot , 2);
               OpenOrder(OLot);
             }
            if (i < Attempt && LastOrderProfit() < 0)
             {
               break;
             }

               
         }

Изменено 3 июля, 2020 пользователем Pretor85

#5992
50 минут назад, Pretor85 сказал:

Ребят, пишу советник на базе индикатора ТМА, уже тестирую простенький. Но есть еще задумка заложить в советник элементы теории вероятности.

Не получается создать цикл, уже всю голову сломал.

 

проблема в том, что это должен быть не цикл, а независимые функции.

А вот тот Attempt - должен быть глобальным параметром

#5993

Добавьте в первый пост ссылку на плейлист с уроками в youtube/

#5994

Ребят, начинаю осваивать MQL и напоролся на такую проблему. 

Есть функция, которая проверяет наличие закрывшихся или удаленных ордеров на текущий день.  То есть, если на текущий день был закрыт или удален какой либо ордер, возвращает булевое значение, что дальше в советнике запрещает открытие ордеров в текущий день

bool OrderHitoryClose()
  {
   for(int i=0; i<OrdersHistoryTotal(); i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))                                         // Выбор ордера для дальнейшей работы..
         if(OrderType() == OP_BUY)                                                            // ..тип ордера..
            if(TimeToStr(OrderCloseTime(), TIME_DATE) == TimeToStr(TimeCurrent(), TIME_DATE)) // ..дата закрытия ордера равна текущей дате..
               return(true);                                                                  // ..(на текущий день был закрыт ордер на покупку)
         if(OrderType() == OP_SELL)
           if(TimeToStr(OrderCloseTime(), TIME_DATE) == TimeToStr(TimeCurrent(), TIME_DATE))
              return(true);
     }
   return(false);
  }

Функция работает. Но из за данной функции (я проверял, и уверен, что дело в ней) , скорость тестирования (в тестере стратегий) равна скорости хромой кобылы. Очень долго.
Подскажите пожалуйста, в чем может быть причина?  

#5995

Стоило мне задать вопрос, как спустя час нашлось решение.

Переделал код и избавился от работы с OrdersHistoryTotal()

Работал с временем открытия бара

bool NewBar()
  {
   static datetime BarTime        = 0;             
   datetime        CurrentBarTime = Time[0];       
   
   if(BarTime == CurrentBarTime) return(false);
   else
     {
      BarTime = CurrentBarTime;
      return(true);
     }
  }

 

#5996

Всем привет. Написал цикл подсчета профита ордеров. Ну все как по классике, ошибок не должно быть, однако в журнал выводится какой-то мусор.

Вот код:

Глобальные переменные:
double BuyProfitOpen;
double SellProfitClose;   
---------------------------------------------------------------
for(int s=OrdersHistoryTotal()-1; s>=0; s--)
           {
            if(OrderSelect(s,SELECT_BY_POS,MODE_HISTORY))
              {
               if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic && OrderType()==OP_SELL)
                 {
                     SellProfitClose += OrderProfit();
                     SellProfitClose = NormalizeDouble(SellProfitClose,2);
                     Print("Сумма по истории селл ордеров SellProfitClose= ",SellProfitClose);
                 }
              }
           }

         for(int h = 0; h < OrdersTotal(); h++) 
           {
            if(OrderSelect(h,SELECT_BY_POS,MODE_TRADES))
              {
               if(OrderMagicNumber()==Magic && OrderSymbol()==Symbol())
                 {
                  if(OrderType()==OP_BUY)
                    {
                     BuyProfitOpen += OrderProfit()+OrderSwap()+OrderCommission();
                     BuyProfitOpen = NormalizeDouble(BuyProfitOpen,2);
                     Print("Сумма в рынке по бай ордерам BuyProfitOpen= ",BuyProfitOpen);
                    }
                 }
              }
           }

А теперь про мусор, прикрепил изображение. Что не так? Торги сеткой лотностью 0,01, в сетке по 10 ордеров где-то. И это начало тестирование в тестере MT4. Проверка на ошибки - ошибок нет.

журнал.jpg

Изменено 17 июля, 2020 пользователем diodio

#5997
Только что, diodio сказал:

Всем привет. Написал цикл подсчета профита ордеров. Ну все как по классике, ошибок не должно быть, однако в журнал выводится какой-то мусор.

Вот код:


Глобальные переменные:
double BuyProfitOpen;
double SellProfitClose;   
---------------------------------------------------------------
for(int s=OrdersHistoryTotal()-1; s>=0; s--)
           {
            if(OrderSelect(s,SELECT_BY_POS,MODE_HISTORY))
              {
               if(OrderSymbol()==Symbol() && OrderMagicNumber()==Magic && OrderType()==OP_SELL)
                 {
                     SellProfitClose += OrderProfit();
                     SellProfitClose = NormalizeDouble(SellProfitClose,2);
                     Print("Сумма по истории селл ордеров SellProfitClose= ",SellProfitClose);
                 }
              }
           }

         for(int h = 0; h < OrdersTotal(); h++) 
           {
            if(OrderSelect(h,SELECT_BY_POS,MODE_TRADES))
              {
               if(OrderMagicNumber()==Magic && OrderSymbol()==Symbol())
                 {
                  if(OrderType()==OP_BUY)
                    {
                     BuyProfitOpen += OrderProfit()+OrderSwap()+OrderCommission();
                     BuyProfitOpen = NormalizeDouble(BuyProfitOpen,2);
                     Print("Сумма в рынке по бай ордерам BuyProfitOpen= ",BuyProfitOpen);
                    }
                 }
              }
           }

А теперь про мусор, прикрепил изображение. Что не так? Торги сеткой лотностью 0,01, в сетке по 10 ордеров где-то.

журнал.jpg

В цикле сверху, вы считаете профит/убыток от всех ордеров закрывших по SELL направлению на истории.

В цикле снизу, вы считаете профит/убыток от всех ордеров по BUY направлению в рынке.

 

Написал небольшой советник для подсчета профита.

extern int Magic = 0;

void OnTick() {
	double BuyProfitOpen,  BuyProfitClose;
	double SellProfitOpen, SellProfitClose;  
	int    s;
	for (s = 0; s < OrdersTotal(); s++) {
		if ((OrderSelect(s, SELECT_BY_POS, MODE_TRADES)) && (OrderMagicNumber() == Magic) && (OrderSymbol() == Symbol())) {
			if (OrderType() == OP_BUY)  {
				BuyProfitOpen  += NormalizeDouble((OrderProfit() + OrderSwap() + OrderCommission()), 2);
			}
			if (OrderType() == OP_SELL)  {
				SellProfitOpen += NormalizeDouble((OrderProfit() + OrderSwap() + OrderCommission()), 2);
			}
		}
	}	
	for (s = OrdersHistoryTotal() - 1; s >= 0; s--) {
		if (OrderSelect(s, SELECT_BY_POS,MODE_HISTORY) && (OrderMagicNumber() == Magic) && (OrderSymbol() == Symbol())) {
			if (OrderType() == OP_BUY)  {
				BuyProfitClose  += NormalizeDouble((OrderProfit() + OrderSwap() + OrderCommission()), 2);
			}
			if (OrderType() == OP_SELL)  {
				SellProfitClose += NormalizeDouble((OrderProfit() + OrderSwap() + OrderCommission()), 2);
			}			
		}
	}	
	Comment("Сумма профита открытых BUY ордеров: ",               DoubleToStr(BuyProfitOpen, 2),   "\n",
	        "Сумма профита открытых SELL ордеров: ",              DoubleToStr(SellProfitOpen, 2),  "\n",
			"\n",                                                 
			"Сумма профита закрытых BUY ордеров: ",               DoubleToStr(BuyProfitClose,  2),  "\n",
			"Сумма профита закрытых SELL ордеров: ",              DoubleToStr(SellProfitClose, 2),  "\n",
			"\n",
			"Сумма профита открытых + закрытых BUY ордеров: ",    DoubleToStr((BuyProfitOpen  + BuyProfitClose),  2),  "\n",
			"Сумма профита открытых + закрытых SELL ордеров: ",   DoubleToStr((SellProfitOpen + SellProfitClose), 2),  "\n"			
			);

	return;
}

Единственное для увеличения производительности не рекомендую считать профит/убыток на истории на каждом тике, например, это можно делать только с последним ордером, добавляя профит или убыток к общей переменной.

#5998
2 часа назад, Ent сказал:

Единственное для увеличения производительности не рекомендую считать профит/убыток на истории на каждом тике, например, это можно делать только с последним ордером, добавляя профит или убыток к общей переменной.

Ну у меня почти тоже самое написано, только немного по-другому, вопрос в том почему в журнале такие числа? На каждом тике считает?

#5999
21 минуту назад, diodio сказал:

Ну у меня почти тоже самое написано, только немного по-другому, вопрос в том почему в журнале такие числа? На каждом тике считает?

Сложно сказать, т.к. вы не показываете код целиком.

Если у вас переменные вынесены за функцию OnTick(), то они не обнуляются на каждом тике, как моём примере, выше.

#6000

Пишу свой первый советник. Уроки очень помогают. 

Но не могу разобаться с 

double NormaliseDouble(double Lots, int 2);
Компилятор ругается

'2' - comma expected    Test!.mq4    33    41


 

Для публикации сообщений создайте учётную запись или авторизуйтесь

Перейти к списку тем
Форум · 2.0.20260627.0025