public static IReadOnlyList <Day> Read(Sec sec) { if (!Directory.Exists(CACHE_DIR)) { Directory.CreateDirectory(CACHE_DIR); } var cacheFile = Path.Combine(CACHE_DIR, sec.ID + ".json"); if (!File.Exists(cacheFile) || (DateTime.Now - new FileInfo(cacheFile).LastWriteTime) > TimeSpan.FromHours(1)) { var from = new DateTime(2015, 1, 1); var till = DateTime.Today; File.WriteAllText(cacheFile, JsonConvert.SerializeObject(MoexApi.DownloadHistory(sec, from, till))); } return(JsonConvert.DeserializeObject <Day[]>(File.ReadAllText(cacheFile))); }
static void Main(string[] args) { CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; var(sec, thresholds) = ParseArgs(args); var date = DateTime.Now; Console.WriteLine($"Now: {date:s}"); date = date.Date.AddDays(date < date.Date.AddHours(20) ? -1 : 0); //date = new DateTime(2018, 10, 1); Console.WriteLine($"Trade date: {date:s}"); var history = MoexApi.DownloadHistory(sec, date.AddDays(-60), date).ToArray(); if (history.Last().Date != date) { if (MoexApi.HasCandles(sec, date)) { throw new Exception($"No history entry for {date:yyyy-MM-dd}"); } Console.WriteLine($"No trades on {date:yyyy-MM-dd}"); return; } var indicator = RocEma.Calculate(history); var candidate = new TurnCandidate(indicator, indicator.Count - 2); Console.WriteLine(candidate); if (candidate.IsDip(thresholds.Low)) { Notify($"📈 '{sec.ID}' DIP on {date:yyyy-MM-dd}"); } if (candidate.IsPeak(thresholds.High)) { Notify($"📉 '{sec.ID}' PEAK on {date:yyyy-MM-dd}"); } Console.WriteLine(); }