Урок 4. Свечи, графики, история
Atom Ответить
01.05.2013


Видео-уроки (основное):
Свечи, индикаторы, стратегия, метки, вывод на график




Видео-уроки (экстра):
Создание и работа с кластерными свечками

[vk]http://vk.com/video_ext.php?oid=-66650972&id=167470847&hash=05646cb903828f2e&hd=3" frameborder="0">

Темы занятия:

Свечи (S# документация)
  1. Получение свечей из торгового терминала
  2. Вывод свечного графика

Индикаторы (S# документация)
  1. Создание простого собственного индикатора
  2. Вывод графика индикатора

Стратегия (S# документация)
  1. Получение заявок и сделок
  2. Вывод меток заявок и сделок на график

Работа с графиком (SciChart)
  1. Работа с областями графика
  2. Создание и использование графических элементов

Создание модуля для получения исторических данных
Создание сборки с получением исторических свечей, отрисовкой графиков и запуском стратегии
Выводим свечной график в S#.Studio


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

Полезные ссылки:
Свечи, документация

Вложения:
Скачать проекты

Изменения в проектах:

Теги:


Спасибо:




59 Ответов
1 2 3  >
UsilaDobry

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


Увидел в Вас в примере код свойства:
Код
private bool NoActiveOrders
 {  get { return Orders.Count(o => o.State != OrderStates.Done) == 0 && PendingOrders.Count() == 0; } }

Я бы его написал вот так
Код
private bool NoActiveOrders { get { return Orders.Count(o => o.State == OrderStates.Active) == 0; } }


А в чем замысел?
Спасибо:

UsilaDobry

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


Что-то я не пойму, как мне коллекцию свечей из метода GetHistoryCandles(); передать в метод ProcessCandle(CandleSeries series, Candle candle)?..
В уроке метод Draw(Candle), принимает только свечи, а у меня при выводе на график ProcessCandle(CandleSeries series, Candle candle) принимает еще и серию свечей... В моем варианте использовать метод GetHistoryCandles() не получится?

Спасибо:

IvanB

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


UsilaDobry Перейти
Что-то я не пойму, как мне коллекцию свечей из метода GetHistoryCandles(); передать в метод ProcessCandle(CandleSeries series, Candle candle)?..
В уроке метод Draw(Candle), принимает только свечи, а у меня при выводе на график ProcessCandle(CandleSeries series, Candle candle) принимает еще и серию свечей... В моем варианте использовать метод GetHistoryCandles() не получится?



Можно сделать так:
Код

foreach (var candle in GetHistoryCandles())
{
   ProcessCandle(null, candle);
}

В методе ProcessCandle Вы не используете аргумент CandleSeries series, можно подписаться на получение свечей так:
series.ProcessCandle += ProcessCandle;
в место этого:
_candleManager.Processing += ProcessCandle;
и изменить заголовок метода:
private void ProcessCandle(Candle candle)

тогда получать свечи можно так:
Код

foreach (var candle in GetHistoryCandles())
{
   ProcessCandle(candle);
}

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

UsilaDobry

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


IvanB Перейти

В методе ProcessCandle Вы не используете аргумент CandleSeries series, можно подписаться на получение свечей так:
series.ProcessCandle += ProcessCandle;
в место этого:
_candleManager.Processing += ProcessCandle;
и изменить заголовок метода:
private void ProcessCandle(Candle candle)

тогда получать свечи можно так:
Код

foreach (var candle in GetHistoryCandles())
{
   ProcessCandle(candle);
}



Может в таком случае можно не использовать foreach, а сделать как в видео-уроке

Код
GetHistoryCandles().ForEach(ProcessCandle);


но я не могу этого сейчас испробовать, поскольку срок на демосервер истек, а новые ключи вчера получил, но они не прокатывают. Написал письмо в техподдержку Квика, пока молчат... Процесс остановился BigGrin
Наконец-то подключили...
Проверил, такой вариант работает, но график индикаторов выводит не корректно...
Спасибо:

UsilaDobry

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


И таким способом
Код
foreach (var candle in GetHistoryCandles())
{
   ProcessCandle(null, candle);
}

и таким способом
Код
GetHistoryCandles().ForEach(ProcessCandle);

история выводится корректно, и свечи и индикаторы, но склейка получается неправильная...
например при выводе реальной свечи на 10 минутном графике после свечи 12:10 рисуется свеча 12:45, потом после Finished становится свечой 12:20.
Также в месте склейки искажаются индикаторы...На истории индикаторы переходят из одного дня в другой плавно, а в месте склейки идёт явный разрыв значений...
Что можно придумать...?
Спасибо:

IvanB

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


UsilaDobry Перейти
И таким способом
Код
foreach (var candle in GetHistoryCandles())
{
   ProcessCandle(null, candle);
}

и таким способом
Код
GetHistoryCandles().ForEach(ProcessCandle);

история выводится корректно, и свечи и индикаторы, но склейка получается неправильная...
например при выводе реальной свечи на 10 минутном графике после свечи 12:10 рисуется свеча 12:45, потом после Finished становится свечой 12:20.
Также в месте склейки искажаются индикаторы...На истории индикаторы переходят из одного дня в другой плавно, а в месте склейки идёт явный разрыв значений...
Что можно придумать...?


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

pft_man

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


А какие ещё темы есть в SciChart.ChartTheme, кроме ExpressionDark? Я искал в документации и на форуме, но ничего не нашёл.
Спасибо:

UsilaDobry

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


pft_man Перейти
А какие ещё темы есть в SciChart.ChartTheme, кроме ExpressionDark? Я искал в документации и на форуме, но ничего не нашёл.


Доступные темы: ExpressionLight, ExpressionDark, BlackSteel, BrightSpark, Chrome, Electric, Oscilloscope
Спасибо:

pft_man

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


Спасибо.
Спасибо:

pft_man

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


А как нарисовать на графике свой трейлинг-стоп так, чтобы он ещё и на истории показывался? В Wealth-Lab для этого существует метод PlotStops(), который просто рисует стопы, а я рассчитываю сами значения стопов.

Единственный вариант - сделать свой индикатор, рассчитывающий трейлинг-стоп, так? Такой индикатор будет иметь значение IsFormed, когда есть позиция. То есть он привязан к стратегии. Как лучше это в коде организовать?

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

IvanB

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


pft_man Перейти
А как нарисовать на графике свой трейлинг-стоп так, чтобы он ещё и на истории показывался? В Wealth-Lab для этого существует метод PlotStops(), который просто рисует стопы, а я рассчитываю сами значения стопов.

Единственный вариант - сделать свой индикатор, рассчитывающий трейлинг-стоп, так? Такой индикатор будет иметь значение IsFormed, когда есть позиция. То есть он привязан к стратегии. Как лучше это в коде организовать?

И есть ли свойство у ChartIndicatorElement, позволяющее рисовать не линии, а точки, например. Если нет, то как можно это сделать?


Можно использовать метки заявок и сделок.
Для отрисовки индикатора можно выбирать стиль, свойство ChartIndicatorElement.DrawStyle, можно попробовать использовать тип ChartIndicatorDrawStyles.Dot для Вашей цели.
Можно создать свой графический элемент (метка, аналог метке-заявке или метке-сделке)
Автор топика
Спасибо:

pft_man

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


Ещё один вопрос. Cледующий код по событию изменения свечки:

Код
if ((candle.State == CandleStates.Finished) && (_series.GetCandle<Candle>(0).HighPrice > _series.GetCandle<Candle>(1).HighPrice))

Когда придёт новая цена, которая закроет текущую свечку (возвратит ей статуc finished), какая свечка будет считаться текущей: которая получила статус finished или следующая с первой ценой. Ведь по сути эта цена должна уже начать формировать следующую свечку. То есть обращаться к завершившейся свечке нужно будет через индекс 0 (как у меня в коде) или уже через 1?
В общем, мне нужно, чтобы как только свечка завершится, её High сравнивался с High предыдущей свечки. Мой код будет правильно работать?
Спасибо:

IvanB

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


pft_man Перейти
Ещё один вопрос. Cледующий код по событию изменения свечки:

Код
if ((candle.State == CandleStates.Finished) && (_series.GetCandle<Candle>(0).HighPrice > _series.GetCandle<Candle>(1).HighPrice))

Когда придёт новая цена, которая закроет текущую свечку (возвратит ей статуc finished), какая свечка будет считаться текущей: которая получила статус finished или следующая с первой ценой. Ведь по сути эта цена должна уже начать формировать следующую свечку. То есть обращаться к завершившейся свечке нужно будет через индекс 0 (как у меня в коде) или уже через 1?
В общем, мне нужно, чтобы как только свечка завершится, её High сравнивался с High предыдущей свечки. Мой код будет правильно работать?


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

UsilaDobry

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


Доброго вечера Иван.
Столкнулся с такой ошибкой при закачке истории с Финама "Элемент с таким ключом уже был запущен".
Такая ошибка у меня появляется, когда я запускаю два графика с историей с разными таймфреймами. Первый график выводит историю и реал корректно, а второй график выдает такую ошибку и выводит только реал... Почему, ведь происходит обращение к сайту Финама для получения свечек с разным таймфреймом...?
Спасибо:

UsilaDobry

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


Еще вопрос по обработке исторических свечей.
Для того, чтобы обработать свечи с начала торговой сессии и до времени запуска стратегии я использую вот такое условие:
Код
if (candle.CloseTime <= StartedTime && _parabolic.IsFormed &&
                        candle.State == CandleStates.Finished)

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

IvanB

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


UsilaDobry Перейти
Еще вопрос по обработке исторических свечей.
Для того, чтобы обработать свечи с начала торговой сессии и до времени запуска стратегии я использую вот такое условие:
Код
if (candle.CloseTime <= StartedTime && _parabolic.IsFormed &&
                        candle.State == CandleStates.Finished)

Необходимо получить исторические свечи + свечи с начала торговой сессии и до времени старта стратегии для обработки и определения торговых моделей.
А как передать исторические свечи в стратегию?


Вообще, зависит от того, как Вы реализовали стратегию.
Думаю, лучшим вариантом будет - создать специальный метод в стратегии, который будет принимать свечи, и этот метод будет реализовывать то, что нужно делать с переданными свечами в Вашей стратегии.
Автор топика
Спасибо: UsilaDobry

IvanB

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


UsilaDobry Перейти
Доброго вечера Иван.
Столкнулся с такой ошибкой при закачке истории с Финама "Элемент с таким ключом уже был запущен".
Такая ошибка у меня появляется, когда я запускаю два графика с историей с разными таймфреймами. Первый график выводит историю и реал корректно, а второй график выдает такую ошибку и выводит только реал... Почему, ведь происходит обращение к сайту Финама для получения свечек с разным таймфреймом...?


Измените класс History на это:
Автор топика
Спасибо: VassilSanych UsilaDobry

UsilaDobry

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


Доброго дня!

Пробую добавить вывод реальных свечей от Альфа-коннектора, появляется ошибка "Параметр свечки 00-10-00 неправильный" в строке _candleManager.Start(series); Причем здесь параметр свечки, если в менеджер свечей передается серия свечей, и почему параметр серии 10 минут неправильный?..

Спасибо:

IvanB

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


UsilaDobry Перейти
Доброго дня!

Пробую добавить вывод реальных свечей от Альфа-коннектора, появляется ошибка "Параметр свечки 00-10-00 неправильный" в строке _candleManager.Start(series); Причем здесь параметр свечки, если в менеджер свечей передается серия свечей, и почему параметр серии 10 минут неправильный?..



Если Вы используете свечи типа TimeFrameCandle, то подобное сообщение говорит о том, что параметр Arg свечи (для типа TimeFrameCandle) имеет тип отличный от TimeSpan.
Автор топика
Спасибо: UsilaDobry

UsilaDobry

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


Действительно, поменял тип серии свечей, вместо TimeFrameCandle указал AlfaTimeFrames в строке
Код
_series = new CandleSeries(typeof(AlfaTimeFrames), security, timeFrame);


ошибка пропала, но выводятся только исторические свечи, реальные не хотят...
Спасибо:

IvanB

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


UsilaDobry Перейти
Действительно, поменял тип серии свечей, вместо TimeFrameCandle указал AlfaTimeFrames в строке
Код
_series = new CandleSeries(typeof(AlfaTimeFrames), security, timeFrame);


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


Посмотрите пример SampleAlfaCandles и обновите библиотеки S#.
Автор топика
Спасибо:

UsilaDobry

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


IvanB Перейти
Посмотрите пример SampleAlfaCandles и обновите библиотеки S#.


Я именно этот пример и пытаюсь доработать. В этом примере выводятся только исторические свечи. А я хочу притулить туда candleManager, но почитав ветку форума AlfaDirect понял, что Аlfa не дружит с candleManager. Видимо по этой причине и пример сделан только с историческими свечами.
Я работаю сейчас с библиотекой 4.1.13.2, скачал 4.1.14.1, там пример SampleAlfaCandles нисколько не изменился.
Кстати, пример из предыдущей библиотеки работает корректно, а сейчас запустил из новой библиотеки, выдает ошибку обработки данных, при этом код идентичный. Не знаю чем это объяснить... Ну да ладно, меня интересуют больше реальные свечи из Alfa.
Я взял вот этот блок вывода исторических свечей
Код
private void ShowChartClick(object sender, RoutedEventArgs e)
        {
            
                var security = SelectedSecurity;
                
                var timeFrame = (AlfaTimeFrames)((ComboBoxItem)HistoryInterval.SelectedItem).Tag;
                                
                if (From.Value != null)
                {
                    var from = From.Value.Value;
                    if (To.Value != null)
                    {
                        var to = To.Value.Value;
                
                        if (@from > to)
                        {
                            return;
                        }
                
                        var candles = _trader.GetHistoryData(security, timeFrame, new Range<DateTime>(@from, to));
                        
                        _chartWindow = new ChartWindow
                        {
                            Title = "{0}, {1}, {2} - {3}".Put(security.Code,
                                                              ((ComboBoxItem)HistoryInterval.SelectedItem).Content,
                                                              @from.ToString(CultureInfo.InvariantCulture), to.ToString(CultureInfo.InvariantCulture))
                        };
this.GuiAsync(() => DrawCandles(candles));


И добавил к нему блок обработки реальных свечей через candleManager

Код
_candleManager = new CandleManager(_trader);
                
                        _series = new CandleSeries(typeof(TimeFrameCandle), security, (TimeSpan)AlfaTimeFrames.Minute10);
                        
                        _series.ProcessCandle += Draw;
                        
                        _candleManager.Start(_series);
 private void Draw(Candle candle)
        {
            if (candle.State == CandleStates.Finished || candle.State == CandleStates.Changed)
            {
                var final = candle.State == CandleStates.Finished;
                
                var val = _chartBollingerElement.Indicator.Process(new DecimalIndicatorValue(candle.ClosePrice) {IsFinal = final});
                var bollingerValue = new ChartIndicatorValue(_chartBollingerElement.Indicator, val);
                
                var timeFrame = (TimeSpan)_series.Arg;
                var time = timeFrame.GetCandleBounds(_series.Security).Min - timeFrame;
                
                if (candle.State == CandleStates.Finished || (candle.State == CandleStates.Changed && candle.OpenTime >= time))
                {
                    this.GuiAsync(() => _chartWindow.Chart.ProcessValues(candle.OpenTime, new Dictionary<IChartElement, object>
                                                                                          {
                                                                                              {_candlesElem, candle},
                                                                                              {_chartBollingerElement, bollingerValue},
                                                                                          }));
                }
            }
        }


Вроде бы все как учили, но появляется ошибка
Спасибо:

UsilaDobry

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


Доброго вечера Иван!
Может Вы мне подскажете, а то разработчики на форуме заняты более серьезными задачами или мои вопросы слишком глупы...:-)
К примеру в Quik мы выводили реальные свечи вот так..., причем реальные свечи получаем с 10-00, а историю можно было получить только за прошлые дни

Код
_candleManager = new CandleManager(ConnectionInterFace.SafeConnection.Trader);
            
            var security = ConnectionInterFace.SelectedSecurity;
            
            _candleSeries = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame);
            
            _candleSeries.ProcessCandle += Draw;

            _candleManager.Start(_candleSeries);

private void Draw(Candle candle)
        {
            //Временные рамки свечи
            var candleBounds = ((TimeSpan) candle.Arg).GetCandleBounds(_candleSeries.Security);
                                    
            //Работаем только с завершенными свечами и одной последней свечей с произвольным состоянием
            if (candle.State == CandleStates.Finished || candle.OpenTime >= candleBounds.Min)
            {
                //Выводим значения на график
                this.GuiAsync(() => Chart.ProcessValues(candle.OpenTime, new Dictionary<IChartElement, object>
                    {
                        {_chartCandleElement, candle},                  
                    }));
            }
        }

Из терминала AlfaDirect реальные свечи получаются гораздо проще, при этом историю можно получить вплоть до предпоследней завершенной свечки торговой сессии
Код
_candleManager = new CandleManager(_trader);
                
                _series = new CandleSeries(typeof(TimeFrameCandle), security, (TimeSpan)AlfaTimeFrames.Minute10);

                _series.ProcessCandle += candle => this.GuiAsync(() => _chartWindow.Chart.ProcessCandle(_candlesElem, candle));

                _candleManager.Start(_series);

Но...если в Quik легко отделить завершенные реальные свечи от последней незавершенной, например убрать условие candle.OpenTime >= candleBounds.Min и на график будут выводится только завершенные реальные свечи, то в AlfaDirect такой прием не катит... Не могу дать ума, как отделить завершенные реальный свечи от последней незавершенной. Банальная проверка на finished не помогает... Всё равно выводятся завершенные свечи и последняя незавершенная...
Код
_candleManager = new CandleManager(_trader);
                
                _series = new CandleSeries(typeof(TimeFrameCandle), security, (TimeSpan)AlfaTimeFrames.Minute10);

                _series.ProcessCandle += candle => 
                    {
                        if (candle.State == CandleStates.Finished)
                        {
                          
                          this.GuiAsync(() =>_chartWindow.Chart.ProcessValues(candle.OpenTime, new Dictionary<IChartElement, object>
                                                                   {
                                                                       {_candlesElem, candle},
                                                                   }));
                                               
                    };
_candleManager.Start(_series);
Спасибо:

Самунджян Артем

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


UsilaDobry Перейти

Может Вы мне подскажете..

Разбирательства переносятся в Skype, для более оперативного решения проблемы BigGrin
Спасибо:

Bond

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


На картинке в начале урока цвета свечей должны быть в точности наоборот.
Или поменяйте местами цены открытия и закрытия свечи.
Спасибо:
1 2 3  >

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

loading
clippy