Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Стохастический Осциллятор (Stochastic Oscillator). 11 страница




Qnt_Symb=FileWrite(Handle,Erray[i,0],Erray[i,1]);//Запись в файл

При записи в файл после значения Erray[i,0] будет записан разделитель (символ, используемый как разделитель, указывается в функции открытия файла FileOpen(), в данном случае ';'). После окончания исполнения функции FileWrite(), т.е. в конце записи, будет автоматически записан признак конца строки "\r\n". На всех последующих итерациях цикла for будет сделана очередная запись такого же вида. Каждая новая запись начинается с того места, где остался файловый указатель после последней записи. При этом в файл будут записаны значения следующих элементов массива Erray (индексы элементов на каждой итерации увеличиваются на 1).

Если текущая запись в файл выполнена успешно, то управление передаётся на следующую итерацию. Если же запись в файл закончилась неудачей, то после сообщения пользователю файл закрывается с помощью функции FileClose() и функция start() заканчивает работу. Если все записи в файл выполнены успешно, то после окончания исполнения цикла for управление передаётся функции закрытия файла FileClose() в блок 7-8. В этом случае выводится сообщение об успешном создании файла, после чего исполнение функции start() заканчивается. По окончании исполнения эксперта будет создан файл News.csv, представленный на Рис. 149.

 

Функции, применяемые для осуществления файловых операций

 

Функция Краткое описание
FileClose Закрытие файла, ранее открытого функцией FileOpen().
FileDelete Удаление указанного файла. Файлы могут быть удалены только в том случае, если они расположены в папке каталог_терминала\experts\files (каталог_терминала\tester\files в случае тестирования эксперта) или ее подпапках.
FileFlush Сброс на диск всех данных, оставшихся в файловом буфере ввода-вывода.
FileIsEnding Возвращает TRUE, если файловый указатель находится в конце файла, иначе возвращает FALSE. В случае достижения конца файла в процессе чтения функция GetLastError() вернет ошибку ERR_END_OF_FILE (4099)
FileIsLineEnding Возвращает TRUE, если файловый указатель находится в конце строки файла формата CSV, иначе возвращает FALSE.
FileOpen Открывает Файл для ввода и/или вывода. Возвращает файловый описатель открытого файла или -1 в случае неудачи.
FileOpenHistory Открывает файл в текущей папке истории (каталог_терминала\history\server_name) или ее подпапках. Возвращает описатель файла или -1 в случае неудачи.
FileReadArray Функция читает указанное число элементов из двоичного файла в массив. Перед чтением данных массив должен быть достаточного размера. Функция возвращает количество фактически прочитанных элементов.
FileReadDouble Функция читает число двойной точности с плавающей точкой (double) из текущей позиции бинарного файла. Размер числа может быть 8 байтов (double) или 4 байта (float).
FileReadInteger Функция читает целое число из текущей позиции бинарного файла. Размер целого числа может быть 1, 2 или 4 байта. Если размер числа не указан, система пытается прочитать как 4-байтовое целое число.
FileReadNumber Чтение числа с текущей позиции файла CSV до разделителя. Применяется только для файлов CSV.
FileReadString Функция читает строку с текущей позиции файла. Применяется как к CSV, так и к двоичным файлам. Для текстовых файлов строка будет прочитана до разделителя. Для бинарных файлов в строку будет прочитано указанное количество символов.
FileSeek Функция перемещает файловый указатель на новую позицию, которая является смещением в байтах от начала, конца или текущей позиции файла. Следующее чтение или запись происходят с новой позиции. Если перемещение файлового указателя прошло успешно, функция возвращает TRUE, иначе возвращает FALSE.
FileSize Функция возвращает размер файла в байтах.
FileTell Функция возвращает смещение текущей позицию файлового указателя от начала файла.
FileWrite Функция предназначена для записи данных в файл CSV, разделитель между данными включается автоматически. После записи в файл добавляется признак конца строки "\r\n". При выводе числовые данные преобразуются в текстовый формат. Возвращает количество записанных символов или отрицательное значение, если происходит ошибка.
FileWriteArray Функция записывает массив в бинарный файл.
FileWriteDouble Функция записывает число с плавающей запятой в двоичный файл.
FileWriteInteger Функция записывает значение целого числа в двоичный файл.
FileWriteString Функция записывает строку в двоичный файл с текущей позиции. Возвращает число фактически записанных байтов или отрицательное значение в случае ошибки.

 

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

Массивы и таймсерии

 

При работе с массивами очень важно помнить, что в MQL4 нумерация любой последовательности однотипных элементов начинается с нуля.

Ранее указывалось, что не следует путать максимальное значение индекса элемента массива с количеством элементов этого массива (см. Массивы). Например, если объявлен массив:

int Erray_OHL[3]; // Объявление массива

то это значит, что одномерный массив (имеющий одно измерение) с именем Erray_OHL состоит из трёх элементов. Индексация элементов массива начинается с нуля, т.е. первый из трёх элементов имеет индекс 0 (Erray_OHL[0]), второй элемент - индекс 1 (Erray_OHL[1 ]), а третий элемент - индекс 2 (Erray_OHL[2 ]). Таким образом, максимальное значение индекса элемента массива на единицу меньше, чем количество элементов в этом измерении. В данном случае массив является одномерным, т.е можно говорить о количестве элементов в первом измерении: поскольку количество элементов в массиве равно 3, значит максимальное значение индекса равно 2.

То же можно сказать и о нумерации измерений массива. Например, если объявлен массив:

int Erray_OHL[3][8]; // Объявление массива

то это значит, что массив имеет два измерения. Первое измерение этого массива определяет количество строк (в данном примере 3), а второе измерение - количество элементов в строке (или, что тоже самое, количество столбцов, в данном примере 8). Сами измерения также нумеруется. Первое измерение имеет номер 0, а второе измерение - номер 1. Номера измерений используются, например, в функции ArrayRange().

Функция ArrayRange()

int ArrayRange(object array[], int range_index)

Функция возвращает число элементов в указанном измерении массива.

Использование функции ArrayRange() можно продемонстрировать при решении следующей задачи:

Задача 38. Значения элементов матрицы 3х5 содержатся в массиве Mas_1. Получить значения массива Mas_2, значения элементов в котором равны значениям транспонированной матрицы. Использовать произвольные значения элементов.

Зададимся некоторыми значениями элементов и представим исходную и искомую матрицы, содержащиеся, соответственно, в массивах Mas_1 и Mas_2:

Индексы          
           
           
           

 

Индексы      
       
       
       
       
       

 

Исходная матрица, массив Mas_1. Транспонированная матрица, массив Mas_2.

Рис. 151. Исходная и транспонированная матрицы.

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

//--------------------------------------------------------------------

// matrix.mq4

// Предназначен для использования в качестве примера в учебнике MQL4.

//--------------------------------------------------------------- 1 --

int start() // Спец. функция start

{

int Mas_1[3][5]={1,2,3,4,5, 11,12,13,14,15, 21,22,23,24,25};

int Mas_2[5][3];

int R0= ArrayRange(Mas_1, 0); // Число элементов в первом изм

int R1= ArrayRange(Mas_1, 1); // Число элементов в втором изм

 

for(int i=0; i

В функции start() эксперта открыты два массива. Массив Mas_1 имеет 3 строки по 5 элементов в каждой строке, а массив Mas_2 - 5 строк по з элемента в строке. Собственно перезапись значений элементов из одного массива в другой выполняется в строке:

Mas_2[[j][i] = Mas_1[i][j]; // Транспонирование матрицы

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

Для определения количества элементов в первом и втором измерении массива Mas_1 выполняются вычисления:

int R0 = ArrayRange(Mas_1, 0); // Число элементов в первом изм
int R1 = ArrayRange(Mas_1, 1); // Число элементов в втором изм

Обратите внимание, для первого измерения используется значение 0, а для второго 1. Вычисленные значения переменных R0 и R1 используются для определения количества итераций в циклах for.

Полученные значения элементов массива Mas_2 выводятся на экран с помощью функции Comment().


Рис. 152. Результат работы эксперта matrix.mq4.

 

Функции для работы с массивами

 

Функция Краткое описание
ArrayBsearch Возвращает индекс первого найденного элемента в первом измерении массива. Если элемент с указанным значением в массиве отсутствует, функция вернет индекс ближайшего элемента (по значению).
ArrayCopy Копирует один массив в другой. Массивы должны иметь одинаковый тип. Массивы типа double[], int[], datetime[], color[], и bool[], можно копировать как массивы одного типа. Возвращает количество скопированных элементов.
ArrayCopyRates Копирует в двухмерный массив, вида RateInfo[][6], данные баров текущего графика и возвращает количество скопированных баров, либо -1 в случае неудачи.
ArrayCopySeries Копирует массив-таймсерию в пользовательский массив и возвращает количество скопированных элементов.
ArrayDimension Возвращает ранг многомерного массива.
ArrayGetAsSeries Возвращается TRUE, если массив организован как таймсерия (элементы массива индексируются от последнего к первому), иначе возвращается FALSE.
ArrayInitialize Устанавливает все элементы числового массива в одну величину. Возвращает количество инициализированных элементов.
ArrayIsSeries Возвращается TRUE, если проверяемый массив является массивом-таймсерией (Time[], Open[],Close[],High[],Low[] или Volume[]), иначе возвращается FALSE.
ArrayMaximum Поиск элемента с максимальным значением. Функция возвращает позицию максимального элемента в массиве.
ArrayMinimum Поиск элемента с минимальным значением. Функция возвращает позицию минимального элемента в массиве.
ArrayRange Возвращает число элементов в указанном измерении массива. Поскольку индексы начинаются с нуля, размер измерения на 1 больше, чем самый большой индекс.
ArrayResize Устанавливает новый размер в первом измерении массива. При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера, в противном случае возвращает -1, и массив не меняет размеры.
ArraySetAsSeries Устанавливает направление индексирования в массиве.
ArraySize Возвращает количество элементов массива.
ArraySort Сортировка числовых массивов по первому измерению. Массивы-таймсерии не могут быть отсортированы.

 

Функции доступа к таймсериям

 

Функция Краткое описание
iBars Возвращает количество баров на определенном графике.
iBarShift Поиск бара по времени. Функция возвращает смещение бара, которому принадлежит указанное время. Если для указанного времени бар отсутствует ("дыра" в истории), то функция возвращает, в зависимости от параметра exact, -1 или смещение ближайшего бара.
iClose Возвращает значение цены закрытия указанного параметром shift бара с соответствующего графика (symbol, timeframe). В случае ошибки функция возвращает 0.
iHigh Возвращает значение максимальной цены указанного параметром shift бара с соответствующего графика (symbol, timeframe). В случае ошибки функция возвращает 0.
iHighest Возвращает индекс найденного наибольшего значения (смещение относительно текущего бара).
iLow Возвращает значение минимальной цены указанного параметром shift бара с соответствующего графика (symbol, timeframe). В случае ошибки функция возвращает 0.
iLowest Возвращает индекс найденного наименьшего значения (смещение относительно текущего бара).
iOpen Возвращает значение цены открытия указанного параметром shift бара с соответствующего графика (symbol, timeframe). В случае ошибки функция возвращает 0.
iTime Возвращает значение времени открытия указанного параметром shift бара с соответствующего графика (symbol, timeframe). В случае ошибки функция возвращает 0.
iVolume Возвращает значение тикового объема указанного параметром shift бара с соответствующего графика (symbol, timeframe). В случае ошибки функция возвращает 0.

 

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

Математические функции

 

В составе MQL4 имеются математические и тригонометрические функции. Использование большинства из них не вызывает никаких затруднений. Например, функция MathMax() возвращает максимальное из двух числовых значений, указанных в списке параметров вызова функции. Использование других функций требует определённой внимательности и вдумчивости. Рассмотрим одну из таких функций.

Функция MathFloor()

double MathFloor(double x)

Функция возвращает числовое значение, представляющее наибольшее целое число, которое меньше или равно x.

Параметры:

x - числовое значение.

Обратите внимание, значение, возвращаемое функцией, является действительным числом (типа double), в то же время в назначении функции указано, что функция возвращает целое число. Это нужно понимать так, что функция возвращает действительное число, у которого во всех разрядах после разделительной точки указаны нули. Например, функция MathFloor() может вернуть 37.0 (положительное число типа double) или -4.0 (отрицательное число типа double).

В описании также указано, что функция возвращает максимальное из возможных чисел, которое меньше заданного. Например, если значение передаваемого параметра х равно 13.5, то максимальное действительное число, имеющее после разделительной только нули, равно 13.0. Если же в вызове функции указано отрицательное число -13.5, то максимальное меньшее целое число равно -14.0. Таким образом, изменение знака передаваемого параметра приводит к разным результатам, а именно, получаемые значения не равны по модулю.

В некоторых случаях использование подобных функций оказывается очень удобным. Для примера рассмотрим фрагмент расчёта количества лотов для новых ордеров:

int Percent =30; // % свободных средств

double Free =AccountFreeMargin(); // Свободные средства

double One_Lot=MarketInfo(Symb,MODE_MARGINREQUIRED);//Стоим. 1 лота

double Step =MarketInfo(Symb,MODE_LOTSTEP); // Шаг изменен размера

 

double Lots_New=MathFloor(Free*Percent100One_LotStep)*Step;

Значение переменной Percent задаётся пользователем. В данном случае пользователь выделил для новых ордеров 30% свободных средств. В соответствии с правилами, установленными дилинговым центром, правильно вычисленное количество лотов должно быть кратно минимальному шагу изменения размера лотов (Step). Для расчёта необходимы также значения свободных средств на счёте (Free) и стоимости одного лота (One_Lot).

Рассмотрим логику рассуждений программиста, составившего формулу для расчёта искомого количества лотов Lots_New для новых ордеров. Используем для наглядности численные значения переменных. Пусть Free = 5000.0, One_Lot = 1360.0 (в большинстве ДЦ стоимость 1 лота для валютной пары, в знаменателе которой USD, пропорциональна цене по валютному инструменту), Step = 0.1. В этом случае программную строку для вычисления Lots_New можно переписать так:

Lots_New = MathFloor(5000.0*30/100/1360.0/0.1)*0.1;

Значением выражения 5000.0*30/100 является количество средств, выделенных пользователем для открытия нового ордера. В данном случае стоимость нового ордера может достигать 1500.0. Потратив все эти средства можно открыть один ордер, количество лотов у которого равно 1500.0 / 1360.0 = 1.102941. Однако, дилинговый центр не примет заявку на такое количество лотов, т.к. минимальный шаг (в большинстве дилинговых центров) Step = 0.1. Для вычисления искомого количества лотов необходимо отбросить "лишние" цифры в дробной части и заменить их нулями.

Для этого можно воспользоваться рассматриваемой математической функцией:

Lots_New = MathFloor(1.102941/0.1)*0.1;

Результатом вычисления MathFloor(1.102941/0.1) будет число 11.0, а вычисленным значением переменной Lots_New - число 1.1 лота. Это значение соответствует правилам, установленным дилинговым центром, поэтому его можно использовать как заявляемое количество лотов для новых ордеров.

 

Математические функции

 

Функция Краткое описание
MathAbs Функция возвращает абсолютное значение (значение по модулю) переданного ей числа.
MathArccos Функция возвращает значение арккосинуса x в диапазоне 0 к π в радианах. Если x меньше -1 или больше 1, функция возвращает NaN (неопределенное значение)
MathArcsin Функция возвращает арксинус x в диапазоне от -π/2 до π/2 радианов. Если x -, меньше -1 или больше 1, функция возвращает NaN (неопределенное значение).
MathArctan Функция возвращает арктангенс x. Если x равен 0, функция возвращает 0. MathArctan возвращает значение в диапазоне от -π/2 до π/2 радианов.
MathCeil Функция возвращает числовое значение, представляющую наименьшее целое число, которое больше или равно x.
MathCos Функция возвращает косинус угла.
MathExp Функция возвращает значение числа e в степени d. При переполнении функция возвращает INF (бесконечность), в случае потери порядка MathExp возвращает 0.
MathFloor Функция возвращает числовое значение, представляющее наибольшее целое число, которое меньше или равно x.
MathLog Функции возвращают натуральный логарифм x в случае успеха. Если x отрицателен, функция возвращает NaN (неопределенное значение). Если x равен 0, функция возвращает INF (бесконечность).
MathMax Функция возвращает максимальное из двух числовых значений.
MathMin Функция возвращает минимальное из двух числовых значений.
MathMod Функция возвращает вещественный остаток от деления двух чисел. Функция MathMod рассчитывает вещественный остаток f от x / y таким образом, что x = i * y + f, где i является целым числом, f имеет тот же знак, что и x, и абсолютное значение f меньше, чем абсолютное значение y.
MathPow Функция возвращает значение основания, возведенного в указанную степень.
MathRand Функция возвращает псевдослучайное целое число в дипазоне от 0 до 32767. Перед первым вызовом функции необходимо использовать функцию MathSrand, чтобы перевести генератор псевдослучайных чисел в начальное состояние
MathRound Функция возвращает значение, округленное до ближайшего целого числа указанного числового значения.
MathSin Функция возвращает синус указанного угла.
MathSqrt Функция возвращает квадратный корень x. Если x отрицателен, MathSqrt возвращает NaN (неопределенное значение).
MathSrand Функция устанавливает начальное состояние для генерации ряда псевдослучайных целых чисел.
MathTan Функция возвращает тангенс x. Если x больше или равен 263 или меньше или равен -263, то происходит потеря значения и функция возвращает неопределенное число.

 

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

Глобальные переменные GlobalVariables

 

Значительная часть функций, предназначенных для работы с глобальными переменными клиентского терминала, рассмотрена в разделе Переменные GlobalVariables. В предыдущем изложении указывалось, что при завершении работы правильно составленная программа должна удалить глобальные переменные, которые были ею созданы. После завершения всех программ в клиентском терминале не должно оставаться GV-переменных.

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

Функция GlobalVariablesDeleteAll()

int GlobalVariablesDeleteAll(string prefix_name=NULL)

Удаляет глобальные переменные. Если префикс для имени не задан, то удаляются все глобальные переменные. В противном случае удаляются только те переменные, имена которых начинаются на указанный префикс. Функция возвращает количество удаленных переменных.

Параметры:

prefix_name - префикс имени удаляемых глобальных переменных.

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

//--------------------------------------------------------------------

// deleteall.mq4

// Предназначен для использования в качестве примера в учебнике MQL4.

//--------------------------------------------------------------------

int start() // Специальная функция start()

{

GlobalVariablesDeleteAll(); // Удаление всех GV-переменных

PlaySound("W2.wav"); // Брыньк

return; // И уходим

}

//--------------------------------------------------------------------

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


Рис. 153. Вид окна глобальных переменных клиентского терминала после исполнения скрипта deleteall.mq4.

 

Функции для работы с глобальными переменными

 

Функция Краткое описание
GlobalVariableCheck Возвращает значение TRUE, если GV-переменная существует, иначе возвращает FALSE
GlobalVariableDel Удаляет глобальную переменную. При успешном удалении функция возвращает TRUE, иначе FALSE.
GlobalVariableGet Возвращает значение существующей глобальной переменной или 0 в случае ошибки.
GlobalVariableName Функция возвращает имя глобальной переменной по порядковому номеру в списке глобальных переменных.
GlobalVariableSet Устанавливает новое значение глобальной переменной. Если переменная не существует, то система создает новую глобальную переменную. При успешном выполнении функция возвращает время последнего доступа, иначе 0.
GlobalVariableSetOnCondition Устанавливает новое значение существующей глобальной переменной, если текущее значение переменной равно значению третьего параметра check_value. Если переменной не существует, функция сгенерирует ошибку ERR_GLOBAL_VARIABLE_NOT_FOUND (4058) и вернет FALSE. При успешном выполнении функция возвращает TRUE, иначе FALSE.
GlobalVariablesDeleteAll Удаляет глобальные переменные. Если префикс для имени не задан, то удаляются все глобальные переменные. В противном случае удаляются только те переменные, имена которых начинаются на указанный префикс. Функция возвращает количество удаленных переменных.
GlobalVariablesTotal Функция возвращает общее количество глобальных переменных.

 

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

Пользовательские индикаторы

 

Функции пользовательских индикаторов позволяют выполнить необходимые настройки, чтобы представить индикатор в удобном оформлении. Рассмотрим некоторые из них (см. также Создание пользовательских индикаторов).

Функция SetIndexBuffer()

bool SetIndexBuffer(int index, double array[])

Функция связывает переменную-массив, объявленный на глобальном уровне, с предопределенным буфером пользовательского индикатора. Количество буферов, необходимых для расчета индикатора, задается с помощью функции IndicatorBuffers() и не может быть больше 8. В случае успешного связывания возвращается TRUE, иначе FALSE. Чтобы получить расширенные сведения об ошибке, следует вызвать функцию GetLastError().




Поделиться с друзьями:


Дата добавления: 2014-12-29; Просмотров: 444; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.063 сек.