update to my mt5 libs to include better comments
This commit is contained in:
@@ -12,7 +12,19 @@ private:
|
||||
AtrEntry cache[]; // internal cache of ATR handles
|
||||
|
||||
public:
|
||||
// Get or create an ATR handle for a specific symbol/timeframe/period
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// 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)
|
||||
@@ -32,7 +44,18 @@ public:
|
||||
return handle;
|
||||
}
|
||||
|
||||
// Get ATR value from buffer (returns EMPTY_VALUE if failure)
|
||||
// ---------------------------------------------------------------------
|
||||
// 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) {
|
||||
@@ -51,7 +74,13 @@ public:
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
// Release all handles in the cache
|
||||
// ---------------------------------------------------------------------
|
||||
// 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)
|
||||
@@ -60,4 +89,3 @@ public:
|
||||
ArrayResize(cache, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+31
-19
@@ -1,31 +1,43 @@
|
||||
#include <Object.mqh>
|
||||
|
||||
class ChartUtils : public CObject {
|
||||
|
||||
public:
|
||||
void draw_line(double value, string name, color clr = clrBlack);
|
||||
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 (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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
|
||||
ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_SOLID);
|
||||
ObjectSetInteger(0, name, OBJPROP_WIDTH, 1);
|
||||
}
|
||||
|
||||
ResetLastError();
|
||||
ResetLastError();
|
||||
|
||||
if (!ObjectMove(0, name, 0, 0, value)) {
|
||||
Print(__FUNCTION__, ": failed to move the horizontal line! Error code = ", GetLastError());
|
||||
return;
|
||||
}
|
||||
if (!ObjectMove(0, name, 0, 0, value)) {
|
||||
Print(__FUNCTION__, ": failed to move the horizontal line! Error code = ", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
ChartRedraw();
|
||||
ChartRedraw();
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#include <MyLibs/Myfunctions.mqh>
|
||||
#include <MyLibs/OrderManagement.mqh>
|
||||
#include <MyLibs/Utils/MyEnums.mqh>
|
||||
#include <MyLibs/BacktestUtils/CustomMax.mqh>
|
||||
#include <MyLibs/BacktestUtils/TestDataSplit.mqh>
|
||||
CustomMax c_max;
|
||||
// MyFunctions mf;
|
||||
// OrderManagment om;
|
||||
//---
|
||||
input LOT_MODE inp_lot_mode = LOT_MODE_PCT_RISK; // Lot Size Mode
|
||||
input double inp_lot_var = 2; // Lot Size Var
|
||||
input SL_MODE inp_sl_mode = SL_ATR_MULTIPLE; // Stop-loss Mode
|
||||
input double inp_sl_var = 1.5; // Stop-loss Var
|
||||
input TP_MODE inp_tp_mode = TP_ATR_MULTIPLE; // Take-profit Mode
|
||||
input double inp_tp_var = 1; // Take-Profit Var
|
||||
string lot_mode = EnumToString(inp_lot_mode);
|
||||
string sl_mode = EnumToString(inp_sl_mode);
|
||||
string tp_mode = EnumToString(inp_tp_mode);
|
||||
input CUSTOM_MAX_TYPE inp_custom_criteria = CM_WIN_PERCENT;
|
||||
input int inp_opt_min_trades = 0; // 0/off
|
||||
input MODE_SPLIT_DATA inp_data_split_method = NO_SPLIT;
|
||||
input int inp_force_opt = 1;
|
||||
input group "-----------------------------------------"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+120
-66
@@ -1,94 +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);
|
||||
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"
|
||||
protected:
|
||||
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
|
||||
// ---------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Checks if a new bar has opened on the given timeframe and symbol
|
||||
// ---------------------------------------------------------------------
|
||||
// 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);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
previousTimes[idx] = bar_open_time;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false; // No new bar
|
||||
return false;
|
||||
}
|
||||
|
||||
// shift = 0 refers to the live candle (still forming)
|
||||
// shift = 1 is the most recently closed candle
|
||||
// shift = 2 is the one before that, etc.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (val[0] == EMPTY_VALUE) {
|
||||
Print("EMPTY_VALUE returned for buffer at shift=", shift);
|
||||
return EMPTY_VALUE;
|
||||
}
|
||||
|
||||
return val[0];
|
||||
return val[0];
|
||||
}
|
||||
|
||||
// Adjusts the point value for symbol to account for fractional pips (e.g., 5-digit brokers)
|
||||
// ---------------------------------------------------------------------
|
||||
// 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; // Adjusted pip value
|
||||
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 current Bid or Ask price for a symbol based on side (1 = Ask, 2 = Bid)
|
||||
// ---------------------------------------------------------------------
|
||||
// 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);
|
||||
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;
|
||||
if (price_side == 1) return ask;
|
||||
if (price_side == 2) return bid;
|
||||
|
||||
return 0.0; // Invalid input
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@@ -1,86 +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:
|
||||
// Struct to hold one (symbol → tracker) mapping
|
||||
private:
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Internal struct to associate a symbol with a SignalStateTracker.
|
||||
// ---------------------------------------------------------------------
|
||||
struct SymbolTracker {
|
||||
string symbol; // Symbol name (e.g. "EURUSD", "HSI")
|
||||
SignalStateTracker* tracker; // Pointer to the signal tracker for that symbol
|
||||
string symbol;
|
||||
SignalStateTracker* tracker;
|
||||
};
|
||||
|
||||
SymbolTracker trackers[]; // Dynamic array of symbol-tracker pairs
|
||||
SymbolTracker trackers[]; // Dynamic array of symbol-tracker mappings
|
||||
|
||||
// Helper function: Find the index of the given symbol in the array
|
||||
// ---------------------------------------------------------------------
|
||||
// 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; // Found symbol, return its index
|
||||
if (trackers[i].symbol == symbol)
|
||||
return i;
|
||||
}
|
||||
return -1; // Not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
public:
|
||||
// Destructor: automatically called when this object is destroyed (e.g. at EA shutdown)
|
||||
public:
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Destructor. Cleans up allocated memory when the object is destroyed.
|
||||
// ---------------------------------------------------------------------
|
||||
~MultiSymbolSignalTracker() {
|
||||
clear(); // Clean up memory when done
|
||||
clear();
|
||||
}
|
||||
|
||||
// Returns the SignalStateTracker for the given symbol.
|
||||
// If it doesn't exist yet, it creates one and stores it.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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; // Tracker already exists — return it
|
||||
if (idx != -1)
|
||||
return trackers[idx].tracker;
|
||||
|
||||
// If not found, create a new tracker for this symbol
|
||||
// Create new tracker
|
||||
SignalStateTracker* tracker = new SignalStateTracker();
|
||||
|
||||
SymbolTracker item;
|
||||
item.symbol = symbol;
|
||||
item.tracker = tracker;
|
||||
|
||||
// Add new item to dynamic array
|
||||
ArrayResize(trackers, ArraySize(trackers) + 1);
|
||||
trackers[ArraySize(trackers) - 1] = item;
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
// Deletes all trackers and resets the array.
|
||||
// Should be called in OnDeinit() to free memory.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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; // Manually free each dynamically created tracker
|
||||
delete trackers[i].tracker;
|
||||
}
|
||||
ArrayResize(trackers, 0); // Reset array to empty
|
||||
ArrayResize(trackers, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
Example usage in an EA:
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
// Declare the tracker globally (outside OnTick/OnTimer)
|
||||
MultiSymbolSignalTracker track_trigger;
|
||||
|
||||
// Inside your strategy() or OnTick():
|
||||
void strategy(string symbol, ...) {
|
||||
bool trig_long = ...; // Your signal logic
|
||||
bool trig_short = ...;
|
||||
|
||||
// Update the signal tracker for this symbol
|
||||
track_trigger.get_tracker(symbol).update_signal(trig_long, trig_short);
|
||||
|
||||
// Example: Check if a recent long signal occurred
|
||||
if (track_trigger.get_tracker(symbol).long_signal_recent(5)) {
|
||||
// Do something like open a trade
|
||||
}
|
||||
}
|
||||
|
||||
// In OnDeinit():
|
||||
void OnDeinit(const int reason) {
|
||||
track_trigger.clear(); // Clean up memory
|
||||
}
|
||||
|
||||
*/
|
||||
+36
-18
@@ -1,44 +1,61 @@
|
||||
#include <MyLibs/Utils/AtrHandleManager.mqh>
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| ResourceManager |
|
||||
//| |
|
||||
//| Tracks and releases indicator handles (iMA, iRSI, etc.) |
|
||||
//| Also delegates ATR handle cleanup to an external ATR manager |
|
||||
//+------------------------------------------------------------------+
|
||||
// ---------------------------------------------------------------------
|
||||
// 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:
|
||||
// --- 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
|
||||
// ---------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
|
||||
// --- Release all tracked resources:
|
||||
// ---------------------------------------------------------------------
|
||||
// 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:
|
||||
// --- Dynamic array of general indicator handles
|
||||
int handles[];
|
||||
|
||||
// --- Append a valid indicator handle to the internal array
|
||||
// Used by register_handle()
|
||||
// ---------------------------------------------------------------------
|
||||
// Adds a handle to the internal tracking list.
|
||||
// ---------------------------------------------------------------------
|
||||
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.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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)
|
||||
@@ -47,8 +64,9 @@ private:
|
||||
ArrayFree(handles);
|
||||
}
|
||||
|
||||
// --- Release ATR handles via external AtrHandleManager
|
||||
// No-op if atr_manager is not assigned
|
||||
// ---------------------------------------------------------------------
|
||||
// Releases any cached ATR handles using the external AtrHandleManager.
|
||||
// ---------------------------------------------------------------------
|
||||
void release_internal_handles() {
|
||||
if (atr_manager != NULL)
|
||||
atr_manager.release_handles();
|
||||
|
||||
@@ -1,22 +1,51 @@
|
||||
class SignalStateTracker {
|
||||
private:
|
||||
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 both directions to a default "unset" state.
|
||||
public:
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor initializes the signal tracker to a reset state.
|
||||
//
|
||||
// Logic:
|
||||
// - Sets both long and short signal indices to -1000.
|
||||
// ---------------------------------------------------------------------
|
||||
SignalStateTracker() {
|
||||
reset();
|
||||
}
|
||||
|
||||
// Resets the tracked signal bar indexes to an invalid default value (-1000).
|
||||
// ---------------------------------------------------------------------
|
||||
// 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 the signal tracker based on trigger presence per bar.
|
||||
// If signal is detected, sets to 1. If not, increments previous value.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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;
|
||||
@@ -31,34 +60,68 @@ class SignalStateTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if a long signal occurred within the last `max_bars` bars.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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 {
|
||||
// Assumes current bar is always bar index 1 (last closed bar).
|
||||
return has_long_signal() && (1 - last_signal_long <= max_bars);
|
||||
}
|
||||
|
||||
// Returns true if a short signal occurred within the last `max_bars` 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 {
|
||||
// Assumes current bar is always bar index 1 (last closed bar).
|
||||
return has_short_signal() && (1 - last_signal_short <= max_bars);
|
||||
}
|
||||
|
||||
// Returns true if a signal has been recorded for the long direction.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Returns true if a signal has been recorded for the short direction.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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 recorded signal bar index for the long direction.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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 recorded signal bar index for the short direction.
|
||||
// ---------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
+150
-118
@@ -1,144 +1,176 @@
|
||||
#property library
|
||||
#include <Trade/Trade.mqh>
|
||||
#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 ny_daily_close_protected(string symbol, int shift_days, bool print_data=false);
|
||||
double required_close;
|
||||
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;
|
||||
|
||||
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);
|
||||
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);
|
||||
};
|
||||
|
||||
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;
|
||||
// ---------------------------------------------------------------------
|
||||
// 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
|
||||
|
||||
datetime TimeZones::get_timezone_time(string time_zone, bool print_time){
|
||||
// https://www.mql5.com/en/code/45287
|
||||
// https://www.mql5.com/en/articles/9926
|
||||
// https://www.mql5.com/en/articles/9929
|
||||
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);
|
||||
|
||||
checkTimeOffset(TimeCurrent()); // check changes of DST
|
||||
// cto();
|
||||
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);
|
||||
}
|
||||
|
||||
tC = TimeCurrent();
|
||||
tGMT = TimeCurrent() + OffsetBroker.actOffset; // GMT
|
||||
tNY = tGMT - (NYShift+DST_USD); // time in New York (EST)
|
||||
tLon = tGMT - (LondonShift+DST_EUR); // time in London
|
||||
tFfm = tGMT - (FfmShift+DST_EUR); // time in Frankfurt
|
||||
tSyd = tGMT - (SidneyShift+DST_AUD); // time in Sidney
|
||||
tMosc = tGMT - (MoskwaShift+DST_RUS); // time in Moscow
|
||||
tTok = tGMT - (TokyoShift); // time in Tokyo - no DST
|
||||
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;
|
||||
|
||||
if(print_time==true){
|
||||
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;
|
||||
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
|
||||
|
||||
datetime TimeZones::timezone_conversions(string time_zone_known, datetime time_given, string time_zone_required){
|
||||
// https://www.mql5.com/en/code/45287
|
||||
// https://www.mql5.com/en/articles/9926
|
||||
// https://www.mql5.com/en/articles/9929
|
||||
// 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);
|
||||
|
||||
tGIVEN = time_given; //StringToTime(time_given);
|
||||
|
||||
checkTimeOffset(tGIVEN); // check changes of DST
|
||||
// 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);
|
||||
|
||||
// Get 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);}
|
||||
|
||||
// define the required time:
|
||||
tREQ = NULL;
|
||||
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;
|
||||
return tREQ;
|
||||
}
|
||||
|
||||
// Calculte NY close time:
|
||||
double TimeZones::ny_daily_close(string symbol, int shift_days, bool print_data=false){
|
||||
required_close = ny_daily_close_protected(symbol, shift_days, print_data);
|
||||
return required_close;
|
||||
// ---------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
double TimeZones::ny_daily_close_protected(string symbol, int shift_days, bool print_data=false){
|
||||
|
||||
// Get the brokers times for when NY openend today and tomorrow:
|
||||
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); // ny close tomorrow
|
||||
// ---------------------------------------------------------------------
|
||||
// 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 = ny_close_time - PeriodSeconds(PERIOD_D1); // ny close today
|
||||
}
|
||||
if (TimeCurrent() < ny_close_time) ny_close_time -= PeriodSeconds(PERIOD_D1);
|
||||
|
||||
// Get the number of hours since NY closed:
|
||||
int shift = iBarShift(symbol, PERIOD_H1, ny_close_time, false) + 1;
|
||||
shift = shift + (24 * (shift_days - 1)); // shift days if required:
|
||||
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);
|
||||
double ny_close = iClose(symbol, PERIOD_H1, shift);
|
||||
double br_close = iClose(symbol, PERIOD_H1, 1);
|
||||
|
||||
if(print_data==true){
|
||||
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;
|
||||
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;
|
||||
}
|
||||
@@ -12,6 +12,23 @@ 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:00–01: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
|
||||
|
||||
Reference in New Issue
Block a user