Библиотеки: Expert - страница 3

 
Пример еще одного применения библиотеки

Forum on trading, automated trading systems and testing trading strategies

ParameterGetRange()

fxsaber, 2018.11.16 09:17

#include <fxsaber\Expert.mqh> // https://www.mql5.com/ru/code/19003

#define TOSTRING(A) (" " + #A + " = " + (string)(A))

// Collects data on the range of input parameters for optimization
string OptimizationData( void )
{
  string Str = NULL;
  MqlParam Params[];
  string Names[];
  
  if (EXPERT::Parameters(0, Params, Names))
  {
    const int Size = ArraySize(Names);
    bool Enable;
    long Value, Start, Step, Stop;
    long Total = 1;
    
    Str = Params[0].string_value;
    
    for (int i = 0; i < Size; i++)
      if (ParameterGetRange(Names[i], Enable, Value, Start, Step, Stop))
      {
        const long Interval = Stop - Start + 1;
        const long Amount =  Enable ? Interval / Step + ((bool)(Interval % Step) ? 1 : 0) : 1;
        
        Str += "\n" + Names[i] + " = " + (string)Value + (Enable ? TOSTRING(Start) + TOSTRING(Step) + TOSTRING(Stop) + TOSTRING(Amount) : NULL);
        
        Total *= Amount;
      }
      
    Str += "\n" + TOSTRING(Total);
  }
  
  return(Str);
}

input int Range1 = 5;
input int Range2 = 5;
input int Range3 = 5;

void OnTesterInit()
{
  ParameterSetRange("Range1", true, 5, 1, 2, 3);
  
  Print(__FUNCTION__ + "\n" + OptimizationData());
}

void OnTesterDeinit()
{
  Print(__FUNCTION__ + "\n" + OptimizationData());
  
  ChartClose();
}

int OnInit()
{
  return(INIT_FAILED);
}


OnTesterInit
Experts\fxsaber\Test3.ex5
Range1 = 5 Start = 5 Step = 1 Stop = 50 Amount = 46
Range2 = 5 Start = 23 Step = 1 Stop = 78 Amount = 56
Range3 = 5 Start = 26 Step = 5 Stop = 83 Amount = 12
 Total = 30912

OnTesterDeinit
Experts\fxsaber\Test3.ex5
Range1 = 5 Start = 1 Step = 2 Stop = 3 Amount = 2
Range2 = 5 Start = 23 Step = 1 Stop = 78 Amount = 56
Range3 = 5 Start = 26 Step = 5 Stop = 83 Amount = 12
 Total = 1344
 
Исправлен баг.
 

Каким образом можно запустить советник в формате .ех4 подключив его в советнике с другим именем, при этом нужно чтоб отображались входные параметры, то есть была возможность полноценной работы с ним.

Имеем скомпилированный советник с названием "Trade.ех4"

Создаём новый советник с названием "Hand.ех4"

Как это совместить, чтобы при запуске "Hand.ех4" полноценно работал "Trade.ех4",   при этом "Trade.ех4" был вшит в "Hand.ех4"

То есть имеем на машине только файл Hand.ех4, а используем в работе Trade.ех4

Спасибо!

 
Vitaly Muzichenko:

Каким образом можно запустить советник в формате .ех4...

Библиотека в текущем виде работает только с EX5.

 
Sergey Eremin:

У себя, в составе некоего проекта, я решил это так (тегом "name" как раз):

Спасибо, так работает!

Только я добавил в имя сохраняемого шаблона chartId, чтобы одинаковые советники на разных графиках не боролись за один файл.


@fxsaber, в коде есть "#ifndef __MQL5__", почему не довести кросс-платформенность до логического завершения?

Чтобы заработала Is, добавляем в начало код:

#property strict

#ifdef __MQL4__
        class SubstringParser
        {
           private:
              string m_text;
              string m_subStart;
              string m_subEnd;
           
           public:
              SubstringParser(const string text, const string subStart, const string subEnd)
              {
                 m_text = text;
                 m_subStart = subStart;
                 m_subEnd = subEnd;
              }
              
              string Get()
              {
                 int startPhraseLengt = StringLen(m_subStart);
                 int startPos = StringFind(m_text, m_subStart) + startPhraseLengt;
                 int endPos = StringFind(m_text, m_subEnd, startPos);
                         
                 if(startPos >= startPhraseLengt && endPos > startPos)
                 {
                    return StringSubstr(m_text, startPos, endPos - startPos);      
                 }
                 else
                 {
                    return "";
                 }
              }
        };

   string GetChartEAName(const long chartId)
   {
      if(!SaveTemplate(chartId))
      {
         return "";
      }
      
      string result = "";
      
      int handle = FileOpen("ea_name_checking_" + (string)chartId + ".tpl",FILE_TXT|FILE_READ);
      if(handle == INVALID_HANDLE)
      {
         Print
         (
            "Error in ", __FILE__,", line ", __LINE__,
            ": can't open template file 'ea_name_checking_" + (string)chartId + ".tpl', error code = ", GetLastError()
         );
      }
      else
      {
         string text = "";
         
         while(!FileIsEnding(handle)) 
         { 
            text = text + FileReadString(handle, (uint)FileSize(handle)) +"\r\n";
         }
         
         SubstringParser eaSectionTextParser(text, "<expert>", "</expert>");            
         string eaSectionText = eaSectionTextParser.Get();
         
         if(StringTrimLeft(StringTrimRight(eaSectionText)) != "")
         {
            SubstringParser eaNameParser(eaSectionText, "name=","\r\n");
            string eaName = StringTrimLeft(StringTrimRight(eaNameParser.Get()));
            
            if(eaName != "")               
            {
               result = eaName;
            }
         }            
      }
      
      FileClose(handle);
      FileDelete("ea_name_checking_" + (string)chartId + ".tpl");
      
      return result;
   }
   
   bool SaveTemplate(const long chartId)
   {
      ResetLastError();
      
      if(!ChartSaveTemplate(chartId, "\\Files\\ea_name_checking_" + (string)chartId + ".tpl"))
      {            
         Print
         (
            "Error in ", __FILE__,", line ", __LINE__,
            ": can't save template to the file 'ea_name_checking_" + (string)chartId + ".tpl', error code = ", GetLastError()
         );
         
         return false;
      }
      
      return true;
   }      
 #endif

И правим саму функцию:

  static bool Is( const long Chart_ID = 0 )
  {
                #ifdef __MQL4__
                        string chartEAName = GetChartEAName(Chart_ID);
                #endif 
                
                #ifdef __MQL5__     
                        string chartEAName = ChartGetString(Chart_ID, CHART_EXPERT_NAME);
                #endif
                return(chartEAName != NULL);
  }


Есть другие сложности?

 
Andrey Khatimlianskii:

Есть другие сложности?

Чарт, на котором запущен только один индикатор.


ЗЫ Так должно работать

SubstringParser eaSectionTextParser(text, "\r\n\r\n<expert>", "</expert>");
 

Весь функционал библиотеки теперь работает и на MT4.

Библиотека стала кроссплатформенной.

 
Vitaly Muzichenko:

Каким образом можно запустить советник в формате .ех4...

#include <fxsaber\Expert.mqh> // https://www.mql5.com/ru/code/19003

void OnStart()
{
  MqlParam Params[2];

  // Путь к советнику
  Params[0].string_value = "Moving Average";
  
  // Первый входной параметр советника
  Params[1].type = TYPE_DOUBLE;
  Params[1].double_value = 0.5;  

  Print(EXPERT::Run(ChartOpen(_Symbol, _Period), Params));
}
 
fxsaber:

Спасибо!

 

В Маркете неоднократно видел, что авторы прикладывают сет-файлы своих ТС для каждого символа. Соответственно, покупатели используют их.


Предлагаю для Маркет-ТС использовать следующую логику

  • Добавляется один входной параметр
    input string FolderSets = NULL; // Папка с сетами нашей ТС
  • Если эта папка задана пользователем, то советник автоматом подхватывает все сеты из этой папки и запускает свои соответствующие версии.
  • Пользователю нужно только поместить сет-файл в папку и прописать путь к этой папке при запуске советника (вшить этот путь сразу может и автор советника).
  • Если пользователь ошибся и запускает дважды, то можно автоматически не давать этого делать.

Такой подход удобен и для запуска своих ТС одним нажатием.

Конечно, решение может быть универсальным для обеих платформ. Грубо говоря, в исходный код любого советника потребуется добавить только одну строку.


Скорее всего, именно так теперь буду запускать советники. Если кто-то видит изъян в таком методе или вариант улучшения, дайте знать.


ЗЫ Допустим, у пользователя уже крутятся советники с настроенными параметрами. Можно автоматически сохранить сет-файлы всех запущенных советников. И далее использовать вышестоящий подход.


ЗЗЫ На MT5 возможно запускать советник не через сет-файла, а через opt-файлы. Представьте, что запустили штатную оптимизацию советника и видите несколько хороших наборов входных параметров. Хочется именно их использовать одновременно - размазать риски для диверсификации. Для этого можно создать свой opt-файл, в котором будут присутсвовать только избранные проходы. Можно будет автоматически запускать эти проходы на боевом счету. И допольнительно можно будет этот opt-файл открывать в MT5-тестере и прогонять каждый проход штатными средствами. Т.е. opt-файл становится диверсифицированным набором сет-файлов. Но при этом еще и полноценно читается самим Тестером.

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