Files
2026-05-27 03:18:59 +07:00

160 lines
5.9 KiB
Plaintext

//+------------------------------------------------------------------+
//| Draw.mqh — swing labels trên chart (adaptive theo chart TF) |
//+------------------------------------------------------------------+
//| Vẽ 3 lớp swing labels, tự động ẩn lớp có TF nhỏ hơn chart hiện |
//| tại để không bị nhiễu: |
//| |
//| Chart TF | Vẽ |
//| --------------+-------------------------------------------------|
//| ≥ InpBiasTf | bH0, bH1, bL0, bL1 |
//| ≥ InpIntra | + iH0, iH1, iL0, iL1 |
//| ≥ InpConfirm | + H0, H1, L0, L1 (Confirm TF swing) |
//| |
//| Bật/tắt từng lớp: |
//| InpDrawBiasSwingLabels |
//| InpDrawIntraSwingLabels |
//| InpDrawConfirmLabels |
//| |
//| So sánh: PeriodSeconds(chart) vs PeriodSeconds(InpXxxTf). |
//| |
//| Skip nếu: InpOnlyStatsMode = true |
//| |
//| Object prefix: ICT26_DR_ |
//| |
//| Public API: |
//| void IctDraw_Render(sym) |
//| void IctDraw_DeleteAll() |
//+------------------------------------------------------------------+
#ifndef ICT2026_DRAW_MQH
#define ICT2026_DRAW_MQH
#include <ICT2026/Config.mqh>
#include <ICT2026/Swing.mqh>
#include <ICT2026/IntradayStructure.mqh>
const string ICT26_DRAW_PFX = "ICT26_DR_";
int IctDraw_ChartPeriodSeconds()
{
return (int)PeriodSeconds((ENUM_TIMEFRAMES)_Period);
}
// Chỉ vẽ swing TF hiện tại + TF lớn hơn; ẩn swing TF nhỏ hơn chart
void IctDraw_ResolveSwingVisibility(bool &showBias, bool &showIntra, bool &showConfirm)
{
showBias = false;
showIntra = false;
showConfirm = false;
const int chartSec = IctDraw_ChartPeriodSeconds();
const int biasSec = (int)PeriodSeconds(InpBiasTf);
const int intraSec = (int)PeriodSeconds(InpIntradayTf);
const int confirmSec = (int)PeriodSeconds(InpConfirmTf);
if(chartSec <= 0 || biasSec <= 0 || intraSec <= 0 || confirmSec <= 0)
return;
showConfirm = (chartSec <= confirmSec);
showIntra = (chartSec <= intraSec);
showBias = (chartSec <= biasSec) || (chartSec >= biasSec);
}
void IctDraw_DeleteByPrefix(const string prefix)
{
const long ch = ChartID();
for(int i = ObjectsTotal(ch, 0, -1) - 1; i >= 0; i--)
{
const string name = ObjectName(ch, i, 0, -1);
if(StringFind(name, prefix) == 0)
ObjectDelete(ch, name);
}
}
void IctDraw_Clear()
{
const long ch = ChartID();
IctDraw_DeleteByPrefix(ICT26_DRAW_PFX);
ObjectDelete(ch, ICT26_DRAW_PFX + "TXT_DAILY");
ObjectDelete(ch, ICT26_DRAW_PFX + "TXT_INTRA");
}
void IctDraw_SwingLabel(const string id, const string text,
const datetime t, const double price,
const bool isHigh, const color clr)
{
const long ch = ChartID();
if(ObjectFind(ch, id) < 0)
ObjectCreate(ch, id, OBJ_TEXT, 0, t, price);
ObjectMove(ch, id, 0, t, price);
ObjectSetString(ch, id, OBJPROP_TEXT, text);
ObjectSetInteger(ch, id, OBJPROP_COLOR, clr);
ObjectSetInteger(ch, id, OBJPROP_FONTSIZE, InpChartLabelFontSize);
ObjectSetString(ch, id, OBJPROP_FONT, "Arial Bold");
ObjectSetInteger(ch, id, OBJPROP_ANCHOR, isHigh ? ANCHOR_BOTTOM : ANCHOR_TOP);
ObjectSetInteger(ch, id, OBJPROP_SELECTABLE, false);
}
void IctDraw_SwingSet(const string objPfx, const string tagPfx,
IctSwingSet &sw,
const color clrHi, const color clrLo)
{
if(!sw.IsComplete())
return;
IctDraw_SwingLabel(objPfx + tagPfx + "H0", tagPfx + "H0",
sw.h0.time, sw.h0.price, true, clrHi);
IctDraw_SwingLabel(objPfx + tagPfx + "H1", tagPfx + "H1",
sw.h1.time, sw.h1.price, true, clrHi);
IctDraw_SwingLabel(objPfx + tagPfx + "L0", tagPfx + "L0",
sw.l0.time, sw.l0.price, false, clrLo);
IctDraw_SwingLabel(objPfx + tagPfx + "L1", tagPfx + "L1",
sw.l1.time, sw.l1.price, false, clrLo);
}
bool IctDraw_BuildConfirmSwings(const string sym, IctSwingSet &sw)
{
ENUM_ICT_STRUCT structural = ICT_STRUCT_NONE;
return IctBuildConfirmSwingSet(sym, sw, structural);
}
void IctDraw_Render(const string sym)
{
if(InpOnlyStatsMode)
return;
if(!InpDrawChartLabels)
{
IctDraw_Clear();
return;
}
IctDraw_Clear();
bool showBias = false, showIntra = false, showConfirm = false;
IctDraw_ResolveSwingVisibility(showBias, showIntra, showConfirm);
const string p = ICT26_DRAW_PFX;
if(InpDrawBiasSwingLabels && showBias && g_ictDailyBias.swings.IsComplete())
{
IctSwingSet biasSw = g_ictDailyBias.swings;
IctDraw_SwingSet(p, "b", biasSw, clrGold, clrKhaki);
}
if(InpDrawIntraSwingLabels && showIntra && g_ictIntraday.swings.IsComplete())
{
IctSwingSet intraSw = g_ictIntraday.swings;
IctDraw_SwingSet(p, "i", intraSw, clrDodgerBlue, clrOrange);
}
if(InpDrawConfirmLabels && showConfirm)
{
IctSwingSet confirmSw;
if(IctDraw_BuildConfirmSwings(sym, confirmSw))
IctDraw_SwingSet(p, "", confirmSw, clrLightGreen, clrLightCoral);
}
ChartRedraw();
}
#endif