Germany | Finland | Saint Petersburg | Drive

Как сделать робота на AmiSharp? Часть 2.

Опубликовано в AmiSharp

В прошлой статье (Как сделать робота на AmiSharp? Часть 1) был приведён текст простейшего робота в Амиброкере, работающего через AmiSharp. Немного усложним задачу.

В прошлый раз для управления позицией мы использовали рыночные заявки. Такой подход вполне надёжно работает, к примеру, на рынке акций ММВБ. На рынке фьючерсов FORTS этот код заявки выставить не сможет: на рынке FORTS нет рыночных заявок. Чтобы на нем сэмулировать рыночную заявку, нужно знать минимальную и максимальную цену инструмента для текущей сессии. Как добиться, чтобы наш робот работал и на фьючерсах тоже?

Можно пойти простым путём. Если нужно купить по рынку, значит выставляем цену "немного" выше, чем текущая. В этом случае заявка исполнится по лучшей цене предложения. Это будет работать, но лишь до тех пор, пока цена инструмента не приблизится к верхней границе и это "немного" не окажется выше границы. Заявка будет отклонена торговой системой, последствия понятны.

Тем не менее, рыночную заявку на рынке FORTS можно эмулировать (подробнее здесь), но для этого нужно получить минимально и максимально возможные значения цены интересующего инструмента. Как?

Есть два пути. Рассмотрим один из них - путем получения из таблицы текущих параметров терминала QUIK.

Итак, задача: сделать доступными эти значения в скрипте AFL.

Решается посредством AmiSharp. Механизм выглядит следующим образом:

  1. Включаем DDE экспорт нужной нам таблицы. В качестве DDE сервера указываем DDE-сервер амишарпа (его имя "Mutant").
  2. Проверяем визуально, что Amisharp получает нужную нам таблицу из терминала (экспорт мы настроили правильно).
  3. Теперь можно из скрипта читать любую из доступных Амишарпу таблиц.
Начнем по порядку. Экспортируем таблицу текущих значений из терминала в Amisharp. Порядок следования столбцов неважен, лишние столбцы не мешают.
 
 

Смотрим, как это выглядит в Amisharp:

Нормально выглядит. Теперь дописываем скрипт, чтобы он работал и с фьючерсами FORTS:

 

_SECTION_BEGIN("Price");
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorBlack ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() );
_SECTION_END();

_SECTION_BEGIN("MA");
P = ParamField("Price field",-1);
Periods = Param("Periods", 15, 2, 300, 1, 10 );
MovingAverage = MA( P, Periods );
Plot(MovingAverage , _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style") );
_SECTION_END();

// Даем возможность пользователю менять параметры для торговли
_SECTION_BEGIN("Trade");
Seccode = ParamStr("SecCode","");
Classcode = ParamStr("ClassCode","");
Account = ParamStr("Account","");
ClientCode = ParamStr("Client code","");
Size = Param("Size",1,1,100);
QUIK_Path = ParamStr("QUIK_Path","e:\quik");
_SECTION_END();

// Включаем AmiSharp
amisharp = CreateStaticObject("AmiSharp.Mutant");
amisharp.QuikConnect(QUIK_Path);

// ================== ТРАНЗАКЦИИ ======================

function SetTransParameter(ParameterString,ParameterName,ParameterValue)
{
return ParameterString + ParameterName + "=" + ParameterValue + ";" ;
}

//======================== Выставляем заявку ==================

function Make_Order(ClassCode,SecCode,TransactionOper,TransactionSize)
{ local result,trans_result,str,step;

str = SetTransParameter("", "ACTION", "NEW_ORDER");
str = SetTransParameter(str,"TRANS_ID", amisharp.Generate_TransID());
str = SetTransParameter(str,"SECCODE", Seccode);
str = SetTransParameter(str,"QUANTITY", TransactionSize);
str = SetTransParameter(str,"OPERATION", StrToUpper(StrLeft(TransactionOper,1)));
str = SetTransParameter(str,"CLASSCODE", ClassCode);
str = SetTransParameter(str,"ACCOUNT", Account);
if (ClientCode != "")
str = SetTransParameter(str,"CLIENT_CODE", ClientCode);

if (ClassCode == "SPBFUT") // Это ФОРТС, лимитированные заявки
{ str = SetTransParameter(str,"TYPE", "L");
   if (StrToUpper(StrLeft(TransactionOper,1)) == "B")
   { MaxPrice = AmiSharp.GetCellName("[testbook]currenttable","pricemax",1);
      str = SetTransParameter(str,"PRICE", MaxPrice);
   }
   else
  { MinPrice = AmiSharp.GetCellName("[testbook]currenttable","pricemin",1);
     str = SetTransParameter(str,"PRICE", MinPrice);
  }
}
else // Это ММВБ - заявки по рынку
{ str = SetTransParameter(str,"TYPE", "M");
//str = SetTransParameter(str,"PRICE", 0);
}

trans_result = amisharp.QuikSendSyncTransaction(str);
return StrExtract( trans_result,1);
}

Buy = Cross(C, MovingAverage);
Sell = Cross(MovingAverage,C);

PlotShapes(Buy * shapeUpArrow,colorGreen);
PlotShapes(Sell * shapeDownArrow,colorGreen);

// Смотрим текущую позицию и отрабатываем сигналы. CurrentPosition хранит 0, если позиции нет и размер позиции, если она есть
CurrentPosition = StrToNum(StaticVarGetText("POSITION"));
if (CurrentPosition == 0)
{ if (LastValue(Buy))
{ Make_Order(ClassCode,SecCode,"Buy",Size);
StaticVarSetText("POSITION","" + CurrentPosition);
}
}
else
{ if (LastValue(Sell))
{ Make_Order(ClassCode,SecCode,"Sell",CurrentPosition);
StaticVarSetText("POSITION","0");
}
}

 

Таким образом, мы получили в скрипте данные из таблицы терминала QUIK и использовали их в скрипте на языке AFL. Точно таким же способом можно получать любые таблицы QUIK, которые подлежат экспорту посредством протокола DDE: таблицу сделок, таблицу стоп-заявок, лимиты, ограничения, все сделки и так далее.

К примеру, экспортируя в Амишарп таблицу сделок, можно в скрипте узнать реальные цены, по которым исполнены заявки. При экспорте стаканов можно в скрипте AFL видеть текущую структуру спроса-предложения и так далее. Таблица текущих значений расскажет скрипту о технических подробностях интересующей бумаги - минимальном шаге цены, размере лота и так далее.

Таким образом, AmiSharp даёт скрипту все те возможности для написания роботов, которые имеются в qpile и в S#, кроме кросс-платформенности последнего. (На самом деле вообще не понимаю, кому и зачем эта кросс-платформенность нужна - никто ни разу не заказал мне алгоритм, который должен работать на Plaza II, QUIK и Ninja одновременно)

В следующей части я проиллюстрирую процесс модификации алгоритма робота в варианте QUIK-AmiSharp-Amibroker на этом же простейшем примере.

См. также Документация AmiSharp

Комментарии   
# madsmart33 11.12.2013 18:09
Спасибо!Все получилось!
Но,робот совершает только покупку и все...
Ответить | Ответить с цитатой | Цитировать
# admin 11.12.2013 18:14
madsmart33, здесь приведен текст очень простого робота, чтобы не нагромождать второстепенные детали.

  • Робот торгует только в лонг
    Текущая позиция хранится в памяти. Если выйти из амиброкера и зайти снова - информация о позиции теряется. Сохраняйте позицию на диске
    Выход из позиции - по сигналу Sell, стопы не использовались. Допиливайие сами при желании :lol:
Ответить | Ответить с цитатой | Цитировать
Добавить комментарий