<< Пред. стр.

стр. 34
(общее количество: 46)

ОГЛАВЛЕНИЕ

След. стр. >>

обычное: генетическому процессу эволюции представится возможность
создать наилучшую модель входа из набора необработанных идей.
ГА будут искать в чрезвычайно большом множестве решений наилуч-
шую модель входа, которая может быть получена для определенных дан-
ных и шаблонов правил. Количество правил для каждой модели будет ог-
раничено во избежание подгонки под исторические данные. Данная за-
дача сводится к поиску оптимальных наборов чисел. Без использования
ГА такой массированный поиск решений был бы практически невозмо-
жен и неразумен в любом смысле. Конечно, вместо ГА всегда можно осу-
ществить лобовую оптимизацию — особенно, если вы располагаете не-
сколькими тысячелетиями на проведение этой работы. В качестве другой
альтернативы можно воспользоваться эмпирическим поиском оптималь-
ных правил, т.е. попытаться найти наилучшие правила с помощью наблю-
дений, однако этот подход не обязательно позволит максимизировать та-
кую сложную функцию, как соотношение риск/прибыль. ГА обеспечи-
вают эффективный способ выполнения очень больших поисков, особен-
но когда нет простых эвристических методов решения данной задачи.


ЭВОЛЮЦИОННЫЙ ПОИСК МОДЕЛИ ВХОДА

В данном примере популяция моделей входа с тремя правилами была по-
лучена с помощью генетического оптимизатора OptEvolve, написанного
на С ++ (Scientific Consultants Services, 516-696-3333). Каждый ген соответ-
ствует блоку из четырех чисел и шаблону правила — таким образом созда-
ется соответствие наборов чисел и наборов правил. Каждая хромосома со-
держит три гена и состоит из 12 чисел: первые четыре числа соответству-
ют первому гену (или правилу), следующие четыре соответствуют второ-
ИССЛЕДОВАНИЕ входов в РЫНОК
286 ЧАСТЬ II




му гену (или правилу), а последние четыре соответствуют третьему гену
(или правилу). ГА должен знать размер гена, чтобы не разрушить важные
гены при выполнении скрещивания. Скрещивание должно произойти толь-
ко на границах генов (блоков из четырех чисел). В настоящем примере это
будет достигнуто путем приравнивания размера гена, который является
параметром генетического оптимизатора, к четырем. Как упомянуто, каж-
дый ген составлен из четырех чисел. Первое число является индексом в
таблице возможных шаблонов правил. Например, если это число 1, то вы-
бирается шаблон сравнения цен, в котором различие между двумя ценами
закрытия сравнивается с некоторым порогом (см. код). Остальные три чис-
ла в гене соответствуют значению порога и двум анализируемым перио-
дам для сравниваемых цен. Если первое число из блока 4 чисел равно 2, то
будет выбран шаблон сравнения цены и скользящего среднего. В этом слу-
чае два из оставшихся трех чисел контролировали бы период скользящего
среднего и направление сравнения (должна ли цена быть выше или ниже
скользящего среднего). Вообще, если первое число в блоке из четырех чи-
сел равно n, тогда используется шаблон для правила n, а любые требуемые
параметры определены оставшимися тремя числами в блоке из четырех
чисел. Эта схема кодирования облегчает поддержание расширяемой базы
данных для шаблонов правил. Каждый из трех блоков четырех чисел свя-
зан с соответствующим правилом. Модель входа, состоящая из трех пра-
вил, соответствует любой хромосоме, состоящей из 12 чисел.


Шаблоны правил
Первый шаблон правила (case l в функции Rules) определяет сравнение
между двумя ценами и порогом: правило принимает значение ИСТИНА
(TRUE), если цена закрытия 1b1 дней назад больше, чем некоторый поро-
говый фактор (thr) плюс цена закрытия 1b2 дней назад. В остальных случа-
ях правило принимает значение ЛОЖЬ (FALSE). Неизвестные (1b1, 1b2 и
thr) оставлены пустыми для будущего использования при реализации про-
граммы. Этот шаблон был включен, потому что тот вид правил, которые
он представляет, был полезен в предыдущих исследованиях.
Второй шаблон правила (case 2) включает простые скользящие сред-
ние, которые часто используются для определения тренда. Обычно счи-
тается, что рынок будет двигаться вверх, если цена выше ее скользящего
среднего, и опускаться вниз, если цена ниже ее скользящего среднего. В
шаблоне присутствуют только два неизвестных: первый (per) контроли-
рует число дней в скользящем среднем и второй (v4) контролирует на-
правление сравнения (выше или ниже).
Третий шаблон правила (case 3) идентичен второму (case 2), за исклю-
чением того, что вместо простого скользящего среднего используется экс-
поненциальное .
ГЕНЕТИЧЕСКИЕ АЛГОРИТМЫ 287
ГЛАВА 12




Было много рассуждений относительно важности данных по суммар-
ной величине открытых позиций на рынке (открытому интересу). Лэрри
Виллиамс (Larry Williams, 1979) упомянул, что снижение открытого инте-
реса в течение периодов застоя цен указывает на потенциал для сильного
подъема. Сокращение открытого интереса может быть интерпретирова-
но как снижение количества обращающихся на рынке контрактов, созда-
вая условия, когда спрос на контракты может перевесить предложение.
Четвертый шаблон правила (case 4) просто вычисляет процентное сниже-
ние открытого интереса за период от 1Ь1 дней назад до 1 дня назад (откры-
тый интерес, как правило, не публикуется для текущего дня) и сравнива-
ет эту величину с порогом (thr). Если снижение больше, чем порог, то пра-
вило принимает значение ИСТИНА. В остальных случаях оно принимает
значение ЛОЖЬ. Порог и период (1b1) — неизвестные, которые будут ис-
пользованы при реализации программы.
Пятый шаблон правила (case 5) подобен четвертому шаблону, но рас-
считывает повышение, а не падение открытого интереса. Если происхо-
дит увеличение, большее чем пороговое значение, то правило возвра-
щает значение ИСТИНА. Другие ситуации соответствуют значению
ЛОЖЬ.
Шестой шаблон правила (case 6) может называться условием «нового
максимума». Шаблон запрашивает, отмечен ли 1b1-дневный новый мак-
симум за период последних 1b2 дней. К примеру, правило может звучать
так: «Если достигнут новый 50-дневный максимум в пределах последних
10 дней, то правило принимает значение ИСТИНА, в других случаях —
ЛОЖЬ». Это правило пытается найти простое условие пробоя, учитывая
пробои, которые произошли несколько дней назад (возможно, сопровож-
даемые откатами к предыдущим уровням сопротивления, ставшими уров-
нями поддержки, что расценивается другим правилом как хорошая точка
входа). В данном правиле есть два пробела, которые необходимо будет
заполнить при проведении расчетов: 1b1 и 1b2.
Седьмой шаблон правила (case 7) идентичен шестому, за исключени-
ем того, что определяются новые минимумы, а не новые максимумы.
Восьмой шаблон правила (case 8) исследует индекс среднего направ-
ленного движения относительно двух порогов (thr1 и thr2). Этот индика-
тор является мерой наличия тренда, как обсуждалось в главе, посвящен-
ной пробоям. Если среднее направленное движение (ADX) выше нижне-
го порога и ниже верхнего порога, то правило возвращает значение ИС-
ТИНА. В других случаях правило возвращает значение ЛОЖЬ.
Девятый шаблон правила (case 9) выполняет сравнение порогов со
значением стохастического осциллятора, аналогично шаблону 8.
Десятый шаблон правила (case 10) оценивает направление наклона
осциллятора MACD. Длины (1b1 и 1b2) двух скользящих средних, которые
составляют MACD, и направление наклона (v4) необходимы для выбора
значения ИСТИНА или ЛОЖЬ и определены как параметры.
ИССЛЕДОВАНИЕ входов в РЫНОК
288 ЧАСТЬ II




МЕТОДОЛОГИЯ ТЕСТИРОВАНИЯ
Ниже приводятся шаги, необходимые для эволюционного создания мо-
дели входа, основанной на шаблонах правил, используемых в этом иссле-
довании:

1. Выберите произвольную хромосому с 12 элементами. Она
представляет собой потенциальное решение (случайное и, ве-
роятно, не очень хорошее).
2. Поставьте в соответствие каждому параметру правил опреде-
ленное число, чтобы получить три полностью определенных
правила (одно для каждого гена), и определите значение
ИСТИНА/ЛОЖЬ для всех дней во временном ряду.
3. Обработайте ценовые данные день за днем. Если в данный день
все три правила возвращают значение ИСТИНА и если нет те-
кущей длинной (или короткий) позиции, то модель получает
рыночный приказ на покупку (или продажу) при завтрашнем
открытии.
4. Если имеется позиция, используйте стандартную стратегию
выхода для осуществления выхода.
5. Оцените торговую эффективность потенциального решения.
Для этого определите «пригодность решения» как соотноше-
ние риск/прибыль в годовом выражении — величина, кото-
рая фактически является значением {-критерия.
6.. Сообщите генетическому оптимизатору, насколько пригодно
(в вышеупомянутом смысле) потенциальное решение (хромо-
сома) . Это позволит генетическому оптимизатору обновить по-
пуляцию хромосом.
7. Если решение отвечает определенным критериям, то следует
сгенерировать сводку эффективности системы и другую ин-
формацию и сохранить эти данные в файле для последующе-
го рассмотрения.
8. Повторять вышеупомянутые шаги снова и снова до тех пор,
пока не пройдет достаточное число «поколений».

Так как вышеупомянутые шаги повторяются, решения или «поколе-
ния», созданные генетическим оптимизатором, в среднем становятся луч-
ше и лучше. Большое количество отдельных эффективных решений по-
явится в течение эволюционного процесса. Большинство решений будет
записано в файле, созданном в ходе неоднократного выполнения первых
семи вычислительных шагов. Ниже будет рассмотрен код, написанный
на C++, который осуществляет вышеупомянутые шаги.
ГЕНЕТИЧЕСКИЕ АЛГОРИТМЫ 289
ГЛАВА 12




Из-за природы правил, вероятно, будет различным поведение моде-
лей при открытии длинных и коротких позиций. В связи с этим модели
входа для длинных позиций найдены и проверены отдельно от моделей
входа для коротких позиций. Эффективность модели оценивается на всем
портфеле. Цель состоит в том, чтобы найти набор правил, которые обес-
печивают наилучшую эффективность торговли всем портфелем финан-
совых инструментов. Процедура, используемая здесь, отличается от на-
ших более ранних исследований (Katz, McCormick, февраль 1997), где по-
иск оптимальных правил проводился на каждом рынке в отдельности -—
подход, в большей степени подверженный эффектам «вредной» подгон-
ки под исторические данные. Напомним вывод, полученный в отноше-
нии нескольких моделей, которые были первоначально оптимизированы
на индивидуальных инструментах: при использовании одной модели для
всех рынков без оптимизации или настройки под отдельный рынок эф-
фективность данной модели может существенно понизиться. В нижесле-
дующих тестах использовалась стандартная платформа C++, стандарт-
ные приказы входа и стратегия выхода.

static int EventPresent (int *es, int m, int cb) {
// Используется функцией Rules для облегчения кодирования
int i ;
for(i=cb-m+l; i<=cb; i++)
if(es[i]) return TRUE;
return FALSE ;
}

static void Rules (float *opn, float *hi, float *lo, float *cls,
float *vol, float *oi, float *atr, int nb, int vl, float v2,
float v3, float v4, int *ans) {

// Процедура определяет шаблоны правил, используемых
// в генетическом процессе эволюции модели, основанной на правилах.
// opn, hi, lo, cls — стандартные ценовые данные [l..nb]
// vol, oi — объем и открытый интерес [l..nb]
// nb — количество дней
// vl, v2, v3, v4 — селектор правил и параметры
// ans — выходные ценовые данные [l..nb]


// локальные макрофункции
#define LinearScale(х,a,b) ( (х)* ( {b}-(а))/1000.0+(а) )
#define BiasedPosScale(х,а) (0 . 000001*(х)*(х)*{а})
#define Compare{a,b,dir) (((dir)> = 0)?((a)>(b) }: (fa)<(b)))

// локальные переменные
static int lbl, lb2, per, cb, maxlb=100;
static float thr, fac, thr2, thrl, tmp, tiny=l.ОЕ-20;
static int IsNewHigh[MAXBAR+l], IsNewLow[MAXBAR+l];
static float Serl[MAXBAR+1] ;

// шаблоны правил
switch(vl} { // выбираем правило

case 1: // сравнение изменения цены с порогом
ИССЛЕДОВАНИЕ входов в РЫНОК
290 ЧАСТЬ II



lb1 = (int)BiasedPosScale(v2, 5 0 . 0 ) ;
lb2 = (int)BiasedPosScale(v3, 5 0 . 0 ) ;
fac = LinearScale(v4, - 2 . 5 , 2 . 5 ) * s q r t ( a b s ( l b l - I b 2 ) > ;
for(cb-maxlb; cb<=nb; cb++) {
thr = fac * atr [cb];
ans[cb] = cls[cb-lbl] - cls[cb-lb2] > thr;
]
break;

case 2: // сравнение цены с простым скользящим средним
per = 2 + (int)BiasedPosScale(v2, 48.0);
Averages(Serl, cls, per, nb) ;
for(cb=maxlb; cb<=nb; cb++)
ans[cb] = Compare(cls[cb], Serl[cb], V4-500.0);
break;

case 3: // сравнение цены с экспоненциальным скользящим средним
per = 2 + (int)BiasedPosScale(v2, 48.0);
XAverageS(Serl, cls, per, nb) ;
for(cb-maxlb; cb<=nb; cb++)
ans[cb] = Compare(cls[cb], Serl[cb], V4-500.0);
break;

case 4: // сравнение падения открытого интереса с пороговым значением
1b1 = 2 + (int)BiasedPosScale (v2, 48.0);
thr = LinearScale(v3, 0.01, 0.50);
for{cb=maxlb; cb<=nb; cb++) {
tmp = (oi[cb-lbl] - oi[cb-l]) / (oi [cb-lbl] + tiny);
ans [cb] = tmp > thr;
]
break;

case 5: // сравнение увеличения открытого интереса с пороговым значением
1b1 = 2 + (int) BiasedPosScale(v2, 48.0);
thr = LinearScale(v3, 0.01, 0.99);
for(cb=maxlb; cb<=nb; cb++) {
tmp = (oi [cb-1] - oi[cb-lblj) / (oi [cb-lbl] + tiny) ;
ans [cb] = tmp > thr;
}
break;

case 6: // недавние новые максимумы
1bl = 2 + (int)BiasedPosScale(v2, 48.0);
1b2 = 1 + (int)BiasedPosScale(v3, 8.0);
for(cb=lbl+3; cb<=nb; cb++)
IsNewHigh[cb] = hi [cb] > Highest(hi, 1b1, cb-1);
for(cb-maxlb; cb<=nb; cb++)
ans[cb] = EventPresent(IsNewHigh, 1b2, cb) ;
break;

case 7: // недавние новые минимумы
1bl = 2 + (int)BiasedPosScale(v2, 48.0);
1b2 = 1 + (int)BiasedPosScale(v3, 8.0);
for(cb=lbl+3; cb<=nb; cb++)
IsNewLow[cb] = lo[cb] < Lowest(lo, 1b1, cb-1) ;
for(cb=maxlb; cb<=nb; cb++)
ans[cb] = EventPresent(IsNewLow, 1b2, cb);
break;

case 8: // среднее направленное движение
thrl = LinearScale(v2, 5.0, 50.0);
thr2 = thrl + LinearScale(v3, 5.0, 20.0);
ГЕНЕТИЧЕСКИЕ АЛГОРИТМЫ 291
ГЛАВА 12




AvgDirMov{hi, lo, cls, nb, 14, Serl);
for(cb=maxlb; cb<=nb; cb++)
ans [cb] = (Serl[cb] > thrl && Serl [cb] < thr2)
&& Compare (Serl[cb] , Serl[cb-l], v4-500.0);
break;

case 9: // Медленный %К
thr = LinearScale(v2, 5.0, 95.0);
fac = LinearScale(v3, 1.0, 20.0);
thrl = thr - fac;
thr2 = thr + fac;
StochOsc(Serl, hi, lo, cls, 2, 10, nb) ;
for(cb=maxlb; cb<=nb; cb++)
ans [cb] = (Serl[cb) > thrl && Serl [cb] < thr2)
&& Compare(Serl[cb], Serl[cb-1], V4-500.0);
break ;

case 10: // направление наклона MACD
lb1 = 2 + (int)BiasedPosScale(v2, 18.0);
lb2 = lbl + 1 + (int)BiasedPosScale(v3, 48.0);
MacdOsc(Serl, cls, 1, lbl, lb2, nb) ;
for(cb=maxlb; cb<=nb; cb++)
ans[cb] = Compare(Serl[cb], Serl[cb-2], v 4 - 5 0 0 . 0 ) , •
break;

default:
nrerror("Undefined rule template selected");
break;
]

// первые maxlb элементов результата должны иметь значение ЛОЖЬ
memset (&ans [1] , 0, sizeof(*ans) * maxlb);

#undef BiasedPosScale
#undef LinearScale

}

static void Model (float *parms, float *dt, float *opn, float *hi,
float *lo, float *cls, float *vol, float *oi, float *dlrv, int nb,
TRDSIM &ts, float *eqcls) {

// Генетическая эволюция модели входа, основанной на правилах.
// File = xl6modOl.c
// parms — набор [1..MAXPRM] параметров
// dt — набор [1..nb] дат в формате ГГММДД
// орn - набор [l..nb] цен открытия
// hi — набор [l..nb] максимальных цен
// 1о — набор [l..nb] минимальных цен
// cls - набор [l..nb] цен закрытия
// vol — набор [l..nb] значений объема
// oi - набор [l..nb] значений открытого интереса
// dlrv — набор [l..nb] средней долларовой волатильности
// nb — количество дней в наборе данных
// ts — ссылка на класс торгового симулятора
// eqcls — набор [l..nb] уровней капитала при закрытых позициях

// описываем локальные переменные
static int rc, cb, ncontracts, maxhold, ordertype, signal;
static int disp, k, modeltype;
static float mmstp, ptlim, stpprice, limprice, tmp;
static float exitatr[MAXBAR+1] ;
static int rulel[MAXBAR+1], rule2[MAXBAR+1], rule3[MAXBAR+1];
292 ИССЛЕДОВАНИЕ входов в РЫНОК
ЧАСТЬ II



// копируем параметры в локальные переменные для более удобного обращения к ним
modeltype = parms[14]; // модель: 1=длинная позиция, 2=короткая
ordertype = parms[15]; // вход: 1=на открытии, 2=по лимитному приказу,
// 3=по стоп- приказу
maxhold = 1 0 ; // максимальный период удержания позиции
ptlim = 4; // целевая прибыль в единицах волатильности
mmstp = 1; // защитная остановка в единицах волатильности

// выполнение расчетов для всей ценовой информации
AvgTrueRangeS(exitatr,hi,lo,cls,50,nb); // средний истинный диапазон для
// выхода
switch(modeltype) {
case 1: case 2: // для моделей открытия длинных и коротких позиций
// для каждого дня отдельно оценить три правила
Rules (opn, hi, lo, cls, vol, oi, exitatr, nb,
parms[1], parms[2], parms[3], parms[4], rulel);
Rules (opn, hi, lo, cls, vol, oi, exitatr, nb,
parms[5] , parms[6] , parms[7] , parms[8] , rule2);
Rules (opn, hi, lo, cls, vol, oi, exitatr, nb,
parms[9] , parms[10] , parms[11] , parms[12] , rule3};
break;
default: nrerror("Invalid model type");


/ проходим через дни, чтобы моделировать настоящую торговлю
or(cb = 1; cb <= nb; cb++) {

// не открываем позиций до начала периода выборки
//... то же самое, что установка MaxBarsBack в TradeStation
if(dt[cb] < IS_DATE) { eqcls[cb] = 0.0; continue; }


// выполняем все ожидающие приказы и сохраняем значение капитала по
// закрытию
rс = ts.update(opn[cb] , hi[cb], lo [cb], cls[cb], cb};

<< Пред. стр.

стр. 34
(общее количество: 46)

ОГЛАВЛЕНИЕ

След. стр. >>