public void Initialize() { using (var context = new QTContext()) { _universe = context.Universe.Where(x => x.FirstDate != null).ToList(); _universe.ForEach(x => { AssetManager.Instance.AddAsset(x.AssetCode, x.AssetName); }); } }
public List <Subject> GetUniverse(string country, string exchange) { if (exchange == null) { return(_universe.Where(x => x.Country == country && x.MarketCap > 0).ToList()); } else { if (exchange.Contains("FX")) { var universe = _universe.Where(x => x.Country == country && x.Exchange == "FX").ToList(); using (var context = new QTContext()) { if (exchange == "FX_1d") { universe.ForEach(subject => { subject.FirstDate = context.FX1D.Where(x => x.AssetCode == subject.AssetCode).Min(x => x.CreatedAt); }); } else if (exchange == "FX_1w") { universe.ForEach(subject => { subject.FirstDate = context.FX1W.Where(x => x.AssetCode == subject.AssetCode).Min(x => x.CreatedAt); }); } else if (exchange == "FX_60m") { universe.ForEach(subject => { subject.FirstDate = context.FX60M.Where(x => x.AssetCode == subject.AssetCode).Min(x => x.CreatedAt); }); } } return(universe); } else { return(_universe.Where(x => x.Country == country && x.Exchange == exchange && x.MarketCap > 0).ToList()); } } }
private List <DateTime> CreateCalendar(DateTime start, DateTime end, string country) { var tradingCalendar = new List <DateTime>(); using (var context = new QTContext()) { if (country.Contains("FX")) { tradingCalendar = context.TradingCalendars.Where(x => x.TradingDate >= start && x.TradingDate <= end && x.IsoCode == country).Select(x => x.TradingDate).ToList(); } else { tradingCalendar = context.TradingCalendars.Where(x => x.TradingDate >= start && x.TradingDate <= end && x.Country == country && !x.IsoCode.Contains("FX")) .Select(x => x.TradingDate).ToList(); } } return(tradingCalendar); }
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); }
public ActionResult <ResOpenPrice> OpenPrice([FromBody] ReqOpenPrice request) { if (!Validate(request.StartDate)) { return(null); } var date = DateTime.ParseExact(request.StartDate, "yyyy-MM-dd", CultureInfo.InvariantCulture); using (var context = new QTContext()) { var response = new ResOpenPrice(); foreach (var asset in request.Assets) { if (asset.AssetCode == "JP225") { var index = context.Indices .Where(x => x.CreatedAt >= date && x.AssetCode == asset.AssetCode) .OrderBy(x => x.CreatedAt) .Take(10) // date가 실제 트레이딩 날짜가 아닐 수 있기 때문에 최대 10일 뒤의 데이터를 가져온다.(10일간 거래를 안할 수 없다는 가정) .FirstOrDefault(); var indexCopy = new Index() { CreatedAt = index.CreatedAt, AssetCode = index.AssetCode, AssetName = index.AssetName, Close = index.Close, Open = index.Open, High = index.High, Low = index.Low, Volume = index.Volume }; // 분할정보 var splits = context.Splits.Where(x => x.AssetCode == asset.AssetCode).ToList(); // 분할적용 splits.ForEach(split => { if (indexCopy.CreatedAt < split.SplitDate) { indexCopy.Open = indexCopy.Open / split.SplitRatio; indexCopy.High = indexCopy.High / split.SplitRatio; indexCopy.Low = indexCopy.Low / split.SplitRatio; indexCopy.Close = indexCopy.Close / split.SplitRatio; } }); response.Data.Add(new ResOpenPrice.Context { AssetCode = asset.AssetCode, AssetName = AssetManager.Instance.GetAssetName(asset.AssetCode), Exchange = asset.Exchange, Date = indexCopy.CreatedAt, OpenPrice = indexCopy.Open, }); } else if (asset.AssetCode == "KOSPI") { var index = context.KoreaIndices .Where(x => x.CreatedAt >= date && x.AssetCode == asset.AssetCode) .OrderBy(x => x.CreatedAt) .Take(10) // date가 실제 트레이딩 날짜가 아닐 수 있기 때문에 최대 10일 뒤의 데이터를 가져온다.(10일간 거래를 안할 수 없다는 가정) .FirstOrDefault(); var indexCopy = new KoreaIndex() { CreatedAt = index.CreatedAt, AssetCode = index.AssetCode, Close = index.Close, Open = index.Open, High = index.High, Low = index.Low, Volume = index.Volume }; response.Data.Add(new ResOpenPrice.Context { AssetCode = asset.AssetCode, AssetName = AssetManager.Instance.GetAssetName(asset.AssetCode), Exchange = asset.Exchange, Date = indexCopy.CreatedAt, OpenPrice = indexCopy.Open, }); } else if (asset.Exchange == "TSE" || asset.Exchange == "ETF" || asset.Exchange == "NIKKEI") { var stock = context.Stocks .Where(x => x.CreatedAt >= date && x.AssetCode == asset.AssetCode) .OrderBy(x => x.CreatedAt) .Take(10) // date가 실제 트레이딩 날짜가 아닐 수 있기 때문에 최대 10일 뒤의 데이터를 가져온다.(10일간 거래를 안할 수 없다는 가정) .FirstOrDefault(); var stockCopy = new Stock { CreatedAt = stock.CreatedAt, AssetCode = stock.AssetCode, Close = stock.Close, Open = stock.Open, High = stock.High, Low = stock.Low, Volume = stock.Volume }; // 분할정보 var splits = context.Splits.Where(x => x.AssetCode == asset.AssetCode).ToList(); // 분할적용 splits.ForEach(split => { if (stockCopy.CreatedAt < split.SplitDate) { stockCopy.Open = stockCopy.Open / split.SplitRatio; stockCopy.High = stockCopy.High / split.SplitRatio; stockCopy.Low = stockCopy.Low / split.SplitRatio; stockCopy.Close = stockCopy.Close / split.SplitRatio; } }); response.Data.Add(new ResOpenPrice.Context { AssetCode = asset.AssetCode, AssetName = AssetManager.Instance.GetAssetName(asset.AssetCode), Exchange = asset.Exchange, Date = stockCopy.CreatedAt, OpenPrice = stockCopy.Open, }); } else if (asset.Exchange == "KOSPI" || asset.Exchange == "KOSDAQ") { var stock = context.KoreaStocks .Where(x => x.CreatedAt >= date && x.AssetCode == asset.AssetCode) .OrderBy(x => x.CreatedAt) .Take(10) // date가 실제 트레이딩 날짜가 아닐 수 있기 때문에 최대 10일 뒤의 데이터를 가져온다.(10일간 거래를 안할 수 없다는 가정) .FirstOrDefault(); var stockCopy = new KoreaStock { CreatedAt = stock.CreatedAt, AssetCode = stock.AssetCode, Close = stock.Close, Open = stock.Open, High = stock.High, Low = stock.Low, Volume = stock.Volume }; response.Data.Add(new ResOpenPrice.Context { AssetCode = asset.AssetCode, AssetName = AssetManager.Instance.GetAssetName(asset.AssetCode), Exchange = asset.Exchange, Date = stockCopy.CreatedAt, OpenPrice = stockCopy.Open, }); } else if (asset.Exchange == "FX_1D") { var fx = context.FX1D .Where(x => x.CreatedAt >= date && x.AssetCode == asset.AssetCode) .OrderBy(x => x.CreatedAt) .Take(10) // date가 실제 트레이딩 날짜가 아닐 수 있기 때문에 최대 10일 뒤의 데이터를 가져온다.(10일간 거래를 안할 수 없다는 가정) .FirstOrDefault(); var fxCopy = new FX1D { CreatedAt = fx.CreatedAt, AssetCode = fx.AssetCode, Close = fx.Close, Open = fx.Open, High = fx.High, Low = fx.Low, Volume = 0 }; response.Data.Add(new ResOpenPrice.Context { AssetCode = asset.AssetCode, AssetName = AssetManager.Instance.GetAssetName(asset.AssetCode), Exchange = asset.Exchange, Date = fxCopy.CreatedAt, OpenPrice = fxCopy.Open, }); } else if (asset.Exchange == "FX_1W") { var fx = context.FX1W .Where(x => x.CreatedAt >= date && x.AssetCode == asset.AssetCode) .OrderBy(x => x.CreatedAt) .Take(10) // date가 실제 트레이딩 날짜가 아닐 수 있기 때문에 최대 10일 뒤의 데이터를 가져온다.(10일간 거래를 안할 수 없다는 가정) .FirstOrDefault(); var fxCopy = new FX1W { CreatedAt = fx.CreatedAt, AssetCode = fx.AssetCode, Close = fx.Close, Open = fx.Open, High = fx.High, Low = fx.Low, Volume = 0 }; response.Data.Add(new ResOpenPrice.Context { AssetCode = asset.AssetCode, AssetName = AssetManager.Instance.GetAssetName(asset.AssetCode), Exchange = asset.Exchange, Date = fxCopy.CreatedAt, OpenPrice = fxCopy.Open, }); } else if (asset.Exchange == "FX_60M") { var fx = context.FX60M .Where(x => x.CreatedAt >= date && x.AssetCode == asset.AssetCode) .OrderBy(x => x.CreatedAt) .Take(10) // date가 실제 트레이딩 날짜가 아닐 수 있기 때문에 최대 10일 뒤의 데이터를 가져온다.(10일간 거래를 안할 수 없다는 가정) .FirstOrDefault(); var fxCopy = new FX60M { CreatedAt = fx.CreatedAt, AssetCode = fx.AssetCode, Close = fx.Close, Open = fx.Open, High = fx.High, Low = fx.Low, Volume = 0 }; response.Data.Add(new ResOpenPrice.Context { AssetCode = asset.AssetCode, AssetName = AssetManager.Instance.GetAssetName(asset.AssetCode), Exchange = asset.Exchange, Date = fxCopy.CreatedAt, OpenPrice = fxCopy.Open, }); } } return(response); } }
public void Run() { using (var context = new QTContext()) { var universe = context.Universe.Where(x => int.Parse(x.AssetCode) < 2201).ToList(); var sql = ""; foreach (var subject in universe) { var tradingDataset = new List <ITradingData>(); // 분할정보 var splits = context.Splits.Where(x => x.AssetCode == subject.AssetCode).ToList(); if (0 < splits.Count) { // 원본 var stock = context.Stocks.Where(x => x.AssetCode == subject.AssetCode).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(); // 분할적용 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)); var year1 = tradingDataset.Where(x => x.CreatedAt >= DateTime.Now.AddYears(-1)).ToList(); var year3 = tradingDataset.Where(x => x.CreatedAt >= DateTime.Now.AddYears(-3)).ToList(); var year5 = tradingDataset.Where(x => x.CreatedAt >= DateTime.Now.AddYears(-5)).ToList(); var year7 = tradingDataset.Where(x => x.CreatedAt >= DateTime.Now.AddYears(-7)).ToList(); var year10 = tradingDataset.Where(x => x.CreatedAt >= DateTime.Now.AddYears(-10)).ToList(); var rate1 = (year1.Max(x => x.High) - year1.Min(x => x.Low)) / year1.Min(x => x.Low); var rate3 = (year3.Max(x => x.High) - year3.Min(x => x.Low)) / year3.Min(x => x.Low); var rate5 = (year5.Max(x => x.High) - year5.Min(x => x.Low)) / year5.Min(x => x.Low); var rate7 = (year7.Max(x => x.High) - year7.Min(x => x.Low)) / year7.Min(x => x.Low); var rate10 = (year10.Max(x => x.High) - year10.Min(x => x.Low)) / year10.Min(x => x.Low); subject.RecentVolatility1Year = rate1; subject.RecentVolatility3Year = rate3; subject.RecentVolatility5Year = rate5; subject.RecentVolatility7Year = rate7; subject.RecentVolatility10Year = rate10; sql += $@"UPDATE qt.japan_universe SET recent_volatility_1_year = {rate1}, recent_volatility_3_year = {rate3}, recent_volatility_5_year = {rate5}, recent_volatility_7_year = {rate7}, recent_volatility_10_year = {rate10} WHERE asset_code = {subject.AssetCode};"; Console.WriteLine($"{subject.AssetCode}"); } } context.Database.ExecuteSqlCommand(sql); // context.SaveChanges(); } }