/// <summary> /// 构造函数 /// </summary> /// <param name="date">指定日期</param> public GetStocks(int startDate, int endDate, string indexName) { this.startDate = startDate; this.endDate = endDate; this.indexName = indexName; if (myTradeDays == null) { myTradeDays = new TradeDays(startDate, endDate); } if (stockList == null) { w.start(); stockList = getExitsStocks(); } }
private void GetBonusPlan() { bonusList = new SortedDictionary <string, stockBonus>(); w.start(); //利用万德wset的“分红预案”抓取数据 WindData wd = w.wset("dividendproposal", "ordertype=1;startdate=2015-06-30;enddate=2020-12-31;sectorid=a001010100000000;field=wind_code,sec_name,progress,cash_dividend,fellow_preplandate"); object[] stockList = wd.data as object[]; int num = stockList.Length / 5; for (int i = 0; i < num; i++) { stockBonus myBonus = new stockBonus(); myBonus.code = Convert.ToString(stockList[i * 5]); myBonus.name = (string)stockList[i * 5 + 1]; myBonus.progress = (string)stockList[i * 5 + 2]; myBonus.planBonus = (stockList[i * 5 + 3] == null? 0:(double)stockList[i * 5 + 3]); string[] date = Convert.ToString(stockList[i * 5 + 4]).Split(new char[] { '/', ' ' }); myBonus.planDate = Convert.ToInt32(date[0]) * 10000 + Convert.ToInt32(date[1]) * 100 + Convert.ToInt32(date[2]); if (TradeDays.GetTimeSpan(myBonus.planDate, yesterday) <= 125 && myBonus.code.Substring(7, 2) == "SH") { if (bonusList.ContainsKey(myBonus.code) == false) { bonusList.Add(myBonus.code, myBonus); } else if (TradeDays.GetTimeSpan(myBonus.planDate, yesterday) < TradeDays.GetTimeSpan(bonusList[myBonus.code].planDate, yesterday)) { bonusList[myBonus.code] = myBonus; } } } foreach (var item in GetStocks.stockList) { string code = item.Key; if (bonusList.ContainsKey(code) == false) { stockBonus myBonus = new stockBonus(); myBonus.code = item.Value.code; myBonus.name = item.Value.name; myBonus.progress = "没有分红预案"; bonusList.Add(myBonus.code, myBonus); } } }
private void EvaluateBonus() { //利用万德wset的“分红送转”抓取数据 foreach (var item in GetStocks.stockList) { stockBonus bonus = bonusList[item.Key]; List <int> dateList = new List <int>(); List <double> historicalBonusList = new List <double>(); WindData wd = w.wset("corporationaction", "startdate=2014-01-01;enddate=2020-06-20;windcode=" + bonus.code + ";field=ex_dividend_date,wind_code,sec_name,cash_payout_ratio,ex_dividend_note"); object[] stockList = wd.data as object[]; int num = (stockList == null ? 0 : stockList.Length / 5); for (int i = 0; i < num; i++) { string[] dateStr = Convert.ToString(stockList[i * 5]).Split(new char[] { '/', ' ' }); int date = Convert.ToInt32(dateStr[0]) * 10000 + Convert.ToInt32(dateStr[1]) * 100 + Convert.ToInt32(dateStr[2]); double planBonus = (stockList[i * 5 + 3] == null ? 0 : (double)stockList[i * 5 + 3]); dateList.Add(date); historicalBonusList.Add(planBonus); } //判断去年是否有2次分红 int thisYear = 0, lastYear = 0; for (int i = 0; i < dateList.Count; i++) { int date = dateList[i]; double myBonus = historicalBonusList[i]; if (date / 10000 + 1 == yesterday / 10000 && myBonus > 0) { lastYear += 1; } if (date / 10000 == yesterday / 10000 && myBonus > 0) { thisYear += 1; } } if (lastYear == 1 && thisYear == 1) { bonus.firstBonus = historicalBonusList[historicalBonusList.Count() - 1]; bonus.firstDate = dateList[dateList.Count() - 1]; bonus.firstStatus = "明确"; } if (lastYear == 1 && thisYear == 0) { if (bonus.planBonus != 0) { bonus.firstBonus = bonus.planBonus; bonus.firstDate = TradeDays.GetRecentTradeDay(dateList[dateList.Count() - 1] + 10000); bonus.firstStatus = "有预案但日期未明确"; } else { string str = DateTime.ParseExact(yesterday.ToString(), "yyyyMMdd", null).ToString("yyyy-MM-dd"); WindData eps = w.wsd(bonus.code, "eps_ttm", "ED-0TD", str, "Days=Alldays");//利用EPS来估算分红 double[] epsList = eps.data as double[]; double thisEps = epsList[0]; if (thisEps < 0) { bonus.firstStatus = "去年亏损无分红"; bonus.firstBonus = 0; bonus.firstDate = 0; } else { str = DateTime.ParseExact((yesterday - 10000).ToString(), "yyyyMMdd", null).ToString("yyyy-MM-dd"); eps = w.wsd(bonus.code, "eps_ttm", "ED-0TD", str, "Days=Alldays"); epsList = eps.data as double[]; double lastEps = (epsList == null?0:epsList[0]); if (lastEps == 0) { bonus.firstStatus = "去年无EPS数据无法预测"; bonus.firstBonus = 0; bonus.firstDate = 0; } else { bonus.firstBonus = historicalBonusList[historicalBonusList.Count() - 1] / lastEps * thisEps; bonus.firstDate = TradeDays.GetRecentTradeDay(dateList[dateList.Count() - 1] + 10000); bonus.firstStatus = "无预案按上次分红预测"; } } } } if (lastYear >= 2 && thisYear == 2) { bonus.firstBonus = historicalBonusList[historicalBonusList.Count() - 2]; bonus.firstDate = dateList[dateList.Count() - 2]; bonus.firstStatus = "明确"; bonus.secondBonus = historicalBonusList[historicalBonusList.Count() - 1]; bonus.secondDate = dateList[dateList.Count() - 1]; bonus.secondStatus = "明确"; } if (lastYear >= 2 && thisYear == 1) { bonus.firstBonus = historicalBonusList[historicalBonusList.Count() - 1]; bonus.firstDate = dateList[dateList.Count() - 1]; bonus.firstStatus = "明确"; if (bonus.planBonus != 0) { bonus.secondBonus = bonus.planBonus; bonus.secondDate = TradeDays.GetRecentTradeDay(dateList[dateList.Count() - 2] + 10000); bonus.secondStatus = "有预案但日期未明确"; } else { bonus.secondDate = TradeDays.GetRecentTradeDay(dateList[dateList.Count() - 2] + 10000); bonus.secondStatus = "无预案按上次分红预测"; bonus.secondBonus = historicalBonusList[historicalBonusList.Count() - 2] / historicalBonusList[historicalBonusList.Count() - 3] * historicalBonusList[historicalBonusList.Count() - 1]; } } if (lastYear >= 2 && thisYear == 0) { if (bonus.planBonus != 0) { bonus.firstBonus = bonus.planBonus; bonus.firstDate = TradeDays.GetRecentTradeDay(dateList[dateList.Count() - 2] + 10000); bonus.firstStatus = "有预案但日期未明确"; bonus.secondDate = TradeDays.GetRecentTradeDay(dateList[dateList.Count() - 1] + 10000); bonus.secondStatus = "无预案按上次分红预测"; bonus.secondBonus = historicalBonusList[historicalBonusList.Count() - 1] / historicalBonusList[historicalBonusList.Count() - 2] * bonus.planBonus; } else { string str = DateTime.ParseExact(yesterday.ToString(), "yyyyMMdd", null).ToString("yyyy-MM-dd"); WindData eps = w.wsd(bonus.code, "eps_ttm", "ED-0TD", str, "Days=Alldays"); double[] epsList = eps.data as double[]; double thisEps = epsList[0]; if (thisEps < 0) { bonus.firstStatus = "去年亏损无分红"; bonus.firstBonus = 0; bonus.firstDate = 0; bonus.secondStatus = "去年亏损无分红"; bonus.secondBonus = 0; bonus.secondDate = 0; } else { str = DateTime.ParseExact((yesterday - 10000).ToString(), "yyyyMMdd", null).ToString("yyyy-MM-dd"); eps = w.wsd(bonus.code, "eps_ttm", "ED-0TD", str, "Days=Alldays"); epsList = eps.data as double[]; double lastEps = (epsList == null ? 0 : epsList[0]); if (lastEps == 0) { bonus.firstStatus = "去年无EPS数据无法预测"; bonus.firstBonus = 0; bonus.firstDate = 0; bonus.secondStatus = "去年无EPS数据无法预测"; bonus.secondBonus = 0; bonus.secondDate = 0; } else { bonus.firstBonus = historicalBonusList[historicalBonusList.Count() - 2] / lastEps * thisEps; bonus.firstDate = TradeDays.GetRecentTradeDay(dateList[dateList.Count() - 2] + 10000); bonus.firstStatus = "无预案按上次分红预测"; bonus.secondBonus = historicalBonusList[historicalBonusList.Count() - 1] / lastEps * thisEps; bonus.secondDate = TradeDays.GetRecentTradeDay(dateList[dateList.Count() - 1] + 10000); bonus.secondStatus = "无预案按上次分红预测"; } } } } if (lastYear == 0 && thisYear == 0) { if (bonus.planBonus > 0) { bonus.firstBonus = bonus.planBonus; bonus.firstDate = 0; bonus.firstStatus = "有预案但日期未明确"; } else { bonus.firstStatus = "无预案无分红数据"; } } if (lastYear == 0 && thisYear == 1) { bonus.firstBonus = historicalBonusList[historicalBonusList.Count() - 1]; bonus.firstDate = dateList[dateList.Count() - 1]; bonus.firstStatus = "明确"; if (bonus.planBonus > 0) { bonus.secondBonus = bonus.planBonus; bonus.secondDate = 0; bonus.secondStatus = "有预案但日期未明确"; } } if (lastYear == 0 && thisYear == 2) { bonus.firstBonus = historicalBonusList[historicalBonusList.Count() - 2]; bonus.firstDate = dateList[dateList.Count() - 2]; bonus.firstStatus = "明确"; bonus.secondBonus = historicalBonusList[historicalBonusList.Count() - 1]; bonus.secondDate = dateList[dateList.Count() - 1]; bonus.secondStatus = "明确"; } if (bonus.firstStatus == "有预案但日期未明确" || bonus.firstStatus == "无预案按上次分红预测") { if (bonus.firstDate <= yesterday) { bonus.firstDate = 0; bonus.firstStatus += "预测日期已过"; } } if (bonus.secondStatus == "有预案但日期未明确" || bonus.secondStatus == "无预案按上次分红预测") { if (bonus.secondDate <= yesterday) { bonus.secondDate = 0; bonus.secondStatus += "预测日期已过"; } } evaluateBonusList.Add(bonus.code, bonus); } //预处理,默认除息除权日是分红的前一天 foreach (var item in GetStocks.stockList) { stockBonus bonus = evaluateBonusList[item.Key]; if (bonus.firstDate > 0) { bonus.firstRegisterDate = TradeDays.GetPreviousTradeDay(bonus.firstDate); } if (bonus.secondDate > 0) { bonus.SecondRegisterDate = TradeDays.GetPreviousTradeDay(bonus.secondDate); } evaluateBonusList[item.Key] = bonus; } //利用万德接口wset的“分红实施”来获取股权登记日 string lastYearStr = (yesterday / 10000 - 1).ToString(); WindData register = w.wset("bonus", "orderby=报告期;year=" + lastYearStr + ";period=y1;sectorid=a001010100000000;field=wind_code,sec_name,shareregister_date,dividend_payment_date"); object[] stockList2 = register.data as object[]; int num2 = (stockList2 == null?0:stockList2.Length / 4); for (int i = 0; i < num2; i++) { string code = Convert.ToString(stockList2[i * 4]); if (evaluateBonusList.ContainsKey(code)) { string[] date = Convert.ToString(stockList2[i * 4 + 3]).Split(new char[] { '/', ' ' }); int planDate = Convert.ToInt32(date[0]) * 10000 + Convert.ToInt32(date[1]) * 100 + Convert.ToInt32(date[2]); stockBonus bonus = evaluateBonusList[code]; if (planDate == bonus.firstDate) { date = Convert.ToString(stockList2[i * 4 + 2]).Split(new char[] { '/', ' ' }); bonus.firstRegisterDate = Convert.ToInt32(date[0]) * 10000 + Convert.ToInt32(date[1]) * 100 + Convert.ToInt32(date[2]); } if (planDate == bonus.secondDate) { date = Convert.ToString(stockList2[i * 4 + 2]).Split(new char[] { '/', ' ' }); bonus.SecondRegisterDate = Convert.ToInt32(date[0]) * 10000 + Convert.ToInt32(date[1]) * 100 + Convert.ToInt32(date[2]); } evaluateBonusList[code] = bonus; } } }
/// <summary> /// 根据程序运行日期,获取截止至昨日的指数成分股的列表 /// </summary> /// <returns>指数成分股列表</returns> private Dictionary <string, stockFormat> getExitsStocks() { Dictionary <string, stockFormat> list = new Dictionary <string, stockFormat>(); int yesterday = TradeDays.GetPreviousTradeDay(Convert.ToInt32(DateTime.Now.ToString("yyyyMMdd"))); foreach (int day in myTradeDays.myTradeDays) { string todayStr = DateTime.ParseExact(day.ToString(), "yyyyMMdd", null).ToString("yyyy-MM-dd"); if (day <= yesterday) { WindData wd = w.wset("sectorconstituent", "date=" + todayStr + ";windcode=" + indexName); object[] stockList = wd.data as object[]; int num = stockList.Length / 3; for (int i = 0; i < num; i++) { stockFormat myStock = new stockFormat(); myStock.code = Convert.ToString(stockList[i * 3 + 1]); myStock.name = (string)stockList[i * 3 + 2]; if (list.ContainsKey(myStock.code) == false) { myStock.existsDate = new List <int>(); myStock.existsDate.Add(day); myStock.existsDate.Add(day); list.Add(myStock.code, myStock); } else { int enterDate = list[myStock.code].existsDate[list[myStock.code].existsDate.Count() - 2]; int quitDate = list[myStock.code].existsDate[list[myStock.code].existsDate.Count() - 1]; if (day > TradeDays.GetNextTradeDay(quitDate)) { list[myStock.code].existsDate.Add(day); list[myStock.code].existsDate.Add(day); } else { list[myStock.code].existsDate[list[myStock.code].existsDate.Count() - 1] = day; } } } } } //若计算时间不包括历史时间,必须读取昨日的数据作为基准 if (list.Count == 0) { string yesterdayStr = DateTime.ParseExact(yesterday.ToString(), "yyyyMMdd", null).ToString("yyyy-MM-dd"); List <stockFormat> myList = new List <stockFormat>(); WindData wd = w.wset("sectorconstituent", "date=" + yesterdayStr + ";windcode=" + indexName); object[] stockList = wd.data as object[]; int num = stockList.Length / 3; for (int i = 0; i < num; i++) { stockFormat myStock = new stockFormat(); myStock.code = Convert.ToString(stockList[i * 3 + 1]).Substring(0, 6); myStock.name = (string)stockList[i * 3 + 2]; myStock.existsDate = new List <int>(); myStock.existsDate.Add(yesterday); myStock.existsDate.Add(yesterday); } } //从stockModify.csv中读取指数成分股变动股票和日期 #region modify int maxDate = yesterday; /* * DataTable dt = CsvApplication.OpenCSV("stockModify.csv"); * SortedDictionary<int, List<stockModify>> stockModifyList = new SortedDictionary<int, List<stockModify>>(); * for (int i = 0; i < dt.Rows.Count; i++) * { * stockModify stock = new stockModify(); * stock.code = dt.Rows[i][0].ToString(); * stock.name = dt.Rows[i][1].ToString(); * stock.date = Convert.ToInt32(dt.Rows[i][2].ToString()); * stock.direction = dt.Rows[i][3].ToString(); * if (stockModifyList.ContainsKey(stock.date)) * { * stockModifyList[stock.date].Add(stock); * } * else * { * List<stockModify> stockList0 = new List<stockModify>(); * stockList0.Add(stock); * stockModifyList.Add(stock.date, stockList0); * } * } * * * //根据文档对我的数据进行处理,如果变动时间大于昨日时间,需要对我的股票列表进行修正 * * foreach (var stockList in stockModifyList) * { * if (stockList.Value[0].date > yesterday) * { * foreach (var stock in stockList.Value) * { * if (stock.direction == "out") * { * if (list.ContainsKey(stock.code) == true) * { * list[stock.code].existsDate[list[stock.code].existsDate.Count() - 1] = stock.date; * } * } * if (stock.direction == "in") * { * if (stockList.Value[0].date > maxDate) * { * maxDate = stockList.Value[0].date; * } * if (list.ContainsKey(stock.code) == true) * { * list[stock.code].existsDate.Add(stock.date); * list[stock.code].existsDate.Add(stock.date); * } * else * { * stockFormat myStock = new stockFormat(); * myStock.name = stock.name; * myStock.code = stock.code; * myStock.existsDate = new List<int>(); * myStock.existsDate.Add(stock.date); * myStock.existsDate.Add(stock.date); * } * } * } * } * } */ #endregion //按照回测日期给股票列表进行修正 foreach (var stock in list) { if (stock.Value.existsDate[stock.Value.existsDate.Count() - 1] == yesterday || stock.Value.existsDate[stock.Value.existsDate.Count() - 1] == maxDate) { stock.Value.existsDate[stock.Value.existsDate.Count() - 1] = endDate; } } return(list); }