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

 
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() добавлять одни сутки. Просто теперь, в ответ на Ваш не совсем корректный код, терминал даёт Вам совет.

 
HistorySelect(xxx,TimeCurrent()+1)

Одна секунда - это частая потеря последней сделки/ордера на реале. Например, на многих бриджах ордер уходит на исполнение на TTL-время, которое может быть равно пяти секундам. Если за пять секунд не исполнился - реджект. Либо исполнился, но секунды за три.

В случае, если от акцепта до исполнения не было тиков, такой вызов HistorySelect не получит об этом информацию.


Возможно, TimeCurrent стоит делать равным MathMax(LastOrder_time, MarketWatch_Time). Тогда HistorySelect будет корректный. Но TimeCurrent, возможно, слишком дорогой.


ЗЫ Кстати, такая схема работа HistorySelect будет пропускать часть истории торгов.

void OnStart()
{
  static MqlTick PrevTick = {0};
  
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))
  {
    if (HistorySelect(PrevTick.time, INT_MAX))
      // Учитываем новые ордера/сделки в Истории торгов

    PrevTick = Tick;  
  }
}

Хотя,  на первый взгляд, все чисто.


Написать дешевый DealsTotal() не просто в MT5. Это не элементарный (и бесплатный) OrdersHistoryTotal() в MT4.

 

мысли вслух, не претендую на актуальность и компетентность:


fxsaber:

В случае, если от акцепта до исполнения не было тиков, такой вызов HistorySelect не получит об этом информацию.

Вы не решите эту проблему, модель взаимодействия сервер - терминал - MQL изначально такая была заложена

в МТ5 еще не дошел до момента проверок, но в МТ4 точно знаю, что бывают ситуации когда на в окне обзор рынка на символе происходят изменения цен по нашему символу, а вот тиков в ЕА может не поступить или поступает меньше


ладно не суть, так работает значит так, Вам просто нужно в ТС выбрать решение, что происходит с ордером при отсутствии информации от сервера с момента отправки ордера - т.е. априори ордер будет выставлен или отклонен, а получив ответ подтверждать это предварительное решение или отменять - т.е. работать с неподтвержденной информацией или ждать все таки ответ от сервера - это предлагают MQ и Вас скорее всего не устраивает


fxsaber:

сать дешевый DealsTotal() не просто в MT5. Это не элементарный (и бесплатный) OrdersHistoryTotal() в MT4.

 а не напишите ;)

вернее, скорее всего напишите и будете тратить ресурсы ЕА на сопровождение алгоритма, думаю нужно выяснить как работает SQLite, MQ тесты производительности заявляла, работа с большими таблицами и выборками это как раз и назначение БД - код ЕА будет минималистическим, всю работу БД будет Вам делать, вся работа сведется к заполнению данных при выставлении ордера и актуализации при ответе от сервера (синхронизация, понятное дело при запуске ЕА, БД в памяти)

 
Igor Makanu:

а не напишите ;)

вернее, скорее всего напишите и будете тратить ресурсы ЕА на сопровождение алгоритма, думаю нужно выяснить как работает SQLite, MQ тесты производительности заявляла, работа с большими таблицами и выборками это как раз и назначение БД - код ЕА будет минималистическим, всю работу БД будет Вам делать, вся работа сведется к заполнению данных при выставлении ордера и актуализации при ответе от сервера (синхронизация, понятное дело при запуске ЕА, БД в памяти)

Изначально был написан и выложен. Вряд ли получится быстрее.

 
fxsaber:

Изначально был написан и выложен. Вряд ли получится быстрее.

значит я задачу не правильно увидел

думал, что нужно актуализировать список ордеров из двух точек OnTradeTransaction() и OnTick() , поэтому и предложил в БД это выполнять

 
void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result)
  {
   if(trans.type==TRADE_TRANSACTION_DEAL_ADD)
     {
      if(!HistoryDealSelect(trans.deal))
         return;
      bool time_to_sum_up=false;
      if(HistoryDealGetInteger(trans.deal,DEAL_ENTRY)==DEAL_ENTRY_OUT)
        {
         time_to_sum_up=true;
        }
      if(!time_to_sum_up)
         return;
      HistorySelect(0,TimeCurrent());
      int deals=HistoryDealsTotal();
      for(int i=deals-1; i>=0; i--)
        {
         if(HistoryDealGetTicket(i)==trans.deal)
           {
            Print("Found!");
            return;
           }
        }
      Print("Not Found!");
     }
   return;
  
This code is a simplified snippet of my EA.
Assume that, in a few cases, the result of running this code is to return "Not Found."
I don't quite understand why.
Why can't it find itself in the events it triggers?
The transaction event sent by the server to the terminal has arrived, but the server cannot simultaneously synchronize the correct time to the terminal?
My understanding is that a second's increase in the value of TimeCurrent() is more than enough.
I must be missing something important, right?
I would be very grateful if you could point out any errors in my understanding.
Объем импорта г/г - экономический индекс Японии
Объем импорта г/г - экономический индекс Японии
  • www.mql5.com
Объем импорта г/г (Imports y/y) отражает изменение объема импорта товаров и услуг в отчетном месяце по сравнению с тем же месяцем прошлого года. Показатели импорта используются для оценки внешней торговой активности Японии и спроса на импортируемые товары внутри страны. Из-за последствий "финансового кризиса" США Япония также столкнулась с...
 
Can you create a method to open Market Deep of some symbol in mql5 please? this is important when working with multiple symbols.