Русский

Учебник по MQL4  Стандартные функции  Строковые функции

Строковые функции


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

Задача 35. Раскрасить 100 последних баров свечного графика: чёрные свечи - красным цветом, а белые - синим.

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

В данном случае в качестве прикладной программы используется эксперт, хотя в общем случае алгоритм может быть реализован и в пользовательском индикаторе. В целом алгоритм программы понятен. При присоединении эксперта к окну финансового инструмента (при исполнении init()) график должен быть раскрашен первый раз. На каждом тике (при исполнении start()) программа должна отслеживать возможные изменения в положении каждого из созданных ею графических объектов (пользователь может случайно удалить или переместить любой из них) и при необходимости восстановить его. А в период завершения программы (deinit()) все созданные программой графические объекты должны быть удалены.

В период практической работы с экспертом пользователь может вручную создать в окне финансового инструмента и другие объекты, например, установить канал стандартных отклонений, уровни Фибоначчи, линии поддержки и пр. Поэтому в программе должен быть реализован алгоритм, позволяющий отличать объекты, созданные программой, от объектов, установленных пользователем. Это особенно важно при завершении программы: необходимо удалить только "свои" объекты, а "пользовательские" оставить без изменения. Каждый графический объект обладает определёнными свойствами, которые, в общем случае, могут совпадать. Единственным отличительным признаком любого объекта является его уникальное имя (одинаковые имена не допускаются).

При составлении имени каждого из создаваемых объектов желательно ввести в имя объекта полезную информацию, по которой можно было бы судить о местоположении и свойствах объекта. Например, имя объекта может содержать префикс, отличающий объект, созданный этой программой, от всех других. В нашем случае это строковое значение "Paint_". Кроме того, необходимо отличать и "свои" объекты между собой. При этом простая нумерация (Paint_1, Paint_2 и т.д.) не может быть использована. Используя такой способ именования имён объектов, невозможно понять: на каком баре должен быть отображён, например, объект Paint_73. Тот бар, который имел индекс 73, с появлением нового бара получит индекс 74, при следующем новом баре 75 и т.д. При таком решении пришлось бы удалять и вновь создавать все объекты на каждом новом баре. Понятно, что это решение (хотя и осуществимо), является очень грубым и затратным.

Каждый из создаваемых объектов должен иметь координаты времени, совпадающие со временем открытия бара. Кроме того, на каждом баре необходимо отображать 2 линии - тонкую и широкую. Наиболее удобно представить имена создаваемых программой объектов в таком виде:

Имя объекта = Paint_2_2007.03.22 16:40, здесь:

Paint_ - префикс, отличающий объекты, созданные программой;

2_ - номер одного из двух объектов, отображаемых на баре (возможные значения 1 и 2);

2007.03.22 16:40 - координата времени, однозначно характеризующая бар, на котором отображается объект.

Paint_ и 2_ - это значения переменных Prefix и Nom_Lin. Координату времени для каждого бара можно получить путём преобразования значения типа datetime в значение типа string с помощью функции преобразования данных:

Функция TimeToStr()

string TimeToStr(datetime value, int mode=TIME_DATE|TIME_MINUTES)

Функция преобразовывает значение, содержащее время в секундах, прошедших с 01.01. 1970 (значение типа datetime), в строку заданного формата (значение типа string).

Параметры:

value - время в секундах от 00:00 1 января 1970;

mode - дополнительный режим вывода данных. Может быть одним или комбинированным флагом:

TIME_DATE получает результат в форме "yyyy.mm.dd";

TIME_MINUTES получает результат в форме "hh:mi";

TIME_SECONDS получает результат в форме "hh:mi:ss".


Рассмотрим эксперт strings.mq4, управляющий графическими объектами для раскраски свечей, и проследим как функция TimeToStr() используется в этой программе:

//--------------------------------------------------------------------
// strings.mq4
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------- 1 --
extern int Quant_Bars=100; // Количество баров
datetime Time_On;
string Prefix ="Paint_";
//--------------------------------------------------------------- 2 --
int init() // Спец. функция init()
{
int Ind_Bar; // Индекс бара
Time_On=Time [Quant_Bars]; // Время первого раскрашенного
for(Ind_Bar=Quant_Bars-1; Ind_Bar>=0; Ind_Bar--)// Цикл по барам
{
Create(Ind_Bar,1); // Нарисуем тонкую линию
Create(Ind_Bar,2); // Нарисуем толстую линию
}
WindowRedraw(); // Перерисовка изображения
return; // Выход из init()
}
//--------------------------------------------------------------- 3 --
int start() // Спец. функция start
{
datetime T1, T2; // 1 и 2 координаты времени
int Error,Ind_Bar; // Код ошибки и индекс бара
double P1, P2; // 1 и 2 координата цены
color Col; // Цвет созданного объекта
//--------------------------------------------------------------- 4 --
for(int Line=1; Line<=2; Line++) // Цикл по видам линий
{
string Nom_Lin =Line + "_"; // Строка с номером линии
// string Nom_Lin = DoubleToStr(Line,0)+"_";// Можно и так
for(Ind_Bar=0; ;Ind_Bar++) // Цикл по барам
{
//--------------------------------------------------------------- 5 --
datetime T_Bar= Time[Ind_Bar];// Время открытия бара
if (T_Bar < Time_On) break; // Заграничные не раскрашиваем
string Str_Time=TimeToStr(T_Bar); // Строка со временем
string His_Name=Prefix+Nom_Lin+Str_Time;// Имя объекта
//--------------------------------------------------------------- 6 --
T1=ObjectGet(His_Name,OBJPROP_TIME1);// Запрос коорд. t1
Error=GetLastError(); // Получение кода ошибки
if (Error==4202) // Если объекта нет :(
{
Create(Ind_Bar,Line); // Вызов ф-ии создания объекта
continue; // На следующую итерацию
}
//--------------------------------------------------------------- 7 --
T2 =ObjectGet(His_Name,OBJPROP_TIME2); // Запрос коорд. t2
P1 =ObjectGet(His_Name,OBJPROP_PRICE1);// Запрос коорд. p1
P2 =ObjectGet(His_Name,OBJPROP_PRICE2);// Запрос коорд. p1
Col=ObjectGet(His_Name,OBJPROP_COLOR); // Запрос цвета
if(T1!=T_Bar || T2!=T_Bar || // Не те координаты или цвет:
(Line==1 && (P1!=High[Ind_Bar] || P2!= Low[Ind_Bar])) ||
(Line==2 && (P1!=Open[Ind_Bar] || P2!=Close[Ind_Bar])) ||
(Open[Ind_Bar] Close[Ind_Bar] && Col!=Red) ||
(Open[Ind_Bar]==Close[Ind_Bar] && Col!=Green) )
{
ObjectDelete(His_Name); // Удаляем объект
Create(Ind_Bar,Line); // Создаём правильный объект
}
//--------------------------------------------------------------- 8 --
}
}
WindowRedraw(); // Перерисовка изображения
return; // Выход из start()
}
//--------------------------------------------------------------- 9 --
int deinit() // Спец. функция deinit()
{
string Name_Del[1]; // Объявление массива
int Quant_Del=0; // Количество удаляемых объектов
int Quant_Objects=ObjectsTotal(); // Cтолько всего ВСЕХ объектов
ArrayResize(Name_Del,Quant_Objects);// Необходимый размер массива
for(int k=0; k<=Quant_Del; i++) // Удаляем объекты с именами,..
ObjectDelete(Name_Del[i]); // .. имеющимися в массиве
return; // Выход из deinit()
}
//-------------------------------------------------------------- 10 --
int Create(int Ind_Bar, int Line) // Пользовательская функция..
{ // ..создания объекта
color Color; // Цвет объекта
datetime T_Bar=Time [Ind_Bar]; // Время открытия бара
double O_Bar=Open [Ind_Bar]; // Цена открытия бара
double C_Bar=Close[Ind_Bar]; // Цена закрытия бара
double H_Bar=High [Ind_Bar]; // Максимальная цена бара
double L_Bar=Low [Ind_Bar]; // Минимальная цена бара

string Nom_Lin =Line + "_"; // Строка - номер линии
// string Nom_Lin = DoubleToStr(Line,0)+"_";// Можно и так
string Str_Time=TimeToStr(T_Bar); // Строка - время откр.
string His_Name=Prefix+Nom_Lin+Str_Time;// Имя созаваемого объект
if (O_Bar < C_Bar) Color=Blue; // Выбор цвета в зависимости..
if (O_Bar >C_Bar) Color=Red; // .. от характеристик бара
if (O_Bar ==C_Bar) Color=Green;

switch(Line) // Тонкая или толстая линия
{
case 1: // Тонкая линия
ObjectCreate(His_Name,OBJ_TREND,0,T_Bar,H_Bar,T_Bar,L_Bar);
break; // Выход из switch
case 2: // Толстая линия
ObjectCreate(His_Name,OBJ_TREND,0,T_Bar,O_Bar,T_Bar,C_Bar);
ObjectSet( His_Name, OBJPROP_WIDTH, 3);// Стиль
}
ObjectSet( His_Name, OBJPROP_COLOR, Color); // Цвет
ObjectSet( His_Name, OBJPROP_RAY, false); // Луч
ObjectSetText(His_Name,"Объект создан экспертом",10);// Описание
return; // Выход из польз. ф-ии
}
//-------------------------------------------------------------- 11 --

Для создания графических объектов в программе имеется пользовательская функция Create() (блок 10-11). В качестве передаваемых параметров в этой функции используются переменная Ind_Bar, указывающая индекс бара, на котором необходимо создать объект, и Line - номер объекта (1я или 2я линия).

При формировании имени создаваемого объекта His_Name используются три составляющих:

   string His_Name = Prefix+Nom_Lin+Str_Time;// Имя создаваемого объект

Значение переменной Prefix задано программистом в головной части программы и при выполнении программы не изменяется:

string     Prefix     = "Paint_";

Значение переменной Nom_Lin получено в результате вычислений:

   string Nom_Lin  = Line + "_";       // Строка - номер линии
// string Nom_Lin = DoubleToStr(Line,0)+"_";// Можно и так

Здесь значение целой переменной (при вычислении выражения в правой части выражения) преобразуется к типу, имеющему более высокий приоритет, а именно, к типу string. В результате, в зависимости от значения переменной Line, переменная Nom_Lin получает значение "1_"или "2_".

Для вычисления значения переменной Str_Time используется функция преобразования данных TimeToStr():

   string Str_Time = TimeToStr(T_Bar); // Строка - время откр.

Обратите внимание, функция TimeToStr() имеет умолчательные значения. В данном случае именно такие значения параметра mode и требуются: "yyyy.mm.dd hh:mi"; использовать дополнительно секунды нет необходимости, потому что минимальный таймфрейм равен 1 минуте.

Для использования в имени объекта можно было бы применить и такой способ вычисления Str_Time:

   string Str_Time = T_Bar;

В этом случае переменная Str_Time получила бы значение, равное количеству секунд, прошедших с 01.01.1970. Чтобы увидеть разницу, можно выполнить программу, содержащую такой код:

int init()
{
string String_Time = TimeToStr(Time[0]); // Время в формате.
string String_Sec = Time[0]; // Количество секунд
Alert("String_Time = ",String_Time," String_Sec = ",String_Sec);
return;
}

В результате исполнения этой программы (в зависимости от времени открытия нулевого бара) на экран будет выведено сообщение:

String_Time = 2007.03.22 19:10 String_Sec = 1174590600

Первый вариант, реализованный в эксперте strings.mq4, несколько более информативен, поэтому в данном случае предпочтение отдано ему (с точки зрения алгоритма, реализованного в программе, эти варианты равнозначны).

В последующих строках пользовательской функции Create() создаётся объект с вычисленным именем His_Name, содержащим сведения о времени открытия бара, и со свойствами, соответствующими номеру линии Line, а также с цветом в зависимости от характеристик бара. Для каждого объекта указывается также значение текстового описания: "Объект создан экспертом".

Вызов функции Create() осуществляется в программе в двух местах - из специальной функции init() для первоначального создания объектов, и из специальной функции start(), в случае необходимости ещё раз создать объект, случайно удалённый или изменённый пользователем. Имена объектов в функции start() (блоки 4-5-6) формируются так же, как и в других местах программы.

В блоке 6-7 определяется первая координата исследуемого объекта. Если при этом объект не найден, то он создаётся с помощью Create(). А если объект существует, то определяются другие его координаты и вычисляется, соответствуют ли его свойства характеристикам бара (блок 7-8). При обнаружении любого несоответствия объект удаляется и создаётся вновь (с тем же именем), но уже с правильными свойствами.

При исполнении функции deinit() решается ещё одна задача: из всей совокупности объектов, имеющихся в окне финансового инструмента, необходимо удалить только те, которые созданы экспертом. Это делается в два этапа: на первом этапе в массив Name_Del[] запоминаются имена всех объектов, которые необходимо удалить, а затем, в отдельном цикле, все эти объекты удаляются. Общее количество всех объектов в окне (в том числе, созданных программой и установленных пользователем вручную) вычисляется с помощью функции ObjectsTotal():

   int Quant_Objects=ObjectsTotal();   // Cтолько всего ВСЕХ объектов

Количество раскрашиваемых баров устанавливается пользователем во внешней переменной, т.е. заранее неизвестно, сколько графических объектов придётся удалять. Поэтому строковый массив, несущий имена удаляемых объектов, объявляется с количеством элементов равным 1, а затем размер массива программно изменяется - количество его элементов увеличивается до общего количества объектов.

   ArrayResize(Name_Del,Quant_Objects);// Необходимый размер массива

Для того, чтобы отобрать объекты, созданные экспертом, в функции deinit() имеется цикл for, в котором производится анализ имени каждого объекта.

      string Obj_Name = ObjectName(k); // Запрашиваем имя объекта

Признаком, отличающим "наши" объекты от всех других, является префикс "Paint_", с которого начинается имя каждого созданного программой объекта. Для анализа названия объекта необходимо извлечь из строковой переменной, являющейся уникальным именем объекта, начальную часть (в данном случае 6 символов), а затем сравнить полученное значение со значением переменной Prefix. Если обнаружится совпадение, то исследуемый объект подлежит удалению, если же нет, то объект удалять не нужно.


Функция StringSubstr()

string StringSubstr(string text, int start, int length=0)
Функция извлекает подстроку из текстовой строки, начинающейся c указанной позиции. Функция возвращает копию извлеченной подстроки, если возможно, иначе возвращается пустая строка.

Параметры:

text - строка, из которой должна быть извлечена подстрока;

start - начальная позиция подстроки. Может быть от 0 до StringLen(text)-1;

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


В рассматриваемом примере извлечение подстроки из имени объекта выполняется так:

      string Head=StringSubstr(Obj_Name,0,6);// Извлекаем первые 6 сим

В данном случае из строковой переменной Obj_Name извлекаются первые 6 символов, начиная с нулевого. Обратите внимание, счёт любых индексов в MQL4 (баров, массивов), строк в списке ордеров, а также номер позиции в строке, начинается с 0, в то же время количественный счёт начинается с 1.

Извлечённая подстрока (значение типа string) присваивается строковой переменной Head. Если имя объекта (и сам объект) было создано рассматриваемым экспертом, то значение извлечённой подстроки будет таким: "Paint_". Если же анализируется другое имя, то искомое значение будет другим. Например, для имени объекта "StdDev Channel 23109" значение извлечённой подстроки будет таким: "StdDev", а для объекта с именем "Fibo 22800" - таким: "Fibo 2".

В последующих строках значение переменной Head сравнивается со значением переменной Prefix:

      if (Head == Prefix)              // Найден объект, ..
{ // .. начинающийся с Paint_

И если эти значения равны, то анализируемое имя объекта заносится в массив Name_Del[] имён объектов, назначенных к удалению. В следующем цикле for удаляются все объекты, имена которых содержатся в этом массиве (отдельно нужно заметить, что в первом цикле for удалять объекты нельзя, т.к. в этом случае после каждого удаления изменится общее количество объектов и их нумерация, в результате чего некоторые имена объектов будут пропущены).

Во время исполнения эксперта strings.mq4 ценовой график будет выглядеть так:


Рис. 142. Ценовой график раскрашен с помощью графических объектов (strings.mq4).

На Рис. 142 кроме группы объектов, покрывающих ценовой график, показаны два других объекта, установленные пользователем вручную, - канал регрессии и уровни Фибоначчи. После прекращения работы эксперта созданные им объекты будут удалены, а объекты, установленные пользователем, останутся в окне финансового инструмента. Указанный результат получен благодаря использованию в программе строковых функций, позволяющих создавать и анализировать строковые значения, в том числе, имена графических объектов.


Строковые функции


Функция Краткое описание
StringConcatenate Формирует строку из переданных параметров и возвращает её. Параметры могут иметь любой тип. Количество параметров не может превышать 64.
StringFind Поиск подстроки. Возвращает номер позиции в строке, с которой начинается искомая подстрока, либо -1, если подстрока не найдена.
StringGetChar Возвращает значение символа, расположенного в указанной позиции строки.
StringLen Возвращает число символов в строке.
StringSetChar Возвращает копию строки с измененным значением символа в указанной позиции.
StringSubstr Извлекает подстроку из текстовой строки, начинающейся c указанной позиции. Функция возвращает копию извлеченной подстроки, если возможно, иначе возвращается пустая строка.
StringTrimLeft Функция урезает символы перевода каретки, пробелы и символы табуляции в левой части строки. Функция возвращает копию преобразованной строки, если это возможно, в противном случае возвращается пустая строка.
StringTrimRight Функция урезает символы перевода каретки, пробелы и символы табуляции в правой части строки. Функция возвращает копию преобразованной строки, если это возможно, в противном случае возвращается пустая строка.

Функции преобразования данных


Функция Краткое описание
CharToStr Преобразование кода символа в односимвольную строку.
DoubleToStr Преобразование числового значения в текстовую строку, содержащую символьное представление числа в указанном формате точности.
NormalizeDouble Округление числа с плавающей запятой до указанной точности. Рассчитываемые значения StopLoss, TakeProfit, а также значения цены открытия отложенных ордеров должны быть нормализованы с точностью, значение которой хранится в предопределенной переменной Digits.
StrToDouble Преобразование строки, содержащей символьное представление числа, в число типа double (формат двойной точности с плавающей точкой).
StrToInteger Преобразование строки, содержащей символьное представление числа, в число типа int (целое).
StrToTime Преобразование строки, содержащей время и/или дату в формате "yyyy.mm.dd [hh:mi]", в число типа datetime (количество секунд, прошедших с 01.01.1970).
TimeToStr Преобразование значения, содержащего время в секундах, прошедшее с 01.01.1970, в строку формата "yyyy.mm.dd hh:mi".

Для получения подробного описания этих и других функций необходимо обратиться к справочной документации на MQL4.community, сайте MetaQuotes Ltd. или к разделу "Справка" в редакторе MetaEditor.