Главная страница
Навигация по странице:

  • ПОЛУЧЕНИЕ ЦИКЛИЧЕСКИХ ТОРГОВЫХ СИГНАЛОВ ВХОДА С ИСПОЛЬЗОВАНИЕМ ГРУПП ФИЛЬТРОВ

  • ХАРАКТЕРИСТИКИ ЦИКЛИЧЕСКИХ ВХОДОВ

  • 240 ЧАСТЬ II

  • МЕТОДОЛОГИЯ ТЕСТИРОВАНИЯ

  • 242 ЧАСТЬ II

  • 244 ЧАСТЬ II

  • РЕЗУЛЬТАТЫ ТЕСТИРОВАНИЯ

  • 246 ЧАСТЬ II

  • Д.Катс.Д.Маккормик.Энциклопедия торговых стратегий. Донна л. Маккормик


    Скачать 5.96 Mb.
    НазваниеДонна л. Маккормик
    АнкорД.Катс.Д.Маккормик.Энциклопедия торговых стратегий.pdf
    Дата28.01.2017
    Размер5.96 Mb.
    Формат файлаpdf
    Имя файлаД.Катс.Д.Маккормик.Энциклопедия торговых стратегий.pdf
    ТипДокументы
    #727
    КатегорияЭкономика. Финансы
    страница26 из 41
    1   ...   22   23   24   25   26   27   28   29   ...   41
    ГЛАВА 10 Входы НА ОСНОВЕ циклов 239
    В дополнение к данным, представленным на графиках, были проведе- ны другие тесты с использованием «плазмод». Плазмодой называют набор данных, подобранных так, чтобы содержать предполагаемые в реальных данных характеристики. Идея состоит в проверке того, насколько алго- ритм или модель может обнаружить и проанализировать эти характерис- тики. Хорошая торговая система на основе циклов должна проявлять вы- сокую эффективность на синтетической серии данных, состоящей из боль- шого количества шума и изредка встроенных циклов. Фильтры, описан- ные в следующих тестах, работали в такой ситуации очень хорошо.
    ПОЛУЧЕНИЕ ЦИКЛИЧЕСКИХ ТОРГОВЫХ СИГНАЛОВ ВХОДА
    С ИСПОЛЬЗОВАНИЕМ ГРУПП ФИЛЬТРОВ
    Одним из способов получения сигналов входа является использование серии фильтров, настроенных на различные частоты или периоды, кото- рые целиком перекрывают весь диапазон анализируемых частот. Если в одном из этих фильтров возникает сильный резонанс при отсутствии ак- тивности в других, можно предположить наличие на рынке сильного цик- ла. На основе поведения выходов фильтров определяются ожидаемые моменты возникновения ценовых минимумов (сигнал к покупке) и мак- симумов (сигнал к продаже). Поскольку наиболее сильно реагирующий фильтр не должен вызывать запаздывания и фазовых сдвигов, при его должной работе и реально существующих циклах на рынке можно полу- чать чрезвычайно своевременные сигналы. Один из традиционных спо- собов использования циклов на рынке — это попытка продавать по цик- лическим максимумам и покупать по циклическим минимумам. Получае- мая от групп фильтров или других источников информация может также дополнять другие системы или адаптировать индикаторы к текущему со- стоянию рынка. Пример того, как метод обнаружения периода домини- рующего цикла и соотношения сигнал/шум включается в другую торго- вую систему, можно найти у Ружжиеро (Ruggiero, 1997).
    ХАРАКТЕРИСТИКИ ЦИКЛИЧЕСКИХ ВХОДОВ
    Исследуемые ниже циклические входы (нацеленные на продажу по мак- симуму и покупку по минимуму) имеют ряд важных характеристик: вы- сокий процент прибыльных сделок, низкое проскальзывание, способность захватывать максимально возможную часть каждого движения рынка —
    одним словом, мечта трейдера. Это справедливо только при условии, что на рынке действительно существуют предсказуемые циклы, которые мож- но обнаружить и, что еще важнее, экстраполировать имеющимися мето- дами. Считается, что на рынках примерно 70% времени присутствует цик-

    240 ЧАСТЬ II ИССЛЕДОВАНИЕ входов в РЫНОК
    лическая активность. Даже если четкие циклы, ведущие к выгодным сдел- кам, возникают гораздо реже, использование близких защитных остано- вок позволяет сводить к минимуму потери от неудачных сделок. Главный недостаток циклических входов состоит в том, что ввиду широкого рас- пространения весьма мощных алгоритмов анализа циклов, например ме- тода максимальной энтропии, рынки изменили свою природу и стали «ме- нее уязвимыми» для подобных методов. Предсказуемые циклы обнару- живаются и нивелируются настолько быстро, что их исследования зачас- тую теряют смысл. Поскольку описываемые циклические входы по при- роде своей направлены против циклов, то при отсутствии продолжения циклов (т.е. при продолжении тренда) трейдер понесет потери, если не будут применены эффективные методы управления капиталом (защит- ные остановки). Пригодность к реальной работе сложных методик анали- за циклов и будет рассмотрена в наших тестах.
    МЕТОДОЛОГИЯ ТЕСТИРОВАНИЯ
    Во всех тестах циклических моделей входа используется стандартный портфель из 36 рынков. Количество контрактов для покупки или прода- жи на каждом рынке подбиралось для соответствия долларовой волатиль- ности двух контрактов S&P 500 на конец 1998 г. Использован стандарт- ный выход: защитная остановка закрывает любую позицию, убытки ко- торой превышают одну единицу волатильности. Кроме того, лимитный приказ закрывает позиции, прибыль которых превышает четыре едини- цы волатильности, а рыночный приказ по цене закрытия закрывает пози- ции, не закрытые предыдущими выходами в течение 10 дней. Правила входов рассмотрены в обсуждении модели и индивидуальных тестов. Все тесты проведены при помощи стандартного C-Trader toolkit. Ниже при- веден код модели, основанный на волновом фильтре со стандартной стра- тегией выходов:
    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 = x14mod01.c
    // parms — набор [1..MAXPRM] параметров
    // dt - набор [l..nb] дат в формате ГГММДД
    // орn — набор [1..nb] цен открытия
    // hi — набор [1..nb] максимальных цен
    // 1о - набор [l..nb] минимальных цен
    //
    cls — набор [1..nb] цен закрытия
    // vol — набор [1..nb] значений объема
    // oi — набор [1..nb] значений открытого интереса
    // dlrv - набор [l..nb] средних долларовой волатильности
    / / nb — количество точек в наборе данных
    // ts - ссылка на класс торгового стимулятора

    ГЛАВА 10 Входы НА ОСНОВЕ циклов 241
    // eqcls - набор [l..nb] уровней капитала по ценам закрытия
    // объявляем локальные переменные static int rc, cb, ncontracts, maxhold, ordertype, signal;
    static int disp, k, modeltype, fcount, goodcycle, domperndx;
    static float mmstp, ptlim, stpprice, limprice, tmp;
    static float width, oldwidth, lper, sper, per, ratio;
    static float exitatr[MAXBAR+1], **inphase, **inquad, **power;
    static float peakpower, phase, peaknoise, domperiod;
    static float buyphase, sellphase, phaseb, oldphase, oldphaseb;
    static WAVFILT filter[20];
    // копируем параметры в локальные переменные для удобного обращения width = parms[l]; // ширина полосы пропускания фильтра (0.05 .. 0.20}
    disp= parms[2]; // временное смещение в градусах modeltype = parms[8]; // модель: 1=торговать развороты циклов ordertype = parms[9]; // вход: 1=на открытии, 2=по лимитному приказу,
    // 3=по стоп-приказу maxhold = 10; // период максимального удержания позиции ptlim = 4; // целевая прибыль в единицах волатильности mmstp = 1; // защитная остановка в единицах волатильности
    // Создаем искусственный набор цен закрытия в
    // форме синусоиды. Это «плазмода» для проведения тестов.
    // Модель должна хорошо торговать на данном наборе цен.
    // #define USESIMEWAVE
    #ifdef USESINEWAVE
    per = 3.0;
    ratio = exp (log (30.0/3.0) / (nb - 1));
    sper=0.0;
    for (cb = 1; cb <= nb; cb++) (
    sper += 2.0 * PI * (1.0 / per);
    cls[cb] = sin(sper);
    per *= ratio;
    }
    #endif
    // инициализируем группу равноотстоящих волновых фильтров
    // заново инициализируем, если параметр ширины полосы изменился if(width != oldwidth) {
    lper ==30.0; // фильтр длинных периодов sper = 3.О ; // фильтр коротких периодов fcount = 2 0 ; // число фильтров в группе ratio = exp (log (lper / sper) / (fcount - 1) ) ;
    per = sper;
    for(k = 1; k <= fcount; k++) (
    filter[k-1].build_kernel(per, width);
    per *= ratio;
    }
    oldwidth = width;
    }
    // рассчитываем выходы фильтров и откорректированный спектр мощности
    // если матрицы (таблицы) пустые, то присваиваем им значения if(inphase == NULL) inphase = matrix(l,fcount,1,MAXBAR);
    if(inquad == NULL) inquad = matrix(1,fcount,l.MAXBAR);
    if(power == NULL) power = matrix(1,fcount,1.MAXBAR);
    for(k = 1 ; k <= fcount; k++) {
    filter[k-1] .apply (cls, inphase[k] , inquad[k], nb);
    for(cb = 1; cb <= nb; cb++)
    power [k] [cb] = (inphase [k] [cb] * inphase [k] [cb] +
    inquad [k] [cb] * inquad [k] [cb] )
    / filter[k-1].period();

    242 ЧАСТЬ II ИССЛЕДОВАНИЕ входов в РЫНОК
    }
    // сохраняем спектральный анализ выборки в файл
    // эта процедура проводится для отладки
    // #define WRITESAMPLE
    #ifdef WRITESAMPLE
    FILE *fil = fopen("test.dat", "wt");
    for(cb = nb-1200; cb < nb; cb++) {
    domperndx = 0 ;
    peakpower = -1.0;
    for(k = 1; k <= fcount; k++) (
    if(power[k][cb] > peakpower) {
    peakpower = power[k] [cb] ;
    domperndx = k;
    }
    )
    phase = (180.0 / PI) * atan2 (inquad [domperndx] [cb] ,
    inphase[domperndx] [cb]);
    for(k = 1; k <= fcount; k++) (
    if (power [k] [cb] > 0.90 * peakpower)
    fprintf(fil, " **");
    else if (power[k][cb] > 0.75 * peakpower)
    fprintf(fil, " ++");
    else if (power[k][cb] > 0.5 * peakpower)
    fprintf(fil, " + ");
    else fprintf(fil, " ");
    )
    fprintf(fil, "%4d %7d %7d %7d %8.1f\n",
    (int)filter[domperndx-1].period(),
    (int)(inphase[domperndx] [cb]),
    (int)(inquad[domperndx] [cb]),
    (int)phase, cls [cb]);
    }
    fclose(fil);
    exit(0);
    #endif
    // используется для отладки сигналов
    // #define SIGNALDEBUG
    #ifdef SIGNALDEBUG
    FILE *fil = fopen("testsig.dat" , "wt");
    #endif
    // выполняем вычисления для всех данных
    AvgTrueRangeS(exitatr,hi,lo,cls,50,nb) ; // средний истинный диапазон для
    // выхода switch (modeltype) [
    case 1:
    // Ничего не делайте! Место для будущего кода,
    break ;
    default: nrerror ("Invalid model type");
    )
    // проходим через дни, чтобы смоделировать реальную торговлю for(cb = 1; cb <= nb; cb++) {
    // не открываем позиций до начала периода выборки
    // ... то же самое, что установка MaxBarsBack в TradeStation if(dt[cb] < IS_DATE) 1 egcls[cb] = 0.0; continue; )

    ГЛАВА 10 Входы НА ОСНОВЕ циклов 243
    // выполняем ожидающие приказы и сохраняем значение капитала rc = ts.update (opn [cb] , hi [cb] , lo [cb] , cls [cb] , cb) ;
    if(rc != 0) nrerror{"Trade buffer overflow");
    eqcls[cb] = ts.currentequity(EQ_CLOSETOTAL);
    / / н е торгуем в последние 30 дней выборки
    // оставляем место в массивах для будущих данных if(cb > nb-30) continue;
    // считаем количество контрактов для позиции
    // ... мы хотим торговать эквивалентом долларовой волатильности
    // ... 2 новых контрактов на S&P-500 от 12/31/98
    ncontracts = RoundToInteger(5673 . О / dlrv[cb] ) ;
    if (ncontracts < 1) ncontracts = 1;
    // избегаем устанавливать приказы на дни с ограниченной торговлей if(hi[cb+1] == lo[cb+1]} continue;
    // генерировать входные сигналы, цены стоп- и лимитных приказов signal = 0;
    switch (modeltype) {
    case 1:
    // ищем хороший цикл для торговли domperndx = 0;
    peakpower = -1.0;
    for(k = 1; k <= fcount; k++) {
    if(power[k][cb] > peakpower) {
    peakpower = power[k][cb];
    domperndx = k;
    }
    }
    goodcycle = FALSE;
    if(domperndx > 3 && domperndx < fcount-1) {
    peaknoise = 0.0;
    for(k = 1; k <= fcount; k++) {
    if (abs(k - domperndx) > 2) {
    if (power[k] [cb] > peaknoise)
    peaknoise - power[k] [cb] ;
    }
    }
    if(peakpower > 1.5 * peaknoise) goodcycle = TRUE;
    }
    // генерируем торговые сигналы if (goodcycle) {
    domperiod = filter [domperndx-1] .period() ;
    phase = (180.0 / PI) *
    atan2(inquad[domperndx] [cb],
    inphase[domperndx] [cb]);
    oldphase = (180.0 / PI) *
    atan2(inquad[domperndx] [cb-1],
    inphase[domperndx] [cb-1] );
    phaseb - (phase<0.0) ? (360.0+phase) : phase;
    oldphaseb = (oldphase<0.0)
    ? (360.0+oldphase) : oldphase;
    sellphase = 0.0 - (disp + 180.0 / domperiod);
    buyphase = 180.0 + sellphase;
    if (phaseb > buyphase && oldphaseb <- buyphase)
    signal = 1; // сигнал на покупку if (phase > sellphase && oldphase <= sellphase)
    signal = -1; // сигнал на продажу
    }
    break;

    244 ЧАСТЬ II ИССЛЕДОВАНИЕ входов в РЫНОК
    }
    limprice = 0.5 * (hi [cb] + lo [cb] ) ;
    stpprice = cls[cb] + 0.5 * signal * exitatr[cb];
    // печатаем отладочную информацию
    #ifdef SIGNALDEBUG
    fprintf(fil, "%8d %8.1f %8d %8d %8d %8d\n",
    cb, cls[cb], signal,
    (int)filter[domperndx-1].period(),
    (int)peakpower, {int)peaknoise);
    #endif
    // входим в сделку, используя определенный тип приказа if(ts.position() <= 0 && signal == 1) (
    switch(ordertype) { // выбираем нужный вид приказа case 1: ts.buyopen('1', ncontracts); break;
    case 2: ts.buylimit ('2', limprice, ncontracts); break;
    case 3: ts.buystop('3', stpprice, ncontracts); break;
    default: nrerror("Invalid buy order selected");
    }
    )
    else if (ts.position() >= 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('X', ptlim*tmp, mmstp*tmp, maxhold);
    } // обрабатываем следующий день
    // закрываем, если в режиме отладки
    #ifdef SIGNALDEBUG
    fclose(fil);
    exit(0);
    #endif
    }
    Вышеприведенный код описывает тестируемую модель. Первый важ- ный блок кода, принципиальный для циклической модели, инициализи- рует индивидуальные фильтры, составляющие группу фильтров. Этот код работает только при первом проходе или при изменении параметра, вли- яющего на инициализацию группы фильтров, например параметра width.
    Если важные параметры остаются без изменений, не имеет смысла пере- запускать фильтры при каждом вызове функции Model.
    Следующий блок применяет к входящему сигналу каждый из фильт- ров в составе группы. В этом блоке отведены два массива для хранения выходного сигнала группы фильтров. Первый массив хранит выход с со- впадающей фазой inphase, а второй — ортогональный выход inquad. Вход- ной сигнал представляет исходные цены закрытия. Поскольку фильтры математически оптимальны и рассчитаны на удаление трендов, предва-

    ГЛАВА 10 Входы НА ОСНОВЕ циклов 245
    рительная обработка данных становится излишней в отличие от менее продвинутых методик анализа. Каждая строка в массиве представляет собой выход отдельного фильтра с данной частотой или периодом, каж- дая колонка представляет собой торговый день. Центральные частоты или периоды фильтров расположены на равных расстояниях на логарифми- ческой шкале, т.е. соотношение между центральной частотой данного и следующего фильтра постоянно. Селективность полосы пропускания
    (width) — единственный настраиваемый параметр в расчете группы филь- тров, и это значение может подбираться путем оптимизации.
    Затем запускается обычный цикл перебора точек данных, и генери- руются собственно торговые сигналы. Сначала проверяется наличие чи- стого, пригодного для торговли цикла. Для этого определяется мощность при периоде, имеющем максимальный резонанс с текущей активностью рынка (peakpower). Также оценивается период, на котором наблюдается максимальная мощность. Если период не попадает на одно из крайних зна- чений рассматриваемого диапазона (диапазон составляет от 3 до 30 дней),
    то потенциально цикл может быть пригоден для торговли. Затем проверя- ется максимальная мощность на расстоянии не менее 2 полос пропуска- ния фильтра от периода пика (peaknoise). Если отношение peakpower/
    peaknoise составляет 1,5 или более, то выполняется второе условие при- годности цикла. На основе пары выходов определяется фазовый угол цик- ла. Затем код проверяет фазовый угол на соответствие максимуму или минимуму цены. Кроме того, в эту оценку вводится небольшое значение смещения (disp). Оно работает подобно смещению в предыдущих моде- лях, хотя здесь относится к фазовому углу, а не к количеству точек дан- ных. Между фазовым углом и количеством точек данных существует пря- мая зависимость: период цикла, умноженный на фазовый угол в градусах и разделенный затем на 360, дает количество точек данных, соответству- ющее фазовому углу. Если фаза после смещения такова, что через неко- торое количество градусов до или после текущего дня можно ожидать минимума, отдается приказ на покупку. Если фаза такова, что можно ожи- дать максимума, отдается приказ на продажу. Затем, как обычно, рассчи- тываются цены для лимитного и стоп-приказов. При поступлении сигна- лов система исполняет требуемые приказы.
    Другие блоки вышеприведенного кода здесь не обсуждаются, посколь- ку связаны с отладкой и тестированием программы. Их предназначение описано в комментариях к коду.
    РЕЗУЛЬТАТЫ ТЕСТИРОВАНИЯ
    Тестировалась только одна модель с входами по цене открытия (тест 1),
    по лимитному приказу (тест 2) и стоп-приказу (тест 3). Правила были про- стыми: покупать на предсказанных минимумах и продавать на предска-

    246 ЧАСТЬ II ИССЛЕДОВАНИЕ входов в РЫНОК
    занных максимумах. Выходы производились при поступлении сигнала к открытию противоположной позиции или при срабатывании стандарт- ного выхода. Эта простая торговая система сначала испытывалась на ис- кусственных ценовых данных, созданных путем добавления шума к иде- альной синусоиде с периодом от 4 до 20 дней. На этих данных были полу- чены сигналы покупки и продажи, идеально совпадающие с максимума- ми и минимумами. Такое совпадение показывает, что при наличии реаль- ных циклов система способна обнаруживать их с высокой точностью и использовать в торговле.
    В табл. 10-1 приведены лучшие показатели, полученные для данных,
    находящихся в пределах выборки, а также эффективность портфеля на данных в пределах и вне пределов выборки. В таблице: ВЫБ. — вид вы- борки данных (В — в пределах, ВНЕ — вне пределов выборки); ДОХ% —
    доходность в процентах годовых; Р/ПРИБ — соотношение риска/прибы- ли в годовом исчислении; ВЕР — ассоциированная вероятность статисти- ческой достоверности; СДЕЛ — число сделок на всех рынках в составе портфеля; ПРИБ% — процент прибыльных сделок; $СДЕЛ — средняя при- быль/убыток со сделки; ДНИ — средняя длительность сделки в днях;
    ПРИБДЛ — общая прибыль от длинных позиций в тысячах долларов;
    ПРИБКР — общая прибыль от коротких позиций в тысячах долларов. Оп- тимизировались два параметра. Первый (Р1) определяет ширину полосы пропускания для каждого фильтра в составе группы. Второй (Р2) отобра- жает фазовое смещение в градусах. Во всех случаях параметры прогоня- лись в пределах выборки для ширины полосы пропускания от 0,05 до 0,2 с шагом 0,05 и для фазового сдвига от —20 до +20° с шагом 10°. Показаны только оптимальные решения.
    Интересно отметить, что в общем циклическая модель имела доста- точно низкую эффективность. По показателю прибыли со сделки эта мо- дель превосходила многие рассмотренные ранее, но сильно уступала луч- шим из них. В пределах выборки убыток со сделки оставил $ 1329 при вхо- де по цене открытия, $1037 при входе по лимитному приказу и $1245 при входе по стоп-приказу. Вход по лимитному приказу обеспечил максималь- ный процент прибыльных сделок и минимальный средний убыток. Длин- ные позиции были слабо прибыльными при входе по цене открытия, бо- лее прибыльны при входе по лимитному приказу и убыточны при входе по стоп-приказу. Вне пределов выборки входы по лимитному приказу и цене открытия работали хуже, чем в пределах выборки. Средний убыток в сделке составил $3741 при входе по цене открытия и $3551 при входе по лимитному приказу. Доля прибыльных сделок также снизилась до 34%.
    Эффективность циклической модели вне пределов выборки была одной из худших среди всех моделей, что нельзя отнести на счет избыточной оптимизации: при других параметрах убытки были еще больше. При ис- пользовании входа по стоп-приказу эффективность вне пределов выбор- ки не ухудшалась, средний убыток ($944) в сделке был близок к убытку в

    1   ...   22   23   24   25   26   27   28   29   ...   41


    написать администратору сайта