Skip to content

Commit

Permalink
Fixes BarsCalculated() method and historic values retrieval (prices, …
Browse files Browse the repository at this point in the history
…volumes, spread). Also boost up Dicts' performance.
  • Loading branch information
nseam committed Oct 14, 2021
1 parent e927298 commit 54f3684
Show file tree
Hide file tree
Showing 18 changed files with 241 additions and 154 deletions.
34 changes: 34 additions & 0 deletions Dict.enum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//+------------------------------------------------------------------+
//| EA31337 framework |
//| Copyright 2016-2021, EA31337 Ltd |
//| https://github.com/EA31337 |
//+------------------------------------------------------------------+

/*
* This file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
* @file
* Includes Dicts's enums and defines.
*/

#ifndef __MQL__
// Allows the preprocessor to include a header file when it is needed.
#pragma once
#endif

#define DICT_GROW_UP_PERCENT_DEFAULT 25
#define DICT_PERFORMANCE_PROBLEM_AVG_CONFLICTS 10
30 changes: 23 additions & 7 deletions Dict.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class Dict : public DictBase<K, V> {
* Inserts or replaces value for a given key.
*/
bool Set(K key, V value) {
if (!InsertInto(_DictSlots_ref, key, value)) return false;
if (!InsertInto(_DictSlots_ref, key, value, true)) return false;
return true;
}

Expand Down Expand Up @@ -190,7 +190,14 @@ class Dict : public DictBase<K, V> {
/**
* Inserts value into given array of DictSlots.
*/
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, const K key, V value) {
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, const K key, V value, bool allow_resize) {
// Will resize dict if there were performance problems before.
if (allow_resize && !dictSlotsRef.IsPerformant()) {
if (!GrowUp()) {
return false;
}
}

if (_mode == DictModeUnknown)
_mode = DictModeDict;
else if (_mode != DictModeDict) {
Expand All @@ -213,8 +220,8 @@ class Dict : public DictBase<K, V> {
}

if (keySlot == NULL) {
// We need to expand array of DictSlotsRef.DictSlots (by 25%).
if (!Resize(MathMax(10, (int)((float)ArraySize(dictSlotsRef.DictSlots) * 1.25)))) return false;
// We need to expand array of DictSlotsRef.DictSlots (by 25% by default).
if (!GrowUp()) return false;
}
}

Expand Down Expand Up @@ -254,6 +261,8 @@ class Dict : public DictBase<K, V> {
// Slot overwrite is not needed. Using empty slot.
++dictSlotsRef._num_used;
}

dictSlotsRef.AddConflicts(_num_conflicts);
}

dictSlotsRef.DictSlots[position].key = key;
Expand All @@ -275,8 +284,8 @@ class Dict : public DictBase<K, V> {
}

if (dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) {
// No DictSlotsRef.DictSlots available, we need to expand array of DictSlotsRef.DictSlots (by 25%).
if (!Resize(MathMax(10, (int)((float)ArraySize(dictSlotsRef.DictSlots) * 1.25)))) return false;
// No DictSlotsRef.DictSlots available, we need to expand array of DictSlotsRef.DictSlots.
if (!GrowUp()) return false;
}

unsigned int position = Hash((unsigned int)dictSlotsRef._list_index) % ArraySize(dictSlotsRef.DictSlots);
Expand All @@ -295,6 +304,13 @@ class Dict : public DictBase<K, V> {
return true;
}

/**
* Expands array of DictSlots by given percentage value.
*/
bool GrowUp(int percent = DICT_GROW_UP_PERCENT_DEFAULT) {
return Resize(MathMax(10, (int)((float)ArraySize(_DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f))));
}

/**
* Shrinks or expands array of DictSlots.
*/
Expand All @@ -321,7 +337,7 @@ class Dict : public DictBase<K, V> {
if (!_DictSlots_ref.DictSlots[i].IsUsed()) continue;

if (_DictSlots_ref.DictSlots[i].HasKey()) {
if (!InsertInto(new_DictSlots, _DictSlots_ref.DictSlots[i].key, _DictSlots_ref.DictSlots[i].value))
if (!InsertInto(new_DictSlots, _DictSlots_ref.DictSlots[i].key, _DictSlots_ref.DictSlots[i].value, false))
return false;
} else {
if (!InsertInto(new_DictSlots, _DictSlots_ref.DictSlots[i].value)) return false;
Expand Down
1 change: 1 addition & 0 deletions DictBase.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

// Includes.
#include "Convert.mqh"
#include "Dict.enum.h"
#include "DictIteratorBase.mqh"
#include "DictSlot.mqh"
#include "Serializer.mqh"
Expand Down
19 changes: 1 addition & 18 deletions DictIteratorBase.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#endif

#include "DictBase.mqh"
#include "DictSlotsRef.h"
#include "SerializerConversions.h"

template <typename K, typename V>
Expand Down Expand Up @@ -137,21 +138,3 @@ class DictIteratorBase {
_invalid_until_incremented |= invalid_until_incremented;
}
};

template <typename K, typename V>
class DictSlot;

template <typename K, typename V>
struct DictSlotsRef {
DictSlot<K, V> DictSlots[];

// Incremental index for dict operating in list mode.
int _list_index;

int _num_used;

DictSlotsRef() {
_list_index = 0;
_num_used = 0;
}
};
38 changes: 30 additions & 8 deletions DictObject.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class DictObject : public DictBase<K, V> {
* Inserts or replaces value for a given key.
*/
bool Set(K key, V& value) {
if (!InsertInto(_DictSlots_ref, key, value)) return false;
if (!InsertInto(_DictSlots_ref, key, value, true)) return false;
return true;
}

Expand Down Expand Up @@ -177,7 +177,14 @@ class DictObject : public DictBase<K, V> {
/**
* Inserts value into given array of DictSlots.
*/
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, const K key, V& value) {
bool InsertInto(DictSlotsRef<K, V>& dictSlotsRef, const K key, V& value, bool allow_resize) {
// Will resize dict if there were performance problems before.
if (allow_resize && !dictSlotsRef.IsPerformant()) {
if (!GrowUp()) {
return false;
}
}

if (_mode == DictModeUnknown)
_mode = DictModeDict;
else if (_mode != DictModeDict) {
Expand All @@ -200,8 +207,8 @@ class DictObject : public DictBase<K, V> {
}

if (keySlot == NULL) {
// We need to expand array of DictSlotsRef.DictSlots (by 25%).
if (!Resize(MathMax(10, (int)((float)ArraySize(dictSlotsRef.DictSlots) * 1.25)))) return false;
// We need to expand array of DictSlotsRef.DictSlots.
if (!GrowUp()) return false;
}
}

Expand Down Expand Up @@ -241,6 +248,8 @@ class DictObject : public DictBase<K, V> {
// Slot overwrite is not needed. Using empty slot.
++dictSlotsRef._num_used;
}

dictSlotsRef.AddConflicts(_num_conflicts);
}

dictSlotsRef.DictSlots[position].key = key;
Expand All @@ -262,8 +271,8 @@ class DictObject : public DictBase<K, V> {
}

if (dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) {
// No DictSlotsRef.DictSlots available, we need to expand array of DictSlotsRef.DictSlots (by 25%).
if (!Resize(MathMax(10, (int)((float)ArraySize(dictSlotsRef.DictSlots) * 1.25)))) return false;
// No DictSlotsRef.DictSlots available, we need to expand array of DictSlotsRef.DictSlots.
if (!GrowUp()) return false;
}

unsigned int position = Hash((unsigned int)dictSlotsRef._list_index) % ArraySize(dictSlotsRef.DictSlots);
Expand All @@ -282,6 +291,13 @@ class DictObject : public DictBase<K, V> {
return true;
}

/**
* Expands array of DictSlots by given percentage value.
*/
bool GrowUp(int percent = DICT_GROW_UP_PERCENT_DEFAULT) {
return Resize(MathMax(10, (int)((float)ArraySize(_DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f))));
}

/**
* Shrinks or expands array of DictSlots.
*/
Expand All @@ -293,14 +309,20 @@ class DictObject : public DictBase<K, V> {

DictSlotsRef<K, V> new_DictSlots;

int i;

if (ArrayResize(new_DictSlots.DictSlots, new_size) == -1) return false;

for (i = 0; i < new_size; ++i) {
new_DictSlots.DictSlots[i].SetFlags(0);
}

// Copies entire array of DictSlots into new array of DictSlots. Hashes will be rehashed.
for (unsigned int i = 0; i < (unsigned int)ArraySize(_DictSlots_ref.DictSlots); ++i) {
for (i = 0; i < ArraySize(_DictSlots_ref.DictSlots); ++i) {
if (!_DictSlots_ref.DictSlots[i].IsUsed()) continue;

if (_DictSlots_ref.DictSlots[i].HasKey()) {
if (!InsertInto(new_DictSlots, _DictSlots_ref.DictSlots[i].key, _DictSlots_ref.DictSlots[i].value))
if (!InsertInto(new_DictSlots, _DictSlots_ref.DictSlots[i].key, _DictSlots_ref.DictSlots[i].value, false))
return false;
} else {
if (!InsertInto(new_DictSlots, _DictSlots_ref.DictSlots[i].value)) return false;
Expand Down
72 changes: 72 additions & 0 deletions DictSlotsRef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//+------------------------------------------------------------------+
//| EA31337 framework |
//| Copyright 2016-2021, EA31337 Ltd |
//| https://github.com/EA31337 |
//+------------------------------------------------------------------+

/*
* This file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

/**
* @file
* DictSlotsRef struct.
*/

#ifndef __MQL__
// Allows the preprocessor to include a header file when it is needed.
#pragma once
#endif

// Includes.
#include "Dict.enum.h"

template <typename K, typename V>
class DictSlot;

template <typename K, typename V>
struct DictSlotsRef {
DictSlot<K, V> DictSlots[];

// Incremental index for dict operating in list mode.
int _list_index;

int _num_used;

int _num_conflicts;

float _avg_conflicts;

DictSlotsRef() {
_list_index = 0;
_num_used = 0;
_num_conflicts = 0;
_avg_conflicts = 0;
}

/**
* Adds given number of conflicts for an insert action, so we can store average number of conflicts.
*/
void AddConflicts(int num) {
if (num != 0) {
_avg_conflicts += float(num) / ++_num_conflicts;
}
}

/**
* Checks whethere there is no performance problems with slots.
*/
bool IsPerformant() { return _avg_conflicts < DICT_PERFORMANCE_PROBLEM_AVG_CONFLICTS; }
};
Loading

0 comments on commit 54f3684

Please sign in to comment.