Pastebin: OmegaChart 1銘柄だけ更新 差し替えその1 UpdateOneBrand.cs 新規追加ファイル

Format
Plain text
Post date
2019-02-06 22:28
Publication Period
Unlimited
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.Text.RegularExpressions;
  6. using Zanetti.Data;
  7. namespace Zanetti
  8. {
  9. class UpdateOneBrand
  10. {
  11. public void Update()
  12. {
  13. AbstractBrand br = Env.Frame.ChartCanvas.GetBrand();
  14. if (br.IsBuiltIn)//個別銘柄だけ
  15. return;
  16. var title = Env.Frame.SetMainFrameTxt;
  17. Env.Frame.SetMainFrameTxt = string.Format("{0} データ更新中", title);
  18. SortedDictionary<int, NewDailyData> Prices = new SortedDictionary<int, NewDailyData>();
  19. var page = string.Empty;
  20. var latestdate = LatestDate();
  21. if (latestdate < int.Parse(DateTime.Today.ToString("yyyyMMdd")))
  22. {
  23. GetPage(br.Code, out page);
  24. ParsePage(br.Code, page, Prices);
  25. if (Prices.Count > 0)
  26. UpdateDataFarm(br.Code, Prices);
  27. }
  28. latestdate = LatestDate();
  29. if (DateTime.UtcNow.Hour >= 0 && DateTime.UtcNow.Hour <= 6)
  30. {
  31. Prices = new SortedDictionary<int, NewDailyData>();
  32. GetPageDetail(br.Code, out page);
  33. ParsePageDetail(br.Code, page, Prices, latestdate);
  34. if (Prices.Count > 0)
  35. UpdateDataFarm(br.Code, Prices);
  36. }
  37. Env.Frame.SetMainFrameTxt = title;
  38. }
  39. private bool IsIndex(int code)
  40. {
  41. return code == (int)BuiltInIndex.Nikkei225 ||
  42. code == (int)BuiltInIndex.TOPIX;
  43. }
  44. private int LatestDate()
  45. {
  46. var br = Env.Frame.ChartCanvas.GetBrand();
  47. var path = Util.GetDailyDataFileName(br.Code);
  48. var last = -1;
  49. if (File.Exists(path))
  50. {
  51. using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
  52. {
  53. var buffer = new byte[fs.Length];
  54. fs.Read(buffer, 0, buffer.Length);
  55. last = BitConverter.ToInt32(buffer, buffer.Length > 32 ? buffer.Length - 32 : 0);
  56. }
  57. }
  58. return last;
  59. }
  60. private void UpdateDataFarm(int code, SortedDictionary<int, NewDailyData> prices)
  61. {
  62. var farm = (DailyDataFarm)Env.BrandCollection.FindBrand(code).CreateDailyFarm(prices.Count);
  63. foreach (var pair in prices)
  64. {
  65. if (IsIndex(code) ? false : pair.Value.volume == 0)
  66. continue;
  67. farm.UpdateDataFarm(pair.Key, pair.Value);
  68. }
  69. farm.Save(Util.GetDailyDataFileName(code));
  70. }
  71. private void GetPageDetail(int code, out string page)
  72. {
  73. var url = string.Format("https://stocks.finance.yahoo.co.jp/stocks/detail/?code={0}", code);
  74. page = string.Empty;
  75. try
  76. {
  77. using (var reader = new StreamReader(Util.HttpDownload(url)))
  78. page = reader.ReadToEnd();
  79. }
  80. catch (System.Net.WebException e)
  81. {
  82. Console.WriteLine(e.Message);
  83. }
  84. }
  85. private void GetPage(int code, out string page)
  86. {
  87. var url = string.Format("https://stocks.finance.yahoo.co.jp/stocks/history/?code={0}", code);
  88. page = string.Empty;
  89. try
  90. {
  91. using (var reader = new StreamReader(Util.HttpDownload(url)))
  92. page = reader.ReadToEnd();
  93. }
  94. catch (System.Net.WebException e)
  95. {
  96. Console.WriteLine(e.Message);
  97. }
  98. }
  99. private bool HtmlAgilitySelectSingleNodeValue(HtmlAgilityPack.HtmlDocument htmldoc, string xpath, ref double val)
  100. {
  101. var doc = htmldoc.DocumentNode.SelectSingleNode(xpath);
  102. if (doc == null)
  103. return false;
  104. if (!double.TryParse(doc.InnerText.Replace(",", "").Trim(), out val))
  105. return false;
  106. return true;
  107. }
  108. private bool HtmlAgilitySelectSingleNodeDatetime(HtmlAgilityPack.HtmlDocument htmldoc, string xpath, ref DateTime dt)
  109. {
  110. var doc = htmldoc.DocumentNode.SelectSingleNode(xpath);
  111. if (doc == null)
  112. return false;
  113. var s = doc.InnerText.Replace("リアルタイム株価", "");
  114. if (!DateTime.TryParse(s, out dt))
  115. return false;
  116. return true;
  117. }
  118. private bool HtmlAgilitySelectNodes(HtmlAgilityPack.HtmlDocument htmldoc, string xpath, ref double val, ref DateTime dt, int cnt, int pos)
  119. {
  120. var doc = htmldoc.DocumentNode.SelectNodes(xpath);
  121. if (doc == null)
  122. return false;
  123. if (doc.Count != cnt)
  124. return false;
  125. var valid = new Regex(xpath);
  126. var s = doc[pos].InnerText.Replace(",", "").Replace("株", "").Trim();
  127. valid = new Regex("(?<value>[0-9,.]+)((?<datetime>[0-9:]+))");
  128. var matches = valid.Matches(s);
  129. if (matches.Count != 1)
  130. return false;
  131. if (!double.TryParse(matches[0].Groups["value"].Value, out val))
  132. return false;
  133. if (!DateTime.TryParse(matches[0].Groups["datetime"].Value, out dt))
  134. dt = DateTime.MinValue;
  135. return true;
  136. }
  137. private void ParsePageDetail(int code, string buf, SortedDictionary<int, NewDailyData> dict, int max_d)
  138. {
  139. var date = int.Parse(DateTime.Now.ToString("yyyyMMdd"));
  140. var shift = 10;
  141. var kabuka = new double[4];
  142. var volume = .0;
  143. var open_datetime = DateTime.MinValue;
  144. var high_datetime = DateTime.MinValue;
  145. var low_datetime = DateTime.MinValue;
  146. var close_datetime = DateTime.MinValue;
  147. var volume_datetime = DateTime.MinValue;
  148. var xpath = string.Empty;
  149. var htmldoc = new HtmlAgilityPack.HtmlDocument();
  150. htmldoc.LoadHtml(buf);
  151. if (!HtmlAgilitySelectSingleNodeValue(htmldoc, "//td[@class=\"stoksPrice\"]", ref kabuka[3]))
  152. return;
  153. if (!HtmlAgilitySelectSingleNodeDatetime(htmldoc, "//dd[@class=\"yjSb real\"]", ref close_datetime))
  154. return;
  155. if (!HtmlAgilitySelectNodes(htmldoc, "//div[@class=\"innerDate\"]/div[@class=\"lineFi clearfix\"]/dl[@class=\"tseDtl\"]/dd[@class=\"ymuiEditLink mar0\"]", ref kabuka[0], ref open_datetime, 3, 0))
  156. return;
  157. if (!HtmlAgilitySelectNodes(htmldoc, "//div[@class=\"innerDate\"]/div[@class=\"lineFi clearfix\"]/dl[@class=\"tseDtl\"]/dd[@class=\"ymuiEditLink mar0\"]", ref kabuka[1], ref high_datetime, 3, 1))
  158. return;
  159. if (!HtmlAgilitySelectNodes(htmldoc, "//div[@class=\"innerDate\"]/div[@class=\"lineFi clearfix\"]/dl[@class=\"tseDtl\"]/dd[@class=\"ymuiEditLink mar0\"]", ref kabuka[2], ref low_datetime, 3, 2))
  160. return;
  161. if (!HtmlAgilitySelectNodes(htmldoc, "//div[@class=\"innerDate\"]/div[@class=\"lineFi clearfix\"]/dl[@class=\"tseDtlDelay\"]/dd[@class=\"ymuiEditLink mar0\"]", ref volume, ref volume_datetime, 4, 1))
  162. return;
  163. dict[date] = new NewDailyData
  164. {
  165. open = (int)(kabuka[0] * shift),
  166. high = (int)(kabuka[1] * shift),
  167. low = (int)(kabuka[2] * shift),
  168. close = (int)(kabuka[3] * shift),
  169. volume = (int)volume
  170. };
  171. }
  172. private void ParsePage(int code, string buf, SortedDictionary<int, NewDailyData> dict)
  173. {
  174. var valid = new Regex(
  175. @"<td>(?<year>\d{4})年(?<month>1?\d)月(?<day>\d?\d)日</td>[\n]" +
  176. "<td>(?<open>[0-9,.]+)</td>[\n]<td>(?<high>[0-9,.]+)</td>[\n]<td>(?<low>[0-9,.]+)</td>[\n]" +
  177. "<td>(?<close>[0-9,.]+)</td>[\n](?:<td>(?<volume>[0-9,]+)</td>[\n])?");
  178. var invalid = new Regex("該当する期間のデータはありません。<br>期間をご確認ください。");
  179. var obs = new Regex("該当する銘柄はありません。<br>再度銘柄(コード)を入力し、「表示」ボタンを押してください。");
  180. var empty = new Regex("<dl class=\"stocksInfo\">\n<dt></dt><dd class=\"category yjSb\"></dd>");
  181. if (buf.Trim() == string.Empty)
  182. return;
  183. var matches = valid.Matches(buf);
  184. if (matches.Count == 0)
  185. return;
  186. try
  187. {
  188. var shift = IsIndex(code) ? 100 : 10; // 指数は100倍、株式は10倍で記録する
  189. const NumberStyles s = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
  190. foreach (Match m in matches)
  191. {
  192. var date = new DateTime(int.Parse(m.Groups["year"].Value),
  193. int.Parse(m.Groups["month"].Value),
  194. int.Parse(m.Groups["day"].Value));
  195. var int_date = Util.DateToInt(date);
  196. dict[int_date] = new NewDailyData
  197. {
  198. open = (int)(double.Parse(m.Groups["open"].Value, s) * shift),
  199. high = (int)(double.Parse(m.Groups["high"].Value, s) * shift),
  200. low = (int)(double.Parse(m.Groups["low"].Value, s) * shift),
  201. close = (int)(double.Parse(m.Groups["close"].Value, s) * shift),
  202. volume = m.Groups["volume"].Value == "" ? 0 : (int)double.Parse(m.Groups["volume"].Value, s)
  203. };
  204. }
  205. }
  206. catch (Exception e)
  207. {
  208. Console.WriteLine(e.Message);
  209. }
  210. }
  211. }
  212. }
Download Printable view

URL of this paste

Embed with JavaScript

Embed with iframe

Raw text