//+------------------------------------------------------------------+ //| AF_Engine3_Render.mqh | //| Project : Algo Forge (refactor total) | //| Sumber inspirasi: SniperGold SMC Pro+ (c) Waseem Shahrukh | //| https://www.mql5.com/en/code/75466 | //+------------------------------------------------------------------+ //| Engine 3 - RENDER DISPLAY (murni menggambar, TIDAK menghitung) | //| | //| - HANYA membaca output Engine 1 (AFEngine1MTF) dan Engine 2 | //| (AFSignalOut, AFAggOut, AFDisplayData). | //| - Tidak ada perhitungan analisis di sini: semua struktur, zona, | //| level, bias sudah disiapkan oleh Engine 2 (AF_BuildDisplayData | //| di AF_Engine2_Display.mqh). | //| - Meniru tampilan kode asli 75466: garis struktur (BOS/CHoCH), | //| swing point (HH/HL/LH/LL), Order Block, FVG, premium/discount, | //| level MTF (PDH/PDL/PWH/PWL), sinyal (entry/SL/TP + panah), | //| dan dashboard (bias, ringkasan struktur, likuiditas, konteks, | //| level kunci, alignment N/C/E/P, trade setup, legenda). | //| - Non-repaint: renderer dipanggil konsumen HANYA saat bar | //| tertutup baru (lihat AF_Engine3_Display.mq5). | //+------------------------------------------------------------------+ #ifndef AF_ENGINE3_RENDER_MQH #define AF_ENGINE3_RENDER_MQH #include "AF_Engine2_Display.mqh" //------------------------------------------------------------------ // Konfigurasi render (diisi konsumen: indikator / EA uji) //------------------------------------------------------------------ struct AFRenderCfg { string prefix; bool showStructure; bool showSwingPoints; bool showOB; int obCount; bool showFVG; int fvgCount; bool showPD; bool showLevels; bool showSignals; bool showDashboard; int fontSize; string fontName; color bull, bear; color obLineBull, obLineBear, obFillBull, obFillBear; color fvgLineBull, fvgLineBear, fvgFillBull, fvgFillBear; color premiumLine, premiumFill; color equilLine, equilFill; color discountLine, discountFill; color mtfLevel; color textCol, accent, panelBG, panelBorder; bool panelTransparent; color sigEntry, sigSL, sigTP; }; // Default (warna LuxAlgo-style, sama dengan kode asli 75466) void AFR_DefaultCfg(AFRenderCfg &cfg) { cfg.prefix=AF_E3_PFX; cfg.showStructure=true; cfg.showSwingPoints=true; cfg.showOB=true; cfg.obCount=AF_E3_OB_DEFAULT; cfg.showFVG=true; cfg.fvgCount=AF_E3_FVG_DEFAULT; cfg.showPD=true; cfg.showLevels=true; cfg.showSignals=true; cfg.showDashboard=true; cfg.fontSize=9; cfg.fontName="Segoe UI"; cfg.bull=C'8,153,129'; cfg.bear=C'242,54,69'; cfg.obLineBull=C'91,156,246'; cfg.obLineBear=C'247,124,128'; cfg.obFillBull=C'9,15,28'; cfg.obFillBear=C'28,13,15'; cfg.fvgLineBull=C'0,255,104'; cfg.fvgLineBear=C'255,0,8'; cfg.fvgFillBull=C'7,26,16'; cfg.fvgFillBear=C'27,8,10'; cfg.premiumLine=C'242,54,69'; cfg.premiumFill=C'27,10,12'; cfg.equilLine=C'178,181,190'; cfg.equilFill=C'20,21,24'; cfg.discountLine=C'8,153,129'; cfg.discountFill=C'7,24,16'; cfg.mtfLevel=C'33,87,243'; cfg.textCol=clrGainsboro; cfg.accent=C'33,87,243'; cfg.panelBG=C'12,16,22'; cfg.panelBorder=C'40,50,62'; cfg.panelTransparent=true; cfg.sigEntry=C'8,153,129'; cfg.sigSL=clrTomato; cfg.sigTP=clrLimeGreen; } //------------------------------------------------------------------ // Helper gambar //------------------------------------------------------------------ void AFR_TrendLine(string name,datetime t1,double p1,datetime t2,double p2, color c,int width,ENUM_LINE_STYLE style) { if(ObjectFind(0,name)<0) ObjectCreate(0,name,OBJ_TREND,0,t1,p1,t2,p2); else { ObjectMove(0,name,0,t1,p1); ObjectMove(0,name,1,t2,p2); } ObjectSetInteger(0,name,OBJPROP_COLOR,c); ObjectSetInteger(0,name,OBJPROP_WIDTH,width); ObjectSetInteger(0,name,OBJPROP_STYLE,style); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,false); ObjectSetInteger(0,name,OBJPROP_BACK,false); ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,name,OBJPROP_HIDDEN,true); } void AFR_Text(string name,datetime t,double price,string text,color c,int fs, ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT) { if(ObjectFind(0,name)<0) ObjectCreate(0,name,OBJ_TEXT,0,t,price); else ObjectMove(0,name,0,t,price); ObjectSetString(0,name,OBJPROP_TEXT,text); ObjectSetInteger(0,name,OBJPROP_FONTSIZE,fs); ObjectSetInteger(0,name,OBJPROP_COLOR,c); ObjectSetInteger(0,name,OBJPROP_ANCHOR,anchor); ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,name,OBJPROP_BACK,false); ObjectSetInteger(0,name,OBJPROP_HIDDEN,true); } void AFR_Box(string name,datetime t1,double p1,datetime t2,double p2, color fill,color border,bool back) { if(ObjectFind(0,name)<0) ObjectCreate(0,name,OBJ_RECTANGLE,0,t1,p1,t2,p2); else { ObjectMove(0,name,0,t1,p1); ObjectMove(0,name,1,t2,p2); } // OBJ_RECTANGLE: border = OBJPROP_COLOR, fill = OBJPROP_BGCOLOR + FILL ObjectSetInteger(0,name,OBJPROP_COLOR,border); ObjectSetInteger(0,name,OBJPROP_BGCOLOR,fill); ObjectSetInteger(0,name,OBJPROP_FILL,true); ObjectSetInteger(0,name,OBJPROP_BACK,back); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false); } void AFR_Panel(const AFRenderCfg &cfg,string name,ENUM_BASE_CORNER corner, int x,int y,int w,int h) { if(ObjectFind(0,name)<0) ObjectCreate(0,name,OBJ_RECTANGLE_LABEL,0,0,0); ObjectSetInteger(0,name,OBJPROP_CORNER,corner); ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x); ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y); ObjectSetInteger(0,name,OBJPROP_XSIZE,w); ObjectSetInteger(0,name,OBJPROP_YSIZE,h); ObjectSetInteger(0,name,OBJPROP_BGCOLOR,cfg.panelTransparent? clrNONE : cfg.panelBG); ObjectSetInteger(0,name,OBJPROP_BORDER_TYPE,BORDER_FLAT); ObjectSetInteger(0,name,OBJPROP_COLOR,cfg.panelBorder); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); ObjectSetInteger(0,name,OBJPROP_BACK,false); ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,name,OBJPROP_HIDDEN,true); } void AFR_PanelLabel(const AFRenderCfg &cfg,string name,ENUM_BASE_CORNER corner, int x,int y,string text,color c,int fs,bool bold=false, ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER) { if(ObjectFind(0,name)<0) ObjectCreate(0,name,OBJ_LABEL,0,0,0); ObjectSetInteger(0,name,OBJPROP_CORNER,corner); ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x); ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y); ObjectSetInteger(0,name,OBJPROP_ANCHOR,anchor); ObjectSetString(0,name,OBJPROP_TEXT,text); ObjectSetString(0,name,OBJPROP_FONT,bold? cfg.fontName+" Bold" : cfg.fontName); ObjectSetInteger(0,name,OBJPROP_FONTSIZE,fs); ObjectSetInteger(0,name,OBJPROP_COLOR,c); ObjectSetInteger(0,name,OBJPROP_BACK,false); ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false); ObjectSetInteger(0,name,OBJPROP_HIDDEN,true); } //------------------------------------------------------------------ // Dashboard (meniru layout kode asli 75466) //------------------------------------------------------------------ void AFR_DrawDashboard(const AFRenderCfg &cfg,const AFDisplayData &dd,const AFAggOut &agg) { string P=cfg.prefix; int fs=cfg.fontSize; color bc=(dd.structure=="Bullish")? cfg.bull : (dd.structure=="Bearish")? cfg.bear : clrSilver; // ---- panel bias (kiri-atas) ---- AFR_Panel(cfg,P+"P_BIAS",CORNER_LEFT_UPPER,12,30,252,180); AFR_PanelLabel(cfg,P+"L_bt",CORNER_LEFT_UPPER,24,40, "AF BIAS: "+(dd.structure=="Range"? "RANGE" : dd.structure), bc,fs+2,true); int y=72, dy=22, xk=24, xv=132; AFR_PanelLabel(cfg,P+"L_b1k",CORNER_LEFT_UPPER,xk,y,"Structure:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_b1v",CORNER_LEFT_UPPER,xv,y,dd.structure,bc,fs); y+=dy; AFR_PanelLabel(cfg,P+"L_b2k",CORNER_LEFT_UPPER,xk,y,"EQ Pos:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_b2v",CORNER_LEFT_UPPER,xv,y,dd.eqPos, dd.eqPos=="Discount"? cfg.bull : (dd.eqPos=="Premium"? cfg.bear : clrSilver),fs); y+=dy; AFR_PanelLabel(cfg,P+"L_b3k",CORNER_LEFT_UPPER,xk,y,"Liquidity:",cfg.textCol,fs); string liq=(dd.eqhSwept||dd.eqlSwept)? "Swept" : "Intact"; AFR_PanelLabel(cfg,P+"L_b3v",CORNER_LEFT_UPPER,xv,y,liq, (dd.eqhSwept||dd.eqlSwept)? cfg.accent : clrSilver,fs); y+=dy; AFR_PanelLabel(cfg,P+"L_b4k",CORNER_LEFT_UPPER,xk,y,"Signal:",cfg.textCol,fs); string sig=(agg.dir>0)? "BUY" : (agg.dir<0)? "SELL" : "WAIT"; color sc=(agg.dir>0)? cfg.bull : (agg.dir<0)? cfg.bear : clrSilver; AFR_PanelLabel(cfg,P+"L_b4v",CORNER_LEFT_UPPER,xv,y,sig,sc,fs); y+=dy; AFR_PanelLabel(cfg,P+"L_b5k",CORNER_LEFT_UPPER,xk,y,"Score:",cfg.textCol,fs); int pct=(int)(agg.score*100.0); AFR_PanelLabel(cfg,P+"L_b5v",CORNER_LEFT_UPPER,xv,y,IntegerToString(pct)+"%", pct>=60? cfg.bull : (pct>=30? clrGold : cfg.bear),fs); // ---- panel bawah-kiri: ringkasan struktur / likuiditas / konteks / level / alignment ---- int bw=180, bh=78, gap=10, bx=14, by=14; AFR_Panel(cfg,P+"P_d1",CORNER_LEFT_LOWER,bx,by+bh,bw,bh); AFR_PanelLabel(cfg,P+"L_d1t",CORNER_LEFT_LOWER,bx+12,by+bh-12,"STRUCTURE SUMMARY",cfg.textCol,fs,true); AFR_PanelLabel(cfg,P+"L_d1a",CORNER_LEFT_LOWER,bx+12,by+bh-34,"HH: "+IntegerToString(dd.HH),cfg.bull,fs); AFR_PanelLabel(cfg,P+"L_d1b",CORNER_LEFT_LOWER,bx+95,by+bh-34,"HL: "+IntegerToString(dd.HL),cfg.bull,fs); AFR_PanelLabel(cfg,P+"L_d1c",CORNER_LEFT_LOWER,bx+12,by+bh-56,"LH: "+IntegerToString(dd.LH),cfg.bear,fs); AFR_PanelLabel(cfg,P+"L_d1d",CORNER_LEFT_LOWER,bx+95,by+bh-56,"LL: "+IntegerToString(dd.LL),cfg.bear,fs); int x2=bx+bw+gap; AFR_Panel(cfg,P+"P_d2",CORNER_LEFT_LOWER,x2,by+bh,bw,bh); AFR_PanelLabel(cfg,P+"L_d2t",CORNER_LEFT_LOWER,x2+12,by+bh-12,"LIQUIDITY STATUS",cfg.textCol,fs,true); AFR_PanelLabel(cfg,P+"L_d2a",CORNER_LEFT_LOWER,x2+12,by+bh-40,"EQH Swept:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_d2av",CORNER_LEFT_LOWER,x2+108,by+bh-40, dd.eqhSwept? "Yes":"No", dd.eqhSwept? cfg.accent : clrGray,fs); AFR_PanelLabel(cfg,P+"L_d2b",CORNER_LEFT_LOWER,x2+12,by+bh-62,"EQL Swept:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_d2bv",CORNER_LEFT_LOWER,x2+108,by+bh-62, dd.eqlSwept? "Yes":"No", dd.eqlSwept? cfg.accent : clrGray,fs); int x3=x2+bw+gap; AFR_Panel(cfg,P+"P_d3",CORNER_LEFT_LOWER,x3,by+bh,bw,bh); AFR_PanelLabel(cfg,P+"L_d3t",CORNER_LEFT_LOWER,x3+12,by+bh-12,"MARKET CONTEXT",cfg.textCol,fs,true); AFR_PanelLabel(cfg,P+"L_d3a",CORNER_LEFT_LOWER,x3+12,by+bh-40,"Price in:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_d3av",CORNER_LEFT_LOWER,x3+95,by+bh-40,dd.eqPos, dd.eqPos=="Discount"? cfg.bull : (dd.eqPos=="Premium"? cfg.bear : clrSilver),fs); AFR_PanelLabel(cfg,P+"L_d3b",CORNER_LEFT_LOWER,x3+12,by+bh-62,"Bias:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_d3bv",CORNER_LEFT_LOWER,x3+95,by+bh-62,dd.structure,bc,fs); int x4=x3+bw+gap; AFR_Panel(cfg,P+"P_d4",CORNER_LEFT_LOWER,x4,by+bh,bw+30,bh); AFR_PanelLabel(cfg,P+"L_d4t",CORNER_LEFT_LOWER,x4+12,by+bh-12,"KEY LEVELS",cfg.textCol,fs,true); AFR_PanelLabel(cfg,P+"L_d4a",CORNER_LEFT_LOWER,x4+12,by+bh-40, "PWH: "+(dd.pwh>0? DoubleToString(dd.pwh,_Digits) : "-"),cfg.accent,fs); AFR_PanelLabel(cfg,P+"L_d4b",CORNER_LEFT_LOWER,x4+118,by+bh-40, "PDL: "+(dd.pdl>0? DoubleToString(dd.pdl,_Digits) : "-"),cfg.accent,fs); AFR_PanelLabel(cfg,P+"L_d4c",CORNER_LEFT_LOWER,x4+12,by+bh-62, "PDH: "+(dd.pdh>0? DoubleToString(dd.pdh,_Digits) : "-"),cfg.accent,fs); AFR_PanelLabel(cfg,P+"L_d4d",CORNER_LEFT_LOWER,x4+118,by+bh-62, "PWL: "+(dd.pwl>0? DoubleToString(dd.pwl,_Digits) : "-"),cfg.accent,fs); int x5=x4+bw+30+gap; int bh5=bh+22; AFR_Panel(cfg,P+"P_d5",CORNER_LEFT_LOWER,x5,by+bh5,bw,bh5); AFR_PanelLabel(cfg,P+"L_d5t",CORNER_LEFT_LOWER,x5+12,by+bh5-12,"ALIGNMENT (N/C/E/P)",cfg.textCol,fs,true); AFR_PanelLabel(cfg,P+"L_d5a",CORNER_LEFT_LOWER,x5+12,by+bh5-36,"Narr:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_d5av",CORNER_LEFT_LOWER,x5+95,by+bh5-36,dd.nBias, dd.nBias=="Bullish"? cfg.bull : (dd.nBias=="Bearish"? cfg.bear : clrSilver),fs); AFR_PanelLabel(cfg,P+"L_d5b",CORNER_LEFT_LOWER,x5+12,by+bh5-58,"Cont:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_d5bv",CORNER_LEFT_LOWER,x5+95,by+bh5-58,dd.cBias, dd.cBias=="Bullish"? cfg.bull : (dd.cBias=="Bearish"? cfg.bear : clrSilver),fs); AFR_PanelLabel(cfg,P+"L_d5c",CORNER_LEFT_LOWER,x5+12,by+bh5-80,"Entry:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_d5cv",CORNER_LEFT_LOWER,x5+95,by+bh5-80,dd.eBias, dd.eBias=="Bullish"? cfg.bull : (dd.eBias=="Bearish"? cfg.bear : clrSilver),fs); AFR_PanelLabel(cfg,P+"L_d5d",CORNER_LEFT_LOWER,x5+12,by+bh5-102,"PA:",cfg.textCol,fs); AFR_PanelLabel(cfg,P+"L_d5dv",CORNER_LEFT_LOWER,x5+95,by+bh5-102,dd.pBias, dd.pBias=="Bullish"? cfg.bull : (dd.pBias=="Bearish"? cfg.bear : clrSilver),fs); // ---- trade setup (kanan-atas) ---- bool active=(agg.dir>0 || agg.dir<0); int rows=active? 5 : 1; int pw=212, px=14, py=30, sdy=21; int ph=64+rows*sdy+8; AFR_Panel(cfg,P+"P_sig",CORNER_RIGHT_UPPER,px,py,pw,ph); AFR_PanelLabel(cfg,P+"L_st",CORNER_RIGHT_UPPER,px+pw-14,py+10,"TRADE SETUP",cfg.textCol,fs,true,ANCHOR_RIGHT_UPPER); int sy=py+38, kx=px+pw-14, vx=px+12; AFR_PanelLabel(cfg,P+"L_s0",CORNER_RIGHT_UPPER,kx,sy,"Signal:",cfg.textCol,fs+1,true,ANCHOR_RIGHT_UPPER); AFR_PanelLabel(cfg,P+"L_s0v",CORNER_RIGHT_UPPER,vx,sy,sig,sc,fs+1,true,ANCHOR_RIGHT_UPPER); sy+=sdy+6; if(active) { AFR_PanelLabel(cfg,P+"SR_2k",CORNER_RIGHT_UPPER,kx,sy,"Entry:",cfg.textCol,fs,false,ANCHOR_RIGHT_UPPER); AFR_PanelLabel(cfg,P+"SR_2v",CORNER_RIGHT_UPPER,vx,sy,DoubleToString(agg.entry,_Digits),cfg.textCol,fs,false,ANCHOR_RIGHT_UPPER); sy+=sdy; AFR_PanelLabel(cfg,P+"SR_3k",CORNER_RIGHT_UPPER,kx,sy,"SL:",cfg.textCol,fs,false,ANCHOR_RIGHT_UPPER); AFR_PanelLabel(cfg,P+"SR_3v",CORNER_RIGHT_UPPER,vx,sy,DoubleToString(agg.sl,_Digits),cfg.sigSL,fs,false,ANCHOR_RIGHT_UPPER); sy+=sdy; AFR_PanelLabel(cfg,P+"SR_4k",CORNER_RIGHT_UPPER,kx,sy,"TP:",cfg.textCol,fs,false,ANCHOR_RIGHT_UPPER); AFR_PanelLabel(cfg,P+"SR_4v",CORNER_RIGHT_UPPER,vx,sy,DoubleToString(agg.tp,_Digits),cfg.sigTP,fs,false,ANCHOR_RIGHT_UPPER); sy+=sdy; double rr=0.0; if(agg.dir>0 && agg.entry>agg.sl && agg.sl>0) rr=(agg.tp-agg.entry)/(agg.entry-agg.sl); if(agg.dir<0 && agg.sl>agg.entry && agg.entry>0) rr=(agg.entry-agg.tp)/(agg.sl-agg.entry); AFR_PanelLabel(cfg,P+"SR_5k",CORNER_RIGHT_UPPER,kx,sy,"R:R:",cfg.textCol,fs,false,ANCHOR_RIGHT_UPPER); AFR_PanelLabel(cfg,P+"SR_5v",CORNER_RIGHT_UPPER,vx,sy,"1 : "+DoubleToString(rr,1), rr>=2.0? cfg.bull : clrGold,fs,false,ANCHOR_RIGHT_UPPER); } else { string note=agg.reason; if(StringLen(note)>60) note=StringSubstr(note,0,57)+"..."; AFR_PanelLabel(cfg,P+"SR_w",CORNER_RIGHT_UPPER,kx,sy,note,clrSilver,fs-1,false,ANCHOR_RIGHT_UPPER); } // ---- legenda (kanan-bawah) ---- int lw=185, lh=140, lx=14, ly=14+bh+gap; AFR_Panel(cfg,P+"P_leg",CORNER_RIGHT_LOWER,lx,ly+lh,lw,lh); AFR_PanelLabel(cfg,P+"L_legt",CORNER_RIGHT_LOWER,lx+lw-12,ly+lh-12,"LEGEND STATUS",cfg.textCol,fs,true,ANCHOR_RIGHT_UPPER); string it[5]={"Structure","Order Blocks","FVG","Premium/Discount","Liquidity"}; bool on[5]={cfg.showStructure||cfg.showSwingPoints,cfg.showOB,cfg.showFVG,cfg.showPD,cfg.showLevels}; int yy=ly+lh-36; for(int i=0;i<5;i++) { AFR_PanelLabel(cfg,P+"L_le"+IntegerToString(i)+"a",CORNER_RIGHT_LOWER,lx+lw-12,yy,it[i],cfg.textCol,fs,false,ANCHOR_RIGHT_UPPER); AFR_PanelLabel(cfg,P+"L_le"+IntegerToString(i)+"b",CORNER_RIGHT_LOWER,lx+12,yy,on[i]? "On":"Off", on[i]? cfg.bull : clrGray,fs,false,ANCHOR_RIGHT_UPPER); yy-=22; } } //------------------------------------------------------------------ // Gambar SEMUA elemen display (dipanggil konsumen per bar tertutup) //------------------------------------------------------------------ void AFR_DrawAll(const AFRenderCfg &cfg,const AFEngine1MTF &e1,int sDisp, const AFDisplayData &dd,const AFSignalOut &n,const AFSignalOut &c, const AFSignalOut &e,const AFSignalOut &p,const AFAggOut &agg) { string P=cfg.prefix; datetime tR=dd.dispEnd; if(tR<=0) tR=TimeCurrent(); // ---- struktur (BOS/CHoCH) ---- if(cfg.showStructure) { int nL=ArraySize(dd.structLines); for(int i=0;i0)? cfg.bull : cfg.bear; AFR_TrendLine(nm,dd.structLines[i].t1,dd.structLines[i].price, dd.structLines[i].t2,dd.structLines[i].price,col,2,STYLE_SOLID); AFR_Text(nm+"_t",(datetime)((dd.structLines[i].t1+dd.structLines[i].t2)/2), dd.structLines[i].price+20*_Point,dd.structLines[i].lbl,col, cfg.fontSize-1,ANCHOR_LOWER); } } // ---- swing points (HH/HL/LH/LL) ---- if(cfg.showSwingPoints) { int nP=ArraySize(dd.pivots); for(int i=0;idd.swLow) { double rng=dd.swHigh-dd.swLow; double pp=AF_E3_PD_PREMIUM_PCT/100.0; double eqh=AF_E3_PD_EQUIL_PCT/2.0/100.0; datetime t1=dd.dispStart; if(t1<=0) t1=(datetime)((long)tR-86400); AFR_Box(P+"PD_PR",t1,dd.swHigh,tR,dd.swLow+(1.0-pp)*rng,cfg.premiumFill,cfg.premiumLine,true); AFR_Box(P+"PD_EQ",t1,dd.swLow+(0.5+eqh)*rng,tR,dd.swLow+(0.5-eqh)*rng,cfg.equilFill,cfg.equilLine,true); AFR_Box(P+"PD_DC",t1,dd.swLow+pp*rng,tR,dd.swLow,cfg.discountFill,cfg.discountLine,true); } // ---- level MTF (PDH/PDL/PWH/PWL) ---- if(cfg.showLevels) { datetime t1=dd.dispStart; if(t1<=0) t1=(datetime)((long)tR-86400); if(dd.pdh>0.0) { AFR_TrendLine(P+"LV_PDH",t1,dd.pdh,tR,dd.pdh,cfg.mtfLevel,1,STYLE_SOLID); AFR_Text(P+"LV_PDH_t",tR,dd.pdh,"PDH "+DoubleToString(dd.pdh,_Digits),cfg.mtfLevel,cfg.fontSize-1,ANCHOR_LEFT); } if(dd.pdl>0.0) { AFR_TrendLine(P+"LV_PDL",t1,dd.pdl,tR,dd.pdl,cfg.mtfLevel,1,STYLE_SOLID); AFR_Text(P+"LV_PDL_t",tR,dd.pdl,"PDL "+DoubleToString(dd.pdl,_Digits),cfg.mtfLevel,cfg.fontSize-1,ANCHOR_LEFT); } if(dd.pwh>0.0) { AFR_TrendLine(P+"LV_PWH",t1,dd.pwh,tR,dd.pwh,cfg.mtfLevel,1,STYLE_DASH); AFR_Text(P+"LV_PWH_t",tR,dd.pwh,"PWH "+DoubleToString(dd.pwh,_Digits),cfg.mtfLevel,cfg.fontSize-1,ANCHOR_LEFT); } if(dd.pwl>0.0) { AFR_TrendLine(P+"LV_PWL",t1,dd.pwl,tR,dd.pwl,cfg.mtfLevel,1,STYLE_DASH); AFR_Text(P+"LV_PWL_t",tR,dd.pwl,"PWL "+DoubleToString(dd.pwl,_Digits),cfg.mtfLevel,cfg.fontSize-1,ANCHOR_LEFT); } } // ---- sinyal (entry/SL/TP + panah) ---- if(cfg.showSignals) { datetime t1=dd.dispStart; if(t1<=0) t1=(datetime)((long)tR-86400); if(agg.dir>0 || agg.dir<0) { bool buy=(agg.dir>0); color cE=buy? cfg.sigEntry : cfg.bear; AFR_TrendLine(P+"SIG_E",t1,agg.entry,tR,agg.entry,cE,2,STYLE_SOLID); AFR_Text(P+"SIG_E_t",tR,agg.entry, (buy? "BUY @ " : "SELL @ ")+DoubleToString(agg.entry,_Digits), cE,cfg.fontSize-1,ANCHOR_LEFT); if(agg.sl>0.0) { AFR_TrendLine(P+"SIG_SL",t1,agg.sl,tR,agg.sl,cfg.sigSL,1,STYLE_DASH); AFR_Text(P+"SIG_SL_t",tR,agg.sl,"SL "+DoubleToString(agg.sl,_Digits),cfg.sigSL,cfg.fontSize-1,ANCHOR_LEFT); } if(agg.tp>0.0) { AFR_TrendLine(P+"SIG_TP",t1,agg.tp,tR,agg.tp,cfg.sigTP,1,STYLE_DOT); AFR_Text(P+"SIG_TP_t",tR,agg.tp,"TP "+DoubleToString(agg.tp,_Digits),cfg.sigTP,cfg.fontSize-1,ANCHOR_LEFT); } datetime tSig=(e1.IsReady(sDisp))? e1.Time(sDisp,0) : tR; string nm=P+"SIG_AR"; if(ObjectFind(0,nm)<0) ObjectCreate(0,nm,OBJ_ARROW,0,tSig,agg.entry); else ObjectMove(0,nm,0,tSig,agg.entry); ObjectSetInteger(0,nm,OBJPROP_ARROWCODE,buy? 233 : 234); ObjectSetInteger(0,nm,OBJPROP_COLOR,cE); ObjectSetInteger(0,nm,OBJPROP_WIDTH,2); ObjectSetInteger(0,nm,OBJPROP_ANCHOR,buy? ANCHOR_TOP : ANCHOR_BOTTOM); ObjectSetInteger(0,nm,OBJPROP_SELECTABLE,false); } } // ---- dashboard ---- if(cfg.showDashboard) AFR_DrawDashboard(cfg,dd,agg); } //------------------------------------------------------------------ // Bersihkan semua objek Engine 3 dari chart //------------------------------------------------------------------ void AFR_Clear(const AFRenderCfg &cfg) { ObjectsDeleteAll(0,cfg.prefix); } #endif // AF_ENGINE3_RENDER_MQH