MQL5 交易策略自动化(第24篇):集成风险管理与移动止损的伦敦时段突破系统·进阶篇
(2/3)·盘前区间识别、挂单偏移与回撤限制,手工盯盘根本顾不过来
「伦敦盘前变量与面板底框的骨架」
做伦敦突破策略的 EA,第一步是把盘前区间和挂单状态全部塞进全局变量。下面这段把 Pre-London 的高低点、对应时间、买卖停损单 ticket,以及当日是否禁交易、回撤额度都先声明好,其中 PreLondonStartHour 写死为 3 点、分钟为 0,意味着盘前窗口从服务器时间 03:00 起算,做黄金或欧系直盘时先确认自己 broker 的时区偏移。 结构体 PositionInfo 里挂了 openPrice、londonRange(以 point 为单位的区间宽度)、sessionID 和 trailingActive,用来在持仓数组里回溯每笔单子属于哪一天的伦敦盘前。positionList[] 就是这些结构的容器,后面遍历持仓做移动止损时直接读数组,不走 OrderSelect 那套旧接口,执行效率高一点。 面板背景用 createRecLabel 画 OBJ_RECTANGLE_LABEL,函数入口先 ResetLastError 再 ObjectCreate,失败就 Print 出 _LastError 码。MT5 里这类 GUI 对象创建失败常见原因是同名对象已存在或图表被冻结,开 EA 前手动清一次图表对象能少踩坑。外汇和贵金属杠杆高,盘前区间突破策略在重大数据日可能瞬间扫单,实盘前务必在策略测试器用至少 3 个月 tick 数据跑一遍。
class="type">class="kw">double openPrice; class=class="str">"cmt">// Entry price class="type">class="kw">double londonRange; class=class="str">"cmt">// Pre-London range in points for this position class="type">class="kw">datetime sessionID; class=class="str">"cmt">// Session identifier(day) class="type">bool trailingActive; class=class="str">"cmt">// Trailing active flag }; class=class="str">"cmt">//--- Global variables CTrade obj_Trade; class=class="str">"cmt">//--- Trade object class="type">class="kw">double PreLondonHigh = class="num">0.0; class=class="str">"cmt">//--- Pre-London session high class="type">class="kw">double PreLondonLow = class="num">0.0; class=class="str">"cmt">//--- Pre-London session low class="type">class="kw">datetime PreLondonHighTime = class="num">0; class=class="str">"cmt">//--- Time of Pre-London high class="type">class="kw">datetime PreLondonLowTime = class="num">0; class=class="str">"cmt">//--- Time of Pre-London low class="type">ulong buyOrderTicket = class="num">0; class=class="str">"cmt">//--- Buy stop order ticket class="type">ulong sellOrderTicket = class="num">0; class=class="str">"cmt">//--- Sell stop order ticket class="type">bool panelVisible = true; class=class="str">"cmt">//--- Panel visibility flag class="type">class="kw">double LondonRangePoints = class="num">0.0; class=class="str">"cmt">//--- Current session&class="macro">#x27;s Pre-London range PositionInfo positionList[]; class=class="str">"cmt">//--- Array to store position info class="type">class="kw">datetime lastCheckedDay = class="num">0; class=class="str">"cmt">//--- Last checked day class="type">bool noTradeToday = false; class=class="str">"cmt">//--- Flag to prevent trading today class="type">bool sessionChecksDone = false; class=class="str">"cmt">//--- Flag for session checks completion class="type">class="kw">datetime analysisTime = class="num">0; class=class="str">"cmt">//--- Time for London analysis class="type">class="kw">double dailyDrawdown = class="num">0.0; class=class="str">"cmt">//--- Current daily drawdown class="type">bool isTrailing = false; class=class="str">"cmt">//--- Global flag for any trailing active const class="type">int PreLondonStartHour = class="num">3; class=class="str">"cmt">//--- Fixed Pre-London Start Hour const class="type">int PreLondonStartMinute = class="num">0; class=class="str">"cmt">//--- Fixed Pre-London Start Minute class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Create a rectangle label for the panel background | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool createRecLabel(class="type">class="kw">string objName, class="type">int xD, class="type">int yD, class="type">int xS, class="type">int yS, class="type">color clrBg, class="type">int widthBorder, class="type">color clrBorder = clrNONE, ENUM_BORDER_TYPE borderType = BORDER_FLAT, ENUM_LINE_STYLE borderStyle = STYLE_SOLID) { ResetLastError(); class=class="str">"cmt">//--- Reset last error if (!ObjectCreate(class="num">0, objName, OBJ_RECTANGLE_LABEL, class="num">0, class="num">0, class="num">0)) { class=class="str">"cmt">//--- Create rectangle label Print(__FUNCTION__, ": failed to create rec label! Error code = ", _LastError); class=class="str">"cmt">//--- Log creation failure
◍ 用 ObjectSetInteger 把面板控件钉死在左上角
在 MT5 里画自定义面板,控件定位全靠 OBJPROP_XDISTANCE / YDISTANCE 这组像素偏移,以及 OBJPROP_CORNER 指定的锚点。上面这段把 CORNER_LEFT_UPPER 写死,意味着所有元素都以图表左上角为原点往外推,xD / yD 直接就是屏幕坐标,不用管价格轴。 OBJPROP_XSIZE / YSIZE 控制的是控件自身的宽高像素,和距离参数是两回事;边框相关用了 OBJPROP_BORDER_TYPE、STYLE、WIDTH、COLOR 四个整数属性,想换虚线还是实线、几像素粗,全在这些值里调。 OBJPROP_BACK 设成 false 是把控件放前景,OBJPROP_SELECTABLE / SELECTED 都关掉,实盘挂 EA 面板时可以避免鼠标误选导致拖拽错位。最后 ChartRedraw(0) 强制重绘,改完属性不刷这行,界面可能卡在旧状态。 下面 createLabel 函数开头先 ResetLastError,再用 ObjectCreate 建 OBJ_LABEL;若返回 false 就 Print 出 _LastError 代码——MT5 里对象创建失败八成是同名对象已存在或图表 ID 传错,开终端看 Experts 日志里的 Error code 就能定位。
class="kw">return false; class=class="str">"cmt">//--- Return failure } ObjectSetInteger(class="num">0, objName, OBJPROP_XDISTANCE, xD); class=class="str">"cmt">//--- Set x-distance ObjectSetInteger(class="num">0, objName, OBJPROP_YDISTANCE, yD); class=class="str">"cmt">//--- Set y-distance ObjectSetInteger(class="num">0, objName, OBJPROP_XSIZE, xS); class=class="str">"cmt">//--- Set x-size ObjectSetInteger(class="num">0, objName, OBJPROP_YSIZE, yS); class=class="str">"cmt">//--- Set y-size ObjectSetInteger(class="num">0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); class=class="str">"cmt">//--- Set corner ObjectSetInteger(class="num">0, objName, OBJPROP_BGCOLOR, clrBg); class=class="str">"cmt">//--- Set background class="type">color ObjectSetInteger(class="num">0, objName, OBJPROP_BORDER_TYPE, borderType); class=class="str">"cmt">//--- Set border type ObjectSetInteger(class="num">0, objName, OBJPROP_STYLE, borderStyle); class=class="str">"cmt">//--- Set border style ObjectSetInteger(class="num">0, objName, OBJPROP_WIDTH, widthBorder); class=class="str">"cmt">//--- Set border width ObjectSetInteger(class="num">0, objName, OBJPROP_COLOR, clrBorder); class=class="str">"cmt">//--- Set border class="type">color ObjectSetInteger(class="num">0, objName, OBJPROP_BACK, false); class=class="str">"cmt">//--- Set foreground ObjectSetInteger(class="num">0, objName, OBJPROP_STATE, false); class=class="str">"cmt">//--- Set state ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTABLE, false); class=class="str">"cmt">//--- Disable selectable ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTED, false); class=class="str">"cmt">//--- Disable selected ChartRedraw(class="num">0); class=class="str">"cmt">//--- Redraw chart class="kw">return true; class=class="str">"cmt">//--- Return success } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Create a text label for panel elements | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool createLabel(class="type">class="kw">string objName, class="type">int xD, class="type">int yD, class="type">class="kw">string txt, class="type">color clrTxt = clrBlack, class="type">int fontSize = class="num">10, class="type">class="kw">string font = "Arial") { ResetLastError(); class=class="str">"cmt">//--- Reset last error if (!ObjectCreate(class="num">0, objName, OBJ_LABEL, class="num">0, class="num">0, class="num">0)) { class=class="str">"cmt">//--- Create label Print(__FUNCTION__, ": failed to create the label! Error code = ", _LastError); class=class="str">"cmt">//--- Log creation failure
给伦敦突破面板钉上坐标与文字
这段收尾逻辑把标签对象的所有视觉属性一次性写死:先用 ObjectSetInteger 在 0 号图表上给定对象名设 XDISTANCE、YDISTANCE 像素偏移,锚点锁在 CORNER_LEFT_UPPER,也就是图表左上角。 文字内容、颜色、字号、字体分别走 ObjectSetString 和 ObjectSetInteger,其中 OBJPROP_BACK 设 false 代表标签置于前景,不会被 K 线盖住;OBJPROP_SELECTABLE 与 OBJPROP_SELECTED 双 false 让散户没法误点拖走。 最后 ChartRedraw(0) 强制重绘,函数返回 true 表示面板元素落地成功,前面任一步失败则早退返回 false。 CreatePanel 里用 panelPrefix="LondonPanel_" 做命名空间,背景矩形 10,10 起、宽 270 高 200,标题字号 12 金色,下方 Range/High/Low/Buy 四个标签 Y 坐标从 40 到 100 每 20 像素排一行,开 MT5 把这段塞进 EA 初始化就能看到左上角控制面板。
class="kw">return false; class=class="str">"cmt">//--- Return failure } ObjectSetInteger(class="num">0, objName, OBJPROP_XDISTANCE, xD); class=class="str">"cmt">//--- Set x-distance ObjectSetInteger(class="num">0, objName, OBJPROP_YDISTANCE, yD); class=class="str">"cmt">//--- Set y-distance ObjectSetInteger(class="num">0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); class=class="str">"cmt">//--- Set corner ObjectSetString(class="num">0, objName, OBJPROP_TEXT, txt); class=class="str">"cmt">//--- Set text ObjectSetInteger(class="num">0, objName, OBJPROP_COLOR, clrTxt); class=class="str">"cmt">//--- Set class="type">color ObjectSetInteger(class="num">0, objName, OBJPROP_FONTSIZE, fontSize); class=class="str">"cmt">//--- Set font size ObjectSetString(class="num">0, objName, OBJPROP_FONT, font); class=class="str">"cmt">//--- Set font ObjectSetInteger(class="num">0, objName, OBJPROP_BACK, false); class=class="str">"cmt">//--- Set foreground ObjectSetInteger(class="num">0, objName, OBJPROP_STATE, false); class=class="str">"cmt">//--- Set state ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTABLE, false); class=class="str">"cmt">//--- Disable selectable ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTED, false); class=class="str">"cmt">//--- Disable selected ChartRedraw(class="num">0); class=class="str">"cmt">//--- Redraw chart class="kw">return true; class=class="str">"cmt">//--- Return success } class="type">class="kw">string panelPrefix = "LondonPanel_"; class=class="str">"cmt">//--- Prefix for panel objects class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Create the information panel | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void CreatePanel() { createRecLabel(panelPrefix + "Background", class="num">10, class="num">10, class="num">270, class="num">200, clrMidnightBlue, class="num">1, clrSilver); class=class="str">"cmt">//--- Create background createLabel(panelPrefix + "Title", class="num">20, class="num">15, "London Breakout Control Center", clrGold, class="num">12); class=class="str">"cmt">//--- Create title createLabel(panelPrefix + "RangePoints", class="num">20, class="num">40, "Range(points): ", clrWhite, class="num">10); class=class="str">"cmt">//--- Create range label createLabel(panelPrefix + "HighPrice", class="num">20, class="num">60, "High Price: ", clrWhite); class=class="str">"cmt">//--- Create high price label createLabel(panelPrefix + "LowPrice", class="num">20, class="num">80, "Low Price: ", clrWhite); class=class="str">"cmt">//--- Create low price label createLabel(panelPrefix + "BuyLevel", class="num">20, class="num">100, "Buy Level: ", clrWhite); class=class="str">"cmt">//--- Create buy level label
「面板标签与数据刷新的落地写法」
在 MT5 图表上做盯盘面板,核心是把关键价位和账户状态挂成可刷新的文本对象。下面这段创建逻辑把卖价线、余额、净值、回撤百分比分别放在 y=120/140/160/180 像素处,x 统一为 20,颜色用 clrWhite,肉眼扫一眼就能定位。 隐藏按钮的做法有点绕:用 createRecLabel 在 (250,10) 画一个 30×22 的暗红方块,再叠一个 Wingdings 字体、编码 251 的字符当图标,最后把 OBJPROP_SELECTABLE 和 OBJPROP_STATE 都置 true,点击交互才不会失灵。 UpdatePanel() 里所有数值都依赖 LondonRangePoints 是否大于 0。若还没算出伦敦盘前区间,Range 显示 Calculating...,High/Low/Buy/Sell 全部回退成 N/A;一旦区间点数大于 0,Buy Level 直接取 PreLondonHigh 加 OrderOffsetPoints 个 _Point,Sell Level 取 PreLondonLow 减同样偏移,精度跟随 _Digits。 外汇与贵金属波动剧烈,这类面板只解决信息呈现,不预示方向;实盘使用前建议在策略测试器用历史数据跑一遍,确认标签不重叠、刷新不卡顿。
createLabel(panelPrefix + "SellLevel", class="num">20, class="num">120, "Sell Level: ", clrWhite); class=class="str">"cmt">//--- Create sell level label createLabel(panelPrefix + "AccountBalance", class="num">20, class="num">140, "Balance: ", clrWhite); class=class="str">"cmt">//--- Create balance label createLabel(panelPrefix + "AccountEquity", class="num">20, class="num">160, "Equity: ", clrWhite); class=class="str">"cmt">//--- Create equity label createLabel(panelPrefix + "CurrentDrawdown", class="num">20, class="num">180, "Drawdown(%): ", clrWhite); class=class="str">"cmt">//--- Create drawdown label createRecLabel(panelPrefix + "Hide", class="num">250, class="num">10, class="num">30, class="num">22, clrCrimson, class="num">1, clrNONE); class=class="str">"cmt">//--- Create hide button createLabel(panelPrefix + "HideText", class="num">258, class="num">12, CharToString(class="num">251), clrWhite, class="num">13, "Wingdings"); class=class="str">"cmt">//--- Create hide text ObjectSetInteger(class="num">0, panelPrefix + "Hide", OBJPROP_SELECTABLE, true); class=class="str">"cmt">//--- Make hide selectable ObjectSetInteger(class="num">0, panelPrefix + "Hide", OBJPROP_STATE, true); class=class="str">"cmt">//--- Set hide state } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Update panel with current data | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void UpdatePanel() { class="type">class="kw">string rangeText = "Range(points): " + (LondonRangePoints > class="num">0 ? DoubleToString(LondonRangePoints, class="num">0) : "Calculating..."); class=class="str">"cmt">//--- Format range text ObjectSetString(class="num">0, panelPrefix + "RangePoints", OBJPROP_TEXT, rangeText); class=class="str">"cmt">//--- Update range text class="type">class="kw">string highText = "High Price: " + (LondonRangePoints > class="num">0 ? DoubleToString(PreLondonHigh, _Digits) : "N/A"); class=class="str">"cmt">//--- Format high text ObjectSetString(class="num">0, panelPrefix + "HighPrice", OBJPROP_TEXT, highText); class=class="str">"cmt">//--- Update high text class="type">class="kw">string lowText = "Low Price: " + (LondonRangePoints > class="num">0 ? DoubleToString(PreLondonLow, _Digits) : "N/A"); class=class="str">"cmt">//--- Format low text ObjectSetString(class="num">0, panelPrefix + "LowPrice", OBJPROP_TEXT, lowText); class=class="str">"cmt">//--- Update low text class="type">class="kw">string buyText = "Buy Level: " + (LondonRangePoints > class="num">0 ? DoubleToString(PreLondonHigh + OrderOffsetPoints * _Point, _Digits) : "N/A"); class=class="str">"cmt">//--- Format buy text ObjectSetString(class="num">0, panelPrefix + "BuyLevel", OBJPROP_TEXT, buyText); class=class="str">"cmt">//--- Update buy text class="type">class="kw">string sellText = "Sell Level: " + (LondonRangePoints > class="num">0 ? DoubleToString(PreLondonLow - OrderOffsetPoints * _Point, _Digits) : "N/A"); class=class="str">"cmt">//--- Format sell text
◍ 面板刷新与生命周期钩子
这段逻辑负责把卖价水平、账户余额、净值和日内回撤实时写进图表面板。回撤文本超过上限一半时,颜色从白切到黄,算是给盯盘者一个低延迟的视觉预警。 ObjectSetString 每次只改 OBJPROP_TEXT,不重建对象,所以 MT5 图表重绘开销很小;若你面板卡顿,优先怀疑是不是在别处频繁删建同名对象。 OnInit 里先给 CTrade 设魔术码,再释放旧仓位数组、建面板、置可见,返回 INIT_SUCCEEDED 即代表 EA 加载成功。OnDeinit 用 ObjectsDeleteAll(0,"LondonPanel_") 按前缀清场,避免退出后残留图形对象。 外汇与贵金属杠杆高,这类面板只做信息呈现,不替代风控;回撤变黄只说明概率上接近警戒线,不代表一定会熔断。
ObjectSetString(class="num">0, panelPrefix + "SellLevel", OBJPROP_TEXT, sellText); class=class="str">"cmt">//--- Update sell text class="type">class="kw">string balanceText = "Balance: " + DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), class="num">2); class=class="str">"cmt">//--- Format balance text ObjectSetString(class="num">0, panelPrefix + "AccountBalance", OBJPROP_TEXT, balanceText); class=class="str">"cmt">//--- Update balance text class="type">class="kw">string equityText = "Equity: " + DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), class="num">2); class=class="str">"cmt">//--- Format equity text ObjectSetString(class="num">0, panelPrefix + "AccountEquity", OBJPROP_TEXT, equityText); class=class="str">"cmt">//--- Update equity text class="type">class="kw">string ddText = "Drawdown(%): " + DoubleToString(dailyDrawdown, class="num">2); class=class="str">"cmt">//--- Format drawdown text ObjectSetString(class="num">0, panelPrefix + "CurrentDrawdown", OBJPROP_TEXT, ddText); class=class="str">"cmt">//--- Update drawdown text ObjectSetInteger(class="num">0, panelPrefix + "CurrentDrawdown", OBJPROP_COLOR, dailyDrawdown > MaxDailyDrawdownPercent / class="num">2 ? clrYellow : clrWhite); class=class="str">"cmt">//--- Set drawdown class="type">color } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Initialize EA | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { obj_Trade.SetExpertMagicNumber(MagicNumber); class=class="str">"cmt">//--- Set magic number ArrayFree(positionList); class=class="str">"cmt">//--- Free position list CreatePanel(); class=class="str">"cmt">//--- Create panel panelVisible = true; class=class="str">"cmt">//--- Set panel visible class="kw">return(INIT_SUCCEEDED); class=class="str">"cmt">//--- Return success } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Deinitialize EA | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnDeinit(const class="type">int reason) { ObjectsDeleteAll(class="num">0, "LondonPanel_"); class=class="str">"cmt">//--- Delete panel objects ArrayFree(positionList); class=class="str">"cmt">//--- Free position list } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Handle chart events(e.g., panel close) | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnChartEvent(const class="type">int id, const class="type">long &lparam, const class="type">class="kw">double &dparam, const class="type">class="kw">string &sparam) {
面板隐藏与日内状态重置的收尾逻辑
伦敦盘面板做成一个可点击隐藏的对象组,点击带 Hide 后缀的按钮后,脚本把 panelVisible 置否,用 ObjectsDeleteAll(0, "LondonPanel_") 清掉前缀相同的全部图形,再 ChartRedraw 强制重绘。这样盘面上不残留半截矩形和文字,盯盘时不会被旧 session 的视觉噪声干扰。 IsNewDay 用 TimeToStruct 把当前 Bar 时间拆成年月日,拼成零点的 datetime 跟 lastCheckedDay 比。一旦跨日,就把 sessionChecksDone、noTradeToday、双向下单 ticket、LondonRangePoints 全部归零,返回 true。实盘里若不在 0 点重算这些变量,可能延续前一天的伦敦区间导致重复触发。 回撤熔断放在 UpdateDailyDrawdown:静态 maxEquity 跟踪历史峰值,每 Tick 取 ACCOUNT_EQUITY,dailyDrawdown = (maxEquity - equity)/maxEquity*100。达到 MaxDailyDrawdownPercent 就 noTradeToday=true,当日停止开仓。外汇与贵金属杠杆高,这类硬止损阈值建议在 MT5 策略测试器里按自己本金压力测过再上。 OnTick 作为主循环入口,前面这些函数都得在它里面按序调用,否则新日判断和回撤拦截不会生效。
if (id == CHARTEVENT_OBJECT_CLICK && sparam == panelPrefix + "Hide") { class=class="str">"cmt">//--- Check hide click panelVisible = false; class=class="str">"cmt">//--- Set panel hidden ObjectsDeleteAll(class="num">0, "LondonPanel_"); class=class="str">"cmt">//--- Delete panel objects ChartRedraw(class="num">0); class=class="str">"cmt">//--- Redraw chart } } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check if it&class="macro">#x27;s a new trading day | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool IsNewDay(class="type">class="kw">datetime currentBarTime) { class="type">MqlDateTime barTime; class=class="str">"cmt">//--- Bar time structure TimeToStruct(currentBarTime, barTime); class=class="str">"cmt">//--- Convert time class="type">class="kw">datetime currentDay = StringToTime(StringFormat("%04d.%02d.%02d", barTime.year, barTime.mon, barTime.day)); class=class="str">"cmt">//--- Get current day if (currentDay != lastCheckedDay) { class=class="str">"cmt">//--- Check new day lastCheckedDay = currentDay; class=class="str">"cmt">//--- Update last day sessionChecksDone = false; class=class="str">"cmt">//--- Reset checks noTradeToday = false; class=class="str">"cmt">//--- Reset no trade buyOrderTicket = class="num">0; class=class="str">"cmt">//--- Reset buy ticket sellOrderTicket = class="num">0; class=class="str">"cmt">//--- Reset sell ticket LondonRangePoints = class="num">0.0; class=class="str">"cmt">//--- Reset range class="kw">return true; class=class="str">"cmt">//--- Return new day } class="kw">return false; class=class="str">"cmt">//--- Return not new day } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Update daily drawdown | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void UpdateDailyDrawdown() { class="kw">static class="type">class="kw">double maxEquity = class="num">0.0; class=class="str">"cmt">//--- Max equity tracker class="type">class="kw">double equity = AccountInfoDouble(ACCOUNT_EQUITY); class=class="str">"cmt">//--- Get equity if (equity > maxEquity) maxEquity = equity; class=class="str">"cmt">//--- Update max equity dailyDrawdown = (maxEquity - equity) / maxEquity * class="num">100; class=class="str">"cmt">//--- Calculate drawdown if (dailyDrawdown >= MaxDailyDrawdownPercent) noTradeToday = true; class=class="str">"cmt">//--- Set no trade if exceeded } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Main tick handler | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() {