Во всех нижеследующих тестах использован стандартный портфель. Количество контрактов при покупке или продаже при входе на любом рынке в любое время подбиралось так, чтобы приблизительно соответствовать долларовой волатильности двух контрактов S&P 500 на конец 1998 г.
Использованы стандартные выходы. Все тесты проведены с использованием 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 = xlOmodOl.c
// parms — набор [1..MAXPRM] параметров
// dt — набор [l..nb] дат в формате ГГММДД
// орn — набор [l..nb] цен открытия
// hi — набор [1..nb] максимальных цен
// 1о — набор [1..nb] минимальных цен
// cls — набор [l..nb] цен закрытия
// vol — набор [l..nb] значений обьема
// oi — набор [1..nb] значений открытого интереса
/ / dlrv — набор [1..nb] значений среднего долларовой волатильности
/ / nb — количество дней в наборе данных
// ts — ссылка на класс торгового симулятора
// eqcls — набор [1..nb] уровней капитала при закрытых позициях
// объявляем локальные переменные
static int rc, cb, ncontracts, maxhold, fastmalen,slowmalen;
static int modeltype, ordertype, avgtype, signal;
static float mmstp, ptlim, stpprice, limprice, tmp;
static float exitatr[MAXBAR+1] ;
static float fastma[MAXBAR+1] , slowma[MAXBAR+1] ;
// копируем параметры в локальные переменные для более удобного обращения
fastmalen = parms[1]; // период для быстрой скользящей средней
slowmalen = parms[2]; // период для медленной скользящей средней
modeltype - parms[5]; // тип модели входа
avgtype = parms[6]; // тип скользящего среднего
ordertype = parms[7]; // тип входного приказа
maxhold = 10; // максимальный период удержания позиции
ptlim = 4; // целевая прибыль в единицах волатильности
mmstp = 1; // защитная остановка в единицах волатильности
// пропускать неверные комбинации параметров
if(fastmalen >= slowmalen) {
set_vector(eqcls, 1, nb, 0.0);
return;
}
// делаем вычисления по всему ряду данных, используя векторизацию
AvgTrueRangeS(exitatr, hi, lo, cls, 50, nb); // средний истинный
// диапазон для выхода
switch(avgtype) { // выбираем тип скользящей средней
case 1: // простые скользящие средние
Averages{fastma, cls, fastmalen, nb);
Averages(slowma, cls, slowmalen, nb);
break;
case 2: // экспоненциальные скользящие средние
XAverageS(fastma, cls, fastmalen, nb);
XAverageS(slowma, cls, slowmalen, nb);
break;
case 3: // треугольные скользящие средние с передним взвешиванием
FWTAverageS(fastma, cls, fastmalen, nb};
FWTAverageS(slowma, cls, slowmalen, nb);
break;
case 4: // VIDYA- адаптивные скользящие средние
VIAverageS(fastma, cls, fastmalen, 10, nb) ;
VIAverageS(slowma, cls, slowmalen, 10, nb) ;
break;
default: nrerror("Invalid moving average selected");
} ;
// проходим через дни, чтобы смоделировать реальную торговлю
for(cb =1; cb < = nb; cb++) {
//не входим в сделки до начала периода выборки
// ...так же, как установка MaxBarsBack в Trade Station
if (dt[cb] < IS_DATE} { eqcls [cb] = 0.0; continue;)
// выполняем все ожидающие приказы и подсчитываем капитал по закрытым
// сделкам
гс = ts.update (opn [cb] , hi [cb] , lo [cb] , cls [cb] , cb) ;
if (rc = 0) nrerror("Trade buffer overflow");
eqcls[cb] = ts.currentequity(EQ_C1OSETOTAL);
// подсчитываем количество контрактов для сделки
/ / ... мы хотим торговать эквивалентом долларовой волатильности
// ... 2 новых контрактов S&P- 500 от 12/31/98
ncontracts = RoundToInteger(5673.0 / dlrv[cb]);
if(ncontracts < 1) ncontracts = 1;
// избегаем установки приказов на день, когда остановлены торги
if (hi[cb+1] == lo [cb+1]) continue;
// генерировать входные сигналы, цены стоп- и лимитных приказов,
// используя модель входа определенной скользящей средней
#define CrossesAbove(a,b, с) {а[с]>=b[с] && a [c- 1]<b[c- 1])
#define CrossesBelow(a,b,c) {a[c]<b[c] && a [c- 1]>=b[c- 1])
#define TurnsUp(a,c) {a [c]>=a[c- l] && a [c- 1]<a[c- 2])
#define TurnsDn(a,c) {a[c]<a[c- l] && a [c- 1]>=a[c- 2] )
signal=0;
switch(modeltype) {
case 1: // классическая следующая за трендом модель, основанная на
// пересечении
if (CrossesAbove(fastma, slowma, cb)) signal = 1;
else if (CrossesBelow(fastma, slowma, cb)) signal = - 1;
limprice = 0.5 * (hi [cb] + lo [cb]);
stpprice = cls [cb] +0.5 * signal * exitatr[cb] ;
break;
case 2: // следующая за трендом модель, основанная на наклоне
if (TurnsUp(fastma, cb)) signal = 1;
else if(TurnsDn{fastma, cb)) signal = - 1;
limprice = 0.5 * (hi[cb] + lo [cb]};
stpprice = cls[cb] +0.5 * signal * exitatr[cb];
break;
case 3: // противотрендовая модель
if(CrossesAbove(fastma, slowma, cb)) signal = - 1 ;
else if(CrossesBelow(fastma, slowma, cb)) signal = 1;
limprice = 0.5* (hi[cb] + lo[cb]);
stpprice = cls[cb] + 0.5 * signal * exitatr[cb];
break;
case 4: // противотрендовая модель, основанная на поддержке
// и сопротивлении
if(slowma[cb] > slowma[cb- 1]
&& CrossesBelow(fastma, slowma, cb) ) signal = 1;
else if(slowma[cb] < slowma[cb- 1]
&& CrossesAbove(fastma, slowma, 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
#tundef TurnsDn
// входим в сделку, используя опеределенный тип приказа
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);
} // обрабатываем следующий день
}