Dear Developer community,
a Workspace user is trying to retrieve data from Workspace via API.
API Product: LSEG Data Library (.NET) - Platform session, viz.
https://developers.lseg.com/en/api-catalog/lseg-data-platform/lseg-data-library-for-net
These values are loaded
HIGH_1, LOW_1, MID_PRICE a DATE
using the object
HistoricalPricing.Summaries.Definition.
https://cdn.refinitiv.com/public/ld-lib-ref-guide/book/en/sections/content-layer/historical-pricing/summaries/definition.html
The code is as following:
using IsUnip2.DataManagement.BLL.Services.BackgroundServices.Configuration;
using IsUnip2.DataManagement.BLL.Services.BackgroundServices.TimerJobs;
using IsUnip2.DataManagement.BLL.Services.Integration.Entities;
using IsUnip2.DataManagement.BLL.Services.Integration.Interface;
using IsUnip2.DataManagement.BLL.Shared.Helpers;
using IsUnip2.DataManagement.DAL;
using IsUnip2.DataManagement.DAL.Entities;
using IsUnip2.DataManagement.Shared.Enum;
using LSEG.Data.Content.HistoricalPricing;
using LSEG.Data.Core;
using Microsoft.EntityFrameworkCore;
using System.Text;
namespace IsUnip2.DataManagement.BLL.Services.Integration.LSEG
{
public class LSEGIntegrationApiService : IIntegrationApiService
{
private readonly IntegrationServiceDataImportTimerJobOptions _options;
private readonly ApiIntegrationCredential _credentials;
private readonly AppDbContext _dbContext;
private const string FLD_LOW = "LOW_1";
private const string FLD_HIGH = "HIGH_1";
private const string FLD_MID = "MID_PRICE";
private const string FLD_DATE = "DATE";
public LSEGIntegrationApiService(IntegrationServiceDataImportTimerJobOptions options, ApiIntegrationCredential credentials, AppDbContext dbContext)
{
_options = options;
_credentials = credentials;
_dbContext = dbContext;
}
public async Task<IntegrationPricesData> GetPricesData()
{
var result = new IntegrationPricesData();
// Create a session into RDP using v1 credentials
using (var session = PlatformSession.Definition().AppKey(_credentials.AppKey)
.OAuthGrantType(new GrantPassword().UserName(_credentials.Login)
.Password(_credentials.Password))
.TakeSignonControl(true)
.GetSession().OnState((state, msg, s) => Console.WriteLine($"State: {state}. {msg}"))
.OnEvent((eventCode, msg, s) => Console.WriteLine($"Event: {eventCode}. {msg}")))
{
if (session.Open() == Session.State.Opened)
Console.WriteLine("Session successfully opened");
else
throw new Exception("Session failed to open");
var to = DateTime.UtcNow;
var from = to.AddDays(-_options.PeriodInDays);
// TRDPRC_1 - Poslední obchodní cena (Last Traded Price)
// BID - Nabídková cena (Bid Price)
// ASK - Poptávková cena (Ask Price)
// OPEN_PRC - Otevírací cena
// HIGH_1 - Denní maximum
// LOW_1 - Denní minimum
// CLOSE_PRC - Uzavírací hodnota předchozího dne
// CHNG_PCT_1 - Procentuální změna
// MID_PRICE - Střední cena(průměr Bid a Ask)
// ACVOL_1 - Objem obchodů
// VWAP - Průměrná cena vážená objemem(Volume Weighted Average Price)
// DIVIDEND_IND - Indikace dividendy
// TRDPRC_1 - Poslední realizovaný obchod (ne vždy dostupné)
// TRNOVR_UNS - Obrat v měně(obchodní hodnota)
// REFIN_MARGIN - Odhad rafinérské marže(pokud existuje jako feed)
// CRACK_SPREAD - Crack spread – rozdíl mezi vstupy a výstupy(např. 3:2:1 spread)
// PE_RATIO - P/E poměr
// CURRENCY - Měna, ve které je instrument kotován
// parse prices
var quotations = await _dbContext.Quotations.AsNoTracking().Where(i => i.IsActive && i.SourceId == _options.SourceId && !string.IsNullOrEmpty(i.ExternalId)).ToListAsync();
if (quotations.Any())
{
var periodMapping = new Dictionary<Summaries.Interval, PeriodTypes>();
var periods = _dbContext.Periods.Where(i => i.IsActive);
if (periods.FirstOrDefault(i => i.Symbol == PeriodTypes.D.ToString()) != null)
periodMapping.Add(Summaries.Interval.P1D, PeriodTypes.D);
if (periods.FirstOrDefault(i => i.Symbol == PeriodTypes.T.ToString()) != null)
{
periodMapping.Add(Summaries.Interval.P1W, PeriodTypes.T);
periodMapping.Add(Summaries.Interval.P7D, PeriodTypes.T);
}
if (periods.FirstOrDefault(i => i.Symbol == PeriodTypes.M.ToString()) != null)
periodMapping.Add(Summaries.Interval.P1M, PeriodTypes.M);
if (periods.FirstOrDefault(i => i.Symbol == PeriodTypes.Q.ToString()) != null)
periodMapping.Add(Summaries.Interval.P3M, PeriodTypes.Q);
if (periods.FirstOrDefault(i => i.Symbol == PeriodTypes.R.ToString()) != null)
{
periodMapping.Add(Summaries.Interval.P1Y, PeriodTypes.R);
periodMapping.Add(Summaries.Interval.P12M, PeriodTypes.R);
}
foreach (var period in periodMapping)
{
// iterate quotations
foreach (var quotation in quotations)
{
var quotationResult = new IntegrationQuotationProcessingInfo(quotation);
var log = new StringBuilder("0;");
try
{
// Retrieve Interday Summaries with P1D (1-day interval).
var response = Summaries.Definition(quotation.ExternalId)
.Interval(period.Key)
.Fields(FLD_LOW, FLD_HIGH, FLD_MID)
.Start(from)
.End(to)
.GetData();
log.Append("1;");
if (response != null)
{
if (response.IsSuccess)
{
log.Append("2;");
if (
response.Data != null &&
response.Data.Records != null &&
response.Data.Records.Count > 0)
{
log.Append("3;");
// parse fields
var index_low = -1;
var index_high = -1;
var index_mid = -1;
var index_date = -1;
var fields = response.Data.Records[0].Fields;
for (var i = 0; i < fields.Count; i++)
{
var fieldName = fields[i]["name"].ToString();
switch (fieldName)
{
case FLD_LOW:
log.Append("4;");
index_low = i;
break;
case FLD_HIGH:
log.Append("5;");
index_high = i;
break;
case FLD_MID:
log.Append("6;");
index_mid = i;
break;
case FLD_DATE:
log.Append("7;");
index_date = i;
break;
}
}
//if (index_low < 0) throw new Exception($"Missing field '{FLD_LOW}' for reading low value. ");
//if (index_high < 0) throw new Exception($"Missing field '{FLD_HIGH}' for reading high value. ");
//if (index_mid < 0) throw new Exception($"Missing field '{FLD_MID}' for reading mid value. ");
if (index_date < 0) throw new Exception($"Missing field '{FLD_DATE}' for reading date value. ");
log.Append("8;");
// parse data
var items = response.Data.Records[0].Data;
log.Append("9;");
foreach (var item in items)
{
var date = DateOnly.Parse(item[index_date].ToString());
log.Append("10;");
var recordDate = ModelHelper.GetPeriodStart(date, period.Value);
log.Append("11;");
decimal? low = null;
if (index_low >= 0) low = decimal.Parse(item[index_low].ToString());
log.Append("12;");
decimal? high = null;
if (index_high >= 0) high = decimal.Parse(item[index_high].ToString());
log.Append("13;");
decimal? mid = null;
if (index_mid >= 0) mid = decimal.Parse(item[index_mid].ToString());
log.Append("14;");
// find existing inbox price
var inboxPrice = result.InBoxPrices.FirstOrDefault(i => i.QuotationId == quotation.Id && i.RecordDate == recordDate);
log.Append("15;");
if (inboxPrice == null)
{
log.Append("16;");
inboxPrice = new InBoxPrice()
{
Created = DateTime.Now,
CreatedBy = _options.CreatedBy,
RecordDataSource = _options.RecordDataSource,
RecordDate = recordDate,
MinPrice = low,
MaxPrice = high,
AveragePrice = mid,
CurrencyId = quotation.CurrencyId, // null - z kotace?
//PeriodId = quotation.PeriodId, // not null - z kotace?
PeriodId = (int)period.Value,
QuotationId = quotation.Id,
MeasurementUnitId = quotation.MeasurementUnitId // null - z kotace?
//AveragePrice =
//MaxPrice =
//MinPrice =
//MigrationId =
//ImportDescription =
//ImportState =
//ValidationState =
//Note =
};
log.Append("17;");
result.InBoxPrices.Add(inboxPrice);
}
}
}
}
else {
log.Append("18;");
var message = Convert.ToString(response.HttpStatus);
throw new Exception(message);
}
}
}
catch (Exception ex)
{
quotationResult.Exception = ex;
quotationResult.ErrorOccured = true;
quotationResult.Log = log.ToString();
result.ErrorOccured = true;
}
finally
{
result.QuotationProcessingInfos.Add(quotationResult);
}
}
}
}
}
return result;
}
}
}
The goal is to get historical trade prices for the instrument PA000280995F1, as in Excel.
However, with API there is
- Incorrect date (1.1.2026; 1.2.2026) … only these two incorrect dates for the whole period from February 18.
- incorrect period (monthly, quarterly – měsíc, čtvrtletí) … the correct period = daily
- prices min max … required settlement
Is there a problem with a code?
Thank you in advance!