← Назад

Как понять, что DDE передал всю историю, и теперь идет реал-тайм?

Разбираюсь с примером Quik SampleSMA. В этом примере если запускать робота не с начала дня, то сыпятся сделки по приходу свечек из истории. Есть ли какой-либо метод, чтобы запретить выставлять ордера на биржу, пока не будет закачана вся история?

Роман.

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

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

Sergey Masyura
Sergey Masyura

RomSunZ: Разбираюсь с примером Quik SampleSMA. В этом примере если запускать робота не с начала дня, то сыпятся сделки по приходу свечек из истории. Есть ли какой-либо метод, чтобы запретить выставлять ордера на биржу, пока не будет закачана вся история?

Роман.

В сделке есть время, есть время запуска стратегии. Можно сравнить.

RomSunZ
RomSunZ Автор

Да, я уже понял


            var tt = candle.Security.LastTrade.Time;
            if (candle.CloseTime != tt) realtime = false;
            else realtime = true;


Помимо этого в примере не обрабатывается построение МАшек при загрузке истории:


		private void ProcessCandle(Candle candle)
		{
            var longValue = candle.State == CandleStates.Finished ? _strategy.LongSma.Process((DecimalIndicatorValue)candle.ClosePrice) : null;
            var shortValue = candle.State == CandleStates.Finished ? _strategy.ShortSma.Process((DecimalIndicatorValue)candle.ClosePrice) : null;

			_chart.ProcessValues(candle.OpenTime, new Dictionary<IChartElement, object>
			{
				{ _candlesElem, candle },
				{ _longMaElem, longValue },
				{ _shortMaElem, shortValue },
			});
		}


Статус свечек, загруженных из файла равен NULL, и они не строятся на графике и, соответственно, не рассчитывают МА. Плюс ко всему в риалтайме машки также считаются непонять как (скорее всего и в окне, и в стратегии расчет дублируется), но я еще не понял, что там нужно поправить.

RomSunZ
RomSunZ Автор

candle.CloseTime не пойдет, всегда возвращает конец таймфрейма, а не время последней сделки свечки. Подскажите, как можно получить тиковые сделки по свечке или время последнего изменения свечки?

Sergey Sokolov
Sergey Sokolov

я делал так:


    public sealed class MyCandle : TimeFrameCandle {
        public MyCandle(TimeFrameCandle copyFrom) {
            this.CopyFrom(copyFrom);
        }

        public DateTime LastTradeTime {get; private set;}

        public class MyCandleBuilder : TimeFrameCandleBuilder {
            protected override TimeFrameCandle CreateCandle(CandleSeries series, ICandleBuilderSourceValue value) {
                var candle = base.CreateCandle(series, value);
                if(candle == null) return null;

                var mycandle = new MyCandle(candle) {LastTradeTime = value.Time};

                return mycandle;
            }

            protected override void UpdateCandle(CandleSeries series, TimeFrameCandle candle, ICandleBuilderSourceValue value) {
                base.UpdateCandle(series, candle, value);
                ((MyCandle)candle).LastTradeTime = value.Time;
            }
        }
    }

Кривовато, но работает.

RomSunZ
RomSunZ Автор

Спасибо. Я сделал еще более коряво, но вроде тоже работает (пока изучаю):


        protected override void OnStarted()
        {
            _series
                .WhenCandlesFinished()
                .Do(ProcessCandle)
                .Apply(this);
            _series
                .WhenCandlesChanged()
                .Do(ProcessCandleTick)
                .Apply(this);
        }

        private void ProcessCandleTick(Candle candle)
        {
            var trr = base.Trader.Trades.Where(tr => tr.Security == candle.Security && tr.Time >= candle.OpenTime && tr.Time <= candle.CloseTime).Last();
            var tt = candle.Security.LastTrade.Time;
            if (trr.Time != tt) realtime = false;
            else realtime = true;
        }


Sergey Sokolov
Sergey Sokolov

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

RomSunZ
RomSunZ Автор

Да, я знаю, просто пока только начал разбираться с библиотекой, и многих моментов просто не знаю. Плюс еще сам с# не особо знаком, так что пока разбираюсь с примерами и делаю как более очевидно для меня 😀

PS а что за метод CopyFrom?

Sergey Sokolov
Sergey Sokolov

        public static void CopyFrom(this TimeFrameCandle candle, TimeFrameCandle copyFrom, bool setState=true) {
            candle.TimeFrame = copyFrom.TimeFrame;
            candle.Security = copyFrom.Security;
            candle.OpenTime = copyFrom.OpenTime;
            candle.CloseTime = copyFrom.CloseTime;
            candle.HighTime = copyFrom.HighTime;
            candle.LowTime = copyFrom.LowTime;
            candle.OpenPrice = copyFrom.OpenPrice;
            candle.ClosePrice = copyFrom.ClosePrice;
            candle.HighPrice = copyFrom.HighPrice;
            candle.LowPrice = copyFrom.LowPrice;
            candle.TotalPrice = copyFrom.TotalPrice;
            candle.OpenVolume = copyFrom.OpenVolume;
            candle.CloseVolume = copyFrom.CloseVolume;
            candle.HighVolume = copyFrom.HighVolume;
            candle.LowVolume = copyFrom.LowVolume;
            candle.TotalVolume = copyFrom.TotalVolume;
            candle.RelativeVolume = copyFrom.RelativeVolume;
            candle.Series = copyFrom.Series;
            candle.Source = copyFrom.Source;
            candle.Arg = copyFrom.Arg;
            if(setState) candle.State = copyFrom.State; // must be the last assignment
        }

RomSunZ
RomSunZ Автор

Ясно, я думал какая-то библиотека c# :)

Вот что у меня получилось, вроде работает, и не надо переопределять свечи:


    public class myTimeFrameCandleBuilder : TimeFrameCandleBuilder
    {
        protected override TimeFrameCandle CreateCandle(CandleSeries series, ICandleBuilderSourceValue value)
        {
            var candle = base.CreateCandle(series, value);
            candle.CloseTime = value.Time;
            return candle;
        }
        protected override bool IsCandleFinishedBeforeChange(CandleSeries series, TimeFrameCandle candle, ICandleBuilderSourceValue value)
        {
            return (value.Time >= candle.OpenTime.Add((TimeSpan)candle.Arg));
        }

        protected override void UpdateCandle(CandleSeries series, TimeFrameCandle candle, ICandleBuilderSourceValue value)
        {
            base.UpdateCandle(series, candle, value);
            candle.CloseTime = value.Time;
        }
    }



                        _candleManager = new CandleManager(_trader);
                        _candleManager.Sources.RemoveWhere(t => t.GetType() == typeof(TimeFrameCandleBuilder));
                        _candleManager.Sources.Add(new myTimeFrameCandleBuilder { Sources = { new TradeCandleBuilderSource(_trader) } });


Не уверен, нужно ли сначала удалять TimeFrameCandleBuilder, но вроде работает

Sergey Sokolov
Sergey Sokolov

CloseTime - это время закрытия свечи, а не время последнего обновления. То, что вы исправили одно место, где логика зависит от правильного CloseTime (IsCandleFinishedBeforeChange), не означает, что нет других таких мест. Наверняка они есть. А значит, от такого фикса могут возникать труднообнаружимые проблемы. Да и после того, как вы таким образом проехались по всем свечкам, CloseTime у них будет расставлен совершенно в разнобой, так как последний тик не обязательно приходит в последнюю секунду, и всегда неверно, так как последний тик свечи всегда идет раньше чем настоящий CloseTime.