private void prepare(string code, DateTime startDate, DateTime endDate) { //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取基本信息 this.code = code; //获取日线数据 var dailyData = stockDailyRepo.GetStockTransactionWithRedis(code, startDate, endDate); //获取分钟线数据 foreach (var date in tradedays) { var minuteKLine = stockMinutelyRepo.GetStockTransactionWithRedis(code, date, date); underlyingKLine.Add(date, minuteKLine); } foreach (var item in dailyData) { var KLines = underlyingKLine[item.DateTime]; foreach (var KLine in KLines) { KLine.AdjFactor = item.AdjFactor; } } for (int n = 3; n < 50; n++) { var dic = getMA(underlyingKLine, n); MADic.Add(n, dic); } }
//将计算用的数据准备好 private void dataPrepare(string underlyingCode, DateTime startDate, DateTime endDate, int pushForwardDays = 0) { //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取日线数据 var dayNow = stockDailyRepo.GetStockTransactionWithRedis(underlyingCode, startDate.AddDays(-pushForwardDays), endDate); if (this.DailyKLine.ContainsKey(underlyingCode)) { var data = DailyKLine[underlyingCode]; data = dayNow; } else { DailyKLine.Add(underlyingCode, dayNow); } //选取需要获取数据的交易日 List <DateTime> myTradedays = new List <DateTime>(); //从日线上观察波动剧烈的日期,并记录数据 for (int i = 1; i < DailyKLine[underlyingCode].Count(); i++) { if (DailyKLine[underlyingCode][i].High / DailyKLine[underlyingCode][i - 1].Close >= 1.07) { var today = DailyKLine[underlyingCode][i].DateTime.Date; if (myTradedays.Contains(today) == false) { myTradedays.Add(DailyKLine[underlyingCode][i].DateTime.Date); } var nextDay = DateTimeExtension.DateUtils.NextTradeDay(DailyKLine[underlyingCode][i].DateTime.Date).Date; if (myTradedays.Contains(nextDay) == false) { myTradedays.Add(nextDay); } } } //foreach (var item in DailyKLine[underlyingCode]) //{ // if (item.High / item.Low - 1 > 0.05) // { // var today = item.DateTime.Date; // if (myTradedays.Contains(today)==false) // { // myTradedays.Add(item.DateTime.Date); // } // var nextDay = DateTimeExtension.DateUtils.NextTradeDay(item.DateTime.Date).Date; // if (myTradedays.Contains(nextDay)==false) // { // myTradedays.Add(nextDay); // } // } //} //getMinuteData(underlyingCode, myTradedays); getTickData(underlyingCode, myTradedays); }
public void getStockDailyData(DateTime startDate, DateTime endDate) { var list = stockInfoRepo.GetStockListInfoFromSql(); foreach (var item in list) { DateTime startTime = startDate; DateTime endTime = endDate; if (startDate < item.IPODate) { startTime = item.IPODate; } if (endDate > item.DelistDate) { endTime = item.DelistDate; } var data = stockDailyRepo.GetStockTransactionWithRedis(item.code, startTime, endTime); Console.WriteLine("code:{0} dailyData form {1} to {2} complete!", item.code, startTime, endTime); } }
//将计算用的数据准备好 private void dataPrepare(string underlyingCode, string indexCode, DateTime startDate, DateTime endDate, int N = 20) { //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取基本信息 this.indexCode = indexCode; this.underlyingCode = underlyingCode; //获取日线数据 var indexData = stockDailyRepo.GetStockTransactionWithRedis(indexCode, startDate, endDate); //获取分钟线数据 foreach (var date in tradedays) { var minuteKLine = stockMinutelyRepo.GetStockTransactionWithRedis(underlyingCode, date, date); underlyingKLine.Add(date, minuteKLine); var minuteKLine2 = stockMinutelyRepo.GetStockTransactionWithRedis(indexCode, date, date); indexKLine.Add(date, minuteKLine2); } for (int n = 10; n <= 30; n++) { Dictionary <DateTime, double> range = new Dictionary <DateTime, double>(); foreach (var date in tradedays) { var index = indexKLine[date]; var underlying = underlyingKLine[date]; double HH = 0; //最高价的最高价 double HC = 0; //收盘价的最高价 double LC = 99999; //收盘价的最低价 double LL = 99999; //最低价的最低价 for (int i = 0; i < n; i++) { if (index[i].High > HH) { HH = index[i].High; } if (index[i].Close > HC) { HC = index[i].Close; } if (index[i].Close < LC) { LC = index[i].Close; } if (index[i].Low < LL) { LL = index[i].Low; } } double rangeNow = Math.Max(HH - LC, HC - LL); range.Add(date, rangeNow); } RangeDic.Add(n, range); } }
private Dictionary <DateTime, StockTransaction> getUnderlyingDailyData(DateTime startDate, DateTime endDate) { Dictionary <DateTime, StockTransaction> underlyingDailyData = new Dictionary <DateTime, StockTransaction>(); var data = stockDailyRepo.GetStockTransactionWithRedis(underlying, startDate, endDate); foreach (var item in data) { underlyingDailyData.Add(item.DateTime, item); } this.underlyingDailyDataList = data; return(underlyingDailyData); }
//将计算用的数据准备好 private void dataPrepare(string underlyingCode, DateTime startDate, DateTime endDate, int N = 20) { //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取基本信息 this.underlyingCode = underlyingCode; //获取日线数据 var underlyingData = stockDailyRepo.GetStockTransactionWithRedis(underlyingCode, startDate, endDate); for (int n = 1; n <= N; n++) { Dictionary <DateTime, double> range = new Dictionary <DateTime, double>(); for (int i = n; i < underlyingData.Count() - 1; i++) { double HH = 0; //最高价的最高价 double HC = 0; //收盘价的最高价 double LC = 99999; //收盘价的最低价 double LL = 99999; //最低价的最低价 for (int k = i - n; k <= i - 1; k++) { if (underlyingData[k].High > HH) { HH = underlyingData[k].High; } if (underlyingData[k].Close > HC) { HC = underlyingData[k].Close; } if (underlyingData[k].Close < LC) { LC = underlyingData[k].Close; } if (underlyingData[k].Low < LL) { LL = underlyingData[k].Low; } } double lastClose = underlyingData[i - 1].Close; double rangeNow = Math.Max(HH - LC, HC - LL); range.Add(underlyingData[i].DateTime, rangeNow); } RangeDic.Add(n, range); } //获取分钟线数据 foreach (var date in tradedays) { var minuteKLine = stockMinutelyRepo.GetStockTransactionWithRedis(underlyingCode, date, date); underlyingKLine.Add(date, minuteKLine); } }
private void dataPrepareAll(string underlyingCode, DateTime startDate, DateTime endDate) { //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取日线数据 var dayNow = stockDailyRepo.GetStockTransactionWithRedis(underlyingCode, startDate, endDate); if (this.DailyKLine.ContainsKey(underlyingCode)) { var data = DailyKLine[underlyingCode]; data = dayNow; } else { DailyKLine.Add(underlyingCode, dayNow); } //选取需要获取数据的交易日 List <DateTime> myTradedays = dateRepo.GetStockTransactionDate(startDate, endDate); getMinuteData(underlyingCode, myTradedays); //getTickData(underlyingCode, myTradedays); }
//将计算用的数据准备好 private void dataPrepare(string underlyingCode, DateTime startDate, DateTime endDate, int N = 20) { //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取基本信息 this.underlyingCode = underlyingCode; //获取日线数据 var underlyingData = stockDailyRepo.GetStockTransactionWithRedis(underlyingCode, startDate, endDate); for (int n = 1; n <= N; n++) { Dictionary <DateTime, double> vol = new Dictionary <DateTime, double>(); for (int i = n; i < underlyingData.Count() - 1; i++) { List <double> openToClose = new List <double>(); for (int j = Math.Max(0, i - n); j < i; j++) { if (underlyingData[j].Volume > 0) { openToClose.Add(underlyingData[j].Close / underlyingData[j].Open - 1); } } if (openToClose.Count() > n / 2) { double volNow = getVol(openToClose); if (volNow > 0) { vol.Add(underlyingData[i].DateTime, volNow); } } } volDic.Add(n, vol); } //获取分钟线数据 foreach (var date in tradedays) { var minuteKLine = stockMinutelyRepo.GetStockTransactionWithRedis(underlyingCode, date, date); underlyingKLine.Add(date, minuteKLine); } }
public void compute(DateTime startDate, DateTime endDate) { var startday = DateTimeExtension.DateUtils.PreviousTradeDay(startDate, duration + 1); var endday = DateTimeExtension.DateUtils.PreviousTradeDay(endDate, duration + 1); priceList = stockDailyRepo.GetStockTransactionWithRedis(code, startday, endDate); var tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); if (priceDic == null || priceDic.Count() == 0) { foreach (var item in priceList) { priceDic.Add(item.DateTime, item.Close); } } for (int i = 0; i < tradedays.Count() - duration; i++) { var call = -getHedgeCost(tradedays[i], tradedays[i + duration], code); Console.WriteLine("call from {0} to {1} costs {2}!", tradedays[i], tradedays[i + duration], call); } }
private void prepare(string underlyingCode, string indexCode, DateTime startDate, DateTime endDate) { //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取基本信息 this.indexCode = indexCode; this.underlyingCode = underlyingCode; //获取日线数据 var indexData = stockDailyRepo.GetStockTransactionWithRedis(indexCode, startDate, endDate); volatilityDaily = getDailyVolatility(indexData); //获取分钟线数据 foreach (var date in tradedays) { var minuteKLine = stockMinutelyRepo.GetStockTransactionWithRedis(underlyingCode, date, date); underlyingKLine.Add(date, minuteKLine); var minuteKLine2 = stockMinutelyRepo.GetStockTransactionWithRedis(indexCode, date, date); indexKLine.Add(date, minuteKLine2); } volatilityMinutely = getMinutelyVolatility(indexKLine, 1); }
private void DataPreparation(DateTime startDate, DateTime endDate) { var tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); var etfDaily = stockDailyRepo.GetStockTransactionWithRedis(code, startDate, endDate); }
private void dataPrepare(DateTime startDate, DateTime endDate) { //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); List <DateTime> ceilDate = new List <DateTime>(); string bondCode; string underlyingCode; //获取可转债信息 this.bondInfo = GetConvertibleBondInfos(endDate); //获取日线数据 try { foreach (var info in bondInfo) { underlyingCode = info.stockCode; DateTime startTime = startDate; DateTime endTime = endDate; if (startTime < info.startDate) { startTime = info.startDate; } if (endTime > info.endDate) { endTime = info.endDate; } if (dailyData.ContainsKey(underlyingCode) == false) { var underlyingData = stockDailyRepo.GetStockTransactionWithRedis(underlyingCode, startTime.AddDays(-10), endTime); dailyData.Add(underlyingCode, underlyingData); endTime = DateTimeExtension.DateUtils.PreviousTradeDay(info.endDate, 7); if (endTime > endDate.Date) { endTime = endDate.Date; } if (startDate > endTime) { startDate = endTime; } var bondData = stockDailyRepo.GetStockTransactionWithRedis(info.code, info.startDate, endTime); dailyData.Add(info.code, bondData); if (info.startDate > endTime) { continue; } var tempDataTable = windReader.GetDailyDataTable(info.code, "clause_conversion2_swapshareprice,underlyingcode,clause_conversion_2_swapsharestartdate,clause_conversion_2_swapshareenddate", info.startDate, endTime); List <ConvertibleBondDailyInfo> bondDaily = new List <ConvertibleBondDailyInfo>(); foreach (DataRow dt in tempDataTable.Rows) { ConvertibleBondDailyInfo bondDailyInfoNow = new ConvertibleBondDailyInfo(); bondDailyInfoNow.code = info.code; bondDailyInfoNow.name = info.name; bondDailyInfoNow.startDate = info.startDate; bondDailyInfoNow.endDate = info.endDate; bondDailyInfoNow.stockCode = info.stockCode; bondDailyInfoNow.conversionPrice = Convert.ToDouble(dt["clause_conversion2_swapshareprice"]); //bondDailyInfoNow.forceConvertDate = Convert.ToDateTime(dt["clause_conversion_2_forceconvertdate"]); bondDailyInfoNow.conversionStartDate = Convert.ToDateTime(dt["clause_conversion_2_swapsharestartdate"]); bondDailyInfoNow.conversionEndDate = Convert.ToDateTime(dt["clause_conversion_2_swapshareenddate"]); bondDailyInfoNow.date = Convert.ToDateTime(dt["datetime"]); bondDaily.Add(bondDailyInfoNow); } bondDailyInfo.Add(info.code, bondDaily); } } } catch (Exception e) { Console.WriteLine(e.Message); } int num = 0; foreach (var item in dailyData) { var data = item.Value; var code = item.Key; num = num + 1; Console.WriteLine(num); for (int i = 1; i < data.Count(); i++) { if (data[i] == null || data[i].DateTime.Date < startDate) { continue; } DateTime day = data[i].DateTime.Date; //获取其对应的可转债 bondCode = getConvetibleCodeByStockCode(code, day, bondInfo); //判断是否涨停 var dataToday = data[i]; var dataYesterday = data[i - 1]; double price = Math.Round(dataYesterday.Close * dataYesterday.AdjFactor / dataToday.AdjFactor * 1.1, 2); //获取日内数据 try { if (data[i].High >= 0.99 * price && bondCode != "") { //获取分钟数据 //var data1 = stockMinutelyRepo.GetStockTransactionWithRedis(bondCode, day, day); //var data2 = stockMinutelyRepo.GetStockTransactionWithRedis(code, day, day); //if (minuteData.ContainsKey(data[i].DateTime) == true) //{ // minuteData[data[i].DateTime].Add(bondCode, data1); // minuteData[data[i].DateTime].Add(code, data2); //} //else //{ // Dictionary<string, List<StockTransaction>> dataNow = new Dictionary<string, List<StockTransaction>>(); // dataNow.Add(bondCode, data1); // dataNow.Add(code, data2); // minuteData.Add(day, dataNow); //} //获取tick数据 DateTime startTime = day.Date + new TimeSpan(9, 30, 0); DateTime endTime = day.Date + new TimeSpan(15, 0, 0); var data3 = tickRepo.GetStockTransaction(bondCode, startTime, endTime); var data4 = tickRepo.GetStockTransaction(code, startTime, endTime); if (tickData.ContainsKey(day.Date) == true) { tickData[day.Date].Add(bondCode, data3); tickData[day.Date].Add(code, data4); } else { Dictionary <string, List <StockTickTransaction> > dataNow = new Dictionary <string, List <StockTickTransaction> >(); dataNow.Add(bondCode, data3); dataNow.Add(code, data4); tickData.Add(day.Date, dataNow); } } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("code:{0} date:{1} No data!", bondCode, day); } } } }
public void compute(DateTime startDate, DateTime endDate) { var tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取日线数据 var underlyingDaily1 = stockDailyRepo.GetStockTransactionWithRedis(code1, tradedays.First(), tradedays.Last()); var underlyingDaily2 = stockDailyRepo.GetStockTransactionWithRedis(code2, tradedays.First(), tradedays.Last()); int length = underlyingDaily1.Count(); double[] y = new double[length]; double[] x = new double[length]; double[] z = new double[length]; double[] alphaList = new double[length]; double[] betaList = new double[length]; double[] cointegrationSequence = new double[length]; //向上穿越下轨1为1,向上穿越中轨为2,向上穿越上轨1为3, //向下穿越下轨1位-1,向下穿越中轨为-2,向下穿越上轨1为-3, //向上穿越上轨2为4,向下穿越下轨2为-4,其他为0 double[] signal = new double[length]; List <signalWithTime> signalList = new List <signalWithTime>(); double[] longsignal = new double[length]; double[] shortsignal = new double[length]; int duration = 30; int duration1 = duration; double lambda1 = 2; double lambda2 = 3; double y0 = underlyingDaily1[0].Close * underlyingDaily1[0].AdjFactor; double x0 = underlyingDaily2[0].Close * underlyingDaily2[0].AdjFactor; for (int i = 0; i < tradedays.Count(); i++) { if ((i - duration1) >= 0) { y[i] = underlyingDaily1[i].Close * underlyingDaily1[i].AdjFactor / (underlyingDaily1[i - duration1].Close * underlyingDaily1[i - duration1].AdjFactor); x[i] = underlyingDaily2[i].Close * underlyingDaily2[i].AdjFactor / (underlyingDaily2[i - duration1].Close * underlyingDaily2[i - duration1].AdjFactor); } else { y[i] = underlyingDaily1[i].Close * underlyingDaily1[i].AdjFactor / y0; x[i] = underlyingDaily2[i].Close * underlyingDaily2[i].AdjFactor / x0; } //z[i] = Math.Log(y[i] / x[i]); z[i] = (y[i]) / (x[i]); } var myboll = getBollingerBand(z, duration); double scale = 0.1; List <BollingerBandwithPrice> myboll2 = new List <BollingerBandwithPrice>(); for (int i = 0; i < myboll.Length; i++) { if (myboll[i] != null) { BollingerBandwithPrice boll0 = new BollingerBandwithPrice(); boll0.mean = myboll[i].mean; boll0.std = myboll[i].std; boll0.price = z[i]; boll0.time = tradedays[i].Date; boll0.low2 = boll0.mean - lambda2 * boll0.std; boll0.low1 = boll0.mean - lambda1 * boll0.std; boll0.up2 = boll0.mean + lambda2 * boll0.std; boll0.up1 = boll0.mean + lambda1 * boll0.std; if (Math.Abs(boll0.price - boll0.mean) <= scale * boll0.std) { boll0.area = 0; } else if (boll0.price - boll0.mean > scale * boll0.std && boll0.price - boll0.up1 < -scale * boll0.std) { boll0.area = 1; } else if (Math.Abs(boll0.price - boll0.up1) <= scale * boll0.std) { boll0.area = 2; } else if (boll0.price - boll0.up1 > scale * boll0.std && boll0.price - boll0.up2 < -scale * boll0.std) { boll0.area = 3; } else if (Math.Abs(boll0.price - boll0.up2) <= scale * boll0.std) { boll0.area = 4; } else if (boll0.price - boll0.up2 > scale * boll0.std) { boll0.area = 5; } else if (boll0.price - boll0.mean < -scale * boll0.std && boll0.price - boll0.low1 > scale * boll0.std) { boll0.area = -1; } else if (Math.Abs(boll0.price - boll0.low1) <= scale * boll0.std) { boll0.area = -2; } else if (boll0.price - boll0.low1 < -scale * boll0.std && boll0.price - boll0.low2 > scale * boll0.std) { boll0.area = -3; } else if (Math.Abs(boll0.price - boll0.low2) <= scale * boll0.std) { boll0.area = -4; } else if (boll0.price - boll0.low2 < -scale * boll0.std) { boll0.area = -5; } myboll2.Add(boll0); } } var dt = DataTableExtension.ToDataTable(myboll2); DataTableExtension.SaveCSV(dt, "E:\\result\\bollinger\\boll.csv"); for (int i = 1; i < length; i++) { if (myboll[i - 1] == null || myboll[i - 1].std == 0) { signal[i - 1] = 0; continue; } if (underlyingDaily1[i].TradeStatus != "交易" || underlyingDaily2[i].TradeStatus != "交易") { signal[i] = signal[i - 1]; continue; } double upper1 = myboll[i].mean + lambda1 * myboll[i].std; double lower1 = myboll[i].mean - lambda1 * myboll[i].std; double middle = myboll[i].mean; double upper2 = myboll[i].mean + lambda2 * myboll[i].std; double lower2 = myboll[i].mean - lambda2 * myboll[i].std; double upper1Previous = myboll[i - 1].mean + lambda1 * myboll[i - 1].std; double lower1Previous = myboll[i - 1].mean - lambda1 * myboll[i - 1].std; double middlePrevious = myboll[i - 1].mean; double upper2Previous = myboll[i - 1].mean + lambda2 * myboll[i - 1].std; double lower2Previous = myboll[i - 1].mean - lambda2 * myboll[i - 1].std; if (z[i] > lower1 && z[i - 1] <= lower1Previous && z[i] < middle) { signal[i] = 1; } else if (z[i] > middle && z[i - 1] <= middlePrevious && z[i] < upper1) { signal[i] = 2; } else if (z[i] > upper1 && z[i - 1] <= upper1Previous && z[i] < upper2) { signal[i] = 3; } else if (z[i] < lower1 && z[i - 1] >= lower1Previous && z[i] > lower2) { signal[i] = -1; } else if (z[i] < middle && z[i - 1] >= middlePrevious && z[i] > lower1) { signal[i] = -2; } else if (z[i] < upper1 && z[i - 1] >= upper1Previous && z[i] > middle) { signal[i] = -3; } else if (z[i] > upper2 && z[i - 1] <= upper2Previous) { signal[i] = 4; } else if (z[i] < lower2 && z[i - 1] >= lower2Previous) { signal[i] = -4; } else { signal[i] = 0; } } //for (int i = duration+1; i < length; i++) //{ // if (myboll[i - 1] == null || myboll[i - 1].std == 0) // { // signal[i - 1] = 0; // continue; // } // if (underlyingDaily1[i].TradeStatus != "交易" || underlyingDaily2[i].TradeStatus != "交易") // { // signal[i] = signal[i - 1]; // continue; // } // int j = i - duration; // //上穿下轨1 // if (myboll2[j-1].area<=-2 && myboll2[j].area==-1) // { // double ratio = 0; // for (int k = j-1; k >j-6; k--) // { // if (myboll2[k].area<=-2) // { // ratio += 1; // } // } // ratio = ratio / 6; // if (ratio<0.5) // { // signal[i] = 1; // } // } // //上穿中轨 // else if (myboll2[j-1].area==-1 && myboll2[j].area==1) // { // signal[i] = 2; // } // //上穿上轨1 // else if (myboll2[j - 1].area == 1 && myboll2[j].area == 3) // { // signal[i] = 3; // } // //下穿下轨1 // else if (myboll2[j - 1].area == -1 && myboll2[j].area == -3) // { // signal[i] = -1; // } // //下穿中轨 // else if (myboll2[j - 1].area == 1 && myboll2[j].area == -1) // { // signal[i] = -2; // } // //下穿上轨1 // else if (myboll2[j - 1].area >= 2 && myboll2[j].area == 1) // { // double ratio = 0; // for (int k = j - 1; k > j - 6; k--) // { // if (myboll2[k].area >=2) // { // ratio += 1; // } // } // ratio = ratio / 6; // if (ratio < 0.5) // { // signal[i] = -3; // } // } // //上穿上轨2 // else if (myboll2[j - 1].area == 3 && myboll2[j].area == 5) // { // signal[i] = 4; // } // //下穿下轨2 // else if (myboll2[j - 1].area == -3 && myboll2[j].area == -5) // { // signal[i] = -4; // } // else // { // signal[i] = 0; // } //} for (int i = 0; i < length; i++) { var signal0 = new signalWithTime(); signal0.signal = signal[i]; signal0.time = tradedays[i].Date; signalList.Add(signal0); } List <OneByOneTransaction> data = new List <OneByOneTransaction>(); List <netvalueDaily> netvalueList = new List <netvalueDaily>(); bollingerBrand1(underlyingDaily1, underlyingDaily2, signal, duration, myboll2, ref data, ref netvalueList); double sharpe = Utilities.strategyPerformance.sharpeRatioByDailyNetValue(netvalueList.Select(s => s.netvalue).ToList()); List <OneByOneTransaction> orderedData = data.OrderByDescending(s => Math.Abs(s.closePrice - s.openPrice)).ToList(); var dt2 = DataTableExtension.ToDataTable(netvalueList); DataTableExtension.SaveCSV(dt2, "E:\\result\\bollinger\\nv.csv"); var dt3 = DataTableExtension.ToDataTable(data); DataTableExtension.SaveCSV(dt3, "E:\\result\\bollinger\\transaction.csv"); }
//计算从开始日期到结束日期的对冲成本 private double deltaHedgePerDate(DateTime startDate, DateTime endDate, Dictionary <DateTime, double> vol) { double option = 0; var tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); int deltaIndex = 220; //计算历史波动率参数 string hedgeCode = ""; double deltaNow = 0; double pnl = 0; double cash = 0; //按第一天的开盘价确定期初价格和行权价 var stock = stockDailyRepo.GetStockTransactionWithRedis(indexCode, startDate, endDate); double startPrice = stock[0].Open; double strike = startPrice; foreach (var date in tradedays) { //获取当日期货合约代码 var list = getSpecialFutureList(date); //获取当日收盘前标的价格 // var index = stockMinutelyRepo.GetStockTransactionWithRedis(indexCode, date, date); var index = allData[date][indexCode]; var indexPrice = index[deltaIndex].Close; double duration = (DateUtils.GetSpanOfTradeDays(date, endDate) + 1 / 12) / 252.0; //按标的计算收盘前delta值 double deltaTarget = ImpliedVolatilityExtension.ComputeOptionDelta(strike, duration, 0.04, 0, "认沽", vol[date], indexPrice); //对冲未开仓进行开仓 if (hedgeCode == "") { hedgeCode = list.Last().Value.code; double futurePrice = allData[date][hedgeCode][deltaIndex + 1].Close; cash += -futurePrice * deltaTarget; deltaNow = deltaTarget; } //如果对冲的合约快到期时,进行移仓操作,移仓到季月合约 if (list.ContainsKey(hedgeCode) && list[hedgeCode].expireDate.Date.AddDays(-7) <= date.Date) { double futurePriceFront = allData[date][hedgeCode][deltaIndex + 1].Close; hedgeCode = list.Last().Value.code; double futurePriceNext = allData[date][hedgeCode][deltaIndex + 1].Close; cash += futurePriceFront * deltaNow - futurePriceNext * deltaTarget; deltaNow = deltaTarget; } else if (list.ContainsKey(hedgeCode)) //对冲的合约未到期,继续对冲 { double futurePrice = allData[date][hedgeCode][deltaIndex + 1].Close; cash += -futurePrice * (deltaTarget - deltaNow); deltaNow = deltaTarget; } //错误情况 if (list.ContainsKey(hedgeCode) == false && hedgeCode != "") { throw new ArgumentOutOfRangeException("对冲选取错误!!"); } } //计算最后一天的PNL=cash+期货值的钱+付出去的期权收益 var lastDate = tradedays.Last(); double futureLastPrice = allData[lastDate][hedgeCode][239].Close; double indexLastPrice = stock.Last().Close; pnl = -(cash + deltaNow * futureLastPrice - Math.Max(startPrice - indexLastPrice, 0)); option = pnl / startPrice; return(option); }
public void compute(DateTime startDate, DateTime endDate) { var tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取日线数据 var underlyingDaily1 = stockDailyRepo.GetStockTransactionWithRedis(code1, tradedays.First(), tradedays.Last()); var underlyingDaily2 = stockDailyRepo.GetStockTransactionWithRedis(code2, tradedays.First(), tradedays.Last()); int duration = 15; double lambda1 = 2.4; double trailingParameter = 0.025; getParameter(tradedays, underlyingDaily1, underlyingDaily2, ref duration, ref lambda1, ref trailingParameter); int length = underlyingDaily1.Count(); double[] y = new double[length]; double[] x = new double[length]; double[] z = new double[length]; double[] alphaList = new double[length]; double[] betaList = new double[length]; double[] cointegrationSequence = new double[length]; //向上穿越下轨1为1,向上穿越中轨为2,向上穿越上轨1为3, //向下穿越下轨1位-1,向下穿越中轨为-2,向下穿越上轨1为-3, //向上穿越上轨2为4,向下穿越下轨2为-4,其他为0 double[] signal = new double[length]; List <signalWithTime> signalList = new List <signalWithTime>(); double[] longsignal = new double[length]; double[] shortsignal = new double[length]; int duration1 = 1000000; double lambda2 = 2.1; double y0 = underlyingDaily1[0].Close * underlyingDaily1[0].AdjFactor; double x0 = underlyingDaily2[0].Close * underlyingDaily2[0].AdjFactor; for (int i = 0; i < tradedays.Count(); i++) { if ((i - duration1) >= 0) { y[i] = underlyingDaily1[i].Close * underlyingDaily1[i].AdjFactor / (underlyingDaily1[i - duration1].Close * underlyingDaily1[i - duration1].AdjFactor); x[i] = underlyingDaily2[i].Close * underlyingDaily2[i].AdjFactor / (underlyingDaily2[i - duration1].Close * underlyingDaily2[i - duration1].AdjFactor); } else { y[i] = underlyingDaily1[i].Close * underlyingDaily1[i].AdjFactor / y0; x[i] = underlyingDaily2[i].Close * underlyingDaily2[i].AdjFactor / x0; } z[i] = Math.Log(y[i] / x[i]); } //计算x,y收益率的相关性 double[] yy = new double[length - 1]; double[] xx = new double[length - 1]; for (int i = 1; i < length; i++) { yy[i - 1] = y[i] / y[i - 1] - 1; xx[i - 1] = x[i] / x[i - 1] - 1; } double corr = MathUtility.correlation(y, x); Console.WriteLine("corr:{0}", corr); var myboll = getBollingerBand(z, duration); double scale = 0.1; List <BollingerBandwithPrice> myboll2 = new List <BollingerBandwithPrice>(); for (int i = 0; i < myboll.Length; i++) { if (myboll[i] != null) { BollingerBandwithPrice boll0 = new BollingerBandwithPrice(); boll0.mean = myboll[i].mean; boll0.std = myboll[i].std; boll0.price = z[i]; boll0.time = tradedays[i].Date; boll0.low2 = boll0.mean - lambda2 * boll0.std; boll0.low1 = boll0.mean - lambda1 * boll0.std; boll0.up2 = boll0.mean + lambda2 * boll0.std; boll0.up1 = boll0.mean + lambda1 * boll0.std; if (Math.Abs(boll0.price - boll0.mean) <= scale * boll0.std) { boll0.area = 0; } else if (boll0.price - boll0.mean > scale * boll0.std && boll0.price - boll0.up1 < -scale * boll0.std) { boll0.area = 1; } else if (Math.Abs(boll0.price - boll0.up1) <= scale * boll0.std) { boll0.area = 2; } else if (boll0.price - boll0.up1 > scale * boll0.std && boll0.price - boll0.up2 < -scale * boll0.std) { boll0.area = 3; } else if (Math.Abs(boll0.price - boll0.up2) <= scale * boll0.std) { boll0.area = 4; } else if (boll0.price - boll0.up2 > scale * boll0.std) { boll0.area = 5; } else if (boll0.price - boll0.mean < -scale * boll0.std && boll0.price - boll0.low1 > scale * boll0.std) { boll0.area = -1; } else if (Math.Abs(boll0.price - boll0.low1) <= scale * boll0.std) { boll0.area = -2; } else if (boll0.price - boll0.low1 < -scale * boll0.std && boll0.price - boll0.low2 > scale * boll0.std) { boll0.area = -3; } else if (Math.Abs(boll0.price - boll0.low2) <= scale * boll0.std) { boll0.area = -4; } else if (boll0.price - boll0.low2 < -scale * boll0.std) { boll0.area = -5; } myboll2.Add(boll0); } } var dt = DataTableExtension.ToDataTable(myboll2); DataTableExtension.SaveCSV(dt, "E:\\result\\bollinger\\boll.csv"); for (int i = 1; i < length; i++) { if (myboll[i - 1] == null || myboll[i - 1].std == 0) { signal[i - 1] = 0; continue; } if (underlyingDaily1[i].TradeStatus != "交易" || underlyingDaily2[i].TradeStatus != "交易") { signal[i] = 0; continue; } double upper1 = myboll[i].mean + lambda1 * myboll[i].std; double lower1 = myboll[i].mean - lambda1 * myboll[i].std; double middle = myboll[i].mean; double upper2 = myboll[i].mean + lambda2 * myboll[i].std; double lower2 = myboll[i].mean - lambda2 * myboll[i].std; double upper1Previous = myboll[i - 1].mean + lambda1 * myboll[i - 1].std; double lower1Previous = myboll[i - 1].mean - lambda1 * myboll[i - 1].std; double middlePrevious = myboll[i - 1].mean; double upper2Previous = myboll[i - 1].mean + lambda2 * myboll[i - 1].std; double lower2Previous = myboll[i - 1].mean - lambda2 * myboll[i - 1].std; if (z[i] > lower1 && z[i - 1] <= lower1Previous && z[i] < middle) { signal[i] = 1; } else if (z[i] > middle && z[i - 1] <= middlePrevious && z[i] < upper1) { signal[i] = 2; } else if (z[i] > upper1 && z[i - 1] <= upper1Previous && z[i] < upper2) { signal[i] = 3; } else if (z[i] < lower1 && z[i - 1] >= lower1Previous && z[i] > lower2) { signal[i] = -1; } else if (z[i] < middle && z[i - 1] >= middlePrevious && z[i] > lower1) { signal[i] = -2; } else if (z[i] < upper1 && z[i - 1] >= upper1Previous && z[i] > middle) { signal[i] = -3; } else if (z[i] > upper2 && z[i - 1] <= upper2Previous) { signal[i] = 4; } else if (z[i] < lower2 && z[i - 1] >= lower2Previous) { signal[i] = -4; } else { signal[i] = 0; } } for (int i = 0; i < length; i++) { var signal0 = new signalWithTime(); signal0.signal = signal[i]; signal0.time = tradedays[i].Date; signalList.Add(signal0); } List <OneByOneTransaction> data = new List <OneByOneTransaction>(); List <netvalueDaily> netvalueList = new List <netvalueDaily>(); bollingerBrand1(underlyingDaily1, underlyingDaily2, signal, duration, myboll2, trailingParameter, ref data, ref netvalueList); double sharpe = Utilities.strategyPerformance.sharpeRatioByDailyNetValue(netvalueList.Select(s => s.netvalue).ToList()); List <OneByOneTransaction> orderedData = data.OrderByDescending(s => Math.Abs(s.closePrice - s.openPrice)).ToList(); var dt2 = DataTableExtension.ToDataTable(netvalueList); DataTableExtension.SaveCSV(dt2, "E:\\result\\bollinger\\nv.csv"); var dt3 = DataTableExtension.ToDataTable(data); DataTableExtension.SaveCSV(dt3, "E:\\result\\bollinger\\transaction.csv"); }
public void getMonitorData() { List <ConvertibleBondMonitor> recordList = new List <ConvertibleBondMonitor>(); DateTime endDate = DateTime.Now; if (endDate.TimeOfDay < new TimeSpan(16, 10, 00)) { endDate = DateTimeExtension.DateUtils.LatestTradeDay(endDate.AddDays(-1)); endDate = endDate.Date; } DateTime startDate = endDate.AddDays(-60).Date; //获取交易日信息 this.tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取可转债信息 this.bondInfo = GetConvertibleBondInfos(endDate); foreach (var item in bondInfo)//每个可转债进行遍历 { DateTime startTime = startDate; DateTime endTime = endDate; if (startTime < item.startDate) { startTime = item.startDate; } if (item.startDate > endDate) { continue; } //获取债券的信息 var bondInfo = getBondDailyInfo(item, endDate); //获取股票的日线数据 var stockData = stockDailyRepo.GetStockTransactionWithRedis(bondInfo.stockCode, startTime.AddDays(-30), endDate); //获取债券的日线数据 var bondData = stockDailyRepo.GetStockTransactionWithRedis(bondInfo.code, startTime, endDate); //找到股票第一个不涨停股票的数据 var nonCeilingStockData = getStartDate(stockData); var lastStockData = stockData[stockData.Count() - 1]; //找到可转债第一个不涨停的数据 var nonCeilingBondData = getBondDataByDate(bondData, nonCeilingStockData.DateTime); //计算正股波动率 double volatility = getStockVolatility(stockData); var nonCeilingOptionPrice = getEstimateOptionPrice(nonCeilingStockData.DateTime, bondInfo, volatility, nonCeilingStockData.Close * nonCeilingStockData.AdjFactor / lastStockData.AdjFactor); double stockCeilPrice = Math.Round(lastStockData.Close * 1.1, 2); var ceilingOptionPrice = getEstimateOptionPrice(nonCeilingStockData.DateTime, bondInfo, volatility, stockCeilPrice); double estimateBondPrice = nonCeilingBondData.Close + 100 / bondInfo.conversionPrice * (ceilingOptionPrice - nonCeilingOptionPrice); double delta = 1; double estimateBondPrice2 = nonCeilingBondData.Close + (stockCeilPrice - nonCeilingStockData.Close) * delta * 100 / bondInfo.conversionPrice; ConvertibleBondMonitor record = new ConvertibleBondMonitor(); record.ceilingStockPrice = stockCeilPrice; record.code = bondInfo.code; record.conversionPrice = bondInfo.conversionPrice; record.estimateCeilingBondPrice = estimateBondPrice; record.name = bondInfo.name; record.nonCeilingBondPrice = nonCeilingBondData.Close; record.nonCeilingStockPrice = nonCeilingStockData.Close; record.stockCode = bondInfo.stockCode; record.updateTime = endDate; record.estimateCeilingBondPrice2 = estimateBondPrice2; recordList.Add(record); } var dt = DataTableExtension.ToDataTable(recordList); string dateStr = endDate.ToString("yyyy-MM-dd"); string str = string.Format("E:\\result\\bond\\convertibleBond{0}.csv", dateStr); DataTableExtension.SaveCSV(dt, str); }
public void compute(DateTime startDate, DateTime endDate) { var tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); List <ETFConsitituent> etfInfo = new List <ETFConsitituent>(); List <double> amountList = getAmount(code, startDate, endDate); double[] arbitraryPurchase = new double[28802]; double[] arbitraryRedeem = new double[28802]; bool[] isNan = new bool[28802]; for (int i = 0; i < 28802; i++) { isNan[i] = true; } for (int k = 0; k < tradedays.Count(); k++) { DateTime date = tradedays[k]; etfInfo = getETFInfo(code, date); foreach (var item in etfInfo) { if (item.cash_substitution_mark == "必须") { for (int i = 0; i < 28802; i++) { if (isNan[i] == true) { arbitraryPurchase[i] += -item.substitution_amout; } } } else { var stockData = stockRepo.GetStockTransaction(item.code, date, date.AddHours(17)); if (stockData != null && stockData.Count > 0) { var stock = DataTimeStampExtension.ModifyStockTickData(stockData); for (int i = 0; i < stock.Count(); i++) { if (isNan[i] == true && stock[i] != null && stock[i].AskV1 != 0 && stock[i].BidV1 != 0) { arbitraryPurchase[i] += -item.volume * stock[i].Ask1; //arbitraryRedeem[i] += item.volume * stock[i].Bid1; } if (stock[i] == null) { isNan[i] = false; arbitraryPurchase[i] = 0; //arbitraryRedeem[i] = 0; } } } else { if (item.cash_substitution_mark == "禁止") { for (int i = 0; i < 28802; i++) { arbitraryPurchase[i] = 0; isNan[i] = false; } } else { var stock = stockDailyRepo.GetStockTransactionWithRedis(item.code, date, date); for (int i = 0; i < 28802; i++) { if (isNan[i] == true) { arbitraryPurchase[i] += -item.volume * stock[stock.Count() - 1].Close * (1 + item.premium_ratio / 100.0); } } } } } } var etf = DataTimeStampExtension.ModifyStockTickData(stockRepo.GetStockTransaction(code, date, date.AddHours(17))); for (int i = 0; i < etf.Count(); i++) { if (isNan[i] == true && etf[i] != null && etf[i].AskV1 != 0 && etf[i].BidV1 != 0) { arbitraryPurchase[i] += amountList[k] * etf[i].Bid1; // arbitraryRedeem[i] += -amountList[k] * etf[i].Ask1; } if (etf[i] == null) { isNan[i] = false; arbitraryPurchase[i] = 0; //arbitraryRedeem[i] = 0; } } Console.WriteLine("today {0} change {1}", date, arbitraryPurchase.Max()); } }
public void compute(DateTime startDate, DateTime endDate) { var tradedays = dateRepo.GetStockTransactionDate(startDate, endDate); //获取日线数据 var underlyingDaily = stockDailyRepo.GetStockTransactionWithRedis(code, tradedays.First(), tradedays.Last()); //获取分钟线数据 foreach (var date in tradedays) { var underlyingToday = stockMinutelyRepo.GetStockTransactionWithRedis(code, date, date); underlying.Add(date, underlyingToday); minutes = underlyingToday.Count(); underlyingAll.AddRange(underlyingToday); } double bestSharpe = 0; double bestf1 = 0.64; double bestf2 = 0.48; double bestf3 = 0.08; double step = 0.04; //for (int i = 1; i <= 1/step; i=i+1) //{ // for (int j = 1; j <= 1 / step; j = j + 1) // { // for (int k = 1; k <= 1 / step; k = k + 1) // { // double f1 = i * step; // double f2 = j * step; // double f3 = k * step; // double[] netvalue0 = getPerformance(startDate, endDate, tradedays, underlyingDaily, f1, f2, f3); // var nv = getNetValueCurveDaily(getNetValueDaily(underlyingAll, netvalue0)); // double sharpe = Utilities.strategyPerformance.sharpeRatioByDailyNetValue(nv); // if (sharpe>bestSharpe) // { // bestf1 = f1; // bestf2 = f2; // bestf3 = f3; // bestSharpe = sharpe; // Console.WriteLine("Best parameters:f1={0}, f2={1}, f3={2}, sharpe={3}", f1, f2, f3, sharpe); // } // } // } //} double[] netvalue = getPerformance(startDate, endDate, tradedays, underlyingDaily, bestf1, bestf2, bestf3); var nvDaily = getNetValueDaily(underlyingAll, netvalue); DataTableExtension.SaveCSV(DataTableExtension.ToDataTable <netvalueDaily>(nvDaily), "E:\\result\\break\\netvalue.csv"); statisticDataOfTransaction(transactionData, tradedays); double mean = 0; double num = 0; for (int i = -5; i <= 5; i = i + 1) { for (int j = -5; j <= 5; j = j + 1) { for (int k = -5; k <= 5; k = k + 1) { double f1 = bestf1 + i * step * 0.25; double f2 = bestf2 + j * step * 0.25; double f3 = bestf3 + k * step * 0.25; if (f1 <= 0 || f2 <= 0 || f3 <= 0) { continue; } double[] netvalue0 = getPerformance(startDate, endDate, tradedays, underlyingDaily, f1, f2, f3); var nv = getNetValueCurveDaily(getNetValueDaily(underlyingAll, netvalue0)); double sharpe = Utilities.strategyPerformance.sharpeRatioByDailyNetValue(nv); mean += sharpe; num += 1; Console.WriteLine("parameters around best:f1={0}, f2={1}, f3={2}, sharpe={3}", f1, f2, f3, sharpe); } } } Console.WriteLine("mean:{0}", mean / num); }
public List <StockBonusEstimate> getIndexBonus(DateTime date, string index, List <indexStockInfo> indexStockList) { var codeList = getIndexStocks(date, index); var bonusDic = getStockBonusList(codeList, date); var bonusDicLastYear = getStockBonusListByYear(bonusDic, date.Year - 1); var bonusDicThisYear = getStockBonusListByYear(bonusDic, date.Year); var bonusPlanDic = getStockBonusPlan(codeList, date); var epsDic = getStockEPSRatio(codeList, date); //获取当前日期 var now = DateTime.Now.Date; double indexClose = stockDailyRepo.GetStockTransactionWithRedis(index, date, date)[0].Close; DateTime lastYearEnd = new DateTime(date.Year - 1, 12, 31); DateTime thisYearMid = new DateTime(date.Year, 6, 30); List <StockBonusEstimate> estimateList = new List <StockBonusEstimate>(); foreach (var code in codeList) { StockBonusEstimate estimate = new StockBonusEstimate(); double epsRatio = 0; var bonusLastYear = new List <StockBonusInfo>(); var bonusThisYear = new List <StockBonusInfo>(); var bonusPlan = new List <StockBonusPlan>(); int lastYearNumber = 0; int thisYearNumber = 0; if (epsDic.ContainsKey(code)) { epsRatio = epsDic[code]; } if (bonusDicLastYear.ContainsKey(code)) { bonusLastYear = bonusDicLastYear[code]; lastYearNumber = bonusLastYear.Count(); } if (bonusDicThisYear.ContainsKey(code)) { bonusThisYear = bonusDicThisYear[code]; thisYearNumber = bonusThisYear.Count(); } if (bonusPlanDic.ContainsKey(code)) { bonusPlan = bonusPlanDic[code]; } //去年无分红 if (lastYearNumber == 0) { //按分红公告统计 foreach (var item in bonusThisYear) { estimate = new StockBonusEstimate(); estimate.code = item.code; estimate.secName = item.secName; estimate.dividend = item.cashPayoutRatio; estimate.dividendDate = item.exDividendDate; estimate.status = "去年无分红;分红公告明确"; estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); if (estimate.dividendDate <= now) { estimate.status += "已分红"; } estimateList.Add(estimate); } //分红无公告的,按分红预案统计 if (thisYearNumber == 0 && bonusPlan.Count > 0) { foreach (var item in bonusPlan) { estimate = new StockBonusEstimate(); estimate.code = item.code; estimate.secName = item.name; estimate.dividend = item.dividend; estimate.status = "去年无分红;分红预案明确;分红日期未知"; estimate.dividendDate = new DateTime(date.Year, 12, 31); estimate.shareRegisterDate = new DateTime(date.Year, 12, 31); estimateList.Add(estimate); } } //既没有分红公告也没有分红预案的,按不分红统计 } //去年分红一次 else if (lastYearNumber == 1) { //先按分红公告统计 foreach (var item in bonusThisYear) { estimate = new StockBonusEstimate(); estimate.code = item.code; estimate.secName = item.secName; estimate.dividend = item.cashPayoutRatio; estimate.dividendDate = item.exDividendDate; estimate.status = "去年分红1次;分红公告明确"; estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); if (estimate.dividendDate <= now) { estimate.status += "已分红"; } estimateList.Add(estimate); } //有分红公告分红1次的和分红预案比较是否有遗漏的,分红两次的不需要比较 if (thisYearNumber == 1 && bonusPlan.Count > 0) { //需要吗? } //没有分红公告但是有分红预案的公告,按照分红预案的信息 if (thisYearNumber == 0 && bonusPlan.Count > 0) { foreach (var item in bonusPlan) { estimate = new StockBonusEstimate(); estimate.code = item.code; estimate.secName = item.name; estimate.dividend = item.dividend; estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[0].exDividendDate.AddYears(+1)); estimate.status = "去年分红1次;分红预案明确;分红日期未知"; estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); if (estimate.dividendDate < now) { estimate.dividendDate = new DateTime(date.Year, 12, 31); estimate.status = estimate.status + ";对应日期已过分红日期未知"; estimate.shareRegisterDate = new DateTime(date.Year, 12, 31); } estimateList.Add(estimate); } } //没有分红公告也没有分红预案,按照EPS和去年分红信息来估计 if (thisYearNumber == 0 && bonusPlan.Count == 0 && epsRatio > 0) { estimate = new StockBonusEstimate(); estimate.code = bonusLastYear[0].code; estimate.secName = bonusLastYear[0].secName; estimate.dividend = bonusLastYear[0].cashPayoutRatio * epsRatio; estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[0].exDividendDate.AddYears(+1)); estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); estimate.status = "去年分红1次;无公告无预案按eps估计"; if (estimate.dividendDate < now) { estimate.dividendDate = new DateTime(date.Year, 12, 31); estimate.status = estimate.status + ";对应日期已过分红日期未知"; estimate.shareRegisterDate = new DateTime(date.Year, 12, 31); } estimateList.Add(estimate); } } //去年分红两次 else if (lastYearNumber >= 2) { int thisyear = 0; //先按分红公告统计 foreach (var item in bonusThisYear) { estimate = new StockBonusEstimate(); estimate.code = item.code; estimate.secName = item.secName; estimate.dividend = item.cashPayoutRatio; estimate.dividendDate = item.exDividendDate; estimate.status = "去年分红2次;分红公告明确"; estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); if (estimate.dividendDate <= now) { estimate.status += "已分红"; } estimateList.Add(estimate); thisyear += 1; } if (bonusThisYear.Count == 0) { foreach (var item in bonusPlan) { estimate = new StockBonusEstimate(); estimate.code = item.code; estimate.secName = item.name; estimate.dividend = item.dividend; estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[0].exDividendDate.AddYears(+1)); estimate.status = "去年分红2次;分红预案明确;分红时间未知"; if (thisyear == 0) { estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[0].exDividendDate.AddYears(+1)); if (estimate.dividendDate < now) { estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[1].exDividendDate.AddYears(+1)); estimate.status = estimate.status + ":去年对应的第1次分红日期已过"; } estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); } else { estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[1].exDividendDate.AddYears(+1)); estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); } if (estimate.dividendDate < now) { estimate.dividendDate = new DateTime(date.Year, 12, 31); estimate.status = estimate.status + ";对应日期已过分红日期未知"; estimate.shareRegisterDate = new DateTime(date.Year, 12, 31); } estimateList.Add(estimate); thisyear += 1; } } else if (bonusThisYear.Count == 1) { foreach (var item in bonusPlan) { estimate = new StockBonusEstimate(); estimate.code = item.code; estimate.secName = item.name; estimate.dividend = item.dividend; estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[0].exDividendDate.AddYears(+1)); estimate.status = "去年分红2次;分红预案明确;分红时间未明确"; estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); if (estimate.dividendDate < now) { estimate.dividendDate = new DateTime(date.Year, 12, 31); estimate.status = estimate.status + ";对应日期已过分红日期未知"; estimate.shareRegisterDate = new DateTime(date.Year, 12, 31); } estimateList.Add(estimate); thisyear += 1; } } else if (bonusThisYear.Count == 2) { //搞定 } //利用去年分红数据估计 if (thisyear == 0 && epsRatio > 0) { estimate = new StockBonusEstimate(); estimate.code = bonusLastYear[0].code; estimate.secName = bonusLastYear[0].secName; estimate.dividend = bonusLastYear[0].cashPayoutRatio * epsRatio; estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[0].exDividendDate.AddYears(+1)); estimate.status = "去年分红2次;按eps估计第1次分红"; estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); if (estimate.dividendDate < now) { estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[1].exDividendDate.AddYears(+1)); estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); estimate.status = estimate.status + ":去年对应的第1次分红日期已过"; } if (estimate.dividendDate < now) { estimate.dividendDate = new DateTime(date.Year, 12, 31); estimate.status = estimate.status + ";对应日期已过分红日期未知"; estimate.shareRegisterDate = new DateTime(date.Year, 12, 31); } estimateList.Add(estimate); estimate = new StockBonusEstimate(); estimate.code = bonusLastYear[1].code; estimate.secName = bonusLastYear[1].secName; estimate.dividend = bonusLastYear[1].cashPayoutRatio * epsRatio; estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[1].exDividendDate.AddYears(+1)); estimate.status = "去年分红2次;按eps估计第2次分红"; estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); if (estimate.dividendDate < now) { estimate.dividendDate = new DateTime(date.Year, 12, 31); estimate.status = estimate.status + ";对应日期已过分红日期未知"; estimate.shareRegisterDate = new DateTime(date.Year, 12, 31); } estimateList.Add(estimate); } else if (thisyear == 1 && epsRatio > 0) { estimate = new StockBonusEstimate(); estimate.code = bonusLastYear[1].code; estimate.secName = bonusLastYear[1].secName; estimate.dividend = bonusLastYear[1].cashPayoutRatio * epsRatio; estimate.dividendDate = DateTimeExtension.DateUtils.PreviousOrCurrentTradeDay(bonusLastYear[1].exDividendDate.AddYears(+1)); estimate.status = "去年分红2次;按eps估计第2次分红"; estimate.shareRegisterDate = DateTimeExtension.DateUtils.LatestTradeDay(estimate.dividendDate.AddDays(-1)); if (estimate.dividendDate < now) { estimate.dividendDate = new DateTime(date.Year, 12, 31); estimate.status = estimate.status + ";对应日期已过分红日期未知"; estimate.shareRegisterDate = new DateTime(date.Year, 12, 31); } estimateList.Add(estimate); } } } //计算具体的指数点 foreach (var item in estimateList) { foreach (var stock in indexStockList) { if (item.code == stock.code) { double points = stock.weight * item.dividend / stock.close * indexClose * 0.01; item.points = points; } } } return(estimateList); }