• R/O
  • SSH
  • HTTPS

protra: Commit


Commit MetaInfo

Revision537 (tree)
Time2018-12-23 22:04:13
Authorpanacoran

Log Message

Yahooから株価を取得できないのを直す

* Protra.Lib/Update/YahooFinanceUpdator.cs (YahooFinanceUpdator.YahooFinanceUpdator): HTTPSで使うプロトコルにTLS1.2を指定する
(YahooFinanceUpdator.UpdatePrice): マルチスレッドで取得するのをやめる
(YahooFinanceUpdator.RunFetchPrices): 削除

Change Summary

Incremental Difference

--- protra/trunk/ChangeLog.txt (revision 536)
+++ protra/trunk/ChangeLog.txt (revision 537)
@@ -1,5 +1,13 @@
11 2018-12-23 panacoran <panacoran@users.osdn.me>
22
3+ Yahooから株価を取得できないのを直す
4+
5+ * Protra.Lib/Update/YahooFinanceUpdator.cs (YahooFinanceUpdator.YahooFinanceUpdator): HTTPSで使うプロトコルにTLS1.2を指定する
6+ (YahooFinanceUpdator.UpdatePrice): マルチスレッドで取得するのをやめる
7+ (YahooFinanceUpdator.RunFetchPrices): 削除
8+
9+2018-12-23 panacoran <panacoran@users.osdn.me>
10+
311 .NET Frameworkのバージョンを4.7.2に上げる
412
513 * Protra.Lib/Protra.Lib.csproj: .NET Frameworkのバージョンを4.7.2に上げる
--- protra/trunk/Protra.Lib/Update/YahooFinanceUpdator.cs (revision 536)
+++ protra/trunk/Protra.Lib/Update/YahooFinanceUpdator.cs (revision 537)
@@ -1,4 +1,4 @@
1-// Copyright (C) 2008, 2010, 2011 panacorn <panacoran@users.sourceforge.jp>
1+// Copyright (C) 2008, 2010, 2011, 2018 panacorn <panacoran@users.sourceforge.jp>
22 //
33 // This program is part of Protra.
44 //
@@ -24,7 +24,6 @@
2424 using System.IO;
2525 using System.Net;
2626 using System.Text.RegularExpressions;
27-using System.Threading;
2827 using Protra.Lib.Data;
2928
3029 namespace Protra.Lib.Update
@@ -34,15 +33,19 @@
3433 /// </summary>
3534 public class YahooFinanceUpdator : PriceDataUpdator
3635 {
37- private readonly Object _syncObject = new object();
3836 private Queue<string> _codeQueue;
3937 private readonly List<DateTime> _series = new List<DateTime>();
40- private readonly Queue<FetchResult> _resultQueue = new Queue<FetchResult>();
41- private bool _terminate;
42- private Exception _exception;
4338 private readonly Progress _progress = new Progress();
4439 private const int DaysAtOnce = 20; // 一度に取得する時系列の営業日数
4540
41+ /// <summary>
42+ /// コンストラクタです。
43+ /// </summary>
44+ public YahooFinanceUpdator()
45+ {
46+ ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
47+ }
48+
4649 private class FetchResult
4750 {
4851 public enum Status
@@ -61,10 +64,7 @@
6164 /// <summary>
6265 /// データが存在する最初の日付を取得する。
6366 /// </summary>
64- public override DateTime DataSince
65- {
66- get { return new DateTime(1991, 1, 4); }
67- }
67+ public override DateTime DataSince => new DateTime(1991, 1, 4);
6868
6969 /// <summary>
7070 /// 株価データを更新します。
@@ -80,9 +80,6 @@
8080 // 新しいデータが置かれるのは早くても午後7時以降
8181 if (end.Hour < 19)
8282 end = end.AddDays(-1);
83- var threads = new Thread[2];
84- for (var i = 0; i < threads.Length; i++)
85- (threads[i] = new Thread(RunFetchPrices) {Name = "Fetch Thread " + i}).Start();
8683 var codes = new List<string>();
8784 foreach (var brand in GlobalEnv.BrandData)
8885 if ((brand.Flags & Brand.Flag.OBS) == 0)
@@ -102,8 +99,7 @@
10299 var n = Math.Min(DaysAtOnce, dates.Count);
103100 var nikkei225 = FetchPrices("1001", dates.GetRange(0, n));
104101 if (nikkei225.ReturnStatus != FetchResult.Status.Success)
105- throw new Exception(string.Format("株価の取得に失敗しました。時間を置いて再試行してください。: {0:d}~{1:d}",
106- _series[0], _series[_series.Count - 1]));
102+ throw new Exception($"株価の取得に失敗しました。時間を置いて再試行してください。: {dates[0]:d}~{dates[n - 1]:d}");
107103 dates.RemoveRange(0, n);
108104 _series.Clear();
109105 foreach (var price in nikkei225.Prices)
@@ -113,17 +109,14 @@
113109 PriceData.Add(price, false);
114110 _series.Add(price.Date);
115111 }
112+
116113 if (_series.Count == 0)
117114 return;
118115 var lastDate = _series[_series.Count - 1];
119116 _progress.IncrementRecords();
120117 _progress.Show(worker, lastDate);
121- lock (_syncObject)
122- {
123- _codeQueue = new Queue<string>(codes);
124- _codeQueue.Dequeue(); // 日経平均を外す。
125- Monitor.PulseAll(_syncObject);
126- }
118+ codes.RemoveAt(0); // 日経平均を外す。
119+ _codeQueue = new Queue<string>(codes);
127120 var retry = 0;
128121 while (true)
129122 {
@@ -135,15 +128,8 @@
135128 e.Cancel = true;
136129 return;
137130 }
138- FetchResult result;
139- lock (_resultQueue)
140- {
141- while (_resultQueue.Count == 0 && _exception == null)
142- Monitor.Wait(_resultQueue);
143- if (_exception != null)
144- throw _exception;
145- result = _resultQueue.Dequeue();
146- }
131+
132+ var result = FetchPrices(_codeQueue.Dequeue(), _series);
147133 switch (result.ReturnStatus)
148134 {
149135 case FetchResult.Status.Failure:
@@ -150,23 +136,23 @@
150136 case FetchResult.Status.Obsolete:
151137 continue;
152138 case FetchResult.Status.Retry:
153- lock (_codeQueue)
154- {
155- _codeQueue.Enqueue(result.Code);
156- }
139+ _codeQueue.Enqueue(result.Code);
157140 continue;
158141 }
142+
159143 foreach (var price in result.Prices)
160144 PriceData.Add(price, false);
161145 _progress.IncrementRecords();
162146 _progress.Show(worker, lastDate);
163147 }
148+
164149 if (_codeQueue.Count == 0)
165150 break;
166151 if (retry++ == 10)
167- throw new Exception(string.Format("株価の取得に失敗しました。時間を置いて再試行してください。: {0:d}~{1:d}",
168- _series[0], _series[_series.Count - 1]));
152+ throw new Exception(
153+ $"株価の取得に失敗しました。時間を置いて再試行してください。: {_series[0]:d}~{_series[_series.Count - 1]:d}");
169154 }
155+
170156 PriceData.MaxDate = lastDate;
171157 _progress.IncrementDays();
172158 } while (dates.Count > 0);
@@ -173,54 +159,13 @@
173159 }
174160 finally
175161 {
176- lock (_syncObject)
177- {
178- _terminate = true;
179- Monitor.PulseAll(_syncObject);
180- }
181- foreach (var thread in threads)
182- thread.Join();
183162 PriceData.CloseAll();
184163 }
185164 }
186165
187- private void RunFetchPrices()
188- {
189- var code = "";
190- try
191- {
192- while (true)
193- {
194- lock (_syncObject)
195- {
196- while ((_codeQueue == null || _codeQueue.Count == 0) && !_terminate)
197- Monitor.Wait(_syncObject);
198- if (_terminate || _codeQueue == null)
199- return;
200- code = _codeQueue.Dequeue();
201- }
202- var price = FetchPrices(code, _series);
203- lock (_resultQueue)
204- {
205- _resultQueue.Enqueue(price);
206- Monitor.Pulse(_resultQueue);
207- }
208- }
209- }
210- catch (Exception e)
211- {
212- lock (_resultQueue)
213- {
214- _exception = new Exception(string.Format("{0}: {1} {2:d}", e.Message, code, _series[0]), e);
215- Monitor.Pulse(_resultQueue);
216- }
217- }
218- }
219-
220166 private FetchResult FetchPrices(string code, IList<DateTime> dates)
221167 {
222- string page;
223- var status = GetPage(code, dates[0], dates[dates.Count - 1], out page);
168+ var status = GetPage(code, dates[0], dates[dates.Count - 1], out var page);
224169 if (status == FetchResult.Status.Failure || status == FetchResult.Status.Retry)
225170 return new FetchResult {Code = code, ReturnStatus = status};
226171 return ParsePage(code, page, dates);
@@ -232,9 +177,8 @@
232177 code = "998407";
233178 else if (code == "1002")
234179 code = "998405";
235- var dl = new DownloadUtil(string.Format(
236- "http://info.finance.yahoo.co.jp/history/?code={0}&sy={1}&sm={2}&sd={3}&ey={4}&em={5}&ed={6}&tm=d",
237- code, begin.Year, begin.Month, begin.Day, end.Year, end.Month, end.Day));
180+ var dl = new DownloadUtil(
181+ $"https://info.finance.yahoo.co.jp/history/?code={code}&sy={begin.Year}&sm={begin.Month}&sd={begin.Day}&ey={end.Year}&em={end.Month}&ed={end.Day}&tm=d");
238182 page = null;
239183 try
240184 {
@@ -262,6 +206,7 @@
262206 throw;
263207 }
264208 }
209+
265210 return FetchResult.Status.Success;
266211 }
267212
@@ -285,6 +230,7 @@
285230 throw new Exception("ページから株価を取得できません。");
286231 // ここに到達するのは出来高がないか株価が用意されていない場合
287232 }
233+
288234 try
289235 {
290236 const NumberStyles s = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
@@ -309,13 +255,14 @@
309255 {
310256 throw new Exception("ページから株価を取得できません。", e);
311257 }
258+
312259 // 出来高がない日の株価データがないので値が0のデータを補う。
313260 var prices = new List<Price>();
314261 foreach (var date in dates)
315262 {
316- Price price;
317- prices.Add(dict.TryGetValue(date, out price) ? price : new Price {Date = date, Code = code});
263+ prices.Add(dict.TryGetValue(date, out var price) ? price : new Price {Date = date, Code = code});
318264 }
265+
319266 return new FetchResult {Code = code, Prices = prices, ReturnStatus = FetchResult.Status.Success};
320267 }
321268
Show on old repository browser