iCustom() в MQL5: нужна ли унификация функции? - страница 3

 
А я бы не отказался от функции OnCustom(int My_par1 = 0, string My_str = "строка" ... string help = "Описание параметром в виде сочинения") и от вкладки в свойствах индикатора, где бы параметры показывались только для озокомления :)
 

Mathemat писал(а) >>

Вот такая строка проходит нормально (MA_Method объявлен как ENUM_MA_METHOD):

MA_Method = (ENUM_MA_METHOD) 3;

а вот такая - нет, ругается компилятор:

MA_Method = 3;

Сразу две оговорки:

1. То, что я выше написал, в таком виде на MQL5 нереализуемо, ввиду отсутствия возможности перегрузки операторов.

2. По-хорошему, кастовать перечисления к инту это плохо

Но, в принципе, такой код нормальный:

{
   params.integers["AppliedPrice"] = (int)PRICE_CLOSE;
   //...
   ENUM_APPLIED_PRICE appliedPrice = (ENUM_APPLIED_PRICE)params.integers["AppliedPrice"];
}

Тип можно узнать по имени.


В общем и в целом в принципе, не так плохо, как я думал вначале, и главное -- реализуемо.

Правда, разработчикам придется попотеть, ибо надо будет располагать параметры в том же порядке, который есть в индикаторе.


Кстати, я конечно могу ошибкаться, но с некоторыми оговорками это можно реализовать на пользовательском уровне.

Т.е. просто дописать руками апгрейд.

 

TheXpert писал(а) >>

Кстати, я конечно могу ошибкаться, но с некоторыми оговорками это можно реализовать на пользовательском уровне.

Реализация параметров для кастомного индикатора (пример)

#property copyright "TheXpert"
#property link      "theforexpert@gmail.com"

#include <IndicatorParams/ParamsCollection.mqh>

class CustomMACDParams
   : public ParamsCollection
{
public:
   CustomMACDParams()
   {
      /// initializing strings. They are often used for description
      /// and mostly have constant or even empty values
      SetParam("SlowMaDescription", "Period for slow moving");
      SetParam("FastMaDescription", "Period for fast moving");
      SetParam("SignalDescription", "Period for fast moving");

      /// default params
      SetParam("SlowMa", 30);
      SetParam("FastMa", 5);
      SetParam("Signal", 2);
   }

   virtual int ICustom(
         string symbol,
         ENUM_TIMEFRAMES period) const
   {
      return iCustom(
            symbol, 
            period, 
            "Custom_MACD", 
            GetString("SlowMaDescription"),
            GetInt("SlowMa"),
            GetString("FastMaDescription"),
            GetInt("FastMa"),
            GetString("SignalDescription"),
            GetInt("Signal")
      );
   }
};

Унификация:

#property copyright "TheXpert"
#property link      "theforexpert@gmail.com"

#include <IndicatorParams/IndicatorsCollection.mqh>

int ICustom(
         string symbol,
         ENUM_TIMEFRAMES period,
         string name,
         const ParamsCollection& params)
{
   if ("Custom_MACD" == name)
   {
      CustomMACDParams macd;
      macd.Join(params);
      
      return macd.ICustom(symbol, period);
   }

   // здесь может быть проверка по имени и вызов соотв функции для любых индикаторов
   // ...   

   // сломается, если включен режим Debug.
   return params.ICustom(symbol, period);
}

Собсно, использование:

//+------------------------------------------------------------------+
//|                                            Example_Indicator.mq5 |
//+------------------------------------------------------------------+
#property copyright "TheXpert"
#property link      "theforexpert@gmail.com"

#property indicator_chart_window

#include <IndicatorParams.mqh>

int CustomEUMACDHandle;
int CustomGUMACDHandle;

int OnInit()
{
   //Вариант использования 1
   {
      CustomMACDParams params;
   
      CustomEUMACDHandle = params.ICustom("EURUSD", 0);
      params.SetParam("SlowMA", 40);
      CustomGUMACDHandle = params.ICustom("GBPUSD", 0);
   }
   
   //Вариант использования 2
   {
      // общий класс для хранения параметров
      ParamsCollection params;

      CustomEUMACDHandle = ICustom("EURUSD", 0, "Custom_MACD", params);
      params.SetParam("SlowMA", 40);
      CustomGUMACDHandle = ICustom("GBPUSD", 0, "Custom_MACD", params);
      
      SetDebug(false);
      // этот код вернет -1
      int handle = ICustom("GBPUSD", 0, "Undefined_Indicator", params);
      
      SetDebug(true);
      // a сейчас приведет к аварийному завершению
      handle = ICustom("GBPUSD", 0, "Undefined_Indicator", params);
   }

   return 0;
}

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(rates_total);
}

Mathemat, писал наполовину из интереса, наполовину для Вас. Так что надеюсь хотя бы на тестирование с Вашей стороны.

Ибо код сырой и непроверенный, а штука довольно прикольная в использовании.


Реализация в аттаче.

Файлы:
4share.zip  6 kb
 

Ага, Андрей, спасибо. Посмотрю, как времени чуть побольше будет.

 

Извини Алексей, спрошу не по теме. Но тут много старых программистов собралось, авось кто нибудь ответит.

Мне нужно использовать двумерный массив, в котором размер одного из измерений мне заранее известен. Скажем-50, array[][50], или array[50][] и он используется в функции, размер второго измерения заранее не известен.

ArrayResize(array, n), где n параметр, который подается на функцию, изменит размерность в первом измерении.

Получится array[n][50].

Теперь мне нужно отсортировать массив по тому измерению, у которого размерность 50, и возможно это сделать так: ArraySort(array,MODE_ASCEND)

Но эта стандартная функция может сортировать только по первому измерению в MQL4, и, если я правильно понял, в MQL5.

Вопрос: Как отсортировать массив стандартными средствами языка, так, что бы то измерение, которое обозначено n не сортировалось?

 

array[i] - указатель на i-й вектор размерностью 50.

Если речь идет об MQL5, то достаточно сделать по аналогии ArraySort(array[i], MODE_ASCEND).

 

//Такой код не годится, так как сортировка по n-ному измерению

void func(int n)

{

double array[][50];

ArrayResize(array, n);

ArraySort(array,MODE_ASCEND);

}


//Такой код не годится, так как массив изменит размерность 50 на размерность n первого измерения

void func(int n)

{

double array[50][];

ArrayResize(array, n);

ArraySort(array,MODE_ASCEND);

}


Условия задачи были такими: 50 - размерное измерение не должно изменить размер, а измерение n не должно сортироваться. Приходится заранее выставлять намного больший размер массива, что очень накладно.

 

Нужно решение на MQL4 или MQL5?

MQL5 - привел выше.

MQL4 - проще (быстро и надежно) написать свою сортировку. Вы же понимаете, что сортировать можно только значения внутри каждого вектора. Вектора между собой сотировать можно только по какому-то своему придуманному критерию, который надо будет заложить в функцию сортировки.

Поэтому, замечательно было бы иметь штатную или возможность написать на MQL5 аналог qsort. Но, вроде, в MQL5 отсутствуют указатели на функции. Поэтому штатную функцию сортировки по ЛЮБОМУ критерию скорее всего реализовать не получится.

 

getch писал(а) >>

Нужно решение на MQL4 или MQL5?

MQL5 - привел выше.

Ваше решение отсортирует по второму измерению?

Я говорю о том, что штатная функция сортирует только по первому измерению, и нельзя сортировать по второму. Мне не нужно сортировать по обоим измерениям одновременно, только по одному из них. А изменять размерность можно только первого измерения.

Ещё раз. Мне нужно сортировать по измерению, размерность которого 50. А изменять размерность того измерения, у которого размерность n.

Свою функцию можно написать, но она будет медленнее, чем была бы штатная.


 
joo >>:

Ваше решение отсортирует по второму измерению?

Я говорю о том, что штатная функция сортирует только по первому измерению, и нельзя сортировать по второму. Мне не нужно сортировать по обоим измерениям одновременно, только по одному из них. А изменять размерность можно только первого измерения.

Ещё раз. Мне нужно сортировать по измерению, размерность которого 50. А изменять размерность того измерения, у которого размерность n.

Свою функцию можно написать, но она будет медленнее, чем была бы штатная.


Да, решение через array[i] отсортирует массив по второму измерения, т.к. array[i] - это одномерный массив. На MQL4 не пробовал, думаю, не получится штатно из-за узости MQL4.

Своя функция на MQL4 не всегда будет быстрее штатной. Причина простая: штатная функция - универсальная (хоть и быстрая), но не могущая использовать особенности вашего массива, которые вы можете для оптимальности использовать в своей функции.

Очень часто сталкивался с тем, что своя функция работала в разы быстрее штатной в таких ситуациях.

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