private Candle(
     string assetPairId, 
     CandlePriceType priceType, 
     CandleTimeInterval timeInterval, 
     DateTime timestamp, 
     DateTime latestChangeTimestamp,
     DateTime openTimestamp,
     double open, 
     double close, 
     double low, 
     double high,
     double tradingVolume,
     double tradingOppositeVolume)
 {
     AssetPairId = assetPairId;
     PriceType = priceType;
     TimeInterval = timeInterval;
     Timestamp = timestamp;
     LatestChangeTimestamp = latestChangeTimestamp;
     OpenTimestamp = openTimestamp;
     Open = open;
     Close = close;
     Low = low;
     High = high;
     TradingVolume = tradingVolume;
     TradingOppositeVolume = tradingOppositeVolume;
 }
        private static ICandle DeserializeCandle(byte[] value, string assetPairId, CandlePriceType priceType, CandleTimeInterval timeInterval)
        {
            // value is:
            // 0 .. TimestampFormat.Length - 1 bytes: timestamp as yyyyMMddHHmmss in ASCII
            // TimestampFormat.Length .. end bytes: serialized RedistCachedCandle

            var timestampLength = TimestampFormat.Length;
            var timestampString = Encoding.ASCII.GetString(value, 0, timestampLength);
            var timestamp       = DateTime.ParseExact(timestampString, TimestampFormat, CultureInfo.InvariantCulture);

            using (var stream = new MemoryStream(value, timestampLength, value.Length - timestampLength, writable: false))
            {
                var cachedCandle = MessagePack.MessagePackSerializer.Deserialize <RedisCachedCandle>(stream);

                return(Candle.Create(
                           assetPairId,
                           priceType,
                           timeInterval,
                           timestamp,
                           cachedCandle.Open,
                           cachedCandle.Close,
                           cachedCandle.High,
                           cachedCandle.Low,
                           cachedCandle.TradingVolume,
                           cachedCandle.TradingOppositVolume,
                           cachedCandle.LastTradePrice,
                           cachedCandle.LastUpdateTimestamp));
            }
        }
示例#3
0
        public Task TruncateCacheAsync(string assetId, CandlePriceType priceType, CandleTimeInterval timeInterval,
                                       int storedCandlesCountLimit, SlotType slotType)
        {
            var key = GetKey(_market, assetId, priceType, timeInterval, slotType);

            return(_database.SortedSetRemoveRangeByRankAsync(key, 0, -storedCandlesCountLimit - 1, CommandFlags.FireAndForget));
        }
示例#4
0
        public IReadOnlyList <ICandle> FillGapUpTo(AssetPair assetPair, CandlePriceType priceType, DateTime dateTime, ICandle endCandle)
        {
            var key = GetKey(assetPair.Id, priceType);

            _lastCandles.TryGetValue(key, out var lastCandle);

            if (lastCandle == null)
            {
                return(new List <ICandle>());
            }

            var lastCandleHeight = lastCandle.High - lastCandle.Low;
            var endCandleHeight  = endCandle?.High - endCandle?.Low ?? lastCandleHeight;
            var spread           = CalculateSpread(lastCandleHeight, endCandleHeight);

            var result = GenerateCandles(
                assetPair,
                priceType,
                lastCandle.Timestamp,
                dateTime,
                lastCandle.Close,
                endCandle?.Open ?? lastCandle.Open,
                spread)
                         .ToList();

            // Remember the last candle, if any
            if (result.Any())
            {
                _lastCandles[key] = Candle.Copy(result.Last());
            }

            return(result);
        }
 private Candle(
     string assetPair,
     CandlePriceType priceType,
     CandleTimeInterval timeInterval,
     DateTime timestamp,
     double open,
     double close,
     double high,
     double low,
     double tradingVolume,
     double tradingOppositeVolume,
     double lastTradePrice,
     DateTime lastUpdateTimestamp)
 {
     AssetPairId           = assetPair;
     PriceType             = priceType;
     TimeInterval          = timeInterval;
     Timestamp             = timestamp;
     Open                  = open;
     Close                 = close;
     High                  = high;
     Low                   = low;
     TradingVolume         = tradingVolume;
     TradingOppositeVolume = tradingOppositeVolume;
     LastTradePrice        = lastTradePrice;
     LastUpdateTimestamp   = lastUpdateTimestamp;
 }
 public static Candle Create(
     string assetPair,
     CandlePriceType priceType,
     CandleTimeInterval timeInterval,
     DateTime timestamp,
     double open,
     double close,
     double high,
     double low,
     double tradingVolume,
     double tradingOppositeVolume,
     double lastTradePrice,
     DateTime lastUpdateTimestamp)
 {
     return(new Candle(
                assetPair,
                priceType,
                timeInterval,
                timestamp.TruncateTo(timeInterval),
                open,
                close,
                high,
                low,
                tradingVolume,
                tradingOppositeVolume,
                lastTradePrice,
                lastUpdateTimestamp));
 }
        public async Task <IEnumerable <ICandle> > GetLastCandlesAsync(CandlePriceType priceType, CandleTimeInterval interval, DateTime to, int number)
        {
            var whereClause =
                "WHERE PriceType=@priceTypeVar AND TimeInterval=@intervalVar AND Timestamp <= @toVar";

            using (var conn = new SqlConnection(_connectionString))
            {
                try
                {
                    var objects = await conn.QueryAsync <SqlCandleHistoryItem>($"SELECT TOP {number} * FROM {_tableName} {whereClause} ORDER BY Timestamp DESC",
                                                                               new { priceTypeVar = priceType, intervalVar = interval, toVar = to }, null, commandTimeout : ReadCommandTimeout);

                    return(objects.OrderBy(x => x.Timestamp));
                }

                catch (Exception ex)
                {
                    _log?.WriteErrorAsync(nameof(SqlCandlesHistoryRepository), nameof(GetLastCandlesAsync),
                                          new
                    {
                        message = "Failed to get an candle list",
                        priceType,
                        interval,
                        to,
                        number,
                        _tableName
                    }.ToJson(), ex);
                    return(Enumerable.Empty <ICandle>());
                }
            }
        }
        public static Candle CreateQuotingCandle(
            string assetPair,
            DateTime timestamp,
            double price,
            CandlePriceType priceType, 
            CandleTimeInterval timeInterval)
        {
            if (priceType != CandlePriceType.Ask &&
                priceType != CandlePriceType.Bid &&
                priceType != CandlePriceType.Mid)
            {
                throw new ArgumentOutOfRangeException(nameof(priceType), priceType, "Price type should be Ask, Bid or Mid for the quoting candle");
            }

            var intervalTimestamp = timestamp.TruncateTo(timeInterval);

            return new Candle
            (
                assetPair,
                priceType,
                timeInterval,
                intervalTimestamp,
                timestamp,
                timestamp,
                price,
                price,
                price,
                price,
                0,
                0
            );
        }
        public async Task <IEnumerable <ICandle> > GetLastCandlesAsync(string assetPairId, CandleTimeInterval interval,
                                                                       CandlePriceType priceType, DateTime to, int number)
        {
            var repo = GetRepo(assetPairId);

            return(await repo.GetLastCandlesAsync(priceType, interval, to, number));
        }
示例#10
0
        /// <summary>
        /// Assumed that all candles have the same AssetPair, PriceType, and Timeinterval
        /// </summary>
        public async Task InsertOrMergeAsync(IEnumerable <ICandle> candles, CandlePriceType priceType)
        {
            var partitionKey = CandleHistoryEntity.GeneratePartitionKey(priceType);

            // Despite of AzureTableStorage already split requests to chunks,
            // splits to the chunks here to reduse cost of operation timeout

            var candleByRowsChunks = candles
                                     .GroupBy(candle => CandleHistoryEntity.GenerateRowKey(candle.Timestamp, _timeInterval))
                                     .Batch(100);

            foreach (var candleByRowsChunk in candleByRowsChunks)
            {
                // If we can't store the candles, we can't do anything else, so just retries until success
                await Policy
                .Handle <Exception>()
                .WaitAndRetryForeverAsync(
                    retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                    (exception, timeSpan) =>
                {
                    var context = $"{_assetPairId}-{priceType}-{_timeInterval}";

                    return(_log.WriteErrorAsync("Persist candle rows chunk with retries", context, exception));
                })
                .ExecuteAsync(() => SaveCandlesBatchAsync(candleByRowsChunk, partitionKey));
            }
        }
示例#11
0
        private decimal GetLastNonZeroPrice(string assetPair, CandlePriceType priceType)
        {
            var key = GetKey(assetPair, priceType);

            _lastNonZeroPrices.TryGetValue(key, out var price);

            return(price);
        }
        /// <summary>
        /// Finds out the oldest stored candle's timestamp (if any).
        /// </summary>
        /// <param name="assetPairId"></param>
        /// <param name="priceType"></param>
        /// <param name="interval"></param>
        /// <returns>The oldest candle or null./></returns>
        /// <exception cref="InvalidOperationException">If the specified asset pair is not currently supported by storage.</exception>
        public async Task <ICandle> TryGetOldestCandleAsync(string assetPairId, CandlePriceType priceType,
                                                            CandleTimeInterval interval)
        {
            CheckupAssetPairOrFail(assetPairId);

            var firstCandle = await _candlesHistoryRepository.TryGetFirstCandleAsync(assetPairId, interval, priceType);

            return(firstCandle); // The risk of the null is minimal but not excluded.
        }
        public async Task <DateTime?> GetStartDateAsync(string assetPair, CandlePriceType priceType)
        {
            var oldestFeedHistory = await _feedHistoryRepository.GetTopRecordAsync(assetPair, priceType);

            return(oldestFeedHistory
                   ?.Candles
                   .First()
                   .ToCandle(assetPair, priceType, oldestFeedHistory.DateTime).Timestamp);
        }
示例#14
0
 /// <summary>
 /// Initializes a new instance of the GetCandlesHistoryBatchRequest
 /// class.
 /// </summary>
 /// <param name="priceType">Possible values include: 'Unspecified',
 /// 'Bid', 'Ask', 'Mid', 'Trades'</param>
 /// <param name="timeInterval">Possible values include: 'Unspecified',
 /// 'Sec', 'Minute', 'Min5', 'Min15', 'Min30', 'Hour', 'Hour4',
 /// 'Hour6', 'Hour12', 'Day', 'Week', 'Month'</param>
 /// <param name="fromMoment">Inclusive from moment</param>
 /// <param name="toMoment">Exclusive to moment. If equals to the
 /// Lykke.Service.CandlesHistory.Models.CandlesHistory.GetCandlesHistoryBatchRequest.FromMoment,
 /// then exactly candle for exactly this moment will be
 /// returned</param>
 public GetCandlesHistoryBatchRequest(CandlePriceType priceType, CandleTimeInterval timeInterval, System.DateTime fromMoment, System.DateTime toMoment, IList <string> assetPairs = default(IList <string>))
 {
     AssetPairs   = assetPairs;
     PriceType    = priceType;
     TimeInterval = timeInterval;
     FromMoment   = fromMoment;
     ToMoment     = toMoment;
     CustomInit();
 }
示例#15
0
        public async Task <ICandle> TryGetFirstCandleAsync(CandlePriceType priceType, CandleTimeInterval timeInterval)
        {
            var candleEntity = await _tableStorage.GetTopRecordAsync(CandleHistoryEntity.GeneratePartitionKey(priceType));

            return(candleEntity
                   ?.Candles
                   .First()
                   .ToCandle(_assetPairId, priceType, candleEntity.DateTime, timeInterval));
        }
        public async Task <ICandle> TryGetFirstCandleAsync(CandlePriceType priceType, CandleTimeInterval timeInterval)
        {
            using (var conn = new SqlConnection(_connectionString))
            {
                var candle = await conn.QueryFirstOrDefaultAsync <SqlCandleHistoryItem>(
                    $"SELECT TOP(1) * FROM {_tableName} WHERE PriceType=@priceTypeVar AND TimeInterval=@intervalVar ",
                    new { priceTypeVar = priceType, intervalVar = timeInterval });

                return(candle);
            }
        }
        // ReSharper disable once UnusedMember.Global
        public static async Task <IReadOnlyDictionary <string, CandlesHistoryResponseModel> > TryGetCandlesHistoryBatchAsync(
            this ICandleshistoryservice service,
            IList <string> assetPairs,
            CandlePriceType priceType,
            CandleTimeInterval timeInterval,
            DateTime fromMoment,
            DateTime toMoment,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var result = await service.GetCandlesHistoryBatchOrErrorAsync(new GetCandlesHistoryBatchRequest(priceType, timeInterval, fromMoment, toMoment, assetPairs), cancellationToken);

            return(result as IReadOnlyDictionary <string, CandlesHistoryResponseModel>);
        }
        public async Task <IActionResult> GetCandlesHistory(string assetPairId, CandlePriceType priceType, CandleTimeInterval timeInterval, DateTime fromMoment, DateTime toMoment)
        {
            fromMoment = fromMoment.ToUniversalTime();
            toMoment   = toMoment.ToUniversalTime();

            if (string.IsNullOrWhiteSpace(assetPairId))
            {
                return(BadRequest(ErrorResponse.Create(nameof(assetPairId), "Asset pair is required")));
            }
            if (priceType == CandlePriceType.Unspecified)
            {
                return(BadRequest(ErrorResponse.Create(nameof(timeInterval), $"Price type should not be {CandlePriceType.Unspecified}")));
            }
            if (timeInterval == CandleTimeInterval.Unspecified)
            {
                return(BadRequest(ErrorResponse.Create(nameof(timeInterval), $"Time interval should not be {CandleTimeInterval.Unspecified}")));
            }
            if (fromMoment > toMoment)
            {
                return(BadRequest(ErrorResponse.Create("From date should be early or equal than To date")));
            }
            if (!_candleHistoryAssetConnections.ContainsKey(assetPairId))
            {
                return(BadRequest(ErrorResponse.Create(nameof(assetPairId), "Asset pair is not configured")));
            }
            if (await _assetPairsManager.TryGetAssetPairAsync(assetPairId) == null)
            {
                return(BadRequest(ErrorResponse.Create(nameof(assetPairId), "Asset pair not found")));
            }

            var activeSlot = await _candlesManager.GetActiveSlotAsync();

            var candles = await _candlesManager.GetCandlesAsync(assetPairId, priceType, timeInterval, fromMoment, toMoment, activeSlot);

            // May return much less candles than it was requested or even an empty set of data for now the service looks
            // only through the cache (no persistent data is used).
            return(Ok(new CandlesHistoryResponseModel
            {
                History = candles.Select(c => new CandlesHistoryResponseModel.Candle
                {
                    DateTime = c.Timestamp,
                    Open = c.Open,
                    Close = c.Close,
                    High = c.High,
                    Low = c.Low,
                    TradingVolume = c.TradingVolume,
                    TradingOppositeVolume = c.TradingOppositeVolume,
                    LastTradePrice = c.LastTradePrice
                })
            }));
        }
示例#19
0
        public async Task <IEnumerable <ICandle> > GetCandlesAsync(CandlePriceType priceType, CandleTimeInterval interval, DateTime from, DateTime to)
        {
            if (priceType == CandlePriceType.Unspecified)
            {
                throw new ArgumentException(nameof(priceType));
            }

            var query    = GetTableQuery(priceType, interval, from, to);
            var entities = await _tableStorage.WhereAsync(query);

            var candles = entities
                          .SelectMany(e => e.Candles.Select(ci => ci.ToCandle(_assetPairId, e.PriceType, e.DateTime, interval)));

            return(candles.Where(c => c.Timestamp >= from && c.Timestamp < to));
        }
            public void GetCandlesHistoryValidateParametersNullAssetPairIdTest()
            {
                CandlePriceType    priceType    = CandlePriceType.Ask;
                CandleTimeInterval timeInterval = CandleTimeInterval.Hour;
                DateTime           fromMoment   = DateTime.Now.AddHours(-12).ToUniversalTime();
                DateTime           toMoment     = DateTime.Now.ToUniversalTime();

                MarketType marketType = MarketType.Mt;

                Step("Make GET /api/candlesHistory without assetPairId and validate response", () =>
                {
                    var response = apiV2.CandlesHistory.GetCandlesHistory(marketType, null, priceType, timeInterval, fromMoment, toMoment);
                    Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
                });
            }
            public void GetCandlesHistoryPositiveSpotTest()
            {
                var                marketType   = MarketType.Spot;
                var                assetPairId  = "BTCUSD";
                CandlePriceType    priceType    = CandlePriceType.Ask;
                CandleTimeInterval timeInterval = CandleTimeInterval.Hour;
                DateTime           fromMoment   = DateTime.Now.AddHours(-12).ToUniversalTime();
                DateTime           toMoment     = DateTime.Now.ToUniversalTime();

                Step($"Make GET /api/candlesHistory with parameters: marketType: {marketType}, assetPairId: {assetPairId}, priceType: {priceType}, timeInterval: {timeInterval}, fromMoment: {fromMoment}, toMoment: {toMoment}", () =>
                {
                    var response = apiV2.CandlesHistory.GetCandlesHistory(marketType, assetPairId, priceType, timeInterval, fromMoment, toMoment);
                    Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
                    Assert.That(response.GetResponseObject(), Is.Not.Null);
                });
            }
示例#22
0
        public MigrationCandleMergeResult Merge(string assetPair, CandlePriceType priceType, CandleTimeInterval timeInterval, DateTime timestamp, double open, double close, double low, double high)
        {
            var key = GetKey(assetPair, timeInterval, priceType);

            Candle oldCandle = null;
            var    newCandle = _candles.AddOrUpdate(key,
                                                    addValueFactory: k => Candle.Create(
                                                        assetPair: assetPair,
                                                        priceType: priceType,
                                                        timeInterval: timeInterval,
                                                        timestamp: timestamp,
                                                        open: open,
                                                        close: close,
                                                        high: high,
                                                        low: low,
                                                        tradingVolume: 0,
                                                        tradingOppositeVolume: 0,
                                                        lastTradePrice: 0,
                                                        lastUpdateTimestamp: timestamp),
                                                    updateValueFactory: (k, old) =>
            {
                oldCandle = old;

                // Start new candle?
                var intervalTimestamp = timestamp.TruncateTo(timeInterval);
                if (oldCandle.Timestamp != intervalTimestamp)
                {
                    return(Candle.Create(
                               assetPair: assetPair,
                               priceType: priceType,
                               timeInterval: timeInterval,
                               timestamp: intervalTimestamp,
                               open: open,
                               close: close,
                               high: high,
                               low: low,
                               tradingVolume: 0,
                               tradingOppositeVolume: 0,
                               lastTradePrice: 0,
                               lastUpdateTimestamp: timestamp));
                }

                return(oldCandle.Update(close, low, high, 0, 0, 0, timestamp));
            });

            return(new MigrationCandleMergeResult(newCandle, !newCandle.Equals(oldCandle)));
        }
示例#23
0
        public async Task InitializeAsync(
            string assetPairId,
            CandlePriceType priceType,
            CandleTimeInterval timeInterval,
            IReadOnlyCollection <ICandle> candles,
            SlotType slotType)
        {
            foreach (var candle in candles)
            {
                if (candle.AssetPairId != assetPairId)
                {
                    throw new ArgumentException($"Candle {candle.ToJson()} has invalid AssetPriceId", nameof(candles));
                }
                if (candle.PriceType != priceType)
                {
                    throw new ArgumentException($"Candle {candle.ToJson()} has invalid PriceType", nameof(candles));
                }
                if (candle.TimeInterval != timeInterval)
                {
                    throw new ArgumentException($"Candle {candle.ToJson()} has invalid TimeInterval", nameof(candles));
                }
            }

            // Since we have introduced a semaphore waiting in cache initialization service, we do not
            // need any additional concurrent-safe actions here. Yes, it's better to wait a semaphore
            // somewhere else but here 'cause otherwise we'll get a fully synchronous cache operation.

            var key = GetKey(_market, assetPairId, priceType, timeInterval, slotType);

            var tasks = new List <Task>
            {
                _database.KeyDeleteAsync(key)
            };

            foreach (var candlesBatch in candles.Batch(400))
            {
                var entites = candlesBatch
                              .Select(candle => new SortedSetEntry(SerializeCandle(candle), 0))
                              .ToArray();

                tasks.Add(_database.SortedSetAddAsync(key, entites));
            }

            _database.WaitAll(tasks.ToArray());
            await Task.WhenAll(tasks);
        }
示例#24
0
        private async Task <decimal?> GetAvg(string assetPairId, CandlePriceType priceType, DateTime now)
        {
            var candlesHistory = await _candlesHistoryService.GetCandlesHistoryAsync(assetPairId, priceType,
                                                                                     CandleTimeInterval.Min5, now.AddHours(-12), now);

            if (!candlesHistory.History.Any())
            {
                _log.WriteErrorAsync(GetComponentName(), nameof(GetAvg),
                                     new Exception("No candles history found for " + assetPairId)
                {
                    Data = { { "AssetPairId", assetPairId } }
                });
                return(null);
            }

            return((decimal)candlesHistory.History.SelectMany(h => new[] { h.Open, h.Close }).Average());
        }
        public async Task <IEnumerable <ICandle> > GetLastCandlesAsync(CandlePriceType priceType, CandleTimeInterval interval, DateTime to, int number)
        {
            if (priceType == CandlePriceType.Unspecified)
            {
                throw new ArgumentException(nameof(priceType));
            }

            var query    = GetTableQuery(priceType, interval, DateTime.MinValue, to);
            var entities = await _tableStorage.WhereAsync(query);

            var candles = entities
                          .SelectMany(e => e.Candles.Select(ci => ci.ToCandle(_assetPairId, e.PriceType, e.DateTime, interval)));

            return(candles.Where(c => c.Timestamp < to)
                   .OrderByDescending(c => c.Timestamp)
                   .Take(number)
                   .OrderBy(c => c.Timestamp));
        }
示例#26
0
        public ICandle ToCandle(string assetPairId, CandlePriceType priceType, DateTime baseTime)
        {
            var timeStamp = baseTime.AddSeconds(Tick);

            return(Candle.Create(
                       open: Open,
                       close: Close,
                       high: High,
                       low: Low,
                       assetPair: assetPairId,
                       priceType: priceType,
                       timeInterval: CandleTimeInterval.Sec,
                       timestamp: timeStamp,
                       tradingVolume: 0,
                       tradingOppositeVolume: 0,
                       lastTradePrice: 0,
                       lastUpdateTimestamp: timeStamp));
        }
示例#27
0
 public IEnumerable <ICandle> GenerateCandles(
     AssetPair assetPair,
     CandlePriceType priceType,
     DateTime exclusiveStartDate,
     DateTime exclusiveEndDate,
     double exclusiveStartPrice,
     double exclusiveEndPrice,
     double spread)
 {
     return(GenerateCandles(
                assetPair,
                priceType,
                exclusiveStartDate,
                exclusiveEndDate,
                ConvertToDecimal(exclusiveStartPrice),
                ConvertToDecimal(exclusiveEndPrice),
                ConvertToDecimal(spread)));
 }
示例#28
0
        public float GetPrice(CandlePriceType priceType)
        {
            switch (priceType)
            {
            case CandlePriceType.Close: return(close);

            case CandlePriceType.Open: return(open);

            case CandlePriceType.High: return(high);

            case CandlePriceType.Low: return(low);

            case CandlePriceType.HighLowMid: return((high + low) * 0.5f);

            case CandlePriceType.OpenCloseMid: return((open + close) * 0.5f);
            }
            return(close);
        }
        public ICandle ToCandle(string assetPairId, CandlePriceType priceType, DateTime baseTime, CandleTimeInterval timeInterval)
        {
            var normalizedTick = Tick - GetIntervalTickOrigin(timeInterval);

            return(Candle.Create
                   (
                       open: Open,
                       close: Close,
                       high: High,
                       low: Low,
                       assetPair: assetPairId,
                       priceType: priceType,
                       timeInterval: timeInterval,
                       timestamp: baseTime.AddIntervalTicks(normalizedTick, timeInterval),
                       tradingVolume: TradingVolume,
                       tradingOppositeVolume: TradingOppositeVolume,
                       lastTradePrice: LastTradePrice,
                       lastUpdateTimestamp: LastUpdateTimestamp
                   ));
        }
        public void UpdateCurrentHistoryDate(DateTime date, CandlePriceType priceType)
        {
            switch (priceType)
            {
            case CandlePriceType.Bid:
                CurrentBidDate = date;
                break;

            case CandlePriceType.Ask:
                CurrentAskDate = date;
                break;

            case CandlePriceType.Mid:
                CurrentMidDate = date;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(priceType), priceType, "Invalid price type");
            }
        }
示例#31
0
 public float GetPrice(CandlePriceType priceType)
 {
     switch (priceType)
     {
         case CandlePriceType.Close : return close;
         case CandlePriceType.Open : return open;
         case CandlePriceType.High : return high;
         case CandlePriceType.Low : return low;
         case CandlePriceType.HighLowMid : return (high + low) * 0.5f;
         case CandlePriceType.OpenCloseMid : return (open + close) * 0.5f;
     }
     return close;
 }