Exemple #1
0
        /// <summary>
        /// 从wind或本地CSV获取当天数据
        /// </summary>
        /// <param name="today">今天的日期</param>
        /// <param name="code">代码</param>
        /// <returns></returns>
        private List <FuturesMinute> getData(DateTime today, string code)
        {
            List <FuturesMinute> orignalList = Platforms.container.Resolve <FuturesMinuteRepository>().fetchFromLocalCsvOrWindAndSave(code, today);
            List <FuturesMinute> data        = KLineDataUtils.leakFilling(orignalList);

            //从本地csv 或者 wind获取数据,从wind拿到额数据会保存在本地
            //List<FuturesMinute> data = KLineDataUtils.leakFilling(Platforms.container.Resolve<FuturesMinuteRepository>().fetchFromLocalCsvOrWindAndSave(code, today));

            #region 20170118更新
            //下面这行需要注释掉,因为可能data的count为0
            var dataModified = FreqTransferUtils.minuteToNMinutes(data, frequency);
            #endregion

            return(dataModified);
        }
        /// <summary>
        /// 计算参数
        /// </summary>
        private void computeParameters()
        {
            List <FuturesMinute> data = new List <FuturesMinute>();

            #region 20170118更新
            //回测开始的首个日期,在tradeDays数组的第一个索引值:
            //当回测期第一个交易日的前三天没有一天有数据,会引发后续代码出现数组索引为负值的情况。
            //bool OutOfRange = false;
            #endregion

            //获取首个回测日之前的三日(日)数据
            data = getData(DateUtils.PreviousTradeDay(tradeDays[0], 3), underlying);
            data.AddRange(getData(DateUtils.PreviousTradeDay(tradeDays[0], 2), underlying));
            data.AddRange(getData(DateUtils.PreviousTradeDay(tradeDays[0], 1), underlying));

            #region 20170118更新
            //当无法获取回测日之前的三日(日)数据,也就是data.count=0时,就需要...
            //if (data.Count == 0)
            //{
            //    Console.WriteLine("回测开始日期错误,自动调整到有数据记录的开始日期...");
            //    OutOfRange = true;
            //}
            #endregion

            //如果回测开始时间早于该品种有数据的时间,
            //逐日获取K线数据(频率为1分钟)
            for (int i = 0; i < tradeDays.Count(); i++)
            {
                var data0 = getData(tradeDays[i], underlying);
                data.AddRange(data0);
            }
            //var dataModified = FreqTransferUtils.minuteToNMinutes(data, frequency);
            //按交易日逐日计算,每日遍历所有的参数,结果记入字典结构的变量中
            ParaPairs pairs = new ParaPairs();

            #region debug数据,请勿删除
            //int[] frequencySet = new int[] { 3 };
            //int[] numbersSet = new int[] { 5 };
            //double[] lossPercentSet = new double[] { 0.015 };
            //double[] longERSet = new double[] {  0.7 };
            //double[] shortERSet = new double[] {-0.7 };

            //int[] frequencySet = new int[] { 3, 4, 5, 6, 7, 8 };
            //int[] numbersSet = new int[] { 3, 4, 5, 6, 8, 10, 15 };
            //double[] lossPercentSet = new double[] { 0.005, 0.01, 0.015, 0.02 };
            //double[] longERSet = new double[] { 0.5, 0.6, 0.7, 0.8, 0.9 };
            //double[] shortERSet = new double[] { -0.5, -0.6, -0.7, -0.8, -0.9 };
            #endregion

            int[]    frequencySet   = new int[] { 3, 4, 5, 6, 7, 8 };
            int[]    numbersSet     = new int[] { 3, 4, 5, 6, 8, 10, 15 };
            double[] lossPercentSet = new double[] { 0.005, 0.01, 0.015, 0.02 };
            double[] longERSet      = new double[] { 0.5, 0.6, 0.7, 0.8, 0.9 };
            double[] shortERSet     = new double[] { -0.5, -0.6, -0.7, -0.8, -0.9 };

            //记录frequency的边际分布
            List <double> frequencyDistrbution = new List <double>();

            foreach (var fre in frequencySet)
            {
                frequency       = fre; //给定K线周期
                pairs.frequency = frequency;
                //data是(1分钟)K线数据,dataModified是(frequency周期)K线数据
                var dataModified = FreqTransferUtils.minuteToNMinutes(data, frequency);
                foreach (var num in numbersSet)
                {
                    numbers       = num; //给定前推的(frequency周期)K线数量
                    pairs.numbers = numbers;
                    foreach (var loss in lossPercentSet)
                    {
                        lossPercent       = loss; //给定追踪止损的参数
                        pairs.lossPercent = lossPercent;
                        foreach (var er in longERSet)
                        {
                            longER       = er; //给定ER比例的参数
                            pairs.longER = longER;
                            foreach (var shortEr in shortERSet)
                            {
                                shortER       = shortEr;
                                pairs.shortER = shortER;

                                #region ...
                                double profitInDay         = 0;
                                double positionVolume      = 0;
                                double openPrice           = 0;
                                double maxIncomeIndividual = 0;
                                Console.WriteLine("开始回测参数--> K线:{0}, 回望时间:{1},追踪止损:{2},longER值:{3}, shortER值:{4}",
                                                  pairs.frequency, pairs.numbers, pairs.lossPercent, pairs.longER, pairs.shortER);

                                //[新版]记录该组参数对应的, 所有交易日的收益
                                FiveParameterPairs newPairs0 = new FiveParameterPairs
                                {
                                    longER      = pairs.longER,
                                    shortER     = pairs.shortER,
                                    frequency   = pairs.frequency,
                                    lossPercent = pairs.lossPercent,
                                    numbers     = pairs.numbers
                                };

                                //用来记录同一套策略情况下,不同交易日的盈利情况
                                SortedDictionary <DateTime, double> sortedDic0 = new SortedDictionary <DateTime, double>();

                                for (int i = 0; i < dataModified.Count(); i++) //开始按日期遍历
                                {
                                    var now = dataModified[i];

                                    #region 20170118更新
                                    //if (OutOfRange)
                                    //{
                                    //    if (now.tradeday <DateUtils.NextTradeDay(dataModified[0].tradeday))
                                    //    {
                                    //        continue;
                                    //    }
                                    //}
                                    //else
                                    //{
                                    //}

                                    //在5分钟K线数据表dataModified中,找到首个交易日 tradeDays[0]开始位置对应的index
                                    if (now.tradeday < tradeDays[0])
                                    {
                                        continue;
                                    }

                                    #endregion

                                    pairs.tradeday = now.tradeday;
                                    //当日最后一根K线,进入结算。
                                    if (i == dataModified.Count() - 1 || (i + 1 < dataModified.Count() && dataModified[i + 1].tradeday > now.tradeday))
                                    {
                                        //强制平仓
                                        if (positionVolume != 0)
                                        {
                                            //减去2倍的滑点,是因为买入和卖出均有手续费
                                            profitInDay += positionVolume * (now.open - openPrice) - 2 * slipPoint;
                                            //   Console.WriteLine("时间:{0},价格:{1}, volume:0", dataModified[i].time, now.open);
                                        }

                                        //记录该组参数当日收益(一个交易日记录一次数据)
                                        sortedDic0.Add(pairs.tradeday, profitInDay);

                                        //重置数据
                                        profitInDay         = 0;
                                        positionVolume      = 0;
                                        maxIncomeIndividual = 0;
                                    }
                                    else
                                    {
                                        double[] prices = new double[numbers];
                                        for (int k = i - numbers; k < i; k++)
                                        {
                                            //导入(前numbersK线)的收盘价
                                            prices[k - (i - numbers)] = dataModified[k].close;
                                        }
                                        //计算出ER值
                                        double ER = computeER(prices);
                                        if (positionVolume == 0)                   //持空仓
                                        {
                                            if (ER > longER && now.open > now.low) //开多仓,且能够开仓
                                            {
                                                openPrice      = now.open;
                                                positionVolume = 1;
                                                // Console.WriteLine("时间:{0},价格:{1}, volume:1", dataModified[i].time, now.open);
                                            }
                                            if (ER < shortER && now.open < now.high) //开空仓
                                            {
                                                openPrice      = now.open;
                                                positionVolume = -1;
                                                // Console.WriteLine("时间:{0},价格:{1}, volume:-1", dataModified[i].time, now.open);
                                            }
                                        }
                                        else if (positionVolume == 1) //持多仓
                                        {
                                            if ((now.open - openPrice) > maxIncomeIndividual)
                                            {
                                                maxIncomeIndividual = now.open - openPrice;
                                            }
                                            //追踪止损,强制平仓
                                            else if (((now.open - openPrice) - maxIncomeIndividual) < -lossPercent * now.open)
                                            {
                                                profitInDay += now.open - openPrice - 2 * slipPoint;

                                                //重置数据
                                                positionVolume      = 0;
                                                maxIncomeIndividual = 0;
                                                // Console.WriteLine("时间:{0},价格:{1}, volume:0", dataModified[i].time, now.open);
                                            }
                                        }
                                        else if (positionVolume == -1) //持空仓
                                        {
                                            if ((openPrice - now.open) > maxIncomeIndividual)
                                            {
                                                maxIncomeIndividual = (openPrice - now.open);
                                            }
                                            else if (((openPrice - now.open) - maxIncomeIndividual) < -lossPercent * now.open)
                                            {
                                                profitInDay        += openPrice - now.open - 2 * slipPoint;
                                                positionVolume      = 0;
                                                maxIncomeIndividual = 0;
                                                // Console.WriteLine("时间:{0},价格:{1}, volume:0", dataModified[i].time, now.open);
                                            }
                                        }
                                    }
                                }
                                //写入每一套参数,对应的所有交易日的收益情况
                                newResult.Add(newPairs0, sortedDic0);
                                #endregion
                            }
                        }
                    }
                }
                //第一层循环底部....
            }
        }
Exemple #3
0
        /// <summary>
        /// 计算参数
        /// </summary>
        private void computeParameters()
        {
            List <FuturesMinute> data = new List <FuturesMinute>();

            //获取首个回测日之前的三日(日)数据
            data = getData(DateUtils.PreviousTradeDay(tradeDays[0], 3), underlying);
            data.AddRange(getData(DateUtils.PreviousTradeDay(tradeDays[0], 2), underlying));
            data.AddRange(getData(DateUtils.PreviousTradeDay(tradeDays[0], 1), underlying));
            //逐日获取K线数据(频率为1分钟)
            for (int i = 0; i < tradeDays.Count(); i++)
            {
                var data0 = getData(tradeDays[i], underlying);
                data.AddRange(data0);
            }
            //var dataModified = FreqTransferUtils.minuteToNMinutes(data, frequency);
            //按交易日逐日计算,每日遍历所有的参数,结果记入字典结构的变量中
            ParameterPairs pairs = new ParameterPairs();

            #region debug数据,请勿删除
            //int[] frequencySet = new int[] { 5 };
            //int[] numbersSet = new int[] { 3 };
            //double[] lossPercentSet = new double[] { 0.015 };
            //double[] ERRatioSet = new double[] { 0.6 };

            //int[] frequencySet = new int[] { 3, 5, 7, 10 };
            //int[] numbersSet = new int[] { 3, 4, 5, 6, 8, 10, 15 };
            //double[] lossPercentSet = new double[] { 0.000625, 0.00125, 0.0025, 0.005, 0.01, 0.015 };
            //double[] ERRatioSet = new double[] { 0.5, 0.6, 0.7, 0.8, 0.9 };
            #endregion

            int[]    frequencySet   = new int[] { 3, 5, 7, 10 };
            int[]    numbersSet     = new int[] { 3, 4, 5, 6, 8, 10, 15 };
            double[] lossPercentSet = new double[] { 0.00125, 0.0025, 0.005, 0.01 };
            double[] ERRatioSet     = new double[] { 0.5, 0.6, 0.7, 0.8, 0.9 };
            //int[] frequencySet = new int[] { 3, 4, 5, 6, 7, 8 };
            //int[] numbersSet = new int[] { 3, 4, 5, 6, 8, 10, 15 };
            //double[] lossPercentSet = new double[] { 0.0025,0.005, 0.01,0.015,0.02};
            //double[] ERRatioSet = new double[] { 0.5, 0.6, 0.7, 0.8, 0.9 };

            //记录frequency的边际分布
            List <double> frequencyDistrbution = new List <double>();

            foreach (var fre in frequencySet)
            {
                frequency       = fre; //给定K线周期
                pairs.frequency = frequency;
                //data是(1分钟)K线数据,dataModified是(frequency周期)K线数据
                var dataModified = FreqTransferUtils.minuteToNMinutes(data, frequency);
                foreach (var num in numbersSet)
                {
                    numbers       = num; //给定前推的(frequency周期)K线数量
                    pairs.numbers = numbers;
                    foreach (var loss in lossPercentSet)
                    {
                        lossPercent       = loss; //给定追踪止损的参数
                        pairs.lossPercent = lossPercent;
                        foreach (var er in ERRatioSet)
                        {
                            ERRatio       = er; //给定ER比例的参数
                            pairs.ERRatio = ERRatio;
                            double profitInDay         = 0;
                            double positionVolume      = 0;
                            double openPrice           = 0;
                            double maxIncomeIndividual = 0;
                            Console.WriteLine("开始回测参数,K线:{0},回望时间:{1},追踪止损:{2},ER值:{3}", pairs.frequency, pairs.numbers, pairs.lossPercent, pairs.ERRatio);

                            //[新版]记录该组参数对应的, 所有交易日的收益
                            FourParameterPairs newPairs0 = new FourParameterPairs
                            {
                                ERRatio     = pairs.ERRatio,
                                frequency   = pairs.frequency,
                                lossPercent = pairs.lossPercent,
                                numbers     = pairs.numbers
                            };

                            //用来记录同一套策略情况下,不同交易日的盈利情况
                            SortedDictionary <DateTime, double> sortedDic0 = new SortedDictionary <DateTime, double>();

                            for (int i = 0; i < dataModified.Count(); i++) //开始按日期遍历
                            {
                                var now = dataModified[i];
                                //在5分钟K线数据表dataModified中,找到首个交易日 tradeDays[0]开始位置对应的index
                                if (now.tradeday < tradeDays[0])
                                {
                                    continue;
                                }
                                pairs.tradeday = now.tradeday;
                                //当日最后一根K线,进入结算。
                                if (i == dataModified.Count() - 1 || (i + 1 < dataModified.Count() && dataModified[i + 1].tradeday > now.tradeday))
                                {
                                    //强制平仓
                                    if (positionVolume != 0)
                                    {
                                        //减去2倍的滑点,是因为买入和卖出均有手续费
                                        profitInDay += positionVolume * (now.open - openPrice) - 2 * slipPoint;
                                        //   Console.WriteLine("时间:{0},价格:{1}, volume:0", dataModified[i].time, now.open);
                                    }

                                    //记录该组参数当日收益(一个交易日记录一次数据)
                                    sortedDic0.Add(pairs.tradeday, profitInDay);

                                    //重置数据
                                    profitInDay         = 0;
                                    positionVolume      = 0;
                                    maxIncomeIndividual = 0;
                                }
                                else
                                {
                                    double[] prices = new double[numbers];
                                    for (int k = i - numbers; k < i; k++)
                                    {
                                        //导入(前numbersK线)的收盘价
                                        prices[k - (i - numbers)] = dataModified[k].close;
                                    }
                                    //计算出ER值
                                    double ER = computeER(prices);
                                    if (positionVolume == 0)                    //持空仓
                                    {
                                        if (ER > ERRatio && now.open > now.low) //开多仓,且能够开仓
                                        {
                                            openPrice      = now.open;
                                            positionVolume = 1;
                                            // Console.WriteLine("时间:{0},价格:{1}, volume:1", dataModified[i].time, now.open);
                                        }
                                        if (ER < -ERRatio && now.open < now.high) //开空仓
                                        {
                                            openPrice      = now.open;
                                            positionVolume = -1;
                                            // Console.WriteLine("时间:{0},价格:{1}, volume:-1", dataModified[i].time, now.open);
                                        }
                                    }
                                    else if (positionVolume == 1) //持多仓
                                    {
                                        if ((now.open - openPrice) > maxIncomeIndividual)
                                        {
                                            maxIncomeIndividual = now.open - openPrice;
                                        }
                                        //追踪止损,强制平仓
                                        else if (((now.open - openPrice) - maxIncomeIndividual) < -lossPercent * now.open)
                                        {
                                            profitInDay += now.open - openPrice - 2 * slipPoint;

                                            //重置数据
                                            positionVolume      = 0;
                                            maxIncomeIndividual = 0;
                                            // Console.WriteLine("时间:{0},价格:{1}, volume:0", dataModified[i].time, now.open);
                                        }
                                    }
                                    else if (positionVolume == -1) //持空仓
                                    {
                                        if ((openPrice - now.open) > maxIncomeIndividual)
                                        {
                                            maxIncomeIndividual = (openPrice - now.open);
                                        }
                                        else if (((openPrice - now.open) - maxIncomeIndividual) < -lossPercent * now.open)
                                        {
                                            profitInDay        += openPrice - now.open - 2 * slipPoint;
                                            positionVolume      = 0;
                                            maxIncomeIndividual = 0;
                                            // Console.WriteLine("时间:{0},价格:{1}, volume:0", dataModified[i].time, now.open);
                                        }
                                    }
                                }
                            }
                            //写入每一套参数,对应的所有交易日的收益情况
                            newResult.Add(newPairs0, sortedDic0);
                        }
                    }
                }
                //第一层循环底部....
            }
        }