/// <summary> /// Запросить инструмент по контракту (асинхронно) /// </summary> /// <param name="contract"> /// Контракт /// </param> /// <param name="objectDescription"> /// Описание объекта, зависящего от контракта /// </param> /// <param name="continuation"> /// Асинхронный коллбек. В случае неудачи резолва инструмента не вызывается. /// </param> public async void GetInstrumentAsync(Contract contract, string objectDescription, Action <Instrument> continuation) { try { string code; Instrument instrument = null; var tryNumber = 0; // Если поле Exchange не указано в contract, тогда нужно сделать дополнительный запрос if (string.IsNullOrEmpty(contract.Exchange)) { // Используем временный инструмент с заведомо уникальным кодом contract = await RequestContract(new Instrument($"TEMPORARY_INSTRUMENT_{Guid.NewGuid():N}"), contract); } // Попытка 1 - сначала пытаемся найти по коду с доп.полями и с указанием родной биржи // Поиск будет идти только по локальному кэшу конвертера if (!string.IsNullOrEmpty(contract.Exchange)) { code = $"exchange:{contract.Exchange};{contract.LocalSymbol}"; instrument = await instrumentConverter.ResolveSymbolAsync(adapter, code, objectDescription); tryNumber++; if (instrument != null) { continuation(instrument); _Log.Debug().Print( $"Instrument {contract.LocalSymbol} was resolved by InstrumentConverter as {instrument}.", LogFields.Code(code), LogFields.Symbol(contract.LocalSymbol), LogFields.Exchange(contract.Exchange), LogFields.Instrument(instrument), LogFields.Attempt(tryNumber) ); return; } } // Попытка 2 - сначала пытаемся найти по коду с доп.полями и с указанием квазибиржи SMART или GLOBEX // поиск будет идти только по локальному кэшу конвертера var exchangeCode = contract.SecType == "FUT" || contract.SecType == "FOP" ? GLOBEX : SMART; code = $"exchange:{exchangeCode};{contract.LocalSymbol}"; instrument = await instrumentConverter.ResolveSymbolAsync(adapter, code, objectDescription); tryNumber++; if (instrument != null) { continuation(instrument); _Log.Debug().Print( $"Instrument {contract.LocalSymbol} was resolved by InstrumentConverter as {instrument}.", LogFields.Code(code), LogFields.Symbol(contract.LocalSymbol), LogFields.Exchange(contract.Exchange), LogFields.Instrument(instrument), LogFields.Attempt(tryNumber) ); return; } // Попытка 3 - ищем просто по коду code = contract.LocalSymbol; instrument = await instrumentConverter.ResolveSymbolAsync(adapter, code, objectDescription); tryNumber++; if (instrument != null) { continuation(instrument); _Log.Debug().Print( $"Instrument {contract.LocalSymbol} was resolved by InstrumentConverter as {instrument}.", LogFields.Code(code), LogFields.Symbol(contract.LocalSymbol), LogFields.Exchange(contract.Exchange), LogFields.Instrument(instrument), LogFields.Attempt(tryNumber) ); return; } _Log.Error().Print( $"Instrument {contract.LocalSymbol} wasn't resolved by InstrumentConverter.", LogFields.Code(code), LogFields.Symbol(contract.LocalSymbol), LogFields.Exchange(contract.Exchange), LogFields.Attempt(tryNumber) ); } catch (Exception e) { _Log.Error().Print(e, $"Failed to get instrument from {contract}"); } }