private void RunBenchmark(ReqAnalyzePortfolio request, BacktestingProperty property, DateTime startDate, DateTime endDate, List <DateTime> tradingCalendar, List <Report> reports) { var simulator = new Simulator(); using (var context = new QTContext()) { var assetCode = request.Benchmark.AssetCode; var tradingDataset = new Dictionary <DateTime, ITradingData>(); var benchmarkDataset = new Dictionary <string, Dictionary <DateTime, ITradingData> >(); if (request.Country == "JP") { var index = context.Indices.Where(x => x.AssetCode == assetCode && x.CreatedAt >= startDate && x.CreatedAt <= endDate); if (0 < index.Count()) { index.ToList().ForEach(x => tradingDataset.Add(x.CreatedAt, x)); } } else if (request.Country == "KR") { var index = context.KoreaIndices.Where(x => x.AssetCode == assetCode && x.CreatedAt >= startDate && x.CreatedAt <= endDate); if (0 < index.Count()) { index.ToList().ForEach(x => tradingDataset.Add(x.CreatedAt, x)); } } benchmarkDataset.Add(assetCode, tradingDataset); var strategy = new BuyAndHold(); var benchmark = new Dictionary <string, PortfolioSubject>(); benchmark.Add(assetCode, request.Benchmark); var report = strategy.Run(benchmarkDataset, tradingCalendar, property, benchmark, period: Period.Day, isBenchmark: true); reports.Add(report); } }
public List <Report> AnalyzePortfolio(ReqAnalyzePortfolio request, bool analyzeBenchmark = true) { var period = Period.Day; if (request.Country == null) { request.Country = "JP"; } var startDate = DateTime.ParseExact(request.StartDate, "yyyy-MM-dd", CultureInfo.InvariantCulture); var endDate = DateTime.ParseExact(request.EndDate, "yyyy-MM-dd", CultureInfo.InvariantCulture); BacktestingProperty property = new BacktestingProperty() { Start = startDate, End = endDate, Capital = request.Capital, BenchmarkType = BenchmarkType.Nikkei225, CommissionType = request.CommissionType == "Ratio" ? CommissionType.Ratio : CommissionType.Fixed, Commission = request.Commission, SlippageType = request.SlippageType == "Ratio" ? SlippageType.Ratio : SlippageType.Fixed, Slippage = request.Slippage, BuyAndHold = true, VolatilityBreakout = true, MovingAverage = true, UseOutstandingBalance = request.AllowLeverage, UsePointVolume = request.AllowDecimalPoint, TradeType = request.OrderVolumeType == "Ratio" ? TradeType.Ratio : TradeType.Fixed }; var strategies = new Dictionary <StrategyType, StrategyBase>(); if (request.UseBuyAndHold) { strategies.Add(StrategyType.BuyAndHold, new BuyAndHold()); } if (request.UseVolatilityBreakout) { strategies.Add(StrategyType.VolatilityBreakout, new VolatilityBreakout()); } if (request.UseMovingAverage) { strategies.Add(StrategyType.MovingAverage, new MovingAverage()); } // 각 종목별 OHLC 데이터 var portfolioDataset = new Dictionary <string, Dictionary <DateTime, ITradingData> >(); foreach (var subject in request.Portfolio) { var tradingDataset = new Dictionary <DateTime, ITradingData>(); using (var context = new QTContext()) { if (request.Country == "FX_1D") { period = Period.Day; var fx = context.FX1D.Where(x => x.AssetCode == subject.AssetCode && x.CreatedAt >= startDate && x.CreatedAt <= endDate).ToList(); var fxCopy = fx.Select(x => new Stock { CreatedAt = x.CreatedAt, AssetCode = x.AssetCode, Close = x.Close, Open = x.Open, High = x.High, Low = x.Low, Volume = 0 }).ToList(); fxCopy.ForEach(x => tradingDataset.Add(x.CreatedAt, x)); } else if (request.Country == "FX_1W") { period = Period.Week; var fx = context.FX1W.Where(x => x.AssetCode == subject.AssetCode && x.CreatedAt >= startDate && x.CreatedAt <= endDate).ToList(); var fxCopy = fx.Select(x => new Stock { CreatedAt = x.CreatedAt, AssetCode = x.AssetCode, Close = x.Close, Open = x.Open, High = x.High, Low = x.Low, Volume = 0 }).ToList(); fxCopy.ForEach(x => tradingDataset.Add(x.CreatedAt, x)); } else if (request.Country == "FX_60M") { period = Period.Min60; var fx = context.FX60M.Where(x => x.AssetCode == subject.AssetCode && x.CreatedAt >= startDate && x.CreatedAt <= endDate).ToList(); var fxCopy = fx.Select(x => new Stock { CreatedAt = x.CreatedAt, AssetCode = x.AssetCode, Close = x.Close, Open = x.Open, High = x.High, Low = x.Low, Volume = 0 }).ToList(); fxCopy.ForEach(x => tradingDataset.Add(x.CreatedAt, x)); } else if (request.Country == "JP") { // 원본 var stock = context.Stocks.Where(x => x.AssetCode == subject.AssetCode && x.CreatedAt >= startDate && x.CreatedAt <= endDate).ToList(); var stockCopy = stock.Select(x => new Stock { CreatedAt = x.CreatedAt, AssetCode = x.AssetCode, Close = x.Close, Open = x.Open, High = x.High, Low = x.Low, Volume = x.Volume }).ToList(); // 분할정보 var splits = context.Splits.Where(x => x.AssetCode == subject.AssetCode).ToList(); // 분할적용 splits.ForEach(split => { foreach (var s in stockCopy.Where(x => x.CreatedAt < split.SplitDate)) { s.Open = s.Open / split.SplitRatio; s.High = s.High / split.SplitRatio; s.Low = s.Low / split.SplitRatio; s.Close = s.Close / split.SplitRatio; } }); stockCopy.ForEach(x => tradingDataset.Add(x.CreatedAt, x)); } else if (request.Country == "KR") { var stock = context.KoreaStocks.Where(x => x.AssetCode == subject.AssetCode && x.CreatedAt >= startDate && x.CreatedAt <= endDate).ToList(); var stockCopy = stock.Select(x => new Stock { CreatedAt = x.CreatedAt, AssetCode = x.AssetCode, Close = x.Close, Open = x.Open, High = x.High, Low = x.Low, Volume = x.Volume }).ToList(); stockCopy.ForEach(x => tradingDataset.Add(x.CreatedAt, x)); } } portfolioDataset.Add(subject.AssetCode, tradingDataset); } var tradingCalendar = CreateCalendar(startDate, endDate, request.Country); var reports = new List <Report>(); // benchmark if (analyzeBenchmark) { RunBenchmark(request, property, startDate, endDate, tradingCalendar, reports); } // portfolio var portfolio = request.Portfolio.ToDictionary(x => x.AssetCode, x => x); foreach (var strategy in strategies.Values) { var report = strategy.Run(portfolioDataset, tradingCalendar, property, portfolio, period); reports.Add(report); } return(reports); }