Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 1549

 
MakarFX:

Хорошо говорить, когда знаешь что делать...

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

Я уже всё сказал достаточно понятно. Ну для тебя лично спрошу

Вот две функции и обе перебирают исторические ордера

//+------------------------------------------------------------------+
//|  Возвращает пункты убытка закрытых ордеров с начала цикла        |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|  Возвращает кол-во серии убыточных ордеров                       |
//+------------------------------------------------------------------+

Два цикла по одним и тем-же ордерам. За один цикл получить всё что возвращают эти функции никак?

 

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

к сову пытаюсь прикрутить переворот сделок. Делаю как указано в инструкции : https://www.mql5.com/ru/forum/128200

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

По журналу выдает ошибку:

2021.07.29 20:06:34.316 2015.01.08 22:10:00  SMA с переворотом через код AUDUSD,M5: OrderSend error 130

2021.07.29 20:06:34.316 2015.01.08 22:05:45  SMA с переворотом через код AUDUSD,M5: OrderSend error 4107

2021.07.29 20:06:34.316 2015.01.08 22:05:45  SMA с переворотом через код AUDUSD,M5: invalid stoploss for OrderSend function

подскажите пожалуйста, в чем тут дело?

я сам думаю, что переменные указанные в 

int ReversOrderSend (string symbol,int cmd,double volume,double price,int slippage,double stoploss,double takeprofit,string comment,int magic=0,datetime expiration=0,color arrow_color=CLR_NONE)

 не связаны с основным кодом.

пробовал в разных терминалах, 4х и 5ти знак. ошибка везде одна и та же.

вот весь код:

//+-----------------------------------------------------------------------------------------------+
//|                                                                     Simple Moving Average.mq4 |
//|                                                                 Copyright 2016, Andrey Minaev |
//|                                                     https://www.mql5.com/ru/users/id.scorpion |
//+-----------------------------------------------------------------------------------------------+
#property copyright "Copyright 2016, Andrey Minaev"
#property link      "https://www.mql5.com/ru/users/id.scorpion"
#property version   "1.00"
#property strict

// Параметры советника
extern string sParametersEA = "";     // Параметры советника
extern double dLots         = 0.01;   // Количество лотов
extern int    iStopLoss     = 30;     // Уровень убытка (в пунктах)
extern int    iTakeProfit   = 30;     // Уровень прибыли (в пунктах)
extern int    iSlippage     = 3;      // Проскальзование (в пунктах)
extern int    iMagic        = 1;      // Индентификатор советника
extern double K_Martin     = 2.0;
extern int    OrdersClose  = 5;
extern int    DigitsLot    = 2;
extern int    ReversOrder  = 0;             // Переворот сделок 1-да; 0-нет;
// Параметры индикатора
extern string sParametersMA = "";     // Параметры индикатора
extern int    iPeriodMA     = 14;     // Период усреднения
// Глобальные переменные
double dMA;
//+-----------------------------------------------------------------------------------------------+
int OnInit()
  {
// Если брокер использует 3 или 5 знаков после запятой, то умножаем на 10
   if(Digits == 3 || Digits == 5)
     {
      iStopLoss   *= 10;
      iTakeProfit *= 10;
      iSlippage   *= 10;
     }

   return(INIT_SUCCEEDED);
  }
//+-----------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+-----------------------------------------------------------------------------------------------+
void OnTick()
  {
// Получим значение индикатора
   dMA = iMA(Symbol(), 0, iPeriodMA, 0, MODE_SMA, PRICE_CLOSE, 0);

// Если нет открытых ордеров, то входим в условие
   if(bCheckOrders() == true)
     {
      // Если появился сигнал на покупку, то откроем ордер на покупку
      if(bSignalBuy() == true)
         vOrderOpenBuy();

      // Если появился сигнал на продажу, то откроем ордер на продажу
      if(bSignalSell() == true)
         vOrderOpenSell();
     }
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция проверки открытых оредров |
//+-----------------------------------------------------------------------------------------------+
bool bCheckOrders()
  {
// Переберем в цикле ордера, для проверки открытых ордеров данным советником
   for(int i = 0; i <= OrdersTotal(); i++)
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMagic)
            return(false);

   return(true);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция поиска сигнала на покупку |
//+-----------------------------------------------------------------------------------------------+
bool bSignalBuy()
  {
   if(dMA > Open[1] && dMA < Close[1])
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция поиска сигнала на продажу |
//+-----------------------------------------------------------------------------------------------+
bool bSignalSell()
  {
   if(dMA < Open[1] && dMA > Close[1])
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                            Функция открытия ордера на покупку |
//+-----------------------------------------------------------------------------------------------+
void vOrderOpenBuy()
  {
   int iOTi = 0;   // Тикет ордера

   iOTi = ReversOrderSend(Symbol(), OP_BUY, LOT(), Ask, iSlippage, 0, 0, "", iMagic, 0, clrNONE);

// Проверим открылся ли ордер
   if(iOTi > 0)
      // Есди да, то выставим уровни убытка и прибыли
      vOrderModify(iOTi);
   else
      // Если нет, то получим ошибку
      vError(GetLastError());
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                            Функция открытия ордера на продажу |
//+-----------------------------------------------------------------------------------------------+
void vOrderOpenSell()
  {
   int iOTi = 0;   // Тикет ордера

   iOTi = ReversOrderSend(Symbol(), OP_SELL, LOT(), Bid, iSlippage, 0, 0, "", iMagic, 0, clrNONE);

// Проверим открылся ли ордер
   if(iOTi > 0)
      // Есди да, то выставим уровни убытка и прибыли
      vOrderModify(iOTi);
   else
      // Если нет, то получим ошибку
      vError(GetLastError());
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                                    Функция модификации ордера |
//+-----------------------------------------------------------------------------------------------+
void vOrderModify(int iOTi)
  {
   int    iOTy = -1;   // Тип ордера
   double dOOP = 0;    // Цена открытия ордера
   double dOSL = 0;    // Стоп Лосс
   int    iMag = 0;    // Идентификатор советника

   double dSL = 0;     // Уровень убытка
   double dTP = 0;     // Уровень прибыли

// Выберем по тикету открытый ордер, получим некоторые значения
   if(OrderSelect(iOTi, SELECT_BY_TICKET, MODE_TRADES))
     {
      iOTy = OrderType();
      dOOP = OrderOpenPrice();
      dOSL = OrderStopLoss();
      iMag = OrderMagicNumber();
     }

// Если ордер открыл данный советник, то входим в условие
   if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMag)
     {
      // Если Стоп Лосс текущего ордера равен нулю, то модифицируем ордер
      if(dOSL == 0)
        {
         if(iOTy == OP_BUY)
           {
            dSL = NormalizeDouble(dOOP - iStopLoss * Point, Digits);
            dTP = NormalizeDouble(dOOP + iTakeProfit * Point, Digits);

            bool bOM = OrderModify(iOTi, dOOP, dSL, dTP, 0, clrNONE);
           }

         if(iOTy == OP_SELL)
           {
            dSL = NormalizeDouble(dOOP + iStopLoss * Point, Digits);
            dTP = NormalizeDouble(dOOP - iTakeProfit * Point, Digits);

            bool bOM = OrderModify(iOTi, dOOP, dSL, dTP, 0, clrNONE);
           }
        }
     }
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                                      Функция обработки ошибок |
//+-----------------------------------------------------------------------------------------------+
void vError(int iErr)
  {
   switch(iErr)
     {
      case 129:   // Неправильная цена
      case 135:   // Цена изменилась
      case 136:   // Нет цен
      case 138:   // Новые цены
         Sleep(1000);
         RefreshRates();
         break;

      case 137:   // Брокер занят
      case 146:   // Подсистема торговли занята
         Sleep(3000);
         RefreshRates();
         break;
     }
  }
//+-----------------------------------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double LOT()
  {
   int n=0;
   double OL=dLots;
   for(int j = OrdersHistoryTotal()-1; j >= 0; j--)
     {
      if(OrderSelect(j, SELECT_BY_POS,MODE_HISTORY))
        {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMagic)
           {
            if(OrderProfit()<0)
              {
               if(n==0)
                  OL=NormalizeDouble(OrderLots()*K_Martin,DigitsLot);
               n++;
               if(n>=OrdersClose)
                 {
                  Comment("1");
                  return(dLots);
                 }
              }
            else
              {
               if(n==0)
                 {
                  Comment("2");
                  return(dLots);
                 }
               else
                 {
                  Comment("3");
                  return(OL);
                 }
              }
           }
        }
     }
   return(OL);
  }
//------------------------------------------------------------------
int ReversOrderSend (string symbol,int cmd,double volume,double price,int slippage,double stoploss,double takeprofit,string comment,int magic=0,datetime expiration=0,color arrow_color=CLR_NONE)
{
int Ret=0;
double sprd=MarketInfo(symbol,MODE_SPREAD)*Point;
//Print ("----------------------------",sprd);
if (ReversOrder==0) // Открываем ордера без разворота
{
Ret=OrderSend (symbol,cmd,volume,price,slippage,stoploss,takeprofit,comment,magic,expiration,arrow_color);
}
if (ReversOrder==1)
{
///////////////
if (cmd==OP_SELLSTOP) // Переворачиваем ордера OP_SELLSTOP
{
Ret=OrderSend (symbol,OP_BUYLIMIT,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUYSTOP) // Переворачиваем ордера OP_BUYSTOP
{
Ret=OrderSend (symbol,OP_SELLLIMIT,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
///////////////
if (cmd==OP_SELL) // Переворачиваем ордера OP_SELL
{
Ret=OrderSend (symbol,OP_BUY,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUY) // Переворачиваем ордера OP_BUY
{
Ret=OrderSend (symbol,OP_SELL,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
//////////////
if (cmd==OP_SELLLIMIT) // Переворачиваем ордера OP_SELLLIMIT
{
Ret=OrderSend (symbol,OP_BUYSTOP,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUYLIMIT) // Переворачиваем ордера OP_BUYLIMIT
{
Ret=OrderSend (symbol,OP_SELLSTOP,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
}
return (Ret);
}
Предлагаю функцию реверса ордеров, для сливающих советников.
Предлагаю функцию реверса ордеров, для сливающих советников.
  • 2010.08.24
  • www.mql5.com
Помню, поначалу сталкивался с вопросом, как грамотно "перевернуть" ордера с покупки на продажу и наоборот...
 
Alexey Viktorov:

Я уже всё сказал достаточно понятно. Ну для тебя лично спрошу

Вот две функции и обе перебирают исторические ордера

Два цикла по одним и тем-же ордерам. За один цикл получить всё что возвращают эти функции никак?

Алексей, я уже писал, я знаю что ты хороший программист!

Но я не программист и то, что для тебя "достаточно понятно", для меня темный лес...

А по поводу двух циклов, то для меня "За один цикл получить всё " никак, т.к. они возвращают разные типы данных.

 
MakarFX:

Алексей, я уже писал, я знаю что ты хороший программист!

Но я не программист и то, что для тебя "достаточно понятно", для меня темный лес...

А по поводу двух циклов, то для меня "За один цикл получить всё " никак, т.к. они возвращают разные типы данных.

возвращаемые типы не при чем. Если есть 2 цикла по одинаковым данным с разными проверками и фильтрами, то всегда можно все засунуть в один цикл, но код будет читать не так понятно, а вот работать должен быстрей) На этапе отладки не делаю все в одном цикле. В разных баги легче искать.

 
MakarFX:

Алексей, я уже писал, я знаю что ты хороший программист!

Но я не программист и то, что для тебя "достаточно понятно", для меня темный лес...

А по поводу двух циклов, то для меня "За один цикл получить всё " никак, т.к. они возвращают разные типы данных.

Вариантов два.

  1. Переменные сделать на глобальном уровне. Тогда они будут доступны во всех функциях.
  2. Передать локальную переменную по ссылке. Тогда при изменении этой переменной будет изменена и та локальная переменная.
    /********************Script program start function*******************/
    void OnStart()
     {
      int a = 0;
      f_0(a);
      Print(a);
     }/******************************************************************/
    
    void f_0(int & b)
     {
      b = 100;
     }
    и таких переменных может быть, дай Бог не соврать, до 64. Если не так кто-то меня поправит.
  3. Внимательно и почаще читай документацию. Об этом во всех подробностях там написано.
 
MakarFX:

Пробуй, спрашивай

Первый результат. есть конфликт между валютными парами по выставлению советником отложенных ордеров. например кинул отложку по EURUSD, советник отработал по алгоритму(Buy по цене 1,18901 открыта сделка, советник выставил стоп 1,18751 и тейк 1,19051 и отложку на селл по цене 1,18751) всё ок по задуманному.

Но пришло время открыть сделку по GBPUSD там цены другие и советник всё делает правильно, за исключением выставления отложенного ордера. Сработала отложка Sell 1,39393 советник включился в работу, выставил стоп 1,39633  и тейк 1,39153, а вот отложенника на покупку по цене 1,39633 он полностью продублировал с EURUSD и выставил  отложку на селл по цене 1,18751)

Ещё проблему только что обнаружил: по открытой сделке по EURUSD сработал стоп по 1,18751 и отложенник sell открылся к которому советник выставил стоп 1,18901 и тейк  1,18595. Советник не прибавил к тейку сработанный стоп, который в истории. 

Вот такие проблемы.

 
законопослушный гражданин:

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

к сову пытаюсь прикрутить переворот сделок

Что Вы имеете ввиду? Определённый диапазон цен от которых покупаете/продаёте?Советник сделки "переворачивает".

 
SGarnov:

Добрый день. Помогите с советником. По стратегии если сработал стоп, то к следующему выставленному тейку советник должен его прибавить (количество пунктов)
из истории по ID, но он не прибавляет почему то.

Что не так в коде?

if(isLimitOn && OrderSelect(OrderMagicNumber(), SELECT_BY_TICKET, MODE_HISTORY)){
            tpc += stop_loss;
            if(OrderSelect(lastMagic, SELECT_BY_TICKET)){
               if(OrderType() == OP_BUY) {
                  double tp_price = NormalizeDouble((OrderOpenPrice() + Point() * (tp + tpc)), Digits);
                  if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), tp_price, OrderExpiration()))
                     Print("Ошибка модификации ордера:", GetLastError());
               }else if(OrderType() == OP_SELL){
                  double tp_price = NormalizeDouble((OrderOpenPrice() - Point() * (tp + tpc)), Digits);
                  if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), tp_price, OrderExpiration()))
                     Print("Ошибка модификации ордера:", GetLastError());
               }
            }
               
            isLimitOn = false;
         }

Макар правильно обратил внимание на OrderMagicNumber(), но не правильно понял ошибку. Прочтите в документации синтаксис этой функции… тут должен быть или индекс в списке ордеров, или тикет конкретного ордера, но никак не магик. И OrderTicket() тут не поможет. Не пытайтесь это туда всунуть.

 
SGarnov:

Что Вы имеете ввиду? Определённый диапазон цен от которых покупаете/продаёте?Советник сделки "переворачивает".

автор кода как я понял, предлагал следующее:

если сов открывает сделку buy со стопом и тейком, то его кусок кода открывает сделку в sell в то же время в том же месте (с учетом спреда) так же со стопом и тейком вместо сделки buy .

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

именно это мне и нужно

 
MakarFX:

Опиши в двух словах что ты хочешь от этого советника(логику работы),

а то мне кажется у тебя много лишнего в коде или я чего-то не понимаю.

сов должен по своему алгоритму открывать сделки

если стоп, то следующая сделка с мартином, и так до указанного мной количества умножений (функция - OrdersClose  = .....;).

далее если сов. выключился вместе с терминалом, просто кнопкой "авто-торгвля", другим совом, то следующий запуск работы начинается со стартового лота, а не с последнего увеличенного мартингейлом.

еще неплохо было бы к нему расписание "прикрутить", но эта мысль только сейчас в голову пришла.

к примеру: включился в понедельник в 10-00 со стартового лота, в течение дня выключился при достижении определенного результата, утром во вторник снова включился в 10-00 и снова начал со стартового лота.

всё.

Причина обращения: