Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3.007-dev-new -> v3.008-dev-new merge. Contains fixes to ItemsHistory. PR is not yet ready for merge. #756

1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
Language: Cpp
BasedOnStyle: Google
ColumnLimit: 120
IndentPPDirectives: BeforeHash
21 changes: 17 additions & 4 deletions Candle.struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
*/

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

// Forward class declaration.
Expand Down Expand Up @@ -262,9 +262,12 @@ struct CandleOCTOHLC : CandleOHLC<T> {
#endif

/**
* Initializes candle with a given start time, lenght in seconds, first tick's timestamp and its price.
* Initializes candle with a given start time, length in seconds, first tick's timestamp and its price.
*/
void Init(int _start_time, int _length, long _timestamp_ms = -1, T _price = 0) {
if (_start_time < 0) {
Print("Error!");
}
is_complete = false;
start_time = _start_time;
length = _length;
Expand All @@ -279,7 +282,16 @@ struct CandleOCTOHLC : CandleOHLC<T> {
*/
void Update(long _timestamp_ms, T _price) {
if (!ContainsTimeMs(_timestamp_ms)) {
Print("Error: Cannot update candle. Given time doesn't fit in candle's time-frame!");
Print("Error: Cannot update candle. Given time doesn't fit in candle's time-frame! Given time ", _timestamp_ms,
", but candle range is ", (long)start_time * 1000, " - ", (long)(start_time + length) * 1000, ".");
long _ms;
if (_timestamp_ms < (long)start_time * 1000) {
_ms = (long)start_time * 1000 - _timestamp_ms;
Print("Looks like given time is ", _ms, " ms (", (double)_ms / 1000, " s) before the candle starts.");
} else {
_ms = _timestamp_ms - (long)(start_time + length) * 1000;
Print("Looks like given time is ", _ms, " ms (", (double)_ms / 1000, "s) after the candle ends.");
}
DebugBreak();
}

Expand All @@ -288,6 +300,7 @@ struct CandleOCTOHLC : CandleOHLC<T> {
if (_is_init || _timestamp_ms < open_timestamp_ms) {
open_timestamp_ms = _timestamp_ms;
THIS_ATTR open = _price;
start_time = int(_timestamp_ms / 1000);
}
if (_is_init || _timestamp_ms > close_timestamp_ms) {
close_timestamp_ms = _timestamp_ms;
Expand Down
8 changes: 4 additions & 4 deletions Dict.enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
*/

#ifndef __MQL__
// Allows the preprocessor to include a header file when it is needed.
#pragma once
// 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
#define DICT_GROW_UP_PERCENT_DEFAULT 50
#define DICT_PERFORMANCE_PROBLEM_AVG_CONFLICTS 20

/**
* Whether Dict operates in yet uknown mode, as dict or as list.
Expand Down
39 changes: 36 additions & 3 deletions DictBase.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -378,17 +378,50 @@ class DictBase {
/**
* Specialization of hashing function.
*/
unsigned int Hash(unsigned int x) { return x; }
unsigned int Hash(float x) { return (unsigned int)((unsigned long)x * 10000 % 10000); }

/**
* Specialization of hashing function.
*/
unsigned int Hash(int x) { return (unsigned int)x; }
unsigned int Hash(int value) {
value ^= (value >> 8);
value ^= (value << 3);
value ^= (value >> 9);
value ^= (value >> 4);
value ^= (value << 6);
value ^= (value >> 14);
return value;
}

/**
* Specialization of hashing function.
*/
unsigned int Hash(float x) { return (unsigned int)((unsigned long)x * 10000 % 10000); }
unsigned int Hash(unsigned int value) { return Hash((int)value); }

/**
* Specialization of hashing function.
*/
unsigned int Hash(long value) {
value ^= (value >> 33);
value ^= (value << 21);
value ^= (value >> 17);

// Step 2: Combine upper and lower 32 bits to form a 32-bit hash
long hash = (int)(value ^ (value >> 32));

// Step 3: Further bit manipulation to spread the bits
hash ^= (hash >> 16);
hash *= 0x85ebca6b; // A large prime number
hash ^= (hash >> 13);
hash *= 0xc2b2ae35; // Another large prime number
hash ^= (hash >> 16);
return int(value >> 32);
}

/**
* Specialization of hashing function.
*/
unsigned int Hash(unsigned long value) { return Hash((unsigned long)value); }
};

#endif
6 changes: 4 additions & 2 deletions DictStruct.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

// Prevents processing this includes file for the second time.
#ifndef __MQL__
#pragma once
#pragma once
#endif

// Includes.
Expand Down Expand Up @@ -409,7 +409,9 @@ class DictStruct : public DictBase<K, V> {

DictSlotsRef<K, V> new_DictSlots;

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

int i;

Expand Down
11 changes: 7 additions & 4 deletions Indicator/Indicator.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,10 +691,13 @@ class Indicator : public IndicatorData {
}

if (_LastError != ERR_SUCCESS) {
datetime _bar_dt = (datetime)_bar_time;
Print("Error: Code ", _LastError, " while trying to retrieve entry at shift ", _rel_shift, " (absolute ",
ToAbsShift(_rel_shift), "), mode ", _mode, ", time ", _bar_dt);
DebugBreak();
if (_LastError != 4806) {
// Error occured and it's not "4806 Requested data not found".
datetime _bar_dt = (datetime)_bar_time;
Print("Error: Code ", _LastError, " while trying to retrieve entry at shift ", _rel_shift, " (absolute ",
ToAbsShift(_rel_shift), "), mode ", _mode, ", time ", _bar_dt);
DebugBreak();
}
}
}
THIS_ATTR GetEntryAlter(_entry, _rel_shift);
Expand Down
25 changes: 21 additions & 4 deletions Indicator/IndicatorCandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
#define INDICATOR_CANDLE_H

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

// Includes.
Expand All @@ -45,7 +45,7 @@
#include "TickBarCounter.h"

#ifndef INDI_CANDLE_HISTORY_SIZE
#define INDI_CANDLE_HISTORY_SIZE 86400
#define INDI_CANDLE_HISTORY_SIZE 86400
#endif

// Indicator modes.
Expand Down Expand Up @@ -338,14 +338,31 @@ class IndicatorCandle : public Indicator<TS> {
/**
* Called when data source emits new entry (new one in ascending order).
*/
void OnDataSourceEntry(IndicatorDataEntry& entry) override {
void OnDataSourceEntry(IndicatorDataEntry& entry,
ENUM_INDI_EMITTED_ENTRY_TYPE type = INDI_EMITTED_ENTRY_TYPE_PARENT) override {
Indicator<TS>::OnDataSourceEntry(entry, type);

if (type != INDI_EMITTED_ENTRY_TYPE_TICK) {
return;
}

// Parent indicator (e.g., Indi_TickMt) emitted an entry containing tick's
// ask and bid price. As an abstract class, we really don't know how to
// update/create candles so we just pass the entry into history's
// ItemsHistoryCandleProvider and it will do all the job.
history.GetItemProvider() PTR_DEREF OnTick(&history, entry.timestamp * 1000, (float)entry[0], (float)entry[1]);
};

/**
* Called when data source expects to emit given number of entries for given type.
*
* Called e.g., from Tick indicator in order Candle indicator to enlarge
* possible history size by given number of entries. We have to do that,
* because otherwise, we could end up with OnCalculate() working on partial
* history candles.
*/
void OnDataSourceWillEmitEntries(ENUM_INDI_EMITTED_ENTRY_TYPE _type, int _num_entries) override {}

/**
* Returns value storage of given kind.
*/
Expand Down
18 changes: 13 additions & 5 deletions Indicator/IndicatorCandle.provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
#define INDICATOR_CANDLE_PROVIDER_H

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

// Includes.
Expand Down Expand Up @@ -56,11 +56,19 @@ class ItemsHistoryCandleProvider : public ItemsHistoryItemProvider<CandleOCTOHLC
* Retrieves given number of items starting from the given microseconds or index (inclusive). "_dir" identifies if we
* want previous or next items from selected starting point.
*/
void GetItems(ItemsHistory<CandleOCTOHLC<TV>, ItemsHistoryCandleProvider<TV>>* _history, long _from_time_ms,
bool GetItems(ItemsHistory<CandleOCTOHLC<TV>, ItemsHistoryCandleProvider<TV>>* _history, long _from_time_ms,
ENUM_ITEMS_HISTORY_DIRECTION _dir, int _num_items, ARRAY_REF(CandleOCTOHLC<TV>, _out_arr)) {
// Method is called if there is a missing item (candle) in the history. We need to regenerate it.
Print("Error: Retrieving items by this item provider is not implemented!");
DebugBreak();
return false;
}

/**
* Retrieves items between given indices (both indices inclusive). Should return false if retrieving items by this
* method is not available.
*/
bool GetItems(ItemsHistory<CandleOCTOHLC<TV>, ItemsHistoryCandleProvider<TV>>* _history, int _start_index,
int _end_index, ARRAY_REF(CandleOCTOHLC<TV>, _out_arr)) {
return false;
}
};

Expand Down
33 changes: 28 additions & 5 deletions Indicator/IndicatorData.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
#define INDICATOR_DATA_H

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

// Forward class declaration.
Expand Down Expand Up @@ -1454,6 +1454,7 @@ class IndicatorData : public IndicatorBase {
virtual ENUM_TIMEFRAMES GetTf() { return GetCandle() PTR_DEREF GetTf(); }

/**
/**
* Traverses source indicators' hierarchy and tries to find Ask, Bid, Spread,
* Volume and Tick Volume-featured indicator. IndicatorTick satisfies such
* requirements.
Expand Down Expand Up @@ -1813,10 +1814,21 @@ class IndicatorData : public IndicatorBase {
/**
* Sends entry to listening indicators.
*/
void EmitEntry(IndicatorDataEntry& entry) {
void EmitEntry(IndicatorDataEntry& _entry, ENUM_INDI_EMITTED_ENTRY_TYPE _type = INDI_EMITTED_ENTRY_TYPE_PARENT) {
for (int i = 0; i < ArraySize(listeners); ++i) {
if (listeners[i].ObjectExists()) {
listeners[i] REF_DEREF OnDataSourceEntry(entry);
listeners[i].Ptr().OnDataSourceEntry(_entry, _type);
}
}
}

/**
* Sends information about expected number of emitted entries to listening indicators.
*/
void WillEmitEntries(ENUM_INDI_EMITTED_ENTRY_TYPE _type, int _num_entries) {
for (int i = 0; i < ArraySize(listeners); ++i) {
if (listeners[i].ObjectExists()) {
listeners[i].Ptr().OnDataSourceWillEmitEntries(_type, _num_entries);
}
}
}
Expand Down Expand Up @@ -1880,7 +1892,18 @@ class IndicatorData : public IndicatorBase {
/**
* Called when data source emits new entry (historic or future one).
*/
virtual void OnDataSourceEntry(IndicatorDataEntry& entry){};
virtual void OnDataSourceEntry(IndicatorDataEntry& entry,
ENUM_INDI_EMITTED_ENTRY_TYPE type = INDI_EMITTED_ENTRY_TYPE_PARENT) {}

/**
* Called when data source expects to emit given number of entries for given type.
*
* Called e.g., from Tick indicator in order Candle indicator to enlarge
* possible history size by given number of entries. We have to do that,
* because otherwise, we could end up with OnCalculate() working on partial
* history candles.
*/
virtual void OnDataSourceWillEmitEntries(ENUM_INDI_EMITTED_ENTRY_TYPE _type, int _num_entries) {}

/**
* Called when new tick is retrieved from attached data source.
Expand Down
Loading
Loading