コード例 #1
0
            /// <summary>
            /// 根据个股主力线高位卖出
            /// </summary>
            /// <param name="bouts"></param>
            /// <param name="ds"></param>
            /// <param name="strategyParam"></param>
            /// <param name="backtestParam"></param>
            public void DoSell2(TradeRecords tradeRecords, TimeSerialsDataSet ds, Properties strategyParam, BacktestParameter backtestParam)
            {
                if (tradeRecords == null || tradeRecords.Bouts == null || tradeRecords.Bouts.Count <= 0)
                {
                    return;
                }
                TimeSeries <ITimeSeriesItem <List <double> > > dayFunds = ds.DayFundTrend;
                KLine dayLine = ds.DayKLine;

                if (dayLine == null)
                {
                    return;
                }

                foreach (TradeBout bout in tradeRecords.Bouts)
                {
                    DateTime buyDate = bout.BuyInfo.TradeDate;
                    //找20个工作日的收盘价最高值
                    KLineItem klineItem = dayLine.GetNearest(buyDate, false);
                    if (klineItem == null)
                    {
                        continue;
                    }
                    int      index     = dayLine.IndexOf(klineItem);
                    DateTime sellDate  = buyDate;
                    double   sellPrice = 0;
                    for (int i = index + 1; i < Math.Min(index + 41, dayLine.Count); i++)
                    {
                        if (dayLine[i].CLOSE > sellPrice)
                        {
                            sellPrice = dayLine[i].CLOSE;
                            sellDate  = dayLine[i].Date;
                        }
                    }
                    bout.RecordTrade(2, sellDate, TradeDirection.Sell, sellPrice, bout.BuyInfo.Amount, 0, 0, "");
                }
            }
コード例 #2
0
ファイル: TestCase2.cs プロジェクト: haibo-chen/Security
        public void Execute()
        {
            List <String> codes = new List <string>();

            System.IO.File.ReadAllLines(FileUtils.GetDirectory() + "test.csv")
            .ToList().ForEach(x => codes.Add(x.Split(',')[1]));


            IndicatorRepository repository = new IndicatorRepository("d:\\repository\\");

            repository.Initilization();


            foreach (String code in codes)
            {
                //生成数据
                TimeSerialsDataSet ds = repository[code];
                KLine dayLine         = ds.DayKLine;
                KLine weekLine        = dayLine.CreateWeek();
                ds.WeekKLine = weekLine;

                TimeSeries <ITimeSeriesItem <double> > dayClose  = dayLine.Select <double>("close", 0, 0);
                TimeSeries <ITimeSeriesItem <double> > weekClose = weekLine.Select <double>("close", 0, 0);

                TradingLine dayTradeLine  = ds.CubeCreateOrLoad(TimeUnit.day);
                TradingLine weekTradeLine = ds.CubeCreateOrLoad(TimeUnit.week);

                TimeSeries <ITimeSeriesItem <List <double> > > dayFunds  = ds.FundTrendCreate(TimeUnit.day);
                TimeSeries <ITimeSeriesItem <List <double> > > weekFunds = ds.FundTrendCreate(TimeUnit.week);

                TimeSeries <ITimeSeriesItem <double> > dayCross  = ds.FundTrendCrossCreateOrLoad(TimeUnit.day);
                TimeSeries <ITimeSeriesItem <double> > weedCross = ds.FundTrendCrossCreateOrLoad(TimeUnit.week);

                //测试买入

                List <TradeBout> bouts = new List <TradeBout>();
                TimeSeries <ITimeSeriesItem <char> > dayTradePt = dayTradeLine.buysellPoints;
                for (int i = 0; i < dayTradePt.Count; i++)
                {
                    ITimeSeriesItem <char> item = dayTradePt[i];
                    if (item.Value == 'S')
                    {
                        continue;
                    }
                    if (item.Date < begin || item.Date > end)
                    {
                        continue;
                    }
                    DateTime buyPtDate = item.Date;
                    int      index     = dayFunds.IndexOf(buyPtDate);
                    while (index <= dayFunds.Count)
                    {
                        ITimeSeriesItem <List <double> > fundItem = dayFunds[index];
                        if (fundItem == null)
                        {
                            index += 1;
                            continue;
                        }
                        if (fundItem.Value[0] <= fundItem.Value[1])
                        {
                            index += 1;
                            continue;
                        }
                        TradeBout bout      = new TradeBout(code);
                        KLineItem klineItem = dayLine.GetNearest(fundItem.Date, false);
                        if (klineItem == null)
                        {
                            index += 1;
                            continue;
                        }
                        bout.RecordTrade(1, klineItem.Date, TradeDirection.Buy, klineItem.CLOSE, (int)(funds / klineItem.CLOSE), 0, 0, "发出B点且主力=" + fundItem.Value[0].ToString("F3") + "大于散户" + fundItem.Value[1].ToString("F3") + ",日期=" + fundItem.Date.ToString("yyyyMMdd"));
                        bouts.Add(bout);
                        break;
                    }
                }
                //测试卖出
                for (int i = 0; i < bouts.Count; i++)
                {
                    DateTime buyDate  = bouts[i].BuyInfo.TradeDate;
                    int      buyIndex = dayLine.IndexOf(buyDate);
                    int      index    = buyIndex + 1;
                    while (index <= dayLine.Count - 1)
                    {
                        KLineItem item = dayLine[index];
                        if (index - buyIndex >= maxdays)
                        {
                            bouts[i].RecordTrade(2, item.Date, TradeDirection.Sell, item.CLOSE, bouts[i].BuyInfo.Amount, 0, 0, "大于" + maxdays.ToString() + "天卖出");
                            break;
                        }
                        else
                        {
                            double profile = (item.HIGH - bouts[i].BuyInfo.TradePrice) / bouts[i].BuyInfo.TradePrice;
                            if (profile >= maxProfilt)
                            {
                                bouts[i].RecordTrade(2, item.Date, TradeDirection.Sell, (bouts[i].BuyInfo.TradePrice * (1 + maxProfilt)), bouts[i].BuyInfo.Amount, 0, 0, "利润大于" + maxdays.ToString() + "天卖出");
                                break;
                            }
                        }
                        index += 1;
                    }
                }
                //去掉未完成的
                for (int i = 0; i < bouts.Count; i++)
                {
                    if (!bouts[i].Completed)
                    {
                        bouts.RemoveAt(i--);
                    }
                }

                TradeRecords tradeRecords = new TradeRecords();
                tradeRecords.Bouts.AddRange(bouts);
                //打印结果
                for (int i = 0; i < bouts.Count; i++)
                {
                    Console.WriteLine(bouts[i].ToString());
                }
                Console.WriteLine(tradeRecords.ToString());
            }
        }
コード例 #3
0
        /// <summary>
        /// 执行回测
        /// </summary>
        /// <param name="props"></param>
        /// <returns></returns>
        public virtual TotalStat doTestByDate(List <TradeRecords> tradeRecoreds)
        {
            List <TradeBout> bouts = new List <TradeBout>();

            tradeRecoreds.ForEach(x => bouts.AddRange(x.Bouts));

            double   marketValueMin         = backtestParam.Initfunds; //日最低市值
            double   marketValueMax         = backtestParam.Initfunds; //日最高市值
            double   lastmarketValueMax     = backtestParam.Initfunds; //上一个日最高市值
            DateTime lastmarketValueMaxDate = backtestParam.BeginDate;
            double   curFund = backtestParam.Initfunds;                //当前资金

            TotalStat stat = new TotalStat();
            List <DateDetailRecord> records    = new List <DateDetailRecord>(); //日详细记录
            List <TradeBout>        holdTrades = new List <TradeBout>();        //日持仓回合
            List <int>    holdDays             = new List <int>();              //持仓日期
            List <String> codes     = new List <string>();                      //交易的股票代码
            List <int>    buyCounts = new List <int>();                         //每天买入的回合数

            IndicatorRepository repository = (IndicatorRepository)backtestParam.Get <Object>("repository");
            String reason = "";

            //遍历每一天
            for (DateTime d = backtestParam.BeginDate; d <= backtestParam.EndDate; d = d.AddDays(1))
            {
                //跳过非工作日
                //if (!CalendarUtils.IsWorkDay(d))
                //     continue;


                //生成空的当日记录
                DateDetailRecord record = new DateDetailRecord();
                record.date = d;
                //找到当日的买入回合、卖出回合
                bouts.ForEach(y =>
                {
                    if (y.BuyInfo.TradeDate.Date == d.Date)
                    {
                        record.buyBouts.Add(y);
                    }
                    else if (y.SellInfo.TradeDate.Date == d.Date)
                    {
                        record.sellBouts.Add(y);
                    }
                });

                //当日没有发生买卖操作,也没有持仓,跳过
                if (record.buyBouts.Count <= 0 && record.sellBouts.Count <= 0 && holdTrades.Count <= 0)
                {
                    continue;
                }



                //将buyTrades按照优先规则排序,待实现

                //计算当日买入的花销,如果超过了资金允许买入的量,则删除一部分
                record.willBuyCount = record.buyBouts.Count;
                for (int i = 0; i < record.buyBouts.Count; i++)
                {
                    if (record.buyBouts[i].BuyInfo.TradeCost > curFund)//资金不够
                    {
                        bouts.Remove(record.buyBouts[i]);
                        record.buyBouts.RemoveAt(i--);
                    }
                    else if (isForbidBuy(d, record.buyBouts[i].Code, out reason))//如果策略实现禁止买入
                    {
                        bouts.Remove(record.buyBouts[i]);
                        record.buyBouts.RemoveAt(i--);
                    }
                    else
                    {
                        curFund -= record.buyBouts[i].BuyInfo.TradeCost; //买入
                        holdTrades.Add(record.buyBouts[i]);              //买入后变成持仓
                    }
                }
                record.buyCount = record.buyBouts.Count;
                if (stat.MaxTradeCountPerDay < record.buyBouts.Count)
                {
                    stat.MaxTradeCountPerDay = record.buyBouts.Count;
                }
                buyCounts.Add(record.buyBouts.Count);

                //判断持仓中的股票是否被禁止持仓
                for (int i = 0; i < holdTrades.Count; i++)
                {
                    TradeBout info = holdTrades[i];
                    if (!isForbidHold(d, info.Code, out reason))
                    {
                        continue;
                    }
                    info.SellInfo.Reason = reason + "(" + info.SellInfo.Reason + ")";
                    record.sellBouts.Add(info);
                    holdTrades.RemoveAt(i--);
                }


                //卖出收入放回资金
                for (int i = 0; i < record.sellBouts.Count; i++)
                {
                    if (!codes.Contains(record.sellBouts[i].Code))//记录交易的股票
                    {
                        codes.Add(record.sellBouts[i].Code);
                    }
                    stat.BoutNum += 1;           //回合数加1
                    if (record.sellBouts[i].Win) //胜数加1
                    {
                        stat.WinNum += 1;
                    }
                    holdDays.Add(record.sellBouts[i].PositionDays);    //记录持仓日期

                    curFund += record.sellBouts[i].SellInfo.TradeCost; //回收资金
                    holdTrades.Remove(record.sellBouts[i]);            //从持仓中拿掉
                }
                record.SellCount = record.sellBouts.Count;

                //计算市值
                record.holdCount = holdTrades.Count;
                if (holdTrades.Count <= 0)//如果没有持仓,市值就是资金量
                {
                    marketValueMax = marketValueMin = curFund;
                    records.Add(record);
                }
                else//如果有持仓,则计算市值=资金量+持仓当日市值
                {
                    double min = 0, max = 0;
                    foreach (TradeBout info in holdTrades)
                    {
                        TimeSerialsDataSet ds = repository[info.Code];
                        KLine     kline       = ds.DayKLine;
                        KLineItem klineitem   = kline.GetNearest(d, true, -1);
                        if (klineitem == null)//有一个回合找不到当日K线数据,则当日市值不再计算
                        {
                            min = max = 0;
                            this.log.Warn("日期" + d.ToString("yyyyMMdd") + "中有回合缺少当日和历史K线:" + info.Code);
                            break;
                        }
                        min += info.BuyInfo.Amount * klineitem.LOW;
                        max += info.BuyInfo.Amount * klineitem.HIGH;
                        record.holdBouts.Add(info.Code + "," + info.BuyInfo.Amount + "," + info.BuyInfo.TradePrice.ToString("F2") + "," + klineitem.CLOSE);
                    }
                    if (min != 0)
                    {
                        marketValueMin = curFund + min;
                    }
                    if (max != 0)
                    {
                        marketValueMax = curFund + max;
                    }
                    if (min != 0 && max != 0)
                    {
                        records.Add(record);
                    }
                }
                //记录资金和市值数据
                record.curFund        = curFund;
                record.marketValueMin = marketValueMin;
                record.marketValueMax = marketValueMax;
                if (marketValueMin < backtestParam.Initfunds)
                {
                    record.retracement = (backtestParam.Initfunds - marketValueMin) / backtestParam.Initfunds;
                }
                if (stat.MaxInitRetracementRate < record.retracement)
                {
                    stat.MaxInitRetracementRate = record.retracement;
                    stat.MaxInitRetracementDate = d;
                }
                if (marketValueMax > lastmarketValueMax)
                {
                    lastmarketValueMax     = marketValueMax;
                    lastmarketValueMaxDate = d;
                    record.retracement     = 0;
                }
                else
                {
                    record.retracement      = (lastmarketValueMax - marketValueMax) / lastmarketValueMax;
                    stat.MaxRetracementRate = record.retracement;
                    stat.MaxRetracementDate = d;
                }
            }

            //清除没有卖出的回合
            for (int i = 0; i < holdTrades.Count; i++)
            {
                curFund += holdTrades[i].BuyInfo.TradeCost;
                bouts.Remove(holdTrades[i]);
            }
            holdTrades.Clear();
            marketValueMin = marketValueMax = curFund;
            if (records.Count > 0)
            {
                DateDetailRecord extends = new DateDetailRecord();
                extends.date           = records[records.Count - 1].date.AddDays(1);
                extends.curFund        = curFund;
                extends.marketValueMax = marketValueMax;
                extends.marketValueMin = marketValueMin;
                records.Add(extends);
            }

            //结果统计
            stat.Records = records;

            stat.AverageTradeCountPerDay = buyCounts.Count <= 0?0:buyCounts.Average();
            stat.AvgHoldDays             = holdDays.Count <= 0?0:(int)holdDays.Average();
            stat.Count        = codes.Count;
            stat.MaxHoldDays  = holdDays.Count <= 0 ? 0 : holdDays.Max();
            stat.TotalFund    = curFund;
            stat.TotalProfilt = (curFund - backtestParam.Initfunds) / backtestParam.Initfunds;
            stat.WinRate      = stat.WinNum * 1.0 / stat.BoutNum;

            return(stat);
        }