public void TestPackUnpack() { // подготовить липу var lstEq = new List <EquityOnTime>(); var timeStart = DateTime.Now.Date.AddDays(-190); var timeEnd = DateTime.Now.Date; var i = 0; for (var date = timeStart; date < timeEnd; date = date.AddDays(1)) { var y = 1.5 + Math.Sin(i++ / 20.0); lstEq.Add(new EquityOnTime((float)y, date)); } // упаковать var chartMini = MiniChartPacker.PackChartInArray(lstEq); Assert.Greater(chartMini.Length, 0, "Chart is not empty"); var min = chartMini.Min(); var max = chartMini.Max(); Assert.Greater(max - min, 250, "Chart range is close to 255"); // распаковать var points = MiniChartPacker.MakePolygon(chartMini, 60, 30, 2, 2); Assert.AreEqual(chartMini.Length + 2, points.Length, "unpacked has the same size"); }
public void DataBind(List <PerformerStatEx> performerStats, ChatControlBackEnd chat) { var images = imgListChartMini.Images.Cast <Image>().ToList(); imgListChartMini.Images.Clear(); foreach (var img in images) { img.Dispose(); } var data = new List <PerformerStatEx>(); // UserScore вычисляется на сервере // RecalcUserScore(performerStats); var userInfoExSource = new UserInfoExCache(TradeSharpAccountStatistics.Instance.proxy); var usersInfoEx = userInfoExSource.GetUsersInfo(performerStats.Select(p => p.UserId).Distinct().ToList()); var rowColors = new[] { Color.Red, Color.ForestGreen, Color.Black }; var stringFormat = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }; using (var font = new Font(Font.FontFamily, 7)) foreach (var performerStat in performerStats) { // создать картинку с графиком var bmp = new Bitmap(imgListChartMini.ImageSize.Width, imgListChartMini.ImageSize.Height); if (performerStat.Chart != null) { using (var gr = Graphics.FromImage(bmp)) { var leftValue = performerStat.AvgYearProfit; var leftText = string.Format("{0:f2}%", leftValue); var leftTextWidth = gr.MeasureString(leftText, font).ToSize().Width; var rightValue = performerStat.ProfitLastMonthsAbs; var rightText = rightValue.ToStringUniformMoneyFormat(false); var textWidth = leftTextWidth + gr.MeasureString(rightText, font).ToSize().Width; if (!ShowLabelsInMiniChart) { textWidth = 0; } PointF[] points; if (ChartBrush != null) { points = MiniChartPacker.MakePolygon(performerStat.Chart, imgListChartMini.ImageSize.Width - textWidth, imgListChartMini.ImageSize.Height, 1, 1); } else { points = MiniChartPacker.MakePolyline(performerStat.Chart, imgListChartMini.ImageSize.Width - textWidth, imgListChartMini.ImageSize.Height, 1, 1); } gr.SmoothingMode = SmoothingMode.AntiAlias; gr.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; if (ShowLabelsInMiniChart) { for (var i = 0; i < points.Length; i++) { points[i] = new PointF(points[i].X + leftTextWidth, points[i].Y); } gr.DrawString(leftText, font, new SolidBrush(leftValue >= 0 ? rowColors[1] : rowColors[0]), 0, imgListChartMini.ImageSize.Height / 2, stringFormat); gr.DrawString(rightText, font, new SolidBrush(rightValue >= 0 ? rowColors[1] : rowColors[0]), imgListChartMini.ImageSize.Width - textWidth + leftTextWidth, imgListChartMini.ImageSize.Height / 2, stringFormat); } if (ChartBrush != null) { gr.FillPolygon(ChartBrush, points); } else { gr.DrawLines(ChartPen ?? new Pen(leftValue >= 0 ? rowColors[1] : rowColors[0], 2), points); } } } var item = new PerformerStatEx(performerStat) { ChartIndex = imgListChartMini.Images.Count }; imgListChartMini.Images.Add(bmp); imgListChartMini.Images.SetKeyName(item.ChartIndex, item.ChartIndex.ToString()); // создать фотку UserInfoEx userInfoEx = null; if (usersInfoEx != null) { userInfoEx = usersInfoEx.Find(ui => ui != null && ui.Id == performerStat.UserId); } if (userInfoEx != null && userInfoEx.AvatarSmall != null) { item.AvatarSmallIndex = imgListAvatar.Images.Count; imgListAvatar.Images.Add(userInfoEx.AvatarSmall); imgListAvatar.Images.SetKeyName(item.AvatarSmallIndex, item.AvatarSmallIndex.ToString()); } else { item.AvatarSmallIndex = -1; } data.Add(item); } grid.DataBind(data); grid.Invalidate(); if (this.chat != null) { this.chat.RoomsReceived -= RoomsReceived; } this.chat = chat; if (chat == null) { return; } chat.RoomsReceived += RoomsReceived; chat.GetRooms(); }
public bool Calculate(AccountEfficiency ef) { if (ef == null) { throw new ArgumentException("EfficiencyCalculator.Calculate - input ptr is NULL"); } if (ef.Statistics.Account == 0) { throw new ArgumentException("EfficiencyCalculator.Calculate - input_ptr.AccountId is 0"); } // получить сделки var deals = DealStorage.Instance.GetDeals(ef.Statistics.Account); ef.openedDeals = new List <MarketOrder>(); ef.closedDeals = new List <MarketOrder>(); foreach (var deal in deals) { if (deal.IsOpened) { ef.openedDeals.Add(deal); } else { ef.closedDeals.Add(deal); } } if (deals.Count == 0) { Logger.Info("AccountEfficiency.Calculate - нет сделок"); return(false); } ef.Statistics.DealsCount = deals.Count; ef.DealsStillOpened = ef.openedDeals.Count; // транзакции ef.listTransaction = BalanceStorage.Instance.GetBalanceChanges(ef.Statistics.Account); if (ef.listTransaction == null || ef.listTransaction.Count == 0) { Logger.Info("AccountEfficiency.Calculate - нет транзакций"); return(false); } Logger.Info("AccountEfficiency.Calculate(" + ef.Statistics.Account + ")"); // время отсчета - время первого заведения средств var startDate = ef.listTransaction.Min(t => t.ValueDate); // получить список используемых котировок var symbolsUsed = ef.closedDeals.Select(d => d.Symbol).Union(ef.openedDeals.Select(o => o.Symbol)).Distinct().ToList(); // ... в т.ч., котировок для перевода базовой валюты в валюту депо (плечо) // и перевода контрвалюты в валюту депо (профит) var symbolsMore = new List <string>(); foreach (var smb in symbolsUsed) { bool inverse, eq; var smbBase = DalSpot.Instance.FindSymbol(smb, true, ef.Statistics.DepoCurrency, out inverse, out eq); if (!string.IsNullOrEmpty(smbBase)) { symbolsMore.Add(smbBase); } var smbCounter = DalSpot.Instance.FindSymbol(smb, false, ef.Statistics.DepoCurrency, out inverse, out eq); if (!string.IsNullOrEmpty(smbCounter)) { symbolsMore.Add(smbCounter); } } symbolsUsed.AddRange(symbolsMore); symbolsUsed = symbolsUsed.Distinct().ToList(); // котировки var dicQuote = new Dictionary <string, List <QuoteData> >(); foreach (var smb in symbolsUsed) { dicQuote.Add(smb, dailyQuoteStorage.GetQuotes(smb).Select(q => new QuoteData(q.b, q.b, q.a)).ToList()); } //TickerStorage.Instance.GetQuotes(symbolsUsed.ToDictionary(s => s, s => (DateTime?)null)); if (dicQuote == null || dicQuote.Count == 0) { Logger.Info("AccountEfficiency.Calculate - нет котировок"); return(false); } if (ef.openedDeals.Count > 0) { foreach (var t in ef.openedDeals) { List <QuoteData> dicQuoteValue; if (!dicQuote.TryGetValue(t.Symbol, out dicQuoteValue)) { Logger.Error(String.Format("Symbol {0} was not found in dicQuote", t.Symbol)); } else if (dicQuoteValue.Count == 0) { Logger.Error(String.Format("No quote data for symbol {0}", t.Symbol)); } else { t.PriceExit = dicQuoteValue.Last().GetPrice(t.Side == 1 ? QuoteType.Bid : QuoteType.Ask); } } } var quoteArc = new QuoteArchive(dicQuote); AccountPerformanceRaw performance; try { performance = equityCurveCalculator.CalculateEquityCurve(deals, ef.Statistics.DepoCurrency, quoteArc, ef.listTransaction); } catch (Exception ex) { Logger.Error("Ошибка в EfficiencyCalculator.CalculateEquityCurve()", ex); return(false); } ef.Statistics.TotalTradedInDepoCurrency = performance.totalTradedVolume; var lstEquity = performance.equity; if (lstEquity == null) { return(false); } ef.listLeverage = performance.leverage; // исключить пустые значения с начала отсчета ef.listEquity = new List <EquityOnTime>(); var startCopy = false; foreach (var eq in lstEquity) { if (eq.equity > 0) { startCopy = true; } if (startCopy) { ef.listEquity.Add(eq); } } if (ef.listEquity.Count == 0) { return(false); } ef.StartDate = startDate; ef.InitialBalance = ef.listEquity[0].equity; // рассчитать коэффициенты доходности CalculateProfitCoeffs(ef); CalculateRiskCoeffs(ef); // актуальные котировки ef.currentQuotes = quoteArc.GetCurrentQuotes(); ef.Statistics.Chart = ef.listProfit1000 == null || ef.listProfit1000.Count == 0 ? new byte[MiniChartPacker.profitChartPointCount] : MiniChartPacker.PackChartInArray(ef.listProfit1000); // дней торгует var startDayOpen = DateTime.Now; if (ef.openedDeals.Count > 0) { startDayOpen = ef.openedDeals.Max(d => d.TimeEnter); } if (ef.closedDeals.Count > 0) { var dateClosed = ef.closedDeals.Min(d => d.TimeEnter); if (dateClosed < startDayOpen) { startDayOpen = dateClosed; } } ef.Statistics.DaysTraded = (int)Math.Round((DateTime.Now - startDayOpen).TotalDays); // сумма профитных сделок (результат) к сумме убыточных сделок var sumProf = ef.closedDeals.Sum(d => d.ResultDepo > 0 ? d.ResultDepo : 0) + ef.openedDeals.Sum(d => d.ResultDepo > 0 ? d.ResultDepo : 0); var sumLoss = ef.closedDeals.Sum(d => d.ResultDepo > 0 ? d.ResultDepo : 0) + ef.openedDeals.Sum(d => d.ResultDepo > 0 ? d.ResultDepo : 0); ef.Statistics.AvgWeightedDealProfitToLoss = sumLoss == 0 && sumProf == 0 ? 0 : 100 * sumProf / (sumProf + sumLoss); var dateFirst = DateTime.Now.Date.AddMonths(-3); ef.Statistics.WithdrawalLastMonths = (float)ef.listTransaction.Sum(t => (t.ChangeType == BalanceChangeType.Withdrawal && t.ValueDate >= dateFirst) ? t.AmountDepo : 0); // профит в ПП ef.Statistics.SumProfitPoints = ef.closedDeals.Sum(d => d.ResultPoints); return(true); }