В стратегии МССВ величины защитной остановки и целевой прибыли были фиксированы на достаточно произвольном и, возможно, неоптимальном уровне. Что произойдет, если протестировать ряд значений этих параметров в поисках оптимального сочетания?
В данном тесте положение защитной установки управления капиталом прогоняется от 0,5 до 3,5 с шагом 0,5. Целевая прибыль прогоняется от 0,5 до 5 с шагом 0,5. Под защитной остановкой и целевой прибылью понимается произведение указанного числа на средний истинный диапазон определенного количества последних торговых дней.
float *lo, float *cls, float *vol, float *oi, float *dlrv, int nb, TRDSIM &ts, float *eqcls) {
// Выполняет случайные входы с вариациями
// модифицированного стандартного выхода. Эта модель тестирует
// МСС, используя вариации в параметрах.
// File = x20mod01.c
// parms — набор [1..MAXPRM] параметров
// dt — набор [l..nb] дат в формате ГГММДД
// орn - набор [l..nb] цен открытия
// hi - набор [l..nb] максимальных цен
// 1о — набор [ 1..nb] минимальных цен
// cls - набор [l..nb] цен закрытия
// vol — набор [1..nb] значений объема
// oi — набор [1..nb] значений открытого интереса
// dlrv — набор [1..nb] средних долларовой волатильности
// nb — количество дней в наборе данных
// ts — ссылка на класс торгового симулятора
// eqcls - набор [l..nb] уровней капитала по ценам закрытия
// объявляем локальные переменные
static int rc, cb, neontracts, maxhold, signal, ranseed;
static float mmstp, ptlim, lirnprice, stpprice;
static int entryposted, entrybar;
static float exitatr[MAXBAR+1] , rnum, entryprice;
static long iseed;
// копируем параметры в локальные переменные для удобного обращения
ptlim = parms[1]; // целевая прибыль в единицах среднего истинного
// диапазона
mmstp = parms[2]; // защитная остановка в единицах среднего истинного
// диапазона
maxhold = parms[3]; // период максимального удержания позиции
ranseed = parms[8]; // используется для инициализации случайной
// последовательности
// выполняем вычисления по всему объему данных
AvgTrueRangeS(exitatr,hi,lo,cls,50,nb); // средний истинный диапазон для
// выхода
// очищаем генератор случайных чисел
// ... используем различную случайную последовательность для каждого
//инструмента
// ... 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.currentequity(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;
rnurn = ran2(&iseed) ;
if(rnum < 0.025) signal = - 1; // случайный короткий вход
else if (rnum > 0.975) 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
}
// выходим из сделок, используя модифицированный стандартный выход
if(entryposted > 0) {
// инициализация и выходы для длинных позиций в день входа
limprice = entryprice + ptlim * exitatr[cb];
stpprice = entryprice - mmstp * exitatr[cb];
ts.exitlonglimit{'A' , limprice);
ts.exitlongstop('B', stpprice);
}
else if(entryposted < 0) {
// инициализация и выходы для коротких позиций в день входа
limprice = entryprice - ptlim * exitatr[cb];
stpprice = entryprice + mmstp * exitatr[cb];
ts.exitshortlimit('С' , limprice);
ts.exitshortstop('D' , stpprice);
}
else {
// выходы после дня входа
if (ts- position{) > 0) { // длинные позиции
ts.exitlonglimit('F' , limprice);
ts.exitlongstop('G', stpprice);
if(cb- entrybar >= maxhold) ts.exitlongclose('E');
}
else if(ts.position() < 0) ( // короткие позиции
ts.exitshortlimit('I' , limprice);
ts.exitshortstop('J' , stpprice);
if(cb- entrybar >= maxhold) ts.exitshortclose('H') ;
}
}
} // обрабатываем следующий день
)