Creation of Atr haldle manger and other methods

This commit is contained in:
Matt Corcoran
2025-07-11 16:30:06 +02:00
parent 7de4cf3cb6
commit ec3fc120ce
9 changed files with 516 additions and 367 deletions
+63
View File
@@ -0,0 +1,63 @@
#include <Trade/SymbolInfo.mqh>
class AtrHandleManager {
private:
struct AtrEntry {
string symbol;
ENUM_TIMEFRAMES tf;
int period;
int handle;
};
AtrEntry cache[]; // internal cache of ATR handles
public:
// Get or create an ATR handle for a specific symbol/timeframe/period
int get_atr_handle(string symbol, ENUM_TIMEFRAMES tf, int period) {
for (int i = 0; i < ArraySize(cache); i++) {
if (cache[i].symbol == symbol && cache[i].tf == tf && cache[i].period == period)
return cache[i].handle;
}
int handle = iATR(symbol, tf, period);
if (handle == INVALID_HANDLE) {
Print("Failed to create ATR handle for ", symbol);
return INVALID_HANDLE;
}
AtrEntry entry = { symbol, tf, period, handle };
ArrayResize(cache, ArraySize(cache) + 1);
cache[ArraySize(cache) - 1] = entry;
return handle;
}
// Get ATR value from buffer (returns EMPTY_VALUE if failure)
double get_atr_value(string symbol, ENUM_TIMEFRAMES tf, int period, int shift = 1) {
int handle = get_atr_handle(symbol, tf, period);
if (handle == INVALID_HANDLE) {
PrintFormat("Invalid ATR handle for %s (TF=%d, Period=%d)", symbol, tf, period);
return EMPTY_VALUE;
}
double buffer[];
ArraySetAsSeries(buffer, true);
if (CopyBuffer(handle, 0, shift, 1, buffer) != 1 || buffer[0] == EMPTY_VALUE) {
PrintFormat("Failed to read ATR buffer for %s shift=%d", symbol, shift);
return EMPTY_VALUE;
}
return buffer[0];
}
// Release all handles in the cache
void release_handles() {
for (int i = 0; i < ArraySize(cache); i++) {
if (cache[i].handle != INVALID_HANDLE)
IndicatorRelease(cache[i].handle);
}
ArrayResize(cache, 0);
}
};
+39 -12
View File
@@ -7,23 +7,44 @@ public:
double get_bid_ask_price(string symbol, int price_side);
protected:
datetime previousTime; // Stores the last recorded bar open time
datetime bar_open_time; // Stores the current bar's open time
datetime previousTimes[]; // Stores last recorded open time per key
string bar_keys[]; // Keys are symbol+TF combinations, e.g. "EURUSD_PERIOD_H1"
};
// Helper function to find index of a key in an array
int LinearSearch(string &arr[], string target) {
for (int i = 0; i < ArraySize(arr); i++) {
if (arr[i] == target)
return i;
}
return -1; // Not found
}
// Checks if a new bar has opened on the given timeframe and symbol
bool MarketDataUtils::is_new_bar(string symbol, ENUM_TIMEFRAMES time_frame, string daily_start_time) {
bar_open_time = iTime(symbol, time_frame, 0); // Current open time
datetime bar_open_time = iTime(symbol, time_frame, 0); // Current open time
string key = symbol + "_" + EnumToString(time_frame);
if (previousTime != bar_open_time) {
int idx = LinearSearch(bar_keys, key);
if (idx == -1) {
int new_size = ArraySize(bar_keys) + 1;
ArrayResize(bar_keys, new_size);
ArrayResize(previousTimes, new_size);
idx = new_size - 1;
bar_keys[idx] = key;
previousTimes[idx] = 0;
}
if (previousTimes[idx] != bar_open_time) {
// For daily timeframe, wait for specific time (e.g., 00:10) before triggering
if (PeriodSeconds(time_frame) == PeriodSeconds(PERIOD_D1)) {
if (TimeCurrent() > StringToTime(daily_start_time)) {
previousTime = bar_open_time;
previousTimes[idx] = bar_open_time;
return true;
}
} else {
previousTime = bar_open_time;
previousTimes[idx] = bar_open_time;
return true;
}
}
@@ -35,17 +56,23 @@ bool MarketDataUtils::is_new_bar(string symbol, ENUM_TIMEFRAMES time_frame, stri
// shift = 1 is the most recently closed candle
// shift = 2 is the one before that, etc.
double MarketDataUtils::get_buffer_value(int handle, int shift) {
double val[];
ArraySetAsSeries(val, true);
double val[];
ArraySetAsSeries(val, true);
int copied = CopyBuffer(handle, 0, shift, 1, val);
if (copied <= 0) {
Print("CopyBuffer failed: handle=", handle, " shift=", shift);
return EMPTY_VALUE;
}
if (CopyBuffer(handle, 0, shift, 1, val) == 1 && val[0] != EMPTY_VALUE)
return val[0];
if (val[0] == EMPTY_VALUE) {
Print("EMPTY_VALUE returned for buffer at shift=", shift);
return EMPTY_VALUE;
}
return EMPTY_VALUE;
return val[0];
}
// Adjusts the point value for symbol to account for fractional pips (e.g., 5-digit brokers)
double MarketDataUtils::adjusted_point(string symbol) {
int symbol_digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
+56
View File
@@ -0,0 +1,56 @@
#include <MyLibs/Utils/AtrHandleManager.mqh>
//+------------------------------------------------------------------+
//| ResourceManager |
//| |
//| Tracks and releases indicator handles (iMA, iRSI, etc.) |
//| Also delegates ATR handle cleanup to an external ATR manager |
//+------------------------------------------------------------------+
class ResourceManager {
public:
// --- Pointer to external ATR manager (set externally)
// Used for releasing any internally cached ATR handles
AtrHandleManager* atr_manager;
// --- Register a new indicator handle to be released later
// Only valid (non-INVALID_HANDLE) handles are stored
void register_handle(int handle) {
if (handle != INVALID_HANDLE)
add_handle(handle);
}
// --- Release all tracked resources:
void release_all_handles() {
release_internal_handles(); // ATR manager
release_tracked_handles(); // Generic indicator handles
}
private:
// --- Dynamic array of general indicator handles
int handles[];
// --- Append a valid indicator handle to the internal array
// Used by register_handle()
void add_handle(int handle) {
int size = ArraySize(handles);
ArrayResize(handles, size + 1);
handles[size] = handle;
}
// --- Release all generic indicator handles tracked internally
// This covers iMA, iRSI, iCCI, etc.
void release_tracked_handles() {
for (int i = 0; i < ArraySize(handles); i++) {
if (handles[i] != INVALID_HANDLE)
IndicatorRelease(handles[i]);
}
ArrayFree(handles);
}
// --- Release ATR handles via external AtrHandleManager
// No-op if atr_manager is not assigned
void release_internal_handles() {
if (atr_manager != NULL)
atr_manager.release_handles();
}
};
+14 -5
View File
@@ -15,11 +15,20 @@ class SignalStateTracker {
last_signal_short = -1000;
}
// Updates the signal for both long and short directions in one call, if the respective triggers are true.
// curr_bar should refer to the last CLOSED bar (typically bar index 1).
void update_signal(bool trig_long, bool trig_short, int curr_bar=1) {
if (trig_long) last_signal_long = curr_bar;
if (trig_short) last_signal_short = curr_bar;
// Updates the signal tracker based on trigger presence per bar.
// If signal is detected, sets to 1. If not, increments previous value.
void update_signal_tracker(bool signal_long, bool signal_short) {
if (signal_long) {
last_signal_long = 1;
} else if (last_signal_long > 0) {
last_signal_long++;
}
if (signal_short) {
last_signal_short = 1;
} else if (last_signal_short > 0) {
last_signal_short++;
}
}
// Returns true if a long signal occurred within the last `max_bars` bars.