纺锤形图表指标·进阶篇
(2/3)· 蜡烛图看腻了?VWMA+VR 量价纺锤在 MT5 里得自己造绘制引擎
接上篇的概念铺垫,我们继续深挖纺锤图在 MetaTrader 5 里的落地细节。内置的七种绘制类型没有一种能画出带成交量宽度的纺锤体,多数人卡在「指标写了算不出来图形」这一步就放弃了。
「指标初始化里的缓冲与绘图设定」
在 MT5 自定义指标里,OnInit 阶段先把输入参数做兜底处理:若 spindle 数量非法,代码会强制把 ext_spin_num 设为 10,并弹窗提示参数被改。这一步能避免后续循环越界,实盘加载时若看到该 Alert,说明外部输入没过校验。 缓冲区的映射决定了数据怎么存。上面片段用了 11 个 SetIndexBuffer:0~2 是给图表看的 INDICATOR_DATA 与 COLOR_INDEX,3~5 是扩展数据,6~10 标为 INDICATOR_CALCULATIONS,只参与计算不绘制。注意 Buff_open、Buff_close、Buff_VWMA 等计算缓冲和展示缓冲是分开的,回测时改算法不用动绘图层。 绘图属性上,短名被拼成 "SPC "+magic_numb,精度取 _Digits+1;起始柱设为 long_period+1,long_period 取 VR 与 VWMA 周期二者较大值。PLOT_SHOW_DATA 对 0~3 号全关,空值统一设 0,意味着这些线不会在 DataWindow 里刷数字,只留图形。 当 type_draw==0,程序用 for 循环按 ext_spin_num(可能已被纠正为 10)创建位图对象,命名带 magic_numb 和序号,挂在当前图表子窗口。你开 MT5 把这段塞进 OnInit,改 magic_numb 就能在对象列表里看到成倍的 SPC 位图被建出来。
ext_spin_num=class="num">10; class=class="str">"cmt">// 改变变量值 Alert("Number of spindles was class="kw">input incorrectly and has been changed."); } else ext_spin_num=spindles_num; class=class="str">"cmt">//--- 查找绘制图表所需的最长的周期 if(ext_period_VR>ext_period_VWMA)long_period=ext_period_VR; else long_period=ext_period_VWMA; class=class="str">"cmt">//--- 指标缓存映射 SetIndexBuffer(class="num">0,Buff_up,INDICATOR_DATA); SetIndexBuffer(class="num">1,Buff_down,INDICATOR_DATA); SetIndexBuffer(class="num">2,Buff_color_up_down,INDICATOR_COLOR_INDEX); SetIndexBuffer(class="num">3,Buff_open_ext,INDICATOR_DATA); SetIndexBuffer(class="num">4,Buff_close_ext,INDICATOR_DATA); SetIndexBuffer(class="num">5,Buff_VWMA_ext,INDICATOR_DATA); SetIndexBuffer(class="num">6,Buff_open,INDICATOR_CALCULATIONS); SetIndexBuffer(class="num">7,Buff_close,INDICATOR_CALCULATIONS); SetIndexBuffer(class="num">8,Buff_VWMA,INDICATOR_CALCULATIONS); SetIndexBuffer(class="num">9,Buff_VR,INDICATOR_CALCULATIONS); SetIndexBuffer(class="num">10,Buff_time,INDICATOR_CALCULATIONS); class=class="str">"cmt">//--- 设置指标名称 IndicatorSetString(INDICATOR_SHORTNAME,"SPC "+IntegerToString(magic_numb)); PlotIndexSetString(class="num">0,PLOT_LABEL,"SPC"); class=class="str">"cmt">//--- 设置精度 IndicatorSetInteger(INDICATOR_DIGITS,_Digits+class="num">1); class=class="str">"cmt">//--- 设置开始绘制指标的起始柱形 PlotIndexSetInteger(class="num">0,PLOT_DRAW_BEGIN,long_period+class="num">1); class=class="str">"cmt">//--- 禁止显示指标的当前值 PlotIndexSetInteger(class="num">0,PLOT_SHOW_DATA,class="kw">false); PlotIndexSetInteger(class="num">1,PLOT_SHOW_DATA,class="kw">false); PlotIndexSetInteger(class="num">2,PLOT_SHOW_DATA,class="kw">false); PlotIndexSetInteger(class="num">3,PLOT_SHOW_DATA,class="kw">false); class=class="str">"cmt">//--- 设置不需要显示的值 PlotIndexSetDouble(class="num">1,PLOT_EMPTY_VALUE,class="num">0); PlotIndexSetDouble(class="num">2,PLOT_EMPTY_VALUE,class="num">0); PlotIndexSetDouble(class="num">3,PLOT_EMPTY_VALUE,class="num">0); class=class="str">"cmt">//--- 创建要用到的对象 if(type_draw==class="num">0) { for(class="type">int x=class="num">0; x<=ext_spin_num; x++) { ObjectCreate(class="num">0,"SPC"+IntegerToString(magic_numb)+IntegerToString(x)+"class="num">1",OBJ_BITMAP,ChartWindowFind(),__DATE__,class="num">0); ObjectCreate(class="num">0,"SPC"+IntegerToString(magic_numb)+IntegerToString(x)+"class="num">2",OBJ_BITMAP,ChartWindowFind(),__DATE__,class="num">0);
◍ 用键盘事件触发子窗口图形重绘
在 MT5 指标里,想让用户在看图时手动刷新自旋图形,最轻量的做法是挂一个键盘事件。上面代码在 OnChartEvent 中拦截 CHARTEVENT_KEYDOWN,当 lparam 等于 82(即键盘 R 键的虚拟码)时,先确认子窗口价格轴最大值大于 0,避免空图表误触发,再调用 func_check_chart() 做图表状态校验。 校验通过后若 type_draw==0,就执行 func_drawing(true,ext_spin_num,end_bar) 重画图形。外汇与贵金属市场波动剧烈、杠杆风险高,这种手动触发机制适合用来避免自动重绘造成的资源浪费,但并不能降低交易本身的风险敞口。 func_check_chart() 的核心是先拿到子窗口几何与价格边界:用 ChartWindowFind() 定位指标所在子窗口,再取 CHART_PRICE_MAX / CHART_PRICE_MIN 以及 CHART_HEIGHT_IN_PIXELS、CHART_WIDTH_IN_PIXELS、CHART_WIDTH_IN_BARS。这几个值若与上次记录不同,就说明图表被缩放或加载了新品种,返回 true 才允许后续绘制。 开 MT5 把 R 键绑成重绘开关,比每次 tick 都重画要省 CPU;若你的图表宽度在 200 根 bar 左右,CHART_WIDTH_IN_BARS 的返回值会直接决定位图横向密度,可调 ext_spin_num 看看间距变化。
ObjectCreate(class="num">0,"SPC"+IntegerToString(magic_numb)+IntegerToString(x)+"class="num">3",OBJ_BITMAP,ChartWindowFind(),__DATE__,class="num">0); ObjectCreate(class="num">0,"SPC"+IntegerToString(magic_numb)+IntegerToString(x)+"class="num">4",OBJ_BITMAP,ChartWindowFind(),__DATE__,class="num">0); } } class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| ChartEvent函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnChartEvent(class="kw">const class="type">int id, class="kw">const class="type">long &lparam, class="kw">const class="type">class="kw">double &dparam, class="kw">const class="type">class="kw">string &sparam) { class=class="str">"cmt">//--- 键盘事件 if(id==CHARTEVENT_KEYDOWN) { if(lparam==class="num">82) { if(ChartGetDouble(class="num">0,CHART_PRICE_MAX,ChartWindowFind())>class="num">0)class=class="str">"cmt">// 检查图表上呈现的数据 { if(func_check_chart()==true) { if(type_draw==class="num">0)func_drawing(true,ext_spin_num,end_bar); } } } } } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 图标检查函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool func_check_chart() { class=class="str">"cmt">//--- 响应变量 class="type">bool x=class="kw">false; class=class="str">"cmt">//--- 找出图表尺寸 class="type">int win=ChartWindowFind(); class=class="str">"cmt">// 因为指标在子窗口中显示,定义子窗口 class="type">class="kw">double win_price_max=ChartGetDouble(class="num">0,CHART_PRICE_MAX,win); class=class="str">"cmt">// 图表的最大值 class="type">class="kw">double win_price_min=ChartGetDouble(class="num">0,CHART_PRICE_MIN,win); class=class="str">"cmt">// 图表的最小值 class="type">class="kw">double win_height_pixels=(class="type">class="kw">double)ChartGetInteger(class="num">0,CHART_HEIGHT_IN_PIXELS,win); class=class="str">"cmt">// 高度(像素) class="type">class="kw">double win_width_pixels=(class="type">class="kw">double)ChartGetInteger(class="num">0,CHART_WIDTH_IN_PIXELS,win); class=class="str">"cmt">// 宽度(像素) class="type">class="kw">double win_bars=(class="type">class="kw">double)ChartGetInteger(class="num">0,CHART_WIDTH_IN_BARS,win); class=class="str">"cmt">// 宽度(以柱形数计) class=class="str">"cmt">//--- 检查值是否改变
窗口尺寸与重绘触发怎么对齐
这段代码干的事很直接:先把价格、像素、BAR 数量都乘上 10^_Digits 转成整型再比,避免浮点误差误判窗口变化。只要最大价、最小价、图高、图宽、可见 BAR 数里任意一个整型值变了,或者当前周期出了新 BAR,就返回 true 让上层重绘。 因子计算用 MathPow(10,_Digits),例如 EURUSD 的 _Digits=5,factor 就是 100000,意味着价格比较精确到 0.00001;XAUUSD 的 _Digits=2,factor 仅为 100。同样的比较逻辑在不同品种上灵敏度差 1000 倍,这是写跨品种指标时容易踩的坑。 绘图函数 func_drawing 接收 type_action 区分「只刷最近 2 个纺锤」还是「重刷全部」:false 时只循环 num-2 到 end_bar_now 的两根,true 时从 begin 一直画到当前 BAR。begin 由 end_bar_now 与 num 的大小关系决定,不够数就回退到 long_period+1,防止数组越界。 尺寸换算里 scale_height = 图高像素 / (最高价-最低价),scale_width = 图宽像素 / 可见 BAR 数,这两个比值直接决定纺锤在屏幕上的胖瘦。若你发现 MT5 上纺锤被压成一条线,优先查 win_height_pixels_ext 或 win_price_max_ext 是否没随缩放更新——而这正由前面那段整型比较兜底。
class="type">int factor=(class="type">int)MathPow(class="num">10,_Digits);class=class="str">"cmt">// 设置double型转换成int型的转换因子 if(class="type">int(win_price_max*factor)!=class="type">int(win_price_max_ext*factor)) { win_price_max_ext=win_price_max; x=true; } if(class="type">int(win_price_min*factor)!=class="type">int(win_price_min_ext*factor)) { win_price_min_ext=win_price_min; x=true; } if(class="type">int(win_height_pixels*factor)!=class="type">int(win_height_pixels_ext*factor)) { win_height_pixels_ext=win_height_pixels; x=true; } if(class="type">int(win_width_pixels*factor)!=class="type">int(win_width_pixels_ext*factor)) { win_width_pixels_ext=win_width_pixels; x=true; } if(class="type">int(win_bars*factor)!=class="type">int(win_bars_ext*factor)) { win_bars_ext=win_bars; x=true; } if(func_new_bar(PERIOD_CURRENT)==true) { x=true; } class="kw">return(x); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 绘图函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void func_drawing(class="type">bool type_action,class=class="str">"cmt">// 修正类型: class="num">0-最近2个, class="num">1-所有 class="type">int num, class=class="str">"cmt">// 展现的纺锤形数量 class="type">int end_bar_now) class=class="str">"cmt">// 当前最近的柱形 { class="type">int begin; if(end_bar_now>num)begin=end_bar_now-num; else begin=long_period+class="num">1; class=class="str">"cmt">//--- 找到最大的VR值 class="type">class="kw">double VR_max=class="num">0; for(class="type">int x=begin; x<end_bar_now-class="num">1; x++) { if(Buff_VR[x]<Buff_VR[x+class="num">1])VR_max=Buff_VR[x+class="num">1]; else VR_max=Buff_VR[x]; } class=class="str">"cmt">//--- 计算尺寸 class="type">class="kw">double scale_height=win_height_pixels_ext/(win_price_max_ext-win_price_min_ext); class="type">class="kw">double scale_width=win_width_pixels_ext/win_bars_ext; class=class="str">"cmt">//--- 绘图(x - 对象的部分名称,y - 绘制的数据数组索引) if(type_action==class="kw">false)class=class="str">"cmt">// class="kw">false - 更新最近的两个纺锤 { for(class="type">int x=num-class="num">2,y=end_bar_now-class="num">2; y<end_bar_now; y++,x++) { func_picture("SPC"+IntegerToString(magic_numb)+IntegerToString(x),Buff_open[y],Buff_close[y],class="type">class="kw">datetime(Buff_time[y]),Buff_VR[y],VR_max,Buff_VWMA[y],ext_correct_VR,scale_height,scale_width); } } class=class="str">"cmt">//--- if(type_action==true)class=class="str">"cmt">// true - 更新所有纺锤形 { for(class="type">int x=class="num">0,y=begin; y<end_bar_now; y++,x++) {
「用 VWMA 与 VR 给每根 bar 算绘制角度」
在循环里拼好对象名后调用 func_picture,把开盘、收盘、时间以及成交量比例 VR、VR 峰值、VWMA 等一并传进去,最后统一 ChartRedraw 刷新图表。这个函数决定了每根 bar 在自定义图形里的宽度与倾斜方向。 func_picture 先用 VR/VR_maximum/correct*scale_width 算出像素宽度 cathetus_b;若 open<=close 标为 "r"(涨或十字),open>close 标为 "b"(跌)。这一步直接把价格行为转化成了可视化的几何参数。 当 open<VWMA 时,VWMA 压在开盘价上方,函数用 (VWMA-open)*scale_height 得到直角边 a,再用勾股定理求斜边并反算角度 corner。斜边若算到 0 则强制置 1,避免绘制崩溃。 在 MT5 里把 correct 和 scale_width 调小,会看到图形变窄、角度更陡;外汇与贵金属波动大,这类自定义绘制仅作辅助参考,实盘仍属高风险。
class="type">void func_picture(class="type">class="kw">string name, class=class="str">"cmt">// 对象名称 class="type">class="kw">double open, class=class="str">"cmt">// 柱形的开盘价 class="type">class="kw">double close, class=class="str">"cmt">// 柱形的收盘价 class="type">class="kw">datetime time, class=class="str">"cmt">// 柱形起始时间 class="type">class="kw">double VR, class=class="str">"cmt">// 成交量比例 class="type">class="kw">double VR_maximum,class=class="str">"cmt">// 成交量比例的最大值 class="type">class="kw">double VWMA, class=class="str">"cmt">// 成交量加权移动平均值 class="type">int correct, class=class="str">"cmt">// 成交量比例修正参数 class="type">class="kw">double scale_height,class=class="str">"cmt">// 高度尺寸(像素/价格) class="type">class="kw">double scale_width) class=class="str">"cmt">// 宽度尺寸(像素/柱形) { class="type">class="kw">string first_name;class=class="str">"cmt">// 用于绘图的文件的文件名首字母 class="type">class="kw">string second_name_right;class=class="str">"cmt">// 用于绘制右边图形的文件名的剩余部分 class="type">class="kw">string second_name_left; class=class="str">"cmt">// 用于绘制左边图形的文件名的剩余部分 class="type">class="kw">double cathetus_a;class=class="str">"cmt">// 直角边 a class="type">class="kw">double cathetus_b;class=class="str">"cmt">// 直角边 b class="type">class="kw">double hypotenuse;class=class="str">"cmt">// 斜边 class="type">int corner;class=class="str">"cmt">// 角 class=class="str">"cmt">//--- 找到柱形开始和结束的“角” cathetus_b=class="type">int(VR/VR_maximum/correct*scale_width);class=class="str">"cmt">// 宽度(像素) class=class="str">"cmt">//图像 class="num">540 if(open<=close) first_name="r";class=class="str">"cmt">// 上涨bar或者 Doji if(open>close) first_name="b"; class=class="str">"cmt">// 下跌bar class=class="str">"cmt">//--- if(open<VWMA)class=class="str">"cmt">// VWMA 在开盘价之上 { cathetus_a=class="type">int((VWMA-open)*scale_height); hypotenuse=MathCeil(MathSqrt(MathPow(cathetus_a,class="num">2)+MathPow(cathetus_b,class="num">2))); if(hypotenuse<=class="num">0) hypotenuse=class="num">1; corner=class="type">int(class="num">180-(MathArcsin(cathetus_b/hypotenuse)*class="num">360/(M_PI*class="num">2))); second_name_right=IntegerToString(corner);
◍ 用直角三角形把价格与VWMA的偏离画出来
在MT5里把K线开盘、收盘与VWMA的关系转成图形,核心是用直角边长反推斜边角度,再拼出对应角度的位图。代码里先判 open 与 VWMA 的大小,决定锚点和图片摆放方向。 当 open<VWMA 时,cathetus_a 取 (VWMA-open)*scale_height 的整数部分,斜边用 MathCeil 向上取整避免为0;corner 由 MathArcsin(cathetus_b/hypotenuse) 换算成角度,左块用 corner、右块用 180-corner 命名图片。 open>VWMA 的分支逻辑对称,但锚点换成 ANCHOR_LEFT_UPPER 与 ANCHOR_RIGHT_UPPER,Y偏移用 0 和 540-(cathetus_a+2)。open==VWMA 时直接调 90 度图片、高度写死为2像素,省去三角计算。 close<VWMA 时 corner 用 180 减去反正弦算出的角度,图片挂到 ANCHOR_LEFT_LOWER 并以 close 为基准价。外汇与贵金属波动大,scale_height 设错会让图形严重变形,建议先在EURUSD的M5上用 scale_height=100 验证。
second_name_left=IntegerToString(class="num">180-corner); func_obj_mod(name+"class="num">1","::Images\\for_SPC\\"+first_name+second_name_right+".bmp",class="type">int(cathetus_b+class="num">1),class="type">int(cathetus_a+class="num">1),class="num">540-class="type">int(cathetus_a+class="num">2),ANCHOR_LEFT_LOWER,time,open); func_obj_mod(name+"class="num">2","::Images\\for_SPC\\"+first_name+second_name_left+".bmp",class="type">int(cathetus_b+class="num">1),class="type">int(cathetus_a+class="num">1),class="num">0,ANCHOR_RIGHT_LOWER,time,open); } if(open>VWMA)class=class="str">"cmt">// VWMA在开盘价之下 { cathetus_a=class="type">int((open-VWMA)*scale_height); hypotenuse=MathCeil(MathSqrt(MathPow(cathetus_a,class="num">2)+MathPow(cathetus_b,class="num">2))); if(hypotenuse<=class="num">0) hypotenuse=class="num">1; corner=class="type">int((MathArcsin(cathetus_b/hypotenuse)*class="num">360/(M_PI*class="num">2))); second_name_right=IntegerToString(corner); second_name_left=IntegerToString(class="num">180-corner); func_obj_mod(name+"class="num">1","::Images\\for_SPC\\"+first_name+second_name_right+".bmp",class="type">int(cathetus_b+class="num">1),class="type">int(cathetus_a+class="num">1),class="num">0,ANCHOR_LEFT_UPPER,time,open); func_obj_mod(name+"class="num">2","::Images\\for_SPC\\"+first_name+second_name_left+".bmp",class="type">int(cathetus_b+class="num">1),class="type">int(cathetus_a+class="num">1),class="num">540-class="type">int(cathetus_a+class="num">2),ANCHOR_RIGHT_UPPER,time,open); } if(open==VWMA)class=class="str">"cmt">// VWMA在开盘价格水平上 { func_obj_mod(name+"class="num">1","::Images\\for_SPC\\"+first_name+"class="num">90"+".bmp",class="type">int(cathetus_b+class="num">1),class="num">2,class="num">0,ANCHOR_LEFT,time,open); func_obj_mod(name+"class="num">2","::Images\\for_SPC\\"+first_name+"class="num">90"+".bmp",class="type">int(cathetus_b+class="num">1),class="num">2,class="num">0,ANCHOR_RIGHT,time,open); } if(close<VWMA)class=class="str">"cmt">// VWMA在收盘价之上 { cathetus_a=class="type">int((VWMA-close)*scale_height); hypotenuse=MathCeil(MathSqrt(MathPow(cathetus_a,class="num">2)+MathPow(cathetus_b,class="num">2))); if(hypotenuse<=class="num">0) hypotenuse=class="num">1; corner=class="type">int(class="num">180-(MathArcsin(cathetus_b/hypotenuse)*class="num">360/(M_PI*class="num">2))); second_name_right=IntegerToString(corner); second_name_left=IntegerToString(class="num">180-corner); func_obj_mod(name+"class="num">3","::Images\\for_SPC\\"+first_name+second_name_right+".bmp",class="type">int(cathetus_b+class="num">1),class="type">int(cathetus_a+class="num">1),class="num">540-class="type">int(cathetus_a+class="num">2),ANCHOR_LEFT_LOWER,time,close);
收盘价与VWMA的位置决定贴图角度
当收盘价高于VWMA时,代码以(close-VWMA)*scale_height算出纵向直角边cathetus_a,再用MathCeil(MathSqrt(...))求斜边,若斜边≤0则强制置1避免除零。角度corner = arcsin(cathetus_b/斜边)*360/(π*2),右侧图名取corner、左侧取180-corner,分别用ANCHOR_LEFT_UPPER与ANCHOR_RIGHT_UPPER锚定到time/close坐标。 收盘价低于VWMA的分支镜像处理:锚点换成ANCHOR_RIGHT_LOWER,且右侧图Y偏移为0、左侧图偏移为540-int(cathetus_a+2),让两片位图在价格差构成的直角三角形两侧拼合。close==VWMA时退化成水平线,直接调90度图、高度压到2像素,左右分别用ANCHOR_LEFT/ANCHOR_RIGHT贴附。 func_obj_mod把上述参数落进MT5对象系统:ObjectSetString(0,name,OBJPROP_BMPFILE,file)绑定资源路径,ObjectSetInteger(0,name,OBJPROP_XSIZE,pix_x_b)设定X轴像素宽。你可在MT5里把scale_height调到5~10之间看贴图随波动率放大缩小,外汇与贵金属波动剧烈,此类可视化仅辅助判读,实际信号误判概率不低。
func_obj_mod(name+"class="num">4","::Images\\for_SPC\\"+first_name+second_name_left+".bmp",class="type">int(cathetus_b+class="num">1),class="type">int(cathetus_a+class="num">1),class="num">0,ANCHOR_RIGHT_LOWER,time,close); } if(close>VWMA)class=class="str">"cmt">// VWMA 在收盘价之下 { cathetus_a=class="type">int((close-VWMA)*scale_height); hypotenuse=MathCeil(MathSqrt(MathPow(cathetus_a,class="num">2)+MathPow(cathetus_b,class="num">2))); if(hypotenuse<=class="num">0) hypotenuse=class="num">1; corner=class="type">int((MathArcsin(cathetus_b/hypotenuse)*class="num">360/(M_PI*class="num">2))); second_name_right=IntegerToString(corner); second_name_left=IntegerToString(class="num">180-corner); func_obj_mod(name+"class="num">3","::Images\\for_SPC\\"+first_name+second_name_right+".bmp",class="type">int(cathetus_b+class="num">1),class="type">int(cathetus_a+class="num">1),class="num">0,ANCHOR_LEFT_UPPER,time,close); func_obj_mod(name+"class="num">4","::Images\\for_SPC\\"+first_name+second_name_left+".bmp",class="type">int(cathetus_b+class="num">1),class="type">int(cathetus_a+class="num">1),class="num">540-class="type">int(cathetus_a+class="num">2),ANCHOR_RIGHT_UPPER,time,close); } if(close==VWMA)class=class="str">"cmt">// VWMA在收盘价格水平上 { func_obj_mod(name+"class="num">3","::Images\\for_SPC\\"+first_name+"class="num">90"+".bmp",class="type">int(cathetus_b+class="num">1),class="num">2,class="num">0,ANCHOR_LEFT,time,close); func_obj_mod(name+"class="num">4","::Images\\for_SPC\\"+first_name+"class="num">90"+".bmp",class="type">int(cathetus_b+class="num">1),class="num">2,class="num">0,ANCHOR_RIGHT,time,close); } } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 函数 Obj Mod | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void func_obj_mod(class="type">class="kw">string name, class=class="str">"cmt">// 对象名称 class="type">class="kw">string file, class=class="str">"cmt">// 文件资源路径 class="type">int pix_x_b, class=class="str">"cmt">// X轴可见范围 class="type">int pix_y_a, class=class="str">"cmt">// Y轴可见范围 class="type">int shift_y, class=class="str">"cmt">// Y轴偏移 ENUM_ANCHOR_POINT anchor,class=class="str">"cmt">// 坐标 class="type">class="kw">datetime time, class=class="str">"cmt">// 时间坐标 class="type">class="kw">double price) class=class="str">"cmt">// 价格坐标 { ObjectSetString(class="num">0,name,OBJPROP_BMPFILE,file); ObjectSetInteger(class="num">0,name,OBJPROP_XSIZE,pix_x_b);class=class="str">"cmt">// X轴可见范围