Example #1
0
    private void GetDataAndPrediction(List <TradeStateRecord> tradeStateRecords, Dictionary <String, Trade> lastTradeDict)
    {
        Console.WriteLine("共有记录{0}条", tradeStateRecords.Count);
        DQNTradeDBAccess.ClearTempRecords();
        Console.WriteLine("开始准备数据 ...");

        string dealDateString = Utils.FormatDate(this.dealDate);

        foreach (TradeStateRecord aStateRecord in tradeStateRecords)
        {
            Trade lastTrade = lastTradeDict[aStateRecord.Symbol];
            if (lastTrade == null)
            {
                continue;
            }

            //读取应指数的日线和5分线,证券的日线和分线
            string indexSymbol = "";
            if (aStateRecord.Symbol.IndexOf("SHSE.") >= 0)
            {
                indexSymbol = "SHSE.000001";
            }
            else if (aStateRecord.Symbol.IndexOf("SZSE.3") >= 0)
            {
                indexSymbol = "SZSE.399006";
            }
            else
            {
                indexSymbol = "SZSE.399001";
            }
            List <Daily> indexDailys = BarFeeder.GetDailys(indexSymbol, Const.IndexDailyPeriod);
            List <Bar>   indexMin5s  = BarFeeder.GetBar5s(indexSymbol, Const.IndexMin5Period);
            //***这里多加了当天日线,便于向前复权,以修正价格
            List <Daily> stockDailys = BarFeeder.GetDailys(aStateRecord.Symbol, Const.StockDailyPeriod, true, lastTrade);
            //日线不足周期数的忽略
            if (stockDailys.Count < Const.StockDailyPeriod)
            {
                continue;
            }
            List <Bar> stockMin5s = BarFeeder.GetBar5s(aStateRecord.Symbol, Const.StockMin5Period);

            //正规化数据
            List <NormalBar> indexNormalDailys = BarUtils.NormalBars(indexDailys);
            List <NormalBar> indexNormalMin5s  = BarUtils.NormalBars(indexMin5s);
            List <NormalBar> stockNormalDailys = BarUtils.NormalBars(stockDailys);
            List <NormalBar> stockNormalMin5s  = BarUtils.NormalBars(stockMin5s);
            DQNTradeDBAccess.SaveTempRecord(dealDateString, aStateRecord.Symbol, aStateRecord.HoldingPeriod,
                                            BarUtils.BarsToBsonArray(indexNormalDailys), BarUtils.BarsToBsonArray(indexNormalMin5s),
                                            BarUtils.BarsToBsonArray(stockNormalDailys), BarUtils.BarsToBsonArray(stockNormalMin5s));
        }
        Console.WriteLine("预测中 ...");
        //调用神经网络进行盈利预测
        CMDAgent.RunPythonScript(@"E:\pyfiles\trade_dqn_v2.0\trade_prediction.py", dealDateString);
    }
    protected override bool doJob()
    {
        bool ret = false;
        List <TradeStateRecord> tradeStateRecords = new List <TradeStateRecord>();
        List <string>           recordedSymbols   = new List <string>();

        DateTime dealTime        = this.dealDate.AddMinutes(Const.DealTimeMins);
        DateTime closeTime       = this.dealDate.AddMinutes(Const.CloseTimeMins);
        string   dealTimeString  = Utils.FormatTime(dealTime);
        string   closeTimeString = Utils.FormatTime(closeTime);
        string   dealDateString  = Utils.FormatDate(dealDate);

        //处理已记录的随机交易
        foreach (BsonDocument record in RandomTradeDBAccess.GetRecordsByNextTradeDate(dealDateString))
        {
            TradeStateRecord aTradeRecord = new TradeStateRecord();
            aTradeRecord._id           = record["_id"].ToString();
            aTradeRecord.Symbol        = record["Symbol"].ToString();
            aTradeRecord.HoldingPeriod = (int)record["HoldingPeriod"] + 1;
            tradeStateRecords.Add(aTradeRecord);
            recordedSymbols.Add(aTradeRecord.Symbol);
        }
        //获取指定时间的最新价格,然后随机选择入场
        List <string> activeSymbols = new List <String>();

        activeSymbols.AddRange(this.provider.GetSymbols("SHSE", 1, 1));
        activeSymbols.AddRange(this.provider.GetSymbols("SZSE", 1, 1));

        Dictionary <String, Trade> lastTradeDict = new Dictionary <String, Trade>();

        foreach (string symbol in activeSymbols)
        {
            List <Trade> trades = this.provider.GetLastNTrades(symbol, dealTimeString, 1);
            if (trades.Count > 0 && trades[0].DateTime.Date == this.dealDate)
            {
                lastTradeDict[symbol] = trades[0];
            }
            else
            {
                lastTradeDict[symbol] = null;
            }
        }
        Console.WriteLine("今日共有 {0} 只活跃证券", lastTradeDict.Count);
        List <string> symbols = new List <string>();

        foreach (KeyValuePair <String, Trade> kvp in lastTradeDict)
        {
            if (kvp.Value == null)
            {
                continue;
            }
            GMTrade gmTrade = (GMTrade)kvp.Value;
            if (gmTrade.Price <= 0)
            {
                continue;
            }
            if (gmTrade.Price == gmTrade.UpperLimit)
            {
                continue;
            }
            if (gmTrade.Price / gmTrade.LastClose - 1 <= 0)
            {
                continue;
            }
            if (recordedSymbols.Contains(kvp.Key))
            {
                continue;
            }
            if (!symbols.Contains(kvp.Key))
            {
                symbols.Add(kvp.Key);
            }
        }
        int    total    = symbols.Count;
        Random randomer = new Random((int)DateTime.Now.Ticks);

        int[] randomNumbers = new int[100];
        for (int k = 0; k < 100; k++)
        {
            randomNumbers[k] = randomer.Next(total);
        }
        foreach (int r in randomNumbers)
        {
            string           symbol       = symbols[r];
            TradeStateRecord aTradeRecord = new TradeStateRecord();
            aTradeRecord.Symbol        = symbol;
            aTradeRecord.HoldingPeriod = 1;
            tradeStateRecords.Add(aTradeRecord);
        }
        Console.WriteLine("今日共需保存 {0} 条交易记录", tradeStateRecords.Count);
        //如果当天已写入记录,先删除
        RandomTradeDBAccess.RemoveRecordsByDate(dealDateString);
        BarFeeder.Init(this.provider, dealTime);
        //开始记录每一条交易
        string nextTradeDateString = (string)this.strategy.Global["NextTradeDate"];

        foreach (TradeStateRecord aTradeRecord in tradeStateRecords)
        {
            //读取当天日线
            List <Daily> dailys   = BarFeeder.GetLastNDailys(aTradeRecord.Symbol, 1);
            Daily        curDaily = null;
            if (dailys.Count > 0)
            {
                curDaily = dailys[0];
            }
            //没有当天日线则认为是停盘,有则确定收盘价格
            if (curDaily == null || curDaily.DateTime < this.dealDate)
            {
                aTradeRecord.PriceWhenClose = 0.0;
                Console.WriteLine("证券{0}:今日没有交易", aTradeRecord.Symbol);
                if (aTradeRecord.HoldingPeriod > 1)
                {
                    RandomTradeDBAccess.UpdateNextTradeDate(aTradeRecord._id, nextTradeDateString);
                }
                continue;
            }
            else
            {
                aTradeRecord.PriceWhenClose      = curDaily.Close;
                aTradeRecord.LowerPriceWhenClose = curDaily.Low;
            }
            //读取决断时的价格
            Trade lastTrade = lastTradeDict[aTradeRecord.Symbol];
            if (lastTrade == null || lastTrade.Price <= 0)
            {
                Console.WriteLine(" {0} 在决断时未能获取价格", aTradeRecord.Symbol);
                continue;
            }
            //读取交易价格,这里使用了下1分钟内的第一笔交易,如果没有则继续找下一分钟
            List <Trade> trades;
            Trade        nextTrade = null;
            DateTime     curTime   = dealTime;
            DateTime     nextTime;
            do
            {
                nextTime = curTime.AddMinutes(1);
                string curTimeString  = Utils.FormatTime(curTime);
                string nextTimeString = Utils.FormatTime(nextTime);
                trades = this.provider.GetTrades(aTradeRecord.Symbol, curTimeString, nextTimeString);
                int i = 0;
                int m = trades.Count;
                if (m > 0)
                {
                    while (i < m && (trades[i].DateTime <= lastTrade.DateTime || trades[i].Price >= curDaily.High))          //防止以涨停价成交,因为这是买不到的
                    {
                        i++;
                    }
                    if (i < m)
                    {
                        nextTrade = trades[i];
                    }
                }
                curTime = nextTime;
            }while((nextTrade == null || nextTrade.Price <= 0) && curTime < closeTime);
            //如果没有可交易的价格
            if (nextTrade == null)
            {
                Console.WriteLine("Symbol {0} 在 {1} 时无法在今天内成交", aTradeRecord.Symbol, dealTime);
                aTradeRecord.PriceWhenDeal = 0.0;
                if (aTradeRecord.HoldingPeriod > 1)
                {
                    RandomTradeDBAccess.UpdateNextTradeDate(aTradeRecord._id, nextTradeDateString);
                }
                continue;
            }
            else
            {
                aTradeRecord.PriceWhenDeal      = nextTrade.Price;
                aTradeRecord.LowerPriceWhenDeal = ((GMTrade)nextTrade).Low;
                //修正周期为1时,成交后经历的最低价
                if (aTradeRecord.HoldingPeriod <= 1)
                {
                    trades = this.provider.GetTrades(aTradeRecord.Symbol, Utils.FormatTime(nextTrade.DateTime), Utils.FormatTime(closeTime));
                    aTradeRecord.LowerPriceWhenClose = nextTrade.Price;
                    foreach (Trade trade in trades)
                    {
                        if (trade.Price < aTradeRecord.LowerPriceWhenClose)
                        {
                            aTradeRecord.LowerPriceWhenClose = trade.Price;
                        }
                    }
                }
            }

            //读取应指数的日线和5分线,证券的日线和分线
            string indexSymbol = "";
            if (aTradeRecord.Symbol.IndexOf("SHSE.") >= 0)
            {
                indexSymbol = "SHSE.000001";
            }
            else if (aTradeRecord.Symbol.IndexOf("SZSE.3") >= 0)
            {
                indexSymbol = "SZSE.399006";
            }
            else
            {
                indexSymbol = "SZSE.399001";
            }

            List <Daily> indexDailys = BarFeeder.GetDailys(indexSymbol, Const.IndexDailyPeriod);
            List <Bar>   indexMin5s  = BarFeeder.GetBar5s(indexSymbol, Const.IndexMin5Period);
            //***这里多加了当天日线,便于向前复权,以修正价格
            List <Daily> stockDailys = BarFeeder.GetDailys(aTradeRecord.Symbol, Const.StockDailyPeriod, true, lastTrade);
            //日线不足周期数的忽略
            if (stockDailys.Count < Const.StockDailyPeriod)
            {
                continue;
            }
            List <Bar> stockMin5s = BarFeeder.GetBar5s(aTradeRecord.Symbol, Const.StockMin5Period);
            //昨天的收盘价
            double lastClose = stockDailys[stockDailys.Count - 2].Close;

            //计算当天的奖赏
            double rewardForInside  = 0.0;         //在场内的奖赏
            double rewardForOutside = 0.0;         //在场外的奖赏
            double riskForInside    = 0.0;
            double riskForOutside   = 0.0;

            if (aTradeRecord.HoldingPeriod == 1)
            {
                rewardForInside = Math.Log(aTradeRecord.PriceWhenClose / aTradeRecord.PriceWhenDeal);
                riskForInside   = Math.Log(aTradeRecord.LowerPriceWhenClose / aTradeRecord.PriceWhenDeal);
            }
            else if (aTradeRecord.HoldingPeriod > 1)
            {
                rewardForInside  = Math.Log(aTradeRecord.PriceWhenClose / lastClose);
                rewardForOutside = Math.Log(aTradeRecord.PriceWhenDeal / lastClose);
                riskForInside    = Math.Log(aTradeRecord.LowerPriceWhenClose / lastClose);
                riskForOutside   = Math.Log(aTradeRecord.LowerPriceWhenDeal / lastClose);
            }

            //正规化数据
            List <NormalBar> indexNormalDailys = BarUtils.NormalBars(indexDailys);
            List <NormalBar> indexNormalMin5s  = BarUtils.NormalBars(indexMin5s);
            List <NormalBar> stockNormalDailys = BarUtils.NormalBars(stockDailys);
            List <NormalBar> stockNormalMin5s  = BarUtils.NormalBars(stockMin5s);
            //封装reward
            BsonArray rewards = new BsonArray(2);
            rewards.Add(rewardForInside);
            rewards.Add(rewardForOutside);
            //封装risk
            BsonArray risks = new BsonArray(2);
            risks.Add(riskForInside);
            risks.Add(riskForOutside);
            //确定nextTradeDate
            string dateString = nextTradeDateString;
            if (aTradeRecord.HoldingPeriod >= Const.HoldingPeriodLimit)
            {
                dateString = "";
            }
            //写入数据库
            RandomTradeDBAccess.SaveRocord(dealDateString, aTradeRecord.Symbol, aTradeRecord.HoldingPeriod,
                                           BarUtils.BarsToBsonArray(indexNormalDailys), BarUtils.BarsToBsonArray(indexNormalMin5s),
                                           BarUtils.BarsToBsonArray(stockNormalDailys), BarUtils.BarsToBsonArray(stockNormalMin5s),
                                           rewards, risks, dateString);
        }
        Console.WriteLine("统计完毕。");
        ret = true;
        return(ret);
    }