using System; using System.IO; using System.Collections.Generic; using System.Windows.Forms; using Zanetti.Commands; namespace Zanetti.Data { internal abstract class DataImporter { private const int SHIFT = 10;//株価10倍格納する場合 private const int RECORD_LENGTH = 32; public static void ImportData(string[] fileName) { var code = -1; DataFarm farm = null; var dicCsv = new SortedDictionary<int, NewDailyData2>();//読み込みCSVファイル情報 var dicFarm = new SortedDictionary<int, NewDailyData2>();//OmegaChartのdataフォルダ配下の情報 var dicResult = new SortedDictionary<int, NewDailyData2>();//比較結果格納 if (fileName.Length == 0) return; var path = fileName[0]; if (IsTextFile(path))//複数ファイルNG { ReadCsv(path, ref dicCsv); DecisionCodeAndFarm(path, ref code, ref farm); if (farm.RawDataImage!=null) ReadFarm(farm, ref dicFarm); CompareCsvFarm(farm, dicCsv, dicFarm, ref dicResult); UpdateFarm(dicResult, ref dicFarm); WriteFarm(code, dicResult, dicFarm); } } private static void DecisionCodeAndFarm(string path, ref int code, ref DataFarm farm) { farm = Env.Frame.ChartCanvas.GetBrand().ReserveFarm(); code = Path2IntCode(path); if (code < 0)//パス名が数字じゃなかったら、表示中の銘柄にインポートするものとする { code = farm.Brand.Code; } else//パス名が数字4文字含みだったら銘柄コードと決めつける { AbstractBrand br = Env.BrandCollection.FindBrand(code); if (br == null)//銘柄コードじゃなかったら戻す farmは最初から表示中のfarmを入れてある code = farm.Brand.Code; else farm = Env.BrandCollection.ReserveFarm(br); } } private static int Path2IntCode(string path) { var code = -1; var s = Path.GetFileName(path.Trim()); if (s == string.Empty) return code; var sp = s.Split('.'); if (sp[0].Length == 4) int.TryParse(sp[0], out code); return code; } private static void MakeBackupFile(int code) { var source = Util.GetDailyDataFileName(code); var dest = string.Format("{0}\\{1}.bak", Path.GetDirectoryName(source), code); File.Copy(source, dest, true); } private static void UpdateFarm(SortedDictionary<int, NewDailyData2> dicResult, ref SortedDictionary<int, NewDailyData2> dicFarm) { List<int> keyListResult = new List<int>(dicResult.Keys); foreach (var e in keyListResult) { if (dicFarm.ContainsKey(e))//キー(日付)が重複、かつ変更された日付の情報 { //dicFarm[e] = dicResult[e]; dicFarm[e].open = dicResult[e].open; dicFarm[e].high = dicResult[e].high; dicFarm[e].low = dicResult[e].low; dicFarm[e].close = dicResult[e].close; dicFarm[e].volume = dicResult[e].volume; } else//新規データ { dicFarm.Add(e, dicResult[e]); } } } private static void WriteFarm(int code, SortedDictionary<int, NewDailyData2> dicResult, SortedDictionary<int, NewDailyData2> dicFarm) { if (dicResult.Count > 0) { var message = string.Empty; message = string.Format("OmegaChartのデータを変更しますか?\n\n銘柄コード:{0:D4} 変更箇所数:{1}\n", code, dicResult.Count); List<int> keyListResult = new List<int>(dicResult.Keys); var cnt = 0; foreach (var key in keyListResult) { message += string.Format("{0:D8},{1},{2},{3},{4},{5}\n" , key , dicResult[key].open / SHIFT , dicResult[key].high / SHIFT , dicResult[key].low / SHIFT , dicResult[key].close / SHIFT , dicResult[key].volume); cnt++; if (cnt > 3) { message += "・・・以下略・・・"; break; } } DialogResult result = MessageBox.Show(message, "質問", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2); if (result == DialogResult.OK) { MakeBackupFile(code); UpdateDataFarm(code, dicFarm); AbstractBrand br = Env.BrandCollection.FindBrand(code); CommandExec.ShowBrand(br); //CommandExec.RefreshChart(); } } } private static void ReadFarm(DataFarm farm, ref SortedDictionary<int, NewDailyData2> dic) { for (var i = 0; i < farm.RawDataImage.Length / 32; i++) { var date = BitConverter.ToInt32(farm.RawDataImage, i * 32); NewDailyData2 ndd = new NewDailyData2(); ndd.open = BitConverter.ToInt32(farm.RawDataImage, i * 32 + 4); ndd.high = BitConverter.ToInt32(farm.RawDataImage, i * 32 + 8); ndd.low = BitConverter.ToInt32(farm.RawDataImage, i * 32 + 12); ndd.close = BitConverter.ToInt32(farm.RawDataImage, i * 32 + 16); ndd.volume = BitConverter.ToInt32(farm.RawDataImage, i * 32 + 20); ndd.creditlong = BitConverter.ToInt32(farm.RawDataImage, i * 32 + 24); ndd.creditshort = BitConverter.ToInt32(farm.RawDataImage, i * 32 + 28); dic.Add(date, ndd); } } private static void CompareCsvFarm(DataFarm farm, SortedDictionary<int, NewDailyData2> dicCsv, SortedDictionary<int, NewDailyData2> dicFarm, ref SortedDictionary<int, NewDailyData2> dicResult) { List<int> keyList = new List<int>(dicCsv.Keys); foreach (var key in keyList) { if (dicCsv[key].volume == 0) {//個別銘柄で出来高ゼロの場合は特別作業が必要。OmegaChartは出来高がない日は前の日の値で埋められているため if (farm.Brand != null && farm.Brand.Market != MarketType.B && farm.Brand.Market != MarketType.Custom) { NewDailyData2 ndd = new NewDailyData2(); ndd.open = 0; ndd.high = 0; ndd.low = 0; ndd.close = 0; ndd.volume = 0; dicCsv[key] = ndd; } } if (!dicFarm.ContainsKey(key)) dicResult.Add(key, dicCsv[key]); else { if (dicFarm[key].open != dicCsv[key].open || dicFarm[key].high != dicCsv[key].high || dicFarm[key].low != dicCsv[key].low || dicFarm[key].close != dicCsv[key].close || dicFarm[key].volume != dicCsv[key].volume) dicResult.Add(key, dicCsv[key]); } } } private static void ReadCsv(string filename, ref SortedDictionary<int, NewDailyData2> dic) { System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis"); var str = System.IO.File.ReadAllText(filename, enc).Replace("\r", ""); var lines = str.Split('\n'); for (var i = 0; i < lines.Length; i++) { var sp = lines[i].Split(','); if (sp.Length != 6) continue; var dt = DateTime.MinValue; NewDailyData2 ndd = new NewDailyData2(); double open = .0; double high = .0; double low = .0; double close = .0; if (DateTime.TryParse(sp[0], out dt) && double.TryParse(sp[1], out open) && double.TryParse(sp[2], out high) && double.TryParse(sp[3], out low) && double.TryParse(sp[4], out close) && int.TryParse(sp[5], out ndd.volume)) { ndd.open = (int)(open * SHIFT); ndd.high = (int)(high * SHIFT); ndd.low = (int)(low * SHIFT); ndd.close = (int)(close * SHIFT); if (dt != DateTime.MinValue) dic.Add(int.Parse(dt.ToString("yyyyMMdd")), ndd); } } } private static void UpdateDataFarm(int code, SortedDictionary<int, NewDailyData2> prices) { var farm = (DailyDataFarm)Env.BrandCollection.FindBrand(code).CreateDailyFarm(prices.Count); var empty = farm.IsEmpty; var skip = true; foreach (var pair in prices) { if (empty && skip && pair.Value.volume == 0) continue; skip = false; farm.UpdateDataFarm(pair.Key, pair.Value); } farm.Save(Util.GetDailyDataFileName(code)); } private static bool IsTextFile(string filePath) { var file = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read); var byteData = new byte[1]; while (file.Read(byteData, 0, byteData.Length) > 0) { if (byteData[0] == 0) return false; } return true; } } }