Dividere le posizioni aperte in gruppi - pagina 3

 

Urrà, credo di aver raggiunto un risultato accettabile.

L'array si riempie con i dati richiesti man mano che le posizioni vengono aperte.

Se eseguo l'EA nel tester, posso vedere le prime quattro voci nei commenti, se il tester è a bassa velocità, e si usa una pausa - tutto è chiaro.

Allego il file con il codice.

Ora provo a scherzare con la prima condizione e assegno N_Caste = 1 alle posizioni che soddisfano questa condizione;

Le critiche sono benvenute.

Grazie a tutti non indifferente.

File:
Sower_1_3.mq5  21 kb
 
Nikolay Kositsin:

... Queste cose sono o auto-scritte o commissionate da freelance.

Mi dispiace, non sono riuscito a superarlo. Non ci sono cose del genere?

 

Buonanotte.

Come seguito ai messaggi di cui sopra - ha insegnato all'EA a creare un array bidimensionale, inserirvi i valori del ticket e del rank per ogni posizione, man mano che le posizioni si aprono.

In futuro, quando arriveranno segnali o condizioni, i ranghi delle posizioni corrispondenti cambieranno. Questo è il modo in cui ho intenzione di gestire le posizioni.

C'è un problema - chiedo ai professionisti di rispondere. Aiutatemi a gestire la cancellazione di elementi dall'array.

Man mano che le posizioni vengono chiuse, le élite si accumulano nell'array, che memorizza il biglietto e il rango di una posizione"morta" già chiusa, come rimuovere non lo so.

L'operazione su pp. 172-173 non funziona.

         if(dead_pos)ArrayRemove(Arr_Position,e,2);
         ArrayResize(Arr_Position,All_Position);

In OnTick() ad ogni candela, le posizioni vengono aperte, i loro stop vengono modificati, i loro tick vengono inseriti in una matrice e viene assegnato il rango zero originale.

Man mano che gli arresti si innescano, l'array accumula elementi inutili. Per chiarezza ho emesso i commenti necessari e tutto è visibile online.

Il codice è piccolo, quindi lo posterò qui e allegherò anche il file.

Per favore, aiutatemi a organizzare la pulizia dell'array.

//+------------------------------------------------------------------+
//|                                                        Sower_1_6 |
//|                                              Sergei Voicehovskii |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Sergei Voicehovskii"
#property link      "https://www.mql5.com"
#property version   "1.00"
//---
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\HistoryOrderInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\TerminalInfo.mqh>
#include <Trade\Trade.mqh>
#include <Arrays\ArrayInt.mqh>
//---
CAccountInfo      m_account;
CDealInfo         m_deal;
CHistoryOrderInfo m_history;
COrderInfo        m_order;
CPositionInfo     m_position;
CSymbolInfo       m_symbol;
CTerminalInfo     m_terminal;
CTrade            m_trade;
CArrayInt         m_array;
//---
#define  observations 2
int  Arr_Position[][observations];
int  Array_Change[];
//--- input parameters
input int      SL                      = 50;
input int      TP                      = 50;
input double   Lot                     = 0.01;
input double   InpCloseProfit_money    = 5.0;   
input double   InpCloseProfit_points   = 50.0;   
input double   InpCloseProfit_percent  = 3.0;   
input ulong    InpDeviation            = 10;    
input bool     InpPrintLog             = true;
input bool     InpCommentLog           = true;
input ulong    Magic                  = 557755; 
//---
      int   stoploss    = SL;   
      int   takeprofit  = TP;
      ulong slippage    = InpDeviation;
      
      datetime Time_OpenPos;
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Обновляем данные
   Refresh_Rates();
//--- Устанавливаем символ
   m_symbol.Name(_Symbol);
//--- Устанавливаем Magic
   m_trade.SetExpertMagicNumber(Magic);
//--- Определяем режим расчета маржи    
   m_trade.SetMarginMode();
//--- Определяем режим исполнения ордеров    
   m_trade.SetTypeFillingBySymbol(m_symbol.Name());
//--- Устанавливаем максимальное отклонение от запрашиваемой цены   
   m_trade.SetDeviationInPoints(slippage);
//---
   ArrayFree(Arr_Position);  
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   if(Checking_NewBar())
   {
//+---Открываем начальные позиции "свежего" бара       
      m_trade.Buy(0.01);
      m_trade.Sell(0.01);
//+---Выставляем стопы начальных позиций       
      ModifySLTP_1_range(stoploss,takeprofit,Magic);
//+---Заполняем массив c тикет/кастой позиций 
      int N = Array_Creating_Caste_Positions();
//+--- 
      int R = ArrayRange(Arr_Position,0)-1;
      if(R<30)R=0;else R=30;
      int tic = Arr_Position[R][0];
      if(m_position.SelectByTicket(tic))
      Time_OpenPos = m_position.Time();
      int P = PositionsTotal();
      
      if(InpCommentLog){
         Comment("Выводим данные \n"
         "ticket:                       ",tic,"\n"
         "Время открытия позиции:       ",Time_OpenPos,"\n"
         "Сколько элементов в массиве:  ",R+1,"\n"
         "Проверок тикета за проход:  ",N,"\n"
         "Ввсего открыто позиций:       ",P,"\n"
         //"Время жизни позиции (стр): ",structura_time.year," год. ",structura_time.mon," мес. ",structura_time.day," дн. ",structura_time.hour," час. ",structura_time.min," мин. ",structura_time.sec," сек. \n"
         );}
//---
      ArrayPrint(Arr_Position); 
//---
   }
//---
}
//+------------------------------------------------------------------+
int Array_Creating_Caste_Positions()
{
   int  n           = 0;
   long ticket      = 0;
   bool new_pos     = true;
//---Запись новых тикетов в массив позиций        
   int All_Position = PositionsTotal();
   int Array_Size   = ArrayRange(Arr_Position,0);
//---  
   for(int i = 0; i < All_Position; i++)
      {
      if(m_position.SelectByIndex(i))
         {
            ticket  = PositionGetInteger(POSITION_TICKET);
            new_pos = true;
         }
      for(int e = 0; e < Array_Size; e++)
         {
            if(Arr_Position[e][0]==ticket)
               {
                  new_pos = false;
                  n++;
                  break;
               }
         }
      if(new_pos){
      int New_Size = Array_Size+1;
      ArrayResize(Arr_Position,New_Size,0);
         Arr_Position[Array_Size][0] = (int)ticket;//Ticket
         Arr_Position[Array_Size][1] = 0;//Number_Caste (0 = начальные позиции)
         n++;}                       
      }
//---Удаление из массива мёртвых тикетов 
      Array_Size   = ArrayRange(Arr_Position,0);
      All_Position = PositionsTotal();
//---      
      for(int e = 0; e < Array_Size; e++)
      {
         int tickt = Arr_Position[e][0];
         bool dead_pos = true;
         
         for(int i = 0; i < All_Position; i++)
         {
            if(m_position.SelectByIndex(i))
               {
                  if(tickt == PositionGetInteger(POSITION_TICKET))
                     {
                        dead_pos = false;
                        n++;
                        break;
                     }   
               }
         }
         if(dead_pos)ArrayRemove(Arr_Position,e,2);
         ArrayResize(Arr_Position,All_Position);
      }
//---     
return(n);
}
//+------------------------------------------------------------------+
//Проверка на наличие нового бара
//+------------------------------------------------------------------+
bool Checking_NewBar()
{
//--- переменная для возврата функции
   bool new_bar_opened = false;
//--- статическая переменная для хранения времени открытия последнего бара 
   static datetime last_bar_time=0; 
//--- если статическая переменная еще неинициализирована 
   if(last_bar_time==0) 
     { 
      //--- это первый вызов, запишем время открытия и выйдем 
      last_bar_time=(datetime)SeriesInfoInteger(_Symbol,Period(),SERIES_LASTBAR_DATE); 
      if(InpPrintLog)
      PrintFormat("Инициализировали переменную last_bar_time значением %s",TimeToString(last_bar_time)); 
     } 
//--- получим время открытия последнего бара по своему символу 
   datetime curr_time=(datetime)SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE); 
//--- если время открытия текущего бара не совпадает с тем, что хранится в last_bar_time то открылся новый бар
   if(curr_time!=last_bar_time) 
     { 
      new_bar_opened = true;
      //--- запомним время открытия нового бара в статической переменной 
      last_bar_time=curr_time; 
      //--- выведем сообщение об этом событии 
      if(InpPrintLog)
      PrintFormat("На символе %s открылся новый бар в %s",_Symbol,TimeToString(TimeCurrent())); 
     } 
return(new_bar_opened);   
} 
//+------------------------------------------------------------------+
//Обновление котировок
//+------------------------------------------------------------------+
bool Refresh_Rates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
     {
      if(InpPrintLog)
         Print(__FILE__," ",__FUNCTION__,", ERROR: ","RefreshRates error");
      return(false);
     }
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
     {
      if(InpPrintLog)
         Print(__FILE__," ",__FUNCTION__,", ERROR: ","Ask == 0.0 OR Bid == 0.0");
      return(false);
     }
//---
   return(true);
  }

//+------------------------------------------------------------------+
void ModifySLTP_1_range(int    stplss, 
                        int    tkprfit, 
                        ulong  mgc)
{
      double sl     = 0.0,
             tp     = 0.0;      
      double slbuy  = 0.0,
             slsell = 0.0,
             tpbuy  = 0.0,
             tpsell = 0.0;
             
      Refresh_Rates();
      
      if(stplss>0)
      {
       slbuy  = m_symbol.Bid() - stplss*m_symbol.Point();
       slsell = m_symbol.Ask() + stplss*m_symbol.Point();
      }
      if(tkprfit>0)
      { 
       tpbuy  = m_symbol.Bid() + tkprfit*m_symbol.Point();    
       tpsell = m_symbol.Ask() - tkprfit*m_symbol.Point();
      }

      for(int i=PositionsTotal()-1;i>=0;i--)
      {
         if(m_position.SelectByIndex(i))
         {
            if(m_position.Symbol()==Symbol())
            { 
                if(m_position.Magic() == mgc)
                {   
                     if(m_position.PositionType()==POSITION_TYPE_BUY)
                     {
                        sl = m_position.StopLoss()   > 0 ? m_position.StopLoss()   : slbuy;
                        tp = m_position.TakeProfit() > 0 ? m_position.TakeProfit() : tpbuy;
                              m_trade.PositionModify(m_position.Ticket(),NormalizeDouble(sl,Digits()),NormalizeDouble(tp,Digits()));
                     }
                     if(m_position.PositionType()==POSITION_TYPE_SELL)
                     {
                        sl = m_position.StopLoss()   > 0 ? m_position.StopLoss()   : slsell;
                        tp = m_position.TakeProfit() > 0 ? m_position.TakeProfit() : tpsell;
                              m_trade.PositionModify(m_position.Ticket(),NormalizeDouble(sl,Digits()),NormalizeDouble(tp,Digits()));
                     }
               }
            }
         }
      }
}  
//+------------------------------------------------------------------+
File:
Sower_1_6.mq5  20 kb
 

Per la chiarezza del processo è meglio mettere StLoss 0, TProf dovrebbe rimanere 50, e l'EA dovrebbe essere posizionato sul grafico orario di qualsiasi valuta. Questo è nel tester.

Sulla demo di onlan, ovviamente i minuti sono migliori

 
Sergey Voytsekhovsky:

Per la chiarezza del processo è meglio mettere StLoss 0, TProf dovrebbe rimanere 50, e l'EA dovrebbe essere posizionato sul grafico orario di qualsiasi valuta. Questo è nel tester.

Sulla demo di onlan, ovviamente i minuti sono migliori.

Santa Perdita † ©Sul tuo muro!

Sono caduto dalla sedia)

La perdita è inevitabile.

Hmmm... abbiamo qualcuno sull'argomento, beh †, già sul forum... )

 
onedollarusd:

Santa Perdita † © Sul tuo muro!

Sono caduto dalla sedia)

A quanto pare St.Loss è inevitabile.

Hmmm... qualcuno che abbiamo su un tale argomento, bene †, già sul forum... )

Sono d'accordo, sembra ridicolo. Ma è solo un modello per elaborare una parte dell'algoritmo. Sono contento di aver potuto migliorare il tuo umore.

Se non ti dispiace lanciare un link a ".... qualcuno su questo argomento, beh †, è già sul forum... "plz".

 
Sergey Voytsekhovsky:

Se non ti dispiace buttare un link a ".... qualcuno su un argomento come questo, beh †, è già sul forum... per favore".

E meglio ancora, ditemi se sapete come rimuovere elementi da un array bidimensionale, che non sono più necessari?

Mi ha rotto la testa, l'elenco ha cancellato i buchi. È un peccato che io non abbia il cervello per farlo.

 
Sergey Voytsekhovsky:

come rimuovere elementi da un array bidimensionale che non sono più necessari?

ArrayResize();

ArrayResize - Операции с массивами - Справочник MQL4
ArrayResize - Операции с массивами - Справочник MQL4
  • docs.mql4.com
При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера; в противном случае возвращает -1 и массив не меняет размеры. Функция может быть применена только к динамическим массивам. При этом необходимо иметь ввиду, что нельзя изменять размер для динамических массивов, назначенных в...
 
Sergey Voytsekhovsky:

Meglio ancora, se sapete come rimuovere elementi da un array bidimensionale che non sono più necessari.

Ho perso la testa, ho buttato a terra il libro di riferimento. È un peccato che io non abbia il cervello per farlo.

Copia dell'array "in sé", a partire dalla posizione accanto alla cancellata e scrittura a partire dalla cancellata. E poi ridimensionare come suggerito da Grigori.S.B

   int src_data[10];
   //--- Не важно как заполнен массив
   //--- Удалим индекс 4
   ArrayCopy(src_data, src_data, 4, 5);
   ArrayResize(src_data, ArraySize(src_data)-1);
Per una matrice a 2 dimensioni, moltiplicate il numero di riga da cancellare per 2. Per una matrice tridimensionale moltiplicare per 3...
 
Grigori.S.B:

ArrayResize();

Buongiorno, grazie per la risposta.

Immagino che non l'abbiate notato, potete guardare sopra, tutte le domande riguardavano MQL5.

Capisco che la differenza non è cruciale a volte, ma tuttavia. La funzione che hai citato ridimensiona l'array, forse tagliando elementi extra se la dimensione è ridotta.

Questo non è ciò che è necessario. È necessario rimuovere un elemento trovandolo per valore. Ho provato anch'io questa funzione, ne ho scritto nel #23. Grazie comunque.

Motivazione: