Скачать MetaTrader 5

Библиотека Generic классов - ошибки, описание, вопросы, особенности использования и предложения - страница 13

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
fxsaber
10832
fxsaber  
Renat Fatkhullin:

Нельзя сопоставлять HistorySelect(ставит range доступа в тестере) и HistoryDealSelect(ticket), который реально ищет конкретный тикет и кеширует его.

Из-за понимания этого и был создан Clear-вариант сразу. Чтобы можно было сравнить Clear vs Full заодно.

MetaQuotes
Админ
26090
Renat Fatkhullin  
fxsaber:
Так история (особенно в тестере) только дополняется, старые записи не изменяются. Речь про Clear-вариант.


На реале, вроде, даже когда ордер исполняется частично и порождает несколько сделок, он не попадет в историю, пока полностью не зафиллится или не будет отменен. Т.е. сохраняется правило замороженной истории.

Если бы мы писали софт без проверок, все давно развалили бы.

Финансовый софт не позволяет писать в режиме "срежу углы". Срежешь в одном месте, затем в другом, а потом разработчики уверуют в право пропускать жесткие проверки и провал неминуем.

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

fxsaber
10832
fxsaber  
Renat Fatkhullin:

Если бы мы писали софт без проверок, все давно развалили бы.

Финансовый софт не позволяет писать в режиме "срежу углы". Срежешь в одном месте, затем в другом, а потом разработчики уверуют в право пропускать жесткие проверки и провал неминуем.

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

Спасибо за разъяснение! Тестер, надеюсь, подкрутите немного.

MetaQuotes
Админ
26090
Renat Fatkhullin  
fxsaber:

Из-за понимания этого и был создан Clear-вариант сразу. Чтобы можно было сравнить Clear vs Full заодно.

Вы неправильно понимаете, что тестировали. Это никак не Clear вариант и нет никакой связи с исходно заявленной ссылкой на HistorySelect.

Ваш Full вариант по сути означает двойной вызов(поиск тикета), первый из которого выбирает сделку в кеш, а второй доступается к кешированному результату. В конкретной задаче, где сделка заведомо существует, первый вызов select лишний. Get методы неявно поднимают в кеш затронутую запись.



Для информации: мы внутри обязаны выставлять детальные Last Error коды (под GetLastError() вызов), чтобы разработчики могли получить глубинные причины отказа. Обычно таких проверок несколько на один вызов вглубь платформы.
fxsaber
10832
fxsaber  
Renat Fatkhullin:

Вы неправильно понимаете, что тестировали. Это никак не Clear вариант и нет никакой связи с исходно заявленной ссылкой на HistorySelect.

Похоже, Вы этого не заметили

Или, может, мы о разных вещах говорим.
MetaQuotes
Админ
26090
Renat Fatkhullin  
fxsaber:

Похоже, Вы этого не заметили

Или, может, мы о разных вещах говорим.

Заметил.

Какая предварительно загруженная история? Я же указал, что HistorySelect в тестере фейковый и не делает реального переноса в кеш всей указанной в запросе истории, а лишь помечает позиции from & to в существующей базе сделок. Поэтому и стоимость нулевая.

В GetDealProfitClear вы точно так же и точно туда же делаете запрос через  HistoryDealGetDouble(Deal, DEAL_PROFIT) как и в неправильно понятом вами методе GetDealProfitFull, где стоят два точно таких же по физической сути метода

return(HistoryDealSelect(Deal) ? HistoryDealGetDouble(Deal, DEAL_PROFIT) : 0)

То есть, доступ к истории в тестере очень оптимизирован и реально ориентируется на то, что никто не может поменять торговую историю кроме вашего эксперта(при этому проверки все равно есть).

В реальном терминале все не так и HistorySelect дорогой.

fxsaber
10832
fxsaber  
Renat Fatkhullin:

Понял, что Вы имели в виду. Спасибо за подробности! Интересно, что у Вас выйдет по итогу

А Generic-тема очень полезная, однако! Буду следить с интересом.
Sergey Dzyublik
5307
Sergey Dzyublik  

Ознакомился с реализацией CHashMap
Честно, понравилась.

//+------------------------------------------------------------------+
//| Class CHashMap<TKey, TValue>.                                    |
//| Usage: Represents a collection of keys and values.               |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
class CHashMap: public IMap<TKey,TValue>
  {
protected:
   int               m_buckets[];                        
   Entry<TKey,TValue>m_entries[];
   int               m_count;
   int               m_free_list;
   int               m_free_count;
   IEqualityComparer<TKey>*m_comparer;
   bool              m_delete_comparer;

public:
                     CHashMap(void);
                     CHashMap(const int capacity);
                     CHashMap(IEqualityComparer<TKey>*comparer);
                     CHashMap(const int capacity,IEqualityComparer<TKey>*comparer);
                     CHashMap(IMap<TKey,TValue>*map);
                     CHashMap(IMap<TKey,TValue>*map,IEqualityComparer<TKey>*comparer);
                    ~CHashMap(void);
   //--- methods of filling data 
   bool              Add(CKeyValuePair<TKey,TValue>*pair);
   bool              Add(TKey key,TValue value);
   //--- methods of access to protected data
   int               Count(void)                                       { return(m_count-m_free_count); }
   IEqualityComparer<TKey>*Comparer(void)                        const { return(m_comparer);           }
   bool              Contains(CKeyValuePair<TKey,TValue>*item);
   bool              Contains(TKey key,TValue value);
   bool              ContainsKey(TKey key);
   bool              ContainsValue(TValue value);
   //--- methods of copy data from collection   
   int               CopyTo(CKeyValuePair<TKey,TValue>*&dst_array[],const int dst_start=0);
   int               CopyTo(TKey &dst_keys[],TValue &dst_values[],const int dst_start=0);
   //--- methods of cleaning and deleting
   void              Clear(void);
   bool              Remove(CKeyValuePair<TKey,TValue>*item);
   bool              Remove(TKey key);
   //--- method of access to the data
   bool              TryGetValue(TKey key,TValue &value);
   bool              TrySetValue(TKey key,TValue value);

private:
   void              Initialize(const int capacity);
   void              Resize(int new_size,bool new_hash_codes);
   int               FindEntry(TKey key);
   bool              Insert(TKey key,TValue value,const bool add);
  };


Есть несколько предложений по возможному улучшению:

1) По скромному мнению реализация содержит не совсем корректный выбор capacity - как начальный размер 3, так и последующие при перестройке хеш-таблицы.
Да, все верно, что нужно выбирать простое число для равномерности распределения. 
Однако реализация CPrimeGenerator не отвечает ожиданиям и содержит пропуски простых чисел.
Цель такого "генератора" понятна - обеспечить коэффициент прироста порядка 1.2 с автоматическим получением простых чисел.
Однако, разве это не слишком маленький коэффициент? В C++ для vectors обычно коэффициент составляет 1.5-2.0 в зависимости от библиотеки (так как сильно влияет на среднюю сложность операции).
Выходом может быть константный коэффициент с последующим округлением числа до простого через бинарный поиск в списку простых чисел.
И начальный размер capacity в 3 - это уж слишком мало, мы же не в прошлом веке живем.

2) На данный момент перестройка хеш-таблицы (Resize) выполняется исключительно при 100% заполнении capacity (заполнении всех m_entries[])
В связи с чем возможно значительное количество коллизий для ключей с не очень равномерным распределением.
Как вариант рассмотреть возможность введение коэффициента заполнения, который уменьшит 100% на необходимый лимит для выполнения перестройки хеш-таблицы.

Vasiliy Sokolov
30835
Vasiliy Sokolov  
fxsaber:

А классический вариант сколько возвращает в Вашем случае?

ulong GetDealOrder( const ulong Deal )
{
  return(HistoryDealSelect(Deal) ? HistoryDealGetInteger(Deal, DEAL_ORDER) : 0);
}
2017.12.08 17:56:05.184 OrdersID (SBRF Splice,M1)       Время выполнения запроса: 9 микросекунд

Это время выполнения printf.

Вы как-то странно поняли мой пример. У меня нет цели что-либо сравнивать с штатным функционалом MetaTrader. Речь лишь о том, как на своем пользовательском уровне организовать эффективные алгоритмы ассоциаций и выборки чего угодно с чем угодно. Пример связи номера сделки с номером ордера нужно рассматривать лишь как пример, с низкой практической ценностью, т.к. есть системная HistoryDealGetInteger(Deal, DEAL_ORDER). 

Vasiliy Sokolov
30835
Vasiliy Sokolov  
fxsaber:

Ну вот сравниваем два выделенных показателя. Получается, что HashMap-доступ в 4 раза быстрее того, что у разработчиков. Но у разработчиков он уже включает историю...

По той же причине сравнение некорректное. Как можно сравнивать пользовательский CHashMap и работу с системными функциями для получения торгового окружения? 

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий