Автор |
Сообщение |
pongo
Зарегистрирован: 01.09.2009
Сообщения: 19
|
Есть некая стратегия, по которой был написан алгоритм:
Код: |
1. Робот работает с 10:55 до 23:40
2. Если последняя свеча белая и предыдущая свеча белая, то заходим в лонг и ставим стоп 600 пунктов.
2.1. Если закрытие следующей свечи больше закрытия предыдущей, то переставляем стоп по закрытию этой свечи минус 2100 пунктов. Переставляем стоп когда закрытие свечи будет больше, чем последнее максимальное закрытие.
2.2. Если срывает стоп, возвращаемся на пункт 1
3. Если последняя свеча черная и предыдущая свеча черная, то заходим в шорт и ставим стоп 600 пунктов.
3.1. Если закрытие следующей свечи меньше предыдущей, то переставляем стоп по закрытию этой свечи плюс 2100 пунктов. Переставляем стоп, когда закрытие свечи, будет меньше, чем последнее минимальное закрытие.
3.2. Если срывает стоп, возвращаемся на пункт 1
|
По алгоритму составлен хитрый код:
Код: |
OptimizerSetEngine("trib");
_TRACE("!CLEAR!");
InitialEquity = 59000; InitialEquity = 220000; InitialEquity = 25000;
SetOption("InitialEquity", InitialEquity);
SetPositionSize(1, 4);
start_time = 105500;
end_time = 234000;
stop1 = 600;
stop2 = 2100;
/////////////////////////////////////////////////////////////////////////////////////////
// инициализируем переменые для работы
time = TimeNum();
white = IIf(O-C==0, 1, O < C);
black = IIf(O-C==0, 1, O > C);
size = abs(C - O);
pos = 0; // pos = 1 - лонг, pos = -1 - шорт
stop = 0;
price = 0; // цена входа
maxc = 0; // максимальное закрытие
minc = 0;
todayprofit = 0; // сегодняший доход на 1 контракт
/////////////////////////////////////////////////////////////////////////////////////////
// главный цикл
for (i = 1; i < BarCount; i++) {
// обнуляем переменные в начале нового дня
if (time[i] == 103000) {
pos = 0;
stop = 0;
price = 0;
maxc = 0;
minc = 0;
todayprofit = 0;
}
Buy[i] = Short[i] = Sell[i] = Cover[i] = False;
// правило 1
if (time[i] >= start_time AND time[i] < end_time) {
// long
if (pos == 1 OR pos == 0) {
if (pos == 0) {
// правило 2
if (white[i] AND white[i-1]) {
Buy[i] = True;
price = C[i];
pos = 1;
stop = price - stop1;
maxc = price;
}
}
else if (pos == 1) {
// правило 2.2
if (L[i] <= stop) {
prof = stop - price;
Sell[i] = IIf(prof >= 0, 3, 2);
SellPrice[i] = stop;
todayprofit = todayprofit + prof;
pos = 0;
stop = 0;
maxc = 0;
price = 0;
}
// правило 2.1
else if (C[i] > C[i-1] AND C[i] > maxc) {
stop = C[i] - stop2;
maxc = C[i];
}
}
}
// short
if (pos == -1 OR pos == 0) {
if (pos == 0) {
// правило 3
if (black[i] AND black[i-1]) {
Short[i] = True;
price = C[i];
pos = -1;
stop = price + stop1;
minc = price;
}
}
else if (pos == -1) {
// правило 3.2
if (H[i] >= stop) {
prof = price - stop;
Cover[i] = IIf(prof >= 0, 3, 2);
CoverPrice[i] = stop;
todayprofit = todayprofit + prof;
pos = 0;
stop = 0;
minc = 0;
price = 0;
}
// правило 3.1
else if (C[i] < C[i-1] AND C[i] < minc) {
stop = C[i] + stop2;
minc = C[i];
}
}
}
}
if (time[i] == end_time) {
if (pos == 1) { Sell[i] = 1; }
if (pos == -1) { Cover[i] = 1; }
pos = 0;
}
} |
Все хорошо, но с пунктами 2.2 и 3.2 ошибка вышла. Получается, что робот может зайти на той же свечке, на которой у него стоп сорвало. И если после лонга он легко входит в шорт (потому что после проверки стопа идет проверка на вход в шорт), то вот после шорта в лонг войти не удавалось никак.
Ну, в принципе, можно просто после проверки шорта добавить еще одну проверку лонга, но хочется сделать все без грязных трюков и дублирования кода. Т.е. нужно еще раз проверить эту свечку.
Было решено поменять цикл с for на while, в конце цикла делать i++, а после стопов делать continue. Так мы будем еще раз проверять текущую свечку. Пишется такой код:
Код: |
OptimizerSetEngine("trib");
_TRACE("!CLEAR!");
InitialEquity = 59000; InitialEquity = 220000; InitialEquity = 25000;
SetOption("InitialEquity", InitialEquity);
SetPositionSize(1, 4);
start_time = 105500;
end_time = 234000;
stop1 = Optimize("stop1", 600, 100, 4000, 100);
stop2 = Optimize("stop2", 2100, 100, 4000, 100);
/////////////////////////////////////////////////////////////////////////////////////////
// инициализируем переменые для работы
time = TimeNum();
white = IIf(O-C==0, 1, O < C);
black = IIf(O-C==0, 1, O > C);
size = abs(C - O);
pos = 0; // pos = 1 - лонг, pos = -1 - шорт
stop = 0;
price = 0; // цена входа
maxc = 0; // максимальное закрытие
minc = 0;
todayprofit = 0; // сегодняший доход на 1 контракт
/////////////////////////////////////////////////////////////////////////////////////////
// главный цикл
i = 1;
while(i < BarCount) {
// обнуляем переменные в начале нового дня
if (time[i] == 103000) {
pos = 0;
stop = 0;
price = 0;
maxc = 0;
minc = 0;
todayprofit = 0;
}
Buy[i] = Short[i] = Sell[i] = Cover[i] = False;
if (time[i] >= start_time AND time[i] < end_time) {
// long
if (pos == 1 OR pos == 0) {
if (pos == 0) {
if (white[i] AND white[i-1]) {
Buy[i] = True;
price = C[i];
pos = 1;
stop = price - stop1;
maxc = price;
}
}
else if (pos == 1) {
if (L[i] <= stop) {
prof = stop - price;
Sell[i] = IIf(prof >= 0, 3, 2);
SellPrice[i] = stop;
todayprofit = todayprofit + prof;
pos = 0;
stop = 0;
maxc = 0;
price = 0;
continue;
}
else if (C[i] > C[i-1] AND C[i] > maxc) {
stop = C[i] - stop2;
maxc = C[i];
}
}
}
// short
if (pos == -1 OR pos == 0) {
if (pos == 0) {
if (black[i] AND black[i-1]) {
Short[i] = True;
price = C[i];
pos = -1;
stop = price + stop1;
minc = price;
}
}
else if (pos == -1) {
if (H[i] >= stop) {
prof = price - stop;
Cover[i] = IIf(prof >= 0, 3, 2);
CoverPrice[i] = stop;
todayprofit = todayprofit + prof;
pos = 0;
stop = 0;
minc = 0;
price = 0;
continue;
}
else if (C[i] < C[i-1] AND C[i] < minc) {
stop = C[i] + stop2;
minc = C[i];
}
}
}
}
if (time[i] == end_time) {
if (pos == 1) { Sell[i] = 1; }
if (pos == -1) { Cover[i] = 1; }
pos = 0;
}
i++;
} |
И оказывается, что он неправильно работает. Теперь он всегда заходит в 11:00 или 10:55, а выходит в 23:40. Так не должно быть. Видимо сигналы на выход почему-то не срабатывают. И не понятно что делать.
(Версия ами 5.26 бета) |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Вот как надо писать алгоритм и код! Всем учится. Читать приятно.
По вопросу. Во втором коде.
1. Не понятно зачем поменялся способ задания цикла. В данном случае работает абсолютно идентично. continue можно использовать и в цикле залаваемом For
2. в цикле вот эту запись IIf(prof >= 0, 3, 2); использовать в данном случае нельзя. Оператор IIf работает с массивами. Пиши
Код: |
if(prof >= 0)
Cover[i] = 3;
else
Cover[i] = 2;
|
Все остальное там вроде правильно.
Вот еще что. Второй код у тебя не проверяет возможность входа на баре где был выход а наоборот блокирует вход на баре выхода. |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Упс. Сори. Да. На счет цикла while и i++ в конце я погорячился. Действительно так еще раз проверяет ту же свечку и будет входить на баре выхода.
Это не тоже что for... |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Во. Еще. Вот смотри. Сработал у тебя на баре i стоп и появилась запись Sell[i] = 1;
Потом этот бар прогоняется еще раз в цикле, а там в начале
Buy[i] = Short[i] = Sell[i] = Cover[i] = False;
Соответственно сигнал выхода обнуляется.
Вот это основной косяк и есть. |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
pongo
Зарегистрирован: 01.09.2009
Сообщения: 19
|
Спасибо за комплимент :)
1. По поводу IIF. А какая разница? В справке я не нашел никаких запретов, и, тем более, IIF в этом коде отлично работает. И с производительностью разницы никакой.
2. "Buy[i] = Short[i] = Sell[i] = Cover[i] = False; "
Блин! И ведь вправду! Бывает же такое, что ошибка прямо под носом. А я думал, что ами бажит :)
Большое спасибо. Ты мой спаситель :). |
Последний раз редактировалось: pongo (Сб Янв 30, 2010 12:34 am), всего редактировалось 1 раз |
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Цитата: |
1. По поводу IIF. А какая разница? В справке я не нашел никаких запретов, и, тем более, IIF в этом коде отлично работает. И с производительностью разницы никакой.
|
Ну там есть нюансы.
IIF возвращает массив. А ты его присваиваешь элементу массива. Ну не правильно это. В общем тебя спасло то, что весь присваиваемый массив равен 2 или 3. Он практически константа.
В общем там не очень понятно.
Я стараюсь так не делать. |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
pongo
Зарегистрирован: 01.09.2009
Сообщения: 19
|
А, вот в чем дело. Хм. Вроде как если самому писать функции, то возвращать тоже можно только массивы. Наверное это все как-то связано. АФЛ же завязан на массивах.
Тогда тоже буду использовать IIF только с массивами. |
|
|
Посмотреть профиль Отправить личное сообщение |
|
Gluhov
Зарегистрирован: 06.02.2009
Сообщения: 44
|
вопрос автору.
А что за библиотека используется для оптимизации? Она в открытом доступе или собственное творение? |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
Я не автор правда.
Какая библиотека? Стандартный оптимизатор Ами... |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
pongo
Зарегистрирован: 01.09.2009
Сообщения: 19
|
Gluhov писал(а): |
вопрос автору.
А что за библиотека используется для оптимизации? Она в открытом доступе или собственное творение? |
Посмотрите в справке OptimizerSetEngine. Это стандартная штука.
spso и trib — это алгоритмы генетической модификации, работают гораздо быстрее, чем стандартный перебор. Особенно когда много параметров.
cmae — я не очень понял, что это. |
|
|
Посмотреть профиль Отправить личное сообщение |
|
Gluhov
Зарегистрирован: 06.02.2009
Сообщения: 44
|
у меня под 5.10 это строчка OptimizerSetEngine возвразает ошибку.
Нужна более новая версия? |
|
|
Посмотреть профиль Отправить личное сообщение |
|
pongo
Зарегистрирован: 01.09.2009
Сообщения: 19
|
|
Посмотреть профиль Отправить личное сообщение |
|
|