public List <OptionTickFromMssql> fetchFromLocalCsvOrMssqlAndResampleAndSave(string code, DateTime date, TimeLine timeline)
        {
            var data = fetchFromLocalCsv(code, date, "OptionTickFromMssql.Resampled");

            //从csv中取出数据后,需要整理bid及ask数据
            if (data != null)
            {
                foreach (var item in data)
                {
                    if (item.ask == null)
                    {
                        item.ask    = new Position[5];
                        item.ask[0] = new Position(item.ask1, item.askv1);
                        item.ask[1] = new Position(item.ask2, item.askv2);
                        item.ask[2] = new Position(item.ask3, item.askv3);
                        item.ask[3] = new Position(item.ask4, item.askv4);
                        item.ask[4] = new Position(item.ask5, item.askv5);
                    }
                    if (item.bid == null)
                    {
                        item.bid    = new Position[5];
                        item.bid[0] = new Position(item.bid1, item.bidv1);
                        item.bid[1] = new Position(item.bid2, item.bidv2);
                        item.bid[2] = new Position(item.bid3, item.bidv3);
                        item.bid[3] = new Position(item.bid4, item.bidv4);
                        item.bid[4] = new Position(item.bid5, item.bidv5);
                    }
                }
            }
            bool csvFound = (data != null);

            data = fetchFromMssql(code, date, "OptionTickFromMssql.Resampled");
            var data2 = SequentialUtils.ResampleAndAlign(data, timeline, date);

            if (!csvFound && data != null)
            {
                saveToLocalCsv(data2, code, date, "OptionTickFromMssql.Resampled");
            }
            return(data2);
        }
        public void compute()
        {
            ///数据准备
            //交易日信息
            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(targetVariety, tempDay);
                if (!data.ContainsKey(targetVariety))
                {
                    data.Add(targetVariety, ETFData.Cast <KLine>().ToList());
                }
                else
                {
                    data[targetVariety].AddRange(ETFData.Cast <KLine>().ToList());
                }
            }

            var tick = Platforms.container.Resolve <StockTickRepository>().fetchFromMssql(targetVariety, Kit.ToDate(20160905));
            List <StockTickFromMssql> tick2 = SequentialUtils.ResampleAndAlign(tick, Constants.timeline500ms, Kit.ToDate(20160905));


            ///指标计算
            var closePrice = tick2.Select(x => x.bid[1].price).ToArray();

            Stopwatch stopwatch2 = new Stopwatch();

            stopwatch2.Start(); //  开始监视代码运行时间
            var MAValue = TA_MA.SMA(closePrice, periods);

            stopwatch2.Stop();                       //  停止监视
            TimeSpan timespan2 = stopwatch2.Elapsed; //  获取当前实例测量得出的总时间

            Console.WriteLine("Calc MA2 Running Time: {0}", timespan2.TotalSeconds);
            Console.ReadKey();
        }
        /// <summary>
        /// 50ETF,Tick级双均线策略
        /// </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);

            Dictionary <string, List <TickFromMssql> > data = new Dictionary <string, List <TickFromMssql> >();

            foreach (var tempDay in tradeDays)
            {
                var tick = Platforms.container.Resolve <FuturesTickRepository>().fetchFromMssql(targetVariety, tempDay);
                List <FuturesTickFromMssql> tick2 = SequentialUtils.ResampleAndAlign(tick, Constants.timeline500ms, tempDay);
                if (!data.ContainsKey(targetVariety))
                {
                    data.Add(targetVariety, tick2.Cast <TickFromMssql>().ToList());
                }
                else
                {
                    data[targetVariety].AddRange(tick2.Cast <TickFromMssql>().ToList());
                }
            }

            //计算需要指标
            //(1)回测期长均线
            //(2)回测期短均线
            List <double> longMA    = new List <double>();
            List <double> shortMA   = new List <double>();
            List <double> benchmark = new List <double>();

            var lastPrice = data[targetVariety].Select(x => x.lastPrice).ToArray();

            longMA  = TA_MA.SMA(lastPrice, longLength).ToList();
            shortMA = TA_MA.SMA(lastPrice, shortLength).ToList();

            //   double[] dif = new double[lastPrice.Length];
            //   double[] dea = new double[lastPrice.Length];
            //   double[] macdHist = new double[lastPrice.Length];
            //   TA_MACD.compute(lastPrice, new int[] { 26, 12, 9 }, out dif, out dea, out macdHist);

            int indexOfNow = -1;//记录整个data的索引

            /**/

            ///回测循环
            //回测循环--By Day
            foreach (var day in tradeDays)
            {
                //取出当天的数据
                Dictionary <string, List <TickFromMssql> > dataToday = new Dictionary <string, List <TickFromMssql> >();
                foreach (var variety in data)
                {
                    dataToday.Add(variety.Key, data[variety.Key].FindAll(s => s.time.Year == day.Year && s.time.Month == day.Month && s.time.Day == day.Day));
                }

                int dayLength = dataToday[targetVariety].Count;
                int index     = 0;
                //交易开关设置,控制day级的交易开关
                bool tradingOn = true; //总交易开关
                bool openingOn = true; //开仓开关
                bool closingOn = true; //平仓开关

                //是否为回测最后一天
                bool isLastDayOfBackTesting = day.Equals(endDate);

                //回测循环 -- By Tick

                while (index < dayLength)
                {
                    int nextIndex = index + 1;
                    indexOfNow++;
                    DateTime now = TimeListUtility.IndexToTickDateTime(Kit.ToInt_yyyyMMdd(day), index);
                    Dictionary <string, TickSignal> signal = new Dictionary <string, TickSignal>();
                    DateTime next = new DateTime();
                    // int indexOfNow = data[targetVariety].FindIndex(s => s.time == now);
                    double nowPrice = dataToday[targetVariety][index].lastPrice;
                    myAccount.time = now;

                    //实际操作从第一个回望期后开始
                    if (indexOfNow < longLength - 1)
                    {
                        index = nextIndex;
                        continue;
                    }

                    try
                    {
                        //持仓查询,先平后开.
                        //若当前有持仓 且 允许平仓
                        //是否是空仓,若position中所有品种volum都为0,则说明是空仓
                        bool isEmptyPosition = positions.Count != 0 ? positions[positions.Keys.Last()].Values.Sum(x => Math.Abs(x.volume)) == 0 : true;
                        //若当前有持仓且允许交易
                        if (!isEmptyPosition && closingOn)
                        {
                            ///平仓条件
                            /// (1)若当前为 回测结束日 或 tradingOn 为false,平仓
                            /// (2)若短均线下穿长均线,平多
                            //(1)若当前为 回测结束日 或 tradingOn 为false,平仓
                            if (isLastDayOfBackTesting || tradingOn == false)
                            {
                                next = TickCloseAllPositonsWithSlip.closeAllPositions(dataToday, ref positions, ref myAccount, now: now, slipPoint: slipPoint);
                                break;
                            }

                            //(2)若短均线下穿长均线,平多
                            else if (Cross.crossDown(shortMA, longMA, indexOfNow))
                            {
                                next = TickCloseAllPositonsWithSlip.closeAllPositions(dataToday, ref positions, ref myAccount, now: now, slipPoint: slipPoint);
                            }
                        }
                        //空仓 且可交易 可开仓
                        else if (isEmptyPosition && tradingOn && openingOn)
                        {
                            ///开仓条件
                            /// 可用资金足够,且短均线上传长均线
                            double nowFreeCash = myAccount.freeCash;
                            //开仓量,满仓梭哈
                            double openVolume = Math.Truncate(nowFreeCash / data[targetVariety][indexOfNow].lastPrice / contractTimes) * contractTimes;
                            //若剩余资金至少购买一手 且 出上反转信号 开仓
                            if (openVolume >= 1 && Cross.crossUp(shortMA, longMA, indexOfNow))
                            {
                                TickSignal openSignal = new TickSignal()
                                {
                                    code = targetVariety, volume = openVolume, time = now, tradingVarieties = "stock", price = dataToday[targetVariety][index].lastPrice, tickIndex = index
                                };
                                signal.Add(targetVariety, openSignal);
                                next = TickTransactionWithSlip.computeTickOpenPositions(signal, dataToday, ref positions, ref myAccount, slipPoint: slipPoint, now: now);
                                //当天买入不可卖出
                                closingOn = false;
                            }
                        }

                        //账户信息更新
                        AccountUpdatingForTick.computeAccountUpdating(ref myAccount, positions, now, dataToday);
                    }

                    catch (Exception)
                    {
                        throw;
                    }
                    nextIndex = Math.Max(nextIndex, TimeListUtility.TickToIndex(next));
                    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);
                //抓取benchmark
                benchmark.Add(dataToday[targetVariety].Last().lastPrice);

                //显示当前信息
                Console.WriteLine("Time:{0,-8:F},netWorth:{1,-8:F3}", day, myAccount.totalAssets / initialCapital);
            }

            /*
             * //遍历输出到console
             * foreach (var account in accountHistory)
             *  Console.WriteLine("time:{0,-8:F}, 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 上输出
            PerformanceStatisics myStgStats = new PerformanceStatisics();

            myStgStats = PerformanceStatisicsUtils.compute(accountHistory, positions, benchmark.ToArray());
            Console.WriteLine("--------Strategy Performance Statistics--------\n");
            Console.WriteLine(" netProfit:{0,-3:F} \n totalReturn:{1,-3:F} \n anualReturn:{2,-3:F} \n anualSharpe :{3,-3:F} \n winningRate:{4,-3:F} \n PnLRatio:{5,-3:F} \n maxDrawDown:{6,-3:F} \n maxProfitRatio:{7,-3:F} \n informationRatio:{8,-3:F} \n alpha:{9,-3:F} \n beta:{10,-3:F} \n averageHoldingRate:{11,-3:F} \n", myStgStats.netProfit, myStgStats.totalReturn, myStgStats.anualReturn, myStgStats.anualSharpe, myStgStats.winningRate, myStgStats.PnLRatio, myStgStats.maxDrawDown, myStgStats.maxProfitRatio, myStgStats.informationRatio, myStgStats.alpha, myStgStats.beta, myStgStats.averageHoldingRate);
            Console.WriteLine("-----------------------------------------------\n");

            //画图
            Dictionary <string, double[]> line = new Dictionary <string, double[]>();

            double[] netWorth = accountHistory.Select(a => a.totalAssets / initialCapital).ToArray();
            line.Add("NetWorth", netWorth);

            //benchmark净值
            List <double> netWorthOfBenchmark = benchmark.Select(x => x / benchmark[0]).ToList();

            line.Add("50ETF", netWorthOfBenchmark.ToArray());


            string[] datestr = accountHistory.Select(a => a.time.ToString("yyyyMMdd")).ToArray();
            Application.Run(new PLChart(line, datestr));

            Console.ReadKey();
        }