Событийный подход
Atom Ответить
28.03.2011


Доброго всем дня, особенно Михаилу :).
Начал осваивать событийный подход, забуксовал.

Подскажите, пожалуйста, как правильно запускать стратегию наподобие той,
что приведена в примере (class MyOwnStrategy : ActionStrategy)?
Нужно ли добавлять в нее конструктор и отдельно передавать Security?

Сейчас запускаю на ФОРТС так:

Код
_strategy = new MyOwnStrategy() { Volume = 1 };
_manager.Register(_strategy, this.Portfolios.SelectedPortfolio, _rts);
if (_strategy.ProcessState == StrategyProcessStates.Stopped)
    {
    _strategy.Start();
    }
    else
    {
    _strategy.Stop();
    }

Стратегия нормально запускается и останавливается из GUI примера SampleSMA, лог пишется, но сделок не происходит на любом таймфрейме.

Лог обычно такой:
MOS 20:34:52.0212958 Стратегия запущена.
MOS 20:36:11.3213772 Стратегия останавливается.
MOS 20:36:11.6273947 Стратегия остановлена.

Событийную стратегию взял из мануала, без изменений, версия 3.0.
Буду признателен за помощь.

Весь запускающий код, кроме самой стратегии из примера:

Код
namespace SampleSMA
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ComponentModel;
    using System.Globalization;
    using System.IO;
    using System.Threading;
    using System.Windows;
    using System.Windows.Forms;
    using MessageBox = System.Windows.MessageBox;
    using AmCharts.Windows.Stock;
using Ecng.Collections;
    using Ecng.Common;
    using Ecng.ComponentModel;
    using Ecng.Trading.Algo;
    using Ecng.Trading.Algo.Candles;
using Ecng.Trading.Algo.Logging;
    using Ecng.Trading.Algo.Reporting;
    using Ecng.Trading.Algo.Strategies;
    using Ecng.Trading.BusinessEntities;
    using Ecng.Trading.Quik;
    using Ecng.Trading.Xaml;
    using Ecng.Xaml;

    public partial class MainWindow
    {
        private readonly TimeSpan _timeFrame = TimeSpan.FromMinutes(1);
        private QuikTrader _trader;
        private MyOwnStrategy _strategy;
        private RealTimeStrategyManager _manager;
        private bool _isDdeStarted;
        private Security _rts;
public CandleManager _candleManager;

        public MainWindow()
        {
             InitializeComponent();

            // изменяет текущий формат, чтобы нецелое числа интерпритировалось как разделенное точкой.
             var cci = new CultureInfo(Thread.CurrentThread.CurrentCulture.Name) { NumberFormat = { NumberDecimalSeparator = "." } };
         Thread.CurrentThread.CurrentCulture = cci;

            }

        private void _orders_OrderSelected(object sender, EventArgs e)
        {
            this.CancelOrders.IsEnabled = _orders.SelectedOrders.Count() > 0;
        }

         protected override void OnClosing(CancelEventArgs e)
        {
            if (_trader != null)
            {
                _manager.Dispose();

                if (_isDdeStarted)
                    StopDde();

                _trader.Dispose();
            }

            base.OnClosing(e);
        }

        private void FindPath_Click(object sender, RoutedEventArgs e)
        {
            var dlg = new FolderBrowserDialog();

            if (!this.Path.Text.IsEmpty())
                dlg.SelectedPath = this.Path.Text;

            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.Path.Text = dlg.SelectedPath;
            }
        }

        private void Connect_Click(object sender, RoutedEventArgs e)
        {
            if (_trader == null || !_trader.IsConnected)
            {
                if (_trader == null)
                {
                    if (this.Path.Text.IsEmpty())
                    {
                        MessageBox.Show(this, "Путь к Quik не выбран.");
                        return;
                    }

                    // создаем шлюз
                    _trader = new QuikTrader(this.Path.Text);

                    // создаем менеджер стратегий
                    _manager = new RealTimeStrategyManager(_trader);

                    this.Portfolios.Trader = _trader;

                    _trader.Connected += () =>
                    {
_candleManager = new CandleManager(_trader);

_trader.NewSecurities += securities => this.GuiAsync(() =>
                        {
                            // находим нужную бумагу
                            var rts = securities.FirstOrDefault(s => s.Code == "RIM1");

                            if (rts != null)
                            {
                                _rts = rts;

                                this.GuiAsync(() =>
                                {
                                    this.Start.IsEnabled = true;
                                });
                            }
                        });

                        
                        _trader.ConnectionError += ex =>
                        {
                            if (ex != null)
                                this.GuiAsync(() => MessageBox.Show(this, ex.ToString()));
                        };

                        this.GuiAsync(() =>
                        {
                            this.ConnectBtn.IsEnabled = false;
                            this.ExportDde.IsEnabled = true;
                            this.Report.IsEnabled = true;
                        });
                    };
                }

                _trader.Connect();
            }
            else
                _trader.Disconnect();
        }

    private void OnNewOrder(Order order)
        {
            _orders.Orders.Add(order);
            this.GuiAsync(() => _chart.Orders.Add(order));
        }

        private void OnLog(Strategy strategy, StrategyErrorStates errorState, string message)
        {
            // если стратегия вывела не просто сообщение, то вывести на экран.
            if (errorState != StrategyErrorStates.None)
                this.GuiAsync(() => MessageBox.Show(this, message));
        }

        
        private void OnStrategyPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.GuiAsync(() =>
            {
                this.Status.Content = _strategy.ProcessState;
                this.PnL.Content = _strategy.PnLManager.PnL;
                this.Slippage.Content = _strategy.SlippageManager.Slippage;
                this.Position.Content = _strategy.PositionManager.Position;
                this.Latency.Content = _strategy.LatencyManager.Latency;
            });
        }

        private void StartDde()
        {
            _trader.StartExport();
            _isDdeStarted = true;
        }

        private void StopDde()
        {
            _trader.StopExport();
            _isDdeStarted = false;
        }

        private void ExportDde_Click(object sender, RoutedEventArgs e)
        {
            if (_isDdeStarted)
                StopDde();
            else
                StartDde();
        }

        private void CancelOrders_Click(object sender, RoutedEventArgs e)
        {
            _orders.SelectedOrders.ForEach(_trader.CancelOrder);
        }

        private void Start_Click(object sender, RoutedEventArgs e)
        {
            if (_strategy == null)
            {
                if (this.Portfolios.SelectedPortfolio == null)
                {
                    MessageBox.Show(this, "Портфель не выбран.");
                    return;
                }

                
                // создаем стратегию
                _strategy = new MyOwnStrategy() { Volume = 1 };
                _strategy.Log += OnLog;
                _strategy.NewOrder += OnNewOrder;
                _strategy.PropertyChanged += OnStrategyPropertyChanged;

                // регистрируем стратегию, чтобы она начала обрабатываться
                _manager.Register(_strategy, this.Portfolios.SelectedPortfolio, _rts);

                var fileLogger = new FileStrategyLogger("{0}_{1:00}_{2:00}.txt".Put(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day));

fileLogger.Strategies.Add(_strategy);

this.Report.IsEnabled = true;

            }

            if (_strategy.ProcessState == StrategyProcessStates.Stopped)
            {
                _strategy.Start();
                this.Start.Content = "Хватит";
            }
            else
            {
                _strategy.Stop();
                this.Start.Content = "Понеслась";
            }
        }

private void Report_Click(object sender, RoutedEventArgs e)
        {
            var fileName = "report_{0}_{1}.xls".Put(_strategy.Security.Code, DateTime.Now.ToString("yyyy_MM_dd_HH_mm"));
            new ExcelStrategyReport(_strategy, System.IO.Path.Combine(Directory.GetCurrentDirectory(), fileName)).Generate();
        }
    }
}

Теги:


Спасибо:




14 Ответов
Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 28.03.2011
Ответить


poilka Перейти

Стратегия нормально запускается и останавливается из GUI примера SampleSMA, лог пишется, но сделок не происходит на любом таймфрейме.


Точка останова, дебаггер и вперед.Smile
Спасибо:

poilka

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


Спасибо, буду ковыряться.
Автор топика
Спасибо:

poilka

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


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

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

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 28.03.2011
Ответить


poilka Перейти
Попробовал и с конструктором, и без - говорит, что
не может получить значение _candleBounds.
Хотя _candleManager на месте, и на остальные поля не ругается.


Потому что там лямбда выражение стоит. Прочитайте, как эта вещь работает. И бряку ставьте во внутрь.
Спасибо:

poilka

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


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

Roman0

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


Чтобы не плодить сущности напишу здесь )
Есть ли вообще возможность запускать очередную итерацию стратегии не периодически, а именно по событию? Хотелось бы воспользоваться преимуществами оформления кода с виде Strategy, но не очень нравится исполнение по времени.

PS Только начал разбираться, извините, если что пропустил.
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 25.04.2011
Ответить


Roman0 Перейти
Есть ли вообще возможность запускать очередную итерацию стратегии не периодически, а именно по событию?


Не итерацию, а действие. Так же, как и выше написал, через событийную модель.
Спасибо:

Roman0

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


Mikhail Sukhov Перейти
Roman0 Перейти
Есть ли вообще возможность запускать очередную итерацию стратегии не периодически, а именно по событию?


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

Я правильно понял, что условие в When проверяется с периодичностью Strategy.Interval? Если нет, то каков смысл MakePeriodical?
Вопрос такой: можно ли запускать код внутри стратегии по событию? Т.е. пришли новые данные -> очередная проверка условия. Вроде бы это можно сделать запуская всю стратегию (ActionStrategy.Start) по событию без MakePeriodical? Если все это можно сделать как-то еще, то пожалуйста, расскажите как. Как я уже писал, хотелось бы использовать преимущества стратегий. Большое спасибо!
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 25.04.2011
Ответить


Roman0 Перейти
Mikhail Sukhov Перейти
Roman0 Перейти
Есть ли вообще возможность запускать очередную итерацию стратегии не периодически, а именно по событию?


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

Я правильно понял, что условие в When проверяется с периодичностью Strategy.Interval? Если нет, то каков смысл MakePeriodical?


Цитата:
Сделать действие периодичным (будет вызвано более одного раза).


Roman0 Перейти

Вопрос такой: можно ли запускать код внутри стратегии по событию? Т.е. пришли новые данные -> очередная проверка условия. Вроде бы это можно сделать запуская всю стратегию (ActionStrategy.Start) по событию без MakePeriodical? Если все это можно сделать как-то еще, то пожалуйста, расскажите как. Как я уже писал, хотелось бы использовать преимущества стратегий. Большое спасибо!


Через ActionStrategy и добавления событий... Вопрос уже содержит ответ. Или я видимо что-то не понимаю в вопросе, или вы не до конца мысль расписываете. Как предложение, попробуйте написать практический пример с событиями.
Спасибо:

Roman0

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


Большое спасибо за ответ!

Mikhail Sukhov Перейти
Roman0 Перейти
каков смысл MakePeriodical?


Сделать действие периодичным (будет вызвано более одного раза).


Вопрос как\где контролируется с какой периодичностью (и сколько раз?) будет выполняться действие?

Mikhail Sukhov Перейти

Roman0 Перейти

Вопрос такой: можно ли запускать код внутри стратегии по событию? Т.е. пришли новые данные -> очередная проверка условия. Вроде бы это можно сделать запуская всю стратегию (ActionStrategy.Start) по событию без MakePeriodical? Если все это можно сделать как-то еще, то пожалуйста, расскажите как. Как я уже писал, хотелось бы использовать преимущества стратегий. Большое спасибо!


Через ActionStrategy и добавления событий... Вопрос уже содержит ответ.


Дело в том, что нужно, чтобы условия проверялись не периодически, а по событию. Как это сделать?

Mikhail Sukhov Перейти

Или я видимо что-то не понимаю в вопросе, или вы не до конца мысль расписываете.

Вопрос очень прост: как выполнять вычисления по собственной стратегии (и в результате выставлять заявки, выдавать какие-то сообщения и т.п.) по событию (не периодически!) появления или изменения свечей используя Strategy и преимущества такого подхода (как это сделать без привлечения Strategy понятно)?. Такое возможно? Если кто-то напишет пример или даже без кода, но с названиями классов\методов опишет как это сделать буду очень благодарен )
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 26.04.2011
Ответить


Roman0 Перейти
Вопрос как\где контролируется с какой периодичностью (и сколько раз?) будет выполняться действие?


Если просто MakePeriodica(), то бесконечно. Если через перегруженный метод
https://stocksharp.ru/do...nRule_MakePeriodical.htm Через то можно указывать критерий.

Roman0 Перейти

Дело в том, что нужно, чтобы условия проверялись не периодически, а по событию. Как это сделать?

Вопрос очень прост: как выполнять вычисления по собственной стратегии (и в результате выставлять заявки, выдавать какие-то сообщения и т.п.) по событию (не периодически!) появления или изменения свечей используя Strategy и преимущества такого подхода (как это сделать без привлечения Strategy понятно)?. Такое возможно? Если кто-то напишет пример или даже без кода, но с названиями классов\методов опишет как это сделать буду очень благодарен )


Мы опять вернулись к началу. Нужно использовать событийную модель. Как это сделать я показал в документации.
Спасибо:

Roman0

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


Mikhail Sukhov Перейти
Roman0 Перейти
Вопрос как\где контролируется с какой периодичностью (и сколько раз?) будет выполняться действие?


Если просто MakePeriodica(), то бесконечно. Если через перегруженный метод
https://stocksharp.ru/do...nRule_MakePeriodical.htm Через то можно указывать критерий.

Roman0 Перейти

Дело в том, что нужно, чтобы условия проверялись не периодически, а по событию. Как это сделать?

Вопрос очень прост: как выполнять вычисления по собственной стратегии (и в результате выставлять заявки, выдавать какие-то сообщения и т.п.) по событию (не периодически!) появления или изменения свечей используя Strategy и преимущества такого подхода (как это сделать без привлечения Strategy понятно)?. Такое возможно? Если кто-то напишет пример или даже без кода, но с названиями классов\методов опишет как это сделать буду очень благодарен )


Мы опять вернулись к началу. Нужно использовать событийную модель. Как это сделать я показал в документации.


Проблема, для меня по крайней мере, в том, что в документации фрагменты кода, а работающего примера нет. Спасибо за ответы!
Спасибо:

Mikhail Sukhov

Фотография
Автор статей Программист Трейдер
Дата: 26.04.2011
Ответить


Roman0 Перейти
Проблема, для меня по крайней мере, в том, что в документации фрагменты кода, а работающего примера нет. Спасибо за ответы!


У вас как с языком C#? Событийная модель построена на делегатах, Action и Func. Прочитайте что это такое и как используется. Я подозреваю, что вы просто подошли к задаче не с того конца.
Спасибо:

Roman0

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


Mikhail Sukhov Перейти
Roman0 Перейти
Проблема, для меня по крайней мере, в том, что в документации фрагменты кода, а работающего примера нет. Спасибо за ответы!


У вас как с языком C#? Событийная модель построена на делегатах, Action и Func. Прочитайте что это такое и как используется. Я подозреваю, что вы просто подошли к задаче не с того конца.

Я недавно начал разбираться со всем этим и вроде бы более менее разобрался, по крайней мере с Action и Func Smile (прямо из закладок ссылки, может кому будет интересно Smile
http://msdn.microsoft.com/ru-ru/library/dd460699
http://msdn.microsoft.com/ru-ru/library/ms173171(v=VS.90).aspx
http://msdn.microsoft.com/ru-ru/library/bb397687(v=VS.90).aspx

Все-таки было бы очень желательно, чтобы такие ключевые вещи имели более подробные объяснения (см. например https://stocksharp.ru/forum/1287/ и https://stocksharp.ru/fo...astota-provierki-1-siek/ ) и рабочие примеры с разнообразными вариантами применения. А уж с какой целью "делать событие периодичным" ( https://stocksharp.ru/do...e0-aba8-0d4b93dea60e.htm ) и что и как конкретно делает MakePeriodical (про собственно период до сих пор ничего не известно Smile) из описания малопонятно. Я подозреваю, что там все просто и логично, но из документации это сразу понять для начинающего все-таки сложновато (не претендую на суперсообразительность Smile).

UPD
Еще добавлю для ясности: я не использую импорт из таблицы всех сделок и CandleManager для формирования свечей. И вот эти два замечания несколько меня дезориентировали:

ustas
Так всё таки проверка выполнения условия When в ActionStrategy - происходит ежесекундно , а не по событию?

Mikhail Sukhov
Да, ActionStrategy с некоторым периодом смотрит на появления сигналов от условий. Уменьшать такой период можно через Strategy.Interval.


Mikhail Sukhov
ActionToken - это структура, которая содержит условие и действие. ActionStrategy проверяет (периодически?) коллекцию таких токенов путем вызова условия

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


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

loading
clippy