Welcome Forex EA downloads & MT4/MT5 auto-trading resources — EAs, Gold EAs, quant tools and real-world automation.
Sign In Sign Up

# Institutional-level EA development document (MT4 simulated trading version)-2 | Trading script download-MetaTrader 4 resources

author blogger | 564 reads | 0 comments |

//+------------------------------------------------------------------+ //| chan_structure_sim.mq4 | //| Simulate institutional-level entanglement structure and back-step prompts (only simulation, no order placement) | //+------------------------------------------------------------------+ #property strict #property copyright "Generated with assistance from Codex" #property link "https://example.com&quot; #property version "1.000" #property description "Simulated winding structure EA based on development documents. Only drawings and logs, no real orders are executed." //--- Input parameters input ENUM_TIMEFRAMES InpPrimaryTF = PERIOD_H1; // Main structure period input ENUM_TIMEFRAMES InpHigherTF = PERIOD_H4; // Superior confirmation period input int InpFractalDepth = 2; // Type confirmation left and right K number input int InpMaxRecords = 500; // Structure maximum cache input double InpSimLots = 0.01; // Simulate each lot input color InpPremiumColor = clrTomato; // Premium area color input color InpDiscountColor = clrLightGreen; // Discount area color input color InpLiquidityColor= clrDeepSkyBlue; // Liquidity cleaning area color input double InpLiquidityPad = 5.0; // Cleaning area extension points input bool InpEnableLogging = true; // Write log file input bool InpShowDevelopingZhongshu = true; // Display progress center //--- Constant #define INVALID_INDEX (-1) #define OBJPREFIX "ChanEA" //--- Structure struct FractalPoint { datetime time; double price; bool isHigh; int shift; }; struct Pen { FractalPoint start; FractalPoint end; double high; double low; bool confirmed; }; struct ZhongShu { Pen a; Pen b; Pen c; double zg; double zd; datetime startTime; datetime endTime; bool locked; }; struct SimTrade { string id; datetime openTime; string reason; int state; // 0 open, 1 closed }; struct TrendInfo { ENUM_TIMEFRAMES tf; string highStatus; string lowStatus; string trendState; bool hasZone; bool developing; ZhongShu zone; double longSL; double shortSL; datetime g_lastPrimaryBar = 0; datetime g_lastHigherBar = 0; FractalPoint g_fractals[]; Pen g_pens[]; ZhongShu g_zhongshus[]; SimTrade g_trades[]; int g_logHandle = INVALID_HANDLE; string g_logFile = ""; ZhongShu g_developingZone; bool g_hasDevelopingZone = false; #define GV_SYNC_ZG "CHANEA_SYNC_ZG" #define GV_SYNC_ZD "CHANEA_SYNC_ZD" #define GV_SYNC_LONGSL "CHANEA_SYNC_LONGSL" #define GV_SYNC_SHORTSL "CHANEA_SYNC_SHORTSL" #define GV_SYNC_TIME "CHANEA_SYNC_TIME" #define GV_SYNC_DEV "CHANEA_SYNC_DEV" //--- Function declaration void InitializeCollections(); void CloseLog(); bool PrepareLog(); void WriteLog(string text); bool CheckNewBar(ENUM_TIMEFRAMES tf, datetime &lastTime); void ProcessPrimary(); void UpdateFractals(ENUM_TIMEFRAMES tf); bool IsFractal(ENUM_TIMEFRAMES tf, int shift, bool up); void AppendFractal(FractalPoint &point); void BuildPens(); void TryCreateZhongshu(); void DrawVisuals(); void DrawZhongshu(const ZhongShu &zone, int index); string ObjName(string suffix, int index); void double CleanupObjects(); PointsToPrice(double points); int DisplayDigits(); string PriceToStr(double value); string ShortStatusTag(const string status); void GetStructureStatus(string &highStatus, string &lowStatus); bool ComputeDevelopingZone(ZhongShu &zone); void DrawDevelopingZone(const ZhongShu &zone); void ClearDevelopingZoneObjects(); void UpdateSimulation(); void HighlightDiscountRetest(const ZhongShu &zone, int index); int FindOpenTradeIndex(string id); void OpenSimTrade(const ZhongShu &zone, bool isLong, double entryPrice, double pad); void CloseTrade(int index, bool hitTarget, datetime closeTime); void UpdateTradePanel(); void UpdateTradeOverlayText(string text); void UpdateStructureOverlayText(string text); bool CollectFractalsTF(ENUM_TIMEFRAMES tf, FractalPoint &arr[], int &count, int maxBars); void AppendFractalLocal(FractalPoint &point, FractalPoint &arr[], int &count); void BuildPensFromFractals(FractalPoint &arr[], int count, Pen &pens[], int &penCount); bool FindLatestZhongshuLocal(Pen &pens[], int penCount, ZhongShu &zone); bool ComputeDevelopingZoneFromData(Pen &pens[], int penCount, FractalPoint &fracs[], int fracCount, ENUM_TIMEFRAMES tf, ZhongShu &zone); bool ComputeTrendInfo(ENUM_TIMEFRAMES tf, TrendInfo &info); string TFToString(ENUM_TIMEFRAMES tf); void AppendTrendPanelLine(string label, TrendInfo &info, string &panel); void ShareKeyLevelsForM15(TrendInfo &info); void DrawSharedKeyLevels(); color DetermineOverlayColor(); void ApplyOverlayLabelStyle(const string name, ENUM_BASE_CORNER corner, int xDist, int yDist, int fontSize); int ColorWithAlpha(color base, int alpha); void EnsureHLine(string name, double price, color clr, ENUM_LINE_STYLE style, int width); void TrimFractals(); void TrimPens(); void TrimZhongshus(); void TrimTrades(); bool BuildFallbackZoneFromFractals(FractalPoint &fracs[], int count, ZhongShu &zone); //+--------------------------------------------------------------------------------+ int OnInit() { g_digits = (int)MarketInfo(Symbol(), MODE_DIGITS); g_point = MarketInfo(Symbol(), MODE_POINT); InitializeCollections(); if(InpEnableLogging && !PrepareLog()) { Print(FUNCTION, ": Unable to create log file."); } CleanupObjects(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Comment(""); CloseLog(); CleanupObjects(); ArrayResize(g_fractals, 0); ArrayResize(g_pens, 0); ArrayResize(g_zhongshus, 0); if(CheckNewBar(InpPrimaryTF, g_lastPrimaryBar)) { ProcessPrimary(); } } //+------------------------------------------------------------------+ void InitializeCollections() { ArrayResize(g_fractals, 0); ArrayResize(g_pens, 0); ArrayResize(g_zhongshus, 0); ArrayResize(g_trades, 0); g_hasDevelopingZone = false; } //+------------------------------------------------------------------+ bool PrepareLog() { g_logFile = StringFormat("%s_chan_sim_log.csv", TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES)); g_logHandle = FileOpen(g_logFile, FILE_WRITE|FILE_CSV|FILE_SHARE_WRITE, ';'); if(g_logHandle == INVALID_HANDLE) return(false); FileWrite(g_logHandle, "time", "type", "message"); FileFlush(g_logHandle); return(true); } //+--------------------------------------------------------------------------------+ void CloseLog() { if(g_logHandle != INVALID_HANDLE) { FileFlush(g_logHandle); FileClose(g_logHandle); g_logHandle = INVALID_HANDLE; } } //+------------------------------------------------------------------+ void WriteLog(string text) { if(!InpEnableLogging || g_logHandle == INVALID_HANDLE) return; FileWrite(g_logHandle, TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES), "INFO", text); } //+------------------------------------------------------------------+ bool CheckNewBar(ENUM_TIMEFRAMES tf, datetime &lastTime) { datetime current = iTime(Symbol(), tf, 0); if(current == 0) return(false); if(current != lastTime) { lastTime = current; return(true); } return(false); } //+----------------------------------------------------------------+ void ProcessPrimary() { UpdateFractals(InpPrimaryTF); BuildPens(); TryCreateZhongshu(); DrawVisuals(); UpdateSimulation(); } //+-----------------------------------------------------------------+ void UpdateFractals(ENUM_TIMEFRAMES tf) { int totalBars = iBars(Symbol(), tf); if(totalBars <= InpFractalDepth * 2 + 1) return; int processed = 0; for(int shift = totalBars - (InpFractalDepth + 2); shift >= InpFractalDepth; --shift) { if(processed >= 500) break; bool isHigh = IsFractal(tf, shift, true); bool isLow = IsFractal(tf, shift, false); if(isHigh || isLow) { datetime fTime = iTime(Symbol(), tf, shift); double fPrice= isHigh ? iHigh(Symbol(), tf, shift) : iLow(Symbol(), tf, shift); // Check if it already exists bool exists=false; int total = ArraySize(g_fractals); for(int i=0;i <total;++i)
{
if(g_fractals[i].time == fTime && g_fractals[i].isHigh == isHigh)
{
exists = true;
break;
}
}
if(exists)
continue;

     FractalPoint fp;
     fp.time   = fTime;
     fp.price  = fPrice;
     fp.isHigh = isHigh;
     fp.shift  = shift;
     AppendFractal(fp);
     processed++;
  }

}
}

//+------------------------------------------------------------------+
bool IsFractal(ENUM_TIMEFRAMES tf, int shift, bool up)
{
for(int i=1; i<=InpFractalDepth; ++i)
{
double current = up ? iHigh(Symbol(), tf, shift) : iLow(Symbol(), tf, shift);
double compareLeft = up ? iHigh(Symbol(), tf, shift+i) : iLow(Symbol(), tf, shift+i);
double compareRight = up ? iHigh(Symbol(), tf, shift-i) : iLow(Symbol(), tf, shift-i);

  if(up)
  {
     if(current <= compareLeft || current <= compareRight)
        return(false);
  }
  else
  {
     if(current >= compareLeft || current &gt;= compareRight) return(false); } } return(true); } //+------------------------------------------------------------------+ void AppendFractal(FractalPoint &amp;point) { int total = ArraySize(g_fractals); if(total &gt; 0) { FractalPoint last = g_fractals[total-1]; if(last.isHigh == point.isHigh) { if(point.isHigh == point.isHigh) &amp;&amp; point.price &gt; last.price) { g_fractals[total-1] = point; } else if(!point.isHigh &amp;&amp; point.price &lt; last.price) { g_fractals[total-1] = point; } return; } } ArrayResize(g_fractals, total + 1); g_fractals[total] = point; TrimFractals(); } //+--------------------------------------------------------------------------------+ void BuildPens() { int total = ArraySize(g_fractals); if(total &lt; 2) { ArrayResize(g_pens, 0); return; } ArrayResize(g_pens, total-1); for(int i=0; ijectSetInteger(0, rectName, OBJPROP_WIDTH, 1); // String upperName = ObjName(&quot;ZS_UPPER_&quot;, index); ObjectCreate(0, upperName, OBJ_TREND, 0, tStart, zone.zg, tEnd, zone.zg); ObjectSetInteger(0, upperName, OBJPROP_COLOR, clrDimGray); ObjectSetInteger(0, upperName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, upperName, OBJPROP_WIDTH, 2); ObjectSetInteger(0, upperName, OBJPROP_RAY, false); // Center lower edge string lowerName = ObjName(&quot;ZS_LOWER_&quot;, index); ObjectCreate(0, lowerName, OBJ_TREND, 0, tStart, zone.zd, tEnd, zone.zd); ObjectSetInteger(0, lowerName, OBJPROP_COLOR, clrDimGray); ObjectSetInteger(0, lowerName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, lowerName, OBJPROP_WIDTH, 2); ObjectSetInteger(0, lowerName, OBJPROP_RAY, false); // Central midline double midPrice = (zone.zg + zone.zd) / 2.0; string midName = ObjName(&quot;ZS_MID_&quot;, index); ObjectCreate(0, midName, OBJ_TREND, 0, tStart, midPrice, tEnd, midPrice); ObjectSetInteger(0, midName, OBJPROP_COLOR, clrSilver); ObjectSetInteger(0, midName, OBJPROP_STYLE, STYLE_DOT); ObjectSetInteger(0, midName, OBJPROP_WIDTH, 1); ObjectSetInteger(0, midName, OBJPROP_RAY, false); double padPrice = PointsToPrice(InpLiquidityPad); // Premium warning line string premiumLine = ObjName(&quot;ZSPREM_LINE_&quot;, index); ObjectCreate(0, premiumLine, OBJ_TREND, 0, tStart, zone.zg + padPrice, tEnd, zone.zg + padPrice); ObjectSetInteger(0, premiumLine, OBJPROP_COLOR, InpPremiumColor); ObjectSetInteger(0, premiumLine, OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(0, premiumLine, OBJPROP_WIDTH, 2); ObjectSetInteger(0, premiumLine, OBJPROP_RAY, false); // discount warning line string discountLine = ObjName(&quot;ZSDISC_LINE_&quot;, index); ObjectCreate(0, discountLine, OBJ_TREND, 0, tStart, zone.zd - padPrice, tEnd, zone.zd - padPrice); ObjectSetInteger(0, discountLine, OBJPROP_COLOR, InpDiscountColor); ObjectSetInteger(0, discountLine, OBJPROP_STYLE, STYLE_DASH); ObjectSetInteger(0, discountLine, OBJPROP_WIDTH, 2); ObjectSetInteger(0, discountLine, OBJPROP_RAY, false); datetime midTime = tStart + (tEnd - tStart) / 2; // Premium block string premiumBox = ObjName(&quot;ZSPREM_BOX_&quot;, index); ObjectCreate(0, premiumBox, OBJ_RECTANGLE, 0, tStart, zone.zg + padPrice, tEnd, zone.zg); ObjectSetInteger(0, premiumBox, OBJPROP_COLOR, ColorWithAlpha(InpPremiumColor, 80)); ObjectSetInteger(0, premiumBox, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, premiumBox, OBJPROP_WIDTH, 1); ObjectSetInteger(0, premiumBox, OBJPROP_FILL, true); ObjectSetInteger(0, premiumBox, OBJPROP_BACK, false); // discount block string discountBox = ObjName(&quot;ZSDISC_BOX_&quot;, index); ObjectCreate(0, discountBox, OBJ_RECTANGLE, 0, tStart, zone.zd, tEnd, zone.zd - padPrice); ObjectSetInteger(0, discountBox, OBJPROP_COLOR, ColorWithAlpha(InpDiscountColor, 80)); ObjectSetInteger(0, discountBox, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, discountBox, OBJPROP_WIDTH, 1); ObjectSetInteger(0, discountBox, OBJPROP_FILL, true); ObjectSetInteger(0, discountBox, OBJPROP_BACK, false); // Premium tag string premiumTag = ObjName(&quot;ZSPREM_TAG_&quot;, index); ObjectCreate(0, premiumTag, OBJ_TEXT, 0, midTime, zone.zg + padPrice * 0.5); ObjectSetString(0, premiumTag, OBJPROP_TEXT, &quot;Premium&quot;); ObjectSetInteger(0, premiumTag, OBJPROP_COLOR, InpPremiumColor); ObjectSetInteger(0, premiumTag, OBJPROP_FONTSIZE, 8); ObjectSetInteger(0, premiumTag, OBJPROP_BACK, false); ObjectSetInteger(0, premiumTag, OBJPROP_ANCHOR, ANCHOR_CENTER); // discount tag string discountTag = ObjName(&quot;ZSDISC_TAG_&quot;, index); ObjectCreate(0, discountTag, OBJ_TEXT, 0, midTime, zone.zd - padPrice * 0.5); ObjectSetString(0, discountTag, OBJPROP_TEXT, &quot;discount&quot;); ObjectSetInteger(0, discountTag, OBJPROP_COLOR, InpDiscountColor); ObjectSetInteger(0, discountTag, OBJPROP_FONTSIZE, 8); ObjectSetInteger(0, discountTag, OBJPROP_BACK, false); ObjectSetInteger(0, discountTag, OBJPROP_ANCHOR, ANCHOR_CENTER); // Label text string labelName = ObjName(&quot;ZS_LABEL_&quot;, index); ObjectCreate(0, labelName, OBJ_TEXT, 0, midTime, zone.zg); ObjectSetString(0, labelName, OBJPROP_TEXT, StringFormat(&quot;ZS #%d&quot;, index+1)); ObjectSetInteger(0, labelName, OBJPROP_COLOR, clrWhite); ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8); ObjectSetInteger(0, labelName, OBJPROP_BACK, false); } //+-------------------------------------------------------------------------+ void HighlightDiscountRetest(const ZhongShu &amp;zone, int index) { // Monitor whether the latest price is within the discount zone. double price = iClose(Symbol(), InpPrimaryTF, 1); if(price &lt;= zone.zd &amp;&amp; price &gt;= zone.zd - PointsToPrice(InpLiquidityPad)) { string infoName = ObjName(&quot;ZSDISC_ALERT_&quot;, index); ObjectCreate(0, infoName, OBJ_TEXT, 0, TimeCurrent(), zone.zd - PointsToPrice(InpLiquidityPad) ); ObjectSetString(0, infoName, OBJPROP_TEXT, &quot;Discount confirmation&quot;); ObjectSetInteger(0, infoName, OBJPROP_COLOR, clrWhite); ObjectSetInteger(0, infoName, OBJPROP_FONTSIZE, 8); ObjectSetInteger(0, infoName, OBJPROP_BACK, false); string zoneName = ObjName(&quot;ZSDISC_HIGHLIGHT_&quot;, index); ObjectCreate(0, zoneName, OBJ_RECTANGLE, 0, zone.startTime, zone.zd, TimeCurrent(), zone.zd - PointsToPrice(InpLiquidityPad)); ObjectSetInteger(0, zoneName, OBJPROP_COLOR, InpLiquidityColor); ObjectSetInteger(0, zoneName, OBJPROP_FILL, true); WriteLog(&quot;Discount zone back-up prompt triggered.&quot;); } } //+------------------------------------------------------------------+ void CleanupObjects() { int total = ObjectsTotal(); for(int i=total-1; i&gt;=0; --i) { string name = ObjectName(0, i); if(StringFind(name, OBJ_PREFIX) == 0 || StringFind(name, &quot;DEV_&quot;) == 0 || StringFind(name, &quot;FRAC_HIGH&quot;) &gt;= 0 || StringFind(name, &quot;FRAC_LOW&quot;) &gt;= 0) { ObjectDelete(0, name); } } } //+----------------------------------------------------------------------------------+ string ObjName(string suffix, int index) { return(OBJ_PREFIX + suffix + IntegerToString(index)); } //+----------------------------------------------------------------------------------+ double PointsToPrice(double points) { return(points * g_point); } //+------------------------------------------------------------------+ void UpdateSimulation() { int zsTotal = ArraySize(g_zhongshus); if(zsTotal == 0) return; double padPrice = PointsToPrice(InpLiquidityPad); double closePrice = iClose(Symbol(), InpPrimaryTF, 1); double barHigh = iHigh(Symbol(), InpPrimaryTF, 1); double barLow = iLow(Symbol(), InpPrimaryTF, 1); datetime barTime = iTime(Symbol(), InpPrimaryTF, 1); // Check whether each hub triggers a new simulated transaction for(int i=0; i <zsTotal; ++i)

{
ZhongShu zone = gzhongshus[i];
string longId = StringFormat("%I64u
%I64ulong", (long)zone.startTime, (long)zone.endTime);
string shortId = StringFormat("%I64u
%I64u_short", (long)zone.startTime, (long)zone.endTime);

  // Go long if you step back in the discount area
  if(closePrice <= zone.zd && closePrice >= zone.zd - padPrice &amp;&amp; FindOpenTradeIndex(longId) == -1) { OpenSimTrade(zone, true, closePrice, padPrice); } // The premium zone will be shorted if(closePrice &gt;= zone.zg &amp;&amp; closePrice &lt;= zone.zg + padPrice &amp;&amp; FindOpenTradeIndex(shortId) == -1) { OpenSimTrade(zone, false, closePrice, padPrice); } } // Check the take profit and stop loss of the existing simulated position for(int t=0; t <ArraySize(g_trades); ++t)

{
if(g_trades[t].state != 0)
continue;

  if(g_trades[t].isLong)
  {
     if(barLow <= g_trades[t].stop)
     {
        CloseTrade(t, false, barTime);
     }
     else if(barHigh > + int FindOpenTradeIndex(string id) { for(int i=0; iif(isLong) trade.stop = zone.zd - pad; else trade.stop = zone.zg + pad; if(isLong) trade.target = trade.entry + 2.0 * (trade.entry - trade.stop); else trade.target = trade.entry - 2.0 * (trade.stop - trade.entry); int idx = ArraySize(g_trades); ArrayResize(g_trades, idx + 1); g_trades[idx] = trade; TrimTrades(); WriteLog(StringFormat(&quot;Open a position: %s entry=%.5f stop=%.5f target=%.5f lots=%.2f&quot;, trade.reason, trade.entry, trade.stop, trade.target, trade.lots)); } //+--------------------------------------------------------------------------------+ void CloseTrade(int index, bool hitTarget, datetime closeTime) { g_trades[index].state = 1; string result = hitTarget ? &quot;Take profit&quot; : &quot;Stop loss&quot;; WriteLog(StringFormat(&quot;Close position: %s result=%s entry=%.5f stop=%.5f target=%.5f&quot;, g_trades[index].reason, result, g_trades[index].entry, g_trades[index].stop, g_trades[index].target)); UpdateTradePanel(); ; } //+------------------------------------------------------------------+ void UpdateTradePanel() { string structure = &quot;&quot;; string overlay = &quot;Simulated position information:\n&quot;; bool hasOpen = false; for(int t=0; t <ArraySize(g_trades); ++t)

{
if(g_trades[t].state != 0)
continue;

  hasOpen = true;
  overlay += StringFormat("%s | Lot size %.2f | Admission %.5f | stop loss %.5f | Take profit %.5f | Open a position %s\n",
     g_trades[t].isLong ? "long" : "short",
     g_trades[t].lots,
     g_trades[t].entry,
     g_trades[t].stop,
     g_trades[t].target,
     TimeToString(g_trades[t].openTime, TIME_DATE|TIME_MINUTES));

}

if(!hasOpen)
overlay += "No open simulated orders。\n";

string highStatus, lowStatus;
GetStructureStatus(highStatus, lowStatus);
string highTag = ShortStatusTag(highStatus);
string lowTag = ShortStatusTag(lowStatus);
structure += StringFormat("structure top%s end%s\n", highTag, lowTag);

string trendState = "shock";
if(StringFind(highStatus, "HH") == 0 && StringFind(lowStatus, "HL") == 0)
trendState = "Upward";
else if(StringFind(highStatus, "LH") == 0 && StringFind(lowStatus, "LL") == 0)
trendState = "Downward";
structure += StringFormat("trend %s\n", trendState);

ZhongShu refZone;
bool haveZone = false;
ClearZhongShuStruct(refZone);
if(g_hasDevelopingZone)
{
refZone = g_developingZone;
haveZone = true;
}
else if(ArraySize(g_zhongshus) > 0) { refZone = g_zhongshus[ArraySize(g_zhongshus)-1]; haveZone = true; } if(haveZone) { double longSL = refZone.zd - PointsToPrice(InpLiquidityPad); double shortSL= refZone.zg + PointsToPrice(InpLiquidityPad); string zoneFlag = refZone.locked ? "" : "*"; structure += StringFormat("Interval %s-%s%s\n", PriceToStr(refZone.zd), PriceToStr(refZone.zg), zoneFlag); structure += StringFormat("SL more than %s empty ≥%s\n", PriceToStr(longSL), PriceToStr(shortSL)); overlay += StringFormat("Order flow benchmark: zg %.5f / zd %.5f\n", refZone.zg, refZone.zd); overlay += StringFormat("Long SL≤%.5f | Short SL≥%.5f\n", longSL, shortSL); overlay += "Target tip: maintain 1:2 profit and loss ratio\n"; } structure += "Period:\n"; TrendInfo infoHigher, infoPrimary, infoLower; InitTrendInfo(infoHigher, InpHigherTF); InitTrendInfo(infoPrimary, InpPrimaryTF); InitTrendInfo(infoLower, PERIOD_M15); bool infoHigherOK = ComputeTrendInfo(InpHigherTF, infoHigher); bool infoPrimaryOK = ComputeTrendInfo(InpPrimaryTF, infoPrimary); bool infoLowerOK = ComputeTrendInfo(PERIOD_M15, infoLower); if(infoHigherOK) AppendTrendPanelLine(TFToString(InpHigherTF), infoHigher, structure); if(infoPrimaryOK) AppendTrendPanelLine(TFToString(InpPrimaryTF), infoPrimary, structure); if(infoLowerOK) AppendTrendPanelLine(TFToString(PERIOD_M15), infoLower, structure); if(Period() == InpPrimaryTF) { if(infoPrimaryOK) ShareKeyLevelsForM15(infoPrimary); else { TrendInfo dummy; InitTrendInfo(dummy, InpPrimaryTF); ShareKeyLevelsForM15(dummy); } } Comment(""); UpdateTradeOverlayText(overlay); UpdateStructureOverlayText(structure); } //+------------------------------------------------------------------+ void TrimFractals() { int total = ArraySize(g_fractals); if(total <= InpMaxRecords) return; int keep = InpMaxRecords; int start = total - keep; for(int i=0; iyResize(g_fractals, keep); } //+------------------------------------------------------------------+ void TrimPens() { int total = ArraySize(g_pens); if(total <= InpMaxRecords) return; int keep = InpMaxRecords; int start = total - keep; for(int i=0; i <keep; ++i)
g_pens[i] = g_pens[start + i];
ArrayResize(g_pens, keep);
}

//+------------------------------------------------------------------+
void TrimZhongshus()
{
int total = ArraySize(g_zhongshus);
if(total <= InpMaxRecords)
return;

int keep = InpMaxRecords;
int start = total - keep;
for(int i=0; i<keep; ++i)
g_zhongshus[i] = g_zhongshus[start + i];
ArrayResize(g_zhongshus, keep);
}

//+------------------------------------------------------------------+
void TrimTrades()
{
int total = ArraySize(g_trades);
if(total <= InpMaxRecords)
return;

int keep = InpMaxRecords;
int start = total - keep;
for(int i=0; i<keep; ++i)
g_trades[i] = g_trades[start + i];
ArrayResize(g_trades, keep);
}

//+------------------------------------------------------------------+
void ClearFractalPoint(FractalPoint &fp)
{
fp.time = 0;
fp.price = 0.0;
fp.isHigh = false;
fp.shift = 0;
}

//+------------------------------------------------------------------+
void ClearPenStruct(Pen &pen)
{
ClearFractalPoint(pen.start);
ClearFractalPoint(pen.end);
pen.high = 0.0;
pen.low = 0.0;
pen.confirmed = false;
}

//+------------------------------------------------------------------+
void ClearZhongShuStruct(ZhongShu &zone)
{
ClearPenStruct(zone.a);
ClearPenStruct(zone.b);
ClearPenStruct(zone.c);
zone.zg = 0.0;
zone.zd = 0.0;
zone.startTime = 0;
zone.endTime = 0;
zone.locked = false;
}

//+------------------------------------------------------------------+
void InitTrendInfo(TrendInfo &info, ENUM_TIMEFRAMES tf)
{
info.tf = tf;
info.highStatus = "Not enough data";
info.lowStatus = "Not enough data";
info.trendState = "unknown";
info.hasZone = false;
info.developing = false;
info.longSL = 0.0;
info.shortSL = 0.0;
info.sweepStrength = "No structure";
info.rrHint = "";
ClearZhongShuStruct(info.zone);
}

//+------------------------------------------------------------------+
void GetStructureStatus(string &highStatus, string &lowStatus)
{
highStatus = "Not enough data";
lowStatus = "Not enough data";

int total = ArraySize(g_fractals);
if(total < 2)
return;

double highVals[2]={0.0,0.0};
double lowVals[2]={0.0,0.0};
int highCount = 0;
int lowCount = 0;

for(int i=total-1; i> =0 && (highCount<2 || lowCount<2); --i) { if(g_fractals[i].isHigh && highCount < 2) { highVals[highCount] = g_fractals[i].price; highCount++; } else if(!g_fractals[i].isHigh && lowCount < 2) { lowVals[lowCount] = g_fractals[i].price; lowCount++; } } if(highCount == 2) { if(highVals[0] > highVals[1]) highStatus = StringFormat("HH (%.5f > %.5f)", highVals[0], highVals[1]); else if(highVals[0] < highVals[1]) highStatus = StringFormat("LH (%.5f < %.5f)", highVals[0], highVals[1]); else highStatus = StringFormat("Equal (%.5f)", highVals[0]); } if(lowCount == 2) { if(lowVals[0] < lowVals[1]) lowStatus = StringFormat("LL (%.5f < %.5f)", lowVals[0], lowVals[1]); else if(lowVals[0] > lowVals[1]) lowStatus = StringFormat("HL (%.5f > %.5f)", lowVals[0], lowVals[1]); else lowStatus = StringFormat("Equal (%.5f)", lowVals[0]); } } //+--------------------------------------------------------------------------------+ int DisplayDigits() { int digits = g_digits; if(digits <= 0) digits = (int)MarketInfo(Symbol(), MODE_DIGITS); if(digits > 4) digits = 4; return(digits); } //+----------------------------------------------------------------------------------+ string PriceToStr(double value) { return(DoubleToString(value, DisplayDigits())); } //+----------------------------------------------------------------------------------+ string ShortStatusTag(const string status) { if(status == "" || StringFind(status, "Insufficient data") == 0) return("NA"); if(StringFind(status, "Equal") == 0) return("EQ"); string tag = StringSubstr(status, 0, 2); return(StringToUpper(tag)); }//+------------------------------------------------------------------+ bool ComputeDevelopingZone(ZhongShu &zone) { if(!InpShowDevelopingZhongshu) return(false); int penTotal = ArraySize(g_pens); int fracTotal = ArraySize(g_fractals); if(penTotal < 2 || fracTotal < 1) return(false); Pen penA = g_pens[penTotal-2]; Pen penB = g_pens[penTotal-1]; FractalPoint lastFrac = g_fractals[fracTotal-1]; double livePrice = iClose(Symbol(), InpPrimaryTF, 0); Pen penC; penC.start = lastFrac; penC.end.time = TimeCurrent(); penC.end.price = livePrice; penC.high = MathMax(lastFrac.price, livePrice); penC.low = MathMin(lastFrac.price, livePrice); penC.confirmed = false; double zg = MathMin(MathMin(penA.high, penB.high), penC.high); double zd = MathMax(MathMax(penA.low, penB.low), penC.low); if(zg <= zd) { // If there is already a confirmation hub covering the latest structure, it will not be displayed repeatedly int zsTotal = ArraySize(g_zhongshus); if(zsTotal > 0) { ZhongShu last = g_zhongshus[zsTotal-1]; if(last.endTime >= penB.end.time && MathAbs(last.zg - zone.zg) < g_point5 && MathAbs(last.zd - zone.zd) < g_point5) { if(BuildFallbackZoneFromFractals(g_fractals, ArraySize(g_fractals), zone)) return(true); return(false); } } return(true); } //+--------------------------------------------------------------------------------+ void DrawDevelopingZone(const ZhongShu &zone) { string frame = ObjName("DEVFRAME", 0); ObjectCreate(0, frame, OBJ_RECTANGLE, 0, zone.startTime, zone.zg, zone.endTime, zone.zd); ObjectSetInteger(0, frame, OBJPROP_COLOR, clrSlateGray); ObjectSetInteger(0, frame, OBJPROP_BACK, false); ObjectSetInteger(0, frame, OBJPROP_FILL, false); ObjectSetInteger(0, frame, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, frame, OBJPROP_WIDTH, 2); string upper = ObjName("DEVUPPER", 0); ObjectCreate(0, upper, OBJ_TREND, 0, zone.startTime, zone.zg, zone.endTime, zone.zg); ObjectSetInteger(0, upper, OBJPROP_COLOR, clrSlateGray); ObjectSetInteger(0, upper, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, upper, OBJPROP_WIDTH, 2); ObjectSetInteger(0, upper, OBJPROP_RAY, false); string lower = ObjName("DEVLOWER", 0); ObjectCreate(0, lower, OBJ_TREND, 0, zone.startTime, zone.zd, zone.endTime, zone.zd); ObjectSetInteger(0, lower, OBJPROP_COLOR, clrSlateGray); ObjectSetInteger(0, lower, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, lower, OBJPROP_WIDTH, 2); ObjectSetInteger(0, lower, OBJPROP_RAY, false); string label = ObjName("DEVLABEL", 0); datetime midTime = zone.startTime + (zone.endTime - zone.startTime)/2; ObjectCreate(0, label, OBJ_TEXT, 0, midTime, zone.zg); ObjectSetString(0, label, OBJPROP_TEXT, zone.a.start.time==0 && zone.b.start.time==0 && zone.c.start.time==0 ? "ZS(fb)" : "ZS(dev)"); ObjectSetInteger(0, label, OBJPROP_COLOR, clrSlateGray); ObjectSetInteger(0, label, OBJPROP_FONTSIZE, 8); ObjectSetInteger(0, label, OBJPROP_BACK, false); } //+--------------------------------------------------------------------------------+ void ClearDevelopingZoneObjects() { int total = ObjectsTotal(); for(int i=total-1; i>=0; --i) { string name = ObjectName(0, i); if(StringFind(name, OBJPREFIX + "DEV") == 0) ObjectDelete(0, name); } } //+--------------------------------------------------------------------------------+ bool CollectFractalsTF(ENUM_TIMEFRAMES tf, FractalPoint &arr[], int &count, int maxBars) { count = 0; ArrayResize(arr, 0); int totalBars = iBars(Symbol(), tf); if(totalBars <= InpFractalDepth*2 + 1) return(false); int lastShift = totalBars - InpFractalDepth - 1; int startShift = MathMax(InpFractalDepth, lastShift - maxBars); if(startShift > lastShift) startShift = InpFractalDepth; for(int shift = lastShift; shift >= startShift; --shift) { bool isHigh = IsFractal(tf, shift, true); bool isLow = IsFractal(tf, shift, false); if(!isHigh && !isLow) continue; FractalPoint fp; fp.time = iTime(Symbol(), tf, shift); fp.price = isHigh ? iHigh(Symbol(), tf, shift) : iLow(Symbol(), tf, shift); fp.isHigh = isHigh; fp.shift = shift; AppendFractalLocal(fp, arr, count); } return(count > 0); } //+------------------------------------------------------------------+ void AppendFractalLocal(FractalPoint &point, FractalPoint &arr[], int &count) { if(count > 0 && arr[count-1].isHigh == point.isHigh) { if(point.isHigh && point.price > arr[count-1].price) arr[count-1] = point; else if(!point.isHigh && point.price < arr[count-1].price) arr[count-1] = point; return; } ArrayResize(arr, count + 1); arr[count] = point; count++; } //+------------------------------------------------------------------+ void BuildPensFromFractals(FractalPoint &arr[], int count, Pen &pens[], int &penCount) { penCount = 0; ArrayResize(pens, 0); if(count < 2) return; penCount = count - 1; ArrayResize(pens, penCount); for(int i=0; i <penCount; ++i)
{
pens[i].start = arr[i];
pens[i].end = arr[i+1];
pens[i].high = MathMax(arr[i].price, arr[i+1].price);
pens[i].low = MathMin(arr[i].price, arr[i+1].price);
pens[i].confirmed = true;
}
}

//+------------------------------------------------------------------+
bool FindLatestZhongshuLocal(Pen &pens[], int penCount, ZhongShu &zone)
{
bool found = false;
for(int i=0; i<penCount-2; ++i)
{
double zg = MathMin(MathMin(pens[i].high, pens[i+1].high), pens[i+2].high);
double zd = MathMax(MathMax(pens[i].low, pens[i+1].low), pens[i+2].low);
if(zg <= zd)
continue;

  zone.a = pens[i];
  zone.b = pens[i+1];
  zone.c = pens[i+2];
  zone.zg = zg;
  zone.zd = zd;
  zone.startTime = pens[i].start.time;
  zone.endTime   = pens[i+2].end.time;
  zone.locked    = true;
  found = true;

}
return(found);
}

//+------------------------------------------------------------------+
bool ComputeDevelopingZoneFromData(Pen &pens[], int penCount, FractalPoint &fracs[], int fracCount, ENUM_TIMEFRAMES tf, ZhongShu &zone)
{
if(penCount < 2 || fracCount < 1)
return(false);

Pen penA = pens[penCount-2];
Pen penB = pens[penCount-1];
FractalPoint lastFrac = fracs[fracCount-1];

double nowPrice = iClose(Symbol(), tf, 0);
datetime nowTime = TimeCurrent();

Pen penC;
penC.start = lastFrac;
penC.end.time = nowTime;
penC.end.price = nowPrice;
penC.high = MathMax(lastFrac.price, nowPrice);
penC.low = MathMin(lastFrac.price, nowPrice);
penC.confirmed = false;

double zg = MathMin(MathMin(penA.high, penB.high), penC.high);
double zd = MathMax(MathMax(penA.low, penB.low), penC.low);

if(zg <= zd)
return(false);

zone.a = penA;
zone.b = penB;
zone.c = penC;
zone.zg = zg;
zone.zd = zd;
zone.startTime = penA.start.time;
zone.endTime = penC.end.time;
zone.locked = false;
return(true);
}

//+------------------------------------------------------------------+
bool BuildFallbackZoneFromFractals(FractalPoint &fracs[], int count, ZhongShu &zone)
{
double lastHigh = 0.0, lastLow = 0.0;
datetime highTime = 0, lowTime = 0;

for(int i=count-1; i> =0 && (lastHigh == 0.0 || lastLow == 0.0); --i) { if(fracs[i].isHigh && lastHigh == 0.0) { lastHigh = fracs[i].price; highTime = fracs[i].time; } else if(!fracs[i].isHigh && lastLow == 0.0) { lastLow = fracs[i].price; lowTime = fracs[i].time; } } if(lastHigh == 0.0 || lastLow == 0.0) return(false); double topPrice = lastHigh; double bottomPrice = lastLow; datetime topTime = highTime; datetime bottomTime = lowTime; if(bottomPrice >= topPrice) { topPrice = MathMax(lastHigh, lastLow); bottomPrice = MathMin(lastHigh, lastLow); topTime = (topPrice == lastHigh) ? highTime : lowTime; bottomTime = (bottomPrice == lastLow) ? lowTime : highTime; if(topPrice - bottomPrice <= 0.0) return(false); } ClearZhongShuStruct(zone); zone.zg = topPrice; zone.zd = bottomPrice; zone.startTime = MathMin(topTime, bottomTime); zone.endTime = TimeCurrent(); zone.locked = false; return(true); } //+--------------------------------------------------------------------------------+ string TFToString(ENUM_TIMEFRAMES tf) { switch(tf) { case PERIOD_M1: return("M1"); case PERIOD_M5: return("M5"); case PERIOD_M15: return("M15"); case PERIOD_M30: return("M30"); case PERIOD_H1: return("H1"); case PERIOD_H4: return("H4"); case PERIOD_D1: return("D1"); case PERIOD_W1: return("W1"); case PERIOD_MN1: return("MN1"); } return("TF"); } //+--------------------------------------------------------------------------------+ bool ComputeTrendInfo(ENUM_TIMEFRAMES tf, TrendInfo &info) { InitTrendInfo(info, tf); FractalPoint fracs[]; int fracCount = 0; if(!CollectFractalsTF(tf, fracs, fracCount, 600)) return(false); if(fracCount >= 2) { double highVals[2]={0.0,0.0}; double lowVals[2]={0.0,0.0}; int h=0,l=0; for(int i=fracCount-1; i>=0 && (h<2 || l<2); --i) { if(fracs[i].isHigh && h<2) highVals[h++] = fracs[i].price; else if(!fracs[i].isHigh && l<2) lowVals[l++] = fracs[i].price; } if(h==2) { if(highVals[0] > highVals[1]) info.highStatus = StringFormat("HH (%.5f > %.5f)", highVals[0], highVals[1]); else if(highVals[0] < highVals[1]) info.highStatus = StringFormat("LH (%.5f < %.5f)", highVals[0], highVals[1]); else info.highStatus = StringFormat("Equal (%.5f)", highVals[0]); } if(l==2) { if(lowVals[0] < lowVals[1]) info.lowStatus = StringFormat("LL (%.5f < %.5f)", lowVals[0], lowVals[1]); else if(lowVals[0] > lowVals[1]) info.lowStatus = StringFormat("HL (%.5f > %.5f)", lowVals[0], lowVals[1]); else info.lowStatus = StringFormat("Equal (%.5f)", lowVals[0]); } } if(StringFind(info.highStatus, "HH") == 0 && StringFind(info.lowStatus, "HL") == 0) info.trendState = "Up"; else if(StringFind(info.highStatus, "LH") == 0 && StringFind(info.lowStatus, "LL") == 0) info.trendState = "Down"; else info.trendState = "Shocking"; Pen pens[]; int penCount = 0; BuildPensFromFractals(fracs, fracCount, pens, penCount); ZhongShu zone; bool confirmed = FindLatestZhongshuLocal(pens, penCount, zone); if(confirmed) { info.zone = zone; info.hasZone = true; info.developing = false; } else { if(ComputeDevelopingZoneFromData(pens, penCount, fracs, fracCount, tf, zone)) { info.zone = zone; info.hasZone = true; info.developing = true; } } if(info.hasZone) { double padPrice = PointsToPrice(InpLiquidityPad); info.longSL = info.zone.zd - padPrice; info.shortSL = info.zone.zg + padPrice; double width = info.zone.zg - info.zone.zd; double ratio = padPrice > 0.0 ? width / padPrice : 0.0; if(ratio < 2.0) info.sweepStrength = "Compact"; else if(ratio < 4.0) info.sweepStrength = "Balanced"; else info.sweepStrength = "Wide"; if(ratio <= 2.0) info.rrHint = "RR is good"; else if(ratio <= 4.0) info.rrHint = "RR stable"; else info.rrHint = "RR wide"; } else if(BuildFallbackZoneFromFractals(fracs, fracCount, info.zone)) { info.hasZone = true; info.developing = true; double padPrice = PointsToPrice(InpLiquidityPad); info.longSL = info.zone.zd - padPrice; info.shortSL = info.zone.zg + padPrice; info.sweepStrength = "Prejudgment"; info.rrHint = "To be confirmed"; } else { info.sweepStrength = "No structure"; info.rrHint = "To be structured"; } return(true); } //+--------------------------------------------------------------------------------+ void AppendTrendPanelLine(string label, TrendInfo &info, string &panel) { panel += label; panel += " "; if(info.highStatus == "Insufficient data" && info.lowStatus == "Insufficient data") { panel += "Insufficient data\n"; return; } string highTag = ShortStatusTag(info.highStatus); string lowTag = ShortStatusTag(info.lowStatus); panel += StringFormat("%s/%s %s", highTag, lowTag, info.trendState); if(info.hasZone) { panel += StringFormat("Zone[%s-%s]%s", PriceToStr(info.zone.zd), PriceToStr(info.zone.zg), info.developing ? "" : ""); panel += StringFormat(" SL%s/%s", PriceToStr(info.longSL), PriceToStr(info.shortSL)); } else { panel+= "zone[--]"; } if(info.rrHint != "") panel += StringFormat(" %s", info.rrHint); panel += "\n"; } //+----------------------------------------------------------------------------------+ void ShareKeyLevelsForM15(TrendInfo &info) { if(Period() != InpPrimaryTF) return; if(!info.hasZone) { GlobalVariableDel(GV_SYNC_ZG); GlobalVariableDel(GV_SYNC_ZD); GlobalVariableDel(GV_SYNC_LONGSL); GlobalVariableDel(GV_SYNC_SHORTSL); GlobalVariableDel(GV_SYNC_TIME); GlobalVariableDel(GV_SYNC_DEV); return; } GlobalVariableSet(GV_SYNC_ZG, info.zone.zg); GlobalVariableSet(GV_SYNC_ZD, info.zone.zd); GlobalVariableSet(GV_SYNC_LONGSL, info.longSL); GlobalVariableSet(GV_SYNC_SHORTSL, info.shortSL); GlobalVariableSet(GV_SYNC_DEV, info.developing ? 1.0 : 0.0); GlobalVariableSet(GV_SYNC_TIME, (double)TimeCurrent()); } //+------------------------------------------------------------------+ void EnsureHLine(string name, double price, color clr, ENUM_LINE_STYLE style, int width) { if(ObjectFind(0, name) < 0) { ObjectCreate(0, name, OBJ_HLINE, 0, TimeCurrent(), price); } ObjectSetDouble(0, name, OBJPROP_PRICE, price); ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetInteger(0, name, OBJPROP_STYLE, style); ObjectSetInteger(0, name, OBJPROP_WIDTH, width); } //+------------------------------------------------------------------+ void DrawSharedKeyLevels() { if(Period() != PERIOD_M15) return; if(!GlobalVariableCheck(GV_SYNC_TIME)) return; double lastTime = GlobalVariableGet(GV_SYNC_TIME); if(TimeCurrent() - (datetime)lastTime > 3600 12) return; double zg = GlobalVariableGet(GV_SYNC_ZG); double zd = GlobalVariableGet(GV_SYNC_ZD); double longSL = GlobalVariableGet(GV_SYNC_LONGSL); double shortSL = GlobalVariableGet(GV_SYNC_SHORTSL); bool dev = GlobalVariableCheck(GV_SYNC_DEV) ? (GlobalVariableGet(GV_SYNC_DEV) > 0.5) : false; EnsureHLine(OBJ_PREFIX + "SYNC_ZG", zg, clrTomato, STYLE_SOLID, 1); EnsureHLine(OBJ_PREFIX + "SYNC_ZD", zd, clrLightGreen, STYLE_SOLID, 1); EnsureHLine(OBJ_PREFIX + "SYNC_LONGSL", longSL, clrDeepSkyBlue, STYLE_DOT, 1); EnsureHLine(OBJ_PREFIX + "SYNC_SHORTSL", shortSL, clrDeepSkyBlue, STYLE_DOT, 1); string label = OBJ_PREFIX + "SYNC_LABEL"; if(ObjectFind(0, label) < 0) ObjectCreate(0, label, OBJ_TEXT, 0, Time[0], zg); ObjectSetString(0, label, OBJPROP_TEXT, StringFormat("H1 hub %s | zg %.5f / zd %.5f", dev ? "(dev)" : "", zg, zd)); ObjectSetInteger(0, label, OBJPROP_COLOR, clrWhite); ObjectSetInteger(0, label, OBJPROP_FONTSIZE, 8); ObjectSetInteger(0, label, OBJPROP_BACK, false); ObjectMove(0, label, 0, Time[0], zg); } //+--------------------------------------------------------------------------------+ color DetermineOverlayColor() { long fgColor; if(ChartGetInteger(0, CHART_COLOR_FOREGROUND, 0, fgColor)) return((color)fgColor); long bgColor; if(ChartGetInteger(0, CHART_COLOR_BACKGROUND, 0, bgColor)) { color bg = (color)bgColor; int r = (int)(bg & 0x0000FF); int g = (int)((bg & 0x00FF00) >> 8); int b = (int)((bg & 0xFF0000) >> 16); double luminance = 0.299 r + 0.587 g + 0.114 * b; return(luminance > 140.0 ? clrBlack : clrWhite); } return(clrWhite); } //+------------------------------------------------------------------+ int ColorWithAlpha(color base, int alpha) { if(alpha < 0) alpha = 0; if(alpha > 255) alpha = 255; return(((alpha & 0xFF) << 24) | (base & 0x00FFFFFF)); } //+------------------------------------------------------------------+ void ApplyOverlayLabelStyle(const string name, ENUM_BASE_CORNER corner, int xDist, int yDist, int fontSize) { color textColor = DetermineOverlayColor(); ObjectSetInteger(0, name, OBJPROP_CORNER, corner); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, xDist); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, yDist); ObjectSetInteger(0, name, OBJPROP_COLOR, textColor); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize); ObjectSetInteger(0, name, OBJPROP_BACK, false); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, false); ObjectSetInteger(0, name, OBJPROP_ZORDER, 0); ENUM_ANCHOR_POINT anchor = ANCHOR_LEFT_UPPER; switch(corner){ case CORNER_RIGHT_UPPER: anchor = ANCHOR_RIGHT_UPPER; break; case CORNER_LEFT_LOWER: anchor = ANCHOR_LEFT_LOWER; break; case CORNER_RIGHT_LOWER: anchor = ANCHOR_RIGHT_LOWER; break; default: anchor = ANCHOR_LEFT_UPPER; break; } ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor); } //+------------------------------------------------------------------+ void UpdateTradeOverlayText(string text) { string name = OBJ_PREFIX + "TRADE_OVERLAY"; if(ObjectFind(0, name) < 0) { ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); } ApplyOverlayLabelStyle(name, CORNER_RIGHT_UPPER, 14, 18, 7); ObjectSetString(0, name, OBJPROP_TEXT, text); } void UpdateStructureOverlayText(string text) { string name = OBJ_PREFIX + "STRUCT_OVERLAY"; if(ObjectFind(0, name) < 0) { ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); } ApplyOverlayLabelStyle(name, CORNER_LEFT_LOWER, 14, 18, 9); ObjectSetString(0, name, OBJPROP_TEXT, text); }

Refresh