DoEasy. 控件(第 6 部分):面板控件,自动调整容器大小来适应内部内容·进阶篇
(2/3)· 当多个子对象先后激活 Dock,面板若逐次重绘便会闪得眼睛发酸,本篇给出合并刷新的解法
在 MT5 里叠放 WinForms 控件时,不少人顺手给每个子对象单独置 Dock,却没意识到面板每响应一次就重绘一遍,整块界面像抽搐。把附着对象的属性变更攒成一批再让容器算一次尺寸,才是顺滑的底子。
◍ 画布控件排序枚举与品种属性接口的底层定义
在 MT5 的自定义图形库里,画布元素(Canvas Element)支持按多种布局属性排序。下面这组枚举值直接暴露了控件自动排版时的判断维度:既能按是否随内容自适应尺寸(AUTOSIZE)、按边缘绑定容器的停靠模式(DOCK_MODE)排,也能精细到控件之间与控件内部的上下左右边距(MARGIN / PADDING 六个方向)。 字符串类属性排序从 FIRST_CANV_ELEMENT_STR_PROP 基准开始,例如按元素对象名(NAME_OBJ)或绑定的图形资源名(NAME_RES)归类。这类定义决定了你后续用 CCanvas 批量重排面板时,能否用一行排序调用替代手算坐标。 品种接口层则给出了可直接取数的方法:SymbolSwapRatio(ENUM_DAY_OF_WEEK day) 返回指定星期几的掉期比例,GetSwapRatioDescription() 拿到对应文字说明;PriceSensitivity() 内联返回 SYMBOL_PROP_PRICE_SENSITIVITY 属性值。外汇与贵金属品种受掉期与敏感度影响明显,持仓过夜成本可能随星期跳变,属高风险变量。 把上面两段代码贴进 MQ5 头文件编译,能在『导航器—类视图』里直接看到这些枚举与方法的符号,验证定义是否生效。
SORT_BY_CANV_ELEMENT_AUTOSIZE, class=class="str">"cmt">// Sort by the flag of the element auto resizing depending on the content SORT_BY_CANV_ELEMENT_DOCK_MODE, class=class="str">"cmt">// Sort by mode of binding control borders to the container SORT_BY_CANV_ELEMENT_MARGIN_TOP, class=class="str">"cmt">// Sort by top margin between the fields of this and another control SORT_BY_CANV_ELEMENT_MARGIN_BOTTOM, class=class="str">"cmt">// Sort by bottom margin between the fields of this and another control SORT_BY_CANV_ELEMENT_MARGIN_LEFT, class=class="str">"cmt">// Sort by left margin between the fields of this and another control SORT_BY_CANV_ELEMENT_MARGIN_RIGHT, class=class="str">"cmt">// Sort by right margin between the fields of this and another control SORT_BY_CANV_ELEMENT_PADDING_TOP, class=class="str">"cmt">// Sort by top margin inside the control SORT_BY_CANV_ELEMENT_PADDING_BOTTOM, class=class="str">"cmt">// Sort by bottom margin inside the control SORT_BY_CANV_ELEMENT_PADDING_LEFT, class=class="str">"cmt">// Sort by left margin inside the control SORT_BY_CANV_ELEMENT_PADDING_RIGHT, class=class="str">"cmt">// Sort by right margin inside the control class=class="str">"cmt">//--- Sort by real properties class=class="str">"cmt">//--- Sort by class="type">class="kw">string properties SORT_BY_CANV_ELEMENT_NAME_OBJ = FIRST_CANV_ELEMENT_STR_PROP,class=class="str">"cmt">// Sort by an element object name SORT_BY_CANV_ELEMENT_NAME_RES, class=class="str">"cmt">// Sort by the graphical resource name }; class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double SymbolMarginHedged(class="type">void) class="kw">const; class="type">class="kw">double SymbolSwapRatio(ENUM_DAY_OF_WEEK day) class="kw">const; class="type">bool SymbolMarginLong(class="type">void); class="type">class="kw">string GetSectorDescription(class="type">void) class="kw">const; class="type">class="kw">string GetIndustryDescription(class="type">void) class="kw">const; class="type">class="kw">string GetSwapRatioDescription(class="kw">const ENUM_DAY_OF_WEEK day) class="kw">const; class="type">class="kw">double PriceSensitivity(class="type">void) class="kw">const { class="kw">return this.GetProperty(SYMBOL_PROP_PRICE_SENSITIVITY); }
把隔夜费拆到每一天去读
MT5 里 SYMBOL_PROP_SWAP_* 这组属性把一周七天的掉期系数分开暴露,写类的时候用 const 方法包一层就能随时取某天的 SwapRatio。下面这七个函数各自对应周日到周六,返回的是该品种当天的掉期比率,不是点值。 double SwapRatioSunday(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_SUNDAY); } // 取周日掉期比率,const 保证不修改对象状态 double SwapRatioMonday(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_MONDAY); } // 取周一掉期比率 double SwapRatioTuesday(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_TUESDAY); } // 取周二掉期比率 double SwapRatioWednesday(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_WEDNESDAY); } // 取周三掉期比率,多数品种周三会乘 3 倍计入跨周末仓息 double SwapRatioThursday(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_THURSDAY); } // 取周四掉期比率 double SwapRatioFriday(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_FRIDAY); } // 取周五掉期比率 double SwapRatioSaturday(void) const { return this.GetProperty(SYMBOL_PROP_SWAP_SATURDAY); } // 取周六掉期比率,通常返回 0 还有个未在此展开的 SwapRatioDay(ENUM_DAY_OF_WEEK day),是按枚举直接查某天系数的统一入口,比写七个独立函数更适合循环里调用。 别把正态当圣经 实际跑 MT5 终端按 F4 把上面方法塞进 CSymbol 派生类,用 Print(SymbolInfoDouble(_Symbol,SYMBOL_PROP_SWAP_WEDNESDAY)) 对照看,黄金 XAUUSD 周三系数常常是正数而欧元系多为负,持仓过周三成本倾向明显分化。外汇和贵金属杠杆交易高风险,掉期只是成本一侧,别单凭它决定留仓。
class="type">class="kw">double SwapRatioSunday(class="type">void) class="kw">const { class="kw">return this.GetProperty(SYMBOL_PROP_SWAP_SUNDAY); } class="type">class="kw">double SwapRatioMonday(class="type">void) class="kw">const { class="kw">return this.GetProperty(SYMBOL_PROP_SWAP_MONDAY); } class="type">class="kw">double SwapRatioTuesday(class="type">void) class="kw">const { class="kw">return this.GetProperty(SYMBOL_PROP_SWAP_TUESDAY); } class="type">class="kw">double SwapRatioWednesday(class="type">void) class="kw">const { class="kw">return this.GetProperty(SYMBOL_PROP_SWAP_WEDNESDAY); } class="type">class="kw">double SwapRatioThursday(class="type">void) class="kw">const { class="kw">return this.GetProperty(SYMBOL_PROP_SWAP_THURSDAY); } class="type">class="kw">double SwapRatioFriday(class="type">void) class="kw">const { class="kw">return this.GetProperty(SYMBOL_PROP_SWAP_FRIDAY); } class="type">class="kw">double SwapRatioSaturday(class="type">void) class="kw">const { class="kw">return this.GetProperty(SYMBOL_PROP_SWAP_SATURDAY); } class="type">class="kw">double SwapRatioDay(class="kw">const ENUM_DAY_OF_WEEK day) class="kw">const; class="type">class="kw">double NormalizedPrice(class="kw">const class="type">class="kw">double price) class="kw">const;
「敏感度与周日库存费的阈值监控接口」
在 MT5 的 symbol 属性监控类里,价格敏感度(SYMBOL_PROP_PRICE_SENSITIVITY)和周日库存费比例(SYMBOL_PROP_SWAP_SUNDAY)都提供了一组对称的 setter/getter,用来设定「增量超阈、减量超阈、绝对水平」三类控制值。 调用时统一用 ::fabs(value) 包裹入参,意味着无论你传正还是负,底层都按绝对值处理阈值,避免方向写反导致监控失效。 IsIncreasedPriceSensitivity() 与 IsDecreasedPriceSensitivity() 直接返回布尔标志,可在 EA 的 OnTick 里做条件分支:当敏感度向上突破时倾向减仓,向下突破时倾向观望。外汇与贵金属杠杆高,库存费与敏感度异动可能放大隔夜风险,需结合实盘验证。 下面这段是接口原貌,逐行对应上述逻辑:SetControlPriceSensitivityInc 设敏感度增量阈值;SetControlPriceSensitivityDec 设减量阈值;SetControlPriceSensitivityLevel 设水平线;GetValueChangedPriceSensitivity 取实际变动值;两个 Is 函数读标志位。周日库存费三件套结构完全一致,只是属性换成 SYMBOL_PROP_SWAP_SUNDAY。
class=class="str">"cmt">//--- getting the flag of the option/warrant sensitivity change exceeding the(class="num">5) increase, (class="num">6) decrease value class="type">void SetControlPriceSensitivityInc(class="kw">const class="type">class="kw">double value) { this.SetControlledValueINC(SYMBOL_PROP_PRICE_SENSITIVITY,::fabs(value)); } class="type">void SetControlPriceSensitivityDec(class="kw">const class="type">class="kw">double value) { this.SetControlledValueDEC(SYMBOL_PROP_PRICE_SENSITIVITY,::fabs(value)); } class="type">void SetControlPriceSensitivityLevel(class="kw">const class="type">class="kw">double value) { this.SetControlledValueLEVEL(SYMBOL_PROP_PRICE_SENSITIVITY,::fabs(value)); } class="type">class="kw">double GetValueChangedPriceSensitivity(class="type">void) class="kw">const { class="kw">return this.GetPropDoubleChangedValue(SYMBOL_PROP_PRICE_SENSITIVITY); } class="type">bool IsIncreasedPriceSensitivity(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagINC(SYMBOL_PROP_PRICE_SENSITIVITY); } class="type">bool IsDecreasedPriceSensitivity(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagDEC(SYMBOL_PROP_PRICE_SENSITIVITY); } class=class="str">"cmt">//--- Swap accrual ratio class=class="str">"cmt">//--- setting the controlled Sunday swap accrual ratio(class="num">1) increase, (class="num">2) decrease and(class="num">3) control levels class=class="str">"cmt">//--- get(class="num">4) the swap accrual ratio change(Sunday), class=class="str">"cmt">//--- get the swap accrual ratio change for Sunday exceeding the(class="num">5) increase and(class="num">6) decrease values class="type">void SetControlSwapSundayInc(class="kw">const class="type">class="kw">double value) { this.SetControlledValueINC(SYMBOL_PROP_SWAP_SUNDAY,::fabs(value)); } class="type">void SetControlSwapSundayDec(class="kw">const class="type">class="kw">double value) { this.SetControlledValueDEC(SYMBOL_PROP_SWAP_SUNDAY,::fabs(value)); } class="type">void SetControlSwapSundayLevel(class="kw">const class="type">class="kw">double value) { this.SetControlledValueLEVEL(SYMBOL_PROP_SWAP_SUNDAY,::fabs(value)); }
◍ 抓出周末掉期费用的异动
做黄金和外汇的持仓成本,常被周日、周一的 swap 值悄悄改掉。经纪商在周末调整掉期费率时,MT5 的 SYMBOL_PROP_SWAP_SUNDAY / SWAP_MONDAY 属性会发生变化,但终端不会弹窗提醒你。 下面这段类方法直接封装了「读取变化值」和「判断增减方向」的逻辑。GetValueChangedSwapSunday 返回周日掉期相较基准的变动量;IsIncreasedSwapSunday 与 IsDecreasedSwapSunday 分别用内部 flag 告诉你这次变动是上调还是下调。 double GetValueChangedSwapSunday(void) const { return this.GetPropDoubleChangedValue(SYMBOL_PROP_SWAP_SUNDAY); } bool IsIncreasedSwapSunday(void) const { return (bool)this.GetPropDoubleFlagINC(SYMBOL_PROP_SWAP_SUNDAY); } bool IsDecreasedSwapSunday(void) const { return (bool)this.GetPropDoubleFlagDEC(SYMBOL_PROP_SWAP_SUNDAY); } 周一掉期同样有控制接口。SetControlSwapMondayInc / Dec / Level 三个方法接收double参数,内部用 ::fabs 取绝对值后写入监控阈值,分别对应「增幅超多少报警」「降幅超多少报警」「绝对水平线」。 void SetControlSwapMondayInc(const double value) { this.SetControlledValueINC(SYMBOL_PROP_SWAP_MONDAY,::fabs(value)); } void SetControlSwapMondayDec(const double value) { this.SetControlledValueDEC(SYMBOL_PROP_SWAP_MONDAY,::fabs(value)); } void SetControlSwapMondayLevel(const double value) { this.SetControlledValueLEVEL(SYMBOL_PROP_SWAP_MONDAY,::fabs(value)); } double GetValueChangedSwapMonday(void) const { return this.GetPropDoubleChangedValue(SYMBOL_PROP_SWAP_MONDAY); } bool IsIncreasedSwapMonday(void) const { return (bool)this.GetPropDoubleFlagINC(SYMBOL_PROP_SWAP_MONDAY); } bool IsDecreasedSwapMonday(void) const { return (bool)this.GetPropDoubleFlagDEC(SYMBOL_PROP_SWAP_MONDAY); } 在 MT5 里把这套方法挂上定时器,每 30 秒轮询一次 GetValueChangedSwapMonday,当返回非零且 IsIncreasedSwapMonday 为真,就说明周一掉期可能刚被经纪商上调。外汇与贵金属杠杆品种波动大、隔夜费调整频繁,这类异动仅作成本预警,不构成方向判断。
class="type">class="kw">double GetValueChangedSwapSunday(class="type">void) class="kw">const { class="kw">return this.GetPropDoubleChangedValue(SYMBOL_PROP_SWAP_SUNDAY); } class="type">bool IsIncreasedSwapSunday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagINC(SYMBOL_PROP_SWAP_SUNDAY); } class="type">bool IsDecreasedSwapSunday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagDEC(SYMBOL_PROP_SWAP_SUNDAY); } class="type">void SetControlSwapMondayInc(class="kw">const class="type">class="kw">double value) { this.SetControlledValueINC(SYMBOL_PROP_SWAP_MONDAY,::fabs(value)); } class="type">void SetControlSwapMondayDec(class="kw">const class="type">class="kw">double value) { this.SetControlledValueDEC(SYMBOL_PROP_SWAP_MONDAY,::fabs(value)); } class="type">void SetControlSwapMondayLevel(class="kw">const class="type">class="kw">double value) { this.SetControlledValueLEVEL(SYMBOL_PROP_SWAP_MONDAY,::fabs(value)); } class="type">class="kw">double GetValueChangedSwapMonday(class="type">void) class="kw">const { class="kw">return this.GetPropDoubleChangedValue(SYMBOL_PROP_SWAP_MONDAY); } class="type">bool IsIncreasedSwapMonday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagINC(SYMBOL_PROP_SWAP_MONDAY); } class="type">bool IsDecreasedSwapMonday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagDEC(SYMBOL_PROP_SWAP_MONDAY); }
周二周三库存费异动的监控接口
做跨日持仓的贵金属或外汇头寸,周二、周三的 swap 调整往往藏着经纪商改规则的信号。下面这组方法把 SYMBOL_PROP_SWAP_TUESDAY / WEDNESDAY 的增减阈值和触发电平直接封装进类里,方便盯盘脚本自动比对。 代码里所有传入值都过了 ::fabs,意味着你填正数负数都行,内部只认绝对值。SetControlSwapTuesdayInc 设定周二库存费「相对基准」的上浮敏感幅度,超过就置 INC 标志;SetControlSwapTuesdayDec 同理管下探。 GetValueChangedSwapTuesday 返回实际变动量,IsIncreasedSwapTuesday / IsDecreasedSwapTuesday 直接给布尔,省得你在外层再写判断。周三那一组接口命名结构完全一致,只是把枚举换成 SYMBOL_PROP_SWAP_WEDNESDAY。 实盘接进去后,可以在 OnTick 里轮询 IsIncreasedSwapTuesday(),一旦返回 true 就推小布告警——外汇和贵金属杠杆品种库存费跳变可能预示流动性切换,属高风险事件,别当成普通噪声。
class=class="str">"cmt">//--- get(class="num">4) the swap accrual ratio change(Tuesday), class=class="str">"cmt">//--- get the swap accrual ratio change for Tuesday exceeding the(class="num">5) increase and(class="num">6) decrease values class="type">void SetControlSwapTuesdayInc(class="kw">const class="type">class="kw">double value) { this.SetControlledValueINC(SYMBOL_PROP_SWAP_TUESDAY,::fabs(value)); } class="type">void SetControlSwapTuesdayDec(class="kw">const class="type">class="kw">double value) { this.SetControlledValueDEC(SYMBOL_PROP_SWAP_TUESDAY,::fabs(value)); } class="type">void SetControlSwapTuesdayLevel(class="kw">const class="type">class="kw">double value) { this.SetControlledValueLEVEL(SYMBOL_PROP_SWAP_TUESDAY,::fabs(value)); } class="type">class="kw">double GetValueChangedSwapTuesday(class="type">void) class="kw">const { class="kw">return this.GetPropDoubleChangedValue(SYMBOL_PROP_SWAP_TUESDAY); } class="type">bool IsIncreasedSwapTuesday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagINC(SYMBOL_PROP_SWAP_TUESDAY); } class="type">bool IsDecreasedSwapTuesday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagDEC(SYMBOL_PROP_SWAP_TUESDAY); } class=class="str">"cmt">//--- setting the controlled Wednesday swap accrual ratio(class="num">1) increase, (class="num">2) decrease and(class="num">3) control levels class=class="str">"cmt">//--- get(class="num">4) the swap accrual ratio change(Wednesday), class=class="str">"cmt">//--- get the swap accrual ratio change for Wednesday exceeding the(class="num">5) increase and(class="num">6) decrease values class="type">void SetControlSwapWednesdayInc(class="kw">const class="type">class="kw">double value) { this.SetControlledValueINC(SYMBOL_PROP_SWAP_WEDNESDAY,::fabs(value)); } class="type">void SetControlSwapWednesdayDec(class="kw">const class="type">class="kw">double value) { this.SetControlledValueDEC(SYMBOL_PROP_SWAP_WEDNESDAY,::fabs(value)); } class="type">void SetControlSwapWednesdayLevel(class="kw">const class="type">class="kw">double value) { this.SetControlledValueLEVEL(SYMBOL_PROP_SWAP_WEDNESDAY,::fabs(value)); }
「把周三周四掉期变动写进类里」
延续前面的符号属性监控思路,这里把周三、周四的掉期倍数变动也封装成同一套读写接口。外汇与贵金属持仓过夜成本受经纪商调仓影响明显,周三往往叠加两倍掉期,周四部分品种也会出现单独倍率,属于高风险下的隐性成本点。 下面这段直接挂在之前定义的符号监控类里即可。GetValueChangedSwapWednesday 返回 SYMBOL_PROP_SWAP_WEDNESDAY 的相对变动值,IsIncreasedSwapWednesday / IsDecreasedSwapWednesday 则分别读出该属性相较基准是上调还是下调的布尔标记。 周四部分对称地提供了 SetControlSwapThursdayInc、SetControlSwapThursdayDec、SetControlSwapThursdayLevel 三个写入函数,内部统一用 ::fabs(value) 取绝对值避免方向错设;读取端 GetValueChangedSwapThursday、IsIncreasedSwapThursday、IsDecreasedSwapThursday 逻辑与周三完全一致。 实盘验证时,在 MT5 策略测试器外挂一个 Print(IsIncreasedSwapWednesday()) 的探针,就能在经纪商周末调参后第一时间看到周三掉期是否被拉高,从而调整波段持仓周期。
class="type">class="kw">double GetValueChangedSwapWednesday(class="type">void) class="kw">const { class="kw">return this.GetPropDoubleChangedValue(SYMBOL_PROP_SWAP_WEDNESDAY); } class="type">bool IsIncreasedSwapWednesday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagINC(SYMBOL_PROP_SWAP_WEDNESDAY); } class="type">bool IsDecreasedSwapWednesday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagDEC(SYMBOL_PROP_SWAP_WEDNESDAY); } class=class="str">"cmt">//--- setting the controlled Thursday swap accrual ratio(class="num">1) increase, (class="num">2) decrease and(class="num">3) control levels class=class="str">"cmt">//--- get(class="num">4) the swap accrual ratio change(Thursday), class=class="str">"cmt">//--- get the swap accrual ratio change for Thursday exceeding the(class="num">5) increase and(class="num">6) decrease values class="type">void SetControlSwapThursdayInc(class="kw">const class="type">class="kw">double value) { this.SetControlledValueINC(SYMBOL_PROP_SWAP_THURSDAY,::fabs(value)); } class="type">void SetControlSwapThursdayDec(class="kw">const class="type">class="kw">double value) { this.SetControlledValueDEC(SYMBOL_PROP_SWAP_THURSDAY,::fabs(value)); } class="type">void SetControlSwapThursdayLevel(class="kw">const class="type">class="kw">double value) { this.SetControlledValueLEVEL(SYMBOL_PROP_SWAP_THURSDAY,::fabs(value)); } class="type">class="kw">double GetValueChangedSwapThursday(class="type">void) class="kw">const { class="kw">return this.GetPropDoubleChangedValue(SYMBOL_PROP_SWAP_THURSDAY); } class="type">bool IsIncreasedSwapThursday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagINC(SYMBOL_PROP_SWAP_THURSDAY); } class="type">bool IsDecreasedSwapThursday(class="type">void) class="kw">const { class="kw">return (class="type">bool)this.GetPropDoubleFlagDEC(SYMBOL_PROP_SWAP_THURSDAY); } class=class="str">"cmt">//--- setting the controlled Friday swap accrual ratio(class="num">1) increase, (class="num">2) decrease and(class="num">3) control levels class=class="str">"cmt">//--- get(class="num">4) the swap accrual ratio change(Friday),