예제 #1
0
 /// <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);
             }
         }
     }
 }
예제 #2
0
        public void saveToLocalFile(List <positionShot> optionMinuteData, string path)
        {
            var dt = DataTableUtils.ToDataTable(optionMinuteData);

            CsvFileUtils.WriteToCsvFile(path, dt);
            Console.WriteLine("{0} saved!", path);
        }
예제 #3
0
        private static void WriteToCsv(List <NameCount> nameCollection, List <string> addressCollection)
        {
            var addressCsvPath       = CsvFileUtils.WriteCSV(addressCollection, "address_sorted.csv");
            var nameFrequencyCsvPath = CsvFileUtils.WriteCSV(nameCollection, "name_frequency.csv", true);

            Console.WriteLine(Environment.NewLine);

            // Check if we got a file path if the is no csv write file path then something went wrong
            if (nameFrequencyCsvPath != null)
            {
                Console.WriteLine($"\tName sorted frequency wrote to csv file:{Environment.NewLine}{nameFrequencyCsvPath}");
            }
            else
            {
                Console.WriteLine("\tFailed to write Name sorted frequency csv file");
            }

            if (addressCsvPath != null)
            {
                Console.WriteLine($"\tSorted address wrote to csv file:{Environment.NewLine}{addressCsvPath}");
            }
            else
            {
                Console.WriteLine("\tFailed to write sorted address csv file");
            }
        }
예제 #4
0
        static void Main(string[] args)
        {
            // Get data from csv file
            List <Person> personList = CsvFileUtils.GetPersonDataFromCsv("Resources/data.csv");

            if (personList?.Count > 0)
            {
                Console.WriteLine("Successfully read csv file");
                Console.WriteLine($"Total lines found: { personList.Count}");

                // Get name frequency base on firstname and lastname and order by count descending and by name ascending
                var nameCollection = WordFrequency.GetPersonNamesFrequency(personList);
                // Get address sorted by name not by number
                var addressCollection = WordFrequency.GetAddressAlphabatically(personList);

                // Print data to console window
                PrintNameFrequencies(nameCollection);
                PrintAddressFrequencies(addressCollection);

                // Writing our sorted data and frequency data to csv files
                WriteToCsv(nameCollection, addressCollection);
            }
            else
            {
                Console.WriteLine("Total lines found: 0");
            }
            Console.ReadKey();
        }
예제 #5
0
        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);
        }
예제 #6
0
        /// <summary>
        ///  尝试从本地csv文件获取数据,可能会抛出异常
        /// </summary>
        /// <returns></returns>
        protected List <T> readFromLocalCsv(string path)
        {
            DataTable dt = CsvFileUtils.ReadFromCsvFile(path);

            if (dt == null)
            {
                return(null);
            }
            //T tmp2 = toEntityFromCsv(dt.Rows[0]);
            //List<T> tmp= dt.AsEnumerable().Select(toEntityFromCsv).ToList();
            return(dt.AsEnumerable().Select(toEntityFromCsv).ToList());
        }
        //public abstract List<T> readFromLocalCSV(String path);
        public virtual List <T> readFromLocalCSV(string path)
        {
            if (path == null || !File.Exists(path))
            {
                log.Debug("未找到文件{0}!", path);
                return(null);
            }
            DataTable dt = CsvFileUtils.ReadFromCsvFile(path);

            if (dt == null)
            {
                return(null);
            }
            return(dt.AsEnumerable().Select(toEntityFromCsv).ToList());
        }
예제 #8
0
        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)
            {
            }
        }
예제 #9
0
        /// <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);
            }
        }
예제 #10
0
        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)
            {
            }
        }
예제 #11
0
        /// <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文件失败!");
            }
        }
예제 #12
0
        /// <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();
        }
예제 #13
0
        /// <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();
        }