文章 "利用 CCanvas 类开发自定义指标"

 

新文章 利用 CCanvas 类开发自定义指标已发布:

本文利用 CCanvas 类的图形基元应对自定义图形指标的开发。

不同于简单的弧形指示, 扇区图看起来好像具有间隔相等的标签。当创建这类指标的布局时, 我决定制作十个扇区并添加一个新的元素 – 内框。具有弧形扇区指示的基本结构如图例. 5 所示。


图例. 5. 带有弧形指示的圆形指标的基本结构

作者:Alexander Fedosov

 

感谢作者的文章。我注意到了很多简单(但同时也很优雅)的解决方案,我一定会在我的程序中使用它们。

 
MetaQuotes Software Corp.:

已发布文章使用 CCanvas 类创建自定义指标

作者:亚历山大-费多索夫


哦,真漂亮!我把它添加到我的纪念册中;)
 

我想再次提请您注意,在应用使用 CustomGUI 类实现的同一指标的多个副本时,Create() 方法中的名称必须不同。 示例如下。

#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0
//---
#include <CustomGUI\CustomGUI.mqh>
CCircleSection ind;
//+------------------------------------------------------------------+
//| 指标的输入参数|
//+------------------------------------------------------------------+
input ENUM_TIMEFRAMES   tf=PERIOD_CURRENT;
input int               period=10;
input int               indsize=50;
input ENUM_ORIENTATION  orient=VERTICAL;
input int               X=100;
input int               Y=100;
//---
int      IndHandle;
double   rsi[];
//+------------------------------------------------------------------+
//| 自定义指示器初始化函数
//+------------------------------------------------------------------+
int OnInit()
  {
//--- 获取指标句柄
   IndHandle=iRSI(Symbol(),tf,period,PRICE_CLOSE);
   if(IndHandle==INVALID_HANDLE)
     {
      Print("Failed to get indicator handle");
      return(INIT_FAILED);
     }
   ArraySetAsSeries(rsi,true);
//---
   ind.Radius(indsize);
   ind.LabelSize(15);
   ind.LabelValue("RSI "+"("+IntegerToString(period)+")");
   ind.Orientation(orient);
   ind.Create("rsi_custom"+IntegerToString(MathRand()),X,Y);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 自定义指标迭代函数
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   if(CopyBuffer(IndHandle,0,0,1,rsi)<1)
      return(0);
   ind.NewValue(rsi[0]);
//--- 为下一次调用返回 prev_calculated 的值
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| 自定义指标去初始化功能
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ind.Delete();
   ChartRedraw();
  }
//+------------------------------------------------------------------+

Create() 方法有一个唯一的名称。

附加的文件:
 

谢谢。

能否在 MT4 或 MT5 中实现选择 指标对象的 功能?(例如,线条)。

例如,双击一条线,它就会以粗线突出显示,并出现该线的描述,反之亦然。

 
Ilmir Galiev:

谢谢。

能否在 MT4 或 MT5 中实现选择 指标对象的 功能?(例如,线条)。

例如,双击一条线,它就会以粗线条突出显示,出现对该线的描述,反之亦然。

不是。这种方法的本质是,当任何条件发生变化时,都会重新绘制一幅。它不会对热键或鼠标点击事件做出反应。
 
Alexander Fedosov:
这种方法的本质是,当任何条件发生变化时,都会重新绘制一幅图片。它不响应热键或鼠标点击事件。

得了吧。鼠标点击是什么?不是 "改变任何条件"。它会产生一个事件,用来重新绘制画布。伊尔米尔,你的问题的正确答案是当然可以。

 

好主题。感谢作者,我将在 canvas..... 上制作一个tick 指标。

我注意到这一点。

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CCanvasBase
  {
private:
   //--- 画布名称
   string            m_canvas_name;
   //--- 画布坐标
   int               m_x;
   int               m_y;
   //--- 画布尺寸
   int               m_x_size;
   int               m_y_size;
protected:
   CCanvas           m_canvas;
   //--- 为对象创建图形资源
   bool              CreateCanvas(void);
   //-- 删除图形资源
   bool              DeleteCanvas(void);
public:
                     CCanvasBase(void);
                    ~CCanvasBase(void);
   //--- 设置并返回坐标
   void              X(const int x)                         { m_x=x;                      }
   void              Y(const int y)                         { m_y=y;                      }
   int               X(void)                                { return(m_x);                }
   int               Y(void)                                { return(m_y);                }
   //--- 设置并返回尺寸
   void              XSize(const int x_size)                { m_x_size=x_size;            }
   void              YSize(const int y_size)                { m_y_size=y_size;            }
   int               XSize(void)                            { return(m_x_size);           }
   int               YSize(void)                            { return(m_y_size);           }
   //--- 创建时设置指标名称
   void              Name(const string canvas_name) { m_canvas_name=canvas_name;  }
  };

有一个私有 数据成员m_canvas_name,但设置其值的方法Name()公共的。我认为这违反了封装原则。我将把这个方法设为私有。

 
Dennis Kirichenko:

好主题。感谢作者,我将在 canvas.... 上制作一个tick 指标。

如果您有草图,请发送截图/视频。我自己也发布过这样一个指标,但没有得到大家的认可。虽然我还没有找到更好的方案。在画布上看到其他解决方案很有意思。

 
fxsaber:

我自己也贴出了这样一个指标,但它并没有到人民那里去。

它确实去了,确实去了。

我甚至正试图在此基础上制作一个滴答速度指示器。

 
Andrey Khatimlianskii:
走,走,走。

我甚至想用它来制作一个滴答声速率指示器。

这是好消息!你的想法是什么?用自定义时间序列代替刻度 线历史记录