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..nЬ] минимальных цен
// cls — набор [l..nb] цен закрытия
// vol - набор [l..nb] значений обьема
// oi — набор [l..nb] значений открытого интереса
// dlrv — набор [l..nb] средних долларовой волатильности
// nb — количество дней в наборе данных
// ts — ссылка на класс торгового симулятора
// eqcls — набор [l..nb] уровней капитала при закрытых позициях
// объявляем локальные переменные
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еnЗ = parms[3]; // длина теста дивергенции
modeltype = parms[7]; // тип осцилляторной модели входа
osctype - parms[8]; // тип осциллятора
ordertype = parms[9]; // тип входного приказа
maxhold =10; // период максимального удержания позиции
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
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]#define CrossesBelow(a,b, с) (a[c]=b [с-1] )
#define TurnsUp(a,c) (а[с]>=а[с-1] && а[с-1]<а[с-2])
#define TurnsDn(a,c) (a[c]=а [с-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;
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 — по стоп-приказу. Затем симулятор использует стандартную модель выхода для закрытия сделок.
Точные логические основания для входа будут обсуждаться ниже в контексте индивидуальных тестов, что не требует от читателя понимания или обращения к коду.
Далее
Вернуться к оглавлению
|