OmegaChartのソースコードの保守
Rev. | 9cd2e32808deefe5bc4041be433772fef9fe3cbe |
---|---|
Tamaño | 9,082 octetos |
Tiempo | 2017-03-03 18:40:22 |
Autor | panacoran |
Log Message | 上場してから出来高のない銘柄でスクリーニングが失敗するのを再度直す
|
// Copyright (c) 2014 panacoran <panacoran@users.osdn.me>
// This program is part of OmegaChart.
// OmegaChart is licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using Zanetti.Data;
namespace Zanetti.DataSource.Specialized
{
internal class KdbComDataSource : DailyDataSource
{
public KdbComDataSource(int[] dates) : base(dates)
{
}
public override void Run()
{
GetIndices(); // 先に指数のデータを読む。
var newdata = new Dictionary<int, Dictionary<int, NewDailyData>>();
foreach (var date in _dates)
{
newdata[date] = FillData(date);
SendMessage(AsyncConst.WM_ASYNCPROCESS, date | DATE_MASK, AsyncConst.LPARAM_PROGRESS_SUCCESSFUL);
}
foreach (AbstractBrand br in Env.BrandCollection.Values)
{
if (br.Market == MarketType.B && !IsSupportedIndex(br.Code) || br.Market == MarketType.Custom)
continue;
using (var farm = (DailyDataFarm)br.CreateDailyFarm(_dates.Length))
{
var traceFlag = false;
foreach (var date in _dates)
{
NewDailyData td;
if (newdata[date].TryGetValue(br.Code, out td))
{
farm.UpdateDataFarm(date, td);
}
else
{
if (traceFlag)
continue;
traceFlag = true;
Debug.WriteLine("Data not found(k-db.com) : code=" + br.Code + " market=" + br.Market);
}
}
farm.Save(Util.GetDailyDataFileName(br.Code));
SendMessage(AsyncConst.WM_ASYNCPROCESS, br.Code, AsyncConst.LPARAM_PROGRESS_SUCCESSFUL);
}
}
}
private readonly Dictionary<DateTime, int> _marketVolume = new Dictionary<DateTime, int>();
private readonly Dictionary<DateTime, NewDailyData> _nikkei225 = new Dictionary<DateTime, NewDailyData>();
private readonly Dictionary<DateTime, NewDailyData> _topix = new Dictionary<DateTime, NewDailyData>();
private void GetIndices()
{
GetMarketVolume();
GetIndexValues();
}
private void GetMarketVolume()
{
const string url = "http://k-db.com/statistics/T1?download=csv";
using (var reader = new StreamReader(Util.HttpDownload(url), Encoding.GetEncoding("shift_jis")))
{
string line;
while ((line = reader.ReadLine()) != null)
{
var tokens = line.Split(',');
switch (tokens[0])
{
case "東証1部":
case "日付":
continue;
}
var date = DateTime.Parse(tokens[0]);
var volume = double.Parse(tokens[1]);
_marketVolume[date] = (int)(volume * 0.001);
}
}
}
private void GetIndexValues()
{
foreach (var kdbCode in new[] {"I101", "I102"})
{
var url = string.Format("http://k-db.com/indices/{0}?download=csv", kdbCode);
var prices = kdbCode == "I101" ? _nikkei225 : _topix;
using (var reader = new StreamReader(Util.HttpDownload(url), Encoding.GetEncoding("shift_jis")))
{
string line;
while ((line = reader.ReadLine()) != null)
{
var tokens = line.Split(',');
if (tokens.Length != 5)
continue;
if (tokens[0] == "日付")
continue;
var date = DateTime.Parse(tokens[0]);
prices[date] = new NewDailyData
{
open = (int)(double.Parse(tokens[1]) * 100),
high = (int)(double.Parse(tokens[2]) * 100),
low = (int)(double.Parse(tokens[3]) * 100),
close = (int)(double.Parse(tokens[4]) * 100),
volume = _marketVolume[date]
};
}
}
}
}
private void InsertIndices(DateTime date, Dictionary<int, NewDailyData> result)
{
result[(int)BuiltInIndex.Nikkei225] = _nikkei225[date];
result[(int)BuiltInIndex.TOPIX] = _topix[date];
}
private Dictionary<int, NewDailyData> FillData(int date)
{
var result = new Dictionary<int, NewDailyData>();
var d2 = Util.IntToDate(date);
var url = string.Format("http://k-db.com/stocks/{0:yyyy-MM-dd}?download=csv", d2);
using (var reader = new StreamReader(Util.HttpDownload(url), Encoding.GetEncoding("shift_jis")))
{
InsertIndices(d2, result);
string line;
while ((line = reader.ReadLine()) != null)
{
var tokens = line.Split(',');
if (tokens.Length != 9 || tokens[0].Length != 6)
continue;
var code = int.Parse(tokens[0].Substring(0, 4));
var br = Env.BrandCollection.FindBrand(code) as BasicBrand;
if (br == null || !CheckMarket(br.Market, tokens[2]))
continue;
var volume = (int)ParseField(tokens[7]);
const int shift = 10; // 株価は10倍で記録
var td = new NewDailyData
{
volume = volume,
open = (int)(ParseField(tokens[3]) * shift),
high = (int)(ParseField(tokens[4]) * shift),
low = (int)(ParseField(tokens[5]) * shift),
close = (int)(ParseField(tokens[6]) * shift)
};
result[code] = td;
}
}
return result;
}
private bool CheckMarket(MarketType market, string name)
{
switch (name)
{
case "東証":
case "東証1部":
return market == MarketType.T1;
case "東証2部":
return market == MarketType.T2;
case "東証マザーズ":
case "東証マザーズ外国":
case "東証マザーズ審査": //20150119 k-db仕様変更にて追加
return market == MarketType.M;
case "東証TPM":
return market == MarketType.Custom;
case "東証1部外国":
return market == MarketType.T1;
case "東証2部外国":
return market == MarketType.T2;
case "大証":
case "大証1部":
return market == MarketType.O1;
case "大証2部":
return market == MarketType.O2;
case "東証JQグロース":
case "東証JQスタンダード":
case "東証JQスタンダード外国":
case "JQ":
case "JQスタンダード":
case "JQスタンダード外国":
case "JQグロース":
case "JQNEO":
return market == MarketType.J;
case "HCスタンダード":
case "HCスタンダード外国":
case "HCグロース":
return market == MarketType.H;
case "福証":
case "福証Q-Board":
case "札証":
case "札証アンビシャス":
case "名証":
return false;
}
return false;
}
private bool IsSupportedIndex(int code)
{
return code == (int)BuiltInIndex.Nikkei225 ||
code == (int)BuiltInIndex.TOPIX;
}
private double ParseField(string s)
{
// 空文字列を0として扱う。
return s == "" ? 0 : double.Parse(s);
}
}
}