using System; using System.Text; using System.IO; using System.Collections; using System.Diagnostics; using Zanetti.Data; namespace Zanetti.DataSource.Specialized { internal class KabuPlusDataSource : DailyDataSource { private bool _includesDomesticIndices; private const string HOZON_DIR = @"C:\tmp";//要変更 KABU+からダウンロードしたCSVファイルを保存しておくフォルダ名 public KabuPlusDataSource(int[] dates) : base(dates) { } public bool IncludesDomesticIndices { get { return _includesDomesticIndices; } set { _includesDomesticIndices = value; } } public override void Run() { Hashtable[] newdata = new Hashtable[_dates.Length]; //データをまずダウンロード for (int i = 0; i < _dates.Length; i++) { newdata[i] = FillData(_dates[i]); SendMessage(AsyncConst.WM_ASYNCPROCESS, _dates[i] | DATE_MASK, AsyncConst.LPARAM_PROGRESS_SUCCESSFUL); } //各データの追加と保存 IDictionaryEnumerator ie = Env.BrandCollection.GetEnumerator(); while (ie.MoveNext()) { AbstractBrand br = (AbstractBrand)ie.Value; if ((br.Market == MarketType.B && !IsMujinzouSupportedIndices(br.Code)) || br.Market == MarketType.Custom) continue; bool trace_flag = false; using (DailyDataFarm f = (DailyDataFarm)br.CreateDailyFarm(_dates.Length)) { for (int i = 0; i < _dates.Length; i++) { NewDailyData td = (NewDailyData)newdata[i][br.Code]; if (td == null) { if (!trace_flag) { trace_flag = true; Debug.WriteLine("Data not found(mujinzou) : code=" + br.Code + " market=" + br.Market.ToString()); } } else f.UpdateDataFarm(_dates[i], td); } f.Save(Util.GetDailyDataFileName(br.Code)); } SendMessage(AsyncConst.WM_ASYNCPROCESS, br.Code, AsyncConst.LPARAM_PROGRESS_SUCCESSFUL); } } //ある日付に対して、コードのint値からPanRollingTradeDataへのハッシュテーブルを構築して返す //japan-all-stock-prices-2 25列 //SC,名称,市場,業種,日時,株価,前日比,前日比(%),前日終値,始値,高値,安値,VWAP,出来高,出来高率,売買代金(千円),時価総額(百万円),値幅下限,値幅上限,高値日付,年初来高値,年初来高値乖離率,安値日付,年初来安値,年初来安値乖離率 //tosho-etf-stock-prices 17列 //tosho-reit-stock-prices 17列 //tosho-fund-and-others-stock-prices 17列 //SC,名称,市場,業種,日時,株価,前日比,前日比(%),前日終値,始値,高値,安値,出来高,売買代金(千円),時価総額(百万円),値幅下限,値幅上限 private Hashtable FillData(int date) { Hashtable result = new Hashtable(); try { DateTime d2 = Util.IntToDate(date); var files = System.IO.Directory.GetFiles(HOZON_DIR, string.Format("*{0}*.csv", date), System.IO.SearchOption.TopDirectoryOnly); String2Hashtable(files, ref result); } catch(Exception ex) { Console.WriteLine(ex.Message); } return result; } private void String2Hashtable(string[] files, ref Hashtable result) { Array.Sort(files); foreach (var fn in files) { var is_japanallstockprices2 = false; if (!ChkFilename(fn, ref is_japanallstockprices2)) continue; using (var sr = new StreamReader(fn, System.Text.Encoding.GetEncoding("shift_jis"))) { var line = sr.ReadLine(); while (line != null) { line = line.Replace("\"", ""); string[] t = line.Split(','); if (chk_t(t)) { var code = ParseCode(t[0]); if (code == 0) continue; BasicBrand br = Env.BrandCollection.FindBrand(code) as BasicBrand; if (code == 101 || code == 102) { line = sr.ReadLine(); continue;//日経平均とTOPIXはここで取らない場合は抜ける } if (br != null && CheckMarket(br, t[2])) { double vv = 1, pv = 10; // 株価は10倍で記録 //倍率調整 if (IsDomesticIndex(code)) { vv = 0.001; //DreamVisorのものにあわせる格好で。1000株単位かな pv = 100; } if (code == (int)BuiltInIndex.TOPIX_F) { //TOPIX先物は整数単位で記録されている pv = 10; } NewDailyData td = new NewDailyData(); try { td.volume = (int)(String2Double(t[is_japanallstockprices2 ? 13 : 12]) * vv);//個別株用のCSVファイルはその他と出来高の位置が違う NewDailyData existing = (NewDailyData)result[code]; //Debug.WriteLine(line); td.open = (int)(String2Double(t[9]) * pv); td.high = (int)(String2Double(t[10]) * pv); td.low = (int)(String2Double(t[11]) * pv); td.close = (int)(String2Double(t[5]) * pv); } catch (Exception ex) { Console.WriteLine(ex.Message); } result[code] = td; } } line = sr.ReadLine(); } } } } private bool ChkFilename(string filename, ref bool is_japanallstockprices2) { is_japanallstockprices2 = false; var ret = false; if (filename.IndexOf("japan-all-stock-prices-2") >= 0) { is_japanallstockprices2 = true; ret = true; } else { foreach (var e in new string[] { "tosho-etf-stock-prices", "tosho-reit-stock-prices", "tosho-fund-and-others-stock-prices" }) { if (filename.IndexOf(e) >= 0) { ret = true; } } } return ret; } private double String2Double(string s) { var line = s.Replace("-", "0"); if (s == string.Empty) line = "0"; var f = .0; if (!double.TryParse(line, out f)) f = 0; return f; } private bool chk_t(string[] t) { var ret = true; var d = 0; if (t[0].Length != 4) ret = false; if (!int.TryParse(t[0], out d)) ret = false; return ret; } private static bool CheckMarket(BasicBrand br, string mar) { MarketType mt = br.Market; switch (mt) { //2006/12/26のデータより、東証はすべてコード11, 大証1・2部は21, ヘラクレスは23に変更になった。旧データを読んだときでも大丈夫なように古い判定も残しておく case MarketType.B: return mar == "東証"; //指数は東証一部として記録されている case MarketType.T1: return mar == "東証一部"; case MarketType.T2: return mar == "東証二部"; case MarketType.M: return mar == "東証マザ"; case MarketType.J: return mar == "JQG" || mar == "JQS"; default: return false; } } private static bool IsMujinzouSupportedIndices(int code) { return code == (int)BuiltInIndex.Nikkei225 || code == (int)BuiltInIndex.TOPIX || code == (int)BuiltInIndex.JASDAQ || code == (int)BuiltInIndex.Nikkei225_F || code == (int)BuiltInIndex.TOPIX_F; } private static int ParseCode(string code) { int t = Util.ParseInt(code); //以下に該当するものでなければデータの取り込みは行われない if (t < 1300) { switch (t) { case 0001: return (int)BuiltInIndex.Nikkei225; case 0002: return (int)BuiltInIndex.TOPIX; case 1004: return (int)BuiltInIndex.Nikkei225_F; case 1005: return (int)BuiltInIndex.JASDAQ; case 1006: return (int)BuiltInIndex.TOPIX_F; default: return 0; } } else return t; //ふつうの銘柄 } private static bool IsDomesticIndex(int code) { return code == (int)BuiltInIndex.Nikkei225 || code == (int)BuiltInIndex.TOPIX || code == (int)BuiltInIndex.JASDAQ; } } }