Using the latest release of the Refinitiv Data Library, we're seeing an issue where the Update values for a 1-minute stream are being populated with the latest Insert values from the Daily stream.
Screenshot from MetaStock in the comments.
The steps are to open a chart of one instrument (AAPL.O) with a Daily interval, change the interval to 1-minute (under the hood the Daily stream is closed and a new 1-minute stream is opened), then open a new chart with a different instrument with Daily interval. After the second chart is opened the updates to the first chart will contain high/low/volume from the last Daily Insert record of the first instrument.
The following code illustrates the problem:
static void Main()
{
try
{
ISession session = DesktopSession.Definition().AppKey("xxxxxxxxxxxxxxxxxxx")
.GetSession().OnState((state, msg, s) => Console.WriteLine($"{DateTime.Now}: State: {state}. {msg}"))
.OnEvent((eventCode, msg, s) => Console.WriteLine($"{DateTime.Now}: Event: {eventCode}. {msg}"));
session.Open();
// Open a stream with an interval of 1 day
var stream1 = Summaries
.Definition("AAPL.O")
.Fields("OPEN_PRC", "HIGH_1", "LOW_1", "TRDPRC_1", "ACVOL_UNS")
.Count(10)
.Interval(Summaries.Interval.P1D)
.GetStream(session);
bool isSecondInsert = false;
bool waitForFirstUpdate = true;
(double Open, double High, double Low, double Close) lastDailyInsert = (double.NaN, double.NaN, double.NaN, double.NaN);
stream1
.OnInsert((data, t) =>
{
if (!isSecondInsert)
{
isSecondInsert = true;
}
else
{
var row = data.Table.Select().FirstOrDefault();
lastDailyInsert.Open = GetDataRowValueAsDouble(row, "OPEN_PRC");
lastDailyInsert.High = GetDataRowValueAsDouble(row, "HIGH_1");
lastDailyInsert.Low = GetDataRowValueAsDouble(row, "LOW_1");
lastDailyInsert.Close = GetDataRowValueAsDouble(row, "TRDPRC_1");
Display.FormatTable(data.Table, 10, 10);
}
})
.OnUpdate((data, t) =>
{
waitForFirstUpdate = false;
})
.OnError((data, t) => { })
.Open();
// I'm not sure if we need an actual update to come in or if we just need to wait some time, but this is required to duplicate the issue.
while (waitForFirstUpdate) { }
// Close the stream with an interval of 1 day
stream1.Close();
// Open a stream with an interval of 1 min
var stream2 = Summaries
.Definition("AAPL.O")
.Fields("OPEN_PRC", "HIGH_1", "LOW_1", "TRDPRC_1", "ACVOL_UNS")
.Count(10)
.Interval(Summaries.Interval.PT1M)
.GetStream(session);
stream2
.OnInsert((data, t) => { })
.OnUpdate((data, t) =>
{
var row = data.Table.Select().FirstOrDefault();
var open = GetDataRowValueAsDouble(row, "OPEN_PRC");
var high = GetDataRowValueAsDouble(row, "HIGH_1");
var low = GetDataRowValueAsDouble(row, "LOW_1");
var close = GetDataRowValueAsDouble(row, "TRDPRC_1");
// Only write out the table if the high and low values from the update match the last insert from stream1
if (high == lastDailyInsert.High && low == lastDailyInsert.Low)
{
Display.FormatTable(data.Table, 10, 10);
}
})
.OnError((data, t) => { })
.Open();
// Open a stream with an interval of 1 day with a different ric than stream1 and stream2
// This is required to reproduce this issue.
var stream3 = Summaries
.Definition("IBM.N")
.Fields("OPEN_PRC", "HIGH_1", "LOW_1", "TRDPRC_1", "ACVOL_UNS")
.Count(10)
.Interval(Summaries.Interval.P1D)
.GetStream(session);
stream3
.OnInsert((data, t) => { })
.OnUpdate((data, t) => { })
.OnError((data, t) => { })
.Open();
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine($"\n**************\nFailed to execute: {e.Message}\n{e.InnerException}\n***************");
}
The key is the OnUpdate handler for stream2. You'll notice that it only outputs to the console if the high and low of the 1-min update record match the high and low of the last Daily insert record, which is the crux of the issue.