From baa8ffcc3d4dc00cbf5cc126622af9a8761005f9 Mon Sep 17 00:00:00 2001 From: Bell Date: Mon, 11 May 2026 01:28:21 +0700 Subject: [PATCH] =?UTF-8?q?C=E1=BA=A7n=20c=E1=BA=A3i=20thi=E1=BB=87n=20ind?= =?UTF-8?q?icator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Đánh giá Indicator (dùng độc lập, manual trading) ⭐ Điểm mạnh # Điểm Chi tiết 1 Cốt lõi chiến lược chắc Trend (EMA200) + Momentum (RSI cross WMA45) — combo cổ điển nhưng hiệu quả: chỉ trade khi pullback trong trend 2 Không repaint Cross check [i+1] vs [i] — cả 2 bar đã đóng. Bar 0 (đang hình thành) bị skip. Mũi tên một khi vẽ là cố định. 3 Bộ filter đa lớp 6 điều kiện độc lập (trend, cross, EMA9 position, persist N bars, slope, RSI extreme) → giảm false signal đáng kể 4 EMA200 auto-attach lên main chart Trader không cần add tay 5 Tooltip mũi tên đầy đủ thông tin Hover thấy RSI/EMA9/WMA45/EMA200 tại bar signal 6 Clean code OnCalculate xử lý prev_calculated đúng, ArraySetAsSeries nhất quán, INDICATOR_DIGITS=2 cho subwindow rõ ❌ Điểm yếu (cho manual trading) # Vấn đề Tác động Ưu tiên fix 1 Không có Alert Trader phải dán mắt vào chart — bỏ lỡ signal khi rời máy 🔴 Critical 2 Không gợi ý Entry/SL/TP Mũi tên chỉ nói "có signal" — không có level entry, SL theo swing/ATR, TP theo R:R. Trader phải tự nghĩ 🔴 High 3 Không phân biệt signal mạnh/yếu Cross gần RSI=50 vs cross gần RSI=68 cùng vẽ arrow giống nhau → không có rating 🟡 Medium 4 Không có volatility filter (ATR) Trade trong thị trường quá lặng (Asia session) hoặc quá điên (news) đều dở 🟡 Medium 5 Không có session/time filter M15-H1 ở session Á cho signal yếu, nên skip 🟡 Medium 6 Trend filter có thể quá khắt N=2 closes trên EMA200 — choppy market sẽ rất ít signal 🟡 Medium 7 Mean-reversion bias Cross-back-into-trend tốt cho pullback, nhưng vào breakout/trending mạnh thì entry trễ 🟢 Low (design choice) 8 Panel position lỗi x=10 từ right edge → bị price scale che 🟡 Medium 9 Không track performance Trader không biết indicator này ở chart hiện tại win/loss thế nào trong N bar gần nhất 🟢 Nice-to-have 10 EMA200 attach có thể trùng Nếu user có EMA200 sẵn từ template → 2 line đè nhau 🟢 Low Phân tích logic chi tiết Entry rule (mạnh): crossUp && trendUp && ema9PersistBelow && ema9SlopeUp && rsiOkBuy Thực ra là pullback confirmation: trend up + RSI giảm về dưới WMA45 (pullback) + giờ cắt lên (resume momentum) ✅ Logic này có edge thực sự trên dữ liệu trending market Cảnh báo về pickup setup: Cross RSI vs WMA45 trên RSI có degree of freedom thấp (45 chu kỳ RSI rất mượt) → cross hiếm và đáng tin hơn cross EMA giá thông thường Tuy nhiên frequency của signal sẽ thấp — phù hợp swing trader hơn scalper Repaint check: ✅ Buffer signal được set TẠI BAR i (bar đã đóng) ✅ Arrow tạo bằng timeArr[i] (timestamp cố định) ⚠️ Lưu ý: trên timeframe nhỏ (M1/M5), nếu bar 0 đang hình thành biến động lớn, indicator panel "Trend" có thể flicker nhưng KHÔNG sai về signal đã vẽ Điểm tổng: 6.5 / 10 (dùng manual) Profile trader Phù hợp? Swing trader có hệ thống RM riêng ✅ Tốt — chỉ cần signal context, đã tự lo entry/SL/TP Discretionary day trader 🟡 Tạm — cần thêm alert + price levels Scalper ❌ Không — signal frequency thấp, lag Người mới ❌ Không — thiếu action info, dễ vào sai entry/SL Đề xuất nâng cấp ưu tiên (nếu muốn perfect cho manual) Alert system — Alert(), SendNotification(), PlaySound() khi có signal mới Entry/SL/TP suggestion — vẽ horizontal lines: Entry: 50% giữa close và swing low/high gần nhất (đúng spec ban đầu của bạn) SL: dưới swing low - ATR*0.2 TP: 2R từ entry Signal strength — coloring: arrow xanh nhạt (weak), xanh đậm (strong) dựa trên RSI distance to OB/OS + EMA9 slope steepness ATR filter — input InpMinATR, skip signal khi ATR(14) < threshold Win/Loss panel — đếm signal trong N bar gần nhất + giả định 2R outcome → hiển thị winrate ước tính Mình có thể implement bất kỳ item nào trên (đề xuất bắt đầu từ #1 + #2 vì là 2 thứ trader manual cần nhất). Bạn muốn làm tiếp không? --- .../RsiMomentumIndicator.ex5 | Bin 21794 -> 25806 bytes .../RsiMomentumIndicator.mq5 | 137 ++++++++++++++---- experts.dat | Bin 80083 -> 79526 bytes 3 files changed, 112 insertions(+), 25 deletions(-) diff --git a/Indicators/RsiMomentumIndicator/RsiMomentumIndicator.ex5 b/Indicators/RsiMomentumIndicator/RsiMomentumIndicator.ex5 index 72b1d7540c3032fce83c2c1d740118a7c86f0336..c97355a5151a965219daf322d8df32cbcf6f57a4 100644 GIT binary patch literal 25806 zcmeFYQ>-vd5G8nR+qP}nwr$(CZQHi3@7lI)WB*BZl9_p&$IVu!)2B{VD(Ox?R4O^5 z8mu6W0F!6}AOHve0Du6;AOQcHK}?rP9|4;D!$FOCit?dX_}_y6Ib{DQ@jw0lw~iq^ z0Kos)10awT|15mB6u=I^1;F(`B>5jQ`HwdSF#M0P2XOjdOaK4)|3fdp2tWtG@Zb8s zHMJjp_c^%%qg2JUaz>uF8#EhJzO=;DE8@f>&qmeT&}zDZq;l{TR(c?|mj$>UM%&Q? z=j8#2xu5&wR6boDBSZ2ZqM}|ecrX&IYV%x6u9-N#)if6Wv^JBtS=q6)8`PB^A3@OQbs>{?edl$ z34p$s`*P#EMnAkTMc}T+le|sRTJ-g74s$6fQXL4wm^Aa9$*vq%aWE2OHccCX!3r6t zlxfg1d+To56&n%))p@R&k7zg-%66ICBAY_6js-S)55e^m;xyorX_$TZ!KoC$B(u3n zwji^UU8)qDH$f5PZ|Oh{&ioxbgnDaPfv1jfyz}5T>YDKzd=y@+n{qW3T`|<=&~`Uq z%Jqc@JDj@@fpa{q`GK@~GfY2|IZR|$>3Jh8v7|u=^f@-OyA1;3u+NOXMd9oPOB93@ zbK~RApf=%sfpP#P&c0|vi?OS=I%OY3Nr$J36AVh%GoVtf+OX999U7L1%C9H24_UjS zfuCO0{o(G`DU{w&MYsBpzn3l!;DDB1&%kHTH^XO-8%=FS=kHu7_X3t#)i4PJv+6kC z$H5i%xLRCqXo^liOa5VW1WB)IyS_Ha{0_~iR^n9R9r-Qc*=G|#S^LB{4n64`a=xVA zdvgCF1ZE8dpORV78rqT%$xICL8dvQh zA9SMSXt{?tNf%4q)Rni#07A$7QeGyFRWs+fa1Nboz1z%&;IImd!cz`H&_IWb=JzoMO`G3pK>m^=D(~Vr+&!&HU}`i&0y9NOdDZ`{ z7WG{98r<&#)+1w_D>drNPqW*t8N? z5#*_mNDuR1^;w4jza-`B>?_8M_>33|l)_5SJV7PENMy<2$Z34nEj-qR_w(QHncsMX zAj_~4jsr=SV&Av8v=`U%ZX}PRZ3+xZ&MNmz#Sq3%f;kKsXgm7n6jOkC`;EFKqq)bL zas_AZQ(yG_RZveenf?Af00A>hU_j-|e@iz9x^^C|fv%-0G6|#0$V`A%{+ZxA9)@^h zwC9zYL}u%Q;cE8IZ&o@SbNMKV!-l>|YC2IjKW?-5I7fXFZDb0m0Lo$8yk=k1Pjb!J z4@bXR@aAX89bWel&&i7MIx^wrrjm>@>Rxy#m2eJjlI-m5Mm|-iPl+wmV`6wZGbVO8 zo@`iYZO=CzmqA3ny<{w?I&LWAXiHfWQU}tTH#nsZU=EJhJbiol0TB9#cPVkX*=tZj zq_91GMFuw7^n-LZQ(|+7ci2+EFg0Y9^h>}}YbHx&N3H9qHQT(sYbX!gc?NYr#JdHB zlN3Y{f4;=KBzw77(AeS=CsB{A)V58M3qcO+iL<&!V?{#<^i&-I2)D z1TF{_yTK~$2FPm@_B-(QiBmPoYyF#+gCwkOg4vl2X9`j$Azm8?U~IO{dp1Q;XP0;- zS>A#9!<|+L7hocr6V2p_TdxkDJKN)g0)4m(hQnq^YU}lef4C}JhiPfRuF<>H zneX{F4nEo+h7M9m*0VSc77PF#%I~lLy(3YZ?kTt}7Ak|)WWq+3bFubS|r86lpnicPCO?-*!9r6ZZ4*h`9frfq4 zPpaCh67UhqFRA7|MZBMpq32@P%_xc<>(h3WpC5Eks*{#>{SB5eW&o-Hj3B!at`CF|DTa@Sec zfr!Wbnjspn8%HM_ekot(q=ZQ9cu#$mn8`*V zwByzbFeB_e1W3LoTftFRh&WWSZxkNP-O zjeiw$Oi_C$-yV2VW$Ciq!Dqk3{A;E=+{*#~31l%bdD#PER{J2xN zAp9esU{mUVIO#_*@awA94Nx<8MF=Uu#ro0>+)}Ise{SRYt)^bZYP=CBL3L9dwHvKt zsUM>C&fV2$mhs1UAq9YS9>6OClV-->Pc9;X7Ks*vs{JZ z#i@eHt&)nnSAo~i2)L9dPE-A17CzHg;ry*Sp)U{d6scqGsPpNqW4n1LgR1~+Xo62# z2?UYdS~&PTg}w2yF5U?y$&|Hh$Eb<&Y2WdLw-?b?I1+Wae z;a44D{cs2TA*p6}fginmO#elPbS`p6HAplE@Im;Sjq%Kx`UvRE`c`Pg`2kwtb+U+d z>a?Y-F6WA+{^A3wNI9pJ4#;!@&hUgfeut84Knlbjn1}}>0VAlNIKfQEDEDxE*M2Dv zj>JC?EoiI(l3Zd}RqJO=xJqFvQCEoW9Hh$_5mV~FGXO4v@=l*k5WemZ2P!5yrWtqk z@FGvgdcv@(*KnoS#Fmssqkah_S-Fw>q`VFMHS95dKB#%gsmdu1o0!lT_&UA8hJ!}! z{-1=J`EIDST~!(l!&lCMYMN>mrafIYxj(HG&QpsJp!YBN>jh(gYm4RB842;ND!DF( zj)(98Z4&2dENbr}-kn)3){wN?l>KLoHS&kDNdyCagQ&_WDEkLr^YrRiCEm3jSs>DK zEOk`(Ga3BV@nzrUI9tHvs?2xgmtue@wmQN`oiuWS4m>HINcNE)oW@AL#{1kVNk{1z z)8uy%>f6YYs7vNmEA4(r;kaklt{(CQizq1pZxr}h@EC^DJl#TLSG^t!m$vDYl zt%Nj9;g3J$t^t={ydA)XdVzsPhf5Kn3&Xwq7IOdG5_sEW4Wb^CB?#%7sG?2(<}!#% zR>JUtT_c!Ycp47N)sa7|bnu9)n4~@2cXR`0ZY&2XU>|r|a>9M$P6j{ye#MYV+y+ip z-l=`;m+E}IBK7KrdaJLgKGgi^byU^o&hwy)0^tWTm!id_{6vE?)~r8~3IB{hl}0XM zoJAcW!OQ)K&5ZDthF9uWd$wK=CS4r+e>+3=E~;c1aDG}r7jUl-^;^kZZJm*GV$n3n z`u%URY3{n!T^fj25Gk|fKh}{DX(dmOs871cM<>Sv@eTukp+&9{*)Gc6NoDUDjZPa# z-fbptsdG4TfzS{3YHMrO4>NJYj2|t|v-NH^VTg|A?`HsMX(A`!&qemR=|SEjY@!-J zian=j5hqF{2CihvoXH|%(w-qhA6PP}8mzyWy15Q&3Jx-CRg80oy z&8-1lA1qzsXJj^veBc|HDND7yBXcxH3=rW!i@oRRwfp2JkYfE{u4$dUD>lK`iQwyI zbEoi+o)Z5K|E$gEA@^A5T|d}jRqJgWDI97}$-{96%E9dH-~1I>l3_O6FzIiVeHM@m z*pHen>nbfvpQmP$n=(fN-Zps^QH4HTh7;+~L^=7-TWWj)e z51y8#X9&^U$@Po*>zFV%$6u-@1DcY`W)-nqq407j6scd>PjW>)Abw1p{13cV&a`|S zvh{gm*3qnYd6h#38Pyru6TG;6AAmhBx|G&hPLq>5E9ZQrG)n3pSNXc`TmHmX5y^+c zUd9~RzUNNF!tr0xotJ>|#etRfoNWO*b#|Pyuk>(}X7eS-i(Fn5Ea71^)lcFTHZVan za640-w3$)C)PzWh35&k3aS=$YDYlTHy72N@#M8WK*sh;8P6tP<0)>1ya7riZyZy9_ z>kZMX1%U&^dcYZuGy7&95uClSSEc<~n#mg{gHJdHZ#(WG73iV|GYa<-<(`WP?9SkH z=6$nz>R1|>@DKx(KuB-iu_#n$6ebw9wyv?M$N6%s`{iQJO9l@%Mo%$?Jip3Zf}} zeC34Ny+B*+wEsTDwFier`_`wYi#F52|q(^~E z=WctT8h+y6w3_48?KA}TZdc1_BB7XS`#|N60ioBwI&DSXTU2edK5f*hL+?Y)M_DkO z6W>`0#i&@Jhmc4$V5^UbZFlP=Bwm3V(1A4$P_)4e)AAz7(nC7(DQQy*QvKEjPdd({NlJ(zU_QDmGdqBrXmriZco%E${2r}rfyG_ zkW0b>6HGXCYk%&+FF+GFZTr=)3jgR@me`Zlq_E%0E2i74vFdAv##o$>hREPJk))k0Jh;l|U}4`4o~rz3yz+_FUUR zU=Y*#zXI;l%zYF)sf_vT2+k!Y7Ty@{b^CArOU5eB$#MuW$q%fq7?1vbM2jV!T77@; z1mj}pRI=Z4f1-h2_H9Xf`GxiK?vZs-Ub%q4^CQSYfFPGjN5ae99j#I7`x3W=EpDu;8|MX__Q+;I$O zY!0);>JHq%iWW$(a6(5yxU69l3!a+cF6f`2BGa%E%sZ|KjNCL=KyO2YK9)?}lvO96 z+eKgn{io&PMWOW+O;ff-sNXAJT};VAvEYU{z)kCe8QmDCj$&IN?w<>^4NCYPCdtDK zKm#Dd&1vQc+uPWRbAD5}b;U_7Fo9!?gICBxOx454=kk2YwTqvo!qv)P@tL04at@rR5j;FzI8_$OMvNfFwmGa^2J>tp)7F{I?>yn;`Fc^l_(>C#`TQ zjHFwV-Y~|*n0+~`Vn_7Y)OML*2o%f1#H+&Y*9TO;6MB;>*u9wQ5CO2HYoiNSbmTSp zQLe~BBF%XG+nB0u2A&|i7~nXt9SmMtIF>=2LT7rr9mATY3>hO(Al`~&o%D?9Z9fB> zkw5b8n*II|@#D74G94o?%?k|`zCC+Ep4C+p*DUy)hLpZh1l_1yaJlISRKel^LF?(3 z`=mr@gBCW~0OHdURlV)W(rKh!d)+e`)ye=3n>J)-3O~YGsp4-Hv~sVH#s_PX+6pWb zr8ayV9jHOe0QbBH7h^bAZ)Y0?z?z7*>o#P2>LTSd(X+4b_9vthD6o(N$Fq7Mk;vOi zVNy{$|I#5CNE%yJ+^d!ktL?mqaRQ8btdfuTN8!v_a%&POo{PvzPD7seds)@1EHtLl zlOi<_A9?8wKB#D6)9XcnTUy1clMIDgL-%H|OoKu?euPi=m&bDg+$LW3(YAO3m6`0U z4uU9Z#{W~4O)V+WJ1W^7`j4leZ9_1^mC;o1xZ5d?`s5i8&6xLvTIauZ0`aGlo(GkE z3$M8OytW7UGjEI}3Lsz&0WBZ>mKT^@orzv4`AfH>S=CTQHbsk{hs`h@cRPc``w)@! zVv9XUFVJMwsP83zGJm|^oGCQ@$ucN$B$Mj{=F;M-Lri%Z@~$O>U45nq4gpa64A+*9 z#d8(??IKVtH^UvWhWn#hjZ`#*--mEFh6+GA$GhCivZ{lVi=HW1G!?y-+WUl378l)p z>G9qYR6P%kDC~BR#U4%NLTh(!A$ui7Kj7aX1(#uMClKf3#WAP@8yd<79-D6SF;JJ# z9Vaqa7pjvSHT6o^;I%r}t59S+?> z5a&`MLE=MHhpUc=w7;8akZFz1&SJyef@$Z8P6CgW@1I&sNbF|y3n8W~UjM&YvK9wd6<#BIbEdMG1aJORS=)e`Zje9wwopdJW+n6MYy$da2H`xWBb!+?G15T%| zLe7m|Hl}-3R4d2jyLh46_E7(;q-8BM*JiNW7c8+2Z4A$U@-XwA{ld`3ylw9cL@8LNZS20nHR-OqLxckAtB7PmU9d*xa5yO>CA`0GC1ac zg$fp~MwaSB!7=jz3cK*u)1ofi#Sf3(s(79Ma&yJ5e-<0`6QSoAAQT$N2w5pt1fs!U(+gJ`{4=IuXv>p`?MO?tuqs*V!*K(Gc^4^vGlI%- zB!|fWjtqXsbVILS${ebd(DSUoO#+~}GzFPP;XV(Jcgmt}nSLi&U5) z?mgu*k{y>1!0G`n@1Q->six9W%owKCmz*f(cWYr;A|wp54ec_hA$SjbLfQ9)B){jk zSY%7&=qNRcWS;FayOZ?LK~nIwvg0C$ zi+tEQM(QZEsfmzoge-K!6yicM^w_ifxG8_fLxAGmQS{RkWh7$TxYtw{pSj#O{k`NFmjx&V+u7pPE;v!liKD4-J(c7A;#I#w170z~*pBMchASTm3V?Hl zbje%U&nOZ$(E*3Bk9>O6ZS)+a1X#rgxVQB0Yq))d6kQ!x;tzLsC=4l}2yoTva4ULk@7wN}1@kWgAI;L6jDf|8PcHmI2GkgEm+4(KLOlXz%GbNF2V7j7H_9B27u0y?Hk?1(re{t2+7XihKP#H0yZ;QvYbwj|E!54K=*c za9Zlb;yDJy4u~i=dx$r%zUp%asZVO_GxrEXXjEZ3u5qu3{$kLRfiT$(9DqJR_ss@h zp;-!amyYMdbocsa?Odjhh>*?O;dYq7#SjDx1&kXEx`B@r%;!8)YjZAraXQkaqCi(~ z#8NxaV+%@;aUGxbbrMgvEyTah3;O!T6=a8UVek_V-;?hT5gb zov%=Mxr&VvQ?fvy(fB;SA*Ozq*Jh@YOr-Jq7xVleWENtB=P2Dq>qd5zO)HgBM1gq< z;u2U3S9V}8?nDk8*W?@T+5U0anB|bS9qL|QGWuK9MOfXp-Hg$9bE#Q+m#)jo(wswwWOKv*>PYddz(f4Y&2N5gO>DUv_)b}RYKt6n+~M!R zJmurhIA8m{bG_cUN@mMf!~BFTdAX9(fDn)yl_P-DI*vg#%C;=^LS9dVAATi0oUZE_ z2}4U*P%p$?{y?|u=z9;jc&{xa6ks!!cN4<<)fcyqBTEh*=}rf)>HpZzt`BdQW? z-FYfGgJmKvIP+LCw^U%nYl`a51ss2>wIO*8-B~uw<{|!~{>J9^OTn0&5sLpRE3{nP zulgN<&LtwVTs`?9AN$KbYMPPlw^D4D&J^K6hJmjnmJX()MbA`@XiKDVmVf|huI17Z zbr(?I({`iC+)jvA7NRyMjTajJR_F3Bx}xL7Z2AOQK{{YH)OTEHwRu6sw@5QGMf84k zm)q}6Av}}@4^Zl%f+nJh<_>*Vtl{w0O;AUj?Kkpne_~H&S3FA})EGSFw)&AG&{(QR z7V)qfZAuzveydsEEU?`*U0fxgaGBeyHf$>0K&xxeMLP}g!j}n~00eIy$o)fpo(V(@ z_DZTW4@l}R9C^l~HC}wsDt4F*J+3)UuW*QRsP67U_Qf=-GlrO|5nTXTbi9BK zt==1}xMVLnhz)T{DWp|2?4hJ*7eo4@yoAl91ZVWm8Q<9HR!p4?1}@~DEif^?prVM$ z;{0c&uNfj{cXP@=V1*dHuEt*3?Y@>9={z;Ey9Y#2m%EW&{#rK6W8rk>WB${kZfVD& zHV7lkAOGfZ--i>(2iMg!)MVKV36C49j2~yntc&h#n(Sh(eqTj;ssu*3LtHIua5wkj z>!J-+O&bI+dHg(uNQuiMLg8tSI(qo32!BJ}@bBce6IcKRCE+AX*m!8w8$^k(+1nN3VVe!#d+)}l#Cp%6KZx`%Er^RQ%kT9;XMPYRFxglMZKe2_q$>wpm6_ocUO^BAj&8=@54DQs`1T^_EKNHHm#+{+q~ zGDUgI+~rMwYf|Uhj@ZKq$w<S#B0MJ9jXMCLmLAa@XX&Z8L7VQN0v60$-{EN8te>y@9)(W3|e^E1(U8H z1ST$Jnem%mYwBlP1XdG9m`FE{j+^^n`)xH>9S;-*A>Hk~BH&tikz$n?4*2C~w_n2) z*Iu%{Lqjz_!`-X9F5D}c25b&c)481?5Kk+NpQcY#1*ZN1D|BUsDe799LuSO}>WmXb zhcUQE(^X&i)XiMbMxo$Ld0i!cQ)!*XB7T{De)HerRB2uxlZQ5>v<=Nu$wadFJVQVY zr<}pOF+Hn`$5dC;7M`bP97)z~bP8g_cs%J$EZ_`fwYIFW;; zYCH)v{f0Ky|7MeGrKx>skzJ&&){dG)$2`LPa63r0Vqupm)ApUGMdNGdF_$-XWBXWr zX*tikRJDjhp~{B++WCWaVSx4yOC@fRpHP)I!}+c4Rxs<-o=)2w08rXadC+8vV_dV9 zfXdt@E!FR8`A#2%W-~ncvqW8kJ&;m0?fY$bR*G3%Wfr#=osDfYR@Z$1t9o9{U$-PU zB)otn0}F`}NjzzZR_g#B!w~7EbA+~iWR8F+Qhfqu!$H7^pBS&6YU`GWiR)n#;7N5b z-^#W^y}*%_%+!W~+>=qPX0lmIuBsS+nj_i>!S?bg_>}txQ?+v6xTV8|66r}^Gb>>W zoGH!`%Hw6eV`;;>GGbF0l+Ty7Oz8 zQCQTqVhhmd`A|n`EhHGX609Ca$f6GEf_Hw=f4$`((ufFulYIG}TaODlY_nxTYp+Bw z+|htU>-LH)U$*ywz2$#J>wlSy<$($kddcydV;^lzJ+FDq5~$jV<_7U7r*cR{QxHOKw^3UKLL6>r5j zS$oKK+U*aAY;;wDp_x#}0_GV~)Gcl3p7x-mqS$U)7s#mqjyYV-al1z(N0pWs>7#09 zsRd*LpO{MMdehwM+$@As&oT&?+E89%Bh_F8^BAc64m|!nY62o5ff>U7KmuY$OU_k<=6{JSTHSt~)AJU53G6 zogiIjE!&xt+5{ij$hzNZeg-b*(&o0}E3{{`ya>JJ)5xMqnEkAQqBv`ge z?ULMxjl=TkYK1$v>8pF)R@}nyB1hyTP}({4S`{D#Fb_@-NQ3(SdL64oc)Z4=Q6*jv zqnhjpvV248$@BHH^3#q4SbWj;;AEk6DHw<<5#=`JjT1$bGVd(nFQzk)DK{ zq%MWQiIj+r{I^zNPtDf(Zd?88H2f%?i6JqSH3Mf5px*?7JYvE`d7Zat-q3b-`^BlJvwe*&=$E4--1aWFK}BX;tEAeV6Bn-4XXaEh)FBTS zHjWaRryrbliITf=%0-|DN|y#$-#L%`6RcxaZB(oS27h_wfx(ZAIZ?EK3e~-thIyK% zIsv|wu6I&5W1RA~rdqo80mlK?MA$`dqo#Y%_OcPsb#V90#q}Lg$UYf&6 zbw`bYp}Nl2&pP!Mo!DqsZY_-HM#@&~(fQr~r7g5V5dcwR2SDXP#?`&BeN6`h?z0WX zZb)sA5H3wKZ~+#2?-d`sWE>`4mmvT5sd(cQ76Rq~w!MsJ$4tkPLQ&9a>RG7(JfyJ+ zM0_QZI+2ps3c{a}h)?EF57yE_2ASHx0>`gP?a`tU2Jb~*m*=g2n##p}uV*Gf;sD0m z%dYnS?sJXP0{h+CihA}EK7+1&JG!TDaAnb}KZmROEbSXiV1$CyTBzH+E`45xf5fbt zNqp@-tyXMsfTAZZ~!y3u6k>{ZDW$y9mxX>z6&k2#d_^02$(4S5J?Z0?e;1 zu`n~K^5WQtLF&Zp+`!dj3B@RkzXs@#sz3(4)t(?QK2(z^0|@B3YNx-Ba#BD9bd~yf zX$;F&PO5#4$28W00ilYLQ?t4>Wm!RNoap;$+&`;X0^=(dtb~k8^$hZac)Q6l=JV9&Ot9+LsDJTukFurYrZx;%8eEKDt-mr^J)8UD+#Vu{%Zzk?ae?2`LK414l840 z2~pG;Vtk8B(f5wYTh8YU*wt_=D|D0Toogx|3sC`;jje^biUFlU0&BAhee`Nrm_l5A zUQ-YjU-R6Eqky||$>}Ik_=8`;qX)|%3}l$;?iO0eCb(0NoJv-q^z702fXcC24;2!j zUg3{FzOH>ue)zYuJg4sUs~(1Z1(T*{|1J?DJOOcb5H8@S80{NyyE@vWEcf`|q3=vn zZ5?|x3Ib9JqK1Gp`PZ z?SzPffx`fa1;<$gvE^y*;hNY3J*);ghw!5XVE}4#)`FBifkl|Lgug~JEw8}chgAi! z=J_*1coX0ow}%phy*c7F?!elsB}IgIfsa=#R-Q|Kyv{;ICtHkT z9I7!P>U%>L>K!05dN)5^p172K)=)lr=XaVPXw`ndY7PA*Kt3p8>;x3>4Lq^S{RT$GaH#J>tE*~?1h<59kcZ|l zD|4@}N40dgi-6>8_f{pU7F<}7`mh{IyKW!S|L4AodYbo?Nq-v}K&b^kT|Q{?SZ+q& zl&EK4NtIy2pL}OJ7QI^ep&7Mc2}CanV-?2l<-P#1vT9Pe1f~w>UIx(bj+xe>>+)%Y z-VpCMT^8h9-)xzTj0Z|^V2a0TzekifxW-6up*H@)k~u_&f6r_Y!Weg8`a?Ntksc|N zU`vJ}K^4#qqwNz@JT=Qj$_!Y16dLKYL?>apt-zB*=?L0A#yX}SqX zgt8IUeR-4s5P%_G&9kzeF4Y;acVt_X(I#%&(xa#8Ep{~|utDyC9HjcsG&U`q*}qJ2 zD*gnTa*Eh3LZ>wlxtzoPhOZ*fC33}fmH%9`?1JW|3w4ljT%D7Ls)q1}q*{bsnhWjIi(4u6A?j%;fjWA|q25`6V+(%-C$pbbF>6`BfW{n_fWa&DA zd7IZ}x{(c&6j7v2EqrSlsQw#3(Jf4`xN^eGywEzHF)tBDk1k3FetGj3V53D`CjkF; z)o;ai!|S!hLZt*RGlzL58Ace+mR_q=4o4#aNqy7nU;)s~Oo``~Vw3{3s2+W6*hbCh zxDyJVb}a(`p9~4U0qn&!LIT1ILlhK*5wftvFBvevAq4_Ih?Z&$mev^f=NYFY3Y2_m za`;ZtrWBiHbr}?6_C@uISpS64#r<+5Io2qEU&aj;#@9n?+A?wrWjIr%c(QZ%u9Qp& zZPU~p4#3#rojXC8Hv&75VWO3SML`k^Sm`5dBcwOgm79}b!17XuzLO*!K4ohDqy2t>1t9q}|L z*2oJS?kX|J%z^^!-%`CEE+6-A7mJC2p@-7Q*@t2TJJ*~d2&q7o9ic2WO|_8# z39Jzcd2|o_2IYoa%QJ@FoJpqqQnZPHHAxj+7>1pG_jN$yFoCxOFB3|PPjvM*A0v?V1$THz>FR&x1AxK2J@;mbu_Qen z=zhSas%@5GNB|# zxrDWZIN{ut`6}1VYmG%_9x_D*rgG`)|mtwvfl2^e{aPFa=+VOBsG$~x3jz;A$_0r3aVlMb&c|0=oA zyzNqNk*#C^-vniPmIX}q!b^u9FE01+1fQQc7ceuo)r?qE;+Y(_^*fdprX+Hyjp`{5laZ_>t z`~r6-*V>)A^RsKo&7unGo~`FoTdG~5Chy}*o8fQPaonZkK&#;abU-<<3HfURP@d*+ zc>$zg?@)(ZI;{L&03S347ufn8TI?%c?cLOEzztOTO;Dbq{{yRynmbMhwDem|dF7WC z2bHVP*-+|A;ZW!AQ1Z~7*z8CG52(;UF1|Q1s9Wd|A{T#xFNT zQeyrM(+wdKN%)h&E78;XM2jVSo(x0m^z0vGFUNAZ#IcsyX3Q3PSPQf(9Ii~Z4m)V6 zuD~i+HEE$JHzCTQZ4qzB@Ch^6W7Q1vWcdMN4>I*0{gBd|No`E442C~{nmr634pNWp zJQ=eOwNMVImS@FmwF2@>Zp;Ogw$JvB;>)J|`Sc&!4_mb~g?e~qqh1)KabjLE!$uwE z)Jgk`{T0*Ld*`^xIz@-B!USfs1rA>~V==1#p+MWPj@v(!P%PZd{8t$PBvS>!k;4?2-+mXv$`Ct!SzEu+Pyu)6qfR523h+Sf>=Gt7?CRT;a+Iz2y*^i zf=9|V6Uo=3fZGxj&#kvX-wwOC2klK0tOt%;O+|A47}gde7h4h{$(*83`gT)DVrGmf zTM1WTAU~j>l(andO-(qbX{|~o6gM+T|4(QJ5&ku}n<~=;e^|a03tG`9YnEYTt>sk& zb~Z0-iQH3LrRea2ZS;thCcCptn2rbp(|04&9KfAWCd2Q+Q?8ZUVwG*cIq#{JdWq` zjK~h?-g>VsfMk%?cDPGEX9~&d)plg3xTWt4s{eq$kB)T*V;tY@^H2TCNr4Bl zLs)@xB9vewfHg>&Y+a#PZl9WVSJTNF@Vcdg_>heiP_R-g2EdpTPYW^@{cW<|m$qa& zvtrAFFUTpm>V((;N1ebYj&VKm%nSQSQ9iu16kLjY#RY~5{SM4clzScNBBOHOw*oH1 z)MKvt>?m@v#jiF?OIeNlT)hc2o$<#yFo$*fPqRjq6uId{ZWdubB3-sHuiJDc63O2z zgIyH-N($-u6+#*9i1@-gd>h#&B(cZrcdc;ci1A>&$!u^Q(I~tU-(F-~)`$dGwEuO4 z6yYF{4kJ}3F18`%ueu-9(Z10&3|NkdT^@M0ho4_W`L<#3^w7ds=H(xIUU;ZfM!_j# zbnXWri=fm=o5*oLMEL3x!_Rn@Wx;?sA#nY>FEux#bPrY}F0WyPxAFMpE8Qz#|AGbZ z)`eS##QSt@g3j<7E(xEMmj*}rNI?1YfFSMBGigDBB4IUttJPNkVc0Eb@&N!3(tE5n z4LTpZV;j2WCkZm+&OGTUICVShwa!=lNcpOMA%WZzQRH~PrM#CIGUlkK7Ad_9c=ANv zFsI?^49F}gs-K#FrtGM>QQdb|ao5jbTX_P_qh?nDhRqB;$DWo54go|7urU`KtRm!% znDd=B9^H0-1IMw^it+$ZOCh3z)iKtqUNezq6aS(FpbOjw-L!UI?fnslpMF*Q-=7mC z-VM^6)z;>YU*t!_ygT(2rur9sv_e!mL+$+Jz^Euz%GWmWW1DWmZac;_;=il~qhAr0 zL8su6CmX(%$0m6?Tw2tp-aZz25=dA>wnCQg9q5zTiJ%IYUT9l=hFAOkn57FBW@Crs z&5v^|J-5Eip2aVpDBDL~ZX_Y>6>4=ed^d0)5@;*uO^rMa&H{sC>OuwK1r*lit4)+j z7<>9;9^Bw>rlG&#t*$YwM>B`vssJg==N(+LfLBljC!~f)YO-6AxToiG{Bvg_`Ixz_ zF=_bcfr3`y3P?ckk)bY~8x-yW9^vgLhl8L}oGnfJR}vr?ucTwP-Fq1HU)_ zQolA^(+85TH9_4(Fhl~dUD_?j8*J|{_X^rNupoYgJQD#BM{R%Hgn>W~e+voQDIQe{ zoSiYH?C}vYkZr(&EZM+YFKiZzGXg+=j)D`j+Q#7`fr;}0k`TF9e5vmnE%Dmz6ZLfc zDY$OaNz*s{oghNR%$0U2-65{+=avI$;)ekS;jZ{g;+`b6bI|e1Ukn2IiK0cxC>wV{ zi7aF??rmg>${^qy^NquzT)u)pV*H&e(vcsyE$ZZnnJQ}Gp>Zz~w27BG5}`LH`3udK zjp4`%YX+jV9Qt7o%;EMKmlnaT&TLn2;J0nU?BMQ>b<9|@6|;+}vee`2qqo{YBlt0( zw<1+-=lzWYS>zP|;wdwdM%u~P*mbt;(D+oN%g?9yHa%24>@1~n4~301tep;4Cz=Wl zUE{^%s@gd-SjN;+k5t&i&;-M>-M+n({l1?&#poNYj3HG9Hlt{GFM-GYg=ZH0cVia69ejkU!G0rKl5)1m16Kn846wqmx_ z0<4eDPJR^#D(T469{mZEh_0{)ZnU1~KdeYI6DDkw%{Z^`DohuLsSU=jgm&8r zSNXNr&R{`SUo`+U*c$&mazan7A{?#7*?LDvc`sR}$LHNvJO{6K>*gF*Psx;DpT^nW zx?mVZzuFLsvznAwH(TWG0=oM_+|5vb8Fo=Y09ywBgr>5n1>jda+<;`^`#bay`e7W=s=MOz zj9==waZJ!3K#qzXrp#g3^kAMiRSv?li^QOdONcR3;8WM`SyLiiR=##uI?5SOtE8nu ziP2c7;RiteNm*n4EOT#={Lv>yxd(ECHsUV#+y5nol z$3HMIq8$%A^X}yJC}GH0F6WyPM&kTYYcGqY5ml2+i@R5Y_GLoeCRbw;pKvvmey^q{w!nK3K=;&JO642WdU({~(71{R`KINA=W7lkX*|SH zuF$B^kKhUNp%-YpH@Pc5H~ zjToGTrzbumbEXo;e)ny=FFALxLnk}R)oe#A)4sj)Qo%}KNns~B1J8-o&XBFXJPXS$ zFf_~P_QL#j%#iX#6&~F9QAJ+}VCU4r7tj~>M#5-MJH|GoOU5aG%GyPz8$`14Q5vUQ z_Hd~%z2gJ_Z3F%Gitv;S^vZY}Lx02!ocWg+=wL{#RJ)*6vk z>l+W}J6h2wm{OcKsiRU=N>Ou!WRf}s%V$@7PBT&;2b=`$M|%FY3QTbO^_XAjw_#Ve zNeqx@ax^tUF2Bd}9RBA7Y#_df6`PqA_xCc5CRo}lH`(Lc?KHI*_P{X#8XKo!w3WD& z&Rclj8(XR^&%y2c(*{7f84lFLoxcitD6DG|G+4sv*<6P0Tj|qps%_>au2#WLcPYwc z){CRcCc=Q)4>Kjd)Db5v{1Lkzcs3;Up8zi1^AwP|t>t)rX)2gEaRuQ4;L!qXy*Z}v zeKMO$if}zWm#@WGfvx_bpTE8@JPi|Nl-vOE-t^fvw52G)=H#W>{?sHoM%$gCvjiWueGX%XtEC_TK~sab(yED<=@1d>X>3@KJj0pY7Ru1W@~Rt9e#yjiY*YeX!9#gfi~(}5>K&l?0;(N z)wxI*8e6>WJbB$G!atlM>HzNqqM#l{s($}D%||RGq8<5T%LV?E1EAe&V@Nfpv#Jcu z#-8X%q(CJ6@VrIT6lipM4vvdV1MxKA$RdL6IaY?l75tljyUNmm%9LBO;Y)zO0sB~+ zq1xs$2jM@;DPTUVk>b|^nkfu86v$r(P;(OPT2ZJ2+;Job);`$(Oy{~agb(_xE7_#8L<^5p%s{#xw20#yXA!7%D0lD>*@gT_s~*&?5WTF~YZ?DgZSFq3Z3}vu z{67I$BB$MX=!z~WJkR4LCpU-F(+=<;xMI$7{bkMyz20stz44N}XTJgfaA-s|gBZ?# zp1WR}=Nn_wV&=|f%ReZJp(Ry3nqsm}f#djJ-9Jczold&1@|(@B`&-a`rHd~M>af10P9Pp5_Mp{q6O(8|ZS!pNZV%EPQIK1pk)jurnpcxz% z>ravT?FYNEUU;lOFUdTUkz;44L3vlMhRH+CY_qxIF|qEp`pcHQ&4UEkTGETMj4ICs z(_t&Knq?koM1(gZ=k+C#y+ z(g8s_`0zDY9mg@+Iq524R9wk;K}$1TwKJ^7M3}U=FzLwcEKJD$TN?Y4nEBt$6`TBr zkGP!QDsG<6AW??N`YKMkXQ7_pg_3L9KIiyX1P7)pl*Ac?GN#LZi?EPtThPgqV3dAva$4U~5vSbSnOHUQFw z$h3(Fru<u6T)l^k^Oz-p+Cn-yKFT`gFuTaS{e73C7K-R2&h75_rt71rIVxE1p2(owW*XJOm;RTq51D}8@celFU`$6bH-Z3Om^E@z zw*~#uk-yHY%eOoVTQ^OZT<4^03|08=~+-rh4EnU?z0#W?ml52LZ5 zff859*$DpC{xqt4N8bs2378QnSVlAuiJ4auk_PWlXztzcjbCh>H$Qy!W2BJ)NTO+2 zz)C~#p){sSNn-RxO~(gGu%R3mE-NyyCv5m&i$tx)I41n342Z(HLYoJmx!SUQ6M2Q9 zATGMWSd}S7DW;)vQS!U-6lhjP;5=bOGHO@4mMs;IKrZh`QXwCTMa9jNIg%v? zUOJ>|d_|qH^WelRqa2b$2NIEaflH{jmgg#4)qgmMnS-2%M>8Zf-TCg1D-Xgk3TWJ) z(4qY;r`H}h@bj4opAGSF;;o5(Zy4vvr+bZCy7DFCqu`AgC+l;pwYRlo;zSX=&PQ=& z4B%dCK63WGSTqK%m!ji8X}Ao@2h^6JWe6qsF?G@(e*>20L&is6j(loHzt4?H$UG&7 zo+47Q7aw<+(;-gzTkXhqnY>QOSVr?|V|+Fm;s2Y?9yw$e#w{UPN-6`*<4lAaczh7! zH?r@f~<}?`2l9V}$Jn7m?5;^@kLlb*+!4jca&%)7}S^BoVDwb^I znNB^kMqmKtX{D_0su*$lLNM8q+^pWEb><|0+Ihr1p`TE0F5H{#>}vA*5op~`I&Rl( z)O86HKpVN=Cgf$v1`?;_~GvWv)|CbX2N`0B=*&d{B!{0i)>+e zb{uh^cWgYIeq1=N+KF#_#r;5f7Z*;Yx)9S926%V3n>&c1Mxox`0{;!)oaIlTC8U*`F>&#<;ELJyYEJ(-)nYb8&C)nX6@H1hI@>7u# z1$~-GMiSD#=>Yc2qDmBs-0m^IW^5&hFUGGt!IZc1S#3F?>2?Au^Tcs8oh)oqUVpeXQ)db|@6{Os&@Rd)CQ1AaxJ?J& zsMLYY(=(ZUvd4PfXolK=FlY7T$#KyLEf~#pOz*@I?>-BXB6QJhRa9f5oZh~kQf*}& zaV(_q^}?{&exLNFB$shYhnDl5O{oNS)tN{=K*U> zP-DSIlD&cjw;py94pEHi9t_?B!?o38XIdW;;5oszkzel9DUu>Z0OFUQTqmqHc{eR$ z3MZ0YxvSglR!`4mzw1tR*uWt8@mtl-*dB*7@7BhCKu zO6y@n6~yIety*Jn>zjXDURuz~=iX^qr_B>!!~%bq0E89k2fwRaeLTGBsA&Ns)`a02 zbHcR}7o%}l%<;Y!x%gXM`LyDLR;%4vli4w?ac@Gb=0a#t>2F5f-{T)T^Wnt!1Q5}* zEe1kYa-%&xLr;l*O|~>HMM6o(K7$W;qFcn>Pa5@tjto4SODtH6nL=)x!jHzV3f}>M zZ}h}_reNb`C^@D^QFnQ-V+%FRQrk!w9+4E2g%(R@rAyBthyI*A{-tlW9gxso6z3Si zN6A*7fvV&|5xowB*cG@o=XD$p!Ajx9GjivaY9ca|||BllxB7j+p z^a2e+zNv*{Na;WlS*)i2hHG?$MjciL^XzqpqMl5$`kAb4_qRi?X`$jJaJ1wUW|zzl zKyamjN)za$mQ*{$$-{RymD$0v0>^55s&;-WLSlI-RnsH3J#?I%8%oSof*Jz@}REM-A%-Xq$I9N>J19V-j?BT>~ND_ZgoVX(oHc`apHNj^Ju> zk!htm++HQ2vomNXC=~RtGIHeD8u8MIwJ-AxnRu)?zpiB)fjB|<^IPJ4_Tn=sbL;Rr zB%E(pMl)`=cR=vp3|Xpw;a!Q@<^ePH8&t^aTqf-gg(2-fmH!Rv3A_3ZZ;nT*?#_P6siMJHuxoFDF zv)KtZvC~=8Bj7dF{y4kayCXhQa#my`$2kAe5byG9dS=F&!4+`60@=FQ@f8pAXal#K zg>KVRy95kWyC!`Sl<2lhe9a}bop(jJQvc#B^4AV6v+K-z--D-Oo9Xmyhym{cRCmES zt%pYqm)i<5OFQ%kX^vSMELyh~8I3u_w_W?X(Yip?B$4J~myW|g6D!83$V!HC6zZ`_ zTiX!Z+{malxcF*XoO)XkKDd0ABE9i_1o^LJ%M={b&T{vW3tz3H?c3xo81lfWm&^f5 z3h$s{3kd7(his$Dp)Pfh@RYcXZY*U zN*oX5PVyG(3{YR*Hm{v{TN?5CZ%GN)*|B7pg>^1MqsWs~W|Z+X|MP=iau~La9#k!T z&y3-rA~e7H_+WdgX2J=5nW>Um(}U^P29%C7Ztw92Zd90D0#Md!=QE{nwZ2KS@d` zMmBGQ^=$6&OH>yNVo5C=d4D4`EBqs@)4CI7z>XK`{+ZvM$4 zeB-XR)+B)=`efL-pk{IQ|^3#+o4iPhz)an&1^f z7JeCWk^(;0dFZbzJ-za=vYviAy!>urqIEBfj!}1^TdN%oQEf&vW>a3}CLL z?%d@s8B^ak+I+Dq_4={S`zv8sx_+XbtIGr|Ql%3XhsA}?M4^A7_aP#1juubAKMmNq z%jiVmxCv_t@we6Y4#`ia_tPj+hrRMpBW3|-FU1xzqD!~hR@fIi7m2B#u{i|sFt7U)2(}CQqBV+;w1OOaM8Q zx?RhN`AQ02)Wd_9?Ut7ZC1#(q6d>!YzNZAzsd(Dl!)b>`U4I3C&y3+KV5Zw4^j!D; z9*)Xi0dhID$47iSJSYgnMuzz8E(PYC$wLQ;>v>X~Bf)7urGko#nO@^v*Llb8IB$5u ztcFxQD`1u0o`X6mR_{X?dLBZOpO(*&w=kZ;GF%)!w2n@o_5cCj{p}_?o4|`qUX1Ct zjy<2Dh%QVEB1FnWlu@SeC2OGOxgos6<5Q0$#y9?Yj0`~l0qxC+3roGR^UAAXjtI== zat%R`7Sfh%(szIR=>yVk_&Ap3sV$TFk4fU*>$YHgLY(XV;f_buZniGMf z6+izWmvJ$J+2iEG;Lr&jexq(LL2t~OaUg<(YY{I-qdGt9JF5T#I9`*ytu@fO*)D2N z@PJvn%_?6$KSd=0gSspLLW@l!P^fH4%SL*4{)Rl0`C@8SP#K<9&;(K-YB4%PGk8W1 z{cxqbdpYpm45j(bFx2=+RZN9PZRS*W=n~TOYD5H9thTq6v!mSbQFcKB6hfbEMDtZw zKI8(y*!qC81Fi!-a_S#82{_Z0wNsBl<0kD39r7oWl;_9mZP`mdfkPzP2icvsL)i_P zAQj7j=MGj42&^&7MVaT_ClwxOQY`x8(FQw&L@D6U{FUjxAjIf6MLcykUDia`wjUr6 zhBNaFVoXg>PajwUWAD1l-0N0KA-5SjBBsP+dgW`y6+pD!6FYEuQkpeQZK&iJx(m`e zOd(c#d`Kva4kwvPk{tb$z-cW4j%Ar?@a3CPw*Uygx?bab_e+_N*~ict1m3KbgShQB z_S=$yu1A}2(sr8a_wFa@4~X^|inMg!RY3tGdC}720l4u>tEO>RY2`v=I)>f+nl|i6W235hgKPMRP&t%VU_qfg{?4u?t@fZ!=fX-lpGyr+4K=wxMCSEi&?C zy6o+!#@-kDMFh|H2^VxM1KK=SJ|Q8Mtmkd#H}px9$PPn^T*O~yhW0YYY1*M3FR$dI zq>ykduI^w|mTgW1F{^Kh6|m%R_w1rrz6TG+!DZ@%{!*aS9@W4q6oOFn{8ESTu+WD) zXh4)uvUZxBsnZPZ6xv88mw-T4%#%}v+s)3;?X~XHDk1F3+$x7V5~&MhOEgS=m7XM? z?zRh6ih{TO&^*`O{cWi};87TqrY2h&8wcm3C1uyk4dlgps3PV7j3-;?ZetnGHGYOY zINV|Tb;%dC0TAYOUvxrhShVR9(#L)UGH9Y6fCMO~s)4#6MMt%^CpPvtuK2iOxGyko zja`=gUe1{tEpN=Ph81@=9^?YA##h5rqd=9j=tq1g`wgg%uWP4O_t$`oo<4IL8(=^$ zuY&Z*3W8(0`BN8D-y2V)~c$+e4AA_~!3$T3RS!Pr>$55|&K`GMn$A z1J(IDM^}&`N3rkGw{*RbVDR)IK98rePk8~>=kfB;?%o$G zjIn$@Pkq{`e=d-cc^^Ie6E(Xvg+iC%7F?0nsuHcV)I@+4w!1QX?$c-NTW3Xo9x@!1Sw{$8^Y@0Hnwm zB^*^3J+>rAxZ@{#~4qqnL=z_Nx86^d(EChA~MLZpWu6sWaoEJ;9JD*E++XM`+s-!8cCtIn= z5=~a&%aLDwYoOI0-otunmM?=?x?Y0P-_{S&_i)|;a-3X#^v;gpHb6liJuPN>+W^aq zp3Eut&VAqE$Zm{FVuT8W)RE?SuA0wfIN^Np5%VvrP05g1Yn#x_&DORappOBE$)JH3 zM81N}S@bBNC*%6}U8b&OU<8RHo$)_4e{FWas)SNIDPEJ@oPjteRP8|)cpN~Gos`Xw zwJw~$Fp{h>SYIEJ=Y)krVLWxz}kxHVIHk=kJTN>!?-+-so5nPUB` z)iG@%#7z|C_ol__>#&e)?s@By)auK%;%O~M({7?JwW?qie8tU#e z$)j;vNPV*VyP#J_a|~cLmpfmtytC}C)J?nIPkA|8(c+?-@QRBlMnrw%LhpqkKJRk0?i_9p~m|`6fVio@MNGX%{~QzlM_e>2=vsD5>mvt`q8pzl@HVH zc@#+0TTlkPB5QLhCCN_cVzvbOL^3;7!DP+d%V?d6NsU@3REpk{_4*!Uuo(0rsq7$PpRP%Ww3K2wbY5>e%5c74N<8 z-F&f%N^T`)lU}muN}0VvPas)+qi@}1)^s!md?MmUou{az!m{hF4m19{&G}X&`>G5M z^_#hPkFhtg0lpJmlGqJXCXOjEP{90=Go)+h`FXBwZdy9_c(^JaVDBy)w^|<6VV~1C zzLQCd@lsl$otgpoa^^Hgkro~S>*cfP*5MX0@z#xesX~@(&2g3G^64Vv3WMKNk0`+Ef@azFCbKpp{Dj zXRx?$Y7Ubvr~64iiFbg?w2oXwGiaUWri(%`UiV8Nf+k9ur=HiDzc{AJI%Fh9yp~p| z{s;-@1@$gMqsWs~W|Z;2mPMzjkTz5kDjcGH&Ez@e8x2CJdzUg%aTQUBD*VGAF~$1O z(bKbU@fC-Az1X>LoD|see;Q8OVO9*nC~!xtVJ!DWfr=G_+9{&(d;va)jIT4yH_XC5Dl zsK^0y)s$aFSLsF+>%So*3b4+Nq{d9f7Skwlr|lwWJEJ~DWz`X;NV$Og4vxcugKtj@ zjm zHUt7+_JR=Xn|1~QL`o3G^dDExMlZ~Kwx00R>hIn<>)^uEr05b5S`Cc&vh%v*95)wR zH3T`in$ygjrwQhPWE_usz(?=#K!807cX;FGxDaN2IiWbLw~K9C#d*bsbwaw6J3TXr z)@ooz&4k@v9Th^nLPg%pmf})M`J(p+IDWHEMJZrshxaqcYTKe7FtFvMrIB$hukT?~ zm26D_EvIXR5v<^oC z2mr=+VkB*EAGV29HSkYfOR7}O6#L5{eq7jQhe}x4PXU}^x1v7*=k|jFt(6s^DvvvU zuIYPyVl9@`i3KxIo#NzbiNFEy6kn{V20DvWF0Cp1PMW<_kB z82SCUUC3#zWM*WkZBhyNCB72pN$n9}ZDgHYgZyfZ{wU}Rfm<8bcu`W%68*^{d|uXQ zg-ll4O#_-^wWK`*<@kXFtCtg^D3LjUtm}DyU@w%`hX*lIo8;zNq;Ig3>eaYYYQA9U z>71WNEjN_knQ_>0D2{30B{oDMWJhYB7W@0UTgqpzVrXJi>n|Di+lwFylgJaCRQ5owMo_1yqf*HK@_F`$uC^ctMFU{F})y zu;1i{*SCQJ>y$PM^dA62I)w-Wx^A$UIZW^Nedpwl=^-c~cs{w0b>@`OwD-DCW~)nT zt9rLzvKX=iJKt%iD?4zy<9K6Creb8-0EP?Ey%;C9(^Bog=?wD3=GG4*gsF5jM|IMn zcqfU9aThi83oWxOd^wIM&=yN>zS)ayavi3`ne{_Jt7|qK{enpN1`QH1OmiCX%v{2UOF9AMkJa{l`wuz~iY&{0ht#IO#^uaCc$r;Ty=ciz z#0JFjP0f3iJt=~y^=5TCxKMV-5_BEE&jvZ9QH<}13|4~e_ zXY%h+mqs&EUFF5_+TZIP^j!D;9*)Xi0dhIC#zuQMIVA%j3CopgdT;zRBz>EY?ka;TtiVg#py8bO*B-7A}-H%~&E^x5596 z^5Np({_ZEfJ+7;4eyj=0qEWN8oI+q9Hdx+RsAam|GYyj11*kP%l7c@U&X1)nXu-PY O;r)Lj0OQ)P-2!W8%mpL> literal 21794 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 FP-JW(6ZrrD diff --git a/Indicators/RsiMomentumIndicator/RsiMomentumIndicator.mq5 b/Indicators/RsiMomentumIndicator/RsiMomentumIndicator.mq5 index 92402b9..b3bc312 100644 --- a/Indicators/RsiMomentumIndicator/RsiMomentumIndicator.mq5 +++ b/Indicators/RsiMomentumIndicator/RsiMomentumIndicator.mq5 @@ -7,7 +7,7 @@ #property copyright "RsiMomentumIndicator" #property version "1.00" #property indicator_separate_window -#property indicator_buffers 3 +#property indicator_buffers 6 #property indicator_plots 3 #property indicator_minimum 0 #property indicator_maximum 100 @@ -40,7 +40,7 @@ input group "Chỉ báo" input int InpRSIPeriod = 14; input int InpEMA9Period = 9; input int InpWMA45Period = 45; -input int InpEMA200Period = 200; +input int InpEMATrendPeriod = 200; input group "Bộ lọc trend" input int InpTrendConfirmBars = 2; // số nến liên tiếp phải đóng cùng phía EMA200 @@ -49,6 +49,9 @@ input group "Bộ lọc RSI" input double InpRSIOverbought = 70.0; // RSI ≥ ngưỡng này → bỏ qua tín hiệu BUY input double InpRSIOversold = 30.0; // RSI ≤ ngưỡng này → bỏ qua tín hiệu SELL +input group "Bộ lọc EMA9 vs WMA45 (chống nhiễu)" +input int InpEma9PersistBars = 3; // EMA9 phải ở cùng phía WMA45 N nến liên tiếp (gồm cả bar signal); 0 hoặc 1 = tắt + input group "Mũi tên giao cắt" input color InpArrowUpColor = clrLime; // màu mũi tên khi RSI cắt lên WMA45 input color InpArrowDownColor = clrTomato; // màu mũi tên khi RSI cắt xuống WMA45 @@ -64,6 +67,9 @@ input bool InpShowPanel = true; double buf_RSI[]; double buf_EMA9[]; double buf_WMA45[]; +double buf_Signal[]; // hidden — +1 BUY, -1 SELL, 0 none +double buf_EMA200[]; // hidden — giá trị EMA200 (cho EA hiển thị) +double buf_Trend[]; // hidden — +1 UP, -1 DOWN, 0 RANGE/SWITCHING int h_RSI = INVALID_HANDLE; int h_EMA9 = INVALID_HANDLE; @@ -110,13 +116,19 @@ void UpdateLabel(const string name, const string text, const color clr) int OnInit() { // Đăng ký buffer — đặt AS_SERIES để [0] = nến hiện tại - SetIndexBuffer(0, buf_RSI, INDICATOR_DATA); - SetIndexBuffer(1, buf_EMA9, INDICATOR_DATA); - SetIndexBuffer(2, buf_WMA45, INDICATOR_DATA); + SetIndexBuffer(0, buf_RSI, INDICATOR_DATA); + SetIndexBuffer(1, buf_EMA9, INDICATOR_DATA); + SetIndexBuffer(2, buf_WMA45, INDICATOR_DATA); + SetIndexBuffer(3, buf_Signal, INDICATOR_CALCULATIONS); // ẩn — phục vụ EA + SetIndexBuffer(4, buf_EMA200, INDICATOR_CALCULATIONS); // ẩn — EMA200 cho EA + SetIndexBuffer(5, buf_Trend, INDICATOR_CALCULATIONS); // ẩn — trend cho EA - ArraySetAsSeries(buf_RSI, true); - ArraySetAsSeries(buf_EMA9, true); - ArraySetAsSeries(buf_WMA45, true); + ArraySetAsSeries(buf_RSI, true); + ArraySetAsSeries(buf_EMA9, true); + ArraySetAsSeries(buf_WMA45, true); + ArraySetAsSeries(buf_Signal, true); + ArraySetAsSeries(buf_EMA200, true); + ArraySetAsSeries(buf_Trend, true); IndicatorSetString (INDICATOR_SHORTNAME, StringFormat("RsiMom(%d)", InpRSIPeriod)); IndicatorSetInteger(INDICATOR_DIGITS, 2); @@ -135,7 +147,7 @@ int OnInit() if (h_WMA45 == INVALID_HANDLE) { Print("[RsiMom] Không tạo được handle WMA45(RSI)"); return INIT_FAILED; } - h_EMA200 = iMA(_Symbol, _Period, InpEMA200Period, 0, MODE_EMA, PRICE_CLOSE); + h_EMA200 = iMA(_Symbol, _Period, InpEMATrendPeriod, 0, MODE_EMA, PRICE_CLOSE); if (h_EMA200 == INVALID_HANDLE) { Print("[RsiMom] Không tạo được handle EMA200"); return INIT_FAILED; } @@ -195,10 +207,20 @@ int OnCalculate(const int rates_total, const int wmaBars = BarsCalculated(h_WMA45); const int ema200Bars = BarsCalculated(h_EMA200); if (rsiBars <= 0 || ema9Bars <= 0 || wmaBars <= 0 || ema200Bars <= 0) + { + static datetime lastWarn = 0; + if (TimeCurrent() - lastWarn > 30) + { + PrintFormat("[RsiMom] Source not ready yet: RSI=%d EMA9=%d WMA45=%d EMA200=%d (rates_total=%d)", + rsiBars, ema9Bars, wmaBars, ema200Bars, rates_total); + lastWarn = TimeCurrent(); + } return 0; // chưa có dữ liệu — return 0 để MT5 retry ngay + } - // Chỉ copy số bar mà tất cả source đã tính xong (tránh return giữa chừng) - const int srcMin = MathMin(MathMin(rsiBars, ema9Bars), wmaBars); + // Chỉ copy số bar mà TẤT CẢ source (incl. EMA200) đã tính xong + // → tránh CopyBuffer EMA200 fail giữa chừng làm buf_EMA200/buf_Trend stale + const int srcMin = MathMin(MathMin(MathMin(rsiBars, ema9Bars), wmaBars), ema200Bars); const int copyN = MathMin(srcMin, rates_total); if (copyN < minBars) return 0; @@ -235,20 +257,24 @@ int OnCalculate(const int rates_total, const double arrowOffset = InpArrowOffsetPts * _Point; + // Reset buffer cho bar 0 (đang hình thành) — đặt giá trị mặc định + buf_Signal[0] = 0.0; + buf_Trend [0] = 0.0; + buf_EMA200[0] = (need > 0) ? ema200Arr[0] : 0.0; + // Phát hiện giao cắt RSI vs WMA45, chỉ vẽ khi khớp với trend EMA200 for (int i = barsToScan; i >= 1; i--) { + buf_Signal[i] = 0.0; // mặc định: không có tín hiệu + buf_Trend [i] = 0.0; + buf_EMA200[i] = (i < need) ? ema200Arr[i] : 0.0; + if (i + 1 >= rates_total) continue; if (i + trendN >= need) continue; // ngoài phạm vi mảng cục bộ (timeArr/closeArr/ema200Arr) if (ema200Arr[i] <= 0.0) continue; // EMA200 chưa tính đủ bars - const bool crossUp = (buf_RSI[i+1] <= buf_WMA45[i+1]) && (buf_RSI[i] > buf_WMA45[i]); - const bool crossDown = (buf_RSI[i+1] >= buf_WMA45[i+1]) && (buf_RSI[i] < buf_WMA45[i]); - - if (!crossUp && !crossDown) continue; - // Lọc theo trend EMA200: cần N nến LIÊN TIẾP gần nhất đều đóng cùng phía - // Quét từ nến tín hiệu i → i+N-1 + // Quét từ nến tín hiệu i → i+N-1 (tính LUÔN, kể cả khi không có cross) bool trendUp = true; bool trendDown = true; for (int k = 0; k < trendN; k++) @@ -259,13 +285,47 @@ int OnCalculate(const int rates_total, if (closeArr[idx] >= ema200Arr[idx]) trendDown = false; if (!trendUp && !trendDown) break; } + buf_Trend[i] = trendUp ? 1.0 : (trendDown ? -1.0 : 0.0); - // Vị trí EMA9 vs WMA45 — kiểm tra "lực mua/bán mới bắt đầu chiếm ưu thế" + const bool crossUp = (buf_RSI[i+1] <= buf_WMA45[i+1]) && (buf_RSI[i] > buf_WMA45[i]); + const bool crossDown = (buf_RSI[i+1] >= buf_WMA45[i+1]) && (buf_RSI[i] < buf_WMA45[i]); + + if (!crossUp && !crossDown) continue; + + // Vị trí EMA9 vs WMA45 tại nến signal — "lực mua/bán mới bắt đầu chiếm ưu thế" // BUY: EMA9 vẫn dưới WMA45 (lực mua chỉ vừa nhú lên qua RSI cross) // SELL: EMA9 vẫn trên WMA45 (lực bán chỉ vừa nhú xuống) const bool ema9BelowWma = (buf_EMA9[i] < buf_WMA45[i]); const bool ema9AboveWma = (buf_EMA9[i] > buf_WMA45[i]); + // ── Filter PERSIST (chống nhiễu) ───────────────────────────────────── + // Yêu cầu EMA9 ở CÙNG PHÍA WMA45 trong N nến liên tiếp (i, i+1, …, i+N-1) + // - Tránh trường hợp EMA9 cắt lên/xuống WMA45 liên tục (lực không rõ) + // - Mặc định N=5: EMA9 phải đã ổn định 1 phía ít nhất 5 bar + // - N <= 1 → tắt filter (chỉ check tại bar signal như cũ) + const int persistN = MathMax(1, InpEma9PersistBars); + bool ema9PersistBelow = ema9BelowWma; + bool ema9PersistAbove = ema9AboveWma; + if (persistN > 1) + { + // Cần thêm (persistN - 1) bar trước nến signal cùng phía + // Đảm bảo không vượt phạm vi buffer (i + persistN - 1 < rates_total) + if (i + persistN - 1 >= rates_total) + { + ema9PersistBelow = false; + ema9PersistAbove = false; + } + else + { + for (int k = 1; k < persistN; k++) + { + if (buf_EMA9[i+k] >= buf_WMA45[i+k]) ema9PersistBelow = false; + if (buf_EMA9[i+k] <= buf_WMA45[i+k]) ema9PersistAbove = false; + if (!ema9PersistBelow && !ema9PersistAbove) break; + } + } + } + // Slope EMA9 — phải đang hướng cùng chiều với tín hiệu const bool ema9SlopeUp = (buf_EMA9[i] > buf_EMA9[i+1]); const bool ema9SlopeDown = (buf_EMA9[i] < buf_EMA9[i+1]); @@ -276,9 +336,9 @@ int OnCalculate(const int rates_total, const bool rsiOkBuy = (buf_RSI[i] < InpRSIOverbought); const bool rsiOkSell = (buf_RSI[i] > InpRSIOversold); - // Tín hiệu hợp lệ khi đủ 5 điều kiện - const bool validBuy = crossUp && trendUp && ema9BelowWma && ema9SlopeUp && rsiOkBuy; - const bool validSell = crossDown && trendDown && ema9AboveWma && ema9SlopeDown && rsiOkSell; + // Tín hiệu hợp lệ khi đủ 6 điều kiện (thêm filter PERSIST) + const bool validBuy = crossUp && trendUp && ema9PersistBelow && ema9SlopeUp && rsiOkBuy; + const bool validSell = crossDown && trendDown && ema9PersistAbove && ema9SlopeDown && rsiOkSell; if (!validBuy && !validSell) continue; @@ -288,6 +348,8 @@ int OnCalculate(const int rates_total, if (validBuy) { + buf_Signal[i] = 1.0; // ghi tín hiệu cho EA đọc qua iCustom + // Mũi tên lên (↑) đặt dưới đáy nến — tín hiệu BUY trong uptrend // ANCHOR_TOP: điểm anchor là đỉnh icon → arrow nằm xuôi xuống dưới price // → tip ↑ ở phía trên, sát đáy nến (cách lowArr[i] một khoảng arrowOffset) @@ -300,12 +362,14 @@ int OnCalculate(const int rates_total, ObjectSetInteger(0, arrowName, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, arrowName, OBJPROP_HIDDEN, true); ObjectSetString (0, arrowName, OBJPROP_TOOLTIP, - StringFormat("BUY signal\n%s\nRSI=%.2f EMA9=%.2f (slope+) WMA45=%.2f\nEMA200=%.5f (Uptrend)", + StringFormat("BUY signal\n%s\nRSI=%.2f EMA9=%.2f (slope+) WMA45=%.2f\nEMA200=%.5f (Uptrend)\nEMA9 below WMA45 ≥ %d bars", TimeToString(timeArr[i], TIME_DATE|TIME_MINUTES), - buf_RSI[i], buf_EMA9[i], buf_WMA45[i], ema200Arr[i])); + buf_RSI[i], buf_EMA9[i], buf_WMA45[i], ema200Arr[i], persistN)); } else // validSell { + buf_Signal[i] = -1.0; // ghi tín hiệu cho EA đọc qua iCustom + // Mũi tên xuống (↓) đặt trên đỉnh nến — tín hiệu SELL trong downtrend // ANCHOR_BOTTOM: điểm anchor là đáy icon → arrow nằm ngược lên trên price // → tip ↓ ở phía dưới, sát đỉnh nến (cách highArr[i] một khoảng arrowOffset) @@ -318,9 +382,9 @@ int OnCalculate(const int rates_total, ObjectSetInteger(0, arrowName, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, arrowName, OBJPROP_HIDDEN, true); ObjectSetString (0, arrowName, OBJPROP_TOOLTIP, - StringFormat("SELL signal\n%s\nRSI=%.2f EMA9=%.2f (slope-) WMA45=%.2f\nEMA200=%.5f (Downtrend)", + StringFormat("SELL signal\n%s\nRSI=%.2f EMA9=%.2f (slope-) WMA45=%.2f\nEMA200=%.5f (Downtrend)\nEMA9 above WMA45 ≥ %d bars", TimeToString(timeArr[i], TIME_DATE|TIME_MINUTES), - buf_RSI[i], buf_EMA9[i], buf_WMA45[i], ema200Arr[i])); + buf_RSI[i], buf_EMA9[i], buf_WMA45[i], ema200Arr[i], persistN)); } } @@ -352,6 +416,29 @@ int OnCalculate(const int rates_total, } ChartRedraw(0); + + // Diagnostic: log lần đầu OnCalculate hoàn thành full để xác minh data + static bool firstSuccess = false; + if (!firstSuccess && copyN >= rates_total) + { + firstSuccess = true; + int upCount = 0, downCount = 0, rangeCount = 0, zeroEma = 0; + const int n = MathMin(500, rates_total - 2); + for (int i = 1; i <= n; i++) + { + if (buf_EMA200[i] <= 0.0) zeroEma++; + if (buf_Trend[i] > 0.5) upCount++; + else if (buf_Trend[i] < -0.5) downCount++; + else rangeCount++; + } + PrintFormat("[RsiMom] First-pass OK rates_total=%d copyN=%d trendN=%d need=%d", + rates_total, copyN, trendN, need); + PrintFormat("[RsiMom] bar1: RSI=%.2f EMA9=%.2f WMA45=%.2f EMA200=%.5f Trend=%.0f Signal=%.0f close[1]=%.5f", + buf_RSI[1], buf_EMA9[1], buf_WMA45[1], buf_EMA200[1], buf_Trend[1], buf_Signal[1], closeArr[1]); + PrintFormat("[RsiMom] last %d bars trend dist: UP=%d DOWN=%d RANGE=%d (zeroEma200=%d)", + n, upCount, downCount, rangeCount, zeroEma); + } + // Return số bar thật sự đã xử lý — nếu copyN < rates_total thì lần sau MT5 // sẽ scan tiếp phần còn lại (do chênh prev_calculated) return copyN; diff --git a/experts.dat b/experts.dat index b78ab5616666feaba6546e19a627bbc795322f82..029014c8c9ad2e6ca0cd93a6452d9f00ab77a94f 100644 GIT binary patch delta 51 zcmV-30L=f>@dT#r1hA|D0gjW=a?7)L0z?4>QYryzlM#2%lW-3Zv!4XKUz3Pt9Fy=} JEVIyN1JXr_7A^n) delta 117 zcmZ4XmgVwCmJMqd8T%(+EIPfpg2{!ECF(Cj)?~r*^OFns1vbxT*%PlG#1PEj$>7G2 z&rrmW%#aG?l`td%aVmo=gCm0;kgi}bWnh@RFj8^zg|w%PlcQ5)xUorW?nsln001>Y BCGY?M