Автор |
Сообщение |
unwar
Зарегистрирован: 22.11.2009
Сообщения: 10
|
Вкратце: пытаюсь перевести парную систему с кода R в AFL. Первая проблема была с вычислением параметров множественной регресии, но судя по теме штатных средств Ами не хватит для этого, в этом случае планирую подгружать результат вычислений из R в виде нового символа в Ами. Перерыл весь форум казалось бы, но простые примеры из парного трейдинга не подходят для задания правил открытия и переворота позиций по паре инструментов. Суть в том что в рассматриваемой системе, лишь сайз одной из бумаг постоянный, а сайз второй пересчитывается на каждом новом сигнале в соответствии с актуальной бетой. Кроме того при поступлении противоположного сигнала получается нужно производить переворот позиции первой бумаги двойным сайзом, а второй бумаги сайзом равным сумме размера ранее открытой позиции и размера вновь расчитанного открываемой позиции. В режиме исследования все вроде бы нормально, сигналы появляются верно, а вот с бэктестом беда, сделки происходят на каждом баре, что-то не так видимо с циклом:
Код: |
z = y / x; // массив соотношений цен
prev_x_qty[0] = 0;
position[0] = 0;
qty_x[0] = 0;
qty_y[0] = 0;
for( i = 1; i < BarCount; i++ )
{
if(buys[i]== 1 AND position[i] == 0 AND sells[i]== 0){
// инициализация покупки спреда
prev_x_qty = round(beta[i] * z[i] * trade_sizeY);
qty_x[i] = -prev_x_qty;
qty_y[i] = trade_sizeY;
position = 1;
if(Name() == "SBRF"){
SetPositionSize(qty_y[i], spsShares);
Buy = buys[i];
}
if(Name() == "VTBR"){
SetPositionSize(-qty_x[i], spsShares);
Short = Signals[i];
}
}
if(sells[i]== 1 AND position[i] == 0 AND buys[i]== 0){
// инициализация продажи спреда
prev_x_qty = round(beta[i] * z[i] * trade_sizeY);
qty_x[i] = prev_x_qty;
qty_y[i] = -trade_sizeY;
position = -1;
if(Name() == "SBRF"){
SetPositionSize(-qty_y[i], spsShares);
Short = sells[i];
}
if(Name() == "VTBR"){
SetPositionSize(qty_x[i], spsShares);
Buy = Signals[i];
}
}
if(buys[i]== 1 AND position[i] == -1 AND sells[i]== 0){
// уже открыт шорт спреда и нужно перевернуться в покупку скорректированным объемом
qty_x[i] = -(round(beta[i] * z[i] * trade_sizeY) + prev_x_qty);
prev_x_qty = round(beta[i] * z[i] * trade_sizeY);
qty_y[i] = 2 * trade_sizeY;
position = 1;
if(Name() == "SBRF"){
SetPositionSize(qty_y[i], spsShares);
Buy = buys[i];
Cover = buys[i];
}
if(Name() == "VTBR"){
SetPositionSize(-qty_x[i], spsShares);
Short = Signals[i];
Sell = Signals[i];
}
}
if(sells[i]== 1 AND position[i] == 1 AND buys[i]== 0){
// уже открыт лонг спреда и нужно перевернуться в шорт скорректированным объемом
qty_x[i] = (round(beta[i] * z[i] * trade_sizeY) + prev_x_qty);
prev_x_qty = round(beta[i] * z[i] * trade_sizeY);
qty_y[i] = -2 * trade_sizeY;
position = -1;
if(Name() == "SBRF"){
SetPositionSize(-qty_y[i], spsShares);
Short = sells[i];
Sell = sells[i];
}
if(Name() == "VTBR"){
SetPositionSize(qty_x[i], spsShares);
Buy = Signals[i];
Cover = Signals[i];
}
}
} |
|
Последний раз редактировалось: unwar (Чт Окт 15, 2015 12:03 pm), всего редактировалось 1 раз |
|
Посмотреть профиль Отправить личное сообщение |
|
yser
Зарегистрирован: 30.11.2011
Сообщения: 76
|
просто бросилось в глаза - в цикле для Buy, Sell, Short, Cover тоже нужно указывать индекс.
вместо Buy = buys[i];
нужно Buy[i] = buys[i];
и так далее по коду для Buy, Sell, Short, Cover.
Buy = buys[i]; - всему массиву сигналов Buy присваивается единственное значение из buys[i] (другими словами - на каждом баре будет покупка) |
|
|
Посмотреть профиль Отправить личное сообщение |
|
unwar
Зарегистрирован: 22.11.2009
Сообщения: 10
|
2yser
Спасибо за идею, правда так тоже не получается, выходит вот такое при бэктесте (ниже прикрепил картинку)
тоже сделки на каждом баре, почему-то только лонги, к тому же видно что есть непарные сделки. Почему происходят непарные , я так и не выловил причину, когда тестил без всяких циклов и без подробного расчета размера входов[/img] |
|
|
Посмотреть профиль Отправить личное сообщение |
|
spitfire
Зарегистрирован: 29.04.2010
Сообщения: 729
Откуда: Moscow
|
Ну замечание про Buy/sell/short/cover верное.
Еще мне так кажется, что тут просто логика неверная. На примере этого if'a
if(sells[i]== 1 AND position[i] == 1 AND buys[i]== 0){
.......
position = -1;// вы изменили переменную position, и при прогоне след символа в этот if мы уже не попадем, то есть это сработает единожды для сбера или втб - чтобы было первее
if(Name() == "SBRF"){
......
}
if(Name() == "VTBR"){
......
}
}
В целях траблшутинга постройте значение position на графике. Для этого ее иницилизируйте через индекс, а не как сейчас, и в начале каждого цикла пишите position[i] = position[i-1] для сохранения значения. |
|
|
Посмотреть профиль Отправить личное сообщение ICQ Number |
|
unwar
Зарегистрирован: 22.11.2009
Сообщения: 10
|
spitfire писал(а): |
Ну замечание про Buy/sell/short/cover верное.
Еще мне так кажется, что тут просто логика неверная. На примере этого if'a
if(sells[i]== 1 AND position[i] == 1 AND buys[i]== 0){
.......
position = -1;// вы изменили переменную position, и при прогоне след символа в этот if мы уже не попадем, то есть это сработает единожды для сбера или втб - чтобы было первее
if(Name() == "SBRF"){
......
}
if(Name() == "VTBR"){
......
}
}
В целях траблшутинга постройте значение position на графике. Для этого ее иницилизируйте через индекс, а не как сейчас, и в начале каждого цикла пишите position[i] = position[i-1] для сохранения значения. |
Спасибо за участие, да замечание было верным, видимо остались еще ошибки. Сделал как вы посоветовали, вывел position на график, правда не совсем понял, что вы имели ввиду под "иницилизируйте через индекс", сделал вот так:
Код: |
for( i = 1; i < BarCount; i++ )
{
position[i] = position[i-1];
if(buys[i]== 1 AND position[i-1] == 0 AND sells[i]== 0){
// инициализация покупки спреда
prev_x_qty[i] = round(beta[i] * z[i] * trade_sizeY);
qty_x[i] = -prev_x_qty[i];
qty_y[i] = trade_sizeY;
position[i] = 1;
if(Name() == "SBRF"){
SetPositionSize(qty_y[i], spsShares);
Buy[i] = buys[i];
}
if(Name() == "VTBR"){
SetPositionSize(-qty_x[i], spsShares);
Short[i] = Signals[i];
}
}
if(sells[i]== 1 AND position[i-1] == 0 AND buys[i]== 0){
// инициализация продажи спреда
// и так далее |
в прикрепленных скринах, то что получилось. Position на графике выглядит верно, если сравнивать с сигналами пересечения спреда и порогов, расположенных ниже. Вот только сделки по ВТБ вобще куда-то пропали. Похоже где-то ошибка в блоке исполнения сделок. Может конструкцию
Код: |
if(Name() == "SBRF"){
SetPositionSize(qty_y[i], spsShares);
// условие сделки }
if(Name() == "VTBR"){
SetPositionSize(-qty_x[i], spsShares);
// условие сделки }
|
вообще вынести в отдельный цикл? как думаете? |
|
|
Посмотреть профиль Отправить личное сообщение |
|
yser
Зарегистрирован: 30.11.2011
Сообщения: 76
|
вобщем у тебя ошибка использования функции SetPositionSize, с помощью нее задается масcив значений (т.е. на каком баре сколько бумаг), а у тебя получается каждым вызовом ты меняеш кол-во на всех барах.
нужно внутри цикла убрать все вызовы SetPositionSize, а после завершения цикла добавить:
Код: |
if(Name() == "SBRF"){
SetPositionSize(abs(qty_y), spsShares);
}
if(Name() == "VTBR"){
SetPositionSize(abs(qty_x), spsShares);
} |
поправил твой код и потестировал - вроде работает так как было задумано тобой.
прикрепил код и то что получается в результате. |
|
|
Посмотреть профиль Отправить личное сообщение |
|
unwar
Зарегистрирован: 22.11.2009
Сообщения: 10
|
yser писал(а): |
вобщем у тебя ошибка использования функции SetPositionSize, с помощью нее задается масcив значений (т.е. на каком баре сколько бумаг), а у тебя получается каждым вызовом ты меняеш кол-во на всех барах.
нужно внутри цикла убрать все вызовы SetPositionSize, а после завершения цикла добавить:
поправил твой код и потестировал - вроде работает так как было задумано тобой.
прикрепил код и то что получается в результате. |
О, благодарствую! хорошо что есть такой форум где можно обратиться за советом к более продвинутым товарищам )) я хоть и давно здесь зареган, но все еще на уровня любителя по AFL, тяжело даются циклы и сложные конструкции.
Что по коду, попробовал, вроде ошибка устранена. Но такой же как у тебя результат почему-то не получился на том же отрезке времени, либо окно расчета порога у тебя уже было оптимизировано, либо настройки тестера так сильно отличаются, не знаю. Результаты ниже.
з.ы. кстати, были небольшие проблемы с твоей фунцией по загрузке файла, Ами версии 5,6 оказалось ругается на строчки
Код: |
{
string = fgets( fh );
read_bar = StrToDateTime(StrExtract(string, 0, ';')); |
к фрагменту ';' выходила ошибка: Error 32. Syntax error, probably missing semicolon at the end of the previous line .
Попробовал на триальной новой версии, там все ок с функцией. Интересно реально ли это вылечить на старой версии? |
|
|
Посмотреть профиль Отправить личное сообщение |
|
000
Site Admin
Зарегистрирован: 10.12.2007
Сообщения: 9106
|
В старых версиях в функции StrExtract() разделитель нельзя задавать. Всегда используется ",". Надо предварительно заменить в строке ";" на "," при помощи функции StrReplace() |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
yser
Зарегистрирован: 30.11.2011
Сообщения: 76
|
unwar писал(а): |
з.ы. кстати, были небольшие проблемы с твоей фунцией по загрузке файла, Ами версии 5,6 оказалось ругается на строчки
Код: |
{
string = fgets( fh );
read_bar = StrToDateTime(StrExtract(string, 0, ';')); |
к фрагменту ';' выходила ошибка: Error 32. Syntax error, probably missing semicolon at the end of the previous line .
Попробовал на триальной новой версии, там все ок с функцией. Интересно реально ли это вылечить на старой версии? |
либо как отправил файлик, либо как вариант можно попробовать так:
read_bar = StrToDateTime(StrExtract(StrReplace(string, ";", ","), 0));
а на счет результата - не оптимизировал, все параметры по умолчанию
да и в окне настроек тестера кроме параметров - периода, лонг/шорт и комиссии ничего не меняю.
добавлено:
о, уже опередили с советом |
|
|
Посмотреть профиль Отправить личное сообщение |
|
unwar
Зарегистрирован: 22.11.2009
Сообщения: 10
|
000 писал(а): |
В старых версиях в функции StrExtract() разделитель нельзя задавать. Всегда используется ",". Надо предварительно заменить в строке ";" на "," при помощи функции StrReplace() |
yser писал(а): |
либо как отправил файлик, либо как вариант можно попробовать так:
read_bar = StrToDateTime(StrExtract(StrReplace(string, ";", ","), 0));
|
Спасибо большое да , теперь все отлично заработало в этой функции.
Ну чтож буду теперь анализировать результаты, возможно какую-то логику из ММ сюда прикручивать еще буду, в связи с этим созрел еще вопросик, возможно ли из кода AFL как-то обратится к результату предыдущей сделки? в этой системе, из-за того что она постоянно в позиции, получается даже не к "предыдущей", а при поступлении сигнала , к результату закрываемой сделки. |
|
|
Посмотреть профиль Отправить личное сообщение |
|
yser
Зарегистрирован: 30.11.2011
Сообщения: 76
|
unwar писал(а): |
... в связи с этим созрел еще вопросик, возможно ли из кода AFL как-то обратится к результату предыдущей сделки? в этой системе, из-за того что она постоянно в позиции, получается даже не к "предыдущей", а при поступлении сигнала , к результату закрываемой сделки. |
можно в том же цикле запоминать цены входа, и перед переворотом вычислить результаты закрываемых сделок . |
|
|
Посмотреть профиль Отправить личное сообщение |
|
|
|
Следующая тема
Предыдущая тема
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах Вы не можете вкладывать файлы Вы не можете скачивать файлы
|
|