В данной статье я покажу как использовать графические компоненты, входящий в S#.API, с целью создания полноценного приложения уровня
S#.Shell:
![image3979.png image3979.png](https://stocksharp.ru/file/108007/image3979_png/?size=800x800)
Вы узнаете, как сделать профессионального уровня программу с настройкой подключений, выводом инструментов, цен и графиков (и чтобы это все еще сохранялось и загружалось при перезапуске). И сложность создания такого приложения не несколько месяцев, а буквально несколько часов (это не шутка! читайте до конца). В этом заключается основное преимущество графического фреймворка, который я назвал по аналогии S#.UI (данное название не официальное, я сам придумал).
Я не буду использовать сложные конструкции и паттерны проектирования, понятные только профессиональным программистам. Наоборот, цель статьи показать, что порог вхождения в создание своих приложений торговли с помощью S#.API очень низкий.
Если вы работаете в компании, и делаете свой уникальный софт (например, вы работает в проп или брокерской компании), вам так же будет интересно. В этой статье вы сможете узнать практику создания подобных систем (особенно, если вы только приступили к своим обязанностям).
Что понадобиться
1) Visual Studio 2017 (Community, бесплатная версия), в ней мы будем программировать.
2) Бесплатное подключение к тестовым торгам на бирже, я буду использовать QUIK.
Создание проекта
Создадим новое WPF приложение в Visual Studio
![image5545.png image5545.png](https://stocksharp.ru/file/108008/image5545_png/?size=800x800)
После чего необходимо добавить S#.API библиотеки в как это сделать описано
здесь . Я предпочитаю установку при помощи Nuget.
Так как все графические элементы S#.API созданы на базе DevExpress, а библиотеки DevExpress идут вместе с S#.API, глупо будет ими не воспользоваться. Всю информацию по графическим элементам DevExpress можно найти в Google.
Перейдем в редактор окна MainWindow.xaml
![image4259.png image4259.png](https://stocksharp.ru/file/108009/image4259_png/?size=800x800)
Заменим Window на DXWindow, это нам понадобиться для использования разных цветовых схем
![image4329.png image4329.png](https://stocksharp.ru/file/108010/image4329_png/?size=800x800)
Visual Studio нам сама предложит вставить необходимые библиотеки.
Разобьем окно на три части в верху будет полоса с кнопками настройки подключений и подключения. В низу окно с логами. В середине все остальные панели. Проще всего так разбить окно с помощью LayoutControl от DevExpress.
В получившиеся три части мы и будем добавлять необходимые нам элементы.
![image2275.png image2275.png](https://stocksharp.ru/file/108011/image2275_png/?size=800x800)
Настройка подключения к коннектору
Добавим две кнопки, одна кнопка настройки подключения, а вторая кнопка подключения. Для этого воспользуемся кнопкой SimpleButton от DevExpress. Кнопки будут расположены в верхней части приложения. В каждую кнопку поместим картинку привычные по Терминалу и Дизайнеру.
![image9977.png image9977.png](https://stocksharp.ru/file/108012/image9977_png/?size=800x800)
В верхнем правом углу экранной экранной формы увидим такую картину
![image1157.png image1157.png](https://stocksharp.ru/file/108013/image1157_png/?size=800x800)
Двойным нажатием на каждую кнопку создадим обработчики событий нажатия на кнопку.
В коде MainWindow необходимо объявить коннектор, а также место и имя файла в котором будут храниться настройки коннектора.
![image836.png image836.png](https://stocksharp.ru/file/108014/image836_png/?size=800x800)
В обработчике события нажатия на кнопку настроек коннектора будем открывать окно конфигурации коннектора и сохранять его в файл.
![image1289.png image1289.png](https://stocksharp.ru/file/108015/image1289_png/?size=800x800)
В конструкторе будем проверять есть ли каталог и файл с настройками коннектора и если он есть будем его загружать в коннектор
![image3497.png image3497.png](https://stocksharp.ru/file/108016/image3497_png/?size=800x800)
Большинство объектов S#.API имеют методы Save и Load, с помощью которых можно сохранить и загрузить этот объект из XML файла.
В методе обработчике нажатия на кнопку подключения подключаем коннектор.
![image6463.png image6463.png](https://stocksharp.ru/file/108017/image6463_png/?size=800x800)
Теперь можно запустить программу и проверить ее.
Установка темной темы
Я предпочитаю темную тему. Поэтому сразу делаем чтобы тема программы была темной. Для этого в файле App.xaml
![image1012.png image1012.png](https://stocksharp.ru/file/108018/image1012_png/?size=800x800)
Заменяем Application на charting:ExtendedBaseApplication Visual Studio нам сама предложит вставить необходимые библиотеки. А в файле App.xaml.cs удалить «: Application». Получиться код следующего вида
![image4777.png image4777.png](https://stocksharp.ru/file/108019/image4777_png/?size=800x800)
![image9701.png image9701.png](https://stocksharp.ru/file/108020/image9701_png/?size=800x800)
В конструкторе MainWindow пишем ApplicationThemeHelper.ApplicationThemeName = Theme.VS2017DarkName;
Полный код на текущий момент:
![image8484.png image8484.png](https://stocksharp.ru/file/108021/image8484_png/?size=800x800)
Запускаем для проверки темной темы.
![image1199.png image1199.png](https://stocksharp.ru/file/108022/image1199_png/?size=800x800)
Создание панели инструментов
Добавим папку, где мы будем хранить все созданные нами контроллы и назовем ее XAML.
Добавим в нее свой первый UserControll, дадим ему имя SecurityGridControl .
![image5159.png image5159.png](https://stocksharp.ru/file/108023/image5159_png/?size=800x800)
В него добавляем один элемент SecurityPicker. В котором будут отображаться имеющиеся инструменты. По аналогии с главным окном будем использовать LayoutControl от DevExpress.
![image2385.png image2385.png](https://stocksharp.ru/file/108024/image2385_png/?size=800x800)
Перейдем в конструктор главного окна и изменим центральную часть в вид закладок. В одной из закладок расположим созданный нами контролл с SecurityPicker
![image5375.png image5375.png](https://stocksharp.ru/file/108025/image5375_png/?size=800x800)
Теперь, когда у нас есть панель инструментов надо задать ей источник данных, в нашем случае это коннектор. Можно было просто в конструкторе MainWindow написать
SecurityPanel.SecPicker.SecurityProvider = Connector;
Но не стоит засорять код MainWindow кодом, который к нему не относится. Поэтому я создам статическую переменную Instance а в конструкторе MainWindow присвою ему значение MainWindow.
![image1508.png image1508.png](https://stocksharp.ru/file/108026/image1508_png/?size=800x800)
Теперь в любом месте нашей программы мы можем обращаться к свойствам MainWindow через код MainWindow.Instance.XXX.
В конструкторе SecurityGridControl таким образом указываем Connector как источник данных
![image6003.png image6003.png](https://stocksharp.ru/file/108027/image6003_png/?size=800x800)
Запустим для проверки.
![image8483.png image8483.png](https://stocksharp.ru/file/108028/image8483_png/?size=800x800)
Добавление логирования
Работу программы, коннектора или робота необходимо контролировать. Для этого в S#.API есть специальный класс LogManager. Данный класс принимает сообщения от источников и передает их в слушатели. В нашем случае источниками будут Connector, стратегии и т.д., а слушателем будет файл и панель логов.
В коде MainWindow объявляем объект LogManager и место, где он будет храниться
![image3414.png image3414.png](https://stocksharp.ru/file/108029/image3414_png/?size=800x800)
В конструкторе MainWindow создаем LogManager, задаем ему источник Connector и задаем слушателя файл
![image5931.png image5931.png](https://stocksharp.ru/file/108030/image5931_png/?size=800x800)
По аналогии с панелью инструментов создадим, панель логов в папку XAML добавляем еще один UserControl. Дадим ему имя MonitorControl. В него добавим элемент Monitor.
![image4717.png image4717.png](https://stocksharp.ru/file/108031/image4717_png/?size=800x800)
В конструкторе MonitorControl зададим в LogManager еще и Monitor как слушателя
![image8141.png image8141.png](https://stocksharp.ru/file/108032/image8141_png/?size=800x800)
В нижнюю часть MainWindow добавляем созданный MonitorControl
![image5572.png image5572.png](https://stocksharp.ru/file/108033/image5572_png/?size=800x800)
Запускаем для проверки
![image6299.png image6299.png](https://stocksharp.ru/file/108034/image6299_png/?size=800x800)
Создание панели портфелей
По аналогии с панелью инструментов создадим, панель логов в папку XAML добавляем еще один UserControl. Дадим ему имя PortfolioGridControl. В него добавим элемент PortfolioGrid.
![image68.png image68.png](https://stocksharp.ru/file/108035/image68_png/?size=800x800)
В конструкторе PortfolioGridControl нам надо подписаться на события появления нового портфеля и событие появления новой позиции у Connector.
![image1333.png image1333.png](https://stocksharp.ru/file/108036/image1333_png/?size=800x800)
Таким образом при появлении нового портфеля он появиться на панели портфелей портфель, а при появлении новой позиции на панели портфелей портфель обновит позицию.
В центральную части MainWindow добавляем созданную панель PortfolioGridControl
![image127.png image127.png](https://stocksharp.ru/file/108037/image127_png/?size=800x800)
Запускаем для проверки
![image3862.png image3862.png](https://stocksharp.ru/file/108038/image3862_png/?size=800x800)
У нас появилась вкладка с портфелями.
Создание панели ордеров
Панель ордеров в S#.API имеет возможность выставления заявок, снятия заявок и перерегистрации.
По аналогии с панелью инструментов создадим панель ордеров, в папку XAML добавляем еще один UserControl. Дадим ему имя OrderGridControl. В него добавим элемент OrderGrid.
![image4502.png image4502.png](https://stocksharp.ru/file/108039/image4502_png/?size=800x800)
OrderGrid имеет событие регистрации заявки OrderRegistering, событие перерегистрации заявки OrderReRegistering и событие отмены заявки OrderCanceling.
Создадим их обработчики
![image6128.png image6128.png](https://stocksharp.ru/file/108040/image6128_png/?size=800x800)
В обработчике события регистрации заявки мы создаем окно OrderWindow, в котором необходимо указать источники данных для инструментов, портфелей, и рыночных данных. В нашем случае это все будет Connector.
После чего мы вызываем OrderWindow методом ShowModal если в этом окне было нажата кнопка ОК то мы через коннектор методом RegisterOrder регистрируем заявку.
![image4848.png image4848.png](https://stocksharp.ru/file/108041/image4848_png/?size=800x800)
В обработчике события перерегистрации заявки мы все делаем тоже самое. Только в этом случае в событие нам приходит объект Order это заявка, которую надо перерегистрировать. Поэтому в OrderWindow мы указываем Order = order.ReRegisterClone(newVolume: order.Balance), чтобы заполнить поля окна OrderWindow.
После чего мы вызываем OrderWindow методом ShowModal если в этом окне было нажата кнопка ОК то мы через коннектор методом ReRegisterClone перерегистрируем заявку. В него мы передаем старую заявку, которую надо отменить и новую которую надо выставить.
![image1314.png image1314.png](https://stocksharp.ru/file/108042/image1314_png/?size=800x800)
В обработчике события отмены заявки достаточно вызвать метод CancelOrder и передать в него ордер, который необходимо отменить.
![image2355.png image2355.png](https://stocksharp.ru/file/108043/image2355_png/?size=800x800)
Чтобы Ордера отображались в OrderGrid необходимо в конструкторе OrderGridControl подписаться на события появления нового ордера и на событие ошибки регистрации и передавать эти события в OrderGrid.
![image9790.png image9790.png](https://stocksharp.ru/file/108044/image9790_png/?size=800x800)
В центральную части MainWindow добавляем созданную панель OrderGridControl
![image4806.png image4806.png](https://stocksharp.ru/file/108045/image4806_png/?size=800x800)
Запускаем для проверки
![image7488.png image7488.png](https://stocksharp.ru/file/108046/image7488_png/?size=800x800)
Создание панели собственных сделок
По аналогии с панелью инструментов создадим панель собственных сделок, в папку XAML добавляем еще один UserControl. Дадим ему имя MyTradeGridControl. В него добавим элемент MyTradeGrid.
![image3653.png image3653.png](https://stocksharp.ru/file/108047/image3653_png/?size=800x800)
В конструкторе MyTradeGridControl нам надо подписаться на события появления новой собственной сделки и передать ее в MyTradeGrid.
![image7227.png image7227.png](https://stocksharp.ru/file/108048/image7227_png/?size=800x800)
В центральную части MainWindow добавляем созданную панель OrderGridControl
![image3738.png image3738.png](https://stocksharp.ru/file/108049/image3738_png/?size=800x800)
Запускаем для проверки
![image514.png image514.png](https://stocksharp.ru/file/108050/image514_png/?size=800x800)
Создание панели стаканов
По аналогии с предыдущими панелями создадим панель стаканов, в папку XAML добавляем еще один UserControl. Дадим ему имя MarketDepthControl.
В MainWindow мы уже использовали LayoutControl, в этом контроле тоже воспользуемся LayoutControl. Разобьем панель на две части по горизонтали
![image1678.png image1678.png](https://stocksharp.ru/file/108051/image1678_png/?size=800x800)
В левую часть добавим SecurityPicker с ним мы встречались, когда создавали панель инструментов.
![image7627.png image7627.png](https://stocksharp.ru/file/108052/image7627_png/?size=800x800)
Правую часть разобьем на части по вертикали. Сверху правой части будет стакан
![image1159.png image1159.png](https://stocksharp.ru/file/108053/image1159_png/?size=800x800)
У MarketDepthControl необходимо задать какое-нибудь значение MaxHeight иначе приложение не будет запускаться.
Под стаканом расположим элементы задания портфеля, цены, и объёма заявки
![image8282.png image8282.png](https://stocksharp.ru/file/108054/image8282_png/?size=800x800)
Здесь стоит отметить свойство Label у LayoutItem, оно позволяет заладь текст перед элементом. А также элемент SpinEdit от DevExpress в котором удобно задавать численные значения. Выглядят эти элементы следующим образом.
![image4967.png image4967.png](https://stocksharp.ru/file/108055/image4967_png/?size=800x800)
Еще ниже расположим кнопки купить, продать.
![image62.png image62.png](https://stocksharp.ru/file/108056/image62_png/?size=800x800)
Полный код
![image9810.png image9810.png](https://stocksharp.ru/file/108057/image9810_png/?size=800x800)
В конструкторе MarketDepthControl зададим источник инструментов для SecurityPicker и источник портфелей для PortfolioComboBox, в нашем случае это будет Connector.
![image651.png image651.png](https://stocksharp.ru/file/108058/image651_png/?size=800x800)
Создадим обработчик события выделения инструмента в SecurityPicker. В нем проверяем не равен ли нулю полученный инструмент. Если он не равен нулю сохраняем полученный инструмент в локальную переменную, нам он пригодиться при обновлении стакана. После чего очищаем регистрируем полученный инструмент в Connector на получение стакана с помощью метода RegisterMarketDepth. С помощь метода GetMarketDepth получаем текущий стакана по инструменту, чтобы им обновить MarketDepthControl.
![image3667.png image3667.png](https://stocksharp.ru/file/108059/image3667_png/?size=800x800)
Чтобы стакан постоянно обновлялся в конструкторе MarketDepthControl подпишемся на событие изменения стакана MarketDepthChanged у коннектора. В обработчике этого события будем проверять какому инструменту принадлежит полученный стакан, и если он принадлежит выделенному инструменту в SecurityPicker то обновляем им MarketDepthControl.
![image4084.png image4084.png](https://stocksharp.ru/file/108060/image4084_png/?size=800x800)
В центральную части MainWindow добавляем созданную панель MarketDepthControl
![image7347.png image7347.png](https://stocksharp.ru/file/108061/image7347_png/?size=800x800)
На данном этапе можно запустить программу и проверить работу обновления стаканов.
Создадим обработчика события нажатия на кнопки купить и продать. В каждом обработчике создаем Order, в нем указываем инструмент выбранный в SecurityPicker, портфель выбранный в PortfolioComboBox, объём и цену из соответствующих SpinEdit. Регистрируем заявку в Connector с помощью метода RegisterOrder.
![image7717.png image7717.png](https://stocksharp.ru/file/108062/image7717_png/?size=800x800)
Оба обработчика отличаются только направлением заявки.
Сделаем чтобы при выделении котировки в стакане значение SpinEditPrice менялось на цену выделенной котировки. Для этого создадим обработчик события SelectionChanged у MarketDepthControl. В котором будем обновлять значение SpinEditPrice ценой выделенной котировки если выделенная котировка не равна нулю.
![image90.png image90.png](https://stocksharp.ru/file/108063/image90_png/?size=800x800)
Запускаем для проверки
![image8902.png image8902.png](https://stocksharp.ru/file/108064/image8902_png/?size=800x800)
Сохранение маркет-данных
Для сохранения портфелей, инструментов, площадок нам необходим класс CsvEntityRegistry. В него надо переделать место хранения сущностей и вызвать метод Init, для их загрузки.
![image7322.png image7322.png](https://stocksharp.ru/file/108065/image7322_png/?size=800x800)
Для сохранения свечей, сделок и т.д. нам понадобиться StorageRegistry
![image809.png image809.png](https://stocksharp.ru/file/108066/image809_png/?size=800x800)
Также нам понадобиться реестр хранилищ-снэпшотов SnapshotRegistry
![image4003.png image4003.png](https://stocksharp.ru/file/108067/image4003_png/?size=800x800)
Все это мы передаем в Connector при его создании
![image6704.png image6704.png](https://stocksharp.ru/file/108068/image6704_png/?size=800x800)
Здесь я также указал что Connector будет переподключаться при разрыве подключения, а также указал сколько дней истории необходимо загружать.
Строка Connector.LookupAll(); запрашивает имеющиеся данные.
![image6016.png image6016.png](https://stocksharp.ru/file/108069/image6016_png/?size=800x800)
После загрузки приложения перейдя в папку Data мы увидим, что появились новые папки.
![image7577.png image7577.png](https://stocksharp.ru/file/108070/image7577_png/?size=800x800)
А при повторном подключении панели инструментов и портфелей уже будут заполнены.
Создание панели со стратегией
Панель стратегий я буду создавать также, как и все предыдущие панели.
В папку XAML добавляем еще один UserControl. Дадим ему имя StrategyControl. С помощь LayoutControl разобьём экранную форму на две части.
В левой части будут вкладка с свечным графиком
![image344.png image344.png](https://stocksharp.ru/file/108071/image344_png/?size=800x800)
А также вкладка статистикой стратегии,
![image4907.png image4907.png](https://stocksharp.ru/file/108072/image4907_png/?size=800x800)
Здесь я использую StatisticParameterGrid для отображения статистики стратегии, а также EquityCurveChart для отображения графика прибыли и убытка.
У StatisticParameterGrid необходимо задать какое-нибудь значение MaxHeight иначе приложение не будет запускаться.
В правой части будет проводиться настройка свойств стратегии в PropertyGridEx
![image721.png image721.png](https://stocksharp.ru/file/108073/image721_png/?size=800x800)
А также кнопки запуска и остановки стратегии.
![image1047.png image1047.png](https://stocksharp.ru/file/108074/image1047_png/?size=800x800)
Полный код
![image2510.png image2510.png](https://stocksharp.ru/file/108075/image2510_png/?size=800x800)
В конструкторе StrategyControl задаем Connector как источники данных для PropertyGridEx, почти в каждом контроле мы выполняли подобные действия.
![image8773.png image8773.png](https://stocksharp.ru/file/108076/image8773_png/?size=800x800)
Нам необходимо как-то передать стратегию в наш контрол. Для этого в StrategyControl создам метод BindStraregy в который будет принимать стратегию, сохранять ссылку на нее в локальной переменной, а также задавать стратегию в PropertyGridEx и StatisticParameterGrid.
С помощь метода SetChart в стратегию предаём график свечей Chart, после этого в стратегии Chart можно будет получить с помощью метода GetChart. Также задаем Connector для стратегии.
![image8230.png image8230.png](https://stocksharp.ru/file/108077/image8230_png/?size=800x800)
При работе с графиком прибыли и убытков надо учесть, что стратегия будем запускать и останавливать и возможно несколько раз, поэму с каждым запуском стратегии график надо очищать. Для это создадим метод ResetEquityCurveChart в котором будем сначала очищать EquityCurveChart. После чего нам необходимо создать графические элементы для EquityCurveChart, им можно указать имя, цвет и тип линии.
![image6360.png image6360.png](https://stocksharp.ru/file/108078/image6360_png/?size=800x800)
После чего подпишемся на событие изменения PnL у стратегии и в обработчике этого события отрисовываем новое значение на графике прибыли убытков EquityCurveChart.
![image3106.png image3106.png](https://stocksharp.ru/file/108079/image3106_png/?size=800x800)
Полный код метода
![image2024.png image2024.png](https://stocksharp.ru/file/108080/image2024_png/?size=800x800)
В обработчике события нажатия на кнопку Старт будем вызвать этот метод. А также будем сбрасывать состояние стратегии и запускать ее.
![image3375.png image3375.png](https://stocksharp.ru/file/108081/image3375_png/?size=800x800)
В обработчике события нажатия на кнопку Стоп будем останавливать стратегию.
![image3399.png image3399.png](https://stocksharp.ru/file/108082/image3399_png/?size=800x800)
В центральную части MainWindow добавляем созданную панель StrategyControl
![image8678.png image8678.png](https://stocksharp.ru/file/108083/image8678_png/?size=800x800)
Создание стратегии
Для примера рассмотрим создание простой стратегии со свечами. Которая будет покупать если свеча растущая (зеленая) и продавать если свеча убывающая (красная).
Создадим еще одну папку в проекте в ней будем хранить все наши стратегии. В этой папке создаем новый класс и назовем его SimpleStrategy. Все стратегии S# должны наследоваться от базового класса стратегии Strategy.
![image1577.png image1577.png](https://stocksharp.ru/file/108084/image1577_png/?size=800x800)
Так как наша стратегия использует свечи то создадим публичное свойство CandleSeries а в конструкторе нашей стратегии зададим ему значение по умолчанию.
![image442.png image442.png](https://stocksharp.ru/file/108085/image442_png/?size=800x800)
Здесь я указал что свечи в CandleSeries будут TimeFrameCandle, с интервалом 15 секунд (TimeSpan.FromSeconds(15)). Для CandleSeries можно указать режим создания свечей BuildCandlesMode. Я указал что свечи будут построены (MarketDataBuildModes.Build), по умолчанию они будут строиться из тиков, но можно указать и другие типы данных.
Так как CandleSeries мы сделали публичным свойством, то CandleSeries можно будет дополнительно настроить из PropertyGridEx описанном в предыдущем пункте.
Все стратегии имеют методы который можно переопределить, нам понадобиться переопределить метод OnStarted. Который вызывается перед запуском стратегии и позволяет предварительно задать ей стартовое состояние.
![image6026.png image6026.png](https://stocksharp.ru/file/108086/image6026_png/?size=800x800)
Здесь мы для CandleSeries задаем инструмент, который указывается в PropertyGridEx. После чего создаем правило обработки законченной свечи. О работе с правилами можно ознакомиться в документации. В правиле указываем метод, который будет обрабатывать каждую законченную свечу в нашем случае это метод ProcessCandle он будет описан позже. После того как все задано подписываемся на появление свечей по CandleSeries в коннекторе через метод SubscribeCandles.
В нашем случае метод ProcessCandle и содержит основную логику стратегии.
![image3324.png image3324.png](https://stocksharp.ru/file/108087/image3324_png/?size=800x800)
В первую очередь нам необходимо определить является ли свеча реал тайм или исторической, если свеча историческая, то мы ее игнорируем. Не все стратегии требуют этого, например для стратегий основанные на стаканах не требуют этого так как стаканы идут всегда реал тайм. Нет универсального способа определить является ли свеча реал тайм или исторической, и в каждой стратегии эту проблему придется решать самостоятельно в зависимости от требований стратегии. В данном случае я просто буду сравнивать время закрытие свечи с временем в коннекторе и если оно не превышает определенный лаг, то свечу считаю реал тайм.
![image2732.png image2732.png](https://stocksharp.ru/file/108088/image2732_png/?size=800x800)
Далее смотрим на то какая это свеча и какая текущая позиция у стратегии. Если свеча растущая, то при позиции равной 0 мы откроем позицию рыночным ордером на объём, заданный нами в PropertyGridEx. Если свеча растущая и позиция меньше 0 то мы переворачиваем позицию.
![image4474.png image4474.png](https://stocksharp.ru/file/108089/image4474_png/?size=800x800)
Противоположные действия делаем для убывающей свечи.
![image5127.png image5127.png](https://stocksharp.ru/file/108090/image5127_png/?size=800x800)
На данный момент наша стратегия готова к работе. Ее необходимо передать в SimpleStrategyControl который мы создали в предыдущем пункте с помощью метода BindStraregy. Это мы делаем в конструкторе MainWindow сразу после инициализации компонентов MainWindow.
![image374.png image374.png](https://stocksharp.ru/file/108091/image374_png/?size=800x800)
Запустим для проверки.
![image9399.png image9399.png](https://stocksharp.ru/file/108092/image9399_png/?size=800x800)
![image5010.png image5010.png](https://stocksharp.ru/file/108093/image5010_png/?size=800x800)
Стратегия работает, совершаются сделки, но пока нет свечей и сделок на графике.
Добавление свечей и сделок на график из стратегии
В пункте про панель стратегий с помощь метода SetChart в стратегию мы предали график свечей Chart. В методе OnStarted стратегии проверяем установлен ли График у стратегии и если он установлен, то инициализируем график, а также подписываемся на события появления новой собственной сделки и изменения свечи.
![image5547.png image5547.png](https://stocksharp.ru/file/108094/image5547_png/?size=800x800)
Метод инициализации графика InitChart.
![image977.png image977.png](https://stocksharp.ru/file/108095/image977_png/?size=800x800)
Здесь мы сохраняем ссылку на Сhart в локальной переменной. Очищаем график. А также создаем и передаем на график элементы графика для свечей и сделок.
Конструкция _chart.GuiSync(() =>{ ... }); нужна для того чтобы инициализация графика выполнилась в главном потоке.
Метод отрисовки свечей на графике CandleSeriesProcessing.
![image9921.png image9921.png](https://stocksharp.ru/file/108096/image9921_png/?size=800x800)
Здесь мы получаем свеча из события CandleSeriesProcessing коннектора, создаем ChartDrawData для отображения его на графике. Указываем время data.Group(candle.OpenTime), указываем что свечу надо добавить в свечной элемент графика .Add(_chartCandleElement, candle);. И указываем что графику надо прорисовать новые данные.
Аналогичные действия выполняем для сделок.
![image4611.png image4611.png](https://stocksharp.ru/file/108097/image4611_png/?size=800x800)
Запустим для проверки.
![image944.png image944.png](https://stocksharp.ru/file/108098/image944_png/?size=800x800)
Краткий вывод
Для создание сложного и профессионально выглядящего приложения не нужно тратить массу времени. Мы за несколько часов создали полноценное приложение с возможностью конфигурирование, отображения и непосредственной торговли.
Не бойтесь пробовать и создавать свои программы. Надеюсь, эта статья вам поможет освоиться в этом деле.