private InstrumentParams GetUpdatedInstrumentParams(int isinId) { InstrumentParams ip = null; using (containerLock.UpgradableReadLock()) { if (!mapIsinId2InstrumentParams.TryGetValue(isinId, out ip)) { using (containerLock.WriteLock()) { var code = instrumentResolver.GetShortIsinByIsinId(isinId); if (!string.IsNullOrEmpty(code)) { var data = instrumentResolver.GetInstrument(code); if (!data.Equals(default(InstrumentData))) { ip = new InstrumentParams { Instrument = data.Instrument, VolaTranslatedByFeed = true, SessionEndTime = sessionEndTime }; } } if (ip != null) { mapIsinId2InstrumentParams.Add(isinId, ip); } } } } return(ip); }
public static uint GetDecimalPlaces(this InstrumentParams ip) { if (ip.DecimalPlaces > 0) { return(ip.DecimalPlaces); } if (ip.PriceStep <= 0) { return(4); } return(decimalPlaces.GetOrAdd(ip.Instrument, _ => { uint precision = 0; var x = ip.PriceStep; while (x * (decimal)Math.Pow(10, precision) != Math.Round(x * (decimal)Math.Pow(10, precision))) { precision++; } return precision; })); }
public async Task <IActionResult> GetInstrumentsPaged([FromQuery] InstrumentParams instrumentParams) { var items = await _repo.GetInstrumentsPaged(instrumentParams); var itemsDto = _mapper.Map <List <DtoInstrument> >(items); Response.AddPagination(items.CurrentPage, items.PageSize, items.TotalCount, items.TotalPages); return(Ok(itemsDto)); }
public InstrumentSubscription(Instrument instrument, IQFeedInstrumentData data, Action <InstrumentSubscription> onTimeout) { Instrument = instrument; InstrumentParams = new InstrumentParams { Instrument = instrument }; Code = data.Symbol; SecurityType = data.SecurityType; this.onTimeout = onTimeout; }
private async Task HandleAsync(QLInstrumentParams message) { var instrument = await adapter.ResolveInstrumentAsync(message.code); if (instrument == null) { Logger.Error().Print($"Unable to resolve instrument for {message.code}"); return; } decimal pricemin = 0, pricemax = 0; decimal.TryParse(message.pricemin, out pricemin); decimal.TryParse(message.pricemax, out pricemax); // цены шага var stepPrices = new[] { message.stepPriceT, message.stepPrice, message.stepPriceCl, message.stepPricePrCl }; // первая ненулевая цена шага var stepPriceValue = stepPrices.FirstOrDefault(x => x != 0); // проверить утверждение: любая цена шага равна либо stepPriceValue, либо 0 //Debug.Assert(stepPrices.All(x => x == stepPriceValue || x == 0)); // NOTE выяснилось, что утверждение иногда не выполняется. Замечен случай с BRM6 stepPricePrCl=stepPrice=stepPriceT=6.61737, stepPriceCl=6.63015 var ip = new InstrumentParams { Instrument = instrument, BestBidPrice = message.bid, LastPrice = message.last, LotSize = message.lotsize, BestOfferPrice = message.offer, Vola = message.volatility, BestBidQuantity = message.bidQuantity, BestOfferQuantity = message.offerQuantity, PriceStep = message.priceStep, PriceStepValue = stepPriceValue, Settlement = message.settlement, PreviousSettlement = message.previousSettlement, BottomPriceLimit = pricemin, TopPriceLimit = pricemax, VolaTranslatedByFeed = true, SessionEndTime = message.endTime, OpenInterest = message.openinterest }; OnMessageReceived(ip); using (fullCodesLock.Lock()) { fullCodes[ip.Instrument] = message.fullCode; } }
private InstrumentParams GetInstrumentParams(Instrument instrument) { if (!paramDictionary.TryGetValue(instrument, out var ip)) { paramDictionary[instrument] = ip = new InstrumentParams { Instrument = instrument, }; } return(ip); }
public InstrumentParams GetInstrumentParams(Instrument instrument) { using (syncRoot.Lock()) { InstrumentParams instrumentParams; if (!cachedInstrumentParams.TryGetValue(instrument, out instrumentParams)) { instrumentParams = new InstrumentParams { Instrument = instrument }; cachedInstrumentParams.Add(instrument, instrumentParams); } return(instrumentParams); } }
public InstrumentSubscription( CQGCInstrumentResolver instrumentResolver, Instrument instrument, uint contractId) { this.instrumentResolver = instrumentResolver; Instrument = instrument; lockCookie = DeadlockMonitor.Cookie <InstrumentSubscription>("lockCookie-" + ContractId); ContractId = contractId; InstrumentParams = new InstrumentParams { Instrument = instrument }; InstrumentParams.VolaTranslatedByFeed = false; OrderBook = new OrderBook(); }
public async Task <SubscriptionResult> Subscribe(Instrument instrument) { var code = await connector.ResolveInstrumentAsync(instrument); if (code == null) { return(SubscriptionResult.Error(instrument, "Unable to resolve instrument symbol")); } using (allInstrumentLock.WriteLock()) { if (allInstruments.Contains(code)) { if (!subscribedInstruments.Contains(code)) { subscribedInstruments.Add(code); InstrumentParams ip; if (instrumentsParams.TryGetValue(code, out ip)) { OnMessageReceived(ip); } else { ip = new InstrumentParams { Instrument = instrument }; instrumentsParams[code] = ip; } return(SubscriptionResult.OK(instrument)); } return(SubscriptionResult.Error(instrument, "Already subscribed.")); } } return(SubscriptionResult.Error(instrument, "Instrument doesn't exist.")); }
public SendMessageFlags Handle(ContractMetadata metadata) { var result = SendMessageFlags.None; var tickSize = (decimal)metadata.tick_size; if (InstrumentParams.PriceStep != tickSize) { InstrumentParams.PriceStep = tickSize; result |= SendMessageFlags.InstrumentParams; } var tickValue = (decimal)metadata.tick_value; if (InstrumentParams.PriceStepValue != tickValue) { InstrumentParams.PriceStepValue = tickValue; result |= SendMessageFlags.InstrumentParams; } // ситуация, когда шаг цены инструмента - плавающая if (metadata.tick_sizes_by_price != null && metadata.tick_sizes_by_price.Count > 0) { TickSizesByPrice = metadata.tick_sizes_by_price.OrderBy(_ => _.minimum_price).ToList(); } var decimalPlaces = metadata.display_price_scale <= 15 // См. описание поля display_price_scale в WebAPI.proto ? metadata.display_price_scale : InstrumentParams.GetDecimalPlaces(); // DecimalPlaces считаются по PriceStep if (InstrumentParams.DecimalPlaces != decimalPlaces) { InstrumentParams.DecimalPlaces = decimalPlaces; result |= SendMessageFlags.InstrumentParams; } return(result); }
public async Task <PagedList <Instrument> > GetInstrumentsPaged(InstrumentParams instrumentParams) { var items = _context.Instruments.OrderBy(x => x.Name).AsQueryable(); return(await PagedList <Instrument> .CreateAsync(items, instrumentParams.PageNumber, instrumentParams.PageSize)); }
/// <summary> /// Расчёт расширенных (теоретических) параметров опциона. /// </summary> /// <param name="ip"> /// Параметры инструмента (опциона). /// </param> /// <param name="oep"> /// Параметры расчета опциона. /// </param> InstrumentCalculatedParams IModel.CalcPriceAndGreeks(InstrumentParams ip, OptionEvaluationParams oep) { // Создаём шаблон результата var rValue = new InstrumentCalculatedParams(ip); // Проверяем переданные параметры расчёта опциона. if (!PopulateOptionEvaluationParams(ip, ref oep)) return rValue; // Расчёт по переданным параметрам невозможен. Debug.Assert(oep.BaseActivePrice != null, "oep.BaseActivePrice != null"); Debug.Assert(oep.Time != null, "oep.Time != null"); Debug.Assert(oep.Vola != null, "oep.Vola != null"); Debug.Assert(oep.VolaShift != null, "oep.VolaShift != null"); // Рассчитываем количество лет до экспирации опциона. var T = GetYearsTillExpiration(ip, oep.Time.Value); // Сохраняем цену базового актива для которой выполняется расчёт rValue.BaseAssetPrice = oep.BaseActivePrice.Value; // Сохраняем волатильность для которой выполняется расчёт rValue.TheorIV = oep.Vola.Value + oep.VolaShift.Value; // Сохраняем дату и время для которых выполняется расчёт // Этого свойства пока нет в публичной версии (будет в 12.8) //rValue.Time = oep.Time; // Считаем цену и греки через модель Black-Scholes var all = BlackScholes.CalcPriceAndGreeks(ip.OptionType, oep.BaseActivePrice.Value, (double)ip.Strike, T, 0, // TODO Добавить ставку в OptionEvaluationParams oep.Vola.Value + oep.VolaShift.Value); // Сохраняем цену и греки rValue.TheorPrice = all[0]; rValue.Delta = all[1]; rValue.Gamma = all[2]; rValue.Vega = all[3]; rValue.Theta = all[4]; return rValue; }
private static double GetYearsTillExpiration(InstrumentParams ip, DateTime dateTime) { // HARDCODE: Время окончания сессии (экспирации опционов) на FORTS return BlackScholes.YearsBetweenDates(dateTime, ip.ExpirationDate.Date.AddHours(18).AddMinutes(45)); }
/// <summary> /// Выплюнуть из фида параметры инструмента /// </summary> /// <param name="instrumentParams"> /// Параметры инструмента /// </param> internal void Transmit(InstrumentParams instrumentParams) => OnMessageReceived(instrumentParams);
/// <summary> /// Проверка и заполнение параметров расчёта опциона. /// </summary> /// <param name="ip">Параметры инструмента (опциона).</param> /// <param name="oep">Парамметры расчёта опциона.</param> /// <returns>true если параметры валидны, false если расчёт по данным параметрам невозможен.</returns> private bool PopulateOptionEvaluationParams(InstrumentParams ip, ref OptionEvaluationParams oep) { #region Цена базового актива // Если не указана конкретная цена базового актива по которой нужно выполнять расчёт if (!oep.BaseActivePrice.HasValue) { // Пытаемся получить параметры фьючерса для данного опциона var ba = InstrumentParamsProvider.GetOptionFuturesParams(ip.Instrument); if (ba == null) // Если параметры фьючерса не получены - мы не можем выполнить расчёт return false; oep.BaseActivePrice = ba.GetLastPriceOrSettlement(); // Получаем последнюю цену фьючерса } #endregion #region Время if (!oep.Time.HasValue) { // Если не указана точка во времени для которой нужно рассчитать цену опциона выполняем расчёт для текущего времени oep.Time = DateTime.Now; } #endregion #region Волатильность // Если не указана волатильность для которой нужно выполнять расчёт if (!oep.Vola.HasValue) { oep.Vola = (double)GetVola(ip); // Запрашиваем волатильность от этой же модели } #endregion #region Сдвиг волатильности // Если не задан сдвиг волатильности для которого нужно выполнять расчёт if (!oep.VolaShift.HasValue) { oep.VolaShift = 0; } #endregion return true; // Все параметры заполнены, можно производить расчёт }
/// <summary> /// Получение волатильности используемой в модели для опциона. /// </summary> /// <param name="ip">Параметры инструмента.</param> /// <returns>Волатильность.</returns> public decimal GetVola(InstrumentParams ip) { return ip.Volty + modelVolaShift; // Берём сдвиг волатильности заданный через контрол настройки }
/// <summary> /// Расчёт цены опциона. /// </summary> /// <param name="ip"> /// Параметры инструмента (опциона). /// </param> /// <param name="oep"> /// Параметры расчета опциона. /// </param> public double CalcPrice(InstrumentParams ip, OptionEvaluationParams oep) { // Проверяем переданные параметры расчёта опциона. if (!PopulateOptionEvaluationParams(ip, ref oep)) return 0; // Расчёт по переданным параметрам невозможен. Debug.Assert(oep.BaseActivePrice != null, "oep.BaseActivePrice != null"); Debug.Assert(oep.Time != null, "oep.Time != null"); Debug.Assert(oep.Vola != null, "oep.Vola != null"); Debug.Assert(oep.VolaShift != null, "oep.VolaShift != null"); // Рассчитываем количество лет до экспирации опциона. var T = GetYearsTillExpiration(ip, oep.Time.Value); // Считаем цену опциона через модель Black-Scholes return BlackScholes.Price(ip.OptionType, oep.BaseActivePrice.Value, (double)ip.Strike, T, 0, // TODO Добавить ставку в OptionEvaluationParams oep.Vola.Value + oep.VolaShift.Value); }
/// <summary> /// Конструктор /// </summary> /// <param name="instrument"> /// Инструмент /// </param> /// <param name="instrumentParams"> /// Параметры инструмента /// </param> public InstrumentParamsEventArgs([NotNull] Instrument instrument, [NotNull] InstrumentParams instrumentParams) { Instrument = instrument; InstrumentParams = instrumentParams; }