/// <summary> /// 将数据以csv文件的形式保存到CacheData文件夹下的预定路径 /// </summary> /// <param name="data">要保存的数据</param> /// <param name="appendMode">是否为追加的文件尾部模式,否则是覆盖模式</param> public virtual void saveToLocalCsv(IList <T> data, bool appendMode = false) { if (data == null) { log.Error("没有任何内容可以保存到csv!"); return; } foreach (var item in data) { var dt = DataTableUtils.ToDataTableOneRowOnly(item); string path = _buildCacheDataFilePath(item.code, item.time, null); // if (File.Exists(path)==false) { try { var s = (File.Exists(path)) ? "覆盖" : "新增"; CsvFileUtils.WriteToCsvFile(path, dt, appendMode); log.Debug("文件已{0}:{1}. 共{2}行数据.", s, path, data.Count); } catch (Exception e) { log.Error(e, "保存到本地csv文件失败!({0})", path); } } } }
public void saveToLocalFile(List <positionShot> optionMinuteData, string path) { var dt = DataTableUtils.ToDataTable(optionMinuteData); CsvFileUtils.WriteToCsvFile(path, dt); Console.WriteLine("{0} saved!", path); }
public static void recordToCsv <T>(IList <T> data, string tag, string type, string parameters = "", string performance = "") { var fullPath = ConfigurationManager.AppSettings["RootPath"] + ConfigurationManager.AppSettings["CacheData.ResultPath"] + ConfigurationManager.AppSettings["CacheData.StrategyPath"]; var dateStr = Kit.ToInt_yyyyMMdd(DateTime.Now).ToString(); fullPath = ResultPathUtil.GetLocalPath(fullPath, tag, dateStr, type, parameters, performance); var dt = DataTableUtils.ToDataTable(data); CsvFileUtils.WriteToCsvFile(fullPath, dt); }
public void CorrOf100and500() { List <StockMinute> all100 = new List <StockMinute>(); List <StockMinute> all500 = new List <StockMinute>(); List <CorrStatic> corrList = new List <CorrStatic>(); for (int i = 0; i < tradeDays.Count(); i++) { var now = tradeDays[i]; var index100 = Platforms.container.Resolve <StockMinuteRepository>().fetchFromLocalCsvOrWindAndSave("399330.SZ", now); var index500 = Platforms.container.Resolve <StockMinuteRepository>().fetchFromLocalCsvOrWindAndSave("000905.SZ", now); all100.AddRange(index100); all500.AddRange(index500); } for (int i = 0; i < tradeDays.Count() - period; i++) { DateTime start = tradeDays[i]; DateTime end = tradeDays[i + period]; int startIndex = i * 240; int endIndex = (i + period) * 240 - 1; CorrStatic corr = new CorrStatic() { start = start, end = end, underlying1 = "399330.SZ", underlying2 = "000905.SZ", corr = 0 }; List <double> underlying1 = new List <double>(); List <double> underlying2 = new List <double>(); for (int j = startIndex; j < endIndex; j++) { underlying1.Add(all100[j].close); underlying2.Add(all500[j].close); } corr.corr = getCorr(underlying1, underlying2); corrList.Add(corr); } var dt = DataTableUtils.ToDataTable(corrList); string path = "d:\\corr0.csv"; try { var s = (File.Exists(path)) ? "覆盖" : "新增"; CsvFileUtils.WriteToCsvFile(path, dt); } catch (Exception e) { } }
/// <summary> /// 将数据以csv文件的形式保存到CacheData文件夹下的预定路径 /// </summary> /// <param name="data">要保存的数据</param> /// <param name="path">读写文件路径</param> /// <param name="appendMode">是否为追加的文件尾部模式,否则是覆盖模式</param> public virtual void saveToLocalCsv(string path, IList <T> data, bool appendMode = false) { if (data == null) { log.Error("没有任何内容可以保存到csv!"); return; } var dt = DataTableUtils.ToDataTable(data); try { var s = (File.Exists(path)) ? "覆盖" : "新增"; CsvFileUtils.WriteToCsvFile(path, dt, appendMode); log.Debug("文件已{0}:{1}. 共{2}行数据.", s, path, data.Count); } catch (Exception e) { log.Error(e, "保存到本地csv文件失败!({0})", path); } }
public void compute() { List <HistoricalVol> volList = new List <HistoricalVol>(); List <DateTime> tradeDays = DateUtils.GetTradeDays(today.AddDays(-360), today.AddDays(-1)); for (int i = 0; i < tradeDays.Count(); i++) { DateTime time = tradeDays[i]; HistoricalVol vol = new HistoricalVol(); vol.time = time; volList.Add(vol); } computeVol("M1705.DCE", period1, ref volList); computeVol("M1705.DCE", period2, ref volList); computeVol("M1707.DCE", period1, ref volList); computeVol("M1707.DCE", period2, ref volList); computeVol("M1708.DCE", period1, ref volList); computeVol("M1708.DCE", period2, ref volList); computeVol("M1709.DCE", period1, ref volList); computeVol("M1709.DCE", period2, ref volList); computeVol("M1711.DCE", period1, ref volList); computeVol("M1711.DCE", period2, ref volList); computeVol("M1712.DCE", period1, ref volList); computeVol("M1712.DCE", period2, ref volList); computeVol("M1801.DCE", period1, ref volList); computeVol("M1801.DCE", period2, ref volList); computeVol("M1803.DCE", period1, ref volList); computeVol("M1803.DCE", period2, ref volList); var dt = DataTableUtils.ToDataTable(volList); string path = "historicalVol.csv"; try { var s = (File.Exists(path)) ? "覆盖" : "新增"; CsvFileUtils.WriteToCsvFile(path, dt); } catch (Exception e) { } }
/// <summary> /// 将数据以csv文件的形式保存到CacheData文件夹下的预定路径 /// </summary> public void saveToLocalCsvFile(IList <T> data, string path, bool appendMode = false, string tag = null) { if (tag == null) { tag = typeof(T).Name; } if (data == null || data.Count == 0) { log.Warn("没有任何内容可以保存到csv!"); return; } var dt = DataTableUtils.ToDataTable(data, toCsvColumnsFromEntity, toCsvRowValuesFromEntity); try { var s = (File.Exists(path)) ? "覆盖" : "新增"; CsvFileUtils.WriteToCsvFile(path, dt); log.Info("文件已{0}:{1} ", s, path); } catch (Exception e) { log.Error(e, "保存到本地csv文件失败!"); } }
/// <summary> /// 策略回测部分,期权时间价值策略 /// 在日循环上判断(1)选择操作标的(2)是否开平仓,在分钟循环上进行具体操作 /// 分钟上的操作:(1)开仓(2)到期平仓(3)调仓平值期权(4)止盈止损 /// (1)若直接开平仓,在开盘15分钟时进行操作(2)若判断止盈止损,在收盘15分钟时进行操作 /// </summary> public void compute() { log.Info("开始回测(回测期{0}到{1})", Kit.ToInt_yyyyMMdd(startdate), Kit.ToInt_yyyyMMdd(endDate)); var repo = Platforms.container.Resolve <OptionInfoRepository>(); var optionInfoList = repo.fetchFromLocalCsvOrWindAndSaveAndCache(1); Caches.put("OptionInfo", optionInfoList); List <DateTime> tradeDays = DateUtils.GetTradeDays(startdate, endDate); //var ETFDaily = Platforms.container.Resolve<StockDailyRepository>().fetchFromLocalCsvOrWindAndSave("510050.SH", Kit.ToDate(20150101),Kit.ToDate(20160731)); ///账户初始化 //初始化position SortedDictionary <DateTime, Dictionary <string, PositionsWithDetail> > positions = new SortedDictionary <DateTime, Dictionary <string, PositionsWithDetail> >(); //初始化Account信息 BasicAccount myAccount = new BasicAccount(); myAccount.totalAssets = initialCapital; myAccount.freeCash = myAccount.totalAssets; //记录历史账户信息 List <BasicAccount> accountHistory = new List <BasicAccount>(); ///回测循环 //回测循环--By Day foreach (var day in tradeDays) { //日内数据准备 Dictionary <string, List <KLine> > data = new Dictionary <string, List <KLine> >(); var list = OptionUtilities.getOptionListByDate(optionInfoList, Kit.ToInt_yyyyMMdd(day)); List <DateTime> endDate = OptionUtilities.getEndDateListByAscending(list); var ETFtoday = Platforms.container.Resolve <StockMinuteRepository>().fetchFromLocalCsvOrWindAndSave("510050.SH", day); data.Add("510050.SH", ETFtoday.Cast <KLine>().ToList()); foreach (var info in list) { string IHCode = OptionUtilities.getCorrespondingIHCode(info, Kit.ToInt_yyyyMMdd(day)); var repoOption = Platforms.container.Resolve <OptionMinuteRepository>(); var optionToday = repoOption.fetchFromLocalCsvOrWindAndSave(info.optionCode, day); data.Add(info.optionCode, optionToday.Cast <KLine>().ToList()); } int index = 0; //交易开关设置,控制day级的交易开关 bool tradingOn = true; //总交易开关 bool openingOn = true; //开仓开关 bool closingOn = true; //平仓开关 //是否为交割日 bool isExpiredDay = day.Equals(endDate[0]); //是否为回测最后一天 bool isLastDayOfBackTesting = day.Equals(endDate); //回测循环 -- By Minute //不允许在同一根1minBar上开平仓 while (index < 240) { int nextIndex = index + 1; DateTime now = TimeListUtility.IndexToMinuteDateTime(Kit.ToInt_yyyyMMdd(day), index); Dictionary <string, MinuteSignal> signal = new Dictionary <string, MinuteSignal>(); double etfPrice = ETFtoday[index].close; //按strike price与etf价格的接近程度排序 List <double> strikeTodayArr = OptionUtilities.getStrikeListByAscending(list).OrderBy(x => Math.Abs(x - etfPrice)).ToList(); try { /* * if (index != 225) * { * index = nextIndex; * continue; * } */ //持仓查询,先平后开 //若当前有持仓 且 允许平仓 //是否是空仓,若position中所有品种volum都为0,则说明是空仓 bool isEmptyPosition = positions.Count != 0 ? positions[positions.Keys.Last()].Values.Sum(x => Math.Abs(x.volume)) == 0 : true; if ((positions.Count != 0 && !isEmptyPosition) && tradingOn) { //平仓条件 //(1)若当天为交割日或回测结束日,平仓,且关闭开仓开关,次日才能开仓; //(2)若closingOn为false,平仓; //(3)检查持仓期权是否为平价期权,若否,清掉当前头寸并建立新的持仓; //-------------------------------------------------------------------- //(1)若当天为交割日或回测结束日,平仓,且关闭开仓开关,次日才能开仓; //(2)若closingOn为false,平仓; //取出当前持仓期权的strike double strikePriceOfPositions = optionInfoList[optionInfoList.FindIndex(a => a.optionCode == positions[positions.Keys.Last()].Values.First().code)].strike; bool isParPriceOption = strikePriceOfPositions == strikeTodayArr[0]; //-------------------------------------------------------------------- if (!isEmptyPosition && (isExpiredDay || isLastDayOfBackTesting || closingOn == false)) { //全部平仓 DateTime next = MinuteCloseAllPositonsWithSlip.closeAllPositions(data, ref positions, ref myAccount, now: now, slipPoint: slipPoint); //当天不可再开仓 openingOn = false; } //(3)检查持仓期权是否为平价期权,若否,清掉当前头寸并建立新的持仓; else if (!isEmptyPosition && !isParPriceOption) { //全部平仓 DateTime next = MinuteCloseAllPositonsWithSlip.closeAllPositions(data, ref positions, ref myAccount, now: now, slipPoint: slipPoint); //当天不可再开仓 openingOn = false; } } //若当前无持仓 且 允许开仓 //若当前为交割日,则不开仓 if (isExpiredDay == true) { openingOn = false; } else if ((positions.Count == 0 || isEmptyPosition) && openingOn && tradingOn) { //标的池构建 //选择目标期权品种放入标的池: //四个头寸(1)short当月平价认购(2)short当月平价认沽(3)long下月平价认购(4)long下月平价认沽 OptionInfo callCandidateFront = OptionUtilities.getSpecifiedOption(list, endDate[0], "认购", strikeTodayArr[0])[0]; OptionInfo putCandidateFront = OptionUtilities.getSpecifiedOption(list, endDate[0], "认沽", strikeTodayArr[0])[0]; OptionInfo callCandidateNext = OptionUtilities.getSpecifiedOption(list, endDate[1], "认购", strikeTodayArr[0])[0]; OptionInfo putCandidateNext = OptionUtilities.getSpecifiedOption(list, endDate[1], "认沽", strikeTodayArr[0])[0]; //检查四个标的strike是否相同,若相同则开仓,若不相同是,说明下月平价期权尚未挂出,则continue bool isSameStrike = callCandidateFront.strike == callCandidateFront.strike; //生成开仓信号 if (isSameStrike) { //查询可用资金 double nowFreeCash = myAccount.freeCash; //计算每个头寸的建仓量,原则:尽量使各头寸等金额 double openVolumeOfCallFront = Math.Floor(nowFreeCash / 4 / data[callCandidateFront.optionCode][index].close / optionContractTimes) * optionContractTimes; double openVolumeOfPutFront = Math.Floor(nowFreeCash / 4 / data[putCandidateFront.optionCode][index].close / optionContractTimes) * optionContractTimes; double openVolumeOfCallNext = Math.Floor(nowFreeCash / 4 / data[callCandidateNext.optionCode][index].close / optionContractTimes) * optionContractTimes; double openVolumeOfPutNext = Math.Floor(nowFreeCash / 4 / data[putCandidateNext.optionCode][index].close / optionContractTimes) * optionContractTimes; MinuteSignal callFront = new MinuteSignal() { code = callCandidateFront.optionCode, volume = -openVolumeOfCallFront, time = now, tradingVarieties = "option", price = data[callCandidateFront.optionCode][index].close, minuteIndex = index }; MinuteSignal putFront = new MinuteSignal() { code = putCandidateFront.optionCode, volume = -openVolumeOfPutFront, time = now, tradingVarieties = "option", price = data[putCandidateFront.optionCode][index].close, minuteIndex = index }; MinuteSignal callNext = new MinuteSignal() { code = callCandidateNext.optionCode, volume = openVolumeOfCallNext, time = now, tradingVarieties = "option", price = data[callCandidateNext.optionCode][index].close, minuteIndex = index }; MinuteSignal putNext = new MinuteSignal() { code = putCandidateNext.optionCode, volume = openVolumeOfPutNext, time = now, tradingVarieties = "option", price = data[putCandidateNext.optionCode][index].close, minuteIndex = index }; signal.Add(callFront.code, callFront); signal.Add(putFront.code, putFront); signal.Add(callNext.code, callNext); signal.Add(putNext.code, putNext); DateTime next = MinuteTransactionWithSlip.computeMinuteOpenPositions(signal, data, ref positions, ref myAccount, slipPoint: slipPoint, now: now); nextIndex = Math.Max(nextIndex, TimeListUtility.MinuteToIndex(next)); } } //账户信息更新 AccountUpdatingForMinute.computeAccountUpdating(ref myAccount, positions, now, data); } catch (Exception) { throw; } index = nextIndex; } //账户信息记录By Day //用于记录的临时账户 BasicAccount tempAccount = new BasicAccount(); tempAccount.time = myAccount.time; tempAccount.freeCash = myAccount.freeCash; tempAccount.margin = myAccount.margin; tempAccount.positionValue = myAccount.positionValue; tempAccount.totalAssets = myAccount.totalAssets; accountHistory.Add(tempAccount); } //遍历输出到console foreach (var account in accountHistory) { Console.WriteLine("time:{0},netWorth:{1,8:F3}\n", account.time, account.totalAssets / initialCapital); } //将accountHistory输出到csv var resultPath = ConfigurationManager.AppSettings["CacheData.ResultPath"] + "accountHistory.csv"; var dt = DataTableUtils.ToDataTable(accountHistory); // List<MyModel> -> DataTable CsvFileUtils.WriteToCsvFile(resultPath, dt); // DataTable -> CSV File Console.ReadKey(); }
/// <summary> /// 50ETF择时策略测试,N-Days Reversion /// </summary> public void compute() { log.Info("开始回测(回测期{0}到{1})", Kit.ToInt_yyyyMMdd(startdate), Kit.ToInt_yyyyMMdd(endDate)); ///账户初始化 //初始化positions SortedDictionary <DateTime, Dictionary <string, PositionsWithDetail> > positions = new SortedDictionary <DateTime, Dictionary <string, PositionsWithDetail> >(); //初始化Account信息 BasicAccount myAccount = new BasicAccount(); myAccount.totalAssets = initialCapital; myAccount.freeCash = myAccount.totalAssets; //记录历史账户信息 List <BasicAccount> accountHistory = new List <BasicAccount>(); ///数据准备 //交易日信息 List <DateTime> tradeDays = DateUtils.GetTradeDays(startdate, endDate); //50etf分钟数据准备,取全回测期的数据存放于data Dictionary <string, List <KLine> > data = new Dictionary <string, List <KLine> >(); foreach (var tempDay in tradeDays) { var ETFData = Platforms.container.Resolve <StockMinuteRepository>().fetchFromLocalCsvOrWindAndSave("510050.SH", tempDay); if (!data.ContainsKey("510050.SH")) { data.Add("510050.SH", ETFData.Cast <KLine>().ToList()); } else { data["510050.SH"].AddRange(ETFData.Cast <KLine>().ToList()); } } ///回测循环 //回测循环--By Day foreach (var day in tradeDays) { //取出当天的数据 var dataToday = data["510050.SH"].FindAll(s => s.time.Day == day.Day); int index = 0; //交易开关设置,控制day级的交易开关 bool tradingOn = true; //总交易开关 bool openingOn = true; //开仓开关 bool closingOn = true; //平仓开关 //是否为回测最后一天 bool isLastDayOfBackTesting = day.Equals(endDate); //回测循环 -- By Minute //不允许在同一根1minBar上开平仓 while (index < 240) { int nextIndex = index + 1; DateTime now = TimeListUtility.IndexToMinuteDateTime(Kit.ToInt_yyyyMMdd(day), index); Dictionary <string, MinuteSignal> signal = new Dictionary <string, MinuteSignal>(); try { //持仓查询,先平后开 //若当前有持仓 且 允许平仓 //是否是空仓,若position中所有品种volum都为0,则说明是空仓 bool isEmptyPosition = positions.Count != 0 ? positions[positions.Keys.Last()].Values.Sum(x => Math.Abs(x.volume)) == 0 : true; //账户信息更新 AccountUpdatingForMinute.computeAccountUpdating(ref myAccount, positions, now, data); } catch (Exception) { throw; } index = nextIndex; } //账户信息记录By Day //用于记录的临时账户 BasicAccount tempAccount = new BasicAccount(); tempAccount.time = myAccount.time; tempAccount.freeCash = myAccount.freeCash; tempAccount.margin = myAccount.margin; tempAccount.positionValue = myAccount.positionValue; tempAccount.totalAssets = myAccount.totalAssets; accountHistory.Add(tempAccount); } //遍历输出到console foreach (var account in accountHistory) { //这里当账户赋值为NULL时会无限循环 Console.WriteLine("time:{0},netWorth:{1,8:F3}\n", account.time, account.totalAssets / initialCapital); } //将accountHistory输出到csv var resultPath = ConfigurationManager.AppSettings["CacheData.ResultPath"] + "accountHistory.csv"; var dt = DataTableUtils.ToDataTable(accountHistory); // List<MyModel> -> DataTable CsvFileUtils.WriteToCsvFile(resultPath, dt); // DataTable -> CSV File Console.ReadKey(); }