d9e5a92d

Методология тестирования генетического компонента выходов

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

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 = x21mod01.c
// parms - набор [1..MAXPRM] параметров
// dt - набор [1..nb] дат в формате ГГММДД
// орn - набор [ 1..nb] цен открытия
// hi - набор [1..nb] максимальных цен
// lo - набор [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, signal, ranseed;
static float iranstp, ptlim, limprice, stpprice, entryprice;
static int entryposted, entrybar, exitsignal, modeltype;
static int rulel[MAXBAR+1], rule2[MAXBAR+1], rule3[MAXBAR+1];
static float exitatr[MAXBAR+1], rnum, thresh;
static long iseed;
// копируем параметры в локальные переменные для удобного обращения
ranseed = parms[14]; // используется для инициализации случайной
// последовательности
modeltype = parms[15]; // 1=длинные позиции, 2=короткие позиции
maxhold = 10; // период максимального удержания позиции


ptlim =4.5; // целевая прибыль в единицах среднего истинного диапазона
mmstp = 1.5; // защитная остановка в единицах среднего истинного диапазона
// выполняем вычисления по всему объему данных, включая правила
AvgTrueRangeS{exitatr,hi,lo,cls,50,nb); // средний истинный диапазон для
/ / выхода
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);
// запускаем генератор случайных чисел
// ... используем различные случайные последовательности для каждого рынка
// ... ts.model() возвращает индекс рынка (SP=1, YX=2, ...)
iseed = - (ranseed + 10 * ts.model());
rnum = ran2(&iseed);
// проходим через дни, чтобы смоделировать реальную торговлю
for(cb = 1; cb <= nb; cb++) (
// не открываем позиций до начала периода выборки
// ... то же самое, что установка MaxBarsBack в TradeStation
if(dt[cb] < IS_DATE) ( eqcls[cb] = 0.0; continue; ]
// выполняем ожидающие приказы и считаем кумулятивный капитал
rc = ts.update(opn[cb], hi[cb], lo[cb], cls[cb),cb);
if(rc != 0) nrerror("Trade buffer overflow");
eqcls[cb] = ts.currenteguity(EQ_CLOSETOTAL);
// считаем количество контрактов для позиции
// ... мы хотим торговать эквивалентом долларовой волатильности
// ... 2 новых контрактов на S&P- 500 от 12/31/98
ncontracts = RoundToInteger(5673.0 / dlrv[cb]);
if(ncontracts < 1) ncontracts = 1;
// избегаем устанавливать приказы на дни с ограниченной торговлей
if(hi[cb+l] == lo[cb+l]) continue;
// генерируем "стандартные" случайные сигналы входа
signal = 0;
rnum = ran2 (Stiseed) ;
if (rnum < 0.025 &&
modeltype == 2) signal = - 1; // случайный короткий вход
else if (rnum > 0.975 &&
modeltype == 1) signal = 1; // случайный длинный вход
// входим в сделки по цене открытия
entryposted = 0;
if(ts.position() <= 0 && signal == 1) (
ts.buyopen('1', ncontracts);
entryposted = 1;
entryprice = opn[cb+l];
entrybar = cb + 1;
}
else if(ts.position() >= 0 && signal == - 1) {
ts.sellopen('2', ncontracts);
entryposted = - 1;
entryprice = opn[cb+l] ;
entrybar = cb + 1;
}



// выходим из сделок, используя модифицированный стандартный выход
// вместе с нейросетевым выходом
exitsignal = rulel[cb] && rule2[cb] && rule3[cb];
if(entryposted > 0} {
// инициализация и выходы для длинных позиций в день входа
limprice = entryprice + ptlim * exitatr[cb];
stpprice = entryprice - mmstp * exitatr[cb];
ts.exitlonglimit{'A' , limprice);
ts.exitlongstop('B', stpprice);
if(exitsignal) ts.exitlongclose('C') ;
}
else if{entryposted < 0) {
// инициализация и выходы для коротких позиций в день входа
limprice = entryprice - ptlim * exitatr[cb];
stpprice = entryprice + mmstp * exitatr[cb) ,•
ts.exitshortlimit('D', limprice);
ts.exitshortstop('E' , stpprice);
if(exitsignal) ts.exitshortclose('F') ;
}
else (
// выходы после дня входа
if(ts.position()> 0) [ // длинные позиции
ts.exitlonglimit('G' , limprice) ;
ts.exitlongstop('H', stpprice);
if(cb- entrybar >= maxhold)
exitsignal) ts.exitlongclose('I') ;
}
else if(ts.position() < 0) [ // короткие позиции
ts.exitshortlimit('J' , limprice);
ts.exitshortstop('K' , stpprice);
if(cb- entrybar >= maxhold
exitsignal) ts.exitshortclose('L');
}
)
} // обрабатываем следующий день
}

Вышеприведенный код демонстрирует логику как входов, так и выходов. Параметр modeltype управляет выбором длинных или коротких позиций для тестирования. Параметры ptlim и mmstp задают соответственно целевую прибыль и защитную остановку; они фиксированы на тех же уровнях, что и в предыдущем тесте нейронной сети. Каждое из трех правил рассчитывается как серия значений ИСТИНА/ЛОЖЬ, и если все три принимают значение ИСТИНА, то подается сигнал на выход exitsig. В текст программы добавлен оператор if, который подает сигнал на выход по цене закрытия, если (if) все три правила дают значение ИСТИНА (exitsig = ИСТИНА). Эволюция правил для длинных и коротких позиций проводилась аналогично эволюции правил для входов, описанной в гл. 12. Использовались 12 хромосом с тремя генами- правилами каждая. Для получения правил выхода из длинных и коротких позиций проводится эволюция 2500 поколений с использованием OptEvolve. Затем для тестирования в пределах и вне пределов выборки отбирались по 10 лучших длинных и коротких решений.


Содержание раздела