新人对MQL4和MQL5的任何问题,对算法和代码的帮助和讨论 - 页 1548

 
SGarnov:

为了方便起见,拿我的源代码来说,它的逻辑是可行的,除了我描述的问题,我不太明白,我的脑袋在沸腾,但我没有任何进展。

你是下一个挂单 还是两个不同方向的挂单
 
SGarnov:
我有一种感觉,机器人越来越强大,我不不喜欢它,当我下订单或不想交易时,因为我已经下了,我不能打开它,因为我已经下了,它只需要打开订单。

@MakarFX已经在做了。让我们不要碍手碍脚。

我想说的是......写所有的东西,让它对你来说很清楚(个人/个人),不要用复制粘贴的方式拉动代码。

和一个大大简化的机器人骨架看起来像这样。

int ticket=-1;             // тикет открытого ордера
bool inited=false;      // признак завершения инициализации

int OnInit()
{
   ticket=-1;
   inited=false;
   // ещё надо проверить параметры, но пока чёрт с ними
   // пробуем загрузить прежнее состояние
   if (LoadState()) {
      // из файла, базы или глоб.переменных загрузились
      if (!CheckState()) {
         // проверили, плохо всё..
         ClearState(); // удалить и поругаться
         Alert("Усё пропало, шеф !");
         return INIT_FAILED();
      }
   }
   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
   if (inited) {
      // инициализация была проведена, стейт мог уже менятся во время работы
      SaveState(); // сохраняем куда-то там
   }
}

void OnTick()
{
   //// ЧТОБЫ БЫ БЫЛО ХОРОШО, 
   //// НЕ БОЛЕЕ 1-го ПРИКАЗА Open/Close/Modify на тик
   //// И ЗАВЕРШИТЬ ВСЁ ПО БЫСТРОМУ
   if (!inited) {
      // связь есть, тики идут
      // довести инициализацию до нужной кондиции
      if (!DoInit()) {
         // не довелась
         Alert("вот же блин...");
         ExpertRemove();
      } else {
         // в DoInit проставлен корректный ticket
         inited=true;
      }
      return;
   }
   // всё проиничено, ticket или -1 если нет нифига или реально тикет
   //// РАЗБОРЫ С ТИКЕТАМИ
   if (ticket<0) {
      // нет открытых ордеров
      // может открыть/переоткрыть ?
   } else {
      if (!OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) {
         // что-то не так с синхронизацией, просто пропустим тик
         return;
      }
      if (OrderCloseTime()!=0) {
         // ордер закрылся ручками или по стопам/тейкам (или стопаут, приплыли)
         OnCloseOrder();   // обработать, разобраться
         ticket=-1;        // нет у нас больше тикета..
         // в этот тик больше не успеть
         return;
      } else {
         if ((OrderStopLoss()==0 && SL!=0) || (OrderTakeProfit()==0 && TP!=0)) {
            // свежачок - надо ему выстаить Тейк и/или стоп
            
         } else {
            // для реала - проверять сработку Sl/Tp на ГЕПАХ, ЭТО ВАЖНО
         }
      }
   }
   //// РАЗБОРЫ с БАРАМИ
   CheckForOnBar();
   ///  и так далее...
}
void OnTimer()
{
   // тики завершаем быстро-быстро, поэтому открытия баров дополнительно проверяем по таймеру
   CheckForOnBar();
}

啤酒能创造奇迹,让人们变得更善良。)

 
MakarFX:
你是下一个挂单 还是两个不同方向的挂单
我总是下一个待定订单
 
SGarnov:
我总是放出一个待定的单子。

试一试,求一求

//+------------------------------------------------------------------+
//|                                                   SGarnov.v2.mq4 |
//|                                           Copyright 2020, DrMak. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, DrMak."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//--- input parameters
input int      T_Profit = 2;     // Коэффициент Take Profit
input int      S_Loss   = 200;   // Уровень Stop Loss
input double   O_Lots   = 0.01;  // Лоты
input int      SL_Count = 2;     // Количество убыточных ордеров
input int      Slippage = 30;    // Проскальзывание
input int      N_Magic  = 888;   // Magic

datetime T_Start;
double sl_price,tp_price,t_profit,s_loss;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- 
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   t_profit = S_Loss*T_Profit;
   tp_price = NormalizeDouble(t_profit * Point(), Digits)+GetPointLoss();
//---
   s_loss   = MathMax(S_Loss, MarketInfo(_Symbol, MODE_STOPLEVEL));
   sl_price = NormalizeDouble(s_loss * Point(), Digits);

   // Удаляем отложенный ордер после профита
   if(CountOrders(-1)==1) DeletePending();
   // Проверяем серию убыточных ордеров
   if(GetLossOrders()<=SL_Count)
     {
      // Устанавливаем отложенный ордер
      SendPending();
     }

   // Проверяем наличие ордеров BUY
   if(CountOrders(0)>0)
     {
      // Устанавливаем StopLoss/TakeProfit
      ModifyOrder();
     }

   // Проверяем наличие ордеров SELL
   if(CountOrders(1)>0)
     {
      // Устанавливаем StopLoss/TakeProfit
      ModifyOrder();
     }
  }
//+------------------------------------------------------------------+
//| Модификация ордера                                               |
//+------------------------------------------------------------------+
void ModifyOrder()
  {
   int ticket=0;
   for(int pos=OrdersTotal()-1;pos>=0;pos--)
     {
      if(OrderSelect(pos,SELECT_BY_POS)==true)
        {
         if(OrderSymbol()==_Symbol)
           {
            if(OrderStopLoss()==0)
              {
               if(OrderType()==OP_BUY)
                 {
                  if(OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-sl_price, OrderOpenPrice()+tp_price, OrderExpiration()))
                    {Print("Ордер модифицирован");}
                  else
                    {Print("Ошибка модификации ордера:", GetLastError());}
                 }
               if(OrderType()==OP_SELL)
                 {
                  if(OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+sl_price, OrderOpenPrice()-tp_price, OrderExpiration()))
                    {Print("Ордер модифицирован");}
                  else
                    {Print("Ошибка модификации ордера:", GetLastError());}
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Подсчет ордеров по типу                                          |
//+------------------------------------------------------------------+
//|  0 - ордера типа BUY          1 - ордера типа SELL               |
//|  2 - ордера типа BUYLIMIT     3 - ордера типа SELLLIMIT          |
//|  4 - ордера типа BUYSTOP      5 - ордера типа SELLSTOP           |
//|  6 - ордера типа Balance     -1 - Все типы ордеров               |
//+------------------------------------------------------------------+
int CountOrders(int or_ty=-1) 
  {
   int cnt=0;
   for(int pos=OrdersTotal()-1;pos>=0;pos--)
     {
      if(OrderSelect(pos,SELECT_BY_POS)==true)
        {
         if(OrderSymbol()==_Symbol)
           {
            if(or_ty<0 || or_ty==OrderType()) cnt++;
           }
        }
     }
   return(cnt);
  }
//+------------------------------------------------------------------+
//| Установка отложенного ордера                                     |
//+------------------------------------------------------------------+
void SendPending()
  {
   double op=0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS)==true)
        {
         if(CountOrders(-1)==1)
           {
            if(OrderType()==OP_BUY)
              {
               if(OrderStopLoss() != 0)
                 {
                  op=OrderStopLoss();
                  if(OrderSend(_Symbol,OP_SELLSTOP,O_Lots,op,Slippage,0,0,NULL,N_Magic))
                    {Print("Отложенный ордер установлен");}
                  else
                    {Print("Ошибка установки отложеного одера: ", GetLastError());}
                 }
              }
            if(OrderType()==OP_SELL)
              {
               if(OrderStopLoss() != 0)
                 {
                  op=OrderStopLoss();
                  if(OrderSend(_Symbol,OP_BUYSTOP,O_Lots,op,Slippage,0,0,NULL,N_Magic))
                    {Print("Отложенный ордер установлен");}
                  else
                    {Print("Ошибка установки отложеного одера: ", GetLastError());}
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Удаление отложенного ордера                                      |
//+------------------------------------------------------------------+
void DeletePending()
  {
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      if(OrderSelect(i, SELECT_BY_POS)==true)
        {
         if(CountOrders(-1)==1)
           {
            if(OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP)
              {
               if(OrderMagicNumber() == N_Magic)
                 {
                  if(OrderDelete(OrderTicket()))
                    {Print("Отложенный ордер удален");}
                  else
                    {Print("Ошибка удаления отложеного одера: ", GetLastError());}
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Возвращает время начала цикла                                    |
//+------------------------------------------------------------------+
datetime TimeStart()
  {
   datetime ts=0;
   if(OrdersTotal()!=0)
     {
      for(int pos=OrdersTotal()-1;pos>=0;pos--)
        {
         if(OrderSelect(pos,SELECT_BY_POS)==true)
           {
            if(OrderSymbol()==_Symbol)
              {
               if(OrderMagicNumber()!=N_Magic)
                 {
                  ts=OrderOpenTime();
                 }
              }
           }
        }
     }
   else
   if(OrdersTotal()==0)
     {
      for(int pos=0; pos<OrdersHistoryTotal(); pos++)
        {
         if(OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY))
           {
            if(OrderSymbol()==_Symbol)
              {
               if(OrderType()==OP_BUY || OrderType()==OP_SELL)
                 {
                  if(OrderProfit()>0)
                    {
                     if(ts<OrderCloseTime())
                       {
                        ts=OrderCloseTime();
                       }
                    }
                 }
              }
           }
        }
     }
   return(ts);
  }
//+------------------------------------------------------------------+
//|  Возвращает пункты убытка закрытых ордеров с начала цикла        |
//+------------------------------------------------------------------+
double GetPointLoss()
  {
   double result=0,b=0,s=0;;
   int i=OrdersHistoryTotal();
   for(int pos=0; pos<i; pos++)
     {
      if(OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY))
        {
         if((OrderSymbol()==_Symbol))
           {
            if(OrderType()==OP_BUY || OrderType()==OP_SELL)
              {
               if(OrderProfit()<0)
                 {
                  if(OrderCloseTime()>TimeStart())
                    {
                     if(OrderType()==OP_BUY&&OrderProfit()<0)
                       {
                        b+=OrderOpenPrice()-OrderClosePrice();
                       }
                     if(OrderType()==OP_SELL&&OrderProfit()<0)
                       {
                        s+=OrderClosePrice()-OrderOpenPrice();
                       }
                    }
                 }
              }
           }
        }
     }
   return(b+s);
  }
//+------------------------------------------------------------------+
//|  Возвращает кол-во серии убыточных ордеров                       |
//+------------------------------------------------------------------+
int GetLossOrders()
  {
   int cnt=0;
   int i=OrdersHistoryTotal();
   for(int pos=0; pos<i; pos++)
     {
      if(OrderSelect(pos, SELECT_BY_POS, MODE_HISTORY))
        {
         if((OrderSymbol()==_Symbol))
           {
            if(OrderCloseTime()>TimeStart())
              {
               if(OrderProfit()<0) cnt++;
              }
           }
        }
     }
   return(cnt);
  }
//+------------------------------------------------------------------+
 
MakarFX:

试一试,求一求

它已经启动并运行,我会告诉你的,谢谢你的帮助。
 
SGarnov:
我会让你知道发生了什么。谢谢你的帮助。

谁能解释一下这种行为的原因?

我开了一个订单

2021.07.29 18:53:57.436 '60744458': order was opened : #1639674290 sell 0.01 USDJPY at 109.519 sl: 0.000 tp: 0.000

那么专家顾问就会修改它

2021.07.29 18:53:57.647 '60744458': modify order #1639674290 sell 0.01 USDJPY at 109.519 sl: 0.000 tp: 0.000 -> sl: 109.919 tp: 108.719

然后发生了这样的事情

2021.07.29 18:53:58.313 '60744458': order #1639674290 sell 0.01 USDJPY closing at 0.000 failed [Off quotes]
2021.07.29 18:53:57.647 '60744458': close order #1639674290 sell 0.01 USDJPY at 109.519 sl: 0.000 tp: 0.000 at price 0.000

有趣的是,它发生在美元兑日元上,而在其他货币对上只卖出。

 
MakarFX:

谁能解释一下这种行为的原因?

我开了一个订单

那么专家顾问就会修改它

然后发生了这样的事情

有趣的是,它只发生在USDJPY上,而其他的都是好的。

如果你想了解一些东西,你必须学会如何在最小的周期内获得最大的有用信息......

 
Alexey Viktorov:

要理解一件事,就要学会如何在最少的周期内拉出最有用的信息......

当你知道该怎么做的时候,就好说话了......

帮助提供关于如何 "从有用的信息中获得最大利益 "的建议

 
MakarFX:

谁能解释一下这种行为的原因?

我开了一个订单

那么专家顾问就会修改它

然后发生了这样的事情

有趣的是,它发生在美元兑日元上,而在其他货币对上只卖出。

你写的代码的顾问是这样工作的吗?
 
SGarnov:
你写的那个EA的代码是这样工作的吗?
这很好,问题出在终端。