Как сделать робота на AmiSharp? Часть 1.
В этой статье я попробую проиллюстрировать процесс создания простейшего робота на связке QUIK-AmiSharp-AmiBroker. Пример боевого фреймворка описан здесь.
Подразумеваю, что у Вас установлен терминал QUIK, программа технического анализа Amibroker и Вы понимаете язык AFL (ну или хотя бы С, достаточно). Некоторый объём информации по этим вопросам Вы найдёте на этом сайте. Также предполагаю, что экспорт котировок из терминала QUIK в Амиброкер у Вас уже настроен и работает (если нет - Настройка экспорта котировок в Amibroker), а также где-нибудь на жестком диске имеется AmiSharp.
Итак, формулируем наш алгоритм. Сделаем робота, работающего по простейшим классическим правилам:
- Если предыдущая свеча закрылась выше простой скользящей средней, то покупаем по рынку;
- Если предыдущая свеча закрылась ниже простой скользящей средней, то продаём по рынку;
- Для простоты работаем только в лонг.
Первое, что делаем - создаём AFL формулу для расчета точек входа-выхода. Создаем новый чарт, копируем в него стандартные графики Price и Simple Moving Average. Автоматически создаётся AFL формула:
_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 );
Plot( MA( P, Periods ), _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style") );
_SECTION_END();
Процедура заняла секунд 10. Теперь добавляем правила входов и выходов из позиций и выводим метки на график. Дописываем 4 строчки:
_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();
Buy = Cross(C, MovingAverage);
Sell = Cross(MovingAverage,C);
PlotShapes(Buy * shapeUpArrow,colorGreen);
PlotShapes(Sell * shapeDownArrow,colorGreen);
На графике появится что-типа такого:
Теперь добавляем выставление заявок через AmiSharp. Используем готовую процедуру из статьи Выставление заявок из AmiBroker:
_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");
// ================== ТРАНЗАКЦИИ ======================
function SetTransParameter(ParameterString,ParameterName,ParameterValue)
{
return ParameterString + ParameterName + "=" + ParameterValue + ";" ;
}
//======================== Выставляем заявку ==================
function Make_Order(ClassCode,SecCode,TransactionOper,TransactionSize)
{ local result,trans_result,str;
str = SetTransParameter("", "ACTION", "NEW_ORDER");
str = SetTransParameter(str,"TRANS_ID", amisharp.Generate_TransID());
str = SetTransParameter(str,"SECCODE", Seccode);
//str = SetTransParameter(str,"PRICE",0);
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);
str = SetTransParameter(str,"TYPE", "M");
amisharp.QuikConnect(QUIK_Path);
trans_result = amisharp.QuikSendSyncTransaction(str);
amisharp.QuikDisconnect();
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","" + Size);
}
}
else
{ if (LastValue(Sell))
{ Make_Order(ClassCode,SecCode,"Sell",CurrentPosition);
StaticVarSetText("POSITION","0");
}
}
Я взял готовый кусок и слегка его подправил. Написать с нуля этот фрагмент можно за 10-15 минут.
Запускаем терминал QUIK, разрешаем ему отрабатывать внешние транзакции (Торговля-Внешние транзакции), указываем скрипту параметры (номер аккаунта, размер позиции и остальные) и наливаем кофе. Итого, максимум полчаса и
все.
Оно работает. Наблюдаем, как амиброкер щелкает заявками. Конечно, это не тот робот, который можно использовать для зарабатывания денег, исключительно иллюстрация механизма. Тем не менее, можно понаблюдать, как расчетные метки Buy и Sell Амиброкера сопровождаются заявками и сделками в таблицах QUIK и дублируются на его графике.
Можно попробовать изменить параметры скользящей средней в диалоге параметров - скользящая средняя будет пересчитана (и отрисована) мгновенно, никаких перезагрузок или каких-то дополнительных манипуляций не потребуется. Вместе с измененной скользящей тут же будут пересчитаны и сигналы Buy и Sell. Можно изменить на ходу размер позиции - и робот отработает эти изменения немедленно и корректно. Впрочем, в процессе работы нашего робота можно изменять любые параметры.
При желании можно запустить несколько копий робота в одном амиброкере параллельно. Например, можно торговать одной бумагой на 5-минутках, другой на часовиках, а третьей на таймфрейме 7 минут (можно и так). Все они будут замечательно трудиться на одном счете или на разных, взависимости от того, какой торговый счет указать в настройках каждого скрипта. Но текст робота придется слегка подправить (изменить 3 строки), чтобы роботы не мешали друг другу - оставляю это Читателю.
Пока ничего необычного нет: рисует, выставляет транзакции... Написан робот быстро и, надеюсь, получился совсем несложным (все-таки язык ANSI C понятен любому, кто знаком с программированием). Очевидно, что в робот нужно много чего добавить - контроль успешности выставления/исполнения заявок, контроль наличия соединения с брокером и т.д., но всё это в демонстрационном варианте для ясности опустим.
Подобный робот можно сделать на qpile/S#/Excel, однако эти способы гораздо сложнее (я писал роботов с использованием всех этих вариантов, но Вы можете воспользоваться правом не согласиться со мной ).
Этот робот пока только посылает транзакции в терминал, не используя никакие возможности обратной связи. В следующих статьях проиллюстрирую, каким образом можно получать внутренние таблицы терминала QUIK и приведу примеры, демонстрирующие преимущества подхода с использованием AmiSharp.
Продолжение: Как сделать робота на AmiSharp? Часть 2.
См. также
P.S. Возникающие вопросы , пожалуйста, на форум.
RSS лента комментариев этой записи