<< Пред. стр.

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

ОГЛАВЛЕНИЕ

След. стр. >>


Медленный стохастический осциллятор




Рисунок 7-1. Осцилляторы и расхождение графиков цены и осцилляторов.




Еще один известный метод — поиск расхождений осциллятора и цены,
описанный МакХортером (McWhorter, 1994). Расхождение получается
тогда, когда цены образуют новый минимум (ниже предыдущих миниму-
мов) , а осциллятор — более высокий минимум (выше предыдущих мини-
мумов). Такое расхождение дает сигнал к покупке. В противоположной
ситуации, когда цены образуют новый максимум, а осциллятору не уда-
ется достичь предыдущего максимума, что является признаком потери
ценового импульса, генерируется сигнал к продаже. Расхождение иногда
легко увидать глазами, но для программы с простыми правилами найти
его почти всегда затруднительно. Механическая генерация сигналов на
основе расхождения требует алгоритма распознавания образов, что ус-
ложняет систему и, следовательно, затрудняет ее тестирование. Впрочем,
получать такие сигналы можно, хорошим примером служит программа
Divergengine от Ruggiero Associates. Пример расхождения можно увидеть
на рис. 7-1.
В использовании осцилляторов для получения сигналов существует ряд
принципиальных моментов, например сглаживание данных и своевремен-
ИССЛЕДОВАНИЕ входов в РЫНОК
162 ЧАСТЬ II



ность входов. Например, MACD иногда обеспечивает сглаживание дан-
ных в реальном времени, что позволяет получать лучшие результаты, чем
при использовании моделей, основанных на скользящих средних, где пики
и провалы на графике значительно запаздывают по сравнению с ценами,
а поздние входы снижают эффективность. MACD, со своей стороны, при
совпадении собственного периода с циклической активностью рынка
обеспечивает примерное совпадение пиков и провалов и сглаживание
графика, что также позволяет избежать характерных для скользящих
средних многочисленных сделок, вызванных шумом, и повысить прибыль
за счет своевременности сделок.
Помимо MACD, другие осцилляторы также, как правило, не отстают
или даже опережают цены. По рассмотренным ниже причинам обгоня-
ющие или одновременные индикаторы вовсе не обязательно дают боль-
шие прибыли, чем запаздывающие скользящие средние — своевремен-
ность сигналов не обязательно означает их прибыльность. Проблема в
том, что даже при наличии некоторых абсолютно точных сигналов, ос-
цилляторы будут генерировать множество ложных. В условиях сильно-
го тренда многие из ожидаемых разворотов никогда не происходят, и
система входит в рынок в неверном направлении. Таким образом, за счет
точности теряется надежность. Что важнее — поздний, но надежный
вход или ранний, но менее надежный — вопрос отдельного эмпиричес-
кого исследования. В принципе эта проблема возникает при использо-
вании любого прогностического метода — чем больше задержка, тем
точнее (и бесполезнее) прогноз и, чем больше опережение, тем он по-
лезнее (и ошибочнее). Эта логика напоминает принцип неопределенно-
сти Гейзенберга.
В качестве примера получения сигналов входа рассмотрим стохасти-
ческий осциллятор: простая модель производит покупку, если значение
осциллятора падает ниже традиционного порога перепроданности на
уровне 20 и затем поднимается. Продажа производится, когда значение
осциллятора поднимается выше традиционного порога перекупленности
на уровне 80 и затем снова опускается. Поскольку при таких торговых
правилах сигнал на закрытие текущей позиции вряд ли появится скоро,
требуется вводить независимый критерий выхода. Трейдеры также ищут
модель, называемую «стохастический крюк»: осциллятор достигает ми-
нимума, немного поднимается, а затем образует еще один минимум на
более высоком уровне. Как только определяется второй минимум, пода-
ется сигнал на покупку. Когда эта же модель встречается в перевернутом
виде, производится продажа.
Как и в случае с пробоями и скользящим средними, для осуществле-
ния входов могут быть использованы различные приказы, а именно ры-
ночный приказ по цене открытия, лимитный приказ и стоп-приказ. Пре-
имущества и недостатки этих входов уже обсуждались в двух предыду-
щих главах.
Входы НА ОСНОВЕ ОСЦИЛЛЯТОРОВ 163
ГЛАВА 7




ХАРАКТЕРИСТИКИ ВХОДОВ НА ОСНОВЕ ОСЦИЛЛЯТОРОВ
Основанные на осцилляторах входы обладают преимуществами опере-
жения или совпадения по времени с поведением цены, следовательно, они
пригодны для входов, направленных против тренда, и теоретически мо-
гут обеспечивать высокий процент выгодных сделок. Осцилляторы обыч-
но работают наилучшим образом на циклических или не подверженных
трендам рынках. На этих рынках осцилляторы указывают на максимум
или минимум еще до начала движения цен. Таким образом, проскальзы-
вание минимально или даже отрицательно, и переоценка позиции стано-
вится положительной уже при очень малом движении цены. В таких слу-
чаях легко получить солидную прибыль даже при неоптимальной страте-
гии выхода. Считается, что на рынках тренды присутствуют всего около
30% времени; по нашим данным, на многих рынках — еще реже. При ис-
пользовании соответствующих фильтров для избежания осцилляторных
входов во время сильного тренда, видимо, можно создать замечательную
модель входа. Такое фильтрование — прямая противоположность тому,
которое используют при тестировании систем, основанных на пробоях,
когда необходимым условием было наличие трендов, а не их отсутствие.
Основная слабость простых осцилляторных входов в том, что они ма-
лоэффективны при длительных трендах и часто выдают множество лож-
ных сигналов разворота. Некоторые осцилляторы легко застревают на
крайних значениях, например стохастический нередко имеет значение
100 очень долго, если на рынке происходит сильное направленное движе-
ние. Кроме того, большинство осцилляторных моделей не регистрирует
тренды, в отличие от систем на скользящих средних и пробоях, которые
не пропустят практически ни одного значимого тренда. Многие трейде-
ры говорят, что «тренд — твой друг», что большая часть доходов возника-
ет после «большой волны» и что прибыль от такого крупного успеха по-
крывает частые и мелкие убытки, свойственные для следующих за трен-
дом систем. Поскольку осцилляторные входы направлены против тренда,
настроены на мелкие движения рынка, особое значение имеет хорошая
стратегия выходов для снижения урона, который возникнет при движе-
нии тренда против сделок.


МЕТОДИКА ТЕСТИРОВАНИЯ
Все приведенные ниже тесты были осуществлены с помощью осцилля-
торных моделей на портфеле разнообразных ценных бумаг. Можно ли
получать прибыльные сделки с осцилляторными моделями? Как они ра-
ботают во времени — ухудшается или улучшается их функционирова-
ние за последние годы? Целью нашего тестирования был ответ на эти
вопросы.
ЧАСТЬ II ИССЛЕДОВАНИЕ входов в РЫНОК
164



Во всех тестах использовался стандартный выход, описанный в пре-
дыдущих главах. Правила входов будут рассмотрены параллельно с ко-
дом модели и отдельными тестами. Сделки закрывались при поступлении
приказа на вход в обратном направлении или при исполнении стандарт-
ного выхода. Платформа тестирования тоже была стандартной.
За последние годы мы закодировали на языке C++ ряд осциллято-
ров, описанных в Technical Analysis of Stocks and Commodities и в ряде
других источников. В этой главе мы сравниваем работу версий C++ ос-
цилляторов MACD, RSI и стохастического с их версиями в TradeStation.
В большинстве случаев результаты идеально совпадали, но в одном слу-
чае, а именно для Медленного %К, результат разительно отличался. Раз-
бор кода показал, что TradeStation рассчитывает Медленный %К как экс-
поненциальное скользящее среднее от Быстрого %К. В нашем же коде
отдельно рассчитываются простые скользящие средние с периодом 3 дня
для числителя и знаменателя формулы Быстрого %К. Согласно уравне-
ниям, приведенным Мейбахом (Meibahr, 1992) и другими источниками,
правильной является наша версия на C++. Если читатели захотят повто-
рить наши расчеты в TradeStation и обнаружат расхождения, мы насто-
ятельно рекомендуем проверить функции индикаторов TradeStation.
Кроме того, при попытке закодировать правильную версию Медленно-
го %К для TradeStation на EasyLanguage мы неожиданно обнаружили,
что TradeStation без предупреждения может выдать неверные результа-
ты, если одна пользовательская функция вызывает другую. Когда мы из-
менили код так, чтобы рассчитывалась промежуточная переменная (что-
бы избежать совместных вызовов), были получены правильные резуль-
таты. В этих тестах использовалась версия TradeStation 4.02 от 29 июля
1996 г.
Нижеследующий код включает большинство использованных в тес-
тах моделей входов на основе осцилляторов. Реальный расчет осциллято-
ров достигается путем вызова внешних функций.

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 = xllmodOl.c
// parms - набор [1.. MAXPRM] параметров
// dt - набор [l..nb] дат в формате ГГММДД
// орn - набор [l..nb] цен открытия
// hi — набор [l..nb] максимальных цен
// 1о - набор [1..пЬ] минимальных цен
cls — набор [l..nb] цен закрытия
//
// vol - набор [l..nb] значений обьема
// oi — набор [l..nb] значений открытого интереса
// dlrv — набор [l..nb] средних долларовой волатильности
// nb — количество дней в наборе данных
// ts — ссылка на класс торгового симулятора
// eqcls — набор [l..nb] уровней капитала при закрытых позициях
Входы НА ОСНОВЕ ОСЦИЛЛЯТОРОВ 165
ГЛАВА 7




// объявляем локальные переменные
static int rc, cb, ncontracts, maxhold, len1, len2, len3;
static int modeltype, ordertype, osctype, signal, i, j, k;
static float mmstp, ptlim, stpprice, limprice, tmp;
static float exitatr[MAXBAR+1];
static float sigline[MAXBAR+1], oscline[MAXBAR+1];
static float upperband[MAXBAR+1] , lowerband [MAXBAR+1] ;

// копируем параметры в локальные переменные для удобного обращения
lenl = parms[l]; // более короткий для первого параметра длины
1еn2 = parms[2] ; // более длинный для второго параметра длины
1епЗ = parms[3]; // длина теста дивергенции
modeltype = parms[7]; // тип осцилляторной модели входа
osctype - parms[8]; // тип осциллятора
ordertype = parms[9]; // тип входного приказа
maxhold = 1 0 ; // период максимального удержания позиции
ptlim =4; // целевая прибыль в единицах волатильности
mmstp =1; // защитная остановка в единицах волатильности

// пропускаем неправильные комбинации параметров,
if ( (osctype==4 && len1>=len2) ) (
set_vector(eqcls, 1, nb, 0.0);
return;
}

// выполняем вычисления для всех данных, используя процедуры быстрой обработки
// массивов
AvgTrueRangeS{exitatr,hi,lo,cls,50,nb); // средний истинный диапазон для выхода
switch(osctype} { // выбираем осциллятор
case 1: // классические быстрые стохастики
StochOsc(oscline,hi,lo,cls,1,len1,nb); //Быстрый %К
MovAvg(sigline, oscline, 1, 3, nb); //Быстрый %D
set_vector(upperband, 1, nb, 80.0); //верхняя граница
set_vector(lowerband, 1, nb, 20.0); //пробой нижней границы
break;
case 2: // классические медленные стохастики
StochOsc(oscline,hi,lo,cls,2,lenl,nb); //Медленный %К
MovAvg(sigline, oscline, 1, 3, nb); //Медленный %D
set_vector(upperband, 1, nb, 80.0); //верхняя граница
set_vector(lowerband, 1, nb, 20.0); //пробой нижней границы
break;
case 3: // классический RSI
RsiOsc(oscline, cls, 1, lenl, nb); //RSI
MovAvgtsigline, oscline, 1, 3, nb) ; //3-дневное ПСС
set_vector(upperband, 1, nb, 70.0); //верхняя граница
set_vector(lowerband, 1, nb, 30.0); //пробой нижней границы
break;
case 4 : // классический MACD
MacdOsc(oscline,cls,1,lenl,len2,nb); //классический MACD
MovAvg(sigline, oscline, 2, 9, nb) ; //9-дневное ЭСС
for{i=l; i<=nb; i++}
lowerband[i]=1.5*fabs(oscline[i] ) ; //пороги
MovAvg(upperband,lowerband,1,120,nb); //как долгосрочная
for{i=l; i<=nb; i++} //отклонение от среднего
lowerband[i]= -upperband[i]; //полосы
break;
default: nrerror("Invalid moving average selected");
};
// проходим через штрихи (дни), чтобы смоделировать реальную торговлю
for{cb = 1; cb <= nb; cb++} {

// не открываем позиций до начала периода выборки
// ... то же самое, что и установка MaxBarsBack в TradeStation
ИССЛЕДОВАНИЕ входов в РЫНОК
166 ЧАСТЬ II



if(dt[cb] < IS_DATE) { egcls[cb] = 0.0; continue; )
// выполняем ожидающие приказы и считаем накопленный капитал
rс = ts.update{opn[cb], hi[cb], lo[cb], cls[cb], cb);
if(rc = 0) nrerror("Trade buffer overflow"};
eqcls[cb] = ts.currentequity(EQ_CLOSETOTAL);
// считаем количество контрактов для позиции
//... мы хотим торговать эквивалентом долларовой волатильности
//... 2 новых контрактов S&P-500 от 12/31/98
ncontracts = RoundToInteger(5673.0 / dlrvfcbj);
if(ncontracts < 1) ncontracts = 1;
// избегаем устанавливать приказы на дни с ограниченной торговлей
if(hi[cb+l] == lo[cb+l]) continue;

// генерируем входные сигналы, цены стоп- и лимитных приказов,
// используя определенную модель входа на осцилляторах
#define CrossesAbove (a,b,c) (а[с]>=b[с] && а[с-1]<b[с-1])
#define CrossesBelow(a,b, с) (a[c]<b[c] && а [с-1] >=b [с-1] )
#define TurnsUp(a,c) (а[с]>=а[с-1] && а[с-1]<а[с-2])
#define TurnsDn(a,c) (a[c]<a[c-l] && а [с-1] >=а [с-2] )
signal=0;
switch (modeltype) {
case 1: // модель перекупленности-перепроданности
if(CrossesAbove(oscline, lowerband, cb)}
signal = 1;
else if(CrossesBelow(oscline, upperband, cb))
signal = -1;
limprice = 0.5 * (hi [cb] + lo [cb] ) ;
stpprice = cls[cb] +0.5 * signal * exitatr[cb];
break;
case 2: // модель сигнальной линии
if(CrossesAbove(oscline, sigline, cb))
signal = 1;
else if(CrossesBelow(oscline, sigline, cb))
signal = -1;
limprice = 0.5 * (hi [cb] + lo[cb]) ;
stpprice = cls[cb] + 0.5 * signal * exitatr[cb];
break;
case 3: // модель дивергенции
i = LowestBar(cls, len3, cb) ;
j = LowestBar(oscline, len3, cb);
if(i < cb && i > cb-6 && j > cb-len3+l && i-j > 4
&& TurnsUp(oscline, cb)) signal = 1;
else {
i = HighestBar(cls, len3, cb} ;
j = HighestBar(oscline, len3, cb);
if(i < cb && i > cb-6 && j > cb-len3+l && i-j > 4
&& TurnsDn(oscline, cb)) signal = -1;
)
limprice = 0.5 * (hi[cb] + lo[cb]);
stpprice = cls[cb] + 0.5 * signal * exitatr[cb];
break;
default: nrerror("Invalid model selected");
)
#undef CrossesAbove
#undef CrossesBelow
#undef TurnsUp
#undef TurnsDn

// входим в сделку, используя определенный тип приказа
if (ts.position() <= 0 && signal == 1) {
switch(ordertype) { // выбираем нужный вид приказа
case 1: ts.buyopen('1', ncontracts); break;
case 2: ts.buylimit('2', limprice, ncontracts); break;
Входы НА ОСНОВЕ ОСЦИЛЛЯТОРОВ 167
ГЛАВА 7




case 3: ts.buystop('3', stpprice, ncontracts); break;
default: nrerror("Invalid buy order selected");
}
}
else if(ts.position1) >= 0 && signal == -1) {
switch(ordertype) { // выбираем желаемый тип приказа
case 1: ts.sellopen('4', ncontracts); break;
case 2: ts.selllimit('5', limprice, ncontracts); break;
case 3: ts.sellstop('6', stpprice, ncontracts); break;
default; nrerror("Invalid sell order selected");
}
}

// симулятор использует стандартную стратегию выхода
tmp = exitatr[cb];
ts.stdexitcls ('Х', ptlim*tmp, nmstp*tmp, maxhold) ;
} // обрабатываем следующий день
]


Логика кода весьма напоминает программу, использованную для тес-
тирования скользящих средних. Сначала копируется ряд параметров в
местные переменные для простоты ссылок и считывания дальнейшим
кодом. Затем проверяется наличие непригодных сочетаний параметров,
например для MACD (osctype = 4) длина короткого скользящего средне-
го должна быть меньше, чем длинного, иначе тест будет пропущен. В сле-
дующем крупном блоке osctype выбирает вид рассчитываемого осцилля-
тора (1 — быстрый стохастический, 2 — медленный стохастический, 3 —
классический RSI, 4 — классический MACD) . Осциллятор oscline затем
рассчитывается в виде ряда данных или вектора, генерируются дополни-
тельные кривые, связанные с ним, например сигнальная линия sigline или
медленная версия осциллятора. Верхний (upperband) и нижний (lowerband)
пороги либо рассчитываются, либо задаются. Для стохастического осцил-
лятора используются стандартные пороги 80 и 20, для RSI — пороги на
уровне 70 и 30. Хотя MACD как таковой не имеет порогов, пороги для него
устанавливаются на уровне плюс-минус полтора стандартных отклоне-
ния от нуля. Затем начинается процесс перебора данных, день за днем.
В цикле перебора данных представляют интерес два главных блока —
первый генерирует сигналы покупки и продажи, а также цены для лимит-
ного и стоп-приказов, используемых выбранной моделью. Параметр
mode/type выбирает модель: 1 — модель перекупленности/перепроданно-
сти, 2 — модель сигнальной линии, 3 — модель на расхождении. При этом
используется один из вышеперечисленных осцилляторов, выбранный
параметром osctype. Последний блок производит вход в рынок согласно
выбранному значению параметра ordertype: 1 — для входа по цене откры-
тия, 2 — по лимитному приказу, 3 — по стоп-приказу. Затем симулятор
использует стандартную модель выхода для закрытия сделок.
Точные логические основания для входа будут обсуждаться ниже в
контексте индивидуальных тестов, что не требует от читателя понимания
или обращения к коду.
ИССЛЕДОВАНИЕ входов в РЫНОК
168 ЧАСТЬ II




РЕЗУЛЬТАТЫ ТЕСТОВ
Проводилось тестирование трех осцилляторных моделей входа: на осно-
ве понятия перекупленности/перепроданности (осцилляторы RSI и сто-
хастический), на основе взаимодействия осциллятора с сигнальной лини-
ей (стохастический осциллятор и MACD) и на основе расхождения (ста-
тистический осциллятор, RSI и MACD). Все индивидуальные комбинации
были исследованы с входами по цене открытия, по лимитному приказу и
по стоп-приказу. Сравнение результатов всех трех видов входов приве-
дено ниже в данной главе.
Табл. 7-1 и 7-2 содержат результаты каждого из 21 тестов. Данные рас-
пределены по торгуемым финансовым инструментам, по моделям, пока-
завшим прибыль и убыток в пределах выборки (табл. 7-1) и вне пределов
выборки (табл. 7-2). Первый столбец (SYM) — это символ рассматривае-
мого рынка, первая строка — номер теста. Степень прибыльности и убы-
точности рынков для каждой модели указана следующим образом: один
минус ( — ) означает убыток в $2000 — 4000, два минуса (- -) — убыток
более $4000; один плюс ( + ) означает прибыль $1000 — 2000, два плю-
са (++) — прибыль более $2000; пустая ячейка означает прибыль до $ 1000
или убыток до $1999 со сделки.


ТЕСТИРОВАНИЕ МОДЕЛЕЙ, ОСНОВАННЫХ НА ПОНЯТИИ
ПЕРЕКУПЛЕННОСТИ/ПЕРЕПРОДАННОСТИ
Входы генерировались, когда осциллятор пересекал верхний порог вниз
или нижний порог вверх. Эти модели являются противотрендовыми. Ког-
да осциллятор указывает на импульс цен, направленный вниз, произво-
дится покупка. В противоположном случае производится продажа. В тес-
тах от 1 до 6 использовались стохастический осциллятор и RSI, поскольку
для них существуют стандартные пороги, часто применяемые вышеопи-
санным способом.

<< Пред. стр.

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

ОГЛАВЛЕНИЕ

След. стр. >>