Робот.
Модернизируем робота работающего через Quik API. Прикручиваем стопы.
Это попытка показать с комментариями как изменить представленного ранее робота чтобы он мог исполнять стопы.
Если хотите использовать эту схему, то надо обновить плагин AS_File.
Старая версия плагина (до февраля 2012г) сохраняла в файл только целые цифры,
а при сохранении цены входа требуется записывать и дробные значения.
Саму систему оставим, только добавим в неё стоп 1% по LKOH и 2% по SBER.
У нас есть простой механизм записи необходимых параметров в файл. Воспользуемся этой возможностью и для начала запишем в файл Quik_Robot цену входа в позицию.
Можно записать и последнюю цену инструмента, по которому была совершена сделка и ту цену, по которой тестировали систему.
Запишем системную цену, чтобы работа робота была максимально приближена к тестируемой системе.
Эту цену в последствии будем использовать для расчета срабатывания стопа.
Разумеется, можно сразу рассчитать и записать цену стопа, но в том случае если размер стопа будет меняться, лучше записать именно цену
входа и от неё вести расчеты. Надо заметить, что если делать трейлинг,
то проще писать в файл именно цену стопа и при необходимости её переписывать.
И так, сначала в настройках символов зададим размеры стопов.
if(Name() == "LKOH") { // Символ как он называется в Ами
SecCode = "LKOH";
Class = "EQBR";
Lots = 5;
TickS = 0.1; // Минимальный шаг цены торгуемой бумаги
Stop = 1; // стоп в %
Otstup = 20; // Заявка будет выставлена хуже текущей цены на Otstup рублей
}
else if(Name() == "SBER") { // Символ как он называется в Ами
SecCode = "SBER03";
Class = "EQBR";
Lots = 2;
TickS = 0.01; // Минимальный шаг цены торгуемой бумаги
Stop = 2; // стоп в %
Otstup = 1; // Заявка будет выставлена хуже текущей цены на Otstup рублей
}
затем изменим процедуру
orders чтобы она записывала не только позицию, но и цену входа
procedure orders(bs, pr, Lot)
{
connection = 0;
QC = AS_QUIK_CONNECT(Quik);
if (QC == 1)
{
connection = 1;
text = "Есть соединение с сервером";
Color = colorGreen;
}
else if (QC == -1)
{
text = "нет соединения с квиком";
Color = colorRed;
}
else if (QC == -2)
{
text = "нет соединения с сервером";
Color = colorRed;
}
else
{
text = "фигня какая то";
Color = colorRed;
}
if(connection == 1)
{
order = AS_QUIK_SEND_SYNC_NEWORDER( "123", // OrderID - Любые цифры
Account,
Client_Code,
"L", // Тип заявки M-рыночная, L-лимитированная
Class,
SecCode,
bs,
pr,
Lot);
}
if(StrToNum(order) > 100)
{
iz = "исполнена";
coloriz = colorGreen;
str = str + " заяка исполнена" + " ответ сервера=" + order;
if(pos > 0 AND bs == "S") // закрытие лонга
{
AS_WRITE_PARAM("Quik_Robot", Name(), "pos", 0);
AS_WRITE_PARAM("Quik_Robot", Name(), "price", 0);
}
else if(pos == 0 AND bs == "S") // шорт
{
AS_WRITE_PARAM("Quik_Robot", Name(), "pos", -1*Lot);
AS_WRITE_PARAM("Quik_Robot", Name(), "price", Close[BarCount - 2]);
}
else if(pos < 0 AND bs == "B") // закрытие шорта
{
AS_WRITE_PARAM("Quik_Robot", Name(), "pos", 0);
AS_WRITE_PARAM("Quik_Robot", Name(), "price", 0);
}
else if(pos == 0 AND bs == "B") // лонг
{
AS_WRITE_PARAM("Quik_Robot", Name(), "pos", Lot);
AS_WRITE_PARAM("Quik_Robot", Name(), "price", Close[BarCount - 2]);
}
str = str + " позиция на момент исполнения " + pos;
}
else {
iz = "не исполнена";
coloriz = colorRed;
str = str + " заяка НЕ исполнена" + " ответ сервера=" + order;
}
}
Теперь мы в любой момент можем узнать, по какой цене открыта позиция, конечно, если робот сейчас в рынке.
Вставим в систему проверку на срабатывание стопа и там же сразу запишем в лог что сработал стоп.
/// стопы ///
if(pos > 0 AND L[BarCount-1] < AS_READ_PARAM("Quik_Robot", Name(), "price")*(1 - Stop/100))
{
Sell1 = 1;
str = str + " сработал стоп при лонге";
}
else if(pos < 0 AND H[BarCount-1] > AS_READ_PARAM("Quik_Robot", Name(), "price")*(1 + Stop/100))
{
Cover1 = 1;
str = str + " сработал стоп при шорте";
}
Тут есть интересный момент. Можно использовать для определения стопа минимум и максимум цены соответственно позиции.
В этом случае даже если цена достигнет стопа кратковременно в промежутке между сканированием рынка, то стоп сработает,
а можно вместо
H[BarCount-1] и
L[BarCount-1] использовать последнюю цену
Close[BarCount-1]. В этом случае стоп сработает
только если в момент сканирования цена превысила уровень стопа. Первый вариант ближе к тестированному варианту,
но в принципе имеет право на жизнь и второй.
Этот блок следует добавить после сдвижки сигналов, чтобы сигналы сгенерированные стопом не сдвигались, который просто для удобства тоже изменим.
Buy1 = Buy1[BarCount - 2];
Sell1 = Sell1[BarCount - 2];
Short1 = Short1[BarCount - 2];
Cover1 = Cover1[BarCount - 2];
Казалось бы все. Однако есть еще один момент который сразу не заметен.
Что произойдет если стоп сработает на том же баре, на котором был вход в рынок?
В файл Quik_Robot будет записана нулевая позиция, а сигнал на открытие на баре остался.
Поэтому робот немедленно снова откроет позицию и сразу снова сработает стоп. Так будет продолжаться, пока не начнется следующий бар.
Такое поведение надо исправить.
Например сразу проверять бар на возможность срабатывания стопа и если он может сработать, то не генерировать сигнал.
Снова исправим блок сдвижки сигналов.
Buy1 = Buy1[BarCount - 2] AND L[BarCount - 1] > C[BarCount - 2]*(1 - Stop/100);
Sell1 = Sell1[BarCount - 2];
Short1 = Short1[BarCount - 2] AND H[BarCount - 1] < C[BarCount - 2]*(1 + Stop/100);
Cover1 = Cover1[BarCount - 2];
Вот и все. Робот со стопом готов.
Удачи.
Удачи.