← Назад

6 семинар ноябрь 2012

[vk]http://vk.com/video_ext.php?oid=-66650972&id=167477859&hash=92b3c312c353312b&hd=3[/vk]

План:

  • Дочерние стратегии
  • Свечки
  • CandleChart
  • Стратегии на свечках

Вложения: Проекты

Комментарии (22)

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

UsilaDobry
UsilaDobry

Каким образом можно внедрить монитор логирования в форму Wpf, чтобы он открывался не отдельным окном, а в приложении?

IvanB
IvanB

UsilaDobry: Каким образом можно внедрить монитор логирования в форму Wpf, чтобы он открывался не отдельным окном, а в приложении?


xmlns:SX="clr-namespace:StockSharp.Xaml;assembly=StockSharp.Xaml"

....

<SX:Monitor Name="MonitorControl" Margin="5,5,5,5" />

UsilaDobry
UsilaDobry

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

Пишу код в конструктор MainWindow()

var candleManger = new CandleManager(InterfaceConnection.SafeConnection.Trader); TimeFrameComboBox.ItemsSource = candleManger.GetSupportedRanges(null); //здесь в качестве аргумента надо указать серию свечек, я ставлю по совету решайпера null, но это не правильно, при запуске выпадает Exception, аргумент вызываемого метода не может быть null.

В обработчик события по нажатию кнопки пишу

var candleManger = new CandleManager(InterfaceConnection.SafeConnection.Trader); var candleSeries = new CandleSeries(typeof (TimeFrameCandle), InterfaceConnection.SelectedSecurity,TimeFrameComboBox.SelectedValue); if (BeginDatePicker != null && EndDatePicker != null) { if (BeginDatePicker.SelectedDate != null) candleSeries.From = (DateTime) BeginDatePicker.SelectedDate; if (EndDatePicker.SelectedDate != null) candleSeries.To = (DateTime) EndDatePicker.SelectedDate; } Приложение вообще не запускается.

IvanB
IvanB

UsilaDobry: ... Пишу код в конструктор MainWindow()

var candleManger = new CandleManager(InterfaceConnection.SafeConnection.Trader); TimeFrameComboBox.ItemsSource = candleManger.GetSupportedRanges(null); //здесь в качестве аргумента надо указать серию свечек, я ставлю по совету решайпера null, но это не правильно, при запуске выпадает Exception, аргумент вызываемого метода не может быть null.

... Правильно пишите, это не верно:


TimeFrameComboBox.ItemsSource = candleManger.GetSupportedRanges(null);

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

UsilaDobry
UsilaDobry

Как вариант создал обработчик события private void TimeFrameComboBox_ContextMenuOpening(object sender, System.Windows.Controls.ContextMenuEventArgs e) { var candleManger = new CandleManager(InterfaceConnection.SafeConnection.Trader); TimeFrameComboBox.ItemsSource = candleManger.GetSupportedRanges(candleSeries); } Все равно программа просит конкретное значение candleSeries, в таком виде воспринимает как null.

IvanB
IvanB

UsilaDobry: Как вариант создал обработчик события private void TimeFrameComboBox_ContextMenuOpening(object sender, System.Windows.Controls.ContextMenuEventArgs e) { var candleManger = new CandleManager(InterfaceConnection.SafeConnection.Trader); TimeFrameComboBox.ItemsSource = candleManger.GetSupportedRanges(candleSeries); } Все равно программа просит конкретное значение candleSeries, в таком виде воспринимает как null. На сколько я теперь понимаю, Вы не правильно пытаетесь использовать метод GetSupportedRanges. Вы пытаетесь получить из него коллекцию таймфреймов свечей, но этот метод возвращает не это, он возвращает "временные диапазоны, для которых у данного источниках для передаваемой серии свечек есть данные.". Подробнее здесь

UsilaDobry
UsilaDobry

Тогда как можно получить значения таймфреймов, которые есть в Quik?

IvanB
IvanB

UsilaDobry: Тогда как можно получить значения таймфреймов, которые есть в Quik? Я думаю, что из Квика никак не извлечь значения таймфреймов, которые используются в его выпадающем списке. Обычно, если надо выбирать значение таймфрейма из списка, то используют специальный компонент (Xceed:TimePicker) или в ручную, в цикле заполняют стандартный компонент выпадающего списка.

UsilaDobry
UsilaDobry

Я в ручную занес значения через ComboBoxItem, потом вызываю значение в следующем коде

        var candleSeries = new CandleSeries(typeof (TimeFrameCandle), InterfaceConnection.SelectedSecurity, TimeSpan.FromMinutes((double) TimeFrameComboBox.SelectedItem));

Выдает exception - Заданное приведение является недопустимым. Где-то явное приведение типов не сделал?

IvanB
IvanB

UsilaDobry: Я в ручную занес значения через ComboBoxItem, потом вызываю значение в следующем коде

var candleSeries = new CandleSeries(typeof (TimeFrameCandle), InterfaceConnection.SelectedSecurity, TimeSpan.FromMinutes((double) TimeFrameComboBox.SelectedItem));

> Выдает exception - Заданное приведение является недопустимым. Где-то явное приведение типов не сделал?
Всего скорее Вы поместили в TimeFrameComboBox значения не типа double.
UsilaDobry
UsilaDobry

IvanB: Всего скорее Вы поместили в TimeFrameComboBox значения не типа double.

<ComboBox x:Name="TimeFrameComboBox" Width="50" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="144,-22,0,0" SelectedIndex="0" > <ComboBoxItem>1</ComboBoxItem> <ComboBoxItem>5</ComboBoxItem> <ComboBoxItem>10</ComboBoxItem> <ComboBoxItem>15</ComboBoxItem> <ComboBoxItem>30</ComboBoxItem> <ComboBoxItem>60</ComboBoxItem> </ComboBox>

Здесь значения int32. Как здесь в коде указать тип значения double? Просто поставить 1.0; 5.0... Это не помогает...

IvanB
IvanB

UsilaDobry:

<ComboBox x:Name="TimeFrameComboBox" Width="50" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="144,-22,0,0" SelectedIndex="0" > <ComboBoxItem>1</ComboBoxItem> <ComboBoxItem>5</ComboBoxItem> <ComboBoxItem>10</ComboBoxItem> <ComboBoxItem>15</ComboBoxItem> <ComboBoxItem>30</ComboBoxItem> <ComboBoxItem>60</ComboBoxItem> </ComboBox>

:::
> 
> Здесь значения int32. Как здесь в коде указать тип значения double? Просто поставить 1.0; 5.0... Это не помогает...

Предлагаю заполнять в коде C#:
```csharp
TimeFrameComboBox.Items.Add(1);
TimeFrameComboBox.Items.Add(5);
...

И можно в цикле это сделать.

UsilaDobry
UsilaDobry

Это все сложно... Хорошо, поставлю элемент TimePicker, он передает значения типа DateTime, а нам надо передать значение типа TimeSpan. Явное преобразование в этой строке не катит, как тогда обратиться к TimePicker в строке:

Finam.History.GetHistoryCandles(InterfaceConnection.SelectedSecurity, TfTimePicker.Value, (DateTime)BeginDatePicker.SelectedDate, (DateTime)EndDatePicker.SelectedDate).ToArray();

UsilaDobry
UsilaDobry

Вот так правильно

Finam.History.GetHistoryCandles(InterfaceConnection.SelectedSecurity, TimeSpan.Parse(TfTimePicker.Value.ToString()), (DateTime)BeginDatePicker.SelectedDate, (DateTime)EndDatePicker.SelectedDate).ToArray();

не правильно... Exception Строка не распознана как действительный TimeSpan.

TimeSpan.Parse(TfTimePicker.Value.ToString()), что здесь не так? берем значение типа DateTime, преобразуем его методом ToString в строку, а потом парсим в тип TimeSpan...

UsilaDobry
UsilaDobry

Убрал вывод исторических данных, на старте candleManager выдает Exception- Значение не может быть неопределенным

using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using Ecng.Xaml;
using StockSharp.Algo.Candles;
using StockSharp.Logging;
using StockSharp.Quik;
using StockSharp.TraderConnection;
using StockSharp.Xaml;

namespace My_FirstROBOT
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        private readonly MonitorWindow _monitor = new MonitorWindow();
        private readonly LogManager _logmanager = new LogManager();

        public MainWindow()
        {
            InitializeComponent();

            InterfaceConnection.SafeConnection = new SafeConnection(new QuikTrader(QuikTerminal.GetDefaultPath()));
  
            InterfaceConnection.SafeConnection.Trader.NewSecurities += securities => this.GuiAsync(() =>
                {
                    TabMyTools.ItemsSource = InterfaceConnection.SafeConnection.Trader.Securities;
                });
            InterfaceConnection.SafeConnection.Trader.NewPortfolios += portfolios => this.GuiAsync(() =>
                {
                    TabMyPortfolios.ItemsSource = InterfaceConnection.SafeConnection.Trader.Portfolios;
                });
            InterfaceConnection.SafeConnection.Trader.NewPositions += positions => this.GuiAsync(() =>
                {
                    TabMyPosition.ItemsSource = InterfaceConnection.SafeConnection.Trader.Positions;
                });
            InterfaceConnection.SafeConnection.Trader.NewOrders += orders => this.GuiAsync(() =>
                {
                    TabMyOrders.ItemsSource = InterfaceConnection.SafeConnection.Trader.Orders;
                });
            InterfaceConnection.SafeConnection.Trader.NewStopOrders += orders => this.GuiAsync(() =>
                {
                    TabMyOrdersStop.ItemsSource = InterfaceConnection.SafeConnection.Trader.StopOrders;
                });
            InterfaceConnection.SafeConnection.Trader.NewMyTrades += trades => this.GuiAsync(() =>
                {
                    TabMyTrades.ItemsSource = InterfaceConnection.SafeConnection.Trader.MyTrades;
                });

            var _candleManager = new CandleManager(InterfaceConnection.SafeConnection.Trader);

             _logmanager.Listeners.Add(new GuiLogListener(_monitor));
            _logmanager.Listeners.Add(new FileLogListener("log.txt"));
            _logmanager.Sources.Add(InterfaceConnection.SafeConnection.Trader);
        }

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            if (InterfaceConnection.SafeConnection.Trader != null &&
                InterfaceConnection.SafeConnection.Trader.IsConnected)
            {
                InterfaceConnection.SafeConnection.Trader.Dispose();
            }
            Thread.CurrentThread.Abort();
            base.OnClosing(e);
        }
  
        private readonly CandleManager _candleManager;
 
        private ChartArea _area;
  
        private ChartCandleElement _candlesElem;
 
        private CandleSeries _series;

          private void InitAreas()
        {
            try
            {
                _area = new ChartArea();
                Chart.Areas.Add(_area);
                _candlesElem = new ChartCandleElement();
                _area.Elements.Add(_candlesElem);
                if (InterfaceConnection != null)
                    _series = new CandleSeries(typeof(TimeFrameCandle), InterfaceConnection.SelectedSecurity, TimeSpan.FromMinutes(1));
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString());
            }
        }

        private void CandlesChartStart()
        {
            try
            {
                _series.ProcessCandle += candle =>
                {
                    
                    if (candle.State == CandleStates.Finished)
                    {
                        this.GuiAsync(() => Chart.ProcessValues(candle.OpenTime, new Dictionary<IChartElement, object>
                            {
                                  {_candlesElem, candle},//свечка
                            }));
                    }
                    else
                    {
                        var timeFrame = (TimeSpan)_series.Arg;
                        var time = timeFrame.GetCandleBounds(_series.Security).Min - timeFrame; //находим последнее время свечки
                        
                        if (candle.OpenTime >= time)
                            Chart.ProcessCandle(_candlesElem, candle);
                    }
                };
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString());
            }
        }
        private void ChartButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                    
                    InitAreas();
                    
                    CandlesChartStart();
                    
                    _candleManager.Start(_series);  ----------!!!!!! Exception - Значение не может быть неопределенным
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString());
            }
        }
UsilaDobry
UsilaDobry

Я дописал создание candleManager в обработчик события ChartButton_Click. Ошибка не вылетает, но свечи не выводятся на график, появляется только сетка координат

using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using Ecng.Xaml;
using StockSharp.Algo.Candles;
using StockSharp.Logging;
using StockSharp.Quik;
using StockSharp.TraderConnection;
using StockSharp.Xaml;

namespace My_FirstROBOT
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        private readonly MonitorWindow _monitor = new MonitorWindow();
        private readonly LogManager _logmanager = new LogManager();

        public MainWindow()
        {
            InitializeComponent();

            InterfaceConnection.SafeConnection = new SafeConnection(new QuikTrader(QuikTerminal.GetDefaultPath()));
            //////////////////////////////////Блок получения информации///////////////////////////////////////////////////////
            InterfaceConnection.SafeConnection.Trader.NewSecurities += securities => this.GuiAsync(() =>
                {
                    TabMyTools.ItemsSource = InterfaceConnection.SafeConnection.Trader.Securities;
                });
            InterfaceConnection.SafeConnection.Trader.NewPortfolios += portfolios => this.GuiAsync(() =>
                {
                    TabMyPortfolios.ItemsSource = InterfaceConnection.SafeConnection.Trader.Portfolios;
                });
            InterfaceConnection.SafeConnection.Trader.NewPositions += positions => this.GuiAsync(() =>
                {
                    TabMyPosition.ItemsSource = InterfaceConnection.SafeConnection.Trader.Positions;
                });
            InterfaceConnection.SafeConnection.Trader.NewOrders += orders => this.GuiAsync(() =>
                {
                    TabMyOrders.ItemsSource = InterfaceConnection.SafeConnection.Trader.Orders;
                });
            InterfaceConnection.SafeConnection.Trader.NewStopOrders += orders => this.GuiAsync(() =>
                {
                    TabMyOrdersStop.ItemsSource = InterfaceConnection.SafeConnection.Trader.StopOrders;
                });
            InterfaceConnection.SafeConnection.Trader.NewMyTrades += trades => this.GuiAsync(() =>
                {
                    TabMyTrades.ItemsSource = InterfaceConnection.SafeConnection.Trader.MyTrades;
                });


            ////////////////////////////////////////////Блок логирования////////////////////////////////////////////////////
            _logmanager.Listeners.Add(new GuiLogListener(_monitor));
            _logmanager.Listeners.Add(new FileLogListener("log.txt"));
            _logmanager.Sources.Add(InterfaceConnection.SafeConnection.Trader);
        }

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            if (InterfaceConnection.SafeConnection.Trader != null &&
                InterfaceConnection.SafeConnection.Trader.IsConnected)
            {
                InterfaceConnection.SafeConnection.Trader.Dispose();
            }
            Thread.CurrentThread.Abort();
            base.OnClosing(e);
        }
        /// <summary>
        /// Менеджер свечек
        /// </summary>
        private readonly CandleManager _candleManager;
        /// <summary>
        /// Основная площадь
        /// </summary>
        private ChartArea _area;
        /// <summary>
        /// Элемент свечек на графике
        /// </summary>
        private ChartCandleElement _candlesElem;
        /// <summary>
        /// Серия для свечек
        /// </summary>
        private CandleSeries _series;

        /// <summary>
        /// Создать и добавить все нужные нам элементы
        /// </summary>
        private void InitAreas()
        {
            try
            {
                //добавляем первую площадь(на которой будем все отмечать)
                _area = new ChartArea();
                Chart.Areas.Add(_area);
                //свечки
                _candlesElem = new ChartCandleElement();
                _area.Elements.Add(_candlesElem);
                if (InterfaceConnection != null)
                    _series = new CandleSeries(typeof(TimeFrameCandle), InterfaceConnection.SelectedSecurity, TimeSpan.FromMinutes(1));
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString());
            }
        }

        private void CandlesChartStart()
        {
            try
            {
                //отрабатываем поступление новых свечек
                _series.ProcessCandle += candle =>
                {
                    //законченные свечки используются для расчета индикатора
                    if (candle.State == CandleStates.Finished)
                    {
                        this.GuiAsync(() => Chart.ProcessValues(candle.OpenTime, new Dictionary<IChartElement, object>
                            {
                                  {_candlesElem, candle},//свечка
                            }));
                    }
                    else
                    {
                        var timeFrame = (TimeSpan)_series.Arg;
                        var time = timeFrame.GetCandleBounds(_series.Security).Min - timeFrame; //находим последнее время свечки
                        //добавляем только последние измененные свечки
                        if (candle.OpenTime >= time)
                            Chart.ProcessCandle(_candlesElem, candle);
                    }
                };
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString());
            }
        }
        private void ChartButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                    var _candleManager = new CandleManager(InterfaceConnection.SafeConnection.Trader);
                    //инициализация графика
                    InitAreas();
                    //прорисовка свечек
                    CandlesChartStart();
                    //запускаем получение свечек
                    _candleManager.Start(_series);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString());
            }
        }

        /// <summary>
        /// Блок работы торговой стратегии
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TakrProfitCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            WidthBbLabel.IsEnabled = true;
            WidthBbTextBox.IsEnabled = true;
            SpradTpLabel.IsEnabled = true;
            SpradTpTextBox.IsEnabled = true;
        }

        private void LevelSARCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            SignalsLevelSarLabel.IsEnabled = true;
            Signal1SarCheckBox.IsEnabled = true;
            Signal2SarCheckBox.IsEnabled = true;
            StartTradingButton.IsEnabled = true;
        }

        private void StartTradingButton_Click(object sender, RoutedEventArgs e)
        {
            StopTradingButton.IsEnabled = true;
            StartTradingButton.IsEnabled = false;
        }

        private void StopTradingButton_Click(object sender, RoutedEventArgs e)
        {
            StopTradingButton.IsEnabled = false;
            StartTradingButton.IsEnabled = true;
        }
    }
}
UsilaDobry
UsilaDobry

Вопросы отпали после просмотра видео-урока CandleChartsProject. Сразу надо было мне смотреть видео-урок.

Compressor
Compressor

По какой причине CancelActiveOrders() не работает?

IvanB
IvanB

Compressor: По какой причине CancelActiveOrders() не работает? Всего скорее Вы вызываете этот метод, где он в принципе не может работать, например если Вы вызываете CancelActiveOrders в переопределенном методе OnStopping, этот метод вызывается когда стратегия уже перешла в остановку и по этому не воспринимает торговые команды. Информация из логирования должна помочь в определении причины не работы CancelActiveOrders.

Compressor
Compressor

Он работает в ProcessCandle(Candle candle), в стандартной схеме (как в болинджере). Какие параметры надо выводить в лог, чтобы понять в чем причина?

IvanB
IvanB

Compressor: Он работает в ProcessCandle(Candle candle), в стандартной схеме (как в болинджере). Какие параметры надо выводить в лог, чтобы понять в чем причина?

Перед вызовом метода CancelActiveOrders() надо проверить есть ли активные заявки, примерно так:


Orders.Count(o => o.State == OrderStates.Active)

И если Вы используете старую версию S#, то желательно перейти на одну из последних, если это ошибка в S# старой версии, то переход на новую версию поможет ее решить.

wkj
wkj
private bool NoActiveOrders
        {get{return Orders.Count(o => o.State != OrderStates.Active) == 0;}}

А как переписать данную конструкцию с учетом введения Messages?