Init SimpleFVG stradegy

This commit is contained in:
Bell
2026-03-11 16:06:24 +07:00
parent d971f23f25
commit 123b0f3644
5 changed files with 759 additions and 754 deletions
+86
View File
@@ -0,0 +1,86 @@
//+------------------------------------------------------------------+
//| Config.mqh Step 0: Inputs, Enums, Constants |
//| Cho phép cấu hình symbol, timeframe, EMA, FVG, drawing |
//+------------------------------------------------------------------+
#ifndef __SIMPLE_FVG_CONFIG_MQH__
#define __SIMPLE_FVG_CONFIG_MQH__
//--- Step 0: Asset & Timeframe ---
input string InpSymbol = ""; // Symbol (empty = current chart)
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_H1; // Analysis Timeframe
//--- Step 1: Trend (EMA) ---
input int InpEMAFastPeriod = 34; // EMA Fast Period
input int InpEMASlowPeriod = 89; // EMA Slow Period
//--- Step 2: FVG Detection ---
input int InpFVGLookbackBars = 100; // FVG: Lookback range (bars)
input int InpFVGMaxAgeBars = 50; // FVG: Max age before expiry (bars)
input double InpFVGMinBodyPct = 50.0; // FVG: Min body % of impulse candle
input double InpFVGMinSizePoints = 0; // FVG: Min gap size (points, 0=any)
//--- Step 4: Drawing ---
input color InpColorBullFVG = C'30,80,140'; // Color: Bullish FVG zone
input color InpColorBearFVG = C'140,30,20'; // Color: Bearish FVG zone
input color InpColorMitigatedFVG = C'60,60,60'; // Color: Mitigated FVG zone
input color InpColorEMAFast = clrDodgerBlue; // Color: EMA Fast line
input color InpColorEMASlow = clrOrangeRed; // Color: EMA Slow line
input bool InpShowPanel = true; // Draw: Show info panel
input bool InpShowFVGLabels = true; // Draw: Show FVG labels
//--- Debug ---
input bool InpDebugLog = true; // Debug: Enable logging
//+------------------------------------------------------------------+
//| Enums |
//+------------------------------------------------------------------+
enum ENUM_TREND_DIRECTION
{
TREND_BULLISH = 1,
TREND_BEARISH = -1,
TREND_NEUTRAL = 0
};
enum ENUM_FVG_TYPE
{
FVG_BULLISH = 1,
FVG_BEARISH = -1
};
//+------------------------------------------------------------------+
//| Constants |
//+------------------------------------------------------------------+
const string EA_PREFIX = "SFVG_";
const int MAX_FVG_SLOTS = 50;
//+------------------------------------------------------------------+
//| Resolved symbol (cached) |
//+------------------------------------------------------------------+
string g_ResolvedSymbol = "";
string GetTradeSymbol()
{
if(g_ResolvedSymbol != "")
return g_ResolvedSymbol;
g_ResolvedSymbol = (InpSymbol == "" || InpSymbol == "current")
? _Symbol
: InpSymbol;
return g_ResolvedSymbol;
}
//+------------------------------------------------------------------+
//| New-bar detector |
//+------------------------------------------------------------------+
datetime g_PreviousBarTime = 0;
bool IsNewBar()
{
datetime currentBarTime = iTime(GetTradeSymbol(), InpTimeframe, 0);
if(currentBarTime == g_PreviousBarTime)
return false;
g_PreviousBarTime = currentBarTime;
return true;
}
#endif
+205
View File
@@ -0,0 +1,205 @@
//+------------------------------------------------------------------+
//| Drawing.mqh Step 4: Visualize FVG zones, EMA info, trend panel |
//+------------------------------------------------------------------+
#ifndef __SIMPLE_FVG_DRAWING_MQH__
#define __SIMPLE_FVG_DRAWING_MQH__
#include "Config.mqh"
#include "Trend.mqh"
#include "FVG.mqh"
//+------------------------------------------------------------------+
//| Object-creation helpers |
//+------------------------------------------------------------------+
void DrawRectangle(string name,
datetime timeStart, double priceTop,
datetime timeEnd, double priceBot,
color clr, bool filled = true)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_RECTANGLE, 0, timeStart, priceTop, timeEnd, priceBot);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FILL, filled);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectMove(0, name, 0, timeStart, priceTop);
ObjectMove(0, name, 1, timeEnd, priceBot);
}
void DrawTrendLine(string name,
datetime t1, double p1,
datetime t2, double p2,
color clr, int style, int width)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_TREND, 0, t1, p1, t2, p2);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, style);
ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectMove(0, name, 0, t1, p1);
ObjectMove(0, name, 1, t2, p2);
}
void DrawLabel(string name, int xDist, int yDist,
string text, color clr, int fontSize)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, xDist);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, yDist);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetString (0, name, OBJPROP_FONT, "Consolas");
ObjectSetString (0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
void DrawTextOnChart(string name, datetime t, double price,
string text, color clr, int fontSize, int anchor)
{
if(ObjectFind(0, name) < 0)
ObjectCreate(0, name, OBJ_TEXT, 0, t, price);
ObjectMove(0, name, 0, t, price);
ObjectSetString (0, name, OBJPROP_TEXT, text);
ObjectSetString (0, name, OBJPROP_FONT, "Arial");
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}
//+------------------------------------------------------------------+
//| Draw all active FVG zones as rectangles on the chart |
//+------------------------------------------------------------------+
void DrawFVGZones()
{
ObjectsDeleteAll(0, EA_PREFIX + "FVG_");
string symbol = GetTradeSymbol();
datetime currentBar = iTime(symbol, InpTimeframe, 0);
for(int i = 0; i < g_FVGCount; i++)
{
if(!g_FVGZones[i].isActive)
continue;
string zoneId = IntegerToString(i);
//--- Zone color depends on type and mitigation status ---
color zoneColor;
if(g_FVGZones[i].isMitigated)
zoneColor = InpColorMitigatedFVG;
else if(g_FVGZones[i].type == FVG_BULLISH)
zoneColor = InpColorBullFVG;
else
zoneColor = InpColorBearFVG;
//--- Draw filled rectangle for the FVG zone ---
DrawRectangle(
EA_PREFIX + "FVG_ZONE_" + zoneId,
g_FVGZones[i].createdTime, g_FVGZones[i].upperEdge,
currentBar, g_FVGZones[i].lowerEdge,
zoneColor, true
);
//--- Draw mid-line (50% of FVG) ---
double midPrice = (g_FVGZones[i].upperEdge + g_FVGZones[i].lowerEdge) / 2.0;
color midColor = g_FVGZones[i].isMitigated ? clrDimGray : clrGold;
DrawTrendLine(
EA_PREFIX + "FVG_MID_" + zoneId,
g_FVGZones[i].createdTime, midPrice,
currentBar, midPrice,
midColor, STYLE_DOT, 1
);
//--- Draw text label ---
if(InpShowFVGLabels)
{
string typeStr = (g_FVGZones[i].type == FVG_BULLISH) ? "BULL" : "BEAR";
string arrow = (g_FVGZones[i].type == FVG_BULLISH) ? "▲" : "▼";
string mitigStr = g_FVGZones[i].isMitigated ? " [MITIGATED]" : "";
color labelColor;
if(g_FVGZones[i].isMitigated)
labelColor = clrDimGray;
else if(g_FVGZones[i].type == FVG_BULLISH)
labelColor = clrDeepSkyBlue;
else
labelColor = clrOrangeRed;
DrawTextOnChart(
EA_PREFIX + "FVG_LBL_" + zoneId,
g_FVGZones[i].createdTime,
g_FVGZones[i].upperEdge,
StringFormat("%s %s [%.2f%.2f]%s",
arrow, typeStr,
g_FVGZones[i].lowerEdge, g_FVGZones[i].upperEdge,
mitigStr),
labelColor, 7, ANCHOR_LEFT_LOWER
);
}
}
}
//+------------------------------------------------------------------+
//| Draw info panel (top-left corner) |
//+------------------------------------------------------------------+
void DrawInfoPanel()
{
if(!InpShowPanel) return;
int bullCount = CountActiveFVGs(FVG_BULLISH);
int bearCount = CountActiveFVGs(FVG_BEARISH);
int mitigCount = CountMitigatedFVGs();
string trendText = TrendToString(g_CurrentTrend);
color trendColor = TrendToColor(g_CurrentTrend);
//--- Row 1: EA header ---
DrawLabel(EA_PREFIX + "PNL_HDR", 12, 22,
StringFormat("SimpleFVG | %s %s",
GetTradeSymbol(), EnumToString(InpTimeframe)),
clrSilver, 10);
//--- Row 2: Trend status ---
DrawLabel(EA_PREFIX + "PNL_TREND", 12, 44,
StringFormat("Trend: %s | EMA%d = %.2f | EMA%d = %.2f",
trendText,
InpEMAFastPeriod, g_EMAFastValue,
InpEMASlowPeriod, g_EMASlowValue),
trendColor, 9);
//--- Row 3: FVG counts ---
DrawLabel(EA_PREFIX + "PNL_FVG", 12, 66,
StringFormat("FVG Active: %d Bull + %d Bear | Mitigated: %d",
bullCount, bearCount, mitigCount),
clrWheat, 9);
}
//+------------------------------------------------------------------+
//| Master draw: call all draw functions |
//+------------------------------------------------------------------+
void DrawAll()
{
DrawFVGZones();
DrawInfoPanel();
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| Clean up all drawn objects |
//+------------------------------------------------------------------+
void DrawCleanup()
{
ObjectsDeleteAll(0, EA_PREFIX);
ChartRedraw(0);
}
#endif
+277
View File
@@ -0,0 +1,277 @@
//+------------------------------------------------------------------+
//| FVG.mqh Step 2: Fair Value Gap detection & management |
//| |
//| 3-candle pattern: |
//| CandleA (oldest) ── CandleB (impulse) ── CandleC (newest) |
//| |
//| Bullish FVG: CandleA.High < CandleC.Low → gap UP |
//| zone = [CandleA.High .. CandleC.Low] |
//| CandleB must be bullish with strong body |
//| |
//| Bearish FVG: CandleA.Low > CandleC.High → gap DOWN |
//| zone = [CandleC.High .. CandleA.Low] |
//| CandleB must be bearish with strong body |
//+------------------------------------------------------------------+
#ifndef __SIMPLE_FVG_FVG_MQH__
#define __SIMPLE_FVG_FVG_MQH__
#include "Config.mqh"
//+------------------------------------------------------------------+
//| FVG data structure |
//+------------------------------------------------------------------+
struct FVGZone
{
bool isActive;
ENUM_FVG_TYPE type;
double upperEdge;
double lowerEdge;
datetime createdTime;
int ageInBars;
bool isMitigated;
};
//+------------------------------------------------------------------+
//| Module state |
//+------------------------------------------------------------------+
FVGZone g_FVGZones[];
int g_FVGCount = 0;
//+------------------------------------------------------------------+
//| Init: allocate array |
//+------------------------------------------------------------------+
void FVGInit()
{
ArrayResize(g_FVGZones, MAX_FVG_SLOTS);
for(int i = 0; i < MAX_FVG_SLOTS; i++)
ZeroMemory(g_FVGZones[i]);
g_FVGCount = 0;
}
//+------------------------------------------------------------------+
//| Check if impulse candle has strong body (body/range >= threshold) |
//+------------------------------------------------------------------+
bool IsImpulseCandleStrong(string symbol, ENUM_TIMEFRAMES tf, int shift)
{
double high = iHigh(symbol, tf, shift);
double low = iLow(symbol, tf, shift);
double open = iOpen(symbol, tf, shift);
double close = iClose(symbol, tf, shift);
double totalRange = high - low;
if(totalRange < _Point)
return false;
double bodySize = MathAbs(close - open);
double bodyRatio = bodySize / totalRange * 100.0;
return (bodyRatio >= InpFVGMinBodyPct);
}
//+------------------------------------------------------------------+
//| Check if this FVG timestamp already exists in our array |
//+------------------------------------------------------------------+
bool FVGAlreadyTracked(datetime fvgTime, ENUM_FVG_TYPE fvgType)
{
for(int i = 0; i < g_FVGCount; i++)
{
if(g_FVGZones[i].isActive
&& g_FVGZones[i].createdTime == fvgTime
&& g_FVGZones[i].type == fvgType)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Add a new FVG zone to the array |
//+------------------------------------------------------------------+
bool AddFVGZone(ENUM_FVG_TYPE type, double upper, double lower, datetime time)
{
if(g_FVGCount >= MAX_FVG_SLOTS)
return false;
if(InpFVGMinSizePoints > 0)
{
double gapSizePoints = (upper - lower) / _Point;
if(gapSizePoints < InpFVGMinSizePoints)
return false;
}
ZeroMemory(g_FVGZones[g_FVGCount]);
g_FVGZones[g_FVGCount].isActive = true;
g_FVGZones[g_FVGCount].type = type;
g_FVGZones[g_FVGCount].upperEdge = upper;
g_FVGZones[g_FVGCount].lowerEdge = lower;
g_FVGZones[g_FVGCount].createdTime = time;
g_FVGZones[g_FVGCount].ageInBars = 0;
g_FVGZones[g_FVGCount].isMitigated = false;
g_FVGCount++;
if(InpDebugLog)
PrintFormat("[FVG] NEW %s [%.5f %.5f] at %s",
(type == FVG_BULLISH) ? "BULL" : "BEAR",
lower, upper, TimeToString(time));
return true;
}
//+------------------------------------------------------------------+
//| Scan for new FVG patterns across the lookback range |
//| Finds ALL FVGs regardless of current trend |
//+------------------------------------------------------------------+
void ScanForNewFVGs()
{
string symbol = GetTradeSymbol();
int totalBars = Bars(symbol, InpTimeframe);
int maxShift = MathMin(InpFVGLookbackBars, totalBars - 3);
for(int shift = 1; shift <= maxShift; shift++)
{
int shiftA = shift + 2; // oldest candle
int shiftB = shift + 1; // impulse (middle) candle
int shiftC = shift; // newest candle
double candleA_High = iHigh(symbol, InpTimeframe, shiftA);
double candleA_Low = iLow (symbol, InpTimeframe, shiftA);
double candleB_Open = iOpen (symbol, InpTimeframe, shiftB);
double candleB_Close = iClose(symbol, InpTimeframe, shiftB);
double candleC_High = iHigh(symbol, InpTimeframe, shiftC);
double candleC_Low = iLow (symbol, InpTimeframe, shiftC);
datetime fvgTime = iTime(symbol, InpTimeframe, shiftC);
//--- Bullish FVG: gap between A.High and C.Low ---
if(candleA_High < candleC_Low
&& candleB_Close > candleB_Open
&& IsImpulseCandleStrong(symbol, InpTimeframe, shiftB))
{
if(!FVGAlreadyTracked(fvgTime, FVG_BULLISH))
AddFVGZone(FVG_BULLISH, candleC_Low, candleA_High, fvgTime);
}
//--- Bearish FVG: gap between C.High and A.Low ---
if(candleA_Low > candleC_High
&& candleB_Close < candleB_Open
&& IsImpulseCandleStrong(symbol, InpTimeframe, shiftB))
{
if(!FVGAlreadyTracked(fvgTime, FVG_BEARISH))
AddFVGZone(FVG_BEARISH, candleA_Low, candleC_High, fvgTime);
}
}
}
//+------------------------------------------------------------------+
//| Check if price has mitigated (filled through) any active FVG |
//+------------------------------------------------------------------+
void CheckMitigationStatus()
{
string symbol = GetTradeSymbol();
for(int i = 0; i < g_FVGCount; i++)
{
if(!g_FVGZones[i].isActive || g_FVGZones[i].isMitigated)
continue;
double lastLow = iLow (symbol, InpTimeframe, 1);
double lastHigh = iHigh(symbol, InpTimeframe, 1);
// Bullish FVG mitigated: price drops through lower edge
if(g_FVGZones[i].type == FVG_BULLISH && lastLow <= g_FVGZones[i].lowerEdge)
{
g_FVGZones[i].isMitigated = true;
if(InpDebugLog)
PrintFormat("[FVG] MITIGATED BULL [%.5f %.5f]",
g_FVGZones[i].lowerEdge, g_FVGZones[i].upperEdge);
}
// Bearish FVG mitigated: price rises through upper edge
if(g_FVGZones[i].type == FVG_BEARISH && lastHigh >= g_FVGZones[i].upperEdge)
{
g_FVGZones[i].isMitigated = true;
if(InpDebugLog)
PrintFormat("[FVG] MITIGATED BEAR [%.5f %.5f]",
g_FVGZones[i].lowerEdge, g_FVGZones[i].upperEdge);
}
}
}
//+------------------------------------------------------------------+
//| Age out old FVGs beyond max age |
//+------------------------------------------------------------------+
void ExpireOldFVGs()
{
for(int i = 0; i < g_FVGCount; i++)
{
if(!g_FVGZones[i].isActive) continue;
g_FVGZones[i].ageInBars++;
if(g_FVGZones[i].ageInBars > InpFVGMaxAgeBars)
{
g_FVGZones[i].isActive = false;
if(InpDebugLog)
PrintFormat("[FVG] EXPIRED %s [%.5f %.5f] age=%d bars",
(g_FVGZones[i].type == FVG_BULLISH) ? "BULL" : "BEAR",
g_FVGZones[i].lowerEdge, g_FVGZones[i].upperEdge,
g_FVGZones[i].ageInBars);
}
}
}
//+------------------------------------------------------------------+
//| Remove inactive FVGs from array to free slots |
//+------------------------------------------------------------------+
void CompactFVGArray()
{
int writeIndex = 0;
for(int i = 0; i < g_FVGCount; i++)
{
if(g_FVGZones[i].isActive)
{
if(writeIndex != i)
g_FVGZones[writeIndex] = g_FVGZones[i];
writeIndex++;
}
}
g_FVGCount = writeIndex;
}
//+------------------------------------------------------------------+
//| Main update: mitigation → expiry → scan new → compact |
//+------------------------------------------------------------------+
void FVGUpdate()
{
CheckMitigationStatus();
ExpireOldFVGs();
ScanForNewFVGs();
CompactFVGArray();
}
//+------------------------------------------------------------------+
//| Count helpers for panel display |
//+------------------------------------------------------------------+
int CountActiveFVGs(ENUM_FVG_TYPE type)
{
int count = 0;
for(int i = 0; i < g_FVGCount; i++)
{
if(g_FVGZones[i].isActive && g_FVGZones[i].type == type)
count++;
}
return count;
}
int CountMitigatedFVGs()
{
int count = 0;
for(int i = 0; i < g_FVGCount; i++)
{
if(g_FVGZones[i].isActive && g_FVGZones[i].isMitigated)
count++;
}
return count;
}
#endif
+147
View File
@@ -0,0 +1,147 @@
//+------------------------------------------------------------------+
//| Trend.mqh Step 1: Trend detection via EMA34 & EMA89 |
//| |
//| Logic: |
//| BULLISH: EMA_fast > EMA_slow AND close > EMA_fast |
//| BEARISH: EMA_fast < EMA_slow AND close < EMA_fast |
//| NEUTRAL: otherwise (EMA crossing or price between EMAs) |
//+------------------------------------------------------------------+
#ifndef __SIMPLE_FVG_TREND_MQH__
#define __SIMPLE_FVG_TREND_MQH__
#include "Config.mqh"
//+------------------------------------------------------------------+
//| Module state |
//+------------------------------------------------------------------+
int g_HandleEMAFast = INVALID_HANDLE;
int g_HandleEMASlow = INVALID_HANDLE;
string g_NameEMAFast = "";
string g_NameEMASlow = "";
double g_EMAFastValue = 0.0;
double g_EMASlowValue = 0.0;
ENUM_TREND_DIRECTION g_CurrentTrend = TREND_NEUTRAL;
//+------------------------------------------------------------------+
//| Init: create EMA indicator handles and add to chart |
//+------------------------------------------------------------------+
bool TrendInit()
{
string symbol = GetTradeSymbol();
g_HandleEMAFast = iMA(symbol, InpTimeframe, InpEMAFastPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(g_HandleEMAFast == INVALID_HANDLE)
{
PrintFormat("[Trend] FAILED to create EMA%d handle", InpEMAFastPeriod);
return false;
}
g_HandleEMASlow = iMA(symbol, InpTimeframe, InpEMASlowPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(g_HandleEMASlow == INVALID_HANDLE)
{
PrintFormat("[Trend] FAILED to create EMA%d handle", InpEMASlowPeriod);
return false;
}
ChartIndicatorAdd(0, 0, g_HandleEMAFast);
int countAfterFast = ChartIndicatorsTotal(0, 0);
if(countAfterFast > 0)
g_NameEMAFast = ChartIndicatorName(0, 0, countAfterFast - 1);
ChartIndicatorAdd(0, 0, g_HandleEMASlow);
int countAfterSlow = ChartIndicatorsTotal(0, 0);
if(countAfterSlow > 0)
g_NameEMASlow = ChartIndicatorName(0, 0, countAfterSlow - 1);
if(InpDebugLog)
PrintFormat("[Trend] OK EMA%d + EMA%d on %s %s",
InpEMAFastPeriod, InpEMASlowPeriod,
symbol, EnumToString(InpTimeframe));
return true;
}
//+------------------------------------------------------------------+
//| Deinit: release handles and remove from chart |
//+------------------------------------------------------------------+
void TrendDeinit()
{
if(g_NameEMAFast != "")
ChartIndicatorDelete(0, 0, g_NameEMAFast);
if(g_NameEMASlow != "")
ChartIndicatorDelete(0, 0, g_NameEMASlow);
if(g_HandleEMAFast != INVALID_HANDLE)
{
IndicatorRelease(g_HandleEMAFast);
g_HandleEMAFast = INVALID_HANDLE;
}
if(g_HandleEMASlow != INVALID_HANDLE)
{
IndicatorRelease(g_HandleEMASlow);
g_HandleEMASlow = INVALID_HANDLE;
}
}
//+------------------------------------------------------------------+
//| Read one EMA value at a given bar shift |
//+------------------------------------------------------------------+
double ReadEMA(int handle, int shift)
{
double buffer[1];
if(handle == INVALID_HANDLE) return 0.0;
if(CopyBuffer(handle, 0, shift, 1, buffer) < 1) return 0.0;
return buffer[0];
}
//+------------------------------------------------------------------+
//| Update trend direction (call once per new bar) |
//+------------------------------------------------------------------+
ENUM_TREND_DIRECTION TrendUpdate()
{
g_EMAFastValue = ReadEMA(g_HandleEMAFast, 1);
g_EMASlowValue = ReadEMA(g_HandleEMASlow, 1);
if(g_EMAFastValue == 0.0 || g_EMASlowValue == 0.0)
{
g_CurrentTrend = TREND_NEUTRAL;
return g_CurrentTrend;
}
double closePrice = iClose(GetTradeSymbol(), InpTimeframe, 1);
if(g_EMAFastValue > g_EMASlowValue && closePrice > g_EMAFastValue)
g_CurrentTrend = TREND_BULLISH;
else if(g_EMAFastValue < g_EMASlowValue && closePrice < g_EMAFastValue)
g_CurrentTrend = TREND_BEARISH;
else
g_CurrentTrend = TREND_NEUTRAL;
return g_CurrentTrend;
}
//+------------------------------------------------------------------+
//| Utility: convert trend enum to readable string |
//+------------------------------------------------------------------+
string TrendToString(ENUM_TREND_DIRECTION trend)
{
switch(trend)
{
case TREND_BULLISH: return "BULLISH";
case TREND_BEARISH: return "BEARISH";
default: return "NEUTRAL";
}
}
color TrendToColor(ENUM_TREND_DIRECTION trend)
{
switch(trend)
{
case TREND_BULLISH: return clrLime;
case TREND_BEARISH: return clrTomato;
default: return clrGray;
}
}
#endif