Optimize code

This commit is contained in:
Bell
2025-12-06 02:54:05 +07:00
parent b732b6161e
commit c168972d73
+79 -126
View File
@@ -7,6 +7,26 @@
#property version "2.00"
#property strict
// Bật/tắt MSS detection cho từng TF
input bool DetectMSS_HTF = true;
input bool DetectMSS_MTF = true;
input bool DetectMSS_LTF = false;
// Cấu hình Swing
input int htfSwingRange = 1; // X: số nến trước và sau để xác định 1 đỉnh/đáy
input int mtfSwingRange = 10; // X: số nến trước và sau để xác định 1 đỉnh/đáy
input int ltfSwingRange = 10; // X: số nến trước và sau để xác định 1 đỉnh/đáy
input int SwingKeep = 2; // Số đỉnh/đáy gần nhất cần lưu (bạn yêu cầu 2)
// Cấu hình vẽ Swing trên chart
input bool ShowSwingMarkers = true; // Hiển thị các marker swing trên chart
input string SwingObjPrefix = "Swing_"; // Tiền tố tên object (dễ xóa/điều chỉnh)
input int SwingMarkerFontSize = 10; // Kích thước font cho label
input int FVGLookback = 200; // Số nến lookback khi tính FVG (dùng ở EnsureFVGUpToDate)
input bool PrintToExperts = true; // In log ra Expert
// --- lưu trend đã tính cho mỗi slot ---
// slot 0 = HTF, 1 = MTF, 2 = LTF
int TrendTF[3]; // 1 = up, -1 = down, 0 = sideway / unknown
@@ -15,20 +35,6 @@ input ENUM_TIMEFRAMES HighTF = PERIOD_D1; // Khung thời gian cao
input ENUM_TIMEFRAMES MiddleTF = PERIOD_H1; // Khung thời gian trung bình (dùng để tìm FVG)
input ENUM_TIMEFRAMES LowTF = PERIOD_M5; // Khung thời gian thấp (Tìm điểm vào lệnh)
input bool PrintToExperts = true; // In log ra Expert
// Cấu hình Swing
input int htfSwingRange = 2; // X: số nến trước và sau để xác định 1 đỉnh/đáy
input int mtfSwingRange = 2; // X: số nến trước và sau để xác định 1 đỉnh/đáy
input int ltfSwingRange = 2; // X: số nến trước và sau để xác định 1 đỉnh/đáy
input int SwingKeep = 2; // Số đỉnh/đáy gần nhất cần lưu (bạn yêu cầu 2)
// Cấu hình vẽ Swing trên chart
input bool ShowSwingMarkers = true; // Hiển thị các marker swing trên chart
input string SwingObjPrefix = "Swing_"; // Tiền tố tên object (dễ xóa/điều chỉnh)
input int SwingMarkerFontSize = 10; // Kích thước font cho label
// --- multi-TF swing storage (slots) ---
// slot 0 = HighTF, slot 1 = MiddleTF, slot 2 = LowTF
// dimension: [slot][index] (index 0 = nearest, 1 = older)
@@ -58,11 +64,6 @@ datetime lastClosedBarTime[3] = {0,0,0};
// cache last FVG compute time (bar C or bar index 1 time used to detect change)
datetime lastFVGBarTime = 0;
// Bật/tắt MSS detection cho từng TF
input bool DetectMSS_HTF = false;
input bool DetectMSS_MTF = false;
input bool DetectMSS_LTF = true;
// struct dùng để trả thông tin khi phát hiện MSS
struct MSSInfo {
bool found; // true nếu tìm thấy MSS
@@ -392,15 +393,15 @@ MSSInfo DetectMSSOnSlot(
// Kiểm tra 1 bar tại index i có phải SwingHigh không (dùng giá đóng cửa theo yêu cầu)
// Kiểm tra 1 bar tại index i có phải SwingHigh không (xét râu - High)
bool IsSwingHigh(string symbol, ENUM_TIMEFRAMES timeframe, int i, int X)
bool IsSwingHigh(string symbol, ENUM_TIMEFRAMES timeframe, int candleIndex, int swingRange)
{
double hi = iHigh(symbol, timeframe, i);
double hi = iHigh(symbol, timeframe, candleIndex);
if(hi == 0.0) return false;
// So sánh với X nến trước (index giảm)
for(int j = 1; j <= X; j++)
for(int i = 1; i <= swingRange; i++)
{
int idxPrev = i - j;
int idxPrev = candleIndex - i;
if(idxPrev < 0) return false; // không đủ dữ liệu
double hprev = iHigh(symbol, timeframe, idxPrev);
if(hprev == 0.0) return false; // dữ liệu thiếu
@@ -409,9 +410,9 @@ bool IsSwingHigh(string symbol, ENUM_TIMEFRAMES timeframe, int i, int X)
}
// So sánh với X nến sau (index tăng)
for(int k = 1; k <= X; k++)
for(int k = 1; k <= swingRange; k++)
{
int idxNext = i + k;
int idxNext = candleIndex + k;
// nếu idxNext vượt quá bars available -> không có dữ liệu đủ -> return false
double hnext = iHigh(symbol, timeframe, idxNext);
if(hnext == 0.0) return false;
@@ -1283,33 +1284,6 @@ void UpdateLabel(string labelName, ENUM_TIMEFRAMES timeframe, int trend)
}
}
int OnInit()
{
// Khởi tạo 3 label cho 3 timeframe
UpdateLabel("LBL_HTF", HighTF, 0);
UpdateLabel("LBL_MTF", MiddleTF, 0);
UpdateLabel("LBL_LTF", LowTF, 0);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
// Xoá 3 label
if(ObjectFind(0, "LBL_HTF") >= 0) ObjectDelete(0, "LBL_HTF");
if(ObjectFind(0, "LBL_MTF") >= 0) ObjectDelete(0, "LBL_MTF");
if(ObjectFind(0, "LBL_LTF") >= 0) ObjectDelete(0, "LBL_LTF");
// Xóa tất cả object dùng tiền tố SwingObjPrefix (bao gồm htf_/mtf_/ltf_ và FVG)
int tot = ObjectsTotal(0);
for(int i = tot - 1; i >= 0; i--)
{
string nm = ObjectName(0, i);
if(StringFind(nm, SwingObjPrefix, 0) == 0)
ObjectDelete(0, nm);
}
}
// Trả true nếu bar đóng mới xuất hiện (dựa vào iTime(...,1))
bool IsNewClosedBar(string symbol, ENUM_TIMEFRAMES tf, int slot)
{
@@ -1338,11 +1312,6 @@ void EnsureFVGUpToDate(string symbol, ENUM_TIMEFRAMES tf, int lookback)
}
}
// ProcessMSSForSlot: hàm chung tách logic MSS cho 1 slot/timeframe
// sym : symbol (Symbol())
// tf : timeframe để check (HighTF/MiddleTF/LowTF)
// slot : index 0=HTF,1=MTF,2=LTF
// enabled : nếu false thì không làm gì
// requireFVG : có cần FVG (true/false) truyền vào DetectMSSOnSlot
// minBreakPips.. : các tham số truyền xuống DetectMSSOnSlot (mặc định hợp lý)
void ProcessMSSForSlot(string sym, ENUM_TIMEFRAMES tf, int slot, bool enabled,
@@ -1354,10 +1323,6 @@ void ProcessMSSForSlot(string sym, ENUM_TIMEFRAMES tf, int slot, bool enabled,
{
if(!enabled) return;
// Nếu là MiddleTF và bạn muốn dùng FVG cache, cập nhật cache trước
if(tf == MiddleTF)
EnsureFVGUpToDate(sym, MiddleTF, fvgLookback);
// Gọi DetectMSSOnSlot với tham số truyền vào
MSSInfo info = DetectMSSOnSlot(sym, tf, slot, minBreakPips, minConsec, lookbackBarsForSweep, fvgLookback, requireFVG);
@@ -1371,78 +1336,66 @@ void ProcessMSSForSlot(string sym, ENUM_TIMEFRAMES tf, int slot, bool enabled,
}
}
void HandleLogicForTimeframe(string sym, ENUM_TIMEFRAMES tf, int slot, bool detectMSS,
int swingRange, bool requireFVG,
double minBreakPips, int minConsec,
int lookbackBarsForSweep, int fvgLookback)
{
UpdateSwings(sym, tf, slot, swingRange);
UpdateTrendForSlot(slot, tf, sym);
if(tf == MiddleTF) EnsureFVGUpToDate(sym, MiddleTF, fvgLookback);
ProcessMSSForSlot(sym, tf, slot, detectMSS, requireFVG, minBreakPips, minConsec, lookbackBarsForSweep, fvgLookback);
if(ShowSwingMarkers)
{
DrawSwingsOnChart(tf);
if(tf == MiddleTF)
DrawFVG(sym, MiddleTF, true);
}
UpdateLabel((tf == HighTF) ? "LBL_HTF" : (tf == MiddleTF) ? "LBL_MTF" : "LBL_LTF", tf, TrendTF[slot]);
}
void OnTick()
{
string sym = Symbol();
// --- 1) Kiểm tra có bar đóng mới (nhưng chưa update swings) ---
bool newHTFCandleClosed = IsNewClosedBar(sym, HighTF, 0);
bool newMTFCandleClosed = IsNewClosedBar(sym, MiddleTF, 1);
bool newLTFCandleClosed = IsNewClosedBar(sym, LowTF, 2);
// Nếu MTF có bar đóng mới, cập nhật cache FVG trước khi detect (Detect có thể require FVG)
if(newMTFCandleClosed)
EnsureFVGUpToDate(sym, MiddleTF, 200);
// --- 2) Chạy MSS detection TRƯỚC khi update swings (dùng swings hiện tại - tức swing "cũ") ---
// HTF
ProcessMSSForSlot(sym, HighTF, 0, DetectMSS_HTF,
/*requireFVG=*/ false,
/*minBreakPips=*/ 10.0,
/*minConsec=*/ 2,
/*lookback=*/ 50,
/*fvgLookback=*/ 200);
//MTF
ProcessMSSForSlot(sym, MiddleTF, 1, DetectMSS_MTF,
/*requireFVG=*/ true,
/*minBreakPips=*/ 10.0,
/*minConsec=*/ 2,
/*lookback=*/ 50,
/*fvgLookback=*/ 200);
// LTF
ProcessMSSForSlot(sym, LowTF, 2, DetectMSS_LTF,
/*requireFVG=*/ true,
/*minBreakPips=*/ 8.0,
/*minConsec=*/ 2,
/*lookback=*/ 30,
/*fvgLookback=*/ 100);
// --- 3) Bây giờ mới update swings & trend cho những TF có bar đóng mới ---
if(newHTFCandleClosed)
{
UpdateSwings(sym, HighTF, 0, htfSwingRange);
UpdateTrendForSlot(0, HighTF, sym);
if(PrintToExperts) PrintFormat("New closed HTF detected at %s", TimeToString(lastClosedBarTime[0], TIME_DATE|TIME_MINUTES));
if(IsNewClosedBar(sym, HighTF, 0)) {
HandleLogicForTimeframe(sym, HighTF, 0, DetectMSS_HTF, htfSwingRange, false, 10.0, 2, 50, FVGLookback);
}
if(newMTFCandleClosed)
{
UpdateSwings(sym, MiddleTF, 1, mtfSwingRange);
UpdateTrendForSlot(1, MiddleTF, sym);
// ensure FVG cache up-to-date (already done above if newMTFCandleClosed)
if(PrintToExperts) PrintFormat("New closed MTF detected at %s", TimeToString(lastClosedBarTime[1], TIME_DATE|TIME_MINUTES));
if(IsNewClosedBar(sym, MiddleTF, 1)) {
HandleLogicForTimeframe(sym, MiddleTF, 1, DetectMSS_MTF, mtfSwingRange, true, 10.0, 2, 50, FVGLookback);
}
if(newLTFCandleClosed)
{
UpdateSwings(sym, LowTF, 2, ltfSwingRange);
UpdateTrendForSlot(2, LowTF, sym);
if(PrintToExperts) PrintFormat("New closed LTF detected at %s", TimeToString(lastClosedBarTime[2], TIME_DATE|TIME_MINUTES));
if(IsNewClosedBar(sym, LowTF, 2)) {
HandleLogicForTimeframe(sym, LowTF, 2, DetectMSS_LTF, ltfSwingRange, false, 10.0, 2, 50, FVGLookback);
}
// --- 4) Vẽ (chỉ khi cần) ---
if(ShowSwingMarkers)
{
DrawSwingsOnChart(HighTF);
// DrawSwingsOnChart(MiddleTF);
// DrawSwingsOnChart(LowTF);
DrawFVG(sym, MiddleTF, true);
}
// --- 5) Update label ---
UpdateLabel("LBL_HTF", HighTF, TrendTF[0]);
UpdateLabel("LBL_MTF", MiddleTF, TrendTF[1]);
UpdateLabel("LBL_LTF", LowTF, TrendTF[2]);
}
int OnInit()
{
string sym = Symbol();
HandleLogicForTimeframe(sym, HighTF, 0, false, htfSwingRange, false, 10.0, 2, 50, FVGLookback);
HandleLogicForTimeframe(sym, MiddleTF, 1, false, mtfSwingRange, true, 10.0, 2, 50, FVGLookback);
HandleLogicForTimeframe(sym, LowTF, 2, false, ltfSwingRange, false, 10.0, 2, 50, FVGLookback);
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
// Xoá 3 label
if(ObjectFind(0, "LBL_HTF") >= 0) ObjectDelete(0, "LBL_HTF");
if(ObjectFind(0, "LBL_MTF") >= 0) ObjectDelete(0, "LBL_MTF");
if(ObjectFind(0, "LBL_LTF") >= 0) ObjectDelete(0, "LBL_LTF");
// Xóa tất cả object dùng tiền tố SwingObjPrefix (bao gồm htf_/mtf_/ltf_ và FVG)
int tot = ObjectsTotal(0);
for(int i = tot - 1; i >= 0; i--)
{
string nm = ObjectName(0, i);
if(StringFind(nm, SwingObjPrefix, 0) == 0)
ObjectDelete(0, nm);
}
}