Jump to content

Общие вопросы по языку MQL


Recommended Posts

matu1

Народ, нужен хэлп!

Пытаюсь сочинить советника, примитивным способом - переделываю пример из учебника. Не факт, что он будет работать, главное - сам процесс :) Собственно, сама проблема:

при компиляции советник выдает ошибку, вызванную тем, что у меня не определен массив для хранения цен закрытия предыдущих N баров. Никак не могу понять, как это сделать... Подскажите, как решить эту проблему?

Link to post
Share on other sites
  • Replies 7.6k
  • Created
  • Last Reply

Top Posters In This Topic

  • AntFX

    577

  • sergey1294

    569

  • Ugar68

    517

  • Programmer

    419

Top Posters In This Topic

Popular Posts

Ну, в данном случае мне стоило бы сразу соблюдать простейшие приёмы защитного программирования, то есть проверять, не равна ли нулю переменная, оказавшаяся под знаком деления. Ведь она "чужая", то ест

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

Основной советник выставляет "сигнальный" отложенный ордер далеко от текущей цены и каждую например, минуту модифицирует у него время экспирации: это может быть текущее время плюс 1 час, или плюс 1 су

Posted Images

Sergey Kovalyov

86-я строчка. Вы как-то неправильно используете iClose -- передаете больше параметров, чем она принимает. http://docs.mql4.com/ru/series/iClose

Link to post
Share on other sites
Programmer
double val2;
// расчет минимального значения цены на Candles последовательных барах
// с индекса 1 по индекс, заданный параметром Candles включительно на текущем графике
val2=iLowest(NULL,0,MODE_LOW,C1,1);


  if ([u]iClose(NULL,0,[b]MODE_CLOSE[/b],1) [/u]> val1)      // Если цена закрытия предыдущей свечи
    {                                          // выше максимума предыд 20-ти
     Opn_B=true;                               // Критерий откр. Buy
     Cls_S=true;                               // Критерий закр. Sell
    }
  if ([u]iClose(NULL,0,[b]MODE_CLOSE[/b],1)[/u] < val2)      // Если цена закр предыд свечи
    {                                          // ниже миним пред 20-ти
     Opn_S=true;                               // Критерий откр. Sell
     Cls_B=true;                               // Критерий закр. Buy
    }
//--------------------------------------------------------------- 6 --

Link to post
Share on other sites
matu1

Спасибо! Сто раз смотрел на эту функцию, а слона и не заметил))))) Теперь пойду дальше:3:

Link to post
Share on other sites
Sim Cat

Подскажите, в чем, собственно дело?

решил вчера прочитать по програмированию и собрать штонибуть в целях эксперимента. покопался в примерах, собрал воть:

 

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

//| sim.mq4 |

//| Copyright © 2008, [email protected] |

//| |

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

#property copyright "Copyright © 2008, [email protected]"

#property link ""

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

//| script program start function |

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

extern int StopLoss_s=0;

extern int TakeProfit_s=10;

extern int StopLoss_b=0;

extern int TakeProfit_b=10;

extern int slippage=2;

void sell_eurusd()

{

double loss_s=0; if (StopLoss_s >0) loss_s =Bid+StopLoss_s*Point;

double profit_s=0; if (TakeProfit_s >0) profit_s=Bid-TakeProfit_s*Point;

if(OrderSend("EURUSD",OP_SELL,0.1,Bid,slippage,loss_s,profit_s,NULL,0,0,CLR_NONE)<0)

Alert("Ошибка открытия позиции № ", GetLastError());

}

void buy_eurusd()

{

double loss_b=0 ; if (StopLoss_b >0) loss_b =Ask-StopLoss_b*Point;

double profit_b=0; if (TakeProfit_b >0) profit_b=Ask+TakeProfit_b*Point;

// OrderSend("EURUSD",OP_BUY,lot,Ask,slippage,loss_b,profit_b,NULL,0,0,CLR_NONE);

if(OrderSend("EURUSD",OP_BUY,0.1,Ask,slippage,loss_b,profit_b,NULL,0,0,CLR_NONE)<0)

Alert("Ошибка открытия позиции № ", GetLastError());

}

int start()

{

if(!IsTradeAllowed())

{

Alert("Торговый поток занят! Эксперт не может открыть позицию!");

return(-1);

}

else

{

sell_eurusd();

buy_eurusd();

return(0);

}

}

теперь вопрос: почему, если не проверять на занятость торгового потока, покупка-продажа совершается (иногда впрочем совершается только продажа, иногда - ничего не происходит), а если проверять, то всегда выдает занятость торгового потока? причем всегда, проверено, загонял в цикл с проверкой.

никаких индикаторов, советников и прочей машинерии не стоит, переустановил на всякий случай метатрэйдер, не помогло. Кто сталкивался, подскажите, в чем трабла?:3:

Link to post
Share on other sites
Sergey Kovalyov

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

 

http://docs.mql4.com/ru/convert/NormalizeDouble

Link to post
Share on other sites
Sergey Kovalyov

Гм, тема не в тот раздел написана...

Link to post
Share on other sites
Programmer

Перенёс.

Link to post
Share on other sites
Sim Cat
Позапускайте его пару раз и покажите журнал работы скрипта. Там можно будет увидеть что и как. Возможно, уровни стопов не нормализованы.

 

http://docs.mql4.com/ru/convert/NormalizeDouble

 

нормализовал

 

void sell_eurusd()

{

double loss_s=0; if (StopLoss_s >0) loss_s =Bid+StopLoss_s*Point;

double profit_s=0; if (TakeProfit_s >0) profit_s=Bid-TakeProfit_s*Point;

// OrderSend("EURUSD",OP_SELL,lot,Bid,slippage,loss_s,profit_s,NULL,0,0,CLR_NONE);

if(OrderSend("EURUSD",OP_SELL,0.1,Bid,slippage,NormalizeDouble(loss_s,4),NormalizeDouble(profit_s,4),NULL,0,0,CLR_NONE)<0)

Alert("Ошибка открытия позиции № ", GetLastError());

}

//120

void buy_eurusd()

{

double loss_b=0 ; if (StopLoss_b >0) loss_b =Ask-StopLoss_b*Point;

double profit_b=0; if (TakeProfit_b >0) profit_b=Ask+TakeProfit_b*Point;

// OrderSend("EURUSD",OP_BUY,lot,Ask,slippage,loss_b,profit_b,NULL,0,0,CLR_NONE);

if(OrderSend("EURUSD",OP_BUY,0.1,Ask,slippage,NormalizeDouble(loss_b,4),NormalizeDouble(profit_b,4),NULL,0,0,CLR_NONE)<0)

Alert("Ошибка открытия позиции № ", GetLastError());

 

выдает то же самое.

в журнале ничего не пишет

 

10:07:50 Script мусор EURUSD,H1: loaded successfully

10:07:50 Script мусор EURUSD,H1: removed

10:08:26 Script мусор EURUSD,H1: loaded successfully

10:08:26 Script мусор EURUSD,H1: removed

10:08:33 Script мусор EURUSD,H1: loaded successfully

10:08:33 Script мусор EURUSD,H1: removed

 

в алерте выдает "торговый поток занят! советник не может открыть позицию"

 

в случаях, когда гонял без проверки - по какой-то причине совсем перестал открывать ордера что на покупку, что на продажу. в журнале также пишет - скрипт загружен, удален успешно. и ни гугу. профит менял до 50 пунктов, лос стоит 0, так что даже не знаю в чем трабла, на кого гадости думать :1111483289:

Link to post
Share on other sites
kifa911

Доброе время суток Всем!

Уважаемый Programmer, я пишу свой советник и естественно его переодически тестирую. В один прекрасный момент в журнале стали появляться ошибки мне не понятные типа: unmatched data error (volume limit 478 at 2008.10.13 23:00 exceeded). Таких ошибок много связаных с максимумами и минимумами и после этого тестер дальше не идет. К сожалению не могу выложить скрин, может кто подскажет как это делать!

Edited by kifa911
Link to post
Share on other sites
matu1

Уважаемые гуру,

не сочтите за труд посмотреть моё творение и сказать, что не так. Дело в том, что я написал советника (почувствовал себя Франкенштейном при этом, т.к. раздербанил на кусочки кода несколько чужих экспертов:). Он почему-то открывает ТОЛЬКО длинные позиции и пишет ошибки при модификации ордера...

Логика советника описана в ветке "Безиндикаторные системы", т.е. он сравнивает цену закрытия предыдущего бара с максимумом предыдущих 20-ти, при цене большей - открывает длинную (для короткой всё наоборот). Стоп выставляет как минимум предыдущих 10 баров. На следующем баре при наличии открытой позы он должен модифицировать ордер, если изменился минимум предыдущих 10 баров (если только он поднялся, но это ещё не вписано в код).

20candles_v1.mq4

Link to post
Share on other sites
gfm73

Всем доброго!

Вопрос к специалистам MQ4.

Проблема следующая, хотел перенести iMa функцию в код советника, и вроде как особых проблем нету, но при анализе результатов понятно, что я что-то упустил, нужна ваша помощь.

//+------------------------------------------------------------------+
//| Exponential Moving Average                                       |
//+------------------------------------------------------------------+
void ema(int MA_Period, int Price_Type, double &ExtMapBuffer[])
{
  double pr = 2.0/(MA_Period + 1);
  int    pos = Bars - 2;
  int counted_bars_ = counted_bars ;
//---- last counted bar will be recounted
  if (counted_bars_ > 0) counted_bars_--;
  if(counted_bars_ > 2) pos = Bars - counted_bars_ - 1;
  ArrayResize(ExtMapBuffer,pos);

//---- main calculation loop
  while(pos>=0){
     if(pos == Bars - 2) ExtMapBuffer[pos+1]= Price(Price_Type,pos+1);
     ExtMapBuffer[pos] = Price(Price_Type,pos)*pr+ExtMapBuffer[pos+1]*(1-pr);
    pos--;
  }
}

double Price(int Price_Type,int shift){
  switch(Price_Type){
     case PRICE_CLOSE:
        return(Close[shift]);
     break;
     case PRICE_OPEN:
        return(Open[shift]);
     break;
     case PRICE_HIGH:
        return(High[shift]);
     break;
     case PRICE_LOW:
        return(Low[shift]);
     break;
     case PRICE_MEDIAN:
        return((Low[shift] + High[shift])/2);
     break;
     case PRICE_TYPICAL:
        return((Low[shift] + High[shift] + Close[shift])/3);
     break;
     case PRICE_WEIGHTED:
        return((Low[shift] + High[shift] + Close[shift] + Close[shift])/3);
     break;

  }
}  

где ExtMapBuffer это результирущий массив.

пример:

  IMA(FastEMA,MODE_EMA,PRICE_CLOSE,FastBuffer);
  Macd1=FastBuffer[1];
  Macd2=iMA(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE,1)

Так вот Macd1 и Macd2 дают различный результат.

 

В чем ошибка ?

Заранее спасибо.

Edited by gfm73
Link to post
Share on other sites
Sergey Kovalyov
нормализовал

 

выдает то же самое.

в журнале ничего не пишет

 

в алерте выдает "торговый поток занят! советник не может открыть позицию"

 

Ну, это потому, что в коде написано такое сообщение выдавать. На самом деле, там должно быть "Торговля запрещена или поток занят". Проверьте настройки терминала. И, лучше, используйте две проверки IsExpertEnabled() и IsTradeContextBusy(). Вот тут про это подробней: http://articles.mql4.com/ru/94

Link to post
Share on other sites
Programmer
Доброе время суток Всем!

Уважаемый Programmer, я пишу свой советник и естественно его переодически тестирую. В один прекрасный момент в журнале стали появляться ошибки мне не понятные типа: unmatched data error (volume limit 478 at 2008.10.13 23:00 exceeded). Таких ошибок много связаных с максимумами и минимумами и после этого тестер дальше не идет. К сожалению не могу выложить скрин, может кто подскажет как это делать!

 

Скачайте историю котировок заново.

Link to post
Share on other sites
Programmer
Всем доброго!

Вопрос к специалистам MQ4.

Проблема следующая, хотел перенести iMa функцию в код советника, и вроде как особых проблем нету, но при анализе результатов понятно, что я что-то упустил, нужна ваша помощь.

//+------------------------------------------------------------------+
//| Exponential Moving Average                                       |
//+------------------------------------------------------------------+
void ema(int MA_Period, int Price_Type, double &ExtMapBuffer[])
{
  double pr = 2.0/(MA_Period + 1);
  int    pos = Bars - 2;
  int counted_bars_ = counted_bars ;
//---- last counted bar will be recounted
  if (counted_bars_ > 0) counted_bars_--;
  if(counted_bars_ > 2) pos = Bars - counted_bars_ - 1;
  ArrayResize(ExtMapBuffer,pos);

//---- main calculation loop
  while(pos>=0){
     if(pos == Bars - 2) ExtMapBuffer[pos+1]= Price(Price_Type,pos+1);
     ExtMapBuffer[pos] = Price(Price_Type,pos)*pr+ExtMapBuffer[pos+1]*(1-pr);
    pos--;
  }
}

double Price(int Price_Type,int shift){
  switch(Price_Type){
     case PRICE_CLOSE:
        return(Close[shift]);
     break;
     case PRICE_OPEN:
        return(Open[shift]);
     break;
     case PRICE_HIGH:
        return(High[shift]);
     break;
     case PRICE_LOW:
        return(Low[shift]);
     break;
     case PRICE_MEDIAN:
        return((Low[shift] + High[shift])/2);
     break;
     case PRICE_TYPICAL:
        return((Low[shift] + High[shift] + Close[shift])/3);
     break;
     case PRICE_WEIGHTED:
        return((Low[shift] + High[shift] + Close[shift] + Close[shift])/3);
     break;

  }
}  

где ExtMapBuffer это результирущий массив.

пример:

  IMA(FastEMA,MODE_EMA,PRICE_CLOSE,FastBuffer);
  Macd1=FastBuffer[1];
  Macd2=iMA(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE,1)

Так вот Macd1 и Macd2 дают различный результат.

 

В чем ошибка ?

Заранее спасибо.

 

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

Link to post
Share on other sites
kifa911
Скачайте историю котировок заново.

Извините, а как это сделать?

Link to post
Share on other sites
Roger
Уважаемые гуру,

не сочтите за труд посмотреть моё творение и сказать, что не так. Дело в том, что я написал советника (почувствовал себя Франкенштейном при этом, т.к. раздербанил на кусочки кода несколько чужих экспертов:). Он почему-то открывает ТОЛЬКО длинные позиции и пишет ошибки при модификации ордера...

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

Link to post
Share on other sites
matu1
Про модификацию - правильно пишет ошибки. Добавь в условия, что предыдущий стоплосс не равен новому. Про короткие позиции - навскидку ошибки не нашел. Добавь в блок формирования сигнала для селл такой же Print, как для покупки. Прогони по истории и посмотри, появляется ли надпись "Minimum". Если появляется, будем думать, если нет - тогда смотри условия.

 

Спасибо за проявленный интерес! Я уже нашел свои ошибки и сделал модификации. Может кому-нибудь будет интересно: 1) как ты и пишешь, нужно было добавить условие неравенства стоплосса 2) про открытие только длинных позиций - у меня переменные, которые разрешают открытие позиции, были объявлены в самом начале, поэтому получалось так: как только срабатывало условие на покупку, значение переменной изменялось на true и дальше во время работы разрешались только длинные позиции. Как только перенес объявление переменных в другое место - всё заработало нормально.

Вобщем, советника доделал:-) Очень доволен своим первым экспериментом. Стратегия советника честно говоря слабенькая, дает большие просадки. Но в целом может работать в плюс, если "ловит" хороший тренд на H1 и H4/ Если добавить фильтры, возможно и будет работать получше, но сделки будет открывать намного реже - не всякий трейдер вытерпит такое)))) Выкладываю советника - смотрите. Вообще-то на его написание меня подвиг опыт одного товарища, который в ветке "Безиндикаторные ТС" выкладывал результаты работы по этой стратегии. Правда он работает на нескольких парах. Может в этом фишка (в хеджировании)?

20candles_v1_1.mq4

Link to post
Share on other sites
Sergey Kovalyov

Простите, мы тут -- программисты. Трейдуны мы -- в других разделах. Если код не компилируется, или ведет себя не так, то спрашивайте.

Link to post
Share on other sites
Sergey Kovalyov
Извините, а как это сделать?

 

Через History Center (F2)

Link to post
Share on other sites
matu1

Подскажите пожалуйста, не слишком ли много условий в этом операторе? Он все условия будет проверять? Или количество условий должно быть ограничено?

 

if (Low[1]>Low[2]&&Low[2]>Low[3]&&Low[3]>Low[4]&&Open[0]>Open[1]&&Open[1]>Open[2]&&Open[2]>Open[3]&&Supervisor()>0)

Link to post
Share on other sites
Sergey Kovalyov

По-моему, это не сюда. Тут программирование как таковое, а не стратегии.

Link to post
Share on other sites
Programmer
Подскажите пожалуйста, не слишком ли много условий в этом операторе? Он все условия будет проверять? Или количество условий должно быть ограничено?

 

if (Low[1]>Low[2]&&Low[2]>Low[3]&&Low[3]>Low[4]&&Open[0]>Open[1]&&Open[1]>Open[2]&&Open[2]>Open[3]&&Supervisor()>0)

 

 

Да, примет всё.

Link to post
Share on other sites
matu1

Помогите пожалуйста начинающему, соратники!

Написал своего первого советника, но при работе всё время возвращает ошибку OrderModifi error 1. Я понимаю, что эта ошибка связана с попыткой установки неправильного стоп-лосс для ордера. Но моего разумения не хватает, чтобы её устранить. Посмотрите пожалуйста код, как его нужно изменить?

Идея такова: проверяется, есть ли открытые ордера. Если есть ордер (например, BUY), проверяется наличие профита и наличие сигнала на закрытие. Если условия выполнены - ордер закрывается с профитом. Если профита и/или сигнала на закрытие нет, выполняется модификация ордера - стоп переносится (расчет стопа в коде)

//---------------- РАССЧИТЫВАЕМ СТОП-ЛОСС ДЛЯ ПОЗИЦИИ -------------

SL_BUY=iMA(NULL,TFforMA,Period_MA,0,1,3,1);

SL_SELL=iMA(NULL,TFforMA,Period_MA,0,1,2,1);

//Print("стоп для BUY=",SL_BUY,"  стоп для SELL=",SL_SELL);

//-------------- ПРОВЕРЯЕМ НАЛИЧИЕ ОТКРЫТЫХ ОРДЕРОВ И ЗАКРЫВАЕМ/МОДИФИЦИРУЕМ--------------
  int total = OrdersTotal();
  for (int i = 0; i < total; i++) 
  {
     OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
     if (OrderSymbol() == Symbol() && OrderMagicNumber() == mn) 
        {
            if(OrderType()==OP_BUY && OrderProfit()>0 && Close[1]<Minimum() && Supervisor()<0)
               {
                OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet);
                return(0);
               }
                   if(OrderType()==OP_BUY) 
                       {  
                        OrderModify(OrderTicket(),OrderOpenPrice(),SL_BUY,OrderTakeProfit(),0,Blue);
                        return(0);
                       }
                            if(OrderType()==OP_SELL && OrderProfit()>0 && Close[1]>Maximum() && Supervisor()>0)
                              {
                               OrderClose(OrderTicket(),OrderLots(),Ask,3,Red);
                               return(0);
                              }
                                 if(OrderType()==OP_SELL && OrderStopLoss()>SL_SELL && OrderStopLoss()!=SL_SELL)      // короткая открытая позиция
                                   {
                                      OrderModify(OrderTicket(),OrderOpenPrice(),SL_SELL,OrderTakeProfit(),0,Red);
                                   } 

                                   return(0);
          } 
  }

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    No registered users viewing this page.


×
×
  • Create New...