Skip to content

Commit

Permalink
Minor improvement
Browse files Browse the repository at this point in the history
  • Loading branch information
jhonabreul committed Apr 4, 2024
1 parent eb471f3 commit fa7d16a
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
48 changes: 35 additions & 13 deletions FactSetApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using FactSetAuthenticationConfiguration = FactSet.SDK.Utils.Authentication.Configuration;
using QuantConnect.Util;
using System.IO.Compression;
using System.Collections.Concurrent;

namespace QuantConnect.Lean.DataSource.FactSet
{
Expand Down Expand Up @@ -199,8 +200,8 @@ public IEnumerable<Symbol> GetOptionsChain(Symbol underlying, DateTime date, Sym
{
// Let's get the details in batches to avoid requests timing out
var batchCount = (int)Math.Ceiling((double)factSetSymbols.Count / BatchSize);
var detailsBatches = Enumerable.Repeat(default(IEnumerable<OptionsReferences>), batchCount).ToList();
var finishedBatchEvents = detailsBatches.Select(_ => new ManualResetEvent(false)).ToList();

var result = new BlockingCollection<OptionsReferences>(factSetSymbols.Count);

Task.Run(() => Parallel.ForEach(Enumerable.Range(0, batchCount),
new ParallelOptions() { MaxDegreeOfParallelism = 16 },
Expand All @@ -211,29 +212,50 @@ public IEnumerable<Symbol> GetOptionsChain(Symbol underlying, DateTime date, Sym

if (details == null)
{
finishedBatchEvents[batchIndex].Set();
result.CompleteAdding();
loopState.Stop();
return;
}

detailsBatches[batchIndex] = details;
finishedBatchEvents[batchIndex].Set();
try
{
foreach (var detail in details)
{
result.Add(detail);
}
}
catch (InvalidOperationException)
{
// The collection was marked as complete, just stop
}
}));

for (var i = 0; i < batchCount; i++)
var i = 0;
// We expect factSetSymbols.Count results, but we may not get them all if any request fails
for (; i < factSetSymbols.Count; i++)
{
finishedBatchEvents[i].WaitOne();
OptionsReferences detail = null;
try
{
detail = result.Take();
}
// Some thread marked the collection as complete prematurely, so we break
catch (InvalidOperationException)
{
break;
}

var batch = detailsBatches[i];
if (batch == null)
// Just a sanity check
if (detail != null)
{
throw new InvalidOperationException("Could not fetch option details for the given options FOS symbols.");
yield return detail;
}
}

foreach (var symbol in batch)
// The collection was marked as complete before we got all the results, at least one request failed
if (i < factSetSymbols.Count)
{
yield return symbol;
}
throw new InvalidOperationException("Could not fetch option details for the given options FOS symbols.");
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/FactSetSymbolMapperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ public void ConvertsOptionsFosSymbolsToLeanSymbolsInBatch()

var leanSymbolsFromFos = mapper.GetLeanSymbolsFromFactSetFosSymbols(fosSymbols, SecurityType.IndexOption).ToList();

Assert.That(leanSymbolsFromFos, Is.EqualTo(expectedLeanSymbols));
Assert.That(leanSymbolsFromFos, Is.EquivalentTo(expectedLeanSymbols));
}

private FactSetApi GetApi(FactSetSymbolMapper symbolMapper)
Expand Down

0 comments on commit fa7d16a

Please sign in to comment.