Forrmat
This commit is contained in:
+63
-76
@@ -17,106 +17,93 @@
|
||||
//| |
|
||||
//| Drawing: objects KHÔNG BAO GIỜ bị xóa, chỉ update |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Bell's ICT EA" // Bản quyền EA
|
||||
#property version "4.30" // Phiên bản
|
||||
#property copyright "Bell's ICT EA"
|
||||
#property version "4.30"
|
||||
|
||||
#define MAX_FVG_POOL 30 // Số FVG tối đa trong pool
|
||||
#define MAX_FVG_POOL 30
|
||||
|
||||
//====================================================
|
||||
// LAYER 1 – Config + Types (no dependencies)
|
||||
//====================================================
|
||||
#include "EA_ICT_CL/Config.mqh" // Inputs và cấu hình
|
||||
#include "EA_ICT_CL/State.mqh" // Enums, structs (EAState, BiasContext, FVGRecord...)
|
||||
#include "EA_ICT_CL/Config.mqh"
|
||||
#include "EA_ICT_CL/State.mqh"
|
||||
|
||||
//====================================================
|
||||
// LAYER 2 – Utility modules (depend on types + inputs)
|
||||
//====================================================
|
||||
#include "EA_ICT_CL/Utils.mqh" // Clamp, RoundToStep, IsNewBar
|
||||
#include "EA_ICT_CL/Logging.mqh" // LogPrint, LogPrintF
|
||||
#include "EA_ICT_CL/Market.mqh" // GetBid, GetAsk, GetPoint, IsTradeAllowedNow
|
||||
#include "EA_ICT_CL/Indicators.mqh" // CopyBufferSafe, CopyTimeSafe
|
||||
#include "EA_ICT_CL/Sessions.mqh" // IsHourInRange, GetUTCHour
|
||||
#include "EA_ICT_CL/Filters.mqh" // Filter_MaxSpreadPoints
|
||||
#include "EA_ICT_CL/Risk.mqh" // NormalizeVolume, LotsFromRiskMoneyAndSLPoints
|
||||
#include "EA_ICT_CL/Orders.mqh" // NormalizePrice, BuildOrderComment
|
||||
#include "EA_ICT_CL/Swing.mqh" // MyBarShift, IsSwingHighAt, ScanSwingStructure, ResolveTrendFromSwings
|
||||
#include "EA_ICT_CL/Trailing.mqh" // Placeholder trailing/BE
|
||||
#include "EA_ICT_CL/Utils.mqh"
|
||||
#include "EA_ICT_CL/Logging.mqh"
|
||||
#include "EA_ICT_CL/Market.mqh"
|
||||
#include "EA_ICT_CL/Indicators.mqh"
|
||||
#include "EA_ICT_CL/Sessions.mqh"
|
||||
#include "EA_ICT_CL/Filters.mqh"
|
||||
#include "EA_ICT_CL/Risk.mqh"
|
||||
#include "EA_ICT_CL/Orders.mqh"
|
||||
#include "EA_ICT_CL/Swing.mqh"
|
||||
#include "EA_ICT_CL/Trailing.mqh"
|
||||
|
||||
//====================================================
|
||||
// GLOBALS
|
||||
//====================================================
|
||||
EAState g_State = EA_IDLE; // Trạng thái EA hiện tại
|
||||
BlockReason g_BlockReason = BLOCK_NONE; // Lý do chặn trade (session/daily loss/bias...)
|
||||
EAState g_State = EA_IDLE;
|
||||
BlockReason g_BlockReason = BLOCK_NONE;
|
||||
|
||||
BiasContext g_Bias; // D1 bias (UP/DOWN/SIDEWAY/NONE)
|
||||
TFTrendContext g_MiddleTrend; // H1 swing + trend + MSS
|
||||
TFTrendContext g_TriggerTrend; // M5 swing + trend
|
||||
DailyRiskContext g_DailyRisk; // Balance đầu ngày, limit hit
|
||||
BiasContext g_Bias;
|
||||
TFTrendContext g_MiddleTrend;
|
||||
TFTrendContext g_TriggerTrend;
|
||||
DailyRiskContext g_DailyRisk;
|
||||
|
||||
FVGRecord g_FVGPool[MAX_FVG_POOL]; // Pool các FVG đã quét
|
||||
int g_FVGCount = 0; // Số FVG trong pool
|
||||
int g_NextFVGId = 0; // ID gán cho FVG mới
|
||||
int g_ActiveFVGIdx = -1; // Chỉ số FVG đang theo dõi (-1 = không có)
|
||||
int g_TradeBarIndex = -1; // Bar index khi vào lệnh (dùng cho timeout...)
|
||||
FVGRecord g_FVGPool[MAX_FVG_POOL];
|
||||
int g_FVGCount = 0;
|
||||
int g_NextFVGId = 0;
|
||||
int g_ActiveFVGIdx = -1;
|
||||
int g_TradeBarIndex = -1;
|
||||
|
||||
OrderPlan g_OrderPlan; // Kế hoạch lệnh (entry, SL, TP, lot)
|
||||
ulong g_PendingTicket = 0; // Ticket lệnh pending đã gửi
|
||||
OrderPlan g_OrderPlan;
|
||||
ulong g_PendingTicket = 0;
|
||||
|
||||
const string PREFIX_SWING_MIDDLE = "SwingMiddle_"; // Tiền tố object H1 swing
|
||||
const string PREFIX_SWING_TRIGGER = "SwingTrigger_"; // Tiền tố object M5 swing
|
||||
const string PREFIX_MSS_MARKER = "MSSMarker_"; // Tiền tố marker MSS
|
||||
const string PREFIX_FVG_POOL = "FVGPool_"; // Tiền tố hình FVG
|
||||
const string PREFIX_ORDER_VISUAL = "OrderVisual_"; // Tiền tố vùng Entry/SL/TP
|
||||
const string PREFIX_DEBUG_PANEL = "DebugPanel_"; // Tiền tố panel debug góc trái
|
||||
const string PREFIX_SWING_MIDDLE = "SwingMiddle_";
|
||||
const string PREFIX_SWING_TRIGGER = "SwingTrigger_";
|
||||
const string PREFIX_MSS_MARKER = "MSSMarker_";
|
||||
const string PREFIX_FVG_POOL = "FVGPool_";
|
||||
const string PREFIX_ORDER_VISUAL = "OrderVisual_";
|
||||
const string PREFIX_DEBUG_PANEL = "DebugPanel_";
|
||||
|
||||
//====================================================
|
||||
// LAYER 3 – Logic modules (depend on globals)
|
||||
//====================================================
|
||||
#include "EA_ICT_CL/Contexts.mqh" // UpdateBiasContext, UpdateTFTrendContext, UpdateAllContexts
|
||||
#include "EA_ICT_CL/Guards.mqh" // IsSessionAllowed, EvaluateGuards
|
||||
#include "EA_ICT_CL/Signals_BOS_FVG_OB.mqh" // ScanAndRegisterFVGs, UpdateFVGStatuses, GetBestActiveFVGIdx
|
||||
#include "EA_ICT_CL/Trade.mqh" // BuildOrderPlan, ExecuteLimitOrder
|
||||
#include "EA_ICT_CL/StateMachine.mqh" // TransitionTo, RunStateMachine, OnStateIdle...
|
||||
#include "EA_ICT_CL/Drawing.mqh" // DrawVisuals, DrawFVGPool, DrawContextDebug...
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| EA LIFECYCLE |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "EA_ICT_CL/Contexts.mqh"
|
||||
#include "EA_ICT_CL/Guards.mqh"
|
||||
#include "EA_ICT_CL/Signals_BOS_FVG_OB.mqh"
|
||||
#include "EA_ICT_CL/Trade.mqh"
|
||||
#include "EA_ICT_CL/StateMachine.mqh"
|
||||
#include "EA_ICT_CL/Drawing.mqh"
|
||||
|
||||
/** Initializes globals, contexts, FVG pool and first draw. */
|
||||
int OnInit()
|
||||
{
|
||||
ZeroMemory(g_Bias); ZeroMemory(g_MiddleTrend); ZeroMemory(g_TriggerTrend); // Xóa context
|
||||
ZeroMemory(g_DailyRisk); ZeroMemory(g_OrderPlan); // Xóa risk + order plan
|
||||
for (int i = 0; i < MAX_FVG_POOL; i++) ZeroMemory(g_FVGPool[i]); // Xóa toàn bộ pool FVG
|
||||
g_FVGCount = 0; g_NextFVGId = 0; // Reset đếm FVG
|
||||
g_ActiveFVGIdx = -1; g_TradeBarIndex = -1; g_PendingTicket = 0; // Không FVG active, không pending
|
||||
g_State = EA_IDLE; g_BlockReason = BLOCK_NONE; // State = IDLE, không block
|
||||
ZeroMemory(g_Bias); ZeroMemory(g_MiddleTrend); ZeroMemory(g_TriggerTrend);
|
||||
ZeroMemory(g_DailyRisk); ZeroMemory(g_OrderPlan);
|
||||
for (int i = 0; i < MAX_FVG_POOL; i++) ZeroMemory(g_FVGPool[i]);
|
||||
g_FVGCount = 0; g_NextFVGId = 0;
|
||||
g_ActiveFVGIdx = -1; g_TradeBarIndex = -1; g_PendingTicket = 0;
|
||||
g_State = EA_IDLE; g_BlockReason = BLOCK_NONE;
|
||||
|
||||
UpdateAllContexts(); // Cập nhật D1 bias, H1/M5 trend, daily risk
|
||||
ScanAndRegisterFVGs(); // Quét H1 và đăng ký FVG vào pool
|
||||
DrawVisuals(); // Vẽ swing, FVG, debug panel (nếu bật)
|
||||
UpdateAllContexts();
|
||||
ScanAndRegisterFVGs();
|
||||
DrawVisuals();
|
||||
|
||||
PrintFormat("✅ ICT EA v4.3 | Bias=%s | H1=%s | M5=%s | Pool=%d",
|
||||
EnumToString(g_Bias.bias), EnumToString(g_MiddleTrend.trend),
|
||||
EnumToString(g_TriggerTrend.trend), g_FVGCount);
|
||||
return INIT_SUCCEEDED; // Khởi tạo thành công
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
/** Each tick: update contexts, run guards and state machine, optionally redraw. */
|
||||
void OnTick()
|
||||
{
|
||||
UpdateAllContexts(); // Mỗi tick: cập nhật bias, H1/M5 swing, daily risk, MSS (nếu WAIT_TRIGGER)
|
||||
if (EvaluateGuards()) // Kiểm tra session, daily loss, bias, alignment
|
||||
RunStateMachine(); // Chạy state machine (Idle/WaitTouch/WaitTrigger/InTrade)
|
||||
UpdateAllContexts();
|
||||
if (EvaluateGuards())
|
||||
RunStateMachine();
|
||||
else if (g_State != EA_IDLE)
|
||||
ResetToIdle(EnumToString(g_BlockReason)); // Đang không IDLE mà fail guard → reset về IDLE
|
||||
if (InpDebugDraw) DrawVisuals(); // Vẽ lại nếu bật debug draw
|
||||
ResetToIdle(EnumToString(g_BlockReason));
|
||||
if (InpDebugDraw) DrawVisuals();
|
||||
}
|
||||
|
||||
/** Removes swing and debug panel objects and redraws chart. */
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
ObjectsDeleteAll(0, PREFIX_SWING_MIDDLE); // Xóa toàn bộ object H1 swing
|
||||
ObjectsDeleteAll(0, PREFIX_SWING_TRIGGER); // Xóa toàn bộ object M5 swing
|
||||
ObjectsDeleteAll(0, PREFIX_DEBUG_PANEL); // Xóa panel debug (FVG/order objects giữ lại theo thiết kế)
|
||||
ChartRedraw(0); // Vẽ lại chart
|
||||
PrintFormat("ICT EA v4.3 deinit | reason=%d | pool=%d", reason, g_FVGCount); // Log thoát
|
||||
ObjectsDeleteAll(0, PREFIX_SWING_MIDDLE);
|
||||
ObjectsDeleteAll(0, PREFIX_SWING_TRIGGER);
|
||||
ObjectsDeleteAll(0, PREFIX_DEBUG_PANEL);
|
||||
ChartRedraw(0);
|
||||
PrintFormat("ICT EA v4.3 deinit | reason=%d | pool=%d", reason, g_FVGCount);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ input int InpLondonEndHour = 17;
|
||||
input int InpNYStartHour = 13;
|
||||
input int InpNYEndHour = 22;
|
||||
|
||||
input int InpSwingRange = 3;
|
||||
input int InpSwingRange = 2;
|
||||
input int InpSwingLookback = 50;
|
||||
input int InpTriggerSwingLookback = 30;
|
||||
|
||||
|
||||
+382
-106
@@ -12,7 +12,8 @@ inline void DrawOneSwingPoint(
|
||||
string keyLevelObjName = prefix + "KL_" + tag;
|
||||
datetime barTime = iTime(_Symbol, tf, barIdx);
|
||||
|
||||
if (ObjectFind(0, arrowObjName) < 0) ObjectCreate(0, arrowObjName, OBJ_ARROW, 0, barTime, price);
|
||||
if (ObjectFind(0, arrowObjName) < 0)
|
||||
ObjectCreate(0, arrowObjName, OBJ_ARROW, 0, barTime, price);
|
||||
ObjectSetInteger(0, arrowObjName, OBJPROP_ARROWCODE, isHigh ? 234 : 233);
|
||||
ObjectSetInteger(0, arrowObjName, OBJPROP_COLOR, clr);
|
||||
ObjectSetInteger(0, arrowObjName, OBJPROP_WIDTH, arrowSz);
|
||||
@@ -21,7 +22,8 @@ inline void DrawOneSwingPoint(
|
||||
|
||||
double barRange = iHigh(_Symbol, tf, barIdx) - iLow(_Symbol, tf, barIdx);
|
||||
double textY = isHigh ? price + barRange * 0.3 : price - barRange * 0.3;
|
||||
if (ObjectFind(0, textObjName) < 0) ObjectCreate(0, textObjName, OBJ_TEXT, 0, barTime, textY);
|
||||
if (ObjectFind(0, textObjName) < 0)
|
||||
ObjectCreate(0, textObjName, OBJ_TEXT, 0, barTime, textY);
|
||||
ObjectMove(0, textObjName, 0, barTime, textY);
|
||||
ObjectSetString (0, textObjName, OBJPROP_TEXT, tag);
|
||||
ObjectSetInteger(0, textObjName, OBJPROP_COLOR, clr);
|
||||
@@ -31,7 +33,8 @@ inline void DrawOneSwingPoint(
|
||||
if (isKL)
|
||||
{
|
||||
datetime endTime = iTime(_Symbol, tf, 0);
|
||||
if (ObjectFind(0, keyLevelObjName) < 0) ObjectCreate(0, keyLevelObjName, OBJ_TREND, 0, barTime, price, endTime, price);
|
||||
if (ObjectFind(0, keyLevelObjName) < 0)
|
||||
ObjectCreate(0, keyLevelObjName, OBJ_TREND, 0, barTime, price, endTime, price);
|
||||
ObjectSetInteger(0, keyLevelObjName, OBJPROP_COLOR, clr);
|
||||
ObjectSetInteger(0, keyLevelObjName, OBJPROP_STYLE, STYLE_DASH);
|
||||
ObjectSetInteger(0, keyLevelObjName, OBJPROP_WIDTH, 1);
|
||||
@@ -52,10 +55,26 @@ inline void DrawMiddleSwingPoints()
|
||||
|
||||
bool isUp = (g_MiddleTrend.trend == DIR_UP);
|
||||
bool isDown = (g_MiddleTrend.trend == DIR_DOWN);
|
||||
DrawOneSwingPoint(PREFIX_SWING_MIDDLE, InpMiddleTF, "MiddleH0", true, g_MiddleTrend.idxH0, g_MiddleTrend.h0, clrAqua, isDown, 2, 8);
|
||||
DrawOneSwingPoint(PREFIX_SWING_MIDDLE, InpMiddleTF, "MiddleH1", true, g_MiddleTrend.idxH1, g_MiddleTrend.h1, C'0,140,160', false, 2, 8);
|
||||
DrawOneSwingPoint(PREFIX_SWING_MIDDLE, InpMiddleTF, "MiddleL0", false, g_MiddleTrend.idxL0, g_MiddleTrend.l0, clrYellow, isUp, 2, 8);
|
||||
DrawOneSwingPoint(PREFIX_SWING_MIDDLE, InpMiddleTF, "MiddleL1", false, g_MiddleTrend.idxL1, g_MiddleTrend.l1, C'160,140,0', false, 2, 8);
|
||||
DrawOneSwingPoint(
|
||||
PREFIX_SWING_MIDDLE, InpMiddleTF, "MiddleH0",
|
||||
true, g_MiddleTrend.idxH0, g_MiddleTrend.h0,
|
||||
clrAqua, isDown, 2, 8
|
||||
);
|
||||
DrawOneSwingPoint(
|
||||
PREFIX_SWING_MIDDLE, InpMiddleTF, "MiddleH1",
|
||||
true, g_MiddleTrend.idxH1, g_MiddleTrend.h1,
|
||||
C'0,140,160', false, 2, 8
|
||||
);
|
||||
DrawOneSwingPoint(
|
||||
PREFIX_SWING_MIDDLE, InpMiddleTF, "MiddleL0",
|
||||
false, g_MiddleTrend.idxL0, g_MiddleTrend.l0,
|
||||
clrYellow, isUp, 2, 8
|
||||
);
|
||||
DrawOneSwingPoint(
|
||||
PREFIX_SWING_MIDDLE, InpMiddleTF, "MiddleL1",
|
||||
false, g_MiddleTrend.idxL1, g_MiddleTrend.l1,
|
||||
C'160,140,0', false, 2, 8
|
||||
);
|
||||
}
|
||||
|
||||
/** Draws M5 swing points when debug draw enabled. */
|
||||
@@ -68,10 +87,26 @@ inline void DrawTriggerSwingPoints()
|
||||
|
||||
bool isUp = (g_TriggerTrend.trend == DIR_UP);
|
||||
bool isDown = (g_TriggerTrend.trend == DIR_DOWN);
|
||||
DrawOneSwingPoint(PREFIX_SWING_TRIGGER, InpTriggerTF, "TriggerH0", true, g_TriggerTrend.idxH0, g_TriggerTrend.h0, C'180,100,255', isDown, 1, 7);
|
||||
DrawOneSwingPoint(PREFIX_SWING_TRIGGER, InpTriggerTF, "TriggerH1", true, g_TriggerTrend.idxH1, g_TriggerTrend.h1, C'100,60,160', false, 1, 7);
|
||||
DrawOneSwingPoint(PREFIX_SWING_TRIGGER, InpTriggerTF, "TriggerL0", false, g_TriggerTrend.idxL0, g_TriggerTrend.l0, C'255,160,40', isUp, 1, 7);
|
||||
DrawOneSwingPoint(PREFIX_SWING_TRIGGER, InpTriggerTF, "TriggerL1", false, g_TriggerTrend.idxL1, g_TriggerTrend.l1, C'160,100,20', false, 1, 7);
|
||||
DrawOneSwingPoint(
|
||||
PREFIX_SWING_TRIGGER, InpTriggerTF, "TriggerH0",
|
||||
true, g_TriggerTrend.idxH0, g_TriggerTrend.h0,
|
||||
C'180,100,255', isDown, 1, 7
|
||||
);
|
||||
DrawOneSwingPoint(
|
||||
PREFIX_SWING_TRIGGER, InpTriggerTF, "TriggerH1",
|
||||
true, g_TriggerTrend.idxH1, g_TriggerTrend.h1,
|
||||
C'100,60,160', false, 1, 7
|
||||
);
|
||||
DrawOneSwingPoint(
|
||||
PREFIX_SWING_TRIGGER, InpTriggerTF, "TriggerL0",
|
||||
false, g_TriggerTrend.idxL0, g_TriggerTrend.l0,
|
||||
C'255,160,40', isUp, 1, 7
|
||||
);
|
||||
DrawOneSwingPoint(
|
||||
PREFIX_SWING_TRIGGER, InpTriggerTF, "TriggerL1",
|
||||
false, g_TriggerTrend.idxL1, g_TriggerTrend.l1,
|
||||
C'160,100,20', false, 1, 7
|
||||
);
|
||||
}
|
||||
|
||||
/** Draws one MSS marker (arrow + label + horizontal level) at given time/level. */
|
||||
@@ -131,10 +166,13 @@ inline void DrawMSSMarkers()
|
||||
if (g_FVGPool[i].mssTime == 0) continue;
|
||||
|
||||
string tid = "T_" + IntegerToString(g_FVGPool[i].id);
|
||||
DrawMSSMarker(tid, InpTriggerTF,
|
||||
DrawMSSMarker(
|
||||
tid,
|
||||
InpTriggerTF,
|
||||
g_FVGPool[i].mssTime,
|
||||
g_FVGPool[i].mssEntry,
|
||||
g_FVGPool[i].direction == DIR_UP ? DIR_UP : DIR_DOWN);
|
||||
g_FVGPool[i].direction == DIR_UP ? DIR_UP : DIR_DOWN
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,9 +193,14 @@ inline void DrawOrderVisualization()
|
||||
|
||||
if (!g_OrderPlan.valid || g_State == EA_IDLE)
|
||||
{
|
||||
ObjectDelete(0, tpZoneN); ObjectDelete(0, slZoneN);
|
||||
ObjectDelete(0, entLineN); ObjectDelete(0, slLineN); ObjectDelete(0, tpLineN);
|
||||
ObjectDelete(0, entLblN); ObjectDelete(0, slLblN); ObjectDelete(0, tpLblN);
|
||||
ObjectDelete(0, tpZoneN);
|
||||
ObjectDelete(0, slZoneN);
|
||||
ObjectDelete(0, entLineN);
|
||||
ObjectDelete(0, slLineN);
|
||||
ObjectDelete(0, tpLineN);
|
||||
ObjectDelete(0, entLblN);
|
||||
ObjectDelete(0, slLblN);
|
||||
ObjectDelete(0, tpLblN);
|
||||
ObjectDelete(0, infoLblN);
|
||||
return;
|
||||
}
|
||||
@@ -180,58 +223,127 @@ inline void DrawOrderVisualization()
|
||||
color tpClr = C'38,166,91';
|
||||
color slClr = C'229,57,53';
|
||||
|
||||
double tpTop = isBuy ? tp : entry, tpBot = isBuy ? entry : tp;
|
||||
if (ObjectFind(0, tpZoneN) < 0) ObjectCreate(0, tpZoneN, OBJ_RECTANGLE, 0, tStart, tpTop, tEnd, tpBot);
|
||||
ObjectSetInteger(0, tpZoneN, OBJPROP_COLOR, tpFill); ObjectSetInteger(0, tpZoneN, OBJPROP_FILL, true);
|
||||
ObjectSetInteger(0, tpZoneN, OBJPROP_BACK, true);
|
||||
ObjectMove(0, tpZoneN, 0, tStart, tpTop); ObjectMove(0, tpZoneN, 1, tEnd, tpBot);
|
||||
double tpTop = isBuy ? tp : entry;
|
||||
double tpBot = isBuy ? entry : tp;
|
||||
if (ObjectFind(0, tpZoneN) < 0)
|
||||
ObjectCreate(0, tpZoneN, OBJ_RECTANGLE, 0, tStart, tpTop, tEnd, tpBot);
|
||||
ObjectSetInteger(0, tpZoneN, OBJPROP_COLOR, tpFill);
|
||||
ObjectSetInteger(0, tpZoneN, OBJPROP_FILL, true);
|
||||
ObjectSetInteger(0, tpZoneN, OBJPROP_BACK, true);
|
||||
ObjectMove(0, tpZoneN, 0, tStart, tpTop);
|
||||
ObjectMove(0, tpZoneN, 1, tEnd, tpBot);
|
||||
|
||||
double slTop = isBuy ? entry : sl, slBot = isBuy ? sl : entry;
|
||||
if (ObjectFind(0, slZoneN) < 0) ObjectCreate(0, slZoneN, OBJ_RECTANGLE, 0, tStart, slTop, tEnd, slBot);
|
||||
ObjectSetInteger(0, slZoneN, OBJPROP_COLOR, slFill); ObjectSetInteger(0, slZoneN, OBJPROP_FILL, true);
|
||||
ObjectSetInteger(0, slZoneN, OBJPROP_BACK, true);
|
||||
ObjectMove(0, slZoneN, 0, tStart, slTop); ObjectMove(0, slZoneN, 1, tEnd, slBot);
|
||||
double slTop = isBuy ? entry : sl;
|
||||
double slBot = isBuy ? sl : entry;
|
||||
if (ObjectFind(0, slZoneN) < 0)
|
||||
ObjectCreate(0, slZoneN, OBJ_RECTANGLE, 0, tStart, slTop, tEnd, slBot);
|
||||
ObjectSetInteger(0, slZoneN, OBJPROP_COLOR, slFill);
|
||||
ObjectSetInteger(0, slZoneN, OBJPROP_FILL, true);
|
||||
ObjectSetInteger(0, slZoneN, OBJPROP_BACK, true);
|
||||
ObjectMove(0, slZoneN, 0, tStart, slTop);
|
||||
ObjectMove(0, slZoneN, 1, tEnd, slBot);
|
||||
|
||||
if (ObjectFind(0, entLineN) < 0) ObjectCreate(0, entLineN, OBJ_TREND, 0, tStart, entry, tEnd, entry);
|
||||
ObjectSetInteger(0, entLineN, OBJPROP_COLOR, entryClr); ObjectSetInteger(0, entLineN, OBJPROP_STYLE, STYLE_SOLID);
|
||||
ObjectSetInteger(0, entLineN, OBJPROP_WIDTH, 2); ObjectSetInteger(0, entLineN, OBJPROP_RAY_RIGHT, true);
|
||||
ObjectMove(0, entLineN, 0, tStart, entry); ObjectMove(0, entLineN, 1, tEnd, entry);
|
||||
if (ObjectFind(0, entLineN) < 0)
|
||||
ObjectCreate(0, entLineN, OBJ_TREND, 0, tStart, entry, tEnd, entry);
|
||||
ObjectSetInteger(0, entLineN, OBJPROP_COLOR, entryClr);
|
||||
ObjectSetInteger(0, entLineN, OBJPROP_STYLE, STYLE_SOLID);
|
||||
ObjectSetInteger(0, entLineN, OBJPROP_WIDTH, 2);
|
||||
ObjectSetInteger(0, entLineN, OBJPROP_RAY_RIGHT, true);
|
||||
ObjectMove(0, entLineN, 0, tStart, entry);
|
||||
ObjectMove(0, entLineN, 1, tEnd, entry);
|
||||
|
||||
if (ObjectFind(0, tpLineN) < 0) ObjectCreate(0, tpLineN, OBJ_TREND, 0, tStart, tp, tEnd, tp);
|
||||
ObjectSetInteger(0, tpLineN, OBJPROP_COLOR, tpClr); ObjectSetInteger(0, tpLineN, OBJPROP_STYLE, STYLE_DASH);
|
||||
ObjectSetInteger(0, tpLineN, OBJPROP_WIDTH, 1); ObjectSetInteger(0, tpLineN, OBJPROP_RAY_RIGHT, true);
|
||||
ObjectMove(0, tpLineN, 0, tStart, tp); ObjectMove(0, tpLineN, 1, tEnd, tp);
|
||||
if (ObjectFind(0, tpLineN) < 0)
|
||||
ObjectCreate(0, tpLineN, OBJ_TREND, 0, tStart, tp, tEnd, tp);
|
||||
ObjectSetInteger(0, tpLineN, OBJPROP_COLOR, tpClr);
|
||||
ObjectSetInteger(0, tpLineN, OBJPROP_STYLE, STYLE_DASH);
|
||||
ObjectSetInteger(0, tpLineN, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(0, tpLineN, OBJPROP_RAY_RIGHT, true);
|
||||
ObjectMove(0, tpLineN, 0, tStart, tp);
|
||||
ObjectMove(0, tpLineN, 1, tEnd, tp);
|
||||
|
||||
if (ObjectFind(0, slLineN) < 0) ObjectCreate(0, slLineN, OBJ_TREND, 0, tStart, sl, tEnd, sl);
|
||||
ObjectSetInteger(0, slLineN, OBJPROP_COLOR, slClr); ObjectSetInteger(0, slLineN, OBJPROP_STYLE, STYLE_DASH);
|
||||
ObjectSetInteger(0, slLineN, OBJPROP_WIDTH, 1); ObjectSetInteger(0, slLineN, OBJPROP_RAY_RIGHT, true);
|
||||
ObjectMove(0, slLineN, 0, tStart, sl); ObjectMove(0, slLineN, 1, tEnd, sl);
|
||||
if (ObjectFind(0, slLineN) < 0)
|
||||
ObjectCreate(0, slLineN, OBJ_TREND, 0, tStart, sl, tEnd, sl);
|
||||
ObjectSetInteger(0, slLineN, OBJPROP_COLOR, slClr);
|
||||
ObjectSetInteger(0, slLineN, OBJPROP_STYLE, STYLE_DASH);
|
||||
ObjectSetInteger(0, slLineN, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(0, slLineN, OBJPROP_RAY_RIGHT, true);
|
||||
ObjectMove(0, slLineN, 0, tStart, sl);
|
||||
ObjectMove(0, slLineN, 1, tEnd, sl);
|
||||
|
||||
datetime lblT = tEnd;
|
||||
|
||||
string eTxt = StringFormat("%s %s | %.2f lot", isBuy?"▶ BUY LIM":"▶ SELL LIM", DoubleToString(entry,_Digits), g_OrderPlan.lot);
|
||||
if (ObjectFind(0, entLblN) < 0) ObjectCreate(0, entLblN, OBJ_TEXT, 0, lblT, entry);
|
||||
ObjectMove(0, entLblN, 0, lblT, entry); ObjectSetString(0, entLblN, OBJPROP_TEXT, eTxt);
|
||||
ObjectSetInteger(0, entLblN, OBJPROP_COLOR, entryClr); ObjectSetInteger(0, entLblN, OBJPROP_FONTSIZE, 8);
|
||||
string eTxt = StringFormat(
|
||||
"%s %s | %.2f lot",
|
||||
isBuy ? "▶ BUY LIM" : "▶ SELL LIM",
|
||||
DoubleToString(entry, _Digits),
|
||||
g_OrderPlan.lot
|
||||
);
|
||||
if (ObjectFind(0, entLblN) < 0)
|
||||
ObjectCreate(0, entLblN, OBJ_TEXT, 0, lblT, entry);
|
||||
ObjectMove(0, entLblN, 0, lblT, entry);
|
||||
ObjectSetString(0, entLblN, OBJPROP_TEXT, eTxt);
|
||||
ObjectSetInteger(0, entLblN, OBJPROP_COLOR, entryClr);
|
||||
ObjectSetInteger(0, entLblN, OBJPROP_FONTSIZE, 8);
|
||||
ObjectSetInteger(0, entLblN, OBJPROP_ANCHOR, ANCHOR_LEFT);
|
||||
|
||||
string tTxt = StringFormat("◎ TP %s +%.0fp (%.1fR)", DoubleToString(tp,_Digits), tpPips, rr);
|
||||
if (ObjectFind(0, tpLblN) < 0) ObjectCreate(0, tpLblN, OBJ_TEXT, 0, lblT, tp);
|
||||
ObjectMove(0, tpLblN, 0, lblT, tp); ObjectSetString(0, tpLblN, OBJPROP_TEXT, tTxt);
|
||||
ObjectSetInteger(0, tpLblN, OBJPROP_COLOR, tpClr); ObjectSetInteger(0, tpLblN, OBJPROP_FONTSIZE, 8);
|
||||
ObjectSetInteger(0, tpLblN, OBJPROP_ANCHOR, isBuy?ANCHOR_LEFT_LOWER:ANCHOR_LEFT_UPPER);
|
||||
string tTxt = StringFormat(
|
||||
"◎ TP %s +%.0fp (%.1fR)",
|
||||
DoubleToString(tp, _Digits),
|
||||
tpPips,
|
||||
rr
|
||||
);
|
||||
if (ObjectFind(0, tpLblN) < 0)
|
||||
ObjectCreate(0, tpLblN, OBJ_TEXT, 0, lblT, tp);
|
||||
ObjectMove(0, tpLblN, 0, lblT, tp);
|
||||
ObjectSetString(0, tpLblN, OBJPROP_TEXT, tTxt);
|
||||
ObjectSetInteger(0, tpLblN, OBJPROP_COLOR, tpClr);
|
||||
ObjectSetInteger(0, tpLblN, OBJPROP_FONTSIZE, 8);
|
||||
ObjectSetInteger(
|
||||
0,
|
||||
tpLblN,
|
||||
OBJPROP_ANCHOR,
|
||||
isBuy ? ANCHOR_LEFT_LOWER : ANCHOR_LEFT_UPPER
|
||||
);
|
||||
|
||||
string sTxt = StringFormat("✕ SL %s -%.0fp", DoubleToString(sl,_Digits), slPips);
|
||||
if (ObjectFind(0, slLblN) < 0) ObjectCreate(0, slLblN, OBJ_TEXT, 0, lblT, sl);
|
||||
ObjectMove(0, slLblN, 0, lblT, sl); ObjectSetString(0, slLblN, OBJPROP_TEXT, sTxt);
|
||||
ObjectSetInteger(0, slLblN, OBJPROP_COLOR, slClr); ObjectSetInteger(0, slLblN, OBJPROP_FONTSIZE, 8);
|
||||
ObjectSetInteger(0, slLblN, OBJPROP_ANCHOR, isBuy?ANCHOR_LEFT_UPPER:ANCHOR_LEFT_LOWER);
|
||||
string sTxt = StringFormat(
|
||||
"✕ SL %s -%.0fp",
|
||||
DoubleToString(sl, _Digits),
|
||||
slPips
|
||||
);
|
||||
if (ObjectFind(0, slLblN) < 0)
|
||||
ObjectCreate(0, slLblN, OBJ_TEXT, 0, lblT, sl);
|
||||
ObjectMove(0, slLblN, 0, lblT, sl);
|
||||
ObjectSetString(0, slLblN, OBJPROP_TEXT, sTxt);
|
||||
ObjectSetInteger(0, slLblN, OBJPROP_COLOR, slClr);
|
||||
ObjectSetInteger(0, slLblN, OBJPROP_FONTSIZE, 8);
|
||||
ObjectSetInteger(
|
||||
0,
|
||||
slLblN,
|
||||
OBJPROP_ANCHOR,
|
||||
isBuy ? ANCHOR_LEFT_UPPER : ANCHOR_LEFT_LOWER
|
||||
);
|
||||
|
||||
string iTxt = StringFormat("Risk %.1f%% | %.0f:%.0f pips | %.1fR", InpRiskPercent, slPips, tpPips, rr);
|
||||
if (ObjectFind(0, infoLblN) < 0) ObjectCreate(0, infoLblN, OBJ_TEXT, 0, lblT, (entry+sl)/2.0);
|
||||
ObjectMove(0, infoLblN, 0, lblT, (entry+sl)/2.0); ObjectSetString(0, infoLblN, OBJPROP_TEXT, iTxt);
|
||||
ObjectSetInteger(0, infoLblN, OBJPROP_COLOR, C'160,160,160'); ObjectSetInteger(0, infoLblN, OBJPROP_FONTSIZE, 7);
|
||||
ObjectSetInteger(0, infoLblN, OBJPROP_ANCHOR, ANCHOR_LEFT);
|
||||
string iTxt = StringFormat(
|
||||
"Risk %.1f%% | %.0f:%.0f pips | %.1fR",
|
||||
InpRiskPercent,
|
||||
slPips,
|
||||
tpPips,
|
||||
rr
|
||||
);
|
||||
if (ObjectFind(0, infoLblN) < 0)
|
||||
ObjectCreate(
|
||||
0,
|
||||
infoLblN,
|
||||
OBJ_TEXT,
|
||||
0,
|
||||
lblT,
|
||||
(entry + sl) / 2.0
|
||||
);
|
||||
ObjectMove(0, infoLblN, 0, lblT, (entry + sl) / 2.0);
|
||||
ObjectSetString(0, infoLblN, OBJPROP_TEXT, iTxt);
|
||||
ObjectSetInteger(0, infoLblN, OBJPROP_COLOR, C'160,160,160');
|
||||
ObjectSetInteger(0, infoLblN, OBJPROP_FONTSIZE, 7);
|
||||
ObjectSetInteger(0, infoLblN, OBJPROP_ANCHOR, ANCHOR_LEFT);
|
||||
}
|
||||
|
||||
/** Draws one FVG record (rectangle + mid line + label) by pool index. */
|
||||
@@ -267,18 +379,51 @@ inline void DrawOneFVGRecord(int idx)
|
||||
else fillColor = C'50,50,50';
|
||||
|
||||
if (ObjectFind(0, rectN) < 0)
|
||||
ObjectCreate(0, rectN, OBJ_RECTANGLE, 0, g_FVGPool[idx].createdTime, g_FVGPool[idx].high, rectEnd, g_FVGPool[idx].low);
|
||||
ObjectSetInteger(0, rectN, OBJPROP_COLOR, fillColor); ObjectSetInteger(0, rectN, OBJPROP_FILL, true);
|
||||
ObjectSetInteger(0, rectN, OBJPROP_BACK, true);
|
||||
ObjectMove(0, rectN, 0, g_FVGPool[idx].createdTime, g_FVGPool[idx].high);
|
||||
ObjectCreate(
|
||||
0,
|
||||
rectN,
|
||||
OBJ_RECTANGLE,
|
||||
0,
|
||||
g_FVGPool[idx].createdTime,
|
||||
g_FVGPool[idx].high,
|
||||
rectEnd,
|
||||
g_FVGPool[idx].low
|
||||
);
|
||||
ObjectSetInteger(0, rectN, OBJPROP_COLOR, fillColor);
|
||||
ObjectSetInteger(0, rectN, OBJPROP_FILL, true);
|
||||
ObjectSetInteger(0, rectN, OBJPROP_BACK, true);
|
||||
ObjectMove(
|
||||
0,
|
||||
rectN,
|
||||
0,
|
||||
g_FVGPool[idx].createdTime,
|
||||
g_FVGPool[idx].high
|
||||
);
|
||||
ObjectMove(0, rectN, 1, rectEnd, g_FVGPool[idx].low);
|
||||
|
||||
color midColor = (g_FVGPool[idx].status == FVG_USED) ? C'60,60,60' : clrSilver;
|
||||
if (ObjectFind(0, midN) < 0)
|
||||
ObjectCreate(0, midN, OBJ_TREND, 0, g_FVGPool[idx].createdTime, g_FVGPool[idx].mid, rectEnd, g_FVGPool[idx].mid);
|
||||
ObjectSetInteger(0, midN, OBJPROP_COLOR, midColor); ObjectSetInteger(0, midN, OBJPROP_STYLE, STYLE_DOT);
|
||||
ObjectSetInteger(0, midN, OBJPROP_WIDTH, 1); ObjectSetInteger(0, midN, OBJPROP_RAY_RIGHT, false);
|
||||
ObjectMove(0, midN, 0, g_FVGPool[idx].createdTime, g_FVGPool[idx].mid);
|
||||
ObjectCreate(
|
||||
0,
|
||||
midN,
|
||||
OBJ_TREND,
|
||||
0,
|
||||
g_FVGPool[idx].createdTime,
|
||||
g_FVGPool[idx].mid,
|
||||
rectEnd,
|
||||
g_FVGPool[idx].mid
|
||||
);
|
||||
ObjectSetInteger(0, midN, OBJPROP_COLOR, midColor);
|
||||
ObjectSetInteger(0, midN, OBJPROP_STYLE, STYLE_DOT);
|
||||
ObjectSetInteger(0, midN, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(0, midN, OBJPROP_RAY_RIGHT, false);
|
||||
ObjectMove(
|
||||
0,
|
||||
midN,
|
||||
0,
|
||||
g_FVGPool[idx].createdTime,
|
||||
g_FVGPool[idx].mid
|
||||
);
|
||||
ObjectMove(0, midN, 1, rectEnd, g_FVGPool[idx].mid);
|
||||
|
||||
string sym = (g_FVGPool[idx].direction == DIR_UP) ? "▲" : "▼";
|
||||
@@ -289,10 +434,34 @@ inline void DrawOneFVGRecord(int idx)
|
||||
else if (g_FVGPool[idx].status == FVG_USED) stTxt = " [EXP]";
|
||||
|
||||
if (ObjectFind(0, lblN) < 0)
|
||||
ObjectCreate(0, lblN, OBJ_TEXT, 0, g_FVGPool[idx].createdTime, g_FVGPool[idx].high);
|
||||
ObjectMove(0, lblN, 0, g_FVGPool[idx].createdTime, g_FVGPool[idx].high);
|
||||
ObjectSetString(0, lblN, OBJPROP_TEXT, StringFormat("FVG#%d %s%s", g_FVGPool[idx].id, sym, stTxt));
|
||||
ObjectSetInteger(0, lblN, OBJPROP_COLOR, fillColor); ObjectSetInteger(0, lblN, OBJPROP_FONTSIZE, 8);
|
||||
ObjectCreate(
|
||||
0,
|
||||
lblN,
|
||||
OBJ_TEXT,
|
||||
0,
|
||||
g_FVGPool[idx].createdTime,
|
||||
g_FVGPool[idx].high
|
||||
);
|
||||
ObjectMove(
|
||||
0,
|
||||
lblN,
|
||||
0,
|
||||
g_FVGPool[idx].createdTime,
|
||||
g_FVGPool[idx].high
|
||||
);
|
||||
ObjectSetString(
|
||||
0,
|
||||
lblN,
|
||||
OBJPROP_TEXT,
|
||||
StringFormat(
|
||||
"FVG#%d %s%s",
|
||||
g_FVGPool[idx].id,
|
||||
sym,
|
||||
stTxt
|
||||
)
|
||||
);
|
||||
ObjectSetInteger(0, lblN, OBJPROP_COLOR, fillColor);
|
||||
ObjectSetInteger(0, lblN, OBJPROP_FONTSIZE, 8);
|
||||
ObjectSetInteger(0, lblN, OBJPROP_ANCHOR, ANCHOR_LEFT_LOWER);
|
||||
}
|
||||
|
||||
@@ -308,71 +477,177 @@ inline void DrawContextDebug()
|
||||
{
|
||||
if (!InpDebugDraw) return;
|
||||
|
||||
#define LBL(name,txt,y,clr) \
|
||||
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, 10); \
|
||||
ObjectSetInteger(0,name,OBJPROP_YDISTANCE, y); \
|
||||
ObjectSetInteger(0,name,OBJPROP_FONTSIZE, 9); \
|
||||
ObjectSetInteger(0,name,OBJPROP_COLOR, clr); \
|
||||
ObjectSetString (0,name,OBJPROP_TEXT, txt);
|
||||
#define LBL(name,txt,y,clr) \
|
||||
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, 10); \
|
||||
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y); \
|
||||
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9); \
|
||||
ObjectSetInteger(0, name, OBJPROP_COLOR, clr); \
|
||||
ObjectSetString (0, name, OBJPROP_TEXT, txt);
|
||||
|
||||
LBL(PREFIX_DEBUG_PANEL + "HDR", "── ICT EA v4.3 ──", 10, clrSilver)
|
||||
|
||||
color cB = (g_Bias.bias==BIAS_UP)?clrLime:(g_Bias.bias==BIAS_DOWN)?clrTomato:(g_Bias.bias==BIAS_SIDEWAY)?clrOrange:clrGray;
|
||||
LBL(PREFIX_DEBUG_PANEL + "BIAS", StringFormat("Bias : %s", EnumToString(g_Bias.bias)), 34, cB)
|
||||
color cB = (g_Bias.bias == BIAS_UP)
|
||||
? clrLime
|
||||
: (g_Bias.bias == BIAS_DOWN)
|
||||
? clrTomato
|
||||
: (g_Bias.bias == BIAS_SIDEWAY) ? clrOrange : clrGray;
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "BIAS",
|
||||
StringFormat("Bias : %s", EnumToString(g_Bias.bias)),
|
||||
34,
|
||||
cB
|
||||
)
|
||||
|
||||
color cMT = (g_MiddleTrend.trend==DIR_UP)?clrLime:(g_MiddleTrend.trend==DIR_DOWN)?clrTomato:clrGray;
|
||||
LBL(PREFIX_DEBUG_PANEL + "MT", StringFormat("H1 : %s KL=%.5f", EnumToString(g_MiddleTrend.trend), g_MiddleTrend.keyLevel), 58, cMT)
|
||||
color cMT = (g_MiddleTrend.trend == DIR_UP)
|
||||
? clrLime
|
||||
: (g_MiddleTrend.trend == DIR_DOWN) ? clrTomato : clrGray;
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "MT",
|
||||
StringFormat(
|
||||
"H1 : %s KL=%.5f",
|
||||
EnumToString(g_MiddleTrend.trend),
|
||||
g_MiddleTrend.keyLevel
|
||||
),
|
||||
58,
|
||||
cMT
|
||||
)
|
||||
|
||||
color cTT = (g_TriggerTrend.trend==DIR_UP)?clrLime:(g_TriggerTrend.trend==DIR_DOWN)?clrTomato:clrGray;
|
||||
LBL(PREFIX_DEBUG_PANEL + "TT", StringFormat("M5 : %s KL=%.5f", EnumToString(g_TriggerTrend.trend), g_TriggerTrend.keyLevel), 82, cTT)
|
||||
color cTT = (g_TriggerTrend.trend == DIR_UP)
|
||||
? clrLime
|
||||
: (g_TriggerTrend.trend == DIR_DOWN) ? clrTomato : clrGray;
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "TT",
|
||||
StringFormat(
|
||||
"M5 : %s KL=%.5f",
|
||||
EnumToString(g_TriggerTrend.trend),
|
||||
g_TriggerTrend.keyLevel
|
||||
),
|
||||
82,
|
||||
cTT
|
||||
)
|
||||
|
||||
if (g_ActiveFVGIdx >= 0 && g_ActiveFVGIdx < g_FVGCount
|
||||
&& g_FVGPool[g_ActiveFVGIdx].usedCase == 2
|
||||
&& g_FVGPool[g_ActiveFVGIdx].mssTime > 0)
|
||||
{
|
||||
int ai = g_ActiveFVGIdx;
|
||||
color cM = (g_FVGPool[ai].direction==DIR_UP)?clrLime:clrTomato;
|
||||
LBL(PREFIX_DEBUG_PANEL + "MSS", StringFormat("MSS : %s entry=%.5f SL=%.5f @ %s (FVG#%d)",
|
||||
(g_FVGPool[ai].direction==DIR_UP)?"▲":"▼",
|
||||
g_FVGPool[ai].mssEntry, g_FVGPool[ai].mssSL,
|
||||
TimeToString(g_FVGPool[ai].mssTime, TIME_MINUTES),
|
||||
g_FVGPool[ai].id), 106, cM)
|
||||
color cM = (g_FVGPool[ai].direction == DIR_UP) ? clrLime : clrTomato;
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "MSS",
|
||||
StringFormat(
|
||||
"MSS : %s entry=%.5f SL=%.5f @ %s (FVG#%d)",
|
||||
(g_FVGPool[ai].direction == DIR_UP) ? "▲" : "▼",
|
||||
g_FVGPool[ai].mssEntry,
|
||||
g_FVGPool[ai].mssSL,
|
||||
TimeToString(g_FVGPool[ai].mssTime, TIME_MINUTES),
|
||||
g_FVGPool[ai].id
|
||||
),
|
||||
106,
|
||||
cM
|
||||
)
|
||||
}
|
||||
else ObjectDelete(0, PREFIX_DEBUG_PANEL + "MSS");
|
||||
|
||||
double lostPct = g_DailyRisk.startBalance > 0
|
||||
? (g_DailyRisk.startBalance - g_DailyRisk.currentBalance) / g_DailyRisk.startBalance * 100.0 : 0.0;
|
||||
color cR = g_DailyRisk.limitHit?clrRed:(lostPct>InpMaxDailyLossPct*0.7?clrOrange:clrLime);
|
||||
LBL(PREFIX_DEBUG_PANEL + "RISK", StringFormat("Risk : %.2f%% / %.2f%%", lostPct, InpMaxDailyLossPct), 130, cR)
|
||||
double lostPct = (g_DailyRisk.startBalance > 0)
|
||||
? (g_DailyRisk.startBalance - g_DailyRisk.currentBalance)
|
||||
/ g_DailyRisk.startBalance * 100.0
|
||||
: 0.0;
|
||||
color cR = g_DailyRisk.limitHit
|
||||
? clrRed
|
||||
: (lostPct > InpMaxDailyLossPct * 0.7) ? clrOrange : clrLime;
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "RISK",
|
||||
StringFormat("Risk : %.2f%% / %.2f%%", lostPct, InpMaxDailyLossPct),
|
||||
130,
|
||||
cR
|
||||
)
|
||||
|
||||
color cS = (g_State==EA_IDLE)?clrSilver:(g_State==EA_WAIT_TOUCH)?clrOrange:(g_State==EA_WAIT_TRIGGER)?clrYellow:clrLime;
|
||||
LBL(PREFIX_DEBUG_PANEL + "ST", StringFormat("State: %s", EnumToString(g_State)), 154, cS)
|
||||
color cS = (g_State == EA_IDLE)
|
||||
? clrSilver
|
||||
: (g_State == EA_WAIT_TOUCH)
|
||||
? clrOrange
|
||||
: (g_State == EA_WAIT_TRIGGER) ? clrYellow : clrLime;
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "ST",
|
||||
StringFormat("State: %s", EnumToString(g_State)),
|
||||
154,
|
||||
cS
|
||||
)
|
||||
|
||||
if (g_BlockReason != BLOCK_NONE)
|
||||
{ LBL(PREFIX_DEBUG_PANEL + "BLK", StringFormat("Block: %s", EnumToString(g_BlockReason)), 178, clrTomato) }
|
||||
{
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "BLK",
|
||||
StringFormat("Block: %s", EnumToString(g_BlockReason)),
|
||||
178,
|
||||
clrTomato
|
||||
)
|
||||
}
|
||||
else ObjectDelete(0, PREFIX_DEBUG_PANEL + "BLK");
|
||||
|
||||
int countPending = 0, countTouched = 0, countUsed = 0;
|
||||
int countPending = 0;
|
||||
int countTouched = 0;
|
||||
int countUsed = 0;
|
||||
for (int i = 0; i < g_FVGCount; i++)
|
||||
{ if (g_FVGPool[i].status == FVG_PENDING) countPending++; else if (g_FVGPool[i].status == FVG_TOUCHED) countTouched++; else countUsed++; }
|
||||
LBL(PREFIX_DEBUG_PANEL + "POOL", StringFormat("Pool : P=%d T=%d U=%d (%d/%d)", countPending, countTouched, countUsed, g_FVGCount, MAX_FVG_POOL), 202, clrDodgerBlue)
|
||||
{
|
||||
if (g_FVGPool[i].status == FVG_PENDING)
|
||||
countPending++;
|
||||
else if (g_FVGPool[i].status == FVG_TOUCHED)
|
||||
countTouched++;
|
||||
else
|
||||
countUsed++;
|
||||
}
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "POOL",
|
||||
StringFormat(
|
||||
"Pool : P=%d T=%d U=%d (%d/%d)",
|
||||
countPending,
|
||||
countTouched,
|
||||
countUsed,
|
||||
g_FVGCount,
|
||||
MAX_FVG_POOL
|
||||
),
|
||||
202,
|
||||
clrDodgerBlue
|
||||
)
|
||||
|
||||
if (g_ActiveFVGIdx >= 0 && g_ActiveFVGIdx < g_FVGCount)
|
||||
{
|
||||
int ai = g_ActiveFVGIdx;
|
||||
LBL(PREFIX_DEBUG_PANEL + "ACT", StringFormat("Act : #%d %s [%.5f–%.5f] %s",
|
||||
g_FVGPool[ai].id, EnumToString(g_FVGPool[ai].direction),
|
||||
g_FVGPool[ai].low, g_FVGPool[ai].high, EnumToString(g_FVGPool[ai].status)), 226, clrDeepSkyBlue)
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "ACT",
|
||||
StringFormat(
|
||||
"Act : #%d %s [%.5f–%.5f] %s",
|
||||
g_FVGPool[ai].id,
|
||||
EnumToString(g_FVGPool[ai].direction),
|
||||
g_FVGPool[ai].low,
|
||||
g_FVGPool[ai].high,
|
||||
EnumToString(g_FVGPool[ai].status)
|
||||
),
|
||||
226,
|
||||
clrDeepSkyBlue
|
||||
)
|
||||
}
|
||||
else ObjectDelete(0, PREFIX_DEBUG_PANEL + "ACT");
|
||||
|
||||
if (g_PendingTicket > 0 && g_OrderPlan.valid)
|
||||
{
|
||||
LBL(PREFIX_DEBUG_PANEL + "ORD", StringFormat("Order: %s #%llu @ %.5f SL=%.5f TP=%.5f",
|
||||
(g_OrderPlan.direction>0)?"BUY":"SELL", g_PendingTicket,
|
||||
g_OrderPlan.entry, g_OrderPlan.stopLoss, g_OrderPlan.takeProfit), 250, clrGold)
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "ORD",
|
||||
StringFormat(
|
||||
"Order: %s #%llu @ %.5f SL=%.5f TP=%.5f",
|
||||
(g_OrderPlan.direction > 0) ? "BUY" : "SELL",
|
||||
g_PendingTicket,
|
||||
g_OrderPlan.entry,
|
||||
g_OrderPlan.stopLoss,
|
||||
g_OrderPlan.takeProfit
|
||||
),
|
||||
250,
|
||||
clrGold
|
||||
)
|
||||
}
|
||||
else ObjectDelete(0, PREFIX_DEBUG_PANEL + "ORD");
|
||||
|
||||
@@ -383,12 +658,13 @@ inline void DrawContextDebug()
|
||||
/** Draws all debug visuals: swings, MSS markers, FVG pool, order, debug panel. */
|
||||
inline void DrawVisuals()
|
||||
{
|
||||
DrawContextDebug();
|
||||
return; // TESTING ONLY
|
||||
DrawMiddleSwingPoints();
|
||||
DrawTriggerSwingPoints();
|
||||
DrawMSSMarkers();
|
||||
DrawFVGPool();
|
||||
DrawOrderVisualization();
|
||||
DrawContextDebug();
|
||||
}
|
||||
|
||||
#endif // EA_ICT_CL__DRAWING_MQH
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef EA_ICT_CL__GUARDS_MQH
|
||||
#define EA_ICT_CL__GUARDS_MQH
|
||||
|
||||
/** True if within allowed session (currently always true). */
|
||||
inline bool IsSessionAllowed() { return true; }
|
||||
/** True if daily loss limit has not been hit. */
|
||||
inline bool IsDailyLossOK() { return !g_DailyRisk.limitHit; }
|
||||
|
||||
@@ -1,29 +1,28 @@
|
||||
#ifndef EA_ICT_CL__MARKET_MQH
|
||||
#define EA_ICT_CL__MARKET_MQH // Tránh include trùng
|
||||
#define EA_ICT_CL__MARKET_MQH
|
||||
|
||||
// Module: Market – giá, point, spread, điều kiện trade
|
||||
|
||||
inline double GetBid(const string symbol) { return SymbolInfoDouble(symbol, SYMBOL_BID); } // Giá bid
|
||||
inline double GetAsk(const string symbol) { return SymbolInfoDouble(symbol, SYMBOL_ASK); } // Giá ask
|
||||
inline double GetPoint(const string symbol) { return SymbolInfoDouble(symbol, SYMBOL_POINT); } // Kích thước 1 point
|
||||
inline int GetDigits(const string symbol) { return (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); } // Số chữ số thập phân
|
||||
inline double GetBid(const string symbol) { return SymbolInfoDouble(symbol, SYMBOL_BID); }
|
||||
inline double GetAsk(const string symbol) { return SymbolInfoDouble(symbol, SYMBOL_ASK); }
|
||||
inline double GetPoint(const string symbol) { return SymbolInfoDouble(symbol, SYMBOL_POINT); }
|
||||
inline int GetDigits(const string symbol) { return (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); }
|
||||
|
||||
/** Returns spread in points (ask - bid) / point. */
|
||||
inline double GetSpreadPoints(const string symbol)
|
||||
{
|
||||
const double bid = GetBid(symbol); // Lấy bid
|
||||
const double ask = GetAsk(symbol); // Lấy ask
|
||||
const double pt = GetPoint(symbol); // Lấy point
|
||||
if (pt <= 0.0) return 0.0; // Tránh chia 0
|
||||
return (ask - bid) / pt; // Spread quy đổi ra số point
|
||||
const double bid = GetBid(symbol);
|
||||
const double ask = GetAsk(symbol);
|
||||
const double pointSize = GetPoint(symbol);
|
||||
if (pointSize <= 0.0) return 0.0;
|
||||
return (ask - bid) / pointSize;
|
||||
}
|
||||
|
||||
/** True if terminal, EA and symbol allow trading. */
|
||||
inline bool IsTradeAllowedNow(const string symbol)
|
||||
{
|
||||
if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) return false; // Terminal có cho trade không
|
||||
if (!MQLInfoInteger(MQL_TRADE_ALLOWED)) return false; // EA có quyền trade không
|
||||
if (!SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE)) return false; // Symbol có cho trade không
|
||||
return true; // Đủ điều kiện
|
||||
if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) return false;
|
||||
if (!MQLInfoInteger(MQL_TRADE_ALLOWED)) return false;
|
||||
if (!SymbolInfoInteger(symbol, SYMBOL_TRADE_MODE)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // EA_ICT_CL__MARKET_MQH
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,9 +20,8 @@ inline double LotsFromRiskMoneyAndSLPoints(const string symbol, const double ris
|
||||
if (riskMoney <= 0.0) return 0.0;
|
||||
if (slPoints <= 0.0) return 0.0;
|
||||
|
||||
double tickValue = 0.0, tickSize = 0.0;
|
||||
if (!SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE, tickValue)) return 0.0;
|
||||
if (!SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE, tickSize)) return 0.0;
|
||||
double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
|
||||
double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
|
||||
if (tickValue <= 0.0 || tickSize <= 0.0) return 0.0;
|
||||
|
||||
const double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
||||
|
||||
+38
-39
@@ -1,76 +1,75 @@
|
||||
#ifndef EA_ICT_CL__SWING_MQH
|
||||
#define EA_ICT_CL__SWING_MQH // Tránh include trùng
|
||||
#define EA_ICT_CL__SWING_MQH
|
||||
|
||||
// Module: Swing – tìm bar shift theo time, swing high/low, quét cấu trúc swing, suy trend
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| MyBarShift: tìm chỉ số bar (series) ứng với thời gian time |
|
||||
//+------------------------------------------------------------------+
|
||||
/** Returns bar index (series) for given time; -1 if not found or exact and no match. */
|
||||
inline int MyBarShift(string symbol, ENUM_TIMEFRAMES tf, datetime time, bool exact = false)
|
||||
{
|
||||
datetime arr[];
|
||||
int maxCopy = MathMin(Bars(symbol, tf), 5000); // Giới hạn copy
|
||||
int copied = CopyTime(symbol, tf, 0, maxCopy, arr);
|
||||
if (copied <= 0) return -1;
|
||||
int maxBarsToCopy = MathMin(Bars(symbol, tf), 5000);
|
||||
int copiedCount = CopyTime(symbol, tf, 0, maxBarsToCopy, arr);
|
||||
if (copiedCount <= 0) return -1;
|
||||
|
||||
for (int i = copied - 1; i >= 0; i--) // Duyệt từ bar cũ → mới
|
||||
for (int i = copiedCount - 1; i >= 0; i--)
|
||||
{
|
||||
if (arr[i] <= time)
|
||||
return copied - 1 - i; // Index trong series (0 = mới nhất)
|
||||
return copiedCount - 1 - i;
|
||||
}
|
||||
return exact ? -1 : copied - 1; // exact: không tìm thấy = -1; không exact: trả về bar xa nhất
|
||||
return exact ? -1 : copiedCount - 1;
|
||||
}
|
||||
|
||||
inline bool IsSwingHighAt(ENUM_TIMEFRAMES tf, int i)
|
||||
/** True if bar at index i is a swing high (InpSwingRange bars each side lower). */
|
||||
inline bool IsSwingHighAt(ENUM_TIMEFRAMES tf, int barIndex)
|
||||
{
|
||||
double p = iHigh(_Symbol, tf, i); // High tại bar i
|
||||
for (int k = 1; k <= InpSwingRange; k++) // So với InpSwingRange bar mỗi bên
|
||||
if (iHigh(_Symbol, tf, i-k) >= p || iHigh(_Symbol, tf, i+k) >= p) return false; // Có high cao hơn → không phải swing high
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool IsSwingLowAt(ENUM_TIMEFRAMES tf, int i)
|
||||
{
|
||||
double p = iLow(_Symbol, tf, i);
|
||||
double highAtBar = iHigh(_Symbol, tf, barIndex);
|
||||
for (int k = 1; k <= InpSwingRange; k++)
|
||||
if (iLow(_Symbol, tf, i-k) <= p || iLow(_Symbol, tf, i+k) <= p) return false;
|
||||
if (iHigh(_Symbol, tf, barIndex - k) >= highAtBar || iHigh(_Symbol, tf, barIndex + k) >= highAtBar) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** True if bar at index i is a swing low (InpSwingRange bars each side higher). */
|
||||
inline bool IsSwingLowAt(ENUM_TIMEFRAMES tf, int barIndex)
|
||||
{
|
||||
double lowAtBar = iLow(_Symbol, tf, barIndex);
|
||||
for (int k = 1; k <= InpSwingRange; k++)
|
||||
if (iLow(_Symbol, tf, barIndex - k) <= lowAtBar || iLow(_Symbol, tf, barIndex + k) <= lowAtBar) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Scans for two most recent swing highs and two most recent swing lows; fills out params, returns true if all found. */
|
||||
inline bool ScanSwingStructure(
|
||||
ENUM_TIMEFRAMES tf, int lookback,
|
||||
double &h0, double &h1, int &idxH0, int &idxH1,
|
||||
double &l0, double &l1, int &idxL0, int &idxL1)
|
||||
{
|
||||
int maxBar = MathMin(lookback, Bars(_Symbol, tf) - InpSwingRange - 2); // Giới hạn quét
|
||||
double highs[2]; int hiIdx[2]; int hc = 0; // 2 swing high gần nhất
|
||||
double lows [2]; int loIdx[2]; int lc = 0; // 2 swing low gần nhất
|
||||
int maxBar = MathMin(lookback, Bars(_Symbol, tf) - InpSwingRange - 2);
|
||||
double highs[2]; int hiIdx[2]; int highCount = 0;
|
||||
double lows [2]; int loIdx[2]; int lowCount = 0;
|
||||
|
||||
for (int i = InpSwingRange + 1; i <= maxBar; i++) // Từ bar gần hiện tại trở lại
|
||||
for (int i = InpSwingRange + 1; i <= maxBar; i++)
|
||||
{
|
||||
if (hc < 2 && IsSwingHighAt(tf, i)) { highs[hc] = iHigh(_Symbol, tf, i); hiIdx[hc] = i; hc++; }
|
||||
if (lc < 2 && IsSwingLowAt (tf, i)) { lows [lc] = iLow (_Symbol, tf, i); loIdx[lc] = i; lc++; }
|
||||
if (hc == 2 && lc == 2) break; // Đủ 2 high + 2 low thì dừng
|
||||
if (highCount < 2 && IsSwingHighAt(tf, i)) { highs[highCount] = iHigh(_Symbol, tf, i); hiIdx[highCount] = i; highCount++; }
|
||||
if (lowCount < 2 && IsSwingLowAt (tf, i)) { lows [lowCount] = iLow (_Symbol, tf, i); loIdx[lowCount] = i; lowCount++; }
|
||||
if (highCount == 2 && lowCount == 2) break;
|
||||
}
|
||||
if (hc < 2 || lc < 2) return false; // Không đủ swing
|
||||
if (highCount < 2 || lowCount < 2) return false;
|
||||
|
||||
h0 = highs[0]; idxH0 = hiIdx[0]; // h0 = swing high gần nhất (index nhỏ)
|
||||
h1 = highs[1]; idxH1 = hiIdx[1]; // h1 = swing high cũ hơn
|
||||
h0 = highs[0]; idxH0 = hiIdx[0];
|
||||
h1 = highs[1]; idxH1 = hiIdx[1];
|
||||
l0 = lows [0]; idxL0 = loIdx[0];
|
||||
l1 = lows [1]; idxL1 = loIdx[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Resolves trend and key level from swing highs/lows and last close. */
|
||||
inline void ResolveTrendFromSwings(
|
||||
ENUM_TIMEFRAMES tf,
|
||||
double h0, double h1, double l0, double l1,
|
||||
MarketDir &trend, double &keyLevel)
|
||||
{
|
||||
double c1 = iClose(_Symbol, tf, 1); // Close bar 1 (gần nhất đã đóng)
|
||||
if (h0 > h1 && l0 > l1 && c1 > l0) { trend = DIR_UP; keyLevel = l0; } // HH + HL, giá trên L0 → uptrend
|
||||
else if (h0 < h1 && l0 < l1 && c1 < h0) { trend = DIR_DOWN; keyLevel = h0; } // LH + LL, giá dưới H0 → downtrend
|
||||
else { trend = DIR_NONE; keyLevel = 0; } // Không rõ
|
||||
double lastClose = iClose(_Symbol, tf, 1);
|
||||
if (h0 > h1 && l0 > l1 && lastClose > l0) { trend = DIR_UP; keyLevel = l0; }
|
||||
else if (h0 < h1 && l0 < l1 && lastClose < h0) { trend = DIR_DOWN; keyLevel = h0; }
|
||||
else { trend = DIR_NONE; keyLevel = 0; }
|
||||
}
|
||||
|
||||
#endif // EA_ICT_CL__SWING_MQH
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user