Hello, we are currently using the PlatformSession C# implementation to login to the RDP Api. We would like to maintain our session for a long period of time and query multiple instruments through it. This is our current implementation, obtained from parts unknown, as it was done before my time.
I saw a previous answer which used the POST mechanism to extend sessions. Is there a way to modify our current implementation that uses PlatformSession, or would you recommend moving completely over to the POST approach?
using System.Data;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Math.EC;
using Refinitiv.Data.Content.Data;
using Refinitiv.Data.Content.HistoricalPricing;
using Refinitiv.Data.Core;
using ReutersRdpApi.Enums;
using ReutersRdpApi.Interfaces;
using ReutersShared;
namespace ReutersRdpApi.Classes;
public class ReutersApi : IReutersApi
{
private ISession _session;
private ISession _openSession;
private readonly string _appKey;
private readonly string _userName;
private readonly string _password;
private Session.State _state;
private readonly ILogger _log;
private static readonly string _confFileName = "refinitiv-data.config.json";
private static readonly object _lock = new object();
public ReutersApi(string apiKey, string userName, string password, ILogger log = null)
{
this._log = log;
this._appKey = apiKey;
this._userName = userName;
this._password = password;
if (!File.Exists(ReutersApi._confFileName)) CreateConfigFile();
_openSession = CreateSession();
}
public static void CreateConfigFile()
{
var config = @"{""sessions"": {
""default"": ""platform"",
""platform"": {
""default"": ""libsession"",
""libsession"": {
""apis"": {
""data"": {
""historical-pricing"": {
""url"": ""https://api.refinitiv.com/data/historical-pricing/v1""
}
}
}
}
}
}
}";
lock (_lock)
{
File.WriteAllText(ReutersApi._confFileName, config);
}
}
private ISession CreateSession()
{
return PlatformSession.Definition().AppKey(this._appKey)
.OAuthGrantType(new GrantPassword().UserName(this._userName).Password(this._password))
.TakeSignonControl(true).GetSession().OnState(this.OnStateUpdate)
.OnEvent(this.OnEventUpdate);
}
private ISession GetSession()
{
return _openSession;
}
/// <summary>
/// Gets the bars from reuters using the full string Ric with expiry Tenor i.e CLZ2 - CME WTI Dec22.
/// </summary>
/// <param name="fullRic"></param>
/// <param name="barInterval"></param>
/// <param name="numberOfBars"></param>
/// <returns></returns>
public List<ReutersBar>? GetBars(string fullRic, Summaries.Interval barInterval, int numberOfBars)
{
this._session = this.GetSession();
var bars = new List<ReutersBar>();
var fields = new string[]
{
ReutersFields.TimeStamp, ReutersFields.Open, ReutersFields.High, ReutersFields.Low, ReutersFields.Close
};
try
{
this._log?.LogInformation($"Opening Session.");
var sw = new Stopwatch();
sw.Start();
while (this._state != Session.State.Opened)
{
this._session.Open();
if (this._state != Session.State.Opened)
{
var newSession = CreateSession();
this._session = newSession;
this._openSession = newSession;
var lastCode = this._session.LastEventCode;
this._log?.LogWarning($"Session failed to open. Last event code: {lastCode.ToString()} Retrying. ");
Task.Delay(1000);
}
if (sw.Elapsed > TimeSpan.FromSeconds(20))
{
this._log?.LogError($"Session connection timed out! Returning null!");
return bars;
}
}
this._log?.LogInformation($"Getting bars for {fullRic}");
var result = Summaries.Definition(fullRic).Interval(barInterval).Fields(fields).Count((uint)numberOfBars).GetData();
if (result.IsSuccess)
{
this._log?.LogInformation($"Bar request returned success.");
if (result.Data.Records.Count == 0)
{
this._log?.LogInformation("No bars returned.");
return bars;
}
var table = result.Data.Table;
var cols = table.Columns;
var barRecords = table.Rows;
var ricInd = cols.IndexOf("Instrument");
var openInd = cols.IndexOf(ReutersFields.Open);
var highInd = cols.IndexOf(ReutersFields.High);
var lowInd = cols.IndexOf(ReutersFields.Low);
var closeInd = cols.IndexOf(ReutersFields.Close);
var timeInd = cols.IndexOf(ReutersFields.TimeStamp);
if(timeInd == -1) timeInd = cols.IndexOf("DATE");
bars.AddRange(from DataRow data in barRecords
select data.ItemArray
into array
select new ReutersBar
{
Ric = (string) array[ricInd],
Timestamp = DateTime.Parse((string) array[timeInd], CultureInfo.InvariantCulture).ToUniversalTime(),
Open = (double) array[openInd],
High = (double) array[highInd],
Low = (double) array[lowInd],
Close = (double) array[closeInd]
});
}
}
catch (Exception e)
{
this._log?.LogInformation($"Failed to get bars for {fullRic} with error {e}");
}
finally
{
}
return bars;
}
private void OnStateUpdate(Session.State state, string msg, ISession session)
{
this._state = state;
this._log?.LogInformation($"OnStateUpdate: state {state}, msg {msg}.");
}
private void OnEventUpdate(Session.EventCode eventCode, JObject msg, ISession arg3)
{
this._log?.LogInformation($"OnEvent: code {eventCode}, msg {msg}.");
}
Thanks!