Пример «Таблица в окне параметров 2» CustomTableInTheParamWindowSample.

Пример «Таблица в окне параметров 2» CustomTableInTheParamWindowSample.

 

В окно параметров OsEngine можно выводить не только параметры, но и другие элементы, включая таблицы и чарты.

Данный пример робота служит демонстрацией реализации кастомной таблицы в окне параметров.

В нем показано:

· Динамическая таблица: Таблица обновляется в реальном времени по мере поступления новых данных.

· Взаимодействие с пользователем: Пользователь может изменять данные в таблице и получать значения конкретных ячеек.

· Настраиваемые параметры: Возможность включать и отключать робота и также настройка трейлинг-стопа для выхода.

 

1. Как это выглядит.

Заходим в тестер и запускаем нашего робота, открываем окно параметров.

Называется: CustomTableInTheParamWindowSample.

1. Вкладка настроек «Base settings»:

В ней находятся настройки:

1. Regime - включение режима торговли.
2. TrailingValue – коэффициент для расчета трейлинг-стопа.
3. MaxPositions – максимальное количество открытых позиций.
4. Volume type – режим выбора объёма.

· Contracts – кол-во контрактов инструмента.

· Contract currency – валюта контракта.

· Deposit percent – процент от депозита.

5. Volume – значение объёма. Что именно, зависит от предыдущего пункта. В случае Contracts тут указывается объём инструмента. В случае Contract currency здесь указывается кол-во рублей или долларов, которыми нужно войти. В случае с Deposit percent здесь указывается % от общего депозита, которым нужно войти в контракт.

6. Asset in portfolio – тут нужно указывать название валюты, которое будет использовано для расчёта объёма, если Вы выбрали тип объёма “Deposit percent”. В тестере оставляем «Prime». На крипте это обычно “USDT”.

2. Вкладка настроек «Table settings»:

Здесь у нас находится сама таблица:

· Security – столбец с названием бумаг.

· Count candle – глубина данных, на которую проверяем движение (Movement to enter).

· Movement to enter – этот столбец мы тоже сами заполняем, он нам потребуется в торговой логике. Если Current movement будет больше Movement to enter, мы заходим в позицию.

· Current movement – текущий процент движения цены бумаги.

· Side – выбор метода входа для каждой бумаги.

 

2. Где найти робота в проекте?

Ссылка на робота GitHub: Ссылка

 

3. Разбор робота.

Строки 1-11:

Импортируются необходимые пространства имен:

Строки 23-26:

Определяется пространство имен OsEngine.Robots.TechSamples для организации кода и класс CustomTableInTheParamWindowSample наследует от BotPanel:

Строки 31-39:

Переопределение методов GetNameStrategyType и ShowIndividualSettingsDialog.

Первый метод возвращает имя стратегии, второй - пустой, предназначен для отображения индивидуальных настроек.

Строка 44-49:

Создание параметров робота:

Строки 51-52:

Инициализируется панель бота:

Cоздается одна вкладка скринера и сохраняется ссылка на вкладку в _tab для дальнейшего использования.

Строки 56-64:

Создание вкладки и самой таблицы для нее:

 

Создание вкладки и настройка ее размеров.

Строка 68:

Вызов метода LoadLines:

Строки 72-74:

Подписка на события:

Событие завершения свечи, удаление робота и обновление значений таблицы.

 

Строки 83-96:

Этот блок отвечает за набор переменных робота:

 

Строки 101-118:

Метод передает изменения, внесенные пользователем в логику робота:

 

Метод CellValueChanget:

1. Итерация по строкам DataGridView:

· Проходит по каждой строке в DataGridView.

2. Обновление свойств объектов Lines:

· Извлекает значения из ячеек текущей строки и присваивает их соответствующим свойствам объектов в коллекции Lines.

· Security: Строковое значение из первой ячейки.

· CandleCount: Целочисленное значение из второй ячейки.

· MovementToEnter: Десятичное число из третьей ячейки.

· Side: Перечисление типа Side, полученное из пятой ячейки.

3. Сохранение изменений:

· Вызывает метод SaveLines() для сохранения обновленных данных.

4. Обработка исключений:

· Оборачивает весь код в блок try-catch для перехвата возможных исключений.

· При возникновении исключения записывает его сообщение в лог с помощью метода _tab.SendNewLogMessage().

 

Строки 123-129:

Данный метод вызывается при удалении робота:


Метод DeleteBotEvent:

1. Проверка существования файла:

· Метод File.Exists проверяет, существует ли файл по указанному пути.

2. Удаление файла:

· Если файл существует, метод File.Delete удаляет его.

 

Строки 134-152:

Сохраняем данные из таблицы в .txt файл:

Метод SaveLines:

1. Создание потока записи:

· Создает новый поток записи (StreamWriter) в указанном файле. Файл создается или перезаписывается в зависимости от второго аргумента конструктора (false).

2. Итерация по строкам Lines.

3. Запись данных в файл:

· Каждая строка записывается в файл, разделяя ячейки знаком “%”.

4. Закрытие потока записи:

· Закрывает поток записи.

5. Обработка исключений:

· Оборачивает весь код в блок try-catch для перехвата возможных исключений.

· При возникновении исключения записывает его сообщение в лог с помощью метода _tab.SendNewLogMessage().

 

Строки 157-187:

Загружаем сохраненные данные в таблицу:

Метод LoadLines:

1. Проверка существования файла:

· Проверяет, существует ли файл с указанным именем.

2. Загрузка данных из файла:

· Если файл существует, открывает его для чтения.

· Читает каждую строку из файла и создает новый объект TableBotLine.

· Добавляет созданный объект в коллекцию Lines.

· Закрывает поток чтения.

3. Обновление DataGridView:

· Добавляет новые строки в DataGridView на основе данных из коллекции Lines.

 

Строки 193-199:

Событие завершения свечи:

Метод _tab_CandleFinishedEvent:

1. _tab_CandleFinishedEvent(List<Candle> candles, BotTabSimple tab):

· Этот метод вызывается при завершении каждой свечи.

· Аргумент tab представляет собой объект, который содержит информацию об этой новой вкладке.

· Вызываются все методы, находящиеся внутри.

 

Строки 204-261:

Метод, отвечающий за создание столбцов в таблице:

Метод CreateColumnsTable:

1. Проверка потока:

· MainWindow.GetDispatcher.CheckAccess(): Проверяет, вызывается ли метод из UI-потока.

· Если метод вызывается не из UI-потока, то он рекурсивно вызывает себя в контексте UI-потока, чтобы обеспечить безопасное обновление пользовательского интерфейса.

2. Создание контейнера для DataGrid:

· Создается объект WindowsFormsHost, который позволяет разместить элемент управления Windows Forms (DataGrid) в приложении WPF.

3. Создание DataGrid:

· Создается объект DataGrid, и настраиваются его основные свойства:

· Режим выбора строк: Выбирается режим, при котором можно выбрать всю строку целиком.

· Автоматическое изменение высоты строк: Строки будут автоматически подстраиваться по высоте содержимого.

· Выравнивание текста: Текст в ячейках выравнивается по центру как по горизонтали, так и по вертикали.

4. Создание столбцов:

· Создаются пять столбцов с названиями "Security", "Count candle", "Movement to enter", "Сurrent movement" и "Side".

· Для каждого столбца задается тип ячейки (DataGridViewTextBoxCell), ширина столбца (автоматическое заполнение) и заголовок.

5. Добавление столбцов в DataGrid:

· Созданные столбцы добавляются в коллекцию столбцов DataGrid.

6. Размещение DataGrid в контейнере:

· Объект DataGrid устанавливается в качестве дочернего элемента объекта WindowsFormsHost.

7. Обработка ошибок:

· В блоке try-catch обрабатываются возможные исключения. В случае ошибки выводится сообщение в лог.

 

Строки 266-302:

Метод, который добавляет новые строки в таблицу:


Метод AddNewLineInTable:

1. Проверка наличия инструмента:

· Если для вкладки не задан финансовый инструмент (tab.Security == null), метод прерывает свою работу.

2. Поиск существующей строки:

· Происходит итерация по всем строкам таблицы.

· Если значение в первом столбце строки (название инструмента) совпадает с названием инструмента текущей вкладки, то считается, что строка для этого инструмента уже существует.

3. Создание новой строки:

· Если строка для инструмента не найдена, создается новый объект TableBotLine с необходимыми значениями (название инструмента, количество свечей, движение для входа и т.д.).

· Этот объект добавляется в коллекцию строк.

· Вызывается метод CreateRowsTable для обновления отображения таблицы.

 

Строки 307-325:

Методы для обновления отображения таблицы:

Метод CreateRowsTable:

1. Проверка потока:

· _tableDataGrid.InvokeRequired: Проверяет, вызывается ли метод из UI-потока.

· Если метод вызывается не из UI-потока, то он рекурсивно вызывает себя в контексте UI-потока, чтобы обеспечить безопасное обновление пользовательского интерфейса.

2. Добавление строки:

· Вызывает метод CreateLine для создания новой строки данных и добавляет ее в таблицу.

3. Сохранение изменений:

· Вызывает метод SaveLines для сохранения изменений в таблице.

4. Обработка ошибок:

· В блоке try-catch обрабатываются возможные исключения. В случае ошибки выводится сообщение в лог.

 

Строки 327-364:

Этот метод создает линию и возвращает ее вызывающему методу:

Метод CreateLine:

1. Создание строки:

· Создается новый объект DataGridViewRow - строка для таблицы.

2. Создание ячеек:

· Для каждого поля объекта TableBotLine создается соответствующая ячейка таблицы (DataGridViewTextBoxCell или DataGridViewComboBoxCell).

· Ячейки добавляются в коллекцию ячеек строки (row.Cells.Add).

· Для некоторых ячеек устанавливается свойство ReadOnly = true, что делает их содержимое неизменяемым пользователем.

3. Заполнение ячеек данными:

· В блоке try-catch происходит заполнение ячеек значениями из объекта Lines[index]:

· Ячейка "Security" заполняется названием инструмента.

· Ячейка "CandleCount" заполняется количеством свечей для расчета текущего движения.

· Ячейка "MovementToEnter" заполняется значением движения для входа.

· Ячейка "CurrentMovement" заполняется значением текущего движения с добавлением символа процента "%".

· Ячейка "Side" заполняется текстовым представлением стороны сделки ("Buy" или "Sell") на основе значения поля Side объекта TableBotLine.

4. Обработка ошибок:

· В случае возникновения исключения при работе с данными выводится сообщение в лог.

5. Возврат строки:

· Заполненная строка таблицы возвращается вызывающему методу.

 

Строки 369-420:

Этот метод сортирует линии:

Метод SortLine:

1. Проверка потока:

· _tableDataGrid.InvokeRequired: Проверяет, вызывается ли метод из UI-потока.

· Если метод вызван не из UI-потока, то он рекурсивно вызывает себя в контексте UI-потока для безопасного обновления интерфейса.

2. Проверка последней строки:

· Проверяет, содержит ли последняя строка таблицы какое-либо значение в первом столбце (_tableDataGrid.Rows[_tableDataGrid.Rows.Count - 1].Cells[0].Value.ToString()).

· Если значение отсутствует, метод завершается, не выполняя дальнейшую обработку.

3. Итерация по строкам:

· Внешний цикл: Перебирает все строки таблицы (_tableDataGrid.Rows.Count).

4. Поиск инструмента:

· Внутренний цикл: Перебирает все вкладки приложения (_tab.Tabs.Count).

· Для каждой строки проверяет, совпадает ли название инструмента в первом столбце (_tableDataGrid.Rows[i].Cells[0].Value.ToString()) с названием инструмента какой-либо вкладки.

· Если совпадение найдено, флаг GotLine устанавливается в true, что означает, что строка найдена.

5. Удаление неиспользуемых строк:

· После прохода по всем строкам, если флаг GotLine остался false (ни для одной строки не найдено совпадение со вкладкой), значит, эта строка не нужна.

· Индекс ненужной строки сохраняется в переменной indexLine.

· Строка с этим индексом удаляется из таблицы с помощью метода _tableDataGrid.Rows.Remove.

· Вызывается метод SaveLines для сохранения изменений.

6. Обработка ошибок:

· В блоке try-catch обрабатываются возможные исключения при работе с данными. В случае ошибки выводится сообщение в лог.

 

Строки 425-479:

Метод обновления текущего процента движения:

Метод MovementPercentUpdate:

1. Проверка потока:

· _tableDataGrid.InvokeRequired: Проверяет, вызывается ли метод из UI-потока.

· Если метод вызван не из UI-потока, то он рекурсивно вызывает себя в контексте UI-потока для безопасного обновления интерфейса.

2. Поиск строки таблицы:

· Ищет строку в таблице, соответствующую инструменту из вкладки (tab.Security.Name).

· Перебирает все строки коллекции Lines и сравнивает значения поля Security с названием инструмента.

· Если совпадение найдено, то сохраняется индекс строки (indexLine) и флаг GotLine устанавливается в true.

3. Проверка количества свечей:

· Сравнивает количество свечей в полученном списке свечей (candles.Count) с количеством свечей, указанным в найденной строке таблицы (TableCandlesCount).

· Если количество свечей в списке меньше, чем в таблице, метод завершает работу, так как для расчета недостаточно данных.

4. Обновление значения процента изменения цены:

· Если строка найдена (GotLine == true), выполняется расчет процента изменения цены в зависимости от направления сделки (Lines[indexLine].Side):

· Для сделок на покупку (Buy): рассчитывается изменение цены как разница между ценой закрытия предпоследней свечи (candles[candles.Count - Lines[indexLine].CandelCount].Close) и ценой закрытия последней свечи (candles[candles.Count - 1].Close), деленная на цену закрытия последней свечи и умноженная на 100.

· Для сделок на продажу (Sell): расчет аналогичен, но разница цен берется с обратным знаком.

· Результат расчета округляется до двух знаков после запятой (Math.Round) и сохраняется в поле CurrentMovement объекта Lines[indexLine].

· Значение процента изменения цены с добавлением символа "%" устанавливается в соответствующую ячейку таблицы (_tableDataGrid.Rows[indexLine].Cells[3].Value).

5. Сохранение изменений:

· Вызывается метод SaveLines для сохранения изменений в таблице данных.

6. Обработка ошибок:

· В блоке try-catch обрабатываются возможные исключения при работе с данными. В случае ошибки выводится сообщение в лог.

 

Строки 488-565:

Торговая логика:

Метод TradeLogicMethod:

1. Проверка активности режима:

· Если значение равно "Off", то метод завершается, не выполняя дальнейшие действия.

2. Проверка наличия свечей:

· Если список пустой, метод завершается, так как для анализа недостаточно данных.

3. Поиск строки таблицы:

· Перебирает все строки коллекции Lines и сравнивает значения поля Security с названием инструмента.

· Если совпадение найдено, то сохраняется индекс строки (indexLine), и флаг GotLine устанавливается в true.

4. Проверка наличия строки:

· Если строка в таблице не найдена (GotLine == false), метод завершается.

5. Получение открытых позиций:

· Из вкладки (tab) извлекается список открытых позиций (positions.Count).

6. Логика открытия позиции (если нет открытых позиций):

· Если открытых позиций нет (positions.Count == 0), выполняется проверка условия для открытия позиции:

· Проверяем, не превышает ли общее количество позиций максимального значение, если превышает, то выходим.

· Значение движения для входа в позицию (movementToEnter) извлекается из соответствующей ячейки таблицы (_tableDataGrid.Rows[indexLine].Cells[2].Value.ToString()) и преобразуется в десятичное число.

· Сравнивается текущее движение цены (Lines[indexLine].CurrentMovement) с заданным движением для входа.

· Если текущее движение превышает заданное значение (movementToEnter < Lines[indexLine].CurrentMovement), в зависимости от направления сделки выполняется покупка по рынку с объемом лота, который рассчитывает метод GetVolume, и продажа по рынку с объемом лота, который рассчитывает метод GetVolume.

7. Логика обновления стоп-лосса (если есть открытые позиции):

· Если позиция не открыта (PositionStateType.Open), метод завершается.

· В зависимости от направления открытой позиции (positions[0].Direction):

1. Для позиции на покупку (Buy) рассчитывается цена стоп-лосса как разница между минимальной ценой последней свечи и произведением этой цены и значения трейлинга, деленным на 100.

2. Для позиции на продажу (Sell) рассчитывается цена стоп-лосса как сумма максимальной цены последней свечи и произведения этой цены и значения трейлинга, деленным на 100.

· Вызывается метод CloseAtTrailingStop вкладки для обновления стоп-лосса открытой позиции (positions[0]) по рассчитанной цене.

 

Строки 567-656:

Метод GetVolume:

1. Инициализация:

· Создается переменная volume со значением 0 для хранения результата.

2. Проверка типа объема:

· Контракты: Если тип объема установлен как "Contracts", то в качестве объема используется значение из переменной Volume.

· Контрактная валюта:

· Если тип объема установлен как "Contract currency", то объем рассчитывается делением значения Volume на цену последнего спроса.

· Корректировка для OS Trader: Если приложение запущено в режиме OS Trader, то объем дополнительно корректируется с учетом лота инструмента и настроек сервера.

· Округление: Результат округляется до числа десятичных знаков, указанного в настройках инструмента.

· Процент от депозита:

· Если тип объема установлен как "Deposit percent", то:

· Определяется текущая стоимость портфеля в основной валюте.

· Рассчитывается сумма денег, которую необходимо вложить в сделку, исходя из указанного процента от портфеля.

· Объем рассчитывается делением этой суммы на цену последнего спроса и лот инструмента.

· Результат округляется.

3. Возврат результата:

· Возвращается вычисленное значение объема.

 

Строки 661-696:

Отдельный класс для хранения и передачи данных о строках таблицы:

Свойства:

· Security: Строка, содержащая название финансового инструмента.

· CandelCount: Целое число, указывающее количество свечей, связанных с этим инструментом.

· MovementToEnter: Десятичное число, представляющее значение движения цены, необходимое для входа в позицию.

· CurrentMovement: Десятичное число, представляющее текущее движение цены.

· Side: Перечисление (enum), определяющее сторону сделки (покупка или продажа).

 

Метод GetSaveStr:

· Инициализация строки: Создается пустая строка saveStr, которая будет использоваться для сборки конечного результата.

· Конкатенация значений:

· К строке saveStr последовательно добавляются значения переменных Security, CandleCount, MovementToEnter и CurrentMovement, разделенных символом процента (%).

· Затем добавляется значение переменной Side без дополнительного разделителя.

· Возврат результата: Готовая строка возвращается как результат работы метода.


Метод SetFromStr:

· Разбиение строки: Строка разбивается на массив строк по знаку “%”.

· Заполнение свойств:

· Security: Первое значение массива присваивается свойству Security.

· CandelCount: Второе значение преобразуется в целое число и присваивается свойству CandleCount.

· MovementToEnter: Третье значение преобразуется в десятичное число и присваивается свойству MovementToEnter.

· CurrentMovement: Четвертое значение очищается от последнего символа (предполагается, что это символ процента) и преобразуется в десятичное число, присваивается свойству CurrentMovement.

· Side: Пятое значение используется для попытки преобразования в перечисление Side. Если преобразование успешно, значение присваивается свойству Side.

Вывод: этот пример робота будет полезен для демонстрации, как создавать и настраивать кастомные элементы в окне параметров робота. Он показывает, как создавать таблицу для вывода значений и использование ее пользователями, что может служить готовым шаблоном для реализации подобных задач.

 

Удачных алгоритмов!

 

 

Поддержка OsEngine: https://t.me/osengine_official_support

 

16:23
191

Комментарии

Нет комментариев. Ваш будет первым!