← 返回

Разделение объема на buy/sell volume

Добрый вечер,

Не знаю даже в какую ветку запостить данный вопрос, но он относится и к S#, и к обработке исходных данных от брокера.

Итак, я знаю, что CQG на русский рынок дает не только общий проторгованный объем, но и разбивку на buy volume (объем, прошедний по offer) и на sell volume (объем, прошедший по bid). Ворос, можно ли через Quik получить такую статистику (думаю, что нет), и вопрос можно ли realtime обрабатывать тиковые данные так, чтобы делить объем на buy/sell volume.

В теории, если мы имеем snapshots стаканов и тиковые данные, а также мы знаем, что на русском рынке нет crossed trades (либо OTC reported trades), то любой объем на ленте проходит либо через bid, либо через offer, а значит мы можем видеть через изменение DOM snapshot (изменение состояния стакана) после каждой сделки какой это был объем.

Как минимум это можно было бы закодить для истории и сравнить с данными CQG.

Если такое в принципе возможно, то было бы супер услышать от команды stocksharp как это можно было бы реализовать.

本主题对您有帮助吗?

分享主题

评论 (13)

登录创建账户, 登录或注册以发表评论

Mikhail Sukhov
Mikhail Sukhov

devruss: Итак, я знаю, что CQG на русский рынок дает не только общий проторгованный объем, но и разбивку на buy volume (объем, прошедний по offer) и на sell volume (объем, прошедший по bid). Ворос, можно ли через Quik получить такую статистику (думаю, что нет), и вопрос можно ли realtime обрабатывать тиковые данные так, чтобы делить объем на buy/sell volume.

Смотря что имеет ввиду под проторгованным объемом? Если имеется ввиду агрессор, то это Trade.OrderDirection. А если имеет ввиду именно сколько по рынку ударяли раз, то это можно в теории посмотреть через стаканы + тики. Но точнее только в ОЛ.

Российский рынок более открыт на данные, чем американский. И на нем можно получить значительно больше информации, чем на америке.

devruss
devruss 作者

Допустим, мы смотрим на 5 минутные свечи. Если мы выведем просто volume - то он покажет, что объем был 1000 контрактов, например. Нам надо знать, сколько из этой 1000 были bid volume, а сколько ask volume. Например 800 ask volume, 200 bid volume.

Что-то вроде этого

Mikhail Sukhov
Mikhail Sukhov

devruss: Допустим, мы смотрим на 5 минутные свечи. Если мы выведем просто volume - то он покажет, что объем был 1000 контрактов, например. Нам надо знать, сколько из этой 1000 были bid volume, а сколько ask volume. Например 800 ask volume, 200 bid volume.

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

devruss
devruss 作者

Михаил,

Не стоит делать поспешных выводов насчет моей компетентности

Судя по вашему ответу, вы видите данную функциональность впервые.

Вот ссылка на видео с данной функциональностью http://www.youtube.com/watch?v=0y4a3h43oO0#t=19, и pdf с подробным описанием http://www.cqg.com/docs/TA.pdf

devruss
devruss 作者

Изначально задача была следующей: "нужно разделять объем на VolumeAsk, VolumeBid If the buyer has lifted the offer, it is counted as VolAsk or volume traded at the ask price. It is a measure of aggressive buyers. If the seller has hit the bid, it is counted as VolBid or volume traded at the bid price. It is a measure of aggressive sellers."

Итак, после 2х месяцев изучения S#, переведу данный вопрос на язык S#:)

Задача сделать индикатор, который принимает значения (decimal Volume, var Aggressor) а на выходе дает значение decimal. Все индикаторы из S# принимают только значения decimal и все....

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

Как это сделать?

methyst
methyst

devruss, имеется ввиду Volume Breakdown? то как вариант можно сравнивать только тики(как были 1-ые инди от Gomi под NT7 ). нынешнюю цену и прошлую if (lastprice != 0) { if (price > lastprice) delta = volume; if (price < lastprice) delta = -volume; } дальше суммировать эти тики в рамках заданного интервала(1мин например) totaldelta+=delta;

Иван З.
Иван З.

methyst: devruss, имеется ввиду Volume Breakdown? то как вариант можно сравнивать только тики(как были 1-ые инди от Gomi под NT7 ). нынешнюю цену и прошлую if (lastprice != 0) { if (price > lastprice) delta = volume; if (price < lastprice) delta = -volume; } дальше суммировать эти тики в рамках заданного интервала(1мин например) totaldelta+=delta;

Неправильных ответов будет процентов 10.

Если для Квика, то есть у сделки свойство OrderDirection, и Квик его транслирует. Как то так получится.

var delta = trade.OrderDirection != OrderDirections.Buy ? -trade.Volume : trade.Volume;

дальше как писалось

methyst: суммировать эти тики в рамках заданного интервала(1мин например) totaldelta+=delta;

С историей другое дело, ее с направлением сделки так просто не найдешь. Надо самому Гидрой с Квика качать. Либо выше описанный methyst вариант, но он ошибки выдает. Ну и как правило дельта рядом с профилем шагает. Я недавно у свечей такое свойство обнаружил.

Candle candle = new TimeFrameCandle();
var priceLevels = candle.VolumeProfileInfo.PriceLevels;

Правда когда обнаружил оно не работало, сейчас не знаю, не проверял. Раз уж горизонтальные объемы в свече найти можно, надо и дельту сделать. Лучше два свойства TotalBuyVolume и TotalSellVolume. Ну и для полного счастья в VolumeProfileInfo.PriceLevels эти свойства тоже сделать, только для горизонтальных объемов.

devruss
devruss 作者

Такой вариант рассматривался, но зачем реализовывать заведомо неточный индикатор, когда силами S# точно можно сделать верный Volume Breakdown... тот же CQG справляется с этой задачей великолепно В твоем примере, неявно подразумевается, что bid/ask spread не может ползти вверх без трейдов - данное предположение допустимо с небольшой натяжкой для ликвидных рынков, но абсолютно неверно для неликвида, либо рынка с больших спредом.

devruss
devruss 作者

Вся история из Квика записана в Гидре вместе со стаканами

Код скорее должен выглядеть так:


if (trade.OrderDirection == OrderDirections.Buy) 
              VolumeAsk += trade.Volume;
else 
              VolumeBid+= trade.Volume

Но чтобы сделать такой индикатор, в него надо передавать <trade.Volume, trade.OrderDirection>

Далее вопрос как суммировать по временному интервалу, чтобы он совпадал с временным интервалом свечки

По хорошему, конечно, надо бы добавить TotalBuyVolume и TotalSellVolume - это очень верное предложение.

Михаил, можем внести в очередь разработок доп функций?

Иван З.
Иван З.

devruss: Но чтобы сделать такой индикатор, в него надо передавать <trade.Volume, trade.OrderDirection> Далее вопрос как суммировать по временному интервалу, чтобы он совпадал с временным интервалом свечки Способа связать сделки со свечками, походу нет. Простого и надежного способа реализации MarketDelta из свечей тоже нет. Как вариант:

  1. В индикатор надо передавать сделки trade
  2. В индикаторе создать свойства OpenTime и TimeFrame на подобие свечных. OpenTime отправляем в ProcessValues для отрисовки.
  3. Пока OpenTime < Trade.Time < (OpenTime + TimeFrame) считаем дельту.
  4. Если((OpenTime + TimeFrame) < Trade.Time) OpenTime=(OpenTime + TimeFrame) начинаем считать дельту для новой свечи. Конечно это туповатый костыль, но он простой.

devruss: По хорошему, конечно, надо бы добавить TotalBuyVolume и TotalSellVolume - это очень верное предложение. Михаил, можем внести в очередь разработок доп функций?

Судя по логике S# надо не только TotalBuyVolume и TotalSellVolume но и CloseOrderDirections. Так как candle.CloseVolume это объем последней сделки в свечи, тогда candle.CloseOrderDirections будет направление последней сделки в свечи. Тогда бы вам индикатор совсем просто было бы сделать.

От сюда вытекает второй вариант решения вашей проблемы, многим сложнее но думаю надежнее. Вам сюда http://www.stocksharp.com/doc/?topic=html/99da6499-9ac1-4e7e-bcaf-a0c832dce4de.htm . Создать свой тип свечей с этими свойствами. Реализации CandleBuilder в S# можно тут посмотреть http://stocksharp.codeplex.com/SourceControl/latest#Sources/Algo/Candles/Compression/CandleBuilder.cs . Я своих свечей не делал, это только в теории.🙂

Вообще MarketDelta, MarketProfile, VolumeProfile сейчас это модные веяния. S# стоит идти в ногу со временем, и дать возможность пользователям простой способ их реализации.🙂

Иван З.
Иван З.

Короче, скажу так, зря мы на S# наезжаем, и умничаем. Все есть и все работает. Приношу свои извинения. 😊 Кто не верит вот код для проверки

                if (candle.State == CandleStates.Finished)
                {
                    var Volume = candle.TotalVolume;
                    var BuyVolume = candle.VolumeProfileInfo.PriceLevels.Select(level => level.BuyVolume).Sum();
                    var SellVolume = candle.VolumeProfileInfo.PriceLevels.Select(level => level.SellVolume).Sum();
                    var TotalVolume = BuyVolume + SellVolume;

                }

Но очень за мудрили и спрятали.😀

whitebar devruss methyst
devruss
devruss 作者

Иван З.: Короче, скажу так, зря мы на S# наезжаем, и умничаем. Все есть и все работает. Приношу свои извинения. 😊 Кто не верит вот код для проверки

            if (candle.State == CandleStates.Finished)
            {
                var Volume = candle.TotalVolume;
                var BuyVolume = candle.VolumeProfileInfo.PriceLevels.Select(level => level.BuyVolume).Sum();
                var SellVolume = candle.VolumeProfileInfo.PriceLevels.Select(level => level.SellVolume).Sum();
                var TotalVolume = BuyVolume + SellVolume;

            }
> Но очень за мудрили и спрятали.😀

Иван действительно нашел решение!

[Сравнение с CQG](http://gyazo.com/ad430475ee54f7ff7f8bb9b0d5f3fd06)
Вывод - картинка действительно правдоподобная. Данные в S# пришли из Гидры, записанные вживую из Финама.
Различия конечно есть, но кто прав сказать сложно, главное, что различия несущественные и профиль объемов один и тот же.
methyst
methyst

Иван З.: Кто не верит вот код для проверки

Спасибо, работает. ЗЫ: Код вроде просили, после проверки.



namespace StockSharp.Algo.Indicators.Misc
{
    using System.Linq;
    using System.ComponentModel;
    using StockSharp.Algo.Candles;

    /// <summary>
    /// Объем свечки.
    /// </summary>
    [DisplayName("Дельта")]
    [Description("Дельта свечки.")]
    public class DeltaIndicator: BaseIndicator<decimal>
    {
        /// <summary>
        /// Создать <see cref="DeltaIndicator"/>.
        /// </summary>
        public DeltaIndicator()
            : base(typeof(Candle))
        {
            Volume = new VolumeIndicator();
        }

        public VolumeIndicator Volume { get; private set; }
        /// <summary>
        /// Сформирован ли индикатор.
        /// </summary>
        public override bool IsFormed
        {
            get { return Volume.IsFormed; }
        }

        /// <summary>
        /// Обработать входное значение.
        /// </summary>
        /// <param name="input">Входное значение.</param>
        /// <returns>Результирующее значение.</returns>
        protected override decimal OnProcess(IIndicatorValue input)
        {
            var candle = input.GetValue<Candle>();           
            var result = candle.VolumeProfileInfo.PriceLevels.Select(level => level.BuyVolume - level.SellVolume).Sum();
            return result;
        }
    }
}

картинка