手工图表和交易工具包(第一部分)。 准备:结构描述和助手类

本文介绍了一位手工交易者如何创建一套工具,使用键盘快捷键在图表上绘制趋势线和其他图形对象,以提高交易分析效率。这套工具包括对不同时间帧的快速切换、图形对象的管理以及自定义极值点等功能,且适用于MQL4和MQL5环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我是一名手工交易者。 我在分析图表时更喜欢不用复杂的公式和指标,只用纯手工(即以图形方式)进行分析。 这有助于我更加灵活地进行交易,关注一些难以形式化的事情,如果我看到波动在增加或放缓,则可以轻松地在时间帧之间切换,并在入场交易之前就知道了可能的价格行为。

基本上,我使用趋势线的不同组合(草叉、扇形、水平、等等)。 为此,我创建了一套便捷的工具,可一键快速绘制趋势线。 现在,我希望与社区共享此工具。

视频演示。 它如何运行

一般概念。 设定任务

故此,我们正在创建一套工具,该工具可帮助您利用键盘快捷键执行最频繁的操作。

可以实现哪些任务? 举例:

  • 按下 “H” 键(“Horizontal”)绘制一条简单的水平线,而按下 “ i ” 则绘制一条垂直线(仅因为它看起来像一条垂直线)
  • 从图表的任意点开始绘制一定长度(不是无限)的水平线
  • 在距起点一定(任意)距离处绘制垂直线
  • l利用按键切换时间帧,并重新排列图表上的图层
  • 在最近的极限点绘制预设价位的斐波那契扇形
  • 在最近的极限点绘制趋势线;它们的长度应为端点之间距离的倍数;在某些情况下,该趋势线也可以是射线
  • 绘制各种类型的安德鲁草叉(标准,Schiff,反向 Schiff 草叉 - 对于快速趋势)(请参阅 视频)
  • 对于草叉、趋势线和扇形的极值点,应能自定义极值点的顺序(分立左、右两侧的柱线数量)
  • 图形界面,可在不打开设置窗口的情况下自定义所需趋势线和极值点的参数
  • 一组订单管理函数:基于存款百分比开立订单,在开立市价订单或没有设置触发止损价位的挂单时自动设置止损价位,启用按价位部分平仓,尾随止损,诸如此类

当然,大多数任务可以用脚本自动执行。 我完成了其中的几个。 您可在文章的附件里找到它们。 然而,我更喜欢另一种方式。

在智能交易系统或指标里,我们能够创建 OnChartEvent 方法,包含针对任何事件的响应描述:击键、鼠标移动、图形对象的创建或删除。

这就是为什么我决定把所创建的程序作为一个包含文件的原因。 所有函数和变量都分布在若干个类里,从而令其更易于访问。 在这一点上,我只需要类即可方便地对函数进行分组。 这就是为什么在此首个实现中,我们将不使用诸如继承或工厂之类的复杂事物的原因。 这只是一个集合。

甚而,我想创建一个可以在 MQL4 和 MQL5 中均可运行的跨平台类。
 

程序结构

该函数库包含五个相关文件。 所有文件都位于 Include 目录中的 “Shortcuts” 文件夹下。 它们的名称如图所示:GlobalVariables.mqh,Graphics.mqh,Mouse.mqh,Shortcuts.mqh,Utilites.mqh。

函数库主文件(Shortcuts.mqh)
 

程序的主文件是 "Shortcuts.mqh"。 按键响应逻辑将写入此文件之中。 这是应该连接到智能交易系统的文件。 所有辅助文件也将包括在其中。

//+------------------------------------------------------------------+
//|                                                    Shortcuts.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                            https://www.mql5.com/ru/articles/7468 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com/en/articles/7468"

#include "GlobalVariables.mqh"
#include "Mouse.mqh"
#include "Utilites.mqh"
#include "Graphics.mqh"

//+------------------------------------------------------------------+
//| The main control class of the program. It should be connected    |
//| to the Expert Advisor                                            |
//+------------------------------------------------------------------+
class CShortcuts
  {
private:
   CGraphics         m_graphics;   // Object for drawing m_graphics
public:
                     CShortcuts();
   void              OnChartEvent(const int id,
                                  const long &lparam,
                                  const double &dparam,
                                  const string &sparam);
  };
//+------------------------------------------------------------------+
//| Default constructor                                              |
//+------------------------------------------------------------------+
CShortcuts::CShortcuts(void)
  {
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
  }

//+------------------------------------------------------------------+
//| Event handling function                                          |
//+------------------------------------------------------------------+
void CShortcuts::OnChartEvent(
   const int id,
   const long &lparam,
   const double &dparam,
   const string &sparam
)
  {
//---

   // This will contain the description of the events related to keystrokes
   // and mouse movements

   //  ...

  }
}

CShortcuts shortcuts;

该文件包含 CShortcuts 类描述。

在文件的开头,已连接所有帮助类

该类只有两个方法。 第一个是 OnChartEvent 事件响应程序,该事件响应程序将处理所有按键和鼠标移动事件。 第二个是默认构造函数,可在其中处理鼠标移动。

在类描述之后,将创建一个 shortcuts 变量,当连接函数库时,应在智能交易系统主体的 OnChartEvent 方法中使用该变量。

连接需要两行:

//+------------------------------------------------------------------+
//| The main Expert (file "Shortcuts-Main-Expert.mq5")               |
//+------------------------------------------------------------------+
#include <Shortcuts\Shortcuts.mqh>


// ...

//+------------------------------------------------------------------+
//| The ChartEvent function                                          |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   shortcuts.OnChartEvent(id,lparam,dparam,sparam);
  }

第一行连接类文件。 第二行则将事件响应控制转移到该类。

之后,智能交易系统就准备就绪,可以进行编译并绘制指标线。
 

鼠标移动响应类

该类将存储当前光标位置的所有基本参数:坐标 X,Y(以像素和价格/时间为单位),指针所处的柱线序号等 - 所有这些都存储在 “ Mouse.mqh ” 文件当中。

//+------------------------------------------------------------------+
//|                                                        Mouse.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                            https://www.mql5.com/ru/articles/7468 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com/en/articles/7468"
//+------------------------------------------------------------------+
//| Mouse movement handling class                                    |
//+------------------------------------------------------------------+
class CMouse
  {
   //--- Members
private:
   static int        m_x;           // X
   static int        m_y;           // Y
   static int        m_barNumber;   // Bar number
   static bool       m_below;       // Indication of a cursor above the price
   static bool       m_above;       // Indication of a cursor below the price

   static datetime   m_currentTime; // Current time
   static double     m_currentPrice;// Current price
   //--- Methods
public:

   //--- Remembers the main parameters of the mouse cursor
   static void       SetCurrentParameters(
      const int id,
      const long &lparam,
      const double &dparam,
      const string &sparam
   );
   //--- Returns the X coordinate (in pixels) of the current cursor position
   static int        X(void) {return m_x;}
   //--- Returns the Y coordinate (in pixels) of the current cursor position
   static int        Y(void) {return m_y;}
   //--- Returns the price of the current cursor position
   static double     Price(void) {return m_currentPrice;}
   //--- Returns the time of the current cursor position
   static datetime   Time(void) {return m_currentTime;}
   //--- Returns the bar number of the current cursor position
   static int        Bar(void) {return m_barNumber;}
   //--- Returns a flag showing that the price is below the Low of the current bar
   static bool       Below(void) {return m_below;}
   //--- Returns a flag showing that the price is above the High of the current bar
   static bool       Above(void) {return m_above;}
  };
//---

int CMouse::m_x=0;
int CMouse::m_y=0;
int CMouse::m_barNumber=0;
bool CMouse::m_below=false;
bool CMouse::m_above=false;
datetime CMouse::m_currentTime=0;
double CMouse::m_currentPrice=0;


//+------------------------------------------------------------------+
//| Remembers the main parameters for a mouse movement: coordinates  |
//| of cursor in pixels and price/time, whether the cursor is        |
//| above or below the price.                                        |
//|+-----------------------------------------------------------------+
static void CMouse::SetCurrentParameters(
   const int id,
   const long &lparam,
   const double &dparam,
   const string &sparam
)
  {
//---
   int window = 0;
//---
   ChartXYToTimePrice(
      0,
      (int)lparam,
      (int)dparam,
      window,
      m_currentTime,
      m_currentPrice
   );
   m_x=(int)lparam;
   m_y=(int)dparam;
   m_barNumber=iBarShift(
                  Symbol(),
                  PERIOD_CURRENT,
                  m_currentTime
               );
   m_below=m_currentPrice<iLow(Symbol(),PERIOD_CURRENT,m_barNumber);
   m_above=m_currentPrice>iHigh(Symbol(),PERIOD_CURRENT,m_barNumber);
  }

//+------------------------------------------------------------------+

该类可在程序中的任何位置使用,因为其方法已被声明为静态。 故此无需创建该类的实例即可调用它。

智能交易系统设置模块的描述。 GlobalVariables.mqh 文件

所有提供给用户的设置均存储在 GlobalVariables.mqh 文件当中。

下一篇文章将提供更多设置的说明,因为我们会添加更多图形对象。

以下是当前版本中的设置代码:

//+------------------------------------------------------------------+
//|                                              GlobalVariables.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                            https://www.mql5.com/ru/articles/7468 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com/en/articles/7468"
//+------------------------------------------------------------------+
//| File describing parameters available to the user                 |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Key settings                                                     |
//+------------------------------------------------------------------+
input string   Keys="=== Key settings ===";
input string   Up_Key="U";            // Switch timeframe up
input string   Down_Key="D";          // Switch timeframe down
input string   Trend_Line_Key="T";              // Trend line
input string   Switch_Trend_Ray_Key="R";        // Indication of a trend line ray
input string   Z_Index_Key="Z";                 // Indication of the chart on top

//+------------------------------------------------------------------+
//| Size settings                                                    |
//+------------------------------------------------------------------+
input string   Dimensions="=== Size settings ===";
input int      Trend_Line_Width=2;        // Trend line width

//+------------------------------------------------------------------+
//| Display styles                                                   |
//+------------------------------------------------------------------+
input string   Styles="=== Display styles ===";
input ENUM_LINE_STYLE      Trend_Line_Style=STYLE_SOLID;       // Trend line style

//+------------------------------------------------------------------+
//| Other parameters                                                 |
//+------------------------------------------------------------------+
input string               Others="=== Other parameters ===";

input bool                 Is_Trend_Ray=false;                      // Trend line - ray
input bool                 Is_Change_Timeframe_On_Create = true;    // Hide objects on higher timeframes?
                                                                    //   (true - hide, false - show)
input bool                 Is_Select_On_Create=true;                // Select upon creation
input bool                 Is_Different_Colors=true;                // Change colors for times

// Number of bars on the left and on the right
// for trend line and fan extreme points
input int                  Fractal_Size_Left=1;                     // Size of the left fractal
input int                  Fractal_Size_Right=1;                    // Size of the right fractal

//+------------------------------------------------------------------+
//| Name prefixes of drawn shapes (can be change only in code,       |
//| not visible in EA parameters)                                    |
//+------------------------------------------------------------------+
// string   Prefixes="=== Prefixes ===";

string   Trend_Line_Prefix="Trend_";                     // Trend line prefix

//+------------------------------------------------------------------+
//| Colors for objects of one timeframe (can be changed only in code,|
//| not visible in EA parameters)                                    |
//+------------------------------------------------------------------+
// string TimeframeColors="=== Time frame colors ===";
color mn1_color=clrCrimson;
color w1_color=clrDarkOrange;
color d1_color=clrGoldenrod;
color h4_color=clrLimeGreen;
color h1_color=clrLime;
color m30_color=clrDeepSkyBlue;
color m15_color=clrBlue;
color m5_color=clrViolet;
color m1_color=clrDarkViolet;
color common_color=clrGray;

//--- Auxiliary constant for displaying error messages
#define DEBUG_MESSAGE_PREFIX "=== ",__FUNCTION__," === "

//--- Constants for describing the main timeframes when drawing
#define PERIOD_LOWER_M5 OBJ_PERIOD_M1|OBJ_PERIOD_M5
#define PERIOD_LOWER_M15 PERIOD_LOWER_M5|OBJ_PERIOD_M15
#define PERIOD_LOWER_M30 PERIOD_LOWER_M15|OBJ_PERIOD_M30
#define PERIOD_LOWER_H1 PERIOD_LOWER_M30|OBJ_PERIOD_H1
#define PERIOD_LOWER_H4 PERIOD_LOWER_H1|OBJ_PERIOD_H4
#define PERIOD_LOWER_D1 PERIOD_LOWER_H4|OBJ_PERIOD_D1
#define PERIOD_LOWER_W1 PERIOD_LOWER_D1|OBJ_PERIOD_W1
//+------------------------------------------------------------------+

辅助函数
 

该程序拥有许多函数,这些函数与绘图没有直接关系,但是它们可以帮助您找到极端点,切换时间表等。 所有这些函数都在 “Utilites.mqh” 文件中实现。

Utilities.mqh 的文件头部

//+------------------------------------------------------------------+
//|                                                     Utilites.mqh |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                            https://www.mql5.com/ru/articles/7468 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com/en/articles/7468"

//+------------------------------------------------------------------+
//| Class describing auxiliary functions                             |
//+------------------------------------------------------------------+
class CUtilites
  {
public:
   //--- Changes the timeframe to the next one on the toolbar
   static void       ChangeTimeframes(bool isUp);
   //--- Converts string command constants to keycodes
   static int        GetCurrentOperationChar(string keyString);
   //--- Switches layers in charts (the chart is on top of all objects)
   static void       ChangeChartZIndex(void);
   //--- Returns the number of the nearest extreme bar
   static int        GetNearestExtremumBarNumber(
      int starting_number=0,
      bool is_search_right=false,
      bool is_up=false,
      int left_side_bars=1,
      int right_side_bars=1,
      string symbol=NULL,
      ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT
   );

   //--- Returns the color for the current timeframe
   static color      GetTimeFrameColor(long allDownPeriodsValue);
   //--- Returns a list of all timeframes lower than the current one (including the current one)
   static long       GetAllLowerTimeframes(int NeededTimeframe=PERIOD_CURRENT);
   //--- Coordinates of the straight line. Writes numbers of extreme bars to points p1 and p2
   static void       SetExtremumsBarsNumbers(bool _is_up,int &p1, int &p2);
   //--- Converts a string to an array of floating point numbers
   static void       StringToDoubleArray(
      string _haystack,
      double &_result[],
      const string _delimiter=","
   );
   //--- Determines the name of the current object
   static string            GetCurrentObjectName(
      const string _prefix,
      const ENUM_OBJECT _type=OBJ_TREND,
      int _number = -1
   );
   //--- Obtains the number of the next object
   static int               GetNextObjectNumber(
      const string _prefix,
      const ENUM_OBJECT _object_type,
      bool true
   );
   //--- Returns the distance, in screen pixels, between adjacent bars
   static int               GetBarsPixelDistance(void);
   //--- Converts a numeric value of the timeframe to its string name
   static string            GetTimeframeSymbolName(
      ENUM_TIMEFRAMES _timeframe=PERIOD_CURRENT  // Desired timeframe
   );
  };

该函数顺序更改图表的周期
 

此文件中的第一个函数很简单。 例如,顺序更改当前图形周期的函数如下所示:

//+------------------------------------------------------------------+
//| Sequentially changes the current chart period                    |
//|                                                                  |
//| In this implementation, only the timeframes shown in the         |
//| standard panel are used.                                         |
//|                                                                  |
//| Parameters:                                                      |
//|    _isUp - timeframe switch direction: up (true)                 |
//|            or down (false)                                       |
//+------------------------------------------------------------------+
static void CUtilites::ChangeTimeframes(bool _isUp)
  {
   ENUM_TIMEFRAMES timeframes[] =
     {
      PERIOD_CURRENT,
      PERIOD_M1,
      PERIOD_M5,
      PERIOD_M15,
      PERIOD_M30,
      PERIOD_H1,
      PERIOD_H4,
      PERIOD_D1,
      PERIOD_W1,
      PERIOD_MN1
     };
   int period = Period();
   int shift = ArrayBsearch(timeframes,period);
   if(_isUp && shift < ArraySize(timeframes)-1)
     {
      ChartSetSymbolPeriod(0,NULL,timeframes[++shift]);
     }
   else
      if(!_isUp && shift > 1)
        {
         ChartSetSymbolPeriod(0,NULL,timeframes[--shift]);
        }
  } 

首先,在函数中,于默认工具栏里指定所有时间帧的数组。 如果您希望在 MetaTrader 5 的所有可用时间帧之间切换,则应将响应的常量写入数组。 不过,在这种情况下,可能会丢失兼容性,并且该函数库在 MQL4 里可能会停止运行。

接下来,我们利用标准函数获取当前周期,并在列表中查找它。

然后,利用标准 ChartSetSymbolPeriod 函数切换图表时间帧,当前时间帧之后下一个时间帧应传递给函数。

代码中用到的其他函数应当很清晰,故无须解释。 这些代码很简单。

一些简单的函数

//+------------------------------------------------------------------+
//| Converts string command constants to keycodes                    |
//+------------------------------------------------------------------+
static int CUtilites::GetCurrentOperationChar(string keyString)
  {
   string keyValue = keyString;
   StringToUpper(keyValue);
   return(StringGetCharacter(keyValue,0));
  }
//+------------------------------------------------------------------+
//| Switch chart position to display on top of other objects         |
//+------------------------------------------------------------------+
static void CUtilites::ChangeChartZIndex(void)
  {
   ChartSetInteger(
      0,
      CHART_FOREGROUND,
      !(bool)ChartGetInteger(0,CHART_FOREGROUND)
   );
   ChartRedraw(0);
  } 
//+------------------------------------------------------------------+
//| Returns a string name for any standard timeframe                 |
//| Parameters:                                                      |
//|    _timeframe - ENUM_TIMEFRAMES numeric value for which we need  |
//|                 to find a string name                            |
//| Return value:                                                    |
//|   string name of the required timeframe                          |
//+------------------------------------------------------------------+
static string CUtilites::GetTimeframeSymbolName(
   ENUM_TIMEFRAMES _timeframe=PERIOD_CURRENT  // Desired timeframe
)
  {
   ENUM_TIMEFRAMES current_timeframe; // current timeframe
   string result = "";
//---
   if(_timeframe == PERIOD_CURRENT)
     {
      current_timeframe = Period();
     }
   else
     {
      current_timeframe = _timeframe;
     }
//---
   switch(current_timeframe)
     {
      case PERIOD_M1:
         return "M1";
      case PERIOD_M2:
         return "M2";
      case PERIOD_M3:
         return "M3";
      case PERIOD_M4:
         return "M4";
      case PERIOD_M5:
         return "M5";
      case PERIOD_M6:
         return "M6";
      case PERIOD_M10:
         return "M10";
      case PERIOD_M12:
         return "M12";
      case PERIOD_M15:
         return "M15";
      case PERIOD_M20:
         return "M20";
      case PERIOD_M30:
         return "M30";
      case PERIOD_H1:
         return "H1";
      case PERIOD_H2:
         return "M1";
      case PERIOD_H3:
         return "H3";
      case PERIOD_H4:
         return "H4";
      case PERIOD_H6:
         return "H6";
      case PERIOD_H8:
         return "H8";
      case PERIOD_D1:
         return "D1";
      case PERIOD_W1:
         return "W1";
      case PERIOD_MN1:
         return "MN1";
      default:
         return "Unknown";
     }
  }
//+------------------------------------------------------------------+
//| Returns the standard color for the current timeframe             |
//+------------------------------------------------------------------+
static color CUtilites::GetTimeFrameColor(long _all_down_periods_value)
  {
   if(Is_Different_Colors)
     {
      switch((int)_all_down_periods_value)
        {
         case OBJ_PERIOD_M1:
            return (m1_color);
         case PERIOD_LOWER_M5:
            return (m5_color);
         case PERIOD_LOWER_M15:
            return (m15_color);
         case PERIOD_LOWER_M30:
            return (m30_color);
         case PERIOD_LOWER_H1:
            return (h1_color);
         case PERIOD_LOWER_H4:
            return (h4_color);
         case PERIOD_LOWER_D1:
            return (d1_color);
         case PERIOD_LOWER_W1:
            return (w1_color);
         case OBJ_ALL_PERIODS:
            return (mn1_color);
         default:
            return (common_color);
        }
     }
   else
     {
      return (common_color);
     }
  }

极值搜索函数及其应用
 

下一个函数有助于找到极值点。 根据参数,极值点可以位于鼠标指针的右侧或左侧。 另外,您可以在极值的左侧和右侧指定所需的柱线数量。

//+------------------------------------------------------------------+
//| Returns the number of the nearest fractal in the selected        |
//|   direction                                                      |
//| Parameters:                                                      |
//|   starting_number - bar number at which the search starts        |
//|   is_search_right - search to the right (true) or left (false)   |
//|   is_up - if "true", search by High levels, otherwise - Low      |
//|   left_side_bars - number of bars on the left                    |
//|   right_side_bars - number of bars on the right                  |
//|   symbol - symbol name for search                                |
//|   timeframe - period for search                                  |
//| Return value:                                                    |
//|   the number of the extremum closest to starting_number,         |
//|   matching the specified parameters                              |                 |
//+------------------------------------------------------------------+
static int CUtilites::GetNearestExtremumBarNumber(
   int starting_number=0,              // Initial bar number
   const bool is_search_right=false,   // Direction to the right
   const bool is_up=false,             // Search by Highs
   const int left_side_bars=1,         // Number of bars to the left
   const int right_side_bars=1,        // Number of bars to the right
   const string symbol=NULL,           // The required symbol
   const ENUM_TIMEFRAMES timeframe=PERIOD_CURRENT // The required timeframe
)
  {
//---
   int   i,
         nextExtremum,
         sign = is_search_right ? -1 : 1;

//--- If the starting bar is specified incorrectly
//--- (is beyond the current chart borders)
//--- and search - towards the border...
   if((starting_number-right_side_bars<0
       && is_search_right)
      || (starting_number+left_side_bars>iBars(symbol,timeframe)
          && !is_search_right)
     )
     { //--- ...it is necessary to display an error message
      if(Print_Warning_Messages)
        {
         Print(DEBUG_MESSAGE_PREFIX,
               "Can't find extremum: ",
               "wrong direction");
         Print("left_side_bars = ",left_side_bars,"; ",
               "right_side_bars = ",right_side_bars);
        }
      return (-2);
     }
   else
     {
      //--- otherwise - the direction allows you to select the correct bar.
      //---   check all bars in the required direction,
      //---   as long as we are beyond the known chart borders
      while((starting_number-right_side_bars<0
             && !is_search_right)
            || (starting_number+left_side_bars>iBars(symbol,timeframe)
                && is_search_right)
           )
        {
         starting_number +=sign;
        }
     }
//---
   i=starting_number;
 
   //--- Preparation is complete. Proceed to search
   while(i-right_side_bars>=0
         && i+left_side_bars<iBars(symbol,timeframe)
        )
     {
      //--- Depending on the level, check the required extremum
      if(is_up)
        { //--- either the upper one
         nextExtremum = iHighest(
                           Symbol(),
                           Period(),
                           MODE_HIGH,
                           left_side_bars+right_side_bars+1,
                           i-right_side_bars
                        );
        }
      else
        {  //--- or the lower one
         nextExtremum = iLowest(
                           Symbol(),
                           Period(),
                           MODE_LOW,
                           left_side_bars+right_side_bars+1,
                           i-right_side_bars
                        );
        }
      if(nextExtremum == i) // If the current bar is an extremum,
        {
         return nextExtremum;  // the problem is solved
        }
      else // Otherwise - continue to shift the counter of the checked candlestick to the desired direction
         if(is_search_right)
           {
            if(nextExtremum<i)
              {
               i=nextExtremum;
              }
            else
              {
               i--;
              }
           }
         else
           {
            if(nextExtremum>i)
              {
               i=nextExtremum;
              }
            else
              {
               i++;
              }
           }
     }
//--- If the edge is reached but no extremum has been found,
   if(Print_Warning_Messages)
     {
      //--- show an error message.
      Print(DEBUG_MESSAGE_PREFIX,
            "Can't find extremum: ",
            "an incorrect starting point or wrong border conditions.");
      Print("left_side_bars = ",left_side_bars,"; ",
            "right_side_bars = ",right_side_bars);
     }
   return (-1);
  } 

为了绘制趋势线,我们需要一个函数来找到鼠标右边两个最近的极值点。 此函数可以使用前一个函数:

//+------------------------------------------------------------------+
//| Finds 2 nearest extreme points to the right of the current       |
//| mouse pointer position                                           |
//| Parameters:                                                      |
//|    _is_up - search by High (true) or Low (false)                 |
//|    int &_p1 - bar number of the first point                      |
//|    int &_p2 - bar number of the second point                     |
//+------------------------------------------------------------------+
static void CUtilites::SetExtremumsBarsNumbers(
   bool _is_up, // search by High (true) or by Low (false)
   int &_p1,    // bar number of the first point
   int &_p2     // bar number of second point
)
  {
   int dropped_bar_number=CMouse::Bar();
//---
   _p1=CUtilites::GetNearestExtremumBarNumber(
          dropped_bar_number,
          true,
          _is_up,
          Fractal_Size_Left,
          Fractal_Size_Right
       );
   _p2=CUtilites::GetNearestExtremumBarNumber(
          _p1-1, // Bar to the left of the previous found extremum
          true,
          _is_up,
          Fractal_Size_Left,
          Fractal_Size_Right
       );
   if(_p2<0)
     {
      _p2=0;
     }
  } 

产生对象名称
 

为了能够绘制一系列相同对象,这些对象的名称必须具有唯一性。 最有效的方法是用与此对象类型相对应的前缀,并为其添加唯一的数字。 GlobalVariables.mqh 中列出了不同对象类型的前缀。

数字则由相应的函数生成。

//+------------------------------------------------------------------+
//| Returns the number of the next object in the series              |
//| Parameters:                                                      |
//|   prefix - name prefix for this group of objects.                |
//|   object_type - the type of objects to search in.                |
//|   only_prefixed - if "false", search in all objects              |
//|                      of this type, "true" - only the objects     |
//|                      with the specified prefix                   |
//| Return value:                                                    |
//|   number of the next object in series. If search by prefix,      |
//|      and the existing numbering has a gap, the next number       |
//|      will be at gap beginning.                                   |
//+------------------------------------------------------------------+
int               CUtilites::GetNextObjectNumber(
   const string prefix,
   const ENUM_OBJECT object_type,
   bool true
)
  {
   int count = ObjectsTotal(0,0,object_type),
       i,
       current_element_number,
       total_elements = 0;
   string current_element_name = "",
          comment_text = "";
//---
   if(only_prefixed)
     {
      for(i=0; i<count; i++)
        {
         current_element_name=ObjectName(0,i,0,object_type);
         if(StringSubstr(current_element_name,0,StringLen(prefix))==prefix)
           {
            current_element_number=
               (int)StringToInteger(
                  StringSubstr(current_element_name,
                               StringLen(prefix),
                               -1)
               );
            if(current_element_number!=total_elements)
              {
               break;
              }
            total_elements++;
           }
        }
     }
   else
     {
      total_elements = ObjectsTotal(0,-1,object_type);
      do
        {
         current_element_name = GetCurrentObjectName(
                                   prefix,
                                   object_type,
                                   total_elements
                                );
         if(ObjectFind(0,current_element_name)>=0)
           {
            total_elements++;
           }
        }
      while(ObjectFind(0,current_element_name)>=0);
     }
//---
   return(total_elements);
  } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值