Init nến m15

This commit is contained in:
Bell
2026-05-16 03:33:17 +07:00
parent 74809e8cef
commit 4058fa21dc
+165
View File
@@ -0,0 +1,165 @@
//+------------------------------------------------------------------+
//| MotherBarBreakout.mq5 |
//| M15: thân nến >= K × TB thân N nến liền trước |
//+------------------------------------------------------------------+
#property copyright "MotherBarBreakout"
#property version "2.01"
#property description "M15 large body: body >= K × average of N prior bodies. Marks on chart."
input ENUM_TIMEFRAMES InpTf = PERIOD_M15;
input int InpAvgPriorBodies = 10; // TB của 10 thân nến liền trước
input double InpBodyVsAvgMult = 3.0; // thân hiện tại >= hệ số này × TB (vd 3 = gấp 3)
input int InpScanBarsOnInit = 300;
input bool InpClearMarksOnInit = true;
input color InpClrBullBar = clrDodgerBlue; // nến tăng (chỉ phân biệt hướng nến, không lọc trend)
input color InpClrBearBar = clrDarkOrange;
input int InpArrowSize = 2;
input int InpArrowOffsetPts = 20;
const string OBJ_PFX = "MBB_";
datetime g_lastBarTime = 0;
//+------------------------------------------------------------------+
double BodyAbs(const string sym, const ENUM_TIMEFRAMES tf, const int sh)
{
return MathAbs(iClose(sym, tf, sh) - iOpen(sym, tf, sh));
}
//+------------------------------------------------------------------+
//| Thân nến sh >= InpBodyVsAvgMult × TB thân sh+1 .. sh+n //
//+------------------------------------------------------------------+
bool IsBodyLargerThanPriorAverage(const string sym, const ENUM_TIMEFRAMES tf,
const int sh, const int nAvg)
{
if(nAvg < 1)
return false;
if(InpBodyVsAvgMult <= 0.0)
return false;
const int need = sh + nAvg + 1;
if(Bars(sym, tf) < need)
return false;
double sum = 0.0;
for(int k = 1; k <= nAvg; k++)
sum += BodyAbs(sym, tf, sh + k);
const double avg = sum / (double)nAvg;
const double body = BodyAbs(sym, tf, sh);
const double threshold = InpBodyVsAvgMult * avg;
return (body >= threshold);
}
//+------------------------------------------------------------------+
void DeleteMarkersByPrefix()
{
const long chart_id = ChartID();
const int n = ObjectsTotal(chart_id, 0, -1);
for(int i = n - 1; i >= 0; i--)
{
const string name = ObjectName(chart_id, i, 0, -1);
if(StringFind(name, OBJ_PFX) == 0)
ObjectDelete(chart_id, name);
}
}
//+------------------------------------------------------------------+
void PlaceMarker(const string sym, const ENUM_TIMEFRAMES tf, const int sh)
{
const datetime t = iTime(sym, tf, sh);
const string name = OBJ_PFX + IntegerToString((long)t);
const long chart_id = ChartID();
if(ObjectFind(chart_id, name) >= 0)
return;
const bool bull = (iClose(sym, tf, sh) >= iOpen(sym, tf, sh));
const int dig = (int)SymbolInfoInteger(sym, SYMBOL_DIGITS);
const double pt = SymbolInfoDouble(sym, SYMBOL_POINT);
double price = 0.0;
if(bull)
price = iLow(sym, tf, sh) - InpArrowOffsetPts * pt;
else
price = iHigh(sym, tf, sh) + InpArrowOffsetPts * pt;
price = NormalizeDouble(price, dig);
if(!ObjectCreate(chart_id, name, OBJ_ARROW, 0, t, price))
return;
ObjectSetInteger(chart_id, name, OBJPROP_ARROWCODE, bull ? 233 : 234);
ObjectSetInteger(chart_id, name, OBJPROP_COLOR, bull ? InpClrBullBar : InpClrBearBar);
ObjectSetInteger(chart_id, name, OBJPROP_WIDTH, InpArrowSize);
ObjectSetInteger(chart_id, name, OBJPROP_ANCHOR, bull ? ANCHOR_TOP : ANCHOR_BOTTOM);
ObjectSetInteger(chart_id, name, OBJPROP_BACK, false);
ObjectSetInteger(chart_id, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(chart_id, name, OBJPROP_HIDDEN, false);
}
//+------------------------------------------------------------------+
void TryMarkAtShift(const string sym, const ENUM_TIMEFRAMES tf, const int sh)
{
if(IsBodyLargerThanPriorAverage(sym, tf, sh, InpAvgPriorBodies))
PlaceMarker(sym, tf, sh);
}
//+------------------------------------------------------------------+
void ScanHistory(const string sym, const ENUM_TIMEFRAMES tf, const int maxBars)
{
if(maxBars <= 0)
return;
const int n = MathMin(maxBars, Bars(sym, tf) - InpAvgPriorBodies - 2);
for(int sh = 1; sh <= n; sh++)
TryMarkAtShift(sym, tf, sh);
}
//+------------------------------------------------------------------+
int OnInit()
{
if(InpAvgPriorBodies < 1)
{
Print("[MBB] InpAvgPriorBodies phải >= 1");
return INIT_FAILED;
}
if(InpBodyVsAvgMult <= 0.0)
{
Print("[MBB] InpBodyVsAvgMult phải > 0");
return INIT_FAILED;
}
if(InpClearMarksOnInit)
DeleteMarkersByPrefix();
ScanHistory(_Symbol, InpTf, InpScanBarsOnInit);
g_lastBarTime = iTime(_Symbol, InpTf, 0);
ChartRedraw();
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
DeleteMarkersByPrefix();
ChartRedraw();
}
//+------------------------------------------------------------------+
void OnTick()
{
const datetime t0 = iTime(_Symbol, InpTf, 0);
if(t0 == 0 || t0 == g_lastBarTime)
return;
g_lastBarTime = t0;
TryMarkAtShift(_Symbol, InpTf, 1);
ChartRedraw();
}
//+------------------------------------------------------------------+