Восстановление сохраненной стратегии
Atom Ответить
25.09.2014


Восстановить сохраненную стратегию можно через SettingsStorage, но туда попадают только настройки, вернуть полностью состояние не получается. То есть, если совершить сделку, сохранить, то при восстановлении сделка теряется.
Если настроить сохранение еще можно, то как восстановить сделки(Trade), по которым открыта позиция.

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

Теги:


Спасибо:




27 Ответов
1 2  >
RomSunZ

Фотография
Программист
Дата: 26.09.2014
Ответить


Есть описание в хелпе в разделе про стратегии. Называется загрузка заявок и сделок.
Спасибо:

Andrii

Фотография
Дата: 01.10.2014
Ответить


RomSunZ Перейти
Есть описание в хелпе в разделе про стратегии. Называется загрузка заявок и сделок.

читал, там описывается как восстановить заявки(Order), но не все заявки заканчиваются удачно, нет метода восстановить сделки(Trade)
нет реального примера?
или ему нужно скормить сделки, которые прошли, или все можно, а он сам поймет?
Автор топика
Спасибо:

devruss

Фотография
Курсы
Дата: 01.10.2014
Ответить


Andrii Перейти
RomSunZ Перейти
Есть описание в хелпе в разделе про стратегии. Называется загрузка заявок и сделок.

читал, там описывается как восстановить заявки(Order), но не все заявки заканчиваются удачно, нет метода восстановить сделки(Trade)
нет реального примера?
или ему нужно скормить сделки, которые прошли, или все можно, а он сам поймет?


На самом деле очень важный вопрос, я для себя так решения и не нашел.

Можно даже обобщить задачу: Есть 2 робота, они торгуют один и тот же инструмент (допустим RiZ4), но на разных таймфреймах, стратегиях и т.д. Произошло отключение (обрыв связи или отключение overnight),
на момент обрыва первый был long 100 контрактов, второй 400.
1. Как после восстановления соединения восстановить правильную позицию у роботов? (именно сделки, а не ордера)
2. Как эти 2 робота поделят общую позицию по RiZ4 (500: +100 (1) +400 (2))? (т.е. как роботом понять какая часть сделок его, а какая нет)

Уверен, что те, кто силен в программировании уже реализовали данную задачу, поделитесь пожалуйста методом решения

Спасибо:

RomSunZ

Фотография
Программист
Дата: 01.10.2014
Ответить


Ну так сохраняйте сделки/ордера во временный файл или в коллекцию после их появления с идентификатором для каждой стратегии, а потом восстанавливайте их от туда.
Спасибо:

Andrii

Фотография
Дата: 01.10.2014
Ответить


RomSunZ Перейти
Ну так сохраняйте сделки/ордера во временный файл или в коллекцию после их появления с идентификатором для каждой стратегии, а потом восстанавливайте их от туда.

каким образом восстанавливать сделки?
или даже как правильно все реализовать? пример есть?
Автор топика
Спасибо:

RomSunZ

Фотография
Программист
Дата: 02.10.2014
Ответить


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

Andrii

Фотография
Дата: 02.10.2014
Ответить


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


восстановить стратегию нахожу, но мне бы ее сделки

нахожу
Код
this.StatisticManager.AddNewOrder();
this.ProcessNewOrders();


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

на текущий момент this.ProcessNewOrders(); не отрабатывает
Автор топика
Спасибо:

Andrii

Фотография
Дата: 02.10.2014
Ответить


так же есть AttachOrder, но как будет корректно не особо понятно, хочется опытное мнение
Автор топика
Спасибо:

Andrii

Фотография
Дата: 03.10.2014
Ответить


секретные разработки?
Автор топика
Спасибо:

JaguarFX

Фотография
Курсы
Дата: 05.10.2014
Ответить


Andrii Перейти
секретные разработки?

Поиск по форуму - лучшее лекарство от подозрительности))
Так мной было описан полный набор функций для сохранения заявок/сделок по стратегии в базу данных в разделе по развитию S#.Shell Ссылка

Сейчас по прошествии 2-х месяцев могу сказать что все работает на 100%.
Однако я внес следующие изменения в подход к сохранению позиций:
1) заменил сохранение в MS SQL на сохранение в MS Access, используя универсальный интерфейс OleDb;
все-таки Access проше, систему не грузит и занимает в 10ки раз меньше места,
2) вообще прекратил сохранять заявки и сделки, сохраняю только позиции; для хранения позиций пришлось сделать отдельный класс TradeBook, в котором как раз расписано для каждой стратегии какую она имеет долю в "общем пироге" открытой по инструменту позиции - это к вопросу devruss'а относительно учета результатов работы нескольких стратегий с одним счетом и инструментом.
Спасибо: Andrii devruss Mikhail Sukhov

Andrii

Фотография
Дата: 05.10.2014
Ответить


lebedevsrg Перейти
Andrii Перейти
секретные разработки?

Поиск по форуму - лучшее лекарство от подозрительности))
Так мной было описан полный набор функций для сохранения заявок/сделок по стратегии в базу данных в разделе по развитию S#.Shell Ссылка

Сейчас по прошествии 2-х месяцев могу сказать что все работает на 100%.
Однако я внес следующие изменения в подход к сохранению позиций:
1) заменил сохранение в MS SQL на сохранение в MS Access, используя универсальный интерфейс OleDb;
все-таки Access проше, систему не грузит и занимает в 10ки раз меньше места,
2) вообще прекратил сохранять заявки и сделки, сохраняю только позиции; для транения позиций пришлось сделать отдельный класс TradeBook, в котором как раз расписано для каждой стратегии какую она имеет долю в "общем пироге" открытой по инструменту позиции - это к вопросу devruss'а относительно учета результатов работы нескольких стратегий с одним счетом и инструментом.


У меня тоже подход по позициям, каждый имеет свою долю и это фиксируется.
Может наивно, но так же использую\отображаю график PnL и статистику, вот и для этого и нужны, чтобы отображались корректно. Или это лучше самому считать?

Но в целом я понял, используется AttachOrder и его сделками... этого и хотел
Автор топика
Спасибо:

RomSunZ

Фотография
Программист
Дата: 08.10.2014
Ответить


Супер секретная разработка по сохранению/восстановлению стратегий:
[url]http://stocksharp.com/forum/4045/S--Shell--Manual/?page=2
Спасибо:

devruss

Фотография
Курсы
Дата: 08.10.2014
Ответить


Большое спасибо за ответ. Так как я не программист, мне потребовалось несколько дней, чтобы разобраться в коде
Есть несколько вопросов:
- Ваша идея восстановления позиции состоит в том, чтобы при каждом запуске заново грузить все сделки и по ним считать позицию. Для этого сделки хранятся в БД. Это абсолютно верно, что из сделок можно получить поозицию, но, как мне кажется, избыточно.
Был ли рассмотрен следующий подход: при совершении сделки (partial fill/ full fill), меняется позиция. Робот узнает об изменении позиции только от feedback от биржи о статусе исполненного ордера (ну либо если ордер лимитный, и робот знает, что пришел confirmation о том, что он выставлен, + цена прошла уровень ордера, то автоматом считаем ордер исполненным - нужно для HFT). Так вот, как только робот узнает об изменении позиции, вместо того, чтобы тут же сохранять сделку в БД он просто записывает в файл позицию. При старте робота, не нужно выгружать все сделки, а только сообщить стартовую позицию и все.

- Встает вопрос, за какой период нужно выгружать сделки. Если робот торгует длинные таймфремы, то это может быть и несколько месяцев. А это дофига сделок, если есть в портфеле есть стратегии торгующие high frequency и low frequency.

- В чем потенциальные минусы предложенного подхода в сравнении с уже реализованным выше. Может я упускаю какие-то тонкости?
Спасибо:

JaguarFX

Фотография
Курсы
Дата: 08.10.2014
Ответить


Тут в каждом подходе есть свои плюсы и свои минусы.

1. Восстановление позиций через восстановление заявок/сделок
Очевидный плюс - получение полноценной статистики и PnL на основе свойств стратегии.
Минус - при большом числе заявок/сделок перфоманс при старте падает.
Кроме того у меня при количестве заявок прим. от 2000 / сделок от 3000 стали возникать проблемы с тем, что предварительный запрос на очистку таблиц от старых записей в целях исключения дублирований стал прерываться при старте следующего по коду запроса на запись, и как результат пошла мультипликация записей. Возможно там для решения проблемы нужно было перейти на асинхронный вызов и дожидаться выполнения первого запроса из кода, но я к этому моменту осознал избыточность для моих интересов данного подхода и остановил запись и восстановление заявок/сделок.
Перешел на подход №2.

2. Восстановление позиций через восстановление информации о позициях
Очевидный плюс - сохранение в БД только самой важной информации.
Далее, если объект заявка содержит только одно поле UserOrderId для хранения информации о сигнале на открытие позиции, то в собственном классе по позициям можно создать несколько полей для последующего использовании при принятии решения о закрытии позиции (н-р сигнал, тайм-фрейм) и подсчете доходов (н-р при торговле фичами размер резерва капитала, даты/спреды ролл-оверов).
Минус - необходимость создания собственного класса для хранения позиций и встраивание его работы в работу стратегии.
Кроме того стандартные статистика и PnL по стратегии теряют свою актуальность. Статистика конечно не столь важна, а вот для расчета PnL пришлось написать отдельную функцию. Для моей стратегии правда это было и так необходимо сделать, так как PnL с учетом колебаний рыночной стоимости не интересен, а интересна мгновенная и общая годовая доходность работы по сигналам.

Поэтому я бы сказал что выбор подхода тут сильно зависит от используемой стратегии. Для относительно простых стратегий с небольшим количеством сделок пойдет и 1й подход, для более сложных конечно удобней сделать свою логику.
Спасибо:

devruss

Фотография
Курсы
Дата: 09.10.2014
Ответить


lebedevsrg Перейти
Тут в каждом подходе есть свои плюсы и свои минусы.

1. Восстановление позиций через восстановление заявок/сделок

2. Восстановление позиций через восстановление информации о позициях


Я тоже создал свои классы и под хранение инфы по трейдам (не позициям), а также по правильному подсчету pnl, mark-to-market pnl, доходности и т.д.
Поправь меня если я не прав, но по ссылке выше ты рассказал именно про реализацию подхода 1 - восстановления позиции через сделки.
Тогда вопрос: Как реализовать именно вараинт 2?
По большому счету тут SQL не нужно. Достаточно 1 файл с элементами типа {Strategy ID/Name, Position}. И при перезапуске робота считывать эти данные и сообщать роботу с какой позицией он стартует. Тогда в общем случае и логику менять не надо, так как робот просто сразу переходит в состояние long/short N контрактов как бы пропуская фазу набора позиции.


Спасибо:

Andrii

Фотография
Дата: 09.10.2014
Ответить


devruss Перейти
lebedevsrg Перейти
Тут в каждом подходе есть свои плюсы и свои минусы.

1. Восстановление позиций через восстановление заявок/сделок

2. Восстановление позиций через восстановление информации о позициях


Я тоже создал свои классы и под хранение инфы по трейдам (не позициям), а также по правильному подсчету pnl, mark-to-market pnl, доходности и т.д.
Поправь меня если я не прав, но по ссылке выше ты рассказал именно про реализацию подхода 1 - восстановления позиции через сделки.
Тогда вопрос: Как реализовать именно вараинт 2?
По большому счету тут SQL не нужно. Достаточно 1 файл с элементами типа {Strategy ID/Name, Position}. И при перезапуске робота считывать эти данные и сообщать роботу с какой позицией он стартует. Тогда в общем случае и логику менять не надо, так как робот просто сразу переходит в состояние long/short N контрактов как бы пропуская фазу набора позиции.




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

покажешь свои классы "подсчету pnl, mark-to-market pnl, доходности и т.д." ?

Автор топика
Спасибо:

RomSunZ

Фотография
Программист
Дата: 09.10.2014
Ответить


А что мешает взять из БД позицию/ордера/сделки по последней открытой позиции, а сохраненные данные по предыдущим сделкам/позициям/ордерам использовать для анализа работы системы?
Спасибо:

devruss

Фотография
Курсы
Дата: 09.10.2014
Ответить


Цитата:

по большому счету да, сохраняешь состояние стратегии и восстанавливаешь его при создании. Но тогда теряется статистика стратегии... но если у тебя свои классы по ее подсчету, то можно себе позволить
покажешь свои классы "подсчету pnl, mark-to-market pnl, доходности и т.д." ?


В данном топике это оффтоп. На самом деле, я даже классы не делал. На каждом тике пересчитываю стоимость позиции (== mark to market), из этого получается и pnl при закрытии позиции (реализованный mark to market) и доходность (pnl/capital)
Спасибо:

devruss

Фотография
Курсы
Дата: 09.10.2014
Ответить


RomSunZ Перейти
А что мешает взять из БД позицию/ордера/сделки по последней открытой позиции, а сохраненные данные по предыдущим сделкам/позициям/ордерам использовать для анализа работы системы?


Я не понял, как можно передать роботу позицию? AttachOrder функция есть, а как указать текущую позицию при старте?
Спасибо:

Andrii

Фотография
Дата: 09.10.2014
Ответить


devruss Перейти
RomSunZ Перейти
А что мешает взять из БД позицию/ордера/сделки по последней открытой позиции, а сохраненные данные по предыдущим сделкам/позициям/ордерам использовать для анализа работы системы?


Я не понял, как можно передать роботу позицию? AttachOrder функция есть, а как указать текущую позицию при старте?


Код
Strategy str = new MyStrategy() { Position = 5 };

Автор топика
Спасибо: devruss

RomSunZ

Фотография
Программист
Дата: 09.10.2014
Ответить


devruss Перейти
RomSunZ Перейти
А что мешает взять из БД позицию/ордера/сделки по последней открытой позиции, а сохраненные данные по предыдущим сделкам/позициям/ордерам использовать для анализа работы системы?


Я не понял, как можно передать роботу позицию? AttachOrder функция есть, а как указать текущую позицию при старте?


Какой сайз и какое направление было у ордера, который через AttachOrder присоединяется к стратегии, такая поза у стратегии и будет. Если несколько ордеров, то позиция суммируется.
Спасибо:

devruss

Фотография
Курсы
Дата: 09.10.2014
Ответить


RomSunZ Перейти
Какой сайз и какое направление было у ордера, который через AttachOrder присоединяется к стратегии, такая поза у стратегии и будет. Если несколько ордеров, то позиция суммируется.


Это так, но я хочу уйти от связки "сделки - высчитываем позицию - позиция" к "записываем изменения позиции - при старте стратегии подается на вход тек. позиция".
Таким образом, мне
1. Не нужна БД. Достаточно 1 файла на стратегию с позицией
2. Быстрый старт

Если вдруг понадобится перейти от моего варианта к предложенному тобой, то этот файл с позицией можно формировать отдельно из сделок (или проверять). Таким образом мы делаем функционально независимый подход к управлению позицией
Спасибо:

Andrii

Фотография
Дата: 09.10.2014
Ответить


вообще все зависит от стратегии и нужных данных, но более универсальный метод - писать только сделки открывающие позицию:

открыли позицию - записали сделку - закрыли позицию - удалили 2 сделки

алгоритм сложный, но оставляет только сделки по открытым позициям
Автор топика
Спасибо:

devruss

Фотография
Курсы
Дата: 09.10.2014
Ответить


Andrii Перейти
вообще все зависит от стратегии и нужных данных, но более универсальный метод - писать только сделки открывающие позицию:

открыли позицию - записали сделку - закрыли позицию - удалили 2 сделки

алгоритм сложный, но оставляет только сделки по открытым позициям


Удалять - это сложно. А вот изменилась позиция - записали в файл, изменилась опять - опять записали, мне кажется как-то проще и fail proof
Спасибо:

Marco

Фотография
Программист
Дата: 10.10.2014
Ответить


devruss Перейти

Удалять - это сложно. А вот изменилась позиция - записали в файл, изменилась опять - опять записали, мне кажется как-то проще и fail proof


Мы например так и делаем. При каждом изменении позиции стратегии по инструментам сохраняются в .csv файл. При старте стратегии - восстанавливаются (без сделок и ордеров).

Код:
Код


        protected List<Position> LoadPositions(string fileName)
        {
            List<Position> positions = new List<Position>();

            using (StreamReader stream = new StreamReader(fileName))
            {
                using (CsvReader reader = new CsvReader(stream))
                {
                    reader.Configuration.Delimiter = ",";
                    reader.Configuration.HasHeaderRecord = false;

                    //var records = reader.GetRecords<MyTrade>();
                    while (reader.Read())
                    {
                        try
                        {
                            string securityCode = reader.GetField<string>(0);
                            decimal value = reader.GetField<decimal>(1);
                            string portfolioName = reader.GetField<string>(2);

                            Portfolio portfolio = Connector.Portfolios.FirstOrDefault((Portfolio pf) =>
                            {
                                return pf.Name == portfolioName;
                            });
                            if (portfolio == null)
                            {
                                this.AddWarningLog("Portfolio with name {0} not found.", portfolioName);
                                continue;
                            }

                            Security security = Connector.Securities.FirstOrDefault((Security sec) =>
                            {
                                return sec.Code == securityCode;
                            });
                            if (security == null)
                            {
                                this.AddWarningLog("Security with code {0} not found.", securityCode);
                                continue;
                            }

                            Position position = new Position()
                            {
                                Portfolio = portfolio,
                                Security = security,
                                CurrentValue = value
                            };

                            positions.Add(position);
                        }
                        catch (Exception ex)
                        {
                            this.AddErrorLog("Ошибка загрузки позиции: {0}", ex.Message);
                        }
                    }
                }
            }

            return positions;
        }


        protected void LoadPositions()
        {
            if (!SavePositionsEnabled)
                return;

            string fileName = GetPersistentFileName("positions", "csv");
            this.AddInfoLog("Загрузка позиций из файла {0}", fileName);

            if (File.Exists(fileName))
            {
                List<Position> positions;

                lock (lockPositionsFile)
                {
                    positions = LoadPositions(fileName);
                }

                PositionManager.Positions = positions;
                RaiseParametersChanged("Position");
            }
            else
            {
                this.AddWarningLog("Файла с сохраненными позициями {0} не существует.", fileName);
            }
        }

        protected void SavePositions(IEnumerable<Position> positions, string fileName, bool append)
        {
            using (StreamWriter stream = new StreamWriter(fileName, append))
            {
                using (CsvWriter writer = new CsvWriter(stream))
                {
                    writer.Configuration.Delimiter = ",";
                    writer.Configuration.HasHeaderRecord = false;

                    foreach (Position position in positions)
                    {
                        try
                        {
                            writer.WriteField(position.Security.Code, true);
                            writer.WriteField(position.CurrentValue);
                            writer.WriteField(position.Portfolio.Name);
                            writer.NextRecord();
                        }
                        catch (Exception ex)
                        {
                            this.AddErrorLog("Ошибка сохранения позиции {0}: {1}", position.ToString(), ex.Message);
                        }
                    }

                    stream.Flush();
                }
            }
        }

        protected void SavePositions(IEnumerable<Position> positions)
        {
            if (!SavePositionsEnabled)
                return;

            string fileName = GetPersistentFileName("positions", "csv");
            this.AddInfoLog("Сохранение позиций в файл {0}", fileName);

            lock (lockPositionsFile)
            {
                SavePositions(PositionManager.Positions, fileName, false);
            }
        }


                PositionsChanged += (IEnumerable<Position> positions) =>
                {
                    SavePositions(positions);
                };


SavePositions() вызывается при изменении позиции и остановке стратегии. LoadPositions - в Strategy.OnStarted().

Метод спорный, но у нас работает. При этом ломается расчет PnL (мы им все равно не пользуемся, PnL стратегий считается скриптами на Python'е по сохраненным трейдам раз в день после клиринга - StockSharp все равно PnL считает неправильно...)
Спасибо: devruss
1 2  >

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

loading
clippy