Fix Phase 3 compilation errors

- Remove duplicate input parameter definitions for visualization settings
- Update visualization functions to use existing parameter names:
  * ShowFairValueGaps → ShowFVG
  * ShowBreakOfStructure → ShowBOS
  * ShowLiquiditySweeps → ShowSweeps
- Keep ShowOrderBlocks and ShowTradeLevels as they were not duplicated
- All visualization functions now compile without errors
This commit is contained in:
rithsila
2025-09-26 10:24:44 +07:00
parent e20b066d60
commit 8dcbe495dd
+510 -11
View File
@@ -72,6 +72,21 @@ input bool EnableDebugMode = true; /
input bool LogPatternDetection = true; // Log pattern detection events
input bool LogTradeExecution = true; // Log trade execution details
input group "=== Visualization Settings ===" input bool EnableVisualization = true; // Enable chart visualization
input bool ShowInfoPanel = true; // Show information panel
input int MaxObjectsPerPattern = 50; // Maximum objects per pattern type
input group "=== Visualization Colors ===" input color BullishOBColor = clrDodgerBlue; // Bullish Order Block color
input color BearishOBColor = clrCrimson; // Bearish Order Block color
input color BullishFVGColor = clrLimeGreen; // Bullish Fair Value Gap color
input color BearishFVGColor = clrOrange; // Bearish Fair Value Gap color
input color BullishBOSColor = clrGreen; // Bullish Break of Structure color
input color BearishBOSColor = clrRed; // Bearish Break of Structure color
input color SweepColor = clrYellow; // Liquidity Sweep color
input color EntryLevelColor = clrWhite; // Entry level color
input color StopLossColor = clrRed; // Stop Loss level color
input color TakeProfitColor = clrGreen; // Take Profit level color
//--- Global variables
string SymbolsToTrade[];
int TotalSymbols = 0;
@@ -387,14 +402,391 @@ void CleanupChartObjects()
Print("Cleaned up ", total_objects, " chart objects");
}
//+------------------------------------------------------------------+
//| Phase 3: Visualization Helper Functions |
//+------------------------------------------------------------------+
string GenerateObjectName(string pattern_type, string symbol, datetime time, int index = 0)
{
return StringFormat("SniperEA_%s_%s_%d_%d", pattern_type, symbol, (int)time, index);
}
void CleanupPatternObjects(string pattern_type, string symbol = "")
{
string prefix = (symbol == "") ? StringFormat("SniperEA_%s_", pattern_type) : StringFormat("SniperEA_%s_%s_", pattern_type, symbol);
int deleted = ObjectsDeleteAll(0, prefix);
if (deleted > 0 && EnableDebugMode)
{
LogDebug(StringFormat("Cleaned up %d %s objects for %s", deleted, pattern_type,
(symbol == "") ? "all symbols" : symbol));
}
}
bool IsVisualizationEnabled()
{
return EnableVisualization;
}
int CountPatternObjects(string pattern_type, string symbol = "")
{
string prefix = (symbol == "") ? StringFormat("SniperEA_%s_", pattern_type) : StringFormat("SniperEA_%s_%s_", pattern_type, symbol);
int count = 0;
int total_objects = ObjectsTotal(0);
for (int i = 0; i < total_objects; i++)
{
string obj_name = ObjectName(0, i);
if (StringFind(obj_name, prefix) == 0)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| Phase 3: Pattern Drawing Functions |
//+------------------------------------------------------------------+
void DrawOrderBlock(string symbol, OrderBlock &ob, color block_color = clrNONE)
{
if (!IsVisualizationEnabled() || !ShowOrderBlocks)
return;
// Check object limit
if (CountPatternObjects("OB", symbol) >= MaxObjectsPerPattern)
{
CleanupPatternObjects("OB", symbol);
}
// Generate unique object name
string obj_name = GenerateObjectName("OB", symbol, ob.time);
// Delete existing object if it exists
ObjectDelete(0, obj_name);
// Determine color based on bullish/bearish and user settings
color draw_color = block_color;
if (draw_color == clrNONE)
{
draw_color = ob.is_bullish ? BullishOBColor : BearishOBColor;
}
// Create rectangle object
if (ObjectCreate(0, obj_name, OBJ_RECTANGLE, 0, ob.time, ob.high, ob.time + PeriodSeconds(PERIOD_H1) * 24, ob.low))
{
// Set rectangle properties
ObjectSetInteger(0, obj_name, OBJPROP_COLOR, draw_color);
ObjectSetInteger(0, obj_name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, obj_name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, obj_name, OBJPROP_FILL, true);
ObjectSetInteger(0, obj_name, OBJPROP_BACK, true);
ObjectSetInteger(0, obj_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, obj_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, obj_name, OBJPROP_HIDDEN, true);
// Add transparency
ObjectSetInteger(0, obj_name, OBJPROP_BGCOLOR, draw_color);
ObjectSetInteger(0, obj_name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
// Set description
string description = StringFormat("Order Block %s - Strength: %.2f - %s",
ob.is_bullish ? "Bullish" : "Bearish",
ob.strength,
ob.is_fresh ? "Fresh" : "Used");
ObjectSetString(0, obj_name, OBJPROP_TOOLTIP, description);
if (EnableDebugMode)
{
LogDebug(StringFormat("Drew Order Block: %s at %.5f-%.5f",
ob.is_bullish ? "Bullish" : "Bearish", ob.low, ob.high));
}
}
else
{
LogWarning(StringFormat("Failed to create Order Block object: %s", obj_name));
}
}
void DrawFairValueGap(string symbol, FairValueGap &fvg, color gap_color = clrNONE)
{
if (!IsVisualizationEnabled() || !ShowFVG)
return;
// Check object limit
if (CountPatternObjects("FVG", symbol) >= MaxObjectsPerPattern)
{
CleanupPatternObjects("FVG", symbol);
}
// Generate unique object name
string obj_name = GenerateObjectName("FVG", symbol, fvg.time);
// Delete existing object if it exists
ObjectDelete(0, obj_name);
// Determine color based on bullish/bearish and user settings
color draw_color = gap_color;
if (draw_color == clrNONE)
{
draw_color = fvg.is_bullish ? BullishFVGColor : BearishFVGColor;
}
// Create rectangle object for FVG
if (ObjectCreate(0, obj_name, OBJ_RECTANGLE, 0, fvg.time, fvg.top, fvg.time + PeriodSeconds(PERIOD_H1) * 12, fvg.bottom))
{
// Set rectangle properties with transparency
ObjectSetInteger(0, obj_name, OBJPROP_COLOR, draw_color);
ObjectSetInteger(0, obj_name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, obj_name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, obj_name, OBJPROP_FILL, true);
ObjectSetInteger(0, obj_name, OBJPROP_BACK, true);
ObjectSetInteger(0, obj_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, obj_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, obj_name, OBJPROP_HIDDEN, true);
// Add transparency and background color
ObjectSetInteger(0, obj_name, OBJPROP_BGCOLOR, draw_color);
ObjectSetInteger(0, obj_name, OBJPROP_BORDER_TYPE, BORDER_FLAT);
// Set description
string description = StringFormat("Fair Value Gap %s - Size: %.1f pips - %s",
fvg.is_bullish ? "Bullish" : "Bearish",
MathAbs(fvg.top - fvg.bottom) / SymbolInfoDouble(symbol, SYMBOL_POINT) / 10,
fvg.is_filled ? "Filled" : "Open");
ObjectSetString(0, obj_name, OBJPROP_TOOLTIP, description);
if (EnableDebugMode)
{
LogDebug(StringFormat("Drew Fair Value Gap: %s at %.5f-%.5f",
fvg.is_bullish ? "Bullish" : "Bearish", fvg.bottom, fvg.top));
}
}
else
{
LogWarning(StringFormat("Failed to create Fair Value Gap object: %s", obj_name));
}
}
void DrawBreakOfStructure(string symbol, BreakOfStructure &bos)
{
if (!IsVisualizationEnabled() || !ShowBOS)
return;
// Check object limit
if (CountPatternObjects("BOS", symbol) >= MaxObjectsPerPattern)
{
CleanupPatternObjects("BOS", symbol);
}
// Generate unique object names for arrow and label
string arrow_name = GenerateObjectName("BOS_Arrow", symbol, bos.time);
string label_name = GenerateObjectName("BOS_Label", symbol, bos.time);
// Delete existing objects if they exist
ObjectDelete(0, arrow_name);
ObjectDelete(0, label_name);
// Determine color and arrow code based on direction
color draw_color = bos.is_bullish ? BullishBOSColor : BearishBOSColor;
int arrow_code = bos.is_bullish ? 233 : 234; // Up arrow for bullish, down arrow for bearish
// Create arrow object
if (ObjectCreate(0, arrow_name, OBJ_ARROW, 0, bos.time, bos.level))
{
// Set arrow properties
ObjectSetInteger(0, arrow_name, OBJPROP_COLOR, draw_color);
ObjectSetInteger(0, arrow_name, OBJPROP_ARROWCODE, arrow_code);
ObjectSetInteger(0, arrow_name, OBJPROP_WIDTH, 3);
ObjectSetInteger(0, arrow_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, arrow_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, arrow_name, OBJPROP_HIDDEN, true);
// Set description
string description = StringFormat("Break of Structure %s at %.5f",
bos.is_bullish ? "Bullish" : "Bearish",
bos.level);
ObjectSetString(0, arrow_name, OBJPROP_TOOLTIP, description);
}
// Create label object
if (ObjectCreate(0, label_name, OBJ_TEXT, 0, bos.time, bos.level))
{
// Set label properties
ObjectSetInteger(0, label_name, OBJPROP_COLOR, draw_color);
ObjectSetInteger(0, label_name, OBJPROP_FONTSIZE, 8);
ObjectSetInteger(0, label_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, label_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, label_name, OBJPROP_HIDDEN, true);
ObjectSetString(0, label_name, OBJPROP_FONT, "Arial Bold");
ObjectSetString(0, label_name, OBJPROP_TEXT, bos.is_bullish ? "BOS↑" : "BOS↓");
// Position label slightly offset from the level
double offset = bos.is_bullish ? SymbolInfoDouble(symbol, SYMBOL_POINT) * 50 : -SymbolInfoDouble(symbol, SYMBOL_POINT) * 50;
ObjectSetDouble(0, label_name, OBJPROP_PRICE, bos.level + offset);
}
if (EnableDebugMode)
{
LogDebug(StringFormat("Drew Break of Structure: %s at %.5f",
bos.is_bullish ? "Bullish" : "Bearish", bos.level));
}
}
void DrawLiquiditySweep(string symbol, LiquiditySweep &sweep)
{
if (!IsVisualizationEnabled() || !ShowSweeps)
return;
// Check object limit
if (CountPatternObjects("SWEEP", symbol) >= MaxObjectsPerPattern)
{
CleanupPatternObjects("SWEEP", symbol);
}
// Generate unique object names for icon and label
string icon_name = GenerateObjectName("SWEEP_Icon", symbol, sweep.time);
string label_name = GenerateObjectName("SWEEP_Label", symbol, sweep.time);
string line_name = GenerateObjectName("SWEEP_Line", symbol, sweep.time);
// Delete existing objects if they exist
ObjectDelete(0, icon_name);
ObjectDelete(0, label_name);
ObjectDelete(0, line_name);
// Create horizontal line at sweep level
if (ObjectCreate(0, line_name, OBJ_HLINE, 0, sweep.time, sweep.level))
{
ObjectSetInteger(0, line_name, OBJPROP_COLOR, SweepColor);
ObjectSetInteger(0, line_name, OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, line_name, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, line_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, line_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, line_name, OBJPROP_HIDDEN, true);
}
// Create sweep icon (triangle)
if (ObjectCreate(0, icon_name, OBJ_ARROW, 0, sweep.time, sweep.level))
{
// Set icon properties - use different arrows for high/low sweeps
int arrow_code = sweep.is_high_sweep ? 242 : 241; // Triangle up for high sweep, down for low sweep
ObjectSetInteger(0, icon_name, OBJPROP_COLOR, SweepColor);
ObjectSetInteger(0, icon_name, OBJPROP_ARROWCODE, arrow_code);
ObjectSetInteger(0, icon_name, OBJPROP_WIDTH, 4);
ObjectSetInteger(0, icon_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, icon_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, icon_name, OBJPROP_HIDDEN, true);
// Set description
string description = StringFormat("Liquidity Sweep %s at %.5f - %s",
sweep.is_high_sweep ? "High" : "Low",
sweep.level,
sweep.confirmed ? "Confirmed" : "Pending");
ObjectSetString(0, icon_name, OBJPROP_TOOLTIP, description);
}
// Create label
if (ObjectCreate(0, label_name, OBJ_TEXT, 0, sweep.time, sweep.level))
{
// Set label properties
ObjectSetInteger(0, label_name, OBJPROP_COLOR, SweepColor);
ObjectSetInteger(0, label_name, OBJPROP_FONTSIZE, 8);
ObjectSetInteger(0, label_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, label_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, label_name, OBJPROP_HIDDEN, true);
ObjectSetString(0, label_name, OBJPROP_FONT, "Arial Bold");
ObjectSetString(0, label_name, OBJPROP_TEXT, sweep.is_high_sweep ? "🔺" : "🔻");
// Position label slightly offset from the level
double offset = sweep.is_high_sweep ? SymbolInfoDouble(symbol, SYMBOL_POINT) * 30 : -SymbolInfoDouble(symbol, SYMBOL_POINT) * 30;
ObjectSetDouble(0, label_name, OBJPROP_PRICE, sweep.level + offset);
}
if (EnableDebugMode)
{
LogDebug(StringFormat("Drew Liquidity Sweep: %s at %.5f",
sweep.is_high_sweep ? "High" : "Low", sweep.level));
}
}
void DrawTradeLevels(string symbol, double entry, double sl, double tp, string trade_type = "")
{
if (!IsVisualizationEnabled() || !ShowTradeLevels)
return;
// Generate unique object names
datetime current_time = TimeCurrent();
string entry_name = GenerateObjectName("ENTRY", symbol, current_time);
string sl_name = GenerateObjectName("SL", symbol, current_time);
string tp_name = GenerateObjectName("TP", symbol, current_time);
// Clean up old trade level objects for this symbol
CleanupPatternObjects("ENTRY", symbol);
CleanupPatternObjects("SL", symbol);
CleanupPatternObjects("TP", symbol);
// Create Entry Level Line
if (entry > 0 && ObjectCreate(0, entry_name, OBJ_HLINE, 0, current_time, entry))
{
ObjectSetInteger(0, entry_name, OBJPROP_COLOR, EntryLevelColor);
ObjectSetInteger(0, entry_name, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, entry_name, OBJPROP_WIDTH, 2);
ObjectSetInteger(0, entry_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, entry_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, entry_name, OBJPROP_HIDDEN, true);
string entry_desc = StringFormat("Entry Level: %.5f %s", entry, trade_type);
ObjectSetString(0, entry_name, OBJPROP_TOOLTIP, entry_desc);
}
// Create Stop Loss Line
if (sl > 0 && ObjectCreate(0, sl_name, OBJ_HLINE, 0, current_time, sl))
{
ObjectSetInteger(0, sl_name, OBJPROP_COLOR, StopLossColor);
ObjectSetInteger(0, sl_name, OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, sl_name, OBJPROP_WIDTH, 2);
ObjectSetInteger(0, sl_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, sl_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, sl_name, OBJPROP_HIDDEN, true);
string sl_desc = StringFormat("Stop Loss: %.5f", sl);
ObjectSetString(0, sl_name, OBJPROP_TOOLTIP, sl_desc);
}
// Create Take Profit Line
if (tp > 0 && ObjectCreate(0, tp_name, OBJ_HLINE, 0, current_time, tp))
{
ObjectSetInteger(0, tp_name, OBJPROP_COLOR, TakeProfitColor);
ObjectSetInteger(0, tp_name, OBJPROP_STYLE, STYLE_DASH);
ObjectSetInteger(0, tp_name, OBJPROP_WIDTH, 2);
ObjectSetInteger(0, tp_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, tp_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, tp_name, OBJPROP_HIDDEN, true);
string tp_desc = StringFormat("Take Profit: %.5f", tp);
ObjectSetString(0, tp_name, OBJPROP_TOOLTIP, tp_desc);
}
if (EnableDebugMode)
{
LogDebug(StringFormat("Drew Trade Levels for %s: Entry=%.5f, SL=%.5f, TP=%.5f",
symbol, entry, sl, tp));
}
}
//+------------------------------------------------------------------+
//| Update information panel |
//+------------------------------------------------------------------+
void UpdateInfoPanel()
{
if (!IsVisualizationEnabled() || !ShowInfoPanel)
return;
// Get current session
string current_session = GetCurrentSession();
// Update EA status
ObjectSetString(0, "SniperEA_Status", OBJPROP_TEXT, "Sniper EA - " + current_session);
// Get account information
double account_balance = AccountInfoDouble(ACCOUNT_BALANCE);
double account_equity = AccountInfoDouble(ACCOUNT_EQUITY);
@@ -403,19 +795,42 @@ void UpdateInfoPanel()
// Count current positions
int total_positions = PositionsTotal();
// Create info text
// Get pattern counts for current symbol
MarketStructureData m1_data;
int ob_count = 0, fvg_count = 0, bos_count = 0, sweep_count = 0;
if (GetTimeframeData(PERIOD_M1, m1_data) && m1_data.is_valid)
{
ob_count = ArraySize(m1_data.order_blocks);
fvg_count = ArraySize(m1_data.fair_value_gaps);
bos_count = ArraySize(m1_data.bos_events);
sweep_count = ArraySize(m1_data.liquidity_sweeps);
}
// Get market bias
string market_bias = GetMarketBias(_Symbol);
// Create comprehensive info text
string info_text = StringFormat(
"Session: %s\n" +
"Balance: %.2f\n" +
"Equity: %.2f\n" +
"Margin: %.2f\n" +
"Positions: %d/%d",
"=== SNIPER EA DASHBOARD ===\n" +
"Status: ACTIVE | Session: %s\n" +
"Balance: $%.2f | Equity: $%.2f\n" +
"Positions: %d/%d | Risk: %.1f%%\n" +
"\n" +
"=== MARKET ANALYSIS ===\n" +
"Symbol: %s | Bias: %s\n" +
"Order Blocks: %d | FVGs: %d\n" +
"BOS Events: %d | Sweeps: %d\n" +
"\n" +
"=== CAMBODIA TIME ===\n" +
"Current Time: %s",
current_session,
account_balance,
account_equity,
account_margin,
total_positions,
MaxPositions);
account_balance, account_equity,
total_positions, MaxPositions, RiskPercent,
_Symbol, market_bias,
ob_count, fvg_count,
bos_count, sweep_count,
TimeToString(TimeGMT() + 7 * 3600, TIME_MINUTES));
// Update info label
if (ObjectFind(0, "SniperEA_Info") < 0)
@@ -435,6 +850,70 @@ void UpdateInfoPanel()
ObjectSetString(0, "SniperEA_Info", OBJPROP_TEXT, info_text);
}
void DrawPatternsOnChart(string symbol, MarketStructureData &mtf_data)
{
if (!IsVisualizationEnabled())
return;
// Draw Order Blocks
if (ShowOrderBlocks)
{
for (int i = 0; i < ArraySize(mtf_data.order_blocks); i++)
{
if (mtf_data.order_blocks[i].is_fresh && mtf_data.order_blocks[i].strength > OBStrengthFilter)
{
DrawOrderBlock(symbol, mtf_data.order_blocks[i]);
}
}
}
// Draw Fair Value Gaps
if (ShowFVG)
{
for (int i = 0; i < ArraySize(mtf_data.fair_value_gaps); i++)
{
if (!mtf_data.fair_value_gaps[i].is_filled)
{
DrawFairValueGap(symbol, mtf_data.fair_value_gaps[i]);
}
}
}
// Draw Break of Structure events
if (ShowBOS)
{
for (int i = 0; i < ArraySize(mtf_data.bos_events); i++)
{
if (mtf_data.bos_events[i].confirmed)
{
DrawBreakOfStructure(symbol, mtf_data.bos_events[i]);
}
}
}
// Draw Liquidity Sweeps
if (ShowSweeps)
{
for (int i = 0; i < ArraySize(mtf_data.liquidity_sweeps); i++)
{
if (mtf_data.liquidity_sweeps[i].confirmed)
{
DrawLiquiditySweep(symbol, mtf_data.liquidity_sweeps[i]);
}
}
}
if (EnableDebugMode)
{
LogDebug(StringFormat("Drew patterns for %s %s: OB=%d, FVG=%d, BOS=%d, Sweeps=%d",
symbol, EnumToString(mtf_data.timeframe),
ArraySize(mtf_data.order_blocks),
ArraySize(mtf_data.fair_value_gaps),
ArraySize(mtf_data.bos_events),
ArraySize(mtf_data.liquidity_sweeps)));
}
}
//+------------------------------------------------------------------+
//| Get current trading session |
//+------------------------------------------------------------------+
@@ -501,6 +980,13 @@ bool ExecuteBuyTrade(string symbol, double entry, double sl, double tp, double l
if (result)
{
LogTrade("BUY EXECUTED", symbol, StringFormat("Entry: %.5f, SL: %.5f, TP: %.5f, Lot: %.2f", entry, sl, tp, lot_size));
// Draw trade levels on chart
if (symbol == _Symbol)
{
DrawTradeLevels(symbol, entry, sl, tp, "BUY");
}
return true;
}
else
@@ -531,6 +1017,13 @@ bool ExecuteSellTrade(string symbol, double entry, double sl, double tp, double
if (result)
{
LogTrade("SELL EXECUTED", symbol, StringFormat("Entry: %.5f, SL: %.5f, TP: %.5f, Lot: %.2f", entry, sl, tp, lot_size));
// Draw trade levels on chart
if (symbol == _Symbol)
{
DrawTradeLevels(symbol, entry, sl, tp, "SELL");
}
return true;
}
else
@@ -2832,6 +3325,12 @@ bool UpdateTimeframeData(string symbol, MarketStructureData &mtf_data)
mtf_data.current_bias.strength,
mtf_data.current_bias.direction,
mtf_data.market_phase));
// Phase 3: Draw patterns on chart (only for current symbol and M15/H4 timeframes for clarity)
if (symbol == _Symbol && (mtf_data.timeframe == PERIOD_M15 || mtf_data.timeframe == PERIOD_H4))
{
DrawPatternsOnChart(symbol, mtf_data);
}
}
return success;