Как начать работу с MQL5 - страница 28

 
Vladimir Karputov:

Задача № 1: Определите, на какую глубину вам нужно просканировать рынок.

Под глубиной, я надеюсь, вы подразумеваете период оглядки, обычно у меня на экране 150-200 баров, поэтому я бы хотел, чтобы он был 200.

 
Ahmad861 :

Под глубиной я надеюсь, вы имеете в виду период оглядки, у меня обычно 150-200 баров на экране, поэтому я хотел бы, чтобы он был 200.

Да, вы все правильно поняли. Далее необходимо ввести параметры "похожие свечи" - это процентный спред или спред в пунктах. Также необходим параметр "группа свечей" - группа соседних свечей, среди которых идет поиск...

 
Vladimir Karputov:

Да, вы все правильно поняли. Далее нужно ввести настройки для "похожих свечей" - это процентный спред или спред в пунктах. Также необходим параметр "группа свечей" - группа соседних свечей, среди которых идет поиск...

Я не понял эту часть

 
Я искал похожие свечи в индикаторе Similar Candle - можете взять его за основу.
Similar Candle
Similar Candle
  • www.mql5.com
Индикатор ищет подобные свечи
 
Vladimir Karputov:
Я искал похожие свечи в индикаторе Similar Candle - можете взять его за основу.

Извините, но я все еще не понимаю, что я должен делать.

 

Закрытие позиции, если своп был начислен

Функция: 'CloseAllPositionsFirstSwap'

//+------------------------------------------------------------------+
//| Close all positions First Swap                                   |
//+------------------------------------------------------------------+
void CloseAllPositionsFirstSwap(void)
  {
   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
           {
            double swap=m_position.Swap();
            if(swap<=0.0)
               continue;
            if(m_position.PositionType()==POSITION_TYPE_BUY)
              {
               if(!m_trade.PositionClose(m_position.Ticket())) // close a position by the specified m_symbol
                  if(InpPrintLog)
                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","BUY PositionClose ",m_position.Ticket(),", ",m_trade.ResultRetcodeDescription());
              }
            if(m_position.PositionType()==POSITION_TYPE_SELL)
              {
               if(!m_trade.PositionClose(m_position.Ticket())) // close a position by the specified m_symbol
                  if(InpPrintLog)
                     Print(__FILE__," ",__FUNCTION__,", ERROR: ","SELL PositionClose ",m_position.Ticket(),", ",m_trade.ResultRetcodeDescription());
              }
           }
  }

Рекомендуется вызывать эту функцию в начале дня.

 

Советник может открыть только одну позицию одного типа
.

Код: Пример Одна позиция одного типа.mq5

Принцип работы эксперта: функция'CalculateAllPositions' вызывается в'OnTick'. Функция'CalculateAllPositions' вычисляет позиции 'BUY' и 'SELL'.

//+------------------------------------------------------------------+
//|                             Example One position of one type.mq5 |
//|                              Copyright © 2021, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021, Vladimir Karputov"
#property version   "1.000"
//---
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
//---
CPositionInfo  m_position;                   // object of CPositionInfo class
CTrade         m_trade;                      // object of CTrade class
CSymbolInfo    m_symbol;                     // object of CSymbolInfo class
//--- input parameters
input group             "Additional features"
input ulong    InpDeviation         = 10;          // Deviation, in Points (1.00045-1.00055=10 points)
input ulong    InpMagic             = 200;         // Magic number
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
//---
   ResetLastError();
   if(!m_symbol.Name(Symbol())) // sets symbol name
     {
      Print(__FILE__," ",__FUNCTION__,", ERROR: CSymbolInfo.Name");
      return(INIT_FAILED);
     }
   RefreshRates();
//---
   m_trade.SetExpertMagicNumber(InpMagic);
   m_trade.SetMarginMode();
   m_trade.SetTypeFillingBySymbol(m_symbol.Name());
   m_trade.SetDeviationInPoints(InpDeviation);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   int count_buys=0,count_sells=0;
   CalculateAllPositions(count_buys,count_sells);
   if(count_buys==0)
     {
      // Search for a BUY signal
     }
   if(count_sells==0)
     {
      // Search for a SELL signal
     }
  }
//+------------------------------------------------------------------+
//| Refreshes the symbol quotes data                                 |
//+------------------------------------------------------------------+
bool RefreshRates()
  {
//--- refresh rates
   if(!m_symbol.RefreshRates())
     {
      Print(__FILE__," ",__FUNCTION__,", ERROR: ","RefreshRates error");
      return(false);
     }
//--- protection against the return value of "zero"
   if(m_symbol.Ask()==0 || m_symbol.Bid()==0)
     {
      Print(__FILE__," ",__FUNCTION__,", ERROR: ","Ask == 0.0 OR Bid == 0.0");
      return(false);
     }
//---
   return(true);
  }
//+------------------------------------------------------------------+
//| Calculate all positions Buy and Sell                             |
//+------------------------------------------------------------------+
void CalculateAllPositions(int &count_buys,int &count_sells)
  {
   count_buys=0;
   count_sells=0;
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
         if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==InpMagic)
           {
            if(m_position.PositionType()==POSITION_TYPE_BUY)
               count_buys++;
            if(m_position.PositionType()==POSITION_TYPE_SELL)
               count_sells++;
           }
//---
   return;
  }
//+------------------------------------------------------------------+
 

Количество отложенных ордеров (только системные функции, без ООП)

Функция'CalculateAllPendingOrdersSystem'

//+------------------------------------------------------------------+
//| Calculate all pending orders for symbol                          |
//+------------------------------------------------------------------+
int CalculateAllPendingOrdersSystem(const string symbol,const ulong magic)
  {
   int total=0;
   for(int i=OrdersTotal()-1; i>=0; i--) // returns the number of current orders
     {
      ulong order_ticket=OrderGetTicket(i); // selects the pending order by index for further access to its properties
      if(order_ticket==0)
         continue;
      string order_symbol=OrderGetString(ORDER_SYMBOL); // get symbol
      long order_magic=OrderGetInteger(ORDER_MAGIC); // get magic
      //---
      if(order_symbol==symbol && order_magic==magic)
         total++;
     }
//---
   return(total);
  }

На рынке есть два отложенных ордера с Magic '200' и один с Magic '100' - всего три отложенных ордера (все три отложенных ордера для символа 'EURAUD').

Запускаем скрипт:

//+------------------------------------------------------------------+
//|                                                     Script 1.mq5 |
//|                              Copyright © 2021, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021, Vladimir Karputov"
#property version   "1.000"
#property script_show_inputs
//--- input parameters
input string   InpSymbol   = "EURUSD"; // Symbol
input ulong    InpMagic    = 200;      // Magic number
//---
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   int total=CalculateAllPendingOrdersSystem(InpSymbol,InpMagic);
   PrintFormat("Symbol %s, Magic %d, Pending Orders %d:",InpSymbol,InpMagic,total);
  }
//+------------------------------------------------------------------+
//| Calculate all pending orders for symbol                          |
//+------------------------------------------------------------------+
int CalculateAllPendingOrdersSystem(const string symbol,const ulong magic)
  {
   int total=0;
   for(int i=OrdersTotal()-1; i>=0; i--) // returns the number of current orders
     {
      ulong order_ticket=OrderGetTicket(i); // selects the pending order by index for further access to its properties
      if(order_ticket==0)
         continue;
      string order_symbol=OrderGetString(ORDER_SYMBOL); // get symbol
      long order_magic=OrderGetInteger(ORDER_MAGIC); // get magic
      //---
      if(order_symbol==symbol && order_magic==magic)
         total++;
     }
//---
   return(total);
  }
//+------------------------------------------------------------------+

Получаем результат:

2021.08.24 08:34:20.871 Script 1 (EURAUD,H1)    Symbol EURUSD, Magic 200, Pending Orders 0:
2021.08.24 08:34:29.510 Script 1 (EURAUD,H1)    Symbol EURAUD, Magic 200, Pending Orders 2:
2021.08.24 08:34:38.224 Script 1 (EURAUD,H1)    Symbol EURAUD, Magic 100, Pending Orders 1:
Файлы:
Script_1.mq5  4 kb
 

Как создать индикатор - разницу между двумя iMA (Moving Average)

Форум о трейдинге, автоматических торговых системах и тестировании торговых стратегий

Невозможно инициализировать буферы

Владимир Карпутов, 2021.08.27 05:32

Как создать индикатор - разницу между двумя iMA (Moving Average).

Шаг 1

Шаг 1. Щелкните правой кнопкой мыши на папке и выберите "Новый файл".

Шаг 2

Шаг 2. Имя индикатора (строка 'Namde'), один входной параметр ('Parameters')

Шаг 3

Шаг 3. Выбор полной версии OnCalculate

Шаг 4

Шаг 4. 'Индикатор в отдельных окнах'c, добавляем одну строку 'Diff_Two_iMA'

Мы получаем заготовку:

//+------------------------------------------------------------------+
//|                                           Difference Two iMA.mq5 |
//|                              Copyright © 2021, Vladimir Karputov |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021, Vladimir Karputov"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Diff_Two_iMA
#property indicator_label1  "Diff_Two_iMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellowGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      Input1=9;
//--- indicator buffers
double         Diff_Two_iMABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Diff_Two_iMABuffer,INDICATOR_DATA);
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+


Теперь начинаем думать: нам нужно добавить два массива - для двух iMA. Поэтому мы изменим счетчик и добавим эти два массива, а также объявим две переменные - они будут хранить два хэндла

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   1
//--- plot Diff_Two_iMA
#property indicator_label1  "Diff_Two_iMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrYellowGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      Input1=9;
//--- indicator buffers
double   Diff_Two_iMABuffer[];
double   FastBuffer[];
double   SlowBuffer[];
//---
int      handle_iMA_Fast;              // variable for storing the handle of the iMA indicator
int      handle_iMA_Slow;              // variable for storing the handle of the iMA indicator
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |


Добавляем переменную'm_init_error' - это флаг. Если при создании индикатора произошла ошибка, то этот флаг будет установлен в 'true'.

double   SlowBuffer[];
//---
bool     m_init_error      = false;    // error on InInit
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |


Добавление входных параметров для индикатора 'Fast' и 'Slow'

//--- input parameters
input group             "Fast MA"
input int                  Inp_MA_Fast_ma_period      = 9;              // MA Fast: averaging period
input int                  Inp_MA_Fast_ma_shift       = 0;              // MA Fast: horizontal shift
input ENUM_MA_METHOD       Inp_MA_Fast_ma_method      = MODE_SMA;       // MA Fast: smoothing type
input ENUM_APPLIED_PRICE   Inp_MA_Fast_applied_price  = PRICE_CLOSE;    // MA Fast: type of price
input group             "Slow MA"
input int                  Inp_MA_Slow_ma_period      = 26;             // MA Slow: averaging period
input int                  Inp_MA_Slow_ma_shift       = 0;              // MA Slow: horizontal shift
input ENUM_MA_METHOD       Inp_MA_Slow_ma_method      = MODE_SMA;       // MA Slow: smoothing type
input ENUM_APPLIED_PRICE   Inp_MA_Slow_applied_price  = PRICE_CLOSE;    // MA Slow: type of price
//--- indicator buffers


Перейдите к 'OnInit': свяжите два массива и создайте два хэндла

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Diff_Two_iMABuffer,INDICATOR_DATA);
   SetIndexBuffer(1,FastBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,SlowBuffer,INDICATOR_DATA);
//--- create handle of the indicator iMA
   handle_iMA_Fast=iMA(Symbol(),Period(),Inp_MA_Fast_ma_period,Inp_MA_Fast_ma_shift,
                       Inp_MA_Fast_ma_method,Inp_MA_Fast_applied_price);
//--- if the handle is not created
   if(handle_iMA_Fast==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA ('Fast') indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      m_init_error=true;
      return(INIT_SUCCEEDED);
     }
//--- create handle of the indicator iMA
   handle_iMA_Slow=iMA(Symbol(),Period(),Inp_MA_Slow_ma_period,Inp_MA_Slow_ma_shift,
                       Inp_MA_Slow_ma_method,Inp_MA_Slow_applied_price);
//--- if the handle is not created
   if(handle_iMA_Slow==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code
      PrintFormat("Failed to create handle of the iMA ('Slow') indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(Period()),
                  GetLastError());
      //--- the indicator is stopped early
      m_init_error=true;
      return(INIT_SUCCEEDED);
     }
//---
   return(INIT_SUCCEEDED);
  }


Переходим к OnCalculate - здесь в основном выполняются операции копирования-вставки (с помощью справки iMA )

Продолжение следует позже ...


 

Форум о трейдинге, автоматизированных торговых системах и тестировании торговых стратегий

Невозможно инициализировать буферы

Владимир Карпутов, 2021.08.27 12:24

Продолжение ...

Применяем copy-paste и делаем немного ручной работы. Из справки ( iMA ) копируем почти всю функцию и немного изменяем ее под себя (меняем название буферов индикатора, меняем название хэндла и выкидываем 'Comment') Здесь просто внимательно сравниваем справку ( iMA ) и мой код. Прежде всего, добавляем в заголовок программы переменную'bars_calculated':

int      handle_iMA_Slow;              // variable for storing the handle of the iMA indicator
//---
int      bars_calculated   = 0;        // we will keep the number of values in the Moving Average indicator 
bool     m_init_error      = false;    // error on InInit
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |


Я выделил главное - это расчет разницы

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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(m_init_error)
      return(0);
//--- number of values copied from the iMA indicator
   int values_to_copy;
//--- determine the number of values calculated in the indicator
   int calculated_fast=BarsCalculated(handle_iMA_Fast);
   if(calculated_fast<=0)
     {
      PrintFormat("BarsCalculated(handle_iMA_Fast) returned %d, error code %d",calculated_fast,GetLastError());
      return(0);
     }
   int calculated_slow=BarsCalculated(handle_iMA_Slow);
   if(calculated_slow<=0)
     {
      PrintFormat("BarsCalculated(handle_iMA_Slow) returned %d, error code %d",calculated_slow,GetLastError());
      return(0);
     }
   if(calculated_fast!=calculated_slow)
     {
      PrintFormat("BarsCalculated(handle_iMA_Fast) returned %d, BarsCalculated(handle_iMA_Slow) returned %d",calculated_fast,calculated_slow);
      return(0);
     }
   int calculated=calculated_fast;
//--- if it is the first start of calculation of the indicator or if the number of values in the iMA indicator changed
//---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history)
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
     {
      //--- if the iMABuffer array is greater than the number of values in the iMA indicator for symbol/period, then we don't copy everything
      //--- otherwise, we copy less than the size of indicator buffers
      if(calculated>rates_total)
         values_to_copy=rates_total;
      else
         values_to_copy=calculated;
     }
   else
     {
      //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate()
      //--- for calculation not more than one bar is added
      values_to_copy=(rates_total-prev_calculated)+1;
     }
//--- fill the iMABuffer array with values of the Moving Average indicator
//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation
   if(!FillArrayFromBuffer(FastBuffer,Inp_MA_Fast_ma_shift,handle_iMA_Fast,values_to_copy))
      return(0);
   if(!FillArrayFromBuffer(SlowBuffer,Inp_MA_Slow_ma_shift,handle_iMA_Slow,values_to_copy))
      return(0);
//--- memorize the number of values in the Moving Average indicator
   bars_calculated=calculated;
//--- main loop
   int limit=prev_calculated-1;
   if(prev_calculated==0)
      limit=0;
   for(int i=limit; i<rates_total; i++)
     {
      Diff_Two_iMABuffer[i]=FastBuffer[i]-SlowBuffer[i];
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Filling indicator buffers from the MA indicator                  |
//+------------------------------------------------------------------+
bool FillArrayFromBuffer(double &values[],   // indicator buffer of Moving Average values
                         int shift,          // shift
                         int ind_handle,     // handle of the iMA indicator
                         int amount          // number of copied values
                        )
  {
//--- reset error code
   ResetLastError();
//--- fill a part of the iMABuffer array with values from the indicator buffer that has 0 index
   if(CopyBuffer(ind_handle,0,-shift,amount,values)<0)
     {
      //--- if the copying fails, tell the error code
      PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated
      return(false);
     }
//--- everything is fine
   return(true);
  }
//+------------------------------------------------------------------+
//| Indicator deinitialization function                              |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(handle_iMA_Fast!=INVALID_HANDLE)
      IndicatorRelease(handle_iMA_Fast);
   if(handle_iMA_Slow!=INVALID_HANDLE)
      IndicatorRelease(handle_iMA_Slow);
  }
//+------------------------------------------------------------------+


Результат:

Разница два iMA


Причина обращения: