Бесплатная библиотека StockSharp предоставляет широкие возможности при разработке торговых роботов различной сложности. Но самое трудное для многих пользователей - сделать первые шаги при разработке своего робота. Поэтому представляем вашему вниманию статью-инструкцию по созданию простого привода для терминала QUIK с использованием S#.API.
Для создания простого привода нам понадобится:
- Quik;
- Библиотека S#;
- Visual Studio Express;
- Немного навыков программирования.
**:::center Подготовка рабочего места
- Для тех, у кого не стоит бесплатный Visual Studio Express С#, скачиваем и устанавливаем.
- Cкачиваем библиотеку с официального сайта StockSharp, либо - по прямой ссылке на последнюю доступную версию. Разархивируем в какую-нибудь папку, чтобы не забыть потом.
- Устанавливаем Quik (демо-версию можно получить с официального сайта). Получаем логин, пароль, ключи, настраиваем Quik соответствующим образом.
После установки Quik, его нужно настроить для работы со S#. Для этого нужно проделать 3 базовых шага:
1) Включить обработку внешних транзакций. "Торговля" → "Внешние Транзакции" → "Начать обработку" и поставить галочку "Запускать процесс обработки внешних транзацкий автоматически"

2) Далее нужно открыть соответствующий Wnd-файл с настройками: "Настройки" → "Загрузить настройки из файла" → выбрать wnd-файл по пути "Разахивированная папка"\Samples\Quik\info.wnd

3) Далее настраиваем счета : "Торговля" → "Настройка счетов" → добавить все счета в выбранные счета депо.

4) В итоге можно настроить окошки - подтянуть их, уменьшить, но названия столбцов менять нельзя, так же как и удалять их. У разных брокеров (квиков) есть особенности , стоят определённые фильтры на таблицах "Мои сделки", "Мои заявки". Нажав правой кнопкой мышки на таблицу "Мои сделки", выделить все. Аналогично и в таблице “Мои заявки”.

Добавьте торгующийся на данный момент инструмент в таблицу "Инструменты"; по нему в дальнейшем мы будем отправлять заявки.
**:::center Создание торгового привода
Открываем Visual Studio. Создаём новый проект → "Приложение Wpf". Настраиваем наш проект на работу S#:
- Правой кнопкой мыши на "Проект" → "Свойства" и меняем "Требуемая версия NetFrameWork" (Net FrameWork 4 Client Profile ) на просто Net FrameWork 4(после этого меняется целевая среда разарботки).
- Добавляем нужные библиотеки в наш проект "Ссылки" → "Добавить ссылку" → "Обзор".
- Выбираем нужные нам библиотеки, которые лежат в "Разахрихированая папка"\References: 1)StockSharp.Quik 2)StockSharp.BusinessEntites 3)StockSharp.Algo 4)Ecng.Common 5)Ecng.ComponentModel 6)Ecng.Xaml
- Прописываем соответсвующие using на наши библиотеки в классе MainWindow.xaml.cs
using System.Windows;
using StockSharp.Quik;
using Ecng.Xaml;
using StockSharp.BusinessEntities;
Заходим в MainWindow.Xaml, создаём соответсвующие кнопки и другие элементы на форме нашего приложения, перетягивая их из панели элементов. Получаем следующую форму:

Даем каждому элементу на нашей форме название, чтобы потом из кода обращаться к нему. Нажимаем два раза на кнопку, чтобы создать метод, который будет вызываться по нажатию на эту кнопку (метод обработчик).
Прописываем код под кнопку подключения. Это простой код демонстрирующий подключение и выгрузку данных из Quik в асинхронном режиме. Теперь осталось дополнить код выводом информации на главную форму, то есть сделать вывод в наши выпадающие списки "Портфели" и "Инструменты".
//обьявляем переменную
private QuikTrader _trader;
/// <summary>
/// Подключение к квику
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Connect_Click(object sender, RoutedEventArgs e)
{
//создаём квик трейдера, передавая ему сразу место расположения нашего терминала
_trader= new QuikTrader(QuikTerminal.GetDefaultPath());
//подписываемся на событие подключения, как только подлючимся, сразу запустим Экспорт
//Connect- просто подключение к потоку
//StartExport- получение он-лайн данных из квика Инструменты,Заявки , Портфели и так далее
_trader.Connected += () => _trader.StartExport();
// подключаем квик
_trader.Connect();
}
Дописываем графический вывод на нашу форму в выпадающие списки:
private void Connect_Click(object sender, RoutedEventArgs e)
{
//создаём квик трейдера, передавая ему сразу место расположения нашего терминала
_trader= new QuikTrader(QuikTerminal.GetDefaultPath());
//подписываемся на событие появление новых инструментов
//оно сработает когда включится экспорт
_trader.NewSecurities += securities =>this.GuiAsync(()=>//GuiASync используется чтобы выводить графику из другого потока
{
//заполняем коллекцию у нашего выпадающего списка (ComboBox)
Securitites.ItemsSource = _trader.Securities;
});
//подписываемся на событие появления новых портфелей
//сработает после запуска экспорта
_trader.NewPortfolios += portfolios =>this.GuiAsync(()=>
{
//заполняем коллекцию у нашего выпадающего списка (ComboBox)
Portfolios.ItemsSource = _trader.Portfolios;
});
//подписываемся на событие подключения, как только подлючимся, сразу запустим Экспорт
//Connect - просто подключение к потоку
//StartExport- получение онлайн данных из квика Инструменты, Заявки, Портфели и так далее
_trader.Connected += () => _trader.StartExport();
// подключаем квик
_trader.Connect();
}
Запускаем проект (F5), нажимаем на кнопку "Подключиться" (в это время у нас уже работает Quik, который подключен к котировкам). После этого наш робот включает эскпорт DDE в Quik и через некоторое время мы получаем заполненные выпадающие списки в нашем проекте.

Остается дописать функционал под две оставшиеся кнопки "Купить", "Снять все заявки":
- "Купить" - отправляем заявку (портфель и инструмент берется из выпадающих списков) по той цене, которая будет указана в нашем текстовом окне;
- "Снять все заявки" - снимаем все выставленные нами заявки. Код для отправки заявки:
private void Buy_Click(object sender, RoutedEventArgs e)
{
//создаём ордер
//заполняем его нужными свойствами
// портфель и инструмент вынимаем из выпадающих списков
//цену для отправки заявки вынимаем из тесктового окна
var order = new Order
{
Trader = _trader,
Portfolio = (Portfolio)Portfolios.SelectedItem,
Security = (Security) Securitites.SelectedItem,
Volume = 1,
Price = decimal.Parse(PRICE.Text),
Direction = OrderDirections.Buy
};
//регистрируем ордер
_trader.RegisterOrder(order);
}
Код для снятия всех заявок:
private void CancelOrders_Click(object sender, RoutedEventArgs e)
{
//отменить все заявки
_trader.CancelOrders();
}
Пример работы простого привода:

Скачать исходники также можноздесь.
**:[:::center Видео-урок по созданию простого торгового робота с использованием библиотеки StockSharp:
Автор статьи: Самунджян Артём
Kommentare (53)
Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen
а как приделать к приводу BestByPriceQuotingStrategy?
Будет такой же материал для Альфы?
Для альфы практически тоже самое 😀 Попробуйте для квика сделать, для альфы сами сможете.
Здравствуйте! Как можно программно узнать текущие средства по портфелю?
Ошибка 1 "StockSharp.BusinessEntities.Portfolio" не содержит определения для "GetFreeMoney" и не был найден метод расширения "GetFreeMoney", принимающий тип "StockSharp.BusinessEntities.Portfolio" в качестве первого аргумента (возможно, пропущена директива using или ссылка на сборку) C:\Users....\Desktop\QuikStockSharp\QuikStockSharp\MainWindow.xaml.cs 45 38 QuikStockSharp
p.s. и все-таки было бы удобнее, если бы к конкретному портфелю можно было обращаться по индексу
чуть-чуть добавил в код из примера
private void Connect_Click(object sender, RoutedEventArgs e) { //создаём квик трейдера , передавая ему сразу место расположения нашего терминала _trader = new QuikTrader(QuikTerminal.GetDefaultPath()); //подписываемся на событие появление новых инструментов //оно сработает когда включится экспорт _trader.NewSecurities += securities => this.GuiAsync(() =>//GuiASync используется чтобы выводить графику из другого потока { //заполняем коллекцию у нашего выпадающего списка (ComboBox) Securities.ItemsSource = _trader.Securities; }); //подписываемся на событие появления новых портфелей //сработает после запуска экспорта _trader.NewPortfolios += portfolios => this.GuiAsync(() => { //заполняем коллекцию у нашего выпадающего списка (ComboBox) Portfolios.ItemsSource = _trader.Portfolios;
Действительно, на все сборки подписаны? На StockSharp.Algo?
sum должно быть decimal
StockSharp.Algo в ссылках была, добавлял как в видеоролике. decimal исправил.
Оказывается тупо забыл using прописать :) И все-таки что насчет доступа по индексу? В принципе можно реализовать через создание нового массива, но должен же быть более правильный вариант.
Доступ по индексу - это потенциальная ошибка. Используйте имя портфеля, оно уникально
А в xaml-файле в <ComboBox x:Name="Portfolios" добавь ```csharp SelectionChanged="Portfolio_SelectionChanged"
Trader.Portfolios.First(p => p.Name == "SPBFUT00451")
Спасибо! Возник еще вопрос. Если этот же код реализовать не в wpf проекте, а в windoes forms, работать будет?
У вас значит нет такого портфеля либо он не успел придти. Используйте FirstOrDefault и проверяйте на нал.
Создал кнопку для выставления заявки по рыночной цене
GetMarketPrice всегда возвращает 0 и система не может регистрировать заявки
Попробовал по-разному
В обеих случаях получается 0. Причем на нескольких инструментах.
Все, наконец-то получилось. Всем спасибо! покопался в справке и просто добавил Type = OrderTypes.Market в order. Скажите пожалуйста, а где можно почитать про то, как создавать заявки других типов (например conditional)?
А попробуй закрываться не Trader.RegisterOrder(order), а с помощью MarketQuotingStrategy
_marketQuotingStrategy = new MarketQuotingStrategy(direction, this.Volume) ChildStrategies.Add(_marketQuotingStrategy);
простите, немного не понял. а как в таком случае указывать портфель, инструмент и _trader?
var _marketQuotingStrategy = new MarketQuotingStrategy(_order, new Unit(), new Unit()); _marketQuotingStrategy.Start();
где в _order указываете портфель, инструмент и шлюз. Цену не указываете
А о каком трейдере идет речь? Не о QUIKTrader? Сервера QUIK частенько выключаются в не рабочее время. Может стоит просто подождать начала работы площадок?
private QuikTrader _trader; как в примере. для экспериментов используется quik-junior (работает и на выходных)
Там вроде от площадок зависит. Какие инструменты?
Возвращаясь к вопросу о windows forms.
Создал WinFroms проект, прицепил библиотеки: все нормально коннектится/дисконнектится. Но вот с получением портфелей и списка активов возникли проблемы:
ругается на GuiAsync. Пробовал написать "в лоб":
получаю пустой список. Можно ли вообще в WinForms проектах реализовать подобное?
Например тут описано решение. Пользуйтесь поиском по форуму, многие вопросы сразу отпадут.
Совет про изучения Форума остается в силе))) http://stocksharp.com/posts/m/15374/
Еще один вопрос. Вряд ли на него есть ответ на форуме:) Я создаю datagridview, в котором создаю столбец с comboox'ами. Пытаюсь передать в combobox данные об активах (чтобы можно было выбрать из выпадающего списка)
Приложение запускается и даже в Combobox вижу список всех активов. Но когда пытаюсь что-то выбрать из этого списка, то datagridview выдает ошибку: недопустимое значение ячейки. В списке находятся значения типа SBER@QJSIM
p.s. имхо, QJSIM это quik junior simulator p.p.s в примере wpf-проекта combobox заполняется таким же образом
Честно говоря, не с WinForms не дружу
Почему у меня такая ошибка в строке private QuikTrader _trader; ? Вроде бы все требуемые ссылки добавил.
Судя по скрину у вас не добавлена StockSharp.Logging.dll и не прописано соответсвующее namespace. Раньше классы для работы с логами были в StockSharp.Algo.dll. Сейчас вынесены в отдельную dll.
Ага, StockSharp.Logging.dll и Ecng.Serialization.dll надо добавить. В статье про это не сказано, устарела.
у меня у одного нет файла Samples/info.wnd ? :o
Подскажите что делать если, в комбобоксах не выдаётся список, где находятся лог файлы ?
Добрый день!
Заинтересовала платформа, видно, что имеется много полезных возможностей. Однако, пример из коробки у меня не пошел, выдает ошибку в отроке
_trader.RegisterOrder(order);
Ошибка следующего вида "System.ArgumentNullException" в StockSharp.Algo.dll {"Значение не может быть неопределенным.\r\nИмя параметра: classCode"}
Возможно что-то изменилось в библиотеке, за это время, у меня стоит сейчас последняя версия. Буду благодарен за помощь.
Заранее спасибо.
Добрый вечер! Подскажите, а можно ли как-то сделать возможность выбора сразу 3-х инструментов и одновременной отправки заявки по ним на покупку/продажу?
А почему нельзя? Один инструмент на стратегию, 3 инструмента - 3 стратегии?
Вот как вы себе это представляете? 3 инструмента у всех у них какая цена на покупку? Не плодите сущностей там где не надо. Пошлите по очереди все три заявки.