diff --git a/Primary.Examples/GetInstrumentsAndDataExample.cs b/Primary.Examples/GetInstrumentsAndDataExample.cs index 93bbac4..ab88eaa 100644 --- a/Primary.Examples/GetInstrumentsAndDataExample.cs +++ b/Primary.Examples/GetInstrumentsAndDataExample.cs @@ -1,4 +1,7 @@ -using System; +using NUnit.Framework; + +using System; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -22,6 +25,25 @@ public static async Task Run() Console.WriteLine($"{instrument.Market},{instrument.Symbol},{instrument.Currency},{instrument.Description},{instrument.PriceConversionFactor}"); } + + // Get instruments with file cache + Console.WriteLine("Getting available instruments with file cache..."); + string cacheFile = ".\\dummy.tmp"; + // Remove cache to test it. + if(System.IO.File.Exists(cacheFile)) System.IO.File.Delete(cacheFile); + + // 1st call -> Lengthy operation + var allIInstrumentsFileCache = await api.GetAllInstrumentsFileCache(cacheFile); + Trace.Assert(allIInstrumentsFileCache != null); + Trace.Assert(allIInstrumentsFileCache.Count() == allIInstruments.Count()); + + // 2do call -> Fast operation + var allInstrumentsFileCache2 = await api.GetAllInstrumentsFileCache(cacheFile); + Trace.Assert(allIInstrumentsFileCache != null); + Trace.Assert(allIInstrumentsFileCache.Count() == allInstrumentsFileCache2.Count()); + + + // Get all the dollar futures and their trades var fiveDaysAgo = DateTime.Today.AddDays(-5); diff --git a/Primary/Api.cs b/Primary/Api.cs index ed2316b..d6a1d70 100644 --- a/Primary/Api.cs +++ b/Primary/Api.cs @@ -1,11 +1,14 @@ using Newtonsoft.Json; using Newtonsoft.Json.Serialization; + using Primary.Data; using Primary.Data.Orders; using Primary.Serialization; using Primary.WebSockets; + using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net.Http; @@ -87,6 +90,53 @@ public async Task> GetAllInstruments() return data.Instruments; } + /// + /// Same as but with cache capabilities + /// + /// (optional) File to use as cache + /// (optional) How long the cache is valid, in days. + /// Instruments information or null if information can not be retrieved + public async Task> GetAllInstrumentsFileCache(string fileCacheName = null, uint cacheValidAntiquity = 1) + { + IEnumerable instrumentDetail = null; + Serialization.CacheInstrumentsDetails cache = null; + bool shouldRefresh = false; + + if (fileCacheName == null) + fileCacheName = System.IO.Path.GetTempPath() + "AllMarketInstrumentsDetailsCache.json"; + + + if (System.IO.File.Exists(fileCacheName) == true) + { + cache = InstrumentsDetailsSerializer.DesSerializeInstrumentDetail(fileCacheName); + if (cache != null && (DateTime.Now.Date - cache.CacheDate.Date).Days < (int)cacheValidAntiquity) + { + shouldRefresh = false; + instrumentDetail = cache.InstrumentDetailList; + cache = null; + } + else + shouldRefresh = true; + } + else + shouldRefresh = true; + + if (shouldRefresh) + { + instrumentDetail = await GetAllInstruments(); + if (instrumentDetail != null) + { + cache = new CacheInstrumentsDetails(); + cache.CacheDate = DateTime.Now.Date; + cache.InstrumentDetailList = new List(instrumentDetail); + InstrumentsDetailsSerializer.SerializeInstrumentsDetails(cache, fileCacheName); + cache = null; + } + } + + return instrumentDetail; + } + private class GetAllInstrumentsResponse { [JsonProperty("instruments")] diff --git a/Primary/Serialization/InstrumentsDetailsSerializer.cs b/Primary/Serialization/InstrumentsDetailsSerializer.cs new file mode 100644 index 0000000..7043c33 --- /dev/null +++ b/Primary/Serialization/InstrumentsDetailsSerializer.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; + +using Primary.Data; +using System.IO; +using System.Diagnostics; + +namespace Primary.Serialization +{ + internal class CacheInstrumentsDetails + { + /// + /// Timestamp of the cached information + /// + public DateTime CacheDate { get; set; } + public List InstrumentDetailList { get; set; } = new List(); + } + + internal static class InstrumentsDetailsSerializer + { + public static void SerializeInstrumentsDetails(CacheInstrumentsDetails cache, string fileName) + { + var options = new JsonSerializerOptions { WriteIndented = true }; + string info = JsonSerializer.Serialize(cache, options); + File.WriteAllText(fileName, info); + } + + public static CacheInstrumentsDetails DesSerializeInstrumentDetail(string fileName) + { + CacheInstrumentsDetails cache = null; + try + { + if (File.Exists(fileName) == true) + { + string info = File.ReadAllText(fileName); + var options = new JsonSerializerOptions { WriteIndented = true }; + cache = new CacheInstrumentsDetails(); + cache = JsonSerializer.Deserialize(info, options); + } + } + catch (System.Text.Json.JsonException jex) + { + Trace.TraceError(jex.Message); + cache = null; + } + catch (Exception ex) + { + Trace.TraceError(ex.Message); + cache = null; + } + + return cache; + } + } +}