public static bool HasCandles(Sec sec, DateTime date) { var dateString = date.ToString(DATE_FORMAT); var url = $"https://iss.moex.com/iss/engines/stock/markets/{sec.Market}/boards/{sec.Board}/securities/{sec.ID}/candles.json" + "?from=" + dateString + "&till=" + dateString; return(JsonConvert.DeserializeObject <JObject>(CURL(url))["candles"]["data"].Count() > 0); }
public static IEnumerable <Day> DownloadHistory(Sec sec, DateTime from, DateTime till) { var start = 0; var limit = 100; while (true) { var url = $"https://iss.moex.com/iss/history/engines/stock/markets/{sec.Market}/boards/{sec.Board}/securities/{sec.ID}.json" + "?from=" + from.ToString(DATE_FORMAT) + "&till=" + till.ToString(DATE_FORMAT) + "&start=" + start + "&limit=" + limit; var obj = JsonConvert.DeserializeObject <JObject>(CURL(url)); var columns = obj["history"]["columns"].ToObject <string[]>(); var data = obj["history"]["data"]; if (data.Count() < 1) { break; } var dateIndex = Array.IndexOf(columns, "TRADEDATE"); var closeIndex = Array.IndexOf(columns, "CLOSE"); foreach (var line in data) { var close = line[closeIndex]; if (close.Type == JTokenType.Null) { continue; } yield return(new Day( DateTime.ParseExact((string)line[dateIndex], DATE_FORMAT, null), (decimal)close )); } if (data.Count() < limit) { break; } start += limit; } }
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) { var sec = new Sec("shares", "TQTF", "FXUS"); var history = RocEma.Calculate(HistoryCache.Read(sec)); //RunExperiment(history, new Thresholds(-1.1m, 2.2m), Console.WriteLine); //Environment.Exit(1); var tasks = SliceHistory(history) .Select(slice => Task.Run(() => BruteThresholds(slice))) .ToArray(); Task.WaitAll(tasks); Console.Error.WriteLine(); var groups = tasks .SelectMany(t => t.Result) .GroupBy(r => r.Thresholds) .Select(g => new { Thresholds = g.Key, Count = g.Count(), AvgXIrr = g.Average(i => i.XIrr), SdXIrr = g.StandardDeviation(i => i.XIrr), AvgTradeCount = g.Average(i => i.TradeCount), AvgSlipCount = g.Average(i => i.SlipCount) }) .ToArray(); var countTolerance = groups.Max(g => g.Count) * 95 / 100; groups = groups .Where(g => g.Count >= countTolerance) .OrderBy(g => g.SdXIrr) .ThenByDescending(g => g.AvgXIrr) .ThenBy(g => g.Thresholds.High) .ThenByDescending(g => g.Thresholds.Low) .ToArray(); var sdXIrrCents = Enumerable.Range(0, 100) .Select(i => groups[groups.Length * i / 100].SdXIrr) .ToArray(); Console.WriteLine(String.Join("\t", "t_lo", "t_hi", "count", "m_xirr", "sd_xirr", "m_trade", "m_slip")); var bestAvgXIrr = -1d; foreach (var g in groups) { if (g.AvgXIrr <= bestAvgXIrr) { continue; } else { bestAvgXIrr = g.AvgXIrr; } var sdXIrrCent = sdXIrrCents.TakeWhile(i => g.SdXIrr >= i).Count(); Console.WriteLine(String.Join("\t", g.Thresholds.Low, g.Thresholds.High, g.Count, Math.Round(100 * g.AvgXIrr, 2), ("p" + sdXIrrCent).Pastel(CentToColor(sdXIrrCent)), Math.Round(g.AvgTradeCount, 1), Math.Round(g.AvgSlipCount, 1) )); } }