Format
Plain text
Post date
2018-10-13 14:02
Publication Period
Unlimited
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using System.IO;
  11. using System.Net;
  12. namespace KabuPlusDownloader
  13. {
  14. public partial class Form1 : Form
  15. {
  16. private const string SITE_ID = "id"; //要変更 KABU+から支給されるID
  17. private const string SITE_PASSWORD = "pass"; //要変更 KABU+から支給されるパスワード
  18. private const string HOZON_DIR = @"c:\tmp"; //要変更 KABU+からダウンロードするCSV群を保存するフォルダ
  19. private const int MAX_DOWNLOAD_NUMBER = 4; //要変更 KABU+契約コースによって違う
  20. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
  21. private const int mindate = 20180104;//データがこれ以前は存在しない。
  22. private string HISTORY_DATE_FILE = string.Format(@"{0}\KabuPlusDownloader.ini", System.Windows.Forms.Application.StartupPath);
  23. public Form1()
  24. {
  25. //InitializeComponent();
  26. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
  27. var update_ymdhms = ReadIniFile();
  28. if (!ChkLastDownload(update_ymdhms))
  29. System.Environment.Exit(0);//強制終了
  30. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
  31. var min = int.MaxValue;
  32. var max = int.MinValue;
  33. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
  34. //保存フォルダ内から最新日付と最古日付を探す(ファイル名)
  35. SearchOldfileNewfile(ref min, ref max);
  36. Run(min, max, ref update_ymdhms);
  37. WriteIniFile(string.Format("{0}", DateTime.Now.ToString("yyyyMMddhhmmss")));
  38. System.Environment.Exit(0);
  39. }
  40. private bool ChkLastDownload(string ymdhms)
  41. {
  42. if (ymdhms.Length != 14) return false;
  43. var ymd = 0; var hms = 0;
  44. if (!int.TryParse(ymdhms.Substring(0, 8), out ymd)) return false;
  45. if (!int.TryParse(ymdhms.Substring(8, 6), out hms)) return false;
  46. var dt = DateTime.Parse(string.Format("{0}/{1}/{2} {3}:{4}:{5}", ymd / 10000, ymd % 10000 / 100, ymd % 100, hms / 10000, hms % 10000 / 100, hms % 100));
  47. var ts = new TimeSpan(0, 1, 0, 0);
  48. if (dt < DateTime.Now - ts)//引数の時間がシステム時間から1時間以内だったらfalse
  49. return true;
  50. else
  51. return false;
  52. }
  53. private void SearchOldfileNewfile(ref int min, ref int max)
  54. {
  55. var files = System.IO.Directory.GetFiles(HOZON_DIR, "*.csv", SearchOption.TopDirectoryOnly);
  56. for(int i=0;i<files.Length;i++)
  57. {
  58. files[i] = Path.GetFileName(files[i]).Replace(".csv", "").Replace("tosho-reit-stock-prices_", "").Replace("tosho-fund-and-others-stock-prices_", "").Replace("tosho-etf-stock-prices_", "").Replace("japan-all-stock-prices-2_", "");
  59. }
  60. Array.Sort(files);
  61. for(int i=0;i<files.Length;i++)
  62. {
  63. var d = 0;
  64. if(int.TryParse(files[i], out d))
  65. {
  66. if (min > d) min = d;
  67. if (max < d) max = d;
  68. }
  69. }
  70. }
  71. private string ReadIniFile()
  72. {
  73. var ret = string.Empty;
  74. if (File.Exists(HISTORY_DATE_FILE))
  75. {
  76. using (var sr = new StreamReader(HISTORY_DATE_FILE, System.Text.Encoding.GetEncoding("shift_jis")))
  77. {
  78. ret = sr.ReadToEnd();
  79. }
  80. }
  81. else
  82. {
  83. //存在しなかったら初回起動とみなす
  84. ret = "19000101000000";
  85. }
  86. return ret;
  87. }
  88. private void WriteIniFile(string s)
  89. {
  90. using (var sw = new StreamWriter(HISTORY_DATE_FILE, false, System.Text.Encoding.GetEncoding("shift_jis")))
  91. {
  92. sw.Write(s);
  93. }
  94. }
  95. public void Run(int olddate, int newdate, ref string updatetime)
  96. {
  97. //DLすべき日付が存在したら、全部で4ファイル(MAX分)ダウンロードする
  98. var cnt = 0;
  99. //初回起動対応
  100. var date_pos = DateTime.Now;
  101. if (newdate < 0)
  102. {
  103. while (true)
  104. {
  105. date_pos = date_pos.AddDays(-1);
  106. if (!IsHoliday(date_pos)) break;
  107. }
  108. newdate = int.Parse(date_pos.ToString("yyyyMMdd"));
  109. olddate = newdate;
  110. }
  111. //最新日付がついてる4ファイルを存在チェック。なかったらDLして補完
  112. DownloadKabuPlusFile(newdate, ref cnt, ref updatetime);
  113. //最新日付とシステム日付の間で、相場日あり→古い日付から順にDL
  114. date_pos = Int2Datetime(newdate);
  115. while (true)
  116. {
  117. date_pos = date_pos.AddDays(1);
  118. if (!IsHoliday(date_pos)) break;
  119. }
  120. if (CompareDatetime2Sysdate(date_pos))
  121. DownloadKabuPlusFile(Datetime2Int(date_pos), ref cnt, ref updatetime);
  122. //履歴日付と2017/1/4(を含む)の間に相場があった日が存在したら返す
  123. DownloadKabuPlusFile(olddate, ref cnt, ref updatetime);
  124. date_pos = Int2Datetime(olddate);
  125. while (true)
  126. {
  127. date_pos = date_pos.AddDays(-1);
  128. if (!IsHoliday(date_pos)) break;
  129. }
  130. if (CompareDatetime2OpeningDate(date_pos))
  131. DownloadKabuPlusFile(Datetime2Int(date_pos), ref cnt, ref updatetime);
  132. }
  133. private bool CompareDatetime2Sysdate(DateTime dt)
  134. {
  135. //dtがシステム日付より前だったら迷わずtrueを返す
  136. //dtがシステム日付より後だったら迷わずfalseを返す
  137. //dtがシステム日付と同じだったら、16:10(KABU+でデータが用意される時間)以前だったらFalse、以降だったらtrue
  138. if (int.Parse(dt.ToString("yyyyMMdd")) < int.Parse(DateTime.Now.ToString("yyyyMMdd")))
  139. return true;
  140. else if (int.Parse(dt.ToString("yyyyMMdd")) > int.Parse(DateTime.Now.ToString("yyyyMMdd")))
  141. return false;
  142. else if (int.Parse(dt.ToString("yyyyMMdd")) == int.Parse(DateTime.Now.ToString("yyyyMMdd")) && int.Parse(DateTime.Now.ToString("hhmm")) > 1610)
  143. return true;
  144. else
  145. return false;
  146. }
  147. private bool CompareDatetime2OpeningDate(DateTime dt)
  148. {
  149. //dtが2017/01/4以内かどうか
  150. if (int.Parse(dt.ToString("yyyyMMdd")) >= 20170104)
  151. return true;
  152. else
  153. return false;
  154. }
  155. private void DownloadKabuPlusFile(int date, ref int cnt, ref string updatetime)
  156. {
  157. for (int i = 0; i < 4; i++)
  158. {
  159. if (cnt >= MAX_DOWNLOAD_NUMBER) break;
  160. var filename = MakeFilename(date, i);
  161. var path = string.Format(@"{0}\{1}", HOZON_DIR, filename);
  162. if (!File.Exists(path))
  163. {
  164. Download(date, MakeUrl(date, i), string.Format(@"{0}\{1}", HOZON_DIR, filename));
  165. cnt++;
  166. updatetime = DateTime.Now.ToString("yyyyMMddhhmmss");
  167. }
  168. }
  169. }
  170. private string MakeUrl(int date, int kind)
  171. {
  172. var url_base = "https://csvex.com/kabu.plus/csv";
  173. switch (kind)
  174. {
  175. case 0://ETF・ETN
  176. return string.Format("{0}/tosho-etf-stock-prices/daily/tosho-etf-stock-prices_{1:D8}.csv", url_base, date);
  177. case 1://REIT
  178. return string.Format("{0}/tosho-reit-stock-prices/daily/tosho-reit-stock-prices_{1:D8}.csv", url_base, date);
  179. case 2://上場ファンド
  180. return string.Format("{0}/tosho-fund-and-others-stock-prices/daily/tosho-fund-and-others-stock-prices_{1:D8}.csv", url_base, date);
  181. case 3:
  182. return string.Format("{0}/japan-all-stock-prices-2/daily/japan-all-stock-prices-2_{1:D8}.csv", url_base, date);
  183. }
  184. return null;
  185. }
  186. private string MakeFilename(int date, int kind)
  187. {
  188. switch (kind)
  189. {
  190. case 0://ETF・ETN
  191. return string.Format("tosho-etf-stock-prices_{0:D8}.csv", date);
  192. case 1://REIT
  193. return string.Format("tosho-reit-stock-prices_{0:D8}.csv", date);
  194. case 2://上場ファンド
  195. return string.Format("tosho-fund-and-others-stock-prices_{0:D8}.csv", date);
  196. case 3:
  197. return string.Format("japan-all-stock-prices-2_{0:D8}.csv", date);
  198. }
  199. return null;
  200. }
  201. private void Download(int date, string url, string filename)
  202. {
  203. var uri = new Uri(url);
  204. using (var webClient = new System.Net.WebClient())
  205. {
  206. webClient.Credentials = new NetworkCredential(SITE_ID, SITE_PASSWORD);
  207. using (var reader = new StreamReader(webClient.OpenRead(url), System.Text.Encoding.GetEncoding("shift_jis")))
  208. {
  209. var line = reader.ReadToEnd();
  210. if (line.Trim() != string.Empty)
  211. {
  212. try
  213. {
  214. System.IO.File.WriteAllText(filename, line, System.Text.Encoding.GetEncoding("shift_jis"));
  215. }
  216. catch (Exception ex)
  217. {
  218. Console.WriteLine(ex.Message);
  219. }
  220. }
  221. }
  222. }
  223. }
  224. private DateTime Int2Datetime(int d)
  225. {
  226. return DateTime.Parse(string.Format("{0:D4}/{1:D2}/{2:D2}", d/10000, d % 10000 / 100, d % 100));
  227. }
  228. private int Datetime2Int(DateTime dt)
  229. {
  230. return int.Parse(dt.ToString("yyyyMMdd"));
  231. }
  232. private bool IsHoliday(DateTime d)
  233. {
  234. //土日
  235. if (d.DayOfWeek == DayOfWeek.Sunday || d.DayOfWeek == DayOfWeek.Saturday)
  236. return true;
  237. // 動かない休日
  238. if ((d.Month == 1 && d.Day == 1) ||
  239. (d.Month == 1 && d.Day == 2) ||
  240. (d.Month == 1 && d.Day == 3) ||
  241. (d.Month == 2 && d.Day == 11) ||
  242. (d.Month == 4 && d.Day == 29) ||
  243. (d.Month == 5 && (d.Day >= 3 && d.Day <= 5)) ||
  244. (d.Month == 11 && (d.Day == 3 || d.Day == 23)) ||
  245. (d.Month == 12 && d.Day == 23))
  246. return true;
  247. if (d.Year >= 2016 && d.Month == 8 && d.Day == 11) // 山の日
  248. return true;
  249. // 春分と秋分(1980~2099年に対応)
  250. if (d.Month == 3 &&
  251. d.Day == (int)(20.8431 + 0.242194 * (d.Year - 1980) - (d.Year - 1980) / 4))
  252. return true;
  253. if (d.Month == 9 &&
  254. d.Day == (int)(23.2488 + 0.242194 * (d.Year - 1980) - (d.Year - 1980) / 4))
  255. return true;
  256. // ハッピーマンデー
  257. if (d.Year < 2000)
  258. {
  259. if ((d.Month == 1 && d.Day == 15) ||
  260. (d.Month == 10 && d.Day == 10))
  261. return true;
  262. }
  263. else
  264. {
  265. if ((d.Month == 1 || d.Month == 10) &&
  266. (d.Day >= 8 && d.Day <= 14) && d.DayOfWeek == DayOfWeek.Monday)
  267. return true;
  268. }
  269. if (d.Year < 2003)
  270. {
  271. if ((d.Month == 7 && d.Day == 20) ||
  272. (d.Month == 9 && d.Day == 15))
  273. return true;
  274. }
  275. else
  276. {
  277. if ((d.Month == 7 || d.Month == 9) &&
  278. (d.Day >= 15 && d.Day <= 21) && d.DayOfWeek == DayOfWeek.Monday)
  279. return true;
  280. // シルバーウィーク
  281. if (d.Month == 9 && (d.Day == 21 || d.Day == 22) && d.DayOfWeek == DayOfWeek.Tuesday)
  282. return IsHoliday(d.AddDays(1));
  283. }
  284. // 5月4日が国民の祝日になったので、振替休日が二日以上繰り越す。
  285. if (d.Year > 2007 && d.Month == 5 && d.Day == 6)
  286. return d.DayOfWeek >= DayOfWeek.Monday &&
  287. d.DayOfWeek <= DayOfWeek.Wednesday;
  288. // 振り替え休日
  289. if (d.DayOfWeek == DayOfWeek.Monday)
  290. return IsHoliday(d.AddDays(-1));
  291. //天皇陛下御退位および皇太子殿下御即位対応
  292. if (d.Year == 2019)
  293. {
  294. if ((d.Month == 4 && d.Day == 30) ||(d.Month == 5 && d.Day <= 2))
  295. return true;
  296. }
  297. return false;
  298. }
  299. }
  300. }
Download Printable view

URL of this paste

Embed with JavaScript

Embed with iframe

Raw text