예제 #1
0
        public IList <Candle> LoadCandles(string currencyPairId,
                                          CandlePeriod period,
                                          int limit,
                                          DateTime currentMoment)
        {
            var momentsByPeriod = GetMomentsByPeriod(period, limit, currentMoment).ToList();

            momentsByPeriod.Sort();

            IList <Candle> storedCandles;

            lock (DbOperationLocker)
            {
                storedCandles = _candleRepository.GetAll()
                                .Where(entity => entity.CurrencyPair == currencyPairId && momentsByPeriod.Contains(entity.Moment))
                                .Select(entity => Tuple.Create(entity.ToModel(), entity.Period))
                                .ToList()
                                .GroupBy(candle => candle.Item1.Moment)
                                .Select(candleGroup =>
                {
                    var candle = candleGroup.FirstOrDefault(tuple => tuple.Item2 == period) ?? candleGroup.First();
                    return(candle.Item1);
                })
                                .OrderBy(candle => candle.Moment)
                                .ToList();
            }

            return(storedCandles);
        }
        public void UpdateCandles(List <Candle> c, CandlePeriod p, string symbol)
        {
            ExchangeModel toUpdate = models.FirstOrDefault(x => x.Symbol.Value.symbol == symbol);

            if (p == CandlePeriod.M1)
            {
                this.UpdateCandles_M1(c, toUpdate);
            }
            else if (p == CandlePeriod.M5)
            {
                this.UpdateCandles_M5(c, toUpdate);
            }
            else if (p == CandlePeriod.M30)
            {
                this.UpdateCandles_M30(c, toUpdate);
            }
            else if (p == CandlePeriod.H1)
            {
                this.UpdateCandles_H1(c, toUpdate);
            }
            else if (p == CandlePeriod.H4)
            {
                this.UpdateCandles_H4(c, toUpdate);
            }
            else if (p == CandlePeriod.D1)
            {
                this.UpdateCandles_D1(c, toUpdate);
            }
            else if (p == CandlePeriod.W1)
            {
                this.UpdateCandles_W1(c, toUpdate);
            }
        }
예제 #3
0
        public async Task SubscribeOnCandles(string currencyPairId, CandlePeriod period, Action <IList <Infrastructure.Common.Models.Market.Candle> > callback, int limit = 30)
        {
            var request = new SocketSubscriptionRequest <CandleRequestParameters>
            {
                RequestMethodName      = "subscribeCandles",
                SnapshotMethodName     = "snapshotCandles",
                NotificationMethodName = "updateCandles",
                UnsubscribeMethodName  = "unsubscribeCandles",
                RequestParameters      = new CandleRequestParameters
                {
                    CurrencyPairId = currencyPairId,
                    Period         = period.ToInnerFormat(),
                    Limit          = limit
                }
            };

            await _connection.Subscribe <CandleNotificationParameters>(request, notificationParameters =>
            {
                var notificationCurrencyPairId = notificationParameters.CurrencyPairId;
                var notificationPeriod         = CandlePeriodMap.ToOuterFormat(notificationParameters.Period);

                if (!(currencyPairId == notificationCurrencyPairId && notificationPeriod == period))
                {
                    return;
                }

                callback(notificationParameters.Candles
                         .Select(CandleMap.ToOuterModel)
                         .ToList());
            });
        }
        public async Task InitializeCandles(int exchangeId)
        {
            using (var scope = _serviceProvider.GetRequiredService <IServiceScopeFactory>().CreateScope())
            {
                var marketRepo            = scope.ServiceProvider.GetRequiredService <IMarketRepository>();
                var candleChartRepo       = scope.ServiceProvider.GetRequiredService <ICandleChartRepository>();
                var exchangeAccessService = scope.ServiceProvider.GetRequiredService <IExchangeAccessService>();

                var marketSymbols = this.GetMarketsNeeded();

                foreach (var symbol in marketSymbols)
                {
                    var market = await marketRepo.GetByCurrencyPairAsync(symbol.Value, symbol.Key, exchangeId);

                    if (market != null)
                    {
                        foreach (var period in CandlePeriod.List())
                        {
                            var existingCandleChart = await candleChartRepo.GetByCurrencyPairAsync(symbol.Value, symbol.Key, exchangeId, period);

                            if (existingCandleChart == null)
                            {
                                var toAdd = CandleChart.FromMarket(market, period);

                                candleChartRepo.Add(toAdd);
                                await candleChartRepo.UnitOfWork.SaveEntitiesAsync();
                            }
                        }
                    }
                }
            }
        }
예제 #5
0
        public static CandleInterval ToInnerFormat(this CandlePeriod candlePeriod)
        {
            switch (candlePeriod)
            {
            case CandlePeriod.Minute1:
                return(CandleInterval.Minute);

            case CandlePeriod.Minute3:
                return(CandleInterval.ThreeMinutes);

            case CandlePeriod.Minute5:
                return(CandleInterval.FiveMinutes);

            case CandlePeriod.Minute15:
                return(CandleInterval.QuarterHour);

            case CandlePeriod.Minute30:
                return(CandleInterval.HalfHour);

            case CandlePeriod.Hour1:
                return(CandleInterval.Hour);

            case CandlePeriod.Day1:
                return(CandleInterval.Day);

            case CandlePeriod.Day7:
                return(CandleInterval.Week);

            case CandlePeriod.Month1:
                return(CandleInterval.Month);

            default:
                throw new ConnectorException("Undefined candle period", null);
            }
        }
 public TraceStartedDomainEvent(string traceId, CandlePeriod idealCandlePeriod, TraceStatus traceStatus, DateTime dateStarted)
 {
     TraceId           = traceId ?? throw new ArgumentNullException(nameof(traceId));
     IdealCandlePeriod = idealCandlePeriod ?? throw new ArgumentNullException(nameof(idealCandlePeriod));
     TraceStatus       = traceStatus ?? throw new ArgumentNullException(nameof(traceStatus));
     this.DateStarted  = dateStarted;
 }
예제 #7
0
        public static CandlePeriod GetLowerFramePeriod(this CandlePeriod targetPeriod)
        {
            switch (targetPeriod)
            {
            case CandlePeriod.Month1:
                return(CandlePeriod.Day7);

            case CandlePeriod.Day7:
                return(CandlePeriod.Day1);

            case CandlePeriod.Day1:
                return(CandlePeriod.Hour4);

            case CandlePeriod.Hour4:
                return(CandlePeriod.Hour1);

            case CandlePeriod.Hour1:
                return(CandlePeriod.Minute15);

            case CandlePeriod.Minute30:
                return(CandlePeriod.Minute5);

            case CandlePeriod.Minute15:
                return(CandlePeriod.Minute5);

            case CandlePeriod.Minute5:
                return(CandlePeriod.Minute1);

            case CandlePeriod.Minute3:
                return(CandlePeriod.Minute1);

            default:
                return(targetPeriod);
            }
        }
예제 #8
0
        private long GetSinceUnixTime(CandlePeriod candlePeriod)
        {
            var utcNow = DateTimeOffset.UtcNow;
            var candlePeridInMinutes = (int)candlePeriod;
            var candleSizeInSeconds  = candlePeridInMinutes * 60;

            return(utcNow.AddSeconds(-1 * (candleSizeInSeconds + utcNow.Second)).ToUnixTimeSeconds());
        }
예제 #9
0
 public CandleRequestPacket(int requestId, string symbol, CandlePeriod period, DateTime from, DateTime to)
     : base(APINetworkPacketType.CandleRequest)
 {
     RequestId = requestId;
     Symbol    = symbol;
     Period    = period;
     FromTime  = from;
     ToTime    = to;
 }
예제 #10
0
 public CandleRequestPacket(int requestId, string symbol, CandlePeriod period, DateTime from, DateTime to)
     : base(APINetworkPacketType.CandleRequest)
 {
     RequestId = requestId;
     Symbol = symbol;
     Period = period;
     FromTime = from;
     ToTime = to;
 }
        public async Task Handle(RoundtripTargetPriceHitIntegrationEvent @event)
        {
            try
            {
                var trace = await this._traceRepository.GetByInvestmentId(@event.InvestmentId);

                if (trace == null)
                {
                    return;
                }

                var idealPeriod = trace.IdealCandlePeriod;

                int minAmounts = 0;
                foreach (var strategy in trace.TradeStrategies)
                {
                    if (strategy.GetIdealPeriod().Name == idealPeriod)
                    {
                        if (strategy.Strategy.MinimumAmountOfCandles > minAmounts)
                        {
                            minAmounts = strategy.Strategy.MinimumAmountOfCandles;
                        }
                    }
                }


                var      period = CandlePeriod.FromName(idealPeriod);
                DateTime fromWithWarmingPeriod = (DateTime)trace.DateStarted;
                var      oneCandleMinutes      = CandlePeriodService.GetOneCandleMinutesByPeriod(period);
                var      currentTime           = new RealTimeService().GetCurrentDateTime();
                var      to = currentTime.AddMinutes(-oneCandleMinutes);
                fromWithWarmingPeriod = fromWithWarmingPeriod.AddMinutes(-oneCandleMinutes * (minAmounts + 1));


                await this._trendAnalysisIntegrationEventService
                .PublishThroughEventBusAsync(new TargetPriceCandleDataRequestedIntegrationEvent(
                                                 trace.TraceId,
                                                 @event.RoundtripId,
                                                 trace.Market.ExchangeId,
                                                 trace.Market.BaseCurrency,
                                                 trace.Market.QuoteCurrency,
                                                 idealPeriod,
                                                 @event.HitPrice,
                                                 fromWithWarmingPeriod,
                                                 to
                                                 ));
            }
            catch (Exception ex)
            {
                Console.WriteLine("Handle Integration Event: RoundtripTargetPriceHitIntegrationEvent.");
                Console.WriteLine("Result: Failure.");
                Console.WriteLine("Error Message: " + ex.Message);
            }
        }
예제 #12
0
        public void UpdateCandles(string currencyPairId, CandlePeriod candlePeriod, IList <Candle> candles)
        {
            lock (DbOperationLocker)
            {
                var storedEntities = _candleRepository.GetAll()
                                     .Where(entity => entity.CurrencyPair == currencyPairId && entity.Period == candlePeriod)
                                     .OrderByDescending(entity => entity.Moment)
                                     .Take(candles.Count)
                                     .ToList();

                var storedCandles = storedEntities
                                    .Select(entity => entity.ToModel())
                                    .ToList();

                var newCandles     = new List <Candle>();
                var updatedCandles = new List <Candle>();
                foreach (var receivedCandle in candles)
                {
                    var storedCandle = storedCandles.FirstOrDefault(candle => candle.Moment == receivedCandle.Moment);
                    if (storedCandle == null)
                    {
                        newCandles.Add(receivedCandle);
                    }
                    else
                    {
                        storedCandle.OpenPrice             = receivedCandle.OpenPrice;
                        storedCandle.ClosePrice            = receivedCandle.ClosePrice;
                        storedCandle.MaxPrice              = receivedCandle.MaxPrice;
                        storedCandle.MinPrice              = receivedCandle.MinPrice;
                        storedCandle.VolumeInBaseCurrency  = receivedCandle.VolumeInBaseCurrency;
                        storedCandle.VolumeInQuoteCurrency = receivedCandle.VolumeInQuoteCurrency;
                        updatedCandles.Add(storedCandle);
                    }
                }

                if (newCandles.Any())
                {
                    _candleRepository.Insert(newCandles
                                             .Select(candle => candle.ToEntity(currencyPairId, candlePeriod))
                                             .ToList());
                }

                if (updatedCandles.Any())
                {
                    _candleRepository.Update(updatedCandles
                                             .Select(candle =>
                    {
                        var storedEntity = storedEntities.Single(entity => entity.Moment == candle.Moment);
                        return(candle.ToEntity(currencyPairId, candlePeriod, storedEntity));
                    })
                                             .ToList());
                }
            }
        }
예제 #13
0
        private int GetPeriodDay(CandlePeriod candlePeriod)
        {
            var period = candlePeriod.Id;
            int days   = 0;

            if (period == CandlePeriod.OneDay.Id)
            {
                days = 1;
            }

            return(days);
        }
예제 #14
0
        private int GetPeriodWeek(CandlePeriod candlePeriod)
        {
            var period = candlePeriod.Id;
            int weeks  = 0;

            if (period == CandlePeriod.OneWeek.Id)
            {
                weeks = 1;
            }

            return(weeks);
        }
예제 #15
0
        private CChartPanel CreateChart(string symbol, CandlePeriod p)
        {
            if (!chartsDic[symbol].ContainsKey(p))
            {
                chartsDic[symbol][p] = new CChartPanel(symbolsOn.Single(kv => kv.Key == symbol), (int)p);
                chartsDic[symbol][p].AfterDisplay       -= OnAfterDisplay;
                chartsDic[symbol][p].AfterDisplay       += OnAfterDisplay;
                chartsDic[symbol][p].EmbededInMultiChart = true;
                chartsDic[symbol][p].ParentCZoom         = toolStripTBZoom;
            }

            return(chartsDic[symbol][p]);
        }
예제 #16
0
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="timeframe">ForexConnect timeframe descriptor</param>
            internal TimeframeItem(O2GTimeframe timeframe)
            {
                mTimeframe = timeframe;
                DateTime start = DateTime.Now.AddDays(-1), end = DateTime.Now;

                // parse the timeframe ID to get Quotes Manager timeframe descriptor
                if (!CandlePeriod.parsePeriod(timeframe.ID, ref mTimeframeUnit, ref mTimeframeLength))
                {
                    throw new ArgumentException("Invalide timeframe", "timeframe");
                }

                // get a candle in that timeframe to get it length
                CandlePeriod.getCandle(DateTime.Now, ref start, ref end, mTimeframeUnit, mTimeframeLength, 0, 0);
                mLength = end.Subtract(start);
            }
예제 #17
0
 public static IList <IndicatorPanelSettings> GetAdditionalPanelsSettings(CandlePeriod period)
 {
     return(new[]
     {
         new IndicatorPanelSettings
         {
             AssignedIndicators = new[]
             {
                 new Tuple <IndicatorType, CandlePeriod>(IndicatorType.MACD, period.GetHigherFramePeriod()),
             }
         },
         new IndicatorPanelSettings
         {
             AssignedIndicators = new[]
             {
                 new Tuple <IndicatorType, CandlePeriod>(IndicatorType.MACD, period),
             }
         },
         new IndicatorPanelSettings
         {
             AssignedIndicators = new[]
             {
                 new Tuple <IndicatorType, CandlePeriod>(IndicatorType.Stochastic, period),
             }
         },
         new IndicatorPanelSettings
         {
             AssignedIndicators = new[]
             {
                 new Tuple <IndicatorType, CandlePeriod>(IndicatorType.RelativeStrengthIndex, period),
             }
         },
         new IndicatorPanelSettings
         {
             AssignedIndicators = new[]
             {
                 new Tuple <IndicatorType, CandlePeriod>(IndicatorType.AccumulationDistribution, period),
             }
         },
         new IndicatorPanelSettings
         {
             AssignedIndicators = new[]
             {
                 new Tuple <IndicatorType, CandlePeriod>(IndicatorType.WilliamsR, period),
             }
         },
     });
 }
예제 #18
0
        private DateTime CalculateCandleStartDateWithWarmUp(CandlePeriod candlePeriod, int warmUp)
        {
            DateTime result = this.DateStarted ?? throw new TrendAnalysisDomainException(nameof(this.DateStarted));

            if (candlePeriod.Id == CandlePeriod.OneMinute.Id)
            {
                result = result.AddMinutes(-warmUp * 1);
            }
            else if (candlePeriod.Id == CandlePeriod.FiveMinutes.Id)
            {
                result = result.AddMinutes(-warmUp * 5);
            }
            else if (candlePeriod.Id == CandlePeriod.FifteenMinutes.Id)
            {
                result = result.AddMinutes(-warmUp * 15);
            }
            else if (candlePeriod.Id == CandlePeriod.ThirtyMinutes.Id)
            {
                result = result.AddMinutes(-warmUp * 30);
            }
            else if (candlePeriod.Id == CandlePeriod.OneHour.Id)
            {
                result = result.AddHours(-warmUp * 1);
            }
            else if (candlePeriod.Id == CandlePeriod.TwoHours.Id)
            {
                result = result.AddHours(-warmUp * 2);
            }
            else if (candlePeriod.Id == CandlePeriod.FourHours.Id)
            {
                result = result.AddHours(-warmUp * 4);
            }
            else if (candlePeriod.Id == CandlePeriod.OneDay.Id)
            {
                result = result.AddDays(-warmUp * 1);
            }
            else if (candlePeriod.Id == CandlePeriod.OneWeek.Id)
            {
                result = result.AddDays(-warmUp * 7);
            }
            else
            {
                throw new TrendAnalysisDomainException("No matching canlde period when calculating candle start date.");
            }

            return(result);
        }
예제 #19
0
        private async Task ExecutePastCandleCheck(string tradingPair, CandlePeriod candlePeriod, long lastScanId)
        {
            var utcNow         = DateTimeOffset.UtcNow;
            var candleInterval = (int)candlePeriod * 60;
            var endTime        = (utcNow.ToUnixTimeSeconds() - utcNow.ToUnixTimeSeconds() % candleInterval) - candleInterval;
            var startTime      = endTime - candleInterval * _strategy.DelayInCandlePeriod;

            var pastCandles = await _exchangeProvider.GetCandlesAsync(tradingPair, candlePeriod, startTime, endTime);

            foreach (var pastCandle in pastCandles)
            {
                await _strategy.CheckTrendAsync(tradingPair, pastCandle);

                await _candleRepository.SaveCandleAsync(tradingPair, Mapper.Map <List <CandleDto> >(new List <CandleModel> {
                    pastCandle
                }), lastScanId);
            }
        }
예제 #20
0
 protected override async Task ObserveCandles(string symbol, CandlePeriod p, CancellationTokenSource token)
 {
     while (!token.IsCancellationRequested)
     {
         try
         {
             await this.RefreshCandles(symbol, p, 100);
         }
         catch (Exception ex)
         {
             this.logService.LogException(this.exchangeSettings.ID, null, ex);
         }
         finally
         {
             await Task.Delay(60000);
         }
     }
 }
예제 #21
0
        public async Task <IActionResult> UpdateCandlesFromExchange([FromBody] UpdateCandlesFromExchangeCommand command)
        {
            /* if (!ModelState.IsValid)
             * {
             *   return BadRequest(ModelState);
             * }
             */

            try
            {
                DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
                var      from       = dtDateTime.AddSeconds(command.From);
                var      to         = dtDateTime.AddSeconds(command.To);

                var candles = await this._exchangeAccessService.GetCandlesData(
                    command.ExchangeId,
                    command.BaseCurrency,
                    command.QuoteCurrency,
                    CandlePeriod.FromName(command.CandlePeriod),
                    from,
                    to);

                var chart = await this._candleChartRepository
                            .GetByCurrencyPairAsync(command.BaseCurrency, command.QuoteCurrency, command.ExchangeId, CandlePeriod.FromName(command.CandlePeriod));

                if (chart == null)
                {
                    throw new KeyNotFoundException();
                }

                foreach (var candle in candles)
                {
                    chart.UpdateCandle(candle.Timestamp, candle.High, candle.Low, candle.Open, candle.Close, candle.Volume);
                }

                await _context.SaveEntitiesAsync();

                return(Ok(chart.CandleChartId));
            }
            catch (Exception ex)
            {
                return(NotFound(ex.Message));
            }
        }
예제 #22
0
        public static string PeriodToString(CandlePeriod cp)
        {
            switch (cp)
            {
            case CandlePeriod.m1:
                return("1-Minute");

            case CandlePeriod.m2:
                return("2-Minute");

            case CandlePeriod.m3:
                return("3-Minute");

            case CandlePeriod.m5:
                return("5-Minute");

            case CandlePeriod.m10:
                return("10-Minute");

            case CandlePeriod.m15:
                return("15-Minute");

            case CandlePeriod.m20:
                return("20-Minute");

            case CandlePeriod.m30:
                return("30-Minute");

            case CandlePeriod.m60:
                return("60-Minute");

            case CandlePeriod.D:
                return("Daily");

            case CandlePeriod.W:
                return("Weekly");

            case CandlePeriod.M:
                return("Monthly");

            default:
                return(string.Empty);
            }
        }
예제 #23
0
        private void OnSinglePeriodBtnClick(object sender, EventArgs e)
        {
            ToolStripButton btn = (ToolStripButton)sender;

            CandlePeriod p = ButtonPeriod(btn);

            foreach (ToolStripButton b in btnPeriods.Values)
            {
                b.Checked = (btn == b);
                periodDic[ButtonPeriod(b)] = (btn == b);
            }
            btnPrefered = btnPeriods[p];

            if (symbolOnDisplay == null)
            {
                return;
            }
            RefreshChartPanel();
        }
예제 #24
0
        private int GetPeriodHour(CandlePeriod candlePeriod)
        {
            var period = candlePeriod.Id;
            int hours  = 0;

            if (period == CandlePeriod.OneHour.Id)
            {
                hours = 1;
            }
            else if (period == CandlePeriod.TwoHours.Id)
            {
                hours = 2;
            }
            else if (period == CandlePeriod.FourHours.Id)
            {
                hours = 4;
            }


            return(hours);
        }
예제 #25
0
        private async Task SubscribeOnTradingEvents()
        {
            _workingCandlePeriod = _configurationService.GetTradingSettings().Period;
            var tradingSettings    = _configurationService.GetTradingSettings();
            var periodsForAnalysis = new[]
            {
                tradingSettings.Period.GetLowerFramePeriod(),
                tradingSettings.Period,
                tradingSettings.Period.GetHigherFramePeriod()
            };
            await _candleLoadingService.InitSubscription(Position.CurrencyPairId, periodsForAnalysis);

            _candleLoadingService.CandlesUpdated += OnCandlesUpdated;

            await _orderBookLoadingService.InitSubscription(Position.CurrencyPair.Id);

            _orderBookLoadingService.OrderBookUpdated += OnOrderBookUpdated;

            await _tradingReportsService.InitSubscription(Position.CurrencyPairId);

            _tradingReportsService.OrdersUpdated += OnOrdersUpdated;
        }
예제 #26
0
        public async Task Handle(PaperTradeDataCreatedIntegrationEvent @event)
        {
            try
            {
                var trace = await this._traceRepository.GetByTraceIdAsync(@event.TraceId);

                if (trace == null)
                {
                    return;
                }

                var candles = new List <Candle>();

                foreach (var candle in @event.Candles)
                {
                    candles.Add(new Candle(
                                    candle.Timestamp,
                                    candle.High,
                                    candle.Low,
                                    candle.Open,
                                    candle.Close,
                                    candle.Volume));
                }

                trace.CandleUpdated(candles, CandlePeriod.FromName(@event.CandlePeriod), new RealTimeService(), new IndicatorService(), @event.StrategyId);

                _traceRepository.Update(trace);


                await _traceRepository.UnitOfWork
                .SaveEntitiesAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Handle Integraion Event: PaperTradeDataCreatedIntegrationEvent \n" +
                                  "Result: Failure. \n" +
                                  "Error Message: " + ex.Message);
            }
        }
예제 #27
0
        public static string ToInnerFormat(this CandlePeriod candlePeriod)
        {
            switch (candlePeriod)
            {
            case CandlePeriod.Minute1:
                return("M1");

            case CandlePeriod.Minute3:
                return("M3");

            case CandlePeriod.Minute5:
                return("M5");

            case CandlePeriod.Minute15:
                return("M15");

            case CandlePeriod.Minute30:
                return("M30");

            case CandlePeriod.Hour1:
                return("H1");

            case CandlePeriod.Hour4:
                return("H4");

            case CandlePeriod.Day1:
                return("D1");

            case CandlePeriod.Day7:
                return("D7");

            case CandlePeriod.Month1:
                return("1M");

            default:
                throw new ConnectorException("Undefined candle period", null);
            }
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="instrument">The instrument name</param>
        /// <param name="timeframe">The timeframe id (e.g. m1)</param>
        /// <param name="alive">The flag indicating whether the collection shall be subscribed for updates</param>
        /// <param name="controller">The price update controller</param>
        public PeriodCollection(string instrument, string timeframe, bool alive, IPriceUpdateController controller)
        {
            mInstrument = instrument;
            mTimeframe  = timeframe;
            mAlive      = alive;
            mFilled     = false;

            if (alive)
            {
                // if collection is alive - we will need to calculate the date/time of the candle
                // to which each tick belongs to, so we need to parse the time frame name for
                // further usage
                if (!CandlePeriod.parsePeriod(timeframe, ref mTimeframeUnit, ref mTimeframeLength))
                {
                    throw new ArgumentException("Invalid timeframe", "timeframe");
                }
                // and we need to subscribe to tick updates
                mWaitingUpdates           = new Queue <IOffer>();
                mTradingDayOffset         = controller.TradingDayOffset;
                controller.OnPriceUpdate += OnPriceUpdate;
                mController = controller;
            }
        }
예제 #29
0
        public void StartTracing(ITimeService timeService, CandlePeriod idealCandlePeriod = null)
        {
            if (timeService == null)
            {
                throw new TrendAnalysisDomainException("Time service is not provided when operating on trace.");
            }

            if (idealCandlePeriod == null)
            {
                idealCandlePeriod      = this.CalculateIdealCandlePeriod();
                this.IdealCandlePeriod = idealCandlePeriod.Name;
            }
            else
            {
                this.IdealCandlePeriod = idealCandlePeriod.Name;
            }

            if (this.TraceStatus.Id == TraceStatus.Closed.Id)
            {
                throw new TrendAnalysisDomainException("Cannot start tracing after closed.");
            }
            if (this.TraceStatus.Id != TraceStatus.Started.Id)
            {
                if (!this.TradeStrategies.Any())
                {
                    throw new TrendAnalysisDomainException("There must be at least one strategy before starting trace.");
                }
                this.DateStarted    = timeService.GetCurrentDateTime();
                this._traceStatusId = TraceStatus.Started.Id;

                this.AddDomainEvent(new TraceStartedDomainEvent(
                                        this.TraceId,
                                        CandlePeriod.FromName(this.IdealCandlePeriod),
                                        this.TraceStatus,
                                        this.DateStarted ?? throw new TrendAnalysisDomainException("DateStarted missing when changing status.")));
            }
        }
예제 #30
0
        private int GetPeriodMinute(CandlePeriod candlePeriod)
        {
            var period  = candlePeriod.Id;
            int minutes = 0;

            if (period == CandlePeriod.OneMinute.Id)
            {
                minutes = 1;
            }
            else if (period == CandlePeriod.FiveMinutes.Id)
            {
                minutes = 5;
            }
            else if (period == CandlePeriod.FifteenMinutes.Id)
            {
                minutes = 15;
            }
            else if (period == CandlePeriod.ThirtyMinutes.Id)
            {
                minutes = 30;
            }

            return(minutes);
        }
        /// <summary>
        /// Handling one tick
        /// </summary>
        /// <param name="offer"></param>
        private void HandleOffer(IOffer offer)
        {
            lock (mPeriods)
            {
                // calculate the start time of the period to which the tick belong to
                DateTime start = DateTime.MinValue, end = DateTime.MinValue;

                // calculate candle in EST time because the trading day is always closed by New York time
                // so to avoid handling different hour depending on daylight saying time - use EST always
                // for candle calculations

                // NOTE: for real application this part can be optimized. The candle calculation
                // is quite complex process, so it is better to avoid it when it is not actually required.
                // the way to optimize it is to keep end time of the period and check whether the tick belongs to
                // the period using the following condition start <= tick < end
                // so the calculation of new candle will be used only when tick is actually >= of the end
                // of the current candle.
                CandlePeriod.getCandle(mController.UtcToEst(offer.LastUpdate), ref start, ref end, mTimeframeUnit, mTimeframeLength, mTradingDayOffset, -1);
                start = mController.EstToUtc(start);
                // calculate the serial number of minute (for easier comparing)
                long currMinute = DateToMinute(offer.LastUpdate);

                if (mPeriods.Count == 0)
                {
                    // if here is no data in the collection yet - just add a dummy candle
                    mPeriods.Add(new Period(start, offer.Bid, offer.Ask, offer.MinuteVolume));
                    mLastMinute       = currMinute;
                    mLastMinuteVolume = offer.MinuteVolume;
                }
                else
                {
                    // otherwise get the most recent candle
                    Period period = mPeriods[mPeriods.Count - 1];
                    if (period.Time == start)
                    {
                        // if tick belongs to that period...

                        // update the latest (close) price of bid and ask bars
                        period._Ask.Close = offer.Ask;
                        period._Bid.Close = offer.Bid;

                        // if tick higher than high value of bars - update
                        if (period._Ask.High < offer.Ask)
                        {
                            period._Ask.High = offer.Ask;
                        }
                        if (period._Bid.High < offer.Bid)
                        {
                            period._Bid.High = offer.Bid;
                        }

                        // if tick lower than low value of bars - update
                        if (period._Ask.Low > offer.Ask)
                        {
                            period._Ask.Low = offer.Ask;
                        }
                        if (period._Bid.Low > offer.Bid)
                        {
                            period._Bid.Low = offer.Bid;
                        }

                        // here is a trick.
                        // we don't receive EVERY tick, so we can't simply count them.
                        // It is not a problem for calculating open, high, low and close, because
                        // the tick filter keeps every first, last, and the current extremum ticks
                        // In order to make the volume calculation also correct, the server
                        // broadcasts the accumulated tick volume for the current minute.

                        // so, if the tick belongs to the same minute as the previous tick -
                        // we must substract previous accumulated volume and add a new value.
                        // If the tick is the first tick of a new minute - we must simply
                        // add new accumulated value.
                        if (mLastMinute == currMinute)
                        {
                            period.Volume -= mLastMinuteVolume;
                            period.Volume += offer.MinuteVolume;
                        }
                        else if (currMinute > mLastMinute)
                        {
                            period.Volume += offer.MinuteVolume;
                        }

                        mLastMinute       = currMinute;
                        mLastMinuteVolume = offer.MinuteVolume;
                    }
                    else if (period.Time < start)
                    {
                        // this is a first tick of new period, simply create this period

                        // please pay attention that we don't use the first tick as an open
                        // value but use the previous close instead.
                        // This is how the current system works by default.

                        // soon, here should be an option to use the first tick for the open
                        // price instead.
                        mPeriods.Add(period = new Period(start, period.Bid.Close, period.Ask.Close, offer.MinuteVolume));

                        // update the latest (close) price of bid and ask bars
                        period._Ask.Close = offer.Ask;
                        period._Bid.Close = offer.Bid;

                        // if tick higher than high value of bars - update
                        if (period._Ask.High < offer.Ask)
                        {
                            period._Ask.High = offer.Ask;
                        }
                        if (period._Bid.High < offer.Bid)
                        {
                            period._Bid.High = offer.Bid;
                        }

                        // if tick lower than low value of bars - update
                        if (period._Ask.Low > offer.Ask)
                        {
                            period._Ask.Low = offer.Ask;
                        }
                        if (period._Bid.Low > offer.Bid)
                        {
                            period._Bid.Low = offer.Bid;
                        }

                        mLastMinute       = currMinute;
                        mLastMinuteVolume = offer.MinuteVolume;
                    }
                    else
                    {
                        // yep, it is possible that tick is older than the last candle.
                        // it may happen because we start to collect ticks actually BEFORE
                        // we sent the request to the server. So on the border of the minute
                        // it is possible that we "catch" some ticks of the previous
                        // minute

                        // so, simply ignore them
                        ;
                    }
                }
            }
        }