Поиск по ключевым словам

Принципы работы языка AFL

Введение

Одним из самых важных аспектов языка AFL является то, что он является языком обработки и вычислений массивов (array processing language). AFL оперирует с массивами (векторами) данных.

Этот способ вычислений очень похож на то, как работают популярные пакеты электронных таблиц (типа Microsoft Excel). Каждый, кто знаком с MS Excel, не должен испытать трудностей с пониманием AFL. Фактически все примеры в этой статье были подготовлены с использованием MS Excel.

Что такое массив (array)

Массив это просто список (или строка) значений. В некоторых книгах он может называться вектором. Каждая пронумерованная строка в последующих примерах представляет собой отдельный массив. Для каждого символа АмиБрокер сохраняет в своей базе данных 6 массивов. Один для цены открытия, один для цены лоу, один для цены хай, один для цены закрытия и один для объёма (см. строки с номерами 1-5 в таблицах далее по тексту) и один для открытого интереса. К ним можно обратиться в AFL по именам: open, low, high, close, volume, openint или O, L, H, C, V, OI.

Bar12345678910
1Open1.231.241.211.261.241.291.331.321.351.31

Массив цен открытия

Любые другие массивы вычисляются из этих шести массивов с использованием встроенных функций AFL. Эти массивы не хранятся в базе данных, а вычисляются, когда они необходимы.

Каждое индивидуальное значение в массиве имеет ассоциированную с ним дату. Если у вас включена опция показывать подсказки (Preferences -> Miscellaneous Tab -> Price data tool tips), то когда вы перемещаете курсор над свечками дневного графика, появляется небольшой желтый прямоугольник. AFL берёт значения open, low, high, close, volume из соответствующих массивов и показывает их в подсказке.

Быстрая обработка массивов в AFL

Рассмотрим, как производится обработка следующего выражения:

MyVariable = ( High + Low )/2;

Когда AFL вычисляет такой оператор как ( High + Low )/2 он не повторяет этот код для каждого бара. Вместо этого он берёт МАССИВ High и МАССИВ Low и суммирует соответственные элементы массивов за один этап. Другими словами оператор «+» (и другие операторы тоже) выполняется над целыми массивами сразу и производится на скорости исполнения полностью откомпилированного кода, затем результирующий массив (каждый его элемент) делится на 2 также за один раз.

Рассмотрим в деталях. Когда движок AFL разбирает выражение ( High + Low )/2 он сначала берёт массивы High (1) и Low (2) и производит (за один откомпилированный шаг) временный массив (3). Затем он создаёт финальный массив (4), деля значение каждого элемента временного массива (3) на два. Этот результат присваивается переменной myVariable:

Bar12345678910
1High (исходный массив)1.241.271.251.291.251.291.351.351.371.29
2Low (исходный массив)1.201.211.191.201.211.241.301.281.311.27
3High+Low (временный массив, создаваемый в процессе вычислений)2.442.482.442.492.462.532.652.632.682.46
4( High+Low ) /2
(назначается в MyVariable)
1.221.241.221.2451.231.2651.3251.3151.341.23

Шаги AFL при вычислении ( High + Low ) /2

Скользящие средние, условные выражения

Рассмотрим следующий код:

Cond1 = Close > MA( Close, 3 );
Cond2 = Volume > Ref( Volume, -1 );
Buy = Cond1 AND Cond2;
Sell = High > 1.30;

Этот код генерирует сигнал на покупку, когда сегодняшние закрытие происходит выше чем 3-х дневное скользящее среднее и сегодняшний объем превосходит вчерашний. Он также генерирует сигнал на продажу, когда цена хай дня пробьёт 1.30.

Когда в своём коде вам необходимо посмотреть, не превзошла ли цена закрытия например 3-х дневную простую скользящую среднюю, AFL сначала перебирает массив close, создавая новый массив, который можно условно назвать как MA(close,3) для анализируемого символа. Каждая ячейка нового массива затем может быть сравнена одна к одной с соответственной ячейкой массива close. В нашем примере таким образом создаётся массив, называемый Cond1. Для каждой ячейки, где цена закрытия выше чем значение в соответствующей ячейке MA(close,3), значение элемента в новом массиве ‘Cond1’ устанавливается в ‘1’. В противном случае значение в ‘Cond1’ устанавливается в ‘0’.

AFL также может заглядывать на заданное число ячеек массива вперёд или назад используя функцию Ref (см. строчку 6 в таблице далее по тексту в которой показан созданный временный массив содержащий значения объёма за предыдущий день).

В строке 9 показан массив Cond2, созданный как результат сравнения значения каждого элемента массива volume с предыдущим ему элементом массива, которое устанавливает в ячейку массива Cond2 значение ‘1’ (истина) или ‘0’ (ложь).

Строка 10 показывает массив ‘Buy’, создающийся как результат сравнения значений ячеек Cond1 с ячейками массива Cond2. Если элемент массива Cond1 равен ‘1’ и соответствующий ему элемент из массива Cond2 также равен ‘1’, то в ячейку массива ‘Buy’ устанавливается значение ‘1’.

Строка 11 показывает массив ‘Sell’, создаваемый во всех случаях когда значение в ячейке массива close превосходит $1.30.

День12345678910
1Open1.231.241.211.261.241.291.331.321.351.37
2High1.241.271.251.291.251.291.351.351.371.29
3Low2.442.482.442.492.462.532.652.632.682.46
4Close1.231.261.241.281.251.251.311.301.321.28
5Volume831030215325283414325666784755567493456
6Ref( Volume, -1 ) (временный массив, создаваемый в процессе вычислений)Null83103021532528341432566678475556749
7MA( Close, 3 ) (временный массив, создаваемый в процессе вычислений)NullNull1.2431.2601.3571.2601.2701.2871.3101.300
8Cond1 = Close < MA(close, 3) (1 (или True), если выражение выполняется. В противном случае ноль)NullNull10110001
9Cond2 = Volume > Ref(volume, -1)Null010011010
10Buy = Cond1 AND Cond2NullNull10010000
11Sell = High > 1.300000001110

Buy и Sell являются специальными массивами, чьи результирующие значения могут быть отображены в окне Analyser или в виде красных или зелёных отметок на экране при необходимости.

Более сложные функции

Приведённые выше примеры очень простые. Далее будет дано объяснение следующим трем вещам, которые обычно вызывают у пользователей некоторые затруднения:

  1. Обращение к выделенным значениям (SelectedValue, BeginValue, EndValue, LastValue);
  2. Функция IIF;
  3. Функция AMA (адаптивная скользящая средняя).

Как описано в обучающем руководстве по базовым графическим средствам (Tutorial: Basic charting guide), вы можете выбрать и отметить любую котировку на графике и выделить временной интервал графика (From-To range). Бар, отмеченный вертикальной линией, называется “выбранным” баром (“selected” bar), также первый и последний бары интервала называются “начальным” и “конечным” барами (“begin” and “end” bars). В AFL есть специальные функции, которые позволяют обращаться к значениям массива на выбранном, начальном и конечном баре соответственно. Это функции SelectedValue, BeginValue и EndValue. Также есть ещё одна функция – LastValue, которая позволяет получить значение массива на самом последнем баре графика. Эти четыре функции берут из массива элемент на заданном баре и возвращают ЕДИНСТВЕННОЕ ЧИСЛО, представляющее собой значение массива в данной точке. Это позволяет вычислять различную статистику относительно выбранных точек графика. Например

EndValue( Close ) - BeginValue( Close )

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

Когда число, полученное с помощью одной из этих функций, сравнивается с массивом или выполняется какая-либо другая арифметическая операция, в которой участвует число и массив, она осуществляется так, как если бы число распространялось на все элементы массива. Это иллюстрируется в приведённой ниже таблице (строки 2, 6, 7). Зелёным цветом отмечен “начальный” бар, а красным цветом – “конечный” бар. “Выбранный” бар закрашен синим.

День12345678910
1Open1.231.241.211.261.241.291.331.321.351.37
2BeginValue( Open )1.241.241.241.241.241.241.241.241.241.24
3EndValue( Open )1.321.321.321.321.321.321.321.321.321.32
4SelectedValue( Open )1.211.211.211.211.211.211.211.211.211.21
5LastValue( Open )1,371,371,371,371,371,371,371,371,371,37
6Close1,221,261,231,281,251,251,311,301,321,28
7Close <= BeginValue( Open )1010000000
8result = IIF( Close <= BeginValue( Open ), Close, Open );1,221,241,231,261,241,291,331,321,351,37
9Period2342352342
10Factor = 2/(Period+1)0,6670,5000,4000,6670,5000,3330,6670,5000,6000,667
111 – Factor0,3330,5000,6000,3330,5000,6670,3330,5000,6000,333
12AMA( Close, Factor )0,81251,03631,11381,22341,23671,23991,28531,29271,30361,2866

Функция

IIF(condition, truepart, falsepart)

работает таким образом, что возвращает значение второго (truepart) или третьего (falsepart) аргумента в зависимости от условия (condition). Как вы можете видеть в вышеприведённой таблице, значения в строку 8 поступают из массива Close (truepart) для баров, когда условие выполняется (1), и приходит из массива Open (falsepart) для всех остальных баров. Таким образом, массив возвращаемый функцией IIF, составляется как из значений элементов из массива Close, так и из значений некоторых элементов из массива Open. Следует отметить, что оба аргумента как truepart так и falsepart являются массивами и они вычисляются независимо от условия, не обращая на него внимание (так что всё это не представляет собой обыкновенный IF-THEN-ELSE оператор, а является функцией возвращающей массив).

Функция

AMA(array, factor)

обчно вызывает наибольшие проблемы с пониманием, но в действительности она очень проста. Функция работает рекурсивным методом. Это означает, что она использует предыдущие свои значения для вычисления текущего результата. Функция обрабатывает массив бар за баром, на каждом шаге она умножает текущую ячейку массива из первого аргумента (array) на текущую ячейку второго аргумента (factor) и прибавляет к этому предыдущее значение AMA, умноженное на (1-Factor).

Рассмотрим колонку 3. Значение AMA в колонке 3 получено как умножение цены закрытия из колонки 3 (1,23) на множитель Factor (0,4). Затем мы прибавляем предыдущее значение AMA (1,0363), умноженное на (1-Factor = 0,6). Результат (округлённый до 4 знаков после запятой) получается 1,23 * 0,4 + 1,0363 * 0,6 = 1,1138.

Если рассмотреть строку 12 этой таблицы, можно отметить, что эти значения выглядят как скользящее среднее массива close. Это так и есть. Фактически мы описали, как вычисляется функция AMA экспоненциального скользящего среднего с переменным периодом.

Циклы

С версией Амиброкера 4.40 появилась возможность организовывать циклы для итерации массивов с помощью операторов for и while и добавлен оператор ветвления if-else. Эти усовершенствования дали возможность работать обоими способами: как с использованием вычислений над массивами (описанными выше) для быстрых и простых расчётов, так и используя циклы для того, чтобы делать сложную обработку. Следующий код приведён в качестве примера, как реализовать экспоненциальное скользящее усреднение с переменным периодом (описанное выше) с использованием циклов:

Period = ... некие вычисления

vaexp[ 0 ] = Close[ 0 ]; // инициализация первого значения

for( i = 1; i < BarCount; i++ )
{
// вычисление значения параметра сглаживания
Factor = 2/(Period[ i ] + 1 );

// вычисление значения i-го элемента массива
// используя close на текущем баре ( close[ i ] )
// и предыдущее значение вычисляемого среднего ( vaexp[ i - 1 ] )
vaexp[ i ] = Factor * Close[ i ] + ( 1 - Factor ) * vaexp[ i - 1 ];
}

Как вы можете видеть, код получается длиннее, но с другой стороны он очень похож на код любого другого языка программирования (C / Pascal / Basic). Так что, пользователи с некоторым опытом в программировании могут легко его понять.

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

Если вы испытываете затруднения с программированием на AFL, то сначала можно потренироваться, создавая примеры массивов в таблице Excel.

Мастер-класс Разработка и оптимизация торговой стратегии в программе AmiBroker

Erenbur

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *