• R/O
  • SSH
  • HTTPS

protra: 提交


Commit MetaInfo

修訂539 (tree)
時間2018-12-23 22:04:36
作者panacoran

Log Message

#37647 株価データをCSVに変換するときに分割を適用しない

* Protra.Lib/Data/PriceData.cs (PriceData.GetPrices): 分割を適用しないよう指示できるようにする
(PriceData.ConvertToCSV): 分割を適用しないデータを出力する

Change Summary

差異

--- protra/trunk/ChangeLog.txt (revision 538)
+++ protra/trunk/ChangeLog.txt (revision 539)
@@ -1,5 +1,12 @@
11 2018-12-23 panacoran <panacoran@users.osdn.me>
22
3+ #37647 株価データをCSVに変換するときに分割を適用しない
4+
5+ * Protra.Lib/Data/PriceData.cs (PriceData.GetPrices): 分割を適用しないよう指示できるようにする
6+ (PriceData.ConvertToCSV): 分割を適用しないデータを出力する
7+
8+2018-12-23 panacoran <panacoran@users.osdn.me>
9+
310 k-db.comがサービスを終了したのでデータソースから削除する
411
512 * Protra.Lib/Protra.Lib.csproj: KdbComUpdator.csを削除する
--- protra/trunk/Protra.Lib/Data/PriceData.cs (revision 538)
+++ protra/trunk/Protra.Lib/Data/PriceData.cs (revision 539)
@@ -1,4 +1,4 @@
1-// Copyright(C) 2010, 2013, 2014 panacoran <panacoran@users.sourceforge.jp>
1+// Copyright(C) 2010, 2013, 2014, 2018 panacoran <panacoran@users.sourceforge.jp>
22 //
33 // This program is part of Protra.
44 //
@@ -35,7 +35,7 @@
3535 /// <summary>
3636 /// レコードサイズ
3737 /// </summary>
38- public static readonly int RecordSize = 4 /* date */+ 4 * 4 /* prices */+ 8 /* volume */;
38+ public static readonly int RecordSize = 4 /* date */ + 4 * 4 /* prices */ + 8 /* volume */;
3939
4040 /// <summary>
4141 /// 証券コード
@@ -144,31 +144,22 @@
144144 /// <summary>
145145 /// タイムフレームを取得する。
146146 /// </summary>
147- public TimeFrame TimeFrame { get; private set; }
147+ public TimeFrame TimeFrame { get; }
148148
149149 /// <summary>
150150 /// 最初の株価データを取得する。
151151 /// </summary>
152- public Price First
153- {
154- get { return _priceList.Count > 0 ? _priceList[0] : null; }
155- }
152+ public Price First => _priceList.Count > 0 ? _priceList[0] : null;
156153
157154 /// <summary>
158155 /// 最後の株価データを取得する。
159156 /// </summary>
160- public Price Last
161- {
162- get { return _priceList.Count > 0 ? _priceList[_priceList.Count - 1] : null; }
163- }
157+ public Price Last => _priceList.Count > 0 ? _priceList[_priceList.Count - 1] : null;
164158
165159 /// <summary>
166160 /// リストの要素数を返す。
167161 /// </summary>
168- public int Count
169- {
170- get { return _priceList.Count; }
171- }
162+ public int Count => _priceList.Count;
172163
173164 /// <summary>
174165 /// コンストラクタ
@@ -204,10 +195,7 @@
204195 /// </summary>
205196 /// <param name="index"></param>
206197 /// <returns></returns>
207- public Price this[int index]
208- {
209- get { return _priceList[index]; }
210- }
198+ public Price this[int index] => _priceList[index];
211199
212200 /// <summary>
213201 /// 指定した日付を持つ株価データのインデックスを返す。
@@ -270,6 +258,7 @@
270258 var dir = Path.Combine(Global.DirPrice, code.Substring(0, 1));
271259 if (!Directory.Exists(dir))
272260 Directory.CreateDirectory(dir);
261+
273262 return Path.Combine(dir, code);
274263 }
275264
@@ -279,13 +268,17 @@
279268 /// <param name="code">証券コード</param>
280269 /// <param name="timeFrame">タイムフレーム</param>
281270 /// <param name="needLastWeek">終わっていない週足を返すか</param>
282- public static PriceList GetPrices(string code, TimeFrame timeFrame, bool needLastWeek = false)
271+ /// <param name="applySplit">分割を適用するか</param>
272+ public static PriceList GetPrices(string code, TimeFrame timeFrame, bool needLastWeek = false,
273+ bool applySplit = true)
283274 {
284275 var file = PricePath(code);
285276 if (!File.Exists(file))
286277 return null;
278+
287279 var prices = new List<Price>();
288280 using (var s = new FileStream(file, FileMode.Open))
281+ {
289282 try
290283 {
291284 var buf = new byte[s.Length];
@@ -301,16 +294,25 @@
301294 catch (EndOfStreamException)
302295 {
303296 }
304- foreach (var split in GlobalEnv.BrandData[code].Split)
297+ }
298+
299+ if (applySplit)
305300 {
306- if (split.Date > prices[prices.Count - 1].Date)
307- continue;
308- foreach (var price in prices)
309- if (price.Date < split.Date)
310- price.Split(split.Ratio);
311- else
312- break;
301+ foreach (var split in GlobalEnv.BrandData[code].Split)
302+ {
303+ if (split.Date > prices[prices.Count - 1].Date)
304+ continue;
305+
306+ foreach (var price in prices)
307+ {
308+ if (price.Date < split.Date)
309+ price.Split(split.Ratio);
310+ else
311+ break;
312+ }
313+ }
313314 }
315+
314316 return timeFrame == TimeFrame.Daily
315317 ? new PriceList(prices, TimeFrame.Daily)
316318 : GenerateWeeklyPrices(prices, needLastWeek);
@@ -320,6 +322,7 @@
320322 {
321323 if (daily.Count == 0) // 空のデータファイルが存在する場合。
322324 return new PriceList(daily, TimeFrame.Weekly);
325+
323326 var weekly = new List<Price>();
324327 var code = daily[0].Code;
325328 var date = daily[0].Date;
@@ -356,14 +359,19 @@
356359 {
357360 if (d.High > high)
358361 high = d.High;
359- if (low == 0 || (d.Low > 0 && d.Low < low))
362+
363+ if (low == 0 || d.Low > 0 && d.Low < low)
360364 low = d.Low;
365+
361366 if (open == 0) // 最初に付いた値段が始値
362367 open = d.Open;
368+
363369 if (d.Close != 0)
364370 close = d.Close;
371+
365372 volume += d.Volume;
366373 }
374+
367375 prevDow = d.Date.DayOfWeek;
368376 }
369377
@@ -382,6 +390,7 @@
382390 };
383391 weekly.Add(w);
384392 }
393+
385394 return new PriceList(weekly, TimeFrame.Weekly);
386395 }
387396
@@ -394,13 +403,13 @@
394403 /// <param name="close">ファイルを閉じるか</param>
395404 public static void Add(Price price, bool close)
396405 {
397- FileStream s;
398- if (!OpenFiles.TryGetValue(price.Code, out s))
406+ if (!OpenFiles.TryGetValue(price.Code, out var s))
399407 {
400408 var file = PricePath(price.Code);
401409 s = new FileStream(file, FileMode.OpenOrCreate);
402410 OpenFiles.Add(price.Code, s);
403411 }
412+
404413 if (s.Length >= Price.RecordSize)
405414 {
406415 s.Seek(-1 * Price.RecordSize, SeekOrigin.End);
@@ -409,10 +418,12 @@
409418 if (price.Date <= last.Date) // すでに存在する。
410419 goto Exit;
411420 }
421+
412422 price.Write(new BinaryWriter(s));
413423 Exit:
414424 if (!close)
415425 return;
426+
416427 s.Close();
417428 OpenFiles.Remove(price.Code);
418429 }
@@ -424,6 +435,7 @@
424435 {
425436 foreach (var s in OpenFiles.Values)
426437 s.Close();
438+
427439 OpenFiles.Clear();
428440 }
429441
@@ -471,8 +483,10 @@
471483 r.Read(b);
472484 if (r.Date < since)
473485 break;
486+
474487 s.Seek(-2 * Price.RecordSize, SeekOrigin.Current);
475488 }
489+
476490 s.SetLength(s.Seek(0, SeekOrigin.Current));
477491 }
478492 catch (IOException)
@@ -483,6 +497,7 @@
483497 s.Close();
484498 }
485499 }
500+
486501 MaxDate = since.AddDays(-1);
487502 }
488503
@@ -498,12 +513,14 @@
498513 foreach (var file in CollectFiles(""))
499514 {
500515 var code = Path.GetFileName(file);
501- if (String.Compare(code, start, StringComparison.Ordinal) < 0 ||
502- String.Compare(code, end, StringComparison.Ordinal) > 0)
516+ if (string.Compare(code, start, StringComparison.Ordinal) < 0 ||
517+ string.Compare(code, end, StringComparison.Ordinal) > 0)
503518 continue;
504- var prices = GetPrices(code, TimeFrame.Daily);
519+
520+ var prices = GetPrices(code, TimeFrame.Daily, applySplit: false);
505521 if (prices == null)
506522 continue;
523+
507524 if (!overwriteAll && File.Exists(file + ".csv"))
508525 {
509526 using (var dialog = new OverwriteDialog())
@@ -513,12 +530,15 @@
513530 var result = dialog.ShowDialog();
514531 if (result == DialogResult.Cancel)
515532 return false;
533+
516534 if (result == DialogResult.No)
517535 continue;
536+
518537 if (result == DialogResult.OK)
519538 overwriteAll = true;
520539 }
521540 }
541+
522542 FileStream f;
523543 Retry:
524544 try
@@ -530,22 +550,26 @@
530550 DialogResult result;
531551 using (new CenteredDialogHelper())
532552 result = MessageBox.Show(e.Message, "株価データの変換", MessageBoxButtons.AbortRetryIgnore);
553+
533554 if (result == DialogResult.Abort)
534555 return false;
556+
535557 if (result == DialogResult.Ignore)
536558 continue;
559+
537560 goto Retry;
538561 }
562+
539563 using (var txt = new StreamWriter(f, Encoding.ASCII))
540564 {
541565 foreach (var p in prices)
542- txt.WriteLine(string.Join(",", new[]
543- {
544- p.Date.ToString("d"), p.Open.ToString(),
545- p.High.ToString(), p.Low.ToString(), p.Close.ToString(), p.Volume.ToString()
546- }));
566+ {
567+ txt.WriteLine(string.Join(",", p.Date.ToString("d"), p.Open.ToString(), p.High.ToString(),
568+ p.Low.ToString(), p.Close.ToString(), p.Volume.ToString()));
569+ }
547570 }
548571 }
572+
549573 return true;
550574 }
551575
@@ -561,9 +585,10 @@
561585 foreach (var file in CollectFiles(".csv"))
562586 {
563587 var code = Path.GetFileNameWithoutExtension(file);
564- if (String.Compare(code, start, StringComparison.Ordinal) < 0 ||
565- String.Compare(code, end, StringComparison.Ordinal) > 0)
588+ if (string.Compare(code, start, StringComparison.Ordinal) < 0 ||
589+ string.Compare(code, end, StringComparison.Ordinal) > 0)
566590 continue;
591+
567592 var prices = new List<Price>();
568593 Retry:
569594 var num = 0;
@@ -594,10 +619,14 @@
594619 {
595620 DialogResult result;
596621 using (new CenteredDialogHelper())
622+ {
597623 result = MessageBox.Show(file + "の" + num + "行目に不正な値があります。" +
598624 "このファイルを無視して処理を継続しますか?", "株価データの変換", MessageBoxButtons.YesNo);
625+ }
626+
599627 if (result == DialogResult.No)
600628 return false;
629+
601630 continue;
602631 }
603632 catch (IOException e)
@@ -605,12 +634,16 @@
605634 DialogResult result;
606635 using (new CenteredDialogHelper())
607636 result = MessageBox.Show(e.Message, "株価データの変換", MessageBoxButtons.AbortRetryIgnore);
637+
608638 if (result == DialogResult.Abort)
609639 return false;
640+
610641 if (result == DialogResult.Ignore)
611642 continue;
643+
612644 goto Retry;
613645 }
646+
614647 var dst = file.Substring(0, file.Length - 4);
615648 if (!overwriteAll && File.Exists(dst))
616649 {
@@ -621,20 +654,25 @@
621654 var result = dialog.ShowDialog();
622655 if (result == DialogResult.Cancel)
623656 return false;
657+
624658 if (result == DialogResult.No)
625659 continue;
660+
626661 if (result == DialogResult.OK)
627662 overwriteAll = true;
628663 }
629664 }
665+
630666 File.Delete(dst);
631667 foreach (var p in prices)
632668 Add(p, false);
669+
633670 CloseAll();
634671 var max = MaxDateByCode(code);
635672 if (max > MaxDate)
636673 MaxDate = max;
637674 }
675+
638676 return true;
639677 }
640678
@@ -641,18 +679,19 @@
641679 /// <summary>
642680 /// 指定した拡張子のファイルを株価データのディレクトリから探す。
643681 /// </summary>
644- /// <param name="extention">拡張子を指定する。</param>
682+ /// <param name="extenstion">拡張子を指定する。</param>
645683 /// <returns>ファイルのリストを返す。</returns>
646- private static IEnumerable<string> CollectFiles(string extention)
684+ private static IEnumerable<string> CollectFiles(string extenstion)
647685 {
648686 var result = new List<string>();
649687 foreach (var dir in Directory.GetDirectories(Global.DirPrice, "*"))
650- foreach (var path in Directory.GetFiles(Path.Combine(Global.DirPrice, dir), "*"))
651- {
652- var ext = Path.GetExtension(path);
653- if (ext != null && String.Compare(ext, extention, StringComparison.InvariantCultureIgnoreCase) == 0)
654- result.Add(path);
655- }
688+ foreach (var path in Directory.GetFiles(Path.Combine(Global.DirPrice, dir), "*"))
689+ {
690+ var ext = Path.GetExtension(path);
691+ if (string.Compare(ext, extenstion, StringComparison.InvariantCultureIgnoreCase) == 0)
692+ result.Add(path);
693+ }
694+
656695 return result;
657696 }
658697 }
Show on old repository browser