Inclustion of example EA

This commit is contained in:
Matt Corcoran
2025-07-12 16:47:54 +02:00
parent 1222236ded
commit 657125d61c
37 changed files with 466 additions and 3341 deletions
+91
View File
@@ -0,0 +1,91 @@
#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:
// ---------------------------------------------------------------------
// Returns a valid ATR handle for the given symbol, timeframe, and period.
// Creates and caches the handle if not already available.
//
// Parameters:
// - symbol : Trading symbol (e.g., "EURUSD").
// - tf : Timeframe (e.g., PERIOD_H1).
// - period : ATR period (e.g., 14).
//
// Returns:
// - The ATR indicator handle, or INVALID_HANDLE if failed.
// ---------------------------------------------------------------------
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;
}
// ---------------------------------------------------------------------
// Gets the ATR value for a given symbol, timeframe, and period.
//
// Parameters:
// - symbol : Trading symbol (e.g., "EURUSD").
// - tf : Timeframe to use (e.g., PERIOD_H1).
// - period : ATR period to calculate.
// - shift : Bar shift to read the value from (default is 1 for last closed bar. NEVER use 0!).
//
// Returns:
// - ATR value at the given shift, or EMPTY_VALUE on 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];
}
// ---------------------------------------------------------------------
// Releases all cached ATR handles and clears the internal cache.
//
// Logic:
// - Calls IndicatorRelease for each handle.
// - Clears the `cache` array.
// ---------------------------------------------------------------------
void release_handles() {
for (int i = 0; i < ArraySize(cache); i++) {
if (cache[i].handle != INVALID_HANDLE)
IndicatorRelease(cache[i].handle);
}
ArrayResize(cache, 0);
}
};
+43
View File
@@ -0,0 +1,43 @@
#include <Object.mqh>
class ChartUtils : public CObject {
public:
void draw_line(double value, string name, color clr = clrBlack);
};
// ---------------------------------------------------------------------
// Draws or updates a horizontal line on the chart at the given price level.
//
// Parameters:
// - value : Price level at which to draw the line.
// - name : Unique name for the line object.
// - clr : Line color (default is black).
//
// Logic:
// - If the object doesn't exist, it creates a new horizontal line.
// - If the object exists, it moves it to the new price level.
// - Calls ChartRedraw to update the chart visually.
// ---------------------------------------------------------------------
void ChartUtils::draw_line(double value, string name, color clr) {
if (ObjectFind(0, name) < 0) {
ResetLastError();
if (!ObjectCreate(0, name, OBJ_HLINE, 0, 0, value)) {
Print(__FUNCTION__, ": failed to create a horizontal line! Error code = ", GetLastError());
return;
}
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
}
ResetLastError();
if (!ObjectMove(0, name, 0, 0, value)) {
Print(__FUNCTION__, ": failed to move the horizontal line! Error code = ", GetLastError());
return;
}
ChartRedraw();
}
Binary file not shown.
+41
View File
@@ -0,0 +1,41 @@
enum LOT_MODE{
LOT_MODE_FIXED, // Fixed Lot Size
LOT_MODE_PCT_ACCOUNT, // Percent of Account (fixed)
LOT_MODE_PCT_RISK // Percent of Account at Risk (from SL)
};
enum SL_MODE{
SL_FIXED_PIPS, // Fixed Pips
SL_FIXED_PERCENT, // Fixed Percent
SL_ATR_MULTIPLE, // ATR Multiple
SL_SPECIFIED_VALUE, // Bespoke calculation in code
NO_STOPLOSS, // No Stop-loss
SL_BREAKEVEN, // Breakeven
};
enum TP_MODE{
TP_FIXED_PIPS, // Fixed Pips
TP_FIXED_PERCENT, // Fixed Percent
TP_ATR_MULTIPLE, // ATR Multiple
TP_SL_MULTIPLE, // Multiple of Risk (from sl)
TP_SPECIFIED_VALUE, // Bespoke calculation in code
NO_TAKE_PROFIT, // No Take-Profit
};
enum TSL_MODE{
TSL_ATR_MULTIPLE, // ATR Multiple
TSL_FIXED_PIPS, // Fixed Pips
TSL_FIXED_PERCENT, // Fixed Percent
};
enum TIME_ZONES{
NY, // New York
Lon, // London
Ffm, // Frankfurt
Syd, // Sidney
Mosc, // Moscow
Tok, // Tokyo - no DST
};
enum MULTI_SYM_MODE{
MULTI_SYM_CHART, // Chart Symbol only
MULTI_SYM_FX_B5, // FX Benchmark 5
MULTI_SYM_FX_28 // FX 28 Majors
};
+148
View File
@@ -0,0 +1,148 @@
class MarketDataUtils {
public:
bool is_new_bar(string symbol, ENUM_TIMEFRAMES time_frame, string daily_start_time = "00:10");
double get_latest_buffer_value(int handle);
double get_buffer_value(int handle, int shift);
double adjusted_point(string symbol);
double get_bid_ask_price(string symbol, int price_side);
protected:
datetime previousTimes[]; // Stores last recorded open time per key
string bar_keys[]; // Keys are symbol+TF combinations, e.g. "EURUSD_PERIOD_H1"
};
// ---------------------------------------------------------------------
// Performs linear search on a string array.
//
// Parameters:
// - arr : Array of strings.
// - target : Target string to find.
//
// Returns:
// - Index of the target, or -1 if not found.
// ---------------------------------------------------------------------
int LinearSearch(string& arr[], string target) {
for (int i = 0; i < ArraySize(arr); i++) {
if (arr[i] == target) return i;
}
return -1;
}
// ---------------------------------------------------------------------
// Implementation of is_new_bar. Tracks the open time of the last bar.
//
// Parameters:
// - symbol : Symbol to check.
// - time_frame : Timeframe to check.
// - daily_start_time: Time string for daily bar sync.
//
// Returns:
// - true if a new bar has formed, false otherwise.
// ---------------------------------------------------------------------
bool MarketDataUtils::is_new_bar(string symbol, ENUM_TIMEFRAMES time_frame, string daily_start_time) {
datetime bar_open_time = iTime(symbol, time_frame, 0); // Current open time
string key = symbol + "_" + EnumToString(time_frame);
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) {
if (PeriodSeconds(time_frame) == PeriodSeconds(PERIOD_D1)) {
if (TimeCurrent() > StringToTime(daily_start_time)) {
previousTimes[idx] = bar_open_time;
return true;
}
} else {
previousTimes[idx] = bar_open_time;
return true;
}
}
return false;
}
// ---------------------------------------------------------------------
// Implementation of get_buffer_value.
//
// Parameters:
// - handle : Indicator handle.
// - shift : Shift index for historical bars.
//
// Returns:
// - The buffer value, or EMPTY_VALUE if error.
// ---------------------------------------------------------------------
double MarketDataUtils::get_buffer_value(int handle, int shift) {
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 (val[0] == EMPTY_VALUE) {
Print("EMPTY_VALUE returned for buffer at shift=", shift);
return EMPTY_VALUE;
}
return val[0];
}
// ---------------------------------------------------------------------
// Gets the latest (live) value from buffer (shift = 0).
//
// Parameters:
// - handle : Indicator handle.
//
// Returns:
// - Buffer value at shift 0 or EMPTY_VALUE if failed.
// ---------------------------------------------------------------------
double MarketDataUtils::get_latest_buffer_value(int handle) {
return get_buffer_value(handle, 0);
}
// ---------------------------------------------------------------------
// Computes adjusted point value considering fractional pip brokers.
//
// Parameters:
// - symbol : Symbol name.
//
// Returns:
// - Adjusted point multiplier.
// ---------------------------------------------------------------------
double MarketDataUtils::adjusted_point(string symbol) {
int symbol_digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
int digits_adjust = (symbol_digits == 3 || symbol_digits == 5) ? 10 : 1;
double point_val = SymbolInfoDouble(symbol, SYMBOL_POINT);
return point_val * digits_adjust;
}
// ---------------------------------------------------------------------
// Returns bid or ask price for a given symbol.
//
// Parameters:
// - symbol : Symbol name.
// - price_side : 1 = Ask, 2 = Bid.
//
// Returns:
// - Price value or 0.0 if input is invalid.
// ---------------------------------------------------------------------
double MarketDataUtils::get_bid_ask_price(string symbol, int price_side) {
int digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
double ask = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), digits);
double bid = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), digits);
if (price_side == 1) return ask;
if (price_side == 2) return bid;
return 0.0;
}
+82
View File
@@ -0,0 +1,82 @@
#include <MyLibs/Utils/SignalStateTracker.mqh>
// ---------------------------------------------------------------------
// This class manages a collection of SignalStateTracker instances — one per symbol.
// It allows you to track signals separately for each symbol in a multi-symbol EA.
// ---------------------------------------------------------------------
class MultiSymbolSignalTracker {
private:
// ---------------------------------------------------------------------
// Internal struct to associate a symbol with a SignalStateTracker.
// ---------------------------------------------------------------------
struct SymbolTracker {
string symbol;
SignalStateTracker* tracker;
};
SymbolTracker trackers[]; // Dynamic array of symbol-tracker mappings
// ---------------------------------------------------------------------
// Finds the index of the symbol in the tracker array.
// ---------------------------------------------------------------------
int find_index(const string& symbol) {
for (int i = 0; i < ArraySize(trackers); i++) {
if (trackers[i].symbol == symbol)
return i;
}
return -1;
}
public:
// ---------------------------------------------------------------------
// Destructor. Cleans up allocated memory when the object is destroyed.
// ---------------------------------------------------------------------
~MultiSymbolSignalTracker() {
clear();
}
// ---------------------------------------------------------------------
// Retrieves the SignalStateTracker instance for a given symbol.
// Creates and stores a new one if it doesn't exist yet.
//
// Parameters:
// - symbol : Symbol for which to retrieve the signal tracker.
//
// Returns:
// - Pointer to the SignalStateTracker instance.
// ---------------------------------------------------------------------
SignalStateTracker* get_tracker(const string& symbol) {
int idx = find_index(symbol);
if (idx != -1)
return trackers[idx].tracker;
// Create new tracker
SignalStateTracker* tracker = new SignalStateTracker();
SymbolTracker item;
item.symbol = symbol;
item.tracker = tracker;
ArrayResize(trackers, ArraySize(trackers) + 1);
trackers[ArraySize(trackers) - 1] = item;
return tracker;
}
// ---------------------------------------------------------------------
// Clears all SignalStateTracker instances and resets the internal array.
// Should be called in `OnDeinit()` to avoid memory leaks.
//
// Logic:
// - Deletes each dynamically allocated SignalStateTracker.
// - Resets array size to 0.
// ---------------------------------------------------------------------
void clear() {
for (int i = 0; i < ArraySize(trackers); i++) {
delete trackers[i].tracker;
}
ArrayResize(trackers, 0);
}
};
+74
View File
@@ -0,0 +1,74 @@
#include <MyLibs/Utils/AtrHandleManager.mqh>
// ---------------------------------------------------------------------
// ResourceManager
//
// Tracks and releases indicator handles (e.g., iMA, iRSI, iCCI).
// Delegates ATR handle management to an external AtrHandleManager instance.
//
// Usage:
// - Register indicator handles via `register_handle()`.
// - Call `release_all_handles()` to release all cached handles.
// ---------------------------------------------------------------------
class ResourceManager {
public:
AtrHandleManager* atr_manager;
// ---------------------------------------------------------------------
// Registers a generic indicator handle to be released later.
//
// Parameters:
// - handle : A valid (non-INVALID_HANDLE) indicator handle.
//
// Logic:
// - If the handle is valid, it is added to an internal list.
// ---------------------------------------------------------------------
void register_handle(int handle) {
if (handle != INVALID_HANDLE)
add_handle(handle);
}
// ---------------------------------------------------------------------
// Releases all tracked indicator resources.
//
// Logic:
// - Releases generic handles tracked via `register_handle()`.
// - Also invokes `atr_manager.release_handles()` if assigned.
// ---------------------------------------------------------------------
void release_all_handles() {
release_internal_handles(); // ATR manager
release_tracked_handles(); // Generic indicator handles
}
private:
int handles[];
// ---------------------------------------------------------------------
// Adds a handle to the internal tracking list.
// ---------------------------------------------------------------------
void add_handle(int handle) {
int size = ArraySize(handles);
ArrayResize(handles, size + 1);
handles[size] = handle;
}
// ---------------------------------------------------------------------
// Releases all tracked indicator handles (iMA, iRSI, etc.).
// ---------------------------------------------------------------------
void release_tracked_handles() {
for (int i = 0; i < ArraySize(handles); i++) {
if (handles[i] != INVALID_HANDLE)
IndicatorRelease(handles[i]);
}
ArrayFree(handles);
}
// ---------------------------------------------------------------------
// Releases any cached ATR handles using the external AtrHandleManager.
// ---------------------------------------------------------------------
void release_internal_handles() {
if (atr_manager != NULL)
atr_manager.release_handles();
}
};
+128
View File
@@ -0,0 +1,128 @@
class SignalStateTracker {
private:
// ---------------------------------------------------------------------
// Index of the last long signal detected (default -1000 when unset).
// ---------------------------------------------------------------------
int last_signal_long;
// ---------------------------------------------------------------------
// Index of the last short signal detected (default -1000 when unset).
// ---------------------------------------------------------------------
int last_signal_short;
public:
// ---------------------------------------------------------------------
// Constructor initializes the signal tracker to a reset state.
//
// Logic:
// - Sets both long and short signal indices to -1000.
// ---------------------------------------------------------------------
SignalStateTracker() {
reset();
}
// ---------------------------------------------------------------------
// Resets the signal tracker.
//
// Logic:
// - Sets `last_signal_long` and `last_signal_short` to -1000,
// representing no signal recorded.
// ---------------------------------------------------------------------
void reset() {
last_signal_long = -1000;
last_signal_short = -1000;
}
// ---------------------------------------------------------------------
// Updates internal state based on whether long/short signals occurred.
//
// Parameters:
// - signal_long : True if a long signal occurred this bar.
// - signal_short : True if a short signal occurred this bar.
//
// Logic:
// - If a signal is detected, sets the index to 1 (bar 1).
// - Otherwise, increments the previous value if it was positive.
// ---------------------------------------------------------------------
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++;
}
}
// ---------------------------------------------------------------------
// Checks if a long signal occurred within the last N bars.
//
// Parameters:
// - max_bars : Number of bars to look back for the signal.
//
// Returns:
// - True if a long signal occurred within `max_bars` bars.
// ---------------------------------------------------------------------
bool long_signal_recent(int max_bars) const {
return has_long_signal() && (1 - last_signal_long <= max_bars);
}
// ---------------------------------------------------------------------
// Checks if a short signal occurred within the last N bars.
//
// Parameters:
// - max_bars : Number of bars to look back for the signal.
//
// Returns:
// - True if a short signal occurred within `max_bars` bars.
// ---------------------------------------------------------------------
bool short_signal_recent(int max_bars) const {
return has_short_signal() && (1 - last_signal_short <= max_bars);
}
// ---------------------------------------------------------------------
// Indicates if any long signal has ever been recorded.
//
// Returns:
// - True if a long signal index is not equal to -1000.
// ---------------------------------------------------------------------
bool has_long_signal() const {
return last_signal_long != -1000;
}
// ---------------------------------------------------------------------
// Indicates if any short signal has ever been recorded.
//
// Returns:
// - True if a short signal index is not equal to -1000.
// ---------------------------------------------------------------------
bool has_short_signal() const {
return last_signal_short != -1000;
}
// ---------------------------------------------------------------------
// Returns the last bar index at which a long signal occurred.
//
// Returns:
// - Integer index representing bars since long signal.
// ---------------------------------------------------------------------
int get_long_signal() const {
return last_signal_long;
}
// ---------------------------------------------------------------------
// Returns the last bar index at which a short signal occurred.
//
// Returns:
// - Integer index representing bars since short signal.
// ---------------------------------------------------------------------
int get_short_signal() const {
return last_signal_short;
}
};
+176
View File
@@ -0,0 +1,176 @@
#property library
#include <MyLibs/Utils/DealingWithTime.mqh>
#include <Trade/Trade.mqh>
class TimeZones : public CObject {
protected:
string dt_s;
int len;
string dt_string;
datetime tC, tGMT, tNY, tLon, tFfm, tMosc, tSyd, tTok;
datetime tz_time;
string tz_date;
datetime time_start;
datetime time_end;
bool is_time;
datetime tGIVEN;
datetime tREQ;
datetime tzt;
datetime tz_req;
double required_close;
double ny_daily_close_protected(string symbol, int shift_days, bool print_data = false);
public:
string get_date_string_from_datetime(datetime dt);
datetime get_timezone_time(string time_zone, bool print_time);
datetime timezone_conversions(string time_zone_known, datetime time_given, string time_zone_required);
double ny_daily_close(string symbol, int shift_days, bool print_data = false);
};
// ---------------------------------------------------------------------
// Converts a datetime to a string excluding seconds.
//
// Parameters:
// - dt : Datetime object.
//
// Returns:
// - A string in the format "yyyy.mm.dd hh:mi".
// ---------------------------------------------------------------------
string TimeZones::get_date_string_from_datetime(datetime dt) {
dt_s = TimeToString(dt);
len = StringLen(dt_s);
dt_string = StringSubstr(dt_s, 0, len - 5);
return dt_string;
}
// ---------------------------------------------------------------------
// Gets the current time in the specified time zone.
//
// Parameters:
// - time_zone : One of "NY", "Lon", "Ffm", "Syd", "Mosc", "Tok".
// - print_time : If true, logs various times for debugging.
//
// Returns:
// - Current time in the specified time zone.
// ---------------------------------------------------------------------
datetime TimeZones::get_timezone_time(string time_zone, bool print_time) {
checkTimeOffset(TimeCurrent()); // Adjust DST
tC = TimeCurrent();
tGMT = TimeCurrent() + OffsetBroker.actOffset;
tNY = tGMT - (NYShift + DST_USD);
tLon = tGMT - (LondonShift + DST_EUR);
tFfm = tGMT - (FfmShift + DST_EUR);
tSyd = tGMT - (SidneyShift + DST_AUD);
tMosc = tGMT - (MoskwaShift + DST_RUS);
tTok = tGMT - (TokyoShift);
if (print_time) {
Print("----------------------------------");
Print("Broker: ", tC);
Print("GMT: ", tGMT);
Print("time in New York: ", tNY);
Print("time in London: ", tLon);
Print("time in Frankfurt: ", tFfm);
Print("time in Sidney: ", tSyd);
Print("time in Moscow: ", tMosc);
Print("time in Tokyo: ", tTok);
}
if (time_zone == "NY") return tNY;
if (time_zone == "Lon") return tLon;
if (time_zone == "Ffm") return tFfm;
if (time_zone == "Syd") return tSyd;
if (time_zone == "Mosc") return tMosc;
if (time_zone == "Tok") return tTok;
return NULL;
}
// ---------------------------------------------------------------------
// Converts a datetime from one timezone to another.
//
// Parameters:
// - time_zone_known : Original timezone of the datetime.
// - time_given : The datetime to convert.
// - time_zone_required : Desired output timezone.
//
// Returns:
// - The equivalent datetime in the target timezone.
// ---------------------------------------------------------------------
datetime TimeZones::timezone_conversions(string time_zone_known, datetime time_given, string time_zone_required) {
tGIVEN = time_given;
checkTimeOffset(tGIVEN); // Adjust DST
// Step 1: Convert known timezone to GMT
if (time_zone_known == "GMT") tGMT = tGIVEN;
if (time_zone_known == "Broker") tGMT = tGIVEN + OffsetBroker.actOffset;
if (time_zone_known == "NY") tGMT = tGIVEN + (NYShift + DST_USD);
if (time_zone_known == "Lon") tGMT = tGIVEN + (LondonShift + DST_EUR);
if (time_zone_known == "Ffm") tGMT = tGIVEN + (FfmShift + DST_EUR);
if (time_zone_known == "Syd") tGMT = tGIVEN + (SidneyShift + DST_AUD);
if (time_zone_known == "Mosc") tGMT = tGIVEN + (MoskwaShift + DST_RUS);
if (time_zone_known == "Tok") tGMT = tGIVEN + (TokyoShift);
// Step 2: Convert GMT to required timezone
if (time_zone_required == "GMT") tREQ = tGMT;
if (time_zone_required == "Broker") tREQ = tGMT - OffsetBroker.actOffset;
if (time_zone_required == "NY") tREQ = tGMT - (NYShift + DST_USD);
if (time_zone_required == "Lon") tREQ = tGMT - (LondonShift + DST_EUR);
if (time_zone_required == "Ffm") tREQ = tGMT - (FfmShift + DST_EUR);
if (time_zone_required == "Syd") tREQ = tGMT - (SidneyShift + DST_AUD);
if (time_zone_required == "Mosc") tREQ = tGMT - (MoskwaShift + DST_RUS);
if (time_zone_required == "Tok") tREQ = tGMT - (TokyoShift);
return tREQ;
}
// ---------------------------------------------------------------------
// Returns the most recent NY daily close price.
//
// Parameters:
// - symbol : Trading symbol.
// - shift_days : How many NY daily closes back to return.
// - print_data : If true, logs debug information.
//
// Returns:
// - The NY close price.
// ---------------------------------------------------------------------
double TimeZones::ny_daily_close(string symbol, int shift_days, bool print_data) {
required_close = ny_daily_close_protected(symbol, shift_days, print_data);
return required_close;
}
// ---------------------------------------------------------------------
// Internal implementation to compute NY daily close price.
//
// Logic:
// - Defines NY close as 5pm NY time = 00:00 broker + 17H back.
// - Adjusts for day shifts if required.
// - Returns the close price of the NY daily session.
// ---------------------------------------------------------------------
double TimeZones::ny_daily_close_protected(string symbol, int shift_days, bool print_data) {
datetime time_5pm = iTime(symbol, PERIOD_D1, 0) - (PeriodSeconds(PERIOD_H1) * 7);
datetime ny_close_in_brokers_time = timezone_conversions("NY", time_5pm, "Broker");
datetime ny_close_time = ny_close_in_brokers_time + PeriodSeconds(PERIOD_D1);
if (TimeCurrent() < ny_close_time) ny_close_time -= PeriodSeconds(PERIOD_D1);
int shift = iBarShift(symbol, PERIOD_H1, ny_close_time, false) + 1;
shift += (24 * (shift_days - 1));
double ny_close = iClose(symbol, PERIOD_H1, shift);
double br_close = iClose(symbol, PERIOD_H1, 1);
if (print_data) {
Print("shift ", shift);
Print("time_5pm ", time_5pm);
Print("ny_close_in_brokers_time ", ny_close_in_brokers_time);
Print("ny_close_time ", ny_close_time);
Print("ny_close ", ny_close);
Print("br_close ", br_close);
}
return ny_close;
}
+84
View File
@@ -0,0 +1,84 @@
#include <MyLibs/Utils/TimeZones.mqh>
class TradeSessionUtils {
protected:
TimeZones tz; // For handling timezone conversion
bool in_window; // Whether the current time is in the allowed window
datetime start_time; // Session start time (converted to Broker time)
datetime end_time; // Session end time (converted to Broker time)
public:
bool trade_window(string t1, string t2, string time_zone = "Broker", bool plot_range_inp = true);
};
// ---------------------------------------------------------------------
// Determines whether the current time is inside a defined trade session.
//
// Parameters:
// - t1 : Start time string (e.g., "22:00").
// - t2 : End time string (e.g., "01:00").
// - time_zone : The timezone of input times (default = "Broker").
// - plot_range_inp : If true, draws vertical lines for start/end.
//
// Returns:
// - true if current time is within the session window, false otherwise.
//
// Logic:
// - Handles overnight sessions (e.g. 22:0001:00) correctly.
// - Automatically rolls the window to the next day when expired.
// - Uses TimeZones class to convert time to broker timezone.
// ---------------------------------------------------------------------
bool TradeSessionUtils::trade_window(string t1, string t2, string time_zone, bool plot_range_inp) {
datetime _t1 = StringToTime(t1); // Convert string to datetime
datetime _t2 = StringToTime(t2); // Convert string to datetime
// Handle overnight windows (e.g. 22:0001:00)
if (_t1 > _t2) {
_t2 = _t2 + PeriodSeconds(PERIOD_D1);
}
int w_duration = (int)(_t2 - _t1); // Duration of the session in seconds
// Check if we're currently within the window
if (TimeCurrent() >= start_time && TimeCurrent() <= end_time) {
in_window = true;
}
// If we've moved beyond the previous window, define a new one
if (TimeCurrent() >= end_time) {
in_window = false;
// Convert start time to broker time based on user timezone input
start_time = tz.timezone_conversions(time_zone, StringToTime(t1), "Broker");
// If we've already passed today's start time, push it to tomorrow
if (TimeCurrent() >= start_time) {
start_time += PeriodSeconds(PERIOD_D1);
}
// End time is relative to updated start time
end_time = start_time + w_duration;
// Plot vertical lines if requested
if (plot_range_inp) {
string name = "Start Time" + (string)start_time;
if (start_time > 0) {
ObjectCreate(NULL, name, OBJ_VLINE, 0, start_time, 0);
ObjectSetInteger(NULL, name, OBJPROP_COLOR, clrBlue);
ObjectSetInteger(NULL, name, OBJPROP_BACK, true);
}
name = "End Time" + (string)end_time;
if (end_time > 0) {
ObjectCreate(NULL, name, OBJ_VLINE, 0, end_time, 0);
ObjectSetInteger(NULL, name, OBJPROP_COLOR, C'56,108,26');
ObjectSetInteger(NULL, name, OBJPROP_BACK, true);
}
ChartRedraw();
}
}
return in_window;
}