/// <summary> /// моделировать поведение портфеля методом монте-карло /// возвращает массив: кол-во строк равно количеству percentiles /// в каждой строке intervalsCount значений по каждому перцентилю /// </summary> public static double[][] CalculateRisks(List <PortfolioActive> actives, double [][] corrM, List <double> sigmas, int intervalMinutes, int intervalsCount, int iterationsCount, List <double> percentiles, ReportProgressDel reportProgress) { // преобразование Холецкого var chM = CholeskyTransform(corrM, corrM.Length, corrM.Length); // массив: одна строка соотв. одному испытанию // ячейка i строки - накопленнный за i-интервалов профит, % var profitByDay = new float[intervalsCount][]; for (var i = 0; i < intervalsCount; i++) { profitByDay[i] = new float[iterationsCount]; } var lastPercent = 0; for (var i = 0; i < iterationsCount; i++) { if (stoppingCalculation) { stoppingCalculation = false; return(null); } var startPrices = actives.Select(a => a.Price).ToList(); for (var j = 0; j < intervalsCount; j++) { ShiftPrices(startPrices, chM, sigmas); // посчитать отклонение портфеля var profit = PortfolioActive.CalculateProfitPercent(actives, startPrices); profitByDay[j][i] = profit; } var percent = 100 * i / iterationsCount; if (percent - lastPercent >= 5) { reportProgress(string.Format(Localizer.GetString("MessagePortfolioSimulationCompletedPercentFmt"), percent)); lastPercent = percent; } } // посчитать перцентили var percents = new double[percentiles.Count][]; for (var i = 0; i < percentiles.Count; i++) { percents[i] = new double[intervalsCount]; } lastPercent = 0; for (var j = 0; j < intervalsCount; j++) { if (stoppingCalculation) { stoppingCalculation = false; return(null); } // упорядочить массив профитов на день (ну, вообще-то - на данный интервал времени) var intervalProfit = new EverSortedList <float>(); for (var i = 0; i < iterationsCount; i++) { intervalProfit.Add(profitByDay[j][i]); } // записать перцентили на интервал for (var i = 0; i < percentiles.Count; i++) { var index = (int)(iterationsCount * percentiles[i] / 100); percents[i][j] = intervalProfit[index]; if (j > 0) { if (Math.Abs(percents[i][j]) < Math.Abs(percents[i][j - 1])) { percents[i][j] = percents[i][j - 1]; } } } var percent = 100 * j / intervalsCount; if (percent - lastPercent >= 5) { reportProgress(string.Format(Localizer.GetString("MessageResultProcessingCompletedPercentFmt"), percent)); lastPercent = percent; } } return(percents); }
private void BtnEstimateRiskClick(object sender, EventArgs e) { if (!AccountStatus.Instance.isAuthorized || AccountStatus.Instance.AccountData == null) { MessageBox.Show(EnumFriendlyName<RequestStatus>.GetString(RequestStatus.Unauthorized)); return; } var orders = MarketOrdersStorage.Instance.MarketOrders; if (orders.Count == 0) { MessageBox.Show(Localizer.GetString("MessageNoOpenPositions")); return; } var summary = PositionSummary.GetPositionSummary(orders, AccountCurrency, (float)AccountStatus.Instance.AccountData.Balance); var portfolio = new List<PortfolioActive>(); foreach (var pos in summary) { if (string.IsNullOrEmpty(pos.Symbol)) continue; var act = new PortfolioActive {Ticker = pos.Symbol, Side = pos.Side, Leverage = pos.Leverage, Price = pos.AveragePrice }; portfolio.Add(act); } var dlg = new PortfolioRiskForm {portfolio = portfolio}; dlg.ShowDialog(); }