Overview To fully integrate the enhanced external trade management system, updates are required to 5 out of 7 existing modules. The updates maintain backward compatibility while adding new functionality for external trade handling. Module Update Requirements 🟢 No Updates Required (2 modules) TechnicalAnalysis.mqh - Already provides necessary calculations EntrySystem.mqh - Only handles EA's own entry signals 🟡 Minor Updates (2 modules) DataTypes.mqh - Add external trade structures and fields Utilities.mqh - Enhanced logging for external trades 🟠 Moderate Updates (3 modules) RiskManager.mqh - Enhanced risk enforcement methods TradeManager.mqh - Improved stop management for externals Dashboard.mqh - Display external trade information Integration Steps Phase 1: Data Structures (DataTypes.mqh) Add ENUM_EXTERNAL_STATUS enumeration Extend ManagedTrade structure with external-specific fields Add ExternalTradeStats structure for metrics Update DashboardConfig with show_external flag Key additions: external_status - Track state of external trade source_name - Identify where trade came from stops_modified - Track if we modified the trade original_sl/tp - Store original values for comparison Phase 2: Risk Management (RiskManager.mqh) Add EnforceRiskRulesEnhanced() method Implement GetExternalExposure() for risk aggregation Add UpdateExternalStats() for tracking Enhance ValidateAndAdjustRiskExternal() method Key features: Separate risk calculation for external trades Cache mechanism for performance Statistical tracking of external positions Smart risk adjustment without closing trades Phase 3: Trade Management (TradeManager.mqh) Add ApplyDefaultStopsEnhanced() with better logic Implement OverrideExternalStops() with smart override Create ManageExternalTrade() with different rules Add ApplyBreakevenExternal() with wider triggers Key features: Smart stop override (only improve, never worsen) Different management rules for external trades Respect minimum broker distances Track modification success/failure rates Phase 4: User Interface (Dashboard.mqh) Add CreateExternalSection() for display area Implement UpdateExternalSection() for real-time updates Add SetCustomText() for flexible display Create ShowExternalTrades() toggle method Key features: Real-time external trade count and risk Color-coded risk warnings List of active external positions Modification statistics display Phase 5: Logging (Utilities.mqh) Add LogExternalTrade() for detailed event logging Create separate CSV log for external trades Enhance GenerateReportEnhanced() with external section Add IdentifyTradeSource() for magic number interpretation Key features: Separate CSV log for external trade events Detailed tracking of all modifications Source identification from magic numbers Enhanced reporting with external statistics
746 lines
No EOL
29 KiB
MQL5
746 lines
No EOL
29 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| QQE_Cross_v6.0_Main.mq5 |
|
|
//| Converted from Pine Script v3 |
|
|
//| by JustUncleL |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2024, Based on JustUncleL's work"
|
|
#property link "https://www.mql5.com"
|
|
#property version "6.00"
|
|
#property indicator_chart_window
|
|
#property indicator_buffers 22
|
|
#property indicator_plots 12
|
|
|
|
// Input parameters
|
|
input int RSILen = 14; // RSI Length
|
|
input int SF = 8; // RSI Smoothing Factor
|
|
input double QQEfactor = 5.0; // Fast QQE Factor
|
|
input int threshhold = 10; // RSI Threshold
|
|
input int anchor = 4; // Relative TimeFrame Multiplier for Second MA Ribbon
|
|
|
|
// MA parameters
|
|
input ENUM_MA_METHOD type1 = MODE_EMA; // Fast MA Type
|
|
input int len1 = 16; // Fast MA Length
|
|
input ENUM_MA_METHOD type2 = MODE_EMA; // Medium MA Type
|
|
input int len2 = 21; // Medium MA Length
|
|
input ENUM_MA_METHOD type3 = MODE_EMA; // Slow MA Type
|
|
input int len3 = 26; // Slow MA Length
|
|
|
|
// Display options
|
|
input bool showAvgs = true; // Show Moving Average Lines
|
|
input bool dynamicMAColors = true; // Use Dynamic MA Colors (Bullish/Bearish)
|
|
input bool colorBars = true; // Color Price Bars by Trend
|
|
input bool sQQEx = true; // Show QQE Signal crosses
|
|
input bool sQQEz = false; // Show QQE Zero crosses
|
|
input bool sQQEc = true; // Show QQE Threshold Channel Exits
|
|
|
|
// Color inputs for MAs (when not using dynamic colors)
|
|
input color colorMAFast = clrLime; // Fast MA Color
|
|
input color colorMAMedium = clrYellow; // Medium MA Color
|
|
input color colorMASlow = clrRed; // Slow MA Color
|
|
input color colorMAFastAlt = clrLightGreen; // Fast MA Alt Color
|
|
input color colorMAMediumAlt = clrGold; // Medium MA Alt Color
|
|
input color colorMASlowAlt = clrCrimson; // Slow MA Alt Color
|
|
|
|
// Dynamic color inputs (when dynamicMAColors = true)
|
|
input color colorMABullish = clrLime; // MA Bullish Color
|
|
input color colorMABearish = clrRed; // MA Bearish Color
|
|
input color colorMANeutral = clrGray; // MA Neutral Color
|
|
|
|
// Color inputs for signals
|
|
input color colorBuySignal = clrLime; // Buy Signal Color
|
|
input color colorSellSignal = clrRed; // Sell Signal Color
|
|
input color colorMAGreen = clrAqua; // MA Turned Green Color
|
|
input color colorMABlue = clrBlue; // MA Turned Red Color
|
|
input color colorTPSignal = clrViolet; // Take Profit Color
|
|
|
|
// Signal options
|
|
input string tradeSignal = "XC"; // Select which QQE signal to Buy/Sell (XC/XQ/XZ)
|
|
input string closeSignal = "XQ"; // Select which QQE signal to Close Order (XC/XQ/XZ)
|
|
input bool xfilter = true; // Filter XQ Buy/Sell Orders by Threshold
|
|
input bool filter = false; // Use Moving Average Filter
|
|
input bool dfilter = true; // Use Trend Directional Filter
|
|
input bool ufirst = false; // Only Alert First Buy/Sell in a new Trend
|
|
|
|
// Indicator buffers
|
|
double ma_fastBuffer[];
|
|
double ma_mediumBuffer[];
|
|
double ma_slowBuffer[];
|
|
double ma_fast_altBuffer[];
|
|
double ma_medium_altBuffer[];
|
|
double ma_slow_altBuffer[];
|
|
double BuySignalBuffer[];
|
|
double SellSignalBuffer[];
|
|
double TurnedAquaBuffer[];
|
|
double TurnedBlueBuffer[];
|
|
double TPLongBuffer[];
|
|
double TPShortBuffer[];
|
|
// Color index buffers for dynamic MA colors
|
|
double ma_mediumColorBuffer[];
|
|
double ma_medium_altColorBuffer[];
|
|
|
|
// Calculation buffers
|
|
double RSIBuffer[];
|
|
double RSIndexBuffer[];
|
|
double FastAtrRsiTLBuffer[];
|
|
double longbandBuffer[];
|
|
double shortbandBuffer[];
|
|
double CloseLongBuffer[];
|
|
double CloseShortBuffer[];
|
|
double ColorBuffer[];
|
|
|
|
// Global variables
|
|
int rsi_handle;
|
|
int trend[];
|
|
int direction[];
|
|
int altDirection[];
|
|
double AtrRsi[];
|
|
double MaAtrRsi[];
|
|
double DeltaFastAtrRsi[];
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
// Set indicator name
|
|
IndicatorSetString(INDICATOR_SHORTNAME, "QQE Cross v6.0");
|
|
IndicatorSetInteger(INDICATOR_DIGITS, _Digits);
|
|
|
|
// Set buffer mapping
|
|
int idx = 0;
|
|
|
|
// Data buffers
|
|
SetIndexBuffer(idx++, ma_fastBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, ma_mediumBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, ma_slowBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, ma_fast_altBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, ma_medium_altBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, ma_slow_altBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, BuySignalBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, SellSignalBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, TurnedAquaBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, TurnedBlueBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, TPLongBuffer, INDICATOR_DATA);
|
|
SetIndexBuffer(idx++, TPShortBuffer, INDICATOR_DATA);
|
|
|
|
// Color buffers for dynamic MA colors
|
|
SetIndexBuffer(idx++, ma_mediumColorBuffer, INDICATOR_COLOR_INDEX);
|
|
SetIndexBuffer(idx++, ma_medium_altColorBuffer, INDICATOR_COLOR_INDEX);
|
|
|
|
// Calculation buffers
|
|
SetIndexBuffer(idx++, RSIBuffer, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(idx++, RSIndexBuffer, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(idx++, FastAtrRsiTLBuffer, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(idx++, longbandBuffer, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(idx++, shortbandBuffer, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(idx++, CloseLongBuffer, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(idx++, CloseShortBuffer, INDICATOR_CALCULATIONS);
|
|
SetIndexBuffer(idx++, ColorBuffer, INDICATOR_CALCULATIONS);
|
|
|
|
// Configure MA plots
|
|
PlotIndexSetInteger(0, PLOT_DRAW_TYPE, showAvgs ? DRAW_LINE : DRAW_NONE);
|
|
PlotIndexSetInteger(0, PLOT_LINE_COLOR, colorMAFast);
|
|
PlotIndexSetString(0, PLOT_LABEL, "MA Fast");
|
|
|
|
PlotIndexSetInteger(1, PLOT_DRAW_TYPE, showAvgs ? (dynamicMAColors ? DRAW_COLOR_LINE : DRAW_LINE) : DRAW_NONE);
|
|
PlotIndexSetInteger(1, PLOT_LINE_COLOR, colorMAMedium);
|
|
PlotIndexSetInteger(1, PLOT_LINE_WIDTH, 2);
|
|
PlotIndexSetString(1, PLOT_LABEL, "MA Medium");
|
|
if(dynamicMAColors)
|
|
{
|
|
PlotIndexSetInteger(1, PLOT_COLOR_INDEXES, 3);
|
|
PlotIndexSetInteger(1, PLOT_LINE_COLOR, 0, colorMABullish);
|
|
PlotIndexSetInteger(1, PLOT_LINE_COLOR, 1, colorMANeutral);
|
|
PlotIndexSetInteger(1, PLOT_LINE_COLOR, 2, colorMABearish);
|
|
}
|
|
|
|
PlotIndexSetInteger(2, PLOT_DRAW_TYPE, showAvgs ? DRAW_LINE : DRAW_NONE);
|
|
PlotIndexSetInteger(2, PLOT_LINE_COLOR, colorMASlow);
|
|
PlotIndexSetString(2, PLOT_LABEL, "MA Slow");
|
|
|
|
PlotIndexSetInteger(3, PLOT_DRAW_TYPE, showAvgs && anchor > 1 ? DRAW_LINE : DRAW_NONE);
|
|
PlotIndexSetInteger(3, PLOT_LINE_COLOR, colorMAFastAlt);
|
|
PlotIndexSetInteger(3, PLOT_LINE_STYLE, STYLE_DASH);
|
|
PlotIndexSetString(3, PLOT_LABEL, "MA Fast Alt");
|
|
|
|
PlotIndexSetInteger(4, PLOT_DRAW_TYPE, showAvgs && anchor > 1 ? (dynamicMAColors ? DRAW_COLOR_LINE : DRAW_LINE) : DRAW_NONE);
|
|
PlotIndexSetInteger(4, PLOT_LINE_COLOR, colorMAMediumAlt);
|
|
PlotIndexSetInteger(4, PLOT_LINE_WIDTH, 2);
|
|
PlotIndexSetInteger(4, PLOT_LINE_STYLE, STYLE_DASH);
|
|
PlotIndexSetString(4, PLOT_LABEL, "MA Medium Alt");
|
|
if(dynamicMAColors)
|
|
{
|
|
PlotIndexSetInteger(4, PLOT_COLOR_INDEXES, 3);
|
|
PlotIndexSetInteger(4, PLOT_LINE_COLOR, 0, colorMABullish);
|
|
PlotIndexSetInteger(4, PLOT_LINE_COLOR, 1, colorMANeutral);
|
|
PlotIndexSetInteger(4, PLOT_LINE_COLOR, 2, colorMABearish);
|
|
}
|
|
|
|
PlotIndexSetInteger(5, PLOT_DRAW_TYPE, showAvgs && anchor > 1 ? DRAW_LINE : DRAW_NONE);
|
|
PlotIndexSetInteger(5, PLOT_LINE_COLOR, colorMASlowAlt);
|
|
PlotIndexSetInteger(5, PLOT_LINE_STYLE, STYLE_DASH);
|
|
PlotIndexSetString(5, PLOT_LABEL, "MA Slow Alt");
|
|
|
|
// Signal arrows
|
|
PlotIndexSetInteger(6, PLOT_DRAW_TYPE, DRAW_ARROW);
|
|
PlotIndexSetInteger(6, PLOT_ARROW, 233);
|
|
PlotIndexSetInteger(6, PLOT_LINE_COLOR, colorBuySignal);
|
|
PlotIndexSetInteger(6, PLOT_LINE_WIDTH, 2);
|
|
PlotIndexSetString(6, PLOT_LABEL, "Buy Signal");
|
|
|
|
PlotIndexSetInteger(7, PLOT_DRAW_TYPE, DRAW_ARROW);
|
|
PlotIndexSetInteger(7, PLOT_ARROW, 234);
|
|
PlotIndexSetInteger(7, PLOT_LINE_COLOR, colorSellSignal);
|
|
PlotIndexSetInteger(7, PLOT_LINE_WIDTH, 2);
|
|
PlotIndexSetString(7, PLOT_LABEL, "Sell Signal");
|
|
|
|
PlotIndexSetInteger(8, PLOT_DRAW_TYPE, DRAW_ARROW);
|
|
PlotIndexSetInteger(8, PLOT_ARROW, 233);
|
|
PlotIndexSetInteger(8, PLOT_LINE_COLOR, colorMAGreen);
|
|
PlotIndexSetString(8, PLOT_LABEL, "MA Turned Green");
|
|
|
|
PlotIndexSetInteger(9, PLOT_DRAW_TYPE, DRAW_ARROW);
|
|
PlotIndexSetInteger(9, PLOT_ARROW, 234);
|
|
PlotIndexSetInteger(9, PLOT_LINE_COLOR, colorMABlue);
|
|
PlotIndexSetString(9, PLOT_LABEL, "MA Turned Red");
|
|
|
|
PlotIndexSetInteger(10, PLOT_DRAW_TYPE, DRAW_ARROW);
|
|
PlotIndexSetInteger(10, PLOT_ARROW, 116);
|
|
PlotIndexSetInteger(10, PLOT_LINE_COLOR, colorTPSignal);
|
|
PlotIndexSetString(10, PLOT_LABEL, "Take Profit Long");
|
|
|
|
PlotIndexSetInteger(11, PLOT_DRAW_TYPE, DRAW_ARROW);
|
|
PlotIndexSetInteger(11, PLOT_ARROW, 116);
|
|
PlotIndexSetInteger(11, PLOT_LINE_COLOR, colorTPSignal);
|
|
PlotIndexSetString(11, PLOT_LABEL, "Take Profit Short");
|
|
|
|
// Initialize arrays
|
|
ArraySetAsSeries(ma_fastBuffer, true);
|
|
ArraySetAsSeries(ma_mediumBuffer, true);
|
|
ArraySetAsSeries(ma_slowBuffer, true);
|
|
ArraySetAsSeries(ma_fast_altBuffer, true);
|
|
ArraySetAsSeries(ma_medium_altBuffer, true);
|
|
ArraySetAsSeries(ma_slow_altBuffer, true);
|
|
ArraySetAsSeries(BuySignalBuffer, true);
|
|
ArraySetAsSeries(SellSignalBuffer, true);
|
|
ArraySetAsSeries(TurnedAquaBuffer, true);
|
|
ArraySetAsSeries(TurnedBlueBuffer, true);
|
|
ArraySetAsSeries(TPLongBuffer, true);
|
|
ArraySetAsSeries(TPShortBuffer, true);
|
|
ArraySetAsSeries(ma_mediumColorBuffer, true);
|
|
ArraySetAsSeries(ma_medium_altColorBuffer, true);
|
|
ArraySetAsSeries(RSIBuffer, true);
|
|
ArraySetAsSeries(RSIndexBuffer, true);
|
|
ArraySetAsSeries(FastAtrRsiTLBuffer, true);
|
|
ArraySetAsSeries(longbandBuffer, true);
|
|
ArraySetAsSeries(shortbandBuffer, true);
|
|
ArraySetAsSeries(CloseLongBuffer, true);
|
|
ArraySetAsSeries(CloseShortBuffer, true);
|
|
ArraySetAsSeries(ColorBuffer, true);
|
|
|
|
// Create RSI handle
|
|
rsi_handle = iRSI(NULL, 0, RSILen, PRICE_CLOSE);
|
|
if(rsi_handle == INVALID_HANDLE)
|
|
{
|
|
Print("Error creating RSI handle");
|
|
return(INIT_FAILED);
|
|
}
|
|
|
|
// Resize arrays
|
|
int bars = Bars(_Symbol, _Period);
|
|
ArrayResize(trend, bars);
|
|
ArrayResize(direction, bars);
|
|
ArrayResize(altDirection, bars);
|
|
ArrayResize(AtrRsi, bars);
|
|
ArrayResize(MaAtrRsi, bars);
|
|
ArrayResize(DeltaFastAtrRsi, bars);
|
|
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator deinitialization function |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
IndicatorRelease(rsi_handle);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate EMA |
|
|
//+------------------------------------------------------------------+
|
|
double CalculateEMA(const double &price[], int period, int shift, double prev_ema)
|
|
{
|
|
if(shift >= ArraySize(price) - 1) return price[shift];
|
|
|
|
double alpha = 2.0 / (period + 1);
|
|
if(prev_ema == 0)
|
|
{
|
|
// Calculate SMA for first value
|
|
double sum = 0;
|
|
for(int i = 0; i < period && shift + i < ArraySize(price); i++)
|
|
sum += price[shift + i];
|
|
return sum / period;
|
|
}
|
|
|
|
return alpha * price[shift] + (1 - alpha) * prev_ema;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate Moving Average |
|
|
//+------------------------------------------------------------------+
|
|
double CalculateMA(const double &price[], ENUM_MA_METHOD method, int period, int shift)
|
|
{
|
|
double ma_values[];
|
|
ArraySetAsSeries(ma_values, true);
|
|
|
|
int copied = 0;
|
|
switch(method)
|
|
{
|
|
case MODE_SMA:
|
|
copied = iMA(_Symbol, _Period, period, 0, MODE_SMA, PRICE_CLOSE);
|
|
break;
|
|
case MODE_EMA:
|
|
copied = iMA(_Symbol, _Period, period, 0, MODE_EMA, PRICE_CLOSE);
|
|
break;
|
|
case MODE_SMMA:
|
|
copied = iMA(_Symbol, _Period, period, 0, MODE_SMMA, PRICE_CLOSE);
|
|
break;
|
|
case MODE_LWMA:
|
|
copied = iMA(_Symbol, _Period, period, 0, MODE_LWMA, PRICE_CLOSE);
|
|
break;
|
|
}
|
|
|
|
if(copied > 0 && shift < ArraySize(price))
|
|
{
|
|
if(CopyBuffer(copied, 0, shift, 1, ma_values) > 0)
|
|
return ma_values[0];
|
|
}
|
|
|
|
// Fallback to manual calculation
|
|
if(method == MODE_SMA)
|
|
{
|
|
double sum = 0;
|
|
for(int i = 0; i < period && shift + i < ArraySize(price); i++)
|
|
sum += price[shift + i];
|
|
return sum / period;
|
|
}
|
|
else if(method == MODE_EMA)
|
|
{
|
|
static double prev_ema = 0;
|
|
if(shift == ArraySize(price) - 1) prev_ema = 0;
|
|
prev_ema = CalculateEMA(price, period, shift, prev_ema);
|
|
return prev_ema;
|
|
}
|
|
|
|
return price[shift];
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check if value is rising |
|
|
//+------------------------------------------------------------------+
|
|
bool IsRising(const double &buffer[], int shift, int period)
|
|
{
|
|
if(shift + period >= ArraySize(buffer)) return false;
|
|
return buffer[shift] > buffer[shift + period];
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Check if value is falling |
|
|
//+------------------------------------------------------------------+
|
|
bool IsFalling(const double &buffer[], int shift, int period)
|
|
{
|
|
if(shift + period >= ArraySize(buffer)) return false;
|
|
return buffer[shift] < buffer[shift + period];
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator iteration function |
|
|
//+------------------------------------------------------------------+
|
|
int OnCalculate(const int rates_total,
|
|
const int prev_calculated,
|
|
const datetime &time[],
|
|
const double &open[],
|
|
const double &high[],
|
|
const double &low[],
|
|
const double &close[],
|
|
const long &tick_volume[],
|
|
const long &volume[],
|
|
const int &spread[])
|
|
{
|
|
if(rates_total < RSILen + SF + 10) return(0);
|
|
|
|
// Copy RSI data
|
|
if(CopyBuffer(rsi_handle, 0, 0, rates_total, RSIBuffer) <= 0) return(0);
|
|
|
|
ArraySetAsSeries(close, true);
|
|
ArraySetAsSeries(open, true);
|
|
ArraySetAsSeries(high, true);
|
|
ArraySetAsSeries(low, true);
|
|
|
|
int limit = rates_total - prev_calculated;
|
|
if(prev_calculated > 0) limit++;
|
|
|
|
// Calculate QQE
|
|
int Wilders_Period = RSILen * 2 - 1;
|
|
|
|
for(int i = rates_total - 1; i >= 0; i--)
|
|
{
|
|
// Calculate RSIndex (EMA of RSI)
|
|
if(i == rates_total - 1)
|
|
RSIndexBuffer[i] = RSIBuffer[i];
|
|
else
|
|
RSIndexBuffer[i] = CalculateEMA(RSIBuffer, SF, i, RSIndexBuffer[i+1]);
|
|
|
|
// Calculate AtrRsi
|
|
if(i < rates_total - 1)
|
|
AtrRsi[i] = MathAbs(RSIndexBuffer[i+1] - RSIndexBuffer[i]);
|
|
else
|
|
AtrRsi[i] = 0;
|
|
}
|
|
|
|
// Calculate MaAtrRsi and DeltaFastAtrRsi
|
|
for(int i = rates_total - 1; i >= 0; i--)
|
|
{
|
|
if(i == rates_total - 1)
|
|
{
|
|
MaAtrRsi[i] = AtrRsi[i];
|
|
DeltaFastAtrRsi[i] = AtrRsi[i] * QQEfactor;
|
|
}
|
|
else
|
|
{
|
|
MaAtrRsi[i] = CalculateEMA(AtrRsi, Wilders_Period, i, MaAtrRsi[i+1]);
|
|
double temp = CalculateEMA(MaAtrRsi, Wilders_Period, i, (i < rates_total - 2 ? DeltaFastAtrRsi[i+1] / QQEfactor : MaAtrRsi[i]));
|
|
DeltaFastAtrRsi[i] = temp * QQEfactor;
|
|
}
|
|
}
|
|
|
|
// Calculate bands and trend
|
|
for(int i = rates_total - 1; i >= 0; i--)
|
|
{
|
|
double newshortband = RSIndexBuffer[i] + DeltaFastAtrRsi[i];
|
|
double newlongband = RSIndexBuffer[i] - DeltaFastAtrRsi[i];
|
|
|
|
if(i == rates_total - 1)
|
|
{
|
|
longbandBuffer[i] = newlongband;
|
|
shortbandBuffer[i] = newshortband;
|
|
trend[i] = 1;
|
|
}
|
|
else
|
|
{
|
|
// Longband calculation
|
|
if(RSIndexBuffer[i+1] > longbandBuffer[i+1] && RSIndexBuffer[i] > longbandBuffer[i+1])
|
|
longbandBuffer[i] = MathMax(longbandBuffer[i+1], newlongband);
|
|
else
|
|
longbandBuffer[i] = newlongband;
|
|
|
|
// Shortband calculation
|
|
if(RSIndexBuffer[i+1] < shortbandBuffer[i+1] && RSIndexBuffer[i] < shortbandBuffer[i+1])
|
|
shortbandBuffer[i] = MathMin(shortbandBuffer[i+1], newshortband);
|
|
else
|
|
shortbandBuffer[i] = newshortband;
|
|
|
|
// Trend calculation
|
|
if(RSIndexBuffer[i] > shortbandBuffer[i+1])
|
|
trend[i] = 1;
|
|
else if(RSIndexBuffer[i] < longbandBuffer[i+1])
|
|
trend[i] = -1;
|
|
else
|
|
trend[i] = trend[i+1];
|
|
}
|
|
|
|
FastAtrRsiTLBuffer[i] = (trend[i] == 1) ? longbandBuffer[i] : shortbandBuffer[i];
|
|
}
|
|
|
|
// Calculate Moving Averages
|
|
for(int i = rates_total - 1; i >= 0; i--)
|
|
{
|
|
ma_fastBuffer[i] = CalculateMA(close, type1, len1, i);
|
|
ma_mediumBuffer[i] = CalculateMA(close, type2, len2, i);
|
|
ma_slowBuffer[i] = CalculateMA(close, type3, len3, i);
|
|
|
|
if(anchor > 1)
|
|
{
|
|
ma_fast_altBuffer[i] = CalculateMA(close, type1, len1 * anchor, i);
|
|
ma_medium_altBuffer[i] = CalculateMA(close, type2, len2 * anchor, i);
|
|
ma_slow_altBuffer[i] = CalculateMA(close, type3, len3 * anchor, i);
|
|
}
|
|
|
|
// Direction
|
|
direction[i] = IsRising(ma_mediumBuffer, i, 3) ? 1 : (IsFalling(ma_mediumBuffer, i, 3) ? -1 : 0);
|
|
if(anchor > 1)
|
|
altDirection[i] = IsRising(ma_medium_altBuffer, i, 3) ? 1 : (IsFalling(ma_medium_altBuffer, i, 3) ? -1 : 0);
|
|
}
|
|
|
|
// Calculate signals
|
|
static int QQExlong = 0, QQExshort = 0;
|
|
static int QQEzlong = 0, QQEzshort = 0;
|
|
static int QQEclong = 0, QQEcshort = 0;
|
|
static int buy_ = 0, sell_ = 0;
|
|
static int Buy = 0, Sell = 0;
|
|
static int tradestate = 0;
|
|
|
|
for(int i = limit - 1; i >= 0; i--)
|
|
{
|
|
// Initialize buffers
|
|
BuySignalBuffer[i] = EMPTY_VALUE;
|
|
SellSignalBuffer[i] = EMPTY_VALUE;
|
|
TurnedAquaBuffer[i] = EMPTY_VALUE;
|
|
TurnedBlueBuffer[i] = EMPTY_VALUE;
|
|
TPLongBuffer[i] = EMPTY_VALUE;
|
|
TPShortBuffer[i] = EMPTY_VALUE;
|
|
|
|
if(i >= rates_total - 2) continue;
|
|
|
|
// QQE Crosses
|
|
QQExlong = (FastAtrRsiTLBuffer[i] < RSIndexBuffer[i]) ? QQExlong + 1 : 0;
|
|
QQExshort = (FastAtrRsiTLBuffer[i] > RSIndexBuffer[i]) ? QQExshort + 1 : 0;
|
|
|
|
// Zero crosses
|
|
QQEzlong = (RSIndexBuffer[i] >= 50) ? QQEzlong + 1 : 0;
|
|
QQEzshort = (RSIndexBuffer[i] < 50) ? QQEzshort + 1 : 0;
|
|
|
|
// Threshold channel crosses
|
|
QQEclong = (RSIndexBuffer[i] > (50 + threshhold)) ? QQEclong + 1 : 0;
|
|
QQEcshort = (RSIndexBuffer[i] < (50 - threshhold)) ? QQEcshort + 1 : 0;
|
|
|
|
// Filter conditions
|
|
bool QQEflong = true;
|
|
bool QQEfshort = true;
|
|
|
|
if(filter)
|
|
{
|
|
if(anchor == 1)
|
|
{
|
|
QQEflong = (close[i] > ma_mediumBuffer[i] && ma_mediumBuffer[i] > ma_slowBuffer[i] && ma_fastBuffer[i] > ma_mediumBuffer[i]);
|
|
QQEfshort = (close[i] < ma_mediumBuffer[i] && ma_mediumBuffer[i] < ma_slowBuffer[i] && ma_fastBuffer[i] < ma_mediumBuffer[i]);
|
|
}
|
|
else
|
|
{
|
|
QQEflong = (ma_mediumBuffer[i] > ma_medium_altBuffer[i] && close[i] > ma_fastBuffer[i] && ma_fastBuffer[i] > ma_mediumBuffer[i]);
|
|
QQEfshort = (ma_mediumBuffer[i] < ma_medium_altBuffer[i] && close[i] < ma_fastBuffer[i] && ma_fastBuffer[i] < ma_mediumBuffer[i]);
|
|
}
|
|
}
|
|
|
|
if(dfilter)
|
|
{
|
|
if(anchor == 1)
|
|
{
|
|
QQEflong = QQEflong && (direction[i] > 0);
|
|
QQEfshort = QQEfshort && (direction[i] < 0);
|
|
}
|
|
else
|
|
{
|
|
QQEflong = QQEflong && (direction[i] > 0 && altDirection[i] > 0 && close[i] > ma_mediumBuffer[i]);
|
|
QQEfshort = QQEfshort && (direction[i] < 0 && altDirection[i] < 0 && close[i] < ma_mediumBuffer[i]);
|
|
}
|
|
}
|
|
|
|
bool QQExfilter = (!xfilter || RSIndexBuffer[i] > (50 + threshhold) || RSIndexBuffer[i] < (50 - threshhold));
|
|
|
|
// Buy/Sell signals
|
|
if(tradeSignal == "XC")
|
|
{
|
|
buy_ = (QQEclong == 1 && QQEflong) ? buy_ + 1 : 0;
|
|
sell_ = (QQEcshort == 1 && QQEfshort) ? sell_ + 1 : 0;
|
|
}
|
|
else if(tradeSignal == "XQ")
|
|
{
|
|
buy_ = (QQExlong == 1 && QQEflong && QQExfilter) ? buy_ + 1 : 0;
|
|
sell_ = (QQExshort == 1 && QQEfshort && QQExfilter) ? sell_ + 1 : 0;
|
|
}
|
|
else if(tradeSignal == "XZ")
|
|
{
|
|
buy_ = (QQEzlong == 1 && QQEflong) ? buy_ + 1 : 0;
|
|
sell_ = (QQEzshort == 1 && QQEfshort) ? sell_ + 1 : 0;
|
|
}
|
|
|
|
// First buy/sell in trend
|
|
Buy = (sell_ > 0) ? 0 : ((buy_ == 1 || Buy > 0) ? Buy + 1 : Buy);
|
|
Sell = (buy_ > 0) ? 0 : ((sell_ == 1 || Sell > 0) ? Sell + 1 : Sell);
|
|
|
|
int buy = ufirst ? Buy : buy_;
|
|
int sell = ufirst ? Sell : sell_;
|
|
|
|
// Trade state management
|
|
bool isLong = false;
|
|
bool isShort = false;
|
|
|
|
if(tradestate == 0)
|
|
{
|
|
if(buy == 1)
|
|
{
|
|
tradestate = 1;
|
|
isLong = true;
|
|
}
|
|
else if(sell == 1)
|
|
{
|
|
tradestate = 2;
|
|
isShort = true;
|
|
}
|
|
}
|
|
else if(tradestate == 1)
|
|
{
|
|
// Check for close long conditions
|
|
if(closeSignal == "XQ" && QQExshort == 1)
|
|
tradestate = 0;
|
|
else if(closeSignal == "XC" && QQEcshort == 1)
|
|
tradestate = 0;
|
|
else if(closeSignal == "XZ" && QQEzshort == 1)
|
|
tradestate = 0;
|
|
}
|
|
else if(tradestate == 2)
|
|
{
|
|
// Check for close short conditions
|
|
if(closeSignal == "XQ" && QQExlong == 1)
|
|
tradestate = 0;
|
|
else if(closeSignal == "XC" && QQEclong == 1)
|
|
tradestate = 0;
|
|
else if(closeSignal == "XZ" && QQEzlong == 1)
|
|
tradestate = 0;
|
|
}
|
|
|
|
// Set signals
|
|
if(isLong && i > 0)
|
|
BuySignalBuffer[i-1] = low[i-1] - 10 * _Point;
|
|
if(isShort && i > 0)
|
|
SellSignalBuffer[i-1] = high[i-1] + 10 * _Point;
|
|
|
|
// MA color changes
|
|
if(i < rates_total - 2 && anchor > 1)
|
|
{
|
|
bool turned_aqua = (altDirection[i+1] < 0 && altDirection[i] > 0);
|
|
bool turned_blue = (altDirection[i+1] > 0 && altDirection[i] < 0);
|
|
|
|
if(turned_aqua)
|
|
TurnedAquaBuffer[i] = low[i] - 20 * _Point;
|
|
if(turned_blue)
|
|
TurnedBlueBuffer[i] = high[i] + 20 * _Point;
|
|
|
|
// Take profit signals
|
|
bool take_profit_long = ma_slowBuffer[i] > ma_fast_altBuffer[i] &&
|
|
ma_slowBuffer[i] > ma_slow_altBuffer[i] &&
|
|
direction[i+1] > 0 && direction[i] < 0;
|
|
bool take_profit_short = ma_slowBuffer[i] < ma_fast_altBuffer[i] &&
|
|
ma_slowBuffer[i] < ma_slow_altBuffer[i] &&
|
|
direction[i+1] < 0 && direction[i] > 0;
|
|
|
|
if(take_profit_long)
|
|
TPLongBuffer[i] = high[i] + 30 * _Point;
|
|
if(take_profit_short)
|
|
TPShortBuffer[i] = low[i] - 30 * _Point;
|
|
}
|
|
|
|
// Update color buffer for bar coloring
|
|
if(anchor > 1)
|
|
ColorBuffer[i] = altDirection[i] < 0 ? 0 : 1; // 0 for red, 1 for green
|
|
|
|
// Set dynamic MA colors based on direction
|
|
if(dynamicMAColors)
|
|
{
|
|
// Medium MA color
|
|
if(direction[i] > 0)
|
|
ma_mediumColorBuffer[i] = 0; // Bullish
|
|
else if(direction[i] < 0)
|
|
ma_mediumColorBuffer[i] = 2; // Bearish
|
|
else
|
|
ma_mediumColorBuffer[i] = 1; // Neutral
|
|
|
|
// Medium Alt MA color
|
|
if(anchor > 1)
|
|
{
|
|
if(altDirection[i] > 0)
|
|
ma_medium_altColorBuffer[i] = 0; // Bullish
|
|
else if(altDirection[i] < 0)
|
|
ma_medium_altColorBuffer[i] = 2; // Bearish
|
|
else
|
|
ma_medium_altColorBuffer[i] = 1; // Neutral
|
|
}
|
|
}
|
|
|
|
// Color price bars if enabled
|
|
if(colorBars && anchor > 1 && i == 0)
|
|
{
|
|
if(altDirection[i] > 0)
|
|
ChartSetInteger(ChartID(), CHART_COLOR_CANDLE_BULL, colorMABullish);
|
|
else if(altDirection[i] < 0)
|
|
ChartSetInteger(ChartID(), CHART_COLOR_CANDLE_BEAR, colorMABearish);
|
|
}
|
|
}
|
|
|
|
return(rates_total);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Get QQE signals for Expert Advisors |
|
|
//+------------------------------------------------------------------+
|
|
double GetQQEValue(int shift, int buffer_num)
|
|
{
|
|
// buffer_num: 0=RSIndex, 1=FastAtrRsiTL, 2=Signal State
|
|
switch(buffer_num)
|
|
{
|
|
case 0: return RSIndexBuffer[shift];
|
|
case 1: return FastAtrRsiTLBuffer[shift];
|
|
case 2: return trend[shift];
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
//New Features Added:
|
|
//1. Dynamic MA Colors Option
|
|
//
|
|
//New input: dynamicMAColors (default: true)
|
|
//When enabled, the Medium MA lines change color based on their direction
|
|
//When disabled, MAs use the fixed colors you set
|
|
//
|
|
//2. Color Bar Option
|
|
//
|
|
//New input: colorBars (default: true)
|
|
//Colors the price bars based on the alternative MA ribbon direction
|
|
//Matches the original Pine Script's barcolor() function
|
|
//
|
|
//3. Dynamic Color Scheme
|
|
//
|
|
//colorMABullish - Color when MA is rising (default: Lime)
|
|
//colorMABearish - Color when MA is falling (default: Red)
|
|
//colorMANeutral - Color when MA is flat (default: Gray)
|
|
//
|
|
//How It Works:
|
|
//MA Ribbon Colors:
|
|
//
|
|
//Medium MA (21 EMA):
|
|
//
|
|
//Green/Lime: When rising (bullish)
|
|
//Red: When falling (bearish)
|
|
//Gray: When flat (neutral)
|
|
//
|
|
//
|
|
//Medium Alternative MA (84 EMA) (when anchor > 1):
|
|
//
|
|
//Same color logic as above
|
|
//Helps identify longer-term trend
|
|
//
|
|
//
|
|
//
|
|
//Visual Signals:
|
|
//
|
|
//Colored MA lines show immediate trend direction
|
|
//Price bars change color based on the longer-term trend
|
|
//Arrow signals still appear for MA direction changes
|
|
//Take profit signals when trends diverge
|
|
//
|
|
//Benefits:
|
|
//
|
|
//Quick trend identification: Instantly see if MAs are bullish or bearish
|
|
//Multi-timeframe confirmation: Both regular and alternative MAs show their own trends
|
|
//Clean visual hierarchy: Important MAs change color while others stay fixed
|
|
//Matches original Pine Script: Now includes the bar coloring feature
|
|
//
|
|
//This makes it much easier to:
|
|
//
|
|
//Identify trend changes quickly
|
|
//Confirm trade direction with MA alignment
|
|
//Spot divergences between timeframes
|
|
//Trade with the overall trend
|
|
//+------------------------------------------------------------------+ |