AmiSite.ruЭтот ресурс посвящен замечательной программе технического анализа - AmiBroker. Советы начинающим пользователям. Индикаторы, Системы, Сканеры и другие коды AFL которые показались мне интересными как написанные мной, так и найденные в сети.
|
|
Робот.Модернизируем робота работающего через 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];
Вот и все. Робот со стопом готов. Удачи.
|