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());
                }
            }
        }
示例#3
0
        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);
        }
示例#4
0
        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);
            }
        }
示例#5
0
        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();
            }
        }