• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

OmegaChartのソースコードの保守


Commit MetaInfo

修订版5e51b27cc9eb546e343469111d4f4306fc487666 (tree)
时间2021-04-29 16:08:32
作者panacoran <panacoran@user...>
Commiterpanacoran

Log Message

YahooファイナンスからETF/ETNの株価をダウンロードできないのを直す

更改概述

差异

--- a/Yahoo.cs
+++ b/Yahoo.cs
@@ -125,25 +125,29 @@ namespace Zanetti.DataSource.Specialized
125125
126126 private FetchResult.Status GetPage(int code, DateTime begin, DateTime end, out string page)
127127 {
128- string url;
128+ string codeString;
129129 switch (code)
130130 {
131131 case (int)BuiltInIndex.Nikkei225:
132+ codeString = "998407.O";
133+ break;
132134 case (int)BuiltInIndex.TOPIX:
133- var realCode = code == (int)BuiltInIndex.Nikkei225 ? "998407.O" : "998405.T";
134- url =
135- $"https://info.finance.yahoo.co.jp/history/?code={realCode}&sy={begin.Year}&sm={begin.Month}&sd={begin.Day}&ey={end.Year}&em={end.Month}&ed={end.Day}&tm=d";
135+ codeString = "998405.T";
136136 break;
137137 default:
138- url =
139- $"https://finance.yahoo.co.jp/quote/{code}.T/history?from={begin:yyyyMMdd}&to={end:yyyyMMdd}&timeFrame=d&page=1";
138+ codeString = code.ToString();
140139 break;
141140 }
141+ var oldUrl = $"https://info.finance.yahoo.co.jp/history/?code={codeString}&sy={begin.Year}&sm={begin.Month}&sd={begin.Day}&ey={end.Year}&em={end.Month}&ed={end.Day}&tm=d";
142+ var url = $"https://finance.yahoo.co.jp/quote/{codeString}.T/history?from={begin:yyyyMMdd}&to={end:yyyyMMdd}&timeFrame=d&page=1";
142143 page = null;
144+ retry:
143145 try
144146 {
145147 using (var reader = new StreamReader(Util.HttpDownload(url)))
148+ {
146149 page = reader.ReadToEnd();
150+ }
147151 }
148152 catch (WebException e)
149153 {
@@ -157,7 +161,10 @@ namespace Zanetti.DataSource.Specialized
157161 case HttpStatusCode.BadGateway:
158162 return FetchResult.Status.Retry;
159163 case HttpStatusCode.NotFound:
160- return FetchResult.Status.Failure;
164+ if (url == oldUrl)
165+ return FetchResult.Status.Failure;
166+ url = oldUrl;
167+ goto retry;
161168 }
162169 throw;
163170 case WebExceptionStatus.Timeout:
@@ -172,18 +179,18 @@ namespace Zanetti.DataSource.Specialized
172179 return FetchResult.Status.Success;
173180 }
174181
175- private static readonly Regex ValidNew = new Regex(
182+ private static readonly Regex Valid = new Regex(
176183 @"<tr[^>]*><th[^>]*>(?<year>\d{4})年(?<month>1?\d)月(?<day>\d?\d)日<\/th><td[^>]+>(?:<span[^>]+>)+(?<open>[0-9,.]+)<\/span>.*?<\/td><td[^>]+>(?:<span[^>]+>)+(?<high>[0-9,.]+)<\/span>.*?<\/td><td[^>]+>(?:<span[^>]+>)+(?<low>[0-9,.]+)<\/span>.+?<\/td><td[^>]+>(?:<span[^>]+>)+(?<close>[0-9,.]+)<\/span>.+?<\/td>(?:<td.*?>(?<volume>[0-9,.]+)<\/span>.+?<\/td>)?<\/tr>",
177184 RegexOptions.Compiled);
178185
179- private static readonly Regex NoDataNew = new Regex("時系列情報がありません");
186+ private static readonly Regex NoData = new Regex("時系列情報がありません");
180187
181- private static readonly Regex Valid = new Regex(
188+ private static readonly Regex ValidOld = new Regex(
182189 @"<td>(?<year>\d{4})年(?<month>1?\d)月(?<day>\d?\d)日</td>" +
183190 "<td>(?<open>[0-9,.]+)</td><td>(?<high>[0-9,.]+)</td><td>(?<low>[0-9,.]+)</td>" +
184191 "<td>(?<close>[0-9,.]+)</td>(?:<td>(?<volume>[0-9,]+)</td>)?", RegexOptions.Compiled);
185192
186- private static readonly Regex NoData = new Regex("該当する期間のデータはありません。<br>期間をご確認ください。");
193+ private static readonly Regex NoDataOld = new Regex("該当する期間のデータはありません。<br>期間をご確認ください。");
187194
188195 private static readonly Regex Obs =
189196 new Regex("該当する銘柄はありません。<br>再度銘柄(コード)を入力し、「表示」ボタンを押してください。", RegexOptions.Compiled);
@@ -197,25 +204,22 @@ namespace Zanetti.DataSource.Specialized
197204 var dict = new SortedDictionary<int, NewDailyData>();
198205 MatchCollection matches;
199206
200- if (code == (int)BuiltInIndex.Nikkei225 || code == (int)BuiltInIndex.TOPIX)
207+ matches = Valid.Matches(buf);
208+ if (matches.Count == 0)
201209 {
202- matches = Valid.Matches(buf);
203- if (matches.Count == 0)
210+ if (!NoData.IsMatch(buf))
204211 {
205- if (Obs.Match(buf).Success || Empty.Match(buf).Success) // 上場廃止(銘柄データが空のこともある)
206- return new FetchResult {ReturnStatus = FetchResult.Status.Obsolete};
207- if (!NoData.Match(buf).Success)
208- throw new Exception("ページから株価を取得できません。");
209- // ここに到達するのは出来高がないか株価が用意されていない場合
212+ matches = ValidOld.Matches(buf);
213+ if (matches.Count == 0)
214+ {
215+ if (Obs.Match(buf).Success || Empty.Match(buf).Success) // 上場廃止(銘柄データが空のこともある)
216+ return new FetchResult {ReturnStatus = FetchResult.Status.Obsolete};
217+ if (!NoDataOld.IsMatch(buf))
218+ throw new Exception("ページから株価を取得できません。");
219+ // ここに到達するのは出来高がないか株価が用意されていない場合
220+ }
210221 }
211222 }
212- else
213- {
214- matches = ValidNew.Matches(buf);
215- if (matches.Count == 0 && !NoDataNew.Match(buf).Success)
216- throw new Exception("ページから株価を取得できません。");
217- }
218-
219223 try
220224 {
221225 var shift = IsIndex(code) ? 100 : 10; // 指数は100倍、株式は10倍で記録する