update to my mt5 libs to include better comments
This commit is contained in:
+100
-28
@@ -1,113 +1,173 @@
|
||||
#include <MyLibs/Utils/MarketDataUtils.mqh>
|
||||
#include <MyLibs/Utils/AtrHandleManager.mqh>
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// CLASS: AtrBands
|
||||
// ---------------------------------------------------------------------
|
||||
// Provides ATR-based upper/lower/middle band calculations and checks.
|
||||
// Useful for volatility-based stop placement, trend filters, or overlays.
|
||||
// ---------------------------------------------------------------------
|
||||
class AtrBands {
|
||||
private:
|
||||
MarketDataUtils market_data_utils;
|
||||
AtrHandleManager atr_manager;
|
||||
|
||||
double get_atr(string symbol, int atr_period, ENUM_TIMEFRAMES tf, int shift);
|
||||
|
||||
public:
|
||||
// Core band accessors
|
||||
double upper_band(string symbol, double trendline_var, int atr_period, ENUM_TIMEFRAMES tf, double mult = 1.0, int shift = 1);
|
||||
double lower_band(string symbol, double trendline_var, int atr_period, ENUM_TIMEFRAMES tf, double mult = 1.0, int shift = 1);
|
||||
double middle_band(string symbol, double trendline_var, ENUM_TIMEFRAMES tf, int shift = 1);
|
||||
|
||||
// Band checkers
|
||||
bool inside_upper_band(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult = 1.0, int shift = 1);
|
||||
bool inside_lower_band(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult = 1.0, int shift = 1);
|
||||
bool crossed_below_upper_band(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult = 1.0, int shift = 1);
|
||||
bool crossed_above_lower_band(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult = 1.0, int shift = 1);
|
||||
|
||||
// Plotting
|
||||
void plot_bands(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult = 1.0, int bars = 100, color clr = clrSkyBlue, int width = 1);
|
||||
|
||||
|
||||
protected:
|
||||
double get_atr(string symbol, int atr_period, ENUM_TIMEFRAMES tf, int shift);
|
||||
};
|
||||
|
||||
|
||||
// -------------------
|
||||
// Public Methods
|
||||
// -------------------
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Returns the upper ATR band level.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to use.
|
||||
// - trendline_var : Base trendline value (e.g., MA).
|
||||
// - atr_period : ATR period.
|
||||
// - tf : Timeframe for ATR.
|
||||
// - mult : ATR multiplier.
|
||||
// - shift : Bar shift to evaluate.
|
||||
// ---------------------------------------------------------------------
|
||||
double AtrBands::upper_band(string symbol, double trendline_var, int atr_period, ENUM_TIMEFRAMES tf, double mult, int shift) {
|
||||
double atr = get_atr(symbol, atr_period, tf, shift);
|
||||
return trendline_var + atr * mult;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Returns the lower ATR band level.
|
||||
//
|
||||
// Parameters:
|
||||
// - Same as upper_band, except lower band logic.
|
||||
// ---------------------------------------------------------------------
|
||||
double AtrBands::lower_band(string symbol, double trendline_var, int atr_period, ENUM_TIMEFRAMES tf, double mult, int shift) {
|
||||
double atr = get_atr(symbol, atr_period, tf, shift);
|
||||
return trendline_var - atr * mult;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Returns the middle band, which is simply the trendline.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol.
|
||||
// - trendline_var : The trendline value.
|
||||
// - tf : Timeframe (unused here).
|
||||
// - shift : Shift index (unused here).
|
||||
// ---------------------------------------------------------------------
|
||||
double AtrBands::middle_band(string symbol, double trendline_var, ENUM_TIMEFRAMES tf, int shift) {
|
||||
return trendline_var;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Checks if price is between trendline and upper band.
|
||||
//
|
||||
// Logic:
|
||||
// - Retrieves trendline and price.
|
||||
// - Compares if price lies between trendline and upper band.
|
||||
// ---------------------------------------------------------------------
|
||||
bool AtrBands::inside_upper_band(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult, int shift) {
|
||||
double price = iClose(symbol, tf, shift);
|
||||
double trendline_var = market_data_utils.get_buffer_value(handle, shift);
|
||||
double upper = upper_band(symbol, trendline_var, atr_period, tf, mult, shift);
|
||||
if (price == EMPTY_VALUE || trendline_var == EMPTY_VALUE || upper == EMPTY_VALUE) return false;
|
||||
if (price == EMPTY_VALUE || trendline_var == EMPTY_VALUE || upper == EMPTY_VALUE)
|
||||
return false;
|
||||
return (price > trendline_var && price < upper);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Checks if price is between trendline and lower band.
|
||||
//
|
||||
// Logic:
|
||||
// - Retrieves trendline and price.
|
||||
// - Compares if price lies between trendline and lower band.
|
||||
// ---------------------------------------------------------------------
|
||||
bool AtrBands::inside_lower_band(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult, int shift) {
|
||||
double price = iClose(symbol, tf, shift);
|
||||
double trendline_var = market_data_utils.get_buffer_value(handle, shift);
|
||||
double lower = lower_band(symbol, trendline_var, atr_period, tf, mult, shift);
|
||||
if (price == EMPTY_VALUE || trendline_var == EMPTY_VALUE || lower == EMPTY_VALUE) return false;
|
||||
if (price == EMPTY_VALUE || trendline_var == EMPTY_VALUE || lower == EMPTY_VALUE)
|
||||
return false;
|
||||
return (price < trendline_var && price > lower);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Detects if price has crossed below the upper band.
|
||||
//
|
||||
// Logic:
|
||||
// - Checks crossover from above to below upper band between bars [shift+1] and [shift].
|
||||
// ---------------------------------------------------------------------
|
||||
bool AtrBands::crossed_below_upper_band(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult, int shift) {
|
||||
double price = iClose(symbol, tf, shift);
|
||||
double prev_price = iClose(symbol, tf, shift + 1);
|
||||
|
||||
double trendline_var = market_data_utils.get_buffer_value(handle, shift);
|
||||
double prev_trendline_var = market_data_utils.get_buffer_value(handle, shift + 1);
|
||||
|
||||
double upper = upper_band(symbol, trendline_var, atr_period, tf, mult, shift);
|
||||
double prev_upper = upper_band(symbol, prev_trendline_var, atr_period, tf, mult, shift + 1);
|
||||
|
||||
if (price == EMPTY_VALUE || prev_price == EMPTY_VALUE || trendline_var == EMPTY_VALUE || prev_trendline_var == EMPTY_VALUE) return false;
|
||||
if (price == EMPTY_VALUE || prev_price == EMPTY_VALUE || trendline_var == EMPTY_VALUE || prev_trendline_var == EMPTY_VALUE)
|
||||
return false;
|
||||
|
||||
return (prev_price > prev_upper && price < upper);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Detects if price has crossed above the lower band.
|
||||
//
|
||||
// Logic:
|
||||
// - Checks crossover from below to above lower band between bars [shift+1] and [shift].
|
||||
// ---------------------------------------------------------------------
|
||||
bool AtrBands::crossed_above_lower_band(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult, int shift) {
|
||||
double price = iClose(symbol, tf, shift);
|
||||
double prev_price = iClose(symbol, tf, shift + 1);
|
||||
|
||||
double trendline_var = market_data_utils.get_buffer_value(handle, shift);
|
||||
double prev_trendline_var = market_data_utils.get_buffer_value(handle, shift + 1);
|
||||
|
||||
double lower = lower_band(symbol, trendline_var, atr_period, tf, mult, shift);
|
||||
double prev_lower = lower_band(symbol, prev_trendline_var, atr_period, tf, mult, shift + 1);
|
||||
|
||||
if (price == EMPTY_VALUE || prev_price == EMPTY_VALUE || trendline_var == EMPTY_VALUE || prev_trendline_var == EMPTY_VALUE) return false;
|
||||
if (price == EMPTY_VALUE || prev_price == EMPTY_VALUE || trendline_var == EMPTY_VALUE || prev_trendline_var == EMPTY_VALUE)
|
||||
return false;
|
||||
|
||||
return (prev_price < prev_lower && price > lower);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Plots the ATR bands as OBJ_TREND lines on chart.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to draw on.
|
||||
// - handle : Trendline handle (e.g., MA).
|
||||
// - atr_period : ATR period for bands.
|
||||
// - tf : Timeframe.
|
||||
// - mult : ATR multiplier.
|
||||
// - bars : Number of bars to plot.
|
||||
// - clr : Line color.
|
||||
// - width : Line width.
|
||||
// ---------------------------------------------------------------------
|
||||
void AtrBands::plot_bands(string symbol, int handle, int atr_period, ENUM_TIMEFRAMES tf, double mult, int bars, color line_color, int width) {
|
||||
for (int i = bars; i >= 1; i--) {
|
||||
double trendline = market_data_utils.get_buffer_value(handle, i);
|
||||
if (trendline == EMPTY_VALUE) continue;
|
||||
if (trendline == EMPTY_VALUE)
|
||||
continue;
|
||||
|
||||
double atr = get_atr(symbol, atr_period, tf, i);
|
||||
if (atr == EMPTY_VALUE) continue;
|
||||
if (atr == EMPTY_VALUE)
|
||||
continue;
|
||||
|
||||
double upper = trendline + atr * mult;
|
||||
double lower = trendline - atr * mult;
|
||||
|
||||
datetime time1 = iTime(symbol, tf, i);
|
||||
datetime time2 = iTime(symbol, tf, i - 1);
|
||||
|
||||
string upper_name = "ATR_Upper_" + symbol + "_" + TimeToString(time1, TIME_DATE | TIME_MINUTES);
|
||||
string lower_name = "ATR_Lower_" + symbol + "_" + TimeToString(time1, TIME_DATE | TIME_MINUTES);
|
||||
string middle_name = "ATR_middle_" + symbol + "_" + TimeToString(time1, TIME_DATE | TIME_MINUTES);
|
||||
string upper_name = "ATR_Upper_" + symbol + "_" + TimeToString(time1, TIME_DATE | TIME_MINUTES);
|
||||
string lower_name = "ATR_Lower_" + symbol + "_" + TimeToString(time1, TIME_DATE | TIME_MINUTES);
|
||||
string middle_name = "ATR_Middle_" + symbol + "_" + TimeToString(time1, TIME_DATE | TIME_MINUTES);
|
||||
|
||||
if (ObjectFind(0, upper_name) < 0) {
|
||||
ObjectCreate(0, upper_name, OBJ_TREND, 0, time1, upper, time2, upper);
|
||||
@@ -140,6 +200,18 @@ void AtrBands::plot_bands(string symbol, int handle, int atr_period, ENUM_TIMEFR
|
||||
ChartRedraw();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Retrieves the ATR value via the shared ATR manager.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Symbol to calculate ATR on.
|
||||
// - atr_period : ATR calculation period.
|
||||
// - tf : Timeframe of the ATR.
|
||||
// - shift : Bar index to retrieve.
|
||||
//
|
||||
// Returns:
|
||||
// - The ATR value at the given shift.
|
||||
// ---------------------------------------------------------------------
|
||||
double AtrBands::get_atr(string symbol, int atr_period, ENUM_TIMEFRAMES tf, int shift) {
|
||||
return atr_manager.get_atr_value(symbol, tf, atr_period, shift);
|
||||
}
|
||||
|
||||
@@ -1,59 +1,76 @@
|
||||
#include <MyLibs/Utils/MarketDataUtils.mqh>
|
||||
//+------------------------------------------------------------------+
|
||||
//| TrendlineSignal: A utility class to detect trendline crossovers |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// CLASS: TrendlineAnalyser
|
||||
// ---------------------------------------------------------------------
|
||||
// A utility class to detect price crossovers with a trendline buffer.
|
||||
// Supports both crossover detection and trend direction checks.
|
||||
// ---------------------------------------------------------------------
|
||||
class TrendlineAnalyser {
|
||||
private:
|
||||
private:
|
||||
MarketDataUtils market_data_utils;
|
||||
|
||||
public:
|
||||
// Main method: detects whether price has crossed the trendline up (long) or down (short)
|
||||
// Parameters:
|
||||
// - symbol: the symbol we're evaluating (e.g., "EURUSD")
|
||||
// - handle: the indicator handle for the trendline (e.g., iMA handle)
|
||||
// - cross_long: output bool set to true if a bullish cross is detected
|
||||
// - cross_short: output bool set to true if a bearish cross is detected
|
||||
void detect_cross(string symbol, int handle, bool& cross_long, bool& cross_short, int shift=1) {
|
||||
cross_long = false;
|
||||
cross_short = false;
|
||||
|
||||
// --- Retrieve prices and trendline values from last 2 closed bars
|
||||
double price = iClose(symbol, PERIOD_CURRENT, shift); // most recent closed bar
|
||||
double prev_price = iClose(symbol, PERIOD_CURRENT, shift + 1); // bar before that
|
||||
|
||||
double trendline = market_data_utils.get_buffer_value(handle, shift); // trendline now
|
||||
double prev_trendline = market_data_utils.get_buffer_value(handle, shift+1); // trendline before
|
||||
|
||||
// --- Exit early if any of the data is missing or invalid
|
||||
if (price == EMPTY_VALUE || prev_price == EMPTY_VALUE || trendline == EMPTY_VALUE || prev_trendline == EMPTY_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// --- Detect bullish crossover (price moves from below to above the trendline)
|
||||
cross_long = (prev_price < prev_trendline && price > trendline);
|
||||
|
||||
// --- Detect bearish crossover (price moves from above to below the trendline)
|
||||
cross_short = (prev_price > prev_trendline && price < trendline);
|
||||
}
|
||||
// METHOD: determines if price is currently trending above or below the trendline
|
||||
// Parameters:
|
||||
// - symbol: trading symbol (e.g., "EURUSD")
|
||||
// - handle: trendline indicator handle
|
||||
// - is_direction_long: output bool, true if price is above trendline
|
||||
// - is_direction_short: output bool, true if price is below trendline
|
||||
// - shift: which candle to check (default: 1 = last closed bar)
|
||||
void trend_direction(string symbol, int handle, bool& direction_long, bool& direction_short, int shift = 1) {
|
||||
direction_long = false;
|
||||
direction_short = false;
|
||||
|
||||
double price = iClose(symbol, PERIOD_CURRENT, shift);
|
||||
double trendline = market_data_utils.get_buffer_value(handle, shift);
|
||||
|
||||
if (price == EMPTY_VALUE || trendline == EMPTY_VALUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
direction_long = (price > trendline);
|
||||
direction_short = (price < trendline);
|
||||
}
|
||||
public:
|
||||
void detect_cross(string symbol, int handle, bool& cross_long, bool& cross_short, int shift = 1);
|
||||
void trend_direction(string symbol, int handle, bool& direction_long, bool& direction_short, int shift = 1);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Detects whether price has crossed above (long) or below (short)
|
||||
// a trendline between the two most recent closed bars.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Trading symbol (e.g., "EURUSD").
|
||||
// - handle : Indicator handle for the trendline buffer.
|
||||
// - cross_long : Output true if bullish crossover detected.
|
||||
// - cross_short : Output true if bearish crossover detected.
|
||||
// - shift : Bar shift to evaluate (default: 1 = last closed bar).
|
||||
//
|
||||
// Logic:
|
||||
// - Retrieves price and trendline values for the current and previous bar.
|
||||
// - Checks for a crossover by comparing price vs trendline movement.
|
||||
// ---------------------------------------------------------------------
|
||||
void TrendlineAnalyser::detect_cross(string symbol, int handle, bool& cross_long, bool& cross_short, int shift) {
|
||||
cross_long = false;
|
||||
cross_short = false;
|
||||
|
||||
double price = iClose(symbol, PERIOD_CURRENT, shift);
|
||||
double prev_price = iClose(symbol, PERIOD_CURRENT, shift + 1);
|
||||
|
||||
double trendline = market_data_utils.get_buffer_value(handle, shift);
|
||||
double prev_trendline = market_data_utils.get_buffer_value(handle, shift + 1);
|
||||
|
||||
if (price == EMPTY_VALUE || prev_price == EMPTY_VALUE || trendline == EMPTY_VALUE || prev_trendline == EMPTY_VALUE)
|
||||
return;
|
||||
|
||||
cross_long = (prev_price < prev_trendline && price > trendline);
|
||||
cross_short = (prev_price > prev_trendline && price < trendline);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Checks if price is currently above or below the trendline.
|
||||
//
|
||||
// Parameters:
|
||||
// - symbol : Trading symbol (e.g., "EURUSD").
|
||||
// - handle : Trendline indicator handle.
|
||||
// - direction_long : Output true if price is above trendline.
|
||||
// - direction_short : Output true if price is below trendline.
|
||||
// - shift : Bar index to check (default: 1).
|
||||
//
|
||||
// Logic:
|
||||
// - Retrieves price and trendline at the specified shift.
|
||||
// - Compares relative position of price to trendline.
|
||||
// ---------------------------------------------------------------------
|
||||
void TrendlineAnalyser::trend_direction(string symbol, int handle, bool& direction_long, bool& direction_short, int shift) {
|
||||
direction_long = false;
|
||||
direction_short = false;
|
||||
|
||||
double price = iClose(symbol, PERIOD_CURRENT, shift);
|
||||
double trendline = market_data_utils.get_buffer_value(handle, shift);
|
||||
|
||||
if (price == EMPTY_VALUE || trendline == EMPTY_VALUE)
|
||||
return;
|
||||
|
||||
direction_long = (price > trendline);
|
||||
direction_short = (price < trendline);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user