Ваши вопросы по языку MQL4

Алекc1234

Местный житель
PHP:
Expand Collapse Copy
double fir_or_pr;
 double prof;
 datetime Times=TimeCurrent();
 
for( int i=0; i<OrdersTotal(); i++) 
 { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)&&OrderSymbol() ==  Symbol()) 
  { if (OrderOpenTime()<Times)
    { fir_or_pr=OrderOpenPrice();
      if(OrderType() == OP_BUY) { 
      prof = NormalizeDouble((Bid-fir_or_pr),Digits)/Point; }
      if(OrderType() == OP_SELL) {
      prof = NormalizeDouble((fir_or_pr-Ask),Digits)/Point; } 
      Times=OrderOpenTime();
    }
  }
 }
И не говорите что не работает. Специально в советник вставлял для проверки.Если проверка по символу не нужна уберите её.

Огромное Вам спасибо, что столько времени мне уделили и даже проверяли на работоспособность. Сейчас я вставлю в свой советник и если и сейчас не заработает, значит это нюансы моего сова, так что на этом всё - беспокоить никого больше не буду!
 

hoz

Активный участник
Вот советник _http://www.forextrade.ru/media/Image/MQLabs/184_ag/LinearRegressionEnter_v2_Expert.mq4

Есть 2 вопроса.

1-ый. Сверху глобальная переменная g_ticket

Дальше, при посыле ордера, получается уже переменная ticket
Что-то я не въехал, зачем 2 переменные для того же значения по сути? Ведь это тот же текущий тикет...

2-ой. Передача параметров между функциями должна быть как я знаю из языка Си так: количество параметров в передающей функции должно соответствовать количеству параметров в той функции, в которую передаём.
В коде, ссылке которую я указал выше нарушены все правила, Но по скольку писал явно профессионал то, я всё-таки заинтересовался.

Вот о чём я:

PHP:
Expand Collapse Copy
//+-------------------------------------------------------------------------------------+
//| Открытие ордера при типе исполнения Instant Execution, возвращает тикет             |
//+-------------------------------------------------------------------------------------+
int OpenOrderWithInstantMode(int type, double lot, double price, double sl, double tp, 
                              int magicNumber) 
{ 
   string orderType = OrderTypeToString(type); 
   Comment("Отправлен запрос на открытие ордера ", orderType, "...");   
   int ticket = OrderSend(Symbol(), type, lot,     // Открытие позиции 
                          price, 3, sl, tp, NULL,  
                          magicNumber, 0); 
    
   if (ticket > 0)                                 // Успешное открытие ордера 
   {                           
      Comment("Ордер ", orderType, " открыт успешно!");  
      PlaySound(i_openOrderSound);  
      return(ticket);  
   } 
                           
   int error = GetLastError();                     // Неудачное открытие ордера 
   Comment("Ошибка открытия ордера ", orderType, ": ", error); 
   return(ticket); 
}

PHP:
Expand Collapse Copy
//+-------------------------------------------------------------------------------------+
//| Открытие ордера при типе исполнения Market Execution                                |
//+-------------------------------------------------------------------------------------+
bool OpenOrderWithMarketMode(int type, double lot, double price, double sl, double tp, 
                             int magicNumber) 
{ 
   int ticket = OpenOrderWithInstantMode(type, lot, price, 0, 0, magicNumber);
   if (ticket <= 0) 
      return(false); 
     
   if (!OrderSelect(ticket, SELECT_BY_TICKET) ||  
       OrderCloseTime() != 0)    
   { 
      Alert("Фатальная ошибка при установке стопов и профитов нового ордера!"); 
      return(false); 
   } 
    
   Comment("Установка стоп-приказа и профита ордера..."); 
   int cnt = 0; 
   while (!IsStopped()) 
   { 
      while (!WaitForTradeContext()) {} 
      CorrectionOfStops(type, sl, tp); 
      if (OrderModify(ticket, 0, sl, tp, OrderExpiration())) 
      { 
         Comment("Стоп-приказ и профит успешно установлены!"); 
         return(true); 
      } 
      Sleep(1000); 
   } 
}

PHP:
Expand Collapse Copy
//+-------------------------------------------------------------------------------------+
//| Открытие рыночного ордера с автоматическим определением типа исполнения ордера      |
//+-------------------------------------------------------------------------------------+
bool OpenByMarket(int type, double lot, double sl, double tp,  
                  int magicNumber, bool redefinition = true) 
// redefinition - при true доопределять параметры до минимально допустимых 
//                при false - возвращать ошибку 
{ 
// - 1 - == Проверка правильности типа ордера и достаточности свободных средств =========
   if (type > OP_SELL) 
      return(false); 
    
   if (!IsEnoughMoney(lot)) 
      return(false); 
// - 1 - == Окончание блока =============================================================

// - 2 - == Проверка свободности торгового потока и правильности параметров ордера ======
   if (!WaitForTradeContext()) 
   { 
      Comment("Время ожидания освобождения торгового потока истекло!"); 
      return(false); 
   } 

   double price;                                   // Цена исполнения ордера 
   if (!IsMarketOrderParametersCorrect(type, price, sl, tp, redefinition)) 
      return(false); 
// - 2 - == Окончание блока =============================================================
  
// - 3 - == Открытие ордера с ожидание торгового потока =================================
   if (GetExecutionType() == EXE_MODE_INSTANT || 
       (sl == 0 && tp == 0)) 
      return(OpenOrderWithInstantMode(type, lot, price, sl, tp, magicNumber) > 0);
       
   return(OpenOrderWithMarketMode(type, lot, price, sl, tp, magicNumber));
}


Получается, что из функции OpenByMarket передаются следующие формальные параметры функции OpenOrderWithMarketMode:


PHP:
Expand Collapse Copy
(type, lot, price, sl, tp, magicNumber)


Далее происходит самое интересное и не понятное,.. в функцию OpenOrderWithInstantMode передаются из функции OpenByMarket данные формальные параметры, НО в строке открытия ордера

PHP:
Expand Collapse Copy
int ticket = OrderSend(Symbol(), type, lot,     // Открытие позиции
                          price, 3, sl, tp, NULL,  
                          magicNumber, 0);



количество формальных параметров не соответствует количеству формальных параметров головной функции OpenOrderWithInstantMode

Там есть лишние, и вообще не все формальные параметры идут друг за другом. Почему так?
 
Последнее редактирование модератором:

hoz

Активный участник
Сделайте так:
datetime Times=TimeCurrent( ) ;// ставите перед циклом
OrderSelect(OrdersTotal()-1,SELECT_BY_POS);

if(OrderOpenTime<Times)
{
double fir_or_pr=OrderOpenPrice();
Times=OrderOpenTime( ) ;
}
на выходе цикла будет цена первого по времени ордера.

Просматривал ветку..

Тут же будет цена открытия ордера до времени Times. Но не факт, что это будет предыдущий ордер. Если 10 ордеров до Times, то будет есс-но 10 открытий, т.е. 10 OrderOpenTime.
И какой из OrderOpenTime сравнится ? Ну не обязательно же предпоследний, т.е. предыдущий последнему...
 

alexshell

Элитный участник
Просматривал ветку..

Тут же будет цена открытия ордера до времени Times. Но не факт, что это будет предыдущий ордер. Если 10 ордеров до Times, то будет есс-но 10 открытий, т.е. 10 OrderOpenTime.
И какой из OrderOpenTime сравнится ? Ну не обязательно же предпоследний, т.е. предыдущий последнему...

Цикл переберёт все ордера. И не важно в какой последовательности. Первый ордер изменит Times на свое время открытия. Следующий ордер если его время будет меньше нового Times,снова изменит его. Если нет то не изменит. И в итоге последний изменивший время ордер будет первым по времени. Если в цикле первым ордером будет первый по времени то Times изменится один раз.
 

eevviill

Заблокирован
Не могу понять

Я когда то пробовал создать трейлинг стоп. Так намучился, что не хотелось его потом видеть.
Нашел функцию трейлинга. НО! Для ордера сел условие что если СТ ордера больше..., ну а если СЛ ордера=0?

PHP:
Expand Collapse Copy
void Traling_Stop_f(int mag)
{ 
  for(int i=0; i<OrdersTotal(); i++) { 
    if(!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue; 
    if(OrderSymbol() != Symbol()) continue;        
    if(OrderMagicNumber()!=mag) continue;
///////
    if(OrderType()==OP_BUY) { 
      if(Bid-OrderOpenPrice()>NormalizeDouble(TrailingStop*Point,Digits) && Bid>=NormalizeDouble(OrderOpenPrice()+TrailingStopStart*Point,Digits)) { 
        if(OrderStopLoss()<NormalizeDouble(Bid-(TrailingStop+TrailingStep-1)*Point,Digits)) 
          OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Bid-TrailingStop*Point,Digits), OrderTakeProfit(), 0, CLR_NONE); 
      } 
    } 
////////
    if(OrderType()==OP_SELL) { 
      if(OrderOpenPrice()-Ask>NormalizeDouble(TrailingStop*Point,Digits) && Ask<=NormalizeDouble(OrderOpenPrice()-TrailingStopStart*Point,Digits)) { 
        if(OrderStopLoss()>NormalizeDouble(Ask+(TrailingStop+TrailingStep-1)*Point,Digits)) 
          OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Ask+TrailingStop*Point,Digits), OrderTakeProfit(), 0, CLR_NONE); 
      }
    } 
  } 
  
}
 

eevviill

Заблокирован
2-ой. ...Почему так?
Хмм. Так передать можно хоть милион значений и их вообще можно не использовать и даже разные названия давать.
PHP:
Expand Collapse Copy
int g_fix=8;
...
Counter(g_fix);
...
//////
void Counter(int ger)
{
int fon;
fon++;
}
 
Последнее редактирование:

hoz

Активный участник
Хмм. Так передать можно хоть милион значений и их вообще можно не использовать и даже разные названия давать.


В совке только одна текущая позиция. Данные переменные используются в разных кусках кода при работе с ордерами, значит они уже используются. Просто тут же видно, что переменные е просто объявлены, а они активны в коде. Вот почему разные мне очень интересно. Либо я что-то не понимаю, либо что-то ещё..

Я когда то пробовал создать трейлинг стоп. Так намучился, что не хотелось его потом видеть.
Нашел функцию трейлинга. НО! Для ордера сел условие что если СТ ордера больше..., ну а если СЛ ордера=0?

PHP:
Expand Collapse Copy
void Traling_Stop_f(int mag)
{ 
  for(int i=0; i<OrdersTotal(); i++) { 
    if(!(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))) continue; 
    if(OrderSymbol() != Symbol()) continue;        
    if(OrderMagicNumber()!=mag) continue;
///////
    if(OrderType()==OP_BUY) { 
      if(Bid-OrderOpenPrice()>NormalizeDouble(TrailingStop*Point,Digits) && Bid>=NormalizeDouble(OrderOpenPrice()+TrailingStopStart*Point,Digits)) { 
        if(OrderStopLoss()<NormalizeDouble(Bid-(TrailingStop+TrailingStep-1)*Point,Digits)) 
          OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Bid-TrailingStop*Point,Digits), OrderTakeProfit(), 0, CLR_NONE); 
      } 
    } 
////////
    if(OrderType()==OP_SELL) { 
      if(OrderOpenPrice()-Ask>NormalizeDouble(TrailingStop*Point,Digits) && Ask<=NormalizeDouble(OrderOpenPrice()-TrailingStopStart*Point,Digits)) { 
        if(OrderStopLoss()>NormalizeDouble(Ask+(TrailingStop+TrailingStep-1)*Point,Digits)) 
          OrderModify(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Ask+TrailingStop*Point,Digits), OrderTakeProfit(), 0, CLR_NONE); 
      }
    } 
  } 
  
}

Ну так, а какой в этом смысл? Ты же хочешь установить трейлинг, а если у тебя же SL=0, то проще сразу закрыть ордер. Тут логики особой нет.
Трейлинг ставиться же, чтоб выжать из позиции больше прибыли (теоритически). А когда позиция болтается у открытия, есть риск, что ордер станет - лосём.
Тогда и трейлинг ему не нужен будет.

Кстати, если нет у тебя ещё, вот держи набор трейлингов проверенный временем набор от библиотека тралов от Юрия Дзюбан.
 

Вложения

hoz

Активный участник
Да. После добавления этого всё заработало.

Ну так тут всё логично:oops:
Я тебя понимаю, у меня щяс тоже бывают затупы. Сову свою уже несколько дней всё ни как не осилю. Решил писать всё как профи, по функциям разделять каждый шаг, по ссылкам передачи что куда нужно т тд. И в конечном итоге запутался по ходу.
 

Ugar

Гуру форума
Ну так тут всё логично:oops:
Я тебя понимаю, у меня щяс тоже бывают затупы. Сову свою уже несколько дней всё ни как не осилю. Решил писать всё как профи, по функциям разделять каждый шаг, по ссылкам передачи что куда нужно т тд. И в конечном итоге запутался по ходу.
Так профи отличают работу другого профи от работы новичка косящего под профи. Профи используют функции если есть на это конкретная надобность. Использованием функций они облегчают себе работу. А разделение каждого шага в функцию, только для того что бы выглядело как у профи - ламерство. И только новички считают что это похоже на работу профи. Профи видят сразу что это работа новичка. Не удивительно что новички косящие под профи, сами себя запутывают.
Профи, при написании, стремятся к максимально точной, стабильной и надёжной работе программы. Именно для этого нужна программа не так ли? А для этого она должна выглядеть максимально простой в понимании, для отладки и дальнейших доработок. А как выглядит написанный код в глазах окружающих его мало интересует. За исключением отдельных случаев. Например код на продажу часто пишется максимально запутанно для усложнения взлома. Код конечно всё равно взломают, но взломщик сначала долго по матерится прежде чем поймёт где в коде ловушки. Потом этот код появляется в свободном доступе, а новички считают, этот специально запутанный код, образцом почерка профи. :rolf::rolf::rolf:
Хотите писать как профи? Пишите максимально просто для собственного понимания. Так что бы если понадобиться переделать программу через год, достаточно было взглянуть на код и через минуту стали понятны все нюансы работы программы.
 

hoz

Активный участник
Так профи отличают работу другого профи от работы новичка косящего под профи.

Ugar, оно то, в принципе, и так. НО. Зачем мне начинать писать всё в одной функкции start, как это делают многие новички? Да и не только новички так делают.
Я понимаю, что разделение кода на функции нужно для удобства. Поэтому учусь связывать их между собой. Но не всё так гладко..
Я веду к тому, что лучше начинать писать код в хорошем тоне, а не абы как, дабы потом не пришлось переучиваться.
 

Ugar

Гуру форума
Ugar, оно то, в принципе, и так. НО. Зачем мне начинать писать всё в одной функкции start, как это делают многие новички? Да и не только новички так делают.
Я понимаю, что разделение кода на функции нужно для удобства. Поэтому учусь связывать их между собой. Но не всё так гладко..
Я веду к тому, что лучше начинать писать код в хорошем тоне, а не абы как, дабы потом не пришлось переучиваться.
Разделение кода на функции удобства не добавляет. Добавляет только путаницы. Выделение части кода в функцию может оказаться удобным.
Пример:
Программа одинаково анализирует 10 инструментов.
1. можно код анализа 10 раз скопировать указав разные символы.
2. можно код анализа выделить в функцию. 10 раз её вызвать с заданием разных инструментов.
У 2 варианта очевидные преимущества. Код короче, значит проще в понимании. Если что то нужно изменить в анализе достаточно изменить одну функцию, а не 10 кусков кода.
Ещё пример: У программиста наработаны собственные функции которые понятны, уже многократно проверены и отлажены. Они написаны потому что часто встречаются в программах. Программа пишется Внутри функции start. Но части кода которые часто используются в программах как модули вызываются функции. Удобно потому что меньше придётся писать и проверять.
Ещё другой пример:
Программа без повторяющейся компонентов
1. Код написан последовательно внутри функции start. Всё по порядку, легко понять и разобрать на косточки.
2. Внутри функции start только одна функция. Из неё вызываются ещё функции, из них ещё функции... В общем хороший пример плохого тона.
Никакого удобства в этом нет. А когда часть функций написаны другим программистом и не проверены лично, о стабильности работы речи быть не может. А если выведено в отдельные функции то что используется в коде 1 раз и возможно больше никогда не понадобится, то это ещё и полная дурь. Такие приёмы используют что бы запутать взломщиков. Они при разборе кода будут грязно ругаться. Всё равно взломают если будет на то желание. Но тут палка о двух концах. Сам программист, через время забудет что там он писал. Если через время понадобится внести изменение в работе программы то тогда он уже сам будет грязно ругаться, только уже на себя. :rolf:
Учиться связывать функции конечно нужно, но не надо забывать про саму цель.
1 Цель изучение языка программирования - создание программ.
2. Цель создания программ - заработок.
Вот тут возникает вопрос, на чём заработок. Если на бирже с использованием программ, то не стоит грузиться всякой дурью и даже удобство кода не важно. Важно только поможет ли работающая программа заработать на бирже.
А если заработок на написании программ на заказ, то стоит писать свои библиотеки функций которые чаще всего используются. Тут надо учитывать что программист без опыта в реальной торговле на бирже качественную программу вряд ли напишет. От куда ему знать про нюансы и подводные камни связанные с реальной торговлей.
А если заработок не на бирже, а на продаже "граалей". Тогда да, стоит сразу осваивать максимально запутанное написание кода. Они редко дорабатывают свои граали. По этому запутанный код им только помогает.
 
Последнее редактирование:

Energetik777

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

int FindHighBuyPrice()
{
int l_count_42=0;
int l_ord_total_122 = OrdersTotal();
for (int l_pos_82 = 0; l_pos_82 < l_ord_total_122; l_pos_82++) {
OrderSelect(l_pos_82, SELECT_BY_POS, MODE_TRADES);
if (OrderType() == OP_BUY && OrderOpenPrice() > l_count_42)
{
l_count_42 = OrderOpenPrice();
}
}
return (l_count_42);
}
 

hoz

Активный участник
Ugar, у меня цель именно заработок на бирже, без всяких там продаж и без всяких надувательств и впаривания кому-н. сливаторов. Суть в том, что я учусь на некоторых примерах, один из которых я приводил выше.. На те вопросы мне так никто и не ответил.. Возможно, никто из здесь присуствующих не понял работы того эксперта, ровно как и я. я уже задал вопрос автору, жду..
По сути, у меня есть наработки на длительном промежутке времени, но не хватает пока что навыков программирования.
Искал программиста, с которым можно быстро всё это дело разрулить, и совместо делать толковые совы, НО все к кому обращался, либо шарлатаны, которые сразу просят ТС, либо барыги, которые сразу выставляют ценник за работу (они, как правило, не верят в то, что можно заработать экспертами, а потому такие мелочные), либо лентяи, которые не хотят шевелится, и их нужно пинать постоянно, чтоб дело двигалось. Вот я и начал изучать программирование сам. На данный момент, всё-равно хватает головняков.
Вижу, что то что я понимаю, работает и приносит прибыль, а я в это время пытаюсь освоить кодинг, это, на самом деле, не очень мне нравится..
Но платить кому-то за адекватные ТС, это слишком глупо. Тем более мне не нужно писать, а нужна лишь некоторая помошь. А если б нужно было написать, то есть к кому обратится. Такие вот дела.
А по поводу отдельным функций. Я имел ввиду как-раз таки, те сегменты, которые постоянно используются в коде, или по логике удобно выделить отдельно. Это же и смотрится гораздо читабельнее ежели всё в одном.
 
Последнее редактирование:

Ugar

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

int FindHighBuyPrice()
{
int l_count_42=0;
int l_ord_total_122 = OrdersTotal();
for (int l_pos_82 = 0; l_pos_82 < l_ord_total_122; l_pos_82++) {
OrderSelect(l_pos_82, SELECT_BY_POS, MODE_TRADES);
if (OrderType() == OP_BUY && OrderOpenPrice() > l_count_42)
{
l_count_42 = OrderOpenPrice();
}
}
return (l_count_42);
}
1. Из какого декомпила выкавыривал функцию? Это не красиво!
2. Цена открытия ордера, как и любая другая, всегда дробная. Значит функция должна быть double типа.
3. По этой же причине переменная, в которой хранится цена, то же должна быть double типа

double FindHighBuyPrice()
{
double l_count_42=0;
...

Кстати вот пример нерациональной работы программы с использованием функций.
Если нужно получить минимальную и максимальную цену открытых ордеров можно в функции старт написать цикл и найти все эти и другие нужные значения за один перебор ордеров.
А можно применить несколько функций и вызывая их последовательно получить эти значения. В каждой функции будет свой перебор ордеров для получения и возврата нужного значения.
Лишние функции, лишние циклы, лишняя бесполезная работа программы. Как минимум это не оптимально. Лишняя нагрузка на комп, замедление работы в тестере, вот результат.
Можно конечно извернуться, и в функции найти все нужные значения, но возвращать их придётся через глобальные переменные, так как нормально функция возвращает только одно значение.
 
Последнее редактирование:

Energetik777

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

hoz

Активный участник
Вот функция открытия ордера:

PHP:
Expand Collapse Copy
//+-------------------------------------------------------------------------------------+
//| Открытие длинной позиции                                                            |
//+-------------------------------------------------------------------------------------+
bool OpenBuy()
{
// - 1 - == Закрытие противоположных позиций ============================================
   if (g_type == OP_SELL)
      if (!CloseDeal(g_ticket))
         return(false);
// - 1 - == Окончание блока =============================================================

// - 2 - == Модификация существующей позиции не производится ============================
   if (g_type == OP_BUY)
      return (true);
// - 2 - == Окончание блока =============================================================

// - 3 - == Покупка по рынку ============================================================
   return (OpenByMarket(OP_BUY, GetLots(), 0, 0, i_magicNumber, true));
// - 3 - == Окончание блока =============================================================
}


Я вот пытаюсь понять логику.
Если есть противоположная позиция, то закроем её. Если не закрыли, то выходим из функции.
Если есть ордер бай, то ничего не делаем и выходим из функции.

Т.е. суть в том, что после кажого if имеется return, а это уже выход из функции. Как после того как вышли из функции можно испольнить оператор?

PHP:
Expand Collapse Copy
return (OpenByMarket(OP_BUY, GetLots(), 0, 0, i_magicNumber, true));
 
Последнее редактирование модератором:
Верх