Creation of Atr haldle manger and other methods
This commit is contained in:
@@ -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
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user