/// <summary> /// Получает информацию по объемам текущей свечки /// </summary> /// <param name="crossLine"></param> /// <param name="activeCandle"></param> /*public void GetValueVolume(Point crossLine, GCandles.CandleInfo activeCandle) * { * decimal priceY = GMath.GetValueFromCoordinate(Panel.Rect.Height, Panel.Params.MaxPrice, Panel.Params.MinPrice, crossLine.Y, Panel.Params.CountFloat); * Curr * var hv = activeCandle.Candle.GetHorVolumes().HVolCollection.ToArray().FirstOrDefault(v => v.Price == priceY); * if (hv.NotIsNull()) * { * if (priceY == hv.Price) * { * if (hv.Price == priceY) activeCandle.Description = (hv.VolBuy + hv.VolSell).ToString(); * activeCandle.CurHorVolume = new ChartFull() { Price = priceY, VolBuy = hv.VolBuy, VolSell = hv.VolSell }; * } * } * }*/ /// <summary> /// Обработчик каждой свечки /// </summary> /// <param name="dataCandle"></param> public void EachCandle(CandleInfo dataCandle) { if (dataCandle.Index == 0) { PrepDataHorVol = new PrepareHorVol(); PrepDataHorVol.HorVolumes = new HVolume(); if (activeCandle2.IsNull()) { activeCandle2 = new SelectCandle(); activeCandle2.dataCandle = dataCandle; } } if (activeCandle1.NotIsNull() && activeCandle2.NotIsNull() && CurrTimeFrame.NotIsNull()) { if (dataCandle.Index <= activeCandle1.dataCandle.Index && dataCandle.Index >= activeCandle2.dataCandle.Index) { var hVol = CurrTimeFrame.HVolumes.GetCandle(dataCandle.Candle.Time); if (hVol.NotIsNull()) { foreach (var curVol in hVol.ToArray()) { if (curVol.Price < Panel.Params.MaxPrice && curVol.Price > Panel.Params.MinPrice) { PrepDataHorVol.HorVolumes.Add(curVol.Price, curVol.VolBuy, curVol.VolSell); } } } } } }
/// <summary> Рисует уровни </summary> /// <param name="canvas"></param> public void PaintByCandle(CandleInfo candle) { //this.Panel.Clear(); if (candle.Index >= CollectionLevels.Count) { return; } var canvas = this.Panel.GetGraphics; //this.AllDataLevels.Clear(); if (this.CollectionLevels.IsNull()) { return; } if (candle.Index == 0) { Values.Paint(this.Max, this.Min); Values.Panel.Paint(canvas); } var level = CollectionLevels.ElementAt(candle.Index); if (level.NotIsNull()) { this.PaintOneLevel(canvas, level, candle); } (new Line()).Paint(canvas, new Point(Panel.Rect.X, Panel.Rect.Y), new Point(Panel.Rect.X + Panel.Rect.Width, Panel.Rect.Y), Color.Black); }
public bool PaintLast(CandleInfo candle) { PanelLast.Clear(); if (CollectionLevels.IsNull() || this.CollectionLevels.Count == 0) { return(false); } var canvas = PanelLast.GetGraphics; var level = this.CollectionLevels.ElementAt(0); if (level.NotIsNull()) { if (level.Volume > this.Max || level.Volume < this.Min) { if (this.OnReachLimitValues.NotIsNull()) { this.OnReachLimitValues(level.Volume, this.Max, this.Min); } return(false); } else { PaintOneLevel(canvas, level, candle, true); Values.PaintCurrentValue(level.Volume, this.Max, this.Min); Values.PanelCurValue.Paint(canvas); } } return(true); }
/// <summary> /// Поиск прямоугольных уровней /// </summary> /// <param name="canLeft"></param> /// <param name="canRight"></param> private void SearchRectLevel(CandleInfo canLeft, CandleInfo canRight) { //Ищем Прямоугольные уровни которые попадают в окно видимости var levels = new List <DoubleLevel>(); levels.AddRange(this.Collection.Where(l => l.DateLeft.NotIsNull() && l.DateRight.NotIsNull() && l.Bottom > 0 && ( (l.DateLeft.GetDateTime() <= canLeft.Candle.Time && l.DateRight.GetDateTime() >= canRight.Candle.Time) || (l.DateLeft.GetDateTime() >= canLeft.Candle.Time && l.DateRight.GetDateTime() <= canRight.Candle.Time) || (l.DateLeft.GetDateTime() < canLeft.Candle.Time && l.DateRight.GetDateTime() < canRight.Candle.Time && l.DateRight.GetDateTime() > canLeft.Candle.Time) || (l.DateLeft.GetDateTime() > canLeft.Candle.Time && l.DateRight.GetDateTime() > canRight.Candle.Time && l.DateLeft.GetDateTime() < canRight.Candle.Time) ))); //Линейные уровни которые попадают в окно видимости levels.AddRange(this.Collection.Where(l => l.DateLeft.NotIsNull() && l.Bottom <= 0 && l.DateLeft.GetDateTime() <= canRight.Candle.Time )); levels.ForEach <DoubleLevel>((level) => { listTmpLevRect.Add(new LevelRect() { level = level, candleLeft = canLeft, candleRight = (level.Bottom > 0 ? canRight : null), });; }); }
/// <summary> /// Отрисовка одного уровня /// </summary> /// <param name="canvas"></param> /// <param name="rectPaint"></param> /// <param name="Value"></param> /// <param name="index"></param> private void PaintOneLevel(Graphics canvas, Chart level, CandleInfo candle, bool paintLast = false) { int Y1 = GMath.GetCoordinate(Panel.Rect.Height, this.Max, this.Min, level.Volume > 0 ? level.Volume : 0); int Y2 = GMath.GetCoordinate(Panel.Rect.Height, this.Max, this.Min, level.Volume < 0 ? level.Volume : 0); float bodyWidth = candle.Body.Width < MAX_WIDTH ? candle.Body.Width : MAX_WIDTH;//Panel.Params.WidthCandle - Panel.Params.MarginCandle; //-2 чтобы свечки не слипались int bodyHeight = Y2 - Y1; int bodyX = (int)(candle.Body.X + (candle.Body.Width / 2) - (bodyWidth / 2)); int bodyY = Y1; //bodyHeight = bodyHeight - bodyY; bodyHeight = bodyHeight == 0 ? bodyHeight + 1 : bodyHeight; var rect = new RectDraw(); if (candle.Index != 0 || paintLast) { var Color = ValuePositive; if (candle.Candle.Close < candle.Candle.Open) { Color = ValueNegative; } rect.Paint(canvas, bodyX, bodyY, bodyWidth, bodyHeight, Color, Color); } var data = new DataLevel() { PaintRect = Panel.Rect.Rectangle, Value = level.Volume, MaxValue = this.Max, MinValue = this.Min, Index = candle.Index, DataPaint = rect, Body = new RectangleF(bodyX, bodyY, bodyWidth, bodyHeight) }; if (data.NotIsNull()) { if (data.Index == 1) { this.AllDataLevels.RemoveAll(l => l.Index == data.Index); AllDataLevels.Insert(0, data); } else { AllDataLevels.Add(data); } } }
/// <summary> /// Отрисовка активных частей /// </summary> /// <param name="dCan"></param> /// <returns></returns> protected bool PaintActual(CandleInfo dCan) { if (!Candels.PaintLastCandle(dCan)) { return(false); } //Проверка на перерисовку if (MainPanel.Params.Redraw()) { PaintAll(); return(false); } //Обычные обьемы Volumes.GetFirstLevel().Volume = dCan.Candle.Volume; if (!Volumes.PaintLast(dCan)) { return(false); } RightPrices.PaintCurrentValue(dCan.Candle.Close, MainPanel.Params.MaxPrice, MainPanel.Params.MinPrice); if (dCan.Candle.Close > MainPanel.Params.MaxPrice || dCan.Candle.Close < MainPanel.Params.MinPrice) { if (MainPanel.Params.AutoSize) { if (OnReachLimitPrice.NotIsNull()) { OnReachLimitPrice(dCan.Candle.Close, MainPanel.Params.MaxPrice, MainPanel.Params.MinPrice); } } } Indicators.ForEach((objIndicator) => { if (objIndicator is Indicator) { var obj = (Indicator)objIndicator; if (obj.FastRedraw) { obj.FastUpdate(); } } }); return(true); }
/// <summary> Отрисовка текущей свечи (самой правой) </summary> public bool PaintLastCandle(CandleInfo candle) { PanelLastCandle.Clear(); if (CollectionCandle.IsNull()) { return(false); } var canvas = PanelLastCandle.GetGraphics; if (candle.NotIsNull()) { if (PanelLastCandle.Params.AutoSize) { //контроль максимальной цены if (candle.Candle.High > PanelLastCandle.Params.MaxPrice) { if (OnReachMinMax.NotIsNull()) { OnReachMinMax(candle.Candle.High, PanelLastCandle.Params.MaxPrice, PanelLastCandle.Params.MinPrice); } return(false); } //контроль минимальной цены if (candle.Candle.Low < PanelLastCandle.Params.MinPrice) { if (OnReachMinMax.NotIsNull()) { OnReachMinMax(candle.Candle.Low, PanelLastCandle.Params.MaxPrice, PanelLastCandle.Params.MinPrice); } return(false); } } PaintOneCandle(canvas, PanelLastCandle, candle.Candle, 1); } return(true); }
public string Backtest(string source, string market, KlineInterval kline, DateTime start, DateTime end, StrategyOptions actStrat) { //var source = ""; //var market = "BTCTUSDT"; //var kline = Binance.Net.Objects.KlineInterval.FifteenMinutes; //var start = new DateTime(2019, 11, 1); //var end = new DateTime(2019, 12, 30); //var actStrat = new StrategyOptions(); // get all candles CandleHelper.RetrieveCandles(market, kline, start, end); DateTime small = DateTime.MinValue; DateTime big = DateTime.MinValue; List <CandleInfo> allCandles = null; if (!CandleHelper.CandlesAvailable(market, kline, start, end, out small, out big, out allCandles)) { return("no candles available"); } var temp = new Context(allCandles); temp.ActiveStrategyOptions = Globals.ActiveStrategyOptions; if (!CryptoGlobals.RunScript(source, ref temp)) { return("error in script: " + temp.SCRIPT_ERROR); } var c = new Context(allCandles); c.ActiveStrategyOptions = actStrat; var startingBalance = c.ActiveStrategyOptions.BacktestStartingBalance; var originalBalance = startingBalance; var l = new List <CandleInfo>(); dynamic script = CSScript.RoslynEvaluator.LoadCode(source); foreach (var item in allCandles) { l.Add(item); if (l.Count < 20) { continue; } c.RawCandles = l; try { script.OnData(c); }catch (Exception ex) { return("error: " + ex.Message); } } foreach (var item in c.GetOpenOrders()) { c.CloseOrder(item); } var orders = c.GetAllOrders(); var candlesAndOrders = new SortedDictionary <DateTime, List <OrderInfo> >(); foreach (var item in orders) { var buyDate = item.BuyCandle.OpenTime; var sellDate = item.SellCandle.OpenTime; if (!candlesAndOrders.ContainsKey(buyDate)) { candlesAndOrders[buyDate] = new List <OrderInfo>(); } if (!candlesAndOrders.ContainsKey(sellDate)) { candlesAndOrders[sellDate] = new List <OrderInfo>(); } candlesAndOrders[buyDate].Add(item); candlesAndOrders[sellDate].Add(item); } candlesAndOrders.OrderBy(x => x.Key); var originalEquity = originalBalance; double finalEquity = 0f; var equityOrders = new Dictionary <string, OrderInfo>(); List <OrderResultInfo> finalOrders = new List <OrderResultInfo>(); double totalProfits = 0f; var tempCount = 0; var alreadyAddedIds = new List <string>(); foreach (var cao in candlesAndOrders) { var currDate = cao.Key; var orderList = cao.Value; foreach (var item in orderList) { tempCount++; var isSell = false; if (alreadyAddedIds.Contains(item.Id)) { isSell = true; } else { alreadyAddedIds.Add(item.Id); } var ord = item; var id = ord.Id; string type; DateTime time; double orderPrice = 0.0f;; double size = ord.BuyAmountInUSD; double profitLoss = 0f; double balance = 0f; if (isSell == false) // buy { originalBalance -= ord.BuyAmountInUSD; originalBalance = Math.Round(originalBalance, 2); time = ord.BuyCandle.OpenTime; type = "Buy"; orderPrice = Math.Round(ord.BuyPrice, 2); equityOrders[ord.Id] = ord; } else // sell { var tUsd = ord.TotalUSD(); tUsd = Math.Round(tUsd, 2); originalBalance += tUsd; originalBalance = Math.Round(originalBalance, 2); time = ord.SellCandle.OpenTime; type = "Sell"; var tmpPL = Math.Round(tUsd - ord.BuyAmountInUSD, 2); profitLoss = tmpPL; balance = originalBalance; balance = Math.Round(balance, 2); totalProfits += tmpPL; orderPrice = Math.Round(ord.GetSellPrice(), 2); equityOrders.Remove(ord.Id); } size = Math.Round(size, 8); var finalBalance = balance;// (isSell) ? "$ " + balance.ToString() : ""; finalEquity = 0f; CandleInfo tempCandle = (isSell) ? orderList[0].SellCandle : orderList[0].BuyCandle; double ttttemp = 0f; foreach (var eOrd in equityOrders.Values) { finalEquity += tempCandle.MidPrice * ord.CoinAmount; ttttemp += ord.BuyAmountInUSD; } ttttemp = Math.Round(ttttemp, 3); finalEquity = Math.Round(finalEquity, 3); var ori = new OrderResultInfo() { Id = id.ToString(), Time = time, Type = type, OrderPrice = orderPrice, OrderAmountUSD = size, ProfitLoss = profitLoss, FinalBalance = finalBalance, FinalEquity = finalEquity }; finalOrders.Add(ori); } } var finalPL = Math.Round(originalBalance - startingBalance, 2); finalOrders.Add(new OrderResultInfo() { Id = "", Time = DateTime.MinValue, Type = "blank", OrderPrice = 0f, OrderAmountUSD = 0f, ProfitLoss = 0f, FinalBalance = 0f }); finalOrders.Add(new OrderResultInfo() { Id = "", Time = DateTime.MinValue, Type = "blank2", OrderPrice = 0f, OrderAmountUSD = 0f, ProfitLoss = finalPL, FinalBalance = originalBalance }); var final = JsonConvert.SerializeObject(finalOrders); return(final); }
public override void EachFullCandle(CandleInfo candle) { }
/// <summary> Рисует одну свечку </summary> /// <param name="canvas"></param> /// <param name="rectPaint"></param> /// <param name="candleData"></param> /// <param name="index"></param> /// <param name="maxPrice"></param> /// <param name="minPrice"></param> private CandleInfo PaintOneCandle(Graphics canvas, ViewPanel panel, CandleData candleData, int index, bool paint = true) { int tailY1 = GMath.GetCoordinate(panel.Rect.Height, panel.Params.MaxPrice, panel.Params.MinPrice, candleData.High); int tailY2 = GMath.GetCoordinate(panel.Rect.Height, panel.Params.MaxPrice, panel.Params.MinPrice, candleData.Low); int tailX1 = (int)((panel.Rect.Width - panel.Params.WidthCandle * index) + panel.Params.WidthCandle / 2); int bodyX = (int)(panel.Rect.Width - panel.Params.WidthCandle * index); int bodyY = GMath.GetCoordinate(panel.Rect.Height, panel.Params.MaxPrice, panel.Params.MinPrice, candleData.Open > candleData.Close ? candleData.Open : candleData.Close); float bodyWidth = panel.Params.WidthCandle - MarginCandle > 0.3f ? panel.Params.WidthCandle - MarginCandle : 0.3f; //- чтобы свечки не слипались int bodyHeight = GMath.GetCoordinate(panel.Rect.Height, panel.Params.MaxPrice, panel.Params.MinPrice, candleData.Open < candleData.Close ? candleData.Open : candleData.Close); bodyHeight = bodyHeight - bodyY; bodyHeight = bodyHeight == 0 ? bodyHeight + 1 : bodyHeight; //tail var line = new Line(); line.Width = 1.5f; if (paint) { line.Paint(canvas, new Point(tailX1, tailY1), new Point(tailX1, tailY2), ColorBorderCandle); } //Body var rect = new RectDraw(); var colorCandle = candleData.Open > candleData.Close ? ColorFallCandle : ColorGrowCandle; var colorBorder = ColorBorderCandle; /*if (candleData.Open < candleData.Close && candleData.VolumeBuy - candleData.VolumeSell > 0) * { * colorBorder = colorCandle = Color.DarkGreen; * } * if (candleData.Open > candleData.Close && candleData.VolumeBuy - candleData.VolumeSell < 0) * { * colorBorder = colorCandle = Color.DarkRed; * }*/ if (paint) { rect.Paint(canvas, bodyX, bodyY, bodyWidth, bodyHeight, colorBorder, colorCandle); } if (MaxValues.MinCandle.IsNull()) { MaxValues.MinCandle = candleData; } if (MaxValues.MaxCandle.IsNull()) { MaxValues.MaxCandle = candleData; } if (MaxValues.MaxPrice < candleData.High) { MaxValues.MaxPrice = candleData.High; MaxValues.MaxCandle = candleData; } if (MaxValues.MinPrice > candleData.Low) { MaxValues.MinPrice = candleData.Low; MaxValues.MinCandle = candleData; } /*if (candleData.HorVolumes.HVolCollection.MaxVolume.NotIsNull()) * { * if (MaxValues.MaxHorVolume.Volume < candleData.HorVolumes.HVolCollection.MaxVolume.Volume) * { * MaxValues.MaxHorVolume = candleData.HorVolumes.HVolCollection.MaxVolume; * } * }*/ var dCandle = new CandleInfo() { PaintRect = panel.Rect.Rectangle, Candle = candleData, TailCoord = new TailCoord() { Low = new Point(tailX1, tailY2), High = new Point(tailX1, tailY1) }, Body = new RectangleF() { X = bodyX, Y = bodyY, Width = bodyWidth, Height = bodyHeight }, Index = index - 1, MaxHorVolume = MaxValues.MaxHorVolume, TimeFrame = CurrentTimeFrame }; VerticalLines[index - 1] = dCandle.TailCoord.High.X; if (index == 1) { AllDataPaintedCandle.RemoveAll(c => c.Index == index - 1); AllDataPaintedCandle.Insert(0, dCandle); } else { AllDataPaintedCandle.Add(dCandle); } if (OnPaintedCandle.NotIsNull()) { OnPaintedCandle(dCandle); } return(dCandle); }
/// <summary> /// Обработка каждой свечки cо всеми данными /// </summary> public abstract void EachFullCandle(CandleInfo toolsCandle);
private async Task RunAsync(CancellationToken token) { while (!token.IsCancellationRequested) { // get live orders if (AllMarkets == null) { RefreshMarkets(); } if (AllUsers == null) { RefreshUsers(); } if (AllContexts == null) { AllContexts = new Dictionary <int, Context>(); } foreach (DataRow row in DBHelper.dtJobs.Rows) { var job = new JobInfo(row); if (job.IsLive) { // grab the latest candles var kline = CryptoGlobals.GetKlineFromString(job.Interval); var c = CryptoGlobals.LastCandleInDB(AllMarkets[job.MarketId].Symbol, kline); var shouldGetCandles = false; var firstDate = DateTime.Today.AddDays(60); if (c == null) { // ouch never got any candles :( shouldGetCandles = true; } else { // we got, that's our start date if (c.OpenTime < CryptoGlobals.MinusKlineInterval(DateTime.UtcNow, kline)) { shouldGetCandles = true; firstDate = c.OpenTime; } } if (shouldGetCandles) { CandleHelper.RetrieveCandles(AllMarkets[job.MarketId].Symbol, kline, firstDate, DateTime.Now.AddDays(1)); // TAKE IT ALLLLL } if (!AllUsers.ContainsKey(job.UserId)) { AllUsers = null; RefreshUsers(); if (!AllUsers.ContainsKey(job.UserId)) { // invalid user continue; } } var user = AllUsers[job.UserId]; // get candles var crows = DBHelper.GetDataTable("SELECT * FROM Candles WHERE Symbol='" + AllMarkets[job.MarketId].Symbol + "' AND Interval='" + job.Interval + "'"); // haha crows List <CandleInfo> CurrentCandles = new List <CandleInfo>(); foreach (DataRow crow in crows.Rows) { var tempC = new CandleInfo(crow); CurrentCandles.Add(tempC); } StrategyOptions myStrat = null; var strat = DBHelper.GetDataTable("SELECT * from Strategies where Id=" + job.ScriptId); if (strat.Rows.Count > 0) { myStrat = (new StrategyInfo(strat.Rows[0])).Options; } else { continue; // cancel!?!? } Context cxt = null; if (!AllContexts.ContainsKey(job.Id)) { cxt = new Context(CurrentCandles); cxt.IsLive = true; cxt.User = user; cxt.ActiveStrategyOptions = new StrategyOptions() { BacktestStartingBalance = 1000000, Fees = 0, MaxOpenOrders = myStrat.MaxOpenOrders, MinutesInBetweenOrders = myStrat.MinutesInBetweenOrders }; } else { cxt = AllContexts[job.Id]; cxt.RawCandles = CurrentCandles; } var l = new List <CandleInfo>(); if (CurrentCandles.Count == 0) { continue; } cxt.RawCandles = CurrentCandles; if (cxt.IsLive && !cxt.IsPaper) { //var orders = CryptoGlobals.UserBinances[user.Username].GetOpenOrders(); // //foreach (var item in orders.Data) //{ // // if (item.Symbol != AllMarkets[job.MarketId].Symbol) continue; // // var t = new OrderInfo(cxt, (float)(item.Price * item.ExecutedQuantity)); // t.CoinAmount = (float)item.ExecutedQuantity; // t.IsOpen = true; // t.Id = item.ClientOrderId.ToString(); //} } else { } if (!Globals.RunScript(cxt.StrategyScript, ref cxt)) { continue; } // we now can run the script } } System.Diagnostics.Debug.WriteLine(DateTime.Now); await Task.Delay(1000); } }
/// <summary>Отрисовка всего графика </summary> /// <param name="graphic">Полотно</param> protected void PaintAll() { if (!Candels.IssetCollection()) { return; } GetMinMax(); //Отрисовка свечей в приоритете Candels.PaintCandles(); RightPrices.Paint(RightPrices.Panel.Params.MaxPrice, RightPrices.Panel.Params.MinPrice); if (ActiveCandles.ActiveCandle1.NotIsNull() && ActiveCandles.ActiveCandle2.NotIsNull()) { if (ActiveCandles.ActiveCandle1.dataCandle.Index > ActiveCandles.ActiveCandle2.dataCandle.Index) { GHorVolumes.activeCandle1 = ActiveCandles.ActiveCandle1; GHorVolumes.activeCandle2 = ActiveCandles.ActiveCandle2; } else { GHorVolumes.activeCandle1 = ActiveCandles.ActiveCandle2; GHorVolumes.activeCandle2 = ActiveCandles.ActiveCandle1; } if (TypeHorVolume == 3) { GHorVolumes.activeCandle2 = null; } } CandleInfo LastCandle = null; Levels.Panel.Clear(); var leftCandle = Candels.AllDataPaintedCandle.Last(); var rightCandle = Candels.AllDataPaintedCandle.First(); //Паинт foreach (var dCandle in Candels.AllDataPaintedCandle.ToArray()) { dCandle.PrevCandleInfo = LastCandle; Volumes.PaintByCandle(dCandle); GHorVolumes.EachCandle(dCandle); Levels.PaintByCandle(dCandle, leftCandle, rightCandle, Candels.AllDataPaintedCandle.Count); Indicators.ForEach((ind) => { if (ind is Indicator) { ((Indicator)ind).EachFullCandle(dCandle); } }); LastCandle = dCandle; } LevelsOrders.Paint(); Levels.Paint(); ActualizeActiveCandle(); if (ThreadPaintHotVol.NotIsNull()) { ThreadPaintHotVol.Abort(); ThreadPaintHotVol = null; } if (ThreadPaintHotVol.IsNull()) { ThreadPaintHotVol = MThread.InitThread(() => { GHorVolumes.CollectionCandles = Candels.AllDataPaintedCandle; if (TypeHorVolume == 1) { if (ActiveCandles.ActiveCandle1.NotIsNull()) { GHorVolumes.PaintHorVolEachBlock(ActiveCandles.ActiveCandle1.dataCandle.Index + 1); } } else if (TypeHorVolume == 2 || TypeHorVolume == 3) { GHorVolumes.PaintHorVolByPeriodCandleDelta(false, false); } else if (TypeHorVolume == 5) { GHorVolumes.PaintHorVolByPeriodCandleDelta(false, true, limitHorVol); } else if (TypeHorVolume == 4) { GHorVolumes.PaintCollectionHVol(); } ThreadPaintHotVol = null; }); } ToCanvas(); }
public override void EachFullCandle(CandleInfo candle) { Calculate(candle.Index, candle.TailCoord.High.X); }
public void PaintByCandle(CandleInfo candle, CandleInfo leftCandle, CandleInfo rightCandle, int count) { if (!Visible) { return; } if (this.Collection.IsNull()) { return; } if (candle.IsNull()) { return; } var canvas = Panel.GetGraphics; //Поиск всех уровней попадающий в окно видимости if (candle.Index == 0) { SearchRectLevel(leftCandle, rightCandle); } if (candle.PrevCandleInfo.NotIsNull()) { //Ищем правые грани уровня listTmpLevRect.Where(l => l.level.DateRight.DateTime >= candle.Candle.Time && l.level.DateRight.DateTime < candle.PrevCandleInfo.Candle.Time ).ForEach <LevelRect>((lev) => { lev.candleRight = candle; }); // Ищем левые грани уровня listTmpLevRect.Where(l => l.level.DateLeft.DateTime >= candle.Candle.Time && l.level.DateLeft.DateTime < candle.PrevCandleInfo.Candle.Time ).ForEach <LevelRect>((lev) => { lev.candleLeft = candle; }); } //Обработка на последней свече if (count == candle.Index + 1) { //Рисуем прямоугольные уровни foreach (var levRect in listTmpLevRect.ToArray()) { bool paint = false; Rectangle rect = new Rectangle(); //Прямоугольный уровень if (levRect.candleLeft.NotIsNull() && levRect.candleRight.NotIsNull()) { var width = Panel.Rect.Width - levRect.candleLeft.TailCoord.High.X; rect = (GRectangle.GetRight(Panel.Rect.Clone(), width)).Rectangle; levRect.candleRight.TailCoord.High.X = levRect.candleRight.TailCoord.High.X < 0 ? 0 : levRect.candleRight.TailCoord.High.X; levRect.candleLeft.TailCoord.High.X = levRect.candleLeft.TailCoord.High.X < 0 ? 0 : levRect.candleLeft.TailCoord.High.X; rect.Width = levRect.candleRight.TailCoord.High.X - levRect.candleLeft.TailCoord.High.X; paint = true; } //Линейный уровень else if (levRect.candleLeft.NotIsNull()) { var time = levRect.level.DateLeft.GetDateTime(); if (time <= rightCandle.Candle.Time) { var width = Panel.Rect.Width - levRect.candleLeft.TailCoord.High.X; rect = (GRectangle.GetRight(Panel.Rect.Clone(), width)).Rectangle; levRect.candleLeft.TailCoord.High.X = levRect.candleLeft.TailCoord.High.X < 0 ? 0 : levRect.candleLeft.TailCoord.High.X; paint = true; } } if (paint) { rect.X = rect.X < 0 ? 0 : rect.X; if (levRect.level.Bottom <= 0 && levRect.level.Top > 0) { PaintLineLevel(canvas, rect, levRect.level, 2f); } else { PaintRectangleLevel(canvas, rect, levRect.level, 1); } } listTmpLevRect.Clear(); } } }