public override void OnInit() { //读取日线,计算持仓周期 if (HasPosition) { DateTime curDate = Clock.Now.Date; List <Daily> dailyBars = BarUtils.GetLastNDailys(this.instrument, curDate.AddDays(-1), 40); BarUtils.AdjustDailys(dailyBars); //向前复权 int n = dailyBars.Count; if (n > 0) { int i; for (i = n - 1; i >= 0; i--) { if (dailyBars[i].DateTime <= Position.EntryDate.Date) { break; } } if (dailyBars[i].DateTime < Position.EntryDate.Date) { i++; } if (i < 0) { i = 0; } this.holdingPeriod = n - i + 1; } this.stopLossPrice = Position.EntryPrice * (1 - stopLossRate); } Console.WriteLine("投资组合中的证券 {0} 的持仓周期是 {1} ", this.instrument.Symbol, this.holdingPeriod); }
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); }
// public static IList<double> Decompress(this ISecurity sec, IReadOnlyList<double> data, IMemoryManagement mm = null, // IReadOnlyList<double> increment = null) // { // return Decompress(sec.P) // } public static IList <double> Decompress <T>(IReadOnlyList <T> originalBars, Interval curInterval, IReadOnlyList <double> data, IReadOnlyList <double> increment, Interval dataInterval, IReadOnlyList <T> compressedBars = null, IMemoryManagement mm = null) where T : class, IBaseBar { if (originalBars == null) { throw new ArgumentNullException(nameof(originalBars)); } if (data == null) { throw new ArgumentNullException(nameof(data)); } var count = originalBars.Count; if (compressedBars == null) { compressedBars = BarUtils.CompressTo(originalBars, dataInterval, curInterval); } var newBars = mm?.GetArray <double>(count) ?? new double[count]; var dataIntervalShift = dataInterval.Shift; var shift = (dataIntervalShift - curInterval.Shift).Ticks; var step = curInterval.Shift.Ticks; var steps = dataIntervalShift.Ticks / step; var k = -1; var ticks = 0L; for (var i = 0; i < originalBars.Count; i++) { var bar = originalBars[i]; var t = bar.Ticks; while (t >= ticks + shift && k < data.Count - 1) { var index = Math.Min(++k + 1, compressedBars.Count - 1); ticks = compressedBars[index].Ticks; } var curStep = (ticks - t - shift) / step + 1; var ci = Math.Max(k, 0); newBars[i] = data[ci] - increment[ci] * ((double)curStep / steps + 2); } return(newBars); }
//如果本地有日线,则先读取本地数据 public static List <Daily> GetLastNDailys(string symbol, int n) { List <Daily> dailys; Instrument inst = InstrumentManager.Instruments[symbol]; if (inst != null) { dailys = BarUtils.GetLastNDailys(inst, dealDate, n); } else { dailys = provider.GetLastNDailys(symbol, n, dealDateString); } return(dailys); }
private static void ReviseDailys(List <Daily> dailys, string symbol, Trade lastTrade) { GMTrade gmTrade = (GMTrade)lastTrade; //去掉当天日线后 int m = dailys.Count; if (dailys[m - 1].DateTime == dealDate) { BarUtils.CoverDailyFormTrade(dailys[m - 1], gmTrade); } else { dailys.RemoveAt(0); GMDaily newDaily = new GMDaily(dailys[m - 2] as GMDaily); BarUtils.CoverDailyFormTrade(newDaily, gmTrade); dailys.Add(newDaily); } //向前复权 BarUtils.AdjustDailys(dailys); }
public override void NewSymbolBar(Symbol symbol, BarData bar) { Symbol symbol1 = SystemData.Symbols[0]; Symbol symbol2 = SystemData.Symbols[1]; // Get the current prices for both symbols double close1 = BarUtils.LastValidBar(SystemData.BarCollections[symbol1]).Close; double close2 = BarUtils.LastValidBar(SystemData.BarCollections[symbol2]).Close; // make sure we only process the loop once per bar if (symbol1 == symbol) { // Use the "SpreadThreshold" optimization variable configured in the System Properties window if ((close1 * 3) - (close2 * 2) <= SystemData.SystemParameters["SpreadThreshold"]) { OpenPosition(symbol1, PositionType.Long, OrderType.Market, 0, 3); OpenPosition(symbol2, PositionType.Short, OrderType.Market, 0, 2); } } // Analyze each position for profit double totalProfit = 0.0; foreach (Position position in PositionManager.GetOpenPositions()) { totalProfit += position.CurStats.RealizedProfit; } if (totalProfit >= SystemData.SystemParameters["ProfitThreshold"]) { // Loop through one last time and close all positions foreach (Position pos in PositionManager.GetOpenPositions()) { PositionManager.ClosePosition(pos.PosID); } } // This line of code runs the actions you have set up in in the Project Form Actions.RunActions(symbol); }
public ISecurity CompressToVolume(Interval interval) { var bars = BarUtils.CompressToVolume(Bars, interval); return(CompressTo(interval, bars)); }
public ISecurity CompressTo(Interval interval, int shift, int adjustment, int adjShift) { var bars = BarUtils.CompressTo(Bars, interval, IntervalInstance, 0, shift, adjustment, adjShift); return(CompressTo(interval, bars)); }
public ISecurity CompressToPriceRange(Interval interval) { var bars = BarUtils.CompressToPriceRange(Bars, interval, Tick); return(CompressTo(interval, bars)); }
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); }