Событийный подход
Atom
28.03.2011
poilka


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

Подскажите, пожалуйста, как правильно запускать стратегию наподобие той,
что приведена в примере (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();
        }
    }
}

Теги:


Спасибо:


1 2  >
Mikhail Sukhov

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


poilka

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


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

poilka

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


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

poilka

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


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

Спасибо:

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

Фотография
Дата: 26.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 понятно)?. Такое возможно? Если кто-то напишет пример или даже без кода, но с названиями классов\методов опишет как это сделать буду очень благодарен )
Спасибо:
1 2  >

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

loading
clippy