Tutte le domande dei nuovi arrivati su MQL4 e MQL5, aiuto e discussione su algoritmi e codici - pagina 1549

 
MakarFX:

È bene parlare quando si sa cosa fare...

aiutarmi con consigli su come "far uscire più informazioni utili possibili".

Ho detto tutto molto chiaramente. Beh, per te personalmente, lascia che te lo chieda.

Qui ci sono due funzioni ed entrambe passano attraverso gli ordini storici

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

Due cicli sugli stessi ordini. Non si può ottenere tutto ciò che queste funzioni restituiscono in un solo ciclo, giusto?

 

Ciao!

Sto cercando di aggiungere un'inversione di trade al gufo. Lo sto facendo come descritto nelle istruzioni: https://www.mql5.com/ru/forum/128200

Non ho errori durante la compilazione, ma il flip non funziona nel tester.

Il registro dà un errore:

2021.07.29 20:06:34.316 2015.01.08 22:10:00 SMA con codice flip through AUDUSD,M5: OrderSend error 130

2021.07.29 20:06:34.316 2015.01.08 22:05:45 SMA con inversione via AUDUSD,M5: OrderSend error 4107

2021.07.29 20:06:34.316 2015.01.08 22:05:45 SMA con flip via AUDUSD,M5: stoploss non valido per la funzione OrderSend

Potresti per favore dirmi qual è il problema qui?

Io stesso penso che le variabili specificate in

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)

Non sono legati al codice principale.

Ho provato in diversi terminali, 4 e 5 segni.

Ecco l'intero codice:

//+-----------------------------------------------------------------------------------------------+
//|                                                                     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:

L'ho già detto abbastanza chiaramente. Ti faccio una domanda personale.

Qui ci sono due funzioni ed entrambe fanno un ciclo di ordini storici

Ci sono due cicli sugli stessi ordini. Non si può ottenere tutto ciò che queste funzioni restituiscono in un solo ciclo, giusto?

Alexei, ho già scritto, so che sei un buon programmatore!

Ma io non sono un programmatore, e ciò che è "abbastanza chiaro" per te non lo è per me...

Per quanto riguarda i due cicli, per me"In un solo ciclo prendi tutto" non è possibile, perché restituiscono diversi tipi di dati.

 
MakarFX:

Alexey, ho già scritto, so che sei un buon programmatore!

Ma io non sono un programmatore e quello che è "abbastanza chiaro" per te è una foresta oscura per me...

Per quanto riguarda i due cicli, per me"ottenere tutto in un ciclo" non è possibile, perché restituiscono tipi di dati diversi.

I tipi restituiti non c'entrano niente. Se ci sono 2 loop sugli stessi dati con diversi controlli e filtri, si può sempre mettere tutto in un solo loop, ma il codice non si leggerà così chiaro, ma dovrebbe funzionare più velocemente) In fase di debug non faccio tutto in un solo loop. È più facile cercare i bug in diversi.

 
MakarFX:

Alexey, ho già scritto, so che sei un buon programmatore!

Ma io non sono un programmatore e quello che è "abbastanza chiaro" per te è una foresta oscura per me...

Per quanto riguarda i due cicli, per me"In un solo ciclo per ottenere tutto" non è possibile, perché restituiscono diversi tipi di dati.

Ho due opzioni.

  1. Creare variabili a livello globale. Poi saranno disponibili in tutte le funzioni.
  2. Passa la variabile locale per riferimento. Quindi se cambiate questa variabile, la variabile locale sarà cambiata.
    /********************Script program start function*******************/
    void OnStart()
     {
      int a = 0;
      f_0(a);
      Print(a);
     }/******************************************************************/
    
    void f_0(int & b)
     {
      b = 100;
     }
    E ci possono essere fino a 64 variabili di questo tipo, Dio non voglia che io menta. Se mi sbaglio, qualcuno può correggermi.
  3. Leggete la documentazione con più attenzione. È scritto lì in modo molto dettagliato.
 
MakarFX:

Ho un conflitto tra ordini pendenti.

Per esempio, ho piazzato un ordine pendente per EURUSD, l'EA ha seguito l'algoritmo (acquisto a 1.18901, posizione aperta, EA ha impostato lo stop a 1.18751, take profit a 1.19051 e ordine di vendita a 1.18751) tutto è ok come da programma.

Ma ora è il momento di aprire un'operazione su GBPUSD dove i prezzi sono diversi e l'EA sta facendo tutto bene, tranne che per impostare un ordine pendente. Un ordine di vendita a 1,39393 è scattato e l'EA ha cercato di aprirlo, impostare uno stop a 1,39633 e prendere 1,39153 ma l'ordine di acquisto a 1,39633 è completamente duplicato in EURUSD e un ordine di vendita a 1,18751)

Ho appena trovato un altro problema: uno stop a 1,18751 e un ordine pendente di vendita a 1,18901 e un take a 1,18595 sono scattati su un trade aperto su EURUSD. L'Expert Advisor non ha aggiunto lo stop attivato, che è nella storia.

Questi sono i problemi.

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

Ciao!

Sto cercando di avvitare un capovolgimento dei mestieri al gufo.

Cosa vuoi dire? Una certa gamma di prezzi da cui si compra/vende?

 
SGarnov:

Buon pomeriggio. Aiuto con l'EA. Secondo la strategia, se uno stop è scattato, allora l'EA dovrebbe aggiungere (il numero di punti) al prossimo set takeaway
dalla storia per ID, ma non lo fa per qualche motivo.

Cosa c'è di sbagliato nel codice?

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;
         }

Makar ha indicato correttamente OrderMagicNumber(), ma ha frainteso l'errore. Leggete la documentazione per la sintassi di questa funzione... dovrebbe essere o l'indice nella lista degli ordini o il biglietto di un certo ordine, ma non un magone. E OrderTicket() non aiuta in questo caso. Non cercate di metterlo lì.

 
SGarnov:

Cosa vuoi dire? Una certa fascia di prezzo da cui si compra/vende?

L'autore del codice, da quanto ho capito, ha suggerito quanto segue:

se owl apre un trade di acquisto con stop e take, allora il suo pezzo di codice apre un trade di vendita allo stesso tempo nello stesso posto (tenendo conto dello spread) anche con stop e take invece di un trade di acquisto.

quindi la logica di ricerca di un punto di entrata dell'EA non cambia, e cambia solo la direzione con spread preso in considerazione.

questo è esattamente ciò di cui ho bisogno

 
MakarFX:

Descrivi in poche parole cosa vuoi da questo EA (la logica di funzionamento),

Penso che tu abbia molte cose inutili nel tuo codice o che io non capisca qualcosa.

i gufi dovrebbero aprire i trade secondo il loro algoritmo

se lo stop, il prossimo commercio con un Martin, e così via fino al numero di moltiplicazioni che ho specificato (funzione -OrdersClose = .....;).

Inoltre, se il gufo è disabilitato insieme al terminale, basta premere il pulsante "auto-trade" con un altro gufo, poi il prossimo trade inizierà con il lotto di partenza, non con l'ultimo aumentato da una martingala.

Sarebbe anche bello potervi allegare un programma, ma questa idea mi è venuta in mente solo ora.

Per esempio: è stato attivato alle 10-00 di lunedì con il lotto di partenza, poi è stato spento durante il giorno quando è stato raggiunto qualche risultato, e il martedì mattina è stato attivato alle 10-00 ed è ripartito con il lotto di partenza.

Tutto.