Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 189

 
Nikolai Semko:

È necessario eseguire il metodo Timer4 (evidenziato in blu) della classe CTestTimer

Non ci sono entrati.

#property indicator_chart_window
#include <Timer.mqh> // https://www.mql5.com/ru/code/31306

//+------------------------------------------------------------------+
class CTestTimer {
 private:
   //typedef void (CTestTimer::*TFunc2)(); // так работает в C++, но здесь не работает
 public:
   static int x4;
   CTestTimer() {
      //TFunc2 p=CTestTimer::Timer4;
      //TFunc2 p=Timer4;
      //timers.NewTimer(700,p);
      timers.NewTimer(700,Method2Function); // ошибка 'Timer4' - pointer to this function type is not supported yet
   };
   ~CTestTimer(){};
   static void Timer4() {
      x4++;
      if (x4==7) timers.KillTimer(Method2Function); // удаляем этот таймер
   }
};
//+------------------------------------------------------------------+

static int CTestTimer::x4 = 0;

void Method2Function()
{
  CTestTimer::Timer4();
}
 

Forum sul trading, sistemi di trading automatico e test di strategie di trading

Peculiarità di mql5, consigli e trucchi

fxsaber, 2020.05.14 02:57

L'ho preso di nuovo. Suppongo che questo possa accadere in rare situazioni quando si rifà il log.

La soluzione è, se falso, riprovare dopo una breve pausa.

bool IsTradeAllowed( const int Attempts = 0 )
{        
  // https://www.mql5.com/ru/forum/170952/page174#comment_16363677
  bool Res = false;
  int Count = 0;
  
  // https://www.mql5.com/ru/forum/170952/page174#comment_16363677
  while (!(Res = ::MQLInfoInteger(MQL_TRADE_ALLOWED) &&
                 ::AccountInfoInteger(ACCOUNT_TRADE_EXPERT) &&
                 ::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) &&
                 ::TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) &&
         (Count++ < Attempts) && !::IsStopped())
    ::Sleep(100);
    
  return(Res);
}

Questa è una cattiva soluzione. Ecco una soluzione molto migliore.

const bool Init = EventSetMillisecondTimer(1);

bool Allowed()
{
  return(::MQLInfoInteger(MQL_TRADE_ALLOWED) &&
         ::AccountInfoInteger(ACCOUNT_TRADE_EXPERT) &&
         (::AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) || !::TerminalInfoInteger(TERMINAL_CONNECTED)) &&
         ::TerminalInfoInteger(TERMINAL_TRADE_ALLOWED));
}

void OnTimer()
{
  if (!Allowed())
    ExpertRemove();
}

Se fai un re-login manuale, questo EA funzionerà ancora. Senza la stringa evidenziata, si autocancellerà.

 
fxsaber:

Non ci sono entrati.

Grazie per il vostro tempo. Ma ho scritto sopra che il metodo dovrebbe essere non statico. È chiaro che questo è possibile con i metodi statici. Un metodo statico non è affatto OOP.
Evidentemente volevo troppo, o piuttosto impossibile.
Ero confuso dal fatto che fosse possibile farlo in C++, ma esaminandolo, ho capito che un tale puntatore ha una struttura totalmente diversa,

https://habr.com/ru/post/333334/


Ed è comprensibile.

Un metodo di classe non statico ha una singola implementazione, che si trova da qualche parte in memoria e influisce su tutti gli oggetti della classe.
Ma ogni oggetto ha il suo stato corrente unico di variabili interne, quindi un tale puntatore a un metodo non statico deve anche avere una struttura di parametri compilata dell'oggetto a cui è applicato al momento.
Le mie scuse a tutti per la perdita di tempo.
Dobbiamo cercare altri modi per controllare in generale oggetti di classi diverse.

La prova che non c'è soluzione è anche una soluzione.

 
Nikolai Semko:

Grazie per il vostro tempo. Ma ho scritto sopra che il metodo dovrebbe essere non statico. È chiaro che questo è possibile con la statica.

Vi sono stati dati due esempi sopra. uno con l'implementazione completa
 
TheXpert:
Vi sono stati dati due esempi sopra. uno con l'implementazione completa

Sembra che tu non abbia capito il mio problema.
Non ha soluzione.

 
Nikolai Semko:

Sembra che tu non abbia capito il mio problema.
Non ha soluzione.

Perché sbattere la testa contro il muro quando c'è una porta accanto? Il problema del multitimer con una chiamata del gestore a una classe esterna è stato risolto.

Questo tizio qui ha una soluzione al tuo problema come lo vedi, non pubblica però.

 
TheXpert:
Perché sbattere la testa contro il muro quando c'è una porta accanto? Il compito del multitimer con una chiamata al gestore di una classe esterna è stato risolto.

Non era per il timer.
Stavo solo sognando ad occhi aperti ed ero stupido.

 
Nikolai Semko:

Stavo solo sognando ad occhi aperti e sono rimasto ammutolito.

Sono d'accordo per un typedef completo o gli stessi binding in mql, ma questo è tutto.

 

È possibile distinguere un oggetto grafico creato manualmente da un oggetto creato da un indicatore o EA?

Nella funzione

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
  {
   if(id == CHARTEVENT_OBJECT_CREATE)
     {

     }
  }
 
Vladimir Pastushak:

È possibile distinguere un oggetto grafico creato manualmente da un oggetto creato da un indicatore o EA?

Nella funzione

Puoi farlo con il controllo del tasto sinistro del mouse.
Per esempio così:

#property indicator_chart_window
#include <Timer.mqh> //https://www.mql5.com/ru/code/31306

uint t_LMB=0;
int OnInit() {
   ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,0,true);
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,const int begin,const double &price[]) {
   return(rates_total);
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) {
   static string str=sparam;
   if(str!="1" && sparam=="1") t_LMB=GetTickCount(); // нажате левая кнопка мышки
   if(id == CHARTEVENT_OBJECT_CREATE) {
      CheckManual(GetTickCount());
   }
   str=sparam;
}
//+------------------------------------------------------------------+
void CheckManual(uint start=0) {
   static uint s=0;
   if (start>0) {
      s=start;
      timers.NewTimer(20,Timer1); // Создаем таймер на 20 милисекунд и функцией-обработчиком Timer1()
      return;
   }
   int pause = int(t_LMB-s);
   if (pause>=0 && pause<20) Print("Создан графический объект в ручную");
   else Print ("Создан графический объект программно");
   timers.KillTimer(Timer1); // удаляем таймер Timer1
}
//+------------------------------------------------------------------+
void Timer1() {CheckManual();}