Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 1219

 
Vladimir Karputov:

Похоже на то, что терминал продолжает подкачивать историю - соответственно индикатор всё время пересчитывается. Или другой вариант: в терминале у Вас выставлено ОЧЕНЬ большое число баров для отображения на графике, а Ваш компьютер ОЧЕНЬ 

Спасибо за помощь! 

При выборе другой даты, расчет происходит сразу. При первом тесте присутствовал разрыв в цене, возможно пропуск некоторых цен - скорее всего проблема в этом.

 

Здравствуйте! Есть индикатор для MT5 "Grid Builder", он рисует горизонтальные линии с шагом цены. Можно выбрать например 100п, 200п и тд. И строится горизонтальная сетка вверх и вниз с заданным шагом. Но у него одна  проблема, например, когда я  на таймфрейме  H4 рисую свою графические горизонтальные уровни( ставлю горизонтальные линии из инструментов рисования в терминале) и переключаю на любой другой таймфрейм, все мои линии удаляются. А остаются только горизонтальные уровни индикатора. Как в коде исправить эту ошибку? Чтобы мои горизонтальные уровни никогда не удалялись. Вот код индикатора.  (Вопрос писал уже в другой теме, но там пока ответа нету)

//+------------------------------------------------------------------+
//|                                                  GridBuilder.mq5 |
//|                                              Copyright 2015, AM2 |
//|                                     https://www.forexsystems.biz |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, AM2"
#property link      "https://www.forexsystems.biz"
#property version   "1.00"
#property indicator_chart_window

//---- для расчёта и отрисовки индикатора использовано ноль буферов
#property indicator_buffers 0
//---- использовано всего ноль графических построений
#property indicator_plots   0
//--- входные параметры 
input int count = 50;      //количество линий вверх вниз от цены
input int step  = 333;     //шаг линий 
input double pr = 1.4622;  //цена от которой пляшем
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   ObjectsDeleteAll(0,0,OBJ_HLINE);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
   ObjectsDeleteAll(0,0,OBJ_HLINE);
  }
//+------------------------------------------------------------------+ 
//| Создает горизонтальную линию                                     | 
//+------------------------------------------------------------------+ 
bool HLine(const string name="HLine",double price=0)
  {
//--- создадим горизонтальную линию 
   if(!ObjectCreate(0,name,OBJ_HLINE,0,0,price))
     {
      Print(__FUNCTION__,
            ": не удалось создать горизонтальную линию! Код ошибки = ",GetLastError());
      return(false);
     }
//--- установим цвет линии 
   ObjectSetInteger(0,name,OBJPROP_COLOR,clrGreen);
   ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
   return(true);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   double price=pr;
//--- создадим горизонтальную линию 
   for(int i=0;i<=count;i++)
     {
      HLine("HLine"+(string)i,price+step*i*_Point);
      HLine("HLine"+(string)(i+count+1),price-step*i*_Point);
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Типы объектов
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Типы объектов
  • www.mql5.com
При создании графического объекта функцией ObjectCreate() необходимо указать тип создаваемого объекта, который может принимать одно из значений перечисления ENUM_OBJECT. Дальнейшие уточнения свойств созданного объекта возможно с помощью функций по работе с графическими объектами.
 
Александр:

Здравствуйте! Есть индикатор для MT5 "Grid Builder", он рисует горизонтальные линии с шагом цены. Можно выбрать например 100п, 200п и тд. И строится горизонтальная сетка вверх и вниз с заданным шагом. Но у него одна  проблема, например, когда я  на таймфрейме  H4 рисую свою графические горизонтальные уровни( ставлю горизонтальные линии из инструментов рисования в терминале) и переключаю на любой другой таймфрейм, все мои линии удаляются. А остаются только горизонтальные уровни индикатора. Как в коде исправить эту ошибку? Чтобы мои горизонтальные уровни никогда не удалялись. Вот код индикатора.  (Вопрос писал уже в другой теме, но там пока ответа нету)

Обратите внимание на этот код:

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
   ObjectsDeleteAll(0,0,OBJ_HLINE);
  }
//+------------------------------------------------------------------+ 

В частности прочтите про ObjectsDeleteAll() - там и причина и ответ как подправить.

Документация по MQL5: Графические объекты / ObjectsDeleteAll
Документация по MQL5: Графические объекты / ObjectsDeleteAll
  • www.mql5.com
[in]  Префикс, по которому будут удалены все объекты, чьи имена начинаются с данного набора символов. Префикс можно указывать как 'name' или 'name*' – оба варианта работают одинаково. Если в качестве префикса указана пустая строка, то будут удалены объекты с любым именем. Функция использует синхронный вызов – это...
 
Artyom Trishkin:

Обратите внимание на этот код:

В частности прочтите про ObjectsDeleteAll() - там и причина и ответ как подправить.

Спасибо!!! Разобрался, теперь работает без удаления. 

 
Операции с базой SQLite доступны из тестера ? Я про добавление и изменение данных.
 
Dmitri Custurov:
Операции с базой SQLite доступны из тестера ? Я про добавление и изменение данных.

Доступны. Только следите за расположением базы. Они создаются так-же как и файлы.

 
Alexey Viktorov:

Доступны. Только следите за расположением базы. Они создаются так-же как и файлы.

#define DB_NAME "OHLC_DB"

int db_handle;
string TableName;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
   db_handle = DatabaseOpen(DB_NAME, DATABASE_OPEN_READWRITE|DATABASE_OPEN_CREATE); 

   if (db_handle != INVALID_HANDLE){
      Print(StringFormat("Database %s was opened", DB_NAME));
      
      TableName = Symbol() + "_" + enumTimeFrameToString(Period());
      if (DatabaseTableExists(db_handle, TableName)){
         Print(StringFormat("Table %s is exist", TableName));
      }else{
         if (DatabaseExecute(db_handle, "CREATE TABLE " + TableName + "("
                             "TIME TEXT PRIMARY KEY  NOT NULL,"
                             "OPEN              REAL NOT NULL,"
                             "HIGH              REAL NOT NULL,"
                             "LOW               REAL NOT NULL,"
                             "CLOSE             REAL NOT NULL );")){
            Print(StringFormat("Table %s was created", TableName));
            string time = "'" + TimeToString(iTime(Symbol(), PERIOD_CURRENT, 0)) + "'";
            double open = iOpen(Symbol(), PERIOD_CURRENT, 0);
            double high = iHigh(Symbol(), PERIOD_CURRENT, 0);
            double low = iLow(Symbol(), PERIOD_CURRENT, 0);
            double close = iClose(Symbol(), PERIOD_CURRENT, 0);

            if (!DatabaseExecute(db_handle,"INSERT INTO " + TableName + " (TIME,OPEN,HIGH,LOW,CLOSE) "
                                           "VALUES (" + StringFormat("%s,%.5f,%.5f,%.5f,%.5f", time, open, high, low, close) + ");")){
               Print("Table: ", TableName, " insert failed with code ", GetLastError());
               DatabaseClose(db_handle);
               return(INIT_FAILED);
            }else
               Print("New table started:");   
         }else{
            Print(StringFormat("Could not create %s table. Error is: %d", TableName, GetLastError()));
            DatabaseClose(db_handle);
            return(INIT_FAILED); 
         }
      }
      
      return(INIT_SUCCEEDED);
   }else{
      Print("Could not open db. Error is: ", GetLastError());
      return(INIT_FAILED); 
   }     
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
   DatabaseClose(db_handle);
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){
   string time = "'" + TimeToString(iTime(Symbol(), PERIOD_CURRENT, 0)) + "'";
   double open = iOpen(Symbol(), PERIOD_CURRENT, 0);
   double high = iHigh(Symbol(), PERIOD_CURRENT, 0);
   double low = iLow(Symbol(), PERIOD_CURRENT, 0);
   double close = iClose(Symbol(), PERIOD_CURRENT, 0);
   if (!DatabaseExecute(db_handle,"INSERT INTO " + TableName + " (TIME,OPEN,HIGH,LOW,CLOSE) "
                                  "VALUES (" + StringFormat("%s,%.5f,%.5f,%.5f,%.5f", time, open, high, low, close) + ");")){
      Print("Table: ", TableName, " insert failed with code ", GetLastError());
      DatabaseClose(db_handle);
   }   
}
//+------------------------------------------------------------------+
string enumTimeFrameToString(ENUM_TIMEFRAMES frame){
   switch(frame){
      case PERIOD_M1:  return "M1";
      case PERIOD_M2:  return "M2";
      case PERIOD_M3:  return "M3";
      case PERIOD_M4:  return "M4";
      case PERIOD_M5:  return "M5";
      case PERIOD_M6:  return "M6";
      case PERIOD_M10: return "M10";
      case PERIOD_M12: return "M12";
      case PERIOD_M15: return "M15";
      case PERIOD_M20: return "M20";
      case PERIOD_M30: return "M30";
      case PERIOD_H1:  return "H1";
      case PERIOD_H2:  return "H2";
      case PERIOD_H3:  return "H3";
      case PERIOD_H4:  return "H4";
      case PERIOD_H6:  return "H6";
      case PERIOD_H8:  return "H8";
      case PERIOD_D1:  return "D1";
      case PERIOD_W1:  return "W1";
      default:         return "MN1";
   }
}

Вот мой код. В инициализации он создает в таблице одну запись. В теле OnTick он сразу же должен вернуть ошибку, так как я пытаюсь добавить запись с таким же PRIMARY KEY, и после этого база сразу закрывается. Но при этом я при ее открытии должен увидеть хотя бы ту первую запись, но при запуске в тестере ее нет. И даже таблица не создается. А если запускаю просто в терминале то все нормально. Первая запись есть.

 
Dmitri Custurov:

Вот мой код. В инициализации он создает в таблице одну запись. В теле OnTick он сразу же должен вернуть ошибку, так как я пытаюсь добавить запись с таким же PRIMARY KEY, и после этого база сразу закрывается. Но при этом я при ее открытии должен увидеть хотя бы ту первую запись, но при запуске в тестере ее нет. И даже таблица не создается. А если запускаю просто в терминале то все нормально. Первая запись есть.

В который раз убеждаюсь, что тестер и сам терминал - суть разные ипостаси...

 
HistorySelect(xxx,TimeCurrent()) miss the latest history order / deal sometimes. Now you have to use HistorySelect(xxx,TimeCurrent()+1) To get a more accurate result.

 
tickfenix:

Давно рекомендуется к TimeCurrent() добавлять одни сутки. Просто теперь, в ответ на Ваш не совсем корректный код, терминал даёт Вам совет.